@replayio-app-building/netlify-recorder 0.21.0 → 0.22.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
@@ -205,24 +205,6 @@ interface CreateRecordingRequestHandlerOptions extends FinishRequestOptions {
205
205
  */
206
206
  declare function createRecordingRequestHandler(handler: (event: NetlifyEvent | NetlifyV2Request, context?: unknown) => Promise<HandlerResponse>, options: CreateRecordingRequestHandlerOptions): (event: NetlifyEvent | NetlifyV2Request, context?: unknown) => Promise<HandlerResponse>;
207
207
 
208
- /**
209
- * Redacts sensitive environment variable values from blob data.
210
- *
211
- * This function performs two passes:
212
- *
213
- * Pass 1 — Redact env reads:
214
- * For each captured EnvRead whose value should be redacted,
215
- * replace the value with a "*"-repeated string of the same length.
216
- *
217
- * Pass 2 — Scrub the rest of the blob:
218
- * Any redacted value that appears elsewhere in the blob data
219
- * (network call headers, bodies, request info headers/body) is
220
- * also replaced with the same mask. This prevents secrets from
221
- * leaking through, e.g., an Authorization header that embeds
222
- * an API key captured via process.env.
223
- *
224
- * The function returns a new BlobData object; the input is not mutated.
225
- */
226
208
  declare function redactBlobData(blobData: BlobData): BlobData;
227
209
 
228
210
  interface RecordingResult {
package/dist/index.js CHANGED
@@ -417,11 +417,8 @@ function shouldRedact(key, value) {
417
417
  if (value === void 0 || value.length <= 8) return false;
418
418
  return true;
419
419
  }
420
- function replaceAll(text, searchValue, mask) {
421
- return text.split(searchValue).join(mask);
422
- }
423
- function buildMask(value) {
424
- return "*".repeat(value.length);
420
+ function replaceAll(text, searchValue, replacement) {
421
+ return text.split(searchValue).join(replacement);
425
422
  }
426
423
  function buildPlaceholder(key) {
427
424
  if (key === "DATABASE_URL" || key.endsWith("_DATABASE_URL")) {
@@ -430,20 +427,18 @@ function buildPlaceholder(key) {
430
427
  return `placeholder_${key.toLowerCase()}`;
431
428
  }
432
429
  function redactBlobData(blobData) {
433
- const redactions = /* @__PURE__ */ new Map();
434
- const placeholders = /* @__PURE__ */ new Map();
430
+ const replacements = /* @__PURE__ */ new Map();
435
431
  const redactedEnvReads = blobData.capturedData.envReads.map(
436
432
  (read) => {
437
433
  if (shouldRedact(read.key, read.value) && read.value !== void 0) {
438
- const mask = buildMask(read.value);
439
- redactions.set(read.value, mask);
440
- placeholders.set(read.value, buildPlaceholder(read.key));
441
- return { ...read, value: mask };
434
+ const placeholder = buildPlaceholder(read.key);
435
+ replacements.set(read.value, placeholder);
436
+ return { ...read, value: placeholder };
442
437
  }
443
438
  return { ...read };
444
439
  }
445
440
  );
446
- if (redactions.size === 0) {
441
+ if (replacements.size === 0) {
447
442
  return {
448
443
  ...blobData,
449
444
  capturedData: {
@@ -452,14 +447,14 @@ function redactBlobData(blobData) {
452
447
  }
453
448
  };
454
449
  }
455
- const sortedRedactions = [...redactions.entries()].sort(
450
+ const sorted = [...replacements.entries()].sort(
456
451
  (a, b) => b[0].length - a[0].length
457
452
  );
458
453
  function scrub(text) {
459
454
  if (text === void 0) return void 0;
460
455
  let result = text;
461
- for (const [original, mask] of sortedRedactions) {
462
- result = replaceAll(result, original, mask);
456
+ for (const [original, placeholder] of sorted) {
457
+ result = replaceAll(result, original, placeholder);
463
458
  }
464
459
  return result;
465
460
  }
@@ -470,29 +465,11 @@ function redactBlobData(blobData) {
470
465
  }
471
466
  return out;
472
467
  }
473
- const sortedPlaceholders = [...placeholders.entries()].sort(
474
- (a, b) => b[0].length - a[0].length
475
- );
476
- function scrubForRequest(text) {
477
- if (text === void 0) return void 0;
478
- let result = text;
479
- for (const [original, placeholder] of sortedPlaceholders) {
480
- result = replaceAll(result, original, placeholder);
481
- }
482
- return result;
483
- }
484
- function scrubHeadersForRequest(headers) {
485
- const out = {};
486
- for (const [k, v] of Object.entries(headers)) {
487
- out[k] = scrubForRequest(v) ?? v;
488
- }
489
- return out;
490
- }
491
468
  const redactedRequestInfo = {
492
469
  ...blobData.requestInfo,
493
- url: scrubForRequest(blobData.requestInfo.url) ?? blobData.requestInfo.url,
494
- headers: scrubHeadersForRequest(blobData.requestInfo.headers),
495
- body: scrubForRequest(blobData.requestInfo.body)
470
+ url: scrub(blobData.requestInfo.url) ?? blobData.requestInfo.url,
471
+ headers: scrubHeaders(blobData.requestInfo.headers),
472
+ body: scrub(blobData.requestInfo.body)
496
473
  };
497
474
  const redactedNetworkCalls = blobData.capturedData.networkCalls.map(
498
475
  (call) => ({
@@ -643,15 +620,6 @@ async function createRequestRecording(blobUrlOrData, handlerPath, requestInfo) {
643
620
  } else {
644
621
  blobData = blobUrlOrData;
645
622
  }
646
- for (const read of blobData.capturedData.envReads) {
647
- if (read.value && read.value.length > 8 && /^\*+$/.test(read.value)) {
648
- if (read.key === "DATABASE_URL" || read.key.endsWith("_DATABASE_URL")) {
649
- read.value = "postgresql://replay:replay@localhost:5432/replay";
650
- } else {
651
- read.value = `placeholder_${read.key.toLowerCase()}`;
652
- }
653
- }
654
- }
655
623
  const networkHandle = installNetworkInterceptor(
656
624
  "replay",
657
625
  blobData.capturedData.networkCalls
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@replayio-app-building/netlify-recorder",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Capture and replay Netlify function executions as Replay recordings",
5
5
  "type": "module",
6
6
  "exports": {