@groundcover/browser 2.0.0-rc.0 → 2.0.0-rc.1

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/CHANGELOG.md CHANGED
@@ -4,6 +4,51 @@ All notable changes to `@groundcover/browser` are documented here. This project
4
4
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and the
5
5
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format.
6
6
 
7
+ ## [2.0.0-rc.1] — 2026-09-29
8
+
9
+ Second release candidate of `2.0.0`. Network and exception shaping move into the core shared with
10
+ `@groundcover/react-native`. The `/json/rum` envelope is unchanged; the changes below are the only
11
+ differences on the wire.
12
+
13
+ ### Fixed
14
+
15
+ - **`tracing.propagationUrls` treats only `*` as a wildcard.** Every other character kept its regex
16
+ meaning, so `https://api.example.com/*` also matched `https://api-example.com/…` and trace headers
17
+ (plus any `tracing.origin` header) were sent to lookalike hosts.
18
+ - **A path pattern such as `"/api/*"` matches same-origin requests only, whether they are written as
19
+ relative or absolute URLs.** XHR requests opened with a relative URL were never matched (XHR stores
20
+ the resolved URL), and a protocol-relative `//other-host/api/…` was. Patterns are matched against
21
+ the URL the browser actually requests, so `https://app/api/../private` no longer matches
22
+ `https://app/api/*`.
23
+ - **`fetch` events keep their trace ids when a configured header name has capitals.** `fetch` stores
24
+ request headers lowercased, so `traceIdHeaderName: "X-Trace-Id"` or
25
+ `propagationHeaders: ["X-Custom"]` never matched on read-back.
26
+ - **A read-only `fetch` no longer costs the XHR capture** (and no longer throws out of
27
+ initialization); the two transports are instrumented independently.
28
+ - **Navigation instrumentation wraps the history methods present at initialization**, keeping a
29
+ router that wrapped them after the SDK was constructed.
30
+
31
+ ### Changed
32
+
33
+ - **`span_name` carries the upper-cased method**, like `operation.name`: `fetch(url, { method: "post" })`
34
+ is the span `POST /path`, not a separate `post /path`. A missing method reads `UNKNOWN`.
35
+ - **An opaque host object passed without a key is labelled `opaque_node`** (was `dom_node`) by the
36
+ enricher's placeholder. Keyed placeholders are unchanged.
37
+
38
+ ## [2.0.0-rc.0] — 2026-09-28
39
+
40
+ First release candidate of `2.0.0`. **Contains breaking changes from `1.x`** — see
41
+ [Migrating from 1.x to 2.0.0](./README.md#migrating-from-1x-to-200).
42
+
43
+ ### Changed (breaking)
44
+
45
+ - **Event-level sampling is removed.** `options.eventSampleRate` warns and is ignored, on `init` and
46
+ on `updateConfig`; use `options.sessionSampleRate` to select whole sessions. Rates are not
47
+ converted.
48
+ - **`appId` is required and fixed per SDK instance.** It must be a non-blank string, its value is
49
+ preserved exactly, the first successful `init` wins (later calls are ignored; a failed init may be
50
+ retried), and `updateConfig` rejects any update that contains `appId`.
51
+
7
52
  ## [1.0.9]
8
53
 
9
54
  Stable release of `1.0.9-rc.0`. The shipped `dist/` is byte-for-byte the RC's — nothing landed after
package/README.md CHANGED
@@ -145,7 +145,7 @@ Distributed-tracing header propagation for outgoing requests.
145
145
 
146
146
  | Option | Type | Default | Description |
147
147
  |---|---|---|---|
148
- | `propagationUrls` | `string[]` | `[]` | Request URLs (prefix/`*`-glob match) that receive injected tracing headers. |
148
+ | `propagationUrls` | `string[]` | `[]` | Request URLs that receive injected tracing headers. Each pattern must match the whole URL; only `*` is a wildcard. A path pattern such as `"/api/*"` matches same-origin requests only. |
149
149
  | `propagationHeaders` | `string[]` | `[]` | Header names to read/propagate onto traced requests. |
150
150
  | `traceIdHeaderName` | `string` | `""` | Header carrying the trace id. |
151
151
  | `spanIdHeaderName` | `string` | `""` | Header carrying the span id. |
@@ -521,7 +521,7 @@ successful initialization. These are breaking changes; review your initializatio
521
521
  updates before upgrading:
522
522
 
523
523
  ```bash
524
- npm install @groundcover/browser@2.0.0-rc.0
524
+ npm install @groundcover/browser@2.0.0-rc.1
525
525
  ```
526
526
 
527
527
  | Change | Migration |
package/dist/index.d.mts CHANGED
@@ -1,14 +1,9 @@
1
- /**
2
- * The event kinds the browser SDK ships today. This is the DEFAULT vocabulary,
3
- * not the only permitted one — see `BaseEvent`.
4
- */
5
- type KnownEventType = "dom.event" | "exception" | "network" | "log" | "pageload" | "navigation" | "custom" | "performance" | "replay";
6
1
  /**
7
2
  * `TType` lets a platform name its own event kinds without editing core, and every core class
8
- * flows it through. Defaults to `KnownEventType`, so callers dealing only in browser kinds need
9
- * not spell it out. Shared shapes stay shared — the set of NAMES is open, not the envelope.
3
+ * flows it through. Defaults to `string`, because the set of NAMES is open — a platform that
4
+ * wants a closed union passes its own. Shared shapes stay shared; only the vocabulary is open.
10
5
  */
11
- type BaseEvent<TType extends string = KnownEventType> = {
6
+ type BaseEvent<TType extends string = string> = {
12
7
  type: TType;
13
8
  timestamp?: number;
14
9
  end_timestamp?: number;
@@ -28,30 +23,6 @@ type UserIdentifiers = {
28
23
  organization: string;
29
24
  properties: Record<string, unknown>;
30
25
  };
31
- type DomEventAttributes = {
32
- dom_event_type: string;
33
- dom_event_coordinates: {
34
- clientX: number;
35
- clientY: number;
36
- };
37
- dom_event_target: {
38
- tagName: string;
39
- id: string;
40
- className: string;
41
- text: string;
42
- role: string;
43
- accessibleName: string;
44
- ariaLabel: string;
45
- title: string;
46
- alt: string;
47
- placeholder: string;
48
- name: string;
49
- inputType: string;
50
- href: string;
51
- };
52
- dom_event_selector: string;
53
- dom_event_key_code: string;
54
- };
55
26
  type NetworkEventAttributes = {
56
27
  type: "HTTP";
57
28
  resource_name: string;
@@ -114,31 +85,6 @@ type LogEventAttributes = {
114
85
  message: string;
115
86
  level: string;
116
87
  } & Record<string, unknown>;
117
- type PageLoadEventAttributes = {
118
- page_url: string;
119
- page_resources: {
120
- count: number;
121
- totalSize: number;
122
- totalDuration: number;
123
- byType: {
124
- [key: string]: {
125
- count: number;
126
- size: number;
127
- duration: number;
128
- };
129
- };
130
- };
131
- page_referrer: string;
132
- page_load_time: number;
133
- };
134
- type NavigationEventAttributes = {
135
- page_url: string;
136
- from_url?: string;
137
- metadata?: Record<string, unknown>;
138
- duration_ms: number;
139
- start_timestamp: number;
140
- end_timestamp: number;
141
- };
142
88
  type UserDefinedEventAttributes = {
143
89
  custom_event_name: string;
144
90
  custom_event_attributes?: Record<string, unknown>;
@@ -149,44 +95,9 @@ type PerformanceEventAttributes = {
149
95
  performance_metric_id: string;
150
96
  performance_metric_navigation_type: string;
151
97
  };
152
- type ReplayEventAttributes = {
153
- /**
154
- * Groundcover session replay payload.
155
- *
156
- * NOTE: This key is intentionally prefixed to avoid collisions with customer attributes.
157
- */
158
- _gc_replay_data: {
159
- events: string[];
160
- };
161
- /**
162
- * Indicates this batch starts with a full DOM snapshot.
163
- * Full snapshots are taken at regular intervals to allow seeking directly to any point.
164
- * Queryable for filtering/indexing purposes.
165
- */
166
- replay_is_full_snapshot?: boolean;
167
- /**
168
- * Timestamp when the full snapshot was taken (if replay_is_full_snapshot is true).
169
- */
170
- replay_full_snapshot_timestamp?: number;
171
- };
172
98
 
173
- type Event$1<T extends string, A> = Omit<BaseEvent<T>, "attributes"> & {
174
- type: T;
175
- attributes: A;
176
- };
177
- type EventTypes$1 = {
178
- "dom.event": Event$1<"dom.event", DomEventAttributes>;
179
- exception: Event$1<"exception", ErrorEventAttributes>;
180
- network: Event$1<"network", NetworkEventAttributes>;
181
- log: Event$1<"log", LogEventAttributes>;
182
- pageload: Event$1<"pageload", PageLoadEventAttributes>;
183
- navigation: Event$1<"navigation", NavigationEventAttributes>;
184
- custom: Event$1<"custom", UserDefinedEventAttributes>;
185
- performance: Event$1<"performance", PerformanceEventAttributes>;
186
- replay: Event$1<"replay", ReplayEventAttributes>;
187
- };
188
99
  type PrivacyLevel = "mask-sensitive" | "mask-all" | "allow";
189
- /** The non-replay event surface a redactor field belongs to. */
100
+ /** The event surface a redactor field belongs to. */
190
101
  type RedactKind = "request-body" | "response-body" | "query" | "header" | "log" | "error";
191
102
  interface RedactField {
192
103
  /** Immediate key of the value; `""` for whole-string fields (log/error message). */
@@ -228,23 +139,19 @@ interface PrivacyOptions$1 {
228
139
  /** Extra case-insensitive key substrings treated as sensitive, merged with the built-in patterns. */
229
140
  sensitiveKeys?: string[];
230
141
  /**
231
- * Per-field custom redaction hook for non-replay events. Called on each leaf
142
+ * Per-field custom redaction hook for captured events. Called on each leaf
232
143
  * value during the redaction walk with the original typed value; see
233
144
  * {@link Redactor}. For arbitrary whole-event changes use `enrichEvent`.
234
145
  */
235
146
  redact?: Redactor;
236
- /**
237
- * Session-recording masking — replay is a platform feature (rrweb on the
238
- * browser), so its masking surface is typed by the platform package: the
239
- * browser SDK narrows this to `{ maskTextFn?, maskInputFn? }` over
240
- * HTMLElement (see the browser package's `config/types.ts`). Core never
241
- * reads it — it is resolved platform-side at record() time.
242
- */
243
- replay?: unknown;
244
147
  }
245
148
  /** Distributed-tracing header propagation for outgoing network requests. */
246
149
  interface TracingOptions {
247
- /** Request URLs (prefix match) that receive injected tracing headers. */
150
+ /**
151
+ * Request URLs that receive injected tracing headers: whole-URL matches where
152
+ * only `*` is a wildcard. Which strings a pattern is matched against is the
153
+ * platform's (the browser adds a same-origin request's path).
154
+ */
248
155
  propagationUrls?: string[];
249
156
  /** Inbound header names to read/propagate onto traced requests. */
250
157
  propagationHeaders?: string[];
@@ -264,24 +171,23 @@ interface TransportOptions {
264
171
  batchSize?: number;
265
172
  /** Max ms a batch waits before flushing regardless of size (default 10000). */
266
173
  batchTimeout?: number;
267
- /** Gzip-compress outgoing batches; offloaded to the Web Worker when available (default true). */
174
+ /** Gzip-compress outgoing batches; offloaded to the platform's async encoder when it has one (default true). */
268
175
  compression?: boolean;
269
176
  }
270
- interface SDKOptions$1<TEvent extends BaseEvent<string> = EventTypes$1[keyof EventTypes$1]> {
177
+ interface SDKOptions$1<TEvent extends BaseEvent<string> = BaseEvent<string>> {
271
178
  /**
272
179
  * Which signal listeners to enable, by name. Empty array = all. The NAMES
273
180
  * are platform-defined (each platform ships its own listener set) — the
274
- * platform package narrows this to its literal union (see the browser
275
- * package's `config/types.ts`).
181
+ * platform package narrows this to its literal union.
276
182
  */
277
183
  enabledEvents: string[];
278
184
  sessionSampleRate: number;
279
185
  debug: boolean;
280
186
  excludedUrls?: Array<string | RegExp>;
281
- beforeSend?: (event: TEvent) => boolean;
282
- enrichEvent?: (event: TEvent) => TEvent;
187
+ beforeSend?(event: TEvent): boolean;
188
+ enrichEvent?(event: TEvent): TEvent;
283
189
  /**
284
- * Unified privacy / data-masking config driving replay + non-replay masking.
190
+ * Unified privacy / data-masking config for every captured surface.
285
191
  * ON by default (`level: 'mask-sensitive'`); see {@link PrivacyOptions}.
286
192
  */
287
193
  privacy?: PrivacyOptions$1;
@@ -289,15 +195,9 @@ interface SDKOptions$1<TEvent extends BaseEvent<string> = EventTypes$1[keyof Eve
289
195
  tracing?: TracingOptions;
290
196
  /** Batching & delivery of outgoing events; see {@link TransportOptions}. */
291
197
  transport?: TransportOptions;
292
- /**
293
- * Session-recording controls — a platform feature slot core never reads.
294
- * The platform package types it (the browser SDK narrows this to its
295
- * rrweb `ReplayOptions`; platforms without recording ignore it).
296
- */
297
- replay?: unknown;
298
198
  /**
299
199
  * Target maximum wall-clock duration of a session, in ms. Enforced LAZILY on activity, so NOT
300
- * a hard bound — an idle tab keeps its id past the cap, which deliberately avoids minting
200
+ * a hard bound — an idle session keeps its id past the cap, which deliberately avoids minting
301
201
  * phantom sessions. Also bounded by a 30-minute inactivity gap, counting raw input as
302
202
  * presence so passive reading does not end a session.
303
203
  *
@@ -305,7 +205,7 @@ interface SDKOptions$1<TEvent extends BaseEvent<string> = EventTypes$1[keyof Eve
305
205
  */
306
206
  sessionMaxDuration?: number;
307
207
  }
308
- interface SDKConfigInput$1<TEvent extends BaseEvent<string> = EventTypes$1[keyof EventTypes$1]> {
208
+ interface SDKConfigInput$1<TEvent extends BaseEvent<string> = BaseEvent<string>> {
309
209
  apiKey: string;
310
210
  cluster: string;
311
211
  environment: string;
@@ -318,6 +218,76 @@ interface SDKConfigInput$1<TEvent extends BaseEvent<string> = EventTypes$1[keyof
318
218
  sessionId?: string;
319
219
  }
320
220
 
221
+ type DomEventAttributes = {
222
+ dom_event_type: string;
223
+ dom_event_coordinates: {
224
+ clientX: number;
225
+ clientY: number;
226
+ };
227
+ dom_event_target: {
228
+ tagName: string;
229
+ id: string;
230
+ className: string;
231
+ text: string;
232
+ role: string;
233
+ accessibleName: string;
234
+ ariaLabel: string;
235
+ title: string;
236
+ alt: string;
237
+ placeholder: string;
238
+ name: string;
239
+ inputType: string;
240
+ href: string;
241
+ };
242
+ dom_event_selector: string;
243
+ dom_event_key_code: string;
244
+ };
245
+ type PageLoadEventAttributes = {
246
+ page_url: string;
247
+ page_resources: {
248
+ count: number;
249
+ totalSize: number;
250
+ totalDuration: number;
251
+ byType: {
252
+ [key: string]: {
253
+ count: number;
254
+ size: number;
255
+ duration: number;
256
+ };
257
+ };
258
+ };
259
+ page_referrer: string;
260
+ page_load_time: number;
261
+ };
262
+ type NavigationEventAttributes = {
263
+ page_url: string;
264
+ from_url?: string;
265
+ metadata?: Record<string, unknown>;
266
+ duration_ms: number;
267
+ start_timestamp: number;
268
+ end_timestamp: number;
269
+ };
270
+ type ReplayEventAttributes = {
271
+ /**
272
+ * Groundcover session replay payload.
273
+ *
274
+ * NOTE: This key is intentionally prefixed to avoid collisions with customer attributes.
275
+ */
276
+ _gc_replay_data: {
277
+ events: string[];
278
+ };
279
+ /**
280
+ * Indicates this batch starts with a full DOM snapshot.
281
+ * Full snapshots are taken at regular intervals to allow seeking directly to any point.
282
+ * Queryable for filtering/indexing purposes.
283
+ */
284
+ replay_is_full_snapshot?: boolean;
285
+ /**
286
+ * Timestamp when the full snapshot was taken (if replay_is_full_snapshot is true).
287
+ */
288
+ replay_full_snapshot_timestamp?: number;
289
+ };
290
+
321
291
  /**
322
292
  * The view an event was captured on. Browser-owned: core has no notion of a
323
293
  * "current view" — it merges whatever the platform's `enrichAttributes`
@@ -377,13 +347,13 @@ interface ReplayMaskingOptions {
377
347
  /** rrweb `maskInputFn` pass-through. */
378
348
  maskInputFn?: (text: string, el: HTMLElement) => string;
379
349
  }
380
- interface PrivacyOptions extends Omit<PrivacyOptions$1, "replay"> {
350
+ interface PrivacyOptions extends PrivacyOptions$1 {
381
351
  /** CSS selectors whose text/inputs are always masked (replay + DOM), regardless of `level` except `'allow'`. */
382
352
  maskSelectors?: string[];
383
353
  /** Session-recording (rrweb replay) masking — the only place replay can be masked. */
384
354
  replay?: ReplayMaskingOptions;
385
355
  }
386
- interface SDKOptions extends Omit<SDKOptions$1, "privacy" | "replay" | "enabledEvents" | "beforeSend" | "enrichEvent"> {
356
+ interface SDKOptions extends Omit<SDKOptions$1, "privacy" | "enabledEvents" | "beforeSend" | "enrichEvent"> {
387
357
  /**
388
358
  * Inspect each event before it is queued; return false to drop it. Typed
389
359
  * over the BROWSER event map, so `attributes.location` is visible here.
package/dist/index.d.ts CHANGED
@@ -1,14 +1,9 @@
1
- /**
2
- * The event kinds the browser SDK ships today. This is the DEFAULT vocabulary,
3
- * not the only permitted one — see `BaseEvent`.
4
- */
5
- type KnownEventType = "dom.event" | "exception" | "network" | "log" | "pageload" | "navigation" | "custom" | "performance" | "replay";
6
1
  /**
7
2
  * `TType` lets a platform name its own event kinds without editing core, and every core class
8
- * flows it through. Defaults to `KnownEventType`, so callers dealing only in browser kinds need
9
- * not spell it out. Shared shapes stay shared — the set of NAMES is open, not the envelope.
3
+ * flows it through. Defaults to `string`, because the set of NAMES is open — a platform that
4
+ * wants a closed union passes its own. Shared shapes stay shared; only the vocabulary is open.
10
5
  */
11
- type BaseEvent<TType extends string = KnownEventType> = {
6
+ type BaseEvent<TType extends string = string> = {
12
7
  type: TType;
13
8
  timestamp?: number;
14
9
  end_timestamp?: number;
@@ -28,30 +23,6 @@ type UserIdentifiers = {
28
23
  organization: string;
29
24
  properties: Record<string, unknown>;
30
25
  };
31
- type DomEventAttributes = {
32
- dom_event_type: string;
33
- dom_event_coordinates: {
34
- clientX: number;
35
- clientY: number;
36
- };
37
- dom_event_target: {
38
- tagName: string;
39
- id: string;
40
- className: string;
41
- text: string;
42
- role: string;
43
- accessibleName: string;
44
- ariaLabel: string;
45
- title: string;
46
- alt: string;
47
- placeholder: string;
48
- name: string;
49
- inputType: string;
50
- href: string;
51
- };
52
- dom_event_selector: string;
53
- dom_event_key_code: string;
54
- };
55
26
  type NetworkEventAttributes = {
56
27
  type: "HTTP";
57
28
  resource_name: string;
@@ -114,31 +85,6 @@ type LogEventAttributes = {
114
85
  message: string;
115
86
  level: string;
116
87
  } & Record<string, unknown>;
117
- type PageLoadEventAttributes = {
118
- page_url: string;
119
- page_resources: {
120
- count: number;
121
- totalSize: number;
122
- totalDuration: number;
123
- byType: {
124
- [key: string]: {
125
- count: number;
126
- size: number;
127
- duration: number;
128
- };
129
- };
130
- };
131
- page_referrer: string;
132
- page_load_time: number;
133
- };
134
- type NavigationEventAttributes = {
135
- page_url: string;
136
- from_url?: string;
137
- metadata?: Record<string, unknown>;
138
- duration_ms: number;
139
- start_timestamp: number;
140
- end_timestamp: number;
141
- };
142
88
  type UserDefinedEventAttributes = {
143
89
  custom_event_name: string;
144
90
  custom_event_attributes?: Record<string, unknown>;
@@ -149,44 +95,9 @@ type PerformanceEventAttributes = {
149
95
  performance_metric_id: string;
150
96
  performance_metric_navigation_type: string;
151
97
  };
152
- type ReplayEventAttributes = {
153
- /**
154
- * Groundcover session replay payload.
155
- *
156
- * NOTE: This key is intentionally prefixed to avoid collisions with customer attributes.
157
- */
158
- _gc_replay_data: {
159
- events: string[];
160
- };
161
- /**
162
- * Indicates this batch starts with a full DOM snapshot.
163
- * Full snapshots are taken at regular intervals to allow seeking directly to any point.
164
- * Queryable for filtering/indexing purposes.
165
- */
166
- replay_is_full_snapshot?: boolean;
167
- /**
168
- * Timestamp when the full snapshot was taken (if replay_is_full_snapshot is true).
169
- */
170
- replay_full_snapshot_timestamp?: number;
171
- };
172
98
 
173
- type Event$1<T extends string, A> = Omit<BaseEvent<T>, "attributes"> & {
174
- type: T;
175
- attributes: A;
176
- };
177
- type EventTypes$1 = {
178
- "dom.event": Event$1<"dom.event", DomEventAttributes>;
179
- exception: Event$1<"exception", ErrorEventAttributes>;
180
- network: Event$1<"network", NetworkEventAttributes>;
181
- log: Event$1<"log", LogEventAttributes>;
182
- pageload: Event$1<"pageload", PageLoadEventAttributes>;
183
- navigation: Event$1<"navigation", NavigationEventAttributes>;
184
- custom: Event$1<"custom", UserDefinedEventAttributes>;
185
- performance: Event$1<"performance", PerformanceEventAttributes>;
186
- replay: Event$1<"replay", ReplayEventAttributes>;
187
- };
188
99
  type PrivacyLevel = "mask-sensitive" | "mask-all" | "allow";
189
- /** The non-replay event surface a redactor field belongs to. */
100
+ /** The event surface a redactor field belongs to. */
190
101
  type RedactKind = "request-body" | "response-body" | "query" | "header" | "log" | "error";
191
102
  interface RedactField {
192
103
  /** Immediate key of the value; `""` for whole-string fields (log/error message). */
@@ -228,23 +139,19 @@ interface PrivacyOptions$1 {
228
139
  /** Extra case-insensitive key substrings treated as sensitive, merged with the built-in patterns. */
229
140
  sensitiveKeys?: string[];
230
141
  /**
231
- * Per-field custom redaction hook for non-replay events. Called on each leaf
142
+ * Per-field custom redaction hook for captured events. Called on each leaf
232
143
  * value during the redaction walk with the original typed value; see
233
144
  * {@link Redactor}. For arbitrary whole-event changes use `enrichEvent`.
234
145
  */
235
146
  redact?: Redactor;
236
- /**
237
- * Session-recording masking — replay is a platform feature (rrweb on the
238
- * browser), so its masking surface is typed by the platform package: the
239
- * browser SDK narrows this to `{ maskTextFn?, maskInputFn? }` over
240
- * HTMLElement (see the browser package's `config/types.ts`). Core never
241
- * reads it — it is resolved platform-side at record() time.
242
- */
243
- replay?: unknown;
244
147
  }
245
148
  /** Distributed-tracing header propagation for outgoing network requests. */
246
149
  interface TracingOptions {
247
- /** Request URLs (prefix match) that receive injected tracing headers. */
150
+ /**
151
+ * Request URLs that receive injected tracing headers: whole-URL matches where
152
+ * only `*` is a wildcard. Which strings a pattern is matched against is the
153
+ * platform's (the browser adds a same-origin request's path).
154
+ */
248
155
  propagationUrls?: string[];
249
156
  /** Inbound header names to read/propagate onto traced requests. */
250
157
  propagationHeaders?: string[];
@@ -264,24 +171,23 @@ interface TransportOptions {
264
171
  batchSize?: number;
265
172
  /** Max ms a batch waits before flushing regardless of size (default 10000). */
266
173
  batchTimeout?: number;
267
- /** Gzip-compress outgoing batches; offloaded to the Web Worker when available (default true). */
174
+ /** Gzip-compress outgoing batches; offloaded to the platform's async encoder when it has one (default true). */
268
175
  compression?: boolean;
269
176
  }
270
- interface SDKOptions$1<TEvent extends BaseEvent<string> = EventTypes$1[keyof EventTypes$1]> {
177
+ interface SDKOptions$1<TEvent extends BaseEvent<string> = BaseEvent<string>> {
271
178
  /**
272
179
  * Which signal listeners to enable, by name. Empty array = all. The NAMES
273
180
  * are platform-defined (each platform ships its own listener set) — the
274
- * platform package narrows this to its literal union (see the browser
275
- * package's `config/types.ts`).
181
+ * platform package narrows this to its literal union.
276
182
  */
277
183
  enabledEvents: string[];
278
184
  sessionSampleRate: number;
279
185
  debug: boolean;
280
186
  excludedUrls?: Array<string | RegExp>;
281
- beforeSend?: (event: TEvent) => boolean;
282
- enrichEvent?: (event: TEvent) => TEvent;
187
+ beforeSend?(event: TEvent): boolean;
188
+ enrichEvent?(event: TEvent): TEvent;
283
189
  /**
284
- * Unified privacy / data-masking config driving replay + non-replay masking.
190
+ * Unified privacy / data-masking config for every captured surface.
285
191
  * ON by default (`level: 'mask-sensitive'`); see {@link PrivacyOptions}.
286
192
  */
287
193
  privacy?: PrivacyOptions$1;
@@ -289,15 +195,9 @@ interface SDKOptions$1<TEvent extends BaseEvent<string> = EventTypes$1[keyof Eve
289
195
  tracing?: TracingOptions;
290
196
  /** Batching & delivery of outgoing events; see {@link TransportOptions}. */
291
197
  transport?: TransportOptions;
292
- /**
293
- * Session-recording controls — a platform feature slot core never reads.
294
- * The platform package types it (the browser SDK narrows this to its
295
- * rrweb `ReplayOptions`; platforms without recording ignore it).
296
- */
297
- replay?: unknown;
298
198
  /**
299
199
  * Target maximum wall-clock duration of a session, in ms. Enforced LAZILY on activity, so NOT
300
- * a hard bound — an idle tab keeps its id past the cap, which deliberately avoids minting
200
+ * a hard bound — an idle session keeps its id past the cap, which deliberately avoids minting
301
201
  * phantom sessions. Also bounded by a 30-minute inactivity gap, counting raw input as
302
202
  * presence so passive reading does not end a session.
303
203
  *
@@ -305,7 +205,7 @@ interface SDKOptions$1<TEvent extends BaseEvent<string> = EventTypes$1[keyof Eve
305
205
  */
306
206
  sessionMaxDuration?: number;
307
207
  }
308
- interface SDKConfigInput$1<TEvent extends BaseEvent<string> = EventTypes$1[keyof EventTypes$1]> {
208
+ interface SDKConfigInput$1<TEvent extends BaseEvent<string> = BaseEvent<string>> {
309
209
  apiKey: string;
310
210
  cluster: string;
311
211
  environment: string;
@@ -318,6 +218,76 @@ interface SDKConfigInput$1<TEvent extends BaseEvent<string> = EventTypes$1[keyof
318
218
  sessionId?: string;
319
219
  }
320
220
 
221
+ type DomEventAttributes = {
222
+ dom_event_type: string;
223
+ dom_event_coordinates: {
224
+ clientX: number;
225
+ clientY: number;
226
+ };
227
+ dom_event_target: {
228
+ tagName: string;
229
+ id: string;
230
+ className: string;
231
+ text: string;
232
+ role: string;
233
+ accessibleName: string;
234
+ ariaLabel: string;
235
+ title: string;
236
+ alt: string;
237
+ placeholder: string;
238
+ name: string;
239
+ inputType: string;
240
+ href: string;
241
+ };
242
+ dom_event_selector: string;
243
+ dom_event_key_code: string;
244
+ };
245
+ type PageLoadEventAttributes = {
246
+ page_url: string;
247
+ page_resources: {
248
+ count: number;
249
+ totalSize: number;
250
+ totalDuration: number;
251
+ byType: {
252
+ [key: string]: {
253
+ count: number;
254
+ size: number;
255
+ duration: number;
256
+ };
257
+ };
258
+ };
259
+ page_referrer: string;
260
+ page_load_time: number;
261
+ };
262
+ type NavigationEventAttributes = {
263
+ page_url: string;
264
+ from_url?: string;
265
+ metadata?: Record<string, unknown>;
266
+ duration_ms: number;
267
+ start_timestamp: number;
268
+ end_timestamp: number;
269
+ };
270
+ type ReplayEventAttributes = {
271
+ /**
272
+ * Groundcover session replay payload.
273
+ *
274
+ * NOTE: This key is intentionally prefixed to avoid collisions with customer attributes.
275
+ */
276
+ _gc_replay_data: {
277
+ events: string[];
278
+ };
279
+ /**
280
+ * Indicates this batch starts with a full DOM snapshot.
281
+ * Full snapshots are taken at regular intervals to allow seeking directly to any point.
282
+ * Queryable for filtering/indexing purposes.
283
+ */
284
+ replay_is_full_snapshot?: boolean;
285
+ /**
286
+ * Timestamp when the full snapshot was taken (if replay_is_full_snapshot is true).
287
+ */
288
+ replay_full_snapshot_timestamp?: number;
289
+ };
290
+
321
291
  /**
322
292
  * The view an event was captured on. Browser-owned: core has no notion of a
323
293
  * "current view" — it merges whatever the platform's `enrichAttributes`
@@ -377,13 +347,13 @@ interface ReplayMaskingOptions {
377
347
  /** rrweb `maskInputFn` pass-through. */
378
348
  maskInputFn?: (text: string, el: HTMLElement) => string;
379
349
  }
380
- interface PrivacyOptions extends Omit<PrivacyOptions$1, "replay"> {
350
+ interface PrivacyOptions extends PrivacyOptions$1 {
381
351
  /** CSS selectors whose text/inputs are always masked (replay + DOM), regardless of `level` except `'allow'`. */
382
352
  maskSelectors?: string[];
383
353
  /** Session-recording (rrweb replay) masking — the only place replay can be masked. */
384
354
  replay?: ReplayMaskingOptions;
385
355
  }
386
- interface SDKOptions extends Omit<SDKOptions$1, "privacy" | "replay" | "enabledEvents" | "beforeSend" | "enrichEvent"> {
356
+ interface SDKOptions extends Omit<SDKOptions$1, "privacy" | "enabledEvents" | "beforeSend" | "enrichEvent"> {
387
357
  /**
388
358
  * Inspect each event before it is queued; return false to drop it. Typed
389
359
  * over the BROWSER event map, so `attributes.location` is visible here.