@clerk/shared
Version:
Internal package utils used by the Clerk SDKs
1 lines • 22 kB
Source Map (JSON)
{"version":3,"sources":["../src/telemetry/throttler.ts","../src/telemetry/collector.ts","../src/telemetry/events/component-mounted.ts","../src/telemetry/events/framework-metadata.ts"],"sourcesContent":["import type { TelemetryEvent } from '@clerk/types';\n\ntype TtlInMilliseconds = number;\n\nconst DEFAULT_CACHE_TTL_MS = 86400000; // 24 hours\n\n/**\n * Manages throttling for telemetry events using the browser's localStorage to\n * mitigate event flooding in frequently executed code paths.\n */\nexport class TelemetryEventThrottler {\n #storageKey = 'clerk_telemetry_throttler';\n #cacheTtl = DEFAULT_CACHE_TTL_MS;\n\n isEventThrottled(payload: TelemetryEvent): boolean {\n if (!this.#isValidBrowser) {\n return false;\n }\n\n const now = Date.now();\n const key = this.#generateKey(payload);\n const entry = this.#cache?.[key];\n\n if (!entry) {\n const updatedCache = {\n ...this.#cache,\n [key]: now,\n };\n\n localStorage.setItem(this.#storageKey, JSON.stringify(updatedCache));\n }\n\n const shouldInvalidate = entry && now - entry > this.#cacheTtl;\n if (shouldInvalidate) {\n const updatedCache = this.#cache;\n delete updatedCache[key];\n\n localStorage.setItem(this.#storageKey, JSON.stringify(updatedCache));\n }\n\n return !!entry;\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 get #cache(): Record<string, TtlInMilliseconds> | undefined {\n const cacheString = localStorage.getItem(this.#storageKey);\n\n if (!cacheString) {\n return {};\n }\n\n return JSON.parse(cacheString);\n }\n\n /**\n * Checks if the browser's localStorage is supported and writable.\n *\n * If any of these operations fail, it indicates that localStorage is either\n * not supported or not writable (e.g., in cases where the storage is full or\n * the browser is in a privacy mode that restricts localStorage usage).\n */\n get #isValidBrowser(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n\n const storage = window.localStorage;\n if (!storage) {\n return false;\n }\n\n try {\n const testKey = 'test';\n storage.setItem(testKey, testKey);\n storage.removeItem(testKey);\n\n return true;\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 && storage.length > 0) {\n storage.removeItem(this.#storageKey);\n }\n\n return false;\n }\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 type {\n InstanceType,\n TelemetryCollector as TelemetryCollectorInterface,\n TelemetryEvent,\n TelemetryEventRaw,\n} from '@clerk/types';\n\nimport { parsePublishableKey } from '../keys';\nimport { isTruthy } from '../underscore';\nimport { TelemetryEventThrottler } from './throttler';\nimport type { TelemetryCollectorOptions } from './types';\n\ntype TelemetryCollectorConfig = Pick<\n TelemetryCollectorOptions,\n 'samplingRate' | 'disabled' | 'debug' | 'maxBufferSize'\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\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: TelemetryEvent[] = [];\n #pendingFlush: any;\n\n constructor(options: TelemetryCollectorOptions) {\n this.#config = {\n maxBufferSize: options.maxBufferSize ?? DEFAULT_CONFIG.maxBufferSize,\n samplingRate: options.samplingRate ?? DEFAULT_CONFIG.samplingRate,\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 this.#metadata.sdk = options.sdk!;\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 this.#eventThrottler = new TelemetryEventThrottler();\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 (this.#config.disabled || (typeof process !== 'undefined' && isTruthy(process.env.CLERK_TELEMETRY_DISABLED))) {\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 this.#config.debug || (typeof process !== 'undefined' && isTruthy(process.env.CLERK_TELEMETRY_DEBUG));\n }\n\n record(event: TelemetryEventRaw): void {\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(preparedPayload);\n\n this.#scheduleFlush();\n }\n\n #shouldRecord(preparedPayload: TelemetryEvent, eventSamplingRate?: number) {\n return this.isEnabled && !this.isDebug && this.#shouldBeSampled(preparedPayload, eventSamplingRate);\n }\n\n #shouldBeSampled(preparedPayload: TelemetryEvent, eventSamplingRate?: number) {\n const randomSeed = Math.random();\n\n const toBeSampled =\n randomSeed <= this.#config.samplingRate &&\n (typeof eventSamplingRate === 'undefined' || 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\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 const cancel = typeof cancelIdleCallback !== 'undefined' ? cancelIdleCallback : clearTimeout;\n cancel(this.#pendingFlush);\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 });\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 }, 0);\n }\n }\n\n #flush(): void {\n fetch(new URL('/v1/event', this.#config.endpoint), {\n method: 'POST',\n // TODO: We send an array here with that idea that we can eventually send multiple events.\n body: JSON.stringify({\n events: this.#buffer,\n }),\n headers: {\n 'Content-Type': 'application/json',\n },\n })\n .catch(() => void 0)\n .then(() => {\n this.#buffer = [];\n })\n .catch(() => void 0);\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 let sdkMetadata = {\n name: this.#metadata.sdk,\n version: this.#metadata.sdkVersion,\n };\n\n // @ts-expect-error -- The global window.Clerk type is declared in clerk-js, but we can't rely on that here\n if (typeof window !== 'undefined' && window.Clerk) {\n // @ts-expect-error -- The global window.Clerk type is declared in clerk-js, but we can't rely on that here\n sdkMetadata = { ...sdkMetadata, ...window.Clerk.constructor.sdkMetadata };\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","import type { TelemetryEventRaw } from '@clerk/types';\n\nconst EVENT_COMPONENT_MOUNTED = 'COMPONENT_MOUNTED';\nconst EVENT_COMPONENT_OPENED = 'COMPONENT_OPENED';\nconst EVENT_SAMPLING_RATE = 0.1;\n\ntype ComponentMountedBase = {\n component: string;\n};\n\ntype EventPrebuiltComponent = ComponentMountedBase & {\n appearanceProp: boolean;\n elements: boolean;\n variables: boolean;\n baseTheme: boolean;\n};\n\ntype EventComponentMounted = ComponentMountedBase & TelemetryEventRaw['payload'];\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: EVENT_SAMPLING_RATE,\n payload: {\n component,\n appearanceProp: Boolean(props?.appearance),\n baseTheme: Boolean(props?.appearance?.baseTheme),\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 *\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 *\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 *\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: EVENT_SAMPLING_RATE,\n payload: {\n component,\n ...props,\n },\n };\n}\n","import type { TelemetryEventRaw } from '@clerk/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"],"mappings":"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","names":["EVENT_SAMPLING_RATE"]}