@replayio-app-building/netlify-recorder 0.54.0 → 0.56.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.
Files changed (2) hide show
  1. package/dist/index.js +45 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -984,7 +984,7 @@ async function finishRequest(requestContext, callbacks, response, options) {
984
984
  body: typeof response.body === "string" ? response.body : void 0
985
985
  },
986
986
  originalRequestId: options?.originalRequestId,
987
- packageVersion: "0.54.0"
987
+ packageVersion: "0.56.0"
988
988
  };
989
989
  const blobData = redactBlobData(rawBlobData);
990
990
  const blobContent = JSON.stringify(blobData);
@@ -1113,6 +1113,7 @@ function createRecordingRequestHandler(handler, options) {
1113
1113
  }
1114
1114
 
1115
1115
  // src/createRequestRecording.ts
1116
+ import { gunzipSync } from "zlib";
1116
1117
  async function createRequestRecording(blobUrlOrData, handlerPath, requestInfo, precedingBlobs) {
1117
1118
  let blobData;
1118
1119
  if (typeof blobUrlOrData === "string") {
@@ -1122,7 +1123,9 @@ async function createRequestRecording(blobUrlOrData, handlerPath, requestInfo, p
1122
1123
  `Failed to download blob from ${blobUrlOrData}: ${response.status}`
1123
1124
  );
1124
1125
  }
1125
- blobData = await response.json();
1126
+ const buf = Buffer.from(await response.arrayBuffer());
1127
+ const json = buf[0] === 31 && buf[1] === 139 ? gunzipSync(buf).toString("utf-8") : buf.toString("utf-8");
1128
+ blobData = JSON.parse(json);
1126
1129
  } else {
1127
1130
  blobData = blobUrlOrData;
1128
1131
  }
@@ -1143,6 +1146,35 @@ async function createRequestRecording(blobUrlOrData, handlerPath, requestInfo, p
1143
1146
  t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
1144
1147
  return ((t ^ t >>> 14) >>> 0) / 4294967296;
1145
1148
  };
1149
+ const cryptoMod = __require("crypto");
1150
+ const origRandomBytes = cryptoMod.randomBytes;
1151
+ const origRandomUUID = cryptoMod.randomUUID;
1152
+ let cryptoSeed = 3735928559;
1153
+ const nextByte = () => {
1154
+ cryptoSeed = cryptoSeed + 1831565813 | 0;
1155
+ let t = Math.imul(cryptoSeed ^ cryptoSeed >>> 15, 1 | cryptoSeed);
1156
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
1157
+ return (t ^ t >>> 14) >>> 0 & 255;
1158
+ };
1159
+ cryptoMod.randomBytes = (size, cb) => {
1160
+ const buf = Buffer.alloc(size);
1161
+ for (let i = 0; i < size; i++) buf[i] = nextByte();
1162
+ if (cb) {
1163
+ cb(null, buf);
1164
+ return void 0;
1165
+ }
1166
+ return buf;
1167
+ };
1168
+ if (origRandomUUID) {
1169
+ cryptoMod.randomUUID = () => {
1170
+ const bytes = new Uint8Array(16);
1171
+ for (let i = 0; i < 16; i++) bytes[i] = nextByte();
1172
+ bytes[6] = bytes[6] & 15 | 64;
1173
+ bytes[8] = bytes[8] & 63 | 128;
1174
+ const h = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
1175
+ return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;
1176
+ };
1177
+ }
1146
1178
  const g = globalThis;
1147
1179
  if (typeof g.Blob === "undefined") {
1148
1180
  try {
@@ -1507,6 +1539,8 @@ async function createRequestRecording(blobUrlOrData, handlerPath, requestInfo, p
1507
1539
  delete g.__REPLAY_REQUEST_COOKIES__;
1508
1540
  delete g.__REPLAY_REQUEST_HEADERS__;
1509
1541
  Math.random = origMathRandom;
1542
+ cryptoMod.randomBytes = origRandomBytes;
1543
+ if (origRandomUUID) cryptoMod.randomUUID = origRandomUUID;
1510
1544
  networkHandle.restore();
1511
1545
  envHandle.restore();
1512
1546
  }
@@ -1514,6 +1548,8 @@ async function createRequestRecording(blobUrlOrData, handlerPath, requestInfo, p
1514
1548
  }
1515
1549
 
1516
1550
  // src/backendRequests.ts
1551
+ import { gzipSync } from "zlib";
1552
+ import { createHash } from "crypto";
1517
1553
  import { UTApi } from "uploadthing/server";
1518
1554
  async function backendRequestsEnsureTable(sql) {
1519
1555
  await sql`
@@ -1640,10 +1676,15 @@ async function uploadBlobData(blobData, requestId) {
1640
1676
  );
1641
1677
  }
1642
1678
  const utapi = new UTApi({ token });
1643
- const blob = new Blob([blobData], { type: "application/json" });
1644
- const file = Object.assign(blob, { name: `blob-${requestId}.json` });
1679
+ const compressed = gzipSync(Buffer.from(blobData, "utf-8"));
1680
+ const blob = new Blob([compressed], { type: "application/gzip" });
1681
+ const file = Object.assign(blob, { name: `blob-${requestId}.json.gz` });
1645
1682
  const result = await utapi.uploadFiles(file);
1646
1683
  if (result.error || !result.data?.ufsUrl) {
1684
+ const tokenHash = createHash("sha256").update(token).digest("hex").slice(0, 8);
1685
+ console.error(
1686
+ `netlify-recorder: uploadBlobData failed for request ${requestId} (token length=${token.length}, hash=${tokenHash}\u2026): ${JSON.stringify(result.error ?? "no URL returned")}`
1687
+ );
1647
1688
  throw new Error(
1648
1689
  `Failed to upload blob data for request ${requestId}: ${JSON.stringify(result.error ?? "no URL returned")}`
1649
1690
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@replayio-app-building/netlify-recorder",
3
- "version": "0.54.0",
3
+ "version": "0.56.0",
4
4
  "description": "Capture and replay Netlify function executions as Replay recordings",
5
5
  "type": "module",
6
6
  "exports": {