@reopt-ai/data-sdk-client 0.4.0 → 0.5.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.
- package/README.md +50 -2
- package/dist/{client-BCrui21p.d.cts → client-BrtY8ZQB.d.cts} +72 -12
- package/dist/client-BrtY8ZQB.d.cts.map +1 -0
- package/dist/{client-B1GlWwVq.d.ts → client-BvSE7ErY.d.ts} +72 -12
- package/dist/client-BvSE7ErY.d.ts.map +1 -0
- package/dist/{exceptions-CuhGo9A5.cjs → exceptions-BPmC4TTt.cjs} +2 -2
- package/dist/exceptions-BPmC4TTt.cjs.map +1 -0
- package/dist/{exceptions-C9Fh0BIR.js → exceptions-CorACVsv.js} +2 -2
- package/dist/exceptions-CorACVsv.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/next.d.cts +1 -1
- package/dist/next.d.ts +1 -1
- package/dist/react.cjs +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/recorder-B993wv6b.js +390 -0
- package/dist/recorder-B993wv6b.js.map +1 -0
- package/dist/recorder-BSzzSd3Q.cjs +390 -0
- package/dist/recorder-BSzzSd3Q.cjs.map +1 -0
- package/dist/{registry-CGqrOtf4.cjs → registry-DR1N7wD5.cjs} +17 -4
- package/dist/registry-DR1N7wD5.cjs.map +1 -0
- package/dist/{registry-BPhiH_l9.js → registry-IzNqE02g.js} +18 -5
- package/dist/registry-IzNqE02g.js.map +1 -0
- package/package.json +7 -5
- package/dist/client-B1GlWwVq.d.ts.map +0 -1
- package/dist/client-BCrui21p.d.cts.map +0 -1
- package/dist/exceptions-C9Fh0BIR.js.map +0 -1
- package/dist/exceptions-CuhGo9A5.cjs.map +0 -1
- package/dist/registry-BPhiH_l9.js.map +0 -1
- package/dist/registry-CGqrOtf4.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registry-CGqrOtf4.cjs","names":["RESERVED_EVENT_NAMES","zTrackHandlerPayload","DEVICE_ID_HEADER","SESSION_ID_HEADER","WRITE_KEY_HEADER","CLIENT_ID_HEADER","CLIENT_SECRET_HEADER","CONTRACT_VERSION_HEADER","CONTRACT_VERSION","scrollDepthBucket","COOKIE_MAX_AGE_SECONDS","deviceCookieName","consentCookieName","parseConsentCookie","parseDeviceCookie","serializeDeviceCookie","serializeConsentCookie","isValidIdentityId","isOptedOut","parseSessionHeader","formatSessionHeader","isValidIdentityId"],"sources":["../../data-sdk-core/src/circuit-breaker.ts","../../data-sdk-core/src/consent.ts","../../data-sdk-core/src/validate.ts","../../data-sdk-core/src/events.ts","../../data-sdk-core/src/ids.ts","../../data-sdk-core/src/queue.ts","../../data-sdk-core/src/retry.ts","../../data-sdk-core/src/storage.ts","../../data-sdk-core/src/types.ts","../../data-sdk-core/src/transport.ts","../../data-sdk-core/src/client.ts","../src/capture/exception-properties.ts","../src/steps.ts","../src/capture/pageleave.ts","../src/capture/scroll-depth.ts","../src/capture/utm.ts","../src/capture/web-vitals.ts","../src/config.ts","../src/identity/cookie-storage.ts","../src/identity/device.ts","../src/client.ts","../src/registry.ts"],"sourcesContent":["import type { CircuitBreakerConfig } from \"./types.js\";\n\nexport type CircuitState = \"closed\" | \"open\" | \"half-open\";\n\nexport const DEFAULT_CIRCUIT_BREAKER = {\n failureThreshold: 5,\n recoveryTimeout: 60000,\n} as const;\n\n/**\n * Stops hammering a server that is already failing. After `failureThreshold`\n * consecutive transient failures the circuit opens and flushes are skipped\n * until `recoveryTimeout` passes; the next flush is a single probe\n * (half-open) that closes the circuit on success or reopens it on failure.\n *\n * Only *transient* failures count. A 4xx rejection means the server is\n * reachable and disagreeing about the payload — that is not a reason to stop\n * sending the next, possibly valid, batch.\n */\nexport class CircuitBreaker {\n private state: CircuitState = \"closed\";\n private consecutiveFailures = 0;\n private openedAt = 0;\n private readonly failureThreshold: number;\n private readonly recoveryTimeout: number;\n private readonly now: () => number;\n\n constructor(config: CircuitBreakerConfig | undefined, now: () => number) {\n this.failureThreshold = config?.failureThreshold ?? DEFAULT_CIRCUIT_BREAKER.failureThreshold;\n this.recoveryTimeout = config?.recoveryTimeout ?? DEFAULT_CIRCUIT_BREAKER.recoveryTimeout;\n this.now = now;\n }\n\n getState(): CircuitState {\n return this.state;\n }\n\n /**\n * Whether a request may go out right now. Moves an expired `open` circuit\n * to `half-open` as a side effect, so exactly one caller gets to probe.\n */\n allowRequest(): boolean {\n if (this.state !== \"open\") return true;\n if (this.now() - this.openedAt < this.recoveryTimeout) return false;\n this.state = \"half-open\";\n return true;\n }\n\n recordSuccess(): void {\n this.state = \"closed\";\n this.consecutiveFailures = 0;\n }\n\n /** A transient failure. Returns `true` if this one opened the circuit. */\n recordFailure(): boolean {\n this.consecutiveFailures++;\n if (this.state === \"half-open\" || this.consecutiveFailures >= this.failureThreshold) {\n const wasOpen = this.state === \"open\";\n this.state = \"open\";\n this.openedAt = this.now();\n return !wasOpen;\n }\n return false;\n }\n\n /**\n * A permanent rejection: the server is up. Close a half-open circuit and\n * reset the failure streak, but do not count it against the threshold.\n */\n recordRejection(): void {\n if (this.state === \"half-open\") this.state = \"closed\";\n this.consecutiveFailures = 0;\n }\n}\n","import type { ConsentCategory, ConsentConfig, QueueDropReason, StorageBackend } from \"./types.js\";\n\n/** Category applied to an event that does not name one. */\nexport const DEFAULT_CONSENT_CATEGORY: ConsentCategory = \"analytics\";\n\nexport const CONSENT_STORAGE_KEY = \"consent\";\n\nexport type ConsentState = Record<string, boolean>;\n\n/**\n * Per-category consent with two gates:\n *\n * - **enqueue** — an event whose category is refused never enters the queue,\n * so nothing about it is persisted either;\n * - **flush** — if tracking is paused or every category is refused, queued\n * events stay queued (they were accepted under earlier consent).\n *\n * Persistence goes through whatever storage the runtime provides; the\n * browser package hands in a cookie-backed store so the server can read the\n * same decision.\n */\nexport class ConsentManager {\n private state: ConsentState = {};\n private paused = false;\n private readonly storage: StorageBackend | undefined;\n private readonly onChange: ((state: ConsentState) => void) | undefined;\n\n constructor(\n config: ConsentConfig | undefined,\n storage: StorageBackend | undefined,\n onChange?: (state: ConsentState) => void\n ) {\n const persist = config?.persist ?? true;\n this.storage = persist ? storage : undefined;\n this.onChange = onChange;\n\n const defaultConsent = config?.defaultConsent ?? true;\n for (const category of config?.categories ?? [DEFAULT_CONSENT_CATEGORY]) {\n this.state[category] = defaultConsent;\n }\n // A stored decision overrides the default for its category only. A\n // cookie written by another integration that only knows `marketing`\n // must not silently refuse `analytics`; undecided is not refused.\n const stored = this.storage ? readStoredConsent(this.storage) : null;\n if (stored) Object.assign(this.state, stored);\n }\n\n get(category: ConsentCategory): boolean {\n return this.state[category] ?? false;\n }\n\n set(category: ConsentCategory, allowed: boolean): void {\n this.state[category] = allowed;\n this.persist();\n }\n\n setAll(allowed: boolean): void {\n for (const key of Object.keys(this.state)) {\n this.state[key] = allowed;\n }\n this.persist();\n }\n\n snapshot(): ConsentState {\n return { ...this.state };\n }\n\n /** Overlay decisions from elsewhere (a server bootstrap) on the current state. */\n replace(state: ConsentState): void {\n this.state = { ...this.state, ...state };\n this.persist();\n }\n\n pause(): void {\n this.paused = true;\n }\n\n resume(): void {\n this.paused = false;\n }\n\n isPaused(): boolean {\n return this.paused;\n }\n\n /** Why an event in `category` may not be queued right now, or `null`. */\n enqueueBlockReason(category: ConsentCategory): QueueDropReason | null {\n if (this.paused) return \"tracking_paused\";\n if (!this.get(category)) return \"consent_denied\";\n return null;\n }\n\n /** Why nothing may be sent right now, or `null`. */\n flushBlockReason(): QueueDropReason | null {\n if (this.paused) return \"tracking_paused\";\n if (!Object.values(this.state).some((allowed) => allowed === true)) return \"consent_denied\";\n return null;\n }\n\n private persist(): void {\n this.onChange?.(this.snapshot());\n if (!this.storage) return;\n try {\n this.storage.setItem(CONSENT_STORAGE_KEY, JSON.stringify(this.state));\n } catch {\n // A store that refuses writes must not block a consent change.\n }\n }\n}\n\nfunction readStoredConsent(storage: StorageBackend): ConsentState | null {\n try {\n const raw = storage.getItem(CONSENT_STORAGE_KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return null;\n const state: ConsentState = {};\n for (const [category, allowed] of Object.entries(parsed as Record<string, unknown>)) {\n if (typeof allowed === \"boolean\") state[category] = allowed;\n }\n return state;\n } catch {\n return null;\n }\n}\n","import { RESERVED_EVENT_NAMES } from \"@reopt-ai/data-contract/events\";\nimport type { ValidationError } from \"./events.js\";\n\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isId = (value: unknown, required: boolean) =>\n value === undefined\n ? !required\n : typeof value === \"number\" ||\n (typeof value === \"string\" && value.length <= 500 && (!required || value.length > 0));\n\nconst isName = (value: unknown, max = 200) => typeof value === \"string\" && value.length > 0 && value.length <= max;\n\n/**\n * The checks the server will make, written by hand and kept terse so the\n * production bundle carries neither zod nor a page of messages. Mirrors\n * `zTrackHandlerPayload`; the zod schema runs in development and catches\n * anything this misses. Errors name the field; the reason is implied.\n */\nexport function validateStructurally(event: unknown): ValidationError[] {\n const bad: string[] = [];\n if (!isRecord(event)) return [{ field: \"\", message: \"not an object\" }];\n if (!UUID.test(String(event.eventId))) bad.push(\"eventId\");\n if (!Number.isInteger(event.timestamp) || (event.timestamp as number) < 0) bad.push(\"timestamp\");\n const p = event.payload;\n if (!isRecord(p)) return [...bad, \"payload\"].map(field);\n\n switch (event.type) {\n case \"track\":\n if (!isName(p.name)) bad.push(\"payload.name\");\n else if ((RESERVED_EVENT_NAMES as readonly string[]).includes(p.name as string))\n bad.push(\"payload.name:reserved\");\n if (!isId(p.profileId, false)) bad.push(\"payload.profileId\");\n break;\n case \"identify\":\n if (!isId(p.profileId, true)) bad.push(\"payload.profileId\");\n break;\n case \"increment\":\n case \"decrement\":\n if (!isId(p.profileId, true)) bad.push(\"payload.profileId\");\n if (!isName(p.property)) bad.push(\"payload.property\");\n if (p.value !== undefined && !(typeof p.value === \"number\" && p.value > 0)) bad.push(\"payload.value\");\n break;\n default:\n bad.push(\"type\");\n }\n if (p.properties !== undefined && !isRecord(p.properties)) bad.push(\"payload.properties\");\n return bad.map(field);\n}\n\nfunction field(name: string): ValidationError {\n const [path, reason] = name.split(\":\");\n return { field: path!, message: reason ?? \"invalid\" };\n}\n","import { zTrackHandlerPayload } from \"@reopt-ai/data-contract/ingest\";\nimport { validateStructurally } from \"./validate.js\";\nimport type {\n DecrementOptions,\n EventPayload,\n IdentifyOptions,\n IncrementOptions,\n PageContext,\n PageViewOptions,\n TrackEventOptions,\n} from \"./types.js\";\n\nexport { zTrackHandlerPayload as zEventPayload };\n\nexport interface ValidationError {\n field: string;\n message: string;\n}\n\ntype Validation = { valid: true } | { valid: false; errors: ValidationError[] };\n\n/**\n * Validates against the wire contract before the event is queued, so a\n * malformed event is reported to the caller that produced it instead of\n * being discovered by the server after a page has already been left.\n *\n * In development the full zod schema runs as well, so a drift between the\n * hand-written checks and the contract shows up where it is cheapest. In\n * production that branch is dead code and bundlers drop zod with it.\n */\nexport function validateEvent(event: unknown): Validation {\n const errors = validateStructurally(event);\n // `typeof process` guard: this also runs unbundled from a <script> tag,\n // where `process` does not exist. Bundlers still constant-fold the check.\n if (typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\") {\n const result = zTrackHandlerPayload.safeParse(event);\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.issues.map((issue) => ({ field: issue.path.join(\".\"), message: issue.message })),\n };\n }\n if (errors.length > 0) {\n console.warn(\"[reopt] structural validator disagrees with the contract schema — report this\", errors);\n return { valid: true };\n }\n }\n return errors.length === 0 ? { valid: true } : { valid: false, errors };\n}\n\nexport interface EventFactoryDeps {\n createId: () => string;\n now: () => number;\n}\n\ntype Draft<T extends EventPayload> = Omit<T, \"eventId\" | \"timestamp\">;\n\nfunction stamp<T extends EventPayload>(deps: EventFactoryDeps, draft: Draft<T>): T {\n return { ...draft, eventId: deps.createId(), timestamp: deps.now() } as T;\n}\n\nexport function buildTrackEvent(\n deps: EventFactoryDeps,\n options: TrackEventOptions,\n fallbackProfileId: string | number | null\n): Extract<EventPayload, { type: \"track\" }> {\n return stamp(deps, {\n type: \"track\",\n payload: {\n name: options.name,\n properties: options.properties,\n profileId: options.profileId ?? fallbackProfileId ?? undefined,\n },\n });\n}\n\nexport function buildIdentifyEvent(\n deps: EventFactoryDeps,\n options: IdentifyOptions\n): Extract<EventPayload, { type: \"identify\" }> {\n return stamp(deps, {\n type: \"identify\",\n payload: {\n profileId: options.profileId,\n ...(options.firstName && { firstName: options.firstName }),\n ...(options.lastName && { lastName: options.lastName }),\n ...(options.email && { email: options.email }),\n ...(options.avatar && { avatar: options.avatar }),\n properties: options.properties,\n },\n });\n}\n\nexport function buildCounterEvent(\n deps: EventFactoryDeps,\n type: \"increment\" | \"decrement\",\n options: IncrementOptions | DecrementOptions,\n fallbackProfileId: string | number | null\n): Extract<EventPayload, { type: \"increment\" | \"decrement\" }> {\n return stamp(deps, {\n type,\n payload: {\n profileId: options.profileId ?? fallbackProfileId ?? \"\",\n property: options.property,\n value: options.value ?? 1,\n },\n });\n}\n\n/**\n * Merges explicit page-view options over the runtime's page context. UTM\n * keys are only included when present so an empty string never overwrites a\n * value the ingest pipeline would otherwise derive from the referrer.\n */\nexport function buildPageViewOptions(options: PageViewOptions, context: PageContext): TrackEventOptions {\n const utm = options.utm ?? context.utm ?? {};\n return {\n name: \"$pageview\",\n consentCategory: options.consentCategory,\n identity: options.identity,\n properties: {\n path: options.path ?? context.path ?? \"/\",\n origin: options.origin ?? context.origin ?? \"\",\n title: options.title ?? context.title ?? \"\",\n referrer: options.referrer ?? context.referrer ?? \"\",\n ...Object.fromEntries(Object.entries(utm).filter(([, value]) => value)),\n ...context.properties,\n ...options.properties,\n },\n };\n}\n\n/** Restores an event from the offline buffer, filling in what older buffers lacked. */\nexport function normalizePersistedEvent(deps: EventFactoryDeps, event: unknown): EventPayload | null {\n if (!event || typeof event !== \"object\") return null;\n const candidate = event as Partial<EventPayload>;\n if (\n candidate.type !== \"track\" &&\n candidate.type !== \"identify\" &&\n candidate.type !== \"increment\" &&\n candidate.type !== \"decrement\"\n ) {\n return null;\n }\n if (!candidate.payload || typeof candidate.payload !== \"object\") return null;\n return {\n ...candidate,\n eventId: candidate.eventId ?? deps.createId(),\n timestamp: candidate.timestamp ?? deps.now(),\n } as EventPayload;\n}\n","/**\n * Event ids are UUIDv7: the first 48 bits are the millisecond timestamp, so\n * ids sort in creation order. That matters at the storage layer — a\n * time-ordered key clusters a device's events together instead of scattering\n * them across the whole keyspace the way random v4 ids do.\n *\n * Within one millisecond the 12-bit `rand_a` field is used as a counter so\n * ids stay monotonic even when a burst of events shares a timestamp.\n */\n\nlet lastTimestamp = -1;\nlet sequence = 0;\n\nconst HEX = \"0123456789abcdef\";\n\nfunction randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n const cryptoApi = globalThis.crypto;\n if (cryptoApi && typeof cryptoApi.getRandomValues === \"function\") {\n cryptoApi.getRandomValues(bytes);\n return bytes;\n }\n for (let index = 0; index < length; index++) {\n bytes[index] = Math.floor(Math.random() * 256);\n }\n return bytes;\n}\n\nfunction hex(bytes: Uint8Array): string {\n let out = \"\";\n for (const byte of bytes) {\n out += HEX[byte >> 4]! + HEX[byte & 0x0f]!;\n }\n return out;\n}\n\n/** A UUIDv7 for the given instant (defaults to now). */\nexport function uuidv7(now: number = Date.now()): string {\n let timestamp = Math.max(0, Math.floor(now));\n\n if (timestamp === lastTimestamp) {\n sequence = (sequence + 1) & 0x0fff;\n // Counter overflow inside one millisecond: borrow the next millisecond\n // rather than emit a duplicate. Ordering is preserved; the clock is not\n // consulted again so the id stays monotonic even if it steps backwards.\n if (sequence === 0) {\n timestamp = lastTimestamp + 1;\n lastTimestamp = timestamp;\n }\n } else if (timestamp < lastTimestamp) {\n // Clock went backwards. Keep issuing from the last timestamp so ordering\n // never inverts; the ids will catch up once the clock passes it.\n timestamp = lastTimestamp;\n sequence = (sequence + 1) & 0x0fff;\n if (sequence === 0) {\n timestamp = lastTimestamp + 1;\n lastTimestamp = timestamp;\n }\n } else {\n lastTimestamp = timestamp;\n sequence = randomBytes(2)[0]! & 0x0f; // small random start so two processes rarely collide\n }\n\n const bytes = new Uint8Array(16);\n // 48-bit timestamp, big-endian.\n bytes[0] = (timestamp / 2 ** 40) & 0xff;\n bytes[1] = (timestamp / 2 ** 32) & 0xff;\n bytes[2] = (timestamp / 2 ** 24) & 0xff;\n bytes[3] = (timestamp / 2 ** 16) & 0xff;\n bytes[4] = (timestamp / 2 ** 8) & 0xff;\n bytes[5] = timestamp & 0xff;\n // Version 7 in the top nibble, then the 12-bit sequence.\n bytes[6] = 0x70 | (sequence >> 8);\n bytes[7] = sequence & 0xff;\n // Variant 10xx, then 62 random bits.\n const random = randomBytes(8);\n bytes[8] = 0x80 | (random[0]! & 0x3f);\n for (let index = 1; index < 8; index++) {\n bytes[8 + index] = random[index]!;\n }\n\n const text = hex(bytes);\n return `${text.slice(0, 8)}-${text.slice(8, 12)}-${text.slice(12, 16)}-${text.slice(16, 20)}-${text.slice(20)}`;\n}\n\n/** Random UUIDv4 — for identities, where ordering would only leak timing. */\nexport function uuidv4(): string {\n const cryptoApi = globalThis.crypto;\n if (cryptoApi && typeof cryptoApi.randomUUID === \"function\") {\n return cryptoApi.randomUUID();\n }\n const bytes = randomBytes(16);\n bytes[6] = 0x40 | (bytes[6]! & 0x0f);\n bytes[8] = 0x80 | (bytes[8]! & 0x3f);\n const text = hex(bytes);\n return `${text.slice(0, 8)}-${text.slice(8, 12)}-${text.slice(12, 16)}-${text.slice(16, 20)}-${text.slice(20)}`;\n}\n\n/** Reads the millisecond timestamp out of a UUIDv7. `null` for other versions. */\nexport function uuidv7Timestamp(id: string): number | null {\n if (!/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id)) return null;\n return parseInt(id.slice(0, 8) + id.slice(9, 13), 16);\n}\n","import type { EventIdentity, EventPayload, QueuedEvent, StorageBackend } from \"./types.js\";\n\nexport const QUEUE_STORAGE_KEY = \"queue\";\nconst PERSIST_DEBOUNCE_MS = 250;\n\n/** UTF-8 byte length of the serialized value — what the server measures. */\nexport function serializedSize(value: unknown): number {\n const text = JSON.stringify(value);\n if (typeof TextEncoder !== \"undefined\") {\n return new TextEncoder().encode(text).length;\n }\n // Every UTF-16 unit is at most 3 UTF-8 bytes; over-estimating only makes\n // batches smaller, never over the limit.\n let bytes = 0;\n for (let index = 0; index < text.length; index++) {\n const code = text.charCodeAt(index);\n bytes += code < 0x80 ? 1 : code < 0x800 ? 2 : 3;\n }\n return bytes;\n}\n\n/**\n * Two events may share a request only if they carry the same identity —\n * the device and session headers are per request, not per event.\n */\nexport function identityKey(identity: EventIdentity | undefined): string {\n if (!identity) return \"\";\n return `${identity.deviceId ?? \"\"}\u0000${identity.sessionId ?? \"\"}`;\n}\n\nexport interface EventQueueOptions {\n maxSize: number;\n /** Durable store; absent means memory only. */\n storage?: StorageBackend | undefined;\n /** Persist through `storage` (the offline buffer). */\n persist: boolean;\n /** Restores one buffered payload, or `null` to discard it. */\n normalize: (entry: unknown) => EventPayload | null;\n log?: ((...args: unknown[]) => void) | undefined | undefined;\n}\n\n/**\n * FIFO queue with a size cap and an optional offline buffer.\n *\n * Persistence is debounced: a burst of `track()` calls writes storage once,\n * not once per event. `persistNow()` bypasses the debounce for the moments\n * that matter — right before the page goes away, and after a flush changed\n * what is outstanding.\n */\nexport class EventQueue {\n private entries: QueuedEvent[] = [];\n /** The batch currently on the wire. Persisted with the queue so an unload mid-request loses nothing; the server dedupes by eventId. */\n private inFlight: QueuedEvent[] = [];\n private persistTimeout: ReturnType<typeof setTimeout> | null = null;\n private readonly options: EventQueueOptions;\n\n constructor(options: EventQueueOptions) {\n this.options = options;\n }\n\n get length(): number {\n return this.entries.length;\n }\n\n /** Adds an entry, dropping the oldest past `maxSize`. Returns how many were dropped. */\n push(entry: QueuedEvent): number {\n let dropped = 0;\n if (this.entries.length >= this.options.maxSize) {\n dropped = this.entries.length - this.options.maxSize + 1;\n this.entries.splice(0, dropped);\n }\n this.entries.push(entry);\n this.schedulePersist();\n return dropped;\n }\n\n /**\n * Removes and returns the next batch: a run of head entries that share\n * one identity, at most `maxCount` long, whose combined serialized size\n * stays under `maxBytes` (including the array brackets and commas).\n *\n * Always returns at least one entry when the queue is non-empty — a single\n * oversized event must be attempted, and rejected by the server, rather\n * than sit at the head of the queue forever.\n */\n take(maxCount: number, maxBytes: number): QueuedEvent[] {\n if (this.entries.length === 0) return [];\n const key = identityKey(this.entries[0]!.identity);\n let count = 0;\n let bytes = 2; // \"[]\"\n while (count < this.entries.length && count < maxCount) {\n const entry = this.entries[count]!;\n if (count > 0 && identityKey(entry.identity) !== key) break;\n const size = serializedSize(entry.event) + (count > 0 ? 1 : 0);\n if (count > 0 && bytes + size > maxBytes) break;\n bytes += size;\n count++;\n }\n this.inFlight = this.entries.splice(0, count);\n return this.inFlight;\n }\n\n /** The batch returned by the last `take()` has been settled — sent, dropped or requeued. */\n settle(): void {\n this.inFlight = [];\n }\n\n /** Puts a batch back at the head, preserving order, after a transient failure. */\n requeue(entries: QueuedEvent[]): void {\n this.entries.unshift(...entries);\n this.inFlight = [];\n }\n\n clear(): void {\n this.entries = [];\n }\n\n peekAll(): readonly QueuedEvent[] {\n return this.entries;\n }\n\n schedulePersist(): void {\n if (!this.options.persist || !this.options.storage) return;\n if (this.persistTimeout) return;\n this.persistTimeout = setTimeout(() => {\n this.persistTimeout = null;\n this.persistNow();\n }, PERSIST_DEBOUNCE_MS);\n }\n\n persistNow(): void {\n if (this.persistTimeout) {\n clearTimeout(this.persistTimeout);\n this.persistTimeout = null;\n }\n if (!this.options.persist || !this.options.storage) return;\n try {\n // Identity is deliberately not persisted: a buffer restored by a later\n // page belongs to whoever that page's runtime says it is.\n this.options.storage.setItem(\n QUEUE_STORAGE_KEY,\n JSON.stringify([...this.inFlight, ...this.entries].map((entry) => entry.event))\n );\n } catch {\n this.options.log?.(\"Failed to persist queue\");\n }\n }\n\n /**\n * Loads whatever a previous page left behind and removes it from storage,\n * so two tabs restoring the same buffer do not both send it.\n */\n restore(): number {\n if (!this.options.persist || !this.options.storage) return 0;\n try {\n const raw = this.options.storage.getItem(QUEUE_STORAGE_KEY);\n if (!raw) return 0;\n const payloads = JSON.parse(raw) as unknown;\n if (!Array.isArray(payloads)) return 0;\n const restored = payloads.flatMap((payload) => {\n const event = this.options.normalize(payload);\n return event ? [{ event }] : [];\n });\n this.entries.push(...restored);\n this.options.storage.removeItem(QUEUE_STORAGE_KEY);\n return restored.length;\n } catch {\n this.options.log?.(\"Failed to load persisted queue\");\n return 0;\n }\n }\n\n dispose(): void {\n if (this.persistTimeout) {\n clearTimeout(this.persistTimeout);\n this.persistTimeout = null;\n }\n }\n}\n","import type { RetryConfig } from \"./types.js\";\n\n/** Carries the HTTP status so the retry policy can tell transient from permanent. */\nexport class TransportError extends Error {\n readonly status?: number | undefined;\n /**\n * Keep the batch in the durable queue even though it is not retried now.\n * Used for quota exhaustion and contract drift — conditions that need a\n * human, after which an explicit flush should deliver the backlog.\n */\n readonly preserveBatch: boolean;\n\n constructor(message: string, status?: number, preserveBatch = false) {\n super(message);\n this.name = \"TransportError\";\n this.status = status;\n this.preserveBatch = preserveBatch;\n }\n}\n\n/**\n * Transient failures (network errors, 5xx, 429) are retried. Any other 4xx is\n * the server refusing the batch permanently; retrying it only repeats the\n * refusal.\n */\nexport function isRetryableTransportError(error: unknown): boolean {\n if (error instanceof TransportError && typeof error.status === \"number\") {\n if (error.status === 429) return true;\n if (error.status >= 400 && error.status < 500) return false;\n }\n return true;\n}\n\nexport interface ResolvedRetryConfig {\n maxRetries: number;\n baseDelay: number;\n maxDelay: number;\n jitter: number;\n}\n\nexport const DEFAULT_RETRY: ResolvedRetryConfig = {\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 30000,\n jitter: 0.1,\n};\n\nexport function resolveRetryConfig(config: RetryConfig | undefined): ResolvedRetryConfig {\n return {\n maxRetries: config?.maxRetries ?? DEFAULT_RETRY.maxRetries,\n baseDelay: config?.baseDelay ?? DEFAULT_RETRY.baseDelay,\n maxDelay: config?.maxDelay ?? DEFAULT_RETRY.maxDelay,\n jitter: config?.jitter ?? DEFAULT_RETRY.jitter,\n };\n}\n\n/**\n * Exponential back-off with symmetric jitter. `random` is injectable so a\n * test can pin the jitter instead of asserting on a range.\n */\nexport function computeBackoff(\n attempt: number,\n config: ResolvedRetryConfig,\n random: () => number = Math.random\n): number {\n const delay = Math.min(Math.pow(2, attempt) * config.baseDelay, config.maxDelay);\n const jitterAmount = delay * config.jitter * (random() * 2 - 1);\n return Math.max(0, delay + jitterAmount);\n}\n\n/**\n * Runs `operation` until it succeeds, throws a non-retryable error, or the\n * attempts run out. The last error is rethrown unchanged so callers keep its\n * status and `preserveBatch` flag.\n */\nexport async function withRetry<T>(\n operation: (attempt: number) => Promise<T>,\n config: ResolvedRetryConfig,\n hooks: { onRetry?: (attempt: number, waitMs: number, error: unknown) => void; random?: () => number } = {}\n): Promise<T> {\n for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n try {\n return await operation(attempt);\n } catch (error) {\n if (!isRetryableTransportError(error) || attempt === config.maxRetries) {\n throw error;\n }\n const waitMs = computeBackoff(attempt, config, hooks.random);\n hooks.onRetry?.(attempt + 1, waitMs, error);\n await new Promise((resolve) => setTimeout(resolve, waitMs));\n }\n }\n // Unreachable: the loop either returns or throws on the last attempt.\n throw new TransportError(\"Retry loop exhausted\", 500, true);\n}\n","import type { StorageBackend } from \"./types.js\";\n\n/** In-process store. Loses everything on restart — that is the point of a fallback. */\nexport function memoryStorage(): StorageBackend {\n const store = new Map<string, string>();\n return {\n getItem: (key) => store.get(key) ?? null,\n setItem: (key, value) => {\n store.set(key, value);\n },\n removeItem: (key) => {\n store.delete(key);\n },\n };\n}\n\n/**\n * Wraps a backend so that a throwing store (Safari private mode, a full\n * quota, a sandboxed iframe) degrades to \"nothing persisted\" rather than\n * taking the calling code down. `onError` is for debug logging only.\n */\nexport function safeStorage(\n backend: StorageBackend,\n onError?: (operation: string, error: unknown) => void\n): StorageBackend {\n return {\n getItem: (key) => {\n try {\n return backend.getItem(key);\n } catch (error) {\n onError?.(\"getItem\", error);\n return null;\n }\n },\n setItem: (key, value) => {\n try {\n backend.setItem(key, value);\n } catch (error) {\n onError?.(\"setItem\", error);\n }\n },\n removeItem: (key) => {\n try {\n backend.removeItem(key);\n } catch (error) {\n onError?.(\"removeItem\", error);\n }\n },\n };\n}\n\n/** A backend whose keys all share a prefix. */\nexport function prefixedStorage(backend: StorageBackend, prefix: string): StorageBackend {\n return {\n getItem: (key) => backend.getItem(prefix + key),\n setItem: (key, value) => backend.setItem(prefix + key, value),\n removeItem: (key) => backend.removeItem(prefix + key),\n };\n}\n","/**\n * Types shared by every runtime. Nothing here refers to `window`, `document`\n * or a Node built-in — the runtime-specific pieces are injected through\n * {@link ReoptRuntime}.\n */\n\n/** Consent categories. `analytics` is the one whose refusal stops everything. */\nexport type ConsentCategory = \"analytics\" | \"marketing\" | \"functional\" | \"performance\";\n\nexport interface ConsentConfig {\n /** Default decision for every configured category. Default: `true` (opt-out model). */\n defaultConsent?: boolean | undefined;\n /** Categories the integration recognises. Default: `[\"analytics\"]`. */\n categories?: ConsentCategory[] | undefined;\n /** Persist decisions through the runtime's storage. Default: `true`. */\n persist?: boolean | undefined;\n}\n\n/** Minimal synchronous key/value store — `localStorage`-shaped on purpose. */\nexport interface StorageBackend {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nexport interface RetryConfig {\n /** Attempts after the first. Default: 3. */\n maxRetries?: number | undefined;\n /** First back-off, milliseconds. Default: 1000. */\n baseDelay?: number | undefined;\n /** Back-off ceiling, milliseconds. Default: 30000. */\n maxDelay?: number | undefined;\n /** ± fraction of the delay. Default: 0.1. */\n jitter?: number | undefined;\n}\n\nexport interface CircuitBreakerConfig {\n /** Consecutive transient failures before the circuit opens. Default: 5. */\n failureThreshold?: number | undefined;\n /** How long the circuit stays open before one probe is allowed. Default: 60000. */\n recoveryTimeout?: number | undefined;\n}\n\nexport interface BatchConfig {\n /** Events per request. Default: 100. */\n size?: number | undefined;\n /** Milliseconds to wait for a batch to fill before sending. Default: 1000. */\n intervalMs?: number | undefined;\n /**\n * Serialized bytes per request. Default: 400 000, under the server's\n * 512 000 hard cap with room for the JSON envelope. A 413 is a 4xx, and 4xx\n * drops the batch — so overshooting the cap loses every event in it.\n */\n maxBytes?: number | undefined;\n}\n\n/** Browser credentials — public, ships in the page. */\nexport interface WriteKeyAuth {\n writeKey: string;\n}\n\n/** Server credentials — must never reach a client bundle. */\nexport interface ClientCredentialsAuth {\n clientId: string;\n clientSecret: string;\n}\n\nexport type ReoptAuth = WriteKeyAuth | ClientCredentialsAuth;\n\nexport function isWriteKeyAuth(auth: ReoptAuth): auth is WriteKeyAuth {\n return \"writeKey\" in auth;\n}\n\nexport type FetchLike = (input: string, init: FetchInit) => Promise<FetchResponseLike>;\n\nexport interface FetchInit {\n method: string;\n headers: Record<string, string>;\n body: string;\n keepalive?: boolean | undefined;\n}\n\nexport interface FetchResponseLike {\n ok: boolean;\n status: number;\n headers: { get(name: string): string | null };\n text(): Promise<string>;\n}\n\n/** Context the runtime fills in for a `$pageview` when the caller does not. */\nexport interface PageContext {\n path?: string | undefined;\n origin?: string | undefined;\n title?: string | undefined;\n referrer?: string | undefined;\n utm?: UTMParams | undefined;\n /** Extra properties the runtime derived from the page, e.g. a `normalizePath` hook's output. */\n properties?: Record<string, unknown> | undefined;\n}\n\n/**\n * Everything the engine needs from the world around it. The browser package\n * fills this from cookies, `localStorage` and `window`; the server package\n * from request cookies and headers; tests from plain objects.\n */\nexport interface ReoptRuntime {\n /** Resolved device id. Identity resolution is the runtime's job, not the engine's. */\n deviceId: string;\n /**\n * Value for the `reopt-session-id` header — the `\"<id>.<token>\"` credential\n * ingest handed back, if the runtime kept it. Unsigned values are ignored\n * by ingest, so only send what came from `onSession`.\n */\n getSessionId?: (() => string | null | undefined) | undefined;\n /** Ingest assigned (or confirmed) a session for this batch. The runtime persists it. */\n onSession?: ((credential: { id: string; token: string }) => void) | undefined | undefined;\n /** Durable store for the offline queue and consent. Absent = memory only. */\n storage?: StorageBackend | undefined;\n /** Clock. Defaults to `Date.now`; the browser package corrects for server skew. */\n now?: (() => number) | undefined | undefined;\n /** Id generator. Defaults to monotonic UUIDv7. */\n createId?: (() => string) | undefined | undefined;\n /** `fetch` implementation. Defaults to `globalThis.fetch`. */\n fetch?: FetchLike | undefined;\n /**\n * Subscribe to \"the process is about to go away\" signals (pagehide,\n * visibilitychange, SIGTERM). The engine flushes on each signal. Returns\n * the unsubscribe function.\n */\n onFlushSignal?: (flush: () => void) => () => void | undefined | undefined;\n /**\n * Last-chance delivery used when a flush signal fires, e.g. `sendBeacon`.\n * Return `true` if the runtime accepted the payload; `false` falls back to\n * keepalive fetch.\n */\n sendLastChance?: ((url: string, body: string, headers: Record<string, string>) => boolean) | undefined | undefined;\n /** Defaults for `$pageview` properties. */\n getPageContext?: (() => PageContext) | undefined | undefined;\n /**\n * Mint and persist a fresh device id. Called by `reset()`; without it a\n * reset keeps the old device, which is wrong on a shared machine.\n */\n regenerateDeviceId?: (() => string) | undefined | undefined;\n}\n\nexport interface ReoptCoreConfig {\n auth: ReoptAuth;\n /** Origin of the reopt-data deployment, or a same-origin proxy prefix like `/ingest`. */\n baseUrl: string;\n runtime: ReoptRuntime;\n debug?: boolean | undefined;\n batch?: BatchConfig | undefined;\n /** Upper bound on queued events; the oldest are dropped past it. Default: 10000. */\n maxQueueSize?: number | undefined;\n retry?: RetryConfig | undefined;\n circuitBreaker?: CircuitBreakerConfig | undefined;\n consent?: ConsentConfig | undefined;\n /** Prefix for storage keys. Default: `reopt_`. */\n storagePrefix?: string | undefined;\n /** Persist the queue through `runtime.storage`. Default: `true` when storage exists. */\n enableOfflineBuffer?: boolean | undefined;\n /** Flush on runtime flush signals. Default: `true` when the runtime provides them. */\n autoFlushOnUnload?: boolean | undefined;\n}\n\n/**\n * Identity a single event was recorded under, when it differs from the\n * runtime's. The server SDK uses this to file events from many requests\n * through one engine: each request's device travels with its events and\n * becomes that batch's `reopt-device-id`.\n */\nexport interface EventIdentity {\n deviceId?: string | undefined;\n sessionId?: string | null | undefined;\n}\n\nexport interface TrackEventOptions {\n /** File this event under another visitor than the runtime's. Server SDK use. */\n identity?: EventIdentity | undefined;\n name: string;\n properties?: Record<string, unknown> | undefined;\n profileId?: string | number | undefined;\n /** Consent category this event belongs to. Default: `analytics`. */\n consentCategory?: ConsentCategory | undefined;\n}\n\nexport interface IdentifyOptions {\n /** File this event under another visitor than the runtime's. Server SDK use. */\n identity?: EventIdentity | undefined;\n profileId: string | number;\n firstName?: string | undefined;\n lastName?: string | undefined;\n email?: string | undefined;\n avatar?: string | undefined;\n properties?: Record<string, unknown> | undefined;\n consentCategory?: ConsentCategory | undefined;\n}\n\nexport interface IncrementOptions {\n /** File this event under another visitor than the runtime's. Server SDK use. */\n identity?: EventIdentity | undefined;\n profileId: string | number;\n property: string;\n value?: number | undefined;\n consentCategory?: ConsentCategory | undefined;\n}\n\nexport interface DecrementOptions {\n /** File this event under another visitor than the runtime's. Server SDK use. */\n identity?: EventIdentity | undefined;\n profileId: string | number;\n property: string;\n value?: number | undefined;\n consentCategory?: ConsentCategory | undefined;\n}\n\nexport interface UTMParams {\n utm_source?: string | undefined;\n utm_medium?: string | undefined;\n utm_campaign?: string | undefined;\n utm_term?: string | undefined;\n utm_content?: string | undefined;\n}\n\nexport interface PageViewOptions {\n /** File this event under another visitor than the runtime's. Server SDK use. */\n identity?: EventIdentity | undefined;\n path?: string | undefined;\n /** Scheme + host. */\n origin?: string | undefined;\n title?: string | undefined;\n referrer?: string | undefined;\n properties?: Record<string, unknown> | undefined;\n utm?: UTMParams | undefined;\n consentCategory?: ConsentCategory | undefined;\n}\n\nexport type EventPayload =\n | {\n type: \"track\";\n eventId: string;\n timestamp: number;\n payload: {\n name: string;\n properties?: Record<string, unknown> | undefined;\n profileId?: string | number | undefined;\n };\n }\n | {\n type: \"identify\";\n eventId: string;\n timestamp: number;\n payload: {\n profileId: string | number;\n firstName?: string | undefined;\n lastName?: string | undefined;\n email?: string | undefined;\n avatar?: string | undefined;\n properties?: Record<string, unknown> | undefined;\n };\n }\n | {\n type: \"increment\";\n eventId: string;\n timestamp: number;\n payload: { profileId: string | number; property: string; value?: number };\n }\n | {\n type: \"decrement\";\n eventId: string;\n timestamp: number;\n payload: { profileId: string | number; property: string; value?: number };\n };\n\n/** What the queue holds: the wire payload plus the identity it belongs to. */\nexport interface QueuedEvent {\n event: EventPayload;\n identity?: EventIdentity | undefined;\n}\n\nexport type QueueDropReason = \"tracking_paused\" | \"consent_denied\" | \"validation_failed\" | \"payload_too_large\";\n\nexport interface QueueResult {\n eventId: string;\n queued: boolean;\n reason?: QueueDropReason | undefined;\n errors?: Array<{ field: string; message: string }> | undefined;\n}\n\nexport interface FlushResult {\n status: \"idle\" | \"success\" | \"failed\" | \"skipped\";\n sent: number;\n failed: number;\n pending: number;\n}\n\nexport interface DeliveryResult {\n queue: QueueResult;\n flush: FlushResult | null;\n}\n\nexport interface FlushOptions {\n /** Ask the transport to outlive the page (keepalive fetch / beacon). */\n keepalive?: boolean | undefined;\n /** Keep sending until the queue is empty or no progress is made. */\n drain?: boolean | undefined;\n}\n","import {\n CLIENT_ID_HEADER,\n CLIENT_SECRET_HEADER,\n CONTRACT_VERSION,\n CONTRACT_VERSION_HEADER,\n DEVICE_ID_HEADER,\n SESSION_ID_HEADER,\n WRITE_KEY_HEADER,\n} from \"@reopt-ai/data-contract/identity\";\nimport { TransportError } from \"./retry.js\";\nimport { isWriteKeyAuth, type EventIdentity, type EventPayload, type FetchLike, type ReoptAuth } from \"./types.js\";\n\nexport interface BatchDelivery {\n sent: number;\n failed: number;\n /** The signed session credential ingest returned, when it did. */\n session?: { id: string; token: string } | undefined;\n}\n\ninterface IngestCounts {\n accepted: number;\n duplicates: number;\n rejected: number;\n session?: { id: string; token: string } | undefined;\n}\n\n/**\n * Reads the counts out of a 2xx body. Hand-written rather than the zod\n * schema so the browser bundle does not carry zod; the shape is\n * `zIngestResponse` in `@reopt-ai/data-contract/ingest`, and only the three\n * fields the reconciliation needs are checked.\n */\nfunction readIngestCounts(rawBody: string): IngestCounts {\n let body: unknown;\n try {\n body = JSON.parse(rawBody);\n } catch (error) {\n throw new TransportError(\n `Track response did not match contract: ${error instanceof Error ? error.message : String(error)}`,\n 409,\n true\n );\n }\n const record = typeof body === \"object\" && body !== null ? (body as Record<string, unknown>) : null;\n const count = (value: unknown) => typeof value === \"number\" && Number.isInteger(value) && value >= 0;\n if (\n !record ||\n (record.status !== \"ok\" && record.status !== \"accepted\") ||\n !count(record.accepted) ||\n !count(record.duplicates) ||\n !Array.isArray(record.rejected)\n ) {\n throw new TransportError(\"Track response did not match contract: unexpected shape\", 409, true);\n }\n const session = record.session as Record<string, unknown> | undefined;\n const credential =\n session && typeof session.id === \"string\" && typeof session.token === \"string\"\n ? { id: session.id, token: session.token }\n : undefined;\n return {\n accepted: record.accepted as number,\n duplicates: record.duplicates as number,\n rejected: record.rejected.length,\n ...(credential ? { session: credential } : {}),\n };\n}\n\nexport interface TransportOptions {\n baseUrl: string;\n auth: ReoptAuth;\n getDeviceId: () => string;\n getSessionId?: (() => string | null | undefined) | undefined;\n fetch?: FetchLike | undefined;\n /**\n * Called once when the server first reports a contract version other than\n * the one this SDK was built against. Observation only — a browser SDK\n * cannot be upgraded in lockstep with the server (customer sites keep old\n * bundles loaded and cached), so a mismatch must never cost events. The\n * server validates every payload anyway; the response is checked\n * structurally below.\n */\n onVersionMismatch?: ((serverVersion: string | null) => void) | undefined | undefined;\n}\n\nexport interface SendOptions {\n keepalive?: boolean | undefined;\n /** Overrides the runtime's device/session for this request only. */\n identity?: EventIdentity | undefined;\n}\n\nexport interface Transport {\n readonly url: string;\n headers(identity?: EventIdentity): Record<string, string>;\n send(batch: EventPayload[], options?: SendOptions): Promise<BatchDelivery>;\n}\n\n/**\n * Where events are sent. Throws rather than defaulting: a default endpoint\n * makes a forgotten config look like a working integration — the SDK reports\n * success, the events go nowhere, and nothing surfaces until somebody\n * notices an empty dashboard.\n */\nexport function resolveBaseUrl(value: string | undefined): string {\n if (!value) {\n throw new Error(\"[reopt] `baseUrl` is required (your reopt-data origin, or the /ingest proxy prefix)\");\n }\n return value.replace(/\\/+$/, \"\");\n}\n\nexport function createTransport(options: TransportOptions): Transport {\n const url = `${resolveBaseUrl(options.baseUrl)}/api/track`;\n\n const headers = (identity?: EventIdentity): Record<string, string> => {\n const result: Record<string, string> = { \"Content-Type\": \"application/json\" };\n // No device is a legitimate state (server batches with no visitor); an\n // empty header would only leave a meaningless value in proxy logs.\n const deviceId = identity?.deviceId ?? options.getDeviceId();\n if (deviceId) result[DEVICE_ID_HEADER] = deviceId;\n const sessionId = identity?.sessionId !== undefined ? identity.sessionId : options.getSessionId?.();\n if (sessionId) result[SESSION_ID_HEADER] = sessionId;\n if (isWriteKeyAuth(options.auth)) {\n result[WRITE_KEY_HEADER] = options.auth.writeKey;\n } else {\n result[CLIENT_ID_HEADER] = options.auth.clientId;\n result[CLIENT_SECRET_HEADER] = options.auth.clientSecret;\n }\n return result;\n };\n\n let reportedVersion: string | null | undefined;\n const send = async (batch: EventPayload[], sendOptions: SendOptions = {}): Promise<BatchDelivery> => {\n const fetchImpl = options.fetch ?? (globalThis.fetch as FetchLike | undefined);\n if (!fetchImpl) {\n throw new TransportError(\"No fetch implementation available\", undefined, true);\n }\n\n const response = await fetchImpl(url, {\n method: \"POST\",\n headers: headers(sendOptions.identity),\n body: JSON.stringify(batch),\n ...(sendOptions.keepalive ? { keepalive: true } : {}),\n });\n\n const rawBody = await response.text();\n\n // Status first. A 502 from a CDN, a 404 from a bad rewrite or a captive\n // portal's HTML carry no contract header; classifying them as contract\n // drift would make them non-retryable *and* preserved — a fixed-interval\n // resend with no back-off and no breaker.\n if (!response.ok) {\n let code: string | undefined;\n try {\n const parsed = JSON.parse(rawBody) as { code?: unknown };\n if (typeof parsed.code === \"string\") code = parsed.code;\n } catch {\n // Not every proxy returns JSON on failure; the raw body is kept below.\n }\n // Quota can be raised later, so the batch is worth keeping. A purging\n // project is explicitly permanent in the wire contract and must not pin\n // an offline queue forever.\n const preserveBatch = code === \"quota_exceeded\";\n const effectiveStatus = code === \"quota_exceeded\" ? 402 : response.status;\n throw new TransportError(`Failed to send batch: ${rawBody}`, effectiveStatus, preserveBatch);\n }\n\n const serverVersion = response.headers.get(CONTRACT_VERSION_HEADER);\n if (serverVersion !== CONTRACT_VERSION && reportedVersion !== serverVersion) {\n reportedVersion = serverVersion;\n options.onVersionMismatch?.(serverVersion);\n }\n\n const counts = readIngestCounts(rawBody);\n // accepted + duplicates + rejected === sent — the invariant a forwarder\n // relies on to know the server dropped nothing silently.\n if (counts.accepted + counts.duplicates + counts.rejected !== batch.length) {\n throw new TransportError(\"Track response counts do not reconcile with the submitted batch\", 409, true);\n }\n\n return {\n sent: counts.accepted + counts.duplicates,\n failed: counts.rejected,\n ...(counts.session ? { session: counts.session } : {}),\n };\n };\n\n return { url, headers, send };\n}\n","import { CircuitBreaker } from \"./circuit-breaker.js\";\nimport { ConsentManager, DEFAULT_CONSENT_CATEGORY, type ConsentState } from \"./consent.js\";\nimport {\n buildCounterEvent,\n buildIdentifyEvent,\n buildPageViewOptions,\n buildTrackEvent,\n normalizePersistedEvent,\n validateEvent,\n type EventFactoryDeps,\n} from \"./events.js\";\nimport { uuidv7 } from \"./ids.js\";\nimport { EventQueue, serializedSize } from \"./queue.js\";\nimport {\n isRetryableTransportError,\n resolveRetryConfig,\n TransportError,\n withRetry,\n type ResolvedRetryConfig,\n} from \"./retry.js\";\nimport { prefixedStorage, safeStorage } from \"./storage.js\";\nimport { createTransport, type Transport } from \"./transport.js\";\nimport type {\n ConsentCategory,\n DecrementOptions,\n EventIdentity,\n EventPayload,\n FlushOptions,\n FlushResult,\n IdentifyOptions,\n IncrementOptions,\n PageViewOptions,\n QueuedEvent,\n QueueResult,\n ReoptCoreConfig,\n ReoptRuntime,\n TrackEventOptions,\n} from \"./types.js\";\n\nexport const DEFAULT_BATCH = {\n size: 100,\n intervalMs: 1000,\n maxBytes: 400_000,\n} as const;\n\n/**\n * The Fetch spec caps the *total* in-flight keepalive body per origin at\n * 64 KiB. A batch bigger than that is refused outright, so an unload flush\n * chunks well under it.\n */\nexport const KEEPALIVE_MAX_BYTES = 60_000;\n\nexport const DEFAULT_MAX_QUEUE_SIZE = 10_000;\nexport const DEFAULT_STORAGE_PREFIX = \"reopt_\";\n\ninterface ResolvedBatch {\n size: number;\n intervalMs: number;\n maxBytes: number;\n}\n\n/**\n * The engine: queue → batch → transport, with retry, a circuit breaker and\n * consent gates. Everything that differs between browser and server comes in\n * through {@link ReoptRuntime}; the engine itself never touches `window`,\n * `document`, `process` or a Node built-in.\n */\nexport class ReoptCore {\n protected readonly runtime: ReoptRuntime;\n protected readonly transport: Transport;\n private readonly queue: EventQueue;\n private readonly consent: ConsentManager;\n private readonly breaker: CircuitBreaker;\n private readonly retry: ResolvedRetryConfig;\n private readonly batch: ResolvedBatch;\n private readonly factory: EventFactoryDeps;\n private readonly debug: boolean;\n\n private deviceId: string;\n private profileId: string | number | null = null;\n private globalProperties: Record<string, unknown> = {};\n private activeFlush: Promise<FlushResult> | null = null;\n private flushTimeout: ReturnType<typeof setTimeout> | null = null;\n private removeFlushSignal: (() => void) | null = null;\n private closed = false;\n /** Bumped by `reset()`; a batch from an older generation is never requeued. */\n private generation = 0;\n private lastFlushRequeued = false;\n\n constructor(config: ReoptCoreConfig) {\n this.runtime = config.runtime;\n this.debug = config.debug ?? false;\n this.deviceId = config.runtime.deviceId;\n\n const now = config.runtime.now ?? (() => Date.now());\n this.factory = { now, createId: config.runtime.createId ?? (() => uuidv7(now())) };\n\n const rawStorage = config.runtime.storage;\n const storage = rawStorage\n ? prefixedStorage(\n safeStorage(rawStorage, (operation) => this.log(`storage ${operation} failed`)),\n config.storagePrefix ?? DEFAULT_STORAGE_PREFIX\n )\n : undefined;\n\n this.batch = {\n size: config.batch?.size ?? DEFAULT_BATCH.size,\n intervalMs: config.batch?.intervalMs ?? DEFAULT_BATCH.intervalMs,\n maxBytes: config.batch?.maxBytes ?? DEFAULT_BATCH.maxBytes,\n };\n this.retry = resolveRetryConfig(config.retry);\n this.breaker = new CircuitBreaker(config.circuitBreaker, now);\n\n this.transport = createTransport({\n baseUrl: config.baseUrl,\n auth: config.auth,\n getDeviceId: () => this.deviceId,\n getSessionId: config.runtime.getSessionId,\n fetch: config.runtime.fetch,\n onVersionMismatch: (serverVersion) => this.log(\"server contract version\", serverVersion),\n });\n\n this.consent = new ConsentManager(config.consent, storage);\n\n this.queue = new EventQueue({\n maxSize: config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE,\n storage,\n persist: config.enableOfflineBuffer ?? storage !== undefined,\n normalize: (entry) => normalizePersistedEvent(this.factory, entry),\n log: (...args) => this.log(...args),\n });\n\n const restored = this.queue.restore();\n if (restored > 0) {\n this.log(`restored ${restored}`);\n this.scheduleFlush();\n }\n\n const autoFlush = config.autoFlushOnUnload ?? config.runtime.onFlushSignal !== undefined;\n if (autoFlush && config.runtime.onFlushSignal) {\n this.removeFlushSignal = config.runtime.onFlushSignal(() => this.flushOnSignal());\n }\n }\n\n protected log(...args: unknown[]): void {\n if (this.debug) {\n console.log(\"[reopt]\", ...args);\n }\n }\n\n // --- Identity ---\n\n getDeviceId(): string {\n return this.deviceId;\n }\n\n /** Swap the device id, e.g. after a server bootstrap or a `reset()`. */\n setDeviceId(deviceId: string): void {\n this.deviceId = deviceId;\n }\n\n setProfileId(profileId: string | number | null): void {\n this.profileId = profileId;\n this.log(\"profile\", profileId);\n }\n\n getProfileId(): string | number | null {\n return this.profileId;\n }\n\n // --- Consent ---\n\n setConsent(category: ConsentCategory, allowed: boolean): void {\n this.consent.set(category, allowed);\n this.log(\"consent\", category, allowed);\n }\n\n getConsent(category: ConsentCategory): boolean {\n return this.consent.get(category);\n }\n\n setAllConsent(allowed: boolean): void {\n this.consent.setAll(allowed);\n this.log(\"consent all\", allowed);\n }\n\n getConsentState(): ConsentState {\n return this.consent.snapshot();\n }\n\n replaceConsentState(state: ConsentState): void {\n this.consent.replace(state);\n }\n\n pauseTracking(): void {\n this.consent.pause();\n this.log(\"paused\");\n }\n\n resumeTracking(): void {\n this.consent.resume();\n this.log(\"resumed\");\n if (this.queue.length > 0) this.scheduleFlush();\n }\n\n // --- Global properties ---\n\n /**\n * Properties attached to every `track` event (and so every automatic\n * event) from now on. An event's own properties win on conflict. This is\n * how a host adds its breakdown axis — a `page_id`, a tenant — to\n * `$web_vitals` and `$pageleave`, which the SDK otherwise stamps with\n * only a path.\n */\n register(properties: Record<string, unknown>): void {\n this.globalProperties = { ...this.globalProperties, ...properties };\n }\n\n unregister(...keys: string[]): void {\n for (const key of keys) delete this.globalProperties[key];\n }\n\n getGlobalProperties(): Record<string, unknown> {\n return { ...this.globalProperties };\n }\n\n // --- Events ---\n\n /**\n * `options.identity` files the event under another visitor than the\n * runtime's — the server SDK's way of serving many requests from one\n * engine. Such an event never reads or writes the engine's own profile:\n * that belongs to the runtime's visitor, not the request's.\n */\n track(options: TrackEventOptions): QueueResult {\n const merged =\n Object.keys(this.globalProperties).length > 0\n ? { ...options, properties: { ...this.globalProperties, ...options.properties } }\n : options;\n const event = buildTrackEvent(this.factory, merged, options.identity ? null : this.profileId);\n return this.enqueue(event, options.consentCategory ?? DEFAULT_CONSENT_CATEGORY, options.identity);\n }\n\n identify(options: IdentifyOptions): QueueResult {\n if (!options.identity) this.profileId = options.profileId;\n const event = buildIdentifyEvent(this.factory, options);\n return this.enqueue(event, options.consentCategory ?? DEFAULT_CONSENT_CATEGORY, options.identity);\n }\n\n increment(options: IncrementOptions): QueueResult {\n const event = buildCounterEvent(this.factory, \"increment\", options, options.identity ? null : this.profileId);\n return this.enqueue(event, options.consentCategory ?? DEFAULT_CONSENT_CATEGORY, options.identity);\n }\n\n decrement(options: DecrementOptions): QueueResult {\n const event = buildCounterEvent(this.factory, \"decrement\", options, options.identity ? null : this.profileId);\n return this.enqueue(event, options.consentCategory ?? DEFAULT_CONSENT_CATEGORY, options.identity);\n }\n\n pageView(options: PageViewOptions = {}): QueueResult {\n return this.track(buildPageViewOptions(options, this.runtime.getPageContext?.() ?? {}));\n }\n\n screenView(screenName: string, properties?: Record<string, unknown>, identity?: EventIdentity): QueueResult {\n return this.track({ name: \"$screen_view\", properties: { screen_name: screenName, ...properties }, identity });\n }\n\n // --- Queue ---\n\n get pending(): number {\n return this.queue.length;\n }\n\n private enqueue(event: EventPayload, category: ConsentCategory, identity?: EventIdentity): QueueResult {\n const blockReason = this.consent.enqueueBlockReason(category);\n if (blockReason) {\n this.log(\"dropped:\", blockReason);\n return { eventId: event.eventId, queued: false, reason: blockReason };\n }\n\n const validation = validateEvent(event);\n if (!validation.valid) {\n this.log(\"invalid:\", validation.errors);\n return { eventId: event.eventId, queued: false, reason: \"validation_failed\", errors: validation.errors };\n }\n\n // An event that cannot fit in any batch would be sent alone, rejected\n // with 413, and dropped — after occupying the head of the queue for a\n // full retry cycle. Refusing it here tells the caller immediately.\n if (serializedSize(event) + 2 > this.batch.maxBytes) {\n this.log(\"too large\");\n return {\n eventId: event.eventId,\n queued: false,\n reason: \"payload_too_large\",\n errors: [{ field: \"payload\", message: `serialized event exceeds ${this.batch.maxBytes} bytes` }],\n };\n }\n\n const entry: QueuedEvent = identity ? { event, identity } : { event };\n const dropped = this.queue.push(entry);\n if (dropped > 0) this.log(\"queue full, dropped\", dropped);\n\n if (this.queue.length >= this.batch.size) {\n void this.flush();\n } else {\n this.scheduleFlush();\n }\n return { eventId: event.eventId, queued: true };\n }\n\n private scheduleFlush(): void {\n if (this.flushTimeout || this.closed) return;\n this.flushTimeout = setTimeout(() => {\n this.flushTimeout = null;\n void this.flush();\n }, this.batch.intervalMs);\n }\n\n private clearScheduledFlush(): void {\n if (!this.flushTimeout) return;\n clearTimeout(this.flushTimeout);\n this.flushTimeout = null;\n }\n\n // --- Flush ---\n\n flush(options: FlushOptions = {}): Promise<FlushResult> {\n return options.drain ? this.flushAll(options) : this.flushExclusive(options);\n }\n\n /**\n * The page (or process) is going away. Persist first so nothing is lost if\n * the request never completes, then send what can be sent with keepalive.\n */\n private flushOnSignal(): void {\n this.queue.persistNow();\n if (this.queue.length === 0 || this.consent.flushBlockReason()) return;\n\n const lastChance = this.runtime.sendLastChance;\n if (lastChance) {\n const batch = this.queue.take(this.batch.size, KEEPALIVE_MAX_BYTES);\n const body = JSON.stringify(batch.map((entry) => entry.event));\n if (lastChance(this.transport.url, body, this.transport.headers(batch[0]?.identity))) {\n this.queue.settle();\n this.queue.persistNow();\n if (this.queue.length > 0) this.flushOnSignal();\n return;\n }\n this.queue.requeue(batch);\n }\n // A regular flush may be in flight; waiting for it means waiting past\n // the page's death. Keepalive requests are fire-and-forget by nature, so\n // bypass the exclusivity and put everything left on the wire now.\n while (this.queue.length > 0) {\n const batch = this.queue.take(this.batch.size, Math.min(this.batch.maxBytes, KEEPALIVE_MAX_BYTES));\n const events = batch.map((entry) => entry.event);\n const identity = this.identityFor(batch);\n this.queue.settle();\n void this.transport.send(events, { keepalive: true, identity }).catch((error) => {\n this.log(\"keepalive failed\", error);\n });\n }\n this.queue.persistNow();\n }\n\n /**\n * The identity a batch is sent under, fixed when it leaves the queue. A\n * `reset()` during a retry must not re-address the previous visitor's\n * events to the new device.\n */\n private identityFor(batch: QueuedEvent[]): EventIdentity {\n return batch[0]?.identity ?? { deviceId: this.deviceId };\n }\n\n private flushExclusive(options: FlushOptions): Promise<FlushResult> {\n if (this.activeFlush) return this.activeFlush;\n const activeFlush = this.flushOnce(options).finally(() => {\n if (this.activeFlush === activeFlush) this.activeFlush = null;\n });\n this.activeFlush = activeFlush;\n return activeFlush;\n }\n\n private async flushAll(options: FlushOptions): Promise<FlushResult> {\n let sent = 0;\n let failed = 0;\n let status: FlushResult[\"status\"] = \"idle\";\n\n while (this.queue.length > 0) {\n const pendingBefore = this.queue.length;\n const result = await this.flushExclusive({ ...options, drain: true });\n sent += result.sent;\n failed += result.failed;\n status = result.status;\n // Progress means events left the queue — sent or discarded. No progress\n // means a transient failure requeued them; looping would only spin.\n const madeProgress = !this.lastFlushRequeued && (result.sent > 0 || this.queue.length < pendingBefore);\n if (!madeProgress) return { status, sent, failed, pending: result.pending };\n }\n\n return { status: sent > 0 ? \"success\" : status, sent, failed, pending: this.queue.length };\n }\n\n private async flushOnce(options: FlushOptions): Promise<FlushResult> {\n if (this.queue.length === 0) {\n this.clearScheduledFlush();\n return { status: \"idle\", sent: 0, failed: 0, pending: 0 };\n }\n if (this.consent.flushBlockReason()) {\n return { status: \"skipped\", sent: 0, failed: 0, pending: this.queue.length };\n }\n if (!this.breaker.allowRequest()) {\n this.log(\"breaker open\");\n return { status: \"skipped\", sent: 0, failed: 0, pending: this.queue.length };\n }\n if (this.breaker.getState() === \"half-open\") {\n this.log(\"breaker half-open\");\n }\n\n const maxBytes = options.keepalive ? Math.min(this.batch.maxBytes, KEEPALIVE_MAX_BYTES) : this.batch.maxBytes;\n const batch = this.queue.take(this.batch.size, maxBytes);\n const events = batch.map((entry) => entry.event);\n const identity = this.identityFor(batch);\n const generation = this.generation;\n this.lastFlushRequeued = false;\n\n try {\n const delivery = await withRetry(() => this.transport.send(events, { ...options, identity }), this.retry, {\n onRetry: (attempt, waitMs) => this.log(\"retry\", attempt, Math.round(waitMs)),\n });\n this.log(\"flushed\", delivery.sent, delivery.failed);\n if (delivery.session && !batch[0]?.identity) {\n // Only for the runtime's own visitor — a batch sent under a request's\n // identity must not overwrite the process's session.\n this.runtime.onSession?.(delivery.session);\n }\n if (this.breaker.getState() === \"half-open\") this.log(\"breaker closed\");\n this.breaker.recordSuccess();\n this.queue.settle();\n this.queue.persistNow();\n this.continueOrSettle(options);\n return {\n status: delivery.failed > 0 ? \"failed\" : \"success\",\n sent: delivery.sent,\n failed: delivery.failed,\n pending: this.queue.length,\n };\n } catch (error) {\n const preserve = error instanceof TransportError && error.preserveBatch;\n\n // A permanently rejected batch (4xx, not 429) would fail again on every\n // retry and block everything behind it. Drop it. The server is up, so\n // the breaker is not touched — except to close a half-open probe.\n if (!isRetryableTransportError(error) && !preserve) {\n this.log(\"rejected\", batch.length, error);\n this.breaker.recordRejection();\n this.queue.settle();\n this.queue.persistNow();\n this.continueOrSettle(options);\n return { status: \"failed\", sent: 0, failed: batch.length, pending: this.queue.length };\n }\n\n this.log(\"flush failed\", error);\n if (generation !== this.generation) {\n // reset() ran meanwhile: these events belong to a visitor who is gone.\n this.queue.settle();\n return { status: \"failed\", sent: 0, failed: batch.length, pending: this.queue.length };\n }\n this.lastFlushRequeued = true;\n this.queue.requeue(batch);\n this.queue.persistNow();\n\n // Quota exhaustion and contract drift need a human, not a retry storm.\n // The queue is kept; the breaker is left alone so a later explicit\n // flush can try again once the condition is fixed.\n if (!isRetryableTransportError(error)) {\n return { status: \"failed\", sent: 0, failed: batch.length, pending: this.queue.length };\n }\n\n if (this.breaker.recordFailure()) {\n this.log(\"breaker opened\");\n }\n return { status: \"failed\", sent: 0, failed: batch.length, pending: this.queue.length };\n }\n }\n\n private continueOrSettle(options: FlushOptions): void {\n if (!options.drain && this.queue.length > 0) {\n this.scheduleFlush();\n } else if (this.queue.length === 0) {\n this.clearScheduledFlush();\n }\n }\n\n // --- Lifecycle ---\n\n /**\n * Forget who this is: profile, queued events and — when the runtime can\n * mint one — the device id. A shared computer that logs out must not keep\n * attributing the next person to the previous one.\n */\n reset(): void {\n this.generation += 1;\n this.profileId = null;\n this.globalProperties = {};\n this.queue.clear();\n this.queue.settle();\n this.queue.persistNow();\n const regenerate = this.runtime.regenerateDeviceId;\n if (regenerate) {\n this.deviceId = regenerate();\n }\n this.log(\"reset\");\n }\n\n async close(): Promise<FlushResult> {\n this.closed = true;\n this.removeFlushSignal?.();\n this.removeFlushSignal = null;\n this.clearScheduledFlush();\n this.queue.dispose();\n // The debounced persist was just cancelled; if the flush below is\n // skipped (breaker open, paused, refused) nothing else would save it.\n this.queue.persistNow();\n const result = await this.flush({ drain: true });\n this.clearScheduledFlush();\n return result;\n }\n}\n","/**\n * The `$exception` property shape, and the parser-free way to build it.\n *\n * This module is in the main bundle; the stack parsers are not. The size\n * budget leaves a few hundred gzipped bytes of headroom and the parsers are\n * several times that, so anything reachable from the SDK's entry has to make do\n * with what `Error` already tells us: name, message, and the raw stack string.\n *\n * The structured `$exception_list` is built in `describe-error.ts`, which lives\n * in the lazily-imported `capture/exceptions` chunk.\n */\nimport type { ExceptionEntry } from \"@reopt-ai/data-contract/events\";\n\nexport type ExceptionSource = \"window.onerror\" | \"unhandledrejection\" | \"captureException\";\n\nexport type ExceptionProperties = {\n $exception_type: string;\n $exception_message: string;\n $exception_stack?: string;\n $exception_source: ExceptionSource;\n $exception_handled: boolean;\n /**\n * The structured cause chain, outermost first.\n *\n * Absent only when the parsers were not loaded yet — see\n * {@link describeErrorFlat}. The server falls back to V1 fingerprinting on\n * the flat keys in that case, so the event still groups.\n */\n $exception_list?: ExceptionEntry[];\n path: string;\n};\n\nexport const MAX_STACK_CHARS = 8_000;\n\n/**\n * Name, message and raw stack — everything obtainable without a parser.\n *\n * Used for a manual `captureException` that arrives before the exception chunk\n * has loaded. Every consumer written against the flat keys sees exactly what it\n * saw before the structured list existed.\n */\nexport function describeErrorFlat(value: unknown, source: ExceptionSource): ExceptionProperties {\n const path = typeof location !== \"undefined\" ? location.pathname : \"\";\n const handled = source === \"captureException\";\n\n if (value instanceof Error) {\n return {\n $exception_type: value.name || \"Error\",\n $exception_message: value.message,\n ...(value.stack ? { $exception_stack: value.stack.slice(0, MAX_STACK_CHARS) } : {}),\n $exception_source: source,\n $exception_handled: handled,\n path,\n };\n }\n\n return {\n $exception_type: typeof value === \"object\" && value !== null ? \"UnknownError\" : typeof value,\n $exception_message: safeString(value),\n $exception_source: source,\n $exception_handled: handled,\n path,\n };\n}\n\nfunction safeString(value: unknown): string {\n try {\n return typeof value === \"string\" ? value : (JSON.stringify(value) ?? String(value));\n } catch {\n return String(value);\n }\n}\n","/**\n * The breadcrumbs leading up to an exception.\n *\n * Has to live in the main bundle: steps are recorded *before* anything throws,\n * so it cannot wait for the exception chunk to load. Kept to a ring buffer and\n * three functions for that reason — every byte here is paid for by pages that\n * never throw, and the budget was raised 150 B to make room for it.\n *\n * Bounded three ways, because breadcrumbs are the part of an error report that\n * grows without anyone deciding to: 20 steps, a 200-character message, and 1 KB\n * of serialized `data`. Past those the payload costs more than the context is\n * worth, and a chatty app would push the real exception out of the request.\n *\n * One buffer per page, not per client: breadcrumbs describe what the visitor\n * did, which is a fact about the page rather than about whichever SDK instance\n * happens to be reporting.\n */\nimport type { ExceptionStep } from \"@reopt-ai/data-contract/events\";\n\nconst MAX_STEPS = 20;\nconst MAX_MESSAGE_CHARS = 200;\nconst MAX_DATA_BYTES = 1_024;\n\nexport type ExceptionStepInput = {\n category: ExceptionStep[\"category\"];\n message: string;\n data?: Record<string, unknown> | undefined;\n};\n\n/** Newest last. A plain array trimmed at the cap — 20 entries is not worth a real ring. */\nconst steps: ExceptionStep[] = [];\n\n/** Drop `data` rather than truncate it: half a JSON object is worse than none. */\nfunction boundData(data: Record<string, unknown> | undefined): Record<string, unknown> | undefined {\n if (!data) return undefined;\n try {\n const json = JSON.stringify(data);\n return json && json.length <= MAX_DATA_BYTES ? data : undefined;\n } catch {\n // Circular, or a getter that throws. An SDK must not turn one crash into two.\n return undefined;\n }\n}\n\nexport function addExceptionStep(step: ExceptionStepInput): void {\n const data = boundData(step.data);\n steps.push({\n timestamp: Date.now(),\n category: step.category,\n message: step.message.slice(0, MAX_MESSAGE_CHARS),\n ...(data ? { data } : {}),\n });\n if (steps.length > MAX_STEPS) steps.splice(0, steps.length - MAX_STEPS);\n}\n\n/** A copy, so a caller cannot mutate the buffer through the event it just sent. */\nexport function readExceptionSteps(): ExceptionStep[] {\n return steps.slice();\n}\n\n/** Test seam — the buffer is module-global. */\nexport function clearExceptionSteps(): void {\n steps.length = 0;\n}\n","/**\n * Remembers the page currently being viewed so `$pageleave` can say how long\n * it was on screen. A page \"starts\" on every `$pageview` (initial load or a\n * client-side route change) and \"ends\" on the next one, or when the page is\n * hidden.\n *\n * `duration` is seconds, as ingest expects for `events.duration`.\n */\nimport { scrollDepthBucket } from \"@reopt-ai/data-contract/events\";\n\nexport interface CurrentPage {\n path: string;\n origin: string;\n startedAt: number;\n}\n\nexport type PageLeaveProperties = {\n path: string;\n origin: string;\n duration: number;\n scroll_depth?: number | undefined;\n /** Deepest threshold reached (\"0\" | \"25\" | \"50\" | \"75\" | \"100\") — the value to break down by. */\n scroll_depth_bucket?: string | undefined;\n};\n\nexport class PageLeaveTracker {\n private current: CurrentPage | null = null;\n private readonly now: () => number;\n\n constructor(now: () => number) {\n this.now = now;\n }\n\n /** Called on every `$pageview`. Returns the `$pageleave` for the page it replaces, if any. */\n enter(path: string, origin: string, scrollDepth: number | null): PageLeaveProperties | null {\n const left = this.leave(scrollDepth);\n this.current = { path, origin, startedAt: this.now() };\n return left;\n }\n\n /** Called when the page is hidden. Returns the leave, or `null` if nothing was entered. */\n leave(scrollDepth: number | null): PageLeaveProperties | null {\n const page = this.current;\n if (!page) return null;\n this.current = null;\n const seconds = Math.max(0, Math.round((this.now() - page.startedAt) / 1000));\n return {\n path: page.path,\n origin: page.origin,\n duration: seconds,\n ...(scrollDepth !== null\n ? { scroll_depth: scrollDepth, scroll_depth_bucket: scrollDepthBucket(scrollDepth) }\n : {}),\n };\n }\n\n /**\n * After the page was hidden and the visitor came back, the same page is\n * on screen again with a fresh timer.\n */\n resume(): void {\n // Nothing to do if `leave()` was never called; `enter()` handles the rest.\n }\n\n peek(): CurrentPage | null {\n return this.current;\n }\n}\n","/**\n * Tracks the deepest point the visitor scrolled to on the current page, as a\n * percentage of the document. Reset on every page view so it describes one\n * page, not the whole visit.\n */\nexport interface ScrollDepthTracker {\n /** 0–100, or `null` if nothing could be measured. */\n read(): number | null;\n reset(): void;\n stop(): void;\n}\n\nfunction currentDepth(): number | null {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") return null;\n const root = document.documentElement;\n const scrollable = Math.max(root.scrollHeight, document.body?.scrollHeight ?? 0) - window.innerHeight;\n if (!Number.isFinite(scrollable) || scrollable <= 0) return 100;\n const scrolled = window.scrollY ?? root.scrollTop ?? 0;\n return Math.max(0, Math.min(100, Math.round((scrolled / scrollable) * 100)));\n}\n\nexport function startScrollDepth(): ScrollDepthTracker {\n let max: number | null = null;\n const sample = () => {\n const depth = currentDepth();\n if (depth !== null && (max === null || depth > max)) max = depth;\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"scroll\", sample, { passive: true });\n window.addEventListener(\"resize\", sample, { passive: true });\n }\n sample();\n return {\n read: () => {\n sample();\n return max;\n },\n reset: () => {\n max = null;\n sample();\n },\n stop: () => {\n if (typeof window === \"undefined\") return;\n window.removeEventListener(\"scroll\", sample);\n window.removeEventListener(\"resize\", sample);\n },\n };\n}\n","import type { UTMParams } from \"@reopt-ai/data-sdk-core\";\n\nconst UTM_KEYS = [\"utm_source\", \"utm_medium\", \"utm_campaign\", \"utm_term\", \"utm_content\"] as const;\n\n/** UTM parameters from a query string. Empty values are omitted. */\nexport function extractUTMParams(search: string = typeof location !== \"undefined\" ? location.search : \"\"): UTMParams {\n try {\n const params = new URLSearchParams(search);\n const utm: UTMParams = {};\n for (const key of UTM_KEYS) {\n const value = params.get(key);\n if (value) utm[key] = value;\n }\n return utm;\n } catch {\n return {};\n }\n}\n","/**\n * The shape `next/web-vitals`' `useReportWebVitals` and the `web-vitals`\n * package both produce. Declared here so the vanilla entry does not have to\n * import either.\n */\nexport interface WebVitalMetric {\n id: string;\n name: string;\n value: number;\n delta?: number | undefined;\n rating?: \"good\" | \"needs-improvement\" | \"poor\" | undefined;\n navigationType?: string | undefined;\n}\n\nexport type WebVitalProperties = {\n metric_name: string;\n metric_id: string;\n value: number;\n delta?: number | undefined;\n rating?: string | undefined;\n navigation_type?: string | undefined;\n path: string;\n};\n\n/** Flattens a metric into `$web_vitals` properties; `path` is what ingest keys pages on. */\nexport function webVitalProperties(metric: WebVitalMetric, path: string): WebVitalProperties {\n return {\n metric_name: metric.name,\n metric_id: metric.id,\n value: metric.value,\n ...(metric.delta !== undefined ? { delta: metric.delta } : {}),\n ...(metric.rating ? { rating: metric.rating } : {}),\n ...(metric.navigationType ? { navigation_type: metric.navigationType } : {}),\n path,\n };\n}\n","import type { ReoptBootstrap } from \"@reopt-ai/data-contract/identity\";\nimport type {\n BatchConfig,\n CircuitBreakerConfig,\n ConsentCategory,\n ConsentConfig,\n FetchLike,\n RetryConfig,\n StorageBackend,\n} from \"@reopt-ai/data-sdk-core\";\n\nexport type ReoptObservedEventType = \"track\" | \"identify\" | \"increment\" | \"decrement\";\n\n/**\n * Observation-only lifecycle facts for local tooling. The callback is never\n * part of delivery: throwing from it is ignored and cannot block the SDK.\n */\nexport type ReoptClientObservation =\n | {\n type: \"config\";\n at: number;\n disabled: boolean;\n baseUrl: string;\n writeKeyPresent: boolean;\n debug: boolean;\n capture: ResolvedCaptureConfig;\n consentPersisted: boolean;\n batchIntervalMs: number;\n }\n | {\n type: \"event\";\n at: number;\n phase: \"queued\" | \"dropped\";\n eventId: string;\n eventType: ReoptObservedEventType;\n name: string;\n pending: number;\n reason?: string | undefined;\n errors?: Array<{ field: string; message: string }> | undefined;\n }\n | {\n type: \"identity\";\n at: number;\n action: \"initialized\" | \"identified\" | \"profile_changed\" | \"reset\";\n deviceId: string;\n profileId: string | number | null;\n storage: IdentityStorageKind;\n }\n | {\n type: \"consent\";\n at: number;\n category: ConsentCategory | \"all\";\n allowed: boolean;\n }\n | {\n type: \"tracking\";\n at: number;\n paused: boolean;\n };\n\nexport type ReoptClientObserver = (observation: ReoptClientObservation) => void;\n\n/**\n * Rewrites a pathname before it is attached to an event, and may lift the\n * parts it removed into properties so they stay available for breakdowns:\n * `/workspace/8f3…/crm/customers/2a1…` → `{ path: \"/workspace/:id/crm/customers/:id\",\n * properties: { workspace_id: \"8f3…\" } }`.\n *\n * Applied wherever the SDK fills in a path itself — the default `$pageview`\n * path, `$pageleave`, `$web_vitals`, `$exception`. A `path` you pass to\n * `pageView()` explicitly is used as-is, so run the same function on it\n * yourself; two different rules would give one visit two different paths.\n * Must be synchronous and pure. If it throws, the raw pathname is used.\n */\nexport type NormalizePath = (pathname: string) => string | { path: string; properties?: Record<string, unknown> };\n\nexport type { ReoptBootstrap };\n\nexport type IdentityStorageKind = \"auto\" | \"cookie\" | \"localStorage\" | \"memory\";\n\nexport interface IdentityConfig {\n /**\n * Where the device id lives. `auto` (default) prefers a cookie: Safari\n * expires script-written `localStorage` after seven days of inactivity,\n * which turns every returning visitor into a new device. A cookie the\n * server also reads survives that, and lets server-side events join the\n * same device.\n */\n storage?: IdentityStorageKind | undefined;\n /** Cookie `Domain`; omit for host-only. Set to share across subdomains. */\n cookieDomain?: string | undefined;\n /** Cookie lifetime. Default 400 days (the longest Chrome honours). */\n cookieMaxAgeSeconds?: number | undefined;\n}\n\nexport interface CaptureConfig {\n /**\n * Send `$pageview` on `init()`. Default `true` for the vanilla entry.\n * The Next entry sets it to `false` because `<ReoptPageView />` owns page\n * views there — including the first one.\n */\n pageview?: boolean | undefined;\n /** Send `$pageleave` with time-on-page when the page is hidden or the route changes. Default `true`. */\n pageleave?: boolean | undefined;\n /** Attach max scroll depth to `$pageleave`. Default `true`. */\n scrollDepth?: boolean | undefined;\n /** Send `$exception` for uncaught errors and unhandled rejections. Default `false`. */\n exceptions?: boolean | undefined;\n /**\n * Throttle automatic exception capture, per exception type. Default on\n * (10 events, one token back every 10s). `false` reports everything — only\n * useful when you are deliberately measuring an error storm.\n *\n * Never applies to `captureException()`: a report you asked for explicitly is\n * not noise the SDK gets to drop.\n */\n exceptionRateLimit?: { bucketSize?: number; refillSeconds?: number } | false | undefined;\n /**\n * Record breadcrumbs (`$exception_steps`) leading up to an exception.\n * Default `false` — it puts navigation history on every error, which is a\n * privacy decision the host makes, not the SDK.\n */\n exceptionSteps?: boolean | undefined;\n}\n\nexport interface ReoptClientConfig {\n writeKey: string;\n /** reopt-data origin, or the same-origin proxy prefix (e.g. `/ingest`) the Next.js proxy rewrites. */\n baseUrl: string;\n /** What the server already knows about this visitor. `null` = nothing. */\n bootstrap?: ReoptBootstrap | null | undefined;\n identity?: IdentityConfig | undefined;\n capture?: CaptureConfig | undefined;\n /**\n * Hosts that receive the `reopt-device-id` header on outgoing `fetch`/XHR,\n * so a server-side `track()` lands on the same device. `true` = the page's\n * own hostname. **Default: off** — the trusted path is passing\n * `getDeviceId()` to your server call explicitly; this patches `fetch`\n * and loads as a separate chunk only when enabled.\n */\n tracingHeaders?: boolean | string[] | undefined;\n /** See {@link NormalizePath}. */\n normalizePath?: NormalizePath | undefined;\n /**\n * Properties attached to every event from the very first one. Same as\n * calling `register()` right after `init()`, except that nothing can\n * slip out in between: web vitals arrive from a buffered\n * `PerformanceObserver` and can fire the instant the client exists.\n * Pass the page context the server already knows here; update it on\n * client-side navigation with `register()`.\n */\n properties?: Record<string, unknown> | undefined;\n /**\n * The build this page is running, sent on every event as `$release_id`.\n *\n * What lets error tracking say an issue first appeared in 1.4.0, and whether\n * the fix shipped in 1.4.1 held. A string the host chooses — a version, a\n * commit sha, a build id — not something the server issues, and an unknown\n * one is never rejected.\n *\n * Falls back to `globalThis.__REOPT_RELEASE__`, which is where a build step\n * writes the version the app's own config cannot know:\n *\n * ```js\n * // vite.config.js / next.config.js\n * define: { __REOPT_RELEASE__: JSON.stringify(process.env.GIT_SHA) }\n * ```\n *\n * Sugar over `properties: { $release_id }`, which still works and costs\n * nothing — the option exists because threading a build constant through a\n * properties bag is the part hosts get wrong.\n */\n release?: string | undefined;\n consent?: ConsentConfig | undefined;\n batch?: BatchConfig | undefined;\n retry?: RetryConfig | undefined;\n circuitBreaker?: CircuitBreakerConfig | undefined;\n /** Upper bound on queued events. Default 10 000. */\n maxQueueSize?: number | undefined;\n /** Overrides the store for the offline queue. Default `localStorage`. */\n queueStorage?: StorageBackend | undefined;\n /** Prefix for storage keys. Default `reopt_`. */\n storagePrefix?: string | undefined;\n /**\n * Transport override. Tests hand in a recording function so a Playwright\n * spec can assert on the exact payload the SDK built, without intercepting\n * the network. Defaults to the page's `fetch` (captured at init, before the\n * tracing patch, so the SDK's own requests are never tagged twice).\n */\n fetch?: FetchLike | undefined;\n /**\n * Observation-only lifecycle hook for devtools. It receives no credentials\n * and is ignored when it throws. Facts are buffered in order while the\n * opt-in observer chunk loads; delivery never depends on this callback.\n */\n observe?: ReoptClientObserver | undefined;\n debug?: boolean | undefined;\n}\n\nexport interface ResolvedCaptureConfig {\n pageview: boolean;\n pageleave: boolean;\n scrollDepth: boolean;\n exceptions: boolean;\n /**\n * `false` disables throttling; otherwise the host's overrides, if any.\n *\n * Deliberately not defaulted here: the defaults live beside the limiter in\n * the lazily-loaded exception chunk, so the main bundle carries the option\n * but not the numbers.\n */\n exceptionRateLimit: { bucketSize?: number; refillSeconds?: number } | false;\n exceptionSteps: boolean;\n}\n\nexport function resolveCapture(config: CaptureConfig | undefined, pageviewDefault: boolean): ResolvedCaptureConfig {\n return {\n pageview: config?.pageview ?? pageviewDefault,\n pageleave: config?.pageleave ?? true,\n scrollDepth: config?.scrollDepth ?? true,\n exceptions: config?.exceptions ?? false,\n exceptionRateLimit: config?.exceptionRateLimit ?? {},\n exceptionSteps: config?.exceptionSteps ?? false,\n };\n}\n\n/**\n * Resolves the `tracingHeaders` option to a host list. Off unless asked:\n * the trusted way to tie a server call to the device is to pass\n * `getDeviceId()` explicitly; patching `fetch` is a convenience.\n */\nexport function resolveTracingHosts(option: boolean | string[] | undefined): string[] {\n if (!option) return [];\n if (Array.isArray(option)) return option;\n if (typeof location === \"undefined\" || !location.hostname) return [];\n return [location.hostname];\n}\n","import { COOKIE_MAX_AGE_SECONDS } from \"@reopt-ai/data-contract/identity\";\n\nexport interface CookieOptions {\n domain?: string | undefined;\n maxAgeSeconds?: number | undefined;\n}\n\n/** Reads one cookie by name. `null` when absent. */\nexport function readCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const prefix = `${name}=`;\n for (const part of document.cookie.split(\";\")) {\n const trimmed = part.trim();\n if (trimmed.startsWith(prefix)) return trimmed.slice(prefix.length);\n }\n return null;\n}\n\n/**\n * Writes a first-party cookie the server can read too:\n * - `SameSite=Lax` so it rides along on top-level navigations but not on\n * cross-site subrequests;\n * - `Secure` whenever the page is https (a `Secure` cookie on http is\n * silently dropped, which would look like storage failing);\n * - never `HttpOnly` — this SDK has to read it back.\n */\nexport function writeCookie(name: string, value: string, options: CookieOptions = {}): void {\n if (typeof document === \"undefined\") return;\n const maxAge = options.maxAgeSeconds ?? COOKIE_MAX_AGE_SECONDS;\n let cookie = `${name}=${value}; Path=/; Max-Age=${maxAge}; SameSite=Lax`;\n if (options.domain) cookie += `; Domain=${options.domain}`;\n if (typeof location !== \"undefined\" && location.protocol === \"https:\") cookie += \"; Secure\";\n document.cookie = cookie;\n}\n\nexport function deleteCookie(name: string, options: CookieOptions = {}): void {\n if (typeof document === \"undefined\") return;\n let cookie = `${name}=; Path=/; Max-Age=0; SameSite=Lax`;\n if (options.domain) cookie += `; Domain=${options.domain}`;\n document.cookie = cookie;\n}\n\n/**\n * Whether cookies can be written at all — false in a sandboxed iframe, with\n * cookies blocked, or when `document.cookie` throws. A probe cookie is set\n * and removed; its presence is the answer.\n */\nexport function cookiesAvailable(): boolean {\n if (typeof document === \"undefined\") return false;\n try {\n const probe = \"reopt_probe\";\n document.cookie = `${probe}=1; Path=/; Max-Age=60; SameSite=Lax`;\n const ok = readCookie(probe) === \"1\";\n document.cookie = `${probe}=; Path=/; Max-Age=0; SameSite=Lax`;\n return ok;\n } catch {\n return false;\n }\n}\n","import {\n consentCookieName,\n deviceCookieName,\n isValidIdentityId,\n parseConsentCookie,\n parseDeviceCookie,\n serializeConsentCookie,\n serializeDeviceCookie,\n type ConsentCookieState,\n type DeviceCookieState,\n} from \"@reopt-ai/data-contract/identity\";\nimport { memoryStorage, uuidv4, type StorageBackend } from \"@reopt-ai/data-sdk-core\";\nimport type { IdentityConfig, IdentityStorageKind } from \"../config.js\";\nimport { cookiesAvailable, deleteCookie, readCookie, writeCookie, type CookieOptions } from \"./cookie-storage.js\";\n\n/** Key the previous SDK generation used for its `localStorage` device id. */\nconst LEGACY_DEVICE_KEY = \"device_id\";\n\nexport interface IdentityStore {\n readonly kind: Exclude<IdentityStorageKind, \"auto\">;\n readDevice(): DeviceCookieState | null;\n writeDevice(state: DeviceCookieState): void;\n clearDevice(): void;\n readConsent(): ConsentCookieState | null;\n writeConsent(state: ConsentCookieState): void;\n /** Engine-facing backend for the consent key, so consent decisions land in the same place. */\n consentBackend(): StorageBackend;\n}\n\n/** `localStorage` as a backend, or `null` when it is absent or refuses writes. */\nexport function localStorageBackend(): StorageBackend | null {\n try {\n if (typeof window === \"undefined\" || !window.localStorage) return null;\n const storage = window.localStorage;\n const probe = \"reopt_probe\";\n storage.setItem(probe, \"1\");\n storage.removeItem(probe);\n return storage;\n } catch {\n return null;\n }\n}\n\n/**\n * One store shape over any raw key/value backend. For cookies the backend\n * is `document.cookie`; the JSON envelope is URI-encoded either way, so a\n * value written through one backend parses through another.\n */\nfunction makeStore(kind: IdentityStore[\"kind\"], writeKey: string, backend: StorageBackend): IdentityStore {\n const deviceName = deviceCookieName(writeKey);\n const consentName = consentCookieName(writeKey);\n const readConsent = () => parseConsentCookie(backend.getItem(consentName));\n return {\n kind,\n readDevice: () => parseDeviceCookie(backend.getItem(deviceName)),\n writeDevice: (state) => backend.setItem(deviceName, serializeDeviceCookie(state)),\n clearDevice: () => backend.removeItem(deviceName),\n readConsent,\n writeConsent: (state) => backend.setItem(consentName, serializeConsentCookie(state)),\n consentBackend: () => ({\n getItem: () => {\n const state = readConsent();\n return state ? JSON.stringify(state) : null;\n },\n setItem: (_key, value) => backend.setItem(consentName, encodeURIComponent(value)),\n removeItem: () => backend.removeItem(consentName),\n }),\n };\n}\n\nfunction cookieBackend(cookie: CookieOptions): StorageBackend {\n return {\n getItem: readCookie,\n setItem: (name, value) => writeCookie(name, value, cookie),\n removeItem: (name) => deleteCookie(name, cookie),\n };\n}\n\n/**\n * Picks where identity lives. `auto` walks cookie → localStorage → memory,\n * stopping at the first that actually works in this document.\n */\nexport function createIdentityStore(writeKey: string, config: IdentityConfig | undefined): IdentityStore {\n const kind = config?.storage ?? \"auto\";\n const cookie: CookieOptions = { domain: config?.cookieDomain, maxAgeSeconds: config?.cookieMaxAgeSeconds };\n\n if (kind === \"cookie\" || (kind === \"auto\" && cookiesAvailable())) {\n return makeStore(\"cookie\", writeKey, cookieBackend(cookie));\n }\n const local = kind === \"memory\" ? null : localStorageBackend();\n if (local) return makeStore(\"localStorage\", writeKey, local);\n return makeStore(\"memory\", writeKey, memoryStorage());\n}\n\nexport interface ResolvedIdentity {\n deviceId: string;\n /** Where the id came from — for debugging and for tests. */\n source: \"store\" | \"bootstrap\" | \"legacy\" | \"generated\";\n}\n\n/**\n * Establishes the device id for this page, in order of trust:\n *\n * 1. what the store already has — the browser's own state wins over anything\n * the server says, because a server bootstrap that disagrees with the\n * cookie means the cookie changed after the page was rendered;\n * 2. the server bootstrap (the proxy seeded a cookie the browser could not\n * read yet, e.g. `auto` fell back to localStorage);\n * 3. the previous SDK generation's localStorage id, migrated so returning\n * visitors keep their history;\n * 4. a new id.\n *\n * Whatever wins is written back so every store agrees from now on.\n */\nexport function resolveDeviceId(\n store: IdentityStore,\n bootstrapDeviceId: string | null | undefined,\n storagePrefix: string\n): ResolvedIdentity {\n const stored = store.readDevice();\n if (stored) return { deviceId: stored.deviceId, source: \"store\" };\n\n if (isValidIdentityId(bootstrapDeviceId)) {\n store.writeDevice({ deviceId: bootstrapDeviceId });\n return { deviceId: bootstrapDeviceId, source: \"bootstrap\" };\n }\n\n const local = localStorageBackend();\n const legacy = local?.getItem(`${storagePrefix}${LEGACY_DEVICE_KEY}`);\n if (isValidIdentityId(legacy)) {\n store.writeDevice({ deviceId: legacy });\n local?.removeItem(`${storagePrefix}${LEGACY_DEVICE_KEY}`);\n return { deviceId: legacy, source: \"legacy\" };\n }\n\n // Random, not time-ordered: a device id is an identity, and a v7 id would\n // reveal when the device was first seen to anyone who reads it.\n const generated = uuidv4();\n store.writeDevice({ deviceId: generated });\n return { deviceId: generated, source: \"generated\" };\n}\n\n/** A brand-new device, written through. For `reset()`. */\nexport function regenerateDeviceId(store: IdentityStore): string {\n const deviceId = uuidv4();\n store.writeDevice({ deviceId });\n return deviceId;\n}\n","import {\n formatSessionHeader,\n isOptedOut,\n isValidIdentityId,\n parseSessionHeader,\n type ReoptBootstrap,\n} from \"@reopt-ai/data-contract/identity\";\nimport {\n DEFAULT_STORAGE_PREFIX,\n memoryStorage,\n ReoptCore,\n type FetchLike,\n type FlushResult,\n type ConsentCategory,\n type DecrementOptions,\n type IdentifyOptions,\n type IncrementOptions,\n type PageContext,\n type PageViewOptions,\n type QueueResult,\n type ReoptRuntime,\n type StorageBackend,\n type TrackEventOptions,\n} from \"@reopt-ai/data-sdk-core\";\nimport { describeErrorFlat, type ExceptionProperties } from \"./capture/exception-properties.js\";\nimport { addExceptionStep, readExceptionSteps, type ExceptionStepInput } from \"./steps.js\";\nimport { PageLeaveTracker } from \"./capture/pageleave.js\";\nimport { startScrollDepth, type ScrollDepthTracker } from \"./capture/scroll-depth.js\";\nimport { extractUTMParams } from \"./capture/utm.js\";\nimport { webVitalProperties, type WebVitalMetric } from \"./capture/web-vitals.js\";\nimport {\n resolveCapture,\n resolveTracingHosts,\n type NormalizePath,\n type ReoptClientConfig,\n type ReoptObservedEventType,\n type ResolvedCaptureConfig,\n} from \"./config.js\";\nimport {\n createIdentityStore,\n localStorageBackend,\n regenerateDeviceId,\n resolveDeviceId,\n type IdentityStore,\n} from \"./identity/device.js\";\nimport type { ObservationFact, ObservationSink } from \"./observe.js\";\nimport type { ExceptionLevel } from \"@reopt-ai/data-contract/events\";\n\n/**\n * Below this, a difference between the server's clock and the device's is\n * indistinguishable from network and hydration latency, and \"correcting\"\n * it would only add noise. Above it, the device clock is wrong.\n */\nconst CLOCK_SKEW_THRESHOLD_MS = 30_000;\n/** Beyond a day the \"server time\" is more likely a cached page than a broken clock. */\nconst MAX_CLOCK_SKEW_MS = 24 * 60 * 60 * 1000;\n\nexport interface ReoptClientDefaults {\n /** Whether `init()` sends the first `$pageview`. The Next entry says no. */\n pageview: boolean;\n}\n\n/**\n * Storage the engine sees. Consent goes wherever identity lives (a cookie,\n * by default — so the server and the proxy can read the visitor's\n * decision); the offline queue goes to `localStorage`.\n */\nfunction routedStorage(consentKey: string, consent: StorageBackend, rest: StorageBackend): StorageBackend {\n const pick = (key: string) => (key === consentKey ? consent : rest);\n return {\n getItem: (key) => pick(key).getItem(key),\n setItem: (key, value) => pick(key).setItem(key, value),\n removeItem: (key) => pick(key).removeItem(key),\n };\n}\n\n/** The current pathname through `normalizePath`, with whatever properties it lifted out. */\nfunction normalizedPath(\n normalize: NormalizePath | undefined,\n pathname: string\n): { path: string; properties?: Record<string, unknown> } {\n if (!normalize) return { path: pathname };\n try {\n const result = normalize(pathname);\n if (typeof result === \"string\") return { path: result || pathname };\n if (result && typeof result.path === \"string\" && result.path) return result;\n } catch {\n // A broken hook must not lose the event; the raw path is still useful.\n }\n return { path: pathname };\n}\n\nfunction pageContext(normalize?: NormalizePath): PageContext {\n const hasWindow = typeof window !== \"undefined\";\n const hasDocument = typeof document !== \"undefined\";\n const normalized = normalizedPath(normalize, hasWindow ? window.location.pathname : \"/\");\n return {\n path: normalized.path,\n origin: hasWindow ? window.location.origin : \"\",\n title: hasDocument ? document.title : \"\",\n referrer: hasDocument ? document.referrer : \"\",\n utm: hasWindow ? extractUTMParams(window.location.search) : {},\n ...(normalized.properties ? { properties: normalized.properties } : {}),\n };\n}\n\n/**\n * Stands in for a client that could not be configured. Every call is a\n * no-op that reports `tracking_paused`; nothing is thrown. Analytics must\n * never be the reason a page fails.\n */\nconst DISABLED_BASE_URL = \"https://reopt.invalid\";\n\n/**\n * The browser client: the shared engine plus everything that only makes\n * sense in a document — cookie identity, tracing headers, page leave,\n * scroll depth, exception capture, and a clock corrected against the\n * server's.\n */\n/**\n * What to attach to a manual `captureException`.\n *\n * The second argument used to be a bare properties bag. That shape is still\n * accepted, so no existing call site has to change — see\n * {@link readCaptureExceptionOptions} for how the two are told apart.\n */\nexport interface CaptureExceptionOptions {\n /** Group this error yourself instead of letting the server fingerprint it. */\n fingerprint?: string | undefined;\n level?: ExceptionLevel | undefined;\n properties?: Record<string, unknown> | undefined;\n}\n\n/**\n * Read the second argument as options, or as the properties bag it used to be.\n *\n * An object carrying any of the three option keys is options; anything else is\n * properties. The overlap is theoretical — a host would have to name one of its\n * own properties `fingerprint`, `level` or `properties` — and choosing this way\n * means the release that adds options breaks nobody.\n */\nfunction readCaptureExceptionOptions(\n value: CaptureExceptionOptions | Record<string, unknown> | undefined\n): CaptureExceptionOptions {\n if (!value) return {};\n if (\"fingerprint\" in value || \"level\" in value || \"properties\" in value) return value as CaptureExceptionOptions;\n return { properties: value as Record<string, unknown> };\n}\n\nexport class ReoptClient extends ReoptCore {\n readonly writeKey: string;\n readonly capture: ResolvedCaptureConfig;\n private readonly store: IdentityStore;\n private readonly pageLeave: PageLeaveTracker;\n private readonly scroll: ScrollDepthTracker | null;\n private readonly uninstallers: Array<() => void> = [];\n private torndown = false;\n /** The lazily-loaded exception chunk, once it has resolved. */\n private exceptionChunk: typeof import(\"./capture/exceptions.js\") | undefined;\n private exceptionChunkPromise: Promise<typeof import(\"./capture/exceptions.js\")> | undefined;\n private readonly session: { header: string | null };\n private readonly optedOut: { value: boolean };\n private readonly normalize: NormalizePath | undefined;\n private readonly observer: ObservationSink | undefined;\n /** True when `writeKey` or `baseUrl` was missing: every call is a silent no-op. */\n readonly disabled: boolean;\n\n constructor(config: ReoptClientConfig, defaults: ReoptClientDefaults = { pageview: true }) {\n const disabled = !config.writeKey || !config.baseUrl;\n if (disabled) {\n // Fail open. A missing key is a configuration bug, not a reason to\n // take the page down — warn loudly, queue nothing, throw nothing.\n console.warn(`[reopt] ${!config.writeKey ? \"writeKey\" : \"baseUrl\"} missing — analytics disabled`);\n }\n const writeKey = config.writeKey || \"disabled\";\n const storagePrefix = config.storagePrefix ?? DEFAULT_STORAGE_PREFIX;\n const rawStore = createIdentityStore(writeKey, { ...config.identity, ...(disabled ? { storage: \"memory\" } : {}) });\n // An opted-out visitor must not be re-identified on every load: the proxy\n // deletes their device cookie, and minting a new one here would undo\n // that. While opted out the store accepts no device writes; the id lives\n // in memory for this page only. Granting consent later writes it through.\n const optedOut = {\n value:\n isOptedOut(rawStore.readConsent() ?? config.bootstrap?.consent ?? null) ||\n config.consent?.defaultConsent === false,\n };\n const store: IdentityStore = {\n ...rawStore,\n writeDevice: (state) => {\n if (!optedOut.value) rawStore.writeDevice(state);\n },\n };\n const identity = resolveDeviceId(store, config.bootstrap?.deviceId, storagePrefix);\n const now = correctedClock(config.bootstrap);\n const queueStorage = disabled ? memoryStorage() : (config.queueStorage ?? localStorageBackend() ?? memoryStorage());\n // Captured before the tracing patch installs, so our own requests go out\n // through the original fetch and are never tagged by our own patch.\n const transportFetch =\n config.fetch ?? (typeof window !== \"undefined\" ? (window.fetch.bind(window) as FetchLike) : undefined);\n\n // `super()` runs before `this` exists, so the unload handler reaches the\n // client through a box that is filled in right after.\n const box: { leave?: () => void } = {};\n // The signed session ingest handed back, kept in the device cookie so the\n // server SDK can send it too. Unsigned values never travel.\n const session = { header: store.readDevice()?.sessionId ?? null };\n const runtime: ReoptRuntime = {\n deviceId: identity.deviceId,\n getSessionId: () => (parseSessionHeader(session.header) ? session.header : null),\n onSession: (credential) => {\n session.header = formatSessionHeader(credential);\n const current = store.readDevice();\n store.writeDevice({ ...current, deviceId: current?.deviceId ?? identity.deviceId, sessionId: session.header });\n },\n storage: routedStorage(`${storagePrefix}consent`, store.consentBackend(), queueStorage),\n now,\n fetch: transportFetch,\n getPageContext: () => pageContext(config.normalizePath),\n regenerateDeviceId: () => regenerateDeviceId(store),\n onFlushSignal: (flush) => {\n if (typeof window === \"undefined\") return () => {};\n const onHide = () => {\n box.leave?.();\n flush();\n };\n const onVisibility = () => {\n if (document.visibilityState === \"hidden\") onHide();\n };\n window.addEventListener(\"pagehide\", onHide);\n document.addEventListener(\"visibilitychange\", onVisibility);\n return () => {\n window.removeEventListener(\"pagehide\", onHide);\n document.removeEventListener(\"visibilitychange\", onVisibility);\n };\n },\n };\n\n super({\n auth: { writeKey },\n baseUrl: disabled ? DISABLED_BASE_URL : config.baseUrl,\n runtime,\n debug: config.debug,\n batch: config.batch,\n maxQueueSize: config.maxQueueSize,\n retry: config.retry,\n circuitBreaker: config.circuitBreaker,\n consent: config.consent,\n storagePrefix,\n });\n\n this.writeKey = config.writeKey;\n this.disabled = disabled;\n this.session = session;\n this.optedOut = optedOut;\n this.normalize = config.normalizePath;\n this.store = store;\n this.capture = resolveCapture(config.capture, defaults.pageview);\n if (config.observe) {\n const pending: ObservationFact[] = [];\n let sink: ObservationSink = (fact) => pending.push(fact);\n this.observer = (fact) => sink(fact);\n void import(\"./observe.js\")\n .then(({ createObservationSink }) => {\n sink = createObservationSink(config.observe!);\n for (const fact of pending.splice(0)) sink(fact);\n })\n .catch(() => {\n // A devtool chunk must never surface an unhandled rejection or retain\n // buffered observations when delivery itself can continue normally.\n pending.length = 0;\n });\n }\n this.pageLeave = new PageLeaveTracker(now);\n this.scroll = !disabled && this.capture.scrollDepth && typeof window !== \"undefined\" ? startScrollDepth() : null;\n this.observe([\n \"config\",\n Date.now(),\n disabled,\n config.baseUrl,\n Boolean(config.writeKey),\n config.debug ?? false,\n this.capture,\n config.consent?.persist ?? true,\n config.batch?.intervalMs ?? 1000,\n ]);\n this.observeIdentity(\"initialized\");\n if (disabled) {\n this.pauseTracking();\n return;\n }\n // Before any listener is installed or any automatic event can fire.\n if (config.properties) this.register(config.properties);\n // Inline, not a helper, and the literal rather than the contract's\n // `RELEASE_PROPERTY`: this runs in the initial chunk, and importing the\n // constant pulls the events module's property tables with it.\n // `globalThis.__REOPT_RELEASE__` is where a build step writes the version\n // the app's own config cannot know.\n const release = (config.release ?? (globalThis as { __REOPT_RELEASE__?: string }).__REOPT_RELEASE__)?.trim();\n if (release) this.register({ $release_id: release });\n box.leave = () => this.emitPageLeave();\n this.log(`Device ${identity.deviceId} (${identity.source}, ${store.kind})`);\n\n // The server's view of consent fills in only when the browser has none\n // of its own — a decision made in this browser always wins.\n if (config.bootstrap?.consent && !store.readConsent() && Object.keys(config.bootstrap.consent).length > 0) {\n this.replaceConsentState(config.bootstrap.consent);\n }\n\n // Opt-in features load as separate chunks so a page that does not use\n // them does not pay for them in its initial bundle.\n const hosts = resolveTracingHosts(config.tracingHeaders);\n if (hosts.length > 0) {\n void import(\"./identity/tracing.js\").then(({ installTracingHeaders }) => {\n if (!this.torndown)\n this.uninstallers.push(installTracingHeaders({ hosts, getDeviceId: () => this.getDeviceId() }));\n });\n }\n if (this.capture.exceptions) {\n void this.loadExceptionChunk().then((chunk) => {\n if (!this.torndown)\n this.uninstallers.push(\n chunk.installExceptionCapture((properties) => this.trackException(properties), {\n rateLimit: this.capture.exceptionRateLimit,\n onThrottled: (type) => this.log(`exception rate limit reached for ${type} — further ones are dropped`),\n })\n );\n });\n }\n if (typeof document !== \"undefined\") {\n const onVisible = () => {\n // Coming back to a page that was hidden starts a new stay on it.\n if (document.visibilityState === \"visible\" && !this.pageLeave.peek()) {\n const context = pageContext(this.normalize);\n this.pageLeave.enter(context.path ?? \"/\", context.origin ?? \"\", null);\n this.scroll?.reset();\n }\n };\n document.addEventListener(\"visibilitychange\", onVisible);\n this.uninstallers.push(() => document.removeEventListener(\"visibilitychange\", onVisible));\n }\n\n if (this.capture.pageview && typeof document !== \"undefined\") {\n this.pageView();\n }\n }\n\n /** Which store identity ended up in — `cookie`, `localStorage` or `memory`. */\n get identityStorage(): IdentityStore[\"kind\"] {\n return this.store.kind;\n }\n\n private observe(fact: ObservationFact): void {\n this.observer?.(fact);\n }\n\n private observeIdentity(action: Extract<ObservationFact, [\"identity\", ...unknown[]]>[2]): void {\n this.observe([\"identity\", Date.now(), action, this.getDeviceId(), this.getProfileId(), this.store.kind]);\n }\n\n private observeEvent(eventType: ReoptObservedEventType, name: string, result: QueueResult): void {\n // A disabled client is a true no-op. Configuration and tracking-state\n // facts remain observable, but attempted analytics calls are not events.\n if (this.disabled) return;\n this.observe([\"event\", Date.now(), eventType, name, result, this.pending]);\n }\n\n override track(options: TrackEventOptions): QueueResult {\n const result = super.track(options);\n this.observeEvent(\"track\", options.name, result);\n return result;\n }\n\n override pageView(options: PageViewOptions = {}): QueueResult {\n const context = pageContext(this.normalize);\n const path = options.path ?? context.path ?? \"/\";\n const origin = options.origin ?? context.origin ?? \"\";\n // The only automatic breadcrumb, because it rides a hook that already\n // exists. A click trail would mean a new document-wide listener on every\n // page — a cost every page that never throws would pay — and this SDK has\n // no `data-track` click hook to piggyback on.\n if (this.capture.exceptionSteps) addExceptionStep({ category: \"navigation\", message: path });\n if (this.capture.pageleave) {\n const left = this.pageLeave.enter(path, origin, this.scroll?.read() ?? null);\n if (left) this.track({ name: \"$pageleave\", properties: left });\n }\n this.scroll?.reset();\n return super.pageView(options);\n }\n\n override setConsent(category: ConsentCategory, allowed: boolean): void {\n super.setConsent(category, allowed);\n this.syncOptOut();\n this.observe([\"consent\", Date.now(), category, allowed]);\n }\n\n override setAllConsent(allowed: boolean): void {\n super.setAllConsent(allowed);\n this.syncOptOut();\n this.observe([\"consent\", Date.now(), \"all\", allowed]);\n }\n\n override replaceConsentState(state: Record<string, boolean>): void {\n super.replaceConsentState(state);\n this.syncOptOut();\n for (const [category, allowed] of Object.entries(state)) {\n this.observe([\"consent\", Date.now(), category as ConsentCategory, allowed]);\n }\n }\n\n override pauseTracking(): void {\n super.pauseTracking();\n this.observe([\"tracking\", Date.now(), true]);\n }\n\n override resumeTracking(): void {\n super.resumeTracking();\n this.observe([\"tracking\", Date.now(), false]);\n }\n\n override setProfileId(profileId: string | number | null): void {\n super.setProfileId(profileId);\n this.observeIdentity(\"profile_changed\");\n }\n\n /**\n * Refusing `analytics` removes the stored identity (the proxy does the\n * same on its side); granting it again writes the current device through\n * so the visit is attributable from that point on.\n */\n private syncOptOut(): void {\n const now = isOptedOut(this.getConsentState());\n if (now === this.optedOut.value) return;\n this.optedOut.value = now;\n if (now) {\n this.store.clearDevice();\n this.session.header = null;\n } else {\n this.store.writeDevice({ deviceId: this.getDeviceId() });\n }\n }\n\n override identify(options: IdentifyOptions): QueueResult {\n const result = super.identify(options);\n if (!options.identity && result.queued) {\n // A hint for the server SDK; ingest never trusts it.\n this.store.writeDevice({ deviceId: this.getDeviceId(), profileId: String(options.profileId) });\n }\n this.observeEvent(\"identify\", \"identify\", result);\n this.observeIdentity(\"identified\");\n return result;\n }\n\n override increment(options: IncrementOptions): QueueResult {\n const result = super.increment(options);\n this.observeEvent(\"increment\", \"increment\", result);\n return result;\n }\n\n override decrement(options: DecrementOptions): QueueResult {\n const result = super.decrement(options);\n this.observeEvent(\"decrement\", \"decrement\", result);\n return result;\n }\n\n /** Feed a Web Vitals metric (from `next/web-vitals` or the `web-vitals` package). */\n captureWebVital(metric: WebVitalMetric): QueueResult {\n const { path, properties } = this.currentPath();\n return this.track({ name: \"$web_vitals\", properties: { ...properties, ...webVitalProperties(metric, path) } });\n }\n\n /** The page's path through `normalizePath`, for events the SDK stamps itself. */\n private currentPath(): { path: string; properties?: Record<string, unknown> } {\n return normalizedPath(this.normalize, typeof location !== \"undefined\" ? location.pathname : \"/\");\n }\n\n /**\n * Report an error you caught yourself.\n *\n * The stack parsers live in a lazily-loaded chunk — they are several times\n * the size budget's remaining headroom, and a page that never throws should\n * not pay for them. So the first call before that chunk resolves reports the\n * flat keys only (name, message, raw stack) and starts the load; every call\n * after it carries the structured `$exception_list` too. The server groups\n * both: without a list it falls back to V1 fingerprinting on the flat keys.\n */\n captureException(\n error: unknown,\n optionsOrProperties?: CaptureExceptionOptions | Record<string, unknown>\n ): QueueResult {\n const options = readCaptureExceptionOptions(optionsOrProperties);\n const described = this.exceptionChunk\n ? this.exceptionChunk.describeError(error, \"captureException\")\n : describeErrorFlat(error, \"captureException\");\n void this.loadExceptionChunk();\n\n const extra: Record<string, unknown> = { ...options?.properties };\n if (options?.level) extra.$exception_level = options.level;\n // A caller-supplied fingerprint is a *suggestion*: the server bounds it and\n // decides. Sending it is how \"group these two differently\" is expressed.\n if (options?.fingerprint) extra.$exception_fingerprint = options.fingerprint;\n\n // No extension-stack filtering here, unlike automatic capture: that filter\n // exists to drop noise the SDK picked up on its own. A developer calling\n // this asked for the report explicitly, and silently discarding it would be\n // worse than one unactionable issue.\n return this.trackException({ ...described, ...extra, $exception_handled: true });\n }\n\n /**\n * Record a breadcrumb for the next exception.\n *\n * Always available, whether or not automatic steps are on: a host that wants\n * to leave its own trail should not have to opt into the SDK leaving one too.\n */\n addExceptionStep(step: ExceptionStepInput): void {\n addExceptionStep(step);\n }\n\n /** Loads the exception chunk once and remembers it, so manual captures can use the parsers. */\n private loadExceptionChunk(): Promise<typeof import(\"./capture/exceptions.js\")> {\n this.exceptionChunkPromise ??= import(\"./capture/exceptions.js\").then((chunk) => {\n this.exceptionChunk = chunk;\n return chunk;\n });\n return this.exceptionChunkPromise;\n }\n\n private trackException(properties: ExceptionProperties): QueueResult {\n const current = this.currentPath();\n const steps = readExceptionSteps();\n return this.track({\n name: \"$exception\",\n properties: {\n ...current.properties,\n ...properties,\n // Copied, not moved: a second exception in the same session should see\n // the same history, not an empty trail.\n ...(steps.length > 0 ? { $exception_steps: steps } : {}),\n path: current.path,\n },\n });\n }\n\n private emitPageLeave(): void {\n if (!this.capture.pageleave) return;\n const left = this.pageLeave.leave(this.scroll?.read() ?? null);\n if (left) this.track({ name: \"$pageleave\", properties: left });\n }\n\n /**\n * Log out: forget the profile and the queue, and become a new device.\n * On a shared computer the next person must not inherit this one's\n * history.\n */\n override reset(): void {\n super.reset();\n // A new device, no profile hint, no session.\n this.session.header = null;\n this.store.writeDevice({ deviceId: this.getDeviceId() });\n this.observeIdentity(\"reset\");\n }\n\n override async close(): Promise<FlushResult> {\n this.torndown = true;\n this.emitPageLeave();\n this.scroll?.stop();\n for (const uninstall of this.uninstallers.splice(0)) uninstall();\n return super.close();\n }\n}\n\nfunction correctedClock(bootstrap: ReoptBootstrap | null | undefined): () => number {\n if (!bootstrap || !Number.isFinite(bootstrap.serverTimeMs)) return () => Date.now();\n const skew = bootstrap.serverTimeMs - Date.now();\n // A bootstrap from a cached render is stale, not evidence of a broken clock.\n if (Math.abs(skew) < CLOCK_SKEW_THRESHOLD_MS || Math.abs(skew) > MAX_CLOCK_SKEW_MS) return () => Date.now();\n return () => Date.now() + skew;\n}\n\nexport type { TrackEventOptions, ReoptClientConfig };\n\n/** Guards against a bootstrap whose device id is not usable. */\nexport function usableBootstrap(bootstrap: ReoptBootstrap | null | undefined): ReoptBootstrap | null {\n if (!bootstrap) return null;\n if (bootstrap.deviceId && !isValidIdentityId(bootstrap.deviceId)) return { ...bootstrap, deviceId: \"\" };\n return bootstrap;\n}\n","import { ReoptClient, usableBootstrap, type ReoptClientDefaults } from \"./client.js\";\nimport type { ReoptClientConfig } from \"./config.js\";\n\ninterface Registry {\n clients: Map<string, ReoptClient>;\n}\n\n/**\n * One client per write key per page, held on `window` rather than in module\n * scope. Module scope is not enough: a page can end up with two copies of\n * this package (two bundles, or a vanilla script next to the React one),\n * and each copy would happily create its own client — two device cookies,\n * two queues, every event twice.\n */\nfunction registry(): Registry | null {\n if (typeof window === \"undefined\") return null;\n const holder = window as unknown as { __reopt?: Registry };\n if (!holder.__reopt) holder.__reopt = { clients: new Map() };\n return holder.__reopt;\n}\n\n/**\n * Returns the existing client for `config.writeKey`, or creates it. Safe to\n * call during render: React StrictMode's double render, a remount, or a\n * second `init()` all land on the same instance.\n */\nexport function getOrCreateClient(config: ReoptClientConfig, defaults?: ReoptClientDefaults): ReoptClient {\n const store = registry();\n const existing = store?.clients.get(config.writeKey);\n if (existing) return existing;\n const client = new ReoptClient({ ...config, bootstrap: usableBootstrap(config.bootstrap) }, defaults);\n store?.clients.set(config.writeKey, client);\n return client;\n}\n\nexport function getClient(writeKey?: string): ReoptClient | null {\n const store = registry();\n if (!store) return null;\n if (writeKey) return store.clients.get(writeKey) ?? null;\n const first = store.clients.values().next();\n return first.done ? null : first.value;\n}\n\nexport function forgetClient(client: ReoptClient): void {\n registry()?.clients.delete(client.writeKey);\n}\n"],"mappings":"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"}
|