@clerk/shared 4.42.0-snapshot.v20261021181323 → 4.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/_chunks/{runtimeEnvironment-Pa5vb-_o.mjs → runtimeEnvironment-CTVGzENl.mjs} +2 -19
  2. package/dist/_chunks/runtimeEnvironment-CTVGzENl.mjs.map +1 -0
  3. package/dist/_chunks/{runtimeEnvironment-BlRyHkye.js → runtimeEnvironment-DVXDje4R.js} +1 -30
  4. package/dist/_chunks/runtimeEnvironment-DVXDje4R.js.map +1 -0
  5. package/dist/_chunks/{telemetry-bR1HEN-w.mjs → telemetry-9C6N5ppw.mjs} +2 -2
  6. package/dist/_chunks/{telemetry-bR1HEN-w.mjs.map → telemetry-9C6N5ppw.mjs.map} +1 -1
  7. package/dist/_chunks/{telemetry-DenGWatg.js → telemetry-DZp9OI1j.js} +2 -2
  8. package/dist/_chunks/{telemetry-DenGWatg.js.map → telemetry-DZp9OI1j.js.map} +1 -1
  9. package/dist/_chunks/{utils-C4oBdUAp.js → utils-B43KYtlc.js} +2 -2
  10. package/dist/_chunks/{utils-C4oBdUAp.js.map → utils-B43KYtlc.js.map} +1 -1
  11. package/dist/_chunks/{utils-BVxAoPFk.mjs → utils-V2FbmPWk.mjs} +2 -2
  12. package/dist/_chunks/{utils-BVxAoPFk.mjs.map → utils-V2FbmPWk.mjs.map} +1 -1
  13. package/dist/deprecated.js +1 -1
  14. package/dist/deprecated.mjs +1 -1
  15. package/dist/internal/clerk-js/componentGuards.js +1 -1
  16. package/dist/internal/clerk-js/componentGuards.js.map +1 -1
  17. package/dist/internal/clerk-js/componentGuards.mjs +1 -1
  18. package/dist/internal/clerk-js/componentGuards.mjs.map +1 -1
  19. package/dist/keyless/index.js +1 -1
  20. package/dist/keyless/index.mjs +1 -1
  21. package/dist/loadClerkJsScript.js +1 -1
  22. package/dist/loadClerkJsScript.js.map +1 -1
  23. package/dist/loadClerkJsScript.mjs +1 -1
  24. package/dist/loadClerkJsScript.mjs.map +1 -1
  25. package/dist/react/hooks/createCacheKeys.d.mts +24 -0
  26. package/dist/react/hooks/createCacheKeys.d.ts +24 -0
  27. package/dist/react/hooks/index.d.mts +3 -0
  28. package/dist/react/hooks/index.d.ts +3 -0
  29. package/dist/react/hooks/index.js +3 -0
  30. package/dist/react/hooks/useClearQueriesOnSignOut.d.mts +24 -0
  31. package/dist/react/hooks/useClearQueriesOnSignOut.d.ts +24 -0
  32. package/dist/react/hooks/useReverification.js +1 -1
  33. package/dist/react/index.d.mts +4 -1
  34. package/dist/react/index.d.ts +4 -1
  35. package/dist/react/index.js +4 -1
  36. package/dist/react/index.js.map +1 -1
  37. package/dist/react/index.mjs +2 -2
  38. package/dist/react/index.mjs.map +1 -1
  39. package/dist/react/query/queryOptions.d.mts +14 -0
  40. package/dist/react/query/queryOptions.d.ts +14 -0
  41. package/dist/react/query/types.d.mts +17 -0
  42. package/dist/react/query/types.d.ts +17 -0
  43. package/dist/react/query/useBaseQuery.d.mts +8 -0
  44. package/dist/react/query/useBaseQuery.d.ts +8 -0
  45. package/dist/react/query/useQuery.d.mts +12 -0
  46. package/dist/react/query/useQuery.d.ts +12 -0
  47. package/dist/react/stable-keys.d.mts +40 -0
  48. package/dist/react/stable-keys.d.ts +40 -0
  49. package/dist/telemetry.js +1 -1
  50. package/dist/telemetry.mjs +1 -1
  51. package/dist/types/json.d.mts +1 -0
  52. package/dist/types/json.d.ts +1 -0
  53. package/dist/types/organization.d.mts +4 -0
  54. package/dist/types/organization.d.ts +4 -0
  55. package/dist/types/session.d.mts +1 -1
  56. package/dist/types/session.d.ts +1 -1
  57. package/dist/utils/index.d.mts +2 -2
  58. package/dist/utils/index.d.ts +2 -2
  59. package/dist/utils/index.js +2 -4
  60. package/dist/utils/index.mjs +3 -3
  61. package/dist/utils/runtimeEnvironment.d.mts +1 -3
  62. package/dist/utils/runtimeEnvironment.d.ts +1 -3
  63. package/dist/utils/runtimeEnvironment.js +0 -19
  64. package/dist/versionSelector.js +1 -1
  65. package/dist/versionSelector.js.map +1 -1
  66. package/dist/versionSelector.mjs +1 -1
  67. package/dist/versionSelector.mjs.map +1 -1
  68. package/package.json +1 -21
  69. package/dist/_chunks/runtimeEnvironment-BlRyHkye.js.map +0 -1
  70. package/dist/_chunks/runtimeEnvironment-Pa5vb-_o.mjs.map +0 -1
  71. package/dist/agentRules/index.d.mts +0 -46
  72. package/dist/agentRules/index.d.ts +0 -46
  73. package/dist/agentRules/index.js +0 -167
  74. package/dist/agentRules/index.js.map +0 -1
  75. package/dist/agentRules/index.mjs +0 -158
  76. package/dist/agentRules/index.mjs.map +0 -1
  77. package/dist/vite.d.mts +0 -15
  78. package/dist/vite.d.ts +0 -15
  79. package/dist/vite.js +0 -29
  80. package/dist/vite.js.map +0 -1
  81. package/dist/vite.mjs +0 -28
  82. package/dist/vite.mjs.map +0 -1
@@ -19,17 +19,6 @@ const automatedEnvironmentVariables = [
19
19
  "BAMBOO_BUILDKEY",
20
20
  "CF_PAGES"
21
21
  ];
22
- const agentEnvironmentVariables = [
23
- "CLAUDECODE",
24
- "CURSOR_AGENT",
25
- "CURSOR_CLI",
26
- "CURSOR_EXTENSION_HOST_ROLE",
27
- "CURSOR_TRACE_ID",
28
- "GITHUB_COPILOT_AGENT",
29
- "GITHUB_COPILOT_CHAT",
30
- "AGENT",
31
- "AGENTS"
32
- ];
33
22
  const isTruthyEnvValue = (value) => {
34
23
  if (typeof value !== "string" || !value) return false;
35
24
  return ![
@@ -60,13 +49,7 @@ const isProductionEnvironment = () => {
60
49
  const isAutomatedEnvironment = () => {
61
50
  return automatedEnvironmentVariables.some((name) => isTruthyEnvValue(getEnvVariable(name)));
62
51
  };
63
- const isAgentEnvironment = () => {
64
- return agentEnvironmentVariables.some((name) => {
65
- const value = getEnvVariable(name);
66
- return name === "CURSOR_EXTENSION_HOST_ROLE" ? value === "agent-exec" : isTruthyEnvValue(value);
67
- });
68
- };
69
52
 
70
53
  //#endregion
71
- export { isDevelopmentEnvironment as a, isAutomatedEnvironment as i, automatedEnvironmentVariables as n, isProductionEnvironment as o, isAgentEnvironment as r, isTestEnvironment as s, agentEnvironmentVariables as t };
72
- //# sourceMappingURL=runtimeEnvironment-Pa5vb-_o.mjs.map
54
+ export { isTestEnvironment as a, isProductionEnvironment as i, isAutomatedEnvironment as n, isDevelopmentEnvironment as r, automatedEnvironmentVariables as t };
55
+ //# sourceMappingURL=runtimeEnvironment-CTVGzENl.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeEnvironment-CTVGzENl.mjs","names":[],"sources":["../../src/utils/runtimeEnvironment.ts"],"sourcesContent":["import { getEnvVariable } from '../getEnvVariable';\n\nexport const automatedEnvironmentVariables = [\n 'CI',\n 'CONTINUOUS_INTEGRATION',\n 'GITHUB_ACTIONS',\n 'GITLAB_CI',\n 'CIRCLECI',\n 'TRAVIS',\n 'BUILDKITE',\n 'BITBUCKET_BUILD_NUMBER',\n 'APPVEYOR',\n 'CODEBUILD_BUILD_ID',\n 'TF_BUILD',\n 'TEAMCITY_VERSION',\n 'JENKINS_URL',\n 'HUDSON_URL',\n 'BAMBOO_BUILDKEY',\n 'CF_PAGES',\n] as const;\n\nconst isTruthyEnvValue = (value: unknown): boolean => {\n if (typeof value !== 'string' || !value) {\n return false;\n }\n\n return !['0', 'false', 'off', 'no'].includes(value.toLowerCase());\n};\n\nexport const isDevelopmentEnvironment = (): boolean => {\n try {\n return process.env.NODE_ENV === 'development';\n // eslint-disable-next-line no-empty\n } catch {}\n\n // TODO: add support for import.meta.env.DEV that is being used by vite\n\n return false;\n};\n\nexport const isTestEnvironment = (): boolean => {\n try {\n return process.env.NODE_ENV === 'test';\n // eslint-disable-next-line no-empty\n } catch {}\n\n // TODO: add support for import.meta.env.DEV that is being used by vite\n return false;\n};\n\nexport const isProductionEnvironment = (): boolean => {\n try {\n return process.env.NODE_ENV === 'production';\n // eslint-disable-next-line no-empty\n } catch {}\n\n // TODO: add support for import.meta.env.DEV that is being used by vite\n return false;\n};\n\nexport const isAutomatedEnvironment = (): boolean => {\n return automatedEnvironmentVariables.some(name => isTruthyEnvValue(getEnvVariable(name)));\n};\n"],"mappings":";;;AAEA,MAAa,gCAAgC;CAC3C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,oBAAoB,UAA4B;CACpD,IAAI,OAAO,UAAU,YAAY,CAAC,OAChC,OAAO;CAGT,OAAO,CAAC;EAAC;EAAK;EAAS;EAAO;CAAI,CAAC,CAAC,SAAS,MAAM,YAAY,CAAC;AAClE;AAEA,MAAa,iCAA0C;CACrD,IAAI;EACF,OAAO,QAAQ,IAAI,aAAa;CAElC,QAAQ,CAAC;CAIT,OAAO;AACT;AAEA,MAAa,0BAAmC;CAC9C,IAAI;EACF,OAAO,QAAQ,IAAI,aAAa;CAElC,QAAQ,CAAC;CAGT,OAAO;AACT;AAEA,MAAa,gCAAyC;CACpD,IAAI;EACF,OAAO,QAAQ,IAAI,aAAa;CAElC,QAAQ,CAAC;CAGT,OAAO;AACT;AAEA,MAAa,+BAAwC;CACnD,OAAO,8BAA8B,MAAK,SAAQ,iBAAiB,eAAe,IAAI,CAAC,CAAC;AAC1F"}
@@ -19,17 +19,6 @@ const automatedEnvironmentVariables = [
19
19
  "BAMBOO_BUILDKEY",
20
20
  "CF_PAGES"
21
21
  ];
22
- const agentEnvironmentVariables = [
23
- "CLAUDECODE",
24
- "CURSOR_AGENT",
25
- "CURSOR_CLI",
26
- "CURSOR_EXTENSION_HOST_ROLE",
27
- "CURSOR_TRACE_ID",
28
- "GITHUB_COPILOT_AGENT",
29
- "GITHUB_COPILOT_CHAT",
30
- "AGENT",
31
- "AGENTS"
32
- ];
33
22
  const isTruthyEnvValue = (value) => {
34
23
  if (typeof value !== "string" || !value) return false;
35
24
  return ![
@@ -60,32 +49,14 @@ const isProductionEnvironment = () => {
60
49
  const isAutomatedEnvironment = () => {
61
50
  return automatedEnvironmentVariables.some((name) => isTruthyEnvValue(require_getEnvVariable.getEnvVariable(name)));
62
51
  };
63
- const isAgentEnvironment = () => {
64
- return agentEnvironmentVariables.some((name) => {
65
- const value = require_getEnvVariable.getEnvVariable(name);
66
- return name === "CURSOR_EXTENSION_HOST_ROLE" ? value === "agent-exec" : isTruthyEnvValue(value);
67
- });
68
- };
69
52
 
70
53
  //#endregion
71
- Object.defineProperty(exports, 'agentEnvironmentVariables', {
72
- enumerable: true,
73
- get: function () {
74
- return agentEnvironmentVariables;
75
- }
76
- });
77
54
  Object.defineProperty(exports, 'automatedEnvironmentVariables', {
78
55
  enumerable: true,
79
56
  get: function () {
80
57
  return automatedEnvironmentVariables;
81
58
  }
82
59
  });
83
- Object.defineProperty(exports, 'isAgentEnvironment', {
84
- enumerable: true,
85
- get: function () {
86
- return isAgentEnvironment;
87
- }
88
- });
89
60
  Object.defineProperty(exports, 'isAutomatedEnvironment', {
90
61
  enumerable: true,
91
62
  get: function () {
@@ -110,4 +81,4 @@ Object.defineProperty(exports, 'isTestEnvironment', {
110
81
  return isTestEnvironment;
111
82
  }
112
83
  });
113
- //# sourceMappingURL=runtimeEnvironment-BlRyHkye.js.map
84
+ //# sourceMappingURL=runtimeEnvironment-DVXDje4R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeEnvironment-DVXDje4R.js","names":["getEnvVariable"],"sources":["../../src/utils/runtimeEnvironment.ts"],"sourcesContent":["import { getEnvVariable } from '../getEnvVariable';\n\nexport const automatedEnvironmentVariables = [\n 'CI',\n 'CONTINUOUS_INTEGRATION',\n 'GITHUB_ACTIONS',\n 'GITLAB_CI',\n 'CIRCLECI',\n 'TRAVIS',\n 'BUILDKITE',\n 'BITBUCKET_BUILD_NUMBER',\n 'APPVEYOR',\n 'CODEBUILD_BUILD_ID',\n 'TF_BUILD',\n 'TEAMCITY_VERSION',\n 'JENKINS_URL',\n 'HUDSON_URL',\n 'BAMBOO_BUILDKEY',\n 'CF_PAGES',\n] as const;\n\nconst isTruthyEnvValue = (value: unknown): boolean => {\n if (typeof value !== 'string' || !value) {\n return false;\n }\n\n return !['0', 'false', 'off', 'no'].includes(value.toLowerCase());\n};\n\nexport const isDevelopmentEnvironment = (): boolean => {\n try {\n return process.env.NODE_ENV === 'development';\n // eslint-disable-next-line no-empty\n } catch {}\n\n // TODO: add support for import.meta.env.DEV that is being used by vite\n\n return false;\n};\n\nexport const isTestEnvironment = (): boolean => {\n try {\n return process.env.NODE_ENV === 'test';\n // eslint-disable-next-line no-empty\n } catch {}\n\n // TODO: add support for import.meta.env.DEV that is being used by vite\n return false;\n};\n\nexport const isProductionEnvironment = (): boolean => {\n try {\n return process.env.NODE_ENV === 'production';\n // eslint-disable-next-line no-empty\n } catch {}\n\n // TODO: add support for import.meta.env.DEV that is being used by vite\n return false;\n};\n\nexport const isAutomatedEnvironment = (): boolean => {\n return automatedEnvironmentVariables.some(name => isTruthyEnvValue(getEnvVariable(name)));\n};\n"],"mappings":";;;AAEA,MAAa,gCAAgC;CAC3C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,oBAAoB,UAA4B;CACpD,IAAI,OAAO,UAAU,YAAY,CAAC,OAChC,OAAO;CAGT,OAAO,CAAC;EAAC;EAAK;EAAS;EAAO;CAAI,CAAC,CAAC,SAAS,MAAM,YAAY,CAAC;AAClE;AAEA,MAAa,iCAA0C;CACrD,IAAI;EACF,OAAO,QAAQ,IAAI,aAAa;CAElC,QAAQ,CAAC;CAIT,OAAO;AACT;AAEA,MAAa,0BAAmC;CAC9C,IAAI;EACF,OAAO,QAAQ,IAAI,aAAa;CAElC,QAAQ,CAAC;CAGT,OAAO;AACT;AAEA,MAAa,gCAAyC;CACpD,IAAI;EACF,OAAO,QAAQ,IAAI,aAAa;CAElC,QAAQ,CAAC;CAGT,OAAO;AACT;AAEA,MAAa,+BAAwC;CACnD,OAAO,8BAA8B,MAAK,SAAQ,iBAAiBA,sCAAe,IAAI,CAAC,CAAC;AAC1F"}
@@ -1,5 +1,5 @@
1
1
  import { parsePublishableKey } from "../keys.mjs";
2
- import { n as automatedEnvironmentVariables } from "./runtimeEnvironment-Pa5vb-_o.mjs";
2
+ import { t as automatedEnvironmentVariables } from "./runtimeEnvironment-CTVGzENl.mjs";
3
3
  import { isTruthy } from "../underscore.mjs";
4
4
 
5
5
  //#region src/telemetry/notice.ts
@@ -615,4 +615,4 @@ function extractThemeName(theme) {
615
615
 
616
616
  //#endregion
617
617
  export { eventMethodCalled as a, eventPrebuiltComponentMounted as c, eventFrameworkMetadata as i, eventPrebuiltComponentOpened as l, EVENT_THEME_USAGE as n, eventFlowStepMounted as o, eventThemeUsage as r, eventComponentMounted as s, EVENT_SAMPLING_RATE as t, TelemetryCollector as u };
618
- //# sourceMappingURL=telemetry-bR1HEN-w.mjs.map
618
+ //# sourceMappingURL=telemetry-9C6N5ppw.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry-bR1HEN-w.mjs","names":["#cache","#generateKey","#cacheTtl","#getCache","#storageKey","#maxSize","#config","#metadata","#eventThrottler","#preparePayload","#logEvent","#shouldRecord","#buffer","#scheduleFlush","#shouldRecordLog","#getSDKMetadata","#sanitizeContext","#shouldBeSampled","#flush","#pendingFlush","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE"],"sources":["../../src/telemetry/notice.ts","../../src/telemetry/throttler.ts","../../src/telemetry/collector.ts","../../src/telemetry/events/component-mounted.ts","../../src/telemetry/events/flow-step.ts","../../src/telemetry/events/method-called.ts","../../src/telemetry/events/framework-metadata.ts","../../src/telemetry/events/theme-usage.ts"],"sourcesContent":["/**\n * One-time runtime disclosure that Clerk collects telemetry from development instances.\n *\n * Replaces the previous `postinstall` script. Disclosure is intentionally surfaced\n * only on Node (server-side) so the noise profile matches the original postinstall\n * (terminal-only, dev-eyes-only). Browser consoles are not used because they are\n * frequently observed by non-developers (QA, screenshots, demos), and adding another\n * console warning is a common source of customer complaints.\n *\n * Known gap: pure browser-only setups with no server-side Clerk runtime (e.g. a Vite\n * SPA using `@clerk/clerk-react` or `@clerk/clerk-js` directly, without any Node/Edge\n * backend that imports `@clerk/shared`) will never hit this code path and therefore\n * see no in-band disclosure. This is an accepted trade-off: the original postinstall\n * already fired only once at install time and was easily missed, so the practical\n * delta is small. Authoritative disclosure for those setups lives in the Clerk\n * telemetry docs (https://clerk.com/docs/telemetry). Opt-out continues to work the\n * same way (`telemetry={false}` on `<ClerkProvider>` or the framework-specific\n * `*_CLERK_TELEMETRY_DISABLED` env var).\n *\n * Persistence is in-process via a `globalThis` Symbol, which survives Next.js HMR\n * module reloads. No filesystem access, no `node:` imports, no dynamic-code APIs, so\n * the module remains safe to bundle for Edge Runtime, Workers, and any browser path.\n *\n * All work is wrapped in try/catch. Failure to display the notice must never affect\n * the SDK.\n */\n\nimport { isTruthy } from '../underscore';\nimport { automatedEnvironmentVariables } from '../utils/runtimeEnvironment';\n\nconst PROCESS_FLAG = Symbol.for('@clerk/shared.telemetryNoticeShown');\n\nconst NOTICE_LINES = [\n 'Attention: Clerk collects telemetry data from its SDKs when connected to development instances.',\n \"The data collected is used to inform Clerk's product roadmap.\",\n 'To learn more, including how to opt-out from the telemetry program, visit: https://clerk.com/docs/telemetry.',\n];\n\nfunction isServerRuntime(): boolean {\n // Skip in browsers.\n if (typeof window !== 'undefined') {\n return false;\n }\n // Skip in Next.js Edge Runtime, which exposes a global `EdgeRuntime` marker. We detect via\n // this marker (rather than checking `process.versions`) because the Edge Runtime build-time\n // analyzer flags any reachable read of `process.versions` even when it sits behind a guard.\n if (typeof (globalThis as { EdgeRuntime?: string }).EdgeRuntime !== 'undefined') {\n return false;\n }\n return true;\n}\n\n// Server-only notice: read process.env directly rather than going through\n// getEnvVariable(), which would pull the multi-runtime env resolver into the\n// clerk.browser.js bundle (it ships there via TelemetryCollector). We reuse the\n// shared CI env-var list so the set of detected providers stays in one place.\nfunction isCI(): boolean {\n if (typeof process === 'undefined' || !process.env) {\n return false;\n }\n return automatedEnvironmentVariables.some(name => isTruthy(process.env[name]));\n}\n\nfunction hasSeen(): boolean {\n return Boolean((globalThis as Record<symbol, unknown>)[PROCESS_FLAG]);\n}\n\nfunction markSeen(): void {\n (globalThis as Record<symbol, unknown>)[PROCESS_FLAG] = true;\n}\n\nfunction printNotice(): void {\n if (typeof console === 'undefined' || typeof console.log !== 'function') {\n return;\n }\n for (const line of NOTICE_LINES) {\n console.log(line);\n }\n console.log('');\n}\n\nexport type MaybeShowTelemetryNoticeOptions = {\n /**\n * Skip the notice entirely. Used when the caller has already determined that no\n * telemetry will be sent (e.g. opt-out, non-development instance), in which case\n * there is nothing to disclose.\n */\n skip?: boolean;\n};\n\n/**\n * Display the one-time telemetry disclosure on server runtimes if it has not already been\n * shown in this process. Browser and Edge Runtime callers are silently skipped. Never throws.\n */\nexport function maybeShowTelemetryNotice(options: MaybeShowTelemetryNoticeOptions = {}): void {\n if (options.skip) {\n return;\n }\n try {\n if (!isServerRuntime()) {\n return;\n }\n if (isCI()) {\n return;\n }\n if (hasSeen()) {\n return;\n }\n printNotice();\n markSeen();\n } catch {\n // never let disclosure break the SDK\n }\n}\n\n/**\n * Test-only: clear the in-process flag so the next call re-runs the gating logic.\n *\n * @internal\n */\nexport function __resetTelemetryNoticeForTests(): void {\n delete (globalThis as Record<symbol, unknown>)[PROCESS_FLAG];\n}\n","import type { TelemetryEvent } from '../types';\n\ntype TtlInMilliseconds = number;\n\nconst DEFAULT_CACHE_TTL_MS = 86400000; // 24 hours\n\n/**\n * Interface for cache storage used by the telemetry throttler.\n * Implementations can use localStorage, in-memory storage, or any other storage mechanism.\n */\nexport interface ThrottlerCache {\n getItem(key: string): TtlInMilliseconds | undefined;\n setItem(key: string, value: TtlInMilliseconds): void;\n removeItem(key: string): void;\n}\n\n/**\n * Manages throttling for telemetry events using a configurable cache implementation\n * to mitigate event flooding in frequently executed code paths.\n */\nexport class TelemetryEventThrottler {\n #cache: ThrottlerCache;\n #cacheTtl = DEFAULT_CACHE_TTL_MS;\n\n constructor(cache: ThrottlerCache) {\n this.#cache = cache;\n }\n\n isEventThrottled(payload: TelemetryEvent): boolean {\n const now = Date.now();\n const key = this.#generateKey(payload);\n const entry = this.#cache.getItem(key);\n\n if (!entry) {\n this.#cache.setItem(key, now);\n return false;\n }\n\n const shouldInvalidate = now - entry > this.#cacheTtl;\n if (shouldInvalidate) {\n this.#cache.setItem(key, now);\n return false;\n }\n\n return true;\n }\n\n /**\n * Generates a consistent unique key for telemetry events by sorting payload properties.\n * This ensures that payloads with identical content in different orders produce the same key.\n */\n #generateKey(event: TelemetryEvent): string {\n const { sk: _sk, pk: _pk, payload, ...rest } = event;\n\n const sanitizedEvent: Omit<TelemetryEvent, 'sk' | 'pk' | 'payload'> & TelemetryEvent['payload'] = {\n ...payload,\n ...rest,\n };\n\n return JSON.stringify(\n Object.keys({\n ...payload,\n ...rest,\n })\n .sort()\n .map(key => sanitizedEvent[key]),\n );\n }\n}\n\n/**\n * LocalStorage-based cache implementation for browser environments.\n */\nexport class LocalStorageThrottlerCache implements ThrottlerCache {\n #storageKey = 'clerk_telemetry_throttler';\n\n getItem(key: string): TtlInMilliseconds | undefined {\n return this.#getCache()[key];\n }\n\n setItem(key: string, value: TtlInMilliseconds): void {\n try {\n const cache = this.#getCache();\n cache[key] = value;\n localStorage.setItem(this.#storageKey, JSON.stringify(cache));\n } catch (err: unknown) {\n const isQuotaExceededError =\n err instanceof DOMException &&\n // Check error names for different browsers\n (err.name === 'QuotaExceededError' || err.name === 'NS_ERROR_DOM_QUOTA_REACHED');\n\n if (isQuotaExceededError && localStorage.length > 0) {\n // Clear our cache if quota exceeded\n localStorage.removeItem(this.#storageKey);\n }\n }\n }\n\n removeItem(key: string): void {\n try {\n const cache = this.#getCache();\n delete cache[key];\n localStorage.setItem(this.#storageKey, JSON.stringify(cache));\n } catch {\n // Silently fail if we can't remove\n }\n }\n\n #getCache(): Record<string, TtlInMilliseconds> {\n try {\n const cacheString = localStorage.getItem(this.#storageKey);\n if (!cacheString) {\n return {};\n }\n return JSON.parse(cacheString);\n } catch {\n return {};\n }\n }\n\n static isSupported(): boolean {\n return typeof window !== 'undefined' && !!window.localStorage;\n }\n}\n\n/**\n * In-memory cache implementation for non-browser environments (e.g., React Native).\n */\nexport class InMemoryThrottlerCache implements ThrottlerCache {\n #cache: Map<string, TtlInMilliseconds> = new Map();\n #maxSize = 10000; // Defensive limit to prevent memory issues\n\n getItem(key: string): TtlInMilliseconds | undefined {\n // Defensive: clear cache if it gets too large\n if (this.#cache.size > this.#maxSize) {\n this.#cache.clear();\n return undefined;\n }\n\n return this.#cache.get(key);\n }\n\n setItem(key: string, value: TtlInMilliseconds): void {\n this.#cache.set(key, value);\n }\n\n removeItem(key: string): void {\n this.#cache.delete(key);\n }\n}\n","/**\n * The `TelemetryCollector` class handles collection of telemetry events from Clerk SDKs. Telemetry is opt-out and can be disabled by setting a CLERK_TELEMETRY_DISABLED environment variable.\n * The `ClerkProvider` also accepts a `telemetry` prop that will be passed to the collector during initialization:.\n *\n * ```jsx\n * <ClerkProvider telemetry={false}>\n * ...\n * </ClerkProvider>\n * ```\n *\n * For more information, please see the telemetry documentation page: https://clerk.com/docs/telemetry.\n */\nimport { parsePublishableKey } from '../keys';\nimport type {\n InstanceType,\n SDKMetadata,\n TelemetryCollector as TelemetryCollectorInterface,\n TelemetryEvent,\n TelemetryEventRaw,\n TelemetryLogEntry,\n} from '../types';\nimport { isTruthy } from '../underscore';\nimport { maybeShowTelemetryNotice } from './notice';\nimport { InMemoryThrottlerCache, LocalStorageThrottlerCache, TelemetryEventThrottler } from './throttler';\nimport type { TelemetryCollectorOptions } from './types';\n\n/**\n * Local interface for window.Clerk to avoid global type pollution.\n * This is only used within this module and doesn't affect other packages.\n */\ninterface WindowWithClerk extends Window {\n Clerk?: {\n constructor?: {\n sdkMetadata?: SDKMetadata;\n };\n };\n}\n\n/**\n * Type guard to check if window.Clerk exists and has the expected structure.\n */\nfunction isWindowClerkWithMetadata(clerk: unknown): clerk is { constructor: { sdkMetadata?: SDKMetadata } } {\n return (\n typeof clerk === 'object' && clerk !== null && 'constructor' in clerk && typeof clerk.constructor === 'function'\n );\n}\n\ntype TelemetryCollectorConfig = Pick<\n TelemetryCollectorOptions,\n 'samplingRate' | 'disabled' | 'debug' | 'maxBufferSize' | 'perEventSampling'\n> & {\n endpoint: string;\n};\n\ntype TelemetryMetadata = Required<\n Pick<TelemetryCollectorOptions, 'clerkVersion' | 'sdk' | 'sdkVersion' | 'publishableKey' | 'secretKey'>\n> & {\n /**\n * The instance type, derived from the provided publishableKey.\n */\n instanceType: InstanceType;\n};\n\n/**\n * Structure of log data sent to the telemetry endpoint.\n */\ntype TelemetryLogData = {\n /** Service that generated the log. */\n sdk: string;\n /** The version of the SDK where the event originated from. */\n sdkv: string;\n /** The version of Clerk where the event originated from. */\n cv: string;\n /** Log level (info, warn, error, debug, etc.). */\n lvl: TelemetryLogEntry['level'];\n /** Log message. */\n msg: string;\n /** Instance ID - optional. */\n iid?: string;\n /** Timestamp when log was generated. */\n ts: string;\n /** Primary key. */\n pk: string | null;\n /** Additional payload for the log. */\n payload: Record<string, unknown> | null;\n};\n\ntype TelemetryBufferItem = { kind: 'event'; value: TelemetryEvent } | { kind: 'log'; value: TelemetryLogData };\n\n// Accepted log levels for runtime validation\nconst VALID_LOG_LEVELS = new Set<string>(['error', 'warn', 'info', 'debug', 'trace']);\n\nconst DEFAULT_CONFIG: Partial<TelemetryCollectorConfig> = {\n samplingRate: 1,\n maxBufferSize: 5,\n // Production endpoint: https://clerk-telemetry.com\n // Staging endpoint: https://staging.clerk-telemetry.com\n // Local: http://localhost:8787\n endpoint: 'https://clerk-telemetry.com',\n};\n\nexport class TelemetryCollector implements TelemetryCollectorInterface {\n #config: Required<TelemetryCollectorConfig>;\n #eventThrottler: TelemetryEventThrottler;\n #metadata: TelemetryMetadata = {} as TelemetryMetadata;\n #buffer: TelemetryBufferItem[] = [];\n #pendingFlush: number | ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: TelemetryCollectorOptions) {\n this.#config = {\n maxBufferSize: options.maxBufferSize ?? DEFAULT_CONFIG.maxBufferSize,\n samplingRate: options.samplingRate ?? DEFAULT_CONFIG.samplingRate,\n perEventSampling: options.perEventSampling ?? true,\n disabled: options.disabled ?? false,\n debug: options.debug ?? false,\n endpoint: DEFAULT_CONFIG.endpoint,\n } as Required<TelemetryCollectorConfig>;\n\n if (!options.clerkVersion && typeof window === 'undefined') {\n // N/A in a server environment\n this.#metadata.clerkVersion = '';\n } else {\n this.#metadata.clerkVersion = options.clerkVersion ?? '';\n }\n\n // We will try to grab the SDK data lazily when an event is triggered, so it should always be defined once the event is sent.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#metadata.sdk = options.sdk!;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#metadata.sdkVersion = options.sdkVersion!;\n\n this.#metadata.publishableKey = options.publishableKey ?? '';\n\n const parsedKey = parsePublishableKey(options.publishableKey);\n if (parsedKey) {\n this.#metadata.instanceType = parsedKey.instanceType;\n }\n\n if (options.secretKey) {\n // Only send the first 16 characters of the secret key to to avoid sending the full key. We can still query against the partial key.\n this.#metadata.secretKey = options.secretKey.substring(0, 16);\n }\n\n // Use LocalStorage cache in browsers where it's supported, otherwise fall back to in-memory cache\n const cache = LocalStorageThrottlerCache.isSupported()\n ? new LocalStorageThrottlerCache()\n : new InMemoryThrottlerCache();\n this.#eventThrottler = new TelemetryEventThrottler(cache);\n\n // Surface the one-time telemetry disclosure at runtime instead of via a postinstall script.\n // Gated on `isEnabled` so users who opted out (or are not on a development instance) are not\n // shown a notice for collection that will never happen.\n maybeShowTelemetryNotice({ skip: !this.isEnabled });\n }\n\n get isEnabled(): boolean {\n if (this.#metadata.instanceType !== 'development') {\n return false;\n }\n\n // In browser or client environments, we most likely pass the disabled option to the collector, but in environments\n // where environment variables are available we also check for `CLERK_TELEMETRY_DISABLED`.\n if (\n this.#config.disabled ||\n (typeof process !== 'undefined' && process.env && isTruthy(process.env.CLERK_TELEMETRY_DISABLED))\n ) {\n return false;\n }\n\n // navigator.webdriver is a property generally set by headless browsers that are running in an automated testing environment.\n // Data from these environments is not meaningful for us and has the potential to produce a large volume of events, so we disable\n // collection in this case. (ref: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/webdriver)\n if (typeof window !== 'undefined' && !!window?.navigator?.webdriver) {\n return false;\n }\n\n return true;\n }\n\n get isDebug(): boolean {\n return (\n this.#config.debug ||\n (typeof process !== 'undefined' && process.env && isTruthy(process.env.CLERK_TELEMETRY_DEBUG))\n );\n }\n\n record(event: TelemetryEventRaw): void {\n try {\n const preparedPayload = this.#preparePayload(event.event, event.payload);\n\n this.#logEvent(preparedPayload.event, preparedPayload);\n\n if (!this.#shouldRecord(preparedPayload, event.eventSamplingRate)) {\n return;\n }\n\n this.#buffer.push({ kind: 'event', value: preparedPayload });\n\n this.#scheduleFlush();\n } catch (error) {\n console.error('[clerk/telemetry] Error recording telemetry event', error);\n }\n }\n\n /**\n * Records a telemetry log entry if logging is enabled and not in debug mode.\n *\n * @param entry - The telemetry log entry to record.\n */\n recordLog(entry: TelemetryLogEntry): void {\n try {\n if (!this.#shouldRecordLog(entry)) {\n return;\n }\n\n const levelIsValid = typeof entry?.level === 'string' && VALID_LOG_LEVELS.has(entry.level);\n const messageIsValid = typeof entry?.message === 'string' && entry.message.trim().length > 0;\n\n let normalizedTimestamp: Date | null = null;\n const timestampInput: unknown = (entry as unknown as { timestamp?: unknown })?.timestamp;\n if (typeof timestampInput === 'number' || typeof timestampInput === 'string') {\n const candidate = new Date(timestampInput);\n if (!Number.isNaN(candidate.getTime())) {\n normalizedTimestamp = candidate;\n }\n }\n\n if (!levelIsValid || !messageIsValid || normalizedTimestamp === null) {\n if (this.isDebug && typeof console !== 'undefined') {\n console.warn('[clerk/telemetry] Dropping invalid telemetry log entry', {\n levelIsValid,\n messageIsValid,\n timestampIsValid: normalizedTimestamp !== null,\n });\n }\n return;\n }\n\n const sdkMetadata = this.#getSDKMetadata();\n\n const logData: TelemetryLogData = {\n sdk: sdkMetadata.name,\n sdkv: sdkMetadata.version,\n cv: this.#metadata.clerkVersion ?? '',\n lvl: entry.level,\n msg: entry.message,\n ts: normalizedTimestamp.toISOString(),\n pk: this.#metadata.publishableKey || null,\n payload: this.#sanitizeContext(entry.context),\n };\n\n this.#buffer.push({ kind: 'log', value: logData });\n\n this.#scheduleFlush();\n } catch (error) {\n console.error('[clerk/telemetry] Error recording telemetry log entry', error);\n }\n }\n\n #shouldRecord(preparedPayload: TelemetryEvent, eventSamplingRate?: number) {\n return this.isEnabled && !this.isDebug && this.#shouldBeSampled(preparedPayload, eventSamplingRate);\n }\n\n #shouldRecordLog(_entry: TelemetryLogEntry): boolean {\n // Always allow logs from debug logger to be sent. Debug logger itself is already gated elsewhere.\n return true;\n }\n\n #shouldBeSampled(preparedPayload: TelemetryEvent, eventSamplingRate?: number) {\n const randomSeed = Math.random();\n\n const toBeSampled =\n randomSeed <= this.#config.samplingRate &&\n (this.#config.perEventSampling === false ||\n typeof eventSamplingRate === 'undefined' ||\n randomSeed <= eventSamplingRate);\n\n if (!toBeSampled) {\n return false;\n }\n\n return !this.#eventThrottler.isEventThrottled(preparedPayload);\n }\n\n #scheduleFlush(): void {\n // On the server, we want to flush immediately as we have less guarantees about the lifecycle of the process\n if (typeof window === 'undefined') {\n this.#flush();\n return;\n }\n const isBufferFull = this.#buffer.length >= this.#config.maxBufferSize;\n if (isBufferFull) {\n // If the buffer is full, flush immediately to make sure we minimize the chance of event loss.\n // Cancel any pending flushes as we're going to flush immediately\n if (this.#pendingFlush) {\n if (typeof cancelIdleCallback !== 'undefined') {\n cancelIdleCallback(Number(this.#pendingFlush));\n } else {\n clearTimeout(Number(this.#pendingFlush));\n }\n }\n this.#flush();\n return;\n }\n\n // If we have a pending flush, do nothing\n if (this.#pendingFlush) {\n return;\n }\n\n if ('requestIdleCallback' in window) {\n this.#pendingFlush = requestIdleCallback(() => {\n this.#flush();\n this.#pendingFlush = null;\n });\n } else {\n // This is not an ideal solution, but it at least waits until the next tick\n this.#pendingFlush = setTimeout(() => {\n this.#flush();\n this.#pendingFlush = null;\n }, 0);\n }\n }\n\n #flush(): void {\n // Capture the current buffer and clear it immediately to avoid closure references\n const itemsToSend = [...this.#buffer];\n this.#buffer = [];\n\n this.#pendingFlush = null;\n\n if (itemsToSend.length === 0) {\n return;\n }\n\n const eventsToSend = itemsToSend\n .filter(item => item.kind === 'event')\n .map(item => (item as { kind: 'event'; value: TelemetryEvent }).value);\n\n const logsToSend = itemsToSend\n .filter(item => item.kind === 'log')\n .map(item => (item as { kind: 'log'; value: TelemetryLogData }).value);\n\n if (eventsToSend.length > 0) {\n const eventsUrl = new URL('/v1/event', this.#config.endpoint);\n fetch(eventsUrl, {\n headers: {\n 'Content-Type': 'application/json',\n },\n keepalive: true,\n method: 'POST',\n // TODO: We send an array here with that idea that we can eventually send multiple events.\n body: JSON.stringify({ events: eventsToSend }),\n }).catch(() => void 0);\n }\n\n if (logsToSend.length > 0) {\n const logsUrl = new URL('/v1/logs', this.#config.endpoint);\n fetch(logsUrl, {\n headers: {\n 'Content-Type': 'application/json',\n },\n keepalive: true,\n method: 'POST',\n body: JSON.stringify({ logs: logsToSend }),\n }).catch(() => void 0);\n }\n }\n\n /**\n * If running in debug mode, log the event and its payload to the console.\n */\n #logEvent(event: TelemetryEvent['event'], payload: Record<string, any>) {\n if (!this.isDebug) {\n return;\n }\n\n if (typeof console.groupCollapsed !== 'undefined') {\n console.groupCollapsed('[clerk/telemetry]', event);\n console.log(payload);\n console.groupEnd();\n } else {\n console.log('[clerk/telemetry]', event, payload);\n }\n }\n\n /**\n * If in browser, attempt to lazily grab the SDK metadata from the Clerk singleton, otherwise fallback to the initially passed in values.\n *\n * This is necessary because the sdkMetadata can be set by the host SDK after the TelemetryCollector is instantiated.\n */\n #getSDKMetadata() {\n const sdkMetadata = {\n name: this.#metadata.sdk,\n version: this.#metadata.sdkVersion,\n };\n\n if (typeof window !== 'undefined') {\n const windowWithClerk = window as WindowWithClerk;\n\n if (windowWithClerk.Clerk) {\n const windowClerk = windowWithClerk.Clerk;\n\n if (isWindowClerkWithMetadata(windowClerk) && windowClerk.constructor.sdkMetadata) {\n const { name, version } = windowClerk.constructor.sdkMetadata;\n\n if (name !== undefined) {\n sdkMetadata.name = name;\n }\n if (version !== undefined) {\n sdkMetadata.version = version;\n }\n }\n }\n }\n\n return sdkMetadata;\n }\n\n /**\n * Append relevant metadata from the Clerk singleton to the event payload.\n */\n #preparePayload(event: TelemetryEvent['event'], payload: TelemetryEvent['payload']): TelemetryEvent {\n const sdkMetadata = this.#getSDKMetadata();\n\n return {\n event,\n cv: this.#metadata.clerkVersion ?? '',\n it: this.#metadata.instanceType ?? '',\n sdk: sdkMetadata.name,\n sdkv: sdkMetadata.version,\n ...(this.#metadata.publishableKey ? { pk: this.#metadata.publishableKey } : {}),\n ...(this.#metadata.secretKey ? { sk: this.#metadata.secretKey } : {}),\n payload,\n };\n }\n\n /**\n * Best-effort sanitization of the context payload. Returns a plain object with JSON-serializable\n * values or null when the input is missing or not serializable. Arrays are not accepted.\n */\n #sanitizeContext(context: unknown): Record<string, unknown> | null {\n if (context === null || typeof context === 'undefined') {\n return null;\n }\n if (typeof context !== 'object') {\n return null;\n }\n try {\n const cleaned = JSON.parse(JSON.stringify(context));\n if (cleaned && typeof cleaned === 'object' && !Array.isArray(cleaned)) {\n return cleaned as Record<string, unknown>;\n }\n return null;\n } catch {\n return null;\n }\n }\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_COMPONENT_MOUNTED = 'COMPONENT_MOUNTED';\nconst EVENT_COMPONENT_OPENED = 'COMPONENT_OPENED';\nconst EVENT_SAMPLING_RATE = 0.1;\n\n/** Increase sampling for high-signal auth components on mount. */\nconst AUTH_COMPONENTS = new Set<string>(['SignIn', 'SignUp']);\n\n/**\n * Returns the per-event sampling rate for component-mounted telemetry events.\n * Uses a higher rate for SignIn/SignUp to improve signal quality.\n *\n * @internal\n */\nfunction getComponentMountedSamplingRate(component: string): number {\n return AUTH_COMPONENTS.has(component) ? 1 : EVENT_SAMPLING_RATE;\n}\n\ntype ComponentMountedBase = {\n component: string;\n};\n\ntype EventPrebuiltComponent = ComponentMountedBase & {\n appearanceProp: boolean;\n elements: boolean;\n variables: boolean;\n theme: boolean;\n};\n\ntype EventComponentMounted = ComponentMountedBase & TelemetryEventRaw['payload'];\n\n/**\n * Factory for prebuilt component telemetry events.\n *\n * @internal\n */\nfunction createPrebuiltComponentEvent(event: typeof EVENT_COMPONENT_MOUNTED | typeof EVENT_COMPONENT_OPENED) {\n return function (\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n ): TelemetryEventRaw<EventPrebuiltComponent> {\n return {\n event,\n eventSamplingRate:\n event === EVENT_COMPONENT_MOUNTED ? getComponentMountedSamplingRate(component) : EVENT_SAMPLING_RATE,\n payload: {\n component,\n appearanceProp: Boolean(props?.appearance),\n theme: Boolean(props?.appearance?.theme),\n elements: Boolean(props?.appearance?.elements),\n variables: Boolean(props?.appearance?.variables),\n ...additionalPayload,\n },\n };\n };\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a prebuilt (AIO) component is mounted.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Will be filtered to a known list of props.\n * @param additionalPayload - Additional data to send with the event.\n * @example\n * telemetry.record(eventPrebuiltComponentMounted('SignUp', props));\n */\nexport function eventPrebuiltComponentMounted(\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n): TelemetryEventRaw<EventPrebuiltComponent> {\n return createPrebuiltComponentEvent(EVENT_COMPONENT_MOUNTED)(component, props, additionalPayload);\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a prebuilt (AIO) component is opened as a modal.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Will be filtered to a known list of props.\n * @param additionalPayload - Additional data to send with the event.\n * @example\n * telemetry.record(eventPrebuiltComponentOpened('GoogleOneTap', props));\n */\nexport function eventPrebuiltComponentOpened(\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n): TelemetryEventRaw<EventPrebuiltComponent> {\n return createPrebuiltComponentEvent(EVENT_COMPONENT_OPENED)(component, props, additionalPayload);\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a component is mounted. Use `eventPrebuiltComponentMounted` for prebuilt components.\n *\n * **Caution:** Filter the `props` you pass to this function to avoid sending too much data.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Ideally you only pass a handful of props here.\n * @example\n * telemetry.record(eventComponentMounted('SignUp', props));\n */\nexport function eventComponentMounted(\n component: string,\n props: TelemetryEventRaw['payload'] = {},\n): TelemetryEventRaw<EventComponentMounted> {\n return {\n event: EVENT_COMPONENT_MOUNTED,\n eventSamplingRate: getComponentMountedSamplingRate(component),\n payload: {\n component,\n ...props,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_FLOW_STEP_MOUNTED = 'FLOW_STEP_MOUNTED';\nconst EVENT_SAMPLING_RATE = 1;\n\ntype EventFlowStepMounted = {\n /** The flow the step belongs to, e.g. `configureSSO` (mirrors `Flow.Root`'s `flow`). */\n flow: string;\n /** The step/part that mounted, e.g. `verify-domain` */\n step: string;\n /** Free-form, flow-specific metadata supplied by the caller (e.g. `timestamp`, `connectionStatus`). */\n metadata: TelemetryEventRaw['payload'];\n} & TelemetryEventRaw['payload'];\n\n/**\n * Fires an event from a part of a multi-step flow.\n *\n * @param flow - The flow identifier (matches `Flow.Root`'s `flow`).\n * @param step - The step/part that mounted.\n * @param metadata - Flow-specific metadata sent under `payload.metadata`.\n * @param eventSamplingRate - Override the default full-capture sampling rate.\n * @example\n * telemetry.record(eventFlowStepMounted('configureSSO', 'verify-domain', { timestamp: new Date().toISOString(), connectionStatus: 'unconfigured' }));\n */\nexport function eventFlowStepMounted(\n flow: string,\n step: string,\n metadata: TelemetryEventRaw['payload'] = {},\n eventSamplingRate: number = EVENT_SAMPLING_RATE,\n): TelemetryEventRaw<EventFlowStepMounted> {\n return {\n event: EVENT_FLOW_STEP_MOUNTED,\n eventSamplingRate,\n payload: {\n flow,\n step,\n metadata,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_METHOD_CALLED = 'METHOD_CALLED';\nconst EVENT_SAMPLING_RATE = 0.1;\n\ntype EventMethodCalled = {\n method: string;\n} & Record<string, string | number | boolean>;\n\n/**\n * Fired when a helper method is called from a Clerk SDK.\n */\nexport function eventMethodCalled(\n method: string,\n payload?: Record<string, unknown>,\n): TelemetryEventRaw<EventMethodCalled> {\n return {\n event: EVENT_METHOD_CALLED,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload: {\n method,\n ...payload,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_FRAMEWORK_METADATA = 'FRAMEWORK_METADATA';\nconst EVENT_SAMPLING_RATE = 0.1;\n\ntype EventFrameworkMetadata = Record<string, string | number | boolean>;\n\n/**\n * Fired when a helper method is called from a Clerk SDK.\n */\nexport function eventFrameworkMetadata(payload: EventFrameworkMetadata): TelemetryEventRaw<EventFrameworkMetadata> {\n return {\n event: EVENT_FRAMEWORK_METADATA,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload,\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nexport const EVENT_THEME_USAGE = 'THEME_USAGE';\nexport const EVENT_SAMPLING_RATE = 1;\n\ntype EventThemeUsage = {\n /**\n * The name of the theme being used (e.g., \"shadcn\", \"neobrutalism\", etc.).\n */\n themeName?: string;\n};\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for tracking theme usage in ClerkProvider.\n *\n * @param appearance - The appearance prop from ClerkProvider.\n * @example\n * telemetry.record(eventThemeUsage(appearance));\n */\nexport function eventThemeUsage(appearance?: any): TelemetryEventRaw<EventThemeUsage> {\n const payload = analyzeThemeUsage(appearance);\n\n return {\n event: EVENT_THEME_USAGE,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload,\n };\n}\n\n/**\n * Analyzes the appearance prop to extract theme usage information for telemetry.\n *\n * @internal\n */\nfunction analyzeThemeUsage(appearance?: any): EventThemeUsage {\n if (!appearance || typeof appearance !== 'object') {\n return {};\n }\n\n const themeProperty = appearance.theme;\n\n if (!themeProperty) {\n return {};\n }\n\n let themeName: string | undefined;\n\n if (Array.isArray(themeProperty)) {\n // Look for the first identifiable theme name in the array\n for (const theme of themeProperty) {\n const name = extractThemeName(theme);\n if (name) {\n themeName = name;\n break;\n }\n }\n } else {\n themeName = extractThemeName(themeProperty);\n }\n\n return { themeName };\n}\n\n/**\n * Extracts the theme name from a theme object.\n *\n * @internal\n */\nfunction extractThemeName(theme: any): string | undefined {\n if (typeof theme === 'string') {\n return theme;\n }\n\n if (typeof theme === 'object' && theme !== null) {\n // Check for explicit theme name\n if ('name' in theme && typeof theme.name === 'string') {\n return theme.name;\n }\n }\n\n return undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,eAAe,OAAO,IAAI,oCAAoC;AAEpE,MAAM,eAAe;CACnB;CACA;CACA;AACF;AAEA,SAAS,kBAA2B;CAElC,IAAI,OAAO,WAAW,aACpB,OAAO;CAKT,IAAI,OAAQ,WAAwC,gBAAgB,aAClE,OAAO;CAET,OAAO;AACT;AAMA,SAAS,OAAgB;CACvB,IAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,KAC7C,OAAO;CAET,OAAO,8BAA8B,MAAK,SAAQ,SAAS,QAAQ,IAAI,KAAK,CAAC;AAC/E;AAEA,SAAS,UAAmB;CAC1B,OAAO,QAAS,WAAuC,aAAa;AACtE;AAEA,SAAS,WAAiB;CACxB,AAAC,WAAuC,gBAAgB;AAC1D;AAEA,SAAS,cAAoB;CAC3B,IAAI,OAAO,YAAY,eAAe,OAAO,QAAQ,QAAQ,YAC3D;CAEF,KAAK,MAAM,QAAQ,cACjB,QAAQ,IAAI,IAAI;CAElB,QAAQ,IAAI,EAAE;AAChB;;;;;AAeA,SAAgB,yBAAyB,UAA2C,CAAC,GAAS;CAC5F,IAAI,QAAQ,MACV;CAEF,IAAI;EACF,IAAI,CAAC,gBAAgB,GACnB;EAEF,IAAI,KAAK,GACP;EAEF,IAAI,QAAQ,GACV;EAEF,YAAY;EACZ,SAAS;CACX,QAAQ,CAER;AACF;;;;AC7GA,MAAM,uBAAuB;;;;;AAgB7B,IAAa,0BAAb,MAAqC;CACnC;CACA,YAAY;CAEZ,YAAY,OAAuB;EACjC,KAAKA,SAAS;CAChB;CAEA,iBAAiB,SAAkC;EACjD,MAAM,MAAM,KAAK,IAAI;EACrB,MAAM,MAAM,KAAKC,aAAa,OAAO;EACrC,MAAM,QAAQ,KAAKD,OAAO,QAAQ,GAAG;EAErC,IAAI,CAAC,OAAO;GACV,KAAKA,OAAO,QAAQ,KAAK,GAAG;GAC5B,OAAO;EACT;EAGA,IADyB,MAAM,QAAQ,KAAKE,WACtB;GACpB,KAAKF,OAAO,QAAQ,KAAK,GAAG;GAC5B,OAAO;EACT;EAEA,OAAO;CACT;;;;;CAMA,aAAa,OAA+B;EAC1C,MAAM,EAAE,IAAI,KAAK,IAAI,KAAK,SAAS,GAAG,SAAS;EAE/C,MAAM,iBAA4F;GAChG,GAAG;GACH,GAAG;EACL;EAEA,OAAO,KAAK,UACV,OAAO,KAAK;GACV,GAAG;GACH,GAAG;EACL,CAAC,CAAC,CACC,KAAK,CAAC,CACN,KAAI,QAAO,eAAe,IAAI,CACnC;CACF;AACF;;;;AAKA,IAAa,6BAAb,MAAkE;CAChE,cAAc;CAEd,QAAQ,KAA4C;EAClD,OAAO,KAAKG,UAAU,CAAC,CAAC;CAC1B;CAEA,QAAQ,KAAa,OAAgC;EACnD,IAAI;GACF,MAAM,QAAQ,KAAKA,UAAU;GAC7B,MAAM,OAAO;GACb,aAAa,QAAQ,KAAKC,aAAa,KAAK,UAAU,KAAK,CAAC;EAC9D,SAAS,KAAc;GAMrB,IAJE,eAAe,iBAEd,IAAI,SAAS,wBAAwB,IAAI,SAAS,iCAEzB,aAAa,SAAS,GAEhD,aAAa,WAAW,KAAKA,WAAW;EAE5C;CACF;CAEA,WAAW,KAAmB;EAC5B,IAAI;GACF,MAAM,QAAQ,KAAKD,UAAU;GAC7B,OAAO,MAAM;GACb,aAAa,QAAQ,KAAKC,aAAa,KAAK,UAAU,KAAK,CAAC;EAC9D,QAAQ,CAER;CACF;CAEA,YAA+C;EAC7C,IAAI;GACF,MAAM,cAAc,aAAa,QAAQ,KAAKA,WAAW;GACzD,IAAI,CAAC,aACH,OAAO,CAAC;GAEV,OAAO,KAAK,MAAM,WAAW;EAC/B,QAAQ;GACN,OAAO,CAAC;EACV;CACF;CAEA,OAAO,cAAuB;EAC5B,OAAO,OAAO,WAAW,eAAe,CAAC,CAAC,OAAO;CACnD;AACF;;;;AAKA,IAAa,yBAAb,MAA8D;CAC5D,yBAAyC,IAAI,IAAI;CACjD,WAAW;CAEX,QAAQ,KAA4C;EAElD,IAAI,KAAKJ,OAAO,OAAO,KAAKK,UAAU;GACpC,KAAKL,OAAO,MAAM;GAClB;EACF;EAEA,OAAO,KAAKA,OAAO,IAAI,GAAG;CAC5B;CAEA,QAAQ,KAAa,OAAgC;EACnD,KAAKA,OAAO,IAAI,KAAK,KAAK;CAC5B;CAEA,WAAW,KAAmB;EAC5B,KAAKA,OAAO,OAAO,GAAG;CACxB;AACF;;;;;;;;;;;;;;;;;;;AC5GA,SAAS,0BAA0B,OAAyE;CAC1G,OACE,OAAO,UAAU,YAAY,UAAU,QAAQ,iBAAiB,SAAS,OAAO,MAAM,gBAAgB;AAE1G;AA6CA,MAAM,mBAAmB,IAAI,IAAY;CAAC;CAAS;CAAQ;CAAQ;CAAS;AAAO,CAAC;AAEpF,MAAM,iBAAoD;CACxD,cAAc;CACd,eAAe;CAIf,UAAU;AACZ;AAEA,IAAa,qBAAb,MAAuE;CACrE;CACA;CACA,YAA+B,CAAC;CAChC,UAAiC,CAAC;CAClC,gBAA+D;CAE/D,YAAY,SAAoC;EAC9C,KAAKM,UAAU;GACb,eAAe,QAAQ,iBAAiB,eAAe;GACvD,cAAc,QAAQ,gBAAgB,eAAe;GACrD,kBAAkB,QAAQ,oBAAoB;GAC9C,UAAU,QAAQ,YAAY;GAC9B,OAAO,QAAQ,SAAS;GACxB,UAAU,eAAe;EAC3B;EAEA,IAAI,CAAC,QAAQ,gBAAgB,OAAO,WAAW,aAE7C,KAAKC,UAAU,eAAe;OAE9B,KAAKA,UAAU,eAAe,QAAQ,gBAAgB;EAKxD,KAAKA,UAAU,MAAM,QAAQ;EAE7B,KAAKA,UAAU,aAAa,QAAQ;EAEpC,KAAKA,UAAU,iBAAiB,QAAQ,kBAAkB;EAE1D,MAAM,YAAY,oBAAoB,QAAQ,cAAc;EAC5D,IAAI,WACF,KAAKA,UAAU,eAAe,UAAU;EAG1C,IAAI,QAAQ,WAEV,KAAKA,UAAU,YAAY,QAAQ,UAAU,UAAU,GAAG,EAAE;EAI9D,MAAM,QAAQ,2BAA2B,YAAY,IACjD,IAAI,2BAA2B,IAC/B,IAAI,uBAAuB;EAC/B,KAAKC,kBAAkB,IAAI,wBAAwB,KAAK;EAKxD,yBAAyB,EAAE,MAAM,CAAC,KAAK,UAAU,CAAC;CACpD;CAEA,IAAI,YAAqB;EACvB,IAAI,KAAKD,UAAU,iBAAiB,eAClC,OAAO;EAKT,IACE,KAAKD,QAAQ,YACZ,OAAO,YAAY,eAAe,QAAQ,OAAO,SAAS,QAAQ,IAAI,wBAAwB,GAE/F,OAAO;EAMT,IAAI,OAAO,WAAW,eAAe,CAAC,CAAC,QAAQ,WAAW,WACxD,OAAO;EAGT,OAAO;CACT;CAEA,IAAI,UAAmB;EACrB,OACE,KAAKA,QAAQ,SACZ,OAAO,YAAY,eAAe,QAAQ,OAAO,SAAS,QAAQ,IAAI,qBAAqB;CAEhG;CAEA,OAAO,OAAgC;EACrC,IAAI;GACF,MAAM,kBAAkB,KAAKG,gBAAgB,MAAM,OAAO,MAAM,OAAO;GAEvE,KAAKC,UAAU,gBAAgB,OAAO,eAAe;GAErD,IAAI,CAAC,KAAKC,cAAc,iBAAiB,MAAM,iBAAiB,GAC9D;GAGF,KAAKC,QAAQ,KAAK;IAAE,MAAM;IAAS,OAAO;GAAgB,CAAC;GAE3D,KAAKC,eAAe;EACtB,SAAS,OAAO;GACd,QAAQ,MAAM,qDAAqD,KAAK;EAC1E;CACF;;;;;;CAOA,UAAU,OAAgC;EACxC,IAAI;GACF,IAAI,CAAC,KAAKC,iBAAiB,KAAK,GAC9B;GAGF,MAAM,eAAe,OAAO,OAAO,UAAU,YAAY,iBAAiB,IAAI,MAAM,KAAK;GACzF,MAAM,iBAAiB,OAAO,OAAO,YAAY,YAAY,MAAM,QAAQ,KAAK,CAAC,CAAC,SAAS;GAE3F,IAAI,sBAAmC;GACvC,MAAM,iBAA2B,OAA8C;GAC/E,IAAI,OAAO,mBAAmB,YAAY,OAAO,mBAAmB,UAAU;IAC5E,MAAM,YAAY,IAAI,KAAK,cAAc;IACzC,IAAI,CAAC,OAAO,MAAM,UAAU,QAAQ,CAAC,GACnC,sBAAsB;GAE1B;GAEA,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,wBAAwB,MAAM;IACpE,IAAI,KAAK,WAAW,OAAO,YAAY,aACrC,QAAQ,KAAK,0DAA0D;KACrE;KACA;KACA,kBAAkB,wBAAwB;IAC5C,CAAC;IAEH;GACF;GAEA,MAAM,cAAc,KAAKC,gBAAgB;GAEzC,MAAM,UAA4B;IAChC,KAAK,YAAY;IACjB,MAAM,YAAY;IAClB,IAAI,KAAKR,UAAU,gBAAgB;IACnC,KAAK,MAAM;IACX,KAAK,MAAM;IACX,IAAI,oBAAoB,YAAY;IACpC,IAAI,KAAKA,UAAU,kBAAkB;IACrC,SAAS,KAAKS,iBAAiB,MAAM,OAAO;GAC9C;GAEA,KAAKJ,QAAQ,KAAK;IAAE,MAAM;IAAO,OAAO;GAAQ,CAAC;GAEjD,KAAKC,eAAe;EACtB,SAAS,OAAO;GACd,QAAQ,MAAM,yDAAyD,KAAK;EAC9E;CACF;CAEA,cAAc,iBAAiC,mBAA4B;EACzE,OAAO,KAAK,aAAa,CAAC,KAAK,WAAW,KAAKI,iBAAiB,iBAAiB,iBAAiB;CACpG;CAEA,iBAAiB,QAAoC;EAEnD,OAAO;CACT;CAEA,iBAAiB,iBAAiC,mBAA4B;EAC5E,MAAM,aAAa,KAAK,OAAO;EAQ/B,IAAI,EALF,cAAc,KAAKX,QAAQ,iBAC1B,KAAKA,QAAQ,qBAAqB,SACjC,OAAO,sBAAsB,eAC7B,cAAc,qBAGhB,OAAO;EAGT,OAAO,CAAC,KAAKE,gBAAgB,iBAAiB,eAAe;CAC/D;CAEA,iBAAuB;EAErB,IAAI,OAAO,WAAW,aAAa;GACjC,KAAKU,OAAO;GACZ;EACF;EAEA,IADqB,KAAKN,QAAQ,UAAU,KAAKN,QAAQ,eACvC;GAGhB,IAAI,KAAKa,eACP,IAAI,OAAO,uBAAuB,aAChC,mBAAmB,OAAO,KAAKA,aAAa,CAAC;QAE7C,aAAa,OAAO,KAAKA,aAAa,CAAC;GAG3C,KAAKD,OAAO;GACZ;EACF;EAGA,IAAI,KAAKC,eACP;EAGF,IAAI,yBAAyB,QAC3B,KAAKA,gBAAgB,0BAA0B;GAC7C,KAAKD,OAAO;GACZ,KAAKC,gBAAgB;EACvB,CAAC;OAGD,KAAKA,gBAAgB,iBAAiB;GACpC,KAAKD,OAAO;GACZ,KAAKC,gBAAgB;EACvB,GAAG,CAAC;CAER;CAEA,SAAe;EAEb,MAAM,cAAc,CAAC,GAAG,KAAKP,OAAO;EACpC,KAAKA,UAAU,CAAC;EAEhB,KAAKO,gBAAgB;EAErB,IAAI,YAAY,WAAW,GACzB;EAGF,MAAM,eAAe,YAClB,QAAO,SAAQ,KAAK,SAAS,OAAO,CAAC,CACrC,KAAI,SAAS,KAAkD,KAAK;EAEvE,MAAM,aAAa,YAChB,QAAO,SAAQ,KAAK,SAAS,KAAK,CAAC,CACnC,KAAI,SAAS,KAAkD,KAAK;EAEvE,IAAI,aAAa,SAAS,GAAG;GAC3B,MAAM,YAAY,IAAI,IAAI,aAAa,KAAKb,QAAQ,QAAQ;GAC5D,MAAM,WAAW;IACf,SAAS,EACP,gBAAgB,mBAClB;IACA,WAAW;IACX,QAAQ;IAER,MAAM,KAAK,UAAU,EAAE,QAAQ,aAAa,CAAC;GAC/C,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC;EACvB;EAEA,IAAI,WAAW,SAAS,GAAG;GACzB,MAAM,UAAU,IAAI,IAAI,YAAY,KAAKA,QAAQ,QAAQ;GACzD,MAAM,SAAS;IACb,SAAS,EACP,gBAAgB,mBAClB;IACA,WAAW;IACX,QAAQ;IACR,MAAM,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;GAC3C,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC;EACvB;CACF;;;;CAKA,UAAU,OAAgC,SAA8B;EACtE,IAAI,CAAC,KAAK,SACR;EAGF,IAAI,OAAO,QAAQ,mBAAmB,aAAa;GACjD,QAAQ,eAAe,qBAAqB,KAAK;GACjD,QAAQ,IAAI,OAAO;GACnB,QAAQ,SAAS;EACnB,OACE,QAAQ,IAAI,qBAAqB,OAAO,OAAO;CAEnD;;;;;;CAOA,kBAAkB;EAChB,MAAM,cAAc;GAClB,MAAM,KAAKC,UAAU;GACrB,SAAS,KAAKA,UAAU;EAC1B;EAEA,IAAI,OAAO,WAAW,aAAa;GACjC,MAAM,kBAAkB;GAExB,IAAI,gBAAgB,OAAO;IACzB,MAAM,cAAc,gBAAgB;IAEpC,IAAI,0BAA0B,WAAW,KAAK,YAAY,YAAY,aAAa;KACjF,MAAM,EAAE,MAAM,YAAY,YAAY,YAAY;KAElD,IAAI,SAAS,QACX,YAAY,OAAO;KAErB,IAAI,YAAY,QACd,YAAY,UAAU;IAE1B;GACF;EACF;EAEA,OAAO;CACT;;;;CAKA,gBAAgB,OAAgC,SAAoD;EAClG,MAAM,cAAc,KAAKQ,gBAAgB;EAEzC,OAAO;GACL;GACA,IAAI,KAAKR,UAAU,gBAAgB;GACnC,IAAI,KAAKA,UAAU,gBAAgB;GACnC,KAAK,YAAY;GACjB,MAAM,YAAY;GAClB,GAAI,KAAKA,UAAU,iBAAiB,EAAE,IAAI,KAAKA,UAAU,eAAe,IAAI,CAAC;GAC7E,GAAI,KAAKA,UAAU,YAAY,EAAE,IAAI,KAAKA,UAAU,UAAU,IAAI,CAAC;GACnE;EACF;CACF;;;;;CAMA,iBAAiB,SAAkD;EACjE,IAAI,YAAY,QAAQ,OAAO,YAAY,aACzC,OAAO;EAET,IAAI,OAAO,YAAY,UACrB,OAAO;EAET,IAAI;GACF,MAAM,UAAU,KAAK,MAAM,KAAK,UAAU,OAAO,CAAC;GAClD,IAAI,WAAW,OAAO,YAAY,YAAY,CAAC,MAAM,QAAQ,OAAO,GAClE,OAAO;GAET,OAAO;EACT,QAAQ;GACN,OAAO;EACT;CACF;AACF;;;;ACxcA,MAAM,0BAA0B;AAChC,MAAM,yBAAyB;AAC/B,MAAMa,wBAAsB;;AAG5B,MAAM,kBAAkB,IAAI,IAAY,CAAC,UAAU,QAAQ,CAAC;;;;;;;AAQ5D,SAAS,gCAAgC,WAA2B;CAClE,OAAO,gBAAgB,IAAI,SAAS,IAAI,IAAIA;AAC9C;;;;;;AAoBA,SAAS,6BAA6B,OAAuE;CAC3G,OAAO,SACL,WACA,OACA,mBAC2C;EAC3C,OAAO;GACL;GACA,mBACE,UAAU,0BAA0B,gCAAgC,SAAS,IAAIA;GACnF,SAAS;IACP;IACA,gBAAgB,QAAQ,OAAO,UAAU;IACzC,OAAO,QAAQ,OAAO,YAAY,KAAK;IACvC,UAAU,QAAQ,OAAO,YAAY,QAAQ;IAC7C,WAAW,QAAQ,OAAO,YAAY,SAAS;IAC/C,GAAG;GACL;EACF;CACF;AACF;;;;;;;;;;AAWA,SAAgB,8BACd,WACA,OACA,mBAC2C;CAC3C,OAAO,6BAA6B,uBAAuB,CAAC,CAAC,WAAW,OAAO,iBAAiB;AAClG;;;;;;;;;;AAWA,SAAgB,6BACd,WACA,OACA,mBAC2C;CAC3C,OAAO,6BAA6B,sBAAsB,CAAC,CAAC,WAAW,OAAO,iBAAiB;AACjG;;;;;;;;;;;AAYA,SAAgB,sBACd,WACA,QAAsC,CAAC,GACG;CAC1C,OAAO;EACL,OAAO;EACP,mBAAmB,gCAAgC,SAAS;EAC5D,SAAS;GACP;GACA,GAAG;EACL;CACF;AACF;;;;ACjHA,MAAM,0BAA0B;AAChC,MAAMC,wBAAsB;;;;;;;;;;;AAqB5B,SAAgB,qBACd,MACA,MACA,WAAyC,CAAC,GAC1C,oBAA4BA,uBACa;CACzC,OAAO;EACL,OAAO;EACP;EACA,SAAS;GACP;GACA;GACA;EACF;CACF;AACF;;;;ACrCA,MAAM,sBAAsB;AAC5B,MAAMC,wBAAsB;;;;AAS5B,SAAgB,kBACd,QACA,SACsC;CACtC,OAAO;EACL,OAAO;EACP,mBAAmBA;EACnB,SAAS;GACP;GACA,GAAG;EACL;CACF;AACF;;;;ACtBA,MAAM,2BAA2B;AACjC,MAAMC,wBAAsB;;;;AAO5B,SAAgB,uBAAuB,SAA4E;CACjH,OAAO;EACL,OAAO;EACP,mBAAmBA;EACnB;CACF;AACF;;;;ACdA,MAAa,oBAAoB;AACjC,MAAa,sBAAsB;;;;;;;;AAgBnC,SAAgB,gBAAgB,YAAsD;CAGpF,OAAO;EACL,OAAO;EACP;EACA,SALc,kBAAkB,UAK1B;CACR;AACF;;;;;;AAOA,SAAS,kBAAkB,YAAmC;CAC5D,IAAI,CAAC,cAAc,OAAO,eAAe,UACvC,OAAO,CAAC;CAGV,MAAM,gBAAgB,WAAW;CAEjC,IAAI,CAAC,eACH,OAAO,CAAC;CAGV,IAAI;CAEJ,IAAI,MAAM,QAAQ,aAAa,GAE7B,KAAK,MAAM,SAAS,eAAe;EACjC,MAAM,OAAO,iBAAiB,KAAK;EACnC,IAAI,MAAM;GACR,YAAY;GACZ;EACF;CACF;MAEA,YAAY,iBAAiB,aAAa;CAG5C,OAAO,EAAE,UAAU;AACrB;;;;;;AAOA,SAAS,iBAAiB,OAAgC;CACxD,IAAI,OAAO,UAAU,UACnB,OAAO;CAGT,IAAI,OAAO,UAAU,YAAY,UAAU,MAEzC;MAAI,UAAU,SAAS,OAAO,MAAM,SAAS,UAC3C,OAAO,MAAM;CACf;AAIJ"}
1
+ {"version":3,"file":"telemetry-9C6N5ppw.mjs","names":["#cache","#generateKey","#cacheTtl","#getCache","#storageKey","#maxSize","#config","#metadata","#eventThrottler","#preparePayload","#logEvent","#shouldRecord","#buffer","#scheduleFlush","#shouldRecordLog","#getSDKMetadata","#sanitizeContext","#shouldBeSampled","#flush","#pendingFlush","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE"],"sources":["../../src/telemetry/notice.ts","../../src/telemetry/throttler.ts","../../src/telemetry/collector.ts","../../src/telemetry/events/component-mounted.ts","../../src/telemetry/events/flow-step.ts","../../src/telemetry/events/method-called.ts","../../src/telemetry/events/framework-metadata.ts","../../src/telemetry/events/theme-usage.ts"],"sourcesContent":["/**\n * One-time runtime disclosure that Clerk collects telemetry from development instances.\n *\n * Replaces the previous `postinstall` script. Disclosure is intentionally surfaced\n * only on Node (server-side) so the noise profile matches the original postinstall\n * (terminal-only, dev-eyes-only). Browser consoles are not used because they are\n * frequently observed by non-developers (QA, screenshots, demos), and adding another\n * console warning is a common source of customer complaints.\n *\n * Known gap: pure browser-only setups with no server-side Clerk runtime (e.g. a Vite\n * SPA using `@clerk/clerk-react` or `@clerk/clerk-js` directly, without any Node/Edge\n * backend that imports `@clerk/shared`) will never hit this code path and therefore\n * see no in-band disclosure. This is an accepted trade-off: the original postinstall\n * already fired only once at install time and was easily missed, so the practical\n * delta is small. Authoritative disclosure for those setups lives in the Clerk\n * telemetry docs (https://clerk.com/docs/telemetry). Opt-out continues to work the\n * same way (`telemetry={false}` on `<ClerkProvider>` or the framework-specific\n * `*_CLERK_TELEMETRY_DISABLED` env var).\n *\n * Persistence is in-process via a `globalThis` Symbol, which survives Next.js HMR\n * module reloads. No filesystem access, no `node:` imports, no dynamic-code APIs, so\n * the module remains safe to bundle for Edge Runtime, Workers, and any browser path.\n *\n * All work is wrapped in try/catch. Failure to display the notice must never affect\n * the SDK.\n */\n\nimport { isTruthy } from '../underscore';\nimport { automatedEnvironmentVariables } from '../utils/runtimeEnvironment';\n\nconst PROCESS_FLAG = Symbol.for('@clerk/shared.telemetryNoticeShown');\n\nconst NOTICE_LINES = [\n 'Attention: Clerk collects telemetry data from its SDKs when connected to development instances.',\n \"The data collected is used to inform Clerk's product roadmap.\",\n 'To learn more, including how to opt-out from the telemetry program, visit: https://clerk.com/docs/telemetry.',\n];\n\nfunction isServerRuntime(): boolean {\n // Skip in browsers.\n if (typeof window !== 'undefined') {\n return false;\n }\n // Skip in Next.js Edge Runtime, which exposes a global `EdgeRuntime` marker. We detect via\n // this marker (rather than checking `process.versions`) because the Edge Runtime build-time\n // analyzer flags any reachable read of `process.versions` even when it sits behind a guard.\n if (typeof (globalThis as { EdgeRuntime?: string }).EdgeRuntime !== 'undefined') {\n return false;\n }\n return true;\n}\n\n// Server-only notice: read process.env directly rather than going through\n// getEnvVariable(), which would pull the multi-runtime env resolver into the\n// clerk.browser.js bundle (it ships there via TelemetryCollector). We reuse the\n// shared CI env-var list so the set of detected providers stays in one place.\nfunction isCI(): boolean {\n if (typeof process === 'undefined' || !process.env) {\n return false;\n }\n return automatedEnvironmentVariables.some(name => isTruthy(process.env[name]));\n}\n\nfunction hasSeen(): boolean {\n return Boolean((globalThis as Record<symbol, unknown>)[PROCESS_FLAG]);\n}\n\nfunction markSeen(): void {\n (globalThis as Record<symbol, unknown>)[PROCESS_FLAG] = true;\n}\n\nfunction printNotice(): void {\n if (typeof console === 'undefined' || typeof console.log !== 'function') {\n return;\n }\n for (const line of NOTICE_LINES) {\n console.log(line);\n }\n console.log('');\n}\n\nexport type MaybeShowTelemetryNoticeOptions = {\n /**\n * Skip the notice entirely. Used when the caller has already determined that no\n * telemetry will be sent (e.g. opt-out, non-development instance), in which case\n * there is nothing to disclose.\n */\n skip?: boolean;\n};\n\n/**\n * Display the one-time telemetry disclosure on server runtimes if it has not already been\n * shown in this process. Browser and Edge Runtime callers are silently skipped. Never throws.\n */\nexport function maybeShowTelemetryNotice(options: MaybeShowTelemetryNoticeOptions = {}): void {\n if (options.skip) {\n return;\n }\n try {\n if (!isServerRuntime()) {\n return;\n }\n if (isCI()) {\n return;\n }\n if (hasSeen()) {\n return;\n }\n printNotice();\n markSeen();\n } catch {\n // never let disclosure break the SDK\n }\n}\n\n/**\n * Test-only: clear the in-process flag so the next call re-runs the gating logic.\n *\n * @internal\n */\nexport function __resetTelemetryNoticeForTests(): void {\n delete (globalThis as Record<symbol, unknown>)[PROCESS_FLAG];\n}\n","import type { TelemetryEvent } from '../types';\n\ntype TtlInMilliseconds = number;\n\nconst DEFAULT_CACHE_TTL_MS = 86400000; // 24 hours\n\n/**\n * Interface for cache storage used by the telemetry throttler.\n * Implementations can use localStorage, in-memory storage, or any other storage mechanism.\n */\nexport interface ThrottlerCache {\n getItem(key: string): TtlInMilliseconds | undefined;\n setItem(key: string, value: TtlInMilliseconds): void;\n removeItem(key: string): void;\n}\n\n/**\n * Manages throttling for telemetry events using a configurable cache implementation\n * to mitigate event flooding in frequently executed code paths.\n */\nexport class TelemetryEventThrottler {\n #cache: ThrottlerCache;\n #cacheTtl = DEFAULT_CACHE_TTL_MS;\n\n constructor(cache: ThrottlerCache) {\n this.#cache = cache;\n }\n\n isEventThrottled(payload: TelemetryEvent): boolean {\n const now = Date.now();\n const key = this.#generateKey(payload);\n const entry = this.#cache.getItem(key);\n\n if (!entry) {\n this.#cache.setItem(key, now);\n return false;\n }\n\n const shouldInvalidate = now - entry > this.#cacheTtl;\n if (shouldInvalidate) {\n this.#cache.setItem(key, now);\n return false;\n }\n\n return true;\n }\n\n /**\n * Generates a consistent unique key for telemetry events by sorting payload properties.\n * This ensures that payloads with identical content in different orders produce the same key.\n */\n #generateKey(event: TelemetryEvent): string {\n const { sk: _sk, pk: _pk, payload, ...rest } = event;\n\n const sanitizedEvent: Omit<TelemetryEvent, 'sk' | 'pk' | 'payload'> & TelemetryEvent['payload'] = {\n ...payload,\n ...rest,\n };\n\n return JSON.stringify(\n Object.keys({\n ...payload,\n ...rest,\n })\n .sort()\n .map(key => sanitizedEvent[key]),\n );\n }\n}\n\n/**\n * LocalStorage-based cache implementation for browser environments.\n */\nexport class LocalStorageThrottlerCache implements ThrottlerCache {\n #storageKey = 'clerk_telemetry_throttler';\n\n getItem(key: string): TtlInMilliseconds | undefined {\n return this.#getCache()[key];\n }\n\n setItem(key: string, value: TtlInMilliseconds): void {\n try {\n const cache = this.#getCache();\n cache[key] = value;\n localStorage.setItem(this.#storageKey, JSON.stringify(cache));\n } catch (err: unknown) {\n const isQuotaExceededError =\n err instanceof DOMException &&\n // Check error names for different browsers\n (err.name === 'QuotaExceededError' || err.name === 'NS_ERROR_DOM_QUOTA_REACHED');\n\n if (isQuotaExceededError && localStorage.length > 0) {\n // Clear our cache if quota exceeded\n localStorage.removeItem(this.#storageKey);\n }\n }\n }\n\n removeItem(key: string): void {\n try {\n const cache = this.#getCache();\n delete cache[key];\n localStorage.setItem(this.#storageKey, JSON.stringify(cache));\n } catch {\n // Silently fail if we can't remove\n }\n }\n\n #getCache(): Record<string, TtlInMilliseconds> {\n try {\n const cacheString = localStorage.getItem(this.#storageKey);\n if (!cacheString) {\n return {};\n }\n return JSON.parse(cacheString);\n } catch {\n return {};\n }\n }\n\n static isSupported(): boolean {\n return typeof window !== 'undefined' && !!window.localStorage;\n }\n}\n\n/**\n * In-memory cache implementation for non-browser environments (e.g., React Native).\n */\nexport class InMemoryThrottlerCache implements ThrottlerCache {\n #cache: Map<string, TtlInMilliseconds> = new Map();\n #maxSize = 10000; // Defensive limit to prevent memory issues\n\n getItem(key: string): TtlInMilliseconds | undefined {\n // Defensive: clear cache if it gets too large\n if (this.#cache.size > this.#maxSize) {\n this.#cache.clear();\n return undefined;\n }\n\n return this.#cache.get(key);\n }\n\n setItem(key: string, value: TtlInMilliseconds): void {\n this.#cache.set(key, value);\n }\n\n removeItem(key: string): void {\n this.#cache.delete(key);\n }\n}\n","/**\n * The `TelemetryCollector` class handles collection of telemetry events from Clerk SDKs. Telemetry is opt-out and can be disabled by setting a CLERK_TELEMETRY_DISABLED environment variable.\n * The `ClerkProvider` also accepts a `telemetry` prop that will be passed to the collector during initialization:.\n *\n * ```jsx\n * <ClerkProvider telemetry={false}>\n * ...\n * </ClerkProvider>\n * ```\n *\n * For more information, please see the telemetry documentation page: https://clerk.com/docs/telemetry.\n */\nimport { parsePublishableKey } from '../keys';\nimport type {\n InstanceType,\n SDKMetadata,\n TelemetryCollector as TelemetryCollectorInterface,\n TelemetryEvent,\n TelemetryEventRaw,\n TelemetryLogEntry,\n} from '../types';\nimport { isTruthy } from '../underscore';\nimport { maybeShowTelemetryNotice } from './notice';\nimport { InMemoryThrottlerCache, LocalStorageThrottlerCache, TelemetryEventThrottler } from './throttler';\nimport type { TelemetryCollectorOptions } from './types';\n\n/**\n * Local interface for window.Clerk to avoid global type pollution.\n * This is only used within this module and doesn't affect other packages.\n */\ninterface WindowWithClerk extends Window {\n Clerk?: {\n constructor?: {\n sdkMetadata?: SDKMetadata;\n };\n };\n}\n\n/**\n * Type guard to check if window.Clerk exists and has the expected structure.\n */\nfunction isWindowClerkWithMetadata(clerk: unknown): clerk is { constructor: { sdkMetadata?: SDKMetadata } } {\n return (\n typeof clerk === 'object' && clerk !== null && 'constructor' in clerk && typeof clerk.constructor === 'function'\n );\n}\n\ntype TelemetryCollectorConfig = Pick<\n TelemetryCollectorOptions,\n 'samplingRate' | 'disabled' | 'debug' | 'maxBufferSize' | 'perEventSampling'\n> & {\n endpoint: string;\n};\n\ntype TelemetryMetadata = Required<\n Pick<TelemetryCollectorOptions, 'clerkVersion' | 'sdk' | 'sdkVersion' | 'publishableKey' | 'secretKey'>\n> & {\n /**\n * The instance type, derived from the provided publishableKey.\n */\n instanceType: InstanceType;\n};\n\n/**\n * Structure of log data sent to the telemetry endpoint.\n */\ntype TelemetryLogData = {\n /** Service that generated the log. */\n sdk: string;\n /** The version of the SDK where the event originated from. */\n sdkv: string;\n /** The version of Clerk where the event originated from. */\n cv: string;\n /** Log level (info, warn, error, debug, etc.). */\n lvl: TelemetryLogEntry['level'];\n /** Log message. */\n msg: string;\n /** Instance ID - optional. */\n iid?: string;\n /** Timestamp when log was generated. */\n ts: string;\n /** Primary key. */\n pk: string | null;\n /** Additional payload for the log. */\n payload: Record<string, unknown> | null;\n};\n\ntype TelemetryBufferItem = { kind: 'event'; value: TelemetryEvent } | { kind: 'log'; value: TelemetryLogData };\n\n// Accepted log levels for runtime validation\nconst VALID_LOG_LEVELS = new Set<string>(['error', 'warn', 'info', 'debug', 'trace']);\n\nconst DEFAULT_CONFIG: Partial<TelemetryCollectorConfig> = {\n samplingRate: 1,\n maxBufferSize: 5,\n // Production endpoint: https://clerk-telemetry.com\n // Staging endpoint: https://staging.clerk-telemetry.com\n // Local: http://localhost:8787\n endpoint: 'https://clerk-telemetry.com',\n};\n\nexport class TelemetryCollector implements TelemetryCollectorInterface {\n #config: Required<TelemetryCollectorConfig>;\n #eventThrottler: TelemetryEventThrottler;\n #metadata: TelemetryMetadata = {} as TelemetryMetadata;\n #buffer: TelemetryBufferItem[] = [];\n #pendingFlush: number | ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: TelemetryCollectorOptions) {\n this.#config = {\n maxBufferSize: options.maxBufferSize ?? DEFAULT_CONFIG.maxBufferSize,\n samplingRate: options.samplingRate ?? DEFAULT_CONFIG.samplingRate,\n perEventSampling: options.perEventSampling ?? true,\n disabled: options.disabled ?? false,\n debug: options.debug ?? false,\n endpoint: DEFAULT_CONFIG.endpoint,\n } as Required<TelemetryCollectorConfig>;\n\n if (!options.clerkVersion && typeof window === 'undefined') {\n // N/A in a server environment\n this.#metadata.clerkVersion = '';\n } else {\n this.#metadata.clerkVersion = options.clerkVersion ?? '';\n }\n\n // We will try to grab the SDK data lazily when an event is triggered, so it should always be defined once the event is sent.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#metadata.sdk = options.sdk!;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#metadata.sdkVersion = options.sdkVersion!;\n\n this.#metadata.publishableKey = options.publishableKey ?? '';\n\n const parsedKey = parsePublishableKey(options.publishableKey);\n if (parsedKey) {\n this.#metadata.instanceType = parsedKey.instanceType;\n }\n\n if (options.secretKey) {\n // Only send the first 16 characters of the secret key to to avoid sending the full key. We can still query against the partial key.\n this.#metadata.secretKey = options.secretKey.substring(0, 16);\n }\n\n // Use LocalStorage cache in browsers where it's supported, otherwise fall back to in-memory cache\n const cache = LocalStorageThrottlerCache.isSupported()\n ? new LocalStorageThrottlerCache()\n : new InMemoryThrottlerCache();\n this.#eventThrottler = new TelemetryEventThrottler(cache);\n\n // Surface the one-time telemetry disclosure at runtime instead of via a postinstall script.\n // Gated on `isEnabled` so users who opted out (or are not on a development instance) are not\n // shown a notice for collection that will never happen.\n maybeShowTelemetryNotice({ skip: !this.isEnabled });\n }\n\n get isEnabled(): boolean {\n if (this.#metadata.instanceType !== 'development') {\n return false;\n }\n\n // In browser or client environments, we most likely pass the disabled option to the collector, but in environments\n // where environment variables are available we also check for `CLERK_TELEMETRY_DISABLED`.\n if (\n this.#config.disabled ||\n (typeof process !== 'undefined' && process.env && isTruthy(process.env.CLERK_TELEMETRY_DISABLED))\n ) {\n return false;\n }\n\n // navigator.webdriver is a property generally set by headless browsers that are running in an automated testing environment.\n // Data from these environments is not meaningful for us and has the potential to produce a large volume of events, so we disable\n // collection in this case. (ref: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/webdriver)\n if (typeof window !== 'undefined' && !!window?.navigator?.webdriver) {\n return false;\n }\n\n return true;\n }\n\n get isDebug(): boolean {\n return (\n this.#config.debug ||\n (typeof process !== 'undefined' && process.env && isTruthy(process.env.CLERK_TELEMETRY_DEBUG))\n );\n }\n\n record(event: TelemetryEventRaw): void {\n try {\n const preparedPayload = this.#preparePayload(event.event, event.payload);\n\n this.#logEvent(preparedPayload.event, preparedPayload);\n\n if (!this.#shouldRecord(preparedPayload, event.eventSamplingRate)) {\n return;\n }\n\n this.#buffer.push({ kind: 'event', value: preparedPayload });\n\n this.#scheduleFlush();\n } catch (error) {\n console.error('[clerk/telemetry] Error recording telemetry event', error);\n }\n }\n\n /**\n * Records a telemetry log entry if logging is enabled and not in debug mode.\n *\n * @param entry - The telemetry log entry to record.\n */\n recordLog(entry: TelemetryLogEntry): void {\n try {\n if (!this.#shouldRecordLog(entry)) {\n return;\n }\n\n const levelIsValid = typeof entry?.level === 'string' && VALID_LOG_LEVELS.has(entry.level);\n const messageIsValid = typeof entry?.message === 'string' && entry.message.trim().length > 0;\n\n let normalizedTimestamp: Date | null = null;\n const timestampInput: unknown = (entry as unknown as { timestamp?: unknown })?.timestamp;\n if (typeof timestampInput === 'number' || typeof timestampInput === 'string') {\n const candidate = new Date(timestampInput);\n if (!Number.isNaN(candidate.getTime())) {\n normalizedTimestamp = candidate;\n }\n }\n\n if (!levelIsValid || !messageIsValid || normalizedTimestamp === null) {\n if (this.isDebug && typeof console !== 'undefined') {\n console.warn('[clerk/telemetry] Dropping invalid telemetry log entry', {\n levelIsValid,\n messageIsValid,\n timestampIsValid: normalizedTimestamp !== null,\n });\n }\n return;\n }\n\n const sdkMetadata = this.#getSDKMetadata();\n\n const logData: TelemetryLogData = {\n sdk: sdkMetadata.name,\n sdkv: sdkMetadata.version,\n cv: this.#metadata.clerkVersion ?? '',\n lvl: entry.level,\n msg: entry.message,\n ts: normalizedTimestamp.toISOString(),\n pk: this.#metadata.publishableKey || null,\n payload: this.#sanitizeContext(entry.context),\n };\n\n this.#buffer.push({ kind: 'log', value: logData });\n\n this.#scheduleFlush();\n } catch (error) {\n console.error('[clerk/telemetry] Error recording telemetry log entry', error);\n }\n }\n\n #shouldRecord(preparedPayload: TelemetryEvent, eventSamplingRate?: number) {\n return this.isEnabled && !this.isDebug && this.#shouldBeSampled(preparedPayload, eventSamplingRate);\n }\n\n #shouldRecordLog(_entry: TelemetryLogEntry): boolean {\n // Always allow logs from debug logger to be sent. Debug logger itself is already gated elsewhere.\n return true;\n }\n\n #shouldBeSampled(preparedPayload: TelemetryEvent, eventSamplingRate?: number) {\n const randomSeed = Math.random();\n\n const toBeSampled =\n randomSeed <= this.#config.samplingRate &&\n (this.#config.perEventSampling === false ||\n typeof eventSamplingRate === 'undefined' ||\n randomSeed <= eventSamplingRate);\n\n if (!toBeSampled) {\n return false;\n }\n\n return !this.#eventThrottler.isEventThrottled(preparedPayload);\n }\n\n #scheduleFlush(): void {\n // On the server, we want to flush immediately as we have less guarantees about the lifecycle of the process\n if (typeof window === 'undefined') {\n this.#flush();\n return;\n }\n const isBufferFull = this.#buffer.length >= this.#config.maxBufferSize;\n if (isBufferFull) {\n // If the buffer is full, flush immediately to make sure we minimize the chance of event loss.\n // Cancel any pending flushes as we're going to flush immediately\n if (this.#pendingFlush) {\n if (typeof cancelIdleCallback !== 'undefined') {\n cancelIdleCallback(Number(this.#pendingFlush));\n } else {\n clearTimeout(Number(this.#pendingFlush));\n }\n }\n this.#flush();\n return;\n }\n\n // If we have a pending flush, do nothing\n if (this.#pendingFlush) {\n return;\n }\n\n if ('requestIdleCallback' in window) {\n this.#pendingFlush = requestIdleCallback(() => {\n this.#flush();\n this.#pendingFlush = null;\n });\n } else {\n // This is not an ideal solution, but it at least waits until the next tick\n this.#pendingFlush = setTimeout(() => {\n this.#flush();\n this.#pendingFlush = null;\n }, 0);\n }\n }\n\n #flush(): void {\n // Capture the current buffer and clear it immediately to avoid closure references\n const itemsToSend = [...this.#buffer];\n this.#buffer = [];\n\n this.#pendingFlush = null;\n\n if (itemsToSend.length === 0) {\n return;\n }\n\n const eventsToSend = itemsToSend\n .filter(item => item.kind === 'event')\n .map(item => (item as { kind: 'event'; value: TelemetryEvent }).value);\n\n const logsToSend = itemsToSend\n .filter(item => item.kind === 'log')\n .map(item => (item as { kind: 'log'; value: TelemetryLogData }).value);\n\n if (eventsToSend.length > 0) {\n const eventsUrl = new URL('/v1/event', this.#config.endpoint);\n fetch(eventsUrl, {\n headers: {\n 'Content-Type': 'application/json',\n },\n keepalive: true,\n method: 'POST',\n // TODO: We send an array here with that idea that we can eventually send multiple events.\n body: JSON.stringify({ events: eventsToSend }),\n }).catch(() => void 0);\n }\n\n if (logsToSend.length > 0) {\n const logsUrl = new URL('/v1/logs', this.#config.endpoint);\n fetch(logsUrl, {\n headers: {\n 'Content-Type': 'application/json',\n },\n keepalive: true,\n method: 'POST',\n body: JSON.stringify({ logs: logsToSend }),\n }).catch(() => void 0);\n }\n }\n\n /**\n * If running in debug mode, log the event and its payload to the console.\n */\n #logEvent(event: TelemetryEvent['event'], payload: Record<string, any>) {\n if (!this.isDebug) {\n return;\n }\n\n if (typeof console.groupCollapsed !== 'undefined') {\n console.groupCollapsed('[clerk/telemetry]', event);\n console.log(payload);\n console.groupEnd();\n } else {\n console.log('[clerk/telemetry]', event, payload);\n }\n }\n\n /**\n * If in browser, attempt to lazily grab the SDK metadata from the Clerk singleton, otherwise fallback to the initially passed in values.\n *\n * This is necessary because the sdkMetadata can be set by the host SDK after the TelemetryCollector is instantiated.\n */\n #getSDKMetadata() {\n const sdkMetadata = {\n name: this.#metadata.sdk,\n version: this.#metadata.sdkVersion,\n };\n\n if (typeof window !== 'undefined') {\n const windowWithClerk = window as WindowWithClerk;\n\n if (windowWithClerk.Clerk) {\n const windowClerk = windowWithClerk.Clerk;\n\n if (isWindowClerkWithMetadata(windowClerk) && windowClerk.constructor.sdkMetadata) {\n const { name, version } = windowClerk.constructor.sdkMetadata;\n\n if (name !== undefined) {\n sdkMetadata.name = name;\n }\n if (version !== undefined) {\n sdkMetadata.version = version;\n }\n }\n }\n }\n\n return sdkMetadata;\n }\n\n /**\n * Append relevant metadata from the Clerk singleton to the event payload.\n */\n #preparePayload(event: TelemetryEvent['event'], payload: TelemetryEvent['payload']): TelemetryEvent {\n const sdkMetadata = this.#getSDKMetadata();\n\n return {\n event,\n cv: this.#metadata.clerkVersion ?? '',\n it: this.#metadata.instanceType ?? '',\n sdk: sdkMetadata.name,\n sdkv: sdkMetadata.version,\n ...(this.#metadata.publishableKey ? { pk: this.#metadata.publishableKey } : {}),\n ...(this.#metadata.secretKey ? { sk: this.#metadata.secretKey } : {}),\n payload,\n };\n }\n\n /**\n * Best-effort sanitization of the context payload. Returns a plain object with JSON-serializable\n * values or null when the input is missing or not serializable. Arrays are not accepted.\n */\n #sanitizeContext(context: unknown): Record<string, unknown> | null {\n if (context === null || typeof context === 'undefined') {\n return null;\n }\n if (typeof context !== 'object') {\n return null;\n }\n try {\n const cleaned = JSON.parse(JSON.stringify(context));\n if (cleaned && typeof cleaned === 'object' && !Array.isArray(cleaned)) {\n return cleaned as Record<string, unknown>;\n }\n return null;\n } catch {\n return null;\n }\n }\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_COMPONENT_MOUNTED = 'COMPONENT_MOUNTED';\nconst EVENT_COMPONENT_OPENED = 'COMPONENT_OPENED';\nconst EVENT_SAMPLING_RATE = 0.1;\n\n/** Increase sampling for high-signal auth components on mount. */\nconst AUTH_COMPONENTS = new Set<string>(['SignIn', 'SignUp']);\n\n/**\n * Returns the per-event sampling rate for component-mounted telemetry events.\n * Uses a higher rate for SignIn/SignUp to improve signal quality.\n *\n * @internal\n */\nfunction getComponentMountedSamplingRate(component: string): number {\n return AUTH_COMPONENTS.has(component) ? 1 : EVENT_SAMPLING_RATE;\n}\n\ntype ComponentMountedBase = {\n component: string;\n};\n\ntype EventPrebuiltComponent = ComponentMountedBase & {\n appearanceProp: boolean;\n elements: boolean;\n variables: boolean;\n theme: boolean;\n};\n\ntype EventComponentMounted = ComponentMountedBase & TelemetryEventRaw['payload'];\n\n/**\n * Factory for prebuilt component telemetry events.\n *\n * @internal\n */\nfunction createPrebuiltComponentEvent(event: typeof EVENT_COMPONENT_MOUNTED | typeof EVENT_COMPONENT_OPENED) {\n return function (\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n ): TelemetryEventRaw<EventPrebuiltComponent> {\n return {\n event,\n eventSamplingRate:\n event === EVENT_COMPONENT_MOUNTED ? getComponentMountedSamplingRate(component) : EVENT_SAMPLING_RATE,\n payload: {\n component,\n appearanceProp: Boolean(props?.appearance),\n theme: Boolean(props?.appearance?.theme),\n elements: Boolean(props?.appearance?.elements),\n variables: Boolean(props?.appearance?.variables),\n ...additionalPayload,\n },\n };\n };\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a prebuilt (AIO) component is mounted.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Will be filtered to a known list of props.\n * @param additionalPayload - Additional data to send with the event.\n * @example\n * telemetry.record(eventPrebuiltComponentMounted('SignUp', props));\n */\nexport function eventPrebuiltComponentMounted(\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n): TelemetryEventRaw<EventPrebuiltComponent> {\n return createPrebuiltComponentEvent(EVENT_COMPONENT_MOUNTED)(component, props, additionalPayload);\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a prebuilt (AIO) component is opened as a modal.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Will be filtered to a known list of props.\n * @param additionalPayload - Additional data to send with the event.\n * @example\n * telemetry.record(eventPrebuiltComponentOpened('GoogleOneTap', props));\n */\nexport function eventPrebuiltComponentOpened(\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n): TelemetryEventRaw<EventPrebuiltComponent> {\n return createPrebuiltComponentEvent(EVENT_COMPONENT_OPENED)(component, props, additionalPayload);\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a component is mounted. Use `eventPrebuiltComponentMounted` for prebuilt components.\n *\n * **Caution:** Filter the `props` you pass to this function to avoid sending too much data.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Ideally you only pass a handful of props here.\n * @example\n * telemetry.record(eventComponentMounted('SignUp', props));\n */\nexport function eventComponentMounted(\n component: string,\n props: TelemetryEventRaw['payload'] = {},\n): TelemetryEventRaw<EventComponentMounted> {\n return {\n event: EVENT_COMPONENT_MOUNTED,\n eventSamplingRate: getComponentMountedSamplingRate(component),\n payload: {\n component,\n ...props,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_FLOW_STEP_MOUNTED = 'FLOW_STEP_MOUNTED';\nconst EVENT_SAMPLING_RATE = 1;\n\ntype EventFlowStepMounted = {\n /** The flow the step belongs to, e.g. `configureSSO` (mirrors `Flow.Root`'s `flow`). */\n flow: string;\n /** The step/part that mounted, e.g. `verify-domain` */\n step: string;\n /** Free-form, flow-specific metadata supplied by the caller (e.g. `timestamp`, `connectionStatus`). */\n metadata: TelemetryEventRaw['payload'];\n} & TelemetryEventRaw['payload'];\n\n/**\n * Fires an event from a part of a multi-step flow.\n *\n * @param flow - The flow identifier (matches `Flow.Root`'s `flow`).\n * @param step - The step/part that mounted.\n * @param metadata - Flow-specific metadata sent under `payload.metadata`.\n * @param eventSamplingRate - Override the default full-capture sampling rate.\n * @example\n * telemetry.record(eventFlowStepMounted('configureSSO', 'verify-domain', { timestamp: new Date().toISOString(), connectionStatus: 'unconfigured' }));\n */\nexport function eventFlowStepMounted(\n flow: string,\n step: string,\n metadata: TelemetryEventRaw['payload'] = {},\n eventSamplingRate: number = EVENT_SAMPLING_RATE,\n): TelemetryEventRaw<EventFlowStepMounted> {\n return {\n event: EVENT_FLOW_STEP_MOUNTED,\n eventSamplingRate,\n payload: {\n flow,\n step,\n metadata,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_METHOD_CALLED = 'METHOD_CALLED';\nconst EVENT_SAMPLING_RATE = 0.1;\n\ntype EventMethodCalled = {\n method: string;\n} & Record<string, string | number | boolean>;\n\n/**\n * Fired when a helper method is called from a Clerk SDK.\n */\nexport function eventMethodCalled(\n method: string,\n payload?: Record<string, unknown>,\n): TelemetryEventRaw<EventMethodCalled> {\n return {\n event: EVENT_METHOD_CALLED,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload: {\n method,\n ...payload,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_FRAMEWORK_METADATA = 'FRAMEWORK_METADATA';\nconst EVENT_SAMPLING_RATE = 0.1;\n\ntype EventFrameworkMetadata = Record<string, string | number | boolean>;\n\n/**\n * Fired when a helper method is called from a Clerk SDK.\n */\nexport function eventFrameworkMetadata(payload: EventFrameworkMetadata): TelemetryEventRaw<EventFrameworkMetadata> {\n return {\n event: EVENT_FRAMEWORK_METADATA,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload,\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nexport const EVENT_THEME_USAGE = 'THEME_USAGE';\nexport const EVENT_SAMPLING_RATE = 1;\n\ntype EventThemeUsage = {\n /**\n * The name of the theme being used (e.g., \"shadcn\", \"neobrutalism\", etc.).\n */\n themeName?: string;\n};\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for tracking theme usage in ClerkProvider.\n *\n * @param appearance - The appearance prop from ClerkProvider.\n * @example\n * telemetry.record(eventThemeUsage(appearance));\n */\nexport function eventThemeUsage(appearance?: any): TelemetryEventRaw<EventThemeUsage> {\n const payload = analyzeThemeUsage(appearance);\n\n return {\n event: EVENT_THEME_USAGE,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload,\n };\n}\n\n/**\n * Analyzes the appearance prop to extract theme usage information for telemetry.\n *\n * @internal\n */\nfunction analyzeThemeUsage(appearance?: any): EventThemeUsage {\n if (!appearance || typeof appearance !== 'object') {\n return {};\n }\n\n const themeProperty = appearance.theme;\n\n if (!themeProperty) {\n return {};\n }\n\n let themeName: string | undefined;\n\n if (Array.isArray(themeProperty)) {\n // Look for the first identifiable theme name in the array\n for (const theme of themeProperty) {\n const name = extractThemeName(theme);\n if (name) {\n themeName = name;\n break;\n }\n }\n } else {\n themeName = extractThemeName(themeProperty);\n }\n\n return { themeName };\n}\n\n/**\n * Extracts the theme name from a theme object.\n *\n * @internal\n */\nfunction extractThemeName(theme: any): string | undefined {\n if (typeof theme === 'string') {\n return theme;\n }\n\n if (typeof theme === 'object' && theme !== null) {\n // Check for explicit theme name\n if ('name' in theme && typeof theme.name === 'string') {\n return theme.name;\n }\n }\n\n return undefined;\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  const require_keys = require('../keys.js');
2
- const require_runtimeEnvironment = require('./runtimeEnvironment-BlRyHkye.js');
2
+ const require_runtimeEnvironment = require('./runtimeEnvironment-DVXDje4R.js');
3
3
  const require_underscore = require('../underscore.js');
4
4
 
5
5
  //#region src/telemetry/notice.ts
@@ -674,4 +674,4 @@ Object.defineProperty(exports, 'eventThemeUsage', {
674
674
  return eventThemeUsage;
675
675
  }
676
676
  });
677
- //# sourceMappingURL=telemetry-DenGWatg.js.map
677
+ //# sourceMappingURL=telemetry-DZp9OI1j.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry-DenGWatg.js","names":["automatedEnvironmentVariables","isTruthy","#cache","#generateKey","#cacheTtl","#getCache","#storageKey","#maxSize","#config","#metadata","parsePublishableKey","#eventThrottler","isTruthy","#preparePayload","#logEvent","#shouldRecord","#buffer","#scheduleFlush","#shouldRecordLog","#getSDKMetadata","#sanitizeContext","#shouldBeSampled","#flush","#pendingFlush","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE"],"sources":["../../src/telemetry/notice.ts","../../src/telemetry/throttler.ts","../../src/telemetry/collector.ts","../../src/telemetry/events/component-mounted.ts","../../src/telemetry/events/flow-step.ts","../../src/telemetry/events/method-called.ts","../../src/telemetry/events/framework-metadata.ts","../../src/telemetry/events/theme-usage.ts"],"sourcesContent":["/**\n * One-time runtime disclosure that Clerk collects telemetry from development instances.\n *\n * Replaces the previous `postinstall` script. Disclosure is intentionally surfaced\n * only on Node (server-side) so the noise profile matches the original postinstall\n * (terminal-only, dev-eyes-only). Browser consoles are not used because they are\n * frequently observed by non-developers (QA, screenshots, demos), and adding another\n * console warning is a common source of customer complaints.\n *\n * Known gap: pure browser-only setups with no server-side Clerk runtime (e.g. a Vite\n * SPA using `@clerk/clerk-react` or `@clerk/clerk-js` directly, without any Node/Edge\n * backend that imports `@clerk/shared`) will never hit this code path and therefore\n * see no in-band disclosure. This is an accepted trade-off: the original postinstall\n * already fired only once at install time and was easily missed, so the practical\n * delta is small. Authoritative disclosure for those setups lives in the Clerk\n * telemetry docs (https://clerk.com/docs/telemetry). Opt-out continues to work the\n * same way (`telemetry={false}` on `<ClerkProvider>` or the framework-specific\n * `*_CLERK_TELEMETRY_DISABLED` env var).\n *\n * Persistence is in-process via a `globalThis` Symbol, which survives Next.js HMR\n * module reloads. No filesystem access, no `node:` imports, no dynamic-code APIs, so\n * the module remains safe to bundle for Edge Runtime, Workers, and any browser path.\n *\n * All work is wrapped in try/catch. Failure to display the notice must never affect\n * the SDK.\n */\n\nimport { isTruthy } from '../underscore';\nimport { automatedEnvironmentVariables } from '../utils/runtimeEnvironment';\n\nconst PROCESS_FLAG = Symbol.for('@clerk/shared.telemetryNoticeShown');\n\nconst NOTICE_LINES = [\n 'Attention: Clerk collects telemetry data from its SDKs when connected to development instances.',\n \"The data collected is used to inform Clerk's product roadmap.\",\n 'To learn more, including how to opt-out from the telemetry program, visit: https://clerk.com/docs/telemetry.',\n];\n\nfunction isServerRuntime(): boolean {\n // Skip in browsers.\n if (typeof window !== 'undefined') {\n return false;\n }\n // Skip in Next.js Edge Runtime, which exposes a global `EdgeRuntime` marker. We detect via\n // this marker (rather than checking `process.versions`) because the Edge Runtime build-time\n // analyzer flags any reachable read of `process.versions` even when it sits behind a guard.\n if (typeof (globalThis as { EdgeRuntime?: string }).EdgeRuntime !== 'undefined') {\n return false;\n }\n return true;\n}\n\n// Server-only notice: read process.env directly rather than going through\n// getEnvVariable(), which would pull the multi-runtime env resolver into the\n// clerk.browser.js bundle (it ships there via TelemetryCollector). We reuse the\n// shared CI env-var list so the set of detected providers stays in one place.\nfunction isCI(): boolean {\n if (typeof process === 'undefined' || !process.env) {\n return false;\n }\n return automatedEnvironmentVariables.some(name => isTruthy(process.env[name]));\n}\n\nfunction hasSeen(): boolean {\n return Boolean((globalThis as Record<symbol, unknown>)[PROCESS_FLAG]);\n}\n\nfunction markSeen(): void {\n (globalThis as Record<symbol, unknown>)[PROCESS_FLAG] = true;\n}\n\nfunction printNotice(): void {\n if (typeof console === 'undefined' || typeof console.log !== 'function') {\n return;\n }\n for (const line of NOTICE_LINES) {\n console.log(line);\n }\n console.log('');\n}\n\nexport type MaybeShowTelemetryNoticeOptions = {\n /**\n * Skip the notice entirely. Used when the caller has already determined that no\n * telemetry will be sent (e.g. opt-out, non-development instance), in which case\n * there is nothing to disclose.\n */\n skip?: boolean;\n};\n\n/**\n * Display the one-time telemetry disclosure on server runtimes if it has not already been\n * shown in this process. Browser and Edge Runtime callers are silently skipped. Never throws.\n */\nexport function maybeShowTelemetryNotice(options: MaybeShowTelemetryNoticeOptions = {}): void {\n if (options.skip) {\n return;\n }\n try {\n if (!isServerRuntime()) {\n return;\n }\n if (isCI()) {\n return;\n }\n if (hasSeen()) {\n return;\n }\n printNotice();\n markSeen();\n } catch {\n // never let disclosure break the SDK\n }\n}\n\n/**\n * Test-only: clear the in-process flag so the next call re-runs the gating logic.\n *\n * @internal\n */\nexport function __resetTelemetryNoticeForTests(): void {\n delete (globalThis as Record<symbol, unknown>)[PROCESS_FLAG];\n}\n","import type { TelemetryEvent } from '../types';\n\ntype TtlInMilliseconds = number;\n\nconst DEFAULT_CACHE_TTL_MS = 86400000; // 24 hours\n\n/**\n * Interface for cache storage used by the telemetry throttler.\n * Implementations can use localStorage, in-memory storage, or any other storage mechanism.\n */\nexport interface ThrottlerCache {\n getItem(key: string): TtlInMilliseconds | undefined;\n setItem(key: string, value: TtlInMilliseconds): void;\n removeItem(key: string): void;\n}\n\n/**\n * Manages throttling for telemetry events using a configurable cache implementation\n * to mitigate event flooding in frequently executed code paths.\n */\nexport class TelemetryEventThrottler {\n #cache: ThrottlerCache;\n #cacheTtl = DEFAULT_CACHE_TTL_MS;\n\n constructor(cache: ThrottlerCache) {\n this.#cache = cache;\n }\n\n isEventThrottled(payload: TelemetryEvent): boolean {\n const now = Date.now();\n const key = this.#generateKey(payload);\n const entry = this.#cache.getItem(key);\n\n if (!entry) {\n this.#cache.setItem(key, now);\n return false;\n }\n\n const shouldInvalidate = now - entry > this.#cacheTtl;\n if (shouldInvalidate) {\n this.#cache.setItem(key, now);\n return false;\n }\n\n return true;\n }\n\n /**\n * Generates a consistent unique key for telemetry events by sorting payload properties.\n * This ensures that payloads with identical content in different orders produce the same key.\n */\n #generateKey(event: TelemetryEvent): string {\n const { sk: _sk, pk: _pk, payload, ...rest } = event;\n\n const sanitizedEvent: Omit<TelemetryEvent, 'sk' | 'pk' | 'payload'> & TelemetryEvent['payload'] = {\n ...payload,\n ...rest,\n };\n\n return JSON.stringify(\n Object.keys({\n ...payload,\n ...rest,\n })\n .sort()\n .map(key => sanitizedEvent[key]),\n );\n }\n}\n\n/**\n * LocalStorage-based cache implementation for browser environments.\n */\nexport class LocalStorageThrottlerCache implements ThrottlerCache {\n #storageKey = 'clerk_telemetry_throttler';\n\n getItem(key: string): TtlInMilliseconds | undefined {\n return this.#getCache()[key];\n }\n\n setItem(key: string, value: TtlInMilliseconds): void {\n try {\n const cache = this.#getCache();\n cache[key] = value;\n localStorage.setItem(this.#storageKey, JSON.stringify(cache));\n } catch (err: unknown) {\n const isQuotaExceededError =\n err instanceof DOMException &&\n // Check error names for different browsers\n (err.name === 'QuotaExceededError' || err.name === 'NS_ERROR_DOM_QUOTA_REACHED');\n\n if (isQuotaExceededError && localStorage.length > 0) {\n // Clear our cache if quota exceeded\n localStorage.removeItem(this.#storageKey);\n }\n }\n }\n\n removeItem(key: string): void {\n try {\n const cache = this.#getCache();\n delete cache[key];\n localStorage.setItem(this.#storageKey, JSON.stringify(cache));\n } catch {\n // Silently fail if we can't remove\n }\n }\n\n #getCache(): Record<string, TtlInMilliseconds> {\n try {\n const cacheString = localStorage.getItem(this.#storageKey);\n if (!cacheString) {\n return {};\n }\n return JSON.parse(cacheString);\n } catch {\n return {};\n }\n }\n\n static isSupported(): boolean {\n return typeof window !== 'undefined' && !!window.localStorage;\n }\n}\n\n/**\n * In-memory cache implementation for non-browser environments (e.g., React Native).\n */\nexport class InMemoryThrottlerCache implements ThrottlerCache {\n #cache: Map<string, TtlInMilliseconds> = new Map();\n #maxSize = 10000; // Defensive limit to prevent memory issues\n\n getItem(key: string): TtlInMilliseconds | undefined {\n // Defensive: clear cache if it gets too large\n if (this.#cache.size > this.#maxSize) {\n this.#cache.clear();\n return undefined;\n }\n\n return this.#cache.get(key);\n }\n\n setItem(key: string, value: TtlInMilliseconds): void {\n this.#cache.set(key, value);\n }\n\n removeItem(key: string): void {\n this.#cache.delete(key);\n }\n}\n","/**\n * The `TelemetryCollector` class handles collection of telemetry events from Clerk SDKs. Telemetry is opt-out and can be disabled by setting a CLERK_TELEMETRY_DISABLED environment variable.\n * The `ClerkProvider` also accepts a `telemetry` prop that will be passed to the collector during initialization:.\n *\n * ```jsx\n * <ClerkProvider telemetry={false}>\n * ...\n * </ClerkProvider>\n * ```\n *\n * For more information, please see the telemetry documentation page: https://clerk.com/docs/telemetry.\n */\nimport { parsePublishableKey } from '../keys';\nimport type {\n InstanceType,\n SDKMetadata,\n TelemetryCollector as TelemetryCollectorInterface,\n TelemetryEvent,\n TelemetryEventRaw,\n TelemetryLogEntry,\n} from '../types';\nimport { isTruthy } from '../underscore';\nimport { maybeShowTelemetryNotice } from './notice';\nimport { InMemoryThrottlerCache, LocalStorageThrottlerCache, TelemetryEventThrottler } from './throttler';\nimport type { TelemetryCollectorOptions } from './types';\n\n/**\n * Local interface for window.Clerk to avoid global type pollution.\n * This is only used within this module and doesn't affect other packages.\n */\ninterface WindowWithClerk extends Window {\n Clerk?: {\n constructor?: {\n sdkMetadata?: SDKMetadata;\n };\n };\n}\n\n/**\n * Type guard to check if window.Clerk exists and has the expected structure.\n */\nfunction isWindowClerkWithMetadata(clerk: unknown): clerk is { constructor: { sdkMetadata?: SDKMetadata } } {\n return (\n typeof clerk === 'object' && clerk !== null && 'constructor' in clerk && typeof clerk.constructor === 'function'\n );\n}\n\ntype TelemetryCollectorConfig = Pick<\n TelemetryCollectorOptions,\n 'samplingRate' | 'disabled' | 'debug' | 'maxBufferSize' | 'perEventSampling'\n> & {\n endpoint: string;\n};\n\ntype TelemetryMetadata = Required<\n Pick<TelemetryCollectorOptions, 'clerkVersion' | 'sdk' | 'sdkVersion' | 'publishableKey' | 'secretKey'>\n> & {\n /**\n * The instance type, derived from the provided publishableKey.\n */\n instanceType: InstanceType;\n};\n\n/**\n * Structure of log data sent to the telemetry endpoint.\n */\ntype TelemetryLogData = {\n /** Service that generated the log. */\n sdk: string;\n /** The version of the SDK where the event originated from. */\n sdkv: string;\n /** The version of Clerk where the event originated from. */\n cv: string;\n /** Log level (info, warn, error, debug, etc.). */\n lvl: TelemetryLogEntry['level'];\n /** Log message. */\n msg: string;\n /** Instance ID - optional. */\n iid?: string;\n /** Timestamp when log was generated. */\n ts: string;\n /** Primary key. */\n pk: string | null;\n /** Additional payload for the log. */\n payload: Record<string, unknown> | null;\n};\n\ntype TelemetryBufferItem = { kind: 'event'; value: TelemetryEvent } | { kind: 'log'; value: TelemetryLogData };\n\n// Accepted log levels for runtime validation\nconst VALID_LOG_LEVELS = new Set<string>(['error', 'warn', 'info', 'debug', 'trace']);\n\nconst DEFAULT_CONFIG: Partial<TelemetryCollectorConfig> = {\n samplingRate: 1,\n maxBufferSize: 5,\n // Production endpoint: https://clerk-telemetry.com\n // Staging endpoint: https://staging.clerk-telemetry.com\n // Local: http://localhost:8787\n endpoint: 'https://clerk-telemetry.com',\n};\n\nexport class TelemetryCollector implements TelemetryCollectorInterface {\n #config: Required<TelemetryCollectorConfig>;\n #eventThrottler: TelemetryEventThrottler;\n #metadata: TelemetryMetadata = {} as TelemetryMetadata;\n #buffer: TelemetryBufferItem[] = [];\n #pendingFlush: number | ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: TelemetryCollectorOptions) {\n this.#config = {\n maxBufferSize: options.maxBufferSize ?? DEFAULT_CONFIG.maxBufferSize,\n samplingRate: options.samplingRate ?? DEFAULT_CONFIG.samplingRate,\n perEventSampling: options.perEventSampling ?? true,\n disabled: options.disabled ?? false,\n debug: options.debug ?? false,\n endpoint: DEFAULT_CONFIG.endpoint,\n } as Required<TelemetryCollectorConfig>;\n\n if (!options.clerkVersion && typeof window === 'undefined') {\n // N/A in a server environment\n this.#metadata.clerkVersion = '';\n } else {\n this.#metadata.clerkVersion = options.clerkVersion ?? '';\n }\n\n // We will try to grab the SDK data lazily when an event is triggered, so it should always be defined once the event is sent.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#metadata.sdk = options.sdk!;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#metadata.sdkVersion = options.sdkVersion!;\n\n this.#metadata.publishableKey = options.publishableKey ?? '';\n\n const parsedKey = parsePublishableKey(options.publishableKey);\n if (parsedKey) {\n this.#metadata.instanceType = parsedKey.instanceType;\n }\n\n if (options.secretKey) {\n // Only send the first 16 characters of the secret key to to avoid sending the full key. We can still query against the partial key.\n this.#metadata.secretKey = options.secretKey.substring(0, 16);\n }\n\n // Use LocalStorage cache in browsers where it's supported, otherwise fall back to in-memory cache\n const cache = LocalStorageThrottlerCache.isSupported()\n ? new LocalStorageThrottlerCache()\n : new InMemoryThrottlerCache();\n this.#eventThrottler = new TelemetryEventThrottler(cache);\n\n // Surface the one-time telemetry disclosure at runtime instead of via a postinstall script.\n // Gated on `isEnabled` so users who opted out (or are not on a development instance) are not\n // shown a notice for collection that will never happen.\n maybeShowTelemetryNotice({ skip: !this.isEnabled });\n }\n\n get isEnabled(): boolean {\n if (this.#metadata.instanceType !== 'development') {\n return false;\n }\n\n // In browser or client environments, we most likely pass the disabled option to the collector, but in environments\n // where environment variables are available we also check for `CLERK_TELEMETRY_DISABLED`.\n if (\n this.#config.disabled ||\n (typeof process !== 'undefined' && process.env && isTruthy(process.env.CLERK_TELEMETRY_DISABLED))\n ) {\n return false;\n }\n\n // navigator.webdriver is a property generally set by headless browsers that are running in an automated testing environment.\n // Data from these environments is not meaningful for us and has the potential to produce a large volume of events, so we disable\n // collection in this case. (ref: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/webdriver)\n if (typeof window !== 'undefined' && !!window?.navigator?.webdriver) {\n return false;\n }\n\n return true;\n }\n\n get isDebug(): boolean {\n return (\n this.#config.debug ||\n (typeof process !== 'undefined' && process.env && isTruthy(process.env.CLERK_TELEMETRY_DEBUG))\n );\n }\n\n record(event: TelemetryEventRaw): void {\n try {\n const preparedPayload = this.#preparePayload(event.event, event.payload);\n\n this.#logEvent(preparedPayload.event, preparedPayload);\n\n if (!this.#shouldRecord(preparedPayload, event.eventSamplingRate)) {\n return;\n }\n\n this.#buffer.push({ kind: 'event', value: preparedPayload });\n\n this.#scheduleFlush();\n } catch (error) {\n console.error('[clerk/telemetry] Error recording telemetry event', error);\n }\n }\n\n /**\n * Records a telemetry log entry if logging is enabled and not in debug mode.\n *\n * @param entry - The telemetry log entry to record.\n */\n recordLog(entry: TelemetryLogEntry): void {\n try {\n if (!this.#shouldRecordLog(entry)) {\n return;\n }\n\n const levelIsValid = typeof entry?.level === 'string' && VALID_LOG_LEVELS.has(entry.level);\n const messageIsValid = typeof entry?.message === 'string' && entry.message.trim().length > 0;\n\n let normalizedTimestamp: Date | null = null;\n const timestampInput: unknown = (entry as unknown as { timestamp?: unknown })?.timestamp;\n if (typeof timestampInput === 'number' || typeof timestampInput === 'string') {\n const candidate = new Date(timestampInput);\n if (!Number.isNaN(candidate.getTime())) {\n normalizedTimestamp = candidate;\n }\n }\n\n if (!levelIsValid || !messageIsValid || normalizedTimestamp === null) {\n if (this.isDebug && typeof console !== 'undefined') {\n console.warn('[clerk/telemetry] Dropping invalid telemetry log entry', {\n levelIsValid,\n messageIsValid,\n timestampIsValid: normalizedTimestamp !== null,\n });\n }\n return;\n }\n\n const sdkMetadata = this.#getSDKMetadata();\n\n const logData: TelemetryLogData = {\n sdk: sdkMetadata.name,\n sdkv: sdkMetadata.version,\n cv: this.#metadata.clerkVersion ?? '',\n lvl: entry.level,\n msg: entry.message,\n ts: normalizedTimestamp.toISOString(),\n pk: this.#metadata.publishableKey || null,\n payload: this.#sanitizeContext(entry.context),\n };\n\n this.#buffer.push({ kind: 'log', value: logData });\n\n this.#scheduleFlush();\n } catch (error) {\n console.error('[clerk/telemetry] Error recording telemetry log entry', error);\n }\n }\n\n #shouldRecord(preparedPayload: TelemetryEvent, eventSamplingRate?: number) {\n return this.isEnabled && !this.isDebug && this.#shouldBeSampled(preparedPayload, eventSamplingRate);\n }\n\n #shouldRecordLog(_entry: TelemetryLogEntry): boolean {\n // Always allow logs from debug logger to be sent. Debug logger itself is already gated elsewhere.\n return true;\n }\n\n #shouldBeSampled(preparedPayload: TelemetryEvent, eventSamplingRate?: number) {\n const randomSeed = Math.random();\n\n const toBeSampled =\n randomSeed <= this.#config.samplingRate &&\n (this.#config.perEventSampling === false ||\n typeof eventSamplingRate === 'undefined' ||\n randomSeed <= eventSamplingRate);\n\n if (!toBeSampled) {\n return false;\n }\n\n return !this.#eventThrottler.isEventThrottled(preparedPayload);\n }\n\n #scheduleFlush(): void {\n // On the server, we want to flush immediately as we have less guarantees about the lifecycle of the process\n if (typeof window === 'undefined') {\n this.#flush();\n return;\n }\n const isBufferFull = this.#buffer.length >= this.#config.maxBufferSize;\n if (isBufferFull) {\n // If the buffer is full, flush immediately to make sure we minimize the chance of event loss.\n // Cancel any pending flushes as we're going to flush immediately\n if (this.#pendingFlush) {\n if (typeof cancelIdleCallback !== 'undefined') {\n cancelIdleCallback(Number(this.#pendingFlush));\n } else {\n clearTimeout(Number(this.#pendingFlush));\n }\n }\n this.#flush();\n return;\n }\n\n // If we have a pending flush, do nothing\n if (this.#pendingFlush) {\n return;\n }\n\n if ('requestIdleCallback' in window) {\n this.#pendingFlush = requestIdleCallback(() => {\n this.#flush();\n this.#pendingFlush = null;\n });\n } else {\n // This is not an ideal solution, but it at least waits until the next tick\n this.#pendingFlush = setTimeout(() => {\n this.#flush();\n this.#pendingFlush = null;\n }, 0);\n }\n }\n\n #flush(): void {\n // Capture the current buffer and clear it immediately to avoid closure references\n const itemsToSend = [...this.#buffer];\n this.#buffer = [];\n\n this.#pendingFlush = null;\n\n if (itemsToSend.length === 0) {\n return;\n }\n\n const eventsToSend = itemsToSend\n .filter(item => item.kind === 'event')\n .map(item => (item as { kind: 'event'; value: TelemetryEvent }).value);\n\n const logsToSend = itemsToSend\n .filter(item => item.kind === 'log')\n .map(item => (item as { kind: 'log'; value: TelemetryLogData }).value);\n\n if (eventsToSend.length > 0) {\n const eventsUrl = new URL('/v1/event', this.#config.endpoint);\n fetch(eventsUrl, {\n headers: {\n 'Content-Type': 'application/json',\n },\n keepalive: true,\n method: 'POST',\n // TODO: We send an array here with that idea that we can eventually send multiple events.\n body: JSON.stringify({ events: eventsToSend }),\n }).catch(() => void 0);\n }\n\n if (logsToSend.length > 0) {\n const logsUrl = new URL('/v1/logs', this.#config.endpoint);\n fetch(logsUrl, {\n headers: {\n 'Content-Type': 'application/json',\n },\n keepalive: true,\n method: 'POST',\n body: JSON.stringify({ logs: logsToSend }),\n }).catch(() => void 0);\n }\n }\n\n /**\n * If running in debug mode, log the event and its payload to the console.\n */\n #logEvent(event: TelemetryEvent['event'], payload: Record<string, any>) {\n if (!this.isDebug) {\n return;\n }\n\n if (typeof console.groupCollapsed !== 'undefined') {\n console.groupCollapsed('[clerk/telemetry]', event);\n console.log(payload);\n console.groupEnd();\n } else {\n console.log('[clerk/telemetry]', event, payload);\n }\n }\n\n /**\n * If in browser, attempt to lazily grab the SDK metadata from the Clerk singleton, otherwise fallback to the initially passed in values.\n *\n * This is necessary because the sdkMetadata can be set by the host SDK after the TelemetryCollector is instantiated.\n */\n #getSDKMetadata() {\n const sdkMetadata = {\n name: this.#metadata.sdk,\n version: this.#metadata.sdkVersion,\n };\n\n if (typeof window !== 'undefined') {\n const windowWithClerk = window as WindowWithClerk;\n\n if (windowWithClerk.Clerk) {\n const windowClerk = windowWithClerk.Clerk;\n\n if (isWindowClerkWithMetadata(windowClerk) && windowClerk.constructor.sdkMetadata) {\n const { name, version } = windowClerk.constructor.sdkMetadata;\n\n if (name !== undefined) {\n sdkMetadata.name = name;\n }\n if (version !== undefined) {\n sdkMetadata.version = version;\n }\n }\n }\n }\n\n return sdkMetadata;\n }\n\n /**\n * Append relevant metadata from the Clerk singleton to the event payload.\n */\n #preparePayload(event: TelemetryEvent['event'], payload: TelemetryEvent['payload']): TelemetryEvent {\n const sdkMetadata = this.#getSDKMetadata();\n\n return {\n event,\n cv: this.#metadata.clerkVersion ?? '',\n it: this.#metadata.instanceType ?? '',\n sdk: sdkMetadata.name,\n sdkv: sdkMetadata.version,\n ...(this.#metadata.publishableKey ? { pk: this.#metadata.publishableKey } : {}),\n ...(this.#metadata.secretKey ? { sk: this.#metadata.secretKey } : {}),\n payload,\n };\n }\n\n /**\n * Best-effort sanitization of the context payload. Returns a plain object with JSON-serializable\n * values or null when the input is missing or not serializable. Arrays are not accepted.\n */\n #sanitizeContext(context: unknown): Record<string, unknown> | null {\n if (context === null || typeof context === 'undefined') {\n return null;\n }\n if (typeof context !== 'object') {\n return null;\n }\n try {\n const cleaned = JSON.parse(JSON.stringify(context));\n if (cleaned && typeof cleaned === 'object' && !Array.isArray(cleaned)) {\n return cleaned as Record<string, unknown>;\n }\n return null;\n } catch {\n return null;\n }\n }\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_COMPONENT_MOUNTED = 'COMPONENT_MOUNTED';\nconst EVENT_COMPONENT_OPENED = 'COMPONENT_OPENED';\nconst EVENT_SAMPLING_RATE = 0.1;\n\n/** Increase sampling for high-signal auth components on mount. */\nconst AUTH_COMPONENTS = new Set<string>(['SignIn', 'SignUp']);\n\n/**\n * Returns the per-event sampling rate for component-mounted telemetry events.\n * Uses a higher rate for SignIn/SignUp to improve signal quality.\n *\n * @internal\n */\nfunction getComponentMountedSamplingRate(component: string): number {\n return AUTH_COMPONENTS.has(component) ? 1 : EVENT_SAMPLING_RATE;\n}\n\ntype ComponentMountedBase = {\n component: string;\n};\n\ntype EventPrebuiltComponent = ComponentMountedBase & {\n appearanceProp: boolean;\n elements: boolean;\n variables: boolean;\n theme: boolean;\n};\n\ntype EventComponentMounted = ComponentMountedBase & TelemetryEventRaw['payload'];\n\n/**\n * Factory for prebuilt component telemetry events.\n *\n * @internal\n */\nfunction createPrebuiltComponentEvent(event: typeof EVENT_COMPONENT_MOUNTED | typeof EVENT_COMPONENT_OPENED) {\n return function (\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n ): TelemetryEventRaw<EventPrebuiltComponent> {\n return {\n event,\n eventSamplingRate:\n event === EVENT_COMPONENT_MOUNTED ? getComponentMountedSamplingRate(component) : EVENT_SAMPLING_RATE,\n payload: {\n component,\n appearanceProp: Boolean(props?.appearance),\n theme: Boolean(props?.appearance?.theme),\n elements: Boolean(props?.appearance?.elements),\n variables: Boolean(props?.appearance?.variables),\n ...additionalPayload,\n },\n };\n };\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a prebuilt (AIO) component is mounted.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Will be filtered to a known list of props.\n * @param additionalPayload - Additional data to send with the event.\n * @example\n * telemetry.record(eventPrebuiltComponentMounted('SignUp', props));\n */\nexport function eventPrebuiltComponentMounted(\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n): TelemetryEventRaw<EventPrebuiltComponent> {\n return createPrebuiltComponentEvent(EVENT_COMPONENT_MOUNTED)(component, props, additionalPayload);\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a prebuilt (AIO) component is opened as a modal.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Will be filtered to a known list of props.\n * @param additionalPayload - Additional data to send with the event.\n * @example\n * telemetry.record(eventPrebuiltComponentOpened('GoogleOneTap', props));\n */\nexport function eventPrebuiltComponentOpened(\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n): TelemetryEventRaw<EventPrebuiltComponent> {\n return createPrebuiltComponentEvent(EVENT_COMPONENT_OPENED)(component, props, additionalPayload);\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a component is mounted. Use `eventPrebuiltComponentMounted` for prebuilt components.\n *\n * **Caution:** Filter the `props` you pass to this function to avoid sending too much data.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Ideally you only pass a handful of props here.\n * @example\n * telemetry.record(eventComponentMounted('SignUp', props));\n */\nexport function eventComponentMounted(\n component: string,\n props: TelemetryEventRaw['payload'] = {},\n): TelemetryEventRaw<EventComponentMounted> {\n return {\n event: EVENT_COMPONENT_MOUNTED,\n eventSamplingRate: getComponentMountedSamplingRate(component),\n payload: {\n component,\n ...props,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_FLOW_STEP_MOUNTED = 'FLOW_STEP_MOUNTED';\nconst EVENT_SAMPLING_RATE = 1;\n\ntype EventFlowStepMounted = {\n /** The flow the step belongs to, e.g. `configureSSO` (mirrors `Flow.Root`'s `flow`). */\n flow: string;\n /** The step/part that mounted, e.g. `verify-domain` */\n step: string;\n /** Free-form, flow-specific metadata supplied by the caller (e.g. `timestamp`, `connectionStatus`). */\n metadata: TelemetryEventRaw['payload'];\n} & TelemetryEventRaw['payload'];\n\n/**\n * Fires an event from a part of a multi-step flow.\n *\n * @param flow - The flow identifier (matches `Flow.Root`'s `flow`).\n * @param step - The step/part that mounted.\n * @param metadata - Flow-specific metadata sent under `payload.metadata`.\n * @param eventSamplingRate - Override the default full-capture sampling rate.\n * @example\n * telemetry.record(eventFlowStepMounted('configureSSO', 'verify-domain', { timestamp: new Date().toISOString(), connectionStatus: 'unconfigured' }));\n */\nexport function eventFlowStepMounted(\n flow: string,\n step: string,\n metadata: TelemetryEventRaw['payload'] = {},\n eventSamplingRate: number = EVENT_SAMPLING_RATE,\n): TelemetryEventRaw<EventFlowStepMounted> {\n return {\n event: EVENT_FLOW_STEP_MOUNTED,\n eventSamplingRate,\n payload: {\n flow,\n step,\n metadata,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_METHOD_CALLED = 'METHOD_CALLED';\nconst EVENT_SAMPLING_RATE = 0.1;\n\ntype EventMethodCalled = {\n method: string;\n} & Record<string, string | number | boolean>;\n\n/**\n * Fired when a helper method is called from a Clerk SDK.\n */\nexport function eventMethodCalled(\n method: string,\n payload?: Record<string, unknown>,\n): TelemetryEventRaw<EventMethodCalled> {\n return {\n event: EVENT_METHOD_CALLED,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload: {\n method,\n ...payload,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_FRAMEWORK_METADATA = 'FRAMEWORK_METADATA';\nconst EVENT_SAMPLING_RATE = 0.1;\n\ntype EventFrameworkMetadata = Record<string, string | number | boolean>;\n\n/**\n * Fired when a helper method is called from a Clerk SDK.\n */\nexport function eventFrameworkMetadata(payload: EventFrameworkMetadata): TelemetryEventRaw<EventFrameworkMetadata> {\n return {\n event: EVENT_FRAMEWORK_METADATA,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload,\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nexport const EVENT_THEME_USAGE = 'THEME_USAGE';\nexport const EVENT_SAMPLING_RATE = 1;\n\ntype EventThemeUsage = {\n /**\n * The name of the theme being used (e.g., \"shadcn\", \"neobrutalism\", etc.).\n */\n themeName?: string;\n};\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for tracking theme usage in ClerkProvider.\n *\n * @param appearance - The appearance prop from ClerkProvider.\n * @example\n * telemetry.record(eventThemeUsage(appearance));\n */\nexport function eventThemeUsage(appearance?: any): TelemetryEventRaw<EventThemeUsage> {\n const payload = analyzeThemeUsage(appearance);\n\n return {\n event: EVENT_THEME_USAGE,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload,\n };\n}\n\n/**\n * Analyzes the appearance prop to extract theme usage information for telemetry.\n *\n * @internal\n */\nfunction analyzeThemeUsage(appearance?: any): EventThemeUsage {\n if (!appearance || typeof appearance !== 'object') {\n return {};\n }\n\n const themeProperty = appearance.theme;\n\n if (!themeProperty) {\n return {};\n }\n\n let themeName: string | undefined;\n\n if (Array.isArray(themeProperty)) {\n // Look for the first identifiable theme name in the array\n for (const theme of themeProperty) {\n const name = extractThemeName(theme);\n if (name) {\n themeName = name;\n break;\n }\n }\n } else {\n themeName = extractThemeName(themeProperty);\n }\n\n return { themeName };\n}\n\n/**\n * Extracts the theme name from a theme object.\n *\n * @internal\n */\nfunction extractThemeName(theme: any): string | undefined {\n if (typeof theme === 'string') {\n return theme;\n }\n\n if (typeof theme === 'object' && theme !== null) {\n // Check for explicit theme name\n if ('name' in theme && typeof theme.name === 'string') {\n return theme.name;\n }\n }\n\n return undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"telemetry-DZp9OI1j.js","names":["automatedEnvironmentVariables","isTruthy","#cache","#generateKey","#cacheTtl","#getCache","#storageKey","#maxSize","#config","#metadata","parsePublishableKey","#eventThrottler","isTruthy","#preparePayload","#logEvent","#shouldRecord","#buffer","#scheduleFlush","#shouldRecordLog","#getSDKMetadata","#sanitizeContext","#shouldBeSampled","#flush","#pendingFlush","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE","EVENT_SAMPLING_RATE"],"sources":["../../src/telemetry/notice.ts","../../src/telemetry/throttler.ts","../../src/telemetry/collector.ts","../../src/telemetry/events/component-mounted.ts","../../src/telemetry/events/flow-step.ts","../../src/telemetry/events/method-called.ts","../../src/telemetry/events/framework-metadata.ts","../../src/telemetry/events/theme-usage.ts"],"sourcesContent":["/**\n * One-time runtime disclosure that Clerk collects telemetry from development instances.\n *\n * Replaces the previous `postinstall` script. Disclosure is intentionally surfaced\n * only on Node (server-side) so the noise profile matches the original postinstall\n * (terminal-only, dev-eyes-only). Browser consoles are not used because they are\n * frequently observed by non-developers (QA, screenshots, demos), and adding another\n * console warning is a common source of customer complaints.\n *\n * Known gap: pure browser-only setups with no server-side Clerk runtime (e.g. a Vite\n * SPA using `@clerk/clerk-react` or `@clerk/clerk-js` directly, without any Node/Edge\n * backend that imports `@clerk/shared`) will never hit this code path and therefore\n * see no in-band disclosure. This is an accepted trade-off: the original postinstall\n * already fired only once at install time and was easily missed, so the practical\n * delta is small. Authoritative disclosure for those setups lives in the Clerk\n * telemetry docs (https://clerk.com/docs/telemetry). Opt-out continues to work the\n * same way (`telemetry={false}` on `<ClerkProvider>` or the framework-specific\n * `*_CLERK_TELEMETRY_DISABLED` env var).\n *\n * Persistence is in-process via a `globalThis` Symbol, which survives Next.js HMR\n * module reloads. No filesystem access, no `node:` imports, no dynamic-code APIs, so\n * the module remains safe to bundle for Edge Runtime, Workers, and any browser path.\n *\n * All work is wrapped in try/catch. Failure to display the notice must never affect\n * the SDK.\n */\n\nimport { isTruthy } from '../underscore';\nimport { automatedEnvironmentVariables } from '../utils/runtimeEnvironment';\n\nconst PROCESS_FLAG = Symbol.for('@clerk/shared.telemetryNoticeShown');\n\nconst NOTICE_LINES = [\n 'Attention: Clerk collects telemetry data from its SDKs when connected to development instances.',\n \"The data collected is used to inform Clerk's product roadmap.\",\n 'To learn more, including how to opt-out from the telemetry program, visit: https://clerk.com/docs/telemetry.',\n];\n\nfunction isServerRuntime(): boolean {\n // Skip in browsers.\n if (typeof window !== 'undefined') {\n return false;\n }\n // Skip in Next.js Edge Runtime, which exposes a global `EdgeRuntime` marker. We detect via\n // this marker (rather than checking `process.versions`) because the Edge Runtime build-time\n // analyzer flags any reachable read of `process.versions` even when it sits behind a guard.\n if (typeof (globalThis as { EdgeRuntime?: string }).EdgeRuntime !== 'undefined') {\n return false;\n }\n return true;\n}\n\n// Server-only notice: read process.env directly rather than going through\n// getEnvVariable(), which would pull the multi-runtime env resolver into the\n// clerk.browser.js bundle (it ships there via TelemetryCollector). We reuse the\n// shared CI env-var list so the set of detected providers stays in one place.\nfunction isCI(): boolean {\n if (typeof process === 'undefined' || !process.env) {\n return false;\n }\n return automatedEnvironmentVariables.some(name => isTruthy(process.env[name]));\n}\n\nfunction hasSeen(): boolean {\n return Boolean((globalThis as Record<symbol, unknown>)[PROCESS_FLAG]);\n}\n\nfunction markSeen(): void {\n (globalThis as Record<symbol, unknown>)[PROCESS_FLAG] = true;\n}\n\nfunction printNotice(): void {\n if (typeof console === 'undefined' || typeof console.log !== 'function') {\n return;\n }\n for (const line of NOTICE_LINES) {\n console.log(line);\n }\n console.log('');\n}\n\nexport type MaybeShowTelemetryNoticeOptions = {\n /**\n * Skip the notice entirely. Used when the caller has already determined that no\n * telemetry will be sent (e.g. opt-out, non-development instance), in which case\n * there is nothing to disclose.\n */\n skip?: boolean;\n};\n\n/**\n * Display the one-time telemetry disclosure on server runtimes if it has not already been\n * shown in this process. Browser and Edge Runtime callers are silently skipped. Never throws.\n */\nexport function maybeShowTelemetryNotice(options: MaybeShowTelemetryNoticeOptions = {}): void {\n if (options.skip) {\n return;\n }\n try {\n if (!isServerRuntime()) {\n return;\n }\n if (isCI()) {\n return;\n }\n if (hasSeen()) {\n return;\n }\n printNotice();\n markSeen();\n } catch {\n // never let disclosure break the SDK\n }\n}\n\n/**\n * Test-only: clear the in-process flag so the next call re-runs the gating logic.\n *\n * @internal\n */\nexport function __resetTelemetryNoticeForTests(): void {\n delete (globalThis as Record<symbol, unknown>)[PROCESS_FLAG];\n}\n","import type { TelemetryEvent } from '../types';\n\ntype TtlInMilliseconds = number;\n\nconst DEFAULT_CACHE_TTL_MS = 86400000; // 24 hours\n\n/**\n * Interface for cache storage used by the telemetry throttler.\n * Implementations can use localStorage, in-memory storage, or any other storage mechanism.\n */\nexport interface ThrottlerCache {\n getItem(key: string): TtlInMilliseconds | undefined;\n setItem(key: string, value: TtlInMilliseconds): void;\n removeItem(key: string): void;\n}\n\n/**\n * Manages throttling for telemetry events using a configurable cache implementation\n * to mitigate event flooding in frequently executed code paths.\n */\nexport class TelemetryEventThrottler {\n #cache: ThrottlerCache;\n #cacheTtl = DEFAULT_CACHE_TTL_MS;\n\n constructor(cache: ThrottlerCache) {\n this.#cache = cache;\n }\n\n isEventThrottled(payload: TelemetryEvent): boolean {\n const now = Date.now();\n const key = this.#generateKey(payload);\n const entry = this.#cache.getItem(key);\n\n if (!entry) {\n this.#cache.setItem(key, now);\n return false;\n }\n\n const shouldInvalidate = now - entry > this.#cacheTtl;\n if (shouldInvalidate) {\n this.#cache.setItem(key, now);\n return false;\n }\n\n return true;\n }\n\n /**\n * Generates a consistent unique key for telemetry events by sorting payload properties.\n * This ensures that payloads with identical content in different orders produce the same key.\n */\n #generateKey(event: TelemetryEvent): string {\n const { sk: _sk, pk: _pk, payload, ...rest } = event;\n\n const sanitizedEvent: Omit<TelemetryEvent, 'sk' | 'pk' | 'payload'> & TelemetryEvent['payload'] = {\n ...payload,\n ...rest,\n };\n\n return JSON.stringify(\n Object.keys({\n ...payload,\n ...rest,\n })\n .sort()\n .map(key => sanitizedEvent[key]),\n );\n }\n}\n\n/**\n * LocalStorage-based cache implementation for browser environments.\n */\nexport class LocalStorageThrottlerCache implements ThrottlerCache {\n #storageKey = 'clerk_telemetry_throttler';\n\n getItem(key: string): TtlInMilliseconds | undefined {\n return this.#getCache()[key];\n }\n\n setItem(key: string, value: TtlInMilliseconds): void {\n try {\n const cache = this.#getCache();\n cache[key] = value;\n localStorage.setItem(this.#storageKey, JSON.stringify(cache));\n } catch (err: unknown) {\n const isQuotaExceededError =\n err instanceof DOMException &&\n // Check error names for different browsers\n (err.name === 'QuotaExceededError' || err.name === 'NS_ERROR_DOM_QUOTA_REACHED');\n\n if (isQuotaExceededError && localStorage.length > 0) {\n // Clear our cache if quota exceeded\n localStorage.removeItem(this.#storageKey);\n }\n }\n }\n\n removeItem(key: string): void {\n try {\n const cache = this.#getCache();\n delete cache[key];\n localStorage.setItem(this.#storageKey, JSON.stringify(cache));\n } catch {\n // Silently fail if we can't remove\n }\n }\n\n #getCache(): Record<string, TtlInMilliseconds> {\n try {\n const cacheString = localStorage.getItem(this.#storageKey);\n if (!cacheString) {\n return {};\n }\n return JSON.parse(cacheString);\n } catch {\n return {};\n }\n }\n\n static isSupported(): boolean {\n return typeof window !== 'undefined' && !!window.localStorage;\n }\n}\n\n/**\n * In-memory cache implementation for non-browser environments (e.g., React Native).\n */\nexport class InMemoryThrottlerCache implements ThrottlerCache {\n #cache: Map<string, TtlInMilliseconds> = new Map();\n #maxSize = 10000; // Defensive limit to prevent memory issues\n\n getItem(key: string): TtlInMilliseconds | undefined {\n // Defensive: clear cache if it gets too large\n if (this.#cache.size > this.#maxSize) {\n this.#cache.clear();\n return undefined;\n }\n\n return this.#cache.get(key);\n }\n\n setItem(key: string, value: TtlInMilliseconds): void {\n this.#cache.set(key, value);\n }\n\n removeItem(key: string): void {\n this.#cache.delete(key);\n }\n}\n","/**\n * The `TelemetryCollector` class handles collection of telemetry events from Clerk SDKs. Telemetry is opt-out and can be disabled by setting a CLERK_TELEMETRY_DISABLED environment variable.\n * The `ClerkProvider` also accepts a `telemetry` prop that will be passed to the collector during initialization:.\n *\n * ```jsx\n * <ClerkProvider telemetry={false}>\n * ...\n * </ClerkProvider>\n * ```\n *\n * For more information, please see the telemetry documentation page: https://clerk.com/docs/telemetry.\n */\nimport { parsePublishableKey } from '../keys';\nimport type {\n InstanceType,\n SDKMetadata,\n TelemetryCollector as TelemetryCollectorInterface,\n TelemetryEvent,\n TelemetryEventRaw,\n TelemetryLogEntry,\n} from '../types';\nimport { isTruthy } from '../underscore';\nimport { maybeShowTelemetryNotice } from './notice';\nimport { InMemoryThrottlerCache, LocalStorageThrottlerCache, TelemetryEventThrottler } from './throttler';\nimport type { TelemetryCollectorOptions } from './types';\n\n/**\n * Local interface for window.Clerk to avoid global type pollution.\n * This is only used within this module and doesn't affect other packages.\n */\ninterface WindowWithClerk extends Window {\n Clerk?: {\n constructor?: {\n sdkMetadata?: SDKMetadata;\n };\n };\n}\n\n/**\n * Type guard to check if window.Clerk exists and has the expected structure.\n */\nfunction isWindowClerkWithMetadata(clerk: unknown): clerk is { constructor: { sdkMetadata?: SDKMetadata } } {\n return (\n typeof clerk === 'object' && clerk !== null && 'constructor' in clerk && typeof clerk.constructor === 'function'\n );\n}\n\ntype TelemetryCollectorConfig = Pick<\n TelemetryCollectorOptions,\n 'samplingRate' | 'disabled' | 'debug' | 'maxBufferSize' | 'perEventSampling'\n> & {\n endpoint: string;\n};\n\ntype TelemetryMetadata = Required<\n Pick<TelemetryCollectorOptions, 'clerkVersion' | 'sdk' | 'sdkVersion' | 'publishableKey' | 'secretKey'>\n> & {\n /**\n * The instance type, derived from the provided publishableKey.\n */\n instanceType: InstanceType;\n};\n\n/**\n * Structure of log data sent to the telemetry endpoint.\n */\ntype TelemetryLogData = {\n /** Service that generated the log. */\n sdk: string;\n /** The version of the SDK where the event originated from. */\n sdkv: string;\n /** The version of Clerk where the event originated from. */\n cv: string;\n /** Log level (info, warn, error, debug, etc.). */\n lvl: TelemetryLogEntry['level'];\n /** Log message. */\n msg: string;\n /** Instance ID - optional. */\n iid?: string;\n /** Timestamp when log was generated. */\n ts: string;\n /** Primary key. */\n pk: string | null;\n /** Additional payload for the log. */\n payload: Record<string, unknown> | null;\n};\n\ntype TelemetryBufferItem = { kind: 'event'; value: TelemetryEvent } | { kind: 'log'; value: TelemetryLogData };\n\n// Accepted log levels for runtime validation\nconst VALID_LOG_LEVELS = new Set<string>(['error', 'warn', 'info', 'debug', 'trace']);\n\nconst DEFAULT_CONFIG: Partial<TelemetryCollectorConfig> = {\n samplingRate: 1,\n maxBufferSize: 5,\n // Production endpoint: https://clerk-telemetry.com\n // Staging endpoint: https://staging.clerk-telemetry.com\n // Local: http://localhost:8787\n endpoint: 'https://clerk-telemetry.com',\n};\n\nexport class TelemetryCollector implements TelemetryCollectorInterface {\n #config: Required<TelemetryCollectorConfig>;\n #eventThrottler: TelemetryEventThrottler;\n #metadata: TelemetryMetadata = {} as TelemetryMetadata;\n #buffer: TelemetryBufferItem[] = [];\n #pendingFlush: number | ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: TelemetryCollectorOptions) {\n this.#config = {\n maxBufferSize: options.maxBufferSize ?? DEFAULT_CONFIG.maxBufferSize,\n samplingRate: options.samplingRate ?? DEFAULT_CONFIG.samplingRate,\n perEventSampling: options.perEventSampling ?? true,\n disabled: options.disabled ?? false,\n debug: options.debug ?? false,\n endpoint: DEFAULT_CONFIG.endpoint,\n } as Required<TelemetryCollectorConfig>;\n\n if (!options.clerkVersion && typeof window === 'undefined') {\n // N/A in a server environment\n this.#metadata.clerkVersion = '';\n } else {\n this.#metadata.clerkVersion = options.clerkVersion ?? '';\n }\n\n // We will try to grab the SDK data lazily when an event is triggered, so it should always be defined once the event is sent.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#metadata.sdk = options.sdk!;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#metadata.sdkVersion = options.sdkVersion!;\n\n this.#metadata.publishableKey = options.publishableKey ?? '';\n\n const parsedKey = parsePublishableKey(options.publishableKey);\n if (parsedKey) {\n this.#metadata.instanceType = parsedKey.instanceType;\n }\n\n if (options.secretKey) {\n // Only send the first 16 characters of the secret key to to avoid sending the full key. We can still query against the partial key.\n this.#metadata.secretKey = options.secretKey.substring(0, 16);\n }\n\n // Use LocalStorage cache in browsers where it's supported, otherwise fall back to in-memory cache\n const cache = LocalStorageThrottlerCache.isSupported()\n ? new LocalStorageThrottlerCache()\n : new InMemoryThrottlerCache();\n this.#eventThrottler = new TelemetryEventThrottler(cache);\n\n // Surface the one-time telemetry disclosure at runtime instead of via a postinstall script.\n // Gated on `isEnabled` so users who opted out (or are not on a development instance) are not\n // shown a notice for collection that will never happen.\n maybeShowTelemetryNotice({ skip: !this.isEnabled });\n }\n\n get isEnabled(): boolean {\n if (this.#metadata.instanceType !== 'development') {\n return false;\n }\n\n // In browser or client environments, we most likely pass the disabled option to the collector, but in environments\n // where environment variables are available we also check for `CLERK_TELEMETRY_DISABLED`.\n if (\n this.#config.disabled ||\n (typeof process !== 'undefined' && process.env && isTruthy(process.env.CLERK_TELEMETRY_DISABLED))\n ) {\n return false;\n }\n\n // navigator.webdriver is a property generally set by headless browsers that are running in an automated testing environment.\n // Data from these environments is not meaningful for us and has the potential to produce a large volume of events, so we disable\n // collection in this case. (ref: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/webdriver)\n if (typeof window !== 'undefined' && !!window?.navigator?.webdriver) {\n return false;\n }\n\n return true;\n }\n\n get isDebug(): boolean {\n return (\n this.#config.debug ||\n (typeof process !== 'undefined' && process.env && isTruthy(process.env.CLERK_TELEMETRY_DEBUG))\n );\n }\n\n record(event: TelemetryEventRaw): void {\n try {\n const preparedPayload = this.#preparePayload(event.event, event.payload);\n\n this.#logEvent(preparedPayload.event, preparedPayload);\n\n if (!this.#shouldRecord(preparedPayload, event.eventSamplingRate)) {\n return;\n }\n\n this.#buffer.push({ kind: 'event', value: preparedPayload });\n\n this.#scheduleFlush();\n } catch (error) {\n console.error('[clerk/telemetry] Error recording telemetry event', error);\n }\n }\n\n /**\n * Records a telemetry log entry if logging is enabled and not in debug mode.\n *\n * @param entry - The telemetry log entry to record.\n */\n recordLog(entry: TelemetryLogEntry): void {\n try {\n if (!this.#shouldRecordLog(entry)) {\n return;\n }\n\n const levelIsValid = typeof entry?.level === 'string' && VALID_LOG_LEVELS.has(entry.level);\n const messageIsValid = typeof entry?.message === 'string' && entry.message.trim().length > 0;\n\n let normalizedTimestamp: Date | null = null;\n const timestampInput: unknown = (entry as unknown as { timestamp?: unknown })?.timestamp;\n if (typeof timestampInput === 'number' || typeof timestampInput === 'string') {\n const candidate = new Date(timestampInput);\n if (!Number.isNaN(candidate.getTime())) {\n normalizedTimestamp = candidate;\n }\n }\n\n if (!levelIsValid || !messageIsValid || normalizedTimestamp === null) {\n if (this.isDebug && typeof console !== 'undefined') {\n console.warn('[clerk/telemetry] Dropping invalid telemetry log entry', {\n levelIsValid,\n messageIsValid,\n timestampIsValid: normalizedTimestamp !== null,\n });\n }\n return;\n }\n\n const sdkMetadata = this.#getSDKMetadata();\n\n const logData: TelemetryLogData = {\n sdk: sdkMetadata.name,\n sdkv: sdkMetadata.version,\n cv: this.#metadata.clerkVersion ?? '',\n lvl: entry.level,\n msg: entry.message,\n ts: normalizedTimestamp.toISOString(),\n pk: this.#metadata.publishableKey || null,\n payload: this.#sanitizeContext(entry.context),\n };\n\n this.#buffer.push({ kind: 'log', value: logData });\n\n this.#scheduleFlush();\n } catch (error) {\n console.error('[clerk/telemetry] Error recording telemetry log entry', error);\n }\n }\n\n #shouldRecord(preparedPayload: TelemetryEvent, eventSamplingRate?: number) {\n return this.isEnabled && !this.isDebug && this.#shouldBeSampled(preparedPayload, eventSamplingRate);\n }\n\n #shouldRecordLog(_entry: TelemetryLogEntry): boolean {\n // Always allow logs from debug logger to be sent. Debug logger itself is already gated elsewhere.\n return true;\n }\n\n #shouldBeSampled(preparedPayload: TelemetryEvent, eventSamplingRate?: number) {\n const randomSeed = Math.random();\n\n const toBeSampled =\n randomSeed <= this.#config.samplingRate &&\n (this.#config.perEventSampling === false ||\n typeof eventSamplingRate === 'undefined' ||\n randomSeed <= eventSamplingRate);\n\n if (!toBeSampled) {\n return false;\n }\n\n return !this.#eventThrottler.isEventThrottled(preparedPayload);\n }\n\n #scheduleFlush(): void {\n // On the server, we want to flush immediately as we have less guarantees about the lifecycle of the process\n if (typeof window === 'undefined') {\n this.#flush();\n return;\n }\n const isBufferFull = this.#buffer.length >= this.#config.maxBufferSize;\n if (isBufferFull) {\n // If the buffer is full, flush immediately to make sure we minimize the chance of event loss.\n // Cancel any pending flushes as we're going to flush immediately\n if (this.#pendingFlush) {\n if (typeof cancelIdleCallback !== 'undefined') {\n cancelIdleCallback(Number(this.#pendingFlush));\n } else {\n clearTimeout(Number(this.#pendingFlush));\n }\n }\n this.#flush();\n return;\n }\n\n // If we have a pending flush, do nothing\n if (this.#pendingFlush) {\n return;\n }\n\n if ('requestIdleCallback' in window) {\n this.#pendingFlush = requestIdleCallback(() => {\n this.#flush();\n this.#pendingFlush = null;\n });\n } else {\n // This is not an ideal solution, but it at least waits until the next tick\n this.#pendingFlush = setTimeout(() => {\n this.#flush();\n this.#pendingFlush = null;\n }, 0);\n }\n }\n\n #flush(): void {\n // Capture the current buffer and clear it immediately to avoid closure references\n const itemsToSend = [...this.#buffer];\n this.#buffer = [];\n\n this.#pendingFlush = null;\n\n if (itemsToSend.length === 0) {\n return;\n }\n\n const eventsToSend = itemsToSend\n .filter(item => item.kind === 'event')\n .map(item => (item as { kind: 'event'; value: TelemetryEvent }).value);\n\n const logsToSend = itemsToSend\n .filter(item => item.kind === 'log')\n .map(item => (item as { kind: 'log'; value: TelemetryLogData }).value);\n\n if (eventsToSend.length > 0) {\n const eventsUrl = new URL('/v1/event', this.#config.endpoint);\n fetch(eventsUrl, {\n headers: {\n 'Content-Type': 'application/json',\n },\n keepalive: true,\n method: 'POST',\n // TODO: We send an array here with that idea that we can eventually send multiple events.\n body: JSON.stringify({ events: eventsToSend }),\n }).catch(() => void 0);\n }\n\n if (logsToSend.length > 0) {\n const logsUrl = new URL('/v1/logs', this.#config.endpoint);\n fetch(logsUrl, {\n headers: {\n 'Content-Type': 'application/json',\n },\n keepalive: true,\n method: 'POST',\n body: JSON.stringify({ logs: logsToSend }),\n }).catch(() => void 0);\n }\n }\n\n /**\n * If running in debug mode, log the event and its payload to the console.\n */\n #logEvent(event: TelemetryEvent['event'], payload: Record<string, any>) {\n if (!this.isDebug) {\n return;\n }\n\n if (typeof console.groupCollapsed !== 'undefined') {\n console.groupCollapsed('[clerk/telemetry]', event);\n console.log(payload);\n console.groupEnd();\n } else {\n console.log('[clerk/telemetry]', event, payload);\n }\n }\n\n /**\n * If in browser, attempt to lazily grab the SDK metadata from the Clerk singleton, otherwise fallback to the initially passed in values.\n *\n * This is necessary because the sdkMetadata can be set by the host SDK after the TelemetryCollector is instantiated.\n */\n #getSDKMetadata() {\n const sdkMetadata = {\n name: this.#metadata.sdk,\n version: this.#metadata.sdkVersion,\n };\n\n if (typeof window !== 'undefined') {\n const windowWithClerk = window as WindowWithClerk;\n\n if (windowWithClerk.Clerk) {\n const windowClerk = windowWithClerk.Clerk;\n\n if (isWindowClerkWithMetadata(windowClerk) && windowClerk.constructor.sdkMetadata) {\n const { name, version } = windowClerk.constructor.sdkMetadata;\n\n if (name !== undefined) {\n sdkMetadata.name = name;\n }\n if (version !== undefined) {\n sdkMetadata.version = version;\n }\n }\n }\n }\n\n return sdkMetadata;\n }\n\n /**\n * Append relevant metadata from the Clerk singleton to the event payload.\n */\n #preparePayload(event: TelemetryEvent['event'], payload: TelemetryEvent['payload']): TelemetryEvent {\n const sdkMetadata = this.#getSDKMetadata();\n\n return {\n event,\n cv: this.#metadata.clerkVersion ?? '',\n it: this.#metadata.instanceType ?? '',\n sdk: sdkMetadata.name,\n sdkv: sdkMetadata.version,\n ...(this.#metadata.publishableKey ? { pk: this.#metadata.publishableKey } : {}),\n ...(this.#metadata.secretKey ? { sk: this.#metadata.secretKey } : {}),\n payload,\n };\n }\n\n /**\n * Best-effort sanitization of the context payload. Returns a plain object with JSON-serializable\n * values or null when the input is missing or not serializable. Arrays are not accepted.\n */\n #sanitizeContext(context: unknown): Record<string, unknown> | null {\n if (context === null || typeof context === 'undefined') {\n return null;\n }\n if (typeof context !== 'object') {\n return null;\n }\n try {\n const cleaned = JSON.parse(JSON.stringify(context));\n if (cleaned && typeof cleaned === 'object' && !Array.isArray(cleaned)) {\n return cleaned as Record<string, unknown>;\n }\n return null;\n } catch {\n return null;\n }\n }\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_COMPONENT_MOUNTED = 'COMPONENT_MOUNTED';\nconst EVENT_COMPONENT_OPENED = 'COMPONENT_OPENED';\nconst EVENT_SAMPLING_RATE = 0.1;\n\n/** Increase sampling for high-signal auth components on mount. */\nconst AUTH_COMPONENTS = new Set<string>(['SignIn', 'SignUp']);\n\n/**\n * Returns the per-event sampling rate for component-mounted telemetry events.\n * Uses a higher rate for SignIn/SignUp to improve signal quality.\n *\n * @internal\n */\nfunction getComponentMountedSamplingRate(component: string): number {\n return AUTH_COMPONENTS.has(component) ? 1 : EVENT_SAMPLING_RATE;\n}\n\ntype ComponentMountedBase = {\n component: string;\n};\n\ntype EventPrebuiltComponent = ComponentMountedBase & {\n appearanceProp: boolean;\n elements: boolean;\n variables: boolean;\n theme: boolean;\n};\n\ntype EventComponentMounted = ComponentMountedBase & TelemetryEventRaw['payload'];\n\n/**\n * Factory for prebuilt component telemetry events.\n *\n * @internal\n */\nfunction createPrebuiltComponentEvent(event: typeof EVENT_COMPONENT_MOUNTED | typeof EVENT_COMPONENT_OPENED) {\n return function (\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n ): TelemetryEventRaw<EventPrebuiltComponent> {\n return {\n event,\n eventSamplingRate:\n event === EVENT_COMPONENT_MOUNTED ? getComponentMountedSamplingRate(component) : EVENT_SAMPLING_RATE,\n payload: {\n component,\n appearanceProp: Boolean(props?.appearance),\n theme: Boolean(props?.appearance?.theme),\n elements: Boolean(props?.appearance?.elements),\n variables: Boolean(props?.appearance?.variables),\n ...additionalPayload,\n },\n };\n };\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a prebuilt (AIO) component is mounted.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Will be filtered to a known list of props.\n * @param additionalPayload - Additional data to send with the event.\n * @example\n * telemetry.record(eventPrebuiltComponentMounted('SignUp', props));\n */\nexport function eventPrebuiltComponentMounted(\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n): TelemetryEventRaw<EventPrebuiltComponent> {\n return createPrebuiltComponentEvent(EVENT_COMPONENT_MOUNTED)(component, props, additionalPayload);\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a prebuilt (AIO) component is opened as a modal.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Will be filtered to a known list of props.\n * @param additionalPayload - Additional data to send with the event.\n * @example\n * telemetry.record(eventPrebuiltComponentOpened('GoogleOneTap', props));\n */\nexport function eventPrebuiltComponentOpened(\n component: string,\n props?: Record<string, any>,\n additionalPayload?: TelemetryEventRaw['payload'],\n): TelemetryEventRaw<EventPrebuiltComponent> {\n return createPrebuiltComponentEvent(EVENT_COMPONENT_OPENED)(component, props, additionalPayload);\n}\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for when a component is mounted. Use `eventPrebuiltComponentMounted` for prebuilt components.\n *\n * **Caution:** Filter the `props` you pass to this function to avoid sending too much data.\n *\n * @param component - The name of the component.\n * @param props - The props passed to the component. Ideally you only pass a handful of props here.\n * @example\n * telemetry.record(eventComponentMounted('SignUp', props));\n */\nexport function eventComponentMounted(\n component: string,\n props: TelemetryEventRaw['payload'] = {},\n): TelemetryEventRaw<EventComponentMounted> {\n return {\n event: EVENT_COMPONENT_MOUNTED,\n eventSamplingRate: getComponentMountedSamplingRate(component),\n payload: {\n component,\n ...props,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_FLOW_STEP_MOUNTED = 'FLOW_STEP_MOUNTED';\nconst EVENT_SAMPLING_RATE = 1;\n\ntype EventFlowStepMounted = {\n /** The flow the step belongs to, e.g. `configureSSO` (mirrors `Flow.Root`'s `flow`). */\n flow: string;\n /** The step/part that mounted, e.g. `verify-domain` */\n step: string;\n /** Free-form, flow-specific metadata supplied by the caller (e.g. `timestamp`, `connectionStatus`). */\n metadata: TelemetryEventRaw['payload'];\n} & TelemetryEventRaw['payload'];\n\n/**\n * Fires an event from a part of a multi-step flow.\n *\n * @param flow - The flow identifier (matches `Flow.Root`'s `flow`).\n * @param step - The step/part that mounted.\n * @param metadata - Flow-specific metadata sent under `payload.metadata`.\n * @param eventSamplingRate - Override the default full-capture sampling rate.\n * @example\n * telemetry.record(eventFlowStepMounted('configureSSO', 'verify-domain', { timestamp: new Date().toISOString(), connectionStatus: 'unconfigured' }));\n */\nexport function eventFlowStepMounted(\n flow: string,\n step: string,\n metadata: TelemetryEventRaw['payload'] = {},\n eventSamplingRate: number = EVENT_SAMPLING_RATE,\n): TelemetryEventRaw<EventFlowStepMounted> {\n return {\n event: EVENT_FLOW_STEP_MOUNTED,\n eventSamplingRate,\n payload: {\n flow,\n step,\n metadata,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_METHOD_CALLED = 'METHOD_CALLED';\nconst EVENT_SAMPLING_RATE = 0.1;\n\ntype EventMethodCalled = {\n method: string;\n} & Record<string, string | number | boolean>;\n\n/**\n * Fired when a helper method is called from a Clerk SDK.\n */\nexport function eventMethodCalled(\n method: string,\n payload?: Record<string, unknown>,\n): TelemetryEventRaw<EventMethodCalled> {\n return {\n event: EVENT_METHOD_CALLED,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload: {\n method,\n ...payload,\n },\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nconst EVENT_FRAMEWORK_METADATA = 'FRAMEWORK_METADATA';\nconst EVENT_SAMPLING_RATE = 0.1;\n\ntype EventFrameworkMetadata = Record<string, string | number | boolean>;\n\n/**\n * Fired when a helper method is called from a Clerk SDK.\n */\nexport function eventFrameworkMetadata(payload: EventFrameworkMetadata): TelemetryEventRaw<EventFrameworkMetadata> {\n return {\n event: EVENT_FRAMEWORK_METADATA,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload,\n };\n}\n","import type { TelemetryEventRaw } from '../../types';\n\nexport const EVENT_THEME_USAGE = 'THEME_USAGE';\nexport const EVENT_SAMPLING_RATE = 1;\n\ntype EventThemeUsage = {\n /**\n * The name of the theme being used (e.g., \"shadcn\", \"neobrutalism\", etc.).\n */\n themeName?: string;\n};\n\n/**\n * Helper function for `telemetry.record()`. Create a consistent event object for tracking theme usage in ClerkProvider.\n *\n * @param appearance - The appearance prop from ClerkProvider.\n * @example\n * telemetry.record(eventThemeUsage(appearance));\n */\nexport function eventThemeUsage(appearance?: any): TelemetryEventRaw<EventThemeUsage> {\n const payload = analyzeThemeUsage(appearance);\n\n return {\n event: EVENT_THEME_USAGE,\n eventSamplingRate: EVENT_SAMPLING_RATE,\n payload,\n };\n}\n\n/**\n * Analyzes the appearance prop to extract theme usage information for telemetry.\n *\n * @internal\n */\nfunction analyzeThemeUsage(appearance?: any): EventThemeUsage {\n if (!appearance || typeof appearance !== 'object') {\n return {};\n }\n\n const themeProperty = appearance.theme;\n\n if (!themeProperty) {\n return {};\n }\n\n let themeName: string | undefined;\n\n if (Array.isArray(themeProperty)) {\n // Look for the first identifiable theme name in the array\n for (const theme of themeProperty) {\n const name = extractThemeName(theme);\n if (name) {\n themeName = name;\n break;\n }\n }\n } else {\n themeName = extractThemeName(themeProperty);\n }\n\n return { themeName };\n}\n\n/**\n * Extracts the theme name from a theme object.\n *\n * @internal\n */\nfunction extractThemeName(theme: any): string | undefined {\n if (typeof theme === 'string') {\n return theme;\n }\n\n if (typeof theme === 'object' && theme !== null) {\n // Check for explicit theme name\n if ('name' in theme && typeof theme.name === 'string') {\n return theme.name;\n }\n }\n\n return undefined;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- const require_runtimeEnvironment = require('./runtimeEnvironment-BlRyHkye.js');
1
+ const require_runtimeEnvironment = require('./runtimeEnvironment-DVXDje4R.js');
2
2
 
3
3
  //#region src/utils/allSettled.ts
4
4
  /**
@@ -120,4 +120,4 @@ Object.defineProperty(exports, 'timeLimit', {
120
120
  return timeLimit;
121
121
  }
122
122
  });
123
- //# sourceMappingURL=utils-C4oBdUAp.js.map
123
+ //# sourceMappingURL=utils-B43KYtlc.js.map