@reopt-ai/data-sdk-client 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +141 -7
  2. package/dist/client-B1GlWwVq.d.ts +744 -0
  3. package/dist/client-B1GlWwVq.d.ts.map +1 -0
  4. package/dist/client-BCrui21p.d.cts +744 -0
  5. package/dist/client-BCrui21p.d.cts.map +1 -0
  6. package/dist/exceptions-C9Fh0BIR.js +285 -0
  7. package/dist/exceptions-C9Fh0BIR.js.map +1 -0
  8. package/dist/exceptions-CuhGo9A5.cjs +289 -0
  9. package/dist/exceptions-CuhGo9A5.cjs.map +1 -0
  10. package/dist/index.cjs +75 -1874
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +83 -0
  13. package/dist/index.d.cts.map +1 -0
  14. package/dist/index.d.ts +35 -33
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +49 -70
  17. package/dist/index.js.map +1 -1
  18. package/dist/next.cjs +51 -1919
  19. package/dist/next.cjs.map +1 -1
  20. package/dist/next.d.cts +31 -0
  21. package/dist/next.d.cts.map +1 -0
  22. package/dist/next.d.ts +8 -10
  23. package/dist/next.d.ts.map +1 -0
  24. package/dist/next.js +36 -49
  25. package/dist/next.js.map +1 -1
  26. package/dist/observe-D-BHMwrO.cjs +54 -0
  27. package/dist/observe-D-BHMwrO.cjs.map +1 -0
  28. package/dist/observe-D1pNg1qL.js +54 -0
  29. package/dist/observe-D1pNg1qL.js.map +1 -0
  30. package/dist/react.cjs +105 -1863
  31. package/dist/react.cjs.map +1 -1
  32. package/dist/react.d.cts +80 -0
  33. package/dist/react.d.cts.map +1 -0
  34. package/dist/react.d.ts +52 -46
  35. package/dist/react.d.ts.map +1 -0
  36. package/dist/react.js +118 -23
  37. package/dist/react.js.map +1 -1
  38. package/dist/registry-BPhiH_l9.js +1775 -0
  39. package/dist/registry-BPhiH_l9.js.map +1 -0
  40. package/dist/registry-CGqrOtf4.cjs +1810 -0
  41. package/dist/registry-CGqrOtf4.cjs.map +1 -0
  42. package/dist/tracing-DAhaKkl0.cjs +93 -0
  43. package/dist/tracing-DAhaKkl0.cjs.map +1 -0
  44. package/dist/tracing-Dt1RVuQ9.js +93 -0
  45. package/dist/tracing-Dt1RVuQ9.js.map +1 -0
  46. package/package.json +31 -16
  47. package/dist/chunk-4MTDZBRS.js +0 -57
  48. package/dist/chunk-4MTDZBRS.js.map +0 -1
  49. package/dist/chunk-SYCBGBTH.js +0 -1627
  50. package/dist/chunk-SYCBGBTH.js.map +0 -1
  51. package/dist/chunk-YRP3I3OD.js +0 -106
  52. package/dist/chunk-YRP3I3OD.js.map +0 -1
  53. package/dist/client-BCd2fgmx.d.ts +0 -581
  54. package/dist/exceptions-NQHZUDYO.js +0 -9
  55. package/dist/exceptions-NQHZUDYO.js.map +0 -1
  56. package/dist/tracing-LC3NZND7.js +0 -91
  57. package/dist/tracing-LC3NZND7.js.map +0 -1
@@ -0,0 +1,744 @@
1
+ import "@reopt-ai/data-contract/ingest";
2
+ import { ExceptionEntry, ExceptionLevel, ExceptionStep } from "@reopt-ai/data-contract/events";
3
+ import { ConsentCookieState, DeviceCookieState, ReoptBootstrap } from "@reopt-ai/data-contract/identity";
4
+ //#region ../data-sdk-core/src/types.d.ts
5
+ /**
6
+ * Types shared by every runtime. Nothing here refers to `window`, `document`
7
+ * or a Node built-in — the runtime-specific pieces are injected through
8
+ * {@link ReoptRuntime}.
9
+ */
10
+ /** Consent categories. `analytics` is the one whose refusal stops everything. */
11
+ type ConsentCategory = "analytics" | "marketing" | "functional" | "performance";
12
+ interface ConsentConfig {
13
+ /** Default decision for every configured category. Default: `true` (opt-out model). */
14
+ defaultConsent?: boolean | undefined;
15
+ /** Categories the integration recognises. Default: `["analytics"]`. */
16
+ categories?: ConsentCategory[] | undefined;
17
+ /** Persist decisions through the runtime's storage. Default: `true`. */
18
+ persist?: boolean | undefined;
19
+ }
20
+ /** Minimal synchronous key/value store — `localStorage`-shaped on purpose. */
21
+ interface StorageBackend {
22
+ getItem(key: string): string | null;
23
+ setItem(key: string, value: string): void;
24
+ removeItem(key: string): void;
25
+ }
26
+ interface RetryConfig {
27
+ /** Attempts after the first. Default: 3. */
28
+ maxRetries?: number | undefined;
29
+ /** First back-off, milliseconds. Default: 1000. */
30
+ baseDelay?: number | undefined;
31
+ /** Back-off ceiling, milliseconds. Default: 30000. */
32
+ maxDelay?: number | undefined;
33
+ /** ± fraction of the delay. Default: 0.1. */
34
+ jitter?: number | undefined;
35
+ }
36
+ interface CircuitBreakerConfig {
37
+ /** Consecutive transient failures before the circuit opens. Default: 5. */
38
+ failureThreshold?: number | undefined;
39
+ /** How long the circuit stays open before one probe is allowed. Default: 60000. */
40
+ recoveryTimeout?: number | undefined;
41
+ }
42
+ interface BatchConfig {
43
+ /** Events per request. Default: 100. */
44
+ size?: number | undefined;
45
+ /** Milliseconds to wait for a batch to fill before sending. Default: 1000. */
46
+ intervalMs?: number | undefined;
47
+ /**
48
+ * Serialized bytes per request. Default: 400 000, under the server's
49
+ * 512 000 hard cap with room for the JSON envelope. A 413 is a 4xx, and 4xx
50
+ * drops the batch — so overshooting the cap loses every event in it.
51
+ */
52
+ maxBytes?: number | undefined;
53
+ }
54
+ /** Browser credentials — public, ships in the page. */
55
+ interface WriteKeyAuth {
56
+ writeKey: string;
57
+ }
58
+ /** Server credentials — must never reach a client bundle. */
59
+ interface ClientCredentialsAuth {
60
+ clientId: string;
61
+ clientSecret: string;
62
+ }
63
+ type ReoptAuth = WriteKeyAuth | ClientCredentialsAuth;
64
+ type FetchLike = (input: string, init: FetchInit) => Promise<FetchResponseLike>;
65
+ interface FetchInit {
66
+ method: string;
67
+ headers: Record<string, string>;
68
+ body: string;
69
+ keepalive?: boolean | undefined;
70
+ }
71
+ interface FetchResponseLike {
72
+ ok: boolean;
73
+ status: number;
74
+ headers: {
75
+ get(name: string): string | null;
76
+ };
77
+ text(): Promise<string>;
78
+ }
79
+ /** Context the runtime fills in for a `$pageview` when the caller does not. */
80
+ interface PageContext {
81
+ path?: string | undefined;
82
+ origin?: string | undefined;
83
+ title?: string | undefined;
84
+ referrer?: string | undefined;
85
+ utm?: UTMParams | undefined;
86
+ /** Extra properties the runtime derived from the page, e.g. a `normalizePath` hook's output. */
87
+ properties?: Record<string, unknown> | undefined;
88
+ }
89
+ /**
90
+ * Everything the engine needs from the world around it. The browser package
91
+ * fills this from cookies, `localStorage` and `window`; the server package
92
+ * from request cookies and headers; tests from plain objects.
93
+ */
94
+ interface ReoptRuntime {
95
+ /** Resolved device id. Identity resolution is the runtime's job, not the engine's. */
96
+ deviceId: string;
97
+ /**
98
+ * Value for the `reopt-session-id` header — the `"<id>.<token>"` credential
99
+ * ingest handed back, if the runtime kept it. Unsigned values are ignored
100
+ * by ingest, so only send what came from `onSession`.
101
+ */
102
+ getSessionId?: (() => string | null | undefined) | undefined;
103
+ /** Ingest assigned (or confirmed) a session for this batch. The runtime persists it. */
104
+ onSession?: ((credential: {
105
+ id: string;
106
+ token: string;
107
+ }) => void) | undefined | undefined;
108
+ /** Durable store for the offline queue and consent. Absent = memory only. */
109
+ storage?: StorageBackend | undefined;
110
+ /** Clock. Defaults to `Date.now`; the browser package corrects for server skew. */
111
+ now?: (() => number) | undefined | undefined;
112
+ /** Id generator. Defaults to monotonic UUIDv7. */
113
+ createId?: (() => string) | undefined | undefined;
114
+ /** `fetch` implementation. Defaults to `globalThis.fetch`. */
115
+ fetch?: FetchLike | undefined;
116
+ /**
117
+ * Subscribe to "the process is about to go away" signals (pagehide,
118
+ * visibilitychange, SIGTERM). The engine flushes on each signal. Returns
119
+ * the unsubscribe function.
120
+ */
121
+ onFlushSignal?: (flush: () => void) => () => void | undefined | undefined;
122
+ /**
123
+ * Last-chance delivery used when a flush signal fires, e.g. `sendBeacon`.
124
+ * Return `true` if the runtime accepted the payload; `false` falls back to
125
+ * keepalive fetch.
126
+ */
127
+ sendLastChance?: ((url: string, body: string, headers: Record<string, string>) => boolean) | undefined | undefined;
128
+ /** Defaults for `$pageview` properties. */
129
+ getPageContext?: (() => PageContext) | undefined | undefined;
130
+ /**
131
+ * Mint and persist a fresh device id. Called by `reset()`; without it a
132
+ * reset keeps the old device, which is wrong on a shared machine.
133
+ */
134
+ regenerateDeviceId?: (() => string) | undefined | undefined;
135
+ }
136
+ interface ReoptCoreConfig {
137
+ auth: ReoptAuth;
138
+ /** Origin of the reopt-data deployment, or a same-origin proxy prefix like `/ingest`. */
139
+ baseUrl: string;
140
+ runtime: ReoptRuntime;
141
+ debug?: boolean | undefined;
142
+ batch?: BatchConfig | undefined;
143
+ /** Upper bound on queued events; the oldest are dropped past it. Default: 10000. */
144
+ maxQueueSize?: number | undefined;
145
+ retry?: RetryConfig | undefined;
146
+ circuitBreaker?: CircuitBreakerConfig | undefined;
147
+ consent?: ConsentConfig | undefined;
148
+ /** Prefix for storage keys. Default: `reopt_`. */
149
+ storagePrefix?: string | undefined;
150
+ /** Persist the queue through `runtime.storage`. Default: `true` when storage exists. */
151
+ enableOfflineBuffer?: boolean | undefined;
152
+ /** Flush on runtime flush signals. Default: `true` when the runtime provides them. */
153
+ autoFlushOnUnload?: boolean | undefined;
154
+ }
155
+ /**
156
+ * Identity a single event was recorded under, when it differs from the
157
+ * runtime's. The server SDK uses this to file events from many requests
158
+ * through one engine: each request's device travels with its events and
159
+ * becomes that batch's `reopt-device-id`.
160
+ */
161
+ interface EventIdentity {
162
+ deviceId?: string | undefined;
163
+ sessionId?: string | null | undefined;
164
+ }
165
+ interface TrackEventOptions {
166
+ /** File this event under another visitor than the runtime's. Server SDK use. */
167
+ identity?: EventIdentity | undefined;
168
+ name: string;
169
+ properties?: Record<string, unknown> | undefined;
170
+ profileId?: string | number | undefined;
171
+ /** Consent category this event belongs to. Default: `analytics`. */
172
+ consentCategory?: ConsentCategory | undefined;
173
+ }
174
+ interface IdentifyOptions {
175
+ /** File this event under another visitor than the runtime's. Server SDK use. */
176
+ identity?: EventIdentity | undefined;
177
+ profileId: string | number;
178
+ firstName?: string | undefined;
179
+ lastName?: string | undefined;
180
+ email?: string | undefined;
181
+ avatar?: string | undefined;
182
+ properties?: Record<string, unknown> | undefined;
183
+ consentCategory?: ConsentCategory | undefined;
184
+ }
185
+ interface IncrementOptions {
186
+ /** File this event under another visitor than the runtime's. Server SDK use. */
187
+ identity?: EventIdentity | undefined;
188
+ profileId: string | number;
189
+ property: string;
190
+ value?: number | undefined;
191
+ consentCategory?: ConsentCategory | undefined;
192
+ }
193
+ interface DecrementOptions {
194
+ /** File this event under another visitor than the runtime's. Server SDK use. */
195
+ identity?: EventIdentity | undefined;
196
+ profileId: string | number;
197
+ property: string;
198
+ value?: number | undefined;
199
+ consentCategory?: ConsentCategory | undefined;
200
+ }
201
+ interface UTMParams {
202
+ utm_source?: string | undefined;
203
+ utm_medium?: string | undefined;
204
+ utm_campaign?: string | undefined;
205
+ utm_term?: string | undefined;
206
+ utm_content?: string | undefined;
207
+ }
208
+ interface PageViewOptions {
209
+ /** File this event under another visitor than the runtime's. Server SDK use. */
210
+ identity?: EventIdentity | undefined;
211
+ path?: string | undefined;
212
+ /** Scheme + host. */
213
+ origin?: string | undefined;
214
+ title?: string | undefined;
215
+ referrer?: string | undefined;
216
+ properties?: Record<string, unknown> | undefined;
217
+ utm?: UTMParams | undefined;
218
+ consentCategory?: ConsentCategory | undefined;
219
+ }
220
+ type EventPayload = {
221
+ type: "track";
222
+ eventId: string;
223
+ timestamp: number;
224
+ payload: {
225
+ name: string;
226
+ properties?: Record<string, unknown> | undefined;
227
+ profileId?: string | number | undefined;
228
+ };
229
+ } | {
230
+ type: "identify";
231
+ eventId: string;
232
+ timestamp: number;
233
+ payload: {
234
+ profileId: string | number;
235
+ firstName?: string | undefined;
236
+ lastName?: string | undefined;
237
+ email?: string | undefined;
238
+ avatar?: string | undefined;
239
+ properties?: Record<string, unknown> | undefined;
240
+ };
241
+ } | {
242
+ type: "increment";
243
+ eventId: string;
244
+ timestamp: number;
245
+ payload: {
246
+ profileId: string | number;
247
+ property: string;
248
+ value?: number;
249
+ };
250
+ } | {
251
+ type: "decrement";
252
+ eventId: string;
253
+ timestamp: number;
254
+ payload: {
255
+ profileId: string | number;
256
+ property: string;
257
+ value?: number;
258
+ };
259
+ };
260
+ type QueueDropReason = "tracking_paused" | "consent_denied" | "validation_failed" | "payload_too_large";
261
+ interface QueueResult {
262
+ eventId: string;
263
+ queued: boolean;
264
+ reason?: QueueDropReason | undefined;
265
+ errors?: Array<{
266
+ field: string;
267
+ message: string;
268
+ }> | undefined;
269
+ }
270
+ interface FlushResult {
271
+ status: "idle" | "success" | "failed" | "skipped";
272
+ sent: number;
273
+ failed: number;
274
+ pending: number;
275
+ }
276
+ interface FlushOptions {
277
+ /** Ask the transport to outlive the page (keepalive fetch / beacon). */
278
+ keepalive?: boolean | undefined;
279
+ /** Keep sending until the queue is empty or no progress is made. */
280
+ drain?: boolean | undefined;
281
+ }
282
+ //#endregion
283
+ //#region ../data-sdk-core/src/consent.d.ts
284
+ type ConsentState = Record<string, boolean>;
285
+ //#endregion
286
+ //#region ../data-sdk-core/src/transport.d.ts
287
+ interface BatchDelivery {
288
+ sent: number;
289
+ failed: number;
290
+ /** The signed session credential ingest returned, when it did. */
291
+ session?: {
292
+ id: string;
293
+ token: string;
294
+ } | undefined;
295
+ }
296
+ interface SendOptions {
297
+ keepalive?: boolean | undefined;
298
+ /** Overrides the runtime's device/session for this request only. */
299
+ identity?: EventIdentity | undefined;
300
+ }
301
+ interface Transport {
302
+ readonly url: string;
303
+ headers(identity?: EventIdentity): Record<string, string>;
304
+ send(batch: EventPayload[], options?: SendOptions): Promise<BatchDelivery>;
305
+ }
306
+ //#endregion
307
+ //#region ../data-sdk-core/src/client.d.ts
308
+ /**
309
+ * The engine: queue → batch → transport, with retry, a circuit breaker and
310
+ * consent gates. Everything that differs between browser and server comes in
311
+ * through {@link ReoptRuntime}; the engine itself never touches `window`,
312
+ * `document`, `process` or a Node built-in.
313
+ */
314
+ declare class ReoptCore {
315
+ protected readonly runtime: ReoptRuntime;
316
+ protected readonly transport: Transport;
317
+ private readonly queue;
318
+ private readonly consent;
319
+ private readonly breaker;
320
+ private readonly retry;
321
+ private readonly batch;
322
+ private readonly factory;
323
+ private readonly debug;
324
+ private deviceId;
325
+ private profileId;
326
+ private globalProperties;
327
+ private activeFlush;
328
+ private flushTimeout;
329
+ private removeFlushSignal;
330
+ private closed;
331
+ /** Bumped by `reset()`; a batch from an older generation is never requeued. */
332
+ private generation;
333
+ private lastFlushRequeued;
334
+ constructor(config: ReoptCoreConfig);
335
+ protected log(...args: unknown[]): void;
336
+ getDeviceId(): string;
337
+ /** Swap the device id, e.g. after a server bootstrap or a `reset()`. */
338
+ setDeviceId(deviceId: string): void;
339
+ setProfileId(profileId: string | number | null): void;
340
+ getProfileId(): string | number | null;
341
+ setConsent(category: ConsentCategory, allowed: boolean): void;
342
+ getConsent(category: ConsentCategory): boolean;
343
+ setAllConsent(allowed: boolean): void;
344
+ getConsentState(): ConsentState;
345
+ replaceConsentState(state: ConsentState): void;
346
+ pauseTracking(): void;
347
+ resumeTracking(): void;
348
+ /**
349
+ * Properties attached to every `track` event (and so every automatic
350
+ * event) from now on. An event's own properties win on conflict. This is
351
+ * how a host adds its breakdown axis — a `page_id`, a tenant — to
352
+ * `$web_vitals` and `$pageleave`, which the SDK otherwise stamps with
353
+ * only a path.
354
+ */
355
+ register(properties: Record<string, unknown>): void;
356
+ unregister(...keys: string[]): void;
357
+ getGlobalProperties(): Record<string, unknown>;
358
+ /**
359
+ * `options.identity` files the event under another visitor than the
360
+ * runtime's — the server SDK's way of serving many requests from one
361
+ * engine. Such an event never reads or writes the engine's own profile:
362
+ * that belongs to the runtime's visitor, not the request's.
363
+ */
364
+ track(options: TrackEventOptions): QueueResult;
365
+ identify(options: IdentifyOptions): QueueResult;
366
+ increment(options: IncrementOptions): QueueResult;
367
+ decrement(options: DecrementOptions): QueueResult;
368
+ pageView(options?: PageViewOptions): QueueResult;
369
+ screenView(screenName: string, properties?: Record<string, unknown>, identity?: EventIdentity): QueueResult;
370
+ get pending(): number;
371
+ private enqueue;
372
+ private scheduleFlush;
373
+ private clearScheduledFlush;
374
+ flush(options?: FlushOptions): Promise<FlushResult>;
375
+ /**
376
+ * The page (or process) is going away. Persist first so nothing is lost if
377
+ * the request never completes, then send what can be sent with keepalive.
378
+ */
379
+ private flushOnSignal;
380
+ /**
381
+ * The identity a batch is sent under, fixed when it leaves the queue. A
382
+ * `reset()` during a retry must not re-address the previous visitor's
383
+ * events to the new device.
384
+ */
385
+ private identityFor;
386
+ private flushExclusive;
387
+ private flushAll;
388
+ private flushOnce;
389
+ private continueOrSettle;
390
+ /**
391
+ * Forget who this is: profile, queued events and — when the runtime can
392
+ * mint one — the device id. A shared computer that logs out must not keep
393
+ * attributing the next person to the previous one.
394
+ */
395
+ reset(): void;
396
+ close(): Promise<FlushResult>;
397
+ }
398
+ //#endregion
399
+ //#region src/steps.d.ts
400
+ type ExceptionStepInput = {
401
+ category: ExceptionStep["category"];
402
+ message: string;
403
+ data?: Record<string, unknown> | undefined;
404
+ };
405
+ //#endregion
406
+ //#region src/capture/web-vitals.d.ts
407
+ /**
408
+ * The shape `next/web-vitals`' `useReportWebVitals` and the `web-vitals`
409
+ * package both produce. Declared here so the vanilla entry does not have to
410
+ * import either.
411
+ */
412
+ interface WebVitalMetric {
413
+ id: string;
414
+ name: string;
415
+ value: number;
416
+ delta?: number | undefined;
417
+ rating?: "good" | "needs-improvement" | "poor" | undefined;
418
+ navigationType?: string | undefined;
419
+ }
420
+ type WebVitalProperties = {
421
+ metric_name: string;
422
+ metric_id: string;
423
+ value: number;
424
+ delta?: number | undefined;
425
+ rating?: string | undefined;
426
+ navigation_type?: string | undefined;
427
+ path: string;
428
+ };
429
+ //#endregion
430
+ //#region src/config.d.ts
431
+ type ReoptObservedEventType = "track" | "identify" | "increment" | "decrement";
432
+ /**
433
+ * Observation-only lifecycle facts for local tooling. The callback is never
434
+ * part of delivery: throwing from it is ignored and cannot block the SDK.
435
+ */
436
+ type ReoptClientObservation = {
437
+ type: "config";
438
+ at: number;
439
+ disabled: boolean;
440
+ baseUrl: string;
441
+ writeKeyPresent: boolean;
442
+ debug: boolean;
443
+ capture: ResolvedCaptureConfig;
444
+ consentPersisted: boolean;
445
+ batchIntervalMs: number;
446
+ } | {
447
+ type: "event";
448
+ at: number;
449
+ phase: "queued" | "dropped";
450
+ eventId: string;
451
+ eventType: ReoptObservedEventType;
452
+ name: string;
453
+ pending: number;
454
+ reason?: string | undefined;
455
+ errors?: Array<{
456
+ field: string;
457
+ message: string;
458
+ }> | undefined;
459
+ } | {
460
+ type: "identity";
461
+ at: number;
462
+ action: "initialized" | "identified" | "profile_changed" | "reset";
463
+ deviceId: string;
464
+ profileId: string | number | null;
465
+ storage: IdentityStorageKind;
466
+ } | {
467
+ type: "consent";
468
+ at: number;
469
+ category: ConsentCategory | "all";
470
+ allowed: boolean;
471
+ } | {
472
+ type: "tracking";
473
+ at: number;
474
+ paused: boolean;
475
+ };
476
+ type ReoptClientObserver = (observation: ReoptClientObservation) => void;
477
+ /**
478
+ * Rewrites a pathname before it is attached to an event, and may lift the
479
+ * parts it removed into properties so they stay available for breakdowns:
480
+ * `/workspace/8f3…/crm/customers/2a1…` → `{ path: "/workspace/:id/crm/customers/:id",
481
+ * properties: { workspace_id: "8f3…" } }`.
482
+ *
483
+ * Applied wherever the SDK fills in a path itself — the default `$pageview`
484
+ * path, `$pageleave`, `$web_vitals`, `$exception`. A `path` you pass to
485
+ * `pageView()` explicitly is used as-is, so run the same function on it
486
+ * yourself; two different rules would give one visit two different paths.
487
+ * Must be synchronous and pure. If it throws, the raw pathname is used.
488
+ */
489
+ type NormalizePath = (pathname: string) => string | {
490
+ path: string;
491
+ properties?: Record<string, unknown>;
492
+ };
493
+ type IdentityStorageKind = "auto" | "cookie" | "localStorage" | "memory";
494
+ interface IdentityConfig {
495
+ /**
496
+ * Where the device id lives. `auto` (default) prefers a cookie: Safari
497
+ * expires script-written `localStorage` after seven days of inactivity,
498
+ * which turns every returning visitor into a new device. A cookie the
499
+ * server also reads survives that, and lets server-side events join the
500
+ * same device.
501
+ */
502
+ storage?: IdentityStorageKind | undefined;
503
+ /** Cookie `Domain`; omit for host-only. Set to share across subdomains. */
504
+ cookieDomain?: string | undefined;
505
+ /** Cookie lifetime. Default 400 days (the longest Chrome honours). */
506
+ cookieMaxAgeSeconds?: number | undefined;
507
+ }
508
+ interface CaptureConfig {
509
+ /**
510
+ * Send `$pageview` on `init()`. Default `true` for the vanilla entry.
511
+ * The Next entry sets it to `false` because `<ReoptPageView />` owns page
512
+ * views there — including the first one.
513
+ */
514
+ pageview?: boolean | undefined;
515
+ /** Send `$pageleave` with time-on-page when the page is hidden or the route changes. Default `true`. */
516
+ pageleave?: boolean | undefined;
517
+ /** Attach max scroll depth to `$pageleave`. Default `true`. */
518
+ scrollDepth?: boolean | undefined;
519
+ /** Send `$exception` for uncaught errors and unhandled rejections. Default `false`. */
520
+ exceptions?: boolean | undefined;
521
+ /**
522
+ * Throttle automatic exception capture, per exception type. Default on
523
+ * (10 events, one token back every 10s). `false` reports everything — only
524
+ * useful when you are deliberately measuring an error storm.
525
+ *
526
+ * Never applies to `captureException()`: a report you asked for explicitly is
527
+ * not noise the SDK gets to drop.
528
+ */
529
+ exceptionRateLimit?: {
530
+ bucketSize?: number;
531
+ refillSeconds?: number;
532
+ } | false | undefined;
533
+ /**
534
+ * Record breadcrumbs (`$exception_steps`) leading up to an exception.
535
+ * Default `false` — it puts navigation history on every error, which is a
536
+ * privacy decision the host makes, not the SDK.
537
+ */
538
+ exceptionSteps?: boolean | undefined;
539
+ }
540
+ interface ReoptClientConfig {
541
+ writeKey: string;
542
+ /** reopt-data origin, or the same-origin proxy prefix (e.g. `/ingest`) the Next.js proxy rewrites. */
543
+ baseUrl: string;
544
+ /** What the server already knows about this visitor. `null` = nothing. */
545
+ bootstrap?: ReoptBootstrap | null | undefined;
546
+ identity?: IdentityConfig | undefined;
547
+ capture?: CaptureConfig | undefined;
548
+ /**
549
+ * Hosts that receive the `reopt-device-id` header on outgoing `fetch`/XHR,
550
+ * so a server-side `track()` lands on the same device. `true` = the page's
551
+ * own hostname. **Default: off** — the trusted path is passing
552
+ * `getDeviceId()` to your server call explicitly; this patches `fetch`
553
+ * and loads as a separate chunk only when enabled.
554
+ */
555
+ tracingHeaders?: boolean | string[] | undefined;
556
+ /** See {@link NormalizePath}. */
557
+ normalizePath?: NormalizePath | undefined;
558
+ /**
559
+ * Properties attached to every event from the very first one. Same as
560
+ * calling `register()` right after `init()`, except that nothing can
561
+ * slip out in between: web vitals arrive from a buffered
562
+ * `PerformanceObserver` and can fire the instant the client exists.
563
+ * Pass the page context the server already knows here; update it on
564
+ * client-side navigation with `register()`.
565
+ */
566
+ properties?: Record<string, unknown> | undefined;
567
+ /**
568
+ * The build this page is running, sent on every event as `$release_id`.
569
+ *
570
+ * What lets error tracking say an issue first appeared in 1.4.0, and whether
571
+ * the fix shipped in 1.4.1 held. A string the host chooses — a version, a
572
+ * commit sha, a build id — not something the server issues, and an unknown
573
+ * one is never rejected.
574
+ *
575
+ * Falls back to `globalThis.__REOPT_RELEASE__`, which is where a build step
576
+ * writes the version the app's own config cannot know:
577
+ *
578
+ * ```js
579
+ * // vite.config.js / next.config.js
580
+ * define: { __REOPT_RELEASE__: JSON.stringify(process.env.GIT_SHA) }
581
+ * ```
582
+ *
583
+ * Sugar over `properties: { $release_id }`, which still works and costs
584
+ * nothing — the option exists because threading a build constant through a
585
+ * properties bag is the part hosts get wrong.
586
+ */
587
+ release?: string | undefined;
588
+ consent?: ConsentConfig | undefined;
589
+ batch?: BatchConfig | undefined;
590
+ retry?: RetryConfig | undefined;
591
+ circuitBreaker?: CircuitBreakerConfig | undefined;
592
+ /** Upper bound on queued events. Default 10 000. */
593
+ maxQueueSize?: number | undefined;
594
+ /** Overrides the store for the offline queue. Default `localStorage`. */
595
+ queueStorage?: StorageBackend | undefined;
596
+ /** Prefix for storage keys. Default `reopt_`. */
597
+ storagePrefix?: string | undefined;
598
+ /**
599
+ * Transport override. Tests hand in a recording function so a Playwright
600
+ * spec can assert on the exact payload the SDK built, without intercepting
601
+ * the network. Defaults to the page's `fetch` (captured at init, before the
602
+ * tracing patch, so the SDK's own requests are never tagged twice).
603
+ */
604
+ fetch?: FetchLike | undefined;
605
+ /**
606
+ * Observation-only lifecycle hook for devtools. It receives no credentials
607
+ * and is ignored when it throws. Facts are buffered in order while the
608
+ * opt-in observer chunk loads; delivery never depends on this callback.
609
+ */
610
+ observe?: ReoptClientObserver | undefined;
611
+ debug?: boolean | undefined;
612
+ }
613
+ interface ResolvedCaptureConfig {
614
+ pageview: boolean;
615
+ pageleave: boolean;
616
+ scrollDepth: boolean;
617
+ exceptions: boolean;
618
+ /**
619
+ * `false` disables throttling; otherwise the host's overrides, if any.
620
+ *
621
+ * Deliberately not defaulted here: the defaults live beside the limiter in
622
+ * the lazily-loaded exception chunk, so the main bundle carries the option
623
+ * but not the numbers.
624
+ */
625
+ exceptionRateLimit: {
626
+ bucketSize?: number;
627
+ refillSeconds?: number;
628
+ } | false;
629
+ exceptionSteps: boolean;
630
+ }
631
+ //#endregion
632
+ //#region src/identity/device.d.ts
633
+ interface IdentityStore {
634
+ readonly kind: Exclude<IdentityStorageKind, "auto">;
635
+ readDevice(): DeviceCookieState | null;
636
+ writeDevice(state: DeviceCookieState): void;
637
+ clearDevice(): void;
638
+ readConsent(): ConsentCookieState | null;
639
+ writeConsent(state: ConsentCookieState): void;
640
+ /** Engine-facing backend for the consent key, so consent decisions land in the same place. */
641
+ consentBackend(): StorageBackend;
642
+ }
643
+ //#endregion
644
+ //#region src/client.d.ts
645
+ interface ReoptClientDefaults {
646
+ /** Whether `init()` sends the first `$pageview`. The Next entry says no. */
647
+ pageview: boolean;
648
+ }
649
+ /**
650
+ * The browser client: the shared engine plus everything that only makes
651
+ * sense in a document — cookie identity, tracing headers, page leave,
652
+ * scroll depth, exception capture, and a clock corrected against the
653
+ * server's.
654
+ */
655
+ /**
656
+ * What to attach to a manual `captureException`.
657
+ *
658
+ * The second argument used to be a bare properties bag. That shape is still
659
+ * accepted, so no existing call site has to change — see
660
+ * {@link readCaptureExceptionOptions} for how the two are told apart.
661
+ */
662
+ interface CaptureExceptionOptions {
663
+ /** Group this error yourself instead of letting the server fingerprint it. */
664
+ fingerprint?: string | undefined;
665
+ level?: ExceptionLevel | undefined;
666
+ properties?: Record<string, unknown> | undefined;
667
+ }
668
+ declare class ReoptClient extends ReoptCore {
669
+ readonly writeKey: string;
670
+ readonly capture: ResolvedCaptureConfig;
671
+ private readonly store;
672
+ private readonly pageLeave;
673
+ private readonly scroll;
674
+ private readonly uninstallers;
675
+ private torndown;
676
+ /** The lazily-loaded exception chunk, once it has resolved. */
677
+ private exceptionChunk;
678
+ private exceptionChunkPromise;
679
+ private readonly session;
680
+ private readonly optedOut;
681
+ private readonly normalize;
682
+ private readonly observer;
683
+ /** True when `writeKey` or `baseUrl` was missing: every call is a silent no-op. */
684
+ readonly disabled: boolean;
685
+ constructor(config: ReoptClientConfig, defaults?: ReoptClientDefaults);
686
+ /** Which store identity ended up in — `cookie`, `localStorage` or `memory`. */
687
+ get identityStorage(): IdentityStore["kind"];
688
+ private observe;
689
+ private observeIdentity;
690
+ private observeEvent;
691
+ track(options: TrackEventOptions): QueueResult;
692
+ pageView(options?: PageViewOptions): QueueResult;
693
+ setConsent(category: ConsentCategory, allowed: boolean): void;
694
+ setAllConsent(allowed: boolean): void;
695
+ replaceConsentState(state: Record<string, boolean>): void;
696
+ pauseTracking(): void;
697
+ resumeTracking(): void;
698
+ setProfileId(profileId: string | number | null): void;
699
+ /**
700
+ * Refusing `analytics` removes the stored identity (the proxy does the
701
+ * same on its side); granting it again writes the current device through
702
+ * so the visit is attributable from that point on.
703
+ */
704
+ private syncOptOut;
705
+ identify(options: IdentifyOptions): QueueResult;
706
+ increment(options: IncrementOptions): QueueResult;
707
+ decrement(options: DecrementOptions): QueueResult;
708
+ /** Feed a Web Vitals metric (from `next/web-vitals` or the `web-vitals` package). */
709
+ captureWebVital(metric: WebVitalMetric): QueueResult;
710
+ /** The page's path through `normalizePath`, for events the SDK stamps itself. */
711
+ private currentPath;
712
+ /**
713
+ * Report an error you caught yourself.
714
+ *
715
+ * The stack parsers live in a lazily-loaded chunk — they are several times
716
+ * the size budget's remaining headroom, and a page that never throws should
717
+ * not pay for them. So the first call before that chunk resolves reports the
718
+ * flat keys only (name, message, raw stack) and starts the load; every call
719
+ * after it carries the structured `$exception_list` too. The server groups
720
+ * both: without a list it falls back to V1 fingerprinting on the flat keys.
721
+ */
722
+ captureException(error: unknown, optionsOrProperties?: CaptureExceptionOptions | Record<string, unknown>): QueueResult;
723
+ /**
724
+ * Record a breadcrumb for the next exception.
725
+ *
726
+ * Always available, whether or not automatic steps are on: a host that wants
727
+ * to leave its own trail should not have to opt into the SDK leaving one too.
728
+ */
729
+ addExceptionStep(step: ExceptionStepInput): void;
730
+ /** Loads the exception chunk once and remembers it, so manual captures can use the parsers. */
731
+ private loadExceptionChunk;
732
+ private trackException;
733
+ private emitPageLeave;
734
+ /**
735
+ * Log out: forget the profile and the queue, and become a new device.
736
+ * On a shared computer the next person must not inherit this one's
737
+ * history.
738
+ */
739
+ reset(): void;
740
+ close(): Promise<FlushResult>;
741
+ }
742
+ //#endregion
743
+ export { QueueDropReason as A, FetchInit as C, IdentifyOptions as D, FlushResult as E, UTMParams as F, RetryConfig as M, StorageBackend as N, IncrementOptions as O, TrackEventOptions as P, EventPayload as S, FetchResponseLike as T, CircuitBreakerConfig as _, IdentityConfig as a, DecrementOptions as b, ReoptBootstrap as c, ReoptClientObserver as d, ReoptObservedEventType as f, BatchConfig as g, ExceptionStepInput as h, CaptureConfig as i, QueueResult as j, PageViewOptions as k, ReoptClientConfig as l, WebVitalProperties as m, ReoptClient as n, IdentityStorageKind as o, WebVitalMetric as p, ReoptClientDefaults as r, NormalizePath as s, CaptureExceptionOptions as t, ReoptClientObservation as u, ConsentCategory as v, FetchLike as w, EventIdentity as x, ConsentConfig as y };
744
+ //# sourceMappingURL=client-BCrui21p.d.cts.map