@groundcover/browser 2.1.1-rc.1 → 2.2.0-rc.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/CHANGELOG.md CHANGED
@@ -4,11 +4,72 @@ 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.1.1-rc.1] — 2026-10-13
7
+ ## [2.2.0-rc.0] — 2026-11-05
8
8
 
9
- Release candidate of `2.1.1`, on top of `2.1.0`. Session replay takes its periodic full snapshot
10
- every 5 minutes instead of every 30 seconds. No configuration or API changes. Supersedes
11
- `2.1.1-rc.0`, which tried moving checkouts to idle time instead and was not pursued.
9
+ First release candidate of `2.2.0`. Issues for thrown or rejected values that aren't `Error`s start
10
+ new groups once; see Changed.
11
+
12
+ ### Added
13
+
14
+ - **Third-party notices.** The package now ships `THIRD_PARTY_NOTICES.md` with the MIT notices of
15
+ fflate and `@rrweb/packer`, whose code its session-replay compression worker bundles.
16
+ - **Unhandled rejections of Bluebird promises are reported.** Bluebird announces an unhandled
17
+ rejection with its own `unhandledrejection` event, which the SDK ignored; it is now reported by
18
+ its reason, like a native one.
19
+
20
+ ### Changed
21
+
22
+ - **`captureException` accepts any value, not only an `Error`.** A string, object or other value was
23
+ dropped without a word; it is now reported as an exception with `error_type` `Error`. A string or
24
+ number is its own message. An object is described by its shape, never its values, so captures of
25
+ the same kind group as one issue even when a field such as a request id changes:
26
+ `Object captured as exception with keys: code, requestId`, the class name for a class instance
27
+ (`Response captured as exception`), and an item count for an array. The value itself is sent in
28
+ `error_metadata.captured_value` as JSON, redacted field by field and cut at 10,000 characters. An
29
+ object with a string `message` keeps its own name, message and stack, and a DOM Event, such as an
30
+ image's `error` event, is described by its type and target
31
+ (`Event captured as exception (type=error, target=img)`).
32
+ - **`captureException` takes `unknown`.** Existing calls still compile, but a typed stand-in for it
33
+ written as `(error: Error) => …`, such as a test mock, no longer type-checks.
34
+ - **Thrown objects and rejection reasons that aren't `Error`s are described the same way.** A
35
+ rejection's reason was reported as its JSON, and a thrown object without a `message` as
36
+ `Unknown error`; both are now described by their shape
37
+ (`Object captured as promise rejection with keys: code`), with the value in
38
+ `error_metadata.captured_value`. Issues for such values start new groups once.
39
+ - **`error_message` is capped at 10,000 characters**, as log messages are. The fingerprint, made
40
+ from the first 400 characters, is unchanged.
41
+ - **The SDK no longer adds properties to your `Error` objects.** It defined read-only `fileName`,
42
+ `lineNumber` and `columnNumber` on every uncaught `Error` in Chromium and Safari, and nothing read
43
+ them.
44
+ - **`maskErrors` is documented as it works.** It redacts error messages and metadata; stack frames
45
+ are sent as they are.
46
+ - **The package `homepage` is the current documentation URL**, and the package's LICENSE carries its
47
+ copyright line.
48
+
49
+ ### Fixed
50
+
51
+ - **An uncaught throw of a non-`Error` value is reported at its throw site.** `throw "boom"` or
52
+ `throw 0` outside a promise made the SDK's error listener fail, so the error was dropped. It is now
53
+ an exception with the message `boom` and one stack frame at the location the browser reported.
54
+ - **An uncaught error whose message contains "Script error" is reported.** The SDK dropped every
55
+ such error, such as RequireJS's `Script error for "<module>"`; it now drops only the browser's
56
+ muted cross-origin `Script error.`, which carries nothing to report.
57
+ - **An unhandled rejection whose reason can't be serialized is reported.** A rejection with a
58
+ circular object as its reason made the SDK fail, so it was dropped.
59
+ - **A rejection reason's nested secrets are redacted.** Its JSON was scrubbed as free text, which
60
+ masked only the first line under a sensitive key such as `token` or `credit_card`; the reason is
61
+ now redacted field by field.
62
+ - **An `Error` from another frame keeps its name and message as a rejection reason.** A same-origin
63
+ iframe's `Error` failed the SDK's `instanceof Error` check and was reported as `{}`.
64
+
65
+ ## [2.1.1] — 2026-10-26
66
+
67
+ Stable release of `2.1.1-rc.1`. Session replay takes its periodic full snapshot every 5 minutes
68
+ instead of every 30 seconds. No configuration or API changes from `2.1.0`. `2.1.1-rc.0`, which tried
69
+ moving checkouts to idle time instead, was not pursued.
70
+
71
+ The type declarations are byte-for-byte those of `2.1.0` and rc.1. The shipped JavaScript differs
72
+ from rc.1 only in the text of the removed-option warnings below.
12
73
 
13
74
  ### Changed
14
75
 
@@ -20,6 +81,11 @@ every 5 minutes instead of every 30 seconds. No configuration or API changes. Su
20
81
  send 10× fewer full snapshots. Every recording still starts with a full snapshot. A player that
21
82
  seeks from the nearest earlier full snapshot may fetch more data to reach a point deep in a long
22
83
  recording.
84
+ - **The warnings for removed options point to this package's README on npm.** The console warnings
85
+ for `enableMasking`, `maskFields` and `eventSampleRate` now name the README section to read
86
+ ("Migrating to 1.0.0" or "Migrating from 1.x to 2.0.0") and link to the npm package page, instead
87
+ of a GitHub link.
88
+ - `package.json` no longer has `repository` and `bugs` fields.
23
89
 
24
90
  ## [2.1.0] — 2026-10-12
25
91
 
@@ -252,7 +318,7 @@ golden wire format, `attributes.location` intact, zero console errors).
252
318
 
253
319
  ### Fixed
254
320
 
255
- - **Fetch response bodies are now hardened like request bodies (FE-12851).** Responses are classified
321
+ - **Fetch response bodies are now hardened like request bodies.** Responses are classified
256
322
  by content-type (binary → placeholder, no mojibake) and their read is bounded by a timeout, so a
257
323
  slow or never-ending response stream can no longer stall the network event. An over-cap response is
258
324
  placeholdered instead of emitting an unredactable truncated slice.
@@ -325,6 +391,3 @@ These shipped ahead of 1.0.0 and are part of this major:
325
391
  worker, with a transparent main-thread fallback under strict CSP / sandboxed iframes / SSR.
326
392
  - **Configurable, lazily-enforced `sessionMaxDuration`** (default 4h, range 1 min–8h) plus 30-minute
327
393
  inactivity-gap session rotation.
328
-
329
- [1.0.1]: https://github.com/groundcover-com/rum/releases/tag/1.0.1
330
- [1.0.0]: https://github.com/groundcover-com/rum/releases/tag/1.0.0
package/LICENSE CHANGED
@@ -1,5 +1,7 @@
1
1
  MIT License
2
2
 
3
+ Copyright (c) 2025 groundcover
4
+
3
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
4
6
  this software and associated documentation files (the "Software"), to deal in
5
7
  the Software without restriction, including without limitation the rights to
package/README.md CHANGED
@@ -15,7 +15,7 @@ application — with privacy masking **on by default**.
15
15
 
16
16
  > Session replay is powered by [**rrweb**](https://github.com/rrweb-io/rrweb) under the hood.
17
17
 
18
- See the [groundcover RUM documentation](https://docs.groundcover.com/capabilities/real-user-monitoring-rum/)
18
+ See the [groundcover RUM documentation](https://docs.groundcover.com/investigate/real-user-monitoring-rum)
19
19
  for the full product guide.
20
20
 
21
21
  ---
@@ -351,7 +351,7 @@ and static page text stay visible; use `[data-private]` / `maskSelectors` to mas
351
351
  | `maskNetworkBodies` | `boolean` | `true` | Redact network request/response bodies. |
352
352
  | `maskNetworkQueryParams` | `boolean` | `true` | Redact URL query params. |
353
353
  | `maskLogs` | `boolean` | `true` | Redact console/log messages and attributes. |
354
- | `maskErrors` | `boolean` | `true` | Redact error messages, metadata and stack-frame URLs. |
354
+ | `maskErrors` | `boolean` | `true` | Redact error messages and metadata. Stack frames are sent as they are. |
355
355
  | `sensitiveKeys` | `string[]` | — | Extra case-insensitive key substrings treated as sensitive, merged with built-ins. |
356
356
  | `redact` | `(field) => value \| undefined` | — | Per-leaf custom redactor for non-replay events. Return `undefined` to defer to the SDK default. |
357
357
  | `replay.maskTextFn` | `(text, el) => string` | — | rrweb `maskTextFn` pass-through (replay only). |
@@ -545,7 +545,7 @@ All methods are available on the default export and on `window.groundcover`.
545
545
  | `init(config)` | Initialize the SDK and install instrumentation once; calls after successful initialization are ignored. |
546
546
  | `identifyUser(user)` | Attach user identity to subsequent events. |
547
547
  | `sendCustomEvent({ event, attributes })` | Emit a custom business event. |
548
- | `captureException(error, metadata?)` | Capture a handled error with optional context. |
548
+ | `captureException(error, metadata?)` | Capture a handled error (any value) with optional context. |
549
549
  | `logger.{log,info,warn,error,debug,trace}(message, attributes?)` | Structured logging (see below). |
550
550
  | `updateConfig({ options?, user?, … })` | Update config at runtime (merges nested groups one level deep). |
551
551
  | `startNavigation(metadata)` / `endNavigation(metadata)` | Manual navigation spans (when `navigation` isn’t auto-tracked). |
@@ -587,6 +587,22 @@ groundcover.captureException(new Error("Payment failed"), {
587
587
  });
588
588
  ```
589
589
 
590
+ `captureException` accepts any value, not only an `Error`. A string or number becomes the message.
591
+ An object is described by its shape, never its values, so captures of the same kind group as one
592
+ issue: `Object captured as exception with keys: code, reason`, the class name for a class instance
593
+ (`Response captured as exception`), or an item count for an array. The value itself is sent in
594
+ `error_metadata.captured_value` as JSON, redacted field by field and cut at 10,000 characters. An
595
+ object with a string `message` keeps its own name, message and stack, and a DOM Event is described
596
+ by its type and target (`Event captured as exception (type=error, target=img)`):
597
+
598
+ ```ts
599
+ groundcover.captureException("Payment failed");
600
+ groundcover.captureException({ code: 500, reason: "timeout" });
601
+ ```
602
+
603
+ Pass an `Error` when you can: a value that isn't one carries no stack trace of its own, so the
604
+ reported stack starts inside the SDK.
605
+
590
606
  ---
591
607
 
592
608
  ## Migrating from 1.x to 2.0.0
@@ -0,0 +1,68 @@
1
+ # Third-party notices
2
+
3
+ `@groundcover/browser` is licensed under the MIT License (see [LICENSE](LICENSE)).
4
+
5
+ The session-replay compression worker, which ships inlined in `dist/`, contains code from the
6
+ open-source projects below, whose notices follow.
7
+
8
+ The package's npm dependencies (`rrweb`, `@rrweb/packer`, `fflate`, `error-stack-parser` and
9
+ `web-vitals`) are installed alongside it under their own licenses and are not covered here.
10
+
11
+ ## fflate
12
+
13
+ <https://github.com/101arrowz/fflate>. The worker calls it directly (0.8), and `@rrweb/packer`
14
+ carries its own copy (0.4). The two releases carry the same license, with copyright years 2023
15
+ and 2020 respectively.
16
+
17
+ ```
18
+ MIT License
19
+
20
+ Copyright (c) 2023 Arjun Barrett
21
+ Copyright (c) 2020 Arjun Barrett
22
+
23
+ Permission is hereby granted, free of charge, to any person obtaining a copy
24
+ of this software and associated documentation files (the "Software"), to deal
25
+ in the Software without restriction, including without limitation the rights
26
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27
+ copies of the Software, and to permit persons to whom the Software is
28
+ furnished to do so, subject to the following conditions:
29
+
30
+ The above copyright notice and this permission notice shall be included in all
31
+ copies or substantial portions of the Software.
32
+
33
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39
+ SOFTWARE.
40
+ ```
41
+
42
+ ## @rrweb/packer
43
+
44
+ <https://github.com/rrweb-io/rrweb>, the package the worker uses to pack session-replay events.
45
+
46
+ ```
47
+ MIT License
48
+
49
+ Copyright (c) 2018 Contributors (https://github.com/rrweb-io/rrweb/graphs/contributors)
50
+
51
+ Permission is hereby granted, free of charge, to any person obtaining a copy
52
+ of this software and associated documentation files (the "Software"), to deal
53
+ in the Software without restriction, including without limitation the rights
54
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
55
+ copies of the Software, and to permit persons to whom the Software is
56
+ furnished to do so, subject to the following conditions:
57
+
58
+ The above copyright notice and this permission notice shall be included in all
59
+ copies or substantial portions of the Software.
60
+
61
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
64
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
65
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
66
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
67
+ SOFTWARE.
68
+ ```
package/dist/index.d.mts CHANGED
@@ -134,7 +134,7 @@ interface PrivacyOptions$1 {
134
134
  maskNetworkQueryParams?: boolean;
135
135
  /** Redact console log messages and attributes. Default on unless `level` is `'allow'`. */
136
136
  maskLogs?: boolean;
137
- /** Redact error messages, metadata and stack-frame URLs. Default on unless `level` is `'allow'`. */
137
+ /** Redact error messages and metadata (not stack frames). Default on unless `level` is `'allow'`. */
138
138
  maskErrors?: boolean;
139
139
  /** Extra case-insensitive key substrings treated as sensitive, merged with the built-in patterns. */
140
140
  sensitiveKeys?: string[];
@@ -447,7 +447,7 @@ declare class SessionManager {
447
447
  }): void;
448
448
  startNavigation(metadata: Record<string, unknown>): void;
449
449
  endNavigation(metadata: Record<string, unknown>): void;
450
- captureException(error: Error, metadata?: Record<string, unknown>): void;
450
+ captureException(error: unknown, metadata?: Record<string, unknown>): void;
451
451
  emitLog(message: string, level: LogLevel, attributes?: Record<string, unknown>): void;
452
452
  getSessionId(): string;
453
453
  setSessionId(newSessionId?: string): Promise<void>;
@@ -490,7 +490,7 @@ declare function sendCustomEvent(params: {
490
490
  event: string;
491
491
  attributes: Record<string, unknown>;
492
492
  }): void;
493
- declare function captureException(error: Error, metadata?: Record<string, unknown>): void;
493
+ declare function captureException(error: unknown, metadata?: Record<string, unknown>): void;
494
494
  declare function updateConfig(params: SDKConfigUpdate): void;
495
495
  declare function startNavigation(metadata: Record<string, unknown>): void;
496
496
  declare function endNavigation(metadata: Record<string, unknown>): void;
package/dist/index.d.ts CHANGED
@@ -134,7 +134,7 @@ interface PrivacyOptions$1 {
134
134
  maskNetworkQueryParams?: boolean;
135
135
  /** Redact console log messages and attributes. Default on unless `level` is `'allow'`. */
136
136
  maskLogs?: boolean;
137
- /** Redact error messages, metadata and stack-frame URLs. Default on unless `level` is `'allow'`. */
137
+ /** Redact error messages and metadata (not stack frames). Default on unless `level` is `'allow'`. */
138
138
  maskErrors?: boolean;
139
139
  /** Extra case-insensitive key substrings treated as sensitive, merged with the built-in patterns. */
140
140
  sensitiveKeys?: string[];
@@ -447,7 +447,7 @@ declare class SessionManager {
447
447
  }): void;
448
448
  startNavigation(metadata: Record<string, unknown>): void;
449
449
  endNavigation(metadata: Record<string, unknown>): void;
450
- captureException(error: Error, metadata?: Record<string, unknown>): void;
450
+ captureException(error: unknown, metadata?: Record<string, unknown>): void;
451
451
  emitLog(message: string, level: LogLevel, attributes?: Record<string, unknown>): void;
452
452
  getSessionId(): string;
453
453
  setSessionId(newSessionId?: string): Promise<void>;
@@ -490,7 +490,7 @@ declare function sendCustomEvent(params: {
490
490
  event: string;
491
491
  attributes: Record<string, unknown>;
492
492
  }): void;
493
- declare function captureException(error: Error, metadata?: Record<string, unknown>): void;
493
+ declare function captureException(error: unknown, metadata?: Record<string, unknown>): void;
494
494
  declare function updateConfig(params: SDKConfigUpdate): void;
495
495
  declare function startNavigation(metadata: Record<string, unknown>): void;
496
496
  declare function endNavigation(metadata: Record<string, unknown>): void;