Loading...
\n * }\n *\n * if (!isSignedIn) {\n * return [0]) => {\n if (has) {\n return has(params);\n }\n return createCheckAuthorization({\n userId,\n orgId,\n orgRole,\n orgPermissions,\n factorVerificationAge,\n })(params);\n },\n [userId, factorVerificationAge, orgId, orgRole, orgPermissions],\n );\n\n if (sessionId === undefined && userId === undefined) {\n return {\n isLoaded: false,\n isSignedIn: undefined,\n sessionId,\n userId,\n actor: undefined,\n orgId: undefined,\n orgRole: undefined,\n orgSlug: undefined,\n has: undefined,\n signOut,\n getToken,\n };\n }\n\n if (sessionId === null && userId === null) {\n return {\n isLoaded: true,\n isSignedIn: false,\n sessionId,\n userId,\n actor: null,\n orgId: null,\n orgRole: null,\n orgSlug: null,\n has: () => false,\n signOut,\n getToken,\n };\n }\n\n if (!!sessionId && !!userId && !!orgId && !!orgRole) {\n return {\n isLoaded: true,\n isSignedIn: true,\n sessionId,\n userId,\n actor: actor || null,\n orgId,\n orgRole,\n orgSlug: orgSlug || null,\n has: derivedHas,\n signOut,\n getToken,\n };\n }\n\n if (!!sessionId && !!userId && !orgId) {\n return {\n isLoaded: true,\n isSignedIn: true,\n sessionId,\n userId,\n actor: actor || null,\n orgId: null,\n orgRole: null,\n orgSlug: null,\n has: derivedHas,\n signOut,\n getToken,\n };\n }\n\n return errorThrower.throw(invalidStateError);\n}\n","import { useClientContext } from '@clerk/shared/react';\nimport { eventMethodCalled } from '@clerk/shared/telemetry';\nimport type { UseSignInReturn } from '@clerk/types';\n\nimport { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext';\nimport { useAssertWrappedByClerkProvider } from './useAssertWrappedByClerkProvider';\n\n/**\n * The `useSignIn()` hook provides access to the [`SignIn`](https://clerk.com/docs/references/javascript/sign-in/sign-in) object, which allows you to check the current state of a sign-in attempt and manage the sign-in flow. You can use this to create a [custom sign-in flow](https://clerk.com/docs/custom-flows/overview#sign-in-flow).\n *\n * @example\n * ### Check the current state of a sign-in\n *\n * The following example uses the `useSignIn()` hook to access the [`SignIn`](https://clerk.com/docs/references/javascript/sign-in/sign-in) object, which contains the current sign-in attempt status and methods to create a new sign-in attempt. The `isLoaded` property is used to handle the loading state.\n *\n * ```tsx {{ filename: 'src/pages/SignInPage.tsx' }}\n * import { useSignIn } from '@clerk/clerk-react'\n *\n * export default function SignInPage() {\n * const { isLoaded, signIn } = useSignIn()\n *\n * if (!isLoaded) {\n * // Handle loading state\n * return null\n * }\n *\n * return The current sign-in attempt status is {signIn?.status}.
\n * }\n * ```\n *\n * @example\n * ### Create a custom sign-in flow with `useSignIn()`\n *\n * The `useSignIn()` hook can also be used to build fully custom sign-in flows, if Clerk's prebuilt components don't meet your specific needs or if you require more control over the authentication flow. Different sign-in flows include email and password, email and phone codes, email links, and multifactor (MFA). To learn more about using the `useSignIn()` hook to create custom flows, see the [custom flow guides](https://clerk.com/docs/custom-flows/overview).\n *\n * ```\n * ```\n */\nexport const useSignIn = (): UseSignInReturn => {\n useAssertWrappedByClerkProvider('useSignIn');\n\n const isomorphicClerk = useIsomorphicClerkContext();\n const client = useClientContext();\n\n isomorphicClerk.telemetry?.record(eventMethodCalled('useSignIn'));\n\n if (!client) {\n return { isLoaded: false, signIn: undefined, setActive: undefined };\n }\n\n return {\n isLoaded: true,\n signIn: client.signIn,\n setActive: isomorphicClerk.setActive,\n };\n};\n","import type { LoadedClerk, Without } from '@clerk/types';\nimport React from 'react';\n\nimport { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext';\nimport { useAssertWrappedByClerkProvider } from '../hooks/useAssertWrappedByClerkProvider';\n\nexport const withClerk = (\n Component: React.ComponentType
,\n displayNameOrOptions?: string | { component: string; renderWhileLoading?: boolean },\n) => {\n const passedDisplayedName =\n typeof displayNameOrOptions === 'string' ? displayNameOrOptions : displayNameOrOptions?.component;\n const displayName = passedDisplayedName || Component.displayName || Component.name || 'Component';\n Component.displayName = displayName;\n\n const options = typeof displayNameOrOptions === 'string' ? undefined : displayNameOrOptions;\n\n const HOC = (props: Without
) => {\n useAssertWrappedByClerkProvider(displayName || 'withClerk');\n\n const clerk = useIsomorphicClerkContext();\n\n if (!clerk.loaded && !options?.renderWhileLoading) {\n return null;\n }\n\n return (\n \n );\n };\n HOC.displayName = `withClerk(${displayName})`;\n return HOC;\n};\n","import { deprecated } from '@clerk/shared/deprecated';\nimport type {\n CheckAuthorizationWithCustomPermissions,\n HandleOAuthCallbackParams,\n OrganizationCustomPermissionKey,\n OrganizationCustomRoleKey,\n} from '@clerk/types';\nimport React from 'react';\n\nimport { useAuthContext } from '../contexts/AuthContext';\nimport { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext';\nimport { useSessionContext } from '../contexts/SessionContext';\nimport { useAuth } from '../hooks';\nimport { useAssertWrappedByClerkProvider } from '../hooks/useAssertWrappedByClerkProvider';\nimport type { RedirectToSignInProps, RedirectToSignUpProps, WithClerkProp } from '../types';\nimport { withClerk } from './withClerk';\n\nexport const SignedIn = ({ children }: React.PropsWithChildren) => {\n useAssertWrappedByClerkProvider('SignedIn');\n\n const { userId } = useAuthContext();\n if (userId) {\n return children;\n }\n return null;\n};\n\nexport const SignedOut = ({ children }: React.PropsWithChildren) => {\n useAssertWrappedByClerkProvider('SignedOut');\n\n const { userId } = useAuthContext();\n if (userId === null) {\n return children;\n }\n return null;\n};\n\nexport const ClerkLoaded = ({ children }: React.PropsWithChildren) => {\n useAssertWrappedByClerkProvider('ClerkLoaded');\n\n const isomorphicClerk = useIsomorphicClerkContext();\n if (!isomorphicClerk.loaded) {\n return null;\n }\n return children;\n};\n\nexport const ClerkLoading = ({ children }: React.PropsWithChildren) => {\n useAssertWrappedByClerkProvider('ClerkLoading');\n\n const isomorphicClerk = useIsomorphicClerkContext();\n if (isomorphicClerk.loaded) {\n return null;\n }\n return children;\n};\n\nexport type ProtectProps = React.PropsWithChildren<\n (\n | {\n condition?: never;\n role: OrganizationCustomRoleKey;\n permission?: never;\n }\n | {\n condition?: never;\n role?: never;\n permission: OrganizationCustomPermissionKey;\n }\n | {\n condition: (has: CheckAuthorizationWithCustomPermissions) => boolean;\n role?: never;\n permission?: never;\n }\n | {\n condition?: never;\n role?: never;\n permission?: never;\n }\n ) & {\n fallback?: React.ReactNode;\n }\n>;\n\n/**\n * Use `` in order to prevent unauthenticated or unauthorized users from accessing the children passed to the component.\n *\n * Examples:\n * ```\n * \n * \n * has({permission:\"a_permission_key\"})} />\n * has({role:\"a_role_key\"})} />\n * Unauthorized
} />\n * ```\n */\nexport const Protect = ({ children, fallback, ...restAuthorizedParams }: ProtectProps) => {\n useAssertWrappedByClerkProvider('Protect');\n\n const { isLoaded, has, userId } = useAuth();\n\n /**\n * Avoid flickering children or fallback while clerk is loading sessionId or userId\n */\n if (!isLoaded) {\n return null;\n }\n\n /**\n * Fallback to UI provided by user or `null` if authorization checks failed\n */\n const unauthorized = fallback ?? null;\n\n const authorized = children;\n\n if (!userId) {\n return unauthorized;\n }\n\n /**\n * Check against the results of `has` called inside the callback\n */\n if (typeof restAuthorizedParams.condition === 'function') {\n if (restAuthorizedParams.condition(has)) {\n return authorized;\n }\n return unauthorized;\n }\n\n if (restAuthorizedParams.role || restAuthorizedParams.permission) {\n if (has(restAuthorizedParams)) {\n return authorized;\n }\n return unauthorized;\n }\n\n /**\n * If neither of the authorization params are passed behave as the ``.\n * If fallback is present render that instead of rendering nothing.\n */\n return authorized;\n};\n\nexport const RedirectToSignIn = withClerk(({ clerk, ...props }: WithClerkProp) => {\n const { client, session } = clerk;\n\n const hasSignedInSessions = client.signedInSessions\n ? client.signedInSessions.length > 0\n : // Compat for clerk-js<5.54.0 (which was released with the `signedInSessions` property)\n client.activeSessions && client.activeSessions.length > 0;\n\n React.useEffect(() => {\n if (session === null && hasSignedInSessions) {\n void clerk.redirectToAfterSignOut();\n } else {\n void clerk.redirectToSignIn(props);\n }\n }, []);\n\n return null;\n}, 'RedirectToSignIn');\n\nexport const RedirectToSignUp = withClerk(({ clerk, ...props }: WithClerkProp) => {\n React.useEffect(() => {\n void clerk.redirectToSignUp(props);\n }, []);\n\n return null;\n}, 'RedirectToSignUp');\n\n/**\n * @deprecated Use [`redirectToUserProfile()`](https://clerk.com/docs/references/javascript/clerk/redirect-methods#redirect-to-user-profile) instead, will be removed in the next major version.\n */\nexport const RedirectToUserProfile = withClerk(({ clerk }) => {\n React.useEffect(() => {\n deprecated('RedirectToUserProfile', 'Use the `redirectToUserProfile()` method instead.');\n void clerk.redirectToUserProfile();\n }, []);\n\n return null;\n}, 'RedirectToUserProfile');\n\n/**\n * @deprecated Use [`redirectToOrganizationProfile()`](https://clerk.com/docs/references/javascript/clerk/redirect-methods#redirect-to-organization-profile) instead, will be removed in the next major version.\n */\nexport const RedirectToOrganizationProfile = withClerk(({ clerk }) => {\n React.useEffect(() => {\n deprecated('RedirectToOrganizationProfile', 'Use the `redirectToOrganizationProfile()` method instead.');\n void clerk.redirectToOrganizationProfile();\n }, []);\n\n return null;\n}, 'RedirectToOrganizationProfile');\n\n/**\n * @deprecated Use [`redirectToCreateOrganization()`](https://clerk.com/docs/references/javascript/clerk/redirect-methods#redirect-to-create-organization) instead, will be removed in the next major version.\n */\nexport const RedirectToCreateOrganization = withClerk(({ clerk }) => {\n React.useEffect(() => {\n deprecated('RedirectToCreateOrganization', 'Use the `redirectToCreateOrganization()` method instead.');\n void clerk.redirectToCreateOrganization();\n }, []);\n\n return null;\n}, 'RedirectToCreateOrganization');\n\nexport const AuthenticateWithRedirectCallback = withClerk(\n ({ clerk, ...handleRedirectCallbackParams }: WithClerkProp) => {\n React.useEffect(() => {\n void clerk.handleRedirectCallback(handleRedirectCallbackParams);\n }, []);\n\n return null;\n },\n 'AuthenticateWithRedirectCallback',\n);\n\nexport const MultisessionAppSupport = ({ children }: React.PropsWithChildren) => {\n useAssertWrappedByClerkProvider('MultisessionAppSupport');\n\n const session = useSessionContext();\n return {children};\n};\n","import { CURRENT_DEV_INSTANCE_SUFFIXES, LEGACY_DEV_INSTANCE_SUFFIXES } from './constants';\nimport { isStaging } from './utils/instance';\n\nexport function parseSearchParams(queryString = ''): URLSearchParams {\n if (queryString.startsWith('?')) {\n queryString = queryString.slice(1);\n }\n return new URLSearchParams(queryString);\n}\n\nexport function stripScheme(url = ''): string {\n return (url || '').replace(/^.+:\\/\\//, '');\n}\n\nexport function addClerkPrefix(str: string | undefined) {\n if (!str) {\n return '';\n }\n let regex;\n if (str.match(/^(clerk\\.)+\\w*$/)) {\n regex = /(clerk\\.)*(?=clerk\\.)/;\n } else if (str.match(/\\.clerk.accounts/)) {\n return str;\n } else {\n regex = /^(clerk\\.)*/gi;\n }\n\n const stripped = str.replace(regex, '');\n return `clerk.${stripped}`;\n}\n\n/**\n *\n * Retrieve the clerk-js major tag using the major version from the pkgVersion\n * param or use the frontendApi to determine if the canary tag should be used.\n * The default tag is `latest`.\n */\nexport const getClerkJsMajorVersionOrTag = (frontendApi: string, version?: string) => {\n if (!version && isStaging(frontendApi)) {\n return 'canary';\n }\n\n if (!version) {\n return 'latest';\n }\n\n return version.split('.')[0] || 'latest';\n};\n\n/**\n *\n * Retrieve the clerk-js script url from the frontendApi and the major tag\n * using the {@link getClerkJsMajorVersionOrTag} or a provided clerkJSVersion tag.\n */\nexport const getScriptUrl = (frontendApi: string, { clerkJSVersion }: { clerkJSVersion?: string }) => {\n const noSchemeFrontendApi = frontendApi.replace(/http(s)?:\\/\\//, '');\n const major = getClerkJsMajorVersionOrTag(frontendApi, clerkJSVersion);\n return `https://${noSchemeFrontendApi}/npm/@clerk/clerk-js@${clerkJSVersion || major}/dist/clerk.browser.js`;\n};\n\n// Returns true for hosts such as:\n// * accounts.foo.bar-13.lcl.dev\n// * accounts.foo.bar-13.lclstage.dev\n// * accounts.foo.bar-13.dev.lclclerk.com\nexport function isLegacyDevAccountPortalOrigin(host: string): boolean {\n return LEGACY_DEV_INSTANCE_SUFFIXES.some(legacyDevSuffix => {\n return host.startsWith('accounts.') && host.endsWith(legacyDevSuffix);\n });\n}\n\n// Returns true for hosts such as:\n// * foo-bar-13.accounts.dev\n// * foo-bar-13.accountsstage.dev\n// * foo-bar-13.accounts.lclclerk.com\n// But false for:\n// * foo-bar-13.clerk.accounts.lclclerk.com\nexport function isCurrentDevAccountPortalOrigin(host: string): boolean {\n return CURRENT_DEV_INSTANCE_SUFFIXES.some(currentDevSuffix => {\n return host.endsWith(currentDevSuffix) && !host.endsWith('.clerk' + currentDevSuffix);\n });\n}\n\n/* Functions below are taken from https://github.com/unjs/ufo/blob/main/src/utils.ts. LICENSE: MIT */\n\nconst TRAILING_SLASH_RE = /\\/$|\\/\\?|\\/#/;\n\nexport function hasTrailingSlash(input = '', respectQueryAndFragment?: boolean): boolean {\n if (!respectQueryAndFragment) {\n return input.endsWith('/');\n }\n return TRAILING_SLASH_RE.test(input);\n}\n\nexport function withTrailingSlash(input = '', respectQueryAndFragment?: boolean): string {\n if (!respectQueryAndFragment) {\n return input.endsWith('/') ? input : input + '/';\n }\n if (hasTrailingSlash(input, true)) {\n return input || '/';\n }\n let path = input;\n let fragment = '';\n const fragmentIndex = input.indexOf('#');\n if (fragmentIndex >= 0) {\n path = input.slice(0, fragmentIndex);\n fragment = input.slice(fragmentIndex);\n if (!path) {\n return fragment;\n }\n }\n const [s0, ...s] = path.split('?');\n return s0 + '/' + (s.length > 0 ? `?${s.join('?')}` : '') + fragment;\n}\n\nexport function withoutTrailingSlash(input = '', respectQueryAndFragment?: boolean): string {\n if (!respectQueryAndFragment) {\n return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || '/';\n }\n if (!hasTrailingSlash(input, true)) {\n return input || '/';\n }\n let path = input;\n let fragment = '';\n const fragmentIndex = input.indexOf('#');\n if (fragmentIndex >= 0) {\n path = input.slice(0, fragmentIndex);\n fragment = input.slice(fragmentIndex);\n }\n const [s0, ...s] = path.split('?');\n return (s0.slice(0, -1) || '/') + (s.length > 0 ? `?${s.join('?')}` : '') + fragment;\n}\n\nexport function hasLeadingSlash(input = ''): boolean {\n return input.startsWith('/');\n}\n\nexport function withoutLeadingSlash(input = ''): string {\n return (hasLeadingSlash(input) ? input.slice(1) : input) || '/';\n}\n\nexport function withLeadingSlash(input = ''): string {\n return hasLeadingSlash(input) ? input : '/' + input;\n}\n\nexport function cleanDoubleSlashes(input = ''): string {\n return input\n .split('://')\n .map(string_ => string_.replace(/\\/{2,}/g, '/'))\n .join('://');\n}\n\nexport function isNonEmptyURL(url: string) {\n return url && url !== '/';\n}\n\nconst JOIN_LEADING_SLASH_RE = /^\\.?\\//;\n\nexport function joinURL(base: string, ...input: string[]): string {\n let url = base || '';\n\n for (const segment of input.filter(url => isNonEmptyURL(url))) {\n if (url) {\n // TODO: Handle .. when joining\n const _segment = segment.replace(JOIN_LEADING_SLASH_RE, '');\n url = withTrailingSlash(url) + _segment;\n } else {\n url = segment;\n }\n }\n\n return url;\n}\n\n/* Code below is taken from https://github.com/vercel/next.js/blob/fe7ff3f468d7651a92865350bfd0f16ceba27db5/packages/next/src/shared/lib/utils.ts. LICENSE: MIT */\n\n// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1\n// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3\nconst ABSOLUTE_URL_REGEX = /^[a-zA-Z][a-zA-Z\\d+\\-.]*?:/;\nexport const isAbsoluteUrl = (url: string) => ABSOLUTE_URL_REGEX.test(url);\n","/**\n * This version selector is a bit complicated, so here is the flow:\n * 1. Use the clerkJSVersion prop on the provider\n * 2. Use the exact `@clerk/clerk-js` version if it is a `@snapshot` prerelease\n * 3. Use the prerelease tag of `@clerk/clerk-js` or the packageVersion provided\n * 4. Fallback to the major version of `@clerk/clerk-js` or the packageVersion provided\n * @param clerkJSVersion - The optional clerkJSVersion prop on the provider\n * @param packageVersion - The version of `@clerk/clerk-js` that will be used if an explicit version is not provided\n * @returns The npm tag, version or major version to use\n */\nexport const versionSelector = (clerkJSVersion: string | undefined, packageVersion = JS_PACKAGE_VERSION) => {\n if (clerkJSVersion) {\n return clerkJSVersion;\n }\n\n const prereleaseTag = getPrereleaseTag(packageVersion);\n if (prereleaseTag) {\n if (prereleaseTag === 'snapshot') {\n return JS_PACKAGE_VERSION;\n }\n\n return prereleaseTag;\n }\n\n return getMajorVersion(packageVersion);\n};\n\nconst getPrereleaseTag = (packageVersion: string) =>\n packageVersion\n .trim()\n .replace(/^v/, '')\n .match(/-(.+?)(\\.|$)/)?.[1];\n\nexport const getMajorVersion = (packageVersion: string) => packageVersion.trim().replace(/^v/, '').split('.')[0];\n","export function isValidProxyUrl(key: string | undefined) {\n if (!key) {\n return true;\n }\n\n return isHttpOrHttps(key) || isProxyUrlRelative(key);\n}\n\nexport function isHttpOrHttps(key: string | undefined) {\n return /^http(s)?:\\/\\//.test(key || '');\n}\n\nexport function isProxyUrlRelative(key: string) {\n return key.startsWith('/');\n}\n\nexport function proxyUrlToAbsoluteURL(url: string | undefined): string {\n if (!url) {\n return '';\n }\n return isProxyUrlRelative(url) ? new URL(url, window.location.origin).toString() : url;\n}\n","type Milliseconds = number;\n\ntype RetryOptions = Partial<{\n /**\n * The initial delay before the first retry.\n * @default 125\n */\n initialDelay: Milliseconds;\n /**\n * The maximum delay between retries.\n * The delay between retries will never exceed this value.\n * If set to 0, the delay will increase indefinitely.\n * @default 0\n */\n maxDelayBetweenRetries: Milliseconds;\n /**\n * The multiplier for the exponential backoff.\n * @default 2\n */\n factor: number;\n /**\n * A function to determine if the operation should be retried.\n * The callback accepts the error that was thrown and the number of iterations.\n * The iterations variable references the number of retries AFTER attempt\n * that caused the error and starts at 1 (as in, this is the 1st, 2nd, nth retry).\n * @default (error, iterations) => iterations < 5\n */\n shouldRetry: (error: unknown, iterations: number) => boolean;\n /**\n * Controls whether the helper should retry the operation immediately once before applying exponential backoff.\n * The delay for the immediate retry is 100ms.\n * @default true\n */\n retryImmediately: boolean;\n /**\n * If true, the intervals will be multiplied by a factor in the range of [1,2].\n * @default true\n */\n jitter: boolean;\n}>;\n\nconst defaultOptions: Required = {\n initialDelay: 125,\n maxDelayBetweenRetries: 0,\n factor: 2,\n shouldRetry: (_: unknown, iteration: number) => iteration < 5,\n retryImmediately: true,\n jitter: true,\n};\n\nconst RETRY_IMMEDIATELY_DELAY = 100;\n\nconst sleep = async (ms: Milliseconds) => new Promise(s => setTimeout(s, ms));\n\nconst applyJitter = (delay: Milliseconds, jitter: boolean) => {\n return jitter ? delay * (1 + Math.random()) : delay;\n};\n\nconst createExponentialDelayAsyncFn = (\n opts: Required>,\n) => {\n let timesCalled = 0;\n\n const calculateDelayInMs = () => {\n const constant = opts.initialDelay;\n const base = opts.factor;\n let delay = constant * Math.pow(base, timesCalled);\n delay = applyJitter(delay, opts.jitter);\n return Math.min(opts.maxDelayBetweenRetries || delay, delay);\n };\n\n return async (): Promise => {\n await sleep(calculateDelayInMs());\n timesCalled++;\n };\n};\n\n/**\n * Retries a callback until it succeeds or the shouldRetry function returns false.\n * See {@link RetryOptions} for the available options.\n */\nexport const retry = async (callback: () => T | Promise, options: RetryOptions = {}): Promise => {\n let iterations = 0;\n const { shouldRetry, initialDelay, maxDelayBetweenRetries, factor, retryImmediately, jitter } = {\n ...defaultOptions,\n ...options,\n };\n\n const delay = createExponentialDelayAsyncFn({\n initialDelay,\n maxDelayBetweenRetries,\n factor,\n jitter,\n });\n\n while (true) {\n try {\n return await callback();\n } catch (e) {\n iterations++;\n if (!shouldRetry(e, iterations)) {\n throw e;\n }\n if (retryImmediately && iterations === 1) {\n await sleep(applyJitter(RETRY_IMMEDIATELY_DELAY, jitter));\n } else {\n await delay();\n }\n }\n }\n};\n","import { retry } from './retry';\n\nconst NO_DOCUMENT_ERROR = 'loadScript cannot be called when document does not exist';\nconst NO_SRC_ERROR = 'loadScript cannot be called without a src';\n\ntype LoadScriptOptions = {\n async?: boolean;\n defer?: boolean;\n crossOrigin?: 'anonymous' | 'use-credentials';\n nonce?: string;\n beforeLoad?: (script: HTMLScriptElement) => void;\n};\n\nexport async function loadScript(src = '', opts: LoadScriptOptions): Promise {\n const { async, defer, beforeLoad, crossOrigin, nonce } = opts || {};\n\n const load = () => {\n return new Promise((resolve, reject) => {\n if (!src) {\n reject(new Error(NO_SRC_ERROR));\n }\n\n if (!document || !document.body) {\n reject(NO_DOCUMENT_ERROR);\n }\n\n const script = document.createElement('script');\n\n if (crossOrigin) script.setAttribute('crossorigin', crossOrigin);\n script.async = async || false;\n script.defer = defer || false;\n\n script.addEventListener('load', () => {\n script.remove();\n resolve(script);\n });\n\n script.addEventListener('error', () => {\n script.remove();\n reject();\n });\n\n script.src = src;\n script.nonce = nonce;\n beforeLoad?.(script);\n document.body.appendChild(script);\n });\n };\n\n return retry(load, { shouldRetry: (_, iterations) => iterations <= 5 });\n}\n","/**\n * A function that decodes a string of data which has been encoded using base-64 encoding.\n * Uses `atob` if available, otherwise uses `Buffer` from `global`. If neither are available, returns the data as-is.\n */\nexport const isomorphicAtob = (data: string) => {\n if (typeof atob !== 'undefined' && typeof atob === 'function') {\n return atob(data);\n } else if (typeof global !== 'undefined' && global.Buffer) {\n return new global.Buffer(data, 'base64').toString();\n }\n return data;\n};\n","export const LEGACY_DEV_INSTANCE_SUFFIXES = ['.lcl.dev', '.lclstage.dev', '.lclclerk.com'];\nexport const CURRENT_DEV_INSTANCE_SUFFIXES = ['.accounts.dev', '.accountsstage.dev', '.accounts.lclclerk.com'];\nexport const DEV_OR_STAGING_SUFFIXES = [\n '.lcl.dev',\n '.stg.dev',\n '.lclstage.dev',\n '.stgstage.dev',\n '.dev.lclclerk.com',\n '.stg.lclclerk.com',\n '.accounts.lclclerk.com',\n 'accountsstage.dev',\n 'accounts.dev',\n];\nexport const LOCAL_ENV_SUFFIXES = ['.lcl.dev', 'lclstage.dev', '.lclclerk.com', '.accounts.lclclerk.com'];\nexport const STAGING_ENV_SUFFIXES = ['.accountsstage.dev'];\nexport const LOCAL_API_URL = 'https://api.lclclerk.com';\nexport const STAGING_API_URL = 'https://api.clerkstage.dev';\nexport const PROD_API_URL = 'https://api.clerk.com';\n\n/**\n * Returns the URL for a static image\n * using the new img.clerk.com service\n */\nexport function iconImageUrl(id: string, format: 'svg' | 'jpeg' = 'svg'): string {\n return `https://img.clerk.com/static/${id}.${format}`;\n}\n","import type { PublishableKey } from '@clerk/types';\n\nimport { DEV_OR_STAGING_SUFFIXES, LEGACY_DEV_INSTANCE_SUFFIXES } from './constants';\nimport { isomorphicAtob } from './isomorphicAtob';\nimport { isomorphicBtoa } from './isomorphicBtoa';\n\ntype ParsePublishableKeyOptions = {\n fatal?: boolean;\n domain?: string;\n proxyUrl?: string;\n};\n\nconst PUBLISHABLE_KEY_LIVE_PREFIX = 'pk_live_';\nconst PUBLISHABLE_KEY_TEST_PREFIX = 'pk_test_';\n\n// This regex matches the publishable like frontend API keys (e.g. foo-bar-13.clerk.accounts.dev)\nconst PUBLISHABLE_FRONTEND_API_DEV_REGEX = /^(([a-z]+)-){2}([0-9]{1,2})\\.clerk\\.accounts([a-z.]*)(dev|com)$/i;\n\nexport function buildPublishableKey(frontendApi: string): string {\n const isDevKey =\n PUBLISHABLE_FRONTEND_API_DEV_REGEX.test(frontendApi) ||\n (frontendApi.startsWith('clerk.') && LEGACY_DEV_INSTANCE_SUFFIXES.some(s => frontendApi.endsWith(s)));\n const keyPrefix = isDevKey ? PUBLISHABLE_KEY_TEST_PREFIX : PUBLISHABLE_KEY_LIVE_PREFIX;\n return `${keyPrefix}${isomorphicBtoa(`${frontendApi}$`)}`;\n}\n\nexport function parsePublishableKey(\n key: string | undefined,\n options: ParsePublishableKeyOptions & { fatal: true },\n): PublishableKey;\nexport function parsePublishableKey(\n key: string | undefined,\n options?: ParsePublishableKeyOptions,\n): PublishableKey | null;\nexport function parsePublishableKey(\n key: string | undefined,\n options: { fatal?: boolean; domain?: string; proxyUrl?: string } = {},\n): PublishableKey | null {\n key = key || '';\n\n if (!key || !isPublishableKey(key)) {\n if (options.fatal && !key) {\n throw new Error(\n 'Publishable key is missing. Ensure that your publishable key is correctly configured. Double-check your environment configuration for your keys, or access them here: https://dashboard.clerk.com/last-active?path=api-keys',\n );\n }\n if (options.fatal && !isPublishableKey(key)) {\n throw new Error('Publishable key not valid.');\n }\n return null;\n }\n\n const instanceType = key.startsWith(PUBLISHABLE_KEY_LIVE_PREFIX) ? 'production' : 'development';\n\n let frontendApi = isomorphicAtob(key.split('_')[2]);\n\n // TODO(@dimkl): validate packages/clerk-js/src/utils/instance.ts\n frontendApi = frontendApi.slice(0, -1);\n\n if (options.proxyUrl) {\n frontendApi = options.proxyUrl;\n } else if (instanceType !== 'development' && options.domain) {\n frontendApi = `clerk.${options.domain}`;\n }\n\n return {\n instanceType,\n frontendApi,\n };\n}\n\n/**\n * Checks if the provided key is a valid publishable key.\n *\n * @param key - The key to be checked. Defaults to an empty string if not provided.\n * @returns `true` if 'key' is a valid publishable key, `false` otherwise.\n */\nexport function isPublishableKey(key: string = '') {\n try {\n const hasValidPrefix = key.startsWith(PUBLISHABLE_KEY_LIVE_PREFIX) || key.startsWith(PUBLISHABLE_KEY_TEST_PREFIX);\n\n const hasValidFrontendApiPostfix = isomorphicAtob(key.split('_')[2] || '').endsWith('$');\n\n return hasValidPrefix && hasValidFrontendApiPostfix;\n } catch {\n return false;\n }\n}\n\nexport function createDevOrStagingUrlCache() {\n const devOrStagingUrlCache = new Map();\n\n return {\n isDevOrStagingUrl: (url: string | URL): boolean => {\n if (!url) {\n return false;\n }\n\n const hostname = typeof url === 'string' ? url : url.hostname;\n let res = devOrStagingUrlCache.get(hostname);\n if (res === undefined) {\n res = DEV_OR_STAGING_SUFFIXES.some(s => hostname.endsWith(s));\n devOrStagingUrlCache.set(hostname, res);\n }\n return res;\n },\n };\n}\n\nexport function isDevelopmentFromPublishableKey(apiKey: string): boolean {\n return apiKey.startsWith('test_') || apiKey.startsWith('pk_test_');\n}\n\nexport function isProductionFromPublishableKey(apiKey: string): boolean {\n return apiKey.startsWith('live_') || apiKey.startsWith('pk_live_');\n}\n\nexport function isDevelopmentFromSecretKey(apiKey: string): boolean {\n return apiKey.startsWith('test_') || apiKey.startsWith('sk_test_');\n}\n\nexport function isProductionFromSecretKey(apiKey: string): boolean {\n return apiKey.startsWith('live_') || apiKey.startsWith('sk_live_');\n}\n\nexport async function getCookieSuffix(\n publishableKey: string,\n subtle: SubtleCrypto = globalThis.crypto.subtle,\n): Promise {\n const data = new TextEncoder().encode(publishableKey);\n const digest = await subtle.digest('sha-1', data);\n const stringDigest = String.fromCharCode(...new Uint8Array(digest));\n // Base 64 Encoding with URL and Filename Safe Alphabet: https://datatracker.ietf.org/doc/html/rfc4648#section-5\n return isomorphicBtoa(stringDigest).replace(/\\+/gi, '-').replace(/\\//gi, '_').substring(0, 8);\n}\n\nexport const getSuffixedCookieName = (cookieName: string, cookieSuffix: string): string => {\n return `${cookieName}_${cookieSuffix}`;\n};\n","import type { ClerkOptions, SDKMetadata, Without } from '@clerk/types';\n\nimport { buildErrorThrower } from './error';\nimport { createDevOrStagingUrlCache, parsePublishableKey } from './keys';\nimport { loadScript } from './loadScript';\nimport { isValidProxyUrl, proxyUrlToAbsoluteURL } from './proxy';\nimport { addClerkPrefix } from './url';\nimport { versionSelector } from './versionSelector';\n\nconst FAILED_TO_LOAD_ERROR = 'Clerk: Failed to load Clerk';\n\nconst { isDevOrStagingUrl } = createDevOrStagingUrlCache();\n\nconst errorThrower = buildErrorThrower({ packageName: '@clerk/shared' });\n\n/**\n * Sets the package name for error messages during ClerkJS script loading.\n *\n * @example\n * setClerkJsLoadingErrorPackageName('@clerk/clerk-react');\n */\nexport function setClerkJsLoadingErrorPackageName(packageName: string) {\n errorThrower.setPackageName({ packageName });\n}\n\ntype LoadClerkJsScriptOptions = Without & {\n publishableKey: string;\n clerkJSUrl?: string;\n clerkJSVariant?: 'headless' | '';\n clerkJSVersion?: string;\n sdkMetadata?: SDKMetadata;\n proxyUrl?: string;\n domain?: string;\n nonce?: string;\n};\n\n/**\n * Hotloads the Clerk JS script.\n *\n * Checks for an existing Clerk JS script. If found, it returns a promise\n * that resolves when the script loads. If not found, it uses the provided options to\n * build the Clerk JS script URL and load the script.\n *\n * @param opts - The options used to build the Clerk JS script URL and load the script.\n * Must include a `publishableKey` if no existing script is found.\n *\n * @example\n * loadClerkJsScript({ publishableKey: 'pk_' });\n */\nconst loadClerkJsScript = async (opts?: LoadClerkJsScriptOptions) => {\n const existingScript = document.querySelector('script[data-clerk-js-script]');\n\n if (existingScript) {\n return new Promise((resolve, reject) => {\n existingScript.addEventListener('load', () => {\n resolve(existingScript);\n });\n\n existingScript.addEventListener('error', () => {\n reject(FAILED_TO_LOAD_ERROR);\n });\n });\n }\n\n if (!opts?.publishableKey) {\n errorThrower.throwMissingPublishableKeyError();\n return;\n }\n\n return loadScript(clerkJsScriptUrl(opts), {\n async: true,\n crossOrigin: 'anonymous',\n nonce: opts.nonce,\n beforeLoad: applyClerkJsScriptAttributes(opts),\n }).catch(() => {\n throw new Error(FAILED_TO_LOAD_ERROR);\n });\n};\n\n/**\n * Generates a Clerk JS script URL.\n *\n * @param opts - The options to use when building the Clerk JS script URL.\n *\n * @example\n * clerkJsScriptUrl({ publishableKey: 'pk_' });\n */\nconst clerkJsScriptUrl = (opts: LoadClerkJsScriptOptions) => {\n const { clerkJSUrl, clerkJSVariant, clerkJSVersion, proxyUrl, domain, publishableKey } = opts;\n\n if (clerkJSUrl) {\n return clerkJSUrl;\n }\n\n let scriptHost = '';\n if (!!proxyUrl && isValidProxyUrl(proxyUrl)) {\n scriptHost = proxyUrlToAbsoluteURL(proxyUrl).replace(/http(s)?:\\/\\//, '');\n } else if (domain && !isDevOrStagingUrl(parsePublishableKey(publishableKey)?.frontendApi || '')) {\n scriptHost = addClerkPrefix(domain);\n } else {\n scriptHost = parsePublishableKey(publishableKey)?.frontendApi || '';\n }\n\n const variant = clerkJSVariant ? `${clerkJSVariant.replace(/\\.+$/, '')}.` : '';\n const version = versionSelector(clerkJSVersion);\n return `https://${scriptHost}/npm/@clerk/clerk-js@${version}/dist/clerk.${variant}browser.js`;\n};\n\n/**\n * Builds an object of Clerk JS script attributes.\n */\nconst buildClerkJsScriptAttributes = (options: LoadClerkJsScriptOptions) => {\n const obj: Record = {};\n\n if (options.publishableKey) {\n obj['data-clerk-publishable-key'] = options.publishableKey;\n }\n\n if (options.proxyUrl) {\n obj['data-clerk-proxy-url'] = options.proxyUrl;\n }\n\n if (options.domain) {\n obj['data-clerk-domain'] = options.domain;\n }\n\n if (options.nonce) {\n obj.nonce = options.nonce;\n }\n\n return obj;\n};\n\nconst applyClerkJsScriptAttributes = (options: LoadClerkJsScriptOptions) => (script: HTMLScriptElement) => {\n const attributes = buildClerkJsScriptAttributes(options);\n for (const attribute in attributes) {\n script.setAttribute(attribute, attributes[attribute]);\n }\n};\n\nexport { loadClerkJsScript, buildClerkJsScriptAttributes, clerkJsScriptUrl };\nexport type { LoadClerkJsScriptOptions };\n","import { isDevelopmentEnvironment } from './runtimeEnvironment';\n\nexport const logErrorInDevMode = (message: string) => {\n if (isDevelopmentEnvironment()) {\n console.error(`Clerk: ${message}`);\n }\n};\n","type VOrFnReturnsV = T | undefined | ((v: URL) => T);\nexport function handleValueOrFn(value: VOrFnReturnsV, url: URL): T | undefined;\nexport function handleValueOrFn(value: VOrFnReturnsV, url: URL, defaultValue: T): T;\nexport function handleValueOrFn(value: VOrFnReturnsV, url: URL, defaultValue?: unknown): unknown {\n if (typeof value === 'function') {\n return (value as (v: URL) => T)(url);\n }\n\n if (typeof value !== 'undefined') {\n return value;\n }\n\n if (typeof defaultValue !== 'undefined') {\n return defaultValue;\n }\n\n return undefined;\n}\n","export const without = (obj: T, ...props: P[]): Omit => {\n const copy = { ...obj };\n for (const prop of props) {\n delete copy[prop];\n }\n return copy;\n};\n\nexport const removeUndefined = (obj: T): Partial => {\n return Object.entries(obj).reduce((acc, [key, value]) => {\n if (value !== undefined && value !== null) {\n acc[key as keyof T] = value;\n }\n return acc;\n }, {} as Partial);\n};\n\nexport const applyFunctionToObj = , R>(\n obj: T,\n fn: (val: any, key: string) => R,\n): Record