@replayio-app-building/netlify-recorder 0.26.0 → 0.28.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 +16 -15
- package/dist/index.d.ts +13 -12
- package/dist/index.js +39 -33
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @replayio-app-building/netlify-recorder
|
|
2
2
|
|
|
3
|
-
Capture and replay Netlify function executions as [Replay](https://replay.io) recordings. This package intercepts outbound network calls and environment variable reads during handler execution,
|
|
3
|
+
Capture and replay Netlify function executions as [Replay](https://replay.io) recordings. This package intercepts outbound network calls and environment variable reads during handler execution, uploads the captured data to UploadThing, stores the URL in your app's database, and can later reproduce the exact execution as a Replay recording for debugging and analysis.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -20,19 +20,20 @@ import { backendRequestsEnsureTable } from "@replayio-app-building/netlify-recor
|
|
|
20
20
|
await backendRequestsEnsureTable(sql);
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
This creates a table with columns for the
|
|
23
|
+
This creates a table with columns for the blob data URL (UploadThing), git metadata (commit SHA, branch, repository URL), handler path, recording status, and timestamps.
|
|
24
24
|
|
|
25
25
|
### 2. Set required environment variables
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Set these environment variables on your Netlify site:
|
|
28
28
|
|
|
29
29
|
| Variable | Description | How to set |
|
|
30
30
|
|---|---|---|
|
|
31
31
|
| `REPLAY_REPOSITORY_URL` | Your app's git repository URL (e.g. `https://github.com/org/repo.git`) | Set in your deploy script or Netlify site settings |
|
|
32
32
|
| `COMMIT_SHA` | The git commit hash of the deployed code | Set in your deploy script via `git rev-parse HEAD` |
|
|
33
33
|
| `BRANCH_NAME` | The git branch of the deployed code | Set in your deploy script via `git rev-parse --abbrev-ref HEAD` |
|
|
34
|
+
| `UPLOADTHING_TOKEN` | UploadThing API token for blob data storage | Set in Netlify site settings |
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
The first three are **required** by `finishRequest` (it will throw if missing). `UPLOADTHING_TOKEN` is required by `databaseCallbacks` to upload captured blob data. Your deploy script should resolve the git values and set them on the Netlify site before deploying. Example:
|
|
36
37
|
|
|
37
38
|
```typescript
|
|
38
39
|
// In your deploy script:
|
|
@@ -46,7 +47,7 @@ const repositoryUrl = execSync("git remote get-url origin", { encoding: "utf-8"
|
|
|
46
47
|
|
|
47
48
|
### 3. Wrap your Netlify function
|
|
48
49
|
|
|
49
|
-
Use `createRecordingRequestHandler` with `databaseCallbacks(sql)` to wrap your handler with automatic request capture. The captured data is stored
|
|
50
|
+
Use `createRecordingRequestHandler` with `databaseCallbacks(sql)` to wrap your handler with automatic request capture. The captured data is uploaded to UploadThing and the URL is stored in the `backend_requests` table.
|
|
50
51
|
|
|
51
52
|
**v1 handler** (Netlify Functions v1 — `event` with `httpMethod`, `path`, etc.):
|
|
52
53
|
|
|
@@ -108,13 +109,13 @@ export default createRecordingRequestHandler(
|
|
|
108
109
|
);
|
|
109
110
|
```
|
|
110
111
|
|
|
111
|
-
`createRecordingRequestHandler` automatically captures all outbound network calls and environment variable reads during your handler's execution,
|
|
112
|
+
`createRecordingRequestHandler` automatically captures all outbound network calls and environment variable reads during your handler's execution, uploads the captured data to UploadThing, and stores the URL in the `backend_requests` table. The response includes an `X-Replay-Request-Id` header with the ID of the stored request.
|
|
112
113
|
|
|
113
114
|
> **Note:** Always use the response returned by the wrapper (or `finishRequest`), not your original response object. The wrapper adds the `X-Replay-Request-Id` header to the response it returns.
|
|
114
115
|
|
|
115
116
|
### 4. Create recordings via the Netlify Recorder service
|
|
116
117
|
|
|
117
|
-
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
|
|
118
|
+
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"`.
|
|
118
119
|
|
|
119
120
|
```typescript
|
|
120
121
|
import { ensureRequestRecording } from "@replayio-app-building/netlify-recorder";
|
|
@@ -137,8 +138,6 @@ The function is idempotent — calling it multiple times for the same request is
|
|
|
137
138
|
- **`status: "queued"` or `"processing"`** — returns `null` without re-queuing
|
|
138
139
|
- **`status: "captured"` or `"failed"`** — calls the service, updates status to `"queued"`, returns `null`
|
|
139
140
|
|
|
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.
|
|
141
|
-
|
|
142
141
|
When `webhookUrl` is provided, the service POSTs the result when the recording completes:
|
|
143
142
|
|
|
144
143
|
On success:
|
|
@@ -316,12 +315,14 @@ Logs a `console.warn` when the total duration exceeds 2 seconds to help diagnose
|
|
|
316
315
|
|
|
317
316
|
### `databaseCallbacks(sql): FinishRequestCallbacks`
|
|
318
317
|
|
|
319
|
-
Creates a `FinishRequestCallbacks` object that
|
|
318
|
+
Creates a `FinishRequestCallbacks` object that uploads captured request data to UploadThing and stores the URL in the `backend_requests` table. This is the standard way to provide callbacks to `createRecordingRequestHandler` or `finishRequest`.
|
|
319
|
+
|
|
320
|
+
Requires `UPLOADTHING_TOKEN` environment variable and the `uploadthing` package.
|
|
320
321
|
|
|
321
322
|
**Parameters:**
|
|
322
323
|
- `sql` — A Neon SQL tagged-template function
|
|
323
324
|
|
|
324
|
-
**Returns:** An object with a `storeRequest` method that inserts rows into `backend_requests`.
|
|
325
|
+
**Returns:** An object with a `storeRequest` method that uploads blob data and inserts rows into `backend_requests`.
|
|
325
326
|
|
|
326
327
|
### `backendRequestsEnsureTable(sql): Promise<void>`
|
|
327
328
|
|
|
@@ -332,7 +333,7 @@ The table schema:
|
|
|
332
333
|
| Column | Type | Description |
|
|
333
334
|
|---|---|---|
|
|
334
335
|
| `id` | UUID (PK) | Auto-generated request ID |
|
|
335
|
-
| `
|
|
336
|
+
| `blob_data_url` | TEXT | URL to the uploaded blob JSON (UploadThing) |
|
|
336
337
|
| `handler_path` | TEXT | Path to the handler file |
|
|
337
338
|
| `commit_sha` | TEXT | Git commit SHA |
|
|
338
339
|
| `branch_name` | TEXT | Git branch name (default: `'main'`) |
|
|
@@ -352,7 +353,7 @@ Inserts a new row into `backend_requests` and returns the generated (or provided
|
|
|
352
353
|
|
|
353
354
|
**Parameters:**
|
|
354
355
|
- `sql` — A Neon SQL tagged-template function
|
|
355
|
-
- `data.
|
|
356
|
+
- `data.blobDataUrl` — URL to the uploaded blob JSON (e.g. UploadThing URL)
|
|
356
357
|
- `data.handlerPath` — Handler file path
|
|
357
358
|
- `data.commitSha` — Git commit SHA
|
|
358
359
|
- `data.branchName` — Git branch name
|
|
@@ -367,9 +368,9 @@ Retrieves a single request by ID, or `null` if not found.
|
|
|
367
368
|
- `sql` — A Neon SQL tagged-template function
|
|
368
369
|
- `id` — The request UUID
|
|
369
370
|
|
|
370
|
-
### `
|
|
371
|
+
### `backendRequestsGetBlobUrl(sql, id): Promise<string | null>`
|
|
371
372
|
|
|
372
|
-
Retrieves only the `
|
|
373
|
+
Retrieves only the `blob_data_url` column for a request, or `null` if not found.
|
|
373
374
|
|
|
374
375
|
**Parameters:**
|
|
375
376
|
- `sql` — A Neon SQL tagged-template function
|
package/dist/index.d.ts
CHANGED
|
@@ -234,7 +234,7 @@ declare function createRequestRecording(blobUrlOrData: string | BlobData, handle
|
|
|
234
234
|
type SqlFunction$1 = (...args: any[]) => Promise<any[]>;
|
|
235
235
|
interface BackendRequest {
|
|
236
236
|
id: string;
|
|
237
|
-
|
|
237
|
+
blob_data_url: string;
|
|
238
238
|
handler_path: string;
|
|
239
239
|
commit_sha: string;
|
|
240
240
|
branch_name: string;
|
|
@@ -250,28 +250,30 @@ interface BackendRequest {
|
|
|
250
250
|
*
|
|
251
251
|
* Each package client stores captured request data in its own database
|
|
252
252
|
* using this table. The blob data (captured network calls, env reads, etc.)
|
|
253
|
-
* is
|
|
254
|
-
* blob storage.
|
|
253
|
+
* is uploaded to UploadThing at capture time and only the URL is stored.
|
|
255
254
|
*/
|
|
256
255
|
declare function backendRequestsEnsureTable(sql: SqlFunction$1): Promise<void>;
|
|
257
256
|
declare function backendRequestsInsert(sql: SqlFunction$1, data: {
|
|
258
257
|
id?: string;
|
|
259
|
-
|
|
258
|
+
blobDataUrl: string;
|
|
260
259
|
handlerPath: string;
|
|
261
260
|
commitSha: string;
|
|
262
261
|
branchName: string;
|
|
263
262
|
repositoryUrl?: string | null;
|
|
264
263
|
}): Promise<string>;
|
|
265
264
|
declare function backendRequestsGet(sql: SqlFunction$1, id: string): Promise<BackendRequest | null>;
|
|
266
|
-
declare function
|
|
265
|
+
declare function backendRequestsGetBlobUrl(sql: SqlFunction$1, id: string): Promise<string | null>;
|
|
267
266
|
declare function backendRequestsList(sql: SqlFunction$1, filters?: {
|
|
268
267
|
status?: string;
|
|
269
268
|
limit?: number;
|
|
270
269
|
}): Promise<BackendRequest[]>;
|
|
271
270
|
declare function backendRequestsUpdateStatus(sql: SqlFunction$1, id: string, status: string, recordingId?: string, errorMessage?: string): Promise<void>;
|
|
272
271
|
/**
|
|
273
|
-
* Convenience helper: creates `FinishRequestCallbacks` that
|
|
274
|
-
* captured request data
|
|
272
|
+
* Convenience helper: creates `FinishRequestCallbacks` that upload
|
|
273
|
+
* captured request data to UploadThing and store the URL in the
|
|
274
|
+
* `backend_requests` table.
|
|
275
|
+
*
|
|
276
|
+
* Requires `UPLOADTHING_TOKEN` environment variable and the `uploadthing` package.
|
|
275
277
|
*/
|
|
276
278
|
declare function databaseCallbacks(sql: SqlFunction$1): FinishRequestCallbacks;
|
|
277
279
|
interface EnsureRequestRecordingOptions {
|
|
@@ -286,10 +288,9 @@ interface EnsureRequestRecordingOptions {
|
|
|
286
288
|
* 1. Looks up the request in `backend_requests`.
|
|
287
289
|
* 2. If a recording already exists (`status === "recorded"`), returns the recording ID immediately.
|
|
288
290
|
* 3. If the request is already queued or processing, returns `null` without re-queuing.
|
|
289
|
-
* 4. Otherwise,
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
* Requires `UPLOADTHING_TOKEN` environment variable and the `uploadthing` package.
|
|
291
|
+
* 4. Otherwise, calls the Netlify Recorder service's `create-recording` endpoint
|
|
292
|
+
* with the blob data URL from the stored request, updates the row to `"queued"`,
|
|
293
|
+
* and returns `null`.
|
|
293
294
|
*
|
|
294
295
|
* This function is idempotent — calling it multiple times for the same request
|
|
295
296
|
* is safe. Once the recording completes, subsequent calls return the recording ID.
|
|
@@ -319,4 +320,4 @@ declare function databaseAuditDumpLogTable(sql: SqlFunction): Promise<Record<str
|
|
|
319
320
|
|
|
320
321
|
declare function getCurrentRequestId(): string | null;
|
|
321
322
|
|
|
322
|
-
export { type BackendRequest, type BlobData, type CapturedData, type CreateRecordingRequestHandlerOptions, type EnsureRequestRecordingOptions, type EnvRead, type FinishRequestCallbacks, type FinishRequestOptions, type HandlerResponse$1 as HandlerResponse, type NetlifyEvent, type NetlifyV2Request, type NetworkCall, type RecordingResult, type RequestContext, type RequestInfo, backendRequestsEnsureTable, backendRequestsGet,
|
|
323
|
+
export { type BackendRequest, type BlobData, type CapturedData, type CreateRecordingRequestHandlerOptions, type EnsureRequestRecordingOptions, type EnvRead, type FinishRequestCallbacks, type FinishRequestOptions, type HandlerResponse$1 as HandlerResponse, type NetlifyEvent, type NetlifyV2Request, type NetworkCall, type RecordingResult, type RequestContext, type RequestInfo, backendRequestsEnsureTable, backendRequestsGet, backendRequestsGetBlobUrl, backendRequestsInsert, backendRequestsList, backendRequestsUpdateStatus, createRecordingRequestHandler, createRequestRecording, databaseAuditDumpLogTable, databaseAuditEnsureLogTable, databaseAuditMonitorTable, databaseCallbacks, ensureRequestRecording, finishRequest, getCurrentRequestId, redactBlobData, startRequest };
|
package/dist/index.js
CHANGED
|
@@ -563,10 +563,10 @@ async function finishRequest(requestContext, callbacks, response, options) {
|
|
|
563
563
|
}
|
|
564
564
|
|
|
565
565
|
// src/createRecordingRequestHandler.ts
|
|
566
|
-
import
|
|
566
|
+
import crypto2 from "crypto";
|
|
567
567
|
function createRecordingRequestHandler(handler, options) {
|
|
568
568
|
return async (event, context) => {
|
|
569
|
-
const requestId =
|
|
569
|
+
const requestId = crypto2.randomUUID();
|
|
570
570
|
setCurrentRequestId(requestId);
|
|
571
571
|
const reqContext = startRequest(event);
|
|
572
572
|
let response;
|
|
@@ -602,7 +602,13 @@ function createRecordingRequestHandler(handler, options) {
|
|
|
602
602
|
);
|
|
603
603
|
}
|
|
604
604
|
setCurrentRequestId(null);
|
|
605
|
-
|
|
605
|
+
return {
|
|
606
|
+
...errorResponse,
|
|
607
|
+
headers: {
|
|
608
|
+
...errorResponse.headers,
|
|
609
|
+
"X-Replay-Request-Id": requestId
|
|
610
|
+
}
|
|
611
|
+
};
|
|
606
612
|
}
|
|
607
613
|
reqContext.cleanup();
|
|
608
614
|
setCurrentRequestId(null);
|
|
@@ -944,7 +950,7 @@ async function backendRequestsEnsureTable(sql) {
|
|
|
944
950
|
await sql`
|
|
945
951
|
CREATE TABLE IF NOT EXISTS backend_requests (
|
|
946
952
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
947
|
-
|
|
953
|
+
blob_data_url TEXT NOT NULL,
|
|
948
954
|
handler_path TEXT NOT NULL,
|
|
949
955
|
commit_sha TEXT NOT NULL,
|
|
950
956
|
branch_name TEXT NOT NULL DEFAULT 'main',
|
|
@@ -967,10 +973,10 @@ async function backendRequestsEnsureTable(sql) {
|
|
|
967
973
|
async function backendRequestsInsert(sql, data) {
|
|
968
974
|
if (data.id) {
|
|
969
975
|
await sql`
|
|
970
|
-
INSERT INTO backend_requests (id,
|
|
976
|
+
INSERT INTO backend_requests (id, blob_data_url, handler_path, commit_sha, branch_name, repository_url)
|
|
971
977
|
VALUES (
|
|
972
978
|
${data.id}::uuid,
|
|
973
|
-
${data.
|
|
979
|
+
${data.blobDataUrl},
|
|
974
980
|
${data.handlerPath},
|
|
975
981
|
${data.commitSha},
|
|
976
982
|
${data.branchName},
|
|
@@ -980,9 +986,9 @@ async function backendRequestsInsert(sql, data) {
|
|
|
980
986
|
return data.id;
|
|
981
987
|
}
|
|
982
988
|
const rows = await sql`
|
|
983
|
-
INSERT INTO backend_requests (
|
|
989
|
+
INSERT INTO backend_requests (blob_data_url, handler_path, commit_sha, branch_name, repository_url)
|
|
984
990
|
VALUES (
|
|
985
|
-
${data.
|
|
991
|
+
${data.blobDataUrl},
|
|
986
992
|
${data.handlerPath},
|
|
987
993
|
${data.commitSha},
|
|
988
994
|
${data.branchName},
|
|
@@ -994,23 +1000,23 @@ async function backendRequestsInsert(sql, data) {
|
|
|
994
1000
|
}
|
|
995
1001
|
async function backendRequestsGet(sql, id) {
|
|
996
1002
|
const rows = await sql`
|
|
997
|
-
SELECT id,
|
|
1003
|
+
SELECT id, blob_data_url, handler_path, commit_sha, branch_name, repository_url,
|
|
998
1004
|
status, recording_id, error_message, created_at, updated_at
|
|
999
1005
|
FROM backend_requests WHERE id = ${id}
|
|
1000
1006
|
`;
|
|
1001
1007
|
return rows[0] ?? null;
|
|
1002
1008
|
}
|
|
1003
|
-
async function
|
|
1009
|
+
async function backendRequestsGetBlobUrl(sql, id) {
|
|
1004
1010
|
const rows = await sql`
|
|
1005
|
-
SELECT
|
|
1011
|
+
SELECT blob_data_url FROM backend_requests WHERE id = ${id}
|
|
1006
1012
|
`;
|
|
1007
|
-
return rows[0]?.
|
|
1013
|
+
return rows[0]?.blob_data_url ?? null;
|
|
1008
1014
|
}
|
|
1009
1015
|
async function backendRequestsList(sql, filters) {
|
|
1010
1016
|
const limit = filters?.limit ?? 50;
|
|
1011
1017
|
if (filters?.status) {
|
|
1012
1018
|
const rows2 = await sql`
|
|
1013
|
-
SELECT id,
|
|
1019
|
+
SELECT id, blob_data_url, handler_path, commit_sha, branch_name, repository_url,
|
|
1014
1020
|
status, recording_id, error_message, created_at, updated_at
|
|
1015
1021
|
FROM backend_requests
|
|
1016
1022
|
WHERE status = ${filters.status}
|
|
@@ -1020,7 +1026,7 @@ async function backendRequestsList(sql, filters) {
|
|
|
1020
1026
|
return rows2;
|
|
1021
1027
|
}
|
|
1022
1028
|
const rows = await sql`
|
|
1023
|
-
SELECT id,
|
|
1029
|
+
SELECT id, blob_data_url, handler_path, commit_sha, branch_name, repository_url,
|
|
1024
1030
|
status, recording_id, error_message, created_at, updated_at
|
|
1025
1031
|
FROM backend_requests
|
|
1026
1032
|
ORDER BY created_at DESC
|
|
@@ -1049,33 +1055,19 @@ async function backendRequestsUpdateStatus(sql, id, status, recordingId, errorMe
|
|
|
1049
1055
|
`;
|
|
1050
1056
|
}
|
|
1051
1057
|
}
|
|
1052
|
-
function databaseCallbacks(sql) {
|
|
1053
|
-
return {
|
|
1054
|
-
storeRequest: async (data) => {
|
|
1055
|
-
return backendRequestsInsert(sql, {
|
|
1056
|
-
id: data.requestId,
|
|
1057
|
-
blobData: data.blobData,
|
|
1058
|
-
handlerPath: data.handlerPath,
|
|
1059
|
-
commitSha: data.commitSha,
|
|
1060
|
-
branchName: data.branchName,
|
|
1061
|
-
repositoryUrl: data.repositoryUrl
|
|
1062
|
-
});
|
|
1063
|
-
}
|
|
1064
|
-
};
|
|
1065
|
-
}
|
|
1066
1058
|
async function uploadBlobData(blobData, requestId) {
|
|
1067
1059
|
let UTApi;
|
|
1068
1060
|
try {
|
|
1069
1061
|
({ UTApi } = await Function('return import("uploadthing/server")')());
|
|
1070
1062
|
} catch {
|
|
1071
1063
|
throw new Error(
|
|
1072
|
-
"
|
|
1064
|
+
"netlify-recorder requires the 'uploadthing' package. Install it with: npm install uploadthing"
|
|
1073
1065
|
);
|
|
1074
1066
|
}
|
|
1075
1067
|
const token = process.env.UPLOADTHING_TOKEN;
|
|
1076
1068
|
if (!token) {
|
|
1077
1069
|
throw new Error(
|
|
1078
|
-
"
|
|
1070
|
+
"netlify-recorder: UPLOADTHING_TOKEN environment variable is required to upload blob data"
|
|
1079
1071
|
);
|
|
1080
1072
|
}
|
|
1081
1073
|
const utapi = new UTApi({ token });
|
|
@@ -1092,6 +1084,21 @@ async function uploadBlobData(blobData, requestId) {
|
|
|
1092
1084
|
}
|
|
1093
1085
|
return result.data.ufsUrl;
|
|
1094
1086
|
}
|
|
1087
|
+
function databaseCallbacks(sql) {
|
|
1088
|
+
return {
|
|
1089
|
+
storeRequest: async (data) => {
|
|
1090
|
+
const blobDataUrl = await uploadBlobData(data.blobData, data.requestId ?? crypto.randomUUID());
|
|
1091
|
+
return backendRequestsInsert(sql, {
|
|
1092
|
+
id: data.requestId,
|
|
1093
|
+
blobDataUrl,
|
|
1094
|
+
handlerPath: data.handlerPath,
|
|
1095
|
+
commitSha: data.commitSha,
|
|
1096
|
+
branchName: data.branchName,
|
|
1097
|
+
repositoryUrl: data.repositoryUrl
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1095
1102
|
async function ensureRequestRecording(sql, requestId, options) {
|
|
1096
1103
|
const request = await backendRequestsGet(sql, requestId);
|
|
1097
1104
|
if (!request) {
|
|
@@ -1103,13 +1110,12 @@ async function ensureRequestRecording(sql, requestId, options) {
|
|
|
1103
1110
|
if (request.status === "queued" || request.status === "processing") {
|
|
1104
1111
|
return null;
|
|
1105
1112
|
}
|
|
1106
|
-
const blobDataUrl = await uploadBlobData(request.blob_data, requestId);
|
|
1107
1113
|
const recorderUrl = options.recorderUrl.replace(/\/+$/, "");
|
|
1108
1114
|
const res = await fetch(`${recorderUrl}/api/create-recording`, {
|
|
1109
1115
|
method: "POST",
|
|
1110
1116
|
headers: { "Content-Type": "application/json" },
|
|
1111
1117
|
body: JSON.stringify({
|
|
1112
|
-
blobDataUrl,
|
|
1118
|
+
blobDataUrl: request.blob_data_url,
|
|
1113
1119
|
handlerPath: request.handler_path,
|
|
1114
1120
|
commitSha: request.commit_sha,
|
|
1115
1121
|
branchName: request.branch_name,
|
|
@@ -1220,7 +1226,7 @@ async function databaseAuditDumpLogTable(sql) {
|
|
|
1220
1226
|
export {
|
|
1221
1227
|
backendRequestsEnsureTable,
|
|
1222
1228
|
backendRequestsGet,
|
|
1223
|
-
|
|
1229
|
+
backendRequestsGetBlobUrl,
|
|
1224
1230
|
backendRequestsInsert,
|
|
1225
1231
|
backendRequestsList,
|
|
1226
1232
|
backendRequestsUpdateStatus,
|