@replayio-app-building/netlify-recorder 0.25.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 +1 -10
- package/dist/index.d.ts +4 -8
- package/dist/index.js +31 -1
- package/package.json +6 -2
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
|
-
The `
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
const recordingId = await ensureRequestRecording(sql, requestId, {
|
|
144
|
-
recorderUrl: RECORDER_URL,
|
|
145
|
-
blobDataUrl: `https://utfs.io/f/${blobFileKey}`, // direct URL to stored blob data
|
|
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` — Direct URL where the recording container fetches the blob JSON (e.g. an UploadThing URL)
|
|
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,12 +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
|
-
* Must be a direct URL to the blob data (e.g. an UploadThing URL). The container
|
|
283
|
-
* fetches this URL directly — no callback to the recorder service is involved.
|
|
284
|
-
*/
|
|
285
|
-
blobDataUrl: string;
|
|
286
280
|
/** URL to POST the result to when the recording completes or fails. */
|
|
287
281
|
webhookUrl?: string;
|
|
288
282
|
}
|
|
@@ -292,8 +286,10 @@ interface EnsureRequestRecordingOptions {
|
|
|
292
286
|
* 1. Looks up the request in `backend_requests`.
|
|
293
287
|
* 2. If a recording already exists (`status === "recorded"`), returns the recording ID immediately.
|
|
294
288
|
* 3. If the request is already queued or processing, returns `null` without re-queuing.
|
|
295
|
-
* 4. Otherwise, calls the Netlify Recorder
|
|
296
|
-
* 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.
|
|
297
293
|
*
|
|
298
294
|
* This function is idempotent — calling it multiple times for the same request
|
|
299
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,12 +1103,13 @@ 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
1108
|
const res = await fetch(`${recorderUrl}/api/create-recording`, {
|
|
1079
1109
|
method: "POST",
|
|
1080
1110
|
headers: { "Content-Type": "application/json" },
|
|
1081
1111
|
body: JSON.stringify({
|
|
1082
|
-
blobDataUrl
|
|
1112
|
+
blobDataUrl,
|
|
1083
1113
|
handlerPath: request.handler_path,
|
|
1084
1114
|
commitSha: request.commit_sha,
|
|
1085
1115
|
branchName: request.branch_name,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@replayio-app-building/netlify-recorder",
|
|
3
|
-
"version": "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": {
|