Skip to content

Conversation

@dstaley
Copy link
Member

@dstaley dstaley commented Jan 7, 2026

Description

This PR adds a new package, @clerk/msw (currently unpublished), that allows us to mock out all API interactions in the components. It also adds support for @clerk/msw and its scenario format to the clerk-js sandbox.

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

  • New Features

    • Added a local MSW-based mocking package providing comprehensive mock APIs and scenario controls for billing, sessions, users, organizations, and auth flows.
    • Sandbox: interactive scenario controls, component prop persistence via URL/localStorage, and scenario-aware mocking.
    • Added a mock Service Worker enabling client-driven request interception.
    • Developer UX: MockingProvider, page-level mocking hook, and a dev-only Mocking status indicator.
  • Documentation

    • Added READMEs for the MSW tooling and sandbox usage.

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

@vercel
Copy link

vercel bot commented Jan 7, 2026

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

Project Deployment Review Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jan 7, 2026 6:26pm

@changeset-bot
Copy link

changeset-bot bot commented Jan 7, 2026

🦋 Changeset detected

Latest commit: f66b636

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

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

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

authorized: true,
data: {
response: {
client_secret: 'mock_client_secret_' + Math.random().toString(36).substring(2, 15),

Check failure

Code scanning / CodeQL

Insecure randomness High

This uses a cryptographically insecure random number generated at
Math.random()
in a security context.

Copilot Autofix

AI 3 days ago

In general, to fix insecure randomness you must replace Math.random() (or similar weak PRNGs) with a cryptographically secure PRNG when generating any value that is (or appears to be) a secret, token, or identifier whose predictability could matter. In Node.js, this typically means using crypto.randomBytes; in modern browsers, crypto.getRandomValues.

In this specific case, we should stop using Math.random().toString(36).substring(...) for:

  • The client_secret in initializePaymentSource.
  • The mock card id in createPaymentSource.

Because this is TypeScript in a likely Node-based test environment, the safest and most portable approach is to import Node’s crypto module and create a small helper that returns a base64url-encoded or hex-encoded random string of sufficient length. We should:

  1. Add an import for crypto at the top of packages/msw/BillingService.ts.
  2. Add a private static helper on BillingService, e.g. private static generateSecureId(length: number): string, that uses crypto.randomBytes and encodes to a URL-safe string, trimming/padding to requested length.
  3. Replace:
    • mock_client_secret_' + Math.random().toString(36).substring(2, 15) with something like mock_client_secret_${this.generateSecureId(24)}.
    • 'card_mock_' + Math.random().toString(36).substring(2, 9) with card_mock_${this.generateSecureId(12)}.
      This preserves the mock behavior (random-looking, unique-ish suffixes) while using a CSPRNG, without changing the public API shape or other functionality.
Suggested changeset 1
packages/msw/BillingService.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/msw/BillingService.ts b/packages/msw/BillingService.ts
--- a/packages/msw/BillingService.ts
+++ b/packages/msw/BillingService.ts
@@ -5,10 +5,20 @@
   SessionResource,
   UserResource,
 } from '@clerk/shared/types';
+import crypto from 'crypto';
 
 type AuthCheckResult<T> = { authorized: true; data: T } | { authorized: false; error: string; status: number };
 
 export class BillingService {
+  // Generate a URL-safe, cryptographically secure random string of approximately the given length.
+  private static generateSecureId(length: number): string {
+    // Generate extra bytes to account for base64url expansion, then trim.
+    const bytes = crypto.randomBytes(length);
+    const base64 = bytes.toString('base64');
+    const base64url = base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
+    return base64url.substring(0, length);
+  }
+
   private static createPaymentSources(): BillingPaymentSourceJSON[] {
     return [
       {
@@ -238,7 +244,7 @@
       authorized: true,
       data: {
         response: {
-          client_secret: 'mock_client_secret_' + Math.random().toString(36).substring(2, 15),
+          client_secret: 'mock_client_secret_' + BillingService.generateSecureId(24),
           object: 'payment_intent',
           status: 'requires_payment_method',
         },
@@ -259,7 +265,7 @@
       data: {
         response: {
           card_type: 'visa',
-          id: 'card_mock_' + Math.random().toString(36).substring(2, 9),
+          id: 'card_mock_' + BillingService.generateSecureId(12),
           is_default: false,
           is_removable: true,
           last4: '4242',
EOF
@@ -5,10 +5,20 @@
SessionResource,
UserResource,
} from '@clerk/shared/types';
import crypto from 'crypto';

type AuthCheckResult<T> = { authorized: true; data: T } | { authorized: false; error: string; status: number };

export class BillingService {
// Generate a URL-safe, cryptographically secure random string of approximately the given length.
private static generateSecureId(length: number): string {
// Generate extra bytes to account for base64url expansion, then trim.
const bytes = crypto.randomBytes(length);
const base64 = bytes.toString('base64');
const base64url = base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
return base64url.substring(0, length);
}

private static createPaymentSources(): BillingPaymentSourceJSON[] {
return [
{
@@ -238,7 +244,7 @@
authorized: true,
data: {
response: {
client_secret: 'mock_client_secret_' + Math.random().toString(36).substring(2, 15),
client_secret: 'mock_client_secret_' + BillingService.generateSecureId(24),
object: 'payment_intent',
status: 'requires_payment_method',
},
@@ -259,7 +265,7 @@
data: {
response: {
card_type: 'visa',
id: 'card_mock_' + Math.random().toString(36).substring(2, 9),
id: 'card_mock_' + BillingService.generateSecureId(12),
is_default: false,
is_removable: true,
last4: '4242',
Copilot is powered by AI and may make mistakes. Always verify output.

static addExternalAccount(user: UserResource, strategy: string = 'oauth_google'): ExternalAccountResource {
const provider = strategy.replace('oauth_', '');
const externalAccountId = `eac_${Math.random().toString(36).substring(2, 15)}`;

Check failure

Code scanning / CodeQL

Insecure randomness High

This uses a cryptographically insecure random number generated at
Math.random()
in a security context.

Copilot Autofix

AI 3 days ago

In general, to fix insecure randomness, replace uses of Math.random() in security-relevant identifiers or tokens with a cryptographically secure random generator, such as Node’s crypto.randomBytes or the Web Crypto API’s crypto.getRandomValues. Then convert the random bytes to a string representation without weakening the randomness.

For this specific case, the minimal, behavior-preserving change is to replace Math.random().toString(36).substring(2, 15) with a cryptographically secure random string of similar length and character set. In a Node (or Node-like) environment, we can safely import randomBytes from the built-in crypto module and define a small helper, e.g. generateRandomId(length: number): string, that maps random bytes to base36 characters. We then use this helper in addExternalAccount to produce externalAccountId with the same "eac_" prefix and approximately the same length. Concretely:

  • Add an import at the top of packages/msw/UserService.ts: import { randomBytes } from 'crypto';.

  • Add a helper function near the top of the file, such as:

    function generateSecureBase36Id(length: number): string {
      const bytes = randomBytes(length);
      const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
      let result = '';
      for (let i = 0; i < bytes.length && result.length < length; i++) {
        result += chars[bytes[i] % chars.length];
      }
      return result;
    }
  • Replace line 499 so that externalAccountId becomes:

    const externalAccountId = `eac_${generateSecureBase36Id(13)}`;

This keeps the format eac_ + 13 base36-like characters and avoids changing the rest of the logic.

Suggested changeset 1
packages/msw/UserService.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/msw/UserService.ts b/packages/msw/UserService.ts
--- a/packages/msw/UserService.ts
+++ b/packages/msw/UserService.ts
@@ -5,7 +5,18 @@
   UserResource,
   Web3WalletResource,
 } from '@clerk/shared/types';
+import { randomBytes } from 'crypto';
 
+function generateSecureBase36Id(length: number): string {
+  const bytes = randomBytes(length);
+  const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
+  let result = '';
+  for (let i = 0; i < bytes.length && result.length < length; i++) {
+    result += chars[bytes[i] % chars.length];
+  }
+  return result;
+}
+
 function generateJWT(userId: string, sessionId: string, organizationId?: string | null): string {
   const header = { alg: 'RS256', typ: 'JWT' };
   const payload: Record<string, any> = {
@@ -496,7 +506,7 @@
 
   static addExternalAccount(user: UserResource, strategy: string = 'oauth_google'): ExternalAccountResource {
     const provider = strategy.replace('oauth_', '');
-    const externalAccountId = `eac_${Math.random().toString(36).substring(2, 15)}`;
+    const externalAccountId = `eac_${generateSecureBase36Id(13)}`;
 
     const newExternalAccount = this.createExternalAccount({
       emailAddress: `example@${provider === 'google' ? 'gmail' : provider}.com`,
EOF
@@ -5,7 +5,18 @@
UserResource,
Web3WalletResource,
} from '@clerk/shared/types';
import { randomBytes } from 'crypto';

function generateSecureBase36Id(length: number): string {
const bytes = randomBytes(length);
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < bytes.length && result.length < length; i++) {
result += chars[bytes[i] % chars.length];
}
return result;
}

function generateJWT(userId: string, sessionId: string, organizationId?: string | null): string {
const header = { alg: 'RS256', typ: 'JWT' };
const payload: Record<string, any> = {
@@ -496,7 +506,7 @@

static addExternalAccount(user: UserResource, strategy: string = 'oauth_google'): ExternalAccountResource {
const provider = strategy.replace('oauth_', '');
const externalAccountId = `eac_${Math.random().toString(36).substring(2, 15)}`;
const externalAccountId = `eac_${generateSecureBase36Id(13)}`;

const newExternalAccount = this.createExternalAccount({
emailAddress: `example@${provider === 'google' ? 'gmail' : provider}.com`,
Copilot is powered by AI and may make mistakes. Always verify output.
return createNoStoreResponse({
response: {
billing_interval: intervalLabel,
external_client_secret: `mock_checkout_secret_${checkoutId}`,

Check failure

Code scanning / CodeQL

Insecure randomness High

This uses a cryptographically insecure random number generated at
Math.random()
in a security context.

Copilot Autofix

AI 3 days ago

In general, any value used as a secret, token, or identifier in a security context should be generated with a cryptographically secure PRNG instead of Math.random(). In Node.js, the standard way is to use the crypto module’s randomBytes (or randomUUID for UUID-like IDs) and then encode those bytes as a string.

For this specific file, the safest minimal change is to replace the Math.random().toString(36).slice(2, 10) expressions with a helper that uses crypto.randomBytes to generate a URL-safe, base36-like string of the same length. This keeps the external format (a short alphanumeric suffix) and avoids changing the surrounding logic. Concretely:

  • Add an import for randomBytes from Node’s crypto module at the top of packages/msw/request-handlers.ts.
  • Introduce a small helper function, e.g. generateRandomId(length: number): string, that uses randomBytes to generate enough random bytes and converts them to a base36 string, trimming/padding as needed.
  • Replace the two Math.random().toString(36).slice(2, 10) occurrences at lines 1492 and 1493 with calls to generateRandomId(8) so that checkoutId and paymentIntentId remain 8-character random suffixes.

No other logic needs to change; the handler will still behave the same from the caller’s perspective (string shape and prefixes preserved), while the randomness becomes cryptographically secure.

Suggested changeset 1
packages/msw/request-handlers.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/msw/request-handlers.ts b/packages/msw/request-handlers.ts
--- a/packages/msw/request-handlers.ts
+++ b/packages/msw/request-handlers.ts
@@ -15,11 +15,21 @@
 import { SignInService } from './SignInService';
 import { SignUpService } from './SignUpService';
 import { UserService } from './UserService';
+import { randomBytes } from 'crypto';
 
 type ErrorResponse = {
   error: string;
 };
 
+function generateRandomId(length: number): string {
+  const bytes = randomBytes(Math.ceil((length * 3) / 4));
+  const base36 = bytes.toString('base64').replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
+  if (base36.length >= length) {
+    return base36.slice(0, length);
+  }
+  return (base36 + generateRandomId(length - base36.length)).slice(0, length);
+}
+
 type SuccessResponse = {
   success: boolean;
 };
@@ -1489,8 +1494,8 @@
       }
     }
 
-    const checkoutId = `chk_mock_${Math.random().toString(36).slice(2, 10)}`;
-    const paymentIntentId = `pi_mock_${Math.random().toString(36).slice(2, 10)}`;
+    const checkoutId = `chk_mock_${generateRandomId(8)}`;
+    const paymentIntentId = `pi_mock_${generateRandomId(8)}`;
     const plansResponse = BillingService.getPlans();
     const plans = plansResponse.response?.data ?? plansResponse.data ?? [];
     const paymentSourcesResult = BillingService.getPaymentSources(currentSession, currentUser);
EOF
@@ -15,11 +15,21 @@
import { SignInService } from './SignInService';
import { SignUpService } from './SignUpService';
import { UserService } from './UserService';
import { randomBytes } from 'crypto';

type ErrorResponse = {
error: string;
};

function generateRandomId(length: number): string {
const bytes = randomBytes(Math.ceil((length * 3) / 4));
const base36 = bytes.toString('base64').replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
if (base36.length >= length) {
return base36.slice(0, length);
}
return (base36 + generateRandomId(length - base36.length)).slice(0, length);
}

type SuccessResponse = {
success: boolean;
};
@@ -1489,8 +1494,8 @@
}
}

const checkoutId = `chk_mock_${Math.random().toString(36).slice(2, 10)}`;
const paymentIntentId = `pi_mock_${Math.random().toString(36).slice(2, 10)}`;
const checkoutId = `chk_mock_${generateRandomId(8)}`;
const paymentIntentId = `pi_mock_${generateRandomId(8)}`;
const plansResponse = BillingService.getPlans();
const plans = plansResponse.response?.data ?? plansResponse.data ?? [];
const paymentSourcesResult = BillingService.getPaymentSources(currentSession, currentUser);
Copilot is powered by AI and may make mistakes. Always verify output.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 7, 2026

📝 Walkthrough

Walkthrough

Adds a new local package packages/msw providing MSW-based mocking APIs and tooling: services (UserService, SessionService, BillingService, OrganizationService, SignInService, SignUpService), MockingController, PageMocking, request handlers, React provider/hook/status indicator, types, and a mock service worker; exports consolidated in packages/msw/index.ts and package.json added. Updates clerk-js sandbox to support scenarios and persist component props and scenarios, adds sandbox/public/mockServiceWorker.js, introduces scenario files and README, and adjusts clerk-js dev config and devDependencies to reference the new msw package.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.35% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(msw): Add msw package' accurately summarizes the primary change—introducing a new MSW package—and clearly identifies the main objective of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: Repository YAML (base), Organization UI (inherited)

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 7af7215 and f66b636.

📒 Files selected for processing (1)
  • packages/clerk-js/sandbox/README.md
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx,json,md,yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/clerk-js/sandbox/README.md
**/README.md

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Provide usage examples in documentation

Files:

  • packages/clerk-js/sandbox/README.md
**/*.{md,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Update documentation for API changes

Files:

  • packages/clerk-js/sandbox/README.md
**/*.{js,ts,jsx,tsx,json,md,yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Use Prettier for code formatting across all packages

Files:

  • packages/clerk-js/sandbox/README.md
**/*

⚙️ CodeRabbit configuration file

If there are no tests added or modified as part of the PR, please suggest that tests be added to cover the changes.

**/*: Only comment on issues that would block merging, ignore minor or stylistic concerns.
Restrict feedback to errors, security risks, or functionality-breaking problems.
Do not post comments on code style, formatting, or non-critical improvements.
Keep reviews short: flag only issues that make the PR unsafe to merge.
Group similar issues into a single comment instead of posting multiple notes.
Skip repetition: if a pattern repeats, mention it once at a summary level only.
Do not add general suggestions, focus strictly on merge-blocking concerns.
If there are no critical problems, respond with minimal approval (e.g., 'Looks good'). Do not add additional review.
Avoid line-by-line commentary unless it highlights a critical bug or security hole.
Highlight only issues that could cause runtime errors, data loss, or severe maintainability issues.
Ignore minor optimization opportunities, focus solely on correctness and safety.
Provide a top-level summary of critical blockers rather than detailed per-line notes.
Comment only when the issue must be resolved before merge, otherwise remain silent.
When in doubt, err on the side of fewer comments, brevity and blocking issues only.
Avoid posting any refactoring issues.

Files:

  • packages/clerk-js/sandbox/README.md
🪛 markdownlint-cli2 (0.18.1)
packages/clerk-js/sandbox/README.md

13-13: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (24)
  • GitHub Check: Integration Tests (machine, chrome, RQ)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (nextjs, chrome, 16, RQ)
  • GitHub Check: Integration Tests (nextjs, chrome, 16)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome, 16)
  • GitHub Check: Integration Tests (handshake:staging, chrome)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (billing, chrome, RQ)
  • GitHub Check: Integration Tests (quickstart, chrome, 15)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (sessions:staging, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (handshake, chrome)
  • GitHub Check: Analyze (javascript-typescript)

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

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/clerk-js/sandbox/app.ts (1)

97-110: Unhandled JSON.parse may cause runtime errors.

If URL params or localStorage contain malformed JSON, JSON.parse will throw and break the sandbox. Consider wrapping in try-catch for robustness.

Suggested fix
 function getComponentProps(component: AvailableComponent): unknown | null {
   const url = new URL(window.location.href);
   const encodedProps = url.searchParams.get(component);
   if (encodedProps) {
-    return JSON.parse(encodedProps);
+    try {
+      return JSON.parse(encodedProps);
+    } catch {
+      console.warn(`Invalid JSON in URL param for ${component}`);
+    }
   }

   const localEncodedProps = localStorage.getItem(`${COMPONENT_PROPS_NAMESPACE}-${component}`);
   if (localEncodedProps) {
-    return JSON.parse(localEncodedProps);
+    try {
+      return JSON.parse(localEncodedProps);
+    } catch {
+      console.warn(`Invalid JSON in localStorage for ${component}`);
+    }
   }

   return null;
 }
🤖 Fix all issues with AI agents
In @packages/msw/EnvironmentService.ts:
- Around line 110-112: The object literal in EnvironmentService.ts that
initializes organization_settings uses unsafe assertions like `id: undefined as
never` and `object: undefined as never`; remove these `undefined as never`
assertions and either supply real default values for `id` and `object` in the
initializer or update the TypeScript type for `organization_settings` (or its
interface) to mark `id` and `object` as optional/nullable so callers don't get
forced undefineds; update all occurrences (the initial initializer around
`id`/`object` and the other instances noted at lines 353–355) to follow the
chosen approach and ensure no `as never` assertions remain for required
properties.
- Around line 8-10: The EnvironmentPreset interface currently uses `any` for the
`social` and `meta` properties which disables type checking; change their types
to `unknown` (i.e., `social?: unknown` and `meta?: unknown`) in the
EnvironmentPreset definition so callers must explicitly narrow or cast values,
preserving flexibility for mocking while restoring type safety; update any
related usages of EnvironmentPreset where these properties are accessed to
perform proper type guards or casts.

In @packages/msw/UserService.ts:
- Around line 149-203: Add an explicit return type to the static createSession
method by declaring a Session (or appropriate) interface/type that matches the
returned object shape and annotating createSession with that type (e.g., static
createSession(...): Session). Ensure the type covers fields like id, createdAt,
lastActiveAt, latestActivity (with browserName, browserVersion, city, country,
deviceType, id, ipAddress, isMobile, object), revoke (async function),
__internal_toSnapshot, and other nullable fields so the method signature is
fully typed and matches the object literal returned by createSession.
🧹 Nitpick comments (1)
packages/msw/request-handlers.ts (1)

1072-1124: Duplicated fromArrayObjects function.

The fromArrayObjects helper function is defined identically in two bulk invitation handlers. While not a blocker, extracting this to a shared helper would improve maintainability.

Also applies to: 1153-1205

📜 Review details

Configuration used: Repository YAML (base), Organization UI (inherited)

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 d9b3215 and 0ff91ca.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (25)
  • .changeset/petite-clubs-grab.md
  • packages/clerk-js/package.json
  • packages/clerk-js/rspack.config.js
  • packages/clerk-js/sandbox/app.ts
  • packages/clerk-js/sandbox/public/mockServiceWorker.js
  • packages/clerk-js/sandbox/scenarios/index.ts
  • packages/clerk-js/sandbox/scenarios/user-button-signed-in.ts
  • packages/msw/BillingService.ts
  • packages/msw/EnvironmentService.ts
  • packages/msw/MockingController.ts
  • packages/msw/MockingProvider.tsx
  • packages/msw/MockingStatusIndicator.tsx
  • packages/msw/OrganizationService.ts
  • packages/msw/PageMocking.ts
  • packages/msw/README.md
  • packages/msw/SessionService.ts
  • packages/msw/SignInService.ts
  • packages/msw/SignUpService.ts
  • packages/msw/UserService.ts
  • packages/msw/index.ts
  • packages/msw/package.json
  • packages/msw/request-handlers.ts
  • packages/msw/tsconfig.json
  • packages/msw/types.ts
  • packages/msw/usePageMocking.ts
🧰 Additional context used
📓 Path-based instructions (16)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

All code must pass ESLint checks with the project's configuration

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/clerk-js/rspack.config.js
  • packages/msw/types.ts
  • packages/msw/EnvironmentService.ts
  • packages/msw/usePageMocking.ts
  • packages/msw/MockingController.ts
  • packages/msw/SignInService.ts
  • packages/clerk-js/sandbox/public/mockServiceWorker.js
  • packages/msw/SessionService.ts
  • packages/msw/OrganizationService.ts
  • packages/clerk-js/sandbox/scenarios/index.ts
  • packages/msw/SignUpService.ts
  • packages/msw/index.ts
  • packages/msw/PageMocking.ts
  • packages/clerk-js/sandbox/scenarios/user-button-signed-in.ts
  • packages/msw/BillingService.ts
  • packages/msw/MockingProvider.tsx
  • packages/msw/request-handlers.ts
  • packages/clerk-js/sandbox/app.ts
  • packages/msw/UserService.ts
**/*.{js,jsx,ts,tsx,json,md,yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/clerk-js/rspack.config.js
  • packages/msw/types.ts
  • packages/msw/package.json
  • packages/msw/EnvironmentService.ts
  • packages/msw/usePageMocking.ts
  • packages/msw/MockingController.ts
  • packages/msw/SignInService.ts
  • packages/msw/README.md
  • packages/clerk-js/sandbox/public/mockServiceWorker.js
  • packages/clerk-js/package.json
  • packages/msw/SessionService.ts
  • packages/msw/OrganizationService.ts
  • packages/clerk-js/sandbox/scenarios/index.ts
  • packages/msw/SignUpService.ts
  • packages/msw/index.ts
  • packages/msw/PageMocking.ts
  • packages/clerk-js/sandbox/scenarios/user-button-signed-in.ts
  • packages/msw/BillingService.ts
  • packages/msw/MockingProvider.tsx
  • packages/msw/request-handlers.ts
  • packages/msw/tsconfig.json
  • packages/clerk-js/sandbox/app.ts
  • packages/msw/UserService.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Follow established naming conventions (PascalCase for components, camelCase for variables)

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/clerk-js/rspack.config.js
  • packages/msw/types.ts
  • packages/msw/EnvironmentService.ts
  • packages/msw/usePageMocking.ts
  • packages/msw/MockingController.ts
  • packages/msw/SignInService.ts
  • packages/clerk-js/sandbox/public/mockServiceWorker.js
  • packages/msw/SessionService.ts
  • packages/msw/OrganizationService.ts
  • packages/clerk-js/sandbox/scenarios/index.ts
  • packages/msw/SignUpService.ts
  • packages/msw/index.ts
  • packages/msw/PageMocking.ts
  • packages/clerk-js/sandbox/scenarios/user-button-signed-in.ts
  • packages/msw/BillingService.ts
  • packages/msw/MockingProvider.tsx
  • packages/msw/request-handlers.ts
  • packages/clerk-js/sandbox/app.ts
  • packages/msw/UserService.ts
**/*.ts?(x)

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/msw/types.ts
  • packages/msw/EnvironmentService.ts
  • packages/msw/usePageMocking.ts
  • packages/msw/MockingController.ts
  • packages/msw/SignInService.ts
  • packages/msw/SessionService.ts
  • packages/msw/OrganizationService.ts
  • packages/clerk-js/sandbox/scenarios/index.ts
  • packages/msw/SignUpService.ts
  • packages/msw/index.ts
  • packages/msw/PageMocking.ts
  • packages/clerk-js/sandbox/scenarios/user-button-signed-in.ts
  • packages/msw/BillingService.ts
  • packages/msw/MockingProvider.tsx
  • packages/msw/request-handlers.ts
  • packages/clerk-js/sandbox/app.ts
  • packages/msw/UserService.ts
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.tsx: Use error boundaries in React components
Minimize re-renders in React components

**/*.tsx: Use proper type definitions for props and state in React components
Leverage TypeScript's type inference where possible in React components
Use proper event types for handlers in React components
Implement proper generic types for reusable React components
Use proper type guards for conditional rendering in React components

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/msw/MockingProvider.tsx
**/*.{md,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Update documentation for API changes

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/msw/README.md
  • packages/msw/MockingProvider.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components (e.g., UserProfile, NavigationMenu)
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Separate UI components from business logic components
Use useState for simple state management in React components
Use useReducer for complex state logic in React components
Implement proper state initialization in React components
Use proper state updates with callbacks in React components
Implement proper state cleanup in React components
Use Context API for theme/authentication state management
Implement proper state persistence in React applications
Use React.memo for expensive components
Implement proper useCallback for handlers in React components
Use proper useMemo for expensive computations in React components
Implement proper virtualization for lists in React components
Use proper code splitting with React.lazy in React applications
Implement proper cleanup in useEffect hooks
Use proper refs for DOM access in React components
Implement proper event listener cleanup in React components
Use proper abort controllers for fetch in React components
Implement proper subscription cleanup in React components
Use proper HTML elements for semantic HTML in React components
Implement proper ARIA attributes for accessibility in React components
Use proper heading hierarchy in React components
Implement proper form labels in React components
Use proper button types in React components
Implement proper focus management for keyboard navigation in React components
Use proper keyboard shortcuts in React components
Implement proper tab order in React components
Use proper ...

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/msw/MockingProvider.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Implement type guards for unknown types using the pattern function isType(value: unknown): value is Type
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details in classes
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Use mixins for shared behavior across unrelated classes in TypeScript
Use generic constraints with bounded type parameters like <T extends { id: string }>
Use utility types like Omit, Partial, and Pick for data transformation instead of manual type construction
Use discriminated unions instead of boolean flags for state management and API responses
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation at the type level
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Document functions with JSDoc comments including @param, @returns, @throws, and @example tags
Create custom error classes that extend Error for specific error types
Use the Result pattern for error handling instead of throwing exceptions
Use optional chaining (?.) and nullish coalescing (??) operators for safe property access
Let TypeScript infer obvious types to reduce verbosity
Use const assertions with as const for literal types
Use satisfies operator for type checking without widening types
Declare readonly arrays and objects for immutable data structures
Use spread operator and array spread for immutable updates instead of mutations
Use lazy loading for large types...

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/msw/types.ts
  • packages/msw/EnvironmentService.ts
  • packages/msw/usePageMocking.ts
  • packages/msw/MockingController.ts
  • packages/msw/SignInService.ts
  • packages/msw/SessionService.ts
  • packages/msw/OrganizationService.ts
  • packages/clerk-js/sandbox/scenarios/index.ts
  • packages/msw/SignUpService.ts
  • packages/msw/index.ts
  • packages/msw/PageMocking.ts
  • packages/clerk-js/sandbox/scenarios/user-button-signed-in.ts
  • packages/msw/BillingService.ts
  • packages/msw/MockingProvider.tsx
  • packages/msw/request-handlers.ts
  • packages/clerk-js/sandbox/app.ts
  • packages/msw/UserService.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Use ESLint with custom configurations tailored for different package types

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/clerk-js/rspack.config.js
  • packages/msw/types.ts
  • packages/msw/EnvironmentService.ts
  • packages/msw/usePageMocking.ts
  • packages/msw/MockingController.ts
  • packages/msw/SignInService.ts
  • packages/clerk-js/sandbox/public/mockServiceWorker.js
  • packages/msw/SessionService.ts
  • packages/msw/OrganizationService.ts
  • packages/clerk-js/sandbox/scenarios/index.ts
  • packages/msw/SignUpService.ts
  • packages/msw/index.ts
  • packages/msw/PageMocking.ts
  • packages/clerk-js/sandbox/scenarios/user-button-signed-in.ts
  • packages/msw/BillingService.ts
  • packages/msw/MockingProvider.tsx
  • packages/msw/request-handlers.ts
  • packages/clerk-js/sandbox/app.ts
  • packages/msw/UserService.ts
**/*.{js,ts,jsx,tsx,json,md,yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Use Prettier for code formatting across all packages

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/clerk-js/rspack.config.js
  • packages/msw/types.ts
  • packages/msw/package.json
  • packages/msw/EnvironmentService.ts
  • packages/msw/usePageMocking.ts
  • packages/msw/MockingController.ts
  • packages/msw/SignInService.ts
  • packages/msw/README.md
  • packages/clerk-js/sandbox/public/mockServiceWorker.js
  • packages/clerk-js/package.json
  • packages/msw/SessionService.ts
  • packages/msw/OrganizationService.ts
  • packages/clerk-js/sandbox/scenarios/index.ts
  • packages/msw/SignUpService.ts
  • packages/msw/index.ts
  • packages/msw/PageMocking.ts
  • packages/clerk-js/sandbox/scenarios/user-button-signed-in.ts
  • packages/msw/BillingService.ts
  • packages/msw/MockingProvider.tsx
  • packages/msw/request-handlers.ts
  • packages/msw/tsconfig.json
  • packages/clerk-js/sandbox/app.ts
  • packages/msw/UserService.ts
**/*

⚙️ CodeRabbit configuration file

If there are no tests added or modified as part of the PR, please suggest that tests be added to cover the changes.

**/*: Only comment on issues that would block merging, ignore minor or stylistic concerns.
Restrict feedback to errors, security risks, or functionality-breaking problems.
Do not post comments on code style, formatting, or non-critical improvements.
Keep reviews short: flag only issues that make the PR unsafe to merge.
Group similar issues into a single comment instead of posting multiple notes.
Skip repetition: if a pattern repeats, mention it once at a summary level only.
Do not add general suggestions, focus strictly on merge-blocking concerns.
If there are no critical problems, respond with minimal approval (e.g., 'Looks good'). Do not add additional review.
Avoid line-by-line commentary unless it highlights a critical bug or security hole.
Highlight only issues that could cause runtime errors, data loss, or severe maintainability issues.
Ignore minor optimization opportunities, focus solely on correctness and safety.
Provide a top-level summary of critical blockers rather than detailed per-line notes.
Comment only when the issue must be resolved before merge, otherwise remain silent.
When in doubt, err on the side of fewer comments, brevity and blocking issues only.
Avoid posting any refactoring issues.

Files:

  • packages/msw/MockingStatusIndicator.tsx
  • packages/clerk-js/rspack.config.js
  • packages/msw/types.ts
  • packages/msw/package.json
  • packages/msw/EnvironmentService.ts
  • packages/msw/usePageMocking.ts
  • packages/msw/MockingController.ts
  • packages/msw/SignInService.ts
  • packages/msw/README.md
  • packages/clerk-js/sandbox/public/mockServiceWorker.js
  • packages/clerk-js/package.json
  • packages/msw/SessionService.ts
  • packages/msw/OrganizationService.ts
  • packages/clerk-js/sandbox/scenarios/index.ts
  • packages/msw/SignUpService.ts
  • packages/msw/index.ts
  • packages/msw/PageMocking.ts
  • packages/clerk-js/sandbox/scenarios/user-button-signed-in.ts
  • packages/msw/BillingService.ts
  • packages/msw/MockingProvider.tsx
  • packages/msw/request-handlers.ts
  • packages/msw/tsconfig.json
  • packages/clerk-js/sandbox/app.ts
  • packages/msw/UserService.ts
packages/*/package.json

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

packages/*/package.json: Packages should export TypeScript types alongside runtime code
Follow semantic versioning for all packages

All packages must be published under @clerk namespace

packages/*/package.json: Framework packages should depend on @clerk/clerk-js for core functionality
@clerk/shared should be a common dependency for most packages in the monorepo

Files:

  • packages/msw/package.json
  • packages/clerk-js/package.json
**/package.json

📄 CodeRabbit inference engine (.cursor/rules/global.mdc)

Use pnpm as the package manager for this monorepo

Files:

  • packages/msw/package.json
  • packages/clerk-js/package.json
**/README.md

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Provide usage examples in documentation

Files:

  • packages/msw/README.md
packages/*/README.md

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

packages/*/README.md: Maintain up-to-date README files for each package
Maintain compatibility matrices for supported versions

Files:

  • packages/msw/README.md
**/index.ts

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

Avoid barrel files (index.ts re-exports) as they can cause circular dependencies

Files:

  • packages/clerk-js/sandbox/scenarios/index.ts
  • packages/msw/index.ts
🧬 Code graph analysis (6)
packages/msw/MockingStatusIndicator.tsx (2)
packages/msw/index.ts (2)
  • MockingStatusIndicator (7-7)
  • useMockingContext (6-6)
packages/msw/MockingProvider.tsx (1)
  • useMockingContext (31-37)
packages/msw/MockingController.ts (2)
packages/msw/index.ts (5)
  • MockConfig (4-4)
  • MockingController (5-5)
  • MockScenario (14-14)
  • http (18-18)
  • HttpResponse (18-18)
packages/msw/types.ts (1)
  • MockScenario (9-21)
packages/msw/OrganizationService.ts (2)
packages/shared/src/types/organization.ts (1)
  • OrganizationResource (38-69)
packages/shared/src/types/organizationMembership.ts (1)
  • OrganizationMembershipResource (47-63)
packages/msw/BillingService.ts (2)
packages/shared/src/types/session.ts (1)
  • SessionResource (210-263)
packages/shared/src/types/user.ts (1)
  • UserResource (63-135)
packages/msw/MockingProvider.tsx (2)
packages/msw/types.ts (1)
  • MockScenario (9-21)
packages/msw/usePageMocking.ts (1)
  • usePageMocking (11-51)
packages/msw/UserService.ts (2)
packages/shared/src/types/web3Wallet.ts (1)
  • Web3WalletResource (16-26)
packages/shared/src/types/user.ts (1)
  • UserResource (63-135)
⏰ 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). (26)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome, 16)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (machine, chrome, RQ)
  • GitHub Check: Integration Tests (nextjs, chrome, 16, RQ)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (quickstart, chrome, 15)
  • GitHub Check: Integration Tests (nextjs, chrome, 16)
  • GitHub Check: Integration Tests (handshake, chrome)
  • GitHub Check: Integration Tests (sessions:staging, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (billing, chrome, RQ)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (handshake:staging, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Build Packages
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (20)
packages/clerk-js/rspack.config.js (1)

504-504: Looks good.

The static file serving configuration is correct and necessary for MSW to serve the service worker file in the sandbox environment.

packages/msw/tsconfig.json (1)

1-22: Looks good.

The TypeScript configuration is valid and appropriate for a modern React library package.

.changeset/petite-clubs-grab.md (1)

1-2: Empty changeset noted.

This is acceptable for a new private package (@clerk/msw is marked "private": true). No version bump required.

packages/msw/package.json (1)

1-21: Package configuration looks good for internal use.

The package is correctly marked as private and exports TypeScript source directly, which is acceptable for internal monorepo packages. The msw version (2.11.3) aligns with the mockServiceWorker.js constant.

packages/msw/types.ts (1)

9-21: Type definition is functional.

The handlers: any[] could be more strictly typed using MSW's RequestHandler type, but this is acceptable for an internal package and doesn't block merging.

packages/clerk-js/sandbox/public/mockServiceWorker.js (1)

1-334: Standard MSW-generated service worker file.

This is the official MSW service worker file (version 2.11.3) that should not be manually modified. The version correctly matches the msw dependency in package.json.

packages/clerk-js/sandbox/app.ts (1)

433-442: Scenario integration looks correct.

The PageMocking initialization properly awaits before Clerk.load(), ensuring mocking is ready before components render.

packages/clerk-js/sandbox/scenarios/index.ts (1)

1-1: Scenario export looks good.

Clean re-export for the scenarios module.

packages/msw/MockingStatusIndicator.tsx (1)

5-48: Development-only indicator component looks good.

The component correctly guards against production rendering and provides clear visual feedback for mocking state. The pointerEvents: 'none' ensures it doesn't interfere with user interactions.

packages/msw/index.ts (1)

1-19: LGTM!

The barrel file correctly serves as the package's public API entry point. Type exports are properly distinguished using export type, and the re-exports from msw provide consumers with convenient access to commonly needed utilities.

packages/msw/SessionService.ts (2)

53-72: LGTM!

The toSnakeCase utility correctly handles various edge cases including null, undefined, Date objects, arrays, and functions. The recursive approach is appropriate for mock data which typically doesn't contain circular references.


74-220: LGTM!

The SessionService class provides a comprehensive mock session factory with proper default values and API-compatible response structures. The static methods correctly build session resources and handle serialization for Clerk API compatibility.

packages/msw/UserService.ts (2)

9-34: LGTM!

The mock JWT generation correctly structures header/payload and uses base64 encoding. The static signature is appropriate for testing purposes where cryptographic validity isn't required.


544-559: Unused variable removedPhone.

The variable removedPhone is assigned but never used. This doesn't affect functionality but could be cleaned up.

Suggested fix
 static removePhoneNumber(user: UserResource, phoneId: string): boolean {
   const index = user.phoneNumbers.findIndex(p => p.id === phoneId);
   if (index === -1) {
     return false;
   }

-  const removedPhone = user.phoneNumbers[index];
   user.phoneNumbers.splice(index, 1);

   if (user.primaryPhoneNumberId === phoneId) {
     user.primaryPhoneNumber = user.phoneNumbers[0] ?? null;
     user.primaryPhoneNumberId = user.primaryPhoneNumber?.id ?? null;
   }

   return true;
 }

Likely an incorrect or invalid review comment.

packages/msw/BillingService.ts (2)

9-9: LGTM!

Good use of discriminated union type for AuthCheckResult - this provides type-safe handling of authorized vs unauthorized states.


11-377: LGTM!

The BillingService provides comprehensive mock billing functionality with proper auth checks. The private factory methods create realistic mock data structures that align with Clerk's billing API surface.

packages/msw/request-handlers.ts (4)

163-169: LGTM!

Module-level state variables are appropriate for MSW handler architecture. The state management pattern allows handlers to share and mutate state across requests, which is necessary for simulating stateful API behavior.


171-200: LGTM!

The setClerkState function provides a clean API for test setup, properly initializing all state variables and resetting sign-up/sign-in flows. The backwards compatibility support for instance parameter is a nice touch.


202-269: LGTM!

Environment and client state handlers correctly serialize and return mock data with appropriate cache headers.


1838-1854: No merge-blocking issue: The cameron-walker mock user is unused throughout the codebase, so this handler is never invoked. While the relative fetch would fail (the file doesn't exist), this doesn't impact any tests or functionality since nothing references the cameron_walker user. If this mock user is not intended to be used, no action is needed.

Comment on lines +8 to +10
social?: any; // Allow partial OAuth providers for mocking
};
meta?: any; // Allow extra metadata for mocking
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid any type in public interfaces.

The EnvironmentPreset interface uses any for social and meta properties. While documented as allowing flexibility for mocking, using any bypasses all type checking and could hide bugs.

♻️ Recommended fix

Use unknown instead of any to maintain type safety while allowing flexibility:

     user_settings: Partial<Omit<EnvironmentJSON['user_settings'], 'attributes' | 'social'>> & {
       attributes: EnvironmentJSON['user_settings']['attributes'];
-      social?: any; // Allow partial OAuth providers for mocking
+      social?: unknown; // Allow partial OAuth providers for mocking
     };
-    meta?: any; // Allow extra metadata for mocking
+    meta?: unknown; // Allow extra metadata for mocking
   };
📝 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
social?: any; // Allow partial OAuth providers for mocking
};
meta?: any; // Allow extra metadata for mocking
social?: unknown; // Allow partial OAuth providers for mocking
};
meta?: unknown; // Allow extra metadata for mocking
🤖 Prompt for AI Agents
In @packages/msw/EnvironmentService.ts around lines 8 - 10, The
EnvironmentPreset interface currently uses `any` for the `social` and `meta`
properties which disables type checking; change their types to `unknown` (i.e.,
`social?: unknown` and `meta?: unknown`) in the EnvironmentPreset definition so
callers must explicitly narrow or cast values, preserving flexibility for
mocking while restoring type safety; update any related usages of
EnvironmentPreset where these properties are accessed to perform proper type
guards or casts.

Comment on lines +110 to +112
id: undefined as never,
max_allowed_memberships: 0,
object: undefined as never,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Type assertion undefined as never will cause runtime errors.

Lines 110, 112, 353, and 355 use undefined as never for required properties id and object in organization_settings. This forces undefined values into types that should never be undefined, bypassing TypeScript's type checking. If code attempts to access these properties expecting non-undefined values, it will fail at runtime.

🔧 Proposed fix

Either provide actual values for these properties or make them optional in the type definition:

     organization_settings: {
       actions: {
         admin_delete: true,
       },
       domains: {
         default_role: null,
         enabled: false,
         enrollment_modes: [],
       },
       enabled: false,
       force_organization_selection: false,
-      id: undefined as never,
+      id: 'org_settings_1',
       max_allowed_memberships: 0,
-      object: undefined as never,
+      object: 'organization_settings',
       slug: {
         disabled: false,
       },
     },

Also applies to: 353-355

🤖 Prompt for AI Agents
In @packages/msw/EnvironmentService.ts around lines 110 - 112, The object
literal in EnvironmentService.ts that initializes organization_settings uses
unsafe assertions like `id: undefined as never` and `object: undefined as
never`; remove these `undefined as never` assertions and either supply real
default values for `id` and `object` in the initializer or update the TypeScript
type for `organization_settings` (or its interface) to mark `id` and `object` as
optional/nullable so callers don't get forced undefineds; update all occurrences
(the initial initializer around `id`/`object` and the other instances noted at
lines 353–355) to follow the chosen approach and ensure no `as never` assertions
remain for required properties.

import { UserService } from './UserService';

export class SignUpService {
private static currentSignUp: any = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Multiple any types bypass type safety.

This file uses any type for currentSignUp state (line 7) and multiple as any assertions (lines 140, 157, 158), which completely bypass TypeScript's type checking. Similar patterns appear in SignInService.ts. These could hide type mismatches that lead to runtime errors.

Also applies to: 140-140, 157-158

Comment on lines +149 to +203
static createSession(
userId: string,
overrides: {
browserName?: string;
browserVersion?: string;
deviceType?: string;
id?: string;
ipAddress?: string;
city?: string;
country?: string;
lastActiveAt?: Date;
isMobile?: boolean;
} = {},
) {
const browserName = overrides.browserName || 'Chrome';
const browserVersion = overrides.browserVersion || '138.0.0.0';
const deviceType = overrides.deviceType || 'Macintosh';
const city = overrides.city || 'San Francisco';
const country = overrides.country || 'US';
const ipAddress = overrides.ipAddress || '192.168.1.1';
const lastActiveAt = overrides.lastActiveAt || new Date();
const isMobile = overrides.isMobile ?? false;
const sessionId = overrides.id || 'sess_default';
const createdAt = new Date(Date.now() - 86400000 * 7);

return {
abandonAt: new Date(Date.now() + 86400000 * 30),
actor: null,
createdAt,
expireAt: new Date(Date.now() + 86400000 * 7),
factorVerificationAge: [0, 0],
id: sessionId,
lastActiveAt,
lastActiveOrganizationId: null,
lastActiveToken: null,
latestActivity: {
browserName,
browserVersion,
city,
country,
deviceType,
id: `sess_activity_${sessionId.replace('sess_', '')}`,
ipAddress,
isMobile,
object: 'session_activity',
},
object: 'session',
publicUserData: null,
status: 'active',
updatedAt: lastActiveAt,
user: null,
revoke: async () => ({}) as any,
__internal_toSnapshot: () => ({}) as any,
};
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing explicit return type on createSession.

Per coding guidelines, public APIs should have explicit return types. The method returns a complex object literal that would benefit from a type annotation for clarity.

🤖 Prompt for AI Agents
In @packages/msw/UserService.ts around lines 149 - 203, Add an explicit return
type to the static createSession method by declaring a Session (or appropriate)
interface/type that matches the returned object shape and annotating
createSession with that type (e.g., static createSession(...): Session). Ensure
the type covers fields like id, createdAt, lastActiveAt, latestActivity (with
browserName, browserVersion, city, country, deviceType, id, ipAddress, isMobile,
object), revoke (async function), __internal_toSnapshot, and other nullable
fields so the method signature is fully typed and matches the object literal
returned by createSession.

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

🤖 Fix all issues with AI agents
In @packages/clerk-js/sandbox/README.md:
- Line 7: The HTML anchor in the README has a missing closing quote on the href
(the fragment containing <a
href="http://localhost:4000><code>http://localhost:4000</code></a>); fix the
malformed tag by adding the closing quote after the URL (e.g., <a
href="http://localhost:4000"><code>http://localhost:4000</code></a>) or replace
the anchor with a proper Markdown link to ensure correct rendering.
📜 Review details

Configuration used: Repository YAML (base), Organization UI (inherited)

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 0ff91ca and 7af7215.

📒 Files selected for processing (1)
  • packages/clerk-js/sandbox/README.md
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx,json,md,yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/clerk-js/sandbox/README.md
**/README.md

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Provide usage examples in documentation

Files:

  • packages/clerk-js/sandbox/README.md
**/*.{md,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Update documentation for API changes

Files:

  • packages/clerk-js/sandbox/README.md
**/*.{js,ts,jsx,tsx,json,md,yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Use Prettier for code formatting across all packages

Files:

  • packages/clerk-js/sandbox/README.md
**/*

⚙️ CodeRabbit configuration file

If there are no tests added or modified as part of the PR, please suggest that tests be added to cover the changes.

**/*: Only comment on issues that would block merging, ignore minor or stylistic concerns.
Restrict feedback to errors, security risks, or functionality-breaking problems.
Do not post comments on code style, formatting, or non-critical improvements.
Keep reviews short: flag only issues that make the PR unsafe to merge.
Group similar issues into a single comment instead of posting multiple notes.
Skip repetition: if a pattern repeats, mention it once at a summary level only.
Do not add general suggestions, focus strictly on merge-blocking concerns.
If there are no critical problems, respond with minimal approval (e.g., 'Looks good'). Do not add additional review.
Avoid line-by-line commentary unless it highlights a critical bug or security hole.
Highlight only issues that could cause runtime errors, data loss, or severe maintainability issues.
Ignore minor optimization opportunities, focus solely on correctness and safety.
Provide a top-level summary of critical blockers rather than detailed per-line notes.
Comment only when the issue must be resolved before merge, otherwise remain silent.
When in doubt, err on the side of fewer comments, brevity and blocking issues only.
Avoid posting any refactoring issues.

Files:

  • packages/clerk-js/sandbox/README.md
🪛 markdownlint-cli2 (0.18.1)
packages/clerk-js/sandbox/README.md

7-7: Bare URL used

(MD034, no-bare-urls)


13-13: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (28)
  • GitHub Check: Unit Tests (**)
  • GitHub Check: Unit Tests (shared, clerk-js, RQ)
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Static analysis
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (machine, chrome, RQ)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome, 15)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome, 16)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (nextjs, chrome, 16, RQ)
  • GitHub Check: Integration Tests (handshake, chrome)
  • GitHub Check: Integration Tests (billing, chrome, RQ)
  • GitHub Check: Integration Tests (nextjs, chrome, 16)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (handshake:staging, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (sessions:staging, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: semgrep-cloud-platform/scan

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 7, 2026

Open in StackBlitz

@clerk/agent-toolkit

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

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/dev-cli

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

@clerk/expo

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

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@7551

@clerk/upgrade

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

@clerk/vue

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

commit: f66b636

Comment on lines +11180 to +11188
msw@2.11.3:
resolution: {integrity: sha512-878imp8jxIpfzuzxYfX0qqTq1IFQz/1/RBHs/PyirSjzi+xKM/RRfIpIqHSCWjH0GxidrjhgiiXC+DWXNDvT9w==}
engines: {node: '>=18'}
hasBin: true
peerDependencies:
typescript: '>= 4.8.x'
peerDependenciesMeta:
typescript:
optional: true
Copy link
Member

Choose a reason for hiding this comment

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

Can we dedupe this to a single version of MSW across the repo?

Copy link
Member

@jacekradko jacekradko left a comment

Choose a reason for hiding this comment

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

Thanks for bringing this over! Lots to iterate and improve on here

@dstaley dstaley merged commit 879772a into main Jan 8, 2026
43 of 44 checks passed
@dstaley dstaley deleted the ds.feat/msw branch January 8, 2026 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants