{"version":3,"file":"loadClerkJsScript.mjs","names":["obj: Record<string, string>","timeoutId","pollInterval"],"sources":["../../src/loadClerkJsScript.ts"],"sourcesContent":["import { buildErrorThrower, ClerkRuntimeError } from './error';\nimport { createDevOrStagingUrlCache, parsePublishableKey } from './keys';\nimport { loadScript } from './loadScript';\nimport { isValidProxyUrl, proxyUrlToAbsoluteURL } from './proxy';\nimport type { SDKMetadata } from './types';\nimport { addClerkPrefix } from './url';\nimport { versionSelector } from './versionSelector';\n\nconst { isDevOrStagingUrl } = createDevOrStagingUrlCache();\n\nconst errorThrower = buildErrorThrower({ packageName: '@clerk/shared' });\n\nexport type LoadClerkJSScriptOptions = {\n  publishableKey: string;\n  /** @internal */\n  __internal_clerkJSUrl?: string;\n  /** @internal */\n  __internal_clerkJSVersion?: string;\n  sdkMetadata?: SDKMetadata;\n  proxyUrl?: string;\n  domain?: string;\n  nonce?: string;\n  /**\n   * Timeout in milliseconds to wait for clerk-js to load before considering it failed.\n   *\n   * @default 15000 (15 seconds)\n   */\n  scriptLoadTimeout?: number;\n};\n\n/**\n * @deprecated Use `LoadClerkJSScriptOptions` instead. This alias will be removed in a future major version.\n */\nexport type LoadClerkJsScriptOptions = LoadClerkJSScriptOptions;\n\nexport type LoadClerkUIScriptOptions = {\n  publishableKey: string;\n  /** @internal */\n  __internal_clerkUIUrl?: string;\n  /** @internal */\n  __internal_clerkUIVersion?: string;\n  proxyUrl?: string;\n  domain?: string;\n  nonce?: string;\n  scriptLoadTimeout?: number;\n};\n\n/**\n * Validates that window.Clerk exists and is properly initialized.\n * This ensures we don't have false positives where the script loads but Clerk is malformed.\n *\n * @returns `true` if window.Clerk exists and has the expected structure with a load method.\n */\nfunction isClerkGlobalProperlyLoaded(prop: 'Clerk' | '__internal_ClerkUICtor'): boolean {\n  if (typeof window === 'undefined' || !(window as any)[prop]) {\n    return false;\n  }\n\n  // Basic validation that window.Clerk has the expected structure\n  const val = (window as any)[prop];\n  return !!val;\n}\nconst isClerkProperlyLoaded = () => isClerkGlobalProperlyLoaded('Clerk');\nconst isClerkUIProperlyLoaded = () => isClerkGlobalProperlyLoaded('__internal_ClerkUICtor');\n\n/**\n * Checks if an existing script has a request error using Performance API.\n *\n * @param scriptUrl - The URL of the script to check.\n * @returns True if the script has failed to load due to a network/HTTP error.\n */\nfunction hasScriptRequestError(scriptUrl: string): boolean {\n  if (typeof window === 'undefined' || !window.performance) {\n    return false;\n  }\n\n  const entries = performance.getEntriesByName(scriptUrl, 'resource') as PerformanceResourceTiming[];\n\n  if (entries.length === 0) {\n    return false;\n  }\n\n  const scriptEntry = entries[entries.length - 1];\n\n  // transferSize === 0 with responseEnd === 0 indicates network failure\n  // transferSize === 0 with responseEnd > 0 might be a 4xx/5xx error or blocked request\n  if (scriptEntry.transferSize === 0 && scriptEntry.decodedBodySize === 0) {\n    // If there was no response at all, it's definitely an error\n    if (scriptEntry.responseEnd === 0) {\n      return true;\n    }\n    // If we got a response but no content, likely an HTTP error (4xx/5xx)\n    if (scriptEntry.responseEnd > 0 && scriptEntry.responseStart > 0) {\n      return true;\n    }\n\n    if ('responseStatus' in scriptEntry) {\n      const status = (scriptEntry as any).responseStatus;\n      if (status >= 400) {\n        return true;\n      }\n      if (scriptEntry.responseStatus === 0) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n}\n\n/**\n * Hotloads the Clerk JS script with robust failure detection.\n *\n * Uses a timeout-based approach to ensure absolute certainty about load success/failure.\n * If the script fails to load within the timeout period, or loads but doesn't create\n * a proper Clerk instance, the promise rejects with an error.\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 * @returns Promise that resolves with null if Clerk loads successfully, or rejects with an error.\n *\n * @example\n * ```typescript\n * try {\n *   await loadClerkJsScript({ publishableKey: 'pk_test_...' });\n *   console.log('Clerk loaded successfully');\n * } catch (error) {\n *   console.error('Failed to load Clerk:', error.message);\n * }\n * ```\n */\nexport const loadClerkJSScript = async (opts?: LoadClerkJSScriptOptions): Promise<HTMLScriptElement | null> => {\n  const timeout = opts?.scriptLoadTimeout ?? 15000;\n  const rejectWith = (error?: Error) =>\n    new ClerkRuntimeError('Failed to load Clerk JS' + (error?.message ? `, ${error.message}` : ''), {\n      code: 'failed_to_load_clerk_js',\n      cause: error,\n    });\n\n  if (isClerkProperlyLoaded()) {\n    return null;\n  }\n\n  if (!opts?.publishableKey) {\n    errorThrower.throwMissingPublishableKeyError();\n    return null;\n  }\n\n  const scriptUrl = clerkJSScriptUrl(opts);\n  const existingScript = document.querySelector<HTMLScriptElement>('script[data-clerk-js-script]');\n\n  if (existingScript) {\n    if (hasScriptRequestError(scriptUrl)) {\n      existingScript.remove();\n    } else {\n      try {\n        await waitForPredicateWithTimeout(timeout, isClerkProperlyLoaded, rejectWith(), existingScript);\n        return null;\n      } catch {\n        existingScript.remove();\n      }\n    }\n  }\n\n  const loadPromise = waitForPredicateWithTimeout(timeout, isClerkProperlyLoaded, rejectWith());\n\n  loadScript(scriptUrl, {\n    async: true,\n    crossOrigin: 'anonymous',\n    nonce: opts.nonce,\n    beforeLoad: applyAttributesToScript(buildClerkJSScriptAttributes(opts)),\n  }).catch(error => {\n    throw rejectWith(error);\n  });\n\n  return loadPromise;\n};\n\nexport const loadClerkUIScript = async (opts?: LoadClerkUIScriptOptions): Promise<HTMLScriptElement | null> => {\n  const timeout = opts?.scriptLoadTimeout ?? 15000;\n  const rejectWith = (error?: Error) =>\n    new ClerkRuntimeError('Failed to load Clerk UI' + (error?.message ? `, ${error.message}` : ''), {\n      code: 'failed_to_load_clerk_ui',\n      cause: error,\n    });\n\n  if (isClerkUIProperlyLoaded()) {\n    return null;\n  }\n\n  if (!opts?.publishableKey) {\n    errorThrower.throwMissingPublishableKeyError();\n    return null;\n  }\n\n  const scriptUrl = clerkUIScriptUrl(opts);\n  const existingScript = document.querySelector<HTMLScriptElement>('script[data-clerk-ui-script]');\n\n  if (existingScript) {\n    if (hasScriptRequestError(scriptUrl)) {\n      existingScript.remove();\n    } else {\n      try {\n        await waitForPredicateWithTimeout(timeout, isClerkUIProperlyLoaded, rejectWith(), existingScript);\n        return null;\n      } catch {\n        existingScript.remove();\n      }\n    }\n  }\n\n  const loadPromise = waitForPredicateWithTimeout(timeout, isClerkUIProperlyLoaded, rejectWith());\n\n  loadScript(scriptUrl, {\n    async: true,\n    crossOrigin: 'anonymous',\n    nonce: opts.nonce,\n    beforeLoad: applyAttributesToScript(buildClerkUIScriptAttributes(opts)),\n  }).catch(error => {\n    throw rejectWith(error);\n  });\n\n  return loadPromise;\n};\n\nexport const clerkJSScriptUrl = (opts: LoadClerkJSScriptOptions) => {\n  const { __internal_clerkJSUrl, __internal_clerkJSVersion, proxyUrl, domain, publishableKey } = opts;\n\n  if (__internal_clerkJSUrl) {\n    return __internal_clerkJSUrl;\n  }\n\n  const scriptHost = buildScriptHost({ publishableKey, proxyUrl, domain });\n  const version = versionSelector(__internal_clerkJSVersion);\n  return `https://${scriptHost}/npm/@clerk/clerk-js@${version}/dist/clerk.browser.js`;\n};\n\nexport const clerkUIScriptUrl = (opts: LoadClerkUIScriptOptions) => {\n  const { __internal_clerkUIUrl, __internal_clerkUIVersion, proxyUrl, domain, publishableKey } = opts;\n\n  if (__internal_clerkUIUrl) {\n    return __internal_clerkUIUrl;\n  }\n\n  const scriptHost = buildScriptHost({ publishableKey, proxyUrl, domain });\n  const version = versionSelector(__internal_clerkUIVersion, UI_PACKAGE_VERSION);\n  return `https://${scriptHost}/npm/@clerk/ui@${version}/dist/ui.browser.js`;\n};\n\nexport const buildClerkJSScriptAttributes = (options: LoadClerkJSScriptOptions) => {\n  const obj: Record<string, string> = {};\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\nexport const buildClerkUIScriptAttributes = (options: LoadClerkUIScriptOptions) => {\n  // TODO @nikos do we need this?\n  return buildClerkJSScriptAttributes(options);\n};\n\nconst applyAttributesToScript = (attributes: Record<string, string>) => (script: HTMLScriptElement) => {\n  for (const attribute in attributes) {\n    script.setAttribute(attribute, attributes[attribute]);\n  }\n};\n\nexport const buildScriptHost = (opts: { publishableKey: string; proxyUrl?: string; domain?: string }) => {\n  const { proxyUrl, domain, publishableKey } = opts;\n\n  if (!!proxyUrl && isValidProxyUrl(proxyUrl)) {\n    return proxyUrlToAbsoluteURL(proxyUrl).replace(/http(s)?:\\/\\//, '');\n  } else if (domain && !isDevOrStagingUrl(parsePublishableKey(publishableKey)?.frontendApi || '')) {\n    return addClerkPrefix(domain);\n  } else {\n    return parsePublishableKey(publishableKey)?.frontendApi || '';\n  }\n};\n\nfunction waitForPredicateWithTimeout(\n  timeoutMs: number,\n  predicate: () => boolean,\n  rejectWith: Error,\n  existingScript?: HTMLScriptElement,\n): Promise<HTMLScriptElement | null> {\n  return new Promise((resolve, reject) => {\n    let resolved = false;\n\n    const cleanup = (timeoutId: ReturnType<typeof setTimeout>, pollInterval: ReturnType<typeof setInterval>) => {\n      clearTimeout(timeoutId);\n      clearInterval(pollInterval);\n    };\n\n    // Bail out early if the script fails to load, instead of waiting for the entire timeout\n    existingScript?.addEventListener('error', () => {\n      cleanup(timeoutId, pollInterval);\n      reject(rejectWith);\n    });\n\n    const checkAndResolve = () => {\n      if (resolved) {\n        return;\n      }\n\n      if (predicate()) {\n        resolved = true;\n        cleanup(timeoutId, pollInterval);\n        resolve(null);\n      }\n    };\n\n    const handleTimeout = () => {\n      if (resolved) {\n        return;\n      }\n\n      resolved = true;\n      cleanup(timeoutId, pollInterval);\n\n      if (!predicate()) {\n        reject(rejectWith);\n      } else {\n        resolve(null);\n      }\n    };\n\n    const timeoutId = setTimeout(handleTimeout, timeoutMs);\n\n    checkAndResolve();\n\n    const pollInterval = setInterval(() => {\n      if (resolved) {\n        clearInterval(pollInterval);\n        return;\n      }\n      checkAndResolve();\n    }, 100);\n  });\n}\n\nexport function setClerkJSLoadingErrorPackageName(packageName: string) {\n  errorThrower.setPackageName({ packageName });\n}\n\n/**\n * @deprecated Use `loadClerkJSScript` instead. This alias will be removed in a future major version.\n */\nexport const loadClerkJsScript = loadClerkJSScript;\n\n/**\n * @deprecated Use `clerkJSScriptUrl` instead. This alias will be removed in a future major version.\n */\nexport const clerkJsScriptUrl = clerkJSScriptUrl;\n\n/**\n * @deprecated Use `buildClerkJSScriptAttributes` instead. This alias will be removed in a future major version.\n */\nexport const buildClerkJsScriptAttributes = buildClerkJSScriptAttributes;\n\n/**\n * @deprecated Use `setClerkJSLoadingErrorPackageName` instead. This alias will be removed in a future major version.\n */\nexport const setClerkJsLoadingErrorPackageName = setClerkJSLoadingErrorPackageName;\n"],"mappings":"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"}