diff --git a/.changeset/tidy-pots-sin.md b/.changeset/tidy-pots-sin.md new file mode 100644 index 00000000000..052ba682526 --- /dev/null +++ b/.changeset/tidy-pots-sin.md @@ -0,0 +1,11 @@ +--- +"@clerk/clerk-js": patch +"@clerk/nextjs": patch +"@clerk/react-router": patch +"@clerk/clerk-react": patch +"@clerk/remix": patch +"@clerk/tanstack-react-start": patch +"@clerk/types": patch +--- + +Rename __experimental_checkoutContinueUrl to checkoutContinueUrl diff --git a/packages/clerk-js/package.json b/packages/clerk-js/package.json index fc4d6d025b5..2bda9e3641e 100644 --- a/packages/clerk-js/package.json +++ b/packages/clerk-js/package.json @@ -42,6 +42,7 @@ "clean": "rimraf ./dist", "dev": "rspack serve --config rspack.config.js", "dev:headless": "rspack serve --config rspack.config.js --env variant=\"clerk.headless.browser\"", + "dev:origin": "rspack serve --config rspack.config.js --env devOrigin=http://localhost:4000", "dev:sandbox": "rspack serve --config rspack.config.js --env devOrigin=http://localhost:4000 --env sandbox=1", "lint": "eslint src", "lint:attw": "attw --pack . --profile node16 --ignore-rules named-exports", diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 25b5ad13860..ae60a8ec973 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -175,7 +175,7 @@ const defaultOptions: ClerkOptions = { signInForceRedirectUrl: undefined, signUpForceRedirectUrl: undefined, treatPendingAsSignedOut: true, - __experimental_checkoutContinueUrl: undefined, + checkoutContinueUrl: undefined, }; export class Clerk implements ClerkInterface { @@ -1378,12 +1378,12 @@ export class Clerk implements ClerkInterface { return this.buildUrlWithAuth(this.#options.afterSignOutUrl); } - public __experimental_buildCheckoutContinueUrl(): string { - if (!this.#options.__experimental_checkoutContinueUrl) { + public buildCheckoutContinueUrl(): string { + if (!this.#options.checkoutContinueUrl) { return this.buildAfterSignInUrl(); } - return this.#options.__experimental_checkoutContinueUrl; + return this.#options.checkoutContinueUrl; } public buildWaitlistUrl(options?: { initialValues?: Record }): string { diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx index 39465d51b01..d1f29af89b8 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx @@ -19,11 +19,11 @@ export const CheckoutComplete = ({ }) => { const router = useRouter(); const { setIsOpen } = useDrawerContext(); - const { __experimental_checkoutContinueUrl } = useCheckoutContext(); + const { checkoutContinueUrl } = useCheckoutContext(); const handleClose = () => { - if (__experimental_checkoutContinueUrl) { - void router.navigate(__experimental_checkoutContinueUrl); + if (checkoutContinueUrl) { + void router.navigate(checkoutContinueUrl); } if (setIsOpen) { setIsOpen(false); diff --git a/packages/clerk-js/src/ui/contexts/components/Checkout.ts b/packages/clerk-js/src/ui/contexts/components/Checkout.ts index ea85472fe80..a4fe05e4ab0 100644 --- a/packages/clerk-js/src/ui/contexts/components/Checkout.ts +++ b/packages/clerk-js/src/ui/contexts/components/Checkout.ts @@ -1,12 +1,16 @@ import { useClerk } from '@clerk/shared/react'; import { createContext, useContext, useMemo } from 'react'; +import { isAllowedRedirect } from '../../../utils'; import type { __experimental_CheckoutCtx } from '../../types'; +import { useOptions } from '../OptionsContext'; + export const __experimental_CheckoutContext = createContext<__experimental_CheckoutCtx | null>(null); export const useCheckoutContext = () => { const context = useContext(__experimental_CheckoutContext); const clerk = useClerk(); + const options = useOptions(); if (!context || context.componentName !== 'Checkout') { throw new Error('Clerk: useCheckoutContext called outside Checkout.'); @@ -19,18 +23,15 @@ export const useCheckoutContext = () => { return undefined; } - if (context.__experimental_checkoutContinueUrl) { - return context.__experimental_checkoutContinueUrl; - } - - return clerk.__experimental_buildCheckoutContinueUrl?.(); - }, [context.portalRoot, context.__experimental_checkoutContinueUrl, clerk]); + const url = context.checkoutContinueUrl || clerk.buildCheckoutContinueUrl?.(); + return isAllowedRedirect(options?.allowedRedirectOrigins, window.location.origin)(url) ? url : undefined; + }, [context.portalRoot, context.checkoutContinueUrl, clerk, options?.allowedRedirectOrigins]); const { componentName, ...ctx } = context; return { ...ctx, componentName, - __experimental_checkoutContinueUrl: checkoutContinueUrl, + checkoutContinueUrl, }; }; diff --git a/packages/clerk-js/src/ui/types.ts b/packages/clerk-js/src/ui/types.ts index af7aef1ef07..45dd9d09543 100644 --- a/packages/clerk-js/src/ui/types.ts +++ b/packages/clerk-js/src/ui/types.ts @@ -1,5 +1,4 @@ import type { - __experimental_CheckoutContinueUrl, __experimental_CheckoutProps, __experimental_CommerceInvoiceResource, __experimental_CommercePlanResource, @@ -7,6 +6,7 @@ import type { __experimental_PlanDetailsProps, __experimental_PricingTableProps, __internal_UserVerificationProps, + CheckoutContinueUrl, CreateOrganizationProps, GoogleOneTapProps, OrganizationListProps, @@ -119,7 +119,7 @@ export type __experimental_PricingTableCtx = __experimental_PricingTableProps & export type __experimental_CheckoutCtx = __experimental_CheckoutProps & { componentName: 'Checkout'; -} & __experimental_CheckoutContinueUrl; +} & CheckoutContinueUrl; export type __experimental_PaymentSourcesCtx = { componentName: 'PaymentSources'; diff --git a/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts b/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts index 80ea636ca2d..9068d0ea940 100644 --- a/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts +++ b/packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts @@ -25,8 +25,7 @@ export const mergeNextClerkPropsWithEnv = (props: Omit { signUpFallbackRedirectUrl: getValue('CLERK_SIGN_UP_FALLBACK_REDIRECT_URL'), afterSignInUrl: getValue('CLERK_AFTER_SIGN_IN_URL'), afterSignUpUrl: getValue('CLERK_AFTER_SIGN_UP_URL'), - __experimental_checkoutContinueUrl: getValue('CLERK_CHECKOUT_CONTINUE_URL'), + checkoutContinueUrl: getValue('CLERK_CHECKOUT_CONTINUE_URL'), }; }; diff --git a/packages/react/src/isomorphicClerk.ts b/packages/react/src/isomorphicClerk.ts index 73239079b99..5f43be3380d 100644 --- a/packages/react/src/isomorphicClerk.ts +++ b/packages/react/src/isomorphicClerk.ts @@ -323,12 +323,12 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk { } }; - __experimental_buildCheckoutContinueUrl = (): string | void => { - const callback = () => this.clerkjs?.__experimental_buildCheckoutContinueUrl() || ''; + buildCheckoutContinueUrl = (): string | void => { + const callback = () => this.clerkjs?.buildCheckoutContinueUrl() || ''; if (this.clerkjs && this.loaded) { return callback(); } else { - this.premountMethodCalls.set('__experimental_buildCheckoutContinueUrl', callback); + this.premountMethodCalls.set('buildCheckoutContinueUrl', callback); } }; diff --git a/packages/remix/src/ssr/loadOptions.ts b/packages/remix/src/ssr/loadOptions.ts index cce8f2c6153..5241cc381b1 100644 --- a/packages/remix/src/ssr/loadOptions.ts +++ b/packages/remix/src/ssr/loadOptions.ts @@ -45,8 +45,8 @@ export const loadOptions = (args: LoaderFunctionArgs, overrides: RootAuthLoaderO overrides.signUpFallbackRedirectUrl || getEnvVariable('CLERK_SIGN_UP_FALLBACK_REDIRECT_URL', context) || ''; const afterSignInUrl = overrides.afterSignInUrl || getEnvVariable('CLERK_AFTER_SIGN_IN_URL', context) || ''; const afterSignUpUrl = overrides.afterSignUpUrl || getEnvVariable('CLERK_AFTER_SIGN_UP_URL', context) || ''; - const __experimental_checkoutContinueUrl = - overrides.__experimental_checkoutContinueUrl || getEnvVariable('CLERK_CHECKOUT_CONTINUE_URL', context) || ''; + const checkoutContinueUrl = + overrides.checkoutContinueUrl || getEnvVariable('CLERK_CHECKOUT_CONTINUE_URL', context) || ''; let proxyUrl; if (!!relativeOrAbsoluteProxyUrl && isProxyUrlRelative(relativeOrAbsoluteProxyUrl)) { @@ -83,6 +83,6 @@ export const loadOptions = (args: LoaderFunctionArgs, overrides: RootAuthLoaderO signUpForceRedirectUrl, signInFallbackRedirectUrl, signUpFallbackRedirectUrl, - __experimental_checkoutContinueUrl, + checkoutContinueUrl, }; }; diff --git a/packages/remix/src/ssr/types.ts b/packages/remix/src/ssr/types.ts index 0f5e6bc0615..b83c502c142 100644 --- a/packages/remix/src/ssr/types.ts +++ b/packages/remix/src/ssr/types.ts @@ -1,7 +1,7 @@ import type { AuthObject, Organization, Session, User, VerifyTokenOptions } from '@clerk/backend'; import type { RequestState } from '@clerk/backend/internal'; import type { - __experimental_CheckoutContinueUrl, + CheckoutContinueUrl, LegacyRedirectProps, MultiDomainAndOrProxy, SignInFallbackRedirectUrl, @@ -37,7 +37,7 @@ export type RootAuthLoaderOptions = { SignInFallbackRedirectUrl & SignUpForceRedirectUrl & SignUpFallbackRedirectUrl & - __experimental_CheckoutContinueUrl & + CheckoutContinueUrl & LegacyRedirectProps; export type RequestStateWithRedirectUrls = RequestState & @@ -45,7 +45,7 @@ export type RequestStateWithRedirectUrls = RequestState & SignInFallbackRedirectUrl & SignUpForceRedirectUrl & SignUpFallbackRedirectUrl & - __experimental_CheckoutContinueUrl & + CheckoutContinueUrl & LegacyRedirectProps; export type RootAuthLoaderCallback = ( diff --git a/packages/remix/src/ssr/utils.ts b/packages/remix/src/ssr/utils.ts index 56d43875342..dc25efc1609 100644 --- a/packages/remix/src/ssr/utils.ts +++ b/packages/remix/src/ssr/utils.ts @@ -94,7 +94,7 @@ export function getResponseClerkState(requestState: RequestStateWithRedirectUrls __signUpForceRedirectUrl: requestState.signUpForceRedirectUrl, __signInFallbackRedirectUrl: requestState.signInFallbackRedirectUrl, __signUpFallbackRedirectUrl: requestState.signUpFallbackRedirectUrl, - __experimental_checkoutContinueUrl: requestState.__experimental_checkoutContinueUrl, + checkoutContinueUrl: requestState.checkoutContinueUrl, __clerk_debug: debugRequestState(requestState), __clerkJSUrl: getEnvVariable('CLERK_JS', context), __clerkJSVersion: getEnvVariable('CLERK_JS_VERSION', context), diff --git a/packages/tanstack-react-start/src/utils/env.ts b/packages/tanstack-react-start/src/utils/env.ts index fa1bc745207..0f90ef373c2 100644 --- a/packages/tanstack-react-start/src/utils/env.ts +++ b/packages/tanstack-react-start/src/utils/env.ts @@ -21,6 +21,6 @@ export const getPublicEnvVariables = (context?: H3EventContext) => { telemetryDebug: isTruthy(getValue('CLERK_TELEMETRY_DEBUG')), afterSignInUrl: getValue('CLERK_AFTER_SIGN_IN_URL'), afterSignUpUrl: getValue('CLERK_AFTER_SIGN_UP_URL'), - __experimental_checkoutContinueUrl: getValue('CLERK_CHECKOUT_CONTINUE_URL'), + checkoutContinueUrl: getValue('CLERK_CHECKOUT_CONTINUE_URL'), } as const; }; diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index 862aa28e4f8..511eeec8b2b 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -30,9 +30,9 @@ import type { OAuthProvider, OAuthScope } from './oauth'; import type { OrganizationResource } from './organization'; import type { OrganizationCustomRoleKey } from './organizationMembership'; import type { - __experimental_CheckoutContinueUrl, AfterMultiSessionSingleSignOutUrl, AfterSignOutUrl, + CheckoutContinueUrl, LegacyRedirectProps, RedirectOptions, RedirectUrlProp, @@ -569,7 +569,7 @@ export interface Clerk { /** * Returns the configured checkoutContinueUrl of the instance. */ - __experimental_buildCheckoutContinueUrl(): string; + buildCheckoutContinueUrl(): string; /** * Returns the configured afterMultiSessionSingleSignOutUrl of the instance. @@ -820,7 +820,7 @@ export type ClerkOptions = PendingSessionOptions & SignInFallbackRedirectUrl & SignUpForceRedirectUrl & SignUpFallbackRedirectUrl & - __experimental_CheckoutContinueUrl & + CheckoutContinueUrl & LegacyRedirectProps & AfterSignOutUrl & AfterMultiSessionSingleSignOutUrl & { @@ -1570,7 +1570,7 @@ export type WaitlistModalProps = WaitlistProps; type __experimental_PricingTableDefaultProps = { ctaPosition?: 'top' | 'bottom'; collapseFeatures?: boolean; - __experimental_checkoutContinueUrl?: string; + checkoutContinueUrl?: string; }; type __experimental_PricingTableBaseProps = { @@ -1596,7 +1596,7 @@ export type __experimental_CheckoutProps = { * Full URL or path to navigate to after checkout is complete and the user clicks the "Continue" button. * @default undefined */ - __experimental_checkoutContinueUrl?: string; + checkoutContinueUrl?: string; }; export type __experimental_PlanDetailsProps = { diff --git a/packages/types/src/redirects.ts b/packages/types/src/redirects.ts index f5b6867bd1a..447dc7494e3 100644 --- a/packages/types/src/redirects.ts +++ b/packages/types/src/redirects.ts @@ -122,9 +122,9 @@ export type SignInForceRedirectUrl = { signInForceRedirectUrl?: string | null; }; -export type __experimental_CheckoutContinueUrl = { +export type CheckoutContinueUrl = { /** * The URL to navigate to after the user completes the checkout and clicks the "Continue" button. */ - __experimental_checkoutContinueUrl?: string | null; + checkoutContinueUrl?: string | null; };