@fixback/sdk 0.2.0 → 0.4.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 -10
- package/dist/annotation.d.ts +1 -1
- package/dist/boot.d.ts +23 -3
- package/dist/breadcrumbs.d.ts +315 -32
- package/dist/dom.d.ts +7 -0
- package/dist/error-capture.d.ts +31 -1
- package/dist/fixback.umd.js +115 -54
- package/dist/fixback.umd.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.mjs +5544 -1258
- package/dist/index.mjs.map +1 -1
- package/dist/init.d.ts +62 -8
- package/dist/launcher.d.ts +2 -2
- package/dist/overlay-styles.d.ts +1 -1
- package/dist/overlay.d.ts +12 -0
- package/dist/replay.d.ts +101 -0
- package/dist/report.d.ts +47 -5
- package/dist/screenshot.d.ts +37 -18
- package/dist/scrub.d.ts +5 -4
- package/dist/styles.d.ts +2 -2
- package/dist/submit.d.ts +8 -0
- package/dist/version.d.ts +10 -4
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -8,9 +8,9 @@ launcher **only when it would**. Nothing renders when the origin isn't
|
|
|
8
8
|
allowlisted or the Gate turns the visitor away, and if Fixback can't be reached
|
|
9
9
|
the SDK stays completely silent — it never throws into the host page.
|
|
10
10
|
|
|
11
|
-
Activating the launcher opens the **report overlay**: the Reporter
|
|
12
|
-
**
|
|
13
|
-
|
|
11
|
+
Activating the launcher opens the **report overlay**: the Reporter writes a
|
|
12
|
+
comment, optionally **points at the element** they mean, and hits **Send** —
|
|
13
|
+
which captures a **masked screenshot**
|
|
14
14
|
of the current view, assembles the annotation, and submits it to Fixback. A
|
|
15
15
|
successful send shows a confirmation; a refusal or an unreachable Fixback fails
|
|
16
16
|
quietly, leaving the host page untouched.
|
|
@@ -64,6 +64,7 @@ global:
|
|
|
64
64
|
| `target` | `HTMLElement` | `document.body` | Where to mount the launcher. |
|
|
65
65
|
| `reduceMotion` | `boolean` | `false` | Still the launcher's pulse and motion (see [The launcher](#the-launcher)). |
|
|
66
66
|
| `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 Trace 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. |
|
|
67
68
|
|
|
68
69
|
None of the identity fields is a trust tier — Fixback derives trust on the
|
|
69
70
|
server and never honours a self-declared tier.
|
|
@@ -78,11 +79,12 @@ fixback.destroy();
|
|
|
78
79
|
|
|
79
80
|
The launcher is a bottom-right **Feedback** pill, and it stays out of the way:
|
|
80
81
|
|
|
81
|
-
- **Hover-peek & tuck-away** — the pill's
|
|
82
|
-
small edge nub
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
the
|
|
82
|
+
- **Hover-peek & tuck-away** — the pill's chevron tucks it off-screen to the
|
|
83
|
+
right behind a small edge nub, pointing **right** to tuck away and flipping to
|
|
84
|
+
point **left** while tucked. Hovering the bottom-right corner (or the nub)
|
|
85
|
+
peeks it back, where clicking that same chevron — or the nub, or pressing
|
|
86
|
+
Enter/Space on the nub — restores the launcher, which also covers pointers that
|
|
87
|
+
can't hover (touch, keyboard).
|
|
86
88
|
- **First-visit welcome** — a one-time toast greets a new visitor, drawing the
|
|
87
89
|
eye with a gentle pulse. It shows once per publishable key per browser.
|
|
88
90
|
- **Reduce motion** — pass `reduceMotion: true` to still the pulse and the
|
|
@@ -110,8 +112,8 @@ document.addEventListener(LAUNCH_EVENT, () => {
|
|
|
110
112
|
|
|
111
113
|
The SDK's signature capability: **errors report themselves, with no prompt.** Two
|
|
112
114
|
capture-phase global handlers (`error` + `unhandledrejection`) turn uncaught
|
|
113
|
-
exceptions and unhandled promise rejections into `source: auto
|
|
114
|
-
|
|
115
|
+
exceptions and unhandled promise rejections into `source: auto` Feedback
|
|
116
|
+
(classified `Kind = bug` server-side) for the current session's reporter — carrying the same masked screenshot
|
|
115
117
|
and trace buffer a manual report does, plus a per-session fingerprint. It is
|
|
116
118
|
**on by default across every Gate**; pass `autoCapture: false` to turn it off.
|
|
117
119
|
|
package/dist/annotation.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export type Mark = ArrowMark | BoxMark | PenMark | TextMark;
|
|
|
66
66
|
/**
|
|
67
67
|
* The structured Annotation carried on a report's content (spec §D): the three
|
|
68
68
|
* optional layers. Every field is optional — a report may carry any subset or
|
|
69
|
-
* none (a bare
|
|
69
|
+
* none (a bare comment is a valid Send).
|
|
70
70
|
*/
|
|
71
71
|
export interface Annotation {
|
|
72
72
|
readonly element?: SelectedElement;
|
package/dist/boot.d.ts
CHANGED
|
@@ -26,17 +26,37 @@ export interface IdentityInputs {
|
|
|
26
26
|
export interface BootRequest extends IdentityInputs {
|
|
27
27
|
readonly key: string;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* The Project's effective console/network capture config, served on the boot answer
|
|
31
|
+
* (spec #122 §L; ticket #138). Each flag is the per-project master toggle ANDed with
|
|
32
|
+
* that stream's own toggle, so the SDK gates instrumentation on one boolean per
|
|
33
|
+
* stream. Optional on the wire: an older server that does not send it (or a
|
|
34
|
+
* malformed value) is treated as **capture on** — default-on, matching the server
|
|
35
|
+
* default — and `init` options override whatever is served.
|
|
36
|
+
*/
|
|
37
|
+
export interface CaptureConfig {
|
|
38
|
+
readonly console: boolean;
|
|
39
|
+
readonly network: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* The Project's session-replay toggle (issue #189, ADR-0024). Optional on the
|
|
42
|
+
* wire: a server predating replay omits it, which — like the other streams —
|
|
43
|
+
* means **capture on**.
|
|
44
|
+
*/
|
|
45
|
+
readonly replay?: boolean;
|
|
46
|
+
}
|
|
29
47
|
/**
|
|
30
48
|
* The boot answer: whether this origin is allowlisted, the Project's Gate, the
|
|
31
|
-
* caller's derived tier (`null` when a presented identity was refused),
|
|
32
|
-
*
|
|
33
|
-
* `canSubmit` is true.
|
|
49
|
+
* caller's derived tier (`null` when a presented identity was refused), whether a
|
|
50
|
+
* submission would be accepted right now, and the Project's capture config. The
|
|
51
|
+
* launcher shows only when `canSubmit` is true.
|
|
34
52
|
*/
|
|
35
53
|
export interface BootAnswer {
|
|
36
54
|
readonly originAllowed: boolean;
|
|
37
55
|
readonly gate: ProjectGate;
|
|
38
56
|
readonly tier: ReporterTier | null;
|
|
39
57
|
readonly canSubmit: boolean;
|
|
58
|
+
/** The Project's console/network capture config; absent ⇒ default-on (#138). */
|
|
59
|
+
readonly capture?: CaptureConfig;
|
|
40
60
|
}
|
|
41
61
|
/** Join an API base URL with the boot path, tolerating a trailing slash. */
|
|
42
62
|
export declare function bootEndpoint(apiUrl: string): string;
|
package/dist/breadcrumbs.d.ts
CHANGED
|
@@ -21,7 +21,20 @@
|
|
|
21
21
|
/** Console-style severity a `console` crumb records. */
|
|
22
22
|
export type BreadcrumbLevel = "log" | "info" | "warn" | "error" | "assert" | "debug";
|
|
23
23
|
/** The kind of activity a crumb records. */
|
|
24
|
-
export type BreadcrumbCategory = "console" | "navigation" | "fetch" | "xhr" | "ui.click" | "ui.input" | "error";
|
|
24
|
+
export type BreadcrumbCategory = "console" | "navigation" | "fetch" | "xhr" | "beacon" | "ui.click" | "ui.input" | "error";
|
|
25
|
+
/**
|
|
26
|
+
* Which browser API issued a captured network request (spec #122 §D, ticket #139).
|
|
27
|
+
* Every network crumb's `category` is one of these too, so a stream router and the
|
|
28
|
+
* read model agree on what is a network entry.
|
|
29
|
+
*/
|
|
30
|
+
export type NetworkApi = "fetch" | "xhr" | "beacon";
|
|
31
|
+
/**
|
|
32
|
+
* A network request's failure classification (spec #122 §D, ticket #139). `ok` and
|
|
33
|
+
* the HTTP status classes come from a settled response; `network-error` / `timeout`
|
|
34
|
+
* / `aborted` from how a request failed; `opaque-cors` from a cross-origin response
|
|
35
|
+
* whose status is unreadable. The Network tab flags every non-`ok` outcome.
|
|
36
|
+
*/
|
|
37
|
+
export type NetworkOutcome = "ok" | "http-4xx" | "http-5xx" | "network-error" | "timeout" | "aborted" | "opaque-cors";
|
|
25
38
|
/**
|
|
26
39
|
* A crumb's structured detail. Deliberately narrow: there is **no** field for a
|
|
27
40
|
* request/response body or an input value, so those can never be recorded.
|
|
@@ -36,56 +49,273 @@ export interface BreadcrumbData {
|
|
|
36
49
|
readonly to?: string;
|
|
37
50
|
readonly errorType?: string;
|
|
38
51
|
}
|
|
39
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* The type tag on a structured console argument (spec #122 §C, decision D7). A
|
|
54
|
+
* console call's arguments are preserved **type-tagged** rather than flattened to a
|
|
55
|
+
* string, so an object/array argument can be inspected in the Console tab rather
|
|
56
|
+
* than read as `[object Object]`: `string`/`number`/`bool`/`null` carry the value
|
|
57
|
+
* directly, `json` a depth-/byte-capped JSON-safe clone, and `error` an Error's
|
|
58
|
+
* `{ name, message, stack }`.
|
|
59
|
+
*/
|
|
60
|
+
export type ConsoleArgType = "string" | "number" | "bool" | "null" | "json" | "error";
|
|
61
|
+
/**
|
|
62
|
+
* One structured console argument (spec #122 §C): a type tag plus a JSON-safe value.
|
|
63
|
+
* `v` is always serializable — a `json` arg is depth-, breadth-, and string-capped at
|
|
64
|
+
* assembly, and exotic values (bigint, symbol, function, circular refs) are rendered
|
|
65
|
+
* to safe text — so a console crumb can never carry an unserializable or unbounded
|
|
66
|
+
* value onto the wire.
|
|
67
|
+
*/
|
|
68
|
+
export interface ConsoleArg {
|
|
69
|
+
readonly t: ConsoleArgType;
|
|
70
|
+
readonly v: unknown;
|
|
71
|
+
}
|
|
72
|
+
/** A `file:line` source location (spec #122 §C) — where a console call was made. */
|
|
73
|
+
export interface SourceLocation {
|
|
74
|
+
readonly file: string;
|
|
75
|
+
readonly line: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* One entry in a trace stream. Alongside its semantic fields every entry carries a
|
|
79
|
+
* stable {@link id} and a high-res monotonic {@link mono} timestamp — both stamped
|
|
80
|
+
* by the buffer on `add` — so entries from the three independent streams order and
|
|
81
|
+
* cross-link exactly (spec #122 §B, decision D9). `timestamp` stays epoch ms.
|
|
82
|
+
*/
|
|
40
83
|
export interface Breadcrumb {
|
|
41
84
|
readonly category: BreadcrumbCategory;
|
|
42
85
|
readonly message?: string;
|
|
43
86
|
readonly level?: BreadcrumbLevel;
|
|
44
87
|
/** Epoch milliseconds when the crumb was recorded. */
|
|
45
88
|
readonly timestamp: number;
|
|
89
|
+
/** A stable id, unique within the buffer — assigned on `add` when not already set. */
|
|
90
|
+
readonly id?: string;
|
|
91
|
+
/** A high-res monotonic timestamp (`performance.now()`) — assigned on `add`. */
|
|
92
|
+
readonly mono?: number;
|
|
46
93
|
readonly data?: BreadcrumbData;
|
|
94
|
+
/**
|
|
95
|
+
* For a `console` crumb (spec #122 §C): the call's arguments preserved as
|
|
96
|
+
* structured, type-tagged values (see {@link ConsoleArg}), so the Console tab can
|
|
97
|
+
* render each argument expandably instead of a flattened string. `message` stays
|
|
98
|
+
* the one-line preview. Absent on non-console crumbs.
|
|
99
|
+
*/
|
|
100
|
+
readonly args?: readonly ConsoleArg[];
|
|
101
|
+
/**
|
|
102
|
+
* For a `console` crumb (spec #122 §C): the `file:line` the call was made from,
|
|
103
|
+
* parsed best-effort from the call stack. Captured only for the levels that keep a
|
|
104
|
+
* source — `warn`/`error`/`assert` (ticket #159; see {@link SOURCE_CAPTURE_LEVELS}) —
|
|
105
|
+
* and only when the stack yields a usable location; a chatty app's `log`/`info`/`debug`
|
|
106
|
+
* omit it so the hot-page capture cost stays low. Absent on non-console crumbs.
|
|
107
|
+
*/
|
|
108
|
+
readonly source?: SourceLocation;
|
|
109
|
+
/**
|
|
110
|
+
* For an auto-captured `error` crumb only (spec #122 §F): the ids of the entries
|
|
111
|
+
* immediately preceding the throw — a causal pointer into the same trace, so a
|
|
112
|
+
* machine-filed crash names its lead-up. Absent on every other crumb.
|
|
113
|
+
*/
|
|
114
|
+
readonly causedBy?: readonly string[];
|
|
115
|
+
/**
|
|
116
|
+
* For a network crumb (`fetch` / `xhr` / `beacon`) — spec #122 §D, ticket #139.
|
|
117
|
+
* The rich request metadata the Network tab renders, lifted to the top level (the
|
|
118
|
+
* console-enrichment precedent) so the read model shapes each into a
|
|
119
|
+
* `NetworkTraceEntry`. **No field carries a request/response body or an arbitrary
|
|
120
|
+
* header** — `respSize` derives from the `content-length` response header only and
|
|
121
|
+
* `contentType` from `content-type`; nothing else is read. Absent on every other crumb.
|
|
122
|
+
*/
|
|
123
|
+
readonly api?: NetworkApi;
|
|
124
|
+
/** The request method (network crumb) — e.g. `GET`, `POST`. */
|
|
125
|
+
readonly method?: string;
|
|
126
|
+
/** The scrubbed request URL (network crumb) — query dropped, path PII redacted. */
|
|
127
|
+
readonly url?: string;
|
|
128
|
+
/** The final HTTP status (network crumb), when one was known; absent on a network error/beacon. */
|
|
129
|
+
readonly status?: number;
|
|
130
|
+
/** The HTTP status text (network crumb), when the response carried one. */
|
|
131
|
+
readonly statusText?: string;
|
|
132
|
+
/** Wall-clock duration of the request in ms (network crumb) — a `performance.now()` delta. */
|
|
133
|
+
readonly durationMs?: number;
|
|
134
|
+
/** Request body size in bytes (network crumb) — only when trivially known (string/Blob/ArrayBuffer), never by reading a stream. */
|
|
135
|
+
readonly reqSize?: number;
|
|
136
|
+
/** Response body size in bytes (network crumb) — from the `content-length` response header only. */
|
|
137
|
+
readonly respSize?: number;
|
|
138
|
+
/** Response content type (network crumb) — the `content-type` header's media type. */
|
|
139
|
+
readonly contentType?: string;
|
|
140
|
+
/** The request's failure classification (network crumb) — see {@link NetworkOutcome}. */
|
|
141
|
+
readonly outcome?: NetworkOutcome;
|
|
47
142
|
}
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
|
|
143
|
+
/**
|
|
144
|
+
* The three independent trace streams (spec #122 §A, decision D6). Each is its own
|
|
145
|
+
* FIFO ring with its own size budget, so a chatty stream can't evict another's
|
|
146
|
+
* lead-up. Every {@link BreadcrumbCategory} maps to exactly one stream via
|
|
147
|
+
* {@link streamOf}.
|
|
148
|
+
*/
|
|
149
|
+
export type TraceStream = "network" | "console" | "breadcrumbs";
|
|
150
|
+
/**
|
|
151
|
+
* Per-stream ring budgets — starting points from the grill (D6): network is the
|
|
152
|
+
* chattiest, breadcrumbs the sparsest. Per-project tunable, never frozen.
|
|
153
|
+
*/
|
|
154
|
+
export declare const DEFAULT_STREAM_BUDGETS: Readonly<Record<TraceStream, number>>;
|
|
155
|
+
/**
|
|
156
|
+
* The shared age cap (spec #122 §A): entries older than this are pruned from every
|
|
157
|
+
* stream, whichever trims first. ~3 minutes and — unlike the thin buffer's
|
|
158
|
+
* off-by-default cap — **on** by default, so an idle tab never ships stale context.
|
|
159
|
+
*/
|
|
160
|
+
export declare const DEFAULT_MAX_AGE_MS: number;
|
|
161
|
+
/**
|
|
162
|
+
* Console levels captured by default (spec #122 §C, decision D7): **all** of them, so
|
|
163
|
+
* the Console tab is a real console and not just an error log. Eviction priority (not
|
|
164
|
+
* capture) is what keeps a chatty app's `log`/`info`/`debug` from burying the signal —
|
|
165
|
+
* see {@link PINNED_CONSOLE_LEVELS}.
|
|
166
|
+
*/
|
|
51
167
|
export declare const DEFAULT_CONSOLE_LEVELS: readonly BreadcrumbLevel[];
|
|
168
|
+
/**
|
|
169
|
+
* The console levels **pinned** against eviction (spec #122 §C, decision D7). When the
|
|
170
|
+
* console stream overflows its budget, `warn`/`error`/`assert` are retained ahead of
|
|
171
|
+
* `log`/`info`/`debug`, so an error is never evicted by a burst of chatter — the
|
|
172
|
+
* low-priority levels fill the remainder and are dropped first.
|
|
173
|
+
*/
|
|
174
|
+
export declare const PINNED_CONSOLE_LEVELS: readonly BreadcrumbLevel[];
|
|
175
|
+
/**
|
|
176
|
+
* The console levels for which `source` (`file:line`) is captured (ticket #159).
|
|
177
|
+
*
|
|
178
|
+
* Capturing a call site constructs a `new Error()` to read its stack on **every** console
|
|
179
|
+
* call — a measurable hot-page cost when a chatty app logs in a tight loop (spec #122's
|
|
180
|
+
* "hot-page performance budget" open question, handed onward from the grill). The
|
|
181
|
+
* spec-sanctioned mitigation (decision D7) narrows source capture to the **levels that
|
|
182
|
+
* matter for debugging** — the same `warn`/`error`/`assert` that are pinned against
|
|
183
|
+
* eviction — so `log`/`info`/`debug` pay no per-call stack cost and simply omit `source`.
|
|
184
|
+
* Full-fidelity `source` is preserved exactly where it earns its keep: on warnings,
|
|
185
|
+
* errors, and failed assertions. Per-project tunability of this set is future work; today
|
|
186
|
+
* it deliberately mirrors {@link PINNED_CONSOLE_LEVELS} so "what survives eviction" and
|
|
187
|
+
* "what carries a call site" stay one idea.
|
|
188
|
+
*/
|
|
189
|
+
export declare const SOURCE_CAPTURE_LEVELS: readonly BreadcrumbLevel[];
|
|
190
|
+
/**
|
|
191
|
+
* Which stream a crumb's category belongs to (spec #122 §A). Network APIs
|
|
192
|
+
* (`fetch` / `xhr` / `beacon`) form the network stream, `console` its own, and
|
|
193
|
+
* everything else (navigation, masked UI events, the failing error) breadcrumbs.
|
|
194
|
+
*/
|
|
195
|
+
export declare function streamOf(category: string): TraceStream;
|
|
52
196
|
/** Filters or edits each crumb before it enters the buffer; `null` drops it. */
|
|
53
197
|
export type BeforeBreadcrumb = (crumb: Breadcrumb) => Breadcrumb | null;
|
|
54
198
|
/** Configuration for {@link createBreadcrumbBuffer}. All values are optional. */
|
|
55
199
|
export interface BreadcrumbBufferConfig {
|
|
56
|
-
/**
|
|
57
|
-
|
|
58
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Per-stream size budgets (oldest drop, independently per stream). Any stream
|
|
202
|
+
* omitted falls back to {@link DEFAULT_STREAM_BUDGETS}.
|
|
203
|
+
*/
|
|
204
|
+
readonly budgets?: Partial<Record<TraceStream, number>>;
|
|
205
|
+
/**
|
|
206
|
+
* Shared age cap in ms: entries older than this are dropped from every stream.
|
|
207
|
+
* Defaults to {@link DEFAULT_MAX_AGE_MS} (on); pass `0` (or a non-positive value)
|
|
208
|
+
* to disable age pruning.
|
|
209
|
+
*/
|
|
59
210
|
readonly maxAgeMs?: number;
|
|
60
211
|
/** A per-crumb filter (mute a category, edit, or drop by returning `null`). */
|
|
61
212
|
readonly beforeBreadcrumb?: BeforeBreadcrumb | null;
|
|
62
|
-
/**
|
|
213
|
+
/** Epoch clock source, injectable for tests. Defaults to `Date.now`. */
|
|
63
214
|
readonly now?: () => number;
|
|
215
|
+
/** High-res monotonic clock, injectable for tests. Defaults to `performance.now`. */
|
|
216
|
+
readonly mono?: () => number;
|
|
217
|
+
/** Stable id generator, injectable for tests. Defaults to a per-buffer sequence. */
|
|
218
|
+
readonly nextId?: () => string;
|
|
64
219
|
}
|
|
65
220
|
/** A live trace buffer. */
|
|
66
221
|
export interface BreadcrumbBuffer {
|
|
67
|
-
/** Record a crumb (subject to `beforeBreadcrumb`, size, and age trimming). */
|
|
222
|
+
/** Record a crumb (subject to `beforeBreadcrumb`, id/mono stamping, size, and age trimming). */
|
|
68
223
|
add(crumb: Breadcrumb): void;
|
|
69
|
-
/** The current crumbs,
|
|
224
|
+
/** The current crumbs, merged across streams and ordered in time — a fresh array. */
|
|
70
225
|
snapshot(): Breadcrumb[];
|
|
71
226
|
/** Drop every crumb. */
|
|
72
227
|
clear(): void;
|
|
73
228
|
}
|
|
74
229
|
/**
|
|
75
|
-
* Create
|
|
76
|
-
* `
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
230
|
+
* Create the per-stream trace buffer (spec #122 §A/§B). It holds **three
|
|
231
|
+
* independent FIFO rings** — `network`, `console`, `breadcrumbs` — each trimmed to
|
|
232
|
+
* its own budget so a chatty stream never evicts another's lead-up, plus a shared
|
|
233
|
+
* age cap. On `add`, a crumb passes through `beforeBreadcrumb`, is stamped with a
|
|
234
|
+
* stable `id` and a high-res `mono` timestamp (and an epoch `timestamp` if it has
|
|
235
|
+
* none), routed to its stream, then that stream is pruned by age and trimmed to its
|
|
236
|
+
* budget. `snapshot` prunes by age again, then merges the three streams into one
|
|
237
|
+
* `mono`-ordered array for transport — so the wire keeps its single `trace` field.
|
|
80
238
|
*/
|
|
81
239
|
export declare function createBreadcrumbBuffer(config?: BreadcrumbBufferConfig): BreadcrumbBuffer;
|
|
82
|
-
/**
|
|
83
|
-
|
|
84
|
-
|
|
240
|
+
/**
|
|
241
|
+
* Longest scrubbed URL kept on a crumb (spec #122 §F): capped at assembly so an
|
|
242
|
+
* over-long URL is truncated, never dropped and never allowed to bloat a report.
|
|
243
|
+
*/
|
|
244
|
+
export declare const MAX_URL_LENGTH = 2048;
|
|
245
|
+
/**
|
|
246
|
+
* Structured console argument caps (spec #122 §C/§F), all applied **at assembly** so a
|
|
247
|
+
* single console crumb can never bloat a report:
|
|
248
|
+
* - {@link MAX_ARG_DEPTH} bounds how deep a `json` argument is cloned (deeper nodes
|
|
249
|
+
* collapse to an `[Object]`/`[Array]` marker);
|
|
250
|
+
* - {@link MAX_ARG_ITEMS} bounds how many keys/elements are kept at each level;
|
|
251
|
+
* - {@link MAX_ARG_STRING_LENGTH} truncates a single over-long string value;
|
|
252
|
+
* - {@link MAX_CONSOLE_ARGS_BYTES} bounds the serialized size of the whole args array
|
|
253
|
+
* (trailing args are dropped to fit), kept well under ingest's per-entry byte cap.
|
|
254
|
+
*/
|
|
255
|
+
export declare const MAX_ARG_DEPTH = 4;
|
|
256
|
+
export declare const MAX_ARG_ITEMS = 100;
|
|
257
|
+
export declare const MAX_ARG_STRING_LENGTH = 1024;
|
|
258
|
+
export declare const MAX_CONSOLE_ARGS_BYTES = 4096;
|
|
259
|
+
/** Classify one console argument into a type-tagged {@link ConsoleArg} (spec #122 §C). */
|
|
260
|
+
export declare function toConsoleArg(value: unknown): ConsoleArg;
|
|
261
|
+
/**
|
|
262
|
+
* A `console` crumb from a captured call's level and arguments (spec #122 §C). The
|
|
263
|
+
* `message` is the one-line preview (flattened, truncated); `args` preserves each
|
|
264
|
+
* argument as a structured, type-tagged, size-capped value so the Console tab can
|
|
265
|
+
* render objects/errors expandably; `source` is the best-effort `file:line`, attached
|
|
266
|
+
* only when the stack yielded one. Args are omitted entirely for a no-argument call.
|
|
267
|
+
*/
|
|
268
|
+
export declare function consoleCrumb(level: BreadcrumbLevel, args: readonly unknown[], timestamp: number, source?: SourceLocation): Breadcrumb;
|
|
269
|
+
/** A `navigation` crumb; both URLs are scrubbed and length-capped as the crumb is built. */
|
|
85
270
|
export declare function navigationCrumb(from: string, to: string, timestamp: number): Breadcrumb;
|
|
86
|
-
/**
|
|
271
|
+
/**
|
|
272
|
+
* Classify an HTTP status into a {@link NetworkOutcome} (spec #122 §D). A missing or
|
|
273
|
+
* `0` status is a `network-error` (a request that never got a response); otherwise
|
|
274
|
+
* the 4xx/5xx classes flag failures and everything else is `ok`. Used both as the
|
|
275
|
+
* fallback outcome and by the thin {@link fetchCrumb} / {@link xhrCrumb} builders.
|
|
276
|
+
*/
|
|
277
|
+
export declare function outcomeFromStatus(status: number | undefined): NetworkOutcome;
|
|
278
|
+
/**
|
|
279
|
+
* The trivially-known byte size of a request body (spec #122 §D) — a string's UTF-8
|
|
280
|
+
* length, a `Blob`'s `.size`, or an `ArrayBuffer`/typed-array `.byteLength`. Anything
|
|
281
|
+
* that would require **reading** the body (a `ReadableStream`, `FormData`, a `Request`
|
|
282
|
+
* with a stream body) returns `undefined` — the "never read the body" line holds.
|
|
283
|
+
*/
|
|
284
|
+
export declare function trivialBodySize(body: unknown): number | undefined;
|
|
285
|
+
/** Parse a `content-length` header into a non-negative byte count, or `undefined`. */
|
|
286
|
+
export declare function parseContentLength(value: string | null | undefined): number | undefined;
|
|
287
|
+
/** The media type from a `content-type` header (the part before any `;` parameters). */
|
|
288
|
+
export declare function contentTypeOf(value: string | null | undefined): string | undefined;
|
|
289
|
+
/** The rich metadata a network crumb records (spec #122 §D) — never a body or header. */
|
|
290
|
+
export interface NetworkCrumbInput {
|
|
291
|
+
readonly api: NetworkApi;
|
|
292
|
+
readonly method: string;
|
|
293
|
+
/** The raw request URL — scrubbed (query dropped, path PII redacted) as the crumb is built. */
|
|
294
|
+
readonly url: string;
|
|
295
|
+
readonly status?: number;
|
|
296
|
+
readonly statusText?: string;
|
|
297
|
+
readonly durationMs?: number;
|
|
298
|
+
readonly reqSize?: number;
|
|
299
|
+
readonly respSize?: number;
|
|
300
|
+
readonly contentType?: string;
|
|
301
|
+
readonly outcome: NetworkOutcome;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* A network crumb (`fetch` / `xhr` / `beacon`) with the rich, metadata-only fields
|
|
305
|
+
* the Network tab renders (spec #122 §D, ticket #139): api, method, scrubbed URL,
|
|
306
|
+
* status + statusText, duration, request/response sizes, content type, and a failure
|
|
307
|
+
* outcome. The URL is scrubbed and length-capped at assembly. The shape has **no field
|
|
308
|
+
* for a request/response body or an arbitrary header**, so neither can ever be
|
|
309
|
+
* recorded; only a positive status, and fields that were actually supplied, ride along.
|
|
310
|
+
*/
|
|
311
|
+
export declare function networkCrumb(input: NetworkCrumbInput, timestamp: number): Breadcrumb;
|
|
312
|
+
/**
|
|
313
|
+
* A thin `fetch` crumb from method + URL + status (outcome derived from the status).
|
|
314
|
+
* The instrumentation uses {@link networkCrumb} directly to carry the full metadata;
|
|
315
|
+
* this convenience builder seeds a network crumb from a status alone.
|
|
316
|
+
*/
|
|
87
317
|
export declare function fetchCrumb(method: string, url: string, status: number | undefined, timestamp: number): Breadcrumb;
|
|
88
|
-
/**
|
|
318
|
+
/** A thin `xhr` crumb from method + URL + status (outcome derived from the status). */
|
|
89
319
|
export declare function xhrCrumb(method: string, url: string, status: number | undefined, timestamp: number): Breadcrumb;
|
|
90
320
|
/** A `ui.click` crumb: a masked target selector only — no text or value. */
|
|
91
321
|
export declare function clickCrumb(target: Element, timestamp: number): Breadcrumb;
|
|
@@ -94,8 +324,12 @@ export declare function clickCrumb(target: Element, timestamp: number): Breadcru
|
|
|
94
324
|
* the value typed into it. The `target` element's `.value` is never read.
|
|
95
325
|
*/
|
|
96
326
|
export declare function inputCrumb(target: Element, timestamp: number): Breadcrumb;
|
|
97
|
-
/**
|
|
98
|
-
|
|
327
|
+
/**
|
|
328
|
+
* An `error` crumb for the failing exception or rejection that ends the trace. When
|
|
329
|
+
* `causedBy` is given (an auto-captured error), it rides on the crumb as the causal
|
|
330
|
+
* pointer to the ids of the entries immediately preceding the throw (spec #122 §F).
|
|
331
|
+
*/
|
|
332
|
+
export declare function errorCrumb(error: unknown, timestamp: number, causedBy?: readonly string[]): Breadcrumb;
|
|
99
333
|
/** Detaches an installed instrumentation, restoring the original behaviour. */
|
|
100
334
|
export type Teardown = () => void;
|
|
101
335
|
type AnyFn = (...args: unknown[]) => unknown;
|
|
@@ -107,8 +341,10 @@ interface HistoryLike {
|
|
|
107
341
|
}
|
|
108
342
|
interface XhrInstance {
|
|
109
343
|
status: number;
|
|
344
|
+
statusText?: string;
|
|
110
345
|
open(method: string, url: string | URL, ...rest: unknown[]): void;
|
|
111
346
|
send(body?: unknown): void;
|
|
347
|
+
getResponseHeader?(name: string): string | null;
|
|
112
348
|
addEventListener(type: string, listener: () => void): void;
|
|
113
349
|
removeEventListener(type: string, listener: () => void): void;
|
|
114
350
|
}
|
|
@@ -116,6 +352,10 @@ interface XhrConstructor {
|
|
|
116
352
|
new (): XhrInstance;
|
|
117
353
|
prototype: XhrInstance;
|
|
118
354
|
}
|
|
355
|
+
/** The `navigator.sendBeacon` surface the beacon instrumentation wraps. */
|
|
356
|
+
export interface BeaconNavigator {
|
|
357
|
+
sendBeacon?: (url: string | URL, data?: BodyInit | null) => boolean;
|
|
358
|
+
}
|
|
119
359
|
/** The structural window surface the instrumentation reaches into. */
|
|
120
360
|
export interface InstrumentWindow {
|
|
121
361
|
fetch?: FetchFn;
|
|
@@ -124,6 +364,7 @@ export interface InstrumentWindow {
|
|
|
124
364
|
href: string;
|
|
125
365
|
};
|
|
126
366
|
XMLHttpRequest?: XhrConstructor;
|
|
367
|
+
navigator?: BeaconNavigator;
|
|
127
368
|
addEventListener(type: string, listener: (event: Event) => void, options?: boolean | AddEventListenerOptions): void;
|
|
128
369
|
removeEventListener(type: string, listener: (event: Event) => void, options?: boolean | EventListenerOptions): void;
|
|
129
370
|
}
|
|
@@ -136,22 +377,64 @@ export interface InstrumentOptions {
|
|
|
136
377
|
/** Skip URLs (e.g. the SDK's own ingest calls) so they never become crumbs. */
|
|
137
378
|
readonly ignoreUrl?: (url: string) => boolean;
|
|
138
379
|
readonly now?: () => number;
|
|
380
|
+
/**
|
|
381
|
+
* High-res monotonic clock (spec #122 §D) — used to measure a request's duration as
|
|
382
|
+
* a delta around the wrapped call. Defaults to `performance.now`; injectable for tests.
|
|
383
|
+
*/
|
|
384
|
+
readonly mono?: () => number;
|
|
385
|
+
/**
|
|
386
|
+
* Whether to instrument the **console** stream (spec #122 §L; ticket #138).
|
|
387
|
+
* Defaults to `true`; pass `false` and `console` is never wrapped, so no console
|
|
388
|
+
* entry is ever recorded — the per-project toggle stops the stream at its source.
|
|
389
|
+
*/
|
|
390
|
+
readonly captureConsole?: boolean;
|
|
391
|
+
/**
|
|
392
|
+
* Whether to instrument the **network** stream — `fetch` and `XHR` (spec #122 §L;
|
|
393
|
+
* ticket #138). Defaults to `true`; pass `false` and neither is wrapped, so no
|
|
394
|
+
* network entry is ever recorded. Navigation and masked UI events are unaffected.
|
|
395
|
+
*/
|
|
396
|
+
readonly captureNetwork?: boolean;
|
|
139
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* The best-effort `file:line` a console call was made from (spec #122 §C). Parses the
|
|
400
|
+
* frames of a stack, skipping `skipFrames` leading (SDK-internal) frames so the source
|
|
401
|
+
* points at the host code that called `console.*`. Returns `undefined` when no frame
|
|
402
|
+
* yields a usable location — the crumb then simply omits `source`.
|
|
403
|
+
*/
|
|
404
|
+
export declare function sourceFromStack(stack: string | undefined, skipFrames?: number): SourceLocation | undefined;
|
|
140
405
|
/** Wrap `console` methods so calls at the captured levels become crumbs. */
|
|
141
406
|
export declare function instrumentConsole(buffer: BreadcrumbBuffer, consoleObj: ConsoleLike, levels: readonly BreadcrumbLevel[], now: () => number): Teardown;
|
|
142
407
|
/**
|
|
143
|
-
* Wrap `fetch` to record a crumb on settlement
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
408
|
+
* Wrap `fetch` to record a rich network crumb on settlement (spec #122 §D, ticket
|
|
409
|
+
* #139): method, scrubbed URL, status + statusText, a `performance.now()` duration,
|
|
410
|
+
* request size (only when the body is trivially sized), response size (from the
|
|
411
|
+
* `content-length` header only), content type, and a failure outcome. The **original**
|
|
412
|
+
* outcome is returned untouched — the response is passed through **without its body
|
|
413
|
+
* being read** (only two metadata headers are inspected), and a rejection is re-thrown
|
|
414
|
+
* so the caller's `unhandledrejection` semantics are preserved.
|
|
415
|
+
*/
|
|
416
|
+
export declare function instrumentFetch(buffer: BreadcrumbBuffer, win: InstrumentWindow, ignoreUrl: (url: string) => boolean, now: () => number, mono?: () => number): Teardown;
|
|
417
|
+
/**
|
|
418
|
+
* Patch `XMLHttpRequest` to record a rich network crumb when a request settles (spec
|
|
419
|
+
* #122 §D, ticket #139): method, scrubbed URL, status + statusText, a `performance.now()`
|
|
420
|
+
* duration, request size (only when the body is trivially sized), response size (from
|
|
421
|
+
* the `content-length` header only), content type, and a failure outcome distinguished
|
|
422
|
+
* by which terminal event fired (`error` / `timeout` / `abort` / `load`). The `send`
|
|
423
|
+
* body argument is **never read for content** — only its trivially-known size — so a body
|
|
424
|
+
* can never reach the buffer.
|
|
147
425
|
*/
|
|
148
|
-
export declare function
|
|
426
|
+
export declare function instrumentXhr(buffer: BreadcrumbBuffer, win: InstrumentWindow, ignoreUrl: (url: string) => boolean, now: () => number, mono?: () => number): Teardown;
|
|
149
427
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
428
|
+
* Wrap `navigator.sendBeacon` to record a network crumb for each beacon (spec #122 §D,
|
|
429
|
+
* ticket #139). `sendBeacon` is fire-and-forget with a **synchronous boolean** return —
|
|
430
|
+
* `true` when the user agent queued the beacon, `false` when it declined — so wrapping
|
|
431
|
+
* must return that boolean unchanged: the original is called first and its result both
|
|
432
|
+
* classifies the crumb (`ok` / `network-error`) and is returned to the caller. Only the
|
|
433
|
+
* URL and the trivially-known request size are recorded (no response exists to read);
|
|
434
|
+
* capture failure is swallowed and the boolean still returned, and if the original itself
|
|
435
|
+
* throws we record best-effort and re-throw so the contract is preserved exactly.
|
|
153
436
|
*/
|
|
154
|
-
export declare function
|
|
437
|
+
export declare function instrumentBeacon(buffer: BreadcrumbBuffer, win: InstrumentWindow, ignoreUrl: (url: string) => boolean, now: () => number): Teardown;
|
|
155
438
|
/** Record a `navigation` crumb on `pushState`/`replaceState`/pop/hash changes. */
|
|
156
439
|
export declare function instrumentNavigation(buffer: BreadcrumbBuffer, win: InstrumentWindow, now: () => number): Teardown;
|
|
157
440
|
/** Listen (capture-phase) for clicks and input changes as masked crumbs. */
|
package/dist/dom.d.ts
CHANGED
|
@@ -10,6 +10,13 @@
|
|
|
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;
|
|
13
20
|
/**
|
|
14
21
|
* Is this node part of the SDK's own UI? Walks up parents and out through any
|
|
15
22
|
* Shadow DOM boundary (via `getRootNode().host`), so a click inside the overlay's
|
package/dist/error-capture.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Exactly **two capture-phase listeners** (`window` `error` +
|
|
7
7
|
* `unhandledrejection`) turn uncaught exceptions and unhandled rejections into
|
|
8
|
-
* `source: auto
|
|
8
|
+
* `source: auto` Feedback (stamped `Kind = bug` server-side, ADR-0023) for the current session's Reporter — no
|
|
9
9
|
* native-API monkeypatching, no library. Each firing is deduped by a per-session
|
|
10
10
|
* fingerprint, rate-limited by a token-bucket burst limiter and a per-session cap,
|
|
11
11
|
* scrubbed through the same `beforeSend` choke point as manual reports (§C), and
|
|
@@ -26,6 +26,9 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import type { IdentityInputs } from "./boot";
|
|
28
28
|
import { type BreadcrumbBuffer, type Teardown } from "./breadcrumbs";
|
|
29
|
+
import type { ReporterDisplay } from "./invite";
|
|
30
|
+
import { type CapturedFrame } from "./report";
|
|
31
|
+
import type { ReplaySource } from "./replay";
|
|
29
32
|
import { type BeforeSend } from "./scrub";
|
|
30
33
|
import { type Capture, type CaptureOptions } from "./screenshot";
|
|
31
34
|
import { type SubmitInput, type SubmitResult } from "./submit";
|
|
@@ -57,6 +60,15 @@ export declare function hashString(input: string): string;
|
|
|
57
60
|
* a session. Returns `""` when there is no usable stack (message-only fallback).
|
|
58
61
|
*/
|
|
59
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[];
|
|
60
72
|
/**
|
|
61
73
|
* The per-session fingerprint (research §7.2):
|
|
62
74
|
* `hash(errorType + "|" + normalize(value) + "|" + topFrames)`. Stack frames
|
|
@@ -95,13 +107,31 @@ export interface AutoCaptureConfig {
|
|
|
95
107
|
readonly apiUrl: string;
|
|
96
108
|
readonly key: string;
|
|
97
109
|
readonly identity?: IdentityInputs;
|
|
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;
|
|
98
116
|
/** The window whose global handlers are installed. Defaults to `window`. */
|
|
99
117
|
readonly win?: Window;
|
|
100
118
|
/** The document used for capture + environment. Defaults to the window's. */
|
|
101
119
|
readonly doc?: Document;
|
|
102
120
|
readonly sdkVersion?: string;
|
|
121
|
+
/**
|
|
122
|
+
* The host app's **Release** (#117, ADR-0024) — already validated by `init`
|
|
123
|
+
* (`normaliseRelease`). Stamped into every auto report's environment so the
|
|
124
|
+
* server can symbolicate the captured frames against this build's sourcemaps.
|
|
125
|
+
*/
|
|
126
|
+
readonly release?: string;
|
|
103
127
|
/** The shared trace buffer; the failing error is added to it before filing. */
|
|
104
128
|
readonly buffer?: BreadcrumbBuffer | null;
|
|
129
|
+
/**
|
|
130
|
+
* The shared replay recorder (ADR-0024); the buffered window rides on a rich
|
|
131
|
+
* first report — the moment before an uncaught error is exactly what replay
|
|
132
|
+
* exists to show. Light count-update flushes never re-send it.
|
|
133
|
+
*/
|
|
134
|
+
readonly replay?: ReplaySource | null;
|
|
105
135
|
/** Per-project client scrub hook, run at the `beforeSend` choke point (§C). */
|
|
106
136
|
readonly beforeSend?: BeforeSend;
|
|
107
137
|
/** Run the built-in default scrubbers. Defaults to `true` (private-by-default). */
|