@clerk/shared
Version:
Internal package utils used by the Clerk SDKs
1 lines • 43.6 kB
Source Map (JSON)
{"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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"}