@striae-org/striae 5.0.0 → 5.1.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/.env.example +5 -2
- package/app/components/actions/case-export/download-handlers.ts +6 -7
- package/app/components/actions/case-manage.ts +10 -11
- package/app/components/actions/generate-pdf.ts +43 -1
- package/app/components/actions/image-manage.ts +13 -45
- package/app/routes/striae/hooks/use-striae-reset-helpers.ts +4 -0
- package/app/routes/striae/striae.tsx +15 -4
- package/app/utils/data/operations/case-operations.ts +13 -1
- package/app/utils/data/operations/confirmation-summary-operations.ts +38 -1
- package/app/utils/data/operations/file-annotation-operations.ts +13 -1
- package/package.json +2 -2
- package/scripts/deploy-config.sh +149 -6
- package/scripts/deploy-pages-secrets.sh +0 -6
- package/scripts/deploy-worker-secrets.sh +66 -5
- package/scripts/encrypt-r2-backfill.mjs +376 -0
- package/worker-configuration.d.ts +13 -7
- package/workers/audit-worker/package.json +1 -4
- package/workers/audit-worker/src/audit-worker.example.ts +522 -61
- package/workers/audit-worker/wrangler.jsonc.example +5 -0
- package/workers/data-worker/package.json +1 -4
- package/workers/data-worker/src/data-worker.example.ts +280 -2
- package/workers/data-worker/src/encryption-utils.ts +145 -1
- package/workers/data-worker/wrangler.jsonc.example +4 -0
- package/workers/image-worker/package.json +1 -4
- package/workers/image-worker/src/encryption-utils.ts +217 -0
- package/workers/image-worker/src/image-worker.example.ts +196 -127
- package/workers/image-worker/wrangler.jsonc.example +7 -0
- package/workers/keys-worker/package.json +1 -4
- package/workers/pdf-worker/package.json +1 -4
- package/workers/user-worker/package.json +1 -4
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_STATE_FILE = '.backfill-data-at-rest-state.json';
|
|
8
|
+
const DEFAULT_BATCH_SIZE = 100;
|
|
9
|
+
const MAX_BATCH_SIZE = 1000;
|
|
10
|
+
|
|
11
|
+
function parseArgs(argv) {
|
|
12
|
+
const args = {
|
|
13
|
+
dryRun: false,
|
|
14
|
+
prefix: '',
|
|
15
|
+
cursor: undefined,
|
|
16
|
+
resume: false,
|
|
17
|
+
maxBatches: undefined,
|
|
18
|
+
batchSize: DEFAULT_BATCH_SIZE,
|
|
19
|
+
workerDomain: undefined,
|
|
20
|
+
r2Secret: undefined,
|
|
21
|
+
stateFile: DEFAULT_STATE_FILE,
|
|
22
|
+
keepState: false,
|
|
23
|
+
timeoutMs: 60000
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
27
|
+
const token = argv[index];
|
|
28
|
+
|
|
29
|
+
if (token === '--help' || token === '-h') {
|
|
30
|
+
printHelp();
|
|
31
|
+
process.exit(0);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (token === '--dry-run') {
|
|
35
|
+
args.dryRun = true;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (token === '--resume') {
|
|
40
|
+
args.resume = true;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (token === '--keep-state') {
|
|
45
|
+
args.keepState = true;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const valueToken = argv[index + 1];
|
|
50
|
+
|
|
51
|
+
if (token === '--prefix') {
|
|
52
|
+
args.prefix = valueToken ?? '';
|
|
53
|
+
index += 1;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (token === '--cursor') {
|
|
58
|
+
args.cursor = valueToken;
|
|
59
|
+
index += 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (token === '--state-file') {
|
|
64
|
+
args.stateFile = valueToken ?? DEFAULT_STATE_FILE;
|
|
65
|
+
index += 1;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (token === '--worker-domain') {
|
|
70
|
+
args.workerDomain = valueToken;
|
|
71
|
+
index += 1;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (token === '--r2-secret') {
|
|
76
|
+
args.r2Secret = valueToken;
|
|
77
|
+
index += 1;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (token === '--max-batches') {
|
|
82
|
+
const parsed = Number(valueToken);
|
|
83
|
+
if (!Number.isFinite(parsed) || parsed < 1) {
|
|
84
|
+
throw new Error('Invalid --max-batches value. It must be a positive number.');
|
|
85
|
+
}
|
|
86
|
+
args.maxBatches = Math.floor(parsed);
|
|
87
|
+
index += 1;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (token === '--batch-size') {
|
|
92
|
+
const parsed = Number(valueToken);
|
|
93
|
+
if (!Number.isFinite(parsed) || parsed < 1 || parsed > MAX_BATCH_SIZE) {
|
|
94
|
+
throw new Error(`Invalid --batch-size value. Use a number between 1 and ${MAX_BATCH_SIZE}.`);
|
|
95
|
+
}
|
|
96
|
+
args.batchSize = Math.floor(parsed);
|
|
97
|
+
index += 1;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (token === '--timeout-ms') {
|
|
102
|
+
const parsed = Number(valueToken);
|
|
103
|
+
if (!Number.isFinite(parsed) || parsed < 1000) {
|
|
104
|
+
throw new Error('Invalid --timeout-ms value. It must be >= 1000.');
|
|
105
|
+
}
|
|
106
|
+
args.timeoutMs = Math.floor(parsed);
|
|
107
|
+
index += 1;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
throw new Error(`Unknown argument: ${token}`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return args;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function printHelp() {
|
|
118
|
+
console.log('Usage: node scripts/encrypt-r2-backfill.mjs [options]');
|
|
119
|
+
console.log('');
|
|
120
|
+
console.log('Options:');
|
|
121
|
+
console.log(' --dry-run Scan and report, do not write encrypted objects');
|
|
122
|
+
console.log(' --prefix <value> Restrict scan to an R2 key prefix');
|
|
123
|
+
console.log(' --batch-size <1-1000> Number of objects per request (default: 100)');
|
|
124
|
+
console.log(' --max-batches <n> Stop after n batches');
|
|
125
|
+
console.log(' --cursor <token> Start from an explicit cursor');
|
|
126
|
+
console.log(' --resume Resume from state file cursor');
|
|
127
|
+
console.log(' --state-file <path> State file path (default: .backfill-data-at-rest-state.json)');
|
|
128
|
+
console.log(' --keep-state Keep state file even when completed');
|
|
129
|
+
console.log(' --worker-domain <host> Override DATA_WORKER_DOMAIN from .env');
|
|
130
|
+
console.log(' --r2-secret <value> Override R2_KEY_SECRET from .env');
|
|
131
|
+
console.log(' --timeout-ms <ms> Request timeout (default: 60000)');
|
|
132
|
+
console.log(' -h, --help Show this help text');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function parseDotEnv(filePath) {
|
|
136
|
+
if (!fs.existsSync(filePath)) {
|
|
137
|
+
return {};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
141
|
+
const env = {};
|
|
142
|
+
|
|
143
|
+
for (const line of content.split(/\r?\n/)) {
|
|
144
|
+
const trimmed = line.trim();
|
|
145
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const separatorIndex = trimmed.indexOf('=');
|
|
150
|
+
if (separatorIndex <= 0) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const key = trimmed.slice(0, separatorIndex).trim();
|
|
155
|
+
let value = trimmed.slice(separatorIndex + 1).trim();
|
|
156
|
+
|
|
157
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
158
|
+
value = value.slice(1, -1);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
env[key] = value;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return env;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function getConfigValue(name, overrides, envMap) {
|
|
168
|
+
const overrideValue = overrides[name];
|
|
169
|
+
if (typeof overrideValue === 'string' && overrideValue.length > 0) {
|
|
170
|
+
return overrideValue;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const processValue = process.env[name];
|
|
174
|
+
if (typeof processValue === 'string' && processValue.length > 0) {
|
|
175
|
+
return processValue;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const envFileValue = envMap[name];
|
|
179
|
+
if (typeof envFileValue === 'string' && envFileValue.length > 0) {
|
|
180
|
+
return envFileValue;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return '';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function readStateFile(filePath) {
|
|
187
|
+
if (!fs.existsSync(filePath)) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
193
|
+
return JSON.parse(raw);
|
|
194
|
+
} catch {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function writeStateFile(filePath, state) {
|
|
200
|
+
fs.writeFileSync(filePath, `${JSON.stringify(state, null, 2)}\n`, 'utf8');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function removeStateFile(filePath) {
|
|
204
|
+
if (fs.existsSync(filePath)) {
|
|
205
|
+
fs.unlinkSync(filePath);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function postBackfillBatch({ workerDomain, r2Secret, body, timeoutMs }) {
|
|
210
|
+
const controller = new AbortController();
|
|
211
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
const response = await fetch(`https://${workerDomain}/api/admin/data-at-rest-backfill`, {
|
|
215
|
+
method: 'POST',
|
|
216
|
+
headers: {
|
|
217
|
+
'Content-Type': 'application/json',
|
|
218
|
+
'X-Custom-Auth-Key': r2Secret
|
|
219
|
+
},
|
|
220
|
+
body: JSON.stringify(body),
|
|
221
|
+
signal: controller.signal
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const json = await response.json().catch(() => null);
|
|
225
|
+
|
|
226
|
+
if (!response.ok) {
|
|
227
|
+
const detail = json && typeof json.error === 'string' ? json.error : `${response.status} ${response.statusText}`;
|
|
228
|
+
throw new Error(`Backfill request failed: ${detail}`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (!json || typeof json !== 'object') {
|
|
232
|
+
throw new Error('Backfill response was not valid JSON');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return json;
|
|
236
|
+
} finally {
|
|
237
|
+
clearTimeout(timeoutId);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function formatNumber(value) {
|
|
242
|
+
return new Intl.NumberFormat('en-US').format(value);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async function main() {
|
|
246
|
+
const args = parseArgs(process.argv.slice(2));
|
|
247
|
+
const envPath = path.resolve(process.cwd(), '.env');
|
|
248
|
+
const envFromFile = parseDotEnv(envPath);
|
|
249
|
+
|
|
250
|
+
const workerDomain = getConfigValue('DATA_WORKER_DOMAIN', { DATA_WORKER_DOMAIN: args.workerDomain }, envFromFile)
|
|
251
|
+
.replace(/^https?:\/\//, '')
|
|
252
|
+
.replace(/\/+$/, '');
|
|
253
|
+
const r2Secret = getConfigValue('R2_KEY_SECRET', { R2_KEY_SECRET: args.r2Secret }, envFromFile);
|
|
254
|
+
|
|
255
|
+
if (!workerDomain) {
|
|
256
|
+
throw new Error('Missing DATA_WORKER_DOMAIN. Set it in .env or pass --worker-domain.');
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (!r2Secret) {
|
|
260
|
+
throw new Error('Missing R2_KEY_SECRET. Set it in .env or pass --r2-secret.');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const statePath = path.resolve(process.cwd(), args.stateFile);
|
|
264
|
+
const priorState = args.resume ? readStateFile(statePath) : null;
|
|
265
|
+
|
|
266
|
+
let cursor = args.cursor;
|
|
267
|
+
if (!cursor && priorState && typeof priorState.cursor === 'string') {
|
|
268
|
+
cursor = priorState.cursor;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const totals = {
|
|
272
|
+
scanned: 0,
|
|
273
|
+
eligible: 0,
|
|
274
|
+
encrypted: 0,
|
|
275
|
+
skippedEncrypted: 0,
|
|
276
|
+
skippedNonJson: 0,
|
|
277
|
+
failed: 0,
|
|
278
|
+
batches: 0
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
console.log('R2 data-at-rest backfill starting');
|
|
282
|
+
console.log(`Worker: https://${workerDomain}`);
|
|
283
|
+
console.log(`Mode: ${args.dryRun ? 'dry-run' : 'write'}`);
|
|
284
|
+
console.log(`Prefix: ${args.prefix || '(all keys)'}`);
|
|
285
|
+
console.log(`Batch size: ${args.batchSize}`);
|
|
286
|
+
if (cursor) {
|
|
287
|
+
console.log(`Starting cursor: ${cursor}`);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
while (true) {
|
|
291
|
+
if (args.maxBatches !== undefined && totals.batches >= args.maxBatches) {
|
|
292
|
+
console.log(`Stopping after max batches: ${args.maxBatches}`);
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const batchBody = {
|
|
297
|
+
dryRun: args.dryRun,
|
|
298
|
+
prefix: args.prefix,
|
|
299
|
+
cursor,
|
|
300
|
+
batchSize: args.batchSize
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const result = await postBackfillBatch({
|
|
304
|
+
workerDomain,
|
|
305
|
+
r2Secret,
|
|
306
|
+
body: batchBody,
|
|
307
|
+
timeoutMs: args.timeoutMs
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
totals.batches += 1;
|
|
311
|
+
totals.scanned += Number(result.scanned || 0);
|
|
312
|
+
totals.eligible += Number(result.eligible || 0);
|
|
313
|
+
totals.encrypted += Number(result.encrypted || 0);
|
|
314
|
+
totals.skippedEncrypted += Number(result.skippedEncrypted || 0);
|
|
315
|
+
totals.skippedNonJson += Number(result.skippedNonJson || 0);
|
|
316
|
+
totals.failed += Number(result.failed || 0);
|
|
317
|
+
|
|
318
|
+
cursor = typeof result.nextCursor === 'string' && result.nextCursor.length > 0
|
|
319
|
+
? result.nextCursor
|
|
320
|
+
: undefined;
|
|
321
|
+
|
|
322
|
+
writeStateFile(statePath, {
|
|
323
|
+
updatedAt: new Date().toISOString(),
|
|
324
|
+
dryRun: args.dryRun,
|
|
325
|
+
prefix: args.prefix,
|
|
326
|
+
batchSize: args.batchSize,
|
|
327
|
+
cursor: cursor ?? null,
|
|
328
|
+
hasMore: Boolean(result.hasMore),
|
|
329
|
+
totals
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
console.log(
|
|
333
|
+
`Batch ${totals.batches}: scanned=${formatNumber(Number(result.scanned || 0))}, ` +
|
|
334
|
+
`eligible=${formatNumber(Number(result.eligible || 0))}, ` +
|
|
335
|
+
`encrypted=${formatNumber(Number(result.encrypted || 0))}, ` +
|
|
336
|
+
`failed=${formatNumber(Number(result.failed || 0))}`
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
if (Array.isArray(result.failures) && result.failures.length > 0) {
|
|
340
|
+
for (const failure of result.failures) {
|
|
341
|
+
if (!failure || typeof failure.key !== 'string') {
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
const errorMessage = typeof failure.error === 'string' ? failure.error : 'Unknown error';
|
|
345
|
+
console.error(` failure: ${failure.key} -> ${errorMessage}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (!result.hasMore) {
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (!args.keepState && !cursor) {
|
|
355
|
+
removeStateFile(statePath);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
console.log('Backfill summary');
|
|
359
|
+
console.log(` batches: ${formatNumber(totals.batches)}`);
|
|
360
|
+
console.log(` scanned: ${formatNumber(totals.scanned)}`);
|
|
361
|
+
console.log(` eligible: ${formatNumber(totals.eligible)}`);
|
|
362
|
+
console.log(` encrypted: ${formatNumber(totals.encrypted)}`);
|
|
363
|
+
console.log(` skippedEncrypted: ${formatNumber(totals.skippedEncrypted)}`);
|
|
364
|
+
console.log(` skippedNonJson: ${formatNumber(totals.skippedNonJson)}`);
|
|
365
|
+
console.log(` failed: ${formatNumber(totals.failed)}`);
|
|
366
|
+
|
|
367
|
+
if (totals.failed > 0) {
|
|
368
|
+
process.exitCode = 1;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
main().catch((error) => {
|
|
373
|
+
const message = error instanceof Error ? error.message : 'Unknown backfill error';
|
|
374
|
+
console.error(`Backfill aborted: ${message}`);
|
|
375
|
+
process.exit(1);
|
|
376
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
-
// Generated by Wrangler by running `wrangler types` (hash:
|
|
3
|
-
// Runtime types generated with workerd@1.20250823.0 2026-03-
|
|
2
|
+
// Generated by Wrangler by running `wrangler types` (hash: f4bdacbf5374924fcd3b9a294158d34f)
|
|
3
|
+
// Runtime types generated with workerd@1.20250823.0 2026-03-24 nodejs_compat
|
|
4
4
|
declare namespace Cloudflare {
|
|
5
5
|
interface Env {
|
|
6
6
|
ACCOUNT_ID: string;
|
|
@@ -27,17 +27,23 @@ declare namespace Cloudflare {
|
|
|
27
27
|
KV_STORE_ID: string;
|
|
28
28
|
DATA_WORKER_NAME: string;
|
|
29
29
|
DATA_BUCKET_NAME: string;
|
|
30
|
+
FILES_BUCKET_NAME: string;
|
|
30
31
|
DATA_WORKER_DOMAIN: string;
|
|
31
32
|
MANIFEST_SIGNING_PRIVATE_KEY: string;
|
|
32
33
|
MANIFEST_SIGNING_KEY_ID: string;
|
|
33
34
|
MANIFEST_SIGNING_PUBLIC_KEY: string;
|
|
35
|
+
EXPORT_ENCRYPTION_PRIVATE_KEY: string;
|
|
36
|
+
EXPORT_ENCRYPTION_KEY_ID: string;
|
|
37
|
+
EXPORT_ENCRYPTION_PUBLIC_KEY: string;
|
|
38
|
+
DATA_AT_REST_ENCRYPTION_ENABLED: string;
|
|
39
|
+
DATA_AT_REST_ENCRYPTION_PRIVATE_KEY: string;
|
|
40
|
+
DATA_AT_REST_ENCRYPTION_KEY_ID: string;
|
|
41
|
+
DATA_AT_REST_ENCRYPTION_PUBLIC_KEY: string;
|
|
34
42
|
AUDIT_WORKER_NAME: string;
|
|
35
43
|
AUDIT_BUCKET_NAME: string;
|
|
36
44
|
AUDIT_WORKER_DOMAIN: string;
|
|
37
45
|
IMAGES_WORKER_NAME: string;
|
|
38
46
|
IMAGES_WORKER_DOMAIN: string;
|
|
39
|
-
API_TOKEN: string;
|
|
40
|
-
HMAC_KEY: string;
|
|
41
47
|
PDF_WORKER_NAME: string;
|
|
42
48
|
PDF_WORKER_DOMAIN: string;
|
|
43
49
|
PDF_WORKER_AUTH: string;
|
|
@@ -50,7 +56,7 @@ type StringifyValues<EnvType extends Record<string, unknown>> = {
|
|
|
50
56
|
[Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string;
|
|
51
57
|
};
|
|
52
58
|
declare namespace NodeJS {
|
|
53
|
-
interface ProcessEnv extends StringifyValues<Pick<Cloudflare.Env, "ACCOUNT_ID" | "USER_DB_AUTH" | "R2_KEY_SECRET" | "IMAGES_API_TOKEN" | "API_KEY" | "AUTH_DOMAIN" | "PROJECT_ID" | "STORAGE_BUCKET" | "MESSAGING_SENDER_ID" | "APP_ID" | "MEASUREMENT_ID" | "FIREBASE_SERVICE_ACCOUNT_EMAIL" | "FIREBASE_SERVICE_ACCOUNT_PRIVATE_KEY" | "PAGES_PROJECT_NAME" | "PAGES_CUSTOM_DOMAIN" | "KEYS_WORKER_NAME" | "KEYS_WORKER_DOMAIN" | "KEYS_AUTH" | "ACCOUNT_HASH" | "USER_WORKER_NAME" | "USER_WORKER_DOMAIN" | "KV_STORE_ID" | "DATA_WORKER_NAME" | "DATA_BUCKET_NAME" | "DATA_WORKER_DOMAIN" | "MANIFEST_SIGNING_PRIVATE_KEY" | "MANIFEST_SIGNING_KEY_ID" | "MANIFEST_SIGNING_PUBLIC_KEY" | "
|
|
59
|
+
interface ProcessEnv extends StringifyValues<Pick<Cloudflare.Env, "ACCOUNT_ID" | "USER_DB_AUTH" | "R2_KEY_SECRET" | "IMAGES_API_TOKEN" | "API_KEY" | "AUTH_DOMAIN" | "PROJECT_ID" | "STORAGE_BUCKET" | "MESSAGING_SENDER_ID" | "APP_ID" | "MEASUREMENT_ID" | "FIREBASE_SERVICE_ACCOUNT_EMAIL" | "FIREBASE_SERVICE_ACCOUNT_PRIVATE_KEY" | "PAGES_PROJECT_NAME" | "PAGES_CUSTOM_DOMAIN" | "KEYS_WORKER_NAME" | "KEYS_WORKER_DOMAIN" | "KEYS_AUTH" | "ACCOUNT_HASH" | "USER_WORKER_NAME" | "USER_WORKER_DOMAIN" | "KV_STORE_ID" | "DATA_WORKER_NAME" | "DATA_BUCKET_NAME" | "FILES_BUCKET_NAME" | "DATA_WORKER_DOMAIN" | "MANIFEST_SIGNING_PRIVATE_KEY" | "MANIFEST_SIGNING_KEY_ID" | "MANIFEST_SIGNING_PUBLIC_KEY" | "EXPORT_ENCRYPTION_PRIVATE_KEY" | "EXPORT_ENCRYPTION_KEY_ID" | "EXPORT_ENCRYPTION_PUBLIC_KEY" | "DATA_AT_REST_ENCRYPTION_ENABLED" | "DATA_AT_REST_ENCRYPTION_PRIVATE_KEY" | "DATA_AT_REST_ENCRYPTION_KEY_ID" | "DATA_AT_REST_ENCRYPTION_PUBLIC_KEY" | "AUDIT_WORKER_NAME" | "AUDIT_BUCKET_NAME" | "AUDIT_WORKER_DOMAIN" | "IMAGES_WORKER_NAME" | "IMAGES_WORKER_DOMAIN" | "PDF_WORKER_NAME" | "PDF_WORKER_DOMAIN" | "PDF_WORKER_AUTH" | "BROWSER_API_TOKEN" | "PRIMERSHEAR_EMAILS">> {}
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
// Begin runtime types
|
|
@@ -5485,7 +5491,7 @@ type AIGatewayHeaders = {
|
|
|
5485
5491
|
[key: string]: string | number | boolean | object;
|
|
5486
5492
|
};
|
|
5487
5493
|
type AIGatewayUniversalRequest = {
|
|
5488
|
-
provider: AIGatewayProviders | string;
|
|
5494
|
+
provider: AIGatewayProviders | string; // eslint-disable-line
|
|
5489
5495
|
endpoint: string;
|
|
5490
5496
|
headers: Partial<AIGatewayHeaders>;
|
|
5491
5497
|
query: unknown;
|
|
@@ -5501,7 +5507,7 @@ declare abstract class AiGateway {
|
|
|
5501
5507
|
gateway?: UniversalGatewayOptions;
|
|
5502
5508
|
extraHeaders?: object;
|
|
5503
5509
|
}): Promise<Response>;
|
|
5504
|
-
getUrl(provider?: AIGatewayProviders | string): Promise<string>;
|
|
5510
|
+
getUrl(provider?: AIGatewayProviders | string): Promise<string>; // eslint-disable-line
|
|
5505
5511
|
}
|
|
5506
5512
|
interface AutoRAGInternalError extends Error {
|
|
5507
5513
|
}
|
|
@@ -5,13 +5,10 @@
|
|
|
5
5
|
"scripts": {
|
|
6
6
|
"deploy": "wrangler deploy",
|
|
7
7
|
"dev": "wrangler dev",
|
|
8
|
-
"start": "wrangler dev"
|
|
9
|
-
"test": "vitest"
|
|
8
|
+
"start": "wrangler dev"
|
|
10
9
|
},
|
|
11
10
|
"devDependencies": {
|
|
12
11
|
"@cloudflare/puppeteer": "^1.0.6",
|
|
13
|
-
"@cloudflare/vitest-pool-workers": "^0.13.0",
|
|
14
|
-
"vitest": "~4.1.0",
|
|
15
12
|
"wrangler": "^4.76.0"
|
|
16
13
|
},
|
|
17
14
|
"overrides": {
|