From 4d472a31f854914685d7f39970e03ad30bbf89c5 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 18 Feb 2026 10:29:03 -0600 Subject: [PATCH 01/10] feat(shared,nextjs,astro,react-router,tanstack-react-start,express,nuxt): remove clerkUIVersion and deprecate clerkJSVersion Remove the `clerkUIVersion` prop from all SDKs and deprecate the `clerkJSVersion` prop with @deprecated JSDoc annotations. --- .changeset/remove-clerk-ui-version.md | 11 +++++++++++ packages/astro/src/env.d.ts | 1 - packages/astro/src/integration/create-integration.ts | 3 --- .../astro/src/internal/merge-env-vars-with-params.ts | 2 -- .../astro/src/server/build-clerk-hotload-script.ts | 1 - packages/astro/src/server/get-safe-env.ts | 1 - packages/astro/src/types.ts | 4 ---- packages/express/src/utils.ts | 1 - packages/nextjs/src/pages/ClerkScripts.tsx | 3 +-- packages/nextjs/src/server/constants.ts | 1 - .../nextjs/src/utils/mergeNextClerkPropsWithEnv.ts | 1 - packages/nuxt/src/module.ts | 1 - .../src/client/ReactRouterClerkProvider.tsx | 2 -- packages/react-router/src/client/types.ts | 1 - packages/react-router/src/server/utils.ts | 1 - packages/react-router/src/utils/env.ts | 1 - .../shared/src/__tests__/loadClerkJsScript.spec.ts | 5 ----- packages/shared/src/loadClerkJsScript.ts | 6 +++--- packages/shared/src/types/clerk.ts | 5 +---- packages/tanstack-react-start/src/client/types.ts | 1 - packages/tanstack-react-start/src/client/utils.ts | 3 --- packages/tanstack-react-start/src/server/constants.ts | 1 - .../tanstack-react-start/src/server/utils/index.ts | 1 - packages/tanstack-react-start/src/utils/env.ts | 1 - 24 files changed, 16 insertions(+), 42 deletions(-) create mode 100644 .changeset/remove-clerk-ui-version.md diff --git a/.changeset/remove-clerk-ui-version.md b/.changeset/remove-clerk-ui-version.md new file mode 100644 index 00000000000..35934f14c4c --- /dev/null +++ b/.changeset/remove-clerk-ui-version.md @@ -0,0 +1,11 @@ +--- +'@clerk/shared': minor +'@clerk/nextjs': minor +'@clerk/astro': minor +'@clerk/react-router': minor +'@clerk/tanstack-react-start': minor +'@clerk/express': minor +'@clerk/nuxt': minor +--- + +Remove `clerkUIVersion` prop and deprecate `clerkJSVersion` prop across all SDKs diff --git a/packages/astro/src/env.d.ts b/packages/astro/src/env.d.ts index 205d514c786..e1778007d82 100644 --- a/packages/astro/src/env.d.ts +++ b/packages/astro/src/env.d.ts @@ -6,7 +6,6 @@ interface InternalEnv { readonly PUBLIC_CLERK_JS_URL?: string; readonly PUBLIC_CLERK_JS_VERSION?: string; readonly PUBLIC_CLERK_UI_URL?: string; - readonly PUBLIC_CLERK_UI_VERSION?: string; readonly PUBLIC_CLERK_PREFETCH_UI?: string; readonly CLERK_API_KEY?: string; readonly CLERK_API_URL?: string; diff --git a/packages/astro/src/integration/create-integration.ts b/packages/astro/src/integration/create-integration.ts index 624df99a03a..90a8ae243a6 100644 --- a/packages/astro/src/integration/create-integration.ts +++ b/packages/astro/src/integration/create-integration.ts @@ -22,7 +22,6 @@ function createIntegration() // These are not provided when the "bundled" integration is used const clerkJSUrl = (params as any)?.clerkJSUrl as string | undefined; const clerkJSVersion = (params as any)?.clerkJSVersion as string | undefined; - const clerkUIVersion = (params as any)?.clerkUIVersion as string | undefined; const prefetchUI = (params as any)?.prefetchUI as boolean | undefined; const hasUI = !!(params as any)?.ui; @@ -60,7 +59,6 @@ function createIntegration() ...buildEnvVarFromOption(domain, 'PUBLIC_CLERK_DOMAIN'), ...buildEnvVarFromOption(clerkJSUrl, 'PUBLIC_CLERK_JS_URL'), ...buildEnvVarFromOption(clerkJSVersion, 'PUBLIC_CLERK_JS_VERSION'), - ...buildEnvVarFromOption(clerkUIVersion, 'PUBLIC_CLERK_UI_VERSION'), ...buildEnvVarFromOption( prefetchUI === false || hasUI ? 'false' : undefined, 'PUBLIC_CLERK_PREFETCH_UI', @@ -145,7 +143,6 @@ function createClerkEnvSchema() { PUBLIC_CLERK_JS_URL: envField.string({ context: 'client', access: 'public', optional: true, url: true }), PUBLIC_CLERK_JS_VERSION: envField.string({ context: 'client', access: 'public', optional: true }), PUBLIC_CLERK_UI_URL: envField.string({ context: 'client', access: 'public', optional: true, url: true }), - PUBLIC_CLERK_UI_VERSION: envField.string({ context: 'client', access: 'public', optional: true }), PUBLIC_CLERK_PREFETCH_UI: envField.string({ context: 'client', access: 'public', optional: true }), PUBLIC_CLERK_TELEMETRY_DISABLED: envField.boolean({ context: 'client', access: 'public', optional: true }), PUBLIC_CLERK_TELEMETRY_DEBUG: envField.boolean({ context: 'client', access: 'public', optional: true }), diff --git a/packages/astro/src/internal/merge-env-vars-with-params.ts b/packages/astro/src/internal/merge-env-vars-with-params.ts index 39dbfd9820b..6ba44e6cc3f 100644 --- a/packages/astro/src/internal/merge-env-vars-with-params.ts +++ b/packages/astro/src/internal/merge-env-vars-with-params.ts @@ -37,7 +37,6 @@ const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & InternalR clerkJSUrl: paramClerkJSUrl, clerkJSVersion: paramClerkJSVersion, clerkUIUrl: paramClerkUIUrl, - clerkUIVersion: paramClerkUIVersion, prefetchUI: paramPrefetchUI, ...rest } = params || {}; @@ -56,7 +55,6 @@ const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & InternalR clerkJSUrl: paramClerkJSUrl || import.meta.env.PUBLIC_CLERK_JS_URL, clerkJSVersion: paramClerkJSVersion || import.meta.env.PUBLIC_CLERK_JS_VERSION, clerkUIUrl: paramClerkUIUrl || import.meta.env.PUBLIC_CLERK_UI_URL, - clerkUIVersion: paramClerkUIVersion || import.meta.env.PUBLIC_CLERK_UI_VERSION, prefetchUI: mergePrefetchUIConfig(paramPrefetchUI), telemetry: paramTelemetry || { disabled: isTruthy(import.meta.env.PUBLIC_CLERK_TELEMETRY_DISABLED), diff --git a/packages/astro/src/server/build-clerk-hotload-script.ts b/packages/astro/src/server/build-clerk-hotload-script.ts index 5510759b387..40c7281e9d5 100644 --- a/packages/astro/src/server/build-clerk-hotload-script.ts +++ b/packages/astro/src/server/build-clerk-hotload-script.ts @@ -36,7 +36,6 @@ function buildClerkHotloadScript(locals: APIContext['locals']) { const clerkUIScriptSrc = clerkUIScriptUrl({ clerkUIUrl: env.clerkUIUrl, - clerkUIVersion: env.clerkUIVersion, domain, proxyUrl, publishableKey, diff --git a/packages/astro/src/server/get-safe-env.ts b/packages/astro/src/server/get-safe-env.ts index 76600aac7c0..e9560ac165a 100644 --- a/packages/astro/src/server/get-safe-env.ts +++ b/packages/astro/src/server/get-safe-env.ts @@ -36,7 +36,6 @@ function getSafeEnv(context: ContextOrLocals) { clerkJsUrl: getContextEnvVar('PUBLIC_CLERK_JS_URL', context), clerkJsVersion: getContextEnvVar('PUBLIC_CLERK_JS_VERSION', context), clerkUIUrl: getContextEnvVar('PUBLIC_CLERK_UI_URL', context), - clerkUIVersion: getContextEnvVar('PUBLIC_CLERK_UI_VERSION', context), prefetchUI: getContextEnvVar('PUBLIC_CLERK_PREFETCH_UI', context) === 'false' ? false : undefined, apiVersion: getContextEnvVar('CLERK_API_VERSION', context), apiUrl: getContextEnvVar('CLERK_API_URL', context), diff --git a/packages/astro/src/types.ts b/packages/astro/src/types.ts index 8e65d322c27..a83e9703c4e 100644 --- a/packages/astro/src/types.ts +++ b/packages/astro/src/types.ts @@ -35,10 +35,6 @@ type AstroClerkIntegrationParams = Without< * The URL that `@clerk/ui` should be hot-loaded from. */ clerkUIUrl?: string; - /** - * The npm version for `@clerk/ui`. - */ - clerkUIVersion?: string; /** * Controls prefetching of the `@clerk/ui` script. * - `false` - Skip prefetching the UI (for custom UIs using Control Components) diff --git a/packages/express/src/utils.ts b/packages/express/src/utils.ts index 73a343842df..97c11003020 100644 --- a/packages/express/src/utils.ts +++ b/packages/express/src/utils.ts @@ -14,7 +14,6 @@ export const loadClientEnv = () => { clerkJSUrl: process.env.CLERK_JS || process.env.CLERK_JS_URL || '', clerkJSVersion: process.env.CLERK_JS_VERSION || '', clerkUIUrl: process.env.CLERK_UI_URL || '', - clerkUIVersion: process.env.CLERK_UI_VERSION || '', prefetchUI: process.env.CLERK_PREFETCH_UI === 'false' ? false : undefined, }; }; diff --git a/packages/nextjs/src/pages/ClerkScripts.tsx b/packages/nextjs/src/pages/ClerkScripts.tsx index 508100da3bd..8ca71312b8e 100644 --- a/packages/nextjs/src/pages/ClerkScripts.tsx +++ b/packages/nextjs/src/pages/ClerkScripts.tsx @@ -23,7 +23,7 @@ function ClerkScript(props: { scriptUrl: string; attributes: Record({ jsUrl: options.clerkJSUrl, uiUrl: options.clerkUIUrl, clerkJSVersion: options.clerkJSVersion, - clerkUIVersion: options.clerkUIVersion, // prefetchUI config: can be false or undefined prefetchUI: options.prefetchUI, isSatellite: options.isSatellite, diff --git a/packages/react-router/src/client/ReactRouterClerkProvider.tsx b/packages/react-router/src/client/ReactRouterClerkProvider.tsx index ce2d7857719..1ee21eb578b 100644 --- a/packages/react-router/src/client/ReactRouterClerkProvider.tsx +++ b/packages/react-router/src/client/ReactRouterClerkProvider.tsx @@ -64,7 +64,6 @@ function ClerkProviderBase({ children, ...rest }: ClerkProv __clerkJSUrl, __clerkJSVersion, __clerkUIUrl, - __clerkUIVersion, __prefetchUI, __telemetryDisabled, __telemetryDebug, @@ -96,7 +95,6 @@ function ClerkProviderBase({ children, ...rest }: ClerkProv clerkJSUrl: __clerkJSUrl, clerkJSVersion: __clerkJSVersion, clerkUIUrl: __clerkUIUrl, - clerkUIVersion: __clerkUIVersion, prefetchUI: __prefetchUI, telemetry: { disabled: __telemetryDisabled, diff --git a/packages/react-router/src/client/types.ts b/packages/react-router/src/client/types.ts index 25cdd69f1a7..df3d942d5c8 100644 --- a/packages/react-router/src/client/types.ts +++ b/packages/react-router/src/client/types.ts @@ -21,7 +21,6 @@ export type ClerkState = { __clerkJSUrl: string | undefined; __clerkJSVersion: string | undefined; __clerkUIUrl: string | undefined; - __clerkUIVersion: string | undefined; __prefetchUI: boolean | undefined; __telemetryDisabled: boolean | undefined; __telemetryDebug: boolean | undefined; diff --git a/packages/react-router/src/server/utils.ts b/packages/react-router/src/server/utils.ts index ef9bfa828bd..94a75aecb9e 100644 --- a/packages/react-router/src/server/utils.ts +++ b/packages/react-router/src/server/utils.ts @@ -98,7 +98,6 @@ export function getResponseClerkState(requestState: RequestStateWithRedirectUrls __clerkJSUrl: envVars.clerkJsUrl, __clerkJSVersion: envVars.clerkJsVersion, __clerkUIUrl: envVars.clerkUIUrl, - __clerkUIVersion: envVars.clerkUIVersion, __prefetchUI: envVars.prefetchUI, __telemetryDisabled: envVars.telemetryDisabled, __telemetryDebug: envVars.telemetryDebug, diff --git a/packages/react-router/src/utils/env.ts b/packages/react-router/src/utils/env.ts index 247f50ca56c..0935e5653eb 100644 --- a/packages/react-router/src/utils/env.ts +++ b/packages/react-router/src/utils/env.ts @@ -17,7 +17,6 @@ export const getPublicEnvVariables = (context: AppLoadContext | undefined) => { clerkJsUrl: getValue('CLERK_JS_URL'), clerkJsVersion: getValue('CLERK_JS_VERSION'), clerkUIUrl: getValue('CLERK_UI_URL'), - clerkUIVersion: getValue('CLERK_UI_VERSION'), prefetchUI: getValue('CLERK_PREFETCH_UI') === 'false' ? false : undefined, telemetryDisabled: isTruthy(getValue('CLERK_TELEMETRY_DISABLED')), telemetryDebug: isTruthy(getValue('CLERK_TELEMETRY_DEBUG')), diff --git a/packages/shared/src/__tests__/loadClerkJsScript.spec.ts b/packages/shared/src/__tests__/loadClerkJsScript.spec.ts index 4cc384e7893..ac24b8196de 100644 --- a/packages/shared/src/__tests__/loadClerkJsScript.spec.ts +++ b/packages/shared/src/__tests__/loadClerkJsScript.spec.ts @@ -404,11 +404,6 @@ describe('clerkUIScriptUrl()', () => { expect(result).toBe(`https://example.clerk.com/npm/@clerk/ui@${uiPackageMajorVersion}/dist/ui.browser.js`); }); - test('uses provided clerkUIVersion', () => { - const result = clerkUIScriptUrl({ publishableKey: mockDevPublishableKey, clerkUIVersion: '1' }); - expect(result).toContain('/npm/@clerk/ui@1/'); - }); - test('uses latest as default version when not specified', () => { const result = clerkUIScriptUrl({ publishableKey: mockDevPublishableKey }); // When no version is specified, versionSelector should return the major version diff --git a/packages/shared/src/loadClerkJsScript.ts b/packages/shared/src/loadClerkJsScript.ts index 5c14b538bee..90fa10488a9 100644 --- a/packages/shared/src/loadClerkJsScript.ts +++ b/packages/shared/src/loadClerkJsScript.ts @@ -13,6 +13,7 @@ const errorThrower = buildErrorThrower({ packageName: '@clerk/shared' }); export type LoadClerkJSScriptOptions = { publishableKey: string; clerkJSUrl?: string; + /** @deprecated This option is deprecated. The Clerk SDK will automatically use the correct version. */ clerkJSVersion?: string; sdkMetadata?: SDKMetadata; proxyUrl?: string; @@ -34,7 +35,6 @@ export type LoadClerkJsScriptOptions = LoadClerkJSScriptOptions; export type LoadClerkUIScriptOptions = { publishableKey: string; clerkUIUrl?: string; - clerkUIVersion?: string; proxyUrl?: string; domain?: string; nonce?: string; @@ -232,14 +232,14 @@ export const clerkJSScriptUrl = (opts: LoadClerkJSScriptOptions) => { }; export const clerkUIScriptUrl = (opts: LoadClerkUIScriptOptions) => { - const { clerkUIUrl, clerkUIVersion, proxyUrl, domain, publishableKey } = opts; + const { clerkUIUrl, proxyUrl, domain, publishableKey } = opts; if (clerkUIUrl) { return clerkUIUrl; } const scriptHost = buildScriptHost({ publishableKey, proxyUrl, domain }); - const version = versionSelector(clerkUIVersion, UI_PACKAGE_VERSION); + const version = versionSelector(undefined, UI_PACKAGE_VERSION); return `https://${scriptHost}/npm/@clerk/ui@${version}/dist/ui.browser.js`; }; diff --git a/packages/shared/src/types/clerk.ts b/packages/shared/src/types/clerk.ts index 6f0182ab318..f3b5c8a84e8 100644 --- a/packages/shared/src/types/clerk.ts +++ b/packages/shared/src/types/clerk.ts @@ -2495,16 +2495,13 @@ export type IsomorphicClerkOptions = Without & { clerkJSUrl?: string; /** * The npm version for `@clerk/clerk-js`. + * @deprecated This prop is deprecated. The Clerk SDK will automatically use the correct version. */ clerkJSVersion?: string; /** * The URL that `@clerk/ui` should be hot-loaded from. */ clerkUIUrl?: string; - /** - * The npm version for `@clerk/ui`. - */ - clerkUIVersion?: string; /** * The Clerk Publishable Key for your instance. This can be found on the [API keys](https://dashboard.clerk.com/last-active?path=api-keys) page in the Clerk Dashboard. */ diff --git a/packages/tanstack-react-start/src/client/types.ts b/packages/tanstack-react-start/src/client/types.ts index f967a5a9395..f5ce06237a8 100644 --- a/packages/tanstack-react-start/src/client/types.ts +++ b/packages/tanstack-react-start/src/client/types.ts @@ -19,7 +19,6 @@ export type ClerkState = { __clerkJSUrl: string | undefined; __clerkJSVersion: string | undefined; __clerkUIUrl: string | undefined; - __clerkUIVersion: string | undefined; __prefetchUI: boolean | undefined; __telemetryDisabled: boolean | undefined; __telemetryDebug: boolean | undefined; diff --git a/packages/tanstack-react-start/src/client/utils.ts b/packages/tanstack-react-start/src/client/utils.ts index f89d19d7ce0..50057bef131 100644 --- a/packages/tanstack-react-start/src/client/utils.ts +++ b/packages/tanstack-react-start/src/client/utils.ts @@ -21,7 +21,6 @@ export const pickFromClerkInitState = ( __clerkJSUrl, __clerkJSVersion, __clerkUIUrl, - __clerkUIVersion, __telemetryDisabled, __telemetryDebug, __signInForceRedirectUrl, @@ -44,7 +43,6 @@ export const pickFromClerkInitState = ( clerkJSUrl: __clerkJSUrl, clerkJSVersion: __clerkJSVersion, clerkUIUrl: __clerkUIUrl, - clerkUIVersion: __clerkUIVersion, prefetchUI: __prefetchUI, telemetry: { disabled: __telemetryDisabled, @@ -71,7 +69,6 @@ export const mergeWithPublicEnvs = (restInitState: any) => { clerkJSUrl: restInitState.clerkJSUrl || envVars.clerkJsUrl, clerkJSVersion: restInitState.clerkJSVersion || envVars.clerkJsVersion, clerkUIUrl: restInitState.clerkUIUrl || envVars.clerkUIUrl, - clerkUIVersion: restInitState.clerkUIVersion || envVars.clerkUIVersion, signInForceRedirectUrl: restInitState.signInForceRedirectUrl, prefetchUI: restInitState.prefetchUI ?? envVars.prefetchUI, }; diff --git a/packages/tanstack-react-start/src/server/constants.ts b/packages/tanstack-react-start/src/server/constants.ts index 89590a6ec22..d5224b6e438 100644 --- a/packages/tanstack-react-start/src/server/constants.ts +++ b/packages/tanstack-react-start/src/server/constants.ts @@ -11,7 +11,6 @@ export const commonEnvs = () => { CLERK_JS_VERSION: publicEnvs.clerkJsVersion, CLERK_JS_URL: publicEnvs.clerkJsUrl, CLERK_UI_URL: publicEnvs.clerkUIUrl, - CLERK_UI_VERSION: publicEnvs.clerkUIVersion, PREFETCH_UI: publicEnvs.prefetchUI, PUBLISHABLE_KEY: publicEnvs.publishableKey, DOMAIN: publicEnvs.domain, diff --git a/packages/tanstack-react-start/src/server/utils/index.ts b/packages/tanstack-react-start/src/server/utils/index.ts index 717f4312807..a76e144e120 100644 --- a/packages/tanstack-react-start/src/server/utils/index.ts +++ b/packages/tanstack-react-start/src/server/utils/index.ts @@ -44,7 +44,6 @@ export function getResponseClerkState(requestState: RequestState, additionalStat __clerkJSUrl: getEnvVariable('CLERK_JS') || getEnvVariable('CLERK_JS_URL'), __clerkJSVersion: getEnvVariable('CLERK_JS_VERSION'), __clerkUIUrl: getEnvVariable('CLERK_UI_URL'), - __clerkUIVersion: getEnvVariable('CLERK_UI_VERSION'), __prefetchUI: getPrefetchUIFromEnv(), __telemetryDisabled: isTruthy(getEnvVariable('CLERK_TELEMETRY_DISABLED')), __telemetryDebug: isTruthy(getEnvVariable('CLERK_TELEMETRY_DEBUG')), diff --git a/packages/tanstack-react-start/src/utils/env.ts b/packages/tanstack-react-start/src/utils/env.ts index 0bbdca423e7..c22da072878 100644 --- a/packages/tanstack-react-start/src/utils/env.ts +++ b/packages/tanstack-react-start/src/utils/env.ts @@ -16,7 +16,6 @@ export const getPublicEnvVariables = () => { clerkJsUrl: getValue('CLERK_JS_URL') || getValue('CLERK_JS'), clerkJsVersion: getValue('CLERK_JS_VERSION'), clerkUIUrl: getValue('CLERK_UI_URL'), - clerkUIVersion: getValue('CLERK_UI_VERSION'), prefetchUI: getValue('CLERK_PREFETCH_UI') === 'false' ? false : undefined, telemetryDisabled: isTruthy(getValue('CLERK_TELEMETRY_DISABLED')), telemetryDebug: isTruthy(getValue('CLERK_TELEMETRY_DEBUG')), From debeb36f0ec39e11a4f3017410435ccd5bcda728 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 18 Feb 2026 12:49:27 -0600 Subject: [PATCH 02/10] feat(shared,nextjs,astro,react-router,tanstack-react-start,express,nuxt): rename clerkJSUrl, clerkJSVersion, clerkUIUrl to __internal_ prefix --- .changeset/internal-clerk-js-ui-props.md | 11 ++++++++ .../src/integration/create-integration.ts | 4 +-- .../__tests__/create-clerk-instance.test.ts | 12 ++++----- .../internal/merge-env-vars-with-params.ts | 12 ++++----- .../src/server/build-clerk-hotload-script.ts | 6 ++--- packages/astro/src/types.ts | 15 ++++++++--- packages/express/src/utils.ts | 6 ++--- .../src/app-router/client/ClerkScripts.tsx | 9 ++++--- .../src/app-router/server/ClerkProvider.tsx | 6 ++--- .../app-router/server/DynamicClerkScripts.tsx | 14 +++++----- packages/nextjs/src/pages/ClerkScripts.tsx | 17 ++++++++---- .../nextjs/src/pages/__tests__/index.test.tsx | 9 ++++--- .../nextjs/src/utils/clerk-script-tags.tsx | 14 +++++----- .../src/utils/mergeNextClerkPropsWithEnv.ts | 6 ++--- packages/nuxt/src/global.d.ts | 6 ++++- packages/nuxt/src/module.ts | 8 +++--- packages/nuxt/src/runtime/plugin.ts | 7 ++--- .../src/client/ReactRouterClerkProvider.tsx | 6 ++--- .../client/__tests__/ClerkProvider.test.tsx | 22 +++++++-------- .../src/__tests__/loadClerkJsScript.spec.ts | 12 ++++----- packages/shared/src/loadClerkJsScript.ts | 27 +++++++++++-------- packages/shared/src/types/clerk.ts | 9 ++++--- .../tanstack-react-start/src/client/utils.ts | 12 ++++----- 23 files changed, 147 insertions(+), 103 deletions(-) create mode 100644 .changeset/internal-clerk-js-ui-props.md diff --git a/.changeset/internal-clerk-js-ui-props.md b/.changeset/internal-clerk-js-ui-props.md new file mode 100644 index 00000000000..5a050f0c2b5 --- /dev/null +++ b/.changeset/internal-clerk-js-ui-props.md @@ -0,0 +1,11 @@ +--- +'@clerk/shared': minor +'@clerk/nextjs': minor +'@clerk/astro': minor +'@clerk/react-router': minor +'@clerk/tanstack-react-start': minor +'@clerk/express': minor +'@clerk/nuxt': minor +--- + +Rename `clerkJSUrl`, `clerkJSVersion`, and `clerkUIUrl` props to `__internal_clerkJSUrl`, `__internal_clerkJSVersion`, and `__internal_clerkUIUrl` to mark them as internal-only options. diff --git a/packages/astro/src/integration/create-integration.ts b/packages/astro/src/integration/create-integration.ts index 90a8ae243a6..a55e2048523 100644 --- a/packages/astro/src/integration/create-integration.ts +++ b/packages/astro/src/integration/create-integration.ts @@ -20,8 +20,8 @@ function createIntegration() const { proxyUrl, isSatellite, domain, signInUrl, signUpUrl, enableEnvSchema = true } = params || {}; // These are not provided when the "bundled" integration is used - const clerkJSUrl = (params as any)?.clerkJSUrl as string | undefined; - const clerkJSVersion = (params as any)?.clerkJSVersion as string | undefined; + const clerkJSUrl = (params as any)?.__internal_clerkJSUrl as string | undefined; + const clerkJSVersion = (params as any)?.__internal_clerkJSVersion as string | undefined; const prefetchUI = (params as any)?.prefetchUI as boolean | undefined; const hasUI = !!(params as any)?.ui; diff --git a/packages/astro/src/internal/__tests__/create-clerk-instance.test.ts b/packages/astro/src/internal/__tests__/create-clerk-instance.test.ts index e9f62f67a99..8811a9427d0 100644 --- a/packages/astro/src/internal/__tests__/create-clerk-instance.test.ts +++ b/packages/astro/src/internal/__tests__/create-clerk-instance.test.ts @@ -42,7 +42,7 @@ describe('getClerkUIEntryChunk', () => { (window as any).Clerk = undefined; }); - it('preserves clerkUIUrl from options', async () => { + it('preserves __internal_clerkUIUrl from options', async () => { mockLoadClerkUIScript.mockImplementation(async () => { (window as any).__internal_ClerkUICtor = mockClerkUICtor; return null; @@ -59,18 +59,18 @@ describe('getClerkUIEntryChunk', () => { // Dynamically import to get fresh module with mocks const { createClerkInstance } = await import('../create-clerk-instance'); - // Call createClerkInstance with clerkUIUrl + // Call createClerkInstance with __internal_clerkUIUrl await createClerkInstance({ publishableKey: 'pk_test_xxx', - clerkUIUrl: 'https://custom.selfhosted.example.com/ui.js', + __internal_clerkUIUrl: 'https://custom.selfhosted.example.com/ui.js', }); expect(mockLoadClerkUIScript).toHaveBeenCalled(); const loadClerkUIScriptCall = mockLoadClerkUIScript.mock.calls[0]?.[0] as Record; - expect(loadClerkUIScriptCall?.clerkUIUrl).toBe('https://custom.selfhosted.example.com/ui.js'); + expect(loadClerkUIScriptCall?.__internal_clerkUIUrl).toBe('https://custom.selfhosted.example.com/ui.js'); }); - it('does not set clerkUIUrl when not provided', async () => { + it('does not set __internal_clerkUIUrl when not provided', async () => { mockLoadClerkUIScript.mockImplementation(async () => { (window as any).__internal_ClerkUICtor = mockClerkUICtor; return null; @@ -92,6 +92,6 @@ describe('getClerkUIEntryChunk', () => { expect(mockLoadClerkUIScript).toHaveBeenCalled(); const loadClerkUIScriptCall = mockLoadClerkUIScript.mock.calls[0]?.[0] as Record; - expect(loadClerkUIScriptCall?.clerkUIUrl).toBeUndefined(); + expect(loadClerkUIScriptCall?.__internal_clerkUIUrl).toBeUndefined(); }); }); diff --git a/packages/astro/src/internal/merge-env-vars-with-params.ts b/packages/astro/src/internal/merge-env-vars-with-params.ts index 6ba44e6cc3f..52e656b8ce2 100644 --- a/packages/astro/src/internal/merge-env-vars-with-params.ts +++ b/packages/astro/src/internal/merge-env-vars-with-params.ts @@ -34,9 +34,9 @@ const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & InternalR domain: paramDomain, publishableKey: paramPublishableKey, telemetry: paramTelemetry, - clerkJSUrl: paramClerkJSUrl, - clerkJSVersion: paramClerkJSVersion, - clerkUIUrl: paramClerkUIUrl, + __internal_clerkJSUrl: paramClerkJSUrl, + __internal_clerkJSVersion: paramClerkJSVersion, + __internal_clerkUIUrl: paramClerkUIUrl, prefetchUI: paramPrefetchUI, ...rest } = params || {}; @@ -52,9 +52,9 @@ const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & InternalR // In keyless mode, use server-injected publishableKey from params publishableKey: paramPublishableKey || internalOptions?.publishableKey || import.meta.env.PUBLIC_CLERK_PUBLISHABLE_KEY || '', - clerkJSUrl: paramClerkJSUrl || import.meta.env.PUBLIC_CLERK_JS_URL, - clerkJSVersion: paramClerkJSVersion || import.meta.env.PUBLIC_CLERK_JS_VERSION, - clerkUIUrl: paramClerkUIUrl || import.meta.env.PUBLIC_CLERK_UI_URL, + __internal_clerkJSUrl: paramClerkJSUrl || import.meta.env.PUBLIC_CLERK_JS_URL, + __internal_clerkJSVersion: paramClerkJSVersion || import.meta.env.PUBLIC_CLERK_JS_VERSION, + __internal_clerkUIUrl: paramClerkUIUrl || import.meta.env.PUBLIC_CLERK_UI_URL, prefetchUI: mergePrefetchUIConfig(paramPrefetchUI), telemetry: paramTelemetry || { disabled: isTruthy(import.meta.env.PUBLIC_CLERK_TELEMETRY_DISABLED), diff --git a/packages/astro/src/server/build-clerk-hotload-script.ts b/packages/astro/src/server/build-clerk-hotload-script.ts index 40c7281e9d5..df79c035826 100644 --- a/packages/astro/src/server/build-clerk-hotload-script.ts +++ b/packages/astro/src/server/build-clerk-hotload-script.ts @@ -13,8 +13,8 @@ function buildClerkHotloadScript(locals: APIContext['locals']) { const domain = env.domain!; const clerkJsScriptSrc = clerkJSScriptUrl({ - clerkJSUrl: env.clerkJsUrl, - clerkJSVersion: env.clerkJsVersion, + __internal_clerkJSUrl: env.clerkJsUrl, + __internal_clerkJSVersion: env.clerkJsVersion, domain, proxyUrl, publishableKey, @@ -35,7 +35,7 @@ function buildClerkHotloadScript(locals: APIContext['locals']) { } const clerkUIScriptSrc = clerkUIScriptUrl({ - clerkUIUrl: env.clerkUIUrl, + __internal_clerkUIUrl: env.clerkUIUrl, domain, proxyUrl, publishableKey, diff --git a/packages/astro/src/types.ts b/packages/astro/src/types.ts index a83e9703c4e..f64d033e4aa 100644 --- a/packages/astro/src/types.ts +++ b/packages/astro/src/types.ts @@ -29,12 +29,21 @@ type AstroClerkIntegrationParams = Without< > & MultiDomainAndOrProxyPrimitives & { appearance?: Appearance; - clerkJSUrl?: string; - clerkJSVersion?: string; + /** + * The URL that `@clerk/clerk-js` should be hot-loaded from. + * @internal + */ + __internal_clerkJSUrl?: string; + /** + * The npm version for `@clerk/clerk-js`. + * @internal + */ + __internal_clerkJSVersion?: string; /** * The URL that `@clerk/ui` should be hot-loaded from. + * @internal */ - clerkUIUrl?: string; + __internal_clerkUIUrl?: string; /** * Controls prefetching of the `@clerk/ui` script. * - `false` - Skip prefetching the UI (for custom UIs using Control Components) diff --git a/packages/express/src/utils.ts b/packages/express/src/utils.ts index 97c11003020..00517e1342d 100644 --- a/packages/express/src/utils.ts +++ b/packages/express/src/utils.ts @@ -11,9 +11,9 @@ export const requestHasAuthObject = (req: ExpressRequest): req is ExpressRequest export const loadClientEnv = () => { return { publishableKey: process.env.CLERK_PUBLISHABLE_KEY || '', - clerkJSUrl: process.env.CLERK_JS || process.env.CLERK_JS_URL || '', - clerkJSVersion: process.env.CLERK_JS_VERSION || '', - clerkUIUrl: process.env.CLERK_UI_URL || '', + __internal_clerkJSUrl: process.env.CLERK_JS || process.env.CLERK_JS_URL || '', + __internal_clerkJSVersion: process.env.CLERK_JS_VERSION || '', + __internal_clerkUIUrl: process.env.CLERK_UI_URL || '', prefetchUI: process.env.CLERK_PREFETCH_UI === 'false' ? false : undefined, }; }; diff --git a/packages/nextjs/src/app-router/client/ClerkScripts.tsx b/packages/nextjs/src/app-router/client/ClerkScripts.tsx index bed102c7c08..d20af071d8d 100644 --- a/packages/nextjs/src/app-router/client/ClerkScripts.tsx +++ b/packages/nextjs/src/app-router/client/ClerkScripts.tsx @@ -5,7 +5,8 @@ import { useClerkNextOptions } from '../../client-boundary/NextOptionsContext'; import { ClerkScriptTags } from '../../utils/clerk-script-tags'; export function ClerkScripts() { - const { publishableKey, clerkJSUrl, clerkJSVersion, clerkUIUrl, nonce, prefetchUI } = useClerkNextOptions(); + const { publishableKey, __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, nonce, prefetchUI } = + useClerkNextOptions(); const { domain, proxyUrl } = useClerk(); if (!publishableKey) { @@ -15,9 +16,9 @@ export function ClerkScripts() { return ( ( { type DynamicClerkScriptsProps = { publishableKey: string; - clerkJSUrl?: string; - clerkJSVersion?: string; - clerkUIUrl?: string; + __internal_clerkJSUrl?: string; + __internal_clerkJSVersion?: string; + __internal_clerkUIUrl?: string; domain?: string; proxyUrl?: string; prefetchUI?: boolean; @@ -37,7 +37,7 @@ type DynamicClerkScriptsProps = { * nonce fetching from the rest of the page, allowing static rendering/PPR to work. */ export async function DynamicClerkScripts(props: DynamicClerkScriptsProps) { - const { publishableKey, clerkJSUrl, clerkJSVersion, clerkUIUrl, domain, proxyUrl, prefetchUI } = props; + const { publishableKey, __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, domain, proxyUrl, prefetchUI } = props; if (!publishableKey) { return null; @@ -48,9 +48,9 @@ export async function DynamicClerkScripts(props: DynamicClerkScriptsProps) { return ( { }); }); - describe('clerkUIUrl', () => { + describe('__internal_clerkUIUrl', () => { const defaultProps = { children: '' }; it('accepts string URL for custom UI location', () => { - expectTypeOf({ ...defaultProps, clerkUIUrl: 'https://custom.com/ui.js' }).toMatchTypeOf(); + expectTypeOf({ + ...defaultProps, + __internal_clerkUIUrl: 'https://custom.com/ui.js', + }).toMatchTypeOf(); }); it('accepts undefined', () => { - expectTypeOf({ ...defaultProps, clerkUIUrl: undefined }).toMatchTypeOf(); + expectTypeOf({ ...defaultProps, __internal_clerkUIUrl: undefined }).toMatchTypeOf(); }); }); diff --git a/packages/nextjs/src/utils/clerk-script-tags.tsx b/packages/nextjs/src/utils/clerk-script-tags.tsx index 588d852e349..4ee4ede3d34 100644 --- a/packages/nextjs/src/utils/clerk-script-tags.tsx +++ b/packages/nextjs/src/utils/clerk-script-tags.tsx @@ -3,9 +3,9 @@ import React from 'react'; type ClerkScriptTagsProps = { publishableKey: string; - clerkJSUrl?: string; - clerkJSVersion?: string; - clerkUIUrl?: string; + __internal_clerkJSUrl?: string; + __internal_clerkJSVersion?: string; + __internal_clerkUIUrl?: string; nonce?: string; domain?: string; proxyUrl?: string; @@ -18,13 +18,13 @@ type ClerkScriptTagsProps = { * No hooks or client-only imports — safe for both server and client components. */ export function ClerkScriptTags(props: ClerkScriptTagsProps) { - const { publishableKey, clerkJSUrl, clerkJSVersion, clerkUIUrl, nonce, domain, proxyUrl, prefetchUI } = props; + const { publishableKey, __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, nonce, domain, proxyUrl, prefetchUI } = props; const opts = { publishableKey, - clerkJSUrl, - clerkJSVersion, - clerkUIUrl, + __internal_clerkJSUrl, + __internal_clerkJSVersion, + __internal_clerkUIUrl, nonce, domain, proxyUrl, diff --git a/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts b/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts index 0050cb522f4..dd0fadc3998 100644 --- a/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts +++ b/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts @@ -22,9 +22,9 @@ export const mergeNextClerkPropsWithEnv = (props: Omit & { + clerk: Omit & { /** * The URL that `@clerk/clerk-js` should be hot-loaded from. * Supports NUXT_PUBLIC_CLERK_JS_URL env var. @@ -27,6 +27,10 @@ declare module 'nuxt/schema' { * Supports NUXT_PUBLIC_CLERK_UI_URL env var. */ uiUrl?: string; + /** + * The npm version for `@clerk/clerk-js`. + */ + clerkJSVersion?: string; }; } } diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index e38f8d864f8..36b7b976b2c 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -64,11 +64,11 @@ export default defineNuxtModule({ signUpForceRedirectUrl: options.signUpForceRedirectUrl, signUpUrl: options.signUpUrl, domain: options.domain, - // Using jsUrl/uiUrl instead of clerkJSUrl/clerkUIUrl to support + // Using jsUrl/uiUrl instead of __internal_clerkJSUrl/__internal_clerkUIUrl to support // NUXT_PUBLIC_CLERK_JS_URL and NUXT_PUBLIC_CLERK_UI_URL env vars. - jsUrl: options.clerkJSUrl, - uiUrl: options.clerkUIUrl, - clerkJSVersion: options.clerkJSVersion, + jsUrl: options.__internal_clerkJSUrl, + uiUrl: options.__internal_clerkUIUrl, + clerkJSVersion: options.__internal_clerkJSVersion, // prefetchUI config: can be false or undefined prefetchUI: options.prefetchUI, isSatellite: options.isSatellite, diff --git a/packages/nuxt/src/runtime/plugin.ts b/packages/nuxt/src/runtime/plugin.ts index 03fdeb75d25..76cd2e51c0c 100644 --- a/packages/nuxt/src/runtime/plugin.ts +++ b/packages/nuxt/src/runtime/plugin.ts @@ -21,9 +21,10 @@ export default defineNuxtPlugin(nuxtApp => { nuxtApp.vueApp.use(clerkPlugin as any, { ...clerkConfig, - // Map jsUrl/uiUrl to clerkJSUrl/clerkUIUrl as expected by the Vue plugin - clerkJSUrl: clerkConfig.jsUrl, - clerkUIUrl: clerkConfig.uiUrl, + // Map jsUrl/uiUrl to __internal_clerkJSUrl/__internal_clerkUIUrl as expected by the Vue plugin + __internal_clerkJSUrl: clerkConfig.jsUrl, + __internal_clerkUIUrl: clerkConfig.uiUrl, + __internal_clerkJSVersion: clerkConfig.clerkJSVersion, sdkMetadata: { name: PACKAGE_NAME, version: PACKAGE_VERSION, diff --git a/packages/react-router/src/client/ReactRouterClerkProvider.tsx b/packages/react-router/src/client/ReactRouterClerkProvider.tsx index 1ee21eb578b..bf36cf5dd52 100644 --- a/packages/react-router/src/client/ReactRouterClerkProvider.tsx +++ b/packages/react-router/src/client/ReactRouterClerkProvider.tsx @@ -92,9 +92,9 @@ function ClerkProviderBase({ children, ...rest }: ClerkProv signUpForceRedirectUrl: __signUpForceRedirectUrl, signInFallbackRedirectUrl: __signInFallbackRedirectUrl, signUpFallbackRedirectUrl: __signUpFallbackRedirectUrl, - clerkJSUrl: __clerkJSUrl, - clerkJSVersion: __clerkJSVersion, - clerkUIUrl: __clerkUIUrl, + __internal_clerkJSUrl: __clerkJSUrl, + __internal_clerkJSVersion: __clerkJSVersion, + __internal_clerkUIUrl: __clerkUIUrl, prefetchUI: __prefetchUI, telemetry: { disabled: __telemetryDisabled, diff --git a/packages/react-router/src/client/__tests__/ClerkProvider.test.tsx b/packages/react-router/src/client/__tests__/ClerkProvider.test.tsx index 6164770edb3..b1fc87fc87e 100644 --- a/packages/react-router/src/client/__tests__/ClerkProvider.test.tsx +++ b/packages/react-router/src/client/__tests__/ClerkProvider.test.tsx @@ -21,7 +21,7 @@ vi.mock('../../utils/assert', () => ({ warnForSsr: vi.fn(), })); -describe('ClerkProvider clerkUIUrl prop', () => { +describe('ClerkProvider __internal_clerkUIUrl prop', () => { beforeEach(() => { vi.clearAllMocks(); }); @@ -30,13 +30,13 @@ describe('ClerkProvider clerkUIUrl prop', () => { vi.clearAllMocks(); }); - it('passes clerkUIUrl prop to the underlying ClerkProvider', async () => { + it('passes __internal_clerkUIUrl prop to the underlying ClerkProvider', async () => { const { ClerkProvider } = await import('../ReactRouterClerkProvider'); render(
Test
, @@ -44,12 +44,12 @@ describe('ClerkProvider clerkUIUrl prop', () => { expect(mockClerkProvider).toHaveBeenCalledWith( expect.objectContaining({ - clerkUIUrl: 'https://custom.clerk.ui/ui.js', + __internal_clerkUIUrl: 'https://custom.clerk.ui/ui.js', }), ); }); - it('passes clerkUIUrl as undefined when not provided', async () => { + it('passes __internal_clerkUIUrl as undefined when not provided', async () => { const { ClerkProvider } = await import('../ReactRouterClerkProvider'); render( @@ -60,19 +60,19 @@ describe('ClerkProvider clerkUIUrl prop', () => { expect(mockClerkProvider).toHaveBeenCalledWith( expect.objectContaining({ - clerkUIUrl: undefined, + __internal_clerkUIUrl: undefined, }), ); }); - it('passes clerkUIUrl alongside other props', async () => { + it('passes __internal_clerkUIUrl alongside other props', async () => { const { ClerkProvider } = await import('../ReactRouterClerkProvider'); render( @@ -82,8 +82,8 @@ describe('ClerkProvider clerkUIUrl prop', () => { expect(mockClerkProvider).toHaveBeenCalledWith( expect.objectContaining({ - clerkUIUrl: 'https://custom.clerk.ui/ui.js', - clerkJSUrl: 'https://custom.clerk.js/clerk.js', + __internal_clerkUIUrl: 'https://custom.clerk.ui/ui.js', + __internal_clerkJSUrl: 'https://custom.clerk.js/clerk.js', signInUrl: '/sign-in', signUpUrl: '/sign-up', }), diff --git a/packages/shared/src/__tests__/loadClerkJsScript.spec.ts b/packages/shared/src/__tests__/loadClerkJsScript.spec.ts index ac24b8196de..69eeedf576e 100644 --- a/packages/shared/src/__tests__/loadClerkJsScript.spec.ts +++ b/packages/shared/src/__tests__/loadClerkJsScript.spec.ts @@ -147,9 +147,9 @@ describe('clerkJsScriptUrl()', () => { const mockDevPublishableKey = 'pk_test_Zm9vLWJhci0xMy5jbGVyay5hY2NvdW50cy5kZXYk'; const mockProdPublishableKey = 'pk_live_ZXhhbXBsZS5jbGVyay5jb20k'; // example.clerk.com - test('returns clerkJSUrl when provided', () => { + test('returns __internal_clerkJSUrl when provided', () => { const customUrl = 'https://custom.clerk.com/clerk.js'; - const result = clerkJsScriptUrl({ clerkJSUrl: customUrl, publishableKey: mockDevPublishableKey }); + const result = clerkJsScriptUrl({ __internal_clerkJSUrl: customUrl, publishableKey: mockDevPublishableKey }); expect(result).toBe(customUrl); }); @@ -165,8 +165,8 @@ describe('clerkJsScriptUrl()', () => { expect(result).toBe(`https://example.clerk.com/npm/@clerk/clerk-js@${jsPackageMajorVersion}/dist/clerk.browser.js`); }); - test('uses provided clerkJSVersion', () => { - const result = clerkJsScriptUrl({ publishableKey: mockDevPublishableKey, clerkJSVersion: '6' }); + test('uses provided __internal_clerkJSVersion', () => { + const result = clerkJsScriptUrl({ publishableKey: mockDevPublishableKey, __internal_clerkJSVersion: '6' }); expect(result).toContain('/npm/@clerk/clerk-js@6/'); }); }); @@ -386,9 +386,9 @@ describe('clerkUIScriptUrl()', () => { const mockDevPublishableKey = 'pk_test_Zm9vLWJhci0xMy5jbGVyay5hY2NvdW50cy5kZXYk'; const mockProdPublishableKey = 'pk_live_ZXhhbXBsZS5jbGVyay5jb20k'; // example.clerk.com - test('returns clerkUIUrl when provided', () => { + test('returns __internal_clerkUIUrl when provided', () => { const customUrl = 'https://custom.clerk.com/ui.js'; - const result = clerkUIScriptUrl({ clerkUIUrl: customUrl, publishableKey: mockDevPublishableKey }); + const result = clerkUIScriptUrl({ __internal_clerkUIUrl: customUrl, publishableKey: mockDevPublishableKey }); expect(result).toBe(customUrl); }); diff --git a/packages/shared/src/loadClerkJsScript.ts b/packages/shared/src/loadClerkJsScript.ts index 90fa10488a9..314a9156fe9 100644 --- a/packages/shared/src/loadClerkJsScript.ts +++ b/packages/shared/src/loadClerkJsScript.ts @@ -12,9 +12,13 @@ const errorThrower = buildErrorThrower({ packageName: '@clerk/shared' }); export type LoadClerkJSScriptOptions = { publishableKey: string; - clerkJSUrl?: string; - /** @deprecated This option is deprecated. The Clerk SDK will automatically use the correct version. */ - clerkJSVersion?: string; + /** @internal */ + __internal_clerkJSUrl?: string; + /** + * @deprecated This option is deprecated. The Clerk SDK will automatically use the correct version. + * @internal + */ + __internal_clerkJSVersion?: string; sdkMetadata?: SDKMetadata; proxyUrl?: string; domain?: string; @@ -34,7 +38,8 @@ export type LoadClerkJsScriptOptions = LoadClerkJSScriptOptions; export type LoadClerkUIScriptOptions = { publishableKey: string; - clerkUIUrl?: string; + /** @internal */ + __internal_clerkUIUrl?: string; proxyUrl?: string; domain?: string; nonce?: string; @@ -220,22 +225,22 @@ export const loadClerkUIScript = async (opts?: LoadClerkUIScriptOptions): Promis }; export const clerkJSScriptUrl = (opts: LoadClerkJSScriptOptions) => { - const { clerkJSUrl, clerkJSVersion, proxyUrl, domain, publishableKey } = opts; + const { __internal_clerkJSUrl, __internal_clerkJSVersion, proxyUrl, domain, publishableKey } = opts; - if (clerkJSUrl) { - return clerkJSUrl; + if (__internal_clerkJSUrl) { + return __internal_clerkJSUrl; } const scriptHost = buildScriptHost({ publishableKey, proxyUrl, domain }); - const version = versionSelector(clerkJSVersion); + const version = versionSelector(__internal_clerkJSVersion); return `https://${scriptHost}/npm/@clerk/clerk-js@${version}/dist/clerk.browser.js`; }; export const clerkUIScriptUrl = (opts: LoadClerkUIScriptOptions) => { - const { clerkUIUrl, proxyUrl, domain, publishableKey } = opts; + const { __internal_clerkUIUrl, proxyUrl, domain, publishableKey } = opts; - if (clerkUIUrl) { - return clerkUIUrl; + if (__internal_clerkUIUrl) { + return __internal_clerkUIUrl; } const scriptHost = buildScriptHost({ publishableKey, proxyUrl, domain }); diff --git a/packages/shared/src/types/clerk.ts b/packages/shared/src/types/clerk.ts index f3b5c8a84e8..db862e68147 100644 --- a/packages/shared/src/types/clerk.ts +++ b/packages/shared/src/types/clerk.ts @@ -2491,17 +2491,20 @@ export type IsomorphicClerkOptions = Without & { Clerk?: ClerkProp; /** * The URL that `@clerk/clerk-js` should be hot-loaded from. + * @internal */ - clerkJSUrl?: string; + __internal_clerkJSUrl?: string; /** * The npm version for `@clerk/clerk-js`. * @deprecated This prop is deprecated. The Clerk SDK will automatically use the correct version. + * @internal */ - clerkJSVersion?: string; + __internal_clerkJSVersion?: string; /** * The URL that `@clerk/ui` should be hot-loaded from. + * @internal */ - clerkUIUrl?: string; + __internal_clerkUIUrl?: string; /** * The Clerk Publishable Key for your instance. This can be found on the [API keys](https://dashboard.clerk.com/last-active?path=api-keys) page in the Clerk Dashboard. */ diff --git a/packages/tanstack-react-start/src/client/utils.ts b/packages/tanstack-react-start/src/client/utils.ts index 50057bef131..1c5c01814e0 100644 --- a/packages/tanstack-react-start/src/client/utils.ts +++ b/packages/tanstack-react-start/src/client/utils.ts @@ -40,9 +40,9 @@ export const pickFromClerkInitState = ( isSatellite: !!__isSatellite, signInUrl: __signInUrl, signUpUrl: __signUpUrl, - clerkJSUrl: __clerkJSUrl, - clerkJSVersion: __clerkJSVersion, - clerkUIUrl: __clerkUIUrl, + __internal_clerkJSUrl: __clerkJSUrl, + __internal_clerkJSVersion: __clerkJSVersion, + __internal_clerkUIUrl: __clerkUIUrl, prefetchUI: __prefetchUI, telemetry: { disabled: __telemetryDisabled, @@ -66,9 +66,9 @@ export const mergeWithPublicEnvs = (restInitState: any) => { isSatellite: restInitState.isSatellite || envVars.isSatellite, signInUrl: restInitState.signInUrl || envVars.signInUrl, signUpUrl: restInitState.signUpUrl || envVars.signUpUrl, - clerkJSUrl: restInitState.clerkJSUrl || envVars.clerkJsUrl, - clerkJSVersion: restInitState.clerkJSVersion || envVars.clerkJsVersion, - clerkUIUrl: restInitState.clerkUIUrl || envVars.clerkUIUrl, + __internal_clerkJSUrl: restInitState.__internal_clerkJSUrl || envVars.clerkJsUrl, + __internal_clerkJSVersion: restInitState.__internal_clerkJSVersion || envVars.clerkJsVersion, + __internal_clerkUIUrl: restInitState.__internal_clerkUIUrl || envVars.clerkUIUrl, signInForceRedirectUrl: restInitState.signInForceRedirectUrl, prefetchUI: restInitState.prefetchUI ?? envVars.prefetchUI, }; From e90378edc95abc6bb6a516bd31fe6cc4fe0a06c8 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 18 Feb 2026 14:15:57 -0600 Subject: [PATCH 03/10] fix: update integration templates and playground to use __internal_ prop names Update all ClerkProvider usages in integration test templates and playground to use the renamed __internal_clerkJSUrl, __internal_clerkUIUrl, and __internal_clerkJSVersion props. Also deduplicate pnpm-lock.yaml. --- .../custom-flows-react-vite/src/main.tsx | 4 +- .../templates/expo-web/app/_layout.tsx | 4 +- integration/templates/react-cra/src/index.tsx | 4 +- .../react-router-library/src/main.tsx | 4 +- .../templates/react-router-node/app/root.tsx | 4 +- integration/templates/react-vite/src/main.tsx | 4 +- .../src/routes/__root.tsx | 4 +- integration/templates/vue-vite/src/main.ts | 6 +-- playground/app-router/src/app/layout.tsx | 2 +- pnpm-lock.yaml | 45 ++++++++++++++++++- 10 files changed, 61 insertions(+), 20 deletions(-) diff --git a/integration/templates/custom-flows-react-vite/src/main.tsx b/integration/templates/custom-flows-react-vite/src/main.tsx index 225a3ddd20f..33b3d38e758 100644 --- a/integration/templates/custom-flows-react-vite/src/main.tsx +++ b/integration/templates/custom-flows-react-vite/src/main.tsx @@ -14,8 +14,8 @@ createRoot(document.getElementById('root')!).render(
router.push(to)} routerReplace={to => router.replace(to)} - clerkJSUrl={process.env.EXPO_PUBLIC_CLERK_JS_URL} - clerkUIUrl={process.env.EXPO_PUBLIC_CLERK_UI_URL} + __internal_clerkJSUrl={process.env.EXPO_PUBLIC_CLERK_JS_URL} + __internal_clerkUIUrl={process.env.EXPO_PUBLIC_CLERK_UI_URL} appearance={{ options: { showOptionalFields: true, diff --git a/integration/templates/react-cra/src/index.tsx b/integration/templates/react-cra/src/index.tsx index 81039d51a20..a9d172c24f1 100644 --- a/integration/templates/react-cra/src/index.tsx +++ b/integration/templates/react-cra/src/index.tsx @@ -9,8 +9,8 @@ root.render( { const navigate = useNavigate(); return ( navigate(to)} routerReplace={(to: string) => navigate(to, { replace: true })} appearance={{ diff --git a/integration/templates/tanstack-react-start/src/routes/__root.tsx b/integration/templates/tanstack-react-start/src/routes/__root.tsx index b9adc012c75..cdd38e131cd 100644 --- a/integration/templates/tanstack-react-start/src/routes/__root.tsx +++ b/integration/templates/tanstack-react-start/src/routes/__root.tsx @@ -28,8 +28,8 @@ function RootDocument({ children }: { children: React.ReactNode }) { + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c28dfeb5e9b..5ebfd5c54ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2475,7 +2475,7 @@ packages: '@expo/bunyan@4.0.1': resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==} - engines: {'0': node >=0.10.0} + engines: {node: '>=0.10.0'} '@expo/cli@0.22.26': resolution: {integrity: sha512-I689wc8Fn/AX7aUGiwrh3HnssiORMJtR2fpksX+JIe8Cj/EDleblYMSwRPd0025wrwOV9UN1KM/RuEt/QjCS3Q==} @@ -11878,6 +11878,30 @@ packages: resolution: {integrity: sha512-8xCNE/aT/EXKenuMDZ+xTVwkT8gsoHN2z/Q29l80u0ppGEXVvsKRzNMbtKhg8LS8k1tJLAHHylf6p4VFmP6XUQ==} engines: {node: '>= 0.4.0'} + pkglab-darwin-arm64@0.11.1: + resolution: {integrity: sha512-gy2qv+HWlB1y3jr0cT6wjYkVT/tLoFu2UvqE0oJcY3Ca3FqnsAPnwss8let+L1rb79hzqTSZycOuC+yc6dMiaw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + pkglab-darwin-x64@0.11.1: + resolution: {integrity: sha512-cLXqfSZs2qkvNs4QIQOAICm7nM7p6DaVPz9Wj6RXa4ovkzd5KYD3EO+vQGFojACNKKlWpn28tpp9Z3zaEldvsQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + pkglab-linux-arm64@0.11.1: + resolution: {integrity: sha512-xfXHvwHi+tt4/nRJ4dQZXbiB212YqweJQzIGinwWdHtEAvWl57PBx0giYfpQF3oOHsoVCh65vRCYHmDouLg0BQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + pkglab-linux-x64@0.11.1: + resolution: {integrity: sha512-JFICMlCTRBPi0s2zl8ZrDmh+biyK/c/DkuefdK8irfXPjAYTIq5obe7hrWYEz0v2rT/vDPrBRZ+wg6j1ThpB7Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + pkglab@0.11.1: resolution: {integrity: sha512-FdcO24fiY1DE9Y5ZHpQWfihB67x13KTZm56WNfRpsHgCRALjbSLsJRe7B7Q0OPhCN7Vrmzfg2QULZYHNT+FBIA==} engines: {node: '>=18'} @@ -29311,7 +29335,24 @@ snapshots: pkginfo@0.4.1: {} - pkglab@0.11.1: {} + pkglab-darwin-arm64@0.11.1: + optional: true + + pkglab-darwin-x64@0.11.1: + optional: true + + pkglab-linux-arm64@0.11.1: + optional: true + + pkglab-linux-x64@0.11.1: + optional: true + + pkglab@0.11.1: + optionalDependencies: + pkglab-darwin-arm64: 0.11.1 + pkglab-darwin-x64: 0.11.1 + pkglab-linux-arm64: 0.11.1 + pkglab-linux-x64: 0.11.1 playwright-core@1.56.1: {} From 13aba37f3875798db301241d3a6dab1e0a6490f1 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 18 Feb 2026 14:20:53 -0600 Subject: [PATCH 04/10] style: format DynamicClerkScripts and clerk-script-tags --- .../src/app-router/server/DynamicClerkScripts.tsx | 10 +++++++++- packages/nextjs/src/utils/clerk-script-tags.tsx | 11 ++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/nextjs/src/app-router/server/DynamicClerkScripts.tsx b/packages/nextjs/src/app-router/server/DynamicClerkScripts.tsx index 5f6ce269560..e569fba575d 100644 --- a/packages/nextjs/src/app-router/server/DynamicClerkScripts.tsx +++ b/packages/nextjs/src/app-router/server/DynamicClerkScripts.tsx @@ -37,7 +37,15 @@ type DynamicClerkScriptsProps = { * nonce fetching from the rest of the page, allowing static rendering/PPR to work. */ export async function DynamicClerkScripts(props: DynamicClerkScriptsProps) { - const { publishableKey, __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, domain, proxyUrl, prefetchUI } = props; + const { + publishableKey, + __internal_clerkJSUrl, + __internal_clerkJSVersion, + __internal_clerkUIUrl, + domain, + proxyUrl, + prefetchUI, + } = props; if (!publishableKey) { return null; diff --git a/packages/nextjs/src/utils/clerk-script-tags.tsx b/packages/nextjs/src/utils/clerk-script-tags.tsx index 4ee4ede3d34..475cde144dd 100644 --- a/packages/nextjs/src/utils/clerk-script-tags.tsx +++ b/packages/nextjs/src/utils/clerk-script-tags.tsx @@ -18,7 +18,16 @@ type ClerkScriptTagsProps = { * No hooks or client-only imports — safe for both server and client components. */ export function ClerkScriptTags(props: ClerkScriptTagsProps) { - const { publishableKey, __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, nonce, domain, proxyUrl, prefetchUI } = props; + const { + publishableKey, + __internal_clerkJSUrl, + __internal_clerkJSVersion, + __internal_clerkUIUrl, + nonce, + domain, + proxyUrl, + prefetchUI, + } = props; const opts = { publishableKey, From a186242b89aec6b4d4cfd52a3531039f541b69e3 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 18 Feb 2026 14:54:41 -0600 Subject: [PATCH 05/10] feat: add __internal_clerkUIVersion prop across all packages --- packages/astro/src/env.d.ts | 1 + packages/astro/src/integration/create-integration.ts | 3 +++ .../astro/src/internal/merge-env-vars-with-params.ts | 2 ++ packages/astro/src/server/build-clerk-hotload-script.ts | 1 + packages/astro/src/server/get-safe-env.ts | 1 + packages/astro/src/types.ts | 5 +++++ packages/express/src/utils.ts | 1 + packages/nextjs/src/app-router/server/ClerkProvider.tsx | 1 + .../nextjs/src/app-router/server/DynamicClerkScripts.tsx | 3 +++ packages/nextjs/src/pages/ClerkScripts.tsx | 2 ++ packages/nextjs/src/server/constants.ts | 1 + packages/nextjs/src/utils/clerk-script-tags.tsx | 3 +++ packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts | 1 + packages/nuxt/src/global.d.ts | 9 ++++++++- packages/nuxt/src/module.ts | 1 + packages/nuxt/src/runtime/plugin.ts | 1 + .../react-router/src/client/ReactRouterClerkProvider.tsx | 2 ++ packages/react-router/src/client/types.ts | 1 + packages/react-router/src/server/utils.ts | 1 + packages/react-router/src/utils/env.ts | 1 + packages/shared/src/loadClerkJsScript.ts | 6 ++++-- packages/shared/src/types/clerk.ts | 5 +++++ packages/tanstack-react-start/src/client/types.ts | 1 + packages/tanstack-react-start/src/client/utils.ts | 3 +++ packages/tanstack-react-start/src/server/constants.ts | 1 + packages/tanstack-react-start/src/server/utils/index.ts | 1 + packages/tanstack-react-start/src/utils/env.ts | 1 + 27 files changed, 56 insertions(+), 3 deletions(-) diff --git a/packages/astro/src/env.d.ts b/packages/astro/src/env.d.ts index e1778007d82..205d514c786 100644 --- a/packages/astro/src/env.d.ts +++ b/packages/astro/src/env.d.ts @@ -6,6 +6,7 @@ interface InternalEnv { readonly PUBLIC_CLERK_JS_URL?: string; readonly PUBLIC_CLERK_JS_VERSION?: string; readonly PUBLIC_CLERK_UI_URL?: string; + readonly PUBLIC_CLERK_UI_VERSION?: string; readonly PUBLIC_CLERK_PREFETCH_UI?: string; readonly CLERK_API_KEY?: string; readonly CLERK_API_URL?: string; diff --git a/packages/astro/src/integration/create-integration.ts b/packages/astro/src/integration/create-integration.ts index a55e2048523..18d6749701c 100644 --- a/packages/astro/src/integration/create-integration.ts +++ b/packages/astro/src/integration/create-integration.ts @@ -22,6 +22,7 @@ function createIntegration() // These are not provided when the "bundled" integration is used const clerkJSUrl = (params as any)?.__internal_clerkJSUrl as string | undefined; const clerkJSVersion = (params as any)?.__internal_clerkJSVersion as string | undefined; + const clerkUIVersion = (params as any)?.__internal_clerkUIVersion as string | undefined; const prefetchUI = (params as any)?.prefetchUI as boolean | undefined; const hasUI = !!(params as any)?.ui; @@ -59,6 +60,7 @@ function createIntegration() ...buildEnvVarFromOption(domain, 'PUBLIC_CLERK_DOMAIN'), ...buildEnvVarFromOption(clerkJSUrl, 'PUBLIC_CLERK_JS_URL'), ...buildEnvVarFromOption(clerkJSVersion, 'PUBLIC_CLERK_JS_VERSION'), + ...buildEnvVarFromOption(clerkUIVersion, 'PUBLIC_CLERK_UI_VERSION'), ...buildEnvVarFromOption( prefetchUI === false || hasUI ? 'false' : undefined, 'PUBLIC_CLERK_PREFETCH_UI', @@ -143,6 +145,7 @@ function createClerkEnvSchema() { PUBLIC_CLERK_JS_URL: envField.string({ context: 'client', access: 'public', optional: true, url: true }), PUBLIC_CLERK_JS_VERSION: envField.string({ context: 'client', access: 'public', optional: true }), PUBLIC_CLERK_UI_URL: envField.string({ context: 'client', access: 'public', optional: true, url: true }), + PUBLIC_CLERK_UI_VERSION: envField.string({ context: 'client', access: 'public', optional: true }), PUBLIC_CLERK_PREFETCH_UI: envField.string({ context: 'client', access: 'public', optional: true }), PUBLIC_CLERK_TELEMETRY_DISABLED: envField.boolean({ context: 'client', access: 'public', optional: true }), PUBLIC_CLERK_TELEMETRY_DEBUG: envField.boolean({ context: 'client', access: 'public', optional: true }), diff --git a/packages/astro/src/internal/merge-env-vars-with-params.ts b/packages/astro/src/internal/merge-env-vars-with-params.ts index 52e656b8ce2..c07e9f8d9c3 100644 --- a/packages/astro/src/internal/merge-env-vars-with-params.ts +++ b/packages/astro/src/internal/merge-env-vars-with-params.ts @@ -37,6 +37,7 @@ const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & InternalR __internal_clerkJSUrl: paramClerkJSUrl, __internal_clerkJSVersion: paramClerkJSVersion, __internal_clerkUIUrl: paramClerkUIUrl, + __internal_clerkUIVersion: paramClerkUIVersion, prefetchUI: paramPrefetchUI, ...rest } = params || {}; @@ -55,6 +56,7 @@ const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & InternalR __internal_clerkJSUrl: paramClerkJSUrl || import.meta.env.PUBLIC_CLERK_JS_URL, __internal_clerkJSVersion: paramClerkJSVersion || import.meta.env.PUBLIC_CLERK_JS_VERSION, __internal_clerkUIUrl: paramClerkUIUrl || import.meta.env.PUBLIC_CLERK_UI_URL, + __internal_clerkUIVersion: paramClerkUIVersion || import.meta.env.PUBLIC_CLERK_UI_VERSION, prefetchUI: mergePrefetchUIConfig(paramPrefetchUI), telemetry: paramTelemetry || { disabled: isTruthy(import.meta.env.PUBLIC_CLERK_TELEMETRY_DISABLED), diff --git a/packages/astro/src/server/build-clerk-hotload-script.ts b/packages/astro/src/server/build-clerk-hotload-script.ts index df79c035826..c97be95cd4e 100644 --- a/packages/astro/src/server/build-clerk-hotload-script.ts +++ b/packages/astro/src/server/build-clerk-hotload-script.ts @@ -36,6 +36,7 @@ function buildClerkHotloadScript(locals: APIContext['locals']) { const clerkUIScriptSrc = clerkUIScriptUrl({ __internal_clerkUIUrl: env.clerkUIUrl, + __internal_clerkUIVersion: env.clerkUIVersion, domain, proxyUrl, publishableKey, diff --git a/packages/astro/src/server/get-safe-env.ts b/packages/astro/src/server/get-safe-env.ts index e9560ac165a..76600aac7c0 100644 --- a/packages/astro/src/server/get-safe-env.ts +++ b/packages/astro/src/server/get-safe-env.ts @@ -36,6 +36,7 @@ function getSafeEnv(context: ContextOrLocals) { clerkJsUrl: getContextEnvVar('PUBLIC_CLERK_JS_URL', context), clerkJsVersion: getContextEnvVar('PUBLIC_CLERK_JS_VERSION', context), clerkUIUrl: getContextEnvVar('PUBLIC_CLERK_UI_URL', context), + clerkUIVersion: getContextEnvVar('PUBLIC_CLERK_UI_VERSION', context), prefetchUI: getContextEnvVar('PUBLIC_CLERK_PREFETCH_UI', context) === 'false' ? false : undefined, apiVersion: getContextEnvVar('CLERK_API_VERSION', context), apiUrl: getContextEnvVar('CLERK_API_URL', context), diff --git a/packages/astro/src/types.ts b/packages/astro/src/types.ts index f64d033e4aa..5b8a96b7ad9 100644 --- a/packages/astro/src/types.ts +++ b/packages/astro/src/types.ts @@ -44,6 +44,11 @@ type AstroClerkIntegrationParams = Without< * @internal */ __internal_clerkUIUrl?: string; + /** + * The npm version for `@clerk/ui`. + * @internal + */ + __internal_clerkUIVersion?: string; /** * Controls prefetching of the `@clerk/ui` script. * - `false` - Skip prefetching the UI (for custom UIs using Control Components) diff --git a/packages/express/src/utils.ts b/packages/express/src/utils.ts index 00517e1342d..bd138ed3dbe 100644 --- a/packages/express/src/utils.ts +++ b/packages/express/src/utils.ts @@ -14,6 +14,7 @@ export const loadClientEnv = () => { __internal_clerkJSUrl: process.env.CLERK_JS || process.env.CLERK_JS_URL || '', __internal_clerkJSVersion: process.env.CLERK_JS_VERSION || '', __internal_clerkUIUrl: process.env.CLERK_UI_URL || '', + __internal_clerkUIVersion: process.env.CLERK_UI_VERSION || '', prefetchUI: process.env.CLERK_PREFETCH_UI === 'false' ? false : undefined, }; }; diff --git a/packages/nextjs/src/app-router/server/ClerkProvider.tsx b/packages/nextjs/src/app-router/server/ClerkProvider.tsx index ac8f9e1dec6..9e454b83b4e 100644 --- a/packages/nextjs/src/app-router/server/ClerkProvider.tsx +++ b/packages/nextjs/src/app-router/server/ClerkProvider.tsx @@ -43,6 +43,7 @@ export async function ClerkProvider( __internal_clerkJSUrl={propsWithEnvs.__internal_clerkJSUrl} __internal_clerkJSVersion={propsWithEnvs.__internal_clerkJSVersion} __internal_clerkUIUrl={propsWithEnvs.__internal_clerkUIUrl} + __internal_clerkUIVersion={propsWithEnvs.__internal_clerkUIVersion} domain={propsWithEnvs.domain} proxyUrl={propsWithEnvs.proxyUrl} prefetchUI={propsWithEnvs.prefetchUI} diff --git a/packages/nextjs/src/app-router/server/DynamicClerkScripts.tsx b/packages/nextjs/src/app-router/server/DynamicClerkScripts.tsx index e569fba575d..ce4de15584f 100644 --- a/packages/nextjs/src/app-router/server/DynamicClerkScripts.tsx +++ b/packages/nextjs/src/app-router/server/DynamicClerkScripts.tsx @@ -26,6 +26,7 @@ type DynamicClerkScriptsProps = { __internal_clerkJSUrl?: string; __internal_clerkJSVersion?: string; __internal_clerkUIUrl?: string; + __internal_clerkUIVersion?: string; domain?: string; proxyUrl?: string; prefetchUI?: boolean; @@ -42,6 +43,7 @@ export async function DynamicClerkScripts(props: DynamicClerkScriptsProps) { __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, + __internal_clerkUIVersion, domain, proxyUrl, prefetchUI, @@ -59,6 +61,7 @@ export async function DynamicClerkScripts(props: DynamicClerkScriptsProps) { __internal_clerkJSUrl={__internal_clerkJSUrl} __internal_clerkJSVersion={__internal_clerkJSVersion} __internal_clerkUIUrl={__internal_clerkUIUrl} + __internal_clerkUIVersion={__internal_clerkUIVersion} nonce={nonce} domain={domain} proxyUrl={proxyUrl} diff --git a/packages/nextjs/src/pages/ClerkScripts.tsx b/packages/nextjs/src/pages/ClerkScripts.tsx index dba023d01ae..a9f7e89ebb2 100644 --- a/packages/nextjs/src/pages/ClerkScripts.tsx +++ b/packages/nextjs/src/pages/ClerkScripts.tsx @@ -28,6 +28,7 @@ export function ClerkScripts() { __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, + __internal_clerkUIVersion, nonce, prefetchUI, ui, @@ -43,6 +44,7 @@ export function ClerkScripts() { __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, + __internal_clerkUIVersion, nonce, domain, proxyUrl, diff --git a/packages/nextjs/src/server/constants.ts b/packages/nextjs/src/server/constants.ts index 4165b2ae4d1..b98542bdc27 100644 --- a/packages/nextjs/src/server/constants.ts +++ b/packages/nextjs/src/server/constants.ts @@ -4,6 +4,7 @@ import { isTruthy } from '@clerk/shared/underscore'; export const CLERK_JS_VERSION = process.env.NEXT_PUBLIC_CLERK_JS_VERSION || ''; export const CLERK_JS_URL = process.env.NEXT_PUBLIC_CLERK_JS_URL || ''; export const CLERK_UI_URL = process.env.NEXT_PUBLIC_CLERK_UI_URL || ''; +export const CLERK_UI_VERSION = process.env.NEXT_PUBLIC_CLERK_UI_VERSION || ''; export const API_VERSION = process.env.CLERK_API_VERSION || 'v1'; export const SECRET_KEY = process.env.CLERK_SECRET_KEY || ''; export const MACHINE_SECRET_KEY = process.env.CLERK_MACHINE_SECRET_KEY || ''; diff --git a/packages/nextjs/src/utils/clerk-script-tags.tsx b/packages/nextjs/src/utils/clerk-script-tags.tsx index 475cde144dd..b7d67c73cd4 100644 --- a/packages/nextjs/src/utils/clerk-script-tags.tsx +++ b/packages/nextjs/src/utils/clerk-script-tags.tsx @@ -6,6 +6,7 @@ type ClerkScriptTagsProps = { __internal_clerkJSUrl?: string; __internal_clerkJSVersion?: string; __internal_clerkUIUrl?: string; + __internal_clerkUIVersion?: string; nonce?: string; domain?: string; proxyUrl?: string; @@ -23,6 +24,7 @@ export function ClerkScriptTags(props: ClerkScriptTagsProps) { __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, + __internal_clerkUIVersion, nonce, domain, proxyUrl, @@ -34,6 +36,7 @@ export function ClerkScriptTags(props: ClerkScriptTagsProps) { __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, + __internal_clerkUIVersion, nonce, domain, proxyUrl, diff --git a/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts b/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts index dd0fadc3998..75b0a09178e 100644 --- a/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts +++ b/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts @@ -25,6 +25,7 @@ export const mergeNextClerkPropsWithEnv = (props: Omit & { + clerk: Omit< + PluginOptions, + '__internal_clerkJSUrl' | '__internal_clerkUIUrl' | '__internal_clerkJSVersion' | '__internal_clerkUIVersion' + > & { /** * The URL that `@clerk/clerk-js` should be hot-loaded from. * Supports NUXT_PUBLIC_CLERK_JS_URL env var. @@ -31,6 +34,10 @@ declare module 'nuxt/schema' { * The npm version for `@clerk/clerk-js`. */ clerkJSVersion?: string; + /** + * The npm version for `@clerk/ui`. + */ + clerkUIVersion?: string; }; } } diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index 36b7b976b2c..46ed83fce50 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -69,6 +69,7 @@ export default defineNuxtModule({ jsUrl: options.__internal_clerkJSUrl, uiUrl: options.__internal_clerkUIUrl, clerkJSVersion: options.__internal_clerkJSVersion, + clerkUIVersion: options.__internal_clerkUIVersion, // prefetchUI config: can be false or undefined prefetchUI: options.prefetchUI, isSatellite: options.isSatellite, diff --git a/packages/nuxt/src/runtime/plugin.ts b/packages/nuxt/src/runtime/plugin.ts index 76cd2e51c0c..650358ef02c 100644 --- a/packages/nuxt/src/runtime/plugin.ts +++ b/packages/nuxt/src/runtime/plugin.ts @@ -25,6 +25,7 @@ export default defineNuxtPlugin(nuxtApp => { __internal_clerkJSUrl: clerkConfig.jsUrl, __internal_clerkUIUrl: clerkConfig.uiUrl, __internal_clerkJSVersion: clerkConfig.clerkJSVersion, + __internal_clerkUIVersion: clerkConfig.clerkUIVersion, sdkMetadata: { name: PACKAGE_NAME, version: PACKAGE_VERSION, diff --git a/packages/react-router/src/client/ReactRouterClerkProvider.tsx b/packages/react-router/src/client/ReactRouterClerkProvider.tsx index bf36cf5dd52..6d27d1e5448 100644 --- a/packages/react-router/src/client/ReactRouterClerkProvider.tsx +++ b/packages/react-router/src/client/ReactRouterClerkProvider.tsx @@ -64,6 +64,7 @@ function ClerkProviderBase({ children, ...rest }: ClerkProv __clerkJSUrl, __clerkJSVersion, __clerkUIUrl, + __clerkUIVersion, __prefetchUI, __telemetryDisabled, __telemetryDebug, @@ -95,6 +96,7 @@ function ClerkProviderBase({ children, ...rest }: ClerkProv __internal_clerkJSUrl: __clerkJSUrl, __internal_clerkJSVersion: __clerkJSVersion, __internal_clerkUIUrl: __clerkUIUrl, + __internal_clerkUIVersion: __clerkUIVersion, prefetchUI: __prefetchUI, telemetry: { disabled: __telemetryDisabled, diff --git a/packages/react-router/src/client/types.ts b/packages/react-router/src/client/types.ts index df3d942d5c8..25cdd69f1a7 100644 --- a/packages/react-router/src/client/types.ts +++ b/packages/react-router/src/client/types.ts @@ -21,6 +21,7 @@ export type ClerkState = { __clerkJSUrl: string | undefined; __clerkJSVersion: string | undefined; __clerkUIUrl: string | undefined; + __clerkUIVersion: string | undefined; __prefetchUI: boolean | undefined; __telemetryDisabled: boolean | undefined; __telemetryDebug: boolean | undefined; diff --git a/packages/react-router/src/server/utils.ts b/packages/react-router/src/server/utils.ts index 94a75aecb9e..ef9bfa828bd 100644 --- a/packages/react-router/src/server/utils.ts +++ b/packages/react-router/src/server/utils.ts @@ -98,6 +98,7 @@ export function getResponseClerkState(requestState: RequestStateWithRedirectUrls __clerkJSUrl: envVars.clerkJsUrl, __clerkJSVersion: envVars.clerkJsVersion, __clerkUIUrl: envVars.clerkUIUrl, + __clerkUIVersion: envVars.clerkUIVersion, __prefetchUI: envVars.prefetchUI, __telemetryDisabled: envVars.telemetryDisabled, __telemetryDebug: envVars.telemetryDebug, diff --git a/packages/react-router/src/utils/env.ts b/packages/react-router/src/utils/env.ts index 0935e5653eb..247f50ca56c 100644 --- a/packages/react-router/src/utils/env.ts +++ b/packages/react-router/src/utils/env.ts @@ -17,6 +17,7 @@ export const getPublicEnvVariables = (context: AppLoadContext | undefined) => { clerkJsUrl: getValue('CLERK_JS_URL'), clerkJsVersion: getValue('CLERK_JS_VERSION'), clerkUIUrl: getValue('CLERK_UI_URL'), + clerkUIVersion: getValue('CLERK_UI_VERSION'), prefetchUI: getValue('CLERK_PREFETCH_UI') === 'false' ? false : undefined, telemetryDisabled: isTruthy(getValue('CLERK_TELEMETRY_DISABLED')), telemetryDebug: isTruthy(getValue('CLERK_TELEMETRY_DEBUG')), diff --git a/packages/shared/src/loadClerkJsScript.ts b/packages/shared/src/loadClerkJsScript.ts index 314a9156fe9..dab8eedfdb6 100644 --- a/packages/shared/src/loadClerkJsScript.ts +++ b/packages/shared/src/loadClerkJsScript.ts @@ -40,6 +40,8 @@ export type LoadClerkUIScriptOptions = { publishableKey: string; /** @internal */ __internal_clerkUIUrl?: string; + /** @internal */ + __internal_clerkUIVersion?: string; proxyUrl?: string; domain?: string; nonce?: string; @@ -237,14 +239,14 @@ export const clerkJSScriptUrl = (opts: LoadClerkJSScriptOptions) => { }; export const clerkUIScriptUrl = (opts: LoadClerkUIScriptOptions) => { - const { __internal_clerkUIUrl, proxyUrl, domain, publishableKey } = opts; + const { __internal_clerkUIUrl, __internal_clerkUIVersion, proxyUrl, domain, publishableKey } = opts; if (__internal_clerkUIUrl) { return __internal_clerkUIUrl; } const scriptHost = buildScriptHost({ publishableKey, proxyUrl, domain }); - const version = versionSelector(undefined, UI_PACKAGE_VERSION); + const version = versionSelector(__internal_clerkUIVersion, UI_PACKAGE_VERSION); return `https://${scriptHost}/npm/@clerk/ui@${version}/dist/ui.browser.js`; }; diff --git a/packages/shared/src/types/clerk.ts b/packages/shared/src/types/clerk.ts index db862e68147..73dfaa5e2d0 100644 --- a/packages/shared/src/types/clerk.ts +++ b/packages/shared/src/types/clerk.ts @@ -2505,6 +2505,11 @@ export type IsomorphicClerkOptions = Without & { * @internal */ __internal_clerkUIUrl?: string; + /** + * The npm version for `@clerk/ui`. + * @internal + */ + __internal_clerkUIVersion?: string; /** * The Clerk Publishable Key for your instance. This can be found on the [API keys](https://dashboard.clerk.com/last-active?path=api-keys) page in the Clerk Dashboard. */ diff --git a/packages/tanstack-react-start/src/client/types.ts b/packages/tanstack-react-start/src/client/types.ts index f5ce06237a8..f967a5a9395 100644 --- a/packages/tanstack-react-start/src/client/types.ts +++ b/packages/tanstack-react-start/src/client/types.ts @@ -19,6 +19,7 @@ export type ClerkState = { __clerkJSUrl: string | undefined; __clerkJSVersion: string | undefined; __clerkUIUrl: string | undefined; + __clerkUIVersion: string | undefined; __prefetchUI: boolean | undefined; __telemetryDisabled: boolean | undefined; __telemetryDebug: boolean | undefined; diff --git a/packages/tanstack-react-start/src/client/utils.ts b/packages/tanstack-react-start/src/client/utils.ts index 1c5c01814e0..f2dd57fbc48 100644 --- a/packages/tanstack-react-start/src/client/utils.ts +++ b/packages/tanstack-react-start/src/client/utils.ts @@ -21,6 +21,7 @@ export const pickFromClerkInitState = ( __clerkJSUrl, __clerkJSVersion, __clerkUIUrl, + __clerkUIVersion, __telemetryDisabled, __telemetryDebug, __signInForceRedirectUrl, @@ -43,6 +44,7 @@ export const pickFromClerkInitState = ( __internal_clerkJSUrl: __clerkJSUrl, __internal_clerkJSVersion: __clerkJSVersion, __internal_clerkUIUrl: __clerkUIUrl, + __internal_clerkUIVersion: __clerkUIVersion, prefetchUI: __prefetchUI, telemetry: { disabled: __telemetryDisabled, @@ -69,6 +71,7 @@ export const mergeWithPublicEnvs = (restInitState: any) => { __internal_clerkJSUrl: restInitState.__internal_clerkJSUrl || envVars.clerkJsUrl, __internal_clerkJSVersion: restInitState.__internal_clerkJSVersion || envVars.clerkJsVersion, __internal_clerkUIUrl: restInitState.__internal_clerkUIUrl || envVars.clerkUIUrl, + __internal_clerkUIVersion: restInitState.__internal_clerkUIVersion || envVars.clerkUIVersion, signInForceRedirectUrl: restInitState.signInForceRedirectUrl, prefetchUI: restInitState.prefetchUI ?? envVars.prefetchUI, }; diff --git a/packages/tanstack-react-start/src/server/constants.ts b/packages/tanstack-react-start/src/server/constants.ts index d5224b6e438..89590a6ec22 100644 --- a/packages/tanstack-react-start/src/server/constants.ts +++ b/packages/tanstack-react-start/src/server/constants.ts @@ -11,6 +11,7 @@ export const commonEnvs = () => { CLERK_JS_VERSION: publicEnvs.clerkJsVersion, CLERK_JS_URL: publicEnvs.clerkJsUrl, CLERK_UI_URL: publicEnvs.clerkUIUrl, + CLERK_UI_VERSION: publicEnvs.clerkUIVersion, PREFETCH_UI: publicEnvs.prefetchUI, PUBLISHABLE_KEY: publicEnvs.publishableKey, DOMAIN: publicEnvs.domain, diff --git a/packages/tanstack-react-start/src/server/utils/index.ts b/packages/tanstack-react-start/src/server/utils/index.ts index a76e144e120..717f4312807 100644 --- a/packages/tanstack-react-start/src/server/utils/index.ts +++ b/packages/tanstack-react-start/src/server/utils/index.ts @@ -44,6 +44,7 @@ export function getResponseClerkState(requestState: RequestState, additionalStat __clerkJSUrl: getEnvVariable('CLERK_JS') || getEnvVariable('CLERK_JS_URL'), __clerkJSVersion: getEnvVariable('CLERK_JS_VERSION'), __clerkUIUrl: getEnvVariable('CLERK_UI_URL'), + __clerkUIVersion: getEnvVariable('CLERK_UI_VERSION'), __prefetchUI: getPrefetchUIFromEnv(), __telemetryDisabled: isTruthy(getEnvVariable('CLERK_TELEMETRY_DISABLED')), __telemetryDebug: isTruthy(getEnvVariable('CLERK_TELEMETRY_DEBUG')), diff --git a/packages/tanstack-react-start/src/utils/env.ts b/packages/tanstack-react-start/src/utils/env.ts index c22da072878..0bbdca423e7 100644 --- a/packages/tanstack-react-start/src/utils/env.ts +++ b/packages/tanstack-react-start/src/utils/env.ts @@ -16,6 +16,7 @@ export const getPublicEnvVariables = () => { clerkJsUrl: getValue('CLERK_JS_URL') || getValue('CLERK_JS'), clerkJsVersion: getValue('CLERK_JS_VERSION'), clerkUIUrl: getValue('CLERK_UI_URL'), + clerkUIVersion: getValue('CLERK_UI_VERSION'), prefetchUI: getValue('CLERK_PREFETCH_UI') === 'false' ? false : undefined, telemetryDisabled: isTruthy(getValue('CLERK_TELEMETRY_DISABLED')), telemetryDebug: isTruthy(getValue('CLERK_TELEMETRY_DEBUG')), From fe760e26253574103f4bedd4ee0680867097ffd1 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 18 Feb 2026 19:56:59 -0600 Subject: [PATCH 06/10] feat(upgrade): add codemod for clerkJS/UI prop removal Remove @deprecated annotations from internal props and add a jscodeshift codemod to rename clerkJSUrl, clerkJSVersion, clerkUIUrl, clerkUIVersion to their __internal_ prefixed equivalents. Update changesets to reflect full removal rather than deprecation. --- .changeset/internal-clerk-js-ui-props.md | 2 +- .changeset/remove-clerk-ui-version.md | 2 +- packages/shared/src/loadClerkJsScript.ts | 5 +- packages/shared/src/types/clerk.ts | 1 - ...orm-internal-clerk-js-ui-props.fixtures.js | 251 ++++++++++++++++++ ...ansform-internal-clerk-js-ui-props.test.js | 17 ++ .../transform-internal-clerk-js-ui-props.cjs | 161 +++++++++++ packages/upgrade/src/versions/core-3/index.js | 1 + 8 files changed, 433 insertions(+), 7 deletions(-) create mode 100644 packages/upgrade/src/codemods/__tests__/__fixtures__/transform-internal-clerk-js-ui-props.fixtures.js create mode 100644 packages/upgrade/src/codemods/__tests__/transform-internal-clerk-js-ui-props.test.js create mode 100644 packages/upgrade/src/codemods/transform-internal-clerk-js-ui-props.cjs diff --git a/.changeset/internal-clerk-js-ui-props.md b/.changeset/internal-clerk-js-ui-props.md index 5a050f0c2b5..9bbc67a3dcc 100644 --- a/.changeset/internal-clerk-js-ui-props.md +++ b/.changeset/internal-clerk-js-ui-props.md @@ -8,4 +8,4 @@ '@clerk/nuxt': minor --- -Rename `clerkJSUrl`, `clerkJSVersion`, and `clerkUIUrl` props to `__internal_clerkJSUrl`, `__internal_clerkJSVersion`, and `__internal_clerkUIUrl` to mark them as internal-only options. +Remove `clerkJSUrl`, `clerkJSVersion`, `clerkUIUrl`, and `clerkUIVersion` props and replace with `__internal_clerkJSUrl`, `__internal_clerkJSVersion`, `__internal_clerkUIUrl`, and `__internal_clerkUIVersion` internal-only options. Use `@clerk/upgrade` to migrate. diff --git a/.changeset/remove-clerk-ui-version.md b/.changeset/remove-clerk-ui-version.md index 35934f14c4c..3404d56cb95 100644 --- a/.changeset/remove-clerk-ui-version.md +++ b/.changeset/remove-clerk-ui-version.md @@ -8,4 +8,4 @@ '@clerk/nuxt': minor --- -Remove `clerkUIVersion` prop and deprecate `clerkJSVersion` prop across all SDKs +Remove `clerkUIVersion` and `clerkJSVersion` props across all SDKs. Use `@clerk/upgrade` to migrate to the new `__internal_` prefixed props if needed. diff --git a/packages/shared/src/loadClerkJsScript.ts b/packages/shared/src/loadClerkJsScript.ts index dab8eedfdb6..96171f5c648 100644 --- a/packages/shared/src/loadClerkJsScript.ts +++ b/packages/shared/src/loadClerkJsScript.ts @@ -14,10 +14,7 @@ export type LoadClerkJSScriptOptions = { publishableKey: string; /** @internal */ __internal_clerkJSUrl?: string; - /** - * @deprecated This option is deprecated. The Clerk SDK will automatically use the correct version. - * @internal - */ + /** @internal */ __internal_clerkJSVersion?: string; sdkMetadata?: SDKMetadata; proxyUrl?: string; diff --git a/packages/shared/src/types/clerk.ts b/packages/shared/src/types/clerk.ts index 73dfaa5e2d0..26e71e32c88 100644 --- a/packages/shared/src/types/clerk.ts +++ b/packages/shared/src/types/clerk.ts @@ -2496,7 +2496,6 @@ export type IsomorphicClerkOptions = Without & { __internal_clerkJSUrl?: string; /** * The npm version for `@clerk/clerk-js`. - * @deprecated This prop is deprecated. The Clerk SDK will automatically use the correct version. * @internal */ __internal_clerkJSVersion?: string; diff --git a/packages/upgrade/src/codemods/__tests__/__fixtures__/transform-internal-clerk-js-ui-props.fixtures.js b/packages/upgrade/src/codemods/__tests__/__fixtures__/transform-internal-clerk-js-ui-props.fixtures.js new file mode 100644 index 00000000000..14efd63a29a --- /dev/null +++ b/packages/upgrade/src/codemods/__tests__/__fixtures__/transform-internal-clerk-js-ui-props.fixtures.js @@ -0,0 +1,251 @@ +export const fixtures = [ + { + name: 'JSX: renames clerkJSUrl to __internal_clerkJSUrl', + source: ` +import { ClerkProvider } from '@clerk/nextjs'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + output: ` +import { ClerkProvider } from '@clerk/nextjs'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + }, + { + name: 'JSX: renames clerkJSVersion to __internal_clerkJSVersion', + source: ` +import { ClerkProvider } from '@clerk/react'; + +export const App = () => ( + +
+ +); + `, + output: ` +import { ClerkProvider } from '@clerk/react'; + +export const App = () => ( + +
+ +); + `, + }, + { + name: 'JSX: renames clerkUIUrl and clerkUIVersion', + source: ` +import { ClerkProvider } from '@clerk/nextjs'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + output: ` +import { ClerkProvider } from '@clerk/nextjs'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + }, + { + name: 'JSX: renames all four props at once', + source: ` +import { ClerkProvider } from '@clerk/nextjs'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + output: ` +import { ClerkProvider } from '@clerk/nextjs'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + }, + { + name: 'JSX: does not rename props on non-Clerk components', + source: ` +import { SomeProvider } from 'some-other-package'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + noChange: true, + }, + { + name: 'JSX: handles aliased import', + source: ` +import { ClerkProvider as CP } from '@clerk/react'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + output: ` +import { ClerkProvider as CP } from '@clerk/react'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + }, + { + name: 'JSX: skips if __internal_ prop already exists', + source: ` +import { ClerkProvider } from '@clerk/nextjs'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + output: ` +import { ClerkProvider } from '@clerk/nextjs'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + }, + { + name: 'Object: renames properties in object literal', + source: ` +const options = { + clerkJSUrl: 'https://js.example.com/clerk.js', + clerkJSVersion: '5.0.0', +}; + `, + output: ` +const options = { + __internal_clerkJSUrl: 'https://js.example.com/clerk.js', + __internal_clerkJSVersion: '5.0.0', +}; + `, + }, + { + name: 'Object: renames all four properties', + source: ` +const options = { + clerkJSUrl: 'https://js.example.com/clerk.js', + clerkJSVersion: '5.0.0', + clerkUIUrl: 'https://ui.example.com/ui.js', + clerkUIVersion: '1.0.0', +}; + `, + output: ` +const options = { + __internal_clerkJSUrl: 'https://js.example.com/clerk.js', + __internal_clerkJSVersion: '5.0.0', + __internal_clerkUIUrl: 'https://ui.example.com/ui.js', + __internal_clerkUIVersion: '1.0.0', +}; + `, + }, + { + name: 'No matching props (no changes)', + source: ` +import { ClerkProvider } from '@clerk/nextjs'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + noChange: true, + }, + { + name: 'JSX: expression container value', + source: ` +import { ClerkProvider } from '@clerk/nextjs'; + +const jsUrl = 'https://js.example.com/clerk.js'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + output: ` +import { ClerkProvider } from '@clerk/nextjs'; + +const jsUrl = 'https://js.example.com/clerk.js'; + +export function App({ children }) { + return ( + + {children} + + ); +} + `, + }, +]; diff --git a/packages/upgrade/src/codemods/__tests__/transform-internal-clerk-js-ui-props.test.js b/packages/upgrade/src/codemods/__tests__/transform-internal-clerk-js-ui-props.test.js new file mode 100644 index 00000000000..a045cd5596d --- /dev/null +++ b/packages/upgrade/src/codemods/__tests__/transform-internal-clerk-js-ui-props.test.js @@ -0,0 +1,17 @@ +import { applyTransform } from 'jscodeshift/dist/testUtils'; +import { describe, expect, it } from 'vitest'; + +import transformer from '../transform-internal-clerk-js-ui-props.cjs'; +import { fixtures } from './__fixtures__/transform-internal-clerk-js-ui-props.fixtures'; + +describe('transform-internal-clerk-js-ui-props', () => { + it.each(fixtures)('$name', ({ source, output, noChange }) => { + const result = applyTransform(transformer, {}, { source }); + + if (noChange) { + expect(result).toEqual(''); + } else { + expect(result).toEqual(output.trim()); + } + }); +}); diff --git a/packages/upgrade/src/codemods/transform-internal-clerk-js-ui-props.cjs b/packages/upgrade/src/codemods/transform-internal-clerk-js-ui-props.cjs new file mode 100644 index 00000000000..2fbac369f63 --- /dev/null +++ b/packages/upgrade/src/codemods/transform-internal-clerk-js-ui-props.cjs @@ -0,0 +1,161 @@ +const CLERK_PACKAGE_PREFIX = '@clerk/'; + +const PROP_RENAMES = new Map([ + ['clerkJSUrl', '__internal_clerkJSUrl'], + ['clerkJSVersion', '__internal_clerkJSVersion'], + ['clerkUIUrl', '__internal_clerkUIUrl'], + ['clerkUIVersion', '__internal_clerkUIVersion'], +]); + +const COMPONENTS_WITH_PROPS = new Set(['ClerkProvider']); + +module.exports = function transformInternalClerkJsUiProps({ source }, { jscodeshift: j, stats }) { + const root = j(source); + let dirty = false; + + const { namedImports, namespaceImports } = collectClerkImports(root, j); + + // Transform JSX attributes + root.find(j.JSXOpeningElement).forEach(path => { + const canonicalName = getCanonicalComponentName(path.node.name, namedImports, namespaceImports); + if (!canonicalName || !COMPONENTS_WITH_PROPS.has(canonicalName)) { + return; + } + + for (const [oldName, newName] of PROP_RENAMES) { + if (renameJsxAttribute(j, path.node, oldName, newName)) { + dirty = true; + stats(oldName + 'Renamed'); + } + } + }); + + // Transform object properties + for (const [oldName, newName] of PROP_RENAMES) { + if (renameObjectProperties(root, j, oldName, newName)) { + dirty = true; + stats(oldName + 'Renamed'); + } + } + + return dirty ? root.toSource() : undefined; +}; + +module.exports.parser = 'tsx'; + +function collectClerkImports(root, j) { + const namedImports = new Map(); + const namespaceImports = new Set(); + + root.find(j.ImportDeclaration).forEach(path => { + const sourceVal = path.node.source.value; + if (typeof sourceVal !== 'string' || !sourceVal.startsWith(CLERK_PACKAGE_PREFIX)) { + return; + } + + for (const specifier of path.node.specifiers || []) { + if (j.ImportSpecifier.check(specifier)) { + const localName = specifier.local ? specifier.local.name : specifier.imported.name; + namedImports.set(localName, specifier.imported.name); + } else if (j.ImportNamespaceSpecifier.check(specifier) || j.ImportDefaultSpecifier.check(specifier)) { + namespaceImports.add(specifier.local.name); + } + } + }); + + return { namedImports, namespaceImports }; +} + +function getCanonicalComponentName(nameNode, namedImports, namespaceImports) { + if (!nameNode) { + return null; + } + + if (nameNode.type === 'JSXIdentifier') { + return namedImports.get(nameNode.name) || nameNode.name; + } + + if (nameNode.type === 'JSXMemberExpression') { + return getNamespaceMemberName(nameNode, namespaceImports); + } + + return null; +} + +function getNamespaceMemberName(memberNode, namespaceImports) { + if (memberNode.object.type === 'JSXIdentifier') { + return namespaceImports.has(memberNode.object.name) ? memberNode.property.name : null; + } + + if (memberNode.object.type === 'JSXMemberExpression') { + const resolved = getNamespaceMemberName(memberNode.object, namespaceImports); + return resolved ? memberNode.property.name : null; + } + + return null; +} + +function renameJsxAttribute(j, jsxNode, oldName, newName) { + if (!jsxNode.attributes) { + return false; + } + + const attrIndex = jsxNode.attributes.findIndex(attr => isJsxAttrNamed(attr, oldName)); + if (attrIndex === -1) { + return false; + } + + // If target already exists, just remove the old one + const targetExists = jsxNode.attributes.some(attr => isJsxAttrNamed(attr, newName)); + if (targetExists) { + jsxNode.attributes.splice(attrIndex, 1); + return true; + } + + jsxNode.attributes[attrIndex].name.name = newName; + return true; +} + +function isJsxAttrNamed(attribute, name) { + return attribute && attribute.type === 'JSXAttribute' && attribute.name && attribute.name.name === name; +} + +function renameObjectProperties(root, j, oldName, newName) { + let changed = false; + + root.find(j.ObjectProperty).forEach(path => { + if (!isPropertyKeyNamed(path.node.key, oldName)) { + return; + } + + if (path.node.shorthand) { + path.node.shorthand = false; + path.node.value = j.identifier(oldName); + } + + if (path.node.key.type === 'Identifier') { + path.node.key.name = newName; + } else if (path.node.key.type === 'StringLiteral') { + path.node.key.value = newName; + } else if (path.node.key.type === 'Literal') { + path.node.key.value = newName; + } + + changed = true; + }); + + return changed; +} + +function isPropertyKeyNamed(keyNode, name) { + if (!keyNode) { + return false; + } + if (keyNode.type === 'Identifier') { + return keyNode.name === name; + } + if (keyNode.type === 'StringLiteral' || keyNode.type === 'Literal') { + return keyNode.value === name; + } + return false; +} diff --git a/packages/upgrade/src/versions/core-3/index.js b/packages/upgrade/src/versions/core-3/index.js index b30b1a8ba32..3b893520fe6 100644 --- a/packages/upgrade/src/versions/core-3/index.js +++ b/packages/upgrade/src/versions/core-3/index.js @@ -31,5 +31,6 @@ export default { // Migrate @clerk/react-router/api.server → @clerk/react-router/server { name: 'transform-react-router-api-server', packages: ['react-router'] }, { name: 'transform-satellite-auto-sync', packages: ['nextjs', 'react', 'expo', 'astro', 'tanstack-react-start'] }, + 'transform-internal-clerk-js-ui-props', ], }; From a292b679768e637de71f7a3e50650c0986a6a1a7 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 18 Feb 2026 22:32:01 -0600 Subject: [PATCH 07/10] feat: hide internal script props from consumer-facing types Omit __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, and __internal_clerkUIVersion from consumer-facing ClerkProviderProps and framework SDK types. These props are now only accessible via InternalClerkProvider exported from @clerk/react/internal. - Add InternalClerkScriptProps type to @clerk/shared - Narrow ClerkProviderProps in @clerk/react via Omit - Export InternalClerkProvider from @clerk/react/internal with wider type - Switch all framework SDKs to use InternalClerkProvider - Clean up Vue PluginOptions, Astro, and Nuxt types --- .../internal/merge-env-vars-with-params.ts | 3 +- packages/astro/src/types.ts | 28 ++--------- .../src/react/ClerkProvider.tsx | 2 +- packages/expo/src/provider/ClerkProvider.tsx | 9 ++-- .../src/app-router/client/ClerkProvider.tsx | 3 +- .../client-boundary/NextOptionsContext.tsx | 3 +- packages/nextjs/src/pages/ClerkProvider.tsx | 10 ++-- .../nextjs/src/pages/__tests__/index.test.tsx | 18 +++---- .../src/utils/mergeNextClerkPropsWithEnv.ts | 5 +- packages/nuxt/src/global.d.ts | 5 +- packages/nuxt/src/module.ts | 7 +-- .../src/client/ReactRouterClerkProvider.tsx | 3 +- .../client/__tests__/ClerkProvider.test.tsx | 50 ++++++++++++------- packages/react/src/internal.ts | 18 +++++++ packages/react/src/types.ts | 6 ++- packages/shared/src/types/clerk.ts | 11 ++++ .../src/client/ClerkProvider.tsx | 3 +- .../tanstack-react-start/src/client/utils.ts | 13 +++-- packages/vue/src/plugin.ts | 6 ++- 19 files changed, 116 insertions(+), 87 deletions(-) diff --git a/packages/astro/src/internal/merge-env-vars-with-params.ts b/packages/astro/src/internal/merge-env-vars-with-params.ts index c07e9f8d9c3..e65b3b23530 100644 --- a/packages/astro/src/internal/merge-env-vars-with-params.ts +++ b/packages/astro/src/internal/merge-env-vars-with-params.ts @@ -1,3 +1,4 @@ +import type { InternalClerkScriptProps } from '@clerk/shared/types'; import { isTruthy } from '@clerk/shared/underscore'; import type { AstroClerkIntegrationParams, InternalRuntimeOptions } from '../types'; @@ -25,7 +26,7 @@ function mergePrefetchUIConfig(paramPrefetchUI: AstroClerkIntegrationParams['pre /** * @internal */ -const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & InternalRuntimeOptions) => { +const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & InternalRuntimeOptions & InternalClerkScriptProps) => { const { signInUrl: paramSignIn, signUpUrl: paramSignUp, diff --git a/packages/astro/src/types.ts b/packages/astro/src/types.ts index 5b8a96b7ad9..2248d5ce1f3 100644 --- a/packages/astro/src/types.ts +++ b/packages/astro/src/types.ts @@ -2,6 +2,7 @@ import type { Clerk, ClerkOptions, ClientResource, + InternalClerkScriptProps, MultiDomainAndOrProxyPrimitives, ProtectParams, ShowProps, @@ -29,26 +30,6 @@ type AstroClerkIntegrationParams = Without< > & MultiDomainAndOrProxyPrimitives & { appearance?: Appearance; - /** - * The URL that `@clerk/clerk-js` should be hot-loaded from. - * @internal - */ - __internal_clerkJSUrl?: string; - /** - * The npm version for `@clerk/clerk-js`. - * @internal - */ - __internal_clerkJSVersion?: string; - /** - * The URL that `@clerk/ui` should be hot-loaded from. - * @internal - */ - __internal_clerkUIUrl?: string; - /** - * The npm version for `@clerk/ui`. - * @internal - */ - __internal_clerkUIVersion?: string; /** * Controls prefetching of the `@clerk/ui` script. * - `false` - Skip prefetching the UI (for custom UIs using Control Components) @@ -57,9 +38,10 @@ type AstroClerkIntegrationParams = Without< prefetchUI?: boolean; }; -type AstroClerkCreateInstanceParams = AstroClerkIntegrationParams & { - publishableKey: string; -}; +type AstroClerkCreateInstanceParams = AstroClerkIntegrationParams & + InternalClerkScriptProps & { + publishableKey: string; + }; /** * @internal diff --git a/packages/chrome-extension/src/react/ClerkProvider.tsx b/packages/chrome-extension/src/react/ClerkProvider.tsx index db601b22452..15ec1895cfa 100644 --- a/packages/chrome-extension/src/react/ClerkProvider.tsx +++ b/packages/chrome-extension/src/react/ClerkProvider.tsx @@ -1,6 +1,6 @@ import type { Clerk } from '@clerk/clerk-js/no-rhc'; import type { ClerkProviderProps as ClerkReactProviderProps } from '@clerk/react'; -import { ClerkProvider as ClerkReactProvider } from '@clerk/react'; +import { InternalClerkProvider as ClerkReactProvider } from '@clerk/react/internal'; import { ui } from '@clerk/ui'; import React from 'react'; diff --git a/packages/expo/src/provider/ClerkProvider.tsx b/packages/expo/src/provider/ClerkProvider.tsx index 6c81616a1fc..d76e3fa541c 100644 --- a/packages/expo/src/provider/ClerkProvider.tsx +++ b/packages/expo/src/provider/ClerkProvider.tsx @@ -1,7 +1,7 @@ import '../polyfills'; -import { ClerkProvider as ClerkReactProvider } from '@clerk/react'; -import type { Ui } from '@clerk/react/internal'; +import type { ClerkProviderProps as ReactClerkProviderProps } from '@clerk/react'; +import { InternalClerkProvider as ClerkReactProvider, type Ui } from '@clerk/react/internal'; import * as WebBrowser from 'expo-web-browser'; import type { TokenCache } from '../cache/types'; @@ -9,10 +9,7 @@ import { isNative, isWeb } from '../utils/runtime'; import { getClerkInstance } from './singleton'; import type { BuildClerkOptions } from './singleton/types'; -export type ClerkProviderProps = Omit< - React.ComponentProps>, - 'publishableKey' -> & { +export type ClerkProviderProps = Omit, 'publishableKey'> & { /** * Your Clerk publishable key, available in the Clerk Dashboard. * This is required for React Native / Expo apps. Environment variables inside node_modules diff --git a/packages/nextjs/src/app-router/client/ClerkProvider.tsx b/packages/nextjs/src/app-router/client/ClerkProvider.tsx index 77dc12d7cac..109e1a38c87 100644 --- a/packages/nextjs/src/app-router/client/ClerkProvider.tsx +++ b/packages/nextjs/src/app-router/client/ClerkProvider.tsx @@ -1,6 +1,5 @@ 'use client'; -import { ClerkProvider as ReactClerkProvider } from '@clerk/react'; -import type { Ui } from '@clerk/react/internal'; +import { InternalClerkProvider as ReactClerkProvider, type Ui } from '@clerk/react/internal'; import { InitialStateProvider } from '@clerk/shared/react'; import dynamic from 'next/dynamic'; import { useRouter } from 'next/navigation'; diff --git a/packages/nextjs/src/client-boundary/NextOptionsContext.tsx b/packages/nextjs/src/client-boundary/NextOptionsContext.tsx index 05fa6b0172e..2c3bb6a640e 100644 --- a/packages/nextjs/src/client-boundary/NextOptionsContext.tsx +++ b/packages/nextjs/src/client-boundary/NextOptionsContext.tsx @@ -1,8 +1,9 @@ +import type { InternalClerkScriptProps } from '@clerk/react/internal'; import React from 'react'; import type { NextClerkProviderProps } from '../types'; -type ClerkNextContextValue = Partial>; +type ClerkNextContextValue = Partial & InternalClerkScriptProps>; const ClerkNextOptionsCtx = React.createContext<{ value: ClerkNextContextValue } | undefined>(undefined); ClerkNextOptionsCtx.displayName = 'ClerkNextOptionsCtx'; diff --git a/packages/nextjs/src/pages/ClerkProvider.tsx b/packages/nextjs/src/pages/ClerkProvider.tsx index 5bc6c3b76f8..6d47886a470 100644 --- a/packages/nextjs/src/pages/ClerkProvider.tsx +++ b/packages/nextjs/src/pages/ClerkProvider.tsx @@ -1,7 +1,9 @@ -import { ClerkProvider as ReactClerkProvider } from '@clerk/react'; -import type { Ui } from '@clerk/react/internal'; -// Override Clerk React error thrower to show that errors come from @clerk/nextjs -import { setClerkJSLoadingErrorPackageName, setErrorThrowerOptions } from '@clerk/react/internal'; +import { + InternalClerkProvider as ReactClerkProvider, + setClerkJSLoadingErrorPackageName, + setErrorThrowerOptions, + type Ui, +} from '@clerk/react/internal'; import { useRouter } from 'next/router'; import React from 'react'; diff --git a/packages/nextjs/src/pages/__tests__/index.test.tsx b/packages/nextjs/src/pages/__tests__/index.test.tsx index ac4eac79b7e..fbf771ea902 100644 --- a/packages/nextjs/src/pages/__tests__/index.test.tsx +++ b/packages/nextjs/src/pages/__tests__/index.test.tsx @@ -29,18 +29,12 @@ describe('ClerkProvider', () => { }); }); - describe('__internal_clerkUIUrl', () => { - const defaultProps = { children: '' }; - - it('accepts string URL for custom UI location', () => { - expectTypeOf({ - ...defaultProps, - __internal_clerkUIUrl: 'https://custom.com/ui.js', - }).toMatchTypeOf(); - }); - - it('accepts undefined', () => { - expectTypeOf({ ...defaultProps, __internal_clerkUIUrl: undefined }).toMatchTypeOf(); + describe('internal script props', () => { + it('does not expose internal script props', () => { + expectTypeOf().not.toHaveProperty('__internal_clerkUIUrl'); + expectTypeOf().not.toHaveProperty('__internal_clerkJSUrl'); + expectTypeOf().not.toHaveProperty('__internal_clerkUIVersion'); + expectTypeOf().not.toHaveProperty('__internal_clerkJSVersion'); }); }); diff --git a/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts b/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts index 75b0a09178e..afb09022061 100644 --- a/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts +++ b/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts @@ -1,3 +1,4 @@ +import type { InternalClerkScriptProps } from '@clerk/react/internal'; import { isTruthy } from '@clerk/shared/underscore'; import { SDK_METADATA } from '../server/constants'; @@ -18,7 +19,9 @@ function getPrefetchUIFromEnvAndProps(propsPrefetchUI: NextClerkProviderProps['p } // @ts-ignore - https://github.com/microsoft/TypeScript/issues/47663 -export const mergeNextClerkPropsWithEnv = (props: Omit): any => { +export const mergeNextClerkPropsWithEnv = ( + props: Omit & InternalClerkScriptProps, +): any => { return { ...props, publishableKey: props.publishableKey || process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY || '', diff --git a/packages/nuxt/src/global.d.ts b/packages/nuxt/src/global.d.ts index af372ccac9d..6fd1ecef727 100644 --- a/packages/nuxt/src/global.d.ts +++ b/packages/nuxt/src/global.d.ts @@ -16,10 +16,7 @@ declare module 'nuxt/schema' { }; } interface PublicRuntimeConfig { - clerk: Omit< - PluginOptions, - '__internal_clerkJSUrl' | '__internal_clerkUIUrl' | '__internal_clerkJSVersion' | '__internal_clerkUIVersion' - > & { + clerk: PluginOptions & { /** * The URL that `@clerk/clerk-js` should be hot-loaded from. * Supports NUXT_PUBLIC_CLERK_JS_URL env var. diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index 46ed83fce50..92f5f9861c7 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -1,4 +1,4 @@ -import type { Without } from '@clerk/shared/types'; +import type { InternalClerkScriptProps, Without } from '@clerk/shared/types'; import type { PluginOptions } from '@clerk/vue'; import { addComponent, @@ -15,8 +15,9 @@ import { export type ModuleOptions = Without< PluginOptions, 'routerPush' | 'routerReplace' | 'publishableKey' | 'initialState' -> & { - publishableKey?: string; +> & + InternalClerkScriptProps & { + publishableKey?: string; /** * Skip the automatic server middleware registration. When enabled, you'll need to * register the middleware manually in your application. diff --git a/packages/react-router/src/client/ReactRouterClerkProvider.tsx b/packages/react-router/src/client/ReactRouterClerkProvider.tsx index 6d27d1e5448..5abefcbb341 100644 --- a/packages/react-router/src/client/ReactRouterClerkProvider.tsx +++ b/packages/react-router/src/client/ReactRouterClerkProvider.tsx @@ -1,5 +1,4 @@ -import { ClerkProvider as ReactClerkProvider } from '@clerk/react'; -import type { Ui } from '@clerk/react/internal'; +import { InternalClerkProvider as ReactClerkProvider, type Ui } from '@clerk/react/internal'; import React from 'react'; import { diff --git a/packages/react-router/src/client/__tests__/ClerkProvider.test.tsx b/packages/react-router/src/client/__tests__/ClerkProvider.test.tsx index b1fc87fc87e..1677e93a22a 100644 --- a/packages/react-router/src/client/__tests__/ClerkProvider.test.tsx +++ b/packages/react-router/src/client/__tests__/ClerkProvider.test.tsx @@ -4,10 +4,12 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; const mockClerkProvider = vi.fn(({ children }: { children: React.ReactNode }) =>
{children}
); -vi.mock('@clerk/react', () => ({ - ClerkProvider: (props: any) => mockClerkProvider(props), +vi.mock('@clerk/react/internal', () => ({ + InternalClerkProvider: (props: any) => mockClerkProvider(props), })); +vi.mock('@clerk/react', () => ({})); + vi.mock('react-router', () => ({ useNavigate: () => vi.fn(), useLocation: () => ({ pathname: '/' }), @@ -17,11 +19,11 @@ vi.mock('react-router', () => ({ vi.mock('../../utils/assert', () => ({ assertPublishableKeyInSpaMode: vi.fn(), assertValidClerkState: vi.fn(), - isSpaMode: () => true, + isSpaMode: () => false, warnForSsr: vi.fn(), })); -describe('ClerkProvider __internal_clerkUIUrl prop', () => { +describe('ClerkProvider __internal_clerkUIUrl via clerkState', () => { beforeEach(() => { vi.clearAllMocks(); }); @@ -30,14 +32,20 @@ describe('ClerkProvider __internal_clerkUIUrl prop', () => { vi.clearAllMocks(); }); - it('passes __internal_clerkUIUrl prop to the underlying ClerkProvider', async () => { + it('passes __internal_clerkUIUrl from clerkState to the underlying ClerkProvider', async () => { const { ClerkProvider } = await import('../ReactRouterClerkProvider'); + const clerkState = { + __type: 'clerkState' as const, + __internal_clerk_state: { + __clerk_ssr_state: undefined, + __publishableKey: 'pk_test_xxx', + __clerkUIUrl: 'https://custom.clerk.ui/ui.js', + }, + }; + render( - +
Test
, ); @@ -49,7 +57,7 @@ describe('ClerkProvider __internal_clerkUIUrl prop', () => { ); }); - it('passes __internal_clerkUIUrl as undefined when not provided', async () => { + it('passes __internal_clerkUIUrl as undefined when not in clerkState', async () => { const { ClerkProvider } = await import('../ReactRouterClerkProvider'); render( @@ -65,17 +73,23 @@ describe('ClerkProvider __internal_clerkUIUrl prop', () => { ); }); - it('passes __internal_clerkUIUrl alongside other props', async () => { + it('passes __internal_clerkUIUrl alongside other props from clerkState', async () => { const { ClerkProvider } = await import('../ReactRouterClerkProvider'); + const clerkState = { + __type: 'clerkState' as const, + __internal_clerk_state: { + __clerk_ssr_state: undefined, + __publishableKey: 'pk_test_xxx', + __clerkUIUrl: 'https://custom.clerk.ui/ui.js', + __clerkJSUrl: 'https://custom.clerk.js/clerk.js', + __signInUrl: '/sign-in', + __signUpUrl: '/sign-up', + }, + }; + render( - +
Test
, ); diff --git a/packages/react/src/internal.ts b/packages/react/src/internal.ts index 4f35a1a000f..d3ca39cb89a 100644 --- a/packages/react/src/internal.ts +++ b/packages/react/src/internal.ts @@ -17,3 +17,21 @@ export { } from '@clerk/shared/loadClerkJsScript'; export type { Ui } from '@clerk/ui/internal'; + +export type { InternalClerkScriptProps } from '@clerk/shared/types'; + +import type { InternalClerkScriptProps } from '@clerk/shared/types'; +import type { Ui } from '@clerk/ui/internal'; +import type React from 'react'; + +import type { ClerkProviderProps } from './types'; + +import { ClerkProvider } from './contexts/ClerkProvider'; + +/** + * A wider-typed version of ClerkProvider that accepts internal script props. + * Framework SDKs should use this instead of the public ClerkProvider. + */ +export const InternalClerkProvider = ClerkProvider as unknown as (( + props: ClerkProviderProps & InternalClerkScriptProps, +) => React.JSX.Element) & { displayName: string }; diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts index 99c15fbb0f9..9c38a97c989 100644 --- a/packages/react/src/types.ts +++ b/packages/react/src/types.ts @@ -1,6 +1,7 @@ import type { Clerk, InitialState, + InternalClerkScriptProps, IsomorphicClerkOptions, LoadedClerk, RedirectUrlProp, @@ -36,7 +37,10 @@ declare global { /** * @interface */ -export type ClerkProviderProps = Omit & { +export type ClerkProviderProps = Omit< + IsomorphicClerkOptions, + 'appearance' | keyof InternalClerkScriptProps +> & { children: React.ReactNode; /** * Provide an initial state of the Clerk client during server-side rendering. You don't need to set this value yourself unless you're [developing an SDK](https://clerk.com/docs/guides/development/sdk-development/overview). diff --git a/packages/shared/src/types/clerk.ts b/packages/shared/src/types/clerk.ts index 26e71e32c88..dfede252d9a 100644 --- a/packages/shared/src/types/clerk.ts +++ b/packages/shared/src/types/clerk.ts @@ -2487,6 +2487,17 @@ export type ClerkProp = | undefined | null; +/** + * Internal props used by framework SDKs to configure script URLs and versions. + * These are omitted from consumer-facing types like ClerkProviderProps. + */ +export type InternalClerkScriptProps = { + __internal_clerkJSUrl?: string; + __internal_clerkJSVersion?: string; + __internal_clerkUIUrl?: string; + __internal_clerkUIVersion?: string; +}; + export type IsomorphicClerkOptions = Without & { Clerk?: ClerkProp; /** diff --git a/packages/tanstack-react-start/src/client/ClerkProvider.tsx b/packages/tanstack-react-start/src/client/ClerkProvider.tsx index 8247efbac29..23977e0a999 100644 --- a/packages/tanstack-react-start/src/client/ClerkProvider.tsx +++ b/packages/tanstack-react-start/src/client/ClerkProvider.tsx @@ -1,5 +1,4 @@ -import { ClerkProvider as ReactClerkProvider } from '@clerk/react'; -import type { Ui } from '@clerk/react/internal'; +import { InternalClerkProvider as ReactClerkProvider, type Ui } from '@clerk/react/internal'; import { ScriptOnce } from '@tanstack/react-router'; import { getGlobalStartContext } from '@tanstack/react-start'; import { useEffect } from 'react'; diff --git a/packages/tanstack-react-start/src/client/utils.ts b/packages/tanstack-react-start/src/client/utils.ts index f2dd57fbc48..e97c338885f 100644 --- a/packages/tanstack-react-start/src/client/utils.ts +++ b/packages/tanstack-react-start/src/client/utils.ts @@ -1,3 +1,5 @@ +import type { InternalClerkScriptProps } from '@clerk/shared/types'; + import { getPublicEnvVariables } from '../utils/env'; import type { TanstackStartClerkProviderProps } from './types'; @@ -5,11 +7,12 @@ type TanStackProviderAndInitialProps = Omit { +): TanStackProviderAndInitialProps & + InternalClerkScriptProps & { + clerkSsrState: any; + __keylessClaimUrl?: string; + __keylessApiKeysUrl?: string; + } => { const { __clerk_ssr_state, __publishableKey, diff --git a/packages/vue/src/plugin.ts b/packages/vue/src/plugin.ts index cb61569ee5e..04573bbaa45 100644 --- a/packages/vue/src/plugin.ts +++ b/packages/vue/src/plugin.ts @@ -6,6 +6,7 @@ import type { ClerkOptions, ClientResource, InitialState, + InternalClerkScriptProps, IsomorphicClerkOptions, MultiDomainAndOrProxy, Resources, @@ -23,7 +24,10 @@ declare global { } } -export type PluginOptions = Without & +export type PluginOptions = Without< + IsomorphicClerkOptions, + 'domain' | 'proxyUrl' | 'appearance' | keyof InternalClerkScriptProps +> & MultiDomainAndOrProxy & { initialState?: InitialState; appearance?: Appearance; From 24c3f112ae956dc48034f92a5c782c751617dc72 Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 19 Feb 2026 14:25:17 -0600 Subject: [PATCH 08/10] fix: resolve lint and formatting issues --- packages/nuxt/src/module.ts | 43 ++++++++++++++++------------------ packages/react/src/internal.ts | 15 ++++++------ 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index 92f5f9861c7..49f2505e3ee 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -12,31 +12,28 @@ import { updateRuntimeConfig, } from '@nuxt/kit'; -export type ModuleOptions = Without< - PluginOptions, - 'routerPush' | 'routerReplace' | 'publishableKey' | 'initialState' -> & +export type ModuleOptions = Without & InternalClerkScriptProps & { publishableKey?: string; - /** - * Skip the automatic server middleware registration. When enabled, you'll need to - * register the middleware manually in your application. - * - * @default false - * - * @example - * - * ```ts - * // server/middleware/clerk.ts - * import { clerkMiddleware } from '@clerk/nuxt/server' - * - * export default clerkMiddleware((event) => { - * console.log('auth', event.context.auth()) - * }) - * ``` - */ - skipServerMiddleware?: boolean; -}; + /** + * Skip the automatic server middleware registration. When enabled, you'll need to + * register the middleware manually in your application. + * + * @default false + * + * @example + * + * ```ts + * // server/middleware/clerk.ts + * import { clerkMiddleware } from '@clerk/nuxt/server' + * + * export default clerkMiddleware((event) => { + * console.log('auth', event.context.auth()) + * }) + * ``` + */ + skipServerMiddleware?: boolean; + }; export default defineNuxtModule({ meta: { diff --git a/packages/react/src/internal.ts b/packages/react/src/internal.ts index d3ca39cb89a..ff4db48fe49 100644 --- a/packages/react/src/internal.ts +++ b/packages/react/src/internal.ts @@ -1,3 +1,10 @@ +import type { InternalClerkScriptProps } from '@clerk/shared/types'; +import type { Ui } from '@clerk/ui/internal'; +import type React from 'react'; + +import { ClerkProvider } from './contexts/ClerkProvider'; +import type { ClerkProviderProps } from './types'; + export { setErrorThrowerOptions } from './errors/errorThrower'; export { MultisessionAppSupport } from './components/controlComponents'; export { useRoutingProps } from './hooks/useRoutingProps'; @@ -20,14 +27,6 @@ export type { Ui } from '@clerk/ui/internal'; export type { InternalClerkScriptProps } from '@clerk/shared/types'; -import type { InternalClerkScriptProps } from '@clerk/shared/types'; -import type { Ui } from '@clerk/ui/internal'; -import type React from 'react'; - -import type { ClerkProviderProps } from './types'; - -import { ClerkProvider } from './contexts/ClerkProvider'; - /** * A wider-typed version of ClerkProvider that accepts internal script props. * Framework SDKs should use this instead of the public ClerkProvider. From d8aed9baf9959ba0461c1c2a78efa49e509e6c7a Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 19 Feb 2026 14:42:54 -0600 Subject: [PATCH 09/10] fix: add missing clerkUIUrl env mapping in astro and clerkUIVersion in next.js ClerkScripts --- packages/astro/src/integration/create-integration.ts | 2 ++ .../astro/src/internal/merge-env-vars-with-params.ts | 4 +++- .../nextjs/src/app-router/client/ClerkScripts.tsx | 12 ++++++++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/astro/src/integration/create-integration.ts b/packages/astro/src/integration/create-integration.ts index 18d6749701c..eb5b3200366 100644 --- a/packages/astro/src/integration/create-integration.ts +++ b/packages/astro/src/integration/create-integration.ts @@ -22,6 +22,7 @@ function createIntegration() // These are not provided when the "bundled" integration is used const clerkJSUrl = (params as any)?.__internal_clerkJSUrl as string | undefined; const clerkJSVersion = (params as any)?.__internal_clerkJSVersion as string | undefined; + const clerkUIUrl = (params as any)?.__internal_clerkUIUrl as string | undefined; const clerkUIVersion = (params as any)?.__internal_clerkUIVersion as string | undefined; const prefetchUI = (params as any)?.prefetchUI as boolean | undefined; const hasUI = !!(params as any)?.ui; @@ -60,6 +61,7 @@ function createIntegration() ...buildEnvVarFromOption(domain, 'PUBLIC_CLERK_DOMAIN'), ...buildEnvVarFromOption(clerkJSUrl, 'PUBLIC_CLERK_JS_URL'), ...buildEnvVarFromOption(clerkJSVersion, 'PUBLIC_CLERK_JS_VERSION'), + ...buildEnvVarFromOption(clerkUIUrl, 'PUBLIC_CLERK_UI_URL'), ...buildEnvVarFromOption(clerkUIVersion, 'PUBLIC_CLERK_UI_VERSION'), ...buildEnvVarFromOption( prefetchUI === false || hasUI ? 'false' : undefined, diff --git a/packages/astro/src/internal/merge-env-vars-with-params.ts b/packages/astro/src/internal/merge-env-vars-with-params.ts index e65b3b23530..65128c255bd 100644 --- a/packages/astro/src/internal/merge-env-vars-with-params.ts +++ b/packages/astro/src/internal/merge-env-vars-with-params.ts @@ -26,7 +26,9 @@ function mergePrefetchUIConfig(paramPrefetchUI: AstroClerkIntegrationParams['pre /** * @internal */ -const mergeEnvVarsWithParams = (params?: AstroClerkIntegrationParams & InternalRuntimeOptions & InternalClerkScriptProps) => { +const mergeEnvVarsWithParams = ( + params?: AstroClerkIntegrationParams & InternalRuntimeOptions & InternalClerkScriptProps, +) => { const { signInUrl: paramSignIn, signUpUrl: paramSignUp, diff --git a/packages/nextjs/src/app-router/client/ClerkScripts.tsx b/packages/nextjs/src/app-router/client/ClerkScripts.tsx index d20af071d8d..66017626683 100644 --- a/packages/nextjs/src/app-router/client/ClerkScripts.tsx +++ b/packages/nextjs/src/app-router/client/ClerkScripts.tsx @@ -5,8 +5,15 @@ import { useClerkNextOptions } from '../../client-boundary/NextOptionsContext'; import { ClerkScriptTags } from '../../utils/clerk-script-tags'; export function ClerkScripts() { - const { publishableKey, __internal_clerkJSUrl, __internal_clerkJSVersion, __internal_clerkUIUrl, nonce, prefetchUI } = - useClerkNextOptions(); + const { + publishableKey, + __internal_clerkJSUrl, + __internal_clerkJSVersion, + __internal_clerkUIUrl, + __internal_clerkUIVersion, + nonce, + prefetchUI, + } = useClerkNextOptions(); const { domain, proxyUrl } = useClerk(); if (!publishableKey) { @@ -19,6 +26,7 @@ export function ClerkScripts() { __internal_clerkJSUrl={__internal_clerkJSUrl} __internal_clerkJSVersion={__internal_clerkJSVersion} __internal_clerkUIUrl={__internal_clerkUIUrl} + __internal_clerkUIVersion={__internal_clerkUIVersion} nonce={nonce} domain={domain} proxyUrl={proxyUrl} From 7c88d5f03143f167da1100aca7979d5830b59264 Mon Sep 17 00:00:00 2001 From: Jacek Date: Fri, 20 Feb 2026 10:57:14 -0600 Subject: [PATCH 10/10] add change file --- .../changes/clerk-js-ui-props-internalized.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 packages/upgrade/src/versions/core-3/changes/clerk-js-ui-props-internalized.md diff --git a/packages/upgrade/src/versions/core-3/changes/clerk-js-ui-props-internalized.md b/packages/upgrade/src/versions/core-3/changes/clerk-js-ui-props-internalized.md new file mode 100644 index 00000000000..e9dca2fdcc1 --- /dev/null +++ b/packages/upgrade/src/versions/core-3/changes/clerk-js-ui-props-internalized.md @@ -0,0 +1,28 @@ +--- +title: '`clerkJSUrl`, `clerkJSVersion`, `clerkUIUrl`, and `clerkUIVersion` props removed' +matcher: + - 'clerkJSUrl' + - 'clerkJSVersion' + - 'clerkUIUrl' + - 'clerkUIVersion' +category: 'deprecation-removal' +--- + +The `clerkJSUrl`, `clerkJSVersion`, `clerkUIUrl`, and `clerkUIVersion` props have been removed from `ClerkProvider` and related configuration options. These props were intended for internal use and are no longer part of the public API. + +If you are using these props, prefix them with `__internal_` to continue using them. Note that these are internal APIs and may change without notice. + +A codemod is available to automatically apply this change: + +```diff + +```