@tracelane/core 0.1.0-alpha.14 → 0.1.0-alpha.16

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 CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  # @tracelane/core
4
4
 
5
- > The reporter for your WebdriverIO tests — Playwright and Cypress on the roadmap. Self-contained HTML for every run — replay failures, audit successes, attach to any bug tracker. No SaaS, no dashboard, no signup.
5
+ > The recorder for your WebdriverIO and Playwright tests — Cypress on the roadmap. Self-contained HTML for every run — replay failures, audit successes, attach to any bug tracker. No SaaS, no dashboard, no signup.
6
6
 
7
7
  Framework-agnostic recording engine for `tracelane`. Wraps a per-framework `browser` object behind a common `BrowserExecutor` interface, injects the rrweb capture bundle, drains in-page events to Node, and builds the buffer that the report packages render.
8
8
 
9
9
  **Not intended for direct consumption** — depend on a product package instead:
10
10
 
11
11
  ```sh
12
- npm install --save-dev @tracelane/wdio # WebdriverIO Service
13
- # @tracelane/playwright planned Q3 2026
14
- # @tracelane/cypress — planned Q4 2026
12
+ npm install --save-dev @tracelane/wdio # WebdriverIO Service
13
+ npm install --save-dev @tracelane/playwright # Playwright reporter + fixture
14
+ # @tracelane/cypress — planned Q4 2026
15
15
  ```
16
16
 
17
17
  See the [`@tracelane/wdio` README](https://github.com/Cubenest/rrweb-stack/tree/main/packages/tracelane-wdio) for the integration guide.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export type { BrowserExecutor } from './browser-executor.js';
2
2
  export { __internal, attachNetworkCapture } from './network-capture.js';
3
+ export type { AttachNetworkCaptureOptions, ResponseMeta } from './network-capture.js';
3
4
  export { loadRrwebBundle } from './load-rrweb-bundle.js';
4
5
  export { createRecorder, DEFAULT_COOLDOWN_MS, DEFAULT_DRAIN_INTERVAL_MS } from './recorder.js';
5
6
  export type { FinalizeResult, Recorder, RecorderOptions, TestOutcome } from './recorder.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAO7D,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAIxE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC/F,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5F,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACtD,YAAY,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAO7D,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACxE,YAAY,EAAE,2BAA2B,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAItF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC/F,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5F,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACtD,YAAY,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAK1C,gFAAgF;AAChF,iFAAiF;AACjF,6EAA6E;AAC7E,6EAA6E;AAC7E,kFAAkF;AAClF,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAExE,+EAA+E;AAC/E,yEAAyE;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAI/F,kCAAkC;AAClC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGtD,yEAAyE;AACzE,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,cAAc,GACf,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAK1C,gFAAgF;AAChF,iFAAiF;AACjF,6EAA6E;AAC7E,6EAA6E;AAC7E,kFAAkF;AAClF,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGxE,+EAA+E;AAC/E,yEAAyE;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAI/F,kCAAkC;AAClC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGtD,yEAAyE;AACzE,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,cAAc,GACf,MAAM,iBAAiB,CAAC"}
@@ -1,4 +1,46 @@
1
1
  import type { BrowserExecutor } from './browser-executor.js';
2
+ /** Options for {@link attachNetworkCapture}. */
3
+ export interface AttachNetworkCaptureOptions {
4
+ /**
5
+ * Capture privacy-safe MAIN-DOCUMENT response metadata (security-header
6
+ * PRESENCE + cookie FLAGS only) on a `[tracelane.sec]` console line. Default
7
+ * `true`; set `false` to fully disable — the `[tracelane.net]` behavior is
8
+ * unaffected either way.
9
+ */
10
+ security?: boolean;
11
+ /**
12
+ * Node-side sink for the privacy-safe main-document response metadata. When
13
+ * set, the meta is delivered here (e.g. recorder.addCustomEvent) instead of a
14
+ * page console.error — reliable across navigation. Receives names + flags only.
15
+ */
16
+ onSecurityMeta?: (meta: ResponseMeta) => void;
17
+ }
18
+ /** A privacy-safe per-cookie record: NAME + flag presence booleans only. */
19
+ interface CookieFlags {
20
+ name: string;
21
+ secure: boolean;
22
+ httpOnly: boolean;
23
+ sameSite: boolean;
24
+ }
25
+ /** The privacy-safe main-document response metadata carried on `[tracelane.sec]`. */
26
+ export interface ResponseMeta {
27
+ url: string;
28
+ status: number;
29
+ isMainDocument: true;
30
+ presentSecurityHeaders: string[];
31
+ setCookies: CookieFlags[];
32
+ }
33
+ /**
34
+ * Return the allowlisted security-header NAMES present in `headers` (lowercased).
35
+ * Pure; never reads or returns any header VALUE.
36
+ */
37
+ declare function presentSecurityHeaders(headers: Record<string, string> | undefined, allow: readonly string[]): string[];
38
+ /**
39
+ * Parse a CDP `set-cookie` header into per-cookie FLAG PRESENCE records. CDP
40
+ * joins multiple Set-Cookie headers with newlines. Captures only the cookie
41
+ * NAME (left of the first `=`) and three flag booleans — NEVER the value.
42
+ */
43
+ declare function parseSetCookies(setCookieHeader: string | undefined): CookieFlags[];
2
44
  /**
3
45
  * Page-side logger. Self-contained (no Node closures) so it can be
4
46
  * `.toString()`-serialized by `execute` (PRD §A.4). The console plugin captures
@@ -29,10 +71,13 @@ declare function methodOf(headers: Record<string, string> | undefined): string;
29
71
  * either succeeded (`responseReceived`) or failed (`loadingFailed`) so the map
30
72
  * can't grow unbounded over a long session.
31
73
  */
32
- export declare function attachNetworkCapture(executor: BrowserExecutor): Promise<void>;
74
+ export declare function attachNetworkCapture(executor: BrowserExecutor, options?: AttachNetworkCaptureOptions): Promise<void>;
33
75
  export declare const __internal: {
34
76
  logNetworkErrorInPage: typeof logNetworkErrorInPage;
35
77
  methodOf: typeof methodOf;
78
+ presentSecurityHeaders: typeof presentSecurityHeaders;
79
+ parseSetCookies: typeof parseSetCookies;
80
+ SEC_HEADER_ALLOWLIST: readonly ["content-security-policy", "strict-transport-security", "x-frame-options", "x-content-type-options", "referrer-policy"];
36
81
  };
37
82
  export {};
38
83
  //# sourceMappingURL=network-capture.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"network-capture.d.ts","sourceRoot":"","sources":["../src/network-capture.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAoC7D;;;;;;;;;;GAUG;AACH,iBAAS,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAMhF;AAED,6EAA6E;AAC7E,iBAAS,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAKrE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DnF;AAGD,eAAO,MAAM,UAAU;;;CAAsC,CAAC"}
1
+ {"version":3,"file":"network-capture.d.ts","sourceRoot":"","sources":["../src/network-capture.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAkD7D,gDAAgD;AAChD,MAAM,WAAW,2BAA2B;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;CAC/C;AAeD,4EAA4E;AAC5E,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,qFAAqF;AACrF,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,IAAI,CAAC;IACrB,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,UAAU,EAAE,WAAW,EAAE,CAAC;CAC3B;AAED;;;GAGG;AACH,iBAAS,sBAAsB,CAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC3C,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,MAAM,EAAE,CAIV;AAED;;;;GAIG;AACH,iBAAS,eAAe,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,EAAE,CAgB3E;AAKD;;;;;;;;;;GAUG;AACH,iBAAS,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAMhF;AAED,6EAA6E;AAC7E,iBAAS,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAKrE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,eAAe,EACzB,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,IAAI,CAAC,CAkIf;AAGD,eAAO,MAAM,UAAU;;;;;;CAMtB,CAAC"}
@@ -23,6 +23,51 @@
23
23
  // a true failure only when a method is present (its "true error path" rule —
24
24
  // see `isTrueErrorPath`), so a methodless `loadingFailed` line would be
25
25
  // silently dropped from the panel.
26
+ /**
27
+ * The fixed allowlist of security-relevant response-header names whose PRESENCE
28
+ * (never value) we surface. Lowercased; CDP header keys are case-preserving so
29
+ * presence checks compare case-insensitively.
30
+ */
31
+ const SEC_HEADER_ALLOWLIST = [
32
+ 'content-security-policy',
33
+ 'strict-transport-security',
34
+ 'x-frame-options',
35
+ 'x-content-type-options',
36
+ 'referrer-policy',
37
+ ];
38
+ /**
39
+ * Return the allowlisted security-header NAMES present in `headers` (lowercased).
40
+ * Pure; never reads or returns any header VALUE.
41
+ */
42
+ function presentSecurityHeaders(headers, allow) {
43
+ if (!headers)
44
+ return [];
45
+ const lower = new Set(Object.keys(headers).map((k) => k.toLowerCase()));
46
+ return allow.filter((h) => lower.has(h));
47
+ }
48
+ /**
49
+ * Parse a CDP `set-cookie` header into per-cookie FLAG PRESENCE records. CDP
50
+ * joins multiple Set-Cookie headers with newlines. Captures only the cookie
51
+ * NAME (left of the first `=`) and three flag booleans — NEVER the value.
52
+ */
53
+ function parseSetCookies(setCookieHeader) {
54
+ if (!setCookieHeader)
55
+ return [];
56
+ return setCookieHeader
57
+ .split('\n')
58
+ .map((l) => l.trim())
59
+ .filter(Boolean)
60
+ .map((line) => {
61
+ const name = (line.split('=', 1)[0] ?? '').trim();
62
+ const low = line.toLowerCase();
63
+ return {
64
+ name,
65
+ secure: /(?:^|;)\s*secure(?:\s*;|\s*$)/.test(low),
66
+ httpOnly: /(?:^|;)\s*httponly(?:\s*;|\s*$)/.test(low),
67
+ sameSite: /(?:^|;)\s*samesite\s*=/.test(low),
68
+ };
69
+ });
70
+ }
26
71
  /** Status sentinel for a request that produced no response (a true 0 once parsed). */
27
72
  const NO_RESPONSE_STATUS = 0;
28
73
  /**
@@ -68,7 +113,8 @@ function methodOf(headers) {
68
113
  * either succeeded (`responseReceived`) or failed (`loadingFailed`) so the map
69
114
  * can't grow unbounded over a long session.
70
115
  */
71
- export async function attachNetworkCapture(executor) {
116
+ export async function attachNetworkCapture(executor, options = {}) {
117
+ const security = options.security !== false;
72
118
  await executor.cdp('Network', 'enable');
73
119
  // Correlation map: a `loadingFailed` carries only a requestId, so remember the
74
120
  // method + url from `requestWillBeSent` to reconstruct a method-bearing line.
@@ -82,6 +128,32 @@ export async function attachNetworkCapture(executor) {
82
128
  /* page may be navigating; drop this one line */
83
129
  });
84
130
  };
131
+ // --- Privacy-safe main-document security metadata ([tracelane.sec]) ---------
132
+ // We track the top-level document's requestId, then assemble a ResponseMeta
133
+ // from `responseReceived` (header presence) + `responseReceivedExtraInfo`
134
+ // (cookie flags). Both CDP events for the main-document response are delivered
135
+ // in the same task batch; we defer the single emit to a microtask (scheduled
136
+ // from `responseReceived`) so cookie flags from `responseReceivedExtraInfo`
137
+ // are folded in regardless of arrival order — whichever event arrives second
138
+ // has landed in the same task before the microtask runs. The
139
+ // `responseReceivedExtraInfo` handler only STASHES cookies; it never emits.
140
+ // `mainDocEmitted` guarantees exactly-once (so a missing/late extraInfo still
141
+ // emits with whatever cookies were stashed, possibly `[]`).
142
+ let mainDocId;
143
+ let mainDocMeta;
144
+ let mainDocCookies;
145
+ let mainDocEmitted = false;
146
+ // Emit exactly once, folding in any stashed cookies. Called from the deferred
147
+ // microtask scheduled by `responseReceived`; the guard makes a second call
148
+ // (e.g. if ever scheduled twice) a no-op. Fire-and-forget.
149
+ const tryEmitSec = () => {
150
+ if (mainDocEmitted || !mainDocMeta)
151
+ return;
152
+ mainDocEmitted = true;
153
+ if (mainDocCookies)
154
+ mainDocMeta.setCookies = mainDocCookies;
155
+ options.onSecurityMeta?.(mainDocMeta);
156
+ };
85
157
  executor.on('Network.requestWillBeSent', (params) => {
86
158
  const e = params;
87
159
  const id = e?.requestId;
@@ -90,7 +162,31 @@ export async function attachNetworkCapture(executor) {
90
162
  return;
91
163
  const method = typeof e.request?.method === 'string' ? e.request.method : 'GET';
92
164
  inflight.set(id, { method, url });
165
+ // Remember the top-level document's requestId so we can attach security meta
166
+ // to its response. Only the first Document wins (the main navigation).
167
+ if (security && e.type === 'Document' && mainDocId === undefined) {
168
+ mainDocId = id;
169
+ }
93
170
  });
171
+ if (security) {
172
+ executor.on('Network.responseReceivedExtraInfo', (params) => {
173
+ const e = params;
174
+ if (typeof e?.requestId !== 'string' || e.requestId !== mainDocId)
175
+ return;
176
+ // CDP exposes Set-Cookie here (header keys are typically lowercased in
177
+ // extra-info), not on responseReceived.response.headers.
178
+ const headers = e.headers ?? {};
179
+ const setCookieKey = Object.keys(headers).find((k) => k.toLowerCase() === 'set-cookie');
180
+ const cookies = parseSetCookies(setCookieKey ? headers[setCookieKey] : undefined);
181
+ // STASH ONLY — never emit here. The deferred microtask scheduled by
182
+ // `responseReceived` folds these in. If meta already exists, also write
183
+ // through so it's covered even if this handler runs after the microtask
184
+ // was scheduled (the microtask reads mainDocMeta.setCookies / mainDocCookies).
185
+ mainDocCookies = cookies;
186
+ if (mainDocMeta)
187
+ mainDocMeta.setCookies = cookies;
188
+ });
189
+ }
94
190
  executor.on('Network.responseReceived', (params) => {
95
191
  const e = params;
96
192
  const response = e?.response;
@@ -104,6 +200,26 @@ export async function attachNetworkCapture(executor) {
104
200
  const tracked = typeof id === 'string' ? inflight.get(id) : undefined;
105
201
  if (typeof id === 'string')
106
202
  inflight.delete(id);
203
+ // Main-document security metadata. Per CDP, responseReceivedExtraInfo fires
204
+ // BEFORE responseReceived, so any cookies have usually already been stashed;
205
+ // we fold them in and emit ONCE here. If extraInfo never comes, we still emit
206
+ // with `setCookies: []`. The emit guard prevents a double emit if a stray
207
+ // extraInfo arrives afterwards.
208
+ if (security && typeof id === 'string' && id === mainDocId && !mainDocEmitted) {
209
+ const status = response?.status;
210
+ const meta = {
211
+ url: response?.url ?? '',
212
+ status: typeof status === 'number' ? status : 0,
213
+ isMainDocument: true,
214
+ presentSecurityHeaders: presentSecurityHeaders(response?.headers, SEC_HEADER_ALLOWLIST),
215
+ setCookies: mainDocCookies ?? [],
216
+ };
217
+ mainDocMeta = meta;
218
+ // Defer the single emit so a same-task-batch responseReceivedExtraInfo
219
+ // (which may arrive before OR after this event) lands its cookie flags
220
+ // first. The mainDocEmitted guard keeps it exactly-once.
221
+ queueMicrotask(() => tryEmitSec());
222
+ }
107
223
  const status = response?.status;
108
224
  if (typeof status !== 'number' || status < 400)
109
225
  return;
@@ -126,6 +242,12 @@ export async function attachNetworkCapture(executor) {
126
242
  emit(url, NO_RESPONSE_STATUS, method);
127
243
  });
128
244
  }
129
- // Exposed for unit tests: the page-side logger + method resolver are pure.
130
- export const __internal = { logNetworkErrorInPage, methodOf };
245
+ // Exposed for unit tests: the page-side loggers + pure resolvers/parsers.
246
+ export const __internal = {
247
+ logNetworkErrorInPage,
248
+ methodOf,
249
+ presentSecurityHeaders,
250
+ parseSetCookies,
251
+ SEC_HEADER_ALLOWLIST,
252
+ };
131
253
  //# sourceMappingURL=network-capture.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"network-capture.js","sourceRoot":"","sources":["../src/network-capture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"network-capture.js","sourceRoot":"","sources":["../src/network-capture.ts"],"names":[],"mappings":"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"}
@@ -80,6 +80,8 @@ export interface Recorder {
80
80
  finalize(outcome: TestOutcome): Promise<FinalizeResult>;
81
81
  /** The merged Node-side event buffer (live reference). */
82
82
  getBuffer(): eventWithTime[];
83
+ /** Append a Node-side rrweb Custom event directly to the buffer — immune to page navigation timing (unlike a page console.error). */
84
+ addCustomEvent(tag: string, payload: unknown): void;
83
85
  }
84
86
  export declare function createRecorder(options: RecorderOptions): Recorder;
85
87
  //# sourceMappingURL=recorder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,KAAK,IAAI,EAAe,MAAM,WAAW,CAAC;AACnD,OAAO,EACL,KAAK,oBAAoB,EAEzB,KAAK,oBAAoB,EAI1B,MAAM,kBAAkB,CAAC;AAE1B,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,iBAAiB,EAAE,OAAO,CAAC;IAC3B,kEAAkE;IAClE,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,8EAA8E;IAC9E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,gFAAgF;IAChF,KAAK,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAClC,8CAA8C;IAC9C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACxD,0DAA0D;IAC1D,SAAS,IAAI,aAAa,EAAE,CAAC;CAC9B;AASD,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,QAAQ,CAkGjE"}
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,KAAK,IAAI,EAAe,MAAM,WAAW,CAAC;AACnD,OAAO,EACL,KAAK,oBAAoB,EAEzB,KAAK,oBAAoB,EAI1B,MAAM,kBAAkB,CAAC;AAE1B,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,iBAAiB,EAAE,OAAO,CAAC;IAC3B,kEAAkE;IAClE,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,8EAA8E;IAC9E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,gFAAgF;IAChF,KAAK,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAClC,8CAA8C;IAC9C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACxD,0DAA0D;IAC1D,SAAS,IAAI,aAAa,EAAE,CAAC;IAC7B,qIAAqI;IACrI,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACrD;AAiCD,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,QAAQ,CAgIjE"}
package/dist/recorder.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { EventType } from '@cubenest/rrweb-core';
1
2
  import { resolveMode } from './mode.js';
2
3
  import { DEFAULT_CONSOLE_PLUGIN_OPTIONS, tracelaneDrainScript, tracelaneInitScript, tracelaneNavScript, } from './page-script.js';
3
4
  /** Default re-injection cooldown in ms (ADR-0006). */
@@ -16,6 +17,25 @@ function injectBundleScript(bundle) {
16
17
  // a real global), which is the intended injection behavior in the page context.
17
18
  window.eval(bundle);
18
19
  }
20
+ /**
21
+ * Bounded retry for page-side re-injection. `framenavigated` can fire while the
22
+ * new document's execution context is still being (re)created, so the first
23
+ * page-evaluate races the navigation and throws "Execution context was
24
+ * destroyed". On a real (latency-bearing) navigation that single failure would
25
+ * otherwise be swallowed by the caller and silently lose ALL DOM capture on the
26
+ * new page. The context stabilizes within a few ms of navigation, so a short
27
+ * bounded retry reliably recovers recording.
28
+ */
29
+ const REINJECT_MAX_ATTEMPTS = 6;
30
+ const REINJECT_RETRY_MS = 100;
31
+ /** True for the transient errors a page op throws when it races a navigation. */
32
+ function isNavigationRace(err) {
33
+ const msg = err instanceof Error ? err.message : String(err);
34
+ return /execution context was destroyed|context was destroyed|frame (was )?detached|target closed|because of a navigation/i.test(msg);
35
+ }
36
+ function sleep(ms) {
37
+ return new Promise((resolve) => setTimeout(resolve, ms));
38
+ }
19
39
  export function createRecorder(options) {
20
40
  const { executor, rrwebBundle, drainIntervalMs = DEFAULT_DRAIN_INTERVAL_MS, cooldownMs = DEFAULT_COOLDOWN_MS, consolePluginOptions = DEFAULT_CONSOLE_PLUGIN_OPTIONS, networkPluginOptions, mode: configMode, } = options;
21
41
  const buffer = [];
@@ -40,16 +60,48 @@ export function createRecorder(options) {
40
60
  async function reinject(url) {
41
61
  // Re-eval the bundle (the page may have been torn down by navigation), then
42
62
  // re-run init. The init script's return value is the authority on whether a
43
- // fresh recording started.
44
- await executor.execute(injectBundleScript, rrwebBundle);
45
- const sid = await runInit();
46
- if (sid === 0)
47
- return false; // cooldown-suppressed (same-doc hash/HMR); no nav boundary
48
- await executor.execute(tracelaneNavScript, url, Date.now());
49
- return true;
63
+ // fresh recording started. Retry on navigation-race errors so a single
64
+ // page-evaluate that races the in-flight nav doesn't silently lose all DOM
65
+ // capture on the new page (the failure mode on real, latency-bearing sites).
66
+ let lastErr;
67
+ for (let attempt = 0; attempt < REINJECT_MAX_ATTEMPTS; attempt++) {
68
+ try {
69
+ await executor.execute(injectBundleScript, rrwebBundle);
70
+ const sid = await runInit();
71
+ if (sid === 0)
72
+ return false; // cooldown-suppressed (same-doc hash/HMR); no nav boundary
73
+ await executor.execute(tracelaneNavScript, url, Date.now());
74
+ return true;
75
+ }
76
+ catch (err) {
77
+ lastErr = err;
78
+ if (!isNavigationRace(err))
79
+ throw err; // a real failure, not a transient nav race
80
+ if (attempt < REINJECT_MAX_ATTEMPTS - 1)
81
+ await sleep(REINJECT_RETRY_MS);
82
+ }
83
+ }
84
+ throw lastErr; // retries exhausted; the caller treats reinject as best-effort
85
+ }
86
+ function addCustomEvent(tag, payload) {
87
+ buffer.push({
88
+ type: EventType.Custom,
89
+ timestamp: Date.now(),
90
+ data: { tag, payload },
91
+ });
50
92
  }
51
93
  async function drain() {
52
- const batch = (await executor.execute(tracelaneDrainScript));
94
+ let batch;
95
+ try {
96
+ batch = (await executor.execute(tracelaneDrainScript));
97
+ }
98
+ catch (err) {
99
+ // A poll firing mid-navigation hits "context destroyed"; skip this cycle.
100
+ // The next poll (or the init script's pagehide flush) recovers the events.
101
+ if (isNavigationRace(err))
102
+ return [];
103
+ throw err;
104
+ }
53
105
  if (batch && batch.length > 0) {
54
106
  buffer.push(...batch);
55
107
  return batch;
@@ -91,6 +143,7 @@ export function createRecorder(options) {
91
143
  stop,
92
144
  finalize,
93
145
  getBuffer: () => buffer,
146
+ addCustomEvent,
94
147
  };
95
148
  }
96
149
  //# sourceMappingURL=recorder.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD,OAAO,EAAa,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAEL,8BAA8B,EAE9B,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,sDAAsD;AACtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AA6E7C,kFAAkF;AAClF,SAAS,kBAAkB,CAAC,MAAc;IACxC,8EAA8E;IAC9E,gFAAgF;IAC/E,MAAsD,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACvE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAChC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,iFAAiF;AACjF,SAAS,gBAAgB,CAAC,GAAY;IACpC,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,oHAAoH,CAAC,IAAI,CAC9H,GAAG,CACJ,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAwB;IACrD,MAAM,EACJ,QAAQ,EACR,WAAW,EACX,eAAe,GAAG,yBAAyB,EAC3C,UAAU,GAAG,mBAAmB,EAChC,oBAAoB,GAAG,8BAA8B,EACrD,oBAAoB,EACpB,IAAI,EAAE,UAAU,GACjB,GAAG,OAAO,CAAC;IAEZ,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,IAAI,SAAqD,CAAC;IAC1D,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB;;;;;;;;OAQG;IACH,KAAK,UAAU,OAAO;QACpB,OAAO,QAAQ,CAAC,OAAO,CACrB,mBAAqD,EACrD,UAAU,EACV,oBAAoB,EACpB,oBAAoB,CACrB,CAAC;IACJ,CAAC;IAED,KAAK,UAAU,MAAM;QACnB,MAAM,QAAQ,CAAC,OAAO,CAAC,kBAAkD,EAAE,WAAW,CAAC,CAAC;QACxF,MAAM,OAAO,EAAE,CAAC;IAClB,CAAC;IAED,KAAK,UAAU,QAAQ,CAAC,GAAW;QACjC,4EAA4E;QAC5E,4EAA4E;QAC5E,uEAAuE;QACvE,2EAA2E;QAC3E,6EAA6E;QAC7E,IAAI,OAAgB,CAAC;QACrB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,qBAAqB,EAAE,OAAO,EAAE,EAAE,CAAC;YACjE,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,OAAO,CAAC,kBAAkD,EAAE,WAAW,CAAC,CAAC;gBACxF,MAAM,GAAG,GAAG,MAAM,OAAO,EAAE,CAAC;gBAC5B,IAAI,GAAG,KAAK,CAAC;oBAAE,OAAO,KAAK,CAAC,CAAC,2DAA2D;gBACxF,MAAM,QAAQ,CAAC,OAAO,CAAC,kBAAkD,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;gBAC5F,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,GAAG,GAAG,CAAC;gBACd,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC;oBAAE,MAAM,GAAG,CAAC,CAAC,2CAA2C;gBAClF,IAAI,OAAO,GAAG,qBAAqB,GAAG,CAAC;oBAAE,MAAM,KAAK,CAAC,iBAAiB,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QACD,MAAM,OAAO,CAAC,CAAC,+DAA+D;IAChF,CAAC;IAED,SAAS,cAAc,CAAC,GAAW,EAAE,OAAgB;QACnD,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,SAAS,CAAC,MAAM;YACtB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;SACN,CAAC,CAAC;IACtB,CAAC;IAED,KAAK,UAAU,KAAK;QAClB,IAAI,KAAyC,CAAC;QAC9C,IAAI,CAAC;YACH,KAAK,GAAG,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,oBAAyD,CAAC,CAG7E,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,0EAA0E;YAC1E,2EAA2E;YAC3E,IAAI,gBAAgB,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,CAAC;YACrC,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,KAAK,UAAU,KAAK;QAClB,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,GAAG,IAAI,CAAC;QACf,MAAM,MAAM,EAAE,CAAC;QACf,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;YAC3B,KAAK,KAAK,EAAE,CAAC;QACf,CAAC,EAAE,eAAe,CAAC,CAAC;IACtB,CAAC;IAED,KAAK,UAAU,IAAI;QACjB,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,aAAa,CAAC,SAAS,CAAC,CAAC;YACzB,SAAS,GAAG,SAAS,CAAC;QACxB,CAAC;QACD,OAAO,GAAG,KAAK,CAAC;QAChB,MAAM,KAAK,EAAE,CAAC;IAChB,CAAC;IAED,KAAK,UAAU,QAAQ,CAAC,OAAoB;QAC1C,MAAM,IAAI,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,iBAAiB,GAAG,IAAI,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAC5D,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,wEAAwE;YACxE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;YAClB,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAClD,CAAC;QACD,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACrD,CAAC;IAED,OAAO;QACL,KAAK;QACL,QAAQ;QACR,KAAK;QACL,IAAI;QACJ,QAAQ;QACR,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM;QACvB,cAAc;KACf,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tracelane/core",
3
- "version": "0.1.0-alpha.14",
3
+ "version": "0.1.0-alpha.16",
4
4
  "description": "Framework-agnostic rrweb recording engine for tracelane. Wraps a per-framework browser object behind a common BrowserExecutor interface.",
5
5
  "keywords": [
6
6
  "tracelane",