Skip to content

Conversation

@dannyroosevelt
Copy link
Collaborator

@dannyroosevelt dannyroosevelt commented Jun 11, 2025

userId should be deprecated

WHY

Summary by CodeRabbit

  • New Features

    • Added support for the new externalUserId parameter as the preferred user identifier across all components.
    • Deprecated the userId parameter; usage now triggers console warnings, but remains functional for backward compatibility.
    • Enhanced user identification in account fetching and SDK calls using externalUserId.
    • Provided a migration guide to assist in transitioning to externalUserId.
  • Chores

    • Updated package version to 1.3.0.

userId should be deprecated
@vercel
Copy link

vercel bot commented Jun 11, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

3 Skipped Deployments
Name Status Preview Comments Updated (UTC)
docs-v2 ⬜️ Ignored (Inspect) Visit Preview Jun 11, 2025 9:33pm
pipedream-docs ⬜️ Ignored (Inspect) Jun 11, 2025 9:33pm
pipedream-docs-redirect-do-not-edit ⬜️ Ignored (Inspect) Jun 11, 2025 9:33pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 11, 2025

Walkthrough

This update introduces support for a new externalUserId parameter across all components, deprecating the previous userId parameter but maintaining backward compatibility. The change includes a new utility for resolving user identifiers, updates to type definitions, deprecation warnings, and consistent usage of externalUserId throughout the codebase. The package version is incremented to 1.3.0.

Changes

File(s) Change Summary
packages/connect-react/CHANGELOG.md, packages/connect-react/package.json Documented the addition of externalUserId support, deprecation of userId, and package version bump to 1.3.0.
packages/connect-react/src/components/ComponentForm.tsx Updated ComponentFormProps to use a discriminated union: either externalUserId (preferred) or deprecated userId. Added JSDoc comments for clarity.
packages/connect-react/src/components/ControlApp.tsx Integrated externalUserId from form context and passed it to the accounts fetching logic.
packages/connect-react/src/components/RemoteOptionsContainer.tsx Replaced all usage of userId with externalUserId in component logic and context extraction.
packages/connect-react/src/hooks/form-context.tsx Centralized user ID resolution via new resolveUserId utility, updated context types, added deprecation warnings, and ensured consistent use of resolved user ID throughout the context.
packages/connect-react/src/utils/resolve-user-id.ts Added new utility function resolveUserId to select the appropriate user identifier and signal deprecation or conflicts as needed.

Sequence Diagram(s)

sequenceDiagram
    participant ConsumerApp
    participant ComponentForm
    participant FormContextProvider
    participant resolveUserId
    participant SDK

    ConsumerApp->>ComponentForm: Provide externalUserId or userId
    ComponentForm->>FormContextProvider: Pass externalUserId/userId props
    FormContextProvider->>resolveUserId: Resolve user ID
    resolveUserId-->>FormContextProvider: {resolvedId, warningType}
    FormContextProvider->>SDK: Use resolvedId as user identifier
    Note over FormContextProvider: Log deprecation warning if needed
Loading

Poem

🐇
A new ID hops into view,
"externalUserId"—fresh and true!
The old one’s not gone, just gently warned,
With console hints, you’ll be informed.
Backward we leap, forward we bound,
In version 1.3, new IDs abound!
—Your friendly code rabbit


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e69ed69 and 3228bb3.

📒 Files selected for processing (1)
  • packages/connect-react/CHANGELOG.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/connect-react/CHANGELOG.md
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Lint Code Base

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.
    • @coderabbitai modularize this function.
  • 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.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @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 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
Contributor

@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 (3)
packages/connect-react/src/components/ControlApp.tsx (1)

30-38: 🛠️ Refactor suggestion

Potential unnecessary re-fetch due to unstable input object.

useAccounts({ externalUserId, app, oauth_app_id: oauthAppId }, …) is passed a new
object every render.
If useAccounts forwards that object into the React-Query queryKey, each render
invalidates the cache and triggers a refetch.

Wrap the input in useMemo (or let the hook accept primitives) to stabilise identity:

-  } = useAccounts(
-    {
-      externalUserId,
-      app: app.name_slug,
-      oauth_app_id: oauthAppId,
-    },
+  const accountInput = useMemo(
+    () => ({
+      externalUserId,
+      app: app.name_slug,
+      oauth_app_id: oauthAppId,
+    }),
+    [externalUserId, app.name_slug, oauthAppId],
+  );
+  } = useAccounts(accountInput,
packages/connect-react/src/components/RemoteOptionsContainer.tsx (1)

60-70: 🛠️ Refactor suggestion

Stabilise componentConfigureInput to prevent query-key churn.

componentConfigureInput is rebuilt on every render, which will change the
React-Query key and bypass caching even when none of the constituent values changed.

Wrap in useMemo with [externalUserId, page, context, component.key, prop.name, configuredPropsUpTo, dynamicProps?.id]
dependencies or stringify the object when building the key.

packages/connect-react/src/components/ComponentForm.tsx (1)

12-35: 🛠️ Refactor suggestion

Redundant optional props defeat the “exactly-one” union guarantee

externalUserId and userId are first declared as optional (lines 13-20) and then constrained by the XOR-like union (lines 32-35).
Because the base object already allows both to be undefined, TypeScript will happily accept {} – breaking the “one-of-two required” intent and re-introducing the possibility of both IDs being present (the never constraint is weakened by the preceding ?).

Refactor by removing the duplicate optional fields and folding the JSDoc comments into the union itself:

-export type ComponentFormProps<T extends ConfigurableProps, U = ConfiguredProps<T>> = {
-  /**
-   * Your end user ID, for whom you're configuring the component.
-   */
-  externalUserId?: string;
-  /**
-   * @deprecated Use `externalUserId` instead.
-   */
-  userId?: string;
-  ...
-} & (
-  | { externalUserId: string; userId?: never }
-  | { userId: string; externalUserId?: never }
-);
+export type ComponentFormProps<T extends ConfigurableProps, U = ConfiguredProps<T>> =
+  {
+    ...
+  } & (
+    /**
+     * Provide exactly one of the two IDs.
+     */
+    | {
+        /** Your end-user ID (preferred) */
+        externalUserId: string;
+        userId?: never;
+      }
+    | {
+        /** @deprecated ‑ use `externalUserId` instead */
+        userId: string;
+        externalUserId?: never;
+      }
+  );

This restores the compile-time guarantee that exactly one identifier is supplied.

🧹 Nitpick comments (4)
packages/connect-react/src/utils/resolve-user-id.ts (1)

9-18: Emit deprecation warning once, not on every call.

Down-stream hooks may call resolveUserId on every render causing noisy console spam.
Consider extracting the warning logic to the form-context provider so it fires only once per form instance.

packages/connect-react/src/hooks/form-context.tsx (3)

83-91: Minor: include resolveUserId call in useMemo for safety but drop superfluous arrow

You can shorten the useMemo call:

-const { resolvedId: resolvedExternalUserId, warningType } = useMemo(() => 
-  resolveUserId(externalUserId, userId), 
-  [externalUserId, userId]
-);
+const { resolvedId: resolvedExternalUserId, warningType } = useMemo(
+  () => resolveUserId(externalUserId, userId),
+  [externalUserId, userId],
+);

Not critical, just trims an unnecessary line break.


93-100: Console warnings will fire in every non-production bundle

Consider wrapping the deprecation logs with if (process.env.NODE_ENV !== "production") to avoid shipping noisy console output to end-users in production builds.


571-573: Back-compat field naming may mislead new consumers

userId is still exposed (mirroring externalUserId) to spare legacy code.
Document this clearly in code comments or plan a follow-up major version that removes the alias to prevent accidental new usage.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8616b6d and b51fc2d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • packages/connect-react/CHANGELOG.md (1 hunks)
  • packages/connect-react/package.json (1 hunks)
  • packages/connect-react/src/components/ComponentForm.tsx (2 hunks)
  • packages/connect-react/src/components/ControlApp.tsx (3 hunks)
  • packages/connect-react/src/components/RemoteOptionsContainer.tsx (2 hunks)
  • packages/connect-react/src/hooks/form-context.tsx (6 hunks)
  • packages/connect-react/src/utils/resolve-user-id.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/connect-react/src/components/ControlApp.tsx (1)
packages/connect-react/src/hooks/form-context.tsx (1)
  • useFormContext (58-67)
packages/connect-react/src/hooks/form-context.tsx (2)
packages/connect-react/src/utils/resolve-user-id.ts (1)
  • resolveUserId (5-21)
docs-v2/components/GlobalConnectProvider.jsx (1)
  • externalUserId (38-41)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: pnpm publish
  • GitHub Check: Lint Code Base
🔇 Additional comments (5)
packages/connect-react/package.json (1)

3-3: Verify ancillary version bump artefacts (lock-file, changelog tag, CI release step).

The package version is bumped to 1.3.0, but it’s easy to forget:

  1. Publishing / release automation still points at the previous tag.
  2. A pnpm-lock.yaml or package-lock.json commit may be required.
  3. A corresponding git tag / GitHub release should be queued.

Double-check these before merging to avoid broken downstream installs.

packages/connect-react/src/components/ControlApp.tsx (1)

32-33: Null safety for externalUserId.

externalUserId is typed as string | undefined; passing undefined down to
useAccounts (and ultimately the backend) may yield a 400.

Either guard:

if (!externalUserId) throw new Error("externalUserId is required in ControlApp");

or let the hook enforce it via its type signature.

packages/connect-react/src/components/RemoteOptionsContainer.tsx (1)

15-24: externalUserId propagation mirrors ControlApp concerns (undefined / empty).

Same null-safety & warning considerations apply here. Confirm backend tolerates
undefined or guard early.

packages/connect-react/CHANGELOG.md (1)

5-18: Changelog entry looks good – ensure CI release notes pick it up.

packages/connect-react/src/hooks/form-context.tsx (1)

155-160:

✅ Verification successful

Double-check backend interface: was userId renamed everywhere?

reloadComponentPropsInput now sends { externalUserId, … }. If the backend still expects userId, this will break dynamic-prop loading.

The interface definition should list externalUserId instead of userId. If it still lists userId, update the SDK types or send both keys for backward compatibility.


🏁 Script executed:

#!/usr/bin/env bash
# Verify the expected key of ReloadComponentPropsOpts across the repo
rg -A2 -n "interface ReloadComponentPropsOpts"

Length of output: 48


No definitions for ReloadComponentPropsOpts were found. Let’s broaden the search across possible type names and usages to locate the expected key:


🏁 Script executed:

#!/usr/bin/env bash
# Search for ReloadComponentProps type definitions and invocations
for term in ReloadComponentProps ReloadComponentPropsInput ReloadComponentPropsOpts reloadComponentProps; do
  echo "### Searching for $term ###"
  rg -C3 -n "$term" || true
done

Length of output: 15615


🏁 Script executed:

#!/usr/bin/env bash
echo "### ExternalUserId definition ###"
rg -n "export type ExternalUserId" -C5 packages/sdk/src/shared/index.ts || true

echo
echo "### reloadComponentProps payload construction ###"
sed -n '1370,1420p' packages/sdk/src/shared/index.ts

Length of output: 1651


Let's locate the actual ExternalUserId definition to confirm which key(s) it requires:


🏁 Script executed:

#!/usr/bin/env bash
echo "### Search for `type ExternalUserId` ###"
rg -n "type ExternalUserId" -C5 packages/sdk/src/shared/index.ts || true

echo
echo "### Search for `interface ExternalUserId` ###"
rg -n "interface ExternalUserId" -C5 packages/sdk/src/shared/index.ts || true

Length of output: 908


To confirm the exact shape of ExternalUserId, let’s pull more context around its definition:


🏁 Script executed:

#!/usr/bin/env bash
# Show full ExternalUserId definition (with surrounding lines)
rg -n "type ExternalUserId" -C10 packages/sdk/src/shared/index.ts

Length of output: 796


No action needed: ReloadComponentPropsOpts already handles both externalUserId and userId

  • The SDK’s ExternalUserId type (used by ReloadComponentPropsOpts) requires at least one of externalUserId or userId.
  • In reloadComponentProps, we destructure
    const { userId, externalUserId = userId } = opts;
    so providing only userId still yields a valid externalUserId.
  • The HTTP payload always sends external_user_id: externalUserId, matching the backend’s updated expectations.

@dannyroosevelt dannyroosevelt merged commit e8789b8 into master Jun 11, 2025
8 checks passed
@dannyroosevelt dannyroosevelt deleted the danny/connect-react/externaluserId-update branch June 11, 2025 21:40
joy-chanboop pushed a commit to joy-chanboop/pipedream that referenced this pull request Jun 21, 2025
* Adding externalUserId to connect-react

userId should be deprecated

* linting fixes

* PR feedback

* Update CHANGELOG.md
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.

2 participants