@fixback/sdk 0.4.0 → 0.6.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 +12 -2
- package/dist/annotation.d.ts +10 -73
- package/dist/capture/extract-dom.d.ts +33 -0
- package/dist/connect.d.ts +47 -0
- package/dist/dom.d.ts +7 -19
- package/dist/element-picker.d.ts +1 -1
- package/dist/error-capture.d.ts +21 -93
- package/dist/fixback.umd.js +36 -215
- package/dist/fixback.umd.js.map +1 -1
- package/dist/identity.d.ts +6 -1
- package/dist/index.d.ts +17 -15
- package/dist/index.mjs +3598 -4681
- package/dist/index.mjs.map +1 -1
- package/dist/init.d.ts +63 -97
- package/dist/mount.d.ts +46 -0
- package/dist/overlay/dom.d.ts +16 -0
- package/dist/overlay/icons.d.ts +23 -0
- package/dist/overlay/marking.d.ts +64 -0
- package/dist/overlay/send.d.ts +65 -0
- package/dist/overlay/view.d.ts +78 -0
- package/dist/overlay-styles.d.ts +1 -1
- package/dist/overlay.d.ts +40 -43
- package/dist/package.json +3 -0
- package/dist/report.d.ts +22 -111
- package/dist/reporter-session-store.d.ts +17 -0
- package/dist/session.d.ts +27 -0
- package/dist/submit.d.ts +56 -19
- package/dist/trace/instrument/beacon.d.ts +16 -0
- package/dist/trace/instrument/console.d.ts +11 -0
- package/dist/trace/instrument/fetch.d.ts +16 -0
- package/dist/trace/instrument/index.d.ts +64 -0
- package/dist/trace/instrument/navigation.d.ts +12 -0
- package/dist/trace/instrument/ui.d.ts +23 -0
- package/dist/trace/instrument/window.d.ts +66 -0
- package/dist/trace/instrument/xhr.d.ts +15 -0
- package/dist/version.d.ts +1 -1
- package/package.json +8 -5
- package/dist/auto-report-backoff.d.ts +0 -47
- package/dist/boot.d.ts +0 -74
- package/dist/breadcrumbs.d.ts +0 -448
- package/dist/invite.d.ts +0 -104
- package/dist/onboarding-styles.d.ts +0 -8
- package/dist/onboarding.d.ts +0 -44
- package/dist/screenshot.d.ts +0 -73
- package/dist/scrub.d.ts +0 -61
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
The Fixback capture SDK — a tiny, self-isolating on-page feedback widget.
|
|
4
4
|
|
|
5
|
+
> 📖 **Full documentation: [docs.fixback.dev/sdk/web](https://docs.fixback.dev/sdk/web)** — guides, concepts, and the complete API reference.
|
|
6
|
+
|
|
5
7
|
`init({ key })` asks Fixback whether a submission would be accepted for your
|
|
6
8
|
publishable key, the visitor's origin, and the Project's Gate, and mounts a
|
|
7
9
|
launcher **only when it would**. Nothing renders when the origin isn't
|
|
@@ -58,13 +60,21 @@ global:
|
|
|
58
60
|
| ---------------- | ------------- | -------------------------- | ----------------------------------------------------------------------- |
|
|
59
61
|
| `key` | `string` | — | Your Project's **publishable** key (an identifier, not a secret). |
|
|
60
62
|
| `apiUrl` | `string` | `https://api.fixback.dev` | The Fixback API origin. Override for a self-hosted or local deployment. |
|
|
61
|
-
| `
|
|
63
|
+
| `hostIdentity` | `string` | — | A Host-identity token minted by your server, for trusted reporters. |
|
|
62
64
|
| `reporterId` | `string` | — | The handle returned when a reporter redeems an invite. |
|
|
63
65
|
| `anonymousId` | `string` | a persisted per-browser id | A stable first-party id for an anonymous reporter. |
|
|
64
66
|
| `target` | `HTMLElement` | `document.body` | Where to mount the launcher. |
|
|
65
67
|
| `reduceMotion` | `boolean` | `false` | Still the launcher's pulse and motion (see [The launcher](#the-launcher)). |
|
|
66
68
|
| `autoCapture` | `boolean` | `true` | Automatic error capture — file uncaught errors with no prompt (see [Automatic error capture](#automatic-error-capture)). Set `false` to turn it off. |
|
|
67
|
-
| `capture` | `{ console?: boolean; network?: boolean }` | served per-project | Console / network
|
|
69
|
+
| `capture` | `{ console?: boolean; network?: boolean; replay?: boolean }` | served per-project | Console / network / session-replay capture. **On by default** and normally governed per-project from the dashboard; set a stream here to override what the server serves (e.g. `{ network: false }`). A stream you leave unset follows the Project's setting. |
|
|
70
|
+
| `enabled` | `boolean` | `true` | Master gate. `false` keeps the SDK completely dormant — no boot call, nothing instrumented, nothing mounted. |
|
|
71
|
+
| `release` | `string` | — | The build identifier captured errors symbolicate against; set it to the value `fixback sourcemaps upload --release` used. |
|
|
72
|
+
| `environment` | `string` | — | The deploy environment (`production` / `staging` / …) stamped on every capture. |
|
|
73
|
+
| `scrub` | `boolean` | `true` | The built-in URL / PII scrubbers, run before `beforeSend`. |
|
|
74
|
+
| `beforeSend` | `(draft) => draft \| null` | — | The scrub choke point every report passes through. Mutate the draft, or return `null` to drop it. |
|
|
75
|
+
| `beforeBreadcrumb` | `(crumb) => crumb \| null` | — | Filter or edit each Trace entry at the source; return `null` to drop it. |
|
|
76
|
+
| `trace` | `{ budgets?, maxAgeMs?, consoleLevels? }` | tuned defaults | Trace buffer **tuning** only. Whether a stream is captured is `capture`'s job. |
|
|
77
|
+
| `replay` | `ReplayOptions` | masking on | Session-replay tuning. To turn the recorder off, use `capture: { replay: false }`. |
|
|
68
78
|
|
|
69
79
|
None of the identity fields is a trust tier — Fixback derives trust on the
|
|
70
80
|
server and never honours a self-declared tier.
|
package/dist/annotation.d.ts
CHANGED
|
@@ -1,78 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The Annotation & vector-marks
|
|
2
|
+
* The Annotation & vector-marks geometry (spec 0003 §B/§D).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* This module is the marks' single home — the pure types and geometry used by the
|
|
12
|
-
* region-capture and draw controllers and by the overlay's Send assembly. Like the
|
|
13
|
-
* rest of the SDK's wire types it is vendored (no `@fixback/shared` import); keep
|
|
14
|
-
* `Annotation` in lock-step with the server's ingest contract (spec §D/§H).
|
|
15
|
-
*/
|
|
16
|
-
import type { SelectedElement } from "./report";
|
|
17
|
-
/** A point in screenshot (viewport) coordinate space. */
|
|
18
|
-
export interface Point {
|
|
19
|
-
readonly x: number;
|
|
20
|
-
readonly y: number;
|
|
21
|
-
}
|
|
22
|
-
/** A rectangle in screenshot coordinates — the same shape as an element's rect. */
|
|
23
|
-
export interface Rect {
|
|
24
|
-
readonly x: number;
|
|
25
|
-
readonly y: number;
|
|
26
|
-
readonly width: number;
|
|
27
|
-
readonly height: number;
|
|
28
|
-
}
|
|
29
|
-
/** The draw tools the overlay offers, in toolbar order (spec §B, prototype). */
|
|
30
|
-
export type DrawTool = "arrow" | "box" | "pen" | "text";
|
|
31
|
-
/** Fields shared by every vector mark. */
|
|
32
|
-
interface MarkBase {
|
|
33
|
-
/** Stroke/fill colour, as a CSS colour string. */
|
|
34
|
-
readonly color: string;
|
|
35
|
-
}
|
|
36
|
-
/** A directional arrow from `(x0,y0)` to its tip at `(x1,y1)`. */
|
|
37
|
-
export interface ArrowMark extends MarkBase {
|
|
38
|
-
readonly type: "arrow";
|
|
39
|
-
readonly x0: number;
|
|
40
|
-
readonly y0: number;
|
|
41
|
-
readonly x1: number;
|
|
42
|
-
readonly y1: number;
|
|
43
|
-
}
|
|
44
|
-
/** A rectangle spanning the drag from `(x0,y0)` to `(x1,y1)`. */
|
|
45
|
-
export interface BoxMark extends MarkBase {
|
|
46
|
-
readonly type: "box";
|
|
47
|
-
readonly x0: number;
|
|
48
|
-
readonly y0: number;
|
|
49
|
-
readonly x1: number;
|
|
50
|
-
readonly y1: number;
|
|
51
|
-
}
|
|
52
|
-
/** A freehand polyline through `points` (in order). */
|
|
53
|
-
export interface PenMark extends MarkBase {
|
|
54
|
-
readonly type: "pen";
|
|
55
|
-
readonly points: ReadonlyArray<Point>;
|
|
56
|
-
}
|
|
57
|
-
/** A text label anchored at `(x,y)` (its baseline-left, as SVG text). */
|
|
58
|
-
export interface TextMark extends MarkBase {
|
|
59
|
-
readonly type: "text";
|
|
60
|
-
readonly x: number;
|
|
61
|
-
readonly y: number;
|
|
62
|
-
readonly text: string;
|
|
63
|
-
}
|
|
64
|
-
/** A single vector mark, in screenshot coordinates. */
|
|
65
|
-
export type Mark = ArrowMark | BoxMark | PenMark | TextMark;
|
|
66
|
-
/**
|
|
67
|
-
* The structured Annotation carried on a report's content (spec §D): the three
|
|
68
|
-
* optional layers. Every field is optional — a report may carry any subset or
|
|
69
|
-
* none (a bare comment is a valid Send).
|
|
4
|
+
* The Annotation **wire types** (`Annotation`, `Mark` and friends, `Point`,
|
|
5
|
+
* `Rect`, `SelectedElement`) live in `@fixback/sdk-core` (ADR-0028) so every
|
|
6
|
+
* surface shares one shape; this module re-exports them and holds the browser's
|
|
7
|
+
* pure geometry and Send-assembly used by the region-capture and draw controllers
|
|
8
|
+
* and the overlay. Marks live in the **screenshot's coordinate space** (the full
|
|
9
|
+
* viewport the screenshot is rasterised at), never baked into the PNG: the
|
|
10
|
+
* dashboard composites them at view time (#91).
|
|
70
11
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
readonly region?: Rect;
|
|
74
|
-
readonly marks?: ReadonlyArray<Mark>;
|
|
75
|
-
}
|
|
12
|
+
import { type Annotation, type ArrowMark, type BoxMark, type DrawTool, type Mark, type PenMark, type Point, type Rect, type SelectedElement, type TextMark } from "@fixback/sdk-core";
|
|
13
|
+
export type { Annotation, ArrowMark, BoxMark, DrawTool, Mark, PenMark, Point, Rect, TextMark, };
|
|
76
14
|
/**
|
|
77
15
|
* The default mark colour — Signal's danger red, matching the frozen Reporter
|
|
78
16
|
* prototype's draw layer (`docs/design/Fixback Reporter.dc.html`).
|
|
@@ -103,4 +41,3 @@ export declare function assembleAnnotation(parts: {
|
|
|
103
41
|
readonly region?: Rect | null;
|
|
104
42
|
readonly marks?: ReadonlyArray<Mark> | null;
|
|
105
43
|
}): Annotation | undefined;
|
|
106
|
-
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Distilling the browser's **two error events** into the shape the shared capture
|
|
3
|
+
* state machine keys on.
|
|
4
|
+
*
|
|
5
|
+
* These are the only genuinely DOM-shaped part of automatic error capture: an
|
|
6
|
+
* `ErrorEvent` and an `unhandledrejection` `PromiseRejectionEvent` carry the
|
|
7
|
+
* throwable in different places and deserve different default type names. Everything
|
|
8
|
+
* after — fingerprinting, dedup, the burst limiter, the session cap — is
|
|
9
|
+
* `@fixback/sdk-core`'s (ADR-0028) and shared with the React Native SDK.
|
|
10
|
+
*
|
|
11
|
+
* Both are defensive by construction: a value with no usable message returns `null`
|
|
12
|
+
* rather than filing a Feedback about nothing, which is exactly how a resource-load
|
|
13
|
+
* `error` event (an `<img>`/`<script>` that 404s — never an uncaught exception) is
|
|
14
|
+
* kept out.
|
|
15
|
+
*/
|
|
16
|
+
import { type ExtractedError } from "@fixback/sdk-core";
|
|
17
|
+
/**
|
|
18
|
+
* Distil an uncaught `error` event into a fingerprint-able shape, or `null` when
|
|
19
|
+
* the event names no error at all (a resource-load failure).
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractFromErrorEvent(event: Event): ExtractedError | null;
|
|
22
|
+
/**
|
|
23
|
+
* Distil an `unhandledrejection` event into a fingerprint-able shape. A rejection
|
|
24
|
+
* with a non-Error reason still files — `Promise.reject("nope")` is a real bug —
|
|
25
|
+
* so unlike {@link extractFromErrorEvent} this never returns `null`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractFromRejectionEvent(event: Event): ExtractedError;
|
|
28
|
+
/**
|
|
29
|
+
* Distil whichever of the two global error events fired. The browser registers one
|
|
30
|
+
* listener per type, so the event's `type` is an exact discriminator — and the
|
|
31
|
+
* single `extract` the shared state machine is parameterised over.
|
|
32
|
+
*/
|
|
33
|
+
export declare function extractFromGlobalEvent(event: Event): ExtractedError | null;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The browser **Connect** flow (ADR-0032) — the DOM half of the round trip whose pure
|
|
3
|
+
* pieces (URL building, message parsing, the code exchange) live in `@fixback/sdk-core`.
|
|
4
|
+
*
|
|
5
|
+
* Connect opens the platform's connect page in a **popup**; the page signs the person in
|
|
6
|
+
* and posts back a one-time code, which the SDK exchanges for a Reporter session. When a
|
|
7
|
+
* popup is blocked the SDK falls back to a **full-page redirect** to the same URL; the
|
|
8
|
+
* connect page then returns to the site with the code on the `?fixback=` query
|
|
9
|
+
* parameter, which the SDK reads on the next load ({@link readReturnCode}) and exchanges.
|
|
10
|
+
* A Fixback-issued link (e.g. an Invite claim, ticket #250) carries the same parameter,
|
|
11
|
+
* so arriving on it starts a Connect with no popup at all.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The outcome of starting Connect: `code` when a popup handed one back, `redirected`
|
|
15
|
+
* when a blocked popup sent the page to a full redirect (the page is navigating away and
|
|
16
|
+
* the code will arrive via {@link readReturnCode} on reload), or `cancelled` when the
|
|
17
|
+
* person closed the popup without signing in.
|
|
18
|
+
*/
|
|
19
|
+
export type ConnectStart = {
|
|
20
|
+
readonly kind: "code";
|
|
21
|
+
readonly code: string;
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: "redirected";
|
|
24
|
+
} | {
|
|
25
|
+
readonly kind: "cancelled";
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Start Connect: open the connect page in a popup and resolve to the one-time code it
|
|
29
|
+
* posts back, or fall back to a full-page redirect when the popup is blocked. `returnUrl`
|
|
30
|
+
* is where the person is sent back — validated server-side against the Project's allowed
|
|
31
|
+
* origins, so a hostile page cannot redirect the code elsewhere.
|
|
32
|
+
*/
|
|
33
|
+
export declare function startConnect(win: Window, params: {
|
|
34
|
+
connectUrl: string;
|
|
35
|
+
key: string;
|
|
36
|
+
returnUrl: string;
|
|
37
|
+
}): Promise<ConnectStart>;
|
|
38
|
+
/**
|
|
39
|
+
* Read a Connect return code off the current URL's `?fixback=` parameter, or `null`.
|
|
40
|
+
* The connect page's redirect fallback and Fixback-issued links carry it.
|
|
41
|
+
*/
|
|
42
|
+
export declare function readReturnCode(win: Window): string | null;
|
|
43
|
+
/**
|
|
44
|
+
* Strip the `?fixback=` parameter from the current URL without a reload, so the
|
|
45
|
+
* one-time code is not left in the address bar, history, or a shared link.
|
|
46
|
+
*/
|
|
47
|
+
export declare function stripReturnCode(win: Window): void;
|
package/dist/dom.d.ts
CHANGED
|
@@ -1,30 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Recognising the SDK's **own** UI in the host page's DOM.
|
|
3
3
|
*
|
|
4
|
-
* The SDK mounts
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* The SDK mounts host elements into the page — the launcher and the overlay panel
|
|
5
|
+
* — each tagged with a `data-fixback-*` marker attribute (the element-picker's
|
|
6
|
+
* highlight lives inside the overlay's shadow, so it is covered by the
|
|
7
|
+
* shadow-boundary walk below). {@link isFixbackNode} is what lets the picker, the
|
|
8
|
+
* masked UI crumbs, and the replay recorder skip Fixback's own chrome, so a report
|
|
9
|
+
* never targets or records the tool that filed it.
|
|
10
10
|
*/
|
|
11
11
|
/** Marker attributes on the SDK's own host elements in the light DOM. */
|
|
12
12
|
export declare const FIXBACK_HOST_MARKERS: readonly ["data-fixback-root", "data-fixback-overlay"];
|
|
13
|
-
/**
|
|
14
|
-
* Is this node itself one of the SDK's own host elements (the launcher / overlay
|
|
15
|
-
* roots)? A self-only check — the screenshot's clone walk excludes a node's whole
|
|
16
|
-
* subtree once the host is matched, so catching the host is enough to keep all of
|
|
17
|
-
* Fixback's chrome (light DOM and its shadow tree) out of a capture.
|
|
18
|
-
*/
|
|
19
|
-
export declare function isFixbackHostElement(node: Node | null | undefined): boolean;
|
|
20
13
|
/**
|
|
21
14
|
* Is this node part of the SDK's own UI? Walks up parents and out through any
|
|
22
15
|
* Shadow DOM boundary (via `getRootNode().host`), so a click inside the overlay's
|
|
23
16
|
* shadow is recognised as Fixback's own — not a host-page element to pick.
|
|
24
17
|
*/
|
|
25
18
|
export declare function isFixbackNode(node: EventTarget | null | undefined): boolean;
|
|
26
|
-
/**
|
|
27
|
-
* Remove the SDK's own host elements from a (cloned) subtree, so a captured
|
|
28
|
-
* screenshot never contains the launcher, overlay, or picker highlight.
|
|
29
|
-
*/
|
|
30
|
-
export declare function stripFixbackNodes(root: ParentNode): void;
|
package/dist/element-picker.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SelectedElement } from "
|
|
1
|
+
import type { SelectedElement } from "@fixback/sdk-core";
|
|
2
2
|
/**
|
|
3
3
|
* A stable CSS selector for `el`: its own id when it has one, otherwise a path of
|
|
4
4
|
* tag (with `:nth-of-type` to disambiguate same-tag siblings) climbing until it
|
package/dist/error-capture.d.ts
CHANGED
|
@@ -5,13 +5,17 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Exactly **two capture-phase listeners** (`window` `error` +
|
|
7
7
|
* `unhandledrejection`) turn uncaught exceptions and unhandled rejections into
|
|
8
|
-
* `source:
|
|
9
|
-
* native-API monkeypatching, no library.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
8
|
+
* `source: error` Feedback (stamped `Kind = bug` server-side, ADR-0023) for the
|
|
9
|
+
* current session's Reporter — no native-API monkeypatching, no library.
|
|
10
|
+
* `console.error` is **not** promoted; it stays breadcrumb-only Evidence.
|
|
11
|
+
*
|
|
12
|
+
* This module is the **browser binding** over the shared state machine
|
|
13
|
+
* (`createAutoCapture`, `@fixback/sdk-core`, ADR-0028): it supplies the two
|
|
14
|
+
* listeners, the DOM event distillation (`./capture/extract-dom`), the browser
|
|
15
|
+
* report assembly, and the flush hooks (`pagehide` + `visibilitychange`).
|
|
16
|
+
* Everything between — the per-session fingerprint dedup, the token-bucket burst
|
|
17
|
+
* limiter, the session cap, the causal error crumb, and the `sentCount` rollback —
|
|
18
|
+
* is the core's, identical to the React Native SDK's.
|
|
15
19
|
*
|
|
16
20
|
* Per-firing order (research §7.1): **`canSubmit`/Gate → dedup → rate-limit/cap →
|
|
17
21
|
* `beforeSend` scrub → enqueue Feedback**. The Gate is honoured by construction:
|
|
@@ -19,100 +23,24 @@
|
|
|
19
23
|
* never filed where a manual report would be refused, and it inherits the session
|
|
20
24
|
* Reporter's server-derived tier.
|
|
21
25
|
*
|
|
22
|
-
* The whole module is defensive —
|
|
23
|
-
*
|
|
24
|
-
* The fingerprint/`normalize` shape and the limiter numbers are **starting points**
|
|
25
|
-
* from research (ticket #92), exposed as config — tunable, not frozen.
|
|
26
|
+
* The whole module is defensive — a Fixback problem (or an error thrown while
|
|
27
|
+
* capturing an error) never surfaces on the host page.
|
|
26
28
|
*/
|
|
27
|
-
import type
|
|
28
|
-
import { type BreadcrumbBuffer, type Teardown } from "./breadcrumbs";
|
|
29
|
-
import type { ReporterDisplay } from "./invite";
|
|
30
|
-
import { type CapturedFrame } from "./report";
|
|
29
|
+
import { type BeforeSend, type BreadcrumbBuffer, DEFAULT_BURST_CAPACITY, DEFAULT_BURST_REFILL_MS, DEFAULT_MAX_DISTINCT_AUTO, type IdentityInputs, type Teardown } from "@fixback/sdk-core";
|
|
31
30
|
import type { ReplaySource } from "./replay";
|
|
32
|
-
import { type
|
|
33
|
-
import { type Capture, type CaptureOptions } from "./screenshot";
|
|
34
|
-
import { type SubmitInput, type SubmitResult } from "./submit";
|
|
31
|
+
import { type SubmitDeps, type SubmitInput, type SubmitResult } from "./submit";
|
|
35
32
|
export type { Teardown };
|
|
36
|
-
|
|
37
|
-
export declare const DEFAULT_BURST_CAPACITY = 5;
|
|
38
|
-
/** Burst limiter refill — one token returns every this-many ms (§E). */
|
|
39
|
-
export declare const DEFAULT_BURST_REFILL_MS = 2000;
|
|
40
|
-
/** Per-session ceiling on distinct auto-Feedback; beyond it, only a dropped-count (§E). */
|
|
41
|
-
export declare const DEFAULT_MAX_DISTINCT_AUTO = 20;
|
|
42
|
-
/**
|
|
43
|
-
* Collapse the volatile parts of an error message so a changing string doesn't
|
|
44
|
-
* split one bug: UUIDs, URLs, `0x…` and long hex runs, and long digit runs are
|
|
45
|
-
* replaced with stable placeholders. Short numbers and stable text are kept so
|
|
46
|
-
* genuinely distinct bugs stay distinct. A small, dependency-free regex set —
|
|
47
|
-
* tunable per ticket #92, never a frozen magic set.
|
|
48
|
-
*/
|
|
49
|
-
export declare function normalize(value: string): string;
|
|
50
|
-
/**
|
|
51
|
-
* A dependency-free FNV-1a hash rendered in base-36. It only has to be stable and
|
|
52
|
-
* well-distributed within one session (the client key is a flood guard; the server
|
|
53
|
-
* does canonical cross-session clustering), so a non-cryptographic hash is right.
|
|
54
|
-
*/
|
|
55
|
-
export declare function hashString(input: string): string;
|
|
56
|
-
/**
|
|
57
|
-
* Extract a compact, stable signature of the top in-app frames of a stack: up to
|
|
58
|
-
* {@link FINGERPRINT_FRAME_LIMIT} frames as `function@basename:line:col`, origin
|
|
59
|
-
* and cache-busting query stripped so a per-deploy asset hash doesn't matter within
|
|
60
|
-
* a session. Returns `""` when there is no usable stack (message-only fallback).
|
|
61
|
-
*/
|
|
62
|
-
export declare function extractTopFrames(stack: string | undefined, limit?: number): string;
|
|
63
|
-
/**
|
|
64
|
-
* Extract **structured** frames from a stack for the wire (#117, ADR-0024) —
|
|
65
|
-
* unlike {@link extractTopFrames} (a compact fingerprint signature that drops the
|
|
66
|
-
* origin), these keep the full script URL, because server-side symbolication
|
|
67
|
-
* matches it against uploaded sourcemap paths. URLs are scrubbed (query dropped,
|
|
68
|
-
* PII redacted) before they leave the page; unlocatable frames (`native`,
|
|
69
|
-
* `<anonymous>`, eval) are skipped; the count is capped.
|
|
70
|
-
*/
|
|
71
|
-
export declare function extractStructuredFrames(stack: string | undefined, limit?: number): CapturedFrame[];
|
|
72
|
-
/**
|
|
73
|
-
* The per-session fingerprint (research §7.2):
|
|
74
|
-
* `hash(errorType + "|" + normalize(value) + "|" + topFrames)`. Stack frames
|
|
75
|
-
* dominate when present; otherwise it falls back to type + normalized value.
|
|
76
|
-
*/
|
|
77
|
-
export declare function computeFingerprint(type: string, value: string, stack?: string): string;
|
|
78
|
-
/** Configuration for {@link TokenBucket}. */
|
|
79
|
-
export interface TokenBucketOptions {
|
|
80
|
-
readonly capacity: number;
|
|
81
|
-
readonly refillIntervalMs: number;
|
|
82
|
-
/** Clock source, injectable for tests. Defaults to `Date.now`. */
|
|
83
|
-
readonly now?: () => number;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* A token bucket: starts full at `capacity`, refills one token every
|
|
87
|
-
* `refillIntervalMs`, and refuses (`take() === false`) when empty. So a fast error
|
|
88
|
-
* loop that dodges dedup with distinct fingerprints still can't machine-gun ingest.
|
|
89
|
-
* The clock is injectable so the window is unit-tested deterministically.
|
|
90
|
-
*/
|
|
91
|
-
export declare class TokenBucket {
|
|
92
|
-
private readonly options;
|
|
93
|
-
private tokens;
|
|
94
|
-
private last;
|
|
95
|
-
private readonly now;
|
|
96
|
-
constructor(options: TokenBucketOptions);
|
|
97
|
-
/** Consume a token if one is available (refilling first), else refuse. */
|
|
98
|
-
take(): boolean;
|
|
99
|
-
}
|
|
33
|
+
export { DEFAULT_BURST_CAPACITY, DEFAULT_BURST_REFILL_MS, DEFAULT_MAX_DISTINCT_AUTO };
|
|
100
34
|
/** Injectable collaborators, defaulted to the real implementations. */
|
|
101
35
|
export interface AutoCaptureDeps {
|
|
102
|
-
readonly
|
|
103
|
-
readonly submitReport: (apiUrl: string, input: SubmitInput, fetchImpl?: typeof fetch) => Promise<SubmitResult>;
|
|
36
|
+
readonly submitReport: (apiUrl: string, input: SubmitInput, deps?: SubmitDeps) => Promise<SubmitResult>;
|
|
104
37
|
}
|
|
105
38
|
/** Configuration for {@link installErrorCapture}. */
|
|
106
39
|
export interface AutoCaptureConfig {
|
|
107
40
|
readonly apiUrl: string;
|
|
108
41
|
readonly key: string;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
* The Reporter's self-provided display name / email (spec §F). Carried on
|
|
112
|
-
* auto-captured Feedback too, so a machine-filed crash still names whose session it
|
|
113
|
-
* was — display only, never a trust signal.
|
|
114
|
-
*/
|
|
115
|
-
readonly display?: ReporterDisplay;
|
|
42
|
+
/** Identity evidence, read **live** at capture time (ADR-0032) — the current session token. */
|
|
43
|
+
readonly getIdentity?: () => IdentityInputs;
|
|
116
44
|
/** The window whose global handlers are installed. Defaults to `window`. */
|
|
117
45
|
readonly win?: Window;
|
|
118
46
|
/** The document used for capture + environment. Defaults to the window's. */
|
|
@@ -124,6 +52,8 @@ export interface AutoCaptureConfig {
|
|
|
124
52
|
* server can symbolicate the captured frames against this build's sourcemaps.
|
|
125
53
|
*/
|
|
126
54
|
readonly release?: string;
|
|
55
|
+
/** The deploy environment (`production` / `staging` / …), stamped on every report. */
|
|
56
|
+
readonly deployEnvironment?: string;
|
|
127
57
|
/** The shared trace buffer; the failing error is added to it before filing. */
|
|
128
58
|
readonly buffer?: BreadcrumbBuffer | null;
|
|
129
59
|
/**
|
|
@@ -159,7 +89,5 @@ export interface AutoCaptureHandle {
|
|
|
159
89
|
/**
|
|
160
90
|
* Install automatic error capture on a window and return a handle whose `destroy`
|
|
161
91
|
* removes every listener it added (the two global handlers plus the flush hooks).
|
|
162
|
-
* The caller (`init`) installs this only after boot returned `canSubmit`, so the
|
|
163
|
-
* Gate is respected and the auto-error inherits the session Reporter's tier.
|
|
164
92
|
*/
|
|
165
93
|
export declare function installErrorCapture(config: AutoCaptureConfig): AutoCaptureHandle;
|