Skip to content

Conversation

@ArshadMasood
Copy link

@ArshadMasood ArshadMasood commented Aug 9, 2025

Fixed the 400 error by adding "transactions" product support in the user actions when creating the Plaid link token.

Screenshot 2025-08-09 170516

Before fix — error received

400 Bad Request error

The error occurred because the "transactions" product was missing in the Plaid link token creation.

After fix — added "transactions" product

Fixed the error by including "transactions" in the products array during token creation.

products: ["auth", "transactions"] as Products[], // Added "transactions" here

Summary by CodeRabbit

  • Style

    • Improved code formatting and consistency, including quotation marks, semicolons, and indentation.
  • New Features

    • Added support for the "transactions" product when creating a Plaid link token.

@vercel
Copy link

vercel bot commented Aug 9, 2025

@ArshadMasood is attempting to deploy a commit to the JS Mastery Pro Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Aug 9, 2025

Walkthrough

This change refactors the lib/actions/user.actions.ts file, focusing on code style, formatting, and consistency. It standardizes string quotes, semicolons, import formatting, and object literal style. The only functional adjustment is adding "transactions" to the Plaid link token creation parameters. No function signatures or control flow were altered.

Changes

Cohort / File(s) Change Summary
Stylistic and Formatting Updates
lib/actions/user.actions.ts
Reformatted imports, object literals, string quotes, semicolons, and whitespace for consistency; standardized error logging; changed async function bodies to explicit block form.
Plaid Token Parameter Update
lib/actions/user.actions.ts
Added "transactions" to the Plaid link token creation parameters.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

In fields of code where rabbits hop,
A tidy warren—no need to stop!
Quotes aligned and commas neat,
Async blocks now all complete.
"Transactions" join the Plaid parade—
A burrow where clean code is made!
🐇✨

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (1)
lib/actions/user.actions.ts (1)

174-182: Avoid storing Plaid access_token in plaintext

Storing access tokens directly in the database is a high-value target if compromised. Prefer field-level encryption (e.g., AES-256-GCM with per-record IV) before persistence, or a KMS/HSM solution. Also ensure the value is never logged.

If you want, I can provide a small utils encrypt/decrypt helper (Node crypto) and the minimal changes here to encrypt before write and decrypt on read.

🧹 Nitpick comments (7)
lib/actions/user.actions.ts (7)

7-12: Type the Link Token request to avoid casts and tighten compile-time checks

Import LinkTokenCreateRequest and annotate tokenParams. This removes ambiguity and prevents accidental shape drift.

 import {
   CountryCode,
+  LinkTokenCreateRequest,
   ProcessorTokenCreateRequest,
   ProcessorTokenCreateRequestProcessorEnum,
   Products,
 } from "plaid";
-    const tokenParams = {
+    const tokenParams: LinkTokenCreateRequest = {
       user: {
         client_user_id: user.$id,
       },
       client_name: `${user.firstName} ${user.lastName}`,
-      products: ["auth", "transactions"] as Products[],
+      products: ["auth", "transactions"] as Products[],
       language: "en",
-      country_codes: ["US"] as CountryCode[],
+      country_codes: ["US"] as CountryCode[],
     };

31-37: Harden getUserInfo and standardize error logging

  • Use console.error for errors.
  • Optional: Guard against empty result set to prevent user.documents[0] from being undefined.
-    const user = await database.listDocuments(
+    const user = await database.listDocuments(
       DATABASE_ID!,
       USER_COLLECTION_ID!,
       [Query.equal("userId", [userId])]
     );
 
-    return parseStringify(user.documents[0]);
+    // Optionally guard against no matches
+    // if (!user.total) return null;
+    return parseStringify(user.documents[0]);
   } catch (error) {
-    console.log(error);
+    console.error(error);
   }

118-123: Use console.error for error paths

For consistency with other catch blocks and better log semantics, use console.error here.

-  } catch (error) {
-    console.log(error);
+  } catch (error) {
+    console.error(error);
     return null;
   }

250-250: Nit: clarify error message

Minor grammar improvement for clearer logs.

-    console.error("An error occurred while creating exchanging token:", error);
+    console.error("An error occurred while exchanging the public token:", error);

274-281: Prefer getDocument for direct ID lookups

Since you’re fetching by document ID, getDocument is simpler and more efficient than listDocuments + Query.equal on $id.

-    const bank = await database.listDocuments(
-      DATABASE_ID!,
-      BANK_COLLECTION_ID!,
-      [Query.equal("$id", [documentId])]
-    );
-
-    return parseStringify(bank.documents[0]);
+    const bank = await database.getDocument(
+      DATABASE_ID!,
+      BANK_COLLECTION_ID!,
+      documentId
+    );
+    return parseStringify(bank);

266-266: Standardize error logging to console.error

Use console.error for error paths throughout for consistency and log tooling.

Also applies to: 283-283, 36-36, 122-122


286-299: Ensure uniqueness of accountId (ideally scoped by userId) at the DB level

This function assumes a 1:1 mapping. Enforce a unique index in Appwrite on either:

  • accountId (global unique), or
  • composite (userId + accountId) if the same accountId could appear under different users.

If you’d like, I can draft an Appwrite migration script to declare the attributes and create the index. Do you want me to open an issue for this?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b8d5a8e and e68cddc.

📒 Files selected for processing (1)
  • lib/actions/user.actions.ts (12 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
lib/actions/user.actions.ts (4)
lib/utils.ts (1)
  • parseStringify (79-79)
lib/appwrite.ts (6)
  • user (39-41)
  • createAdminClient (26-43)
  • account (20-22)
  • account (33-35)
  • createSessionClient (6-24)
  • database (36-38)
lib/actions/dwolla.actions.ts (2)
  • createDwollaCustomer (54-64)
  • addFundingSource (94-114)
lib/plaid.ts (1)
  • plaidClient (13-13)
🔇 Additional comments (4)
lib/actions/user.actions.ts (4)

52-52: LGTM: Using getUserInfo after sign-in

Retrieving and returning the normalized user is correct.


131-134: LGTM: Logout clears cookie and invalidates session

Deleting the session cookie and calling account.deleteSession("current") is correct.


217-219: LGTM: Processor token creation request

Typing and request fields look correct for Dwolla processor token creation.


141-154: All Plaid linkTokenCreate calls include “transactions”

Verified that in lib/actions/user.actions.ts (line 141–154) the products array is defined as ["auth", "transactions"]. A repository-wide search for linkTokenCreate shows no other production code calls that would need the same update.

Comment on lines +223 to 231
const fundingSourceUrl = await addFundingSource({
dwollaCustomerId: user.dwollaCustomerId,
processorToken,
bankName: accountData.name,
});

// If the funding source URL is not created, throw an error
if (!fundingSourceUrl) throw Error;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix: throw an Error instance instead of the constructor

throw Error throws the function object, not an Error instance.

-    if (!fundingSourceUrl) throw Error;
+    if (!fundingSourceUrl) throw new Error("Failed to create funding source URL");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const fundingSourceUrl = await addFundingSource({
dwollaCustomerId: user.dwollaCustomerId,
processorToken,
bankName: accountData.name,
});
// If the funding source URL is not created, throw an error
if (!fundingSourceUrl) throw Error;
const fundingSourceUrl = await addFundingSource({
dwollaCustomerId: user.dwollaCustomerId,
processorToken,
bankName: accountData.name,
});
// If the funding source URL is not created, throw an error
if (!fundingSourceUrl) throw new Error("Failed to create funding source URL");
🤖 Prompt for AI Agents
In lib/actions/user.actions.ts around lines 223 to 231, the code throws the
Error constructor instead of an Error instance. Replace "throw Error" with
"throw new Error()" or "throw new Error('Descriptive message')" to correctly
throw an Error object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant