{"version":3,"file":"getToken.mjs","names":[],"sources":["../src/getToken.ts"],"sourcesContent":["import { inBrowser } from './browser';\nimport { ClerkRuntimeError } from './errors/clerkRuntimeError';\nimport type { GetTokenOptions, LoadedClerk } from './types';\n\nconst TIMEOUT_MS = 10000; // 10 second timeout for Clerk to load\n\n/**\n * A promise that includes resolve/reject callbacks for external resolution.\n * Used for coordination between getToken() and clerk-js initialization.\n */\ntype ClerkReadyPromise = Promise<LoadedClerk> & {\n  __resolve?: (clerk: LoadedClerk) => void;\n  __reject?: (error: Error) => void;\n};\n\n/**\n * Local Window type extension for __clerk_internal_ready coordination.\n * Avoids global augmentation to prevent declaration collisions for consumers.\n */\ninterface ClerkWindow extends Window {\n  __clerk_internal_ready?: ClerkReadyPromise;\n}\n\nfunction getWindowClerk(): LoadedClerk | undefined {\n  if (inBrowser() && 'Clerk' in window) {\n    const clerk = (window as unknown as { Clerk?: LoadedClerk }).Clerk;\n    if (clerk && (clerk.status === 'ready' || clerk.status === 'degraded')) {\n      return clerk;\n    }\n    // Legacy fallback for older clerk-js versions without status\n    if (clerk?.loaded && !clerk.status) {\n      return clerk;\n    }\n  }\n  return undefined;\n}\n\nasync function waitForClerk(): Promise<LoadedClerk> {\n  if (!inBrowser()) {\n    throw new ClerkRuntimeError(\n      'getToken can only be used in browser environments. To access auth data server-side, see the Auth object reference doc: https://clerk.com/docs/reference/backend/types/auth-object',\n      {\n        code: 'clerk_runtime_not_browser',\n      },\n    );\n  }\n\n  const clerk = getWindowClerk();\n  if (clerk) {\n    return clerk;\n  }\n\n  const clerkWindow = window as ClerkWindow;\n\n  // Get or create the coordination promise\n  if (!clerkWindow.__clerk_internal_ready) {\n    let resolve!: (clerk: LoadedClerk) => void;\n    let reject!: (error: Error) => void;\n    const promise = new Promise<LoadedClerk>((res, rej) => {\n      resolve = res;\n      reject = rej;\n    }) as ClerkReadyPromise;\n    promise.__resolve = resolve;\n    promise.__reject = reject;\n    clerkWindow.__clerk_internal_ready = promise;\n  }\n\n  const readyPromise = clerkWindow.__clerk_internal_ready;\n\n  let timeoutId: ReturnType<typeof setTimeout>;\n\n  const timeoutPromise = new Promise<never>((_, reject) => {\n    timeoutId = setTimeout(\n      () =>\n        reject(\n          new ClerkRuntimeError('Timeout waiting for Clerk to load.', {\n            code: 'clerk_runtime_load_timeout',\n          }),\n        ),\n      TIMEOUT_MS,\n    );\n  });\n\n  return Promise.race([readyPromise, timeoutPromise]).finally(() => {\n    clearTimeout(timeoutId);\n  });\n}\n\n/**\n * Retrieves the current session token, waiting for Clerk to initialize if necessary.\n *\n * This function is safe to call from anywhere in the browser, such as API interceptors,\n * data fetching layers, or vanilla JavaScript code.\n *\n * **Note:** In frameworks with concurrent rendering (e.g., React 18+), a global token read\n * may not correspond to the currently committed UI during transitions. This is a coherence\n * consideration, not an auth safety issue.\n *\n * @param options - Optional configuration for token retrieval\n * @param options.template - The name of a JWT template to use\n * @param options.organizationId - Organization ID to include in the token\n * @param options.skipCache - Whether to skip the token cache\n * @returns A Promise that resolves to the session token, or `null` if the user is not signed in\n *\n * @throws {ClerkRuntimeError} When called in a non-browser environment (code: `clerk_runtime_not_browser`)\n *\n * @throws {ClerkRuntimeError} When Clerk fails to load within timeout (code: `clerk_runtime_load_timeout`)\n *\n * @throws {ClerkOfflineError} When the browser is offline and unable to fetch a token (code: `clerk_offline`).\n * Use `ClerkOfflineError.is(error)` to check for this error type.\n *\n * @example\n * ```typescript\n * // In an Axios interceptor\n * import { getToken } from '@clerk/nextjs';\n *\n * axios.interceptors.request.use(async (config) => {\n *   const token = await getToken();\n *   if (token) {\n *     config.headers.Authorization = `Bearer ${token}`;\n *   }\n *   return config;\n * });\n * ```\n */\nexport async function getToken(options?: GetTokenOptions): Promise<string | null> {\n  const clerk = await waitForClerk();\n\n  if (!clerk.session) {\n    return null;\n  }\n\n  return clerk.session.getToken(options);\n}\n"],"mappings":";;;;AAIA,MAAM,aAAa;AAmBnB,SAAS,iBAA0C;CACjD,IAAI,UAAU,KAAK,WAAW,QAAQ;EACpC,MAAM,QAAS,OAA8C;EAC7D,IAAI,UAAU,MAAM,WAAW,WAAW,MAAM,WAAW,aACzD,OAAO;EAGT,IAAI,OAAO,UAAU,CAAC,MAAM,QAC1B,OAAO;CAEX;AAEF;AAEA,eAAe,eAAqC;CAClD,IAAI,CAAC,UAAU,GACb,MAAM,IAAI,kBACR,qLACA,EACE,MAAM,4BACR,CACF;CAGF,MAAM,QAAQ,eAAe;CAC7B,IAAI,OACF,OAAO;CAGT,MAAM,cAAc;CAGpB,IAAI,CAAC,YAAY,wBAAwB;EACvC,IAAI;EACJ,IAAI;EACJ,MAAM,UAAU,IAAI,SAAsB,KAAK,QAAQ;GACrD,UAAU;GACV,SAAS;EACX,CAAC;EACD,QAAQ,YAAY;EACpB,QAAQ,WAAW;EACnB,YAAY,yBAAyB;CACvC;CAEA,MAAM,eAAe,YAAY;CAEjC,IAAI;CAEJ,MAAM,iBAAiB,IAAI,SAAgB,GAAG,WAAW;EACvD,YAAY,iBAER,OACE,IAAI,kBAAkB,sCAAsC,EAC1D,MAAM,6BACR,CAAC,CACH,GACF,UACF;CACF,CAAC;CAED,OAAO,QAAQ,KAAK,CAAC,cAAc,cAAc,CAAC,CAAC,CAAC,cAAc;EAChE,aAAa,SAAS;CACxB,CAAC;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,eAAsB,SAAS,SAAmD;CAChF,MAAM,QAAQ,MAAM,aAAa;CAEjC,IAAI,CAAC,MAAM,SACT,OAAO;CAGT,OAAO,MAAM,QAAQ,SAAS,OAAO;AACvC"}