-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[Components] plaid - new components #16586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ |
WalkthroughThis update introduces a comprehensive Plaid integration, adding new Plaid API actions, webhook sources, utility modules, and constants. The Plaid app component is refactored to use the official SDK, with robust prop definitions and methods for API interaction, error handling, and pagination. Webhook sources and test events are implemented for real-time event handling. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Action
participant PlaidApp
participant PlaidAPI
User->>Action: Trigger action (e.g., get-transactions)
Action->>PlaidApp: Call method (e.g., getTransactions)
PlaidApp->>PlaidAPI: Make API request
PlaidAPI-->>PlaidApp: Return API response
PlaidApp-->>Action: Return processed data
Action-->>User: Output result
sequenceDiagram
participant PlaidAPI
participant WebhookSource
participant System
PlaidAPI-->>WebhookSource: Send webhook event
WebhookSource->>WebhookSource: Check event relevance
WebhookSource->>System: Emit event with metadata
Assessment against linked issues
Suggested labels
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (1)
components/plaid/sources/new-accounts-available-instant/new-accounts-available-instant.mjs (1)
24-30
: Same deduplication concern as other sourceSee the note about using
event_id
instead ofDate.now()
for deterministic IDs. Applying the same change here keeps the sources consistent.
🧹 Nitpick comments (18)
components/plaid/common/constants.mjs (1)
4-7
: Consider Named Exports for Tree-Shaking
Using a default export object may hinder tree-shaking. Consider switching to named exports:-export default { - DEFAULT_LIMIT, - DEFAULT_MAX, -}; +export { DEFAULT_LIMIT, DEFAULT_MAX };components/plaid/common/sandbox-institutions.mjs (3)
1-3
: Add File-Level Documentation
This file defines a large static map of sandbox institutions. Adding a JSDoc header or inline comment explaining its purpose and usage will improve developer onboarding and maintainability.
2-21
: Group Institutions by Category
The non-OAuth banks (INS_109508–INS_109512) would benefit from a comment block separating them from other categories. For example:+// ── Non-OAuth sandbox institutions ──────────────────────────────────────── INS_109508: { … }, INS_109509: { … }, …
22-70
: Add Section Comments for Clarity
Institutions span Canadian, UK, OAuth, and degraded/unsupported cases. Adding comments before each logical group will make future updates easier to navigate.components/plaid/sources/common/events.mjs (3)
1-5
: Freeze WEBHOOK_TYPE for Immutability
Protect these constants from unintended mutation by applyingObject.freeze
. E.g.:-const WEBHOOK_TYPE = { … }; +const WEBHOOK_TYPE = Object.freeze({ … });
7-26
: Freeze WEBHOOK_CODE and Nested Objects
Similarly, lock down the nestedWEBHOOK_CODE
object and its sub-objects:-const WEBHOOK_CODE = { … }; +const WEBHOOK_CODE = Object.freeze({ … });
28-31
: Consider Named Exports over Default Export
Using named exports (export { WEBHOOK_TYPE, WEBHOOK_CODE };
) improves tree-shaking and makes individual constants easier to import directly.components/plaid/package.json (1)
16-17
: Verify Dependency Versions and Compatibility
Ensure the newly addedplaid@^33.0.0
SDK and upgraded@pipedream/platform@^3.0.3
are compatible and available. You can run:npm view plaid@^33.0.0 version npm view @pipedream/platform@^3.0.3 versioncomponents/plaid/sources/new-accounts-available-instant/test-event.mjs (1)
8-8
: Remove stray line number.There appears to be a stray character/number "8" at the end of the file that should be removed.
"webhook_type": "ITEM" }; -8
components/plaid/common/utils.mjs (1)
1-17
: Consider adding JSDoc comments to utility functions.Adding JSDoc comments would improve code maintainability by providing clear documentation about parameters, return values, and usage examples.
+/** + * Collects all items from an async iterable into an array + * @param {AsyncIterable} iterations - The async iterable to collect from + * @returns {Promise<Array>} Array containing all items from the iterable + */ async function iterate(iterations) { const items = []; for await (const item of iterations) { items.push(item); } return items; } +/** + * Safely accesses nested properties in an object using a dot-separated path + * @param {Object} obj - The object to access properties from + * @param {string} propertyString - Dot-separated path to the property (e.g., "user.address.zipCode") + * @returns {*} The value at the specified path or undefined if the path doesn't exist + */ function getNestedProperty(obj, propertyString) { const properties = propertyString.split("."); return properties.reduce((prev, curr) => prev?.[curr], obj); }components/plaid/actions/get-transactions/get-transactions.mjs (3)
68-80
: Consider simplifying conditional options handling.The conditional logic for building the options object is well-structured, but could be more concise.
Consider using object property shorthand when the property name matches the variable name:
- if (includeOriginalDescription !== undefined) { - options.include_original_description = includeOriginalDescription; - } + if (includeOriginalDescription !== undefined) { + options.include_original_description = includeOriginalDescription; + }While the implementation is correct, this is just a stylistic suggestion.
88-91
: Simplify conditional spread for options.The conditional spread operator with logical AND could be simplified for better readability.
- ...(Object.keys(options).length > 0 && { - options, - }), + ...(Object.keys(options).length ? { options } : {}),This alternative is more explicit about the intent and avoids potential confusion with the logical AND operator.
95-96
: Consider handling empty transactions array more directly.The current implementation handles the possibility of
transactions
being undefined, which may not be necessary if the paginate method always returns an array.- const transactionCount = transactions?.length || 0; + const transactionCount = transactions.length;If there's a possibility that
transactions
could be undefined or null from the paginate method, then the current implementation is correct. Otherwise, this simplification would be cleaner.components/plaid/sources/common/webhook.mjs (3)
61-62
: Remove console.log statement in production code.Console logging the createLinkToken response may not be appropriate for production code.
- console.log("createLinkToken response", response);
Consider using a debug log level if you need to retain this for troubleshooting, or remove it entirely for production code.
85-87
: Uncomment or remove HTTP response handling.There are commented-out lines related to HTTP response handling. These should either be uncommented or removed to maintain clean code.
Either uncomment and use:
http.respond({ status: 200, });Or remove the commented code entirely if it's not needed.
71-73
: Document the intention of isEventRelevant method.The
isEventRelevant
method always returns true, which means all webhook events will be processed by default. This is likely intended to be overridden by extending components.Add a comment to clarify the intention:
isEventRelevant() { + // Base implementation accepts all events; override in extending components to filter events return true; },
components/plaid/sources/new-event-instant/new-event-instant.mjs (1)
14-21
: Consider using a more unique event ID.The current ID generation uses a timestamp (
Date.now()
), which could potentially cause collisions if multiple events are processed at the exact same millisecond.Consider incorporating the webhook type and code into the ID for better uniqueness:
generateMeta(resource) { const ts = Date.now(); return { - id: ts, + id: `${resource.webhook_type}.${resource.webhook_code}-${ts}`, summary: `New Event: ${resource.webhook_type}.${resource.webhook_code}`, ts, }; },This would ensure that even if two different events arrive at the same millisecond, they would still have unique IDs.
components/plaid/sources/sync-updates-available-instant/sync-updates-available-instant.mjs (1)
20-27
: Use webhook-provided identifiers for deterministic deduping
generateMeta
relies onDate.now()
for bothid
andts
. When two webhooks arrive in the same millisecond the IDs will collide, causing dropped events in “unique” dedupe mode.
Plaid webhook payloads include anevent_id
; prefer that when available, falling back to the timestamp only if not present:generateMeta(resource) { - const ts = Date.now(); - return { - id: ts, - summary: `New Event: ${resource.webhook_type}.${resource.webhook_code}`, - ts, - }; + const ts = Date.now(); + return { + id: resource.event_id ?? ts, + summary: `New Event: ${resource.webhook_type}.${resource.webhook_code}`, + ts, + }; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (17)
components/plaid/actions/create-access-token/create-access-token.mjs
(1 hunks)components/plaid/actions/create-sandbox-public-token/create-sandbox-public-token.mjs
(1 hunks)components/plaid/actions/get-real-time-balance/get-real-time-balance.mjs
(1 hunks)components/plaid/actions/get-transactions/get-transactions.mjs
(1 hunks)components/plaid/common/constants.mjs
(1 hunks)components/plaid/common/sandbox-institutions.mjs
(1 hunks)components/plaid/common/utils.mjs
(1 hunks)components/plaid/package.json
(2 hunks)components/plaid/plaid.app.mjs
(1 hunks)components/plaid/sources/common/events.mjs
(1 hunks)components/plaid/sources/common/webhook.mjs
(1 hunks)components/plaid/sources/new-accounts-available-instant/new-accounts-available-instant.mjs
(1 hunks)components/plaid/sources/new-accounts-available-instant/test-event.mjs
(1 hunks)components/plaid/sources/new-event-instant/new-event-instant.mjs
(1 hunks)components/plaid/sources/new-event-instant/test-event.mjs
(1 hunks)components/plaid/sources/sync-updates-available-instant/sync-updates-available-instant.mjs
(1 hunks)components/plaid/sources/sync-updates-available-instant/test-event.mjs
(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: pnpm publish
- GitHub Check: Verify TypeScript components
- GitHub Check: Lint Code Base
- GitHub Check: Publish TypeScript components
🔇 Additional comments (17)
components/plaid/common/constants.mjs (1)
1-2
: Constants Naming and Purpose Clear
TheDEFAULT_LIMIT
andDEFAULT_MAX
constants follow standard uppercase naming and appropriately centralize pagination settings.components/plaid/package.json (1)
3-3
: Version Bump Looks Good
Updating to0.7.0
correctly reflects the addition of new features; this follows semantic versioning for a minor release.components/plaid/sources/sync-updates-available-instant/test-event.mjs (1)
1-8
: Test Fixture Matches Event Schema
The structure (environment
, flags,item_id
,webhook_code
,webhook_type
) aligns with the webhook event constants. This test event will correctly simulate a"SYNC_UPDATES_AVAILABLE"
transactions webhook.components/plaid/sources/new-event-instant/test-event.mjs (1)
1-8
: Test event looks good and follows Plaid webhook format.The exported object correctly models a Plaid webhook event with the appropriate fields needed for testing the "New Event (Instant)" source. The payload includes all required fields for a webhook update acknowledgment event.
components/plaid/sources/new-accounts-available-instant/test-event.mjs (1)
1-7
: Test event structure looks good for NEW_ACCOUNTS_AVAILABLE webhook.The payload correctly structures a Plaid webhook event for new accounts becoming available, with all the necessary fields.
components/plaid/common/utils.mjs (2)
1-7
: Good implementation of async iteration utility.The
iterate
function correctly collects all items from an async iterable into an array, which is useful for handling paginated responses from the Plaid API.
9-12
: Effective utility for safely accessing nested properties.The
getNestedProperty
function uses optional chaining to safely access nested object properties, which is ideal for handling complex nested response structures from Plaid.components/plaid/actions/get-real-time-balance/get-real-time-balance.mjs (2)
9-29
: Props are well-defined with appropriate descriptions.The props include the required access token and optional account IDs with clear labels and descriptions. The dynamic account ID options based on the access token provide a good user experience.
4-8
: Version suggests this is a new component.The version "0.0.1" indicates this is the first release of this component. Ensure adequate testing has been performed, especially with the Plaid sandbox environment.
Have you tested this component with real Plaid sandbox credentials to verify it works as expected?
components/plaid/actions/create-access-token/create-access-token.mjs (1)
1-32
: Good implementation of the Plaid token exchange action.This action properly implements the exchange of a public token for an access token using the Plaid API. The structure follows Pipedream's conventions with clear property definitions and a straightforward implementation.
components/plaid/actions/get-transactions/get-transactions.mjs (1)
1-100
: Overall well-structured transaction retrieval action.The action correctly implements transaction retrieval with proper pagination support and parameter handling. The code is well-organized with appropriate property definitions and validation rules.
components/plaid/sources/common/webhook.mjs (2)
54-58
: Review hardcoded products array vs. configurable products props.The webhook is configured with hardcoded products ("transactions" and "assets"), but the component also accepts product-related props that aren't being used in the Link token creation.
Consider whether the hardcoded products should be replaced with the configurable products from props:
- products: [ - "transactions", - "assets", - ], + products: this.products,If the intention is to always use these specific products regardless of the props, consider removing the product-related props or adding a comment explaining why they're not used in this context.
1-93
: Solid foundation for Plaid webhook event handling.Overall, this common webhook base component provides a good foundation for handling Plaid webhook events. It correctly sets up the webhook endpoint, defines methods that can be overridden by extending components, and provides a consistent structure for event processing.
components/plaid/sources/new-event-instant/new-event-instant.mjs (1)
1-24
: Clean implementation of webhook event source.This is a well-implemented specific webhook source that correctly extends the common webhook component. It provides appropriate metadata generation for its events and includes a sample event for testing.
components/plaid/actions/create-sandbox-public-token/create-sandbox-public-token.mjs (1)
86-95
: Pass a single payload object tocreateSandboxPublicToken
makeRequest
expectsargs
to be the first positional argument in the SDK call, but spreading the payload (lines 86-95) directly into the wrapper call also spreads it into the options bag understood bymakeRequest
.
A safer pattern is:-const response = await app.createSandboxPublicToken({ - institution_id: institutionId, - initial_products: initialProducts, - ...(Object.keys(options).length > 0 && { options }), - ...(userToken && { user_token: userToken }), -}); +const payload = { + institution_id: institutionId, + initial_products: initialProducts, + ...(Object.keys(options).length && { options }), + ...(userToken && { user_token: userToken }), +}; + +const response = await app.createSandboxPublicToken(payload);This guarantees that the wrapper receives exactly the structure it forward-calls with, safeguarding against accidental argument shadowing.
components/plaid/sources/new-accounts-available-instant/new-accounts-available-instant.mjs (1)
18-23
: Guard against undefined constantsIf
events.WEBHOOK_CODE[webhookType]
is missing (e.g. future Plaid change or typo), accessing.NEW_ACCOUNTS_AVAILABLE
will throw.
Defensively test before dereferencing:const webhookType = events.WEBHOOK_TYPE.ITEM; -const webhookCode = events.WEBHOOK_CODE[webhookType].NEW_ACCOUNTS_AVAILABLE; +const webhookCode = + events.WEBHOOK_CODE?.[webhookType]?.NEW_ACCOUNTS_AVAILABLE;Return
false
early when the constant is absent to avoid runtime exceptions.components/plaid/plaid.app.mjs (1)
217-260
: Pagination loop can spin indefinitely if the API ignoresoffset
offset
is incremented blindly (line 259) without checking whether the next page actually yielded different resources.
If Plaid ever ignoresoffset
for a particular endpoint, the loop will never exit.
Store the last batch’s first resource ID or use the SDK’snext_cursor
(for/transactions/sync
-style endpoints) when available.
WHY
Resolves #15144
Summary by CodeRabbit
New Features
Chores