@replayio-app-building/netlify-recorder 0.42.0 → 0.44.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 CHANGED
@@ -72,6 +72,10 @@ interface NetworkCall {
72
72
  responseHeaders: Record<string, string>;
73
73
  responseBody?: string;
74
74
  timestamp: number;
75
+ /** Epoch ms when the fetch call started. */
76
+ startTime: number;
77
+ /** Epoch ms when the response was received. */
78
+ endTime: number;
75
79
  }
76
80
  interface EnvRead {
77
81
  key: string;
@@ -91,6 +95,14 @@ interface BlobData {
91
95
  endTime: number;
92
96
  /** The response returned to the client, used to detect replay mismatches. */
93
97
  handlerResponse?: HandlerResponse$1;
98
+ /**
99
+ * The request ID of the first request handled by this module instance.
100
+ * When this differs from the current request's ID, the execution environment
101
+ * was reused (warm start) and module-level state from the original request
102
+ * may have affected this request's behavior (e.g. in-memory caches skipping
103
+ * network calls).
104
+ */
105
+ originalRequestId?: string;
94
106
  }
95
107
  interface FinishRequestCallbacks {
96
108
  /**
@@ -174,6 +186,12 @@ interface FinishRequestOptions {
174
186
  * sent to the client in the `X-Replay-Request-Id` header.
175
187
  */
176
188
  requestId?: string;
189
+ /**
190
+ * The request ID of the first request handled by this module instance.
191
+ * Included in the blob data to link warm-start requests back to the
192
+ * cold-start request that populated module-level caches.
193
+ */
194
+ originalRequestId?: string;
177
195
  }
178
196
  /**
179
197
  * Called at the end of the handler execution.
package/dist/index.js CHANGED
@@ -87,7 +87,9 @@ function ensureCaptureInterceptor() {
87
87
  calls
88
88
  );
89
89
  }
90
+ const startTime = Date.now();
90
91
  const response = await _realOriginalFetch(input, init);
92
+ const endTime = Date.now();
91
93
  const responseBody = await response.clone().text();
92
94
  const responseHeaders = {};
93
95
  response.headers.forEach((v, k) => {
@@ -101,7 +103,9 @@ function ensureCaptureInterceptor() {
101
103
  responseStatus: response.status,
102
104
  responseHeaders,
103
105
  responseBody,
104
- timestamp: Date.now()
106
+ timestamp: endTime,
107
+ startTime,
108
+ endTime
105
109
  });
106
110
  return response;
107
111
  };
@@ -154,7 +158,9 @@ function installNetworkInterceptor(mode, calls) {
154
158
  calls
155
159
  );
156
160
  }
161
+ const startTime = Date.now();
157
162
  const response = await originalFetch2(input, init);
163
+ const endTime = Date.now();
158
164
  const responseBody = await response.clone().text();
159
165
  const responseHeaders = {};
160
166
  response.headers.forEach((v, k) => {
@@ -168,7 +174,9 @@ function installNetworkInterceptor(mode, calls) {
168
174
  responseStatus: response.status,
169
175
  responseHeaders,
170
176
  responseBody,
171
- timestamp: Date.now()
177
+ timestamp: endTime,
178
+ startTime,
179
+ endTime
172
180
  });
173
181
  return response;
174
182
  };
@@ -280,7 +288,9 @@ async function handleNeonSqlRequest(originalFetch, input, init, url, method, req
280
288
  ...init,
281
289
  body: JSON.stringify({ queries: txBody })
282
290
  };
291
+ const startTime = Date.now();
283
292
  const response = await originalFetch(input, modifiedInit);
293
+ const endTime = Date.now();
284
294
  const rawBody = await response.clone().text();
285
295
  const responseHeaders = {};
286
296
  response.headers.forEach((v, k) => {
@@ -306,7 +316,9 @@ async function handleNeonSqlRequest(originalFetch, input, init, url, method, req
306
316
  responseStatus: response.status,
307
317
  responseHeaders,
308
318
  responseBody: recordedBody,
309
- timestamp: Date.now()
319
+ timestamp: endTime,
320
+ startTime,
321
+ endTime
310
322
  });
311
323
  return new Response(recordedBody, {
312
324
  status: response.status,
@@ -718,7 +730,8 @@ async function finishRequest(requestContext, callbacks, response, options) {
718
730
  handlerResponse: {
719
731
  statusCode: response.statusCode ?? response.status ?? 0,
720
732
  body: typeof response.body === "string" ? response.body : void 0
721
- }
733
+ },
734
+ originalRequestId: options?.originalRequestId
722
735
  };
723
736
  const blobData = redactBlobData(rawBlobData);
724
737
  const blobContent = JSON.stringify(blobData);
@@ -749,9 +762,13 @@ async function finishRequest(requestContext, callbacks, response, options) {
749
762
 
750
763
  // src/createRecordingRequestHandler.ts
751
764
  import crypto2 from "crypto";
765
+ var _originalRequestId = null;
752
766
  function createRecordingRequestHandler(handler, options) {
753
767
  return async (event, context) => {
754
768
  const requestId = crypto2.randomUUID();
769
+ if (_originalRequestId === null) {
770
+ _originalRequestId = requestId;
771
+ }
755
772
  return runInRequestContext(requestId, async () => {
756
773
  const reqContext = startRequest(event);
757
774
  let response;
@@ -774,7 +791,7 @@ function createRecordingRequestHandler(handler, options) {
774
791
  statusCode: 500,
775
792
  body: JSON.stringify({ error: errorMessage })
776
793
  };
777
- const finishOpts2 = { ...options, requestId };
794
+ const finishOpts2 = { ...options, requestId, originalRequestId: _originalRequestId };
778
795
  const ctx2 = context;
779
796
  if (ctx2 && typeof ctx2.waitUntil === "function") {
780
797
  ctx2.waitUntil(
@@ -813,7 +830,7 @@ function createRecordingRequestHandler(handler, options) {
813
830
  "X-Replay-Request-Id": requestId
814
831
  }
815
832
  };
816
- const finishOpts = { ...options, requestId };
833
+ const finishOpts = { ...options, requestId, originalRequestId: _originalRequestId };
817
834
  const ctx = context;
818
835
  if (ctx && typeof ctx.waitUntil === "function") {
819
836
  ctx.waitUntil(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@replayio-app-building/netlify-recorder",
3
- "version": "0.42.0",
3
+ "version": "0.44.0",
4
4
  "description": "Capture and replay Netlify function executions as Replay recordings",
5
5
  "type": "module",
6
6
  "exports": {
@@ -29,7 +29,7 @@
29
29
  }
30
30
  },
31
31
  "devDependencies": {
32
- "@replayio/app-building": "^1.28.0",
32
+ "@replayio/app-building": "^1.29.0",
33
33
  "@types/node": "^25.6.0",
34
34
  "tsup": "^8.5.1",
35
35
  "typescript": "^5.7.3"