@replayio-app-building/netlify-recorder 0.50.0 → 0.51.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/dist/index.d.ts +3 -1
- package/dist/index.js +93 -54
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -74,8 +74,10 @@ interface NetworkCall {
|
|
|
74
74
|
timestamp: number;
|
|
75
75
|
/** Epoch ms when the fetch call started. */
|
|
76
76
|
startTime: number;
|
|
77
|
-
/** Epoch ms when the response was received. */
|
|
77
|
+
/** Epoch ms when the response was received. 0 if response was never awaited (fire-and-forget). */
|
|
78
78
|
endTime: number;
|
|
79
|
+
/** True when the call was initiated but the response was not awaited by the handler. */
|
|
80
|
+
pending?: boolean;
|
|
79
81
|
}
|
|
80
82
|
interface EnvRead {
|
|
81
83
|
key: string;
|
package/dist/index.js
CHANGED
|
@@ -102,37 +102,46 @@ function patchHttpModules(mode, calls, consumed, silent) {
|
|
|
102
102
|
return origEnd(chunk, ...rest);
|
|
103
103
|
};
|
|
104
104
|
const startTime = Date.now();
|
|
105
|
+
const requestHeaders = {};
|
|
106
|
+
if (options.headers) {
|
|
107
|
+
for (const [k, v] of Object.entries(options.headers)) {
|
|
108
|
+
if (v !== void 0) requestHeaders[k] = Array.isArray(v) ? v.join(", ") : String(v);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const store = getRequestStore();
|
|
112
|
+
const targetCalls = store?.networkCalls ?? calls;
|
|
113
|
+
const entry = {
|
|
114
|
+
url: urlStr,
|
|
115
|
+
method,
|
|
116
|
+
requestHeaders,
|
|
117
|
+
requestBody: bodyChunks.length > 0 ? Buffer.concat(bodyChunks).toString("utf-8") : void 0,
|
|
118
|
+
responseStatus: 0,
|
|
119
|
+
responseHeaders: {},
|
|
120
|
+
responseBody: void 0,
|
|
121
|
+
timestamp: startTime,
|
|
122
|
+
startTime,
|
|
123
|
+
endTime: 0,
|
|
124
|
+
pending: true
|
|
125
|
+
};
|
|
126
|
+
targetCalls.push(entry);
|
|
105
127
|
req.on("response", (res) => {
|
|
106
128
|
const resChunks = [];
|
|
107
129
|
res.on("data", (chunk) => resChunks.push(chunk));
|
|
108
130
|
res.on("end", () => {
|
|
109
131
|
const endTime = Date.now();
|
|
110
|
-
const requestHeaders = {};
|
|
111
|
-
if (options.headers) {
|
|
112
|
-
for (const [k, v] of Object.entries(options.headers)) {
|
|
113
|
-
if (v !== void 0) requestHeaders[k] = Array.isArray(v) ? v.join(", ") : String(v);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
132
|
const responseHeaders = {};
|
|
117
133
|
if (res.headers) {
|
|
118
134
|
for (const [k, v] of Object.entries(res.headers)) {
|
|
119
135
|
if (v !== void 0) responseHeaders[k] = Array.isArray(v) ? v.join(", ") : String(v);
|
|
120
136
|
}
|
|
121
137
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
responseStatus: res.statusCode ?? 0,
|
|
130
|
-
responseHeaders,
|
|
131
|
-
responseBody: Buffer.concat(resChunks).toString("utf-8"),
|
|
132
|
-
timestamp: endTime,
|
|
133
|
-
startTime,
|
|
134
|
-
endTime
|
|
135
|
-
});
|
|
138
|
+
entry.requestBody = bodyChunks.length > 0 ? Buffer.concat(bodyChunks).toString("utf-8") : void 0;
|
|
139
|
+
entry.responseStatus = res.statusCode ?? 0;
|
|
140
|
+
entry.responseHeaders = responseHeaders;
|
|
141
|
+
entry.responseBody = Buffer.concat(resChunks).toString("utf-8");
|
|
142
|
+
entry.timestamp = endTime;
|
|
143
|
+
entry.endTime = endTime;
|
|
144
|
+
entry.pending = false;
|
|
136
145
|
});
|
|
137
146
|
});
|
|
138
147
|
return req;
|
|
@@ -173,11 +182,18 @@ function replayHttpRequest(url, _method, calls, consumed, callback, silent) {
|
|
|
173
182
|
);
|
|
174
183
|
}
|
|
175
184
|
consumed.add(matchIdx);
|
|
185
|
+
const isPending = call.pending || call.endTime === 0 && call.responseStatus === 0;
|
|
176
186
|
if (!silent) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
187
|
+
if (isPending) {
|
|
188
|
+
console.log(
|
|
189
|
+
` [network-replay] Consumed call ${consumed.size}/${calls.length}: ${call.method} ${call.url} => (fire-and-forget, no response captured)`
|
|
190
|
+
);
|
|
191
|
+
} else {
|
|
192
|
+
const duration = call.endTime - call.startTime;
|
|
193
|
+
console.log(
|
|
194
|
+
` [network-replay] Consumed call ${consumed.size}/${calls.length}: ${call.method} ${call.url} => ${call.responseStatus} (original: ${duration}ms)`
|
|
195
|
+
);
|
|
196
|
+
}
|
|
181
197
|
}
|
|
182
198
|
const body = call.responseBody ?? "";
|
|
183
199
|
const fakeRes = new Readable({
|
|
@@ -186,7 +202,7 @@ function replayHttpRequest(url, _method, calls, consumed, callback, silent) {
|
|
|
186
202
|
this.push(null);
|
|
187
203
|
}
|
|
188
204
|
});
|
|
189
|
-
fakeRes.statusCode = call.responseStatus;
|
|
205
|
+
fakeRes.statusCode = isPending ? 200 : call.responseStatus;
|
|
190
206
|
fakeRes.statusMessage = "";
|
|
191
207
|
fakeRes.headers = {};
|
|
192
208
|
if (call.responseHeaders) {
|
|
@@ -246,6 +262,20 @@ function ensureCaptureInterceptor() {
|
|
|
246
262
|
);
|
|
247
263
|
}
|
|
248
264
|
const startTime = Date.now();
|
|
265
|
+
const entry = {
|
|
266
|
+
url,
|
|
267
|
+
method,
|
|
268
|
+
requestHeaders,
|
|
269
|
+
requestBody,
|
|
270
|
+
responseStatus: 0,
|
|
271
|
+
responseHeaders: {},
|
|
272
|
+
responseBody: void 0,
|
|
273
|
+
timestamp: startTime,
|
|
274
|
+
startTime,
|
|
275
|
+
endTime: 0,
|
|
276
|
+
pending: true
|
|
277
|
+
};
|
|
278
|
+
calls.push(entry);
|
|
249
279
|
const response = await _realOriginalFetch(input, init);
|
|
250
280
|
const endTime = Date.now();
|
|
251
281
|
const responseBody = await response.clone().text();
|
|
@@ -253,18 +283,12 @@ function ensureCaptureInterceptor() {
|
|
|
253
283
|
response.headers.forEach((v, k) => {
|
|
254
284
|
responseHeaders[k] = v;
|
|
255
285
|
});
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
responseHeaders,
|
|
263
|
-
responseBody,
|
|
264
|
-
timestamp: endTime,
|
|
265
|
-
startTime,
|
|
266
|
-
endTime
|
|
267
|
-
});
|
|
286
|
+
entry.responseStatus = response.status;
|
|
287
|
+
entry.responseHeaders = responseHeaders;
|
|
288
|
+
entry.responseBody = responseBody;
|
|
289
|
+
entry.timestamp = endTime;
|
|
290
|
+
entry.endTime = endTime;
|
|
291
|
+
entry.pending = false;
|
|
268
292
|
return response;
|
|
269
293
|
};
|
|
270
294
|
globalThis.fetch = captureFetch;
|
|
@@ -320,6 +344,20 @@ function installNetworkInterceptor(mode, calls, options) {
|
|
|
320
344
|
);
|
|
321
345
|
}
|
|
322
346
|
const startTime = Date.now();
|
|
347
|
+
const entry = {
|
|
348
|
+
url,
|
|
349
|
+
method,
|
|
350
|
+
requestHeaders,
|
|
351
|
+
requestBody,
|
|
352
|
+
responseStatus: 0,
|
|
353
|
+
responseHeaders: {},
|
|
354
|
+
responseBody: void 0,
|
|
355
|
+
timestamp: startTime,
|
|
356
|
+
startTime,
|
|
357
|
+
endTime: 0,
|
|
358
|
+
pending: true
|
|
359
|
+
};
|
|
360
|
+
calls.push(entry);
|
|
323
361
|
const response = await originalFetch2(input, init);
|
|
324
362
|
const endTime = Date.now();
|
|
325
363
|
const responseBody = await response.clone().text();
|
|
@@ -327,18 +365,12 @@ function installNetworkInterceptor(mode, calls, options) {
|
|
|
327
365
|
response.headers.forEach((v, k) => {
|
|
328
366
|
responseHeaders[k] = v;
|
|
329
367
|
});
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
responseHeaders,
|
|
337
|
-
responseBody,
|
|
338
|
-
timestamp: endTime,
|
|
339
|
-
startTime,
|
|
340
|
-
endTime
|
|
341
|
-
});
|
|
368
|
+
entry.responseStatus = response.status;
|
|
369
|
+
entry.responseHeaders = responseHeaders;
|
|
370
|
+
entry.responseBody = responseBody;
|
|
371
|
+
entry.timestamp = endTime;
|
|
372
|
+
entry.endTime = endTime;
|
|
373
|
+
entry.pending = false;
|
|
342
374
|
return response;
|
|
343
375
|
};
|
|
344
376
|
globalThis.fetch = captureFetch;
|
|
@@ -388,14 +420,21 @@ function installNetworkInterceptor(mode, calls, options) {
|
|
|
388
420
|
);
|
|
389
421
|
}
|
|
390
422
|
consumed.add(matchIdx);
|
|
423
|
+
const isPending = call.pending || call.endTime === 0 && call.responseStatus === 0;
|
|
391
424
|
if (!silent) {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
425
|
+
if (isPending) {
|
|
426
|
+
console.log(
|
|
427
|
+
` [network-replay] Consumed call ${consumed.size}/${calls.length}: ${call.method} ${call.url} => (fire-and-forget, no response captured)`
|
|
428
|
+
);
|
|
429
|
+
} else {
|
|
430
|
+
const duration = call.endTime - call.startTime;
|
|
431
|
+
console.log(
|
|
432
|
+
` [network-replay] Consumed call ${consumed.size}/${calls.length}: ${call.method} ${call.url} => ${call.responseStatus} (original: ${duration}ms)`
|
|
433
|
+
);
|
|
434
|
+
}
|
|
396
435
|
}
|
|
397
436
|
const body = call.responseBody ?? "";
|
|
398
|
-
const status = call.responseStatus;
|
|
437
|
+
const status = isPending ? 200 : call.responseStatus;
|
|
399
438
|
return {
|
|
400
439
|
ok: status >= 200 && status < 300,
|
|
401
440
|
status,
|