@replayio-app-building/netlify-recorder 0.24.0 → 0.26.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
@@ -137,15 +137,7 @@ The function is idempotent — calling it multiple times for the same request is
137
137
  - **`status: "queued"` or `"processing"`** — returns `null` without re-queuing
138
138
  - **`status: "captured"` or `"failed"`** — calls the service, updates status to `"queued"`, returns `null`
139
139
 
140
- By default, the blob data URL points to `${recorderUrl}/api/get-backend-request-blob?requestId=${requestId}`. If your app serves blob data from a different endpoint, pass a custom `blobDataUrl`:
141
-
142
- ```typescript
143
- const recordingId = await ensureRequestRecording(sql, requestId, {
144
- recorderUrl: RECORDER_URL,
145
- blobDataUrl: `https://your-app.netlify.app/api/get-blob?id=${requestId}`,
146
- webhookUrl: "https://your-app.netlify.app/api/on-recording-complete", // optional
147
- });
148
- ```
140
+ The function reads the `blob_data` from `backend_requests`, uploads it to UploadThing, and passes the URL to the recorder service. This requires the `uploadthing` package and `UPLOADTHING_TOKEN` environment variable.
149
141
 
150
142
  When `webhookUrl` is provided, the service POSTs the result when the recording completes:
151
143
 
@@ -411,7 +403,6 @@ Ensures a Replay recording exists (or is being created) for a backend request. L
411
403
  - `sql` — A Neon SQL tagged-template function
412
404
  - `requestId` — The backend request UUID
413
405
  - `options.recorderUrl` — Base URL of the Netlify Recorder service
414
- - `options.blobDataUrl` — Override the URL where the recording container fetches the blob JSON (defaults to `${recorderUrl}/api/get-backend-request-blob?requestId=${requestId}`)
415
406
  - `options.webhookUrl` — URL to POST the result to when the recording completes or fails
416
407
 
417
408
  **Returns:** The recording ID (`string`) if the request is already recorded, or `null` if the recording was queued or is in progress.
package/dist/index.d.ts CHANGED
@@ -277,11 +277,6 @@ declare function databaseCallbacks(sql: SqlFunction$1): FinishRequestCallbacks;
277
277
  interface EnsureRequestRecordingOptions {
278
278
  /** Base URL of the Netlify Recorder service (e.g. "https://netlify-recorder-bm4wmw.netlify.app"). */
279
279
  recorderUrl: string;
280
- /**
281
- * Full URL where the recording container can fetch the blob JSON for this request.
282
- * Defaults to `${recorderUrl}/api/get-backend-request-blob?requestId=${requestId}`.
283
- */
284
- blobDataUrl?: string;
285
280
  /** URL to POST the result to when the recording completes or fails. */
286
281
  webhookUrl?: string;
287
282
  }
@@ -291,8 +286,10 @@ interface EnsureRequestRecordingOptions {
291
286
  * 1. Looks up the request in `backend_requests`.
292
287
  * 2. If a recording already exists (`status === "recorded"`), returns the recording ID immediately.
293
288
  * 3. If the request is already queued or processing, returns `null` without re-queuing.
294
- * 4. Otherwise, calls the Netlify Recorder service's `create-recording` endpoint,
295
- * updates the row to `"queued"`, and returns `null`.
289
+ * 4. Otherwise, uploads the blob data to UploadThing, calls the Netlify Recorder
290
+ * service's `create-recording` endpoint, updates the row to `"queued"`, and returns `null`.
291
+ *
292
+ * Requires `UPLOADTHING_TOKEN` environment variable and the `uploadthing` package.
296
293
  *
297
294
  * This function is idempotent — calling it multiple times for the same request
298
295
  * is safe. Once the recording completes, subsequent calls return the recording ID.
package/dist/index.js CHANGED
@@ -1063,6 +1063,35 @@ function databaseCallbacks(sql) {
1063
1063
  }
1064
1064
  };
1065
1065
  }
1066
+ async function uploadBlobData(blobData, requestId) {
1067
+ let UTApi;
1068
+ try {
1069
+ ({ UTApi } = await Function('return import("uploadthing/server")')());
1070
+ } catch {
1071
+ throw new Error(
1072
+ "ensureRequestRecording requires the 'uploadthing' package. Install it with: npm install uploadthing"
1073
+ );
1074
+ }
1075
+ const token = process.env.UPLOADTHING_TOKEN;
1076
+ if (!token) {
1077
+ throw new Error(
1078
+ "ensureRequestRecording: UPLOADTHING_TOKEN environment variable is required to upload blob data"
1079
+ );
1080
+ }
1081
+ const utapi = new UTApi({ token });
1082
+ const file = new File(
1083
+ [blobData],
1084
+ `blob-${requestId}.json`,
1085
+ { type: "application/json" }
1086
+ );
1087
+ const result = await utapi.uploadFiles(file);
1088
+ if (result.error || !result.data?.ufsUrl) {
1089
+ throw new Error(
1090
+ `Failed to upload blob data for request ${requestId}: ${JSON.stringify(result.error ?? "no URL returned")}`
1091
+ );
1092
+ }
1093
+ return result.data.ufsUrl;
1094
+ }
1066
1095
  async function ensureRequestRecording(sql, requestId, options) {
1067
1096
  const request = await backendRequestsGet(sql, requestId);
1068
1097
  if (!request) {
@@ -1074,8 +1103,8 @@ async function ensureRequestRecording(sql, requestId, options) {
1074
1103
  if (request.status === "queued" || request.status === "processing") {
1075
1104
  return null;
1076
1105
  }
1106
+ const blobDataUrl = await uploadBlobData(request.blob_data, requestId);
1077
1107
  const recorderUrl = options.recorderUrl.replace(/\/+$/, "");
1078
- const blobDataUrl = options.blobDataUrl ?? `${recorderUrl}/api/get-backend-request-blob?requestId=${requestId}`;
1079
1108
  const res = await fetch(`${recorderUrl}/api/create-recording`, {
1080
1109
  method: "POST",
1081
1110
  headers: { "Content-Type": "application/json" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@replayio-app-building/netlify-recorder",
3
- "version": "0.24.0",
3
+ "version": "0.26.0",
4
4
  "description": "Capture and replay Netlify function executions as Replay recordings",
5
5
  "type": "module",
6
6
  "exports": {
@@ -18,11 +18,15 @@
18
18
  "prepublishOnly": "tsup"
19
19
  },
20
20
  "peerDependencies": {
21
- "@replayio/app-building": ">=1.0.0"
21
+ "@replayio/app-building": ">=1.0.0",
22
+ "uploadthing": ">=7.0.0"
22
23
  },
23
24
  "peerDependenciesMeta": {
24
25
  "@replayio/app-building": {
25
26
  "optional": true
27
+ },
28
+ "uploadthing": {
29
+ "optional": true
26
30
  }
27
31
  },
28
32
  "devDependencies": {