Skip to content

Conversation

@panteliselef
Copy link
Member

@panteliselef panteliselef commented Nov 21, 2025

Description

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • Bug Fixes

    • Disabled automatic query retries and tightened refetch behavior to improve stability (including test defaults).
  • Chores

    • Migrated query dependency resolution to a catalog-based setup.
    • Reworked internal query client initialization for more reliable, lazy startup and clearer readiness signaling.

✏️ Tip: You can customize this high-level summary in your review settings.

@panteliselef panteliselef self-assigned this Nov 21, 2025
@changeset-bot
Copy link

changeset-bot bot commented Nov 21, 2025

🦋 Changeset detected

Latest commit: 3bb19da

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 22 packages
Name Type
@clerk/clerk-js Patch
@clerk/shared Patch
@clerk/chrome-extension Patch
@clerk/clerk-expo Patch
@clerk/agent-toolkit Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/elements Patch
@clerk/expo-passkeys Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/clerk-react Patch
@clerk/remix Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch
@clerk/themes Patch
@clerk/types Patch
@clerk/vue Patch
@clerk/localizations Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Nov 21, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
clerk-js-sandbox Ready Ready Preview Comment Nov 24, 2025 0:42am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 2025

Walkthrough

This patch defers TanStack Query Client initialization with explicit default options (retry and refetch behaviors disabled), migrates @tanstack/query-core to a pnpm catalog entry, updates test defaults, and refactors the shared React hook to use event-driven state for query client availability.

Changes

Cohort / File(s) Summary
Dependency catalog and resolution
pnpm-workspace.yaml, packages/clerk-js/package.json, packages/shared/package.json
Added pnpm catalog entry tanstack mapping '@tanstack/query-core'5.87.4; updated both packages to reference "catalog:tanstack" instead of a fixed version string.
Changeset entry
.changeset/thirty-pears-reply.md
Added changeset patching @clerk/clerk-js and @clerk/shared and noting to disable retry in the QueryClient.
QueryClient initialization and configuration
packages/clerk-js/src/core/clerk.ts
Added RQ_CLIENT_TAG, ClerkRQClient type, clerkQueryClientConfig with retry/refetch flags disabled, and private #initQueryClient to lazy-load @tanstack/query-core, instantiate QueryClient, wrap it with a tagged object, and emit ready status. __internal_queryClient now uses #initQueryClient.
Test client configuration
packages/clerk-js/src/test/mock-helpers.ts
Set defaultQueryClient defaultOptions: refetchOnWindowFocus, refetchOnReconnect, and refetchOnMount to false.
Query client hook refactoring
packages/shared/src/react/clerk-rq/use-clerk-query-client.ts
Added internal ClerkRQClient type, isTaggedRQClient guard, getQueryClientState resolver; refactored hook to subscribe to clerk.queryClientStatus and derive {client, isLoaded} from events instead of direct property access; public signature unchanged.

Sequence Diagram

sequenceDiagram
    participant Component as React Component
    participant Hook as useClerkQueryClient
    participant Clerk as Clerk Instance
    participant QueryClient as `@tanstack/query-core`

    Component->>Hook: call useClerkQueryClient()
    Hook->>Clerk: subscribe to queryClientStatus
    Note over Clerk: client not initialized
    Component->>Component: render with isLoaded=false

    Clerk->>Clerk: access __internal_queryClient -> `#initQueryClient`()
    Clerk->>QueryClient: lazy-load and create QueryClient with clerkQueryClientConfig
    QueryClient-->>Clerk: QueryClient instance
    Clerk->>Clerk: wrap with RQ_CLIENT_TAG and emit "ready"

    Clerk-->>Hook: queryClientStatus change
    Hook->>Clerk: getQueryClientState(clerk)
    Hook->>Component: update state {client, isLoaded:true}
    Component->>Component: re-render with isLoaded=true
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review packages/clerk-js/src/core/clerk.ts for correct lazy-load semantics, tag usage, and race conditions around #initQueryClient.
  • Verify event emission/listener lifecycle and cleanup in packages/shared/src/react/clerk-rq/use-clerk-query-client.ts.
  • Confirm test and production QueryClient configs match intended defaults.
  • Ensure pnpm catalog entry in pnpm-workspace.yaml resolves as expected across environments.

Poem

🐰
I hid the client in a burrow deep,
No retries now disturb its sleep,
A catalog maps the path I tread,
Events wake it from cozy bed,
Hopping ready — queries leap! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: setting default query options (retry disabled) across queryClient in both shared and clerk-js packages, which is the central focus of all modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch elef/consolidate-query-client-settings

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 21, 2025

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@7285

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@7285

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@7285

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@7285

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@7285

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@7285

@clerk/elements

npm i https://pkg.pr.new/@clerk/elements@7285

@clerk/clerk-expo

npm i https://pkg.pr.new/@clerk/clerk-expo@7285

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@7285

@clerk/express

npm i https://pkg.pr.new/@clerk/express@7285

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@7285

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@7285

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@7285

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@7285

@clerk/clerk-react

npm i https://pkg.pr.new/@clerk/clerk-react@7285

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@7285

@clerk/remix

npm i https://pkg.pr.new/@clerk/remix@7285

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@7285

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@7285

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@7285

@clerk/themes

npm i https://pkg.pr.new/@clerk/themes@7285

@clerk/types

npm i https://pkg.pr.new/@clerk/types@7285

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@7285

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@7285

commit: 3bb19da

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: 0

🧹 Nitpick comments (2)
packages/shared/src/react/clerk-rq/use-clerk-query-client.ts (1)

62-69: Consider strengthening the type guard to validate the client property.

The isTaggedRQClient type guard checks for the __tag property but doesn't verify that the client property exists or is a QueryClient. While this is likely safe given internal usage, adding a validation for the client property would make the guard more robust.

Apply this diff to strengthen the type guard:

 const isTaggedRQClient = (value: unknown): value is ClerkRQClient => {
   return (
     typeof value === 'object' &&
     value !== null &&
     '__tag' in (value as Record<string, unknown>) &&
-    (value as Record<string, unknown>).__tag === 'clerk-rq-client'
+    (value as Record<string, unknown>).__tag === 'clerk-rq-client' &&
+    'client' in (value as Record<string, unknown>)
   );
 };
packages/clerk-js/src/core/clerk.ts (1)

299-316: Consider adding error handling for query client initialization.

The #initQueryClient method uses a fire-and-forget pattern with dynamic import but doesn't handle initialization failures. If the import fails or the QueryClient constructor throws, the #queryClient remains undefined and the queryClientStatus event is never emitted, leaving consumers in a perpetual loading state.

Apply this diff to add error handling:

 #initQueryClient = (): void => {
   if (this.#queryClient) {
     return;
   }
 
   void import('./query-core')
     .then(module => module.QueryClient)
     .then(QueryClientCtor => {
       if (this.#queryClient) {
         return;
       }
 
       this.#queryClient = new QueryClientCtor(clerkQueryClientConfig);
 
       // @ts-expect-error - queryClientStatus is not typed
       this.#publicEventBus.emit('queryClientStatus', 'ready');
+    })
+    .catch(error => {
+      // Log initialization failure but don't throw
+      console.error('Failed to initialize query client:', error);
+      // Optionally emit error event
+      // @ts-expect-error - queryClientStatus is not typed
+      this.#publicEventBus.emit('queryClientStatus', 'error');
     });
 };
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 69833fe and fab9ef2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • .changeset/thirty-pears-reply.md (1 hunks)
  • packages/clerk-js/package.json (1 hunks)
  • packages/clerk-js/src/core/clerk.ts (4 hunks)
  • packages/clerk-js/src/test/mock-helpers.ts (1 hunks)
  • packages/shared/package.json (1 hunks)
  • packages/shared/src/react/clerk-rq/use-clerk-query-client.ts (1 hunks)
  • pnpm-workspace.yaml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/clerk-js/src/core/clerk.ts (1)
packages/clerk-js/src/core/query-core.ts (1)
  • QueryClient (3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (9)
packages/shared/src/react/clerk-rq/use-clerk-query-client.ts (2)

71-79: LGTM!

The getQueryClientState function correctly handles both the initialized and uninitialized query client states, providing a mock client when the real one isn't ready yet.


81-101: LGTM!

The event-driven approach for tracking query client initialization is well-implemented:

  • Initial state is correctly derived
  • Event subscription properly updates state
  • Cleanup prevents memory leaks
  • Falls back to mock client when not loaded
packages/shared/package.json (1)

166-166: LGTM!

The migration to catalog-based resolution for @tanstack/query-core aligns with the new catalog entry in pnpm-workspace.yaml and maintains version consistency.

pnpm-workspace.yaml (1)

21-23: LGTM!

The new catalog entry for TanStack Query provides centralized version management across the workspace, which is a best practice for monorepos.

packages/clerk-js/src/test/mock-helpers.ts (1)

58-60: LGTM!

Disabling refetch behaviors in test configuration improves test determinism and prevents flaky tests caused by automatic query refetches. This aligns with the production query client configuration.

packages/clerk-js/package.json (1)

74-74: LGTM!

The migration to catalog-based resolution maintains version consistency across the workspace and aligns with the catalog entry in pnpm-workspace.yaml.

packages/clerk-js/src/core/clerk.ts (3)

97-97: LGTM!

The type-only imports and discriminated union pattern using RQ_CLIENT_TAG are well-designed and enable proper tree-shaking while maintaining type safety.

Also applies to: 201-203


205-217: LGTM!

The query client configuration is well-thought-out:

  • Disables retry to use fapiClient's existing retry logic
  • Disables automatic refetch on window focus/reconnect to reduce unnecessary requests
  • Enables refetch on mount for stale data
  • Clear comments explain the design decisions

264-273: LGTM!

The getter pattern ensures lazy initialization while protecting against re-initialization via the guard in #initQueryClient. Returns undefined safely when the client isn't ready yet.

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

🧹 Nitpick comments (2)
packages/clerk-js/src/core/clerk.ts (2)

201-217: Centralized query client config is clear and aligned with intent

Extracting RQ_CLIENT_TAG, ClerkRQClient, and clerkQueryClientConfig makes the internal query client shape and its defaults explicit and easy to audit. The chosen defaults (no internal retries, no focus/reconnect refetch, refetch-on-mount enabled) fit well with the comment about delegating retry behavior to fapiClient.

If you anticipate needing per-environment tuning later, you could consider threading an optional override into #initQueryClient (or into ClerkOptions) and shallow-merging it into clerkQueryClientConfig, but that’s not necessary for this PR.


264-316: Lazy query client init flow looks correct; consider logging import failures

The interaction between __internal_queryClient and #initQueryClient is sound: the getter kicks off async initialization, returns a tagged wrapper only once the client exists, and guards against duplicate construction if multiple calls race.

One small improvement for observability would be to surface failures of the dynamic import or constructor, so consumers have something concrete to debug instead of a silently missing client. You can, for example, log via the existing debugLogger:

   #initQueryClient = (): void => {
     if (this.#queryClient) {
       return;
     }
 
     void import('./query-core')
       .then(module => module.QueryClient)
       .then(QueryClientCtor => {
         if (this.#queryClient) {
           return;
         }
 
         this.#queryClient = new QueryClientCtor(clerkQueryClientConfig);
 
         // @ts-expect-error - queryClientStatus is not typed
         this.#publicEventBus.emit('queryClientStatus', 'ready');
-      });
+      })
+      .catch(error => {
+        debugLogger.error('Failed to initialize QueryClient', { error }, 'clerk');
+      });
   };

This keeps behavior the same on success while giving a clear signal in dev/production logs when something goes wrong during initialization.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fab9ef2 and 3bb19da.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • .changeset/thirty-pears-reply.md (1 hunks)
  • packages/clerk-js/package.json (1 hunks)
  • packages/clerk-js/src/core/clerk.ts (4 hunks)
  • packages/clerk-js/src/test/mock-helpers.ts (1 hunks)
  • packages/shared/package.json (1 hunks)
  • packages/shared/src/react/clerk-rq/use-clerk-query-client.ts (1 hunks)
  • pnpm-workspace.yaml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/shared/src/react/clerk-rq/use-clerk-query-client.ts
  • packages/clerk-js/package.json
  • packages/clerk-js/src/test/mock-helpers.ts
  • pnpm-workspace.yaml
  • .changeset/thirty-pears-reply.md
🧰 Additional context used
🧬 Code graph analysis (1)
packages/clerk-js/src/core/clerk.ts (1)
packages/clerk-js/src/core/query-core.ts (1)
  • QueryClient (3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (1)
packages/clerk-js/src/core/clerk.ts (1)

97-97: Type-only import for QueryClient/QueryClientConfig is appropriate

Using a type import here keeps runtime bundling tied to the local ./query-core dynamic import while still giving the class strong typing for #queryClient and ClerkRQClient. This looks correct and consistent with the lazy-initialization approach.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants