@cubenest/rrweb-core 0.1.0-alpha.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.
Files changed (135) hide show
  1. package/NOTICE +15 -0
  2. package/README.md +26 -0
  3. package/dist/compat/index.d.ts +37 -0
  4. package/dist/compat/index.d.ts.map +1 -0
  5. package/dist/compat/index.js +97 -0
  6. package/dist/compat/index.js.map +1 -0
  7. package/dist/compression/index.d.ts +24 -0
  8. package/dist/compression/index.d.ts.map +1 -0
  9. package/dist/compression/index.js +61 -0
  10. package/dist/compression/index.js.map +1 -0
  11. package/dist/console/buffer.d.ts +99 -0
  12. package/dist/console/buffer.d.ts.map +1 -0
  13. package/dist/console/buffer.js +169 -0
  14. package/dist/console/buffer.js.map +1 -0
  15. package/dist/console/index.d.ts +3 -0
  16. package/dist/console/index.d.ts.map +1 -0
  17. package/dist/console/index.js +16 -0
  18. package/dist/console/index.js.map +1 -0
  19. package/dist/console/types.d.ts +61 -0
  20. package/dist/console/types.d.ts.map +1 -0
  21. package/dist/console/types.js +11 -0
  22. package/dist/console/types.js.map +1 -0
  23. package/dist/index.d.ts +17 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +18 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/masking/body.d.ts +30 -0
  28. package/dist/masking/body.d.ts.map +1 -0
  29. package/dist/masking/body.js +33 -0
  30. package/dist/masking/body.js.map +1 -0
  31. package/dist/masking/headers.d.ts +16 -0
  32. package/dist/masking/headers.d.ts.map +1 -0
  33. package/dist/masking/headers.js +46 -0
  34. package/dist/masking/headers.js.map +1 -0
  35. package/dist/masking/index.d.ts +8 -0
  36. package/dist/masking/index.d.ts.map +1 -0
  37. package/dist/masking/index.js +11 -0
  38. package/dist/masking/index.js.map +1 -0
  39. package/dist/masking/inputs.d.ts +15 -0
  40. package/dist/masking/inputs.d.ts.map +1 -0
  41. package/dist/masking/inputs.js +36 -0
  42. package/dist/masking/inputs.js.map +1 -0
  43. package/dist/masking/regex.d.ts +96 -0
  44. package/dist/masking/regex.d.ts.map +1 -0
  45. package/dist/masking/regex.js +182 -0
  46. package/dist/masking/regex.js.map +1 -0
  47. package/dist/masking/selectors.d.ts +67 -0
  48. package/dist/masking/selectors.d.ts.map +1 -0
  49. package/dist/masking/selectors.js +137 -0
  50. package/dist/masking/selectors.js.map +1 -0
  51. package/dist/masking/text.d.ts +9 -0
  52. package/dist/masking/text.d.ts.map +1 -0
  53. package/dist/masking/text.js +15 -0
  54. package/dist/masking/text.js.map +1 -0
  55. package/dist/network/cdp.d.ts +54 -0
  56. package/dist/network/cdp.d.ts.map +1 -0
  57. package/dist/network/cdp.js +282 -0
  58. package/dist/network/cdp.js.map +1 -0
  59. package/dist/network/index.d.ts +4 -0
  60. package/dist/network/index.d.ts.map +1 -0
  61. package/dist/network/index.js +14 -0
  62. package/dist/network/index.js.map +1 -0
  63. package/dist/network/types.d.ts +133 -0
  64. package/dist/network/types.d.ts.map +1 -0
  65. package/dist/network/types.js +35 -0
  66. package/dist/network/types.js.map +1 -0
  67. package/dist/network/web-request.d.ts +76 -0
  68. package/dist/network/web-request.d.ts.map +1 -0
  69. package/dist/network/web-request.js +294 -0
  70. package/dist/network/web-request.js.map +1 -0
  71. package/dist/persistence/index.d.ts +3 -0
  72. package/dist/persistence/index.d.ts.map +1 -0
  73. package/dist/persistence/index.js +11 -0
  74. package/dist/persistence/index.js.map +1 -0
  75. package/dist/persistence/store.d.ts +18 -0
  76. package/dist/persistence/store.d.ts.map +1 -0
  77. package/dist/persistence/store.js +327 -0
  78. package/dist/persistence/store.js.map +1 -0
  79. package/dist/persistence/types.d.ts +76 -0
  80. package/dist/persistence/types.d.ts.map +1 -0
  81. package/dist/persistence/types.js +21 -0
  82. package/dist/persistence/types.js.map +1 -0
  83. package/dist/rrweb.d.ts +5 -0
  84. package/dist/rrweb.d.ts.map +1 -0
  85. package/dist/rrweb.js +13 -0
  86. package/dist/rrweb.js.map +1 -0
  87. package/dist/screenshot/base64.d.ts +8 -0
  88. package/dist/screenshot/base64.d.ts.map +1 -0
  89. package/dist/screenshot/base64.js +21 -0
  90. package/dist/screenshot/base64.js.map +1 -0
  91. package/dist/screenshot/cdp.d.ts +50 -0
  92. package/dist/screenshot/cdp.d.ts.map +1 -0
  93. package/dist/screenshot/cdp.js +65 -0
  94. package/dist/screenshot/cdp.js.map +1 -0
  95. package/dist/screenshot/index.d.ts +4 -0
  96. package/dist/screenshot/index.d.ts.map +1 -0
  97. package/dist/screenshot/index.js +10 -0
  98. package/dist/screenshot/index.js.map +1 -0
  99. package/dist/screenshot/tabs.d.ts +44 -0
  100. package/dist/screenshot/tabs.d.ts.map +1 -0
  101. package/dist/screenshot/tabs.js +63 -0
  102. package/dist/screenshot/tabs.js.map +1 -0
  103. package/dist/screenshot/types.d.ts +27 -0
  104. package/dist/screenshot/types.d.ts.map +1 -0
  105. package/dist/screenshot/types.js +18 -0
  106. package/dist/screenshot/types.js.map +1 -0
  107. package/dist/shadow-dom/index.d.ts +3 -0
  108. package/dist/shadow-dom/index.d.ts.map +1 -0
  109. package/dist/shadow-dom/index.js +8 -0
  110. package/dist/shadow-dom/index.js.map +1 -0
  111. package/dist/shadow-dom/traverse.d.ts +54 -0
  112. package/dist/shadow-dom/traverse.d.ts.map +1 -0
  113. package/dist/shadow-dom/traverse.js +209 -0
  114. package/dist/shadow-dom/traverse.js.map +1 -0
  115. package/dist/shadow-dom/types.d.ts +43 -0
  116. package/dist/shadow-dom/types.d.ts.map +1 -0
  117. package/dist/shadow-dom/types.js +25 -0
  118. package/dist/shadow-dom/types.js.map +1 -0
  119. package/dist/throttling/apply.d.ts +59 -0
  120. package/dist/throttling/apply.d.ts.map +1 -0
  121. package/dist/throttling/apply.js +101 -0
  122. package/dist/throttling/apply.js.map +1 -0
  123. package/dist/throttling/defaults.d.ts +60 -0
  124. package/dist/throttling/defaults.d.ts.map +1 -0
  125. package/dist/throttling/defaults.js +81 -0
  126. package/dist/throttling/defaults.js.map +1 -0
  127. package/dist/throttling/guards.d.ts +69 -0
  128. package/dist/throttling/guards.d.ts.map +1 -0
  129. package/dist/throttling/guards.js +212 -0
  130. package/dist/throttling/guards.js.map +1 -0
  131. package/dist/throttling/index.d.ts +5 -0
  132. package/dist/throttling/index.d.ts.map +1 -0
  133. package/dist/throttling/index.js +11 -0
  134. package/dist/throttling/index.js.map +1 -0
  135. package/package.json +35 -0
@@ -0,0 +1,282 @@
1
+ // CDP network adapter — Task 1.7.
2
+ //
3
+ // Subscribes to the four CDP `Network.*` events that together describe an
4
+ // HTTP exchange:
5
+ //
6
+ // - Network.requestWillBeSent — emit `CapturedRequest`
7
+ // - Network.responseReceived — record the response shape (we don't emit
8
+ // yet, because CDP fires loadingFinished afterwards with the size +
9
+ // final timestamp; deferring emission lets us populate `durationMs`
10
+ // and `encodedSize` in one pass).
11
+ // - Network.loadingFinished — finalize + emit `CapturedResponse`
12
+ // - Network.loadingFailed — emit a `CapturedResponse` with `errorText`,
13
+ // and (when registered) a parallel `onError` event.
14
+ //
15
+ // Why this adapter doesn't import a CDP client: same load-bearing reason as
16
+ // the screenshot adapter — the substrate has to be transport-agnostic, and
17
+ // every framework (WDIO/Playwright/Cypress) already owns a CDP session.
18
+ // We accept a `CDPNetworkEventSource` shape and call `.on(event, handler)`.
19
+ //
20
+ // Body fetching is opt-in. Real-environment cost: `Network.getResponseBody`
21
+ // keeps response bodies pinned in memory in the renderer until called,
22
+ // which is why CDP defaults to NOT retaining them. Products turn it on
23
+ // when they want the bodies and accept the memory tax.
24
+ import { redactBody, redactNetworkHeaders } from '../masking';
25
+ function readNumber(value) {
26
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
27
+ }
28
+ function readString(value) {
29
+ return typeof value === 'string' ? value : undefined;
30
+ }
31
+ function readRecord(value) {
32
+ if (value === null || typeof value !== 'object')
33
+ return {};
34
+ const out = {};
35
+ for (const [k, v] of Object.entries(value)) {
36
+ if (typeof v === 'string')
37
+ out[k] = v;
38
+ }
39
+ return out;
40
+ }
41
+ /**
42
+ * Convert a CDP monotonic timestamp (seconds since process start) to an
43
+ * approximate wall-clock ms epoch using a request-time offset. Falls back
44
+ * to `Date.now()` when neither side has the data we need — losing a few
45
+ * ms of precision in exchange for a usable timestamp every time.
46
+ */
47
+ function deriveTs(startTs, startMonotonic, eventMonotonic) {
48
+ if (startMonotonic !== undefined && eventMonotonic !== undefined) {
49
+ return startTs + (eventMonotonic - startMonotonic) * 1000;
50
+ }
51
+ return Date.now();
52
+ }
53
+ /**
54
+ * Build a `NetworkCaptureAdapter` that consumes CDP `Network.*` events.
55
+ *
56
+ * The adapter installs its own subscriptions on `source` and tracks
57
+ * in-flight requests in an internal `Map` keyed by CDP `requestId`. The
58
+ * map is cleared lazily as terminal events arrive; calling `dispose()`
59
+ * unsubscribes all four CDP listeners and drops any remaining entries.
60
+ *
61
+ * @param source A `CDPNetworkEventSource` (typically a thin wrapper around
62
+ * the CDP client owned by the calling framework).
63
+ * @param options `{ captureResponseBodies?, maxBodyBytes? }`.
64
+ */
65
+ export function createCDPNetworkAdapter(source, options = {}) {
66
+ const captureBodies = options.captureResponseBodies ?? false;
67
+ const maxBodyBytes = options.maxBodyBytes ?? 1024 * 1024;
68
+ const inFlight = new Map();
69
+ const requestHandlers = new Set();
70
+ const responseHandlers = new Set();
71
+ const errorHandlers = new Set();
72
+ const emitRequest = (req) => {
73
+ for (const h of requestHandlers)
74
+ h(req);
75
+ };
76
+ const emitResponse = (res) => {
77
+ for (const h of responseHandlers)
78
+ h(res);
79
+ };
80
+ const emitError = (err) => {
81
+ for (const h of errorHandlers)
82
+ h(err);
83
+ };
84
+ // ──────────────────────────────────────────────────────────────────────
85
+ // Network.requestWillBeSent
86
+ // ──────────────────────────────────────────────────────────────────────
87
+ const unsubRequest = source.on('Network.requestWillBeSent', (params) => {
88
+ if (params === null || typeof params !== 'object')
89
+ return;
90
+ const p = params;
91
+ const requestId = readString(p.requestId);
92
+ if (requestId === undefined)
93
+ return;
94
+ const reqObj = (p.request ?? {});
95
+ // `wallTime` is in seconds (CDP convention); we store ms epoch.
96
+ const wallTime = readNumber(p.wallTime);
97
+ const startTs = wallTime !== undefined ? wallTime * 1000 : Date.now();
98
+ const startMonotonic = readNumber(p.timestamp);
99
+ const rawHeaders = readRecord(reqObj.headers);
100
+ const headers = redactNetworkHeaders(rawHeaders);
101
+ const initiatorObj = (p.initiator ?? undefined);
102
+ const initiator = readString(initiatorObj?.url) ?? readString(initiatorObj?.type) ?? undefined;
103
+ const rawBody = readString(reqObj.postData);
104
+ const requestBody = rawBody !== undefined ? redactBody(rawBody, { maxLengthBytes: maxBodyBytes }) : undefined;
105
+ const captured = {
106
+ id: requestId,
107
+ ts: startTs,
108
+ url: readString(reqObj.url) ?? '',
109
+ method: readString(reqObj.method) ?? 'GET',
110
+ headers,
111
+ ...(requestBody !== undefined ? { requestBody } : {}),
112
+ ...(initiator !== undefined ? { initiator } : {}),
113
+ ...(readString(p.type) !== undefined ? { resourceType: readString(p.type) } : {}),
114
+ };
115
+ inFlight.set(requestId, {
116
+ startTs,
117
+ startMonotonic,
118
+ request: captured,
119
+ });
120
+ emitRequest(captured);
121
+ });
122
+ // ──────────────────────────────────────────────────────────────────────
123
+ // Network.responseReceived — record metadata; defer emission until
124
+ // loadingFinished so we can fill durationMs + encodedSize in one pass.
125
+ // ──────────────────────────────────────────────────────────────────────
126
+ const unsubResponseReceived = source.on('Network.responseReceived', (params) => {
127
+ if (params === null || typeof params !== 'object')
128
+ return;
129
+ const p = params;
130
+ const requestId = readString(p.requestId);
131
+ if (requestId === undefined)
132
+ return;
133
+ const entry = inFlight.get(requestId);
134
+ if (entry === undefined)
135
+ return; // out-of-order or pre-attach event
136
+ const respObj = (p.response ?? {});
137
+ const rawHeaders = readRecord(respObj.headers);
138
+ const fromCache = respObj.fromDiskCache === true ||
139
+ respObj.fromServiceWorker === true ||
140
+ respObj.fromPrefetchCache === true;
141
+ entry.response = {
142
+ status: readNumber(respObj.status) ?? 0,
143
+ ...(readString(respObj.statusText) !== undefined
144
+ ? { statusText: readString(respObj.statusText) }
145
+ : {}),
146
+ headers: redactNetworkHeaders(rawHeaders),
147
+ fromCache,
148
+ ...(readString(respObj.mimeType) !== undefined
149
+ ? { mimeType: readString(respObj.mimeType) }
150
+ : {}),
151
+ };
152
+ });
153
+ // ──────────────────────────────────────────────────────────────────────
154
+ // Network.loadingFinished — terminal success; emit CapturedResponse.
155
+ // ──────────────────────────────────────────────────────────────────────
156
+ const unsubLoadingFinished = source.on('Network.loadingFinished', (params) => {
157
+ if (params === null || typeof params !== 'object')
158
+ return;
159
+ const p = params;
160
+ const requestId = readString(p.requestId);
161
+ if (requestId === undefined)
162
+ return;
163
+ const entry = inFlight.get(requestId);
164
+ if (entry === undefined)
165
+ return;
166
+ const finishMonotonic = readNumber(p.timestamp);
167
+ const ts = deriveTs(entry.startTs, entry.startMonotonic, finishMonotonic);
168
+ const durationMs = Math.max(0, ts - entry.startTs);
169
+ const encodedSize = readNumber(p.encodedDataLength);
170
+ const response = entry.response ?? {
171
+ status: 0,
172
+ headers: {},
173
+ fromCache: false,
174
+ };
175
+ // We resolve the response body separately so a failure here doesn't
176
+ // block emission of the terminal event. The fetch is fire-and-forget
177
+ // from the caller's perspective (we await before emitting, but errors
178
+ // are swallowed — the response shape stays correct without the body).
179
+ const finalize = (responseBody) => {
180
+ const captured = {
181
+ id: requestId,
182
+ ts,
183
+ status: response.status,
184
+ ...(response.statusText !== undefined ? { statusText: response.statusText } : {}),
185
+ headers: response.headers,
186
+ ...(responseBody !== undefined ? { responseBody } : {}),
187
+ fromCache: response.fromCache,
188
+ ...(encodedSize !== undefined ? { encodedSize } : {}),
189
+ durationMs,
190
+ };
191
+ inFlight.delete(requestId);
192
+ emitResponse(captured);
193
+ };
194
+ if (captureBodies && source.getResponseBody !== undefined) {
195
+ void source
196
+ .getResponseBody(requestId)
197
+ .then((reply) => {
198
+ // Skip binary payloads — we'd have to base64-decode + sniff the
199
+ // mime to do anything useful with them, and the masking module
200
+ // operates on strings.
201
+ if (reply.base64Encoded) {
202
+ finalize(undefined);
203
+ return;
204
+ }
205
+ finalize(redactBody(reply.body, { maxLengthBytes: maxBodyBytes }));
206
+ })
207
+ .catch(() => {
208
+ // CDP rejects `getResponseBody` for several legitimate reasons
209
+ // (preflight responses, redirects, ‘no data’ for 204s). Swallow
210
+ // and emit without a body — the metadata is still useful.
211
+ finalize(undefined);
212
+ });
213
+ }
214
+ else {
215
+ finalize(undefined);
216
+ }
217
+ });
218
+ // ──────────────────────────────────────────────────────────────────────
219
+ // Network.loadingFailed — terminal failure; emit CapturedResponse with
220
+ // errorText AND (when subscribed) the parallel onError event.
221
+ // ──────────────────────────────────────────────────────────────────────
222
+ const unsubLoadingFailed = source.on('Network.loadingFailed', (params) => {
223
+ if (params === null || typeof params !== 'object')
224
+ return;
225
+ const p = params;
226
+ const requestId = readString(p.requestId);
227
+ if (requestId === undefined)
228
+ return;
229
+ const entry = inFlight.get(requestId);
230
+ const errorText = readString(p.errorText) ?? 'unknown';
231
+ const failMonotonic = readNumber(p.timestamp);
232
+ const startTs = entry?.startTs ?? Date.now();
233
+ const ts = entry !== undefined ? deriveTs(startTs, entry.startMonotonic, failMonotonic) : startTs;
234
+ const durationMs = entry !== undefined ? Math.max(0, ts - startTs) : undefined;
235
+ const response = entry?.response ?? {
236
+ status: 0,
237
+ headers: {},
238
+ fromCache: false,
239
+ };
240
+ const captured = {
241
+ id: requestId,
242
+ ts,
243
+ status: response.status,
244
+ ...(response.statusText !== undefined ? { statusText: response.statusText } : {}),
245
+ headers: response.headers,
246
+ fromCache: response.fromCache,
247
+ ...(durationMs !== undefined ? { durationMs } : {}),
248
+ errorText,
249
+ };
250
+ inFlight.delete(requestId);
251
+ emitResponse(captured);
252
+ emitError({ id: requestId, ts, errorText });
253
+ });
254
+ // ──────────────────────────────────────────────────────────────────────
255
+ // Adapter surface
256
+ // ──────────────────────────────────────────────────────────────────────
257
+ return {
258
+ onRequest(handler) {
259
+ requestHandlers.add(handler);
260
+ return () => requestHandlers.delete(handler);
261
+ },
262
+ onResponse(handler) {
263
+ responseHandlers.add(handler);
264
+ return () => responseHandlers.delete(handler);
265
+ },
266
+ onError(handler) {
267
+ errorHandlers.add(handler);
268
+ return () => errorHandlers.delete(handler);
269
+ },
270
+ async dispose() {
271
+ unsubRequest();
272
+ unsubResponseReceived();
273
+ unsubLoadingFinished();
274
+ unsubLoadingFailed();
275
+ requestHandlers.clear();
276
+ responseHandlers.clear();
277
+ errorHandlers.clear();
278
+ inFlight.clear();
279
+ },
280
+ };
281
+ }
282
+ //# sourceMappingURL=cdp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdp.js","sourceRoot":"","sources":["../../src/network/cdp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type { CapturedRequest, CapturedResponse, NetworkCaptureAdapter } from './types';
2
+ export { createCDPNetworkAdapter, type CDPNetworkEventSource, type CDPNetworkOptions, } from './cdp';
3
+ export { createWebRequestNetworkAdapter, type WebRequestEvent, type WebRequestEventSource, type WebRequestNetworkOptions, } from './web-request';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/network/index.ts"],"names":[],"mappings":"AAYA,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,GACvB,MAAM,OAAO,CAAC;AACf,OAAO,EACL,8BAA8B,EAC9B,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC"}
@@ -0,0 +1,14 @@
1
+ // Public barrel for the network capture module.
2
+ //
3
+ // Locked surface per IMPLEMENTATION_PLAN.md Public API contract
4
+ // (lines 698-700):
5
+ //
6
+ // export type { CapturedRequest, CapturedResponse, NetworkCaptureAdapter } from './network';
7
+ // export { createCDPNetworkAdapter, createWebRequestNetworkAdapter } from './network';
8
+ //
9
+ // The transport-shape types (`CDPNetworkEventSource`,
10
+ // `WebRequestEventSource`) and option types are re-exported so consumers
11
+ // can declare-and-pass without importing internal paths.
12
+ export { createCDPNetworkAdapter, } from './cdp';
13
+ export { createWebRequestNetworkAdapter, } from './web-request';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/network/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,gEAAgE;AAChE,mBAAmB;AACnB,EAAE;AACF,+FAA+F;AAC/F,yFAAyF;AACzF,EAAE;AACF,sDAAsD;AACtD,yEAAyE;AACzE,yDAAyD;AAGzD,OAAO,EACL,uBAAuB,GAGxB,MAAM,OAAO,CAAC;AACf,OAAO,EACL,8BAA8B,GAI/B,MAAM,eAAe,CAAC"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * A single in-flight (or about-to-be-sent) HTTP request, observed at the
3
+ * `requestWillBeSent`-equivalent moment of each transport.
4
+ *
5
+ * Emitted by `NetworkCaptureAdapter.onRequest`. Headers are already redacted
6
+ * via `redactNetworkHeaders`; `requestBody`, when present, is already passed
7
+ * through `redactBody` (type-tagged token replacement + 1 MB cap).
8
+ */
9
+ export interface CapturedRequest {
10
+ /**
11
+ * Unique request id — the transport-native identifier (CDP `requestId`
12
+ * or chrome.webRequest `requestId`), reused verbatim so downstream
13
+ * consumers can correlate request/response without a substrate-side map.
14
+ */
15
+ id: string;
16
+ /** Wall-clock time (ms since epoch) when the request started. */
17
+ ts: number;
18
+ /** Fully-qualified request URL. */
19
+ url: string;
20
+ /** HTTP method — `'GET'`, `'POST'`, `'PUT'`, … */
21
+ method: string;
22
+ /**
23
+ * Request headers, already passed through `redactNetworkHeaders` (deny-list
24
+ * applied; non-sensitive names preserved with original casing).
25
+ */
26
+ headers: Record<string, string>;
27
+ /**
28
+ * Request body — already passed through `redactBody` (PII regex bank +
29
+ * 1 MB truncation cap). Present only when the transport exposes a textual
30
+ * body for the request; omitted otherwise (binary bodies, multipart, or
31
+ * any transport that can't surface the bytes).
32
+ */
33
+ requestBody?: string;
34
+ /**
35
+ * Initiator hint — typically `'script'`, `'parser'`, `'other'`, or a URL
36
+ * pointing at the script that scheduled the request. CDP populates this
37
+ * natively; the webRequest adapter leaves it undefined (no equivalent
38
+ * field).
39
+ */
40
+ initiator?: string;
41
+ /**
42
+ * Resource type, as reported by the transport. CDP vocabulary (e.g.
43
+ * `'Document'`, `'XHR'`, `'Fetch'`, `'Image'`) differs from
44
+ * chrome.webRequest's (e.g. `'main_frame'`, `'xmlhttprequest'`); we pass
45
+ * through verbatim so downstream tooling sees the original signal.
46
+ */
47
+ resourceType?: string;
48
+ }
49
+ /**
50
+ * The terminal observation of an HTTP exchange — either a successful response
51
+ * (`status` populated, `errorText` undefined) or a failure
52
+ * (`errorText` populated, `status` may be `0`). Bodies and headers are
53
+ * already redacted as for `CapturedRequest`.
54
+ */
55
+ export interface CapturedResponse {
56
+ /** Matches the `id` of the corresponding `CapturedRequest`. */
57
+ id: string;
58
+ /** Wall-clock time (ms since epoch) when the response was observed. */
59
+ ts: number;
60
+ /** HTTP status code. `0` on network failure when no response was received. */
61
+ status: number;
62
+ /** HTTP status text (e.g. `'OK'`, `'Not Found'`). Optional — not all transports surface it. */
63
+ statusText?: string;
64
+ /** Response headers, already passed through `redactNetworkHeaders`. */
65
+ headers: Record<string, string>;
66
+ /**
67
+ * Response body, already passed through `redactBody`. Only populated by
68
+ * `createCDPNetworkAdapter` when `captureResponseBodies: true` AND the
69
+ * caller wired a `getResponseBody` fetcher (and the body is textual).
70
+ * Never populated by `createWebRequestNetworkAdapter` — chrome.webRequest
71
+ * cannot access response bodies in MV3.
72
+ */
73
+ responseBody?: string;
74
+ /** `true` when the response was served from the HTTP cache. */
75
+ fromCache: boolean;
76
+ /**
77
+ * Number of bytes on the wire (post-compression), when the transport
78
+ * reports it. CDP fills this from `Network.loadingFinished.encodedDataLength`;
79
+ * chrome.webRequest fills it from `onCompleted.responseSize`.
80
+ */
81
+ encodedSize?: number;
82
+ /** Elapsed time from request start to this observation, in ms, when known. */
83
+ durationMs?: number;
84
+ /**
85
+ * Populated when the transport reports a transport-layer error
86
+ * (CDP `Network.loadingFailed.errorText`, chrome.webRequest `onErrorOccurred.error`).
87
+ * Mutually exclusive with a normal response in practice — when present,
88
+ * the adapter emits this via `onResponse` rather than firing a separate
89
+ * `onError` event, so consumers get a single terminal record per exchange.
90
+ * (The optional `onError` channel is offered for products that want a
91
+ * second signal; it carries the same id/ts/errorText.)
92
+ */
93
+ errorText?: string;
94
+ }
95
+ /**
96
+ * Common surface for network capture. Both factories
97
+ * (`createCDPNetworkAdapter`, `createWebRequestNetworkAdapter`) return this
98
+ * shape; the only intended difference is which transport drives the
99
+ * underlying subscription.
100
+ *
101
+ * Handler registration is additive: each `on*` call returns an unsubscribe
102
+ * function specific to that handler. `dispose()` is a single shot — it
103
+ * tears down ALL transport subscriptions for the adapter.
104
+ */
105
+ export interface NetworkCaptureAdapter {
106
+ /**
107
+ * Subscribe to `CapturedRequest` emissions. The returned function removes
108
+ * THIS handler without affecting other registered handlers.
109
+ */
110
+ onRequest(handler: (req: CapturedRequest) => void): () => void;
111
+ /**
112
+ * Subscribe to `CapturedResponse` emissions. Same unsubscribe semantics
113
+ * as `onRequest`.
114
+ */
115
+ onResponse(handler: (res: CapturedResponse) => void): () => void;
116
+ /**
117
+ * Optional dedicated channel for transport-layer errors. Adapters that
118
+ * surface errors only via `CapturedResponse.errorText` may leave this
119
+ * undefined; adapters that fire a parallel error stream populate it.
120
+ */
121
+ onError?(handler: (err: {
122
+ id: string;
123
+ ts: number;
124
+ errorText: string;
125
+ }) => void): () => void;
126
+ /**
127
+ * Tear down all underlying transport subscriptions. Idempotent. Returning
128
+ * a promise so future adapters that flush async resources can do so
129
+ * cleanly under the same contract.
130
+ */
131
+ dispose?(): Promise<void>;
132
+ }
133
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/network/types.ts"],"names":[],"mappings":"AAkCA;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,iEAAiE;IACjE,EAAE,EAAE,MAAM,CAAC;IACX,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAC;IACX,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,+FAA+F;IAC/F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC/D;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACjE;;;;OAIG;IACH,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5F;;;;OAIG;IACH,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B"}
@@ -0,0 +1,35 @@
1
+ // Network capture abstraction — Task 1.7.
2
+ //
3
+ // ADR-0002: both products consume the same downstream API, only the
4
+ // transport differs. P1/tracelane subscribes to CDP `Network.*` via a
5
+ // WebDriver-supplied CDP session; P2/peek subscribes to
6
+ // `chrome.webRequest.*` from the extension service worker.
7
+ //
8
+ // The shapes below are the contract — `createCDPNetworkAdapter` and
9
+ // `createWebRequestNetworkAdapter` MUST produce structurally identical
10
+ // `CapturedRequest`/`CapturedResponse` records (a cross-adapter equality
11
+ // test in `network.test.ts` is the regression guard). Field availability
12
+ // differs only in the well-documented cases:
13
+ //
14
+ // - `requestBody` — both transports can populate when present.
15
+ // - `responseBody` — CDP only (chrome.webRequest can't access bodies
16
+ // in MV3); CDP also requires opt-in via
17
+ // `CDPNetworkOptions.captureResponseBodies`.
18
+ // - `initiator` — CDP exposes it natively; chrome.webRequest does
19
+ // not (left undefined on the webRequest path).
20
+ // - `resourceType` — both transports expose this, but the vocabulary
21
+ // is transport-native (CDP: `Document`, `XHR`,
22
+ // `Fetch`, …; chrome.webRequest: `main_frame`,
23
+ // `xmlhttprequest`, …). We pass through verbatim
24
+ // and document the difference — re-mapping would
25
+ // throw away signal.
26
+ // - `encodedSize` — both transports populate when available (CDP
27
+ // via `Network.loadingFinished.encodedDataLength`;
28
+ // chrome.webRequest via the `responseSize` field
29
+ // on `onCompleted`).
30
+ //
31
+ // All sensitive material (headers + bodies) is redacted INSIDE the adapter
32
+ // before reaching the consumer's handler — see
33
+ // `redactNetworkHeaders`/`redactBody` from the masking module.
34
+ export {};
35
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/network/types.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,oEAAoE;AACpE,sEAAsE;AACtE,wDAAwD;AACxD,2DAA2D;AAC3D,EAAE;AACF,oEAAoE;AACpE,uEAAuE;AACvE,yEAAyE;AACzE,yEAAyE;AACzE,6CAA6C;AAC7C,EAAE;AACF,qEAAqE;AACrE,0EAA0E;AAC1E,gEAAgE;AAChE,qEAAqE;AACrE,0EAA0E;AAC1E,uEAAuE;AACvE,0EAA0E;AAC1E,uEAAuE;AACvE,uEAAuE;AACvE,yEAAyE;AACzE,yEAAyE;AACzE,6CAA6C;AAC7C,uEAAuE;AACvE,2EAA2E;AAC3E,yEAAyE;AACzE,6CAA6C;AAC7C,EAAE;AACF,2EAA2E;AAC3E,+CAA+C;AAC/C,+DAA+D"}
@@ -0,0 +1,76 @@
1
+ import type { NetworkCaptureAdapter } from './types';
2
+ /**
3
+ * The chrome.webRequest event family we depend on, narrowed to just the
4
+ * `.addListener` / `.removeListener` shape. Each listener payload is
5
+ * `any` at the wire level — the Chrome API documents the shapes per-event,
6
+ * and the type-narrowing happens inside the adapter via small runtime
7
+ * checks (`readString` / `readNumber` / `readHeaders`).
8
+ *
9
+ * We accept this shape (rather than `chrome.webRequest` directly) so the
10
+ * substrate (a) typechecks outside an extension context, (b) is trivially
11
+ * testable with hand-built fakes, and (c) gives the product the option of
12
+ * wrapping the API with telemetry / permission checks.
13
+ */
14
+ export interface WebRequestEvent {
15
+ addListener(cb: (d: any) => void, filter?: unknown, extraInfoSpec?: string[]): void;
16
+ removeListener(cb: (d: any) => void): void;
17
+ }
18
+ /**
19
+ * Aggregate of the five chrome.webRequest events we subscribe to.
20
+ *
21
+ * The product-side wrapper typically exposes `chrome.webRequest` directly
22
+ * (it already matches this shape), but tests inject hand-built fakes.
23
+ */
24
+ export interface WebRequestEventSource {
25
+ onBeforeRequest: WebRequestEvent;
26
+ onSendHeaders: WebRequestEvent;
27
+ onHeadersReceived: WebRequestEvent;
28
+ onCompleted: WebRequestEvent;
29
+ onErrorOccurred: WebRequestEvent;
30
+ }
31
+ /**
32
+ * Factory-time options for `createWebRequestNetworkAdapter`.
33
+ */
34
+ export interface WebRequestNetworkOptions {
35
+ /**
36
+ * chrome.webRequest URL/types filter, forwarded verbatim to each
37
+ * `.addListener` call. Defaults to `{ urls: ['<all_urls>'] }` so the
38
+ * adapter sees everything; products typically narrow this to reduce
39
+ * load.
40
+ */
41
+ filter?: {
42
+ urls: string[];
43
+ types?: string[];
44
+ };
45
+ /**
46
+ * Body cap forwarded to `redactBody` for the (rare) cases where
47
+ * `onBeforeRequest` exposes a textual request body. Defaults to 1 MB.
48
+ */
49
+ maxBodyBytes?: number;
50
+ /**
51
+ * `extraInfoSpec` passed to `onSendHeaders.addListener` /
52
+ * `onHeadersReceived.addListener`. chrome.webRequest requires
53
+ * `['responseHeaders']` to surface response headers and
54
+ * `['requestHeaders']` for the final request-header set. The adapter
55
+ * sets sensible defaults; callers can override (for example, to add
56
+ * `'extraHeaders'` when capturing CORS-restricted headers).
57
+ */
58
+ extraInfoSpec?: {
59
+ onBeforeRequest?: string[];
60
+ onSendHeaders?: string[];
61
+ onHeadersReceived?: string[];
62
+ };
63
+ }
64
+ /**
65
+ * Build a `NetworkCaptureAdapter` that consumes chrome.webRequest events.
66
+ *
67
+ * The adapter installs five listeners on `source`, all gated by
68
+ * `options.filter` (defaulting to `{ urls: ['<all_urls>'] }`). On
69
+ * `dispose()` every listener is removed and the in-flight map is cleared.
70
+ *
71
+ * @param source A `WebRequestEventSource` — typically the global
72
+ * `chrome.webRequest` itself.
73
+ * @param options `{ filter?, maxBodyBytes?, extraInfoSpec? }`.
74
+ */
75
+ export declare function createWebRequestNetworkAdapter(source: WebRequestEventSource, options?: WebRequestNetworkOptions): NetworkCaptureAdapter;
76
+ //# sourceMappingURL=web-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-request.d.ts","sourceRoot":"","sources":["../../src/network/web-request.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAqC,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAExF;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAE9B,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEpF,cAAc,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;CAC5C;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,EAAE,eAAe,CAAC;IAC/B,iBAAiB,EAAE,eAAe,CAAC;IACnC,WAAW,EAAE,eAAe,CAAC;IAC7B,eAAe,EAAE,eAAe,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9C;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE;QACd,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC9B,CAAC;CACH;AA0ED;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,qBAAqB,EAC7B,OAAO,GAAE,wBAA6B,GACrC,qBAAqB,CAyMvB"}