@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.
- package/NOTICE +15 -0
- package/README.md +26 -0
- package/dist/compat/index.d.ts +37 -0
- package/dist/compat/index.d.ts.map +1 -0
- package/dist/compat/index.js +97 -0
- package/dist/compat/index.js.map +1 -0
- package/dist/compression/index.d.ts +24 -0
- package/dist/compression/index.d.ts.map +1 -0
- package/dist/compression/index.js +61 -0
- package/dist/compression/index.js.map +1 -0
- package/dist/console/buffer.d.ts +99 -0
- package/dist/console/buffer.d.ts.map +1 -0
- package/dist/console/buffer.js +169 -0
- package/dist/console/buffer.js.map +1 -0
- package/dist/console/index.d.ts +3 -0
- package/dist/console/index.d.ts.map +1 -0
- package/dist/console/index.js +16 -0
- package/dist/console/index.js.map +1 -0
- package/dist/console/types.d.ts +61 -0
- package/dist/console/types.d.ts.map +1 -0
- package/dist/console/types.js +11 -0
- package/dist/console/types.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/masking/body.d.ts +30 -0
- package/dist/masking/body.d.ts.map +1 -0
- package/dist/masking/body.js +33 -0
- package/dist/masking/body.js.map +1 -0
- package/dist/masking/headers.d.ts +16 -0
- package/dist/masking/headers.d.ts.map +1 -0
- package/dist/masking/headers.js +46 -0
- package/dist/masking/headers.js.map +1 -0
- package/dist/masking/index.d.ts +8 -0
- package/dist/masking/index.d.ts.map +1 -0
- package/dist/masking/index.js +11 -0
- package/dist/masking/index.js.map +1 -0
- package/dist/masking/inputs.d.ts +15 -0
- package/dist/masking/inputs.d.ts.map +1 -0
- package/dist/masking/inputs.js +36 -0
- package/dist/masking/inputs.js.map +1 -0
- package/dist/masking/regex.d.ts +96 -0
- package/dist/masking/regex.d.ts.map +1 -0
- package/dist/masking/regex.js +182 -0
- package/dist/masking/regex.js.map +1 -0
- package/dist/masking/selectors.d.ts +67 -0
- package/dist/masking/selectors.d.ts.map +1 -0
- package/dist/masking/selectors.js +137 -0
- package/dist/masking/selectors.js.map +1 -0
- package/dist/masking/text.d.ts +9 -0
- package/dist/masking/text.d.ts.map +1 -0
- package/dist/masking/text.js +15 -0
- package/dist/masking/text.js.map +1 -0
- package/dist/network/cdp.d.ts +54 -0
- package/dist/network/cdp.d.ts.map +1 -0
- package/dist/network/cdp.js +282 -0
- package/dist/network/cdp.js.map +1 -0
- package/dist/network/index.d.ts +4 -0
- package/dist/network/index.d.ts.map +1 -0
- package/dist/network/index.js +14 -0
- package/dist/network/index.js.map +1 -0
- package/dist/network/types.d.ts +133 -0
- package/dist/network/types.d.ts.map +1 -0
- package/dist/network/types.js +35 -0
- package/dist/network/types.js.map +1 -0
- package/dist/network/web-request.d.ts +76 -0
- package/dist/network/web-request.d.ts.map +1 -0
- package/dist/network/web-request.js +294 -0
- package/dist/network/web-request.js.map +1 -0
- package/dist/persistence/index.d.ts +3 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +11 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/store.d.ts +18 -0
- package/dist/persistence/store.d.ts.map +1 -0
- package/dist/persistence/store.js +327 -0
- package/dist/persistence/store.js.map +1 -0
- package/dist/persistence/types.d.ts +76 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +21 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/rrweb.d.ts +5 -0
- package/dist/rrweb.d.ts.map +1 -0
- package/dist/rrweb.js +13 -0
- package/dist/rrweb.js.map +1 -0
- package/dist/screenshot/base64.d.ts +8 -0
- package/dist/screenshot/base64.d.ts.map +1 -0
- package/dist/screenshot/base64.js +21 -0
- package/dist/screenshot/base64.js.map +1 -0
- package/dist/screenshot/cdp.d.ts +50 -0
- package/dist/screenshot/cdp.d.ts.map +1 -0
- package/dist/screenshot/cdp.js +65 -0
- package/dist/screenshot/cdp.js.map +1 -0
- package/dist/screenshot/index.d.ts +4 -0
- package/dist/screenshot/index.d.ts.map +1 -0
- package/dist/screenshot/index.js +10 -0
- package/dist/screenshot/index.js.map +1 -0
- package/dist/screenshot/tabs.d.ts +44 -0
- package/dist/screenshot/tabs.d.ts.map +1 -0
- package/dist/screenshot/tabs.js +63 -0
- package/dist/screenshot/tabs.js.map +1 -0
- package/dist/screenshot/types.d.ts +27 -0
- package/dist/screenshot/types.d.ts.map +1 -0
- package/dist/screenshot/types.js +18 -0
- package/dist/screenshot/types.js.map +1 -0
- package/dist/shadow-dom/index.d.ts +3 -0
- package/dist/shadow-dom/index.d.ts.map +1 -0
- package/dist/shadow-dom/index.js +8 -0
- package/dist/shadow-dom/index.js.map +1 -0
- package/dist/shadow-dom/traverse.d.ts +54 -0
- package/dist/shadow-dom/traverse.d.ts.map +1 -0
- package/dist/shadow-dom/traverse.js +209 -0
- package/dist/shadow-dom/traverse.js.map +1 -0
- package/dist/shadow-dom/types.d.ts +43 -0
- package/dist/shadow-dom/types.d.ts.map +1 -0
- package/dist/shadow-dom/types.js +25 -0
- package/dist/shadow-dom/types.js.map +1 -0
- package/dist/throttling/apply.d.ts +59 -0
- package/dist/throttling/apply.d.ts.map +1 -0
- package/dist/throttling/apply.js +101 -0
- package/dist/throttling/apply.js.map +1 -0
- package/dist/throttling/defaults.d.ts +60 -0
- package/dist/throttling/defaults.d.ts.map +1 -0
- package/dist/throttling/defaults.js +81 -0
- package/dist/throttling/defaults.js.map +1 -0
- package/dist/throttling/guards.d.ts +69 -0
- package/dist/throttling/guards.d.ts.map +1 -0
- package/dist/throttling/guards.js +212 -0
- package/dist/throttling/guards.js.map +1 -0
- package/dist/throttling/index.d.ts +5 -0
- package/dist/throttling/index.d.ts.map +1 -0
- package/dist/throttling/index.js +11 -0
- package/dist/throttling/index.js.map +1 -0
- 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"}
|