@replayio-app-building/netlify-recorder 0.45.0 → 0.47.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/README.md CHANGED
@@ -169,6 +169,21 @@ const status = await fetch(
169
169
  | `not_found` | 404 | Request ID not found in `backend_requests` |
170
170
  | `error` | 4xx/5xx | Validation error, auth failure, or recording failure |
171
171
 
172
+ #### Warm-start replay (preceding requests)
173
+
174
+ Netlify Functions run on AWS Lambda, where module-level state persists across invocations on the same container instance (warm starts). For example, a module-level `Map` used as a cache will retain entries across requests handled by the same container. This means a recording of a warm-start request may behave differently than the original if module-level state is empty.
175
+
176
+ The recorder handles this automatically. `createRecordingRequestHandler` maintains a module-level `originalRequestId` that captures the ID of the first request handled by each module instance. Every subsequent request on the same instance includes this reference in its blob data, linking all requests from the same warm-start chain.
177
+
178
+ When a recording is triggered for a request that has an `originalRequestId`, the recording service:
179
+
180
+ 1. Looks up all preceding requests from the same module instance (same `original_request_id`, earlier `created_at`)
181
+ 2. Fetches the blob data for each preceding request
182
+ 3. Replays the preceding requests in order on the handler module before executing the target request — each preceding request runs with its own replay interceptors so recorded network responses are served without making real calls
183
+ 4. Executes the target request, now with module-level state populated exactly as it was in production
184
+
185
+ This is fully automatic — no configuration or code changes are needed beyond wrapping your handlers with `createRecordingRequestHandler`. The `original_request_id` column is stored in the `backend_requests` table and the preceding blob URLs are resolved server-side.
186
+
172
187
  ### 5. Create recordings programmatically
173
188
 
174
189
  Use `ensureRequestRecording` to turn a captured request into a Replay recording. It checks the `backend_requests` table first — if a recording already exists, it returns the recording ID immediately without calling the service. Otherwise it passes the stored blob data URL to the Netlify Recorder service and updates the row status to `"queued"`.
package/dist/index.js CHANGED
@@ -225,8 +225,9 @@ function installNetworkInterceptor(mode, calls) {
225
225
  );
226
226
  }
227
227
  consumed.add(matchIdx);
228
+ const duration = call.endTime - call.startTime;
228
229
  console.log(
229
- ` [network-replay] Consumed call ${consumed.size}/${calls.length}: ${call.method} ${call.url} => ${call.responseStatus}`
230
+ ` [network-replay] Consumed call ${consumed.size}/${calls.length}: ${call.method} ${call.url} => ${call.responseStatus} (original: ${duration}ms)`
230
231
  );
231
232
  const body = call.responseBody ?? "";
232
233
  const status = call.responseStatus;
@@ -1308,7 +1309,7 @@ async function backendRequestsInsert(sql, data) {
1308
1309
  async function backendRequestsGet(sql, id) {
1309
1310
  const rows = await sql`
1310
1311
  SELECT id, blob_data_url, handler_path, commit_sha, branch_name, repository_url,
1311
- status, recording_id, error_message, created_at, updated_at
1312
+ original_request_id, status, recording_id, error_message, created_at, updated_at
1312
1313
  FROM backend_requests WHERE id = ${id}
1313
1314
  `;
1314
1315
  return rows[0] ?? null;
@@ -1324,7 +1325,7 @@ async function backendRequestsList(sql, filters) {
1324
1325
  if (filters?.status) {
1325
1326
  const rows2 = await sql`
1326
1327
  SELECT id, blob_data_url, handler_path, commit_sha, branch_name, repository_url,
1327
- status, recording_id, error_message, created_at, updated_at
1328
+ original_request_id, status, recording_id, error_message, created_at, updated_at
1328
1329
  FROM backend_requests
1329
1330
  WHERE status = ${filters.status}
1330
1331
  ORDER BY created_at DESC
@@ -1446,7 +1447,8 @@ async function ensureRequestRecording(sql, requestId, options) {
1446
1447
  commitSha: request.commit_sha,
1447
1448
  branchName: request.branch_name,
1448
1449
  repositoryUrl: request.repository_url ?? void 0,
1449
- webhookUrl: options.webhookUrl
1450
+ webhookUrl: options.webhookUrl,
1451
+ originalRequestId: request.original_request_id ?? void 0
1450
1452
  })
1451
1453
  });
1452
1454
  if (!res.ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@replayio-app-building/netlify-recorder",
3
- "version": "0.45.0",
3
+ "version": "0.47.0",
4
4
  "description": "Capture and replay Netlify function executions as Replay recordings",
5
5
  "type": "module",
6
6
  "exports": {