@voltro/plugin-storage 0.85.0 → 0.86.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/dist/index.js CHANGED
@@ -1,2700 +1,42 @@
1
- import { StorageAccessDenied as e, StorageError as t, StorageRejected as n, StorageScanRejected as r, StorageService as i } from "./types.js";
2
- import { abortMultipartUploadDescriptor as a, beginMultipartUploadDescriptor as o, beginResumableUploadDescriptor as s, completeMultipartUploadDescriptor as c, finalizeUploadDescriptor as l, ingestUrlDescriptor as u, listGrantsDescriptor as d, listRefsDescriptor as f, mintPresignedUploadDescriptor as p, mintUploadTicketDescriptor as m, mintUploadUrlDescriptor as ee, mintUrlDescriptor as te, revokeDescriptor as ne, shareDescriptor as h, signMultipartPartDescriptor as g, storageRpcClientImports as _, uploadDescriptor as re } from "./rpc.js";
3
- import { processIdentity as ie } from "@voltro/protocol/identity";
4
- import { Effect as v, Exit as y, Layer as b, Schedule as x, Schema as S, Stream as C } from "effect";
5
- import { StorageAccessPolicySchema as ae, definePlugin as oe, pluginInstanceName as w } from "@voltro/protocol";
6
- import { readCookie as se, resolveSessionSecret as ce, verifySession as le } from "@voltro/protocol/session";
7
- import { and as ue, authoredError as T, bigint as E, bytes as D, causeBranches as O, column as de, contains as fe, eq as k, extractDbCause as pe, generateId as A, id as j, integer as M, isNull as me, isTransientContention as he, json as ge, mixin as _e, neq as ve, or as N, reference as ye, table as P, text as F, timestamp as be, wireSafeCause as xe } from "@voltro/database";
8
- import { pluginEnv as Se } from "@voltro/env";
9
- import { createHash as Ce, createHmac as I, randomBytes as we, randomUUID as Te, scryptSync as Ee, timingSafeEqual as L } from "node:crypto";
10
- import { ssrfReason as De } from "@voltro/runtime";
11
- import { spawn as Oe } from "node:child_process";
12
- import { mkdtemp as R, readFile as z, rm as ke, writeFile as Ae } from "node:fs/promises";
13
- import { tmpdir as je } from "node:os";
14
- import { join as Me } from "node:path";
15
- import { statSync as Ne } from "node:fs";
16
- //#region src/streamBridge.ts
17
- var Pe = 1 << 20, Fe = (e, n, r = !1) => new t({
18
- provider: e,
19
- message: n,
20
- transient: r
21
- }), Ie = (e) => {
22
- let t = 0;
23
- for (let n of e) t += n.byteLength;
24
- let n = new Uint8Array(t), r = 0;
25
- for (let t of e) n.set(t, r), r += t.byteLength;
26
- return n;
27
- }, Le = (e, t = Pe) => {
28
- let n = [];
29
- for (let r = 0; r < e.byteLength; r += t) n.push(e.subarray(r, Math.min(r + t, e.byteLength)));
30
- return C.fromIterable(n);
31
- }, Re = (e) => e.pipe(C.runCollect, v.map((e) => Ie(e))), ze = (e, t) => C.suspend(() => C.fromAsyncIterable(t(), (t) => Fe(e, `read stream failed: ${String(t?.message ?? t)}`, !0))).pipe(C.map((e) => e instanceof Uint8Array ? e : new Uint8Array(e))), Be = async (e) => {
32
- let { Readable: t } = await import("node:stream");
33
- return t.fromWeb(C.toReadableStream(e));
34
- }, Ve = (e, t) => e.getStream ? e.getStream(t) : e.get(t).pipe(v.map((e) => ({
35
- stream: Le(e.bytes),
36
- contentType: e.contentType,
37
- size: e.bytes.byteLength
38
- }))), He = (e, t, n, r) => e.putStream ? e.putStream(t, n, r) : Re(n).pipe(v.flatMap((n) => e.put(t, n, {
39
- contentType: r.contentType,
40
- ...r.public === void 0 ? {} : { public: r.public }
41
- }))), B = "_voltro_storage_refs", V = "_voltro_storage_grants", H = "_voltro_storage_blobs", Ue = "_voltro_storage_usage", We = P(B, {
42
- id: j({ prefix: "file" }),
43
- tenantId: F().nullable(),
44
- ownerId: F().nullable(),
45
- bucket: F(),
46
- key: F(),
47
- contentType: F(),
48
- size: E(),
49
- checksum: F(),
50
- visibility: F(),
51
- accessPolicy: ge().nullable(),
52
- passwordHash: F().nullable(),
53
- width: M().nullable(),
54
- height: M().nullable(),
55
- duration: M().nullable(),
56
- placeholder: F().nullable(),
57
- folder: F().nullable(),
58
- tags: ge().nullable(),
59
- alt: F().nullable(),
60
- caption: F().nullable(),
61
- derivedFrom: F().nullable(),
62
- kind: F().nullable(),
63
- createdAt: be()
64
- }).index(["key"]).index(["tenantId"]).index(["ownerId"]).index(["folder"]).index(["derivedFrom"]), Ge = P(V, {
65
- id: j({ prefix: "sgrant" }),
66
- refId: F(),
67
- principalType: F(),
68
- principalId: F(),
69
- permission: F(),
70
- createdAt: be(),
71
- expiresAt: be().nullable(),
72
- createdBy: F().nullable()
73
- }).index(["refId"]).index(["principalId"]), Ke = P(Ue, {
74
- id: j({ prefix: "susage" }),
75
- tenantId: F().maxLength(191),
76
- bytes: E().default("0"),
77
- count: E().default("0"),
78
- updatedAt: be()
79
- }).unique("byStorageUsageTenant", ["tenantId"]), qe = P(H, {
80
- id: j({ prefix: "blob" }),
81
- key: F(),
82
- data: D(),
83
- contentType: F(),
84
- size: E()
85
- }).index(["key"]), U = Se([
86
- {
87
- name: "STORAGE_PROVIDER",
88
- required: !1,
89
- secret: !1,
90
- description: "Provider name: 's3' | 'minio' | 'azure' | 'database' | 'filesystem' | 'memory'. Default 'memory'."
91
- },
92
- {
93
- name: "S3_BUCKET",
94
- required: !1,
95
- secret: !1,
96
- description: "S3/MinIO bucket name. Default STORAGE_BUCKET, else \"voltro\"."
97
- },
98
- {
99
- name: "STORAGE_BUCKET",
100
- required: !1,
101
- secret: !1,
102
- description: "Fallback bucket name when S3_BUCKET is unset."
103
- },
104
- {
105
- name: "S3_REGION",
106
- required: !1,
107
- secret: !1,
108
- description: "S3 region. Falls back to AWS_REGION."
109
- },
110
- {
111
- name: "AWS_REGION",
112
- required: !1,
113
- secret: !1,
114
- description: "AWS region fallback for the S3 provider."
115
- },
116
- {
117
- name: "S3_ENDPOINT",
118
- required: !1,
119
- secret: !1,
120
- description: "Custom S3 endpoint URL. Falls back to MINIO_ENDPOINT."
121
- },
122
- {
123
- name: "MINIO_ENDPOINT",
124
- required: !1,
125
- secret: !1,
126
- description: "MinIO endpoint URL fallback for the S3 provider."
127
- },
128
- {
129
- name: "S3_ACCESS_KEY_ID",
130
- required: !1,
131
- secret: !0,
132
- description: "S3 access key id. Falls back to AWS_ACCESS_KEY_ID."
133
- },
134
- {
135
- name: "AWS_ACCESS_KEY_ID",
136
- required: !1,
137
- secret: !0,
138
- description: "AWS access key id fallback for the S3 provider."
139
- },
140
- {
141
- name: "S3_SECRET_ACCESS_KEY",
142
- required: !1,
143
- secret: !0,
144
- description: "S3 secret access key. Falls back to AWS_SECRET_ACCESS_KEY."
145
- },
146
- {
147
- name: "AWS_SECRET_ACCESS_KEY",
148
- required: !1,
149
- secret: !0,
150
- description: "AWS secret access key fallback for the S3 provider."
151
- },
152
- {
153
- name: "S3_FORCE_PATH_STYLE",
154
- required: !1,
155
- secret: !1,
156
- description: "Set to \"1\" to force path-style S3 addressing."
157
- },
158
- {
159
- name: "STORAGE_CDN_URL",
160
- required: !1,
161
- secret: !1,
162
- description: "Public base URL (CDN) served in front of the bucket for public objects."
163
- },
164
- {
165
- name: "VOLTRO_PUBLIC_URL",
166
- required: !1,
167
- secret: !1,
168
- description: "Absolute public base URL of THIS api (scheme://host[:port]) — prepended to the /_voltro/storage/:id serve URL so getUrl/mintUrl/the upload route emit ABSOLUTE URLs. Required when the api is a different origin than the app."
169
- },
170
- {
171
- name: "STORAGE_ALLOWED_ORIGINS",
172
- required: !1,
173
- secret: !1,
174
- description: "Comma-separated origins allowed to read the serve route + POST the upload route cross-origin (CORS). Use '*' for any. Omit for same-origin only."
175
- },
176
- {
177
- name: "AZURE_STORAGE_ACCOUNT",
178
- required: !1,
179
- secret: !1,
180
- description: "Azure storage account name (provider \"azure\")."
181
- },
182
- {
183
- name: "AZURE_STORAGE_KEY",
184
- required: !1,
185
- secret: !0,
186
- description: "Azure account key — needed to mint SAS URLs."
187
- },
188
- {
189
- name: "AZURE_STORAGE_CONNECTION_STRING",
190
- required: !1,
191
- secret: !0,
192
- description: "Azure connection string (carries the account key)."
193
- },
194
- {
195
- name: "AZURE_STORAGE_ENDPOINT",
196
- required: !1,
197
- secret: !1,
198
- description: "Custom Azure blob endpoint (e.g. Azurite)."
199
- },
200
- {
201
- name: "AZURE_STORAGE_CONTAINER",
202
- required: !1,
203
- secret: !1,
204
- description: "Azure blob container name (the \"bucket\")."
205
- },
206
- {
207
- name: "STORAGE_ROOT",
208
- required: !1,
209
- secret: !1,
210
- description: "Filesystem provider root directory. Default \".voltro-storage\"."
211
- },
212
- {
213
- name: "VOLTRO_STORAGE_SECRET",
214
- required: !1,
215
- secret: !0,
216
- description: "HMAC secret for signed grant tokens. Falls back to the session secret."
217
- },
218
- {
219
- name: "VOLTRO_SESSION_COOKIE",
220
- required: !1,
221
- secret: !1,
222
- description: "Session cookie name used to resolve private-object access. Default \"voltro:session\"."
223
- },
224
- {
225
- name: "CLAMAV_HOST",
226
- required: !1,
227
- secret: !1,
228
- description: "clamd host for the optional clamav virus scanner. Default 127.0.0.1."
229
- },
230
- {
231
- name: "CLAMAV_PORT",
232
- required: !1,
233
- secret: !1,
234
- description: "clamd port for the optional clamav virus scanner. Default 3310."
235
- }
236
- ]), W = (e, n) => {
237
- let r = typeof e == "number" ? e : typeof e == "bigint" || typeof e == "string" && /^\d+$/.test(e) ? Number(e) : NaN;
238
- if (!Number.isSafeInteger(r) || r < 0) throw new t({
239
- provider: "metadata",
240
- message: `Storage ${n} must be a non-negative safe integer at most Number.MAX_SAFE_INTEGER`,
241
- transient: !1
242
- });
243
- return r;
244
- }, Je = (e, t, n) => W(e + t, n), G = (e, n, r = !1) => {
245
- let i = O(e).find(S.is(t));
246
- if (i !== void 0) return i;
247
- let a = pe(e), o = a.dbCode === "22003" || a.dbSqlState === "22003" || a.dbCode === "ER_WARN_DATA_OUT_OF_RANGE" || a.dbErrno === 1264 || a.dbNumber === 8115 || a.dbNumber === 248, s = new t({
248
- provider: n,
249
- message: `${o ? "Storage metadata numeric value out of range: " : ""}${xe(e)}`,
250
- transient: o ? !1 : he(e) || r
251
- });
252
- return Object.defineProperty(s, "cause", {
253
- value: e,
254
- configurable: !0
255
- }), s;
256
- }, Ye = (e) => O(e).find(S.is(n)), K = (e, n, r, i) => new t({
257
- provider: e,
258
- message: n,
259
- transient: r,
260
- ...i === void 0 ? {} : { status: i }
261
- }), Xe = (e) => e === void 0 || e === 408 || e === 429 || e >= 500, Ze = /* @__PURE__ */ new Map(), Qe = (e, t) => Ze.get(e)?.get(t)?.bytes, $e = (e) => {
262
- Ze.get(e)?.clear();
263
- }, et = (e = "default") => {
264
- let t = Ze.get(e) ?? /* @__PURE__ */ new Map();
265
- return Ze.set(e, t), {
266
- name: "memory",
267
- presigns: !1,
268
- put: (e, n, r) => v.sync(() => (t.set(e, {
269
- bytes: n,
270
- contentType: r.contentType
271
- }), { size: n.byteLength })),
272
- get: (e) => v.suspend(() => {
273
- let n = t.get(e);
274
- return n ? v.succeed({
275
- bytes: n.bytes,
276
- contentType: n.contentType
277
- }) : v.fail(K("memory", `no object at key '${e}'`, !1, 404));
278
- }),
279
- delete: (e) => v.sync(() => {
280
- t.delete(e);
281
- }),
282
- publicUrl: () => null,
283
- getUrl: () => v.succeed(""),
284
- head: (e) => v.sync(() => {
285
- let n = t.get(e);
286
- return n ? { size: n.bytes.byteLength } : null;
287
- })
288
- };
289
- }, tt = (e) => {
290
- let t = e.root, n = async (e) => {
291
- let { join: n, resolve: r, sep: i } = await import("node:path"), a = r(t), o = r(a, e);
292
- if (o !== a && !o.startsWith(a + i)) throw Error(`key '${e}' escapes the storage root`);
293
- return n(o);
294
- }, r = (e, t, n = !1) => v.tryPromise({
295
- try: e,
296
- catch: (e) => e?.code === "ENOENT" ? K("filesystem", `no object at key '${t}'`, !1, 404) : K("filesystem", String(e?.message ?? e), n)
297
- });
298
- return {
299
- root: t,
300
- name: "filesystem",
301
- presigns: !1,
302
- put: (e, t, i) => r(async () => {
303
- let r = await import("node:fs/promises"), { dirname: i } = await import("node:path"), { randomUUID: a } = await import("node:crypto"), o = await n(e), s = i(o);
304
- await r.mkdir(s, { recursive: !0 });
305
- let c = `${o}.tmp-${a()}`;
306
- try {
307
- await r.writeFile(c, t), await r.rename(c, o);
308
- } catch (e) {
309
- throw await r.rm(c, { force: !0 }).catch(() => {}), e;
310
- }
311
- return { size: t.byteLength };
312
- }, e, !0),
313
- get: (e) => r(async () => {
314
- let t = await (await import("node:fs/promises")).readFile(await n(e));
315
- return {
316
- bytes: new Uint8Array(t),
317
- contentType: "application/octet-stream"
318
- };
319
- }, e),
320
- delete: (e) => r(async () => {
321
- await (await import("node:fs/promises")).rm(await n(e), { force: !0 });
322
- }, e),
323
- publicUrl: () => null,
324
- getUrl: () => v.succeed(""),
325
- head: (e) => v.tryPromise({
326
- try: async () => {
327
- let t = await import("node:fs/promises");
328
- try {
329
- return { size: (await t.stat(await n(e))).size };
330
- } catch (e) {
331
- if (e?.code === "ENOENT") return null;
332
- throw e;
333
- }
334
- },
335
- catch: (e) => K("filesystem", String(e?.message ?? e), !1)
336
- }),
337
- getStream: (e) => r(async () => {
338
- let t = await import("node:fs/promises"), { createReadStream: r } = await import("node:fs"), i = await n(e), a = await t.stat(i);
339
- return {
340
- stream: ze("filesystem", () => r(i)),
341
- contentType: "application/octet-stream",
342
- size: a.size
343
- };
344
- }, e),
345
- putStream: (e, t, i) => r(async () => {
346
- let r = await import("node:fs/promises"), { dirname: i } = await import("node:path"), { randomUUID: a } = await import("node:crypto"), { createWriteStream: o } = await import("node:fs"), { pipeline: s } = await import("node:stream/promises"), c = await n(e);
347
- await r.mkdir(i(c), { recursive: !0 });
348
- let l = `${c}.tmp-${a()}`;
349
- try {
350
- await s(await Be(t), o(l));
351
- let e = await r.stat(l);
352
- return await r.rename(l, c), { size: e.size };
353
- } catch (e) {
354
- throw await r.rm(l, { force: !0 }).catch(() => {}), e;
355
- }
356
- }, e, !0),
357
- getRange: (e, t, i) => r(async () => {
358
- let { createReadStream: r } = await import("node:fs"), a = await n(e), o = [];
359
- return await new Promise((e, n) => {
360
- let s = r(a, {
361
- start: t,
362
- end: i
363
- });
364
- s.on("data", (e) => o.push(e)), s.on("end", () => e()), s.on("error", n);
365
- }), Ie(o);
366
- }, e)
367
- };
368
- }, nt = (e) => {
369
- let t = e.name ?? "s3", n = e.publicAcl ?? !0, r = null, i = () => r || (r = (async () => {
370
- let t, n;
371
- try {
372
- t = await import("@aws-sdk/client-s3"), n = await import("@aws-sdk/s3-request-presigner");
373
- } catch (e) {
374
- throw Error("the 's3'/'minio' storage provider requires the '@aws-sdk/client-s3' + '@aws-sdk/s3-request-presigner' optional dependencies. Install them to enable it.", { cause: e });
375
- }
376
- return {
377
- client: new t.S3Client({
378
- ...e.region ? { region: e.region } : { region: "us-east-1" },
379
- ...e.endpoint ? { endpoint: e.endpoint } : {},
380
- ...e.forcePathStyle ? { forcePathStyle: !0 } : {},
381
- ...e.accessKeyId && e.secretAccessKey ? { credentials: {
382
- accessKeyId: e.accessKeyId,
383
- secretAccessKey: e.secretAccessKey
384
- } } : {}
385
- }),
386
- cmds: t,
387
- presign: n.getSignedUrl
388
- };
389
- })(), r), a = (e) => v.tryPromise({
390
- try: e,
391
- catch: (e) => {
392
- let n = e?.$metadata?.httpStatusCode;
393
- return K(t, String(e?.message ?? e), Xe(n), n);
394
- }
395
- }), o = async (e) => {
396
- let t = e;
397
- if (typeof t.transformToByteArray == "function") return t.transformToByteArray();
398
- let n = [];
399
- for await (let e of t) n.push(e);
400
- let r = n.reduce((e, t) => e + t.byteLength, 0), i = new Uint8Array(r), a = 0;
401
- for (let e of n) i.set(e, a), a += e.byteLength;
402
- return i;
403
- };
404
- return {
405
- name: t,
406
- presigns: !0,
407
- put: (t, r, o) => a(async () => {
408
- let { client: a, cmds: s } = await i();
409
- return await a.send(new s.PutObjectCommand({
410
- Bucket: e.bucket,
411
- Key: t,
412
- Body: r,
413
- ContentType: o.contentType,
414
- ...o.public && n ? { ACL: "public-read" } : {}
415
- })), { size: r.byteLength };
416
- }),
417
- get: (t) => a(async () => {
418
- let { client: n, cmds: r } = await i(), a = await n.send(new r.GetObjectCommand({
419
- Bucket: e.bucket,
420
- Key: t
421
- }));
422
- return {
423
- bytes: await o(a.Body),
424
- contentType: a.ContentType ?? "application/octet-stream"
425
- };
426
- }),
427
- delete: (t) => a(async () => {
428
- let { client: n, cmds: r } = await i();
429
- await n.send(new r.DeleteObjectCommand({
430
- Bucket: e.bucket,
431
- Key: t
432
- }));
433
- }),
434
- publicUrl: (t) => e.cdnBaseUrl ? `${e.cdnBaseUrl.replace(/\/$/, "")}/${t}` : null,
435
- ...n ? { setObjectPublic: (t, n) => a(async () => {
436
- let { client: r, cmds: a } = await i();
437
- await r.send(new a.PutObjectAclCommand({
438
- Bucket: e.bucket,
439
- Key: t,
440
- ACL: n ? "public-read" : "private"
441
- }));
442
- }) } : {},
443
- getUrl: (t, n) => a(async () => {
444
- let { client: r, cmds: a, presign: o } = await i();
445
- return o(r, new a.GetObjectCommand({
446
- Bucket: e.bucket,
447
- Key: t
448
- }), { expiresIn: n });
449
- }),
450
- getUploadUrl: (t, n, r) => a(async () => {
451
- let { client: a, cmds: o, presign: s } = await i();
452
- return s(a, new o.PutObjectCommand({
453
- Bucket: e.bucket,
454
- Key: t,
455
- ContentType: r
456
- }), { expiresIn: n });
457
- }),
458
- createMultipartUpload: (t, r, o) => a(async () => {
459
- let { client: a, cmds: s } = await i(), c = await a.send(new s.CreateMultipartUploadCommand({
460
- Bucket: e.bucket,
461
- Key: t,
462
- ContentType: r,
463
- ...o?.public && n ? { ACL: "public-read" } : {}
464
- }));
465
- if (!c.UploadId) throw Error("s3 createMultipartUpload returned no UploadId");
466
- return { uploadId: c.UploadId };
467
- }),
468
- presignUploadPart: (t, n, r, o) => a(async () => {
469
- let { client: a, cmds: s, presign: c } = await i();
470
- return c(a, new s.UploadPartCommand({
471
- Bucket: e.bucket,
472
- Key: t,
473
- UploadId: n,
474
- PartNumber: r
475
- }), { expiresIn: o });
476
- }),
477
- completeMultipartUpload: (t, n, r) => a(async () => {
478
- let { client: a, cmds: o } = await i(), s = await a.send(new o.CompleteMultipartUploadCommand({
479
- Bucket: e.bucket,
480
- Key: t,
481
- UploadId: n,
482
- MultipartUpload: { Parts: r.map((e) => ({
483
- PartNumber: e.partNumber,
484
- ETag: e.etag
485
- })) }
486
- }));
487
- return s.ETag === void 0 ? {} : { etag: s.ETag };
488
- }),
489
- abortMultipartUpload: (t, n) => a(async () => {
490
- let { client: r, cmds: a } = await i();
491
- await r.send(new a.AbortMultipartUploadCommand({
492
- Bucket: e.bucket,
493
- Key: t,
494
- UploadId: n
495
- }));
496
- }),
497
- head: (n) => v.tryPromise({
498
- try: async () => {
499
- let { client: t, cmds: r } = await i();
500
- try {
501
- let i = await t.send(new r.HeadObjectCommand({
502
- Bucket: e.bucket,
503
- Key: n
504
- }));
505
- return {
506
- size: i.ContentLength ?? 0,
507
- ...i.ETag === void 0 ? {} : { etag: i.ETag }
508
- };
509
- } catch (e) {
510
- if (e?.$metadata?.httpStatusCode === 404) return null;
511
- throw e;
512
- }
513
- },
514
- catch: (e) => {
515
- let n = e?.$metadata?.httpStatusCode;
516
- return K(t, String(e?.message ?? e), Xe(n), n);
517
- }
518
- }),
519
- getStream: (n) => a(async () => {
520
- let { client: r, cmds: a } = await i(), o = await r.send(new a.GetObjectCommand({
521
- Bucket: e.bucket,
522
- Key: n
523
- })), s = o.Body;
524
- return {
525
- stream: ze(t, () => s),
526
- contentType: o.ContentType ?? "application/octet-stream",
527
- ...o.ContentLength === void 0 ? {} : { size: o.ContentLength }
528
- };
529
- }),
530
- putStream: (t, r, o) => a(async () => {
531
- let { client: a, cmds: s } = await i(), c;
532
- try {
533
- c = await import("@aws-sdk/lib-storage");
534
- } catch (e) {
535
- throw Error("s3/minio `putStream` requires the '@aws-sdk/lib-storage' optional dependency (multipart upload). Install it to enable streamed uploads.", { cause: e });
536
- }
537
- let l = await Be(r);
538
- return await new c.Upload({
539
- client: a,
540
- params: {
541
- Bucket: e.bucket,
542
- Key: t,
543
- Body: l,
544
- ContentType: o.contentType,
545
- ...o.public && n ? { ACL: "public-read" } : {}
546
- }
547
- }).done(), { size: o.totalSize ?? (await a.send(new s.HeadObjectCommand({
548
- Bucket: e.bucket,
549
- Key: t
550
- }))).ContentLength ?? 0 };
551
- }),
552
- getRange: (t, n, r) => a(async () => {
553
- let { client: a, cmds: s } = await i(), c = await a.send(new s.GetObjectCommand({
554
- Bucket: e.bucket,
555
- Key: t,
556
- Range: `bytes=${n}-${r}`
557
- }));
558
- return o(c.Body);
559
- })
560
- };
561
- }, rt = (e) => e instanceof Uint8Array ? e : typeof e == "string" ? new Uint8Array(Buffer.from(e, "base64")) : new Uint8Array(e), it = () => {
562
- let e = null, t = () => {
563
- if (!e) throw T("the 'database' storage provider isn't bound to a DataStore yet");
564
- return e;
565
- }, n = (e) => v.tryPromise({
566
- try: e,
567
- catch: (e) => G(e, "database", !0)
568
- }), r = async (e, n) => (await t().query({
569
- table: H,
570
- predicate: {
571
- column: "key",
572
- op: "eq",
573
- value: e
574
- },
575
- order: [],
576
- take: 1,
577
- skip: void 0,
578
- projection: n
579
- }))[0];
580
- return {
581
- name: "database",
582
- presigns: !1,
583
- bindDataStore: (t) => {
584
- e = t;
585
- },
586
- put: (e, i, a) => n(async () => {
587
- let n = await r(e);
588
- return n ? await t().update(H, String(n.id), {
589
- data: i,
590
- contentType: a.contentType,
591
- size: String(i.byteLength)
592
- }) : await t().insert(H, {
593
- id: A({
594
- kind: "typeid",
595
- prefix: "blob"
596
- }, H),
597
- key: e,
598
- data: i,
599
- contentType: a.contentType,
600
- size: String(i.byteLength)
601
- }), { size: i.byteLength };
602
- }),
603
- get: (e) => v.suspend(() => n(() => r(e)).pipe(v.flatMap((t) => t ? v.succeed({
604
- bytes: rt(t.data),
605
- contentType: String(t.contentType)
606
- }) : v.fail(K("database", `no object at key '${e}'`, !1, 404))))),
607
- delete: (e) => n(async () => {
608
- let n = await r(e, ["id"]);
609
- n && await t().delete(H, String(n.id));
610
- }),
611
- publicUrl: () => null,
612
- getUrl: () => v.succeed(""),
613
- head: (e) => n(async () => {
614
- let t = await r(e, ["size"]);
615
- return t ? { size: W(t.size, "blob size") } : null;
616
- })
617
- };
618
- }, at = (e) => {
619
- let t = null, n = () => t || (t = (async () => {
620
- let t;
621
- try {
622
- t = await import("@azure/storage-blob");
623
- } catch (e) {
624
- throw Error("the 'azure' storage provider requires the '@azure/storage-blob' optional dependency. Install it to enable it.", { cause: e });
625
- }
626
- let n = U.read("AZURE_STORAGE_ACCOUNT", e.accountName), r = U.read("AZURE_STORAGE_KEY", e.accountKey), i = n && r ? new t.StorageSharedKeyCredential(n, r) : null, a = U.read("AZURE_STORAGE_CONNECTION_STRING", e.connectionString);
627
- return {
628
- container: (a ? t.BlobServiceClient.fromConnectionString(a) : new t.BlobServiceClient(e.endpoint ?? `https://${n}.blob.core.windows.net`, i ?? void 0)).getContainerClient(e.container),
629
- sdk: t,
630
- cred: i
631
- };
632
- })(), t), r = (e) => v.tryPromise({
633
- try: e,
634
- catch: (e) => {
635
- let t = e?.statusCode;
636
- return K("azure", String(e?.message ?? e), Xe(t), t);
637
- }
638
- }), i = async (e) => {
639
- if (!e) return /* @__PURE__ */ new Uint8Array();
640
- let t = [];
641
- for await (let n of e) t.push(typeof n == "string" ? new TextEncoder().encode(n) : new Uint8Array(n));
642
- let n = t.reduce((e, t) => e + t.byteLength, 0), r = new Uint8Array(n), i = 0;
643
- for (let e of t) r.set(e, i), i += e.byteLength;
644
- return r;
645
- }, a = async (t, r, i) => {
646
- let { container: a, sdk: o, cred: s } = await n();
647
- if (!s) throw Error("azure SAS requires accountName + accountKey (set them or AZURE_STORAGE_ACCOUNT/AZURE_STORAGE_KEY)");
648
- let c = a.getBlockBlobClient(t), l = o.generateBlobSASQueryParameters({
649
- containerName: e.container,
650
- blobName: t,
651
- permissions: o.BlobSASPermissions.parse(r),
652
- startsOn: /* @__PURE__ */ new Date(Date.now() - 6e4),
653
- expiresOn: new Date(Date.now() + i * 1e3)
654
- }, s).toString();
655
- return `${c.url}?${l}`;
656
- };
657
- return {
658
- name: "azure",
659
- presigns: !0,
660
- put: (e, t, i) => r(async () => {
661
- let { container: r } = await n();
662
- return await r.getBlockBlobClient(e).uploadData(Buffer.from(t), { blobHTTPHeaders: { blobContentType: i.contentType } }), { size: t.byteLength };
663
- }),
664
- get: (e) => r(async () => {
665
- let { container: t } = await n(), r = await t.getBlockBlobClient(e).download();
666
- return {
667
- bytes: await i(r.readableStreamBody),
668
- contentType: r.contentType ?? "application/octet-stream"
669
- };
670
- }),
671
- delete: (e) => r(async () => {
672
- let { container: t } = await n();
673
- await t.getBlockBlobClient(e).deleteIfExists();
674
- }),
675
- publicUrl: (t) => e.cdnBaseUrl ? `${e.cdnBaseUrl.replace(/\/$/, "")}/${t}` : null,
676
- getUrl: (e, t) => r(() => a(e, "r", t)),
677
- getUploadUrl: (e, t, n) => r(() => a(e, "cw", t)),
678
- head: (e) => v.tryPromise({
679
- try: async () => {
680
- let { container: t } = await n();
681
- try {
682
- let n = await t.getBlockBlobClient(e).getProperties();
683
- return {
684
- size: n.contentLength ?? 0,
685
- ...n.etag === void 0 ? {} : { etag: n.etag }
686
- };
687
- } catch (e) {
688
- if (e?.statusCode === 404) return null;
689
- throw e;
690
- }
691
- },
692
- catch: (e) => {
693
- let t = e?.statusCode;
694
- return K("azure", String(e?.message ?? e), Xe(t), t);
695
- }
696
- }),
697
- getStream: (e) => r(async () => {
698
- let { container: t } = await n(), r = await t.getBlockBlobClient(e).download();
699
- return {
700
- stream: ze("azure", () => r.readableStreamBody),
701
- contentType: r.contentType ?? "application/octet-stream",
702
- ...r.contentLength === void 0 ? {} : { size: r.contentLength }
703
- };
704
- }),
705
- putStream: (e, t, i) => r(async () => {
706
- let { container: r } = await n(), a = await Be(t);
707
- return await r.getBlockBlobClient(e).uploadStream(a, 4194304, 5, { blobHTTPHeaders: { blobContentType: i.contentType } }), { size: i.totalSize ?? (await r.getBlockBlobClient(e).getProperties()).contentLength ?? 0 };
708
- }),
709
- getRange: (e, t, a) => r(async () => {
710
- let { container: r } = await n(), o = await r.getBlockBlobClient(e).download(t, a - t + 1);
711
- return i(o.readableStreamBody);
712
- })
713
- };
714
- }, ot = (e = {
715
- entries: 200,
716
- bytes: 67108864,
717
- pending: 32
718
- }) => {
719
- let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = 0;
720
- return { getOrCreate: (i, a) => {
721
- let o = t.get(i);
722
- if (o) return Promise.resolve(o);
723
- let s = n.get(i);
724
- if (s) return s;
725
- if (n.size >= e.pending) return Promise.resolve(null);
726
- let c = Promise.resolve().then(a).then((n) => {
727
- if (n && e.entries > 0 && n.bytes.byteLength <= e.bytes) {
728
- for (; t.size >= e.entries || r + n.bytes.byteLength > e.bytes;) {
729
- let e = t.keys().next().value;
730
- if (e === void 0) break;
731
- r -= t.get(e).bytes.byteLength, t.delete(e);
732
- }
733
- t.set(i, n), r += n.bytes.byteLength;
734
- }
735
- return n;
736
- }).finally(() => {
737
- n.delete(i);
738
- });
739
- return n.set(i, c), c;
740
- } };
741
- }, st = (e, t, n, r, i, a) => {
742
- let o = n / r, s = Math.min(e, Math.round(t * o)), c = Math.min(t, Math.round(s / o)), l = (e, t) => Math.max(0, Math.min(t, e));
743
- return {
744
- left: l(Math.round(i * e - s / 2), e - s),
745
- top: l(Math.round(a * t - c / 2), t - c),
746
- width: s,
747
- height: c
748
- };
749
- }, ct = {
750
- webp: "image/webp",
751
- avif: "image/avif",
752
- jpeg: "image/jpeg",
753
- jpg: "image/jpeg",
754
- png: "image/png"
755
- }, lt = (e) => {
756
- if (!e) return null;
757
- let t = new URLSearchParams(e), n = (e) => {
758
- let n = t.get(e);
759
- if (n == null) return;
760
- let r = Number(n);
761
- return Number.isFinite(r) && r > 0 ? Math.floor(r) : void 0;
762
- }, r = n("w"), i = n("h"), a = n("q"), o = (t.get("format") ?? t.get("fm") ?? void 0)?.toLowerCase(), s = t.get("fit") ?? void 0, c = (t.get("fp") ?? "").split(",").map(Number), l = c.length === 2 && c.every((e) => Number.isFinite(e) && e >= 0 && e <= 1) ? {
763
- x: c[0],
764
- y: c[1]
765
- } : void 0;
766
- return r === void 0 && i === void 0 && !o && a === void 0 ? null : {
767
- ...r === void 0 ? {} : { w: r },
768
- ...i === void 0 ? {} : { h: i },
769
- ...o ? { format: o } : {},
770
- ...a === void 0 ? {} : { q: a },
771
- ...s ? { fit: s } : {},
772
- ...l ? { fp: l } : {}
773
- };
774
- }, ut = (e) => e.startsWith("image/") && !e.includes("svg"), dt, ft = async () => (dt ??= import("sharp").then((e) => e.default ?? e, () => null), dt), pt = async (e, t) => t ? null : ut(e) ? await ft() === null ? "no-sharp" : "failed" : "not-an-image", mt = async (e, t, n) => {
775
- if (!ut(t)) return null;
776
- let r = await ft();
777
- if (!r) return null;
778
- try {
779
- let i = r(Buffer.from(e), { failOn: "none" }), a = n.fit ?? "cover";
780
- if (n.fp !== void 0 && n.w !== void 0 && n.h !== void 0 && a === "cover") {
781
- let e = await i.metadata();
782
- e.width !== void 0 && e.height !== void 0 && (i = i.extract(st(e.width, e.height, n.w, n.h, n.fp.x, n.fp.y)));
783
- }
784
- (n.w !== void 0 || n.h !== void 0) && (i = i.resize({
785
- ...n.w === void 0 ? {} : { width: n.w },
786
- ...n.h === void 0 ? {} : { height: n.h },
787
- fit: n.fit ?? "cover",
788
- withoutEnlargement: !0
789
- }));
790
- let o = n.format && ct[n.format] ? n.format : void 0, s = t;
791
- if (o) {
792
- let e = o === "jpg" ? "jpeg" : o;
793
- i = i.toFormat(e, n.q === void 0 ? {} : { quality: n.q }), s = ct[o];
794
- } else n.q !== void 0 && (t === "image/jpeg" || t === "image/webp") && (i = i.toFormat(t === "image/webp" ? "webp" : "jpeg", { quality: n.q }));
795
- let c = await i.toBuffer();
796
- return {
797
- bytes: new Uint8Array(c),
798
- contentType: s
799
- };
800
- } catch {
801
- return null;
802
- }
803
- }, ht = async (e, t, n) => {
804
- if (!ut(t) || n.rotate === void 0 && n.flip !== !0 && n.flop !== !0 && n.grayscale !== !0 && n.crop === void 0) return null;
805
- let r = await ft();
806
- if (!r) return null;
807
- try {
808
- let i = r(Buffer.from(e), { failOn: "none" });
809
- return n.crop !== void 0 && (i = i.extract(n.crop)), n.rotate !== void 0 && (i = i.rotate(n.rotate)), n.flip === !0 && (i = i.flip()), n.flop === !0 && (i = i.flop()), n.grayscale === !0 && (i = i.grayscale()), {
810
- bytes: new Uint8Array(await i.toBuffer()),
811
- contentType: t
812
- };
813
- } catch {
814
- return null;
815
- }
816
- }, gt = ot(), _t = (e, t, n) => JSON.stringify([
817
- e,
818
- t,
819
- n.w,
820
- n.h,
821
- n.format,
822
- n.q,
823
- n.fit,
824
- n.fp?.x,
825
- n.fp?.y
826
- ]), vt = async (e, t, n, r) => gt.getOrCreate(_t(e, n, r), () => mt(t, n, r)), yt = (e) => {
827
- let t = we(16).toString("hex");
828
- return `${t}:${Ee(e, t, 32).toString("hex")}`;
829
- }, bt = (e, t) => {
830
- if (!e || !t) return !1;
831
- let [n, r] = t.split(":");
832
- if (!n || !r) return !1;
833
- let i = Buffer.from(r, "hex"), a = Ee(e, n, i.length);
834
- return a.length === i.length && L(a, i);
835
- }, xt = (e) => Array.isArray(e) ? e.filter((e) => typeof e == "string") : [], St = (e) => xt(e.metadata?.roles), Ct = (e) => xt(e.scopes), wt = (e, t) => e.some((e) => t.includes(e)), Tt = (e) => xt(e.metadata?.groups), Et = (e) => typeof e == "boolean" ? v.succeed(e) : v.isEffect(e) ? e : v.promise(() => e), Dt = (e, t, n = {}) => v.gen(function* () {
836
- if (t.id && e.ownerId && t.id === e.ownerId) return !0;
837
- let r = e.accessPolicy ?? [];
838
- if (r.length === 0) return !1;
839
- let i = n.resolveGroups ? yield* v.promise(async () => await n.resolveGroups(t)) : Tt(t);
840
- for (let a of r) if (yield* Ot(a, e, t, i, n)) return !0;
841
- return !1;
842
- }), Ot = (e, t, n, r, i) => v.gen(function* () {
843
- let a = !1, o = (e) => (a = !0, e);
844
- if (e.owner !== void 0 && e.owner && !o(!!n.id && !!t.ownerId && n.id === t.ownerId) || e.tenant !== void 0 && e.tenant && !o(!!n.tenantId && n.tenantId === t.tenantId) || e.apiKey !== void 0 && e.apiKey && !o(n.type === "apiKey") || e.roles && e.roles.length > 0 && !o(wt(St(n), e.roles)) || e.groups && e.groups.length > 0 && !o(wt(r, e.groups)) || e.scopes && e.scopes.length > 0 && !o(wt(Ct(n), e.scopes)) || e.password !== void 0 && e.password && !o(bt(i.password, t.passwordHash))) return !1;
845
- if (e.guard) {
846
- let r = i.guards?.[e.guard];
847
- if (!o(r ? yield* Et(r({
848
- subject: n,
849
- ref: t
850
- })) : !1)) return !1;
851
- }
852
- return a;
853
- }), kt = (e, t) => {
854
- let n = [];
855
- e.id && n.push({
856
- type: e.type === "apiKey" ? "apiKey" : "user",
857
- id: e.id
858
- });
859
- for (let e of t) n.push({
860
- type: "group",
861
- id: e
862
- });
863
- return n;
864
- }, At = (e, t, n, r, i) => {
865
- let a = kt(t, n);
866
- return e.some((e) => e.expiresAt && e.expiresAt.getTime() < i || r === "write" && e.permission !== "write" ? !1 : a.some((t) => t.type === e.principalType && t.id === e.principalId));
867
- }, jt = (e, t) => t.resolveGroups ? v.promise(async () => await t.resolveGroups(e)) : v.succeed(Tt(e)), q = () => U.read("VOLTRO_STORAGE_SECRET") ?? ce(), J = (e) => (typeof e == "string" ? Buffer.from(e, "utf8") : e).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""), Y = (e) => {
868
- let t = e.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - e.length % 4) % 4);
869
- return Buffer.from(t, "base64");
870
- }, Mt = (e, t, n = q(), r = "/_voltro/storage") => {
871
- if (!n) throw Error("signGrant: secret must be a non-empty string");
872
- let i = {
873
- refId: e,
874
- audience: r,
875
- exp: Math.floor(Date.now() / 1e3) + Math.floor(t)
876
- }, a = J(JSON.stringify(i));
877
- return `${a}.${J(I("sha256", n).update(a).digest())}`;
878
- }, Nt = (e, t = q()) => {
879
- if (!e || !t) return null;
880
- let n = e.indexOf(".");
881
- if (n <= 0 || n === e.length - 1) return null;
882
- let r = e.slice(0, n), i = e.slice(n + 1), a = I("sha256", t).update(r).digest(), o = Y(i);
883
- if (o.length !== a.length || !L(o, a)) return null;
884
- try {
885
- let e = JSON.parse(Y(r).toString("utf8"));
886
- return typeof e.audience != "string" || !e.audience || typeof e.refId != "string" || typeof e.exp != "number" || e.exp < Math.floor(Date.now() / 1e3) ? null : e;
887
- } catch {
888
- return null;
889
- }
890
- }, Pt = (e) => e.version === 1 ? e.access === void 0 || e.vis === "private" && y.isSuccess(S.decodeUnknownExit(ae, { onExcessProperty: "error" })(e.access)) : !1, Ft = (e, t, n = q()) => {
891
- if (!n) throw Error("signUploadTicket: secret must be a non-empty string");
892
- let r = {
893
- ...e,
894
- version: 1,
895
- exp: Math.floor(Date.now() / 1e3) + Math.floor(t)
896
- }, i = J(JSON.stringify(r));
897
- return `${i}.${J(I("sha256", n).update(`u:${i}`).digest())}`;
898
- }, It = (e, t = q()) => {
899
- if (!e || !t) return null;
900
- let n = e.indexOf(".");
901
- if (n <= 0 || n === e.length - 1) return null;
902
- let r = e.slice(0, n), i = e.slice(n + 1), a = I("sha256", t).update(`u:${r}`).digest(), o = Y(i);
903
- if (o.length !== a.length || !L(o, a)) return null;
904
- try {
905
- let e = JSON.parse(Y(r).toString("utf8"));
906
- return !Pt(e) || e.operationId !== void 0 && (typeof e.operationId != "string" || !e.operationId.trim() || e.operationId.length > 200) || typeof e.instance != "string" || !e.instance || typeof e.ct != "string" || typeof e.exp != "number" || e.vis !== "public" && e.vis !== "private" || e.replicaId !== void 0 && (typeof e.replicaId != "string" || !e.replicaId.trim()) || e.exp < Math.floor(Date.now() / 1e3) ? null : e;
907
- } catch {
908
- return null;
909
- }
910
- }, Lt = (e, t, n = q()) => {
911
- if (!n) throw Error("signFinalizeTicket: secret must be a non-empty string");
912
- let r = {
913
- ...e,
914
- version: 1,
915
- exp: Math.floor(Date.now() / 1e3) + Math.floor(t)
916
- }, i = J(JSON.stringify(r));
917
- return `${i}.${J(I("sha256", n).update(`f:${i}`).digest())}`;
918
- }, Rt = (e, t = q()) => {
919
- if (!e || !t) return null;
920
- let n = e.indexOf(".");
921
- if (n <= 0 || n === e.length - 1) return null;
922
- let r = e.slice(0, n), i = e.slice(n + 1), a = I("sha256", t).update(`f:${r}`).digest(), o = Y(i);
923
- if (o.length !== a.length || !L(o, a)) return null;
924
- try {
925
- let e = JSON.parse(Y(r).toString("utf8"));
926
- return !Pt(e) || typeof e.key != "string" || e.key.length === 0 || typeof e.instance != "string" || !e.instance || typeof e.ct != "string" || typeof e.exp != "number" || e.vis !== "public" && e.vis !== "private" || e.exp < Math.floor(Date.now() / 1e3) ? null : e;
927
- } catch {
928
- return null;
929
- }
930
- }, zt = (e, t, n = q()) => {
931
- if (!n) throw Error("signResumableTicket: secret must be a non-empty string");
932
- let r = {
933
- ...e,
934
- version: 1,
935
- exp: Math.floor(Date.now() / 1e3) + Math.floor(t)
936
- }, i = J(JSON.stringify(r));
937
- return `${i}.${J(I("sha256", n).update(`r:${i}`).digest())}`;
938
- }, Bt = (e, t = q()) => {
939
- if (!e || !t) return null;
940
- let n = e.indexOf(".");
941
- if (n <= 0 || n === e.length - 1) return null;
942
- let r = e.slice(0, n), i = e.slice(n + 1), a = I("sha256", t).update(`r:${r}`).digest(), o = Y(i);
943
- if (o.length !== a.length || !L(o, a)) return null;
944
- try {
945
- let e = JSON.parse(Y(r).toString("utf8"));
946
- return !Pt(e) || typeof e.id != "string" || e.id.length === 0 || typeof e.size != "number" || e.size < 0 || typeof e.instance != "string" || !e.instance || typeof e.ct != "string" || typeof e.exp != "number" || e.vis !== "public" && e.vis !== "private" || e.exp < Math.floor(Date.now() / 1e3) ? null : e;
947
- } catch {
948
- return null;
949
- }
950
- }, Vt = (e, t, n = q()) => {
951
- if (!n) throw Error("signMultipartTicket: secret must be a non-empty string");
952
- let r = {
953
- ...e,
954
- version: 1,
955
- exp: Math.floor(Date.now() / 1e3) + Math.floor(t)
956
- }, i = J(JSON.stringify(r));
957
- return `${i}.${J(I("sha256", n).update(`m:${i}`).digest())}`;
958
- }, Ht = (e, t = q()) => {
959
- if (!e || !t) return null;
960
- let n = e.indexOf(".");
961
- if (n <= 0 || n === e.length - 1) return null;
962
- let r = e.slice(0, n), i = e.slice(n + 1), a = I("sha256", t).update(`m:${r}`).digest(), o = Y(i);
963
- if (o.length !== a.length || !L(o, a)) return null;
964
- try {
965
- let e = JSON.parse(Y(r).toString("utf8"));
966
- return !Pt(e) || typeof e.key != "string" || e.key.length === 0 || typeof e.uploadId != "string" || e.uploadId.length === 0 || typeof e.instance != "string" || !e.instance || typeof e.ct != "string" || typeof e.exp != "number" || e.vis !== "public" && e.vis !== "private" || e.exp < Math.floor(Date.now() / 1e3) ? null : e;
967
- } catch {
968
- return null;
969
- }
970
- }, Ut = (e, t) => {
971
- if (!t || t.length === 0) return !0;
972
- let n = e.toLowerCase();
973
- return t.some((e) => {
974
- let t = e.toLowerCase();
975
- return t.endsWith("/*") ? n.startsWith(t.slice(0, -1)) : n === t;
976
- });
977
- }, Wt = [
978
- {
979
- ct: /^image\/png$/,
980
- offset: 0,
981
- magic: [
982
- 137,
983
- 80,
984
- 78,
985
- 71
986
- ]
987
- },
988
- {
989
- ct: /^image\/jpe?g$/,
990
- offset: 0,
991
- magic: [
992
- 255,
993
- 216,
994
- 255
995
- ]
996
- },
997
- {
998
- ct: /^image\/gif$/,
999
- offset: 0,
1000
- magic: [
1001
- 71,
1002
- 73,
1003
- 70,
1004
- 56
1005
- ]
1006
- },
1007
- {
1008
- ct: /^image\/webp$/,
1009
- offset: 0,
1010
- magic: [
1011
- 82,
1012
- 73,
1013
- 70,
1014
- 70
1015
- ]
1016
- },
1017
- {
1018
- ct: /^image\/bmp$/,
1019
- offset: 0,
1020
- magic: [66, 77]
1021
- },
1022
- {
1023
- ct: /^application\/pdf$/,
1024
- offset: 0,
1025
- magic: [
1026
- 37,
1027
- 80,
1028
- 68,
1029
- 70
1030
- ]
1031
- },
1032
- {
1033
- ct: /^application\/zip$/,
1034
- offset: 0,
1035
- magic: [
1036
- 80,
1037
- 75,
1038
- 3,
1039
- 4
1040
- ]
1041
- },
1042
- {
1043
- ct: /^application\/gzip$/,
1044
- offset: 0,
1045
- magic: [31, 139]
1046
- }
1047
- ], Gt = (e, t) => {
1048
- let n = t.toLowerCase(), r = Wt.find((e) => e.ct.test(n));
1049
- return r ? e.length < r.offset + r.magic.length ? !1 : r.magic.every((t, n) => e[r.offset + n] === t) : !0;
1050
- }, Kt = (e, t, n) => n ? n.maxBytes !== void 0 && e.byteLength > n.maxBytes ? {
1051
- reason: "too-large",
1052
- detail: `${e.byteLength} bytes exceeds the ${n.maxBytes}-byte limit`
1053
- } : Ut(t, n.allowedContentTypes) ? n.sniff && !Gt(e, t) ? {
1054
- reason: "content-mismatch",
1055
- detail: `bytes do not match the declared content type '${t}'`
1056
- } : null : {
1057
- reason: "content-type-not-allowed",
1058
- detail: `content type '${t}' is not in the allow-list`
1059
- } : null, qt = async (e, t, n) => {
1060
- if (!ut(t)) return { bytes: e };
1061
- let r = await ft();
1062
- if (!r) return { bytes: e };
1063
- try {
1064
- let t = e;
1065
- if (n?.normalize) {
1066
- let n = await r(Buffer.from(e), { failOn: "none" }).rotate().toBuffer();
1067
- t = new Uint8Array(n);
1068
- }
1069
- let i = await r(Buffer.from(t), { failOn: "none" }).metadata(), a = await r(Buffer.from(t), { failOn: "none" }).resize({
1070
- width: 24,
1071
- height: 24,
1072
- fit: "inside",
1073
- withoutEnlargement: !0
1074
- }).webp({ quality: 40 }).toBuffer().catch(() => null);
1075
- return {
1076
- bytes: t,
1077
- ...typeof i.width == "number" ? { width: i.width } : {},
1078
- ...typeof i.height == "number" ? { height: i.height } : {},
1079
- ...a ? { placeholder: `data:image/webp;base64,${a.toString("base64")}` } : {}
1080
- };
1081
- } catch {
1082
- return { bytes: e };
1083
- }
1084
- }, Jt = 67108864, Yt = (e) => new n({
1085
- reason: "too-large",
1086
- detail: `remote body exceeds the ${e}-byte ingest limit`
1087
- }), Xt = (e, t) => new n({
1088
- reason: "blocked-source",
1089
- detail: `will not fetch ${e}: ${t}`
1090
- }), Zt = (e, r, i = {}) => v.suspend(() => {
1091
- let a = r ?? Jt;
1092
- return !Number.isSafeInteger(a) || a < 0 ? v.fail(new t({
1093
- provider: "ingest",
1094
- message: "limits.maxBytes must be a non-negative safe integer",
1095
- transient: !1
1096
- })) : v.tryPromise({
1097
- try: async (n) => {
1098
- let r = e, o;
1099
- for (let e = 0;; e++) {
1100
- let t = De(r, { ...i.allowHosts === void 0 ? {} : { allowHosts: i.allowHosts } });
1101
- if (t !== null) throw Xt(r, t);
1102
- o = await fetch(r, {
1103
- signal: n,
1104
- redirect: "manual"
1105
- });
1106
- let a = o.headers.get("location");
1107
- if (o.status < 300 || o.status >= 400 || a === null) break;
1108
- if (await o.body?.cancel().catch(() => {}), e >= (i.maxRedirects ?? 5)) throw Xt(r, "too many redirects");
1109
- r = new URL(a, r).toString();
1110
- }
1111
- let s;
1112
- try {
1113
- if (!o.ok) throw new t({
1114
- provider: "ingest",
1115
- message: `remote server returned HTTP ${o.status}`,
1116
- transient: o.status === 429 || o.status >= 500,
1117
- status: o.status
1118
- });
1119
- let e = o.headers.get("content-length"), n = o.headers.get("content-encoding")?.trim().toLowerCase();
1120
- if ((!n || n === "identity") && e !== null && /^\d+$/.test(e) && BigInt(e) > BigInt(a)) throw Yt(a);
1121
- let r = /* @__PURE__ */ new Uint8Array(), i = 0;
1122
- if (o.body !== null) for (s = o.body.getReader();;) {
1123
- let e = await s.read();
1124
- if (e.done) break;
1125
- if (e.value.byteLength > a - i) throw Yt(a);
1126
- if (e.value.byteLength !== 0) {
1127
- let t = i + e.value.byteLength;
1128
- if (t > r.byteLength) {
1129
- let e = Math.min(a, Math.max(65536, r.byteLength * 2, t)), n = new Uint8Array(e);
1130
- n.set(r), r = n;
1131
- }
1132
- r.set(e.value, i), i = t;
1133
- }
1134
- }
1135
- return {
1136
- bytes: i === r.byteLength ? r : r.slice(0, i),
1137
- contentType: o.headers.get("content-type")?.split(";")[0]?.trim() || "application/octet-stream"
1138
- };
1139
- } finally {
1140
- s === void 0 ? await o.body?.cancel().catch(() => {}) : (await s.cancel().catch(() => {}), s.releaseLock());
1141
- }
1142
- },
1143
- catch: (e) => e instanceof n || e instanceof t ? e : new t({
1144
- provider: "ingest",
1145
- message: "remote fetch or body read failed",
1146
- transient: !0
1147
- })
1148
- });
1149
- }), Qt = (e, t) => v.suspend(() => {
1150
- if (t === void 0) return e;
1151
- if (t.aborted) return v.interrupt;
1152
- let n = v.callback((e) => {
1153
- let n = () => e(v.interrupt);
1154
- return t.addEventListener("abort", n, { once: !0 }), t.aborted && n(), v.sync(() => t.removeEventListener("abort", n));
1155
- });
1156
- return v.raceFirst(e, n);
1157
- }), $t = (e) => {
1158
- let r = (e, n) => v.tryPromise({
1159
- try: n,
1160
- catch: (n) => {
1161
- let r = Ye(n);
1162
- if (r !== void 0) return r;
1163
- let i = G(n, "metadata"), a = new t({
1164
- provider: "metadata",
1165
- message: `Storage ${e} was not confirmed: ${i.message}; retain the operation identity for recovery`,
1166
- transient: i.transient,
1167
- ...i.status === void 0 ? {} : { status: i.status }
1168
- });
1169
- return Object.defineProperty(a, "cause", {
1170
- value: n,
1171
- configurable: !0
1172
- }), a;
1173
- }
1174
- });
1175
- return {
1176
- put: (t) => v.gen(function* () {
1177
- if (t.bytes.byteLength !== t.ref.size || Ce("sha256").update(t.bytes).digest("hex") !== t.identity.checksum) return yield* v.fail(new n({
1178
- reason: "operation-content-mismatch",
1179
- detail: "Storage operation bytes do not match their reserved identity"
1180
- }));
1181
- let i = yield* r("put reservation", () => e.metadata.reserve(t.identity, t.ref, t.quota, t.claim)), a = i.outcome;
1182
- return i.ready ? {
1183
- ref: i.ref,
1184
- outcome: a
1185
- } : (yield* e.provider.put(i.ref.key, t.bytes, {
1186
- contentType: i.ref.contentType,
1187
- public: i.ref.visibility === "public"
1188
- }), {
1189
- ref: yield* r("put confirmation", () => e.metadata.confirm(t.identity, t.claim)),
1190
- outcome: a
1191
- });
1192
- }),
1193
- delete: (t, n, i) => v.gen(function* () {
1194
- let a = yield* r("delete acceptance", () => e.metadata.beginDelete(t, n, i));
1195
- "operation" in a && (a.operation.deleteKey !== null && (yield* e.provider.delete(a.operation.deleteKey)), yield* r("delete confirmation", () => e.metadata.confirmDelete(a.identity)));
1196
- })
1197
- };
1198
- }, en = async (e) => {
1199
- let { createHash: t } = await import("node:crypto");
1200
- return t("sha256").update(e).digest("hex");
1201
- }, tn = (e, t, n) => `${e?.replace(/\/+$/, "") ?? ""}${n}/${t}`, nn = (e) => {
1202
- let t = /* @__PURE__ */ new Map(), n = {
1203
- public: 0,
1204
- private: 0
1205
- };
1206
- for (let r of e) {
1207
- let e = r.tenantId ?? "(global)", i = t.get(e) ?? {
1208
- count: 0,
1209
- bytes: 0
1210
- };
1211
- i.count = Je(i.count, r.count, "ref count"), i.bytes = Je(i.bytes, r.bytes, "usage bytes"), t.set(e, i), r.visibility === "public" ? n.public = Je(n.public, r.count, "public ref count") : n.private = Je(n.private, r.count, "private ref count");
1212
- }
1213
- return {
1214
- byTenant: Object.fromEntries(t),
1215
- visibility: n
1216
- };
1217
- }, rn = (e, t) => {
1218
- if (t.search && ![
1219
- e.id,
1220
- e.key,
1221
- e.contentType,
1222
- e.ownerId,
1223
- e.tenantId
1224
- ].some((e) => e?.toLowerCase().includes(t.search.toLowerCase())) || t.tenantId !== void 0 && (e.tenantId ?? null) !== (t.tenantId ?? null) || t.ownerId !== void 0 && e.ownerId !== t.ownerId || !t.includeDerived && e.derivedFrom != null) return !1;
1225
- if (t.folder !== void 0) {
1226
- let n = t.folder.replace(/\/+$/, ""), r = (e.folder ?? "").replace(/\/+$/, "");
1227
- if (r !== n && !r.startsWith(`${n}/`)) return !1;
1228
- }
1229
- if (t.tags.length > 0) {
1230
- let n = e.tags ?? [];
1231
- if (!t.tags.every((e) => n.includes(e))) return !1;
1232
- }
1233
- return !0;
1234
- }, an = (e) => e ?? "global", on = () => {
1235
- let e = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Map();
1236
- return {
1237
- statistics: () => v.try({
1238
- try: () => nn((function* () {
1239
- for (let t of e.values()) yield {
1240
- tenantId: t.tenantId,
1241
- visibility: t.visibility,
1242
- count: 1,
1243
- bytes: t.size
1244
- };
1245
- })()),
1246
- catch: (e) => G(e, "refstore")
1247
- }),
1248
- insert: (t) => v.try({
1249
- try: () => {
1250
- W(t.size, "ref size"), e.set(t.id, t);
1251
- },
1252
- catch: (e) => G(e, "refstore")
1253
- }),
1254
- getById: (t) => v.sync(() => e.get(t) ?? null),
1255
- delete: (t) => v.sync(() => e.delete(t)),
1256
- listRecent: (t) => v.sync(() => [...e.values()].sort((e, t) => t.createdAt.getTime() - e.createdAt.getTime() || t.id.localeCompare(e.id)).slice(0, t)),
1257
- countByKey: (t, n) => v.sync(() => [...e.values()].filter((e) => e.bucket === t && e.key === n).length),
1258
- countPublicByKey: (t, n) => v.sync(() => [...e.values()].filter((e) => e.bucket === t && e.key === n && e.visibility === "public").length),
1259
- setVisibility: (t, n) => v.sync(() => {
1260
- let r = e.get(t);
1261
- if (r === void 0) return null;
1262
- let i = {
1263
- ...r,
1264
- visibility: n
1265
- };
1266
- return e.set(t, i), i;
1267
- }),
1268
- usageByTenant: (t) => v.try({
1269
- try: () => {
1270
- let n = 0, r = 0;
1271
- for (let i of e.values()) (i.tenantId ?? null) === (t ?? null) && (n = Je(n, i.size, "usage bytes"), r++);
1272
- return {
1273
- bytes: n,
1274
- count: r
1275
- };
1276
- },
1277
- catch: (e) => G(e, "refstore")
1278
- }),
1279
- consumeUsage: (e, n, r) => v.try({
1280
- try: () => {
1281
- let i = an(e), a = t.get(i) ?? {
1282
- bytes: 0,
1283
- count: 0
1284
- };
1285
- W(n.bytes, "usage byte delta"), W(n.count, "usage count delta");
1286
- let o = Number.isSafeInteger(a.bytes + n.bytes) && Number.isSafeInteger(a.count + n.count) && (r?.maxBytes === void 0 || a.bytes + n.bytes <= r.maxBytes) && (r?.maxCount === void 0 || a.count + n.count <= r.maxCount);
1287
- return o && t.set(i, {
1288
- bytes: a.bytes + n.bytes,
1289
- count: a.count + n.count
1290
- }), {
1291
- allowed: o,
1292
- bytes: a.bytes,
1293
- count: a.count
1294
- };
1295
- },
1296
- catch: (e) => G(e, "refstore")
1297
- }),
1298
- releaseUsage: (e, n) => v.try({
1299
- try: () => {
1300
- let r = an(e), i = t.get(r);
1301
- W(n.bytes, "usage byte delta"), W(n.count, "usage count delta"), i && t.set(r, {
1302
- bytes: Math.max(0, i.bytes - n.bytes),
1303
- count: Math.max(0, i.count - n.count)
1304
- });
1305
- },
1306
- catch: (e) => G(e, "refstore")
1307
- }),
1308
- listByDerivedFrom: (t) => v.sync(() => [...e.values()].filter((e) => (e.derivedFrom ?? null) === t)),
1309
- listRefs: (t) => v.sync(() => [...e.values()].filter((e) => rn(e, t)).sort((e, t) => t.createdAt.getTime() - e.createdAt.getTime() || t.id.localeCompare(e.id)).slice(t.offset, t.offset + t.limit))
1310
- };
1311
- }, sn = (e) => Array.isArray(e) && e.every((e) => typeof e == "string") ? e : null, X = (e) => ({
1312
- id: String(e.id),
1313
- tenantId: e.tenantId ?? null,
1314
- ownerId: e.ownerId ?? null,
1315
- bucket: String(e.bucket),
1316
- key: String(e.key),
1317
- contentType: String(e.contentType),
1318
- size: W(e.size, "ref size"),
1319
- checksum: String(e.checksum),
1320
- visibility: e.visibility === "public" ? "public" : "private",
1321
- accessPolicy: e.accessPolicy ?? null,
1322
- passwordHash: e.passwordHash ?? null,
1323
- createdAt: e.createdAt instanceof Date ? e.createdAt : new Date(String(e.createdAt)),
1324
- width: e.width ?? null,
1325
- height: e.height ?? null,
1326
- duration: e.duration ?? null,
1327
- placeholder: e.placeholder ?? null,
1328
- folder: e.folder ?? null,
1329
- tags: sn(e.tags),
1330
- alt: e.alt ?? null,
1331
- caption: e.caption ?? null,
1332
- derivedFrom: e.derivedFrom ?? null,
1333
- kind: e.kind ?? null
1334
- }), Z = (e) => v.tryPromise({
1335
- try: e,
1336
- catch: (e) => G(e, "refstore", !0)
1337
- }), cn = async (e, t) => (await e.query({
1338
- table: "_voltro_storage_usage",
1339
- predicate: {
1340
- column: "tenantId",
1341
- op: "eq",
1342
- value: t
1343
- },
1344
- order: [],
1345
- take: 1,
1346
- skip: void 0,
1347
- projection: void 0
1348
- }))[0] ?? null, ln = (e) => ({
1349
- statistics: () => Z(async () => nn((await e.query({
1350
- table: B,
1351
- predicate: void 0,
1352
- order: [],
1353
- take: void 0,
1354
- skip: void 0,
1355
- projection: void 0,
1356
- groupBy: ["tenantId", "visibility"],
1357
- aggregations: [
1358
- de("tenantId"),
1359
- de("visibility"),
1360
- {
1361
- op: "count",
1362
- alias: "count"
1363
- },
1364
- {
1365
- op: "sum",
1366
- column: "size",
1367
- alias: "bytes"
1368
- }
1369
- ]
1370
- })).map((e) => ({
1371
- tenantId: e.tenantId == null ? null : String(e.tenantId),
1372
- visibility: String(e.visibility),
1373
- count: W(e.count, "ref count"),
1374
- bytes: W(e.bytes ?? 0, "usage bytes")
1375
- })))),
1376
- insert: (t) => Z(() => e.insert(B, {
1377
- ...t,
1378
- size: String(W(t.size, "ref size"))
1379
- })),
1380
- getById: (t) => Z(async () => {
1381
- let n = await e.query({
1382
- table: B,
1383
- predicate: {
1384
- column: "id",
1385
- op: "eq",
1386
- value: t
1387
- },
1388
- order: [],
1389
- take: 1,
1390
- skip: void 0,
1391
- projection: void 0
1392
- });
1393
- return n[0] ? X(n[0]) : null;
1394
- }),
1395
- delete: (t) => Z(() => e.delete(B, t)),
1396
- listRecent: (t) => Z(async () => (await e.query({
1397
- table: B,
1398
- predicate: void 0,
1399
- order: [{
1400
- column: "createdAt",
1401
- direction: "desc"
1402
- }],
1403
- take: t,
1404
- skip: void 0,
1405
- projection: void 0
1406
- })).map(X)),
1407
- countByKey: (t, n) => Z(async () => W((await e.query({
1408
- table: B,
1409
- predicate: { and: [{
1410
- column: "bucket",
1411
- op: "eq",
1412
- value: t
1413
- }, {
1414
- column: "key",
1415
- op: "eq",
1416
- value: n
1417
- }] },
1418
- order: [],
1419
- take: void 0,
1420
- skip: void 0,
1421
- projection: void 0,
1422
- aggregations: [{
1423
- op: "count",
1424
- alias: "count"
1425
- }]
1426
- }))[0]?.count ?? 0, "ref count")),
1427
- countPublicByKey: (t, n) => Z(async () => W((await e.query({
1428
- table: B,
1429
- predicate: { and: [
1430
- {
1431
- column: "bucket",
1432
- op: "eq",
1433
- value: t
1434
- },
1435
- {
1436
- column: "key",
1437
- op: "eq",
1438
- value: n
1439
- },
1440
- {
1441
- column: "visibility",
1442
- op: "eq",
1443
- value: "public"
1444
- }
1445
- ] },
1446
- order: [],
1447
- take: void 0,
1448
- skip: void 0,
1449
- projection: void 0,
1450
- aggregations: [{
1451
- op: "count",
1452
- alias: "count"
1453
- }]
1454
- }))[0]?.count ?? 0, "ref count")),
1455
- setVisibility: (t, n) => Z(async () => {
1456
- let r = await e.update(B, t, { visibility: n });
1457
- return r ? X(r) : null;
1458
- }),
1459
- usageByTenant: (t) => Z(async () => {
1460
- let n = await e.query({
1461
- table: B,
1462
- predicate: {
1463
- column: "tenantId",
1464
- op: "eq",
1465
- value: t
1466
- },
1467
- order: [],
1468
- take: void 0,
1469
- skip: void 0,
1470
- projection: void 0,
1471
- aggregations: [
1472
- {
1473
- op: "count",
1474
- alias: "count"
1475
- },
1476
- {
1477
- op: "sum",
1478
- column: "size",
1479
- alias: "bytes"
1480
- },
1481
- {
1482
- op: "min",
1483
- column: "size",
1484
- alias: "minSize"
1485
- },
1486
- {
1487
- op: "max",
1488
- column: "size",
1489
- alias: "maxSize"
1490
- }
1491
- ]
1492
- });
1493
- return W(n[0]?.count ?? 0, "ref count") > 0 && (W(n[0]?.minSize, "ref size"), W(n[0]?.maxSize, "ref size")), {
1494
- bytes: W(n[0]?.bytes ?? 0, "usage bytes"),
1495
- count: W(n[0]?.count ?? 0, "ref count")
1496
- };
1497
- }),
1498
- consumeUsage: (t, n, r) => Z(async () => {
1499
- let i = an(t);
1500
- W(n.bytes, "usage byte delta"), W(n.count, "usage count delta");
1501
- for (let t = 0; t < 32; t++) {
1502
- t > 0 && await new Promise((e) => setTimeout(e, t));
1503
- let a = await cn(e, i), o = a ? W(a.bytes, "usage bytes") : 0, s = a ? W(a.count, "ref count") : 0;
1504
- if (!(Number.isSafeInteger(o + n.bytes) && Number.isSafeInteger(s + n.count) && (r?.maxBytes === void 0 || o + n.bytes <= r.maxBytes) && (r?.maxCount === void 0 || s + n.count <= r.maxCount))) return {
1505
- allowed: !1,
1506
- bytes: o,
1507
- count: s
1508
- };
1509
- if (a) {
1510
- if (await e.updateMany("_voltro_storage_usage", {
1511
- bytes: String(o + n.bytes),
1512
- count: String(s + n.count),
1513
- updatedAt: /* @__PURE__ */ new Date()
1514
- }, { where: ue(k("id", String(a.id)), k("bytes", a.bytes), k("count", a.count)) }) === 1) return {
1515
- allowed: !0,
1516
- bytes: o,
1517
- count: s
1518
- };
1519
- } else {
1520
- let t = A({
1521
- kind: "typeid",
1522
- prefix: "susage"
1523
- }, Ue), r = await e.insertIgnore(Ue, {
1524
- id: t,
1525
- tenantId: i,
1526
- bytes: String(n.bytes),
1527
- count: String(n.count),
1528
- updatedAt: /* @__PURE__ */ new Date()
1529
- }, { conflictColumns: ["tenantId"] });
1530
- if (String(r.id) === t) return {
1531
- allowed: !0,
1532
- bytes: 0,
1533
- count: 0
1534
- };
1535
- }
1536
- }
1537
- throw T("Storage quota reservation contended after 32 attempts; retry");
1538
- }),
1539
- releaseUsage: (t, n) => Z(async () => {
1540
- let r = an(t);
1541
- W(n.bytes, "usage byte delta"), W(n.count, "usage count delta");
1542
- for (let t = 0; t < 32; t++) {
1543
- t > 0 && await new Promise((e) => setTimeout(e, t));
1544
- let i = await cn(e, r);
1545
- if (!i) return;
1546
- let a = W(i.bytes, "usage bytes"), o = W(i.count, "ref count");
1547
- if (await e.updateMany("_voltro_storage_usage", {
1548
- bytes: String(Math.max(0, a - n.bytes)),
1549
- count: String(Math.max(0, o - n.count)),
1550
- updatedAt: /* @__PURE__ */ new Date()
1551
- }, { where: ue(k("id", String(i.id)), k("bytes", i.bytes), k("count", i.count)) }) === 1) return;
1552
- }
1553
- throw T("Storage quota release contended after 32 attempts; retry");
1554
- }),
1555
- listByDerivedFrom: (t) => Z(async () => (await e.query({
1556
- table: B,
1557
- predicate: {
1558
- column: "derivedFrom",
1559
- op: "eq",
1560
- value: t
1561
- },
1562
- order: [{
1563
- column: "createdAt",
1564
- direction: "asc"
1565
- }],
1566
- take: void 0,
1567
- skip: void 0,
1568
- projection: void 0
1569
- })).map(X)),
1570
- listRefs: (t) => Z(async () => {
1571
- let n = [];
1572
- t.tenantId !== void 0 && n.push(k("tenantId", t.tenantId)), t.ownerId !== void 0 && n.push(k("ownerId", t.ownerId)), t.search && n.push(N(...[
1573
- "id",
1574
- "key",
1575
- "contentType",
1576
- "ownerId",
1577
- "tenantId"
1578
- ].map((e) => fe(e, t.search)))), t.includeDerived || n.push(me("derivedFrom"));
1579
- let r = t.folder === void 0 && t.tags.length === 0, i = n.length ? ue(...n) : void 0, a = await e.query({
1580
- table: B,
1581
- predicate: i,
1582
- order: [{
1583
- column: "createdAt",
1584
- direction: "desc"
1585
- }, {
1586
- column: "id",
1587
- direction: "desc"
1588
- }],
1589
- take: r ? t.limit : void 0,
1590
- skip: r ? t.offset : void 0,
1591
- projection: void 0
1592
- });
1593
- return r ? a.map(X) : a.map(X).filter((e) => rn(e, t)).slice(t.offset, t.offset + t.limit);
1594
- })
1595
- }), un = () => {
1596
- let e = /* @__PURE__ */ new Map();
1597
- return {
1598
- insert: (t) => v.sync(() => {
1599
- e.set(t.id, t);
1600
- }),
1601
- delete: (t) => v.sync(() => {
1602
- e.delete(t);
1603
- }),
1604
- getById: (t) => v.sync(() => e.get(t) ?? null),
1605
- listByRef: (t) => v.sync(() => [...e.values()].filter((e) => e.refId === t)),
1606
- deleteByRef: (t) => v.sync(() => {
1607
- for (let [n, r] of e) r.refId === t && e.delete(n);
1608
- })
1609
- };
1610
- }, dn = (e) => ({
1611
- id: String(e.id),
1612
- refId: String(e.refId),
1613
- principalType: e.principalType,
1614
- principalId: String(e.principalId),
1615
- permission: e.permission === "write" ? "write" : "read",
1616
- createdAt: e.createdAt instanceof Date ? e.createdAt : new Date(String(e.createdAt)),
1617
- expiresAt: e.expiresAt ? e.expiresAt instanceof Date ? e.expiresAt : new Date(String(e.expiresAt)) : null,
1618
- createdBy: e.createdBy ?? null
1619
- }), fn = (e) => ({
1620
- insert: (t) => Z(() => e.insert(V, { ...t })),
1621
- delete: (t) => Z(() => e.delete(V, t)),
1622
- getById: (t) => Z(async () => {
1623
- let n = (await e.query({
1624
- table: V,
1625
- predicate: {
1626
- column: "id",
1627
- op: "eq",
1628
- value: t
1629
- },
1630
- order: [],
1631
- take: 1,
1632
- skip: void 0,
1633
- projection: void 0
1634
- }))[0];
1635
- return n ? dn(n) : null;
1636
- }),
1637
- listByRef: (t) => Z(async () => (await e.query({
1638
- table: V,
1639
- predicate: {
1640
- column: "refId",
1641
- op: "eq",
1642
- value: t
1643
- },
1644
- order: [{
1645
- column: "createdAt",
1646
- direction: "desc"
1647
- }],
1648
- take: void 0,
1649
- skip: void 0,
1650
- projection: void 0
1651
- })).map(dn)),
1652
- deleteByRef: (t) => Z(async () => {
1653
- let n = await e.query({
1654
- table: V,
1655
- predicate: {
1656
- column: "refId",
1657
- op: "eq",
1658
- value: t
1659
- },
1660
- order: [],
1661
- take: void 0,
1662
- skip: void 0,
1663
- projection: void 0
1664
- });
1665
- for (let t of n) await e.delete(V, String(t.id));
1666
- })
1667
- }), pn = () => A({
1668
- kind: "typeid",
1669
- prefix: "file"
1670
- }, B), mn = () => A({
1671
- kind: "typeid",
1672
- prefix: "grant"
1673
- }, V), hn = (i) => {
1674
- let { provider: a, refStore: o, grantStore: s, bucket: c } = i, l = i.access ?? {}, u = i.attempts ?? 3, d = i.urlExpiresInSec ?? 3600, f = (e) => tn(i.publicBaseUrl, e, i.httpPath ?? "/_voltro/storage"), p = x.max([x.recurs(Math.max(0, u - 1)), x.exponential("100 millis")]).pipe(x.while(({ input: e }) => e.transient)), m = (e, t, n) => [
1675
- i.tenantPrefix,
1676
- e ?? "global",
1677
- n ?? t
1678
- ].filter(Boolean).join("/"), ee = (e) => {
1679
- if (e === void 0) return v.succeed(void 0);
1680
- let n = e.length === 0 ? "empty" : e.includes("\0") ? "contains NUL" : e.startsWith("/") || e.startsWith("\\") ? "starts with a path separator" : e.includes("\\") ? "contains a backslash" : e.split("/").some((e) => e === "" || e === "." || e === "..") ? "contains an empty, \".\" or \"..\" segment" : void 0;
1681
- return n === void 0 ? v.succeed(e) : v.fail(new t({
1682
- provider: a.name,
1683
- message: `storage key rejected: ${n}`,
1684
- transient: !1,
1685
- status: 400
1686
- }));
1687
- }, te = (e, t, n) => [
1688
- i.tenantPrefix,
1689
- e ?? "global",
1690
- "_incoming",
1691
- t,
1692
- String(n).padStart(6, "0")
1693
- ].filter(Boolean).join("/"), ne = (e, t) => t === void 0 || e.tenantId === t, h = (e, n) => ne(e, n) ? v.succeed(e) : v.fail(new t({
1694
- provider: a.name,
1695
- message: "cross-tenant access denied",
1696
- transient: !1,
1697
- status: 403
1698
- })), g = (e, n, r) => v.gen(function* () {
1699
- let o = i.objects?.(), s = (e) => new t({
1700
- provider: "metadata",
1701
- message: e,
1702
- transient: !1,
1703
- status: 409
1704
- });
1705
- if (o === void 0) return r === void 0 ? !1 : yield* v.fail(s(`claim '${r}' cannot be released: no data store is bound, so ref '${e}' holds no claims`));
1706
- let c = yield* v.tryPromise({
1707
- try: () => o.intent(e),
1708
- catch: (e) => new t({
1709
- provider: "metadata",
1710
- message: String(e?.message ?? e),
1711
- transient: !1
1712
- })
1713
- });
1714
- return c === void 0 ? r === void 0 ? !1 : yield* v.fail(s(`claim '${r}' cannot be released: ref '${e}' was not written through an operation and holds no claims`)) : (yield* h(c.ref, n), yield* $t({
1715
- metadata: o,
1716
- provider: {
1717
- ...a,
1718
- delete: (e) => a.delete(e).pipe(v.retry(p))
1719
- }
1720
- }).delete(e, n, r).pipe(v.catchTag("StorageRejected", (e) => v.fail(e.reason === "claim-not-held" ? s(e.detail) : new t({
1721
- provider: "metadata",
1722
- message: e.detail,
1723
- transient: !1
1724
- })))), !0);
1725
- }), _ = (e, n) => o.getById(e).pipe(v.flatMap((r) => r ? h(r, n) : v.fail(new t({
1726
- provider: a.name,
1727
- message: `no ref '${e}'`,
1728
- transient: !1,
1729
- status: 404
1730
- })))), re = (e) => v.suspend(() => {
1731
- let n = i.scan(e);
1732
- return v.isEffect(n) ? n : v.tryPromise({
1733
- try: () => Promise.resolve(n),
1734
- catch: (e) => new t({
1735
- provider: "scan",
1736
- message: String(e?.message ?? e),
1737
- transient: !0
1738
- })
1739
- });
1740
- }), ie = (e) => v.suspend(() => {
1741
- let t = e.contentType;
1742
- if (!i.videoProbe || !(t.startsWith("video/") || t.startsWith("audio/"))) return v.succeed(null);
1743
- let n;
1744
- try {
1745
- n = i.videoProbe(e);
1746
- } catch {
1747
- return v.succeed(null);
1748
- }
1749
- return v.isEffect(n) ? n.pipe(v.catch(() => v.succeed(null))) : v.tryPromise({
1750
- try: () => Promise.resolve(n),
1751
- catch: () => null
1752
- }).pipe(v.catch(() => v.succeed(null)));
1753
- }), b = (e) => v.gen(function* () {
1754
- let t = Kt(e.bytes, e.contentType, i.limits);
1755
- if (t) return yield* v.fail(new n(t));
1756
- if (e.claim !== void 0 && e.operationId === void 0) return yield* v.fail(new n({
1757
- reason: "claim-without-operation",
1758
- detail: "a put with a claim needs an operationId; the claim names this caller's hold on that operation's object"
1759
- }));
1760
- if (i.scan) {
1761
- let t = yield* re({
1762
- bytes: e.bytes,
1763
- contentType: e.contentType,
1764
- ...e.key ? { key: e.key } : {}
1765
- });
1766
- if (!t.clean) return yield* v.fail(new r({ threat: t.threat ?? "unknown" }));
1767
- }
1768
- let s = yield* v.promise(() => qt(e.bytes, e.contentType, { normalize: i.normalizeImages ?? !1 })), l = s.bytes, u = yield* ie({
1769
- bytes: l,
1770
- contentType: e.contentType
1771
- }), d = s.width ?? u?.width, f = s.height ?? u?.height, te = s.placeholder ?? u?.poster, ne = e.duration ?? u?.duration, h = yield* v.promise(() => en(l)), g = e.tenantId ?? null, _ = e.visibility ?? "private", b = m(g, h, yield* ee(e.key)), x = e.password ? yield* v.sync(() => yt(e.password)) : null, S = {
1772
- id: pn(),
1773
- tenantId: g,
1774
- ownerId: e.ownerId ?? null,
1775
- bucket: c,
1776
- key: b,
1777
- contentType: e.contentType,
1778
- size: l.byteLength,
1779
- checksum: h,
1780
- visibility: _,
1781
- accessPolicy: e.access ?? null,
1782
- passwordHash: x,
1783
- createdAt: /* @__PURE__ */ new Date(),
1784
- ...d === void 0 ? {} : { width: d },
1785
- ...f === void 0 ? {} : { height: f },
1786
- ...te === void 0 ? {} : { placeholder: te },
1787
- ...ne === void 0 ? {} : { duration: ne },
1788
- ...e.folder === void 0 ? {} : { folder: e.folder },
1789
- ...e.tags === void 0 ? {} : { tags: e.tags },
1790
- ...e.alt === void 0 ? {} : { alt: e.alt },
1791
- ...e.caption === void 0 ? {} : { caption: e.caption },
1792
- ...e.derivedFrom === void 0 ? {} : { derivedFrom: e.derivedFrom },
1793
- ...e.kind === void 0 ? {} : { kind: e.kind }
1794
- }, C = i.transcode !== void 0 && i.autoTranscode !== !1, oe = (t) => C && t.derivedFrom == null && (e.contentType.startsWith("video/") || e.contentType.startsWith("audio/")) ? v.forkDetach(ae(t).pipe(v.ignore)) : v.void;
1795
- if (e.operationId !== void 0) {
1796
- let t = i.objects?.();
1797
- if (t === void 0) return yield* v.fail(new n({
1798
- reason: "operation-store-unbound",
1799
- detail: "a put with an operationId needs a bound data store; the in-memory ref store cannot hold operation intents"
1800
- }));
1801
- let r = {
1802
- tenantId: g,
1803
- bucket: c,
1804
- operationId: e.operationId,
1805
- checksum: h,
1806
- logicalKey: b,
1807
- fingerprint: yield* v.promise(() => en(new TextEncoder().encode(JSON.stringify([
1808
- h,
1809
- e.contentType,
1810
- _,
1811
- e.access ?? null,
1812
- e.key ?? null,
1813
- e.ownerId ?? null,
1814
- e.folder ?? null,
1815
- e.tags ?? null,
1816
- e.alt ?? null,
1817
- e.caption ?? null,
1818
- e.derivedFrom ?? null,
1819
- e.kind ?? null,
1820
- ne ?? null,
1821
- e.password !== void 0
1822
- ]))))
1823
- }, o = yield* $t({
1824
- metadata: t,
1825
- provider: {
1826
- ...a,
1827
- put: (e, t, n) => a.put(e, t, n).pipe(v.retry(p))
1828
- }
1829
- }).put({
1830
- identity: r,
1831
- ref: S,
1832
- bytes: l,
1833
- ...i.quota === void 0 ? {} : { quota: i.quota },
1834
- ...e.claim === void 0 ? {} : { claim: e.claim }
1835
- });
1836
- return yield* oe(o.ref), {
1837
- ...o.ref,
1838
- outcome: o.outcome
1839
- };
1840
- }
1841
- let w = {
1842
- bytes: l.byteLength,
1843
- count: 1
1844
- }, se = yield* o.consumeUsage(g, w, i.quota);
1845
- if (!se.allowed) {
1846
- let e = i.quota ?? {}, t = e.maxCount !== void 0 && se.count + 1 > e.maxCount ? `tenant object count ${se.count} + 1 exceeds max ${e.maxCount}` : `tenant usage ${se.bytes} + ${l.byteLength} bytes exceeds max ${e.maxBytes}`;
1847
- return yield* v.fail(new n({
1848
- reason: "quota-exceeded",
1849
- detail: t
1850
- }));
1851
- }
1852
- return yield* ((e) => e.pipe(v.onExit((e) => y.isSuccess(e) ? v.void : o.delete(S.id).pipe(v.andThen(o.releaseUsage(g, w)), v.ignore))))(o.insert(S).pipe(v.andThen(a.put(b, l, {
1853
- contentType: e.contentType,
1854
- public: _ === "public"
1855
- }).pipe(v.retry(p))))), yield* oe(S), {
1856
- ...S,
1857
- outcome: "created"
1858
- };
1859
- }), S = (e) => v.suspend(() => {
1860
- if (!i.transcode) return v.succeed([]);
1861
- let t;
1862
- try {
1863
- t = i.transcode(e);
1864
- } catch {
1865
- return v.succeed([]);
1866
- }
1867
- return v.isEffect(t) ? t.pipe(v.catch(() => v.succeed([]))) : v.tryPromise({
1868
- try: () => Promise.resolve(t),
1869
- catch: () => []
1870
- }).pipe(v.catch(() => v.succeed([])));
1871
- }), ae = (e) => v.gen(function* () {
1872
- if (!i.transcode || e.derivedFrom != null) return [];
1873
- let t = yield* a.get(e.key).pipe(v.retry(p)), n = yield* S({
1874
- bytes: t.bytes,
1875
- contentType: e.contentType,
1876
- ref: e
1877
- }), r = [];
1878
- for (let t of n) {
1879
- let n = yield* b({
1880
- bytes: t.bytes,
1881
- contentType: t.contentType,
1882
- tenantId: e.tenantId,
1883
- ownerId: e.ownerId,
1884
- visibility: e.visibility,
1885
- derivedFrom: e.id,
1886
- kind: t.kind,
1887
- ...t.label === void 0 ? {} : { caption: t.label }
1888
- });
1889
- r.push(n);
1890
- }
1891
- return r;
1892
- }), oe = (e, t, n) => v.gen(function* () {
1893
- if (e.derivedFrom != null) {
1894
- let r = yield* o.getById(e.derivedFrom);
1895
- return r === null ? !1 : yield* oe(r, t, n);
1896
- }
1897
- if (e.visibility === "public") return !0;
1898
- if (e.tenantId !== null && !ne(e, t.tenantId ?? null)) return !1;
1899
- if (yield* Dt(e, t, {
1900
- ...l,
1901
- ...n?.password === void 0 ? {} : { password: n.password }
1902
- })) return !0;
1903
- let r = yield* jt(t, l);
1904
- return At(yield* s.listByRef(e.id), t, r, n?.permission ?? "read", Date.now());
1905
- }), w = (e) => {
1906
- if (e.visibility === "public") {
1907
- let t = a.publicUrl?.(e.key);
1908
- if (t != null) return t;
1909
- }
1910
- return f(e.id);
1911
- };
1912
- return {
1913
- put: b,
1914
- get: (e, t) => _(e, t?.tenantId).pipe(v.flatMap((e) => a.get(e.key).pipe(v.retry(p), v.map((t) => ({
1915
- bytes: t.bytes,
1916
- ref: e
1917
- }))))),
1918
- getStream: (e, t) => _(e, t?.tenantId).pipe(v.map((e) => ({
1919
- ref: e,
1920
- stream: C.unwrap(v.suspend(() => a.getStream ? a.getStream(e.key).pipe(v.retry(p), v.map((e) => e.stream)) : a.get(e.key).pipe(v.retry(p), v.map((e) => C.make(e.bytes)))))
1921
- }))),
1922
- getRange: (e, n, r) => _(e, r?.tenantId).pipe(v.flatMap((e) => {
1923
- let r = e.size, i = Math.max(0, Math.trunc(n.start));
1924
- if (r > 0 && i >= r) return v.fail(new t({
1925
- provider: a.name,
1926
- message: `range start ${i} past end ${r}`,
1927
- transient: !1,
1928
- status: 416
1929
- }));
1930
- let o = Math.min(Math.trunc(n.endInclusive), Math.max(0, r - 1));
1931
- return o < i ? v.fail(new t({
1932
- provider: a.name,
1933
- message: `empty range ${i}-${o}`,
1934
- transient: !1,
1935
- status: 416
1936
- })) : (a.getRange ? a.getRange(e.key, i, o).pipe(v.retry(p)) : a.get(e.key).pipe(v.retry(p), v.map((e) => e.bytes.subarray(i, o + 1)))).pipe(v.map((t) => ({
1937
- bytes: t,
1938
- ref: e,
1939
- totalSize: r
1940
- })));
1941
- })),
1942
- getUrl: (e, t) => _(e, t?.tenantId).pipe(v.flatMap((e) => e.visibility === "public" ? v.succeed(w(e)) : a.presigns ? a.getUrl(e.key, t?.expiresInSec ?? d) : v.succeed(f(e.id)))),
1943
- head: (e, t) => o.getById(e).pipe(v.flatMap((e) => e ? h(e, t?.tenantId).pipe(v.map((e) => e)) : v.succeed(null))),
1944
- delete: (e, t) => g(e, t?.tenantId, t?.claim).pipe(v.flatMap((n) => n ? v.void : _(e, t?.tenantId).pipe(v.flatMap((t) => s.deleteByRef(e).pipe(v.flatMap(() => o.delete(e)), v.flatMap((e) => e ? o.countByKey(t.bucket, t.key).pipe(v.flatMap((e) => e === 0 ? a.delete(t.key).pipe(v.retry(p)) : v.void), v.flatMap(() => o.releaseUsage(t.tenantId, {
1945
- bytes: t.size,
1946
- count: 1
1947
- }))) : v.void), v.asVoid))))),
1948
- signedUrl: (e, t) => _(e, t?.tenantId).pipe(v.flatMap((e) => {
1949
- if (e.visibility === "public") return v.succeed(w(e));
1950
- let n = t?.expiresInSec ?? d;
1951
- return a.presigns ? a.getUrl(e.key, n) : v.sync(() => `${f(e.id)}?t=${Mt(e.id, n, void 0, i.httpPath ?? "/_voltro/storage")}`);
1952
- })),
1953
- setVisibility: (e, r, i) => v.gen(function* () {
1954
- let s = yield* _(e, i?.tenantId);
1955
- if (s.visibility === r) return s;
1956
- let c = o.setVisibility;
1957
- if (c === void 0) return yield* v.fail(new n({
1958
- reason: "visibility-unsupported",
1959
- detail: "the ref store cannot change a stored object's visibility"
1960
- }));
1961
- if (r === "private" && a.publicUrl?.(s.key) != null) return yield* v.fail(new n({
1962
- reason: "visibility-unsupported",
1963
- detail: `objects are served from a public base (${a.name} cdnBaseUrl); a public object cannot be made private there`
1964
- }));
1965
- if (r === "private" && a.setObjectPublic !== void 0 && o.countPublicByKey === void 0) return yield* v.fail(new n({
1966
- reason: "visibility-unsupported",
1967
- detail: "the ref store cannot tell whether other refs keep these bytes public"
1968
- }));
1969
- let l = yield* c(s.id, r);
1970
- if (l === null) return yield* v.fail(new t({
1971
- provider: a.name,
1972
- message: `no ref '${e}'`,
1973
- transient: !1,
1974
- status: 404
1975
- }));
1976
- let u = s.derivedFrom == null ? yield* o.listByDerivedFrom(s.id) : [];
1977
- for (let e of u) e.visibility !== r && (yield* c(e.id, r));
1978
- if (a.setObjectPublic !== void 0) {
1979
- let e = o.countPublicByKey;
1980
- for (let t of [s, ...u]) {
1981
- let n = r === "public" || e !== void 0 && (yield* e(t.bucket, t.key)) > 0;
1982
- yield* a.setObjectPublic(t.key, n);
1983
- }
1984
- }
1985
- return l;
1986
- }),
1987
- mintUrl: (n, r, s) => v.gen(function* () {
1988
- let c = yield* o.getById(n).pipe(v.flatMap((e) => e ? v.succeed(e) : v.fail(new t({
1989
- provider: a.name,
1990
- message: `no ref '${n}'`,
1991
- transient: !1,
1992
- status: 404
1993
- }))));
1994
- if (c.visibility === "public" && c.derivedFrom == null) return w(c);
1995
- if (!(yield* oe(c, r, s?.password === void 0 ? {} : { password: s.password }))) return yield* v.fail(new e({
1996
- refId: n,
1997
- reason: "access denied"
1998
- }));
1999
- let l = s?.expiresInSec ?? d;
2000
- if (a.presigns) return yield* a.getUrl(c.key, l);
2001
- let u = yield* v.sync(() => Mt(c.id, l, void 0, i.httpPath ?? "/_voltro/storage"));
2002
- return `${f(c.id)}?t=${u}`;
2003
- }),
2004
- mintUploadUrl: (e) => v.gen(function* () {
2005
- if (!a.getUploadUrl) return yield* v.fail(new t({
2006
- provider: a.name,
2007
- message: `provider '${a.name}' does not support presigned uploads`,
2008
- transient: !1,
2009
- status: 400
2010
- }));
2011
- let n = m(e.tenantId ?? null, "", yield* ee(e.key));
2012
- return yield* a.getUploadUrl(n, e.expiresInSec ?? d, e.contentType);
2013
- }),
2014
- checkAccess: oe,
2015
- grant: (e) => v.gen(function* () {
2016
- let t = {
2017
- id: mn(),
2018
- refId: e.refId,
2019
- principalType: e.principalType,
2020
- principalId: e.principalId,
2021
- permission: e.permission ?? "read",
2022
- createdAt: /* @__PURE__ */ new Date(),
2023
- expiresAt: e.expiresAt ?? null,
2024
- createdBy: e.createdBy ?? null
2025
- };
2026
- return yield* s.insert(t), t;
2027
- }),
2028
- listRefs: (e) => v.suspend(() => {
2029
- let t = Math.min(500, Math.max(1, Math.trunc(e?.limit ?? 50))), n = Math.max(0, Math.trunc(e?.offset ?? 0)), r = {
2030
- tenantId: e && "tenantId" in e ? e.tenantId : void 0,
2031
- folder: e?.folder,
2032
- tags: e?.tags ?? [],
2033
- ownerId: e?.ownerId,
2034
- includeDerived: e?.includeDerived ?? !1,
2035
- limit: t + 1,
2036
- offset: n
2037
- };
2038
- return o.listRefs(r).pipe(v.map((e) => {
2039
- let r = e.length > t;
2040
- return {
2041
- refs: r ? e.slice(0, t) : e,
2042
- nextOffset: r ? n + t : null
2043
- };
2044
- }));
2045
- }),
2046
- revoke: (e) => s.delete(e),
2047
- getGrant: (e) => s.getById(e),
2048
- listGrants: (e) => s.listByRef(e),
2049
- usage: (e) => o.usageByTenant(e),
2050
- sweepOrphans: (e) => v.gen(function* () {
2051
- let t = e?.limit ?? 1e3, n = e?.dryRun ?? !1, r = yield* o.listRecent(t), i = [];
2052
- for (let e of r) if ((yield* a.head(e.key)) === null) {
2053
- if (!n) {
2054
- if (!(yield* o.delete(e.id))) continue;
2055
- yield* o.releaseUsage(e.tenantId, {
2056
- bytes: e.size,
2057
- count: 1
2058
- });
2059
- }
2060
- i.push(e.id);
2061
- }
2062
- return {
2063
- scanned: r.length,
2064
- removed: i
2065
- };
2066
- }),
2067
- ingestUrl: (e, t) => Qt(v.gen(function* () {
2068
- let n = yield* Zt(e, i.limits?.maxBytes, i.ingest);
2069
- return yield* b({
2070
- bytes: n.bytes,
2071
- contentType: t?.contentType ?? n.contentType,
2072
- ...t?.tenantId === void 0 ? {} : { tenantId: t.tenantId },
2073
- ...t?.operationId === void 0 ? {} : { operationId: t.operationId },
2074
- ...t?.ownerId === void 0 ? {} : { ownerId: t.ownerId },
2075
- ...t?.visibility === void 0 ? {} : { visibility: t.visibility },
2076
- ...t?.access === void 0 ? {} : { access: t.access },
2077
- ...t?.key === void 0 ? {} : { key: t.key },
2078
- ...t?.folder === void 0 ? {} : { folder: t.folder },
2079
- ...t?.tags === void 0 ? {} : { tags: t.tags },
2080
- ...t?.alt === void 0 ? {} : { alt: t.alt },
2081
- ...t?.caption === void 0 ? {} : { caption: t.caption }
2082
- });
2083
- }), t?.abortSignal),
2084
- mintPresignedUpload: (e) => v.gen(function* () {
2085
- if (!a.getUploadUrl) return yield* v.fail(new t({
2086
- provider: a.name,
2087
- message: `provider '${a.name}' does not support presigned uploads`,
2088
- transient: !1,
2089
- status: 400
2090
- }));
2091
- let n = e.expiresInSec ?? d, r = `_incoming/${A({
2092
- kind: "typeid",
2093
- prefix: "up"
2094
- }, B)}`, i = m(e.tenantId ?? null, "", r);
2095
- return {
2096
- uploadUrl: yield* a.getUploadUrl(i, n, e.contentType),
2097
- key: i,
2098
- expiresInSec: n
2099
- };
2100
- }),
2101
- finalizeUpload: (e) => a.get(e.key).pipe(v.retry(p), v.flatMap((t) => b({
2102
- bytes: t.bytes,
2103
- contentType: e.contentType,
2104
- ...e.tenantId === void 0 ? {} : { tenantId: e.tenantId },
2105
- ...e.ownerId === void 0 ? {} : { ownerId: e.ownerId },
2106
- ...e.visibility === void 0 ? {} : { visibility: e.visibility },
2107
- ...e.access === void 0 ? {} : { access: e.access },
2108
- ...e.folder === void 0 ? {} : { folder: e.folder },
2109
- ...e.tags === void 0 ? {} : { tags: e.tags },
2110
- ...e.alt === void 0 ? {} : { alt: e.alt },
2111
- ...e.caption === void 0 ? {} : { caption: e.caption }
2112
- })), v.ensuring(a.delete(e.key).pipe(v.retry(p), v.ignore))),
2113
- putResumableChunk: (e) => a.put(te(e.tenantId ?? null, e.uploadId, e.index), e.bytes, { contentType: "application/octet-stream" }).pipe(v.retry(p), v.asVoid),
2114
- resumableStatus: (e) => v.gen(function* () {
2115
- let t = 0, n = 0;
2116
- for (; t < 1e6;) {
2117
- let r = yield* a.head(te(e.tenantId ?? null, e.uploadId, t)).pipe(v.retry(p), v.catch(() => v.succeed(null)));
2118
- if (r === null) break;
2119
- n += r.size, t += 1;
2120
- }
2121
- return {
2122
- offset: n,
2123
- nextIndex: t
2124
- };
2125
- }),
2126
- finalizeResumable: (e) => v.gen(function* () {
2127
- let r = i.limits?.maxBytes ?? 2 ** 53 - 1;
2128
- if (!Number.isSafeInteger(r) || r < 0 || !Number.isSafeInteger(e.count) || e.count < 0) return yield* v.fail(new t({
2129
- provider: a.name,
2130
- message: "resumable count and limits.maxBytes must be non-negative safe integers",
2131
- transient: !1,
2132
- status: 400
2133
- }));
2134
- let o = (t) => te(e.tenantId ?? null, e.uploadId, t), s = v.gen(function* () {
2135
- for (let t = 0; t < e.count; t++) yield* a.delete(o(t)).pipe(v.retry(p), v.ignore);
2136
- }), c = () => new n({
2137
- reason: "too-large",
2138
- detail: `resumable upload exceeds ${r}-byte limit`
2139
- }), l = yield* v.gen(function* () {
2140
- let n = 0;
2141
- for (let i = 0; i < e.count; i++) {
2142
- let e = yield* a.head(o(i)).pipe(v.retry(p));
2143
- if (e === null) return yield* v.fail(new t({
2144
- provider: a.name,
2145
- message: `no resumable chunk at '${o(i)}'`,
2146
- transient: !1,
2147
- status: 404
2148
- }));
2149
- if (!Number.isSafeInteger(e.size) || e.size < 0) return yield* v.fail(new t({
2150
- provider: a.name,
2151
- message: "resumable chunk metadata has an invalid size",
2152
- transient: !1
2153
- }));
2154
- if (e.size > r - n) return yield* v.fail(c());
2155
- n += e.size;
2156
- }
2157
- let i = /* @__PURE__ */ new Uint8Array(), s = 0;
2158
- for (let t = 0; t < e.count; t++) {
2159
- let e = yield* Ve(a, o(t)).pipe(v.retry(p));
2160
- yield* C.runForEach(e.stream, (e) => v.gen(function* () {
2161
- if (e.byteLength > r - s) return yield* v.fail(c());
2162
- let t = s + e.byteLength;
2163
- if (t > i.byteLength) {
2164
- let e = new Uint8Array(Math.min(r, Math.max(65536, i.byteLength * 2, t)));
2165
- e.set(i.subarray(0, s)), i = e;
2166
- }
2167
- i.set(e, s), s = t;
2168
- }));
2169
- }
2170
- return i.subarray(0, s);
2171
- }).pipe(v.tapError((e) => e._tag === "StorageRejected" ? s : v.void));
2172
- return yield* b({
2173
- bytes: l,
2174
- contentType: e.contentType,
2175
- ...e.tenantId === void 0 ? {} : { tenantId: e.tenantId },
2176
- ...e.ownerId === void 0 ? {} : { ownerId: e.ownerId },
2177
- ...e.visibility === void 0 ? {} : { visibility: e.visibility },
2178
- ...e.access === void 0 ? {} : { access: e.access },
2179
- ...e.folder === void 0 ? {} : { folder: e.folder },
2180
- ...e.tags === void 0 ? {} : { tags: e.tags },
2181
- ...e.alt === void 0 ? {} : { alt: e.alt },
2182
- ...e.caption === void 0 ? {} : { caption: e.caption }
2183
- }).pipe(v.ensuring(s));
2184
- }),
2185
- transcode: (e, t) => _(e, t?.tenantId).pipe(v.flatMap((e) => ae(e))),
2186
- renditions: (e, t) => _(e, t?.tenantId).pipe(v.flatMap(() => o.listByDerivedFrom(e))),
2187
- beginMultipartUpload: (e) => v.gen(function* () {
2188
- if (!a.createMultipartUpload || !a.presignUploadPart || !a.completeMultipartUpload) return yield* v.fail(new t({
2189
- provider: a.name,
2190
- message: `provider '${a.name}' does not support multipart uploads`,
2191
- transient: !1,
2192
- status: 400
2193
- }));
2194
- let n = m(e.tenantId ?? null, "", `multipart/${A({
2195
- kind: "typeid",
2196
- prefix: "mp"
2197
- }, B)}`);
2198
- return {
2199
- uploadId: (yield* a.createMultipartUpload(n, e.contentType, { public: (e.visibility ?? "private") === "public" })).uploadId,
2200
- key: n
2201
- };
2202
- }),
2203
- signMultipartPart: (e) => v.suspend(() => a.presignUploadPart ? a.presignUploadPart(e.key, e.uploadId, e.partNumber, e.expiresInSec ?? d) : v.fail(new t({
2204
- provider: a.name,
2205
- message: "provider does not support multipart uploads",
2206
- transient: !1,
2207
- status: 400
2208
- }))),
2209
- completeMultipart: (e) => v.gen(function* () {
2210
- if (!a.completeMultipartUpload) return yield* v.fail(new t({
2211
- provider: a.name,
2212
- message: "provider does not support multipart uploads",
2213
- transient: !1,
2214
- status: 400
2215
- }));
2216
- let r = yield* a.completeMultipartUpload(e.key, e.uploadId, e.parts), s = yield* a.head(e.key).pipe(v.retry(p)), l = s?.size ?? 0, u = (r.etag ?? s?.etag ?? "").replace(/"/g, ""), d = e.tenantId ?? null, f = {
2217
- bytes: l,
2218
- count: 1
2219
- };
2220
- if (!(yield* o.consumeUsage(d, f, i.quota)).allowed) return yield* a.delete(e.key).pipe(v.retry(p), v.ignore), yield* v.fail(new n({
2221
- reason: "quota-exceeded",
2222
- detail: `multipart upload of ${l} bytes exceeds tenant quota`
2223
- }));
2224
- let m = {
2225
- id: pn(),
2226
- tenantId: e.tenantId ?? null,
2227
- ownerId: e.ownerId ?? null,
2228
- bucket: c,
2229
- key: e.key,
2230
- contentType: e.contentType,
2231
- size: l,
2232
- checksum: u,
2233
- visibility: e.visibility ?? "private",
2234
- accessPolicy: e.access ?? null,
2235
- passwordHash: null,
2236
- createdAt: /* @__PURE__ */ new Date(),
2237
- ...e.folder === void 0 ? {} : { folder: e.folder },
2238
- ...e.tags === void 0 ? {} : { tags: e.tags },
2239
- ...e.alt === void 0 ? {} : { alt: e.alt },
2240
- ...e.caption === void 0 ? {} : { caption: e.caption }
2241
- };
2242
- return yield* o.insert(m).pipe(v.onExit((e) => y.isSuccess(e) ? v.void : o.releaseUsage(d, f).pipe(v.ignore))), m;
2243
- }),
2244
- abortMultipart: (e) => v.suspend(() => a.abortMultipartUpload ? a.abortMultipartUpload(e.key, e.uploadId).pipe(v.retry(p)) : v.void)
2245
- };
2246
- }, gn = (e) => b.succeed(i, hn(e)), _n = "_voltro_storage_operation_locks", Q = "_voltro_storage_object_heads", vn = "_voltro_storage_operations", yn = "_voltro_storage_object_claims", bn = [
2247
- P(_n, {
2248
- id: F().maxLength(64),
2249
- nonce: F()
2250
- }).primaryKey(["id"]).nonReactive(),
2251
- P(Q, {
2252
- id: F().maxLength(64),
2253
- generation: F(),
2254
- key: F(),
2255
- reservations: E()
2256
- }).primaryKey(["id"]).nonReactive(),
2257
- P(vn, {
2258
- id: F().maxLength(64),
2259
- objectId: F().maxLength(64),
2260
- fingerprint: F().maxLength(64),
2261
- generation: F(),
2262
- key: F(),
2263
- refId: F(),
2264
- state: F(),
2265
- deleteKey: F().nullable()
2266
- }).primaryKey(["id"]).nonReactive(),
2267
- P(yn, {
2268
- id: F().maxLength(64),
2269
- operationId: F().maxLength(64),
2270
- claim: F()
2271
- }).primaryKey(["id"]).nonReactive()
2272
- ], xn = S.Struct({
2273
- id: S.String,
2274
- objectId: S.String,
2275
- fingerprint: S.String,
2276
- generation: S.String,
2277
- key: S.String,
2278
- refId: S.String,
2279
- state: S.Literals([
2280
- "reserved",
2281
- "ready",
2282
- "deleting",
2283
- "deleted"
2284
- ]),
2285
- deleteKey: S.NullOr(S.String)
2286
- }), Sn = S.Struct({
2287
- id: S.String,
2288
- generation: S.String,
2289
- key: S.String,
2290
- reservations: S.Int.pipe(S.check(S.isGreaterThanOrEqualTo(0)))
2291
- }), Cn = (e) => S.decodeUnknownSync(Sn)({
2292
- ...e,
2293
- reservations: W(e.reservations, "shared-object reservation count")
2294
- }), wn = (e) => Ce("sha256").update(JSON.stringify(e)).digest("hex"), Tn = (e, t) => wn([e, t]), En = (e) => {
2295
- if (!e.bucket || !e.operationId || !e.logicalKey || !/^[a-f0-9]{64}$/.test(e.fingerprint) || !/^[a-f0-9]{64}$/.test(e.checksum)) throw Error("Storage operation requires a bucket, operation identity, key and SHA-256 fingerprint");
2296
- return {
2297
- id: wn([
2298
- e.bucket,
2299
- e.tenantId,
2300
- e.operationId
2301
- ]),
2302
- objectId: wn([
2303
- e.bucket,
2304
- e.tenantId,
2305
- e.logicalKey,
2306
- e.checksum
2307
- ]),
2308
- lockId: wn([e.tenantId])
2309
- };
2310
- }, Dn = async (e, t, n) => {
2311
- let { lockId: r } = En(t);
2312
- return await e.insertIgnoreWithOutcome(_n, {
2313
- id: r,
2314
- nonce: Te()
2315
- }, { conflictColumns: ["id"] }), e.transactional(async (e) => {
2316
- if ((await e.query({
2317
- table: _n,
2318
- predicate: k("id", r),
2319
- lock: "update",
2320
- order: [],
2321
- take: 1,
2322
- skip: void 0,
2323
- projection: void 0
2324
- })).length !== 1 || await e.update(_n, r, { nonce: Te() }) === null) throw Error("Storage operation lock is unavailable");
2325
- return n(e);
2326
- });
2327
- }, $ = async (e, t) => {
2328
- let r = En(t), i = await e.query({
2329
- table: vn,
2330
- predicate: k("id", r.id),
2331
- order: [],
2332
- take: 1,
2333
- skip: void 0,
2334
- projection: void 0
2335
- });
2336
- if (!i[0]) return;
2337
- let a = S.decodeUnknownSync(xn)(i[0]);
2338
- if (a.fingerprint !== t.fingerprint || a.objectId !== r.objectId) throw new n({
2339
- reason: "operation-identity-reused",
2340
- detail: `storage operation '${t.operationId}' was already used with different inputs`
2341
- });
2342
- return a;
2343
- }, On = async (e, t) => {
2344
- let n = await $(e, t);
2345
- if (n) return n;
2346
- let { id: r, objectId: i } = En(t), a = await e.query({
2347
- table: Q,
2348
- predicate: k("id", i),
2349
- order: [],
2350
- take: 1,
2351
- skip: void 0,
2352
- projection: void 0
2353
- }), o = a[0] ? Cn(a[0]) : void 0, s = o?.generation ?? Te(), c = o?.key ?? `${t.logicalKey}/g-${s}`;
2354
- o ? await e.update(Q, i, { reservations: String(Je(o.reservations, 1, "shared-object reservation count")) }) : await e.insert(Q, {
2355
- id: i,
2356
- generation: s,
2357
- key: c,
2358
- reservations: "1"
2359
- });
2360
- let l = {
2361
- id: r,
2362
- objectId: i,
2363
- fingerprint: t.fingerprint,
2364
- generation: s,
2365
- key: c,
2366
- refId: `file_${Te()}`,
2367
- state: "reserved",
2368
- deleteKey: null
2369
- };
2370
- return await e.insert(vn, l), l;
2371
- }, kn = async (e, t) => {
2372
- let n = await $(e, t);
2373
- if (!n) throw Error("Storage operation is missing");
2374
- if (n.state === "deleting" || n.state === "deleted") throw Error("Deleted storage operation cannot be confirmed by a late put");
2375
- return await e.update(vn, n.id, { state: "ready" }), {
2376
- ...n,
2377
- state: "ready"
2378
- };
2379
- }, An = async (e, t) => {
2380
- let n = await $(e, t);
2381
- if (!n) throw Error("Storage operation is missing");
2382
- if (n.state === "deleting" || n.state === "deleted") return n;
2383
- if (n.state !== "ready") throw Error("An unconfirmed put cannot be deleted");
2384
- let r = await e.query({
2385
- table: Q,
2386
- predicate: k("id", n.objectId),
2387
- order: [],
2388
- take: 1,
2389
- skip: void 0,
2390
- projection: void 0
2391
- }), i = r[0] ? Cn(r[0]) : void 0;
2392
- if (!i || i.generation !== n.generation || i.reservations < 1) throw Error("Storage object generation does not own its reservation");
2393
- let a = i.reservations === 1 ? i.key : null;
2394
- return a === null ? await e.update(Q, i.id, { reservations: String(i.reservations - 1) }) : await e.delete(Q, i.id), await e.update(vn, n.id, {
2395
- state: "deleting",
2396
- deleteKey: a
2397
- }), {
2398
- ...n,
2399
- state: "deleting",
2400
- deleteKey: a
2401
- };
2402
- }, jn = async (e, t) => {
2403
- let n = await $(e, t);
2404
- if (!n || n.state !== "deleting" && n.state !== "deleted") throw Error("Storage deletion has not been accepted");
2405
- return n.state !== "deleted" && (await e.update(vn, n.id, { state: "deleted" }), !0);
2406
- }, Mn = async (e, t, n) => {
2407
- if (!n) throw Error("Storage object claim must be a non-empty string");
2408
- await e.insertIgnoreWithOutcome(yn, {
2409
- id: Tn(t, n),
2410
- operationId: t,
2411
- claim: n
2412
- }, { conflictColumns: ["id"] });
2413
- }, Nn = async (e, t, n) => {
2414
- let r = Tn(t, n);
2415
- return {
2416
- held: await e.delete(yn, r),
2417
- others: (await e.query({
2418
- table: yn,
2419
- predicate: ue(k("operationId", t), ve("claim", n)),
2420
- order: [],
2421
- take: 1,
2422
- skip: void 0,
2423
- projection: void 0
2424
- })).length > 0
2425
- };
2426
- }, Pn = (e, t) => e.deleteMany(yn, { where: k("operationId", t) }), Fn = "_voltro_storage_put_intents", In = P(Fn, {
2427
- id: F().maxLength(64),
2428
- refId: F().maxLength(64),
2429
- identity: ge(),
2430
- ref: ge()
2431
- }).primaryKey(["id"]).unique("storagePutRef", ["refId"]).nonReactive(), Ln = S.Struct({
2432
- tenantId: S.NullOr(S.String),
2433
- bucket: S.String,
2434
- operationId: S.String,
2435
- fingerprint: S.String,
2436
- checksum: S.String,
2437
- logicalKey: S.String
2438
- }), Rn = async (e, t) => {
2439
- let n = await e.query({
2440
- table: Fn,
2441
- predicate: k("refId", t),
2442
- order: [],
2443
- take: 2,
2444
- skip: void 0,
2445
- projection: void 0
2446
- });
2447
- if (n.length === 0) return;
2448
- if (n.length !== 1) throw Error("Storage reference has ambiguous operation ownership");
2449
- let r = n[0], i = S.decodeUnknownSync(Ln)(r.identity);
2450
- if (typeof r.ref != "object" || r.ref === null || Array.isArray(r.ref)) throw Error("Storage operation reference is unreadable");
2451
- let a = X(r.ref);
2452
- if (a.id !== t || a.bucket !== i.bucket || a.tenantId !== i.tenantId || a.checksum !== i.checksum || !Number.isSafeInteger(a.size) || a.size < 0 || !Number.isFinite(a.createdAt.getTime())) throw Error("Storage operation reference does not match its identity");
2453
- return {
2454
- identity: i,
2455
- ref: a
2456
- };
2457
- }, zn = (e) => ({
2458
- intent: (t) => Rn(e, t),
2459
- reserve: (t, r, i, a) => Dn(e, t, async (e) => {
2460
- if (r.tenantId !== t.tenantId || r.bucket !== t.bucket || r.checksum !== t.checksum || !Number.isSafeInteger(r.size) || r.size < 0) throw Error("Storage put metadata does not match its identity");
2461
- let o = await $(e, t);
2462
- if (o) {
2463
- if (o.state === "deleting" || o.state === "deleted") throw Error("Storage put identity has already been deleted");
2464
- let t = await Rn(e, o.refId);
2465
- if (!t) throw Error("Storage operation lost its put intent");
2466
- let n = o.state === "ready";
2467
- return n && a !== void 0 && await Mn(e, o.id, a), {
2468
- ref: t.ref,
2469
- ready: n,
2470
- outcome: n ? "joined" : "resumed"
2471
- };
2472
- }
2473
- let s = await On(e, t), c = ln(e);
2474
- if (!(await v.runPromise(c.consumeUsage(t.tenantId, {
2475
- bytes: r.size,
2476
- count: 1
2477
- }, i))).allowed) throw new n({
2478
- reason: "quota-exceeded",
2479
- detail: "Storage operation exceeds tenant quota"
2480
- });
2481
- let l = X({
2482
- ...r,
2483
- id: s.refId,
2484
- key: s.key
2485
- });
2486
- return await e.insert(Fn, {
2487
- id: s.id,
2488
- refId: l.id,
2489
- identity: t,
2490
- ref: l
2491
- }), {
2492
- ref: l,
2493
- ready: !1,
2494
- outcome: "created"
2495
- };
2496
- }),
2497
- confirm: (t, n) => Dn(e, t, async (e) => {
2498
- let r = await $(e, t);
2499
- if (!r) throw Error("Storage put operation is missing");
2500
- let i = await Rn(e, r.refId);
2501
- if (!i) throw Error("Storage put intent is missing");
2502
- if (n !== void 0 && await Mn(e, r.id, n), r.state === "ready") {
2503
- let n = await v.runPromise(ln(e).getById(r.refId));
2504
- if (!n || n.key !== r.key || n.checksum !== t.checksum) throw Error("Confirmed storage operation lost its reference");
2505
- return n;
2506
- }
2507
- return await kn(e, t), await v.runPromise(ln(e).insert(i.ref)), i.ref;
2508
- }),
2509
- beginDelete: async (t, r, i) => {
2510
- let a = await Rn(e, t);
2511
- if (!a) throw Error("Storage delete operation is missing");
2512
- if (r !== void 0 && a.identity.tenantId !== r) throw Error("Storage delete tenant mismatch");
2513
- return Dn(e, a.identity, async (e) => {
2514
- let r = await Rn(e, t);
2515
- if (!r) throw Error("Storage delete intent disappeared");
2516
- let a = await $(e, r.identity);
2517
- if (!a) throw Error("Storage delete lost its operation");
2518
- let o = a.state !== "deleting" && a.state !== "deleted";
2519
- if (i === void 0) o && await Pn(e, a.id);
2520
- else if (o) {
2521
- let o = await Nn(e, a.id, i);
2522
- if (o.others) return {
2523
- released: !0,
2524
- identity: r.identity
2525
- };
2526
- if (!o.held) throw new n({
2527
- reason: "claim-not-held",
2528
- detail: `claim '${i}' is not held on storage reference '${t}'; a reference put without a claim is deleted as a whole by a delete that names none`
2529
- });
2530
- }
2531
- let s = await An(e, r.identity);
2532
- if (a.state === "ready") {
2533
- let n = ln(e);
2534
- if (await v.runPromise(fn(e).deleteByRef(t)), !await v.runPromise(n.delete(t))) throw Error("Storage deletion lost its confirmed reference");
2535
- await v.runPromise(n.releaseUsage(r.identity.tenantId, {
2536
- bytes: r.ref.size,
2537
- count: 1
2538
- }));
2539
- }
2540
- return {
2541
- released: !0,
2542
- operation: s,
2543
- identity: r.identity
2544
- };
2545
- });
2546
- },
2547
- confirmDelete: (t) => Dn(e, t, (e) => jn(e, t))
2548
- }), Bn = (e, t = 65536) => {
2549
- let n = [Buffer.from("zINSTREAM\0", "utf8")];
2550
- for (let r = 0; r < e.length; r += t) {
2551
- let i = e.subarray(r, Math.min(r + t, e.length)), a = Buffer.alloc(4);
2552
- a.writeUInt32BE(i.length, 0), n.push(a, Buffer.from(i));
2553
- }
2554
- let r = Buffer.alloc(4);
2555
- return r.writeUInt32BE(0, 0), n.push(r), Buffer.concat(n);
2556
- }, Vn = (e) => {
2557
- let t = e.replace(/\0+$/, "").trim();
2558
- if (/\bOK$/.test(t)) return { clean: !0 };
2559
- let n = /:\s*(.+?)\s+FOUND$/.exec(t);
2560
- if (n) return {
2561
- clean: !1,
2562
- threat: n[1] ?? "unknown"
2563
- };
2564
- throw Error(`clamav: unexpected response: ${t}`);
2565
- }, Hn = async (e, t) => {
2566
- let n = await import("node:net"), r = U.read("CLAMAV_HOST", t.host) ?? "127.0.0.1", i = U.read("CLAMAV_PORT"), a = t.port ?? (i ? Number(i) : 3310), o = t.timeoutMs ?? 3e4;
2567
- return new Promise((i, s) => {
2568
- let c = n.createConnection({
2569
- host: r,
2570
- port: a
2571
- }), l = "", u = setTimeout(() => {
2572
- c.destroy(), s(/* @__PURE__ */ Error("clamav scan timed out"));
2573
- }, o);
2574
- c.on("error", (e) => {
2575
- clearTimeout(u), s(e);
2576
- }), c.on("connect", () => {
2577
- c.end(Bn(e, t.chunkSize));
2578
- }), c.on("data", (e) => {
2579
- l += e.toString("utf8");
2580
- }), c.on("close", () => {
2581
- clearTimeout(u);
2582
- try {
2583
- i(Vn(l));
2584
- } catch (e) {
2585
- s(e);
2586
- }
2587
- });
2588
- });
2589
- }, Un = (e = {}) => (t) => Hn(t.bytes, e), Wn = (e, t, n) => new Promise((r, i) => {
2590
- let a = Oe(e, [...t], { stdio: [
2591
- "ignore",
2592
- "ignore",
2593
- "pipe"
2594
- ] }), o = "", s = setTimeout(() => {
2595
- a.kill("SIGKILL"), i(/* @__PURE__ */ Error("ffmpeg timed out"));
2596
- }, n);
2597
- a.stderr?.on("data", (e) => {
2598
- o += String(e);
2599
- }), a.on("error", (e) => {
2600
- clearTimeout(s), i(e);
2601
- }), a.on("close", (e) => {
2602
- clearTimeout(s), e === 0 ? r() : i(/* @__PURE__ */ Error(`ffmpeg exited ${String(e)}: ${o.slice(-400)}`));
2603
- });
2604
- }), Gn = (e) => async ({ bytes: t }) => {
2605
- let n = e.ffmpegPath ?? "ffmpeg", r = e.timeoutMs ?? 3e5, i = await R(Me(je(), "voltro-tc-")), a = Me(i, "in"), o = [];
2606
- try {
2607
- await Ae(a, t);
2608
- for (let t of e.renditions) {
2609
- let e = Me(i, `out.${t.ext}`);
2610
- try {
2611
- await Wn(n, [
2612
- "-y",
2613
- "-i",
2614
- a,
2615
- ...t.args,
2616
- e
2617
- ], r);
2618
- let i = await z(e);
2619
- o.push({
2620
- bytes: new Uint8Array(i),
2621
- contentType: t.contentType,
2622
- kind: t.kind,
2623
- ...t.label === void 0 ? {} : { label: t.label }
2624
- }), await ke(e, { force: !0 });
2625
- } catch {}
2626
- }
2627
- } finally {
2628
- await ke(i, {
2629
- recursive: !0,
2630
- force: !0
2631
- }).catch(() => void 0);
2632
- }
2633
- return o;
2634
- };
2635
- //#endregion
2636
- //#region src/assetRef.ts
2637
- function Kn(e = {}) {
2638
- let t = e.nullable ?? !0, n = e.fk === !1 ? F().externalId() : ye(() => We, { onDelete: e.onDelete ?? "setNull" });
2639
- return t ? n.nullable() : n;
2640
- }
2641
- var qn = () => _e({
2642
- id: "@voltro/plugin-storage/withStorage",
2643
- fields: { asset: Kn() }
2644
- }), Jn = {
2645
- "image/png": "png",
2646
- "image/jpeg": "jpg",
2647
- "image/jpg": "jpg",
2648
- "image/gif": "gif",
2649
- "image/webp": "webp",
2650
- "image/svg+xml": "svg"
2651
- }, Yn = (e) => {
2652
- let t = /^data:([^;,]+)(;base64)?,(.*)$/s.exec(e);
2653
- if (!t) throw Error("not a data URI");
2654
- let n = t[1] || "application/octet-stream", r = !!t[2], i = t[3] ?? "";
2655
- return {
2656
- bytes: r ? new Uint8Array(Buffer.from(i, "base64")) : new Uint8Array(Buffer.from(decodeURIComponent(i), "utf8")),
2657
- contentType: n
2658
- };
2659
- }, Xn = (e, n) => v.gen(function* () {
2660
- let r = yield* v.try({
2661
- try: () => Yn(n.dataUri),
2662
- catch: (e) => new t({
2663
- provider: "avatar",
2664
- message: String(e?.message ?? e),
2665
- transient: !1,
2666
- status: 400
2667
- })
2668
- }), i = Jn[r.contentType] ?? "bin";
2669
- return yield* e.put({
2670
- bytes: r.bytes,
2671
- contentType: r.contentType,
2672
- tenantId: n.tenantId,
2673
- ownerId: n.userId,
2674
- visibility: "public",
2675
- key: `avatars/${n.userId}/avatar.${i}`
2676
- });
2677
- }), Zn = (e) => {
2678
- try {
2679
- let t = Ne(e), n = Ne("/");
2680
- return typeof t.dev != "number" || typeof n.dev != "number" ? "unknown" : t.dev === n.dev ? "same-device-as-root" : "separate-mount";
2681
- } catch {
2682
- return "unknown";
2683
- }
2684
- }, Qn = (e) => {
2685
- if (Zn(e) === "same-device-as-root") return `the capture is going to ${e}, which is on the SAME filesystem as \`/\`.\n A mounted volume would be a separate one. If this process is a container, that means the capture
2686
- dies with it — which is the exact failure it exists for. On a development machine this is normal
2687
- and can be ignored.`;
2688
- }, $n = U.read("VOLTRO_SESSION_COOKIE") ?? "voltro:session", er, tr = (e) => {
2689
- er = e;
2690
- }, nr = () => er ?? ir({}), rr = () => er === void 0 ? U.read("STORAGE_PROVIDER") === void 0 ? void 0 : ir({}) : er, ir = (e) => {
1
+ import { storageObjectNamespace as e } from "./storageNamespaces.js";
2
+ import { STORAGE_REFERENCE_CATALOGUE_TABLE as t, ensureStorageReferenceCatalogue as n, storageReferenceCatalogueTable as r } from "./referenceCatalogue.js";
3
+ import { STORAGE_BLOBS_TABLE as i, STORAGE_GRANTS_TABLE as a, STORAGE_REFS_TABLE as o, STORAGE_USAGE_TABLE as s, _voltroStorageBlobsTable as c, _voltroStorageGrantsTable as l, _voltroStorageRefsTable as u, _voltroStorageUsageTable as d } from "./table.js";
4
+ import { assignStorageReferenceInstancesInTransaction as f, requireStorageReferenceOwnership as ee } from "./storageReferenceInstances.js";
5
+ import { StorageAccessDenied as te, StorageError as p, StorageRejected as ne, StorageScanRejected as re, StorageService as m } from "./types.js";
6
+ import { storageObjectLifecycleTables as h } from "./objectLifecycle.js";
7
+ import { assignStorageObjectNamespacesInTransaction as g, requireStorageObjectNamespaces as _ } from "./storageObjectNamespaces.js";
8
+ import { bytesToStream as v, collectStream as y, concatBytes as b, fromNodeReadable as x, getObjectStream as S, putObjectStream as ie, toNodeReadable as C } from "./streamBridge.js";
9
+ import { storageEnv as w } from "./env.js";
10
+ import { azureProvider as T, clearStorageBuffer as E, databaseProvider as D, filesystemProvider as O, memoryProvider as k, readStorageBuffer as ae, s3Provider as A } from "./providers.js";
11
+ import { createTransformCache as oe } from "./transformCache.js";
12
+ import { editImage as j, parseTransformParams as se, transformCached as ce, transformFallbackReason as le, transformImage as ue, transformKey as de } from "./transform.js";
13
+ import { hashPassword as M, verifyPassword as fe } from "./access.js";
14
+ import { resolveStorageSecret as pe, signFinalizeTicket as me, signGrant as he, signMultipartTicket as ge, signResumableTicket as _e, signUploadTicket as N, verifyFinalizeTicket as ve, verifyGrant as ye, verifyMultipartTicket as P, verifyResumableTicket as be, verifyUploadTicket as F } from "./grant.js";
15
+ import { checkLimits as I, contentTypeAllowed as L, sniffMatches as R } from "./constraints.js";
16
+ import { fetchIngestBody as z } from "./ingest.js";
17
+ import { buildStorageService as xe, dataStoreGrantStore as Se, dataStoreRefStore as Ce, memoryGrantStore as we, memoryRefStore as B, refMatchesListQuery as V, storageServiceLayer as Te } from "./service.js";
18
+ import { makeStorageObjectMetadata as Ee, storagePutIntentsTable as De } from "./objectMetadata.js";
19
+ import { abortMultipartUploadDescriptor as Oe, beginMultipartUploadDescriptor as ke, beginResumableUploadDescriptor as Ae, completeMultipartUploadDescriptor as je, finalizeUploadDescriptor as Me, ingestUrlDescriptor as Ne, listGrantsDescriptor as Pe, listRefsDescriptor as Fe, mintPresignedUploadDescriptor as Ie, mintUploadTicketDescriptor as Le, mintUploadUrlDescriptor as Re, mintUrlDescriptor as ze, revokeDescriptor as Be, shareDescriptor as Ve, signMultipartPartDescriptor as He, storageRpcClientImports as Ue, uploadDescriptor as We } from "./rpc.js";
20
+ import { clamavScanner as Ge, encodeInstream as Ke, parseClamavResponse as qe } from "./scanners.js";
21
+ import { ffmpegTranscoder as Je } from "./transcodeVideo.js";
22
+ import { assetRef as Ye, withStorage as Xe } from "./assetRef.js";
23
+ import { decodeDataUri as Ze, putAvatar as Qe } from "./avatar.js";
24
+ import { durabilityNotice as $e, pathDurability as et } from "./pathDurability.js";
25
+ import { createHash as tt, randomUUID as H } from "node:crypto";
26
+ import { Effect as U, Schema as W, Stream as nt } from "effect";
27
+ import { processIdentity as rt } from "@voltro/protocol/identity";
28
+ import { StorageAccessPolicySchema as it, definePlugin as at, pluginInstanceName as G } from "@voltro/protocol";
29
+ import { readCookie as ot, resolveSessionSecret as st, verifySession as ct } from "@voltro/protocol/session";
30
+ //#region src/index.ts
31
+ var lt = w.read("VOLTRO_SESSION_COOKIE") ?? "voltro:session", K, ut = (e) => {
32
+ K = e;
33
+ }, dt = () => K ?? q({}), ft = () => K === void 0 ? w.read("STORAGE_PROVIDER") === void 0 ? void 0 : q({}) : K, q = (e) => {
2691
34
  if (e.provider && typeof e.provider == "object") return e.provider;
2692
- let t = (e.provider ?? U.read("STORAGE_PROVIDER") ?? "memory").toLowerCase(), n = U.read("S3_BUCKET", e.bucket) ?? U.read("STORAGE_BUCKET") ?? "voltro";
35
+ let t = (e.provider ?? w.read("STORAGE_PROVIDER") ?? "memory").toLowerCase(), n = w.read("S3_BUCKET", e.bucket) ?? w.read("STORAGE_BUCKET") ?? "voltro";
2693
36
  switch (t) {
2694
37
  case "s3":
2695
38
  case "minio": {
2696
- let r = U.read("S3_REGION", e.region) ?? U.read("AWS_REGION"), i = U.read("S3_ENDPOINT", e.endpoint) ?? U.read("MINIO_ENDPOINT"), a = U.read("S3_ACCESS_KEY_ID", e.accessKeyId) ?? U.read("AWS_ACCESS_KEY_ID"), o = U.read("S3_SECRET_ACCESS_KEY", e.secretAccessKey) ?? U.read("AWS_SECRET_ACCESS_KEY"), s = U.read("STORAGE_CDN_URL", e.cdnBaseUrl);
2697
- return nt({
39
+ let r = w.read("S3_REGION", e.region) ?? w.read("AWS_REGION"), i = w.read("S3_ENDPOINT", e.endpoint) ?? w.read("MINIO_ENDPOINT"), a = w.read("S3_ACCESS_KEY_ID", e.accessKeyId) ?? w.read("AWS_ACCESS_KEY_ID"), o = w.read("S3_SECRET_ACCESS_KEY", e.secretAccessKey) ?? w.read("AWS_SECRET_ACCESS_KEY"), s = w.read("STORAGE_CDN_URL", e.cdnBaseUrl), c = {
2698
40
  bucket: n,
2699
41
  name: t,
2700
42
  ...r ? { region: r } : {},
@@ -2703,25 +45,26 @@ var qn = () => _e({
2703
45
  ...o ? { secretAccessKey: o } : {},
2704
46
  ...s ? { cdnBaseUrl: s } : {},
2705
47
  ...e.publicAcl === void 0 ? {} : { publicAcl: e.publicAcl },
2706
- ...t === "minio" || U.read("S3_FORCE_PATH_STYLE") === "1" ? { forcePathStyle: !0 } : {}
2707
- });
48
+ ...t === "minio" || w.read("S3_FORCE_PATH_STYLE") === "1" ? { forcePathStyle: !0 } : {}
49
+ };
50
+ return A(c);
2708
51
  }
2709
52
  case "azure": {
2710
- let t = U.read("AZURE_STORAGE_ACCOUNT", e.accountName), r = U.read("AZURE_STORAGE_KEY", e.accountKey), i = U.read("AZURE_STORAGE_CONNECTION_STRING", e.connectionString), a = U.read("AZURE_STORAGE_ENDPOINT", e.endpoint), o = U.read("STORAGE_CDN_URL", e.cdnBaseUrl);
2711
- return at({
2712
- container: U.read("AZURE_STORAGE_CONTAINER", e.bucket) ?? n,
53
+ let t = w.read("AZURE_STORAGE_ACCOUNT", e.accountName), r = w.read("AZURE_STORAGE_KEY", e.accountKey), i = w.read("AZURE_STORAGE_CONNECTION_STRING", e.connectionString), a = w.read("AZURE_STORAGE_ENDPOINT", e.endpoint), o = w.read("STORAGE_CDN_URL", e.cdnBaseUrl), s = {
54
+ container: w.read("AZURE_STORAGE_CONTAINER", e.bucket) ?? n,
2713
55
  ...t ? { accountName: t } : {},
2714
56
  ...r ? { accountKey: r } : {},
2715
57
  ...i ? { connectionString: i } : {},
2716
58
  ...a ? { endpoint: a } : {},
2717
59
  ...o ? { cdnBaseUrl: o } : {}
2718
- });
60
+ };
61
+ return T(s);
2719
62
  }
2720
- case "database": return it();
2721
- case "filesystem": return tt({ root: U.read("STORAGE_ROOT", e.root) ?? ".voltro-storage" });
2722
- default: return et(e.name ?? "default");
63
+ case "database": return D();
64
+ case "filesystem": return O({ root: w.read("STORAGE_ROOT", e.root) ?? ".voltro-storage" });
65
+ default: return k(e.name ?? "default");
2723
66
  }
2724
- }, ar = (e) => {
67
+ }, pt = (e) => {
2725
68
  let t = "stored files (uploads, renditions) and their reads", n = "provider 'database' or 'filesystem' keeps the bytes inside the installation";
2726
69
  if (e.provider && typeof e.provider == "object") return [{
2727
70
  destination: `runtime:the '${e.provider.name}' storage provider`,
@@ -2729,9 +72,9 @@ var qn = () => _e({
2729
72
  data: ["files"],
2730
73
  disable: n
2731
74
  }];
2732
- let r = (e.provider ?? U.read("STORAGE_PROVIDER") ?? "memory").toLowerCase();
75
+ let r = (e.provider ?? w.read("STORAGE_PROVIDER") ?? "memory").toLowerCase();
2733
76
  if (r === "s3" || r === "minio") {
2734
- let r = U.read("S3_ENDPOINT", e.endpoint) ?? U.read("MINIO_ENDPOINT"), i = U.read("S3_REGION", e.region) ?? U.read("AWS_REGION") ?? "us-east-1";
77
+ let r = w.read("S3_ENDPOINT", e.endpoint) ?? w.read("MINIO_ENDPOINT"), i = w.read("S3_REGION", e.region) ?? w.read("AWS_REGION") ?? "us-east-1";
2735
78
  return [{
2736
79
  destination: r ?? `s3.${i}.amazonaws.com`,
2737
80
  purpose: t,
@@ -2740,7 +83,7 @@ var qn = () => _e({
2740
83
  }];
2741
84
  }
2742
85
  if (r === "azure") {
2743
- let r = U.read("AZURE_STORAGE_ENDPOINT", e.endpoint), i = U.read("AZURE_STORAGE_ACCOUNT", e.accountName);
86
+ let r = w.read("AZURE_STORAGE_ENDPOINT", e.endpoint), i = w.read("AZURE_STORAGE_ACCOUNT", e.accountName);
2744
87
  return [{
2745
88
  destination: r ?? (i === void 0 ? "runtime:the Azure storage connection string" : `${i}.blob.core.windows.net`),
2746
89
  purpose: t,
@@ -2749,11 +92,11 @@ var qn = () => _e({
2749
92
  }];
2750
93
  }
2751
94
  return [];
2752
- }, or = (e) => {
95
+ }, mt = (e) => {
2753
96
  if (e !== void 0) return e;
2754
- let t = U.read("STORAGE_ALLOWED_ORIGINS");
97
+ let t = w.read("STORAGE_ALLOWED_ORIGINS");
2755
98
  return t ? t.trim() === "*" ? "*" : t.split(",").map((e) => e.trim()).filter(Boolean) : [];
2756
- }, sr = (e, t) => {
99
+ }, J = (e, t) => {
2757
100
  if (!e || t !== "*" && !t.includes(e)) return {};
2758
101
  let n = {
2759
102
  "access-control-allow-origin": t === "*" ? "*" : e,
@@ -2763,7 +106,7 @@ var qn = () => _e({
2763
106
  vary: "Origin"
2764
107
  };
2765
108
  return t !== "*" && (n["access-control-allow-credentials"] = "true"), n;
2766
- }, cr = (e) => ({
109
+ }, ht = (e) => ({
2767
110
  id: e.id,
2768
111
  tenantId: e.tenantId,
2769
112
  ownerId: e.ownerId,
@@ -2786,29 +129,29 @@ var qn = () => _e({
2786
129
  caption: e.caption ?? null,
2787
130
  derivedFrom: e.derivedFrom ?? null,
2788
131
  kind: e.kind ?? null
2789
- }), lr = () => new t({
132
+ }), Y = () => new p({
2790
133
  provider: "storage",
2791
134
  message: "not permitted to administer sharing for this object",
2792
135
  transient: !1,
2793
136
  status: 403
2794
- }), ur = (e, t, n) => {
137
+ }), X = (e, t, n) => {
2795
138
  let r = n.request.subject;
2796
- return (r.scopes ?? []).includes("admin:full") ? v.void : e.head(t, { tenantId: r.tenantId ?? null }).pipe(v.catch(() => v.fail(lr())), v.flatMap((e) => {
139
+ return (r.scopes ?? []).includes("admin:full") ? U.void : e.head(t, { tenantId: r.tenantId ?? null }).pipe(U.catch(() => U.fail(Y())), U.flatMap((e) => {
2797
140
  let t = e?.ownerId;
2798
- return t != null && t === r.id ? v.void : v.fail(lr());
141
+ return t != null && t === r.id ? U.void : U.fail(Y());
2799
142
  }));
2800
- }, dr = () => new t({
143
+ }, gt = () => new p({
2801
144
  provider: "storage",
2802
145
  message: "an upload needs an identified caller: this request carries no subject, and the app has not set `anonymousUploads: true` on storagePlugin. The ticket attributes the object to whoever minted it — with no subject there is nobody to attribute it to, so the finalized object would carry no owner and no tenant and no later owner check, tenant filter or quota could reach it.",
2803
146
  transient: !1,
2804
147
  status: 401
2805
- }), fr = (e, t) => {
148
+ }), Z = (e, t) => {
2806
149
  let n = e.request.subject.id ?? null, r = e.request.subject.tenantId ?? null;
2807
- return n === null && !t ? v.fail(dr()) : v.succeed({
150
+ return n === null && !t ? U.fail(gt()) : U.succeed({
2808
151
  id: n,
2809
152
  tenantId: r
2810
153
  });
2811
- }, pr = (e, t) => e !== null && e !== (t ?? null), mr = (e) => ({
154
+ }, _t = (e, t) => e !== null && e !== (t ?? null), Q = (e) => ({
2812
155
  id: e.id,
2813
156
  refId: e.refId,
2814
157
  principalType: e.principalType,
@@ -2817,94 +160,111 @@ var qn = () => _e({
2817
160
  createdAt: e.createdAt.toISOString(),
2818
161
  expiresAt: e.expiresAt ? e.expiresAt.toISOString() : null,
2819
162
  createdBy: e.createdBy
2820
- }), hr = "@voltro/plugin-storage", gr = (e = {}) => w({
2821
- base: hr,
163
+ }), $ = "@voltro/plugin-storage", vt = (e = {}) => G({
164
+ base: $,
2822
165
  alias: e.alias,
2823
166
  instance: e.name
2824
- }), _r = (i = {}) => {
2825
- let y = w({
2826
- base: hr,
2827
- alias: i.alias,
2828
- instance: i.name
2829
- }), b = y === hr ? "/_voltro/storage" : `/_voltro/storage/i/${Buffer.from(y).toString("hex")}`, x = ir(i);
2830
- tr(x);
2831
- let ue = U.read("S3_BUCKET", i.bucket) ?? U.read("STORAGE_BUCKET") ?? "voltro", T = U.read("VOLTRO_PUBLIC_URL", i.publicBaseUrl), E = or(i.allowedOrigins), D = i.limits?.maxBytes, O = i.anonymousUploads === !0, de = 5242880, fe = 21600, k = i.refStore === void 0 || i.refStore === "memory", pe = i.grantStore === void 0 || i.grantStore === "memory", A = (e, n) => v.gen(function* () {
2832
- let r = (e) => S.decodeUnknownEffect(ae)(e, { onExcessProperty: "error" }).pipe(v.mapError(() => new t({
167
+ }), yt = (e) => e.reason === "too-large" ? 413 : e.reason === "operation-identity-reused" || e.reason === "operation-store-unbound" || e.reason === "claim-not-held" ? 409 : 415, bt = (e = {}) => {
168
+ let t = G({
169
+ base: $,
170
+ alias: e.alias,
171
+ instance: e.name
172
+ }), r = t === $ ? "/_voltro/storage" : `/_voltro/storage/i/${Buffer.from(t).toString("hex")}`, i = q(e);
173
+ ut(i);
174
+ let a = w.read("S3_BUCKET", e.bucket) ?? w.read("STORAGE_BUCKET") ?? "voltro", o = w.read("VOLTRO_PUBLIC_URL", e.publicBaseUrl), s = mt(e.allowedOrigins), c = e.limits?.maxBytes, l = e.anonymousUploads === !0, u = 5242880, d = 21600, f = e.refStore === void 0 || e.refStore === "memory", m = e.grantStore === void 0 || e.grantStore === "memory", h = (t, n) => U.gen(function* () {
175
+ let r = (e) => W.decodeUnknownEffect(it)(e, { onExcessProperty: "error" }).pipe(U.mapError(() => new p({
2833
176
  provider: "storage",
2834
177
  message: "Invalid upload access policy",
2835
178
  transient: !1,
2836
179
  status: 400
2837
- }))), a = e.access === void 0 ? void 0 : yield* r(e.access), o = e.visibility ?? "private";
2838
- if (a !== void 0 && o === "public") return yield* v.fail(new t({
180
+ }))), i = t.access === void 0 ? void 0 : yield* r(t.access), a = t.visibility ?? "private";
181
+ if (i !== void 0 && a === "public") return yield* U.fail(new p({
2839
182
  provider: "storage",
2840
183
  message: "An access policy requires a private upload",
2841
184
  transient: !1,
2842
185
  status: 400
2843
186
  }));
2844
- let s = i.uploadAccess;
2845
- if (a !== void 0 && typeof s != "function") return yield* v.fail(new t({
187
+ let o = e.uploadAccess;
188
+ if (i !== void 0 && typeof o != "function") return yield* U.fail(new p({
2846
189
  provider: "storage",
2847
190
  message: "Requested upload access requires an uploadAccess authorization function on storagePlugin",
2848
191
  transient: !1,
2849
192
  status: 403
2850
193
  }));
2851
- let c = typeof s == "function" ? yield* s({
194
+ let s = typeof o == "function" ? yield* o({
2852
195
  subject: n,
2853
- requested: a,
2854
- visibility: o,
2855
- contentType: e.contentType
2856
- }) : o === "private" ? s : void 0, l = c === void 0 ? void 0 : yield* r(c);
2857
- return o === "public" ? l !== void 0 && l.length > 0 ? yield* v.fail(new t({
196
+ requested: i,
197
+ visibility: a,
198
+ contentType: t.contentType
199
+ }) : a === "private" ? o : void 0, c = s === void 0 ? void 0 : yield* r(s);
200
+ return a === "public" ? c !== void 0 && c.length > 0 ? yield* U.fail(new p({
2858
201
  provider: "storage",
2859
202
  message: "A public upload cannot carry an access policy",
2860
203
  transient: !1,
2861
204
  status: 400
2862
- })) : {} : l === void 0 ? {} : { access: l };
2863
- }), j = { current: k ? on() : i.refStore }, M = { current: pe ? un() : i.grantStore }, me = { current: void 0 }, he = {
2864
- insert: (e) => j.current.insert(e),
2865
- getById: (e) => j.current.getById(e),
2866
- delete: (e) => j.current.delete(e),
2867
- statistics: () => j.current.statistics(),
2868
- listRecent: (e) => j.current.listRecent(e),
2869
- countByKey: (e, t) => j.current.countByKey(e, t),
2870
- usageByTenant: (e) => j.current.usageByTenant(e),
2871
- consumeUsage: (e, t, n) => j.current.consumeUsage(e, t, n),
2872
- releaseUsage: (e, t) => j.current.releaseUsage(e, t),
2873
- listByDerivedFrom: (e) => j.current.listByDerivedFrom(e),
2874
- listRefs: (e) => j.current.listRefs(e),
205
+ })) : {} : c === void 0 ? {} : { access: c };
206
+ }), g = { current: f ? B() : e.refStore }, v = { current: m ? we() : e.grantStore }, y = { current: void 0 }, b = {
207
+ get catalogueId() {
208
+ return g.current.catalogueId;
209
+ },
210
+ insert: (e) => g.current.insert(e),
211
+ getById: (e) => g.current.getById(e),
212
+ delete: (e) => g.current.delete(e),
213
+ statistics: () => g.current.statistics(),
214
+ listRecent: (e) => g.current.listRecent(e),
215
+ countByKey: (e, t) => g.current.countByKey(e, t),
216
+ usageByTenant: (e) => g.current.usageByTenant(e),
217
+ consumeUsage: (e, t, n) => g.current.consumeUsage(e, t, n),
218
+ releaseUsage: (e, t) => g.current.releaseUsage(e, t),
219
+ listByDerivedFrom: (e) => g.current.listByDerivedFrom(e),
220
+ listRefs: (e) => g.current.listRefs(e),
2875
221
  get setVisibility() {
2876
- return j.current.setVisibility;
222
+ return g.current.setVisibility;
2877
223
  },
2878
224
  get countPublicByKey() {
2879
- return j.current.countPublicByKey;
225
+ return g.current.countPublicByKey;
2880
226
  }
2881
- }, ge = {
2882
- insert: (e) => M.current.insert(e),
2883
- delete: (e) => M.current.delete(e),
2884
- getById: (e) => M.current.getById(e),
2885
- listByRef: (e) => M.current.listByRef(e),
2886
- deleteByRef: (e) => M.current.deleteByRef(e)
2887
- }, _e = {
2888
- httpPath: b,
2889
- provider: x,
2890
- refStore: he,
2891
- grantStore: ge,
2892
- bucket: ue,
2893
- ...i.tenantPrefix === void 0 ? {} : { tenantPrefix: i.tenantPrefix },
2894
- ...i.attempts === void 0 ? {} : { attempts: i.attempts },
2895
- ...i.urlExpiresInSec === void 0 ? {} : { urlExpiresInSec: i.urlExpiresInSec },
2896
- ...i.access === void 0 ? {} : { access: i.access },
2897
- ...i.limits === void 0 ? {} : { limits: i.limits },
2898
- ...i.ingest === void 0 ? {} : { ingest: i.ingest },
2899
- ...i.scan === void 0 ? {} : { scan: i.scan },
2900
- ...i.videoProbe === void 0 ? {} : { videoProbe: i.videoProbe },
2901
- ...i.transcode === void 0 ? {} : { transcode: i.transcode },
2902
- ...i.autoTranscode === void 0 ? {} : { autoTranscode: i.autoTranscode },
2903
- ...T ? { publicBaseUrl: T } : {},
2904
- ...i.normalizeImages === void 0 ? {} : { normalizeImages: i.normalizeImages },
2905
- ...i.quota === void 0 ? {} : { quota: i.quota },
2906
- objects: () => me.current
2907
- }, ve = gn(_e), N = hn(_e), ye = `${b}/`, P = (e) => v.runPromise(e.pipe(v.catch(() => v.succeed(null)))), F = (e, t) => {
227
+ }, x = {
228
+ insert: (e) => v.current.insert(e),
229
+ delete: (e) => v.current.delete(e),
230
+ getById: (e) => v.current.getById(e),
231
+ listByRef: (e) => v.current.listByRef(e),
232
+ deleteByRef: (e) => v.current.deleteByRef(e)
233
+ }, S = {
234
+ httpPath: r,
235
+ storageInstance: t,
236
+ provider: i,
237
+ refStore: b,
238
+ grantStore: x,
239
+ bucket: a,
240
+ ...e.tenantPrefix === void 0 ? {} : { tenantPrefix: e.tenantPrefix },
241
+ ...e.attempts === void 0 ? {} : { attempts: e.attempts },
242
+ ...e.urlExpiresInSec === void 0 ? {} : { urlExpiresInSec: e.urlExpiresInSec },
243
+ ...e.access === void 0 ? {} : { access: e.access },
244
+ ...e.limits === void 0 ? {} : { limits: e.limits },
245
+ ...e.ingest === void 0 ? {} : { ingest: e.ingest },
246
+ ...e.scan === void 0 ? {} : { scan: e.scan },
247
+ ...e.videoProbe === void 0 ? {} : { videoProbe: e.videoProbe },
248
+ ...e.transcode === void 0 ? {} : { transcode: e.transcode },
249
+ ...e.autoTranscode === void 0 ? {} : { autoTranscode: e.autoTranscode },
250
+ ...o ? { publicBaseUrl: o } : {},
251
+ ...e.normalizeImages === void 0 ? {} : { normalizeImages: e.normalizeImages },
252
+ ...e.quota === void 0 ? {} : { quota: e.quota },
253
+ objects: () => y.current
254
+ }, ie = Te(S), C = xe(S), T = (e) => C.uploadTicketScope().pipe(U.flatMap((t) => t === e.writeScope ? U.void : U.fail(new p({
255
+ provider: "storage",
256
+ message: "Upload ticket belongs to another storage destination",
257
+ transient: !1,
258
+ status: 409
259
+ })))), E = (e, t) => U.runPromise(T(e).pipe(U.match({
260
+ onSuccess: () => null,
261
+ onFailure: (e) => ({
262
+ status: e.status ?? 503,
263
+ body: e.status === 409 ? e.message : "Storage upload destination could not be checked",
264
+ contentType: "text/plain",
265
+ headers: t
266
+ })
267
+ }))), D = `${r}/`, O = (e) => U.runPromise(e.pipe(U.catch(() => U.succeed(null)))), k = (e, t) => {
2908
268
  if (!e) return "invalid";
2909
269
  let n = /^bytes=(\d*)-(\d*)$/.exec(e.trim());
2910
270
  if (!n) return "invalid";
@@ -2925,34 +285,34 @@ var qn = () => _e({
2925
285
  start: a,
2926
286
  endInclusive: o
2927
287
  };
2928
- }, be = i.publicCacheSeconds === void 0 ? "public, max-age=31536000, immutable" : `public, max-age=${Math.max(0, Math.floor(i.publicCacheSeconds))}`, xe = /^(?:image\/(?!svg)|video\/|audio\/|application\/pdf(?:;|$)|text\/plain(?:;|$))/i, Se = (e) => ({
288
+ }, ae = e.publicCacheSeconds === void 0 ? "public, max-age=31536000, immutable" : `public, max-age=${Math.max(0, Math.floor(e.publicCacheSeconds))}`, A = /^(?:image\/(?!svg)|video\/|audio\/|application\/pdf(?:;|$)|text\/plain(?:;|$))/i, j = (e) => ({
2929
289
  "x-content-type-options": "nosniff",
2930
- "content-disposition": xe.test(e) ? "inline" : "attachment"
2931
- }), I = ot(), we = async (e, t, n, r) => {
290
+ "content-disposition": A.test(e) ? "inline" : "attachment"
291
+ }), ce = oe(), M = async (e, t, n, r) => {
2932
292
  if (n) {
2933
- let r, i = await I.getOrCreate(_t(JSON.stringify([e.id, e.checksum]), e.contentType, n), async () => {
2934
- let t = await P(N.get(e.id));
2935
- return t ? (r = t.bytes, mt(t.bytes, e.contentType, n)) : null;
293
+ let r, i = await ce.getOrCreate(de(JSON.stringify([e.id, e.checksum]), e.contentType, n), async () => {
294
+ let t = await O(C.get(e.id));
295
+ return t ? (r = t.bytes, ue(t.bytes, e.contentType, n)) : null;
2936
296
  }).catch(() => null);
2937
- if (!i && r === void 0 && (r = (await P(N.get(e.id)))?.bytes), !i && r === void 0) return {
297
+ if (!i && r === void 0 && (r = (await O(C.get(e.id)))?.bytes), !i && r === void 0) return {
2938
298
  status: 404,
2939
299
  body: "not found",
2940
300
  contentType: "text/plain"
2941
301
  };
2942
- let a = i ? i.bytes : r, o = i ? i.contentType : e.contentType, s = await pt(e.contentType, i !== null);
302
+ let a = i ? i.bytes : r, o = i ? i.contentType : e.contentType, s = await le(e.contentType, i !== null);
2943
303
  return {
2944
304
  status: 200,
2945
305
  body: a,
2946
306
  contentType: o,
2947
307
  headers: {
2948
- ...Se(o),
308
+ ...j(o),
2949
309
  "cache-control": t,
2950
310
  "accept-ranges": "none",
2951
311
  ...s === null ? {} : { "x-voltro-transform": `original; reason=${s}` }
2952
312
  }
2953
313
  };
2954
314
  }
2955
- let i = r === void 0 ? "invalid" : F(r, e.size);
315
+ let i = r === void 0 ? "invalid" : k(r, e.size);
2956
316
  if (i === "unsatisfiable") return {
2957
317
  status: 416,
2958
318
  body: "range not satisfiable",
@@ -2963,13 +323,13 @@ var qn = () => _e({
2963
323
  }
2964
324
  };
2965
325
  if (i !== "invalid") {
2966
- let n = await P(N.getRange(e.id, i));
326
+ let n = await O(C.getRange(e.id, i));
2967
327
  return n ? {
2968
328
  status: 206,
2969
329
  body: n.bytes,
2970
330
  contentType: e.contentType,
2971
331
  headers: {
2972
- ...Se(e.contentType),
332
+ ...j(e.contentType),
2973
333
  "cache-control": t,
2974
334
  "accept-ranges": "bytes",
2975
335
  "content-range": `bytes ${i.start}-${i.endInclusive}/${n.totalSize}`
@@ -2980,69 +340,69 @@ var qn = () => _e({
2980
340
  contentType: "text/plain"
2981
341
  };
2982
342
  }
2983
- let a = await P(N.getStream(e.id));
343
+ let a = await O(C.getStream(e.id));
2984
344
  return a ? {
2985
345
  status: 200,
2986
346
  contentType: e.contentType,
2987
347
  headers: {
2988
- ...Se(e.contentType),
348
+ ...j(e.contentType),
2989
349
  "cache-control": t,
2990
350
  "accept-ranges": "bytes"
2991
351
  },
2992
352
  byteStream: {
2993
353
  contentLength: e.size,
2994
- stream: () => C.toReadableStream(a.stream)
354
+ stream: () => nt.toReadableStream(a.stream)
2995
355
  }
2996
356
  } : {
2997
357
  status: 404,
2998
358
  body: "not found",
2999
359
  contentType: "text/plain"
3000
360
  };
3001
- }, Ee = async (e) => {
3002
- let t = e.path.startsWith(ye) ? e.path.slice(ye.length).split("/")[0] ?? "" : "";
361
+ }, fe = async (e) => {
362
+ let t = e.path.startsWith(D) ? e.path.slice(D.length).split("/")[0] ?? "" : "";
3003
363
  if (!t) return {
3004
364
  status: 404,
3005
365
  body: "not found",
3006
366
  contentType: "text/plain"
3007
367
  };
3008
- let n = await P(N.head(t));
368
+ let n = await O(C.head(t));
3009
369
  if (!n) return {
3010
370
  status: 404,
3011
371
  body: "not found",
3012
372
  contentType: "text/plain"
3013
373
  };
3014
- let r = lt(e.query), i = e.headers.range, a = n.derivedFrom == null ? null : await P(N.head(n.derivedFrom));
3015
- if (n.derivedFrom != null && a === null) return {
374
+ let a = se(e.query), o = e.headers.range, s = n.derivedFrom == null ? null : await O(C.head(n.derivedFrom));
375
+ if (n.derivedFrom != null && s === null) return {
3016
376
  status: 404,
3017
377
  body: "not found",
3018
378
  contentType: "text/plain"
3019
379
  };
3020
- if (n.visibility === "public" && (a === null || a.visibility === "public")) {
3021
- let e = x.publicUrl?.(n.key) ?? null;
3022
- return e && !r ? {
380
+ if (n.visibility === "public" && (s === null || s.visibility === "public")) {
381
+ let e = i.publicUrl?.(n.key) ?? null;
382
+ return e && !a ? {
3023
383
  status: 302,
3024
384
  headers: {
3025
385
  location: e,
3026
386
  "cache-control": "public, max-age=300"
3027
387
  }
3028
- } : we(n, be, r, i);
388
+ } : M(n, ae, a, o);
3029
389
  }
3030
- let o = !1, s = e.query ? new URLSearchParams(e.query).get("t") : null;
3031
- if (s) {
3032
- let e = Nt(s);
3033
- o = !!e && (e.refId === t || a !== null && e.refId === a.id) && e.audience === b;
390
+ let c = !1, l = e.query ? new URLSearchParams(e.query).get("t") : null;
391
+ if (l) {
392
+ let e = ye(l);
393
+ c = !!e && (e.refId === t || s !== null && e.refId === s.id) && e.audience === r;
3034
394
  }
3035
- if (!o) {
3036
- let t = se(e.headers.cookie, $n), r = t ? le(t, ce()) : null;
3037
- r && (o = await P(N.checkAccess(n, r)) === !0);
395
+ if (!c) {
396
+ let t = ot(e.headers.cookie, lt), r = t ? ct(t, st()) : null;
397
+ r && (c = await O(C.checkAccess(n, r)) === !0);
3038
398
  }
3039
- if (!o) return {
399
+ if (!c) return {
3040
400
  status: 403,
3041
401
  body: "forbidden",
3042
402
  contentType: "text/plain"
3043
403
  };
3044
- if (x.presigns && !r) {
3045
- let e = await P(x.getUrl(n.key, 300));
404
+ if (i.presigns && !a) {
405
+ let e = await O(i.getUrl(n.key, 300));
3046
406
  if (e && /^https?:/.test(e)) return {
3047
407
  status: 302,
3048
408
  headers: {
@@ -3051,12 +411,12 @@ var qn = () => _e({
3051
411
  }
3052
412
  };
3053
413
  }
3054
- return we(n, "private, no-store", r, i);
3055
- }, L = {
414
+ return M(n, "private, no-store", a, o);
415
+ }, pe = {
3056
416
  method: "GET",
3057
- path: b,
417
+ path: r,
3058
418
  handle: async (e) => {
3059
- let t = await Ee(e), n = sr(e.headers.origin, E);
419
+ let t = await fe(e), n = J(e.headers.origin, s);
3060
420
  return Object.keys(n).length === 0 ? t : {
3061
421
  ...t,
3062
422
  headers: {
@@ -3065,128 +425,127 @@ var qn = () => _e({
3065
425
  }
3066
426
  };
3067
427
  }
3068
- }, De = {
428
+ }, he = {
3069
429
  method: "*",
3070
- path: `${b}/upload`,
430
+ path: `${r}/upload`,
3071
431
  originGuard: "exempt",
3072
432
  handle: async (e) => {
3073
- let t = sr(e.headers.origin, E);
433
+ let n = J(e.headers.origin, s);
3074
434
  if (e.method === "OPTIONS") return {
3075
435
  status: 204,
3076
- headers: t
436
+ headers: n
3077
437
  };
3078
438
  if (e.method !== "POST") return {
3079
439
  status: 405,
3080
440
  body: "method not allowed",
3081
441
  contentType: "text/plain",
3082
- headers: t
442
+ headers: n
3083
443
  };
3084
- let n = e.query ? new URLSearchParams(e.query).get("ticket") : null, r = n ? It(n) : null;
3085
- if (!r || r.instance !== y) return {
444
+ let r = e.query ? new URLSearchParams(e.query).get("ticket") : null, i = r ? F(r) : null;
445
+ if (!i || i.instance !== t) return {
3086
446
  status: 401,
3087
447
  body: "invalid or expired upload ticket",
3088
448
  contentType: "text/plain",
3089
- headers: t
3090
- };
3091
- if (r.replicaId !== void 0 && r.replicaId !== ie().replicaId) return {
3092
- status: 409,
3093
- body: "upload ticket belongs to another replica",
3094
- contentType: "text/plain",
3095
- headers: t
449
+ headers: n
3096
450
  };
451
+ let a = await E(i, n);
452
+ if (a) return a;
3097
453
  if (e.rawBody.length === 0) return {
3098
454
  status: 400,
3099
455
  body: "empty body",
3100
456
  contentType: "text/plain",
3101
- headers: t
457
+ headers: n
3102
458
  };
3103
- if (r.max && e.rawBody.length > r.max) return {
459
+ if (i.max && e.rawBody.length > i.max) return {
3104
460
  status: 413,
3105
461
  body: "payload too large",
3106
462
  contentType: "text/plain",
3107
- headers: t
463
+ headers: n
3108
464
  };
3109
- let i = await v.runPromise(N.put({
465
+ let o = await U.runPromise(C.put({
3110
466
  bytes: e.rawBody,
3111
- contentType: r.ct,
3112
- tenantId: r.tenant,
3113
- ownerId: r.sub,
3114
- visibility: r.vis,
3115
- ...r.access === void 0 ? {} : { access: r.access },
3116
- ...r.operationId === void 0 ? {} : { operationId: r.operationId },
3117
- ...r.key === void 0 ? {} : { key: r.key },
3118
- ...r.folder === void 0 ? {} : { folder: r.folder },
3119
- ...r.tags === void 0 ? {} : { tags: r.tags },
3120
- ...r.alt === void 0 ? {} : { alt: r.alt },
3121
- ...r.caption === void 0 ? {} : { caption: r.caption }
3122
- }).pipe(v.flatMap((e) => N.getUrl(e.id).pipe(v.map((t) => ({
467
+ contentType: i.ct,
468
+ tenantId: i.tenant,
469
+ ownerId: i.sub,
470
+ visibility: i.vis,
471
+ ...i.access === void 0 ? {} : { access: i.access },
472
+ ...i.operationId === void 0 ? {} : { operationId: i.operationId },
473
+ ...i.key === void 0 ? {} : { key: i.key },
474
+ ...i.folder === void 0 ? {} : { folder: i.folder },
475
+ ...i.tags === void 0 ? {} : { tags: i.tags },
476
+ ...i.alt === void 0 ? {} : { alt: i.alt },
477
+ ...i.caption === void 0 ? {} : { caption: i.caption }
478
+ }).pipe(U.flatMap((e) => C.getUrl(e.id).pipe(U.map((t) => ({
3123
479
  kind: "ok",
3124
480
  ref: e,
3125
481
  url: t
3126
- })))), v.catchTags({
3127
- StorageRejected: (e) => v.succeed({
482
+ })))), U.catchTags({
483
+ StorageRejected: (e) => U.succeed({
3128
484
  kind: "rejected",
3129
- status: e.reason === "too-large" ? 413 : 415,
485
+ status: yt(e),
3130
486
  detail: e.detail
3131
487
  }),
3132
- StorageScanRejected: (e) => v.succeed({
488
+ StorageScanRejected: (e) => U.succeed({
3133
489
  kind: "scan",
3134
490
  threat: e.threat
3135
491
  }),
3136
- StorageError: (e) => v.succeed({
492
+ StorageError: (e) => U.succeed({
3137
493
  kind: "error",
3138
- message: e.message
494
+ message: e.message,
495
+ status: e.status ?? 500
3139
496
  })
3140
497
  })));
3141
- return i.kind === "ok" ? {
498
+ return o.kind === "ok" ? {
3142
499
  status: 201,
3143
500
  body: JSON.stringify({
3144
- id: i.ref.id,
3145
- url: i.url,
3146
- contentType: i.ref.contentType,
3147
- size: i.ref.size
501
+ id: o.ref.id,
502
+ url: o.url,
503
+ contentType: o.ref.contentType,
504
+ size: o.ref.size
3148
505
  }),
3149
506
  contentType: "application/json",
3150
- headers: t
3151
- } : i.kind === "rejected" ? {
3152
- status: i.status,
3153
- body: i.detail,
507
+ headers: n
508
+ } : o.kind === "rejected" ? {
509
+ status: o.status,
510
+ body: o.detail,
3154
511
  contentType: "text/plain",
3155
- headers: t
3156
- } : i.kind === "scan" ? {
512
+ headers: n
513
+ } : o.kind === "scan" ? {
3157
514
  status: 422,
3158
- body: `rejected: ${i.threat}`,
515
+ body: `rejected: ${o.threat}`,
3159
516
  contentType: "text/plain",
3160
- headers: t
517
+ headers: n
3161
518
  } : {
3162
- status: 500,
3163
- body: i.message,
519
+ status: o.status,
520
+ body: o.message,
3164
521
  contentType: "text/plain",
3165
- headers: t
522
+ headers: n
3166
523
  };
3167
524
  }
3168
- }, Oe = {
525
+ }, I = {
3169
526
  method: "*",
3170
- path: `${b}/upload/resumable`,
527
+ path: `${r}/upload/resumable`,
3171
528
  originGuard: "exempt",
3172
529
  handle: async (e) => {
3173
- let t = sr(e.headers.origin, E);
530
+ let n = J(e.headers.origin, s);
3174
531
  if (e.method === "OPTIONS") return {
3175
532
  status: 204,
3176
- headers: t
533
+ headers: n
3177
534
  };
3178
- let n = new URLSearchParams(e.query || ""), r = Bt(n.get("token") ?? "");
3179
- if (!r || r.instance !== y) return {
535
+ let r = new URLSearchParams(e.query || ""), i = be(r.get("token") ?? "");
536
+ if (!i || i.instance !== t) return {
3180
537
  status: 401,
3181
538
  body: "invalid or expired resumable token",
3182
539
  contentType: "text/plain",
3183
- headers: t
540
+ headers: n
3184
541
  };
542
+ let a = await E(i, n);
543
+ if (a) return a;
3185
544
  if (e.method === "GET" || e.method === "HEAD") {
3186
- let e = await v.runPromise(N.resumableStatus({
3187
- uploadId: r.id,
3188
- tenantId: r.tenant
3189
- }).pipe(v.match({
545
+ let e = await U.runPromise(C.resumableStatus({
546
+ uploadId: i.id,
547
+ tenantId: i.tenant
548
+ }).pipe(U.match({
3190
549
  onFailure: (e) => ({ error: e.message }),
3191
550
  onSuccess: (e) => e
3192
551
  })));
@@ -3194,13 +553,13 @@ var qn = () => _e({
3194
553
  status: 500,
3195
554
  body: e.error,
3196
555
  contentType: "text/plain",
3197
- headers: t
556
+ headers: n
3198
557
  } : {
3199
558
  status: 200,
3200
559
  body: JSON.stringify(e),
3201
560
  contentType: "application/json",
3202
561
  headers: {
3203
- ...t,
562
+ ...n,
3204
563
  "upload-offset": String(e.offset)
3205
564
  }
3206
565
  };
@@ -3209,168 +568,177 @@ var qn = () => _e({
3209
568
  status: 405,
3210
569
  body: "method not allowed",
3211
570
  contentType: "text/plain",
3212
- headers: t
571
+ headers: n
3213
572
  };
3214
- let i = Number(n.get("index"));
3215
- if (!Number.isInteger(i) || i < 0) return {
573
+ let o = Number(r.get("index"));
574
+ if (!Number.isInteger(o) || o < 0) return {
3216
575
  status: 400,
3217
576
  body: "missing/invalid chunk index",
3218
577
  contentType: "text/plain",
3219
- headers: t
578
+ headers: n
3220
579
  };
3221
580
  if (e.rawBody.length === 0) return {
3222
581
  status: 400,
3223
582
  body: "empty chunk",
3224
583
  contentType: "text/plain",
3225
- headers: t
584
+ headers: n
3226
585
  };
3227
- let a = n.get("final") === "1", o = await v.runPromise(N.putResumableChunk({
3228
- uploadId: r.id,
3229
- tenantId: r.tenant,
3230
- index: i,
586
+ let c = r.get("final") === "1", l = await U.runPromise(C.putResumableChunk({
587
+ uploadId: i.id,
588
+ tenantId: i.tenant,
589
+ index: o,
3231
590
  bytes: e.rawBody
3232
- }).pipe(v.flatMap(() => a ? N.finalizeResumable({
3233
- uploadId: r.id,
3234
- count: i + 1,
3235
- contentType: r.ct,
3236
- tenantId: r.tenant,
3237
- ownerId: r.sub,
3238
- visibility: r.vis,
3239
- ...r.access === void 0 ? {} : { access: r.access },
3240
- ...r.folder === void 0 ? {} : { folder: r.folder },
3241
- ...r.tags === void 0 ? {} : { tags: r.tags },
3242
- ...r.alt === void 0 ? {} : { alt: r.alt },
3243
- ...r.caption === void 0 ? {} : { caption: r.caption }
3244
- }).pipe(v.flatMap((e) => N.getUrl(e.id).pipe(v.map((t) => ({
591
+ }).pipe(U.flatMap(() => c ? C.finalizeResumable({
592
+ uploadId: i.id,
593
+ count: o + 1,
594
+ contentType: i.ct,
595
+ tenantId: i.tenant,
596
+ ownerId: i.sub,
597
+ visibility: i.vis,
598
+ ...i.access === void 0 ? {} : { access: i.access },
599
+ ...i.folder === void 0 ? {} : { folder: i.folder },
600
+ ...i.tags === void 0 ? {} : { tags: i.tags },
601
+ ...i.alt === void 0 ? {} : { alt: i.alt },
602
+ ...i.caption === void 0 ? {} : { caption: i.caption }
603
+ }).pipe(U.flatMap((e) => C.getUrl(e.id).pipe(U.map((t) => ({
3245
604
  kind: "done",
3246
605
  ref: e,
3247
606
  url: t
3248
- }))))) : v.succeed({ kind: "chunk" })), v.catchTags({
3249
- StorageRejected: (e) => v.succeed({
607
+ }))))) : U.succeed({ kind: "chunk" })), U.catchTags({
608
+ StorageRejected: (e) => U.succeed({
3250
609
  kind: "rejected",
3251
- status: e.reason === "too-large" ? 413 : 415,
610
+ status: yt(e),
3252
611
  detail: e.detail
3253
612
  }),
3254
- StorageScanRejected: (e) => v.succeed({
613
+ StorageScanRejected: (e) => U.succeed({
3255
614
  kind: "scan",
3256
615
  threat: e.threat
3257
616
  }),
3258
- StorageError: (e) => v.succeed({
617
+ StorageError: (e) => U.succeed({
3259
618
  kind: "error",
3260
- message: e.message
619
+ message: e.message,
620
+ status: e.status ?? 500
3261
621
  })
3262
622
  })));
3263
- return o.kind === "chunk" ? {
623
+ return l.kind === "chunk" ? {
3264
624
  status: 204,
3265
625
  headers: {
3266
- ...t,
3267
- "upload-offset": String(i + 1)
626
+ ...n,
627
+ "upload-offset": String(o + 1)
3268
628
  }
3269
- } : o.kind === "done" ? {
629
+ } : l.kind === "done" ? {
3270
630
  status: 201,
3271
631
  body: JSON.stringify({
3272
- id: o.ref.id,
3273
- url: o.url,
3274
- contentType: o.ref.contentType,
3275
- size: o.ref.size
632
+ id: l.ref.id,
633
+ url: l.url,
634
+ contentType: l.ref.contentType,
635
+ size: l.ref.size
3276
636
  }),
3277
637
  contentType: "application/json",
3278
- headers: t
3279
- } : o.kind === "rejected" ? {
3280
- status: o.status,
3281
- body: o.detail,
638
+ headers: n
639
+ } : l.kind === "rejected" ? {
640
+ status: l.status,
641
+ body: l.detail,
3282
642
  contentType: "text/plain",
3283
- headers: t
3284
- } : o.kind === "scan" ? {
643
+ headers: n
644
+ } : l.kind === "scan" ? {
3285
645
  status: 422,
3286
- body: `rejected: ${o.threat}`,
646
+ body: `rejected: ${l.threat}`,
3287
647
  contentType: "text/plain",
3288
- headers: t
648
+ headers: n
3289
649
  } : {
3290
- status: 500,
3291
- body: o.message,
650
+ status: l.status,
651
+ body: l.message,
3292
652
  contentType: "text/plain",
3293
- headers: t
653
+ headers: n
3294
654
  };
3295
655
  }
3296
- }, R = (e) => ({
656
+ }, L = (e) => ({
3297
657
  kind: "json",
3298
658
  data: e
3299
- }), z = (e, t) => ({
659
+ }), R = (e, t) => ({
3300
660
  kind: "json",
3301
661
  status: e,
3302
662
  data: { error: t }
3303
- }), ke = (e, t) => {
663
+ }), z = (e, t) => {
3304
664
  try {
3305
665
  return new URL(e, "http://localhost").searchParams.get(t);
3306
666
  } catch {
3307
667
  return null;
3308
668
  }
3309
- }, Ae = [
669
+ }, V = U.gen(function* () {
670
+ return {
671
+ catalogueId: yield* b.catalogueId,
672
+ objectNamespace: yield* i.objectNamespace,
673
+ storageInstance: t
674
+ };
675
+ }), De = [
3310
676
  {
3311
677
  method: "POST",
3312
678
  path: "/upload-ticket",
3313
679
  description: "Authorize a binary upload with explicit tenant and owner attribution",
3314
- handler: (e) => v.gen(function* () {
3315
- let n = S.String.pipe(S.check(S.makeFilter((e) => e.trim().length > 0))), r = yield* S.decodeUnknownEffect(S.fromJsonString(S.Struct({
3316
- operationId: S.optional(n.pipe(S.check(S.isMaxLength(200)))),
3317
- tenantId: S.NullOr(n),
3318
- ownerId: S.NullOr(n),
3319
- key: n.pipe(S.check(S.isMaxLength(1024))),
3320
- contentType: n.pipe(S.check(S.isMaxLength(255)), S.check(S.makeFilter((e) => !/[\r\n]/.test(e)))),
3321
- size: S.Number.pipe(S.check(S.isInt()), S.check(S.isGreaterThan(0)), S.check(S.makeFilter(Number.isSafeInteger))),
3322
- visibility: S.optional(S.Literals(["public", "private"]))
3323
- })))(e.body).pipe(v.mapError(() => new t({
680
+ handler: (n) => U.gen(function* () {
681
+ let i = W.String.pipe(W.check(W.makeFilter((e) => e.trim().length > 0))), a = yield* W.decodeUnknownEffect(W.fromJsonString(W.Struct({
682
+ operationId: W.optional(i.pipe(W.check(W.isMaxLength(200)))),
683
+ tenantId: W.NullOr(i),
684
+ ownerId: W.NullOr(i),
685
+ key: i.pipe(W.check(W.isMaxLength(1024))),
686
+ contentType: i.pipe(W.check(W.isMaxLength(255)), W.check(W.makeFilter((e) => !/[\r\n]/.test(e)))),
687
+ size: W.Number.pipe(W.check(W.isInt()), W.check(W.isGreaterThan(0)), W.check(W.makeFilter(Number.isSafeInteger))),
688
+ visibility: W.optional(W.Literals(["public", "private"]))
689
+ })))(n.body).pipe(U.mapError(() => new p({
3324
690
  provider: "inspect",
3325
691
  message: "Provide explicit tenantId and ownerId (or null), key, contentType and a positive file size",
3326
692
  transient: !1,
3327
693
  status: 400
3328
694
  })));
3329
- if (r.operationId !== void 0 && me.current === void 0) return z(409, "Durable uploads require a bound operation store with default reference and grant stores");
3330
- if (D !== void 0 && r.size > D) return z(413, "File exceeds the configured upload limit");
3331
- let a = r.visibility !== "public" && Array.isArray(i.uploadAccess) ? yield* S.decodeUnknownEffect(ae)(i.uploadAccess, { onExcessProperty: "error" }).pipe(v.mapError(() => new t({
695
+ if (a.operationId !== void 0 && y.current === void 0) return R(409, "Durable uploads require a bound operation store with default reference and grant stores");
696
+ if (c !== void 0 && a.size > c) return R(413, "File exceeds the configured upload limit");
697
+ let o = a.operationId ?? (y.current === void 0 ? void 0 : H()), s = o === void 0 ? void 0 : "inspect-upload:" + tt("sha256").update(JSON.stringify([t, o])).digest("hex"), l = a.visibility !== "public" && Array.isArray(e.uploadAccess) ? yield* W.decodeUnknownEffect(it)(e.uploadAccess, { onExcessProperty: "error" }).pipe(U.mapError(() => new p({
3332
698
  provider: "storage",
3333
699
  message: "Invalid upload access policy",
3334
700
  transient: !1,
3335
701
  status: 400
3336
- }))) : void 0, o = Ft({
3337
- instance: y,
3338
- ...a === void 0 ? {} : { access: a },
3339
- ...r.operationId === void 0 ? {} : { operationId: `inspect-upload:${Ce("sha256").update(JSON.stringify([y, r.operationId])).digest("hex")}` },
3340
- replicaId: ie().replicaId,
3341
- sub: r.ownerId,
3342
- tenant: r.tenantId,
3343
- ct: r.contentType,
3344
- key: r.key,
3345
- vis: r.visibility ?? "private",
3346
- max: r.size
702
+ }))) : void 0, u = yield* C.uploadTicketScope(), d = N({
703
+ writeScope: u,
704
+ instance: t,
705
+ issuerReplicaId: rt().replicaId,
706
+ ...l === void 0 ? {} : { access: l },
707
+ ...s === void 0 ? {} : { operationId: s },
708
+ sub: a.ownerId,
709
+ tenant: a.tenantId,
710
+ ct: a.contentType,
711
+ key: a.key,
712
+ vis: a.visibility ?? "private",
713
+ max: a.size
3347
714
  }, 300);
3348
- return R({
3349
- uploadPath: `${b}/upload?ticket=${encodeURIComponent(o)}`,
715
+ return L({
716
+ uploadPath: `${r}/upload?ticket=${encodeURIComponent(d)}`,
3350
717
  expiresInSec: 300,
3351
- maxBytes: r.size
718
+ maxBytes: a.size,
719
+ ...o === void 0 ? {} : { operationId: o }
3352
720
  });
3353
- }).pipe(v.catch((e) => v.succeed(z(e.status ?? 500, e.message))))
721
+ }).pipe(U.catch((e) => U.succeed(R(e.status ?? 500, e.message))))
3354
722
  },
3355
723
  {
3356
724
  method: "GET",
3357
725
  path: "/download",
3358
726
  description: "Stream a stored file as an attachment for authorized inspect readers",
3359
- handler: (e) => v.gen(function* () {
3360
- let t = ke(e.url, "refId");
3361
- if (!t?.trim()) return z(400, "A non-empty refId is required");
3362
- let { ref: n, stream: r } = yield* N.getStream(t), i = n.key.split("/").pop() || n.id, a = encodeURIComponent(i).replace(/[!'()*]/g, (e) => `%${e.charCodeAt(0).toString(16).toUpperCase()}`);
727
+ handler: (e) => U.gen(function* () {
728
+ let t = z(e.url, "refId");
729
+ if (!t?.trim()) return R(400, "A non-empty refId is required");
730
+ let { ref: n, stream: r } = yield* C.getStream(t), i = n.key.split("/").pop() || n.id, a = encodeURIComponent(i).replace(/[!'()*]/g, (e) => `%${e.charCodeAt(0).toString(16).toUpperCase()}`);
3363
731
  return {
3364
732
  kind: "bytes",
3365
733
  contentType: n.contentType,
3366
734
  byteStream: {
3367
- stream: () => C.toReadableStream(r),
735
+ stream: () => nt.toReadableStream(r),
3368
736
  contentLength: n.size,
3369
737
  contentDisposition: `attachment; filename="download"; filename*=UTF-8''${a}`
3370
738
  },
3371
739
  headers: { "cache-control": "no-store" }
3372
740
  };
3373
- }).pipe(v.catch((e) => v.succeed(z(e.status ?? 500, e.message))))
741
+ }).pipe(U.catch((e) => U.succeed(R(e.status ?? 500, e.message))))
3374
742
  },
3375
743
  {
3376
744
  method: "GET",
@@ -3378,8 +746,8 @@ var qn = () => _e({
3378
746
  scope: "process",
3379
747
  description: "Searchable storage refs, newest first, paginated",
3380
748
  handler: (e) => {
3381
- let t = Number(ke(e.url, "offset") ?? 0), n = Number.isSafeInteger(t) && t >= 0 ? t : 0, r = (ke(e.url, "search") ?? "").trim().slice(0, 200);
3382
- return he.listRefs({
749
+ let t = Number(z(e.url, "offset") ?? 0), n = Number.isSafeInteger(t) && t >= 0 ? t : 0, r = (z(e.url, "search") ?? "").trim().slice(0, 200);
750
+ return b.listRefs({
3383
751
  tenantId: void 0,
3384
752
  ownerId: void 0,
3385
753
  folder: void 0,
@@ -3388,14 +756,15 @@ var qn = () => _e({
3388
756
  search: r,
3389
757
  limit: 51,
3390
758
  offset: n
3391
- }).pipe(v.map((e) => R({
3392
- refs: e.slice(0, 50).map(cr),
759
+ }).pipe(U.flatMap((e) => V.pipe(U.map((t) => L({
760
+ source: t,
761
+ refs: e.slice(0, 50).map(ht),
3393
762
  page: {
3394
763
  search: r,
3395
764
  offset: n,
3396
765
  nextOffset: e.length > 50 ? n + 50 : null
3397
766
  }
3398
- })), v.catch((e) => v.succeed(z(500, e.message))));
767
+ })))), U.catch((e) => U.succeed(R(500, e.message))));
3399
768
  }
3400
769
  },
3401
770
  {
@@ -3403,11 +772,12 @@ var qn = () => _e({
3403
772
  path: "/stats",
3404
773
  scope: "process",
3405
774
  description: "Object count + total bytes per tenant + visibility split",
3406
- handler: () => he.statistics().pipe(v.map((e) => R({
3407
- provider: x.name,
3408
- bucket: ue,
775
+ handler: () => b.statistics().pipe(U.flatMap((e) => V.pipe(U.map((t) => L({
776
+ source: t,
777
+ provider: i.name,
778
+ bucket: a,
3409
779
  ...e
3410
- })), v.catch((e) => v.succeed(z(500, e.message))))
780
+ })))), U.catch((e) => U.succeed(R(500, e.message))))
3411
781
  },
3412
782
  {
3413
783
  method: "GET",
@@ -3415,171 +785,185 @@ var qn = () => _e({
3415
785
  scope: "process",
3416
786
  description: "Grants for a ref (?refId=…)",
3417
787
  handler: (e) => {
3418
- let t = ke(e.url, "refId");
3419
- return t ? ge.listByRef(t).pipe(v.map((e) => R({ grants: e.map(mr) })), v.catch((e) => v.succeed(z(500, e.message)))) : v.succeed(z(400, "refId query param required"));
788
+ let t = z(e.url, "refId");
789
+ return t ? x.listByRef(t).pipe(U.map((e) => L({ grants: e.map(Q) })), U.catch((e) => U.succeed(R(500, e.message)))) : U.succeed(R(400, "refId query param required"));
3420
790
  }
3421
791
  },
3422
792
  {
3423
793
  method: "POST",
3424
794
  path: "/share",
3425
795
  description: "Grant a principal access to a ref",
3426
- handler: (e) => v.gen(function* () {
3427
- let n = yield* S.decodeUnknownEffect(S.fromJsonString(S.Struct({
3428
- refId: S.String.pipe(S.check(S.makeFilter((e) => e.trim().length > 0))),
3429
- principalType: S.Literals([
796
+ handler: (e) => U.gen(function* () {
797
+ let t = yield* W.decodeUnknownEffect(W.fromJsonString(W.Struct({
798
+ refId: W.String.pipe(W.check(W.makeFilter((e) => e.trim().length > 0))),
799
+ principalType: W.Literals([
3430
800
  "user",
3431
801
  "group",
3432
802
  "apiKey"
3433
803
  ]),
3434
- principalId: S.String.pipe(S.check(S.makeFilter((e) => e.trim().length > 0))),
3435
- permission: S.optional(S.Literals(["read", "write"])),
3436
- expiresInDays: S.optional(S.Number.pipe(S.check(S.isFinite()), S.check(S.isGreaterThan(0))))
3437
- })))(e.body).pipe(v.mapError(() => new t({
804
+ principalId: W.String.pipe(W.check(W.makeFilter((e) => e.trim().length > 0))),
805
+ permission: W.optional(W.Literals(["read", "write"])),
806
+ expiresInDays: W.optional(W.Number.pipe(W.check(W.isFinite()), W.check(W.isGreaterThan(0))))
807
+ })))(e.body).pipe(U.mapError(() => new p({
3438
808
  provider: "inspect",
3439
809
  message: "Invalid share input: provide refId, principalType, principalId, read/write permission and a positive finite expiry if set",
3440
810
  transient: !1,
3441
811
  status: 400
3442
- }))), r = n.expiresInDays === void 0 ? null : new Date(Date.now() + n.expiresInDays * 864e5);
3443
- if (r !== null && !Number.isFinite(r.getTime())) return z(400, "Expiry exceeds the supported date range");
3444
- let i = yield* N.grant({
3445
- refId: n.refId,
3446
- principalType: n.principalType,
3447
- principalId: n.principalId,
3448
- ...n.permission ? { permission: n.permission } : {},
3449
- expiresAt: r
812
+ }))), n = t.expiresInDays === void 0 ? null : new Date(Date.now() + t.expiresInDays * 864e5);
813
+ if (n !== null && !Number.isFinite(n.getTime())) return R(400, "Expiry exceeds the supported date range");
814
+ let r = yield* C.grant({
815
+ refId: t.refId,
816
+ principalType: t.principalType,
817
+ principalId: t.principalId,
818
+ ...t.permission ? { permission: t.permission } : {},
819
+ expiresAt: n
3450
820
  });
3451
- return R({ grant: mr(i) });
3452
- }).pipe(v.catch((e) => v.succeed(z(e.status ?? 500, e.message ?? "share failed"))))
821
+ return L({ grant: Q(r) });
822
+ }).pipe(U.catch((e) => U.succeed(R(e.status ?? 500, e.message ?? "share failed"))))
3453
823
  },
3454
824
  {
3455
825
  method: "POST",
3456
826
  path: "/delete",
3457
827
  description: "Delete an object reference and its grants; release unreferenced bytes",
3458
- handler: (e) => v.gen(function* () {
3459
- let n = yield* S.decodeUnknownEffect(S.fromJsonString(S.Struct({ refId: S.String.pipe(S.check(S.makeFilter((e) => e.trim().length > 0))) })))(e.body).pipe(v.mapError(() => new t({
828
+ handler: (e) => U.gen(function* () {
829
+ let t = yield* W.decodeUnknownEffect(W.fromJsonString(W.Struct({ refId: W.String.pipe(W.check(W.makeFilter((e) => e.trim().length > 0))) })))(e.body).pipe(U.mapError(() => new p({
3460
830
  provider: "inspect",
3461
831
  message: "A non-empty refId is required",
3462
832
  transient: !1,
3463
833
  status: 400
3464
834
  })));
3465
- return yield* N.delete(n.refId), R({ ok: !0 });
3466
- }).pipe(v.catch((e) => v.succeed(z(e.status ?? 500, e.message))))
835
+ return yield* C.delete(t.refId), L({ ok: !0 });
836
+ }).pipe(U.catch((e) => U.succeed(R(e.status ?? 500, e.message))))
3467
837
  },
3468
838
  {
3469
839
  method: "POST",
3470
840
  path: "/revoke",
3471
841
  description: "Revoke a grant by id",
3472
- handler: (e) => v.gen(function* () {
3473
- let n = yield* S.decodeUnknownEffect(S.fromJsonString(S.Struct({ grantId: S.String.pipe(S.check(S.makeFilter((e) => e.trim().length > 0))) })))(e.body).pipe(v.mapError(() => new t({
842
+ handler: (e) => U.gen(function* () {
843
+ let t = yield* W.decodeUnknownEffect(W.fromJsonString(W.Struct({ grantId: W.String.pipe(W.check(W.makeFilter((e) => e.trim().length > 0))) })))(e.body).pipe(U.mapError(() => new p({
3474
844
  provider: "inspect",
3475
845
  message: "A non-empty grantId is required",
3476
846
  transient: !1,
3477
847
  status: 400
3478
848
  })));
3479
- return yield* N.revoke(n.grantId), R({ ok: !0 });
3480
- }).pipe(v.catch((e) => v.succeed(z(e.status ?? 500, e.message ?? "revoke failed"))))
849
+ return yield* C.revoke(t.grantId), L({ ok: !0 });
850
+ }).pipe(U.catch((e) => U.succeed(R(e.status ?? 500, e.message ?? "revoke failed"))))
3481
851
  }
3482
- ], je = [
852
+ ], Ge = [
3483
853
  {
3484
- ...te,
854
+ ...ze,
3485
855
  execute: (e, t) => {
3486
856
  let n = e;
3487
- return N.mintUrl(n.id, t.request.subject, {
857
+ return C.mintUrl(n.id, t.request.subject, {
3488
858
  ...n.password === void 0 ? {} : { password: n.password },
3489
859
  ...n.expiresInSec === void 0 ? {} : { expiresInSec: n.expiresInSec }
3490
- }).pipe(v.map((e) => ({ url: e })));
860
+ }).pipe(U.map((e) => ({ url: e })));
3491
861
  }
3492
862
  },
3493
863
  {
3494
- ...ee,
864
+ ...Re,
3495
865
  execute: (e, t) => {
3496
866
  let n = e;
3497
- return N.mintUploadUrl({
867
+ return C.mintUploadUrl({
3498
868
  key: n.key,
3499
869
  contentType: n.contentType,
3500
870
  tenantId: t.request.subject.tenantId,
3501
871
  ...n.expiresInSec === void 0 ? {} : { expiresInSec: n.expiresInSec }
3502
- }).pipe(v.map((e) => ({ url: e })));
872
+ }).pipe(U.map((e) => ({ url: e })));
3503
873
  }
3504
874
  },
3505
875
  {
3506
- ...m,
3507
- execute: (e, t) => {
3508
- let n = e;
3509
- return fr(t, O).pipe(v.flatMap((e) => A(n, t.request.subject).pipe(v.map((t) => ({
876
+ ...Le,
877
+ execute: (e, n) => {
878
+ let i = e;
879
+ return Z(n, l).pipe(U.flatMap((e) => h(i, n.request.subject).pipe(U.map((t) => ({
3510
880
  writer: e,
3511
881
  policy: t
3512
- })))), v.map(({ writer: e, policy: t }) => {
3513
- let r = n.expiresInSec ?? 900, i = Ft({
3514
- instance: y,
882
+ })))), U.flatMap((e) => i.operationId !== void 0 && y.current === void 0 ? U.fail(new p({
883
+ provider: "storage",
884
+ message: "Durable uploads require a bound operation store with default reference and grant stores",
885
+ transient: !1,
886
+ status: 409
887
+ })) : U.succeed(e)), U.flatMap(({ writer: e, policy: n }) => C.uploadTicketScope().pipe(U.map((a) => {
888
+ let s = i.expiresInSec ?? 900, l = i.operationId ?? (y.current === void 0 ? void 0 : H()), u = l === void 0 ? void 0 : "client-upload:" + tt("sha256").update(JSON.stringify([
889
+ t,
890
+ e.tenantId,
891
+ e.id,
892
+ l
893
+ ])).digest("hex"), d = N({
894
+ writeScope: a,
895
+ instance: t,
896
+ ...u === void 0 ? {} : { operationId: u },
3515
897
  sub: e.id,
3516
898
  tenant: e.tenantId,
3517
- ct: n.contentType,
3518
- vis: n.visibility ?? "private",
3519
- ...t,
3520
- ...n.key === void 0 ? {} : { key: n.key },
3521
- ...n.folder === void 0 ? {} : { folder: n.folder },
3522
- ...n.tags === void 0 ? {} : { tags: n.tags },
3523
- ...n.alt === void 0 ? {} : { alt: n.alt },
3524
- ...n.caption === void 0 ? {} : { caption: n.caption },
3525
- ...D === void 0 ? {} : { max: D }
3526
- }, r);
899
+ ct: i.contentType,
900
+ vis: i.visibility ?? "private",
901
+ ...n,
902
+ ...i.key === void 0 ? {} : { key: i.key },
903
+ ...i.folder === void 0 ? {} : { folder: i.folder },
904
+ ...i.tags === void 0 ? {} : { tags: i.tags },
905
+ ...i.alt === void 0 ? {} : { alt: i.alt },
906
+ ...i.caption === void 0 ? {} : { caption: i.caption },
907
+ ...c === void 0 ? {} : { max: c }
908
+ }, s);
3527
909
  return {
3528
- uploadUrl: `${T ? T.replace(/\/+$/, "") : ""}${b}/upload?ticket=${encodeURIComponent(i)}`,
3529
- expiresInSec: r
910
+ uploadUrl: `${o ? o.replace(/\/+$/, "") : ""}${r}/upload?ticket=${encodeURIComponent(d)}`,
911
+ expiresInSec: s,
912
+ ...l === void 0 ? {} : { operationId: l }
3530
913
  };
3531
- }));
914
+ }))));
3532
915
  }
3533
916
  },
3534
917
  {
3535
- ...p,
3536
- execute: (e, t) => {
3537
- let n = e;
3538
- return fr(t, O).pipe(v.flatMap((e) => A(n, t.request.subject).pipe(v.map((t) => ({
918
+ ...Ie,
919
+ execute: (e, n) => {
920
+ let r = e;
921
+ return Z(n, l).pipe(U.flatMap((e) => h(r, n.request.subject).pipe(U.map((t) => ({
3539
922
  writer: e,
3540
923
  policy: t
3541
- })))), v.flatMap(({ writer: e, policy: t }) => N.mintPresignedUpload({
3542
- contentType: n.contentType,
924
+ })))), U.flatMap(({ writer: e, policy: n }) => C.uploadTicketScope().pipe(U.flatMap((i) => C.mintPresignedUpload({
925
+ contentType: r.contentType,
3543
926
  tenantId: e.tenantId,
3544
- ...n.expiresInSec === void 0 ? {} : { expiresInSec: n.expiresInSec }
3545
- }).pipe(v.map((r) => {
3546
- let i = Lt({
3547
- instance: y,
3548
- key: r.key,
927
+ ...r.expiresInSec === void 0 ? {} : { expiresInSec: r.expiresInSec }
928
+ }).pipe(U.map((a) => {
929
+ let o = me({
930
+ writeScope: i,
931
+ instance: t,
932
+ key: a.key,
3549
933
  sub: e.id,
3550
934
  tenant: e.tenantId,
3551
- ct: n.contentType,
3552
- vis: n.visibility ?? "private",
3553
- ...t,
3554
- ...n.folder === void 0 ? {} : { folder: n.folder },
3555
- ...n.tags === void 0 ? {} : { tags: n.tags },
3556
- ...n.alt === void 0 ? {} : { alt: n.alt },
3557
- ...n.caption === void 0 ? {} : { caption: n.caption },
3558
- ...D === void 0 ? {} : { max: D }
3559
- }, r.expiresInSec);
935
+ ct: r.contentType,
936
+ vis: r.visibility ?? "private",
937
+ ...n,
938
+ ...r.folder === void 0 ? {} : { folder: r.folder },
939
+ ...r.tags === void 0 ? {} : { tags: r.tags },
940
+ ...r.alt === void 0 ? {} : { alt: r.alt },
941
+ ...r.caption === void 0 ? {} : { caption: r.caption },
942
+ ...c === void 0 ? {} : { max: c }
943
+ }, a.expiresInSec);
3560
944
  return {
3561
- uploadUrl: r.uploadUrl,
3562
- finalizeToken: i,
3563
- expiresInSec: r.expiresInSec
945
+ uploadUrl: a.uploadUrl,
946
+ finalizeToken: o,
947
+ expiresInSec: a.expiresInSec
3564
948
  };
3565
- }))));
949
+ }))))));
3566
950
  }
3567
951
  },
3568
952
  {
3569
- ...l,
953
+ ...Me,
3570
954
  execute: (e, n) => {
3571
- let r = Rt(e.finalizeToken);
3572
- return !r || r.instance !== y ? v.fail(new t({
955
+ let r = ve(e.finalizeToken);
956
+ return !r || r.instance !== t ? U.fail(new p({
3573
957
  provider: "storage",
3574
958
  message: "invalid or expired finalize token",
3575
959
  transient: !1,
3576
960
  status: 401
3577
- })) : pr(r.sub, n.request.subject.id) ? v.fail(new t({
961
+ })) : _t(r.sub, n.request.subject.id) ? U.fail(new p({
3578
962
  provider: "storage",
3579
963
  message: "finalize token belongs to another subject",
3580
964
  transient: !1,
3581
965
  status: 403
3582
- })) : N.finalizeUpload({
966
+ })) : T(r).pipe(U.flatMap(() => C.finalizeUpload({
3583
967
  key: r.key,
3584
968
  contentType: r.ct,
3585
969
  tenantId: r.tenant,
@@ -3590,118 +974,120 @@ var qn = () => _e({
3590
974
  ...r.tags === void 0 ? {} : { tags: r.tags },
3591
975
  ...r.alt === void 0 ? {} : { alt: r.alt },
3592
976
  ...r.caption === void 0 ? {} : { caption: r.caption }
3593
- }).pipe(v.flatMap((e) => N.getUrl(e.id).pipe(v.map((t) => ({
977
+ }).pipe(U.flatMap((e) => C.getUrl(e.id).pipe(U.map((t) => ({
3594
978
  id: e.id,
3595
979
  url: t,
3596
980
  contentType: e.contentType,
3597
981
  size: e.size,
3598
982
  ...e.width == null ? {} : { width: e.width },
3599
983
  ...e.height == null ? {} : { height: e.height }
3600
- })))));
984
+ })))))));
3601
985
  }
3602
986
  },
3603
987
  {
3604
- ...s,
3605
- execute: (e, t) => {
3606
- let n = e;
3607
- return fr(t, O).pipe(v.flatMap((e) => A(n, t.request.subject).pipe(v.map((t) => ({
988
+ ...Ae,
989
+ execute: (e, n) => {
990
+ let i = e;
991
+ return Z(n, l).pipe(U.flatMap((e) => h(i, n.request.subject).pipe(U.map((t) => ({
3608
992
  writer: e,
3609
993
  policy: t
3610
- })))), v.map(({ writer: e, policy: t }) => {
3611
- let r = n.expiresInSec ?? fe, i = Te(), a = n.chunkSize && n.chunkSize > 0 ? n.chunkSize : de;
994
+ })))), U.flatMap(({ writer: e, policy: n }) => C.uploadTicketScope().pipe(U.map((a) => {
995
+ let s = i.expiresInSec ?? d, l = H(), f = i.chunkSize && i.chunkSize > 0 ? i.chunkSize : u;
3612
996
  return {
3613
- uploadId: i,
3614
- resumableToken: zt({
3615
- instance: y,
3616
- id: i,
997
+ uploadId: l,
998
+ resumableToken: _e({
999
+ writeScope: a,
1000
+ instance: t,
1001
+ id: l,
3617
1002
  sub: e.id,
3618
1003
  tenant: e.tenantId,
3619
- ct: n.contentType,
3620
- vis: n.visibility ?? "private",
3621
- ...t,
3622
- size: n.size,
3623
- ...n.folder === void 0 ? {} : { folder: n.folder },
3624
- ...n.tags === void 0 ? {} : { tags: n.tags },
3625
- ...n.alt === void 0 ? {} : { alt: n.alt },
3626
- ...n.caption === void 0 ? {} : { caption: n.caption },
3627
- ...D === void 0 ? {} : { max: D }
3628
- }, r),
3629
- uploadUrl: `${T ? T.replace(/\/+$/, "") : ""}${b}/upload/resumable`,
3630
- chunkSize: a,
3631
- expiresInSec: r
1004
+ ct: i.contentType,
1005
+ vis: i.visibility ?? "private",
1006
+ ...n,
1007
+ size: i.size,
1008
+ ...i.folder === void 0 ? {} : { folder: i.folder },
1009
+ ...i.tags === void 0 ? {} : { tags: i.tags },
1010
+ ...i.alt === void 0 ? {} : { alt: i.alt },
1011
+ ...i.caption === void 0 ? {} : { caption: i.caption },
1012
+ ...c === void 0 ? {} : { max: c }
1013
+ }, s),
1014
+ uploadUrl: `${o ? o.replace(/\/+$/, "") : ""}${r}/upload/resumable`,
1015
+ chunkSize: f,
1016
+ expiresInSec: s
3632
1017
  };
3633
- }));
1018
+ }))));
3634
1019
  }
3635
1020
  },
3636
1021
  {
3637
- ...o,
3638
- execute: (e, t) => {
3639
- let n = e, r = n.expiresInSec ?? fe;
3640
- return fr(t, O).pipe(v.flatMap((e) => A(n, t.request.subject).pipe(v.map((t) => ({
1022
+ ...ke,
1023
+ execute: (e, n) => {
1024
+ let r = e, i = r.expiresInSec ?? d;
1025
+ return Z(n, l).pipe(U.flatMap((e) => h(r, n.request.subject).pipe(U.map((t) => ({
3641
1026
  writer: e,
3642
1027
  policy: t
3643
- })))), v.flatMap(({ writer: e, policy: t }) => N.beginMultipartUpload({
3644
- contentType: n.contentType,
1028
+ })))), U.flatMap(({ writer: e, policy: n }) => C.uploadTicketScope().pipe(U.flatMap((a) => C.beginMultipartUpload({
1029
+ contentType: r.contentType,
3645
1030
  tenantId: e.tenantId,
3646
- visibility: n.visibility ?? "private",
3647
- expiresInSec: r
3648
- }).pipe(v.map((i) => ({
3649
- multipartToken: Vt({
3650
- instance: y,
3651
- key: i.key,
3652
- uploadId: i.uploadId,
1031
+ visibility: r.visibility ?? "private",
1032
+ expiresInSec: i
1033
+ }).pipe(U.map((o) => ({
1034
+ multipartToken: ge({
1035
+ writeScope: a,
1036
+ instance: t,
1037
+ key: o.key,
1038
+ uploadId: o.uploadId,
3653
1039
  sub: e.id,
3654
1040
  tenant: e.tenantId,
3655
- ct: n.contentType,
3656
- vis: n.visibility ?? "private",
3657
- ...t,
3658
- size: n.size,
3659
- ...n.folder === void 0 ? {} : { folder: n.folder },
3660
- ...n.tags === void 0 ? {} : { tags: n.tags },
3661
- ...n.alt === void 0 ? {} : { alt: n.alt },
3662
- ...n.caption === void 0 ? {} : { caption: n.caption }
3663
- }, r),
3664
- partSize: n.partSize && n.partSize >= de ? n.partSize : de,
3665
- expiresInSec: r
3666
- })))));
1041
+ ct: r.contentType,
1042
+ vis: r.visibility ?? "private",
1043
+ ...n,
1044
+ size: r.size,
1045
+ ...r.folder === void 0 ? {} : { folder: r.folder },
1046
+ ...r.tags === void 0 ? {} : { tags: r.tags },
1047
+ ...r.alt === void 0 ? {} : { alt: r.alt },
1048
+ ...r.caption === void 0 ? {} : { caption: r.caption }
1049
+ }, i),
1050
+ partSize: r.partSize && r.partSize >= u ? r.partSize : u,
1051
+ expiresInSec: i
1052
+ })))))));
3667
1053
  }
3668
1054
  },
3669
1055
  {
3670
- ...g,
1056
+ ...He,
3671
1057
  execute: (e) => {
3672
- let n = e, r = Ht(n.multipartToken);
3673
- return !r || r.instance !== y ? v.fail(new t({
1058
+ let n = e, r = P(n.multipartToken);
1059
+ return !r || r.instance !== t ? U.fail(new p({
3674
1060
  provider: "storage",
3675
1061
  message: "invalid or expired multipart token",
3676
1062
  transient: !1,
3677
1063
  status: 401
3678
- })) : !Number.isInteger(n.partNumber) || n.partNumber < 1 ? v.fail(new t({
1064
+ })) : !Number.isInteger(n.partNumber) || n.partNumber < 1 ? U.fail(new p({
3679
1065
  provider: "storage",
3680
1066
  message: "partNumber must be a positive integer",
3681
1067
  transient: !1,
3682
1068
  status: 400
3683
- })) : N.signMultipartPart({
1069
+ })) : T(r).pipe(U.flatMap(() => C.signMultipartPart({
3684
1070
  key: r.key,
3685
1071
  uploadId: r.uploadId,
3686
1072
  partNumber: n.partNumber
3687
- }).pipe(v.map((e) => ({ url: e })));
1073
+ }).pipe(U.map((e) => ({ url: e })))));
3688
1074
  }
3689
1075
  },
3690
1076
  {
3691
- ...c,
1077
+ ...je,
3692
1078
  execute: (e, n) => {
3693
- let r = e, i = Ht(r.multipartToken);
3694
- return !i || i.instance !== y ? v.fail(new t({
1079
+ let r = e, i = P(r.multipartToken);
1080
+ return !i || i.instance !== t ? U.fail(new p({
3695
1081
  provider: "storage",
3696
1082
  message: "invalid or expired multipart token",
3697
1083
  transient: !1,
3698
1084
  status: 401
3699
- })) : pr(i.sub, n.request.subject.id) ? v.fail(new t({
1085
+ })) : _t(i.sub, n.request.subject.id) ? U.fail(new p({
3700
1086
  provider: "storage",
3701
1087
  message: "multipart token belongs to another subject",
3702
1088
  transient: !1,
3703
1089
  status: 403
3704
- })) : N.completeMultipart({
1090
+ })) : T(i).pipe(U.flatMap(() => C.completeMultipart({
3705
1091
  key: i.key,
3706
1092
  uploadId: i.uploadId,
3707
1093
  parts: r.parts,
@@ -3714,36 +1100,36 @@ var qn = () => _e({
3714
1100
  ...i.tags === void 0 ? {} : { tags: i.tags },
3715
1101
  ...i.alt === void 0 ? {} : { alt: i.alt },
3716
1102
  ...i.caption === void 0 ? {} : { caption: i.caption }
3717
- }).pipe(v.flatMap((e) => N.getUrl(e.id).pipe(v.map((t) => ({
1103
+ }).pipe(U.flatMap((e) => C.getUrl(e.id).pipe(U.map((t) => ({
3718
1104
  id: e.id,
3719
1105
  url: t,
3720
1106
  size: e.size
3721
- })))));
1107
+ })))))));
3722
1108
  }
3723
1109
  },
3724
1110
  {
3725
- ...a,
1111
+ ...Oe,
3726
1112
  execute: (e) => {
3727
- let n = Ht(e.multipartToken);
3728
- return !n || n.instance !== y ? v.fail(new t({
1113
+ let n = P(e.multipartToken);
1114
+ return !n || n.instance !== t ? U.fail(new p({
3729
1115
  provider: "storage",
3730
1116
  message: "invalid or expired multipart token",
3731
1117
  transient: !1,
3732
1118
  status: 401
3733
- })) : N.abortMultipart({
1119
+ })) : T(n).pipe(U.flatMap(() => C.abortMultipart({
3734
1120
  key: n.key,
3735
1121
  uploadId: n.uploadId
3736
- }).pipe(v.as({ ok: !0 }));
1122
+ }).pipe(U.as({ ok: !0 }))));
3737
1123
  }
3738
1124
  },
3739
1125
  {
3740
- ...re,
1126
+ ...We,
3741
1127
  execute: (e, t) => {
3742
1128
  let n = e, r = new Uint8Array(Buffer.from(n.bytesBase64, "base64"));
3743
- return fr(t, O).pipe(v.flatMap((e) => A(n, t.request.subject).pipe(v.map((t) => ({
1129
+ return Z(t, l).pipe(U.flatMap((e) => h(n, t.request.subject).pipe(U.map((t) => ({
3744
1130
  writer: e,
3745
1131
  policy: t
3746
- })))), v.flatMap(({ writer: e, policy: t }) => N.put({
1132
+ })))), U.flatMap(({ writer: e, policy: t }) => C.put({
3747
1133
  bytes: r,
3748
1134
  ...t,
3749
1135
  contentType: n.contentType,
@@ -3752,17 +1138,17 @@ var qn = () => _e({
3752
1138
  ...n.visibility ? { visibility: n.visibility } : {},
3753
1139
  ...n.key ? { key: n.key } : {},
3754
1140
  ...n.password ? { password: n.password } : {}
3755
- })), v.flatMap((e) => N.getUrl(e.id).pipe(v.map((t) => ({
1141
+ })), U.flatMap((e) => C.getUrl(e.id).pipe(U.map((t) => ({
3756
1142
  id: e.id,
3757
1143
  url: t
3758
1144
  })))));
3759
1145
  }
3760
1146
  },
3761
1147
  {
3762
- ...u,
1148
+ ...Ne,
3763
1149
  execute: (e, t) => {
3764
1150
  let n = e;
3765
- return fr(t, O).pipe(v.flatMap((e) => N.ingestUrl(n.url, {
1151
+ return Z(t, l).pipe(U.flatMap((e) => C.ingestUrl(n.url, {
3766
1152
  tenantId: e.tenantId,
3767
1153
  ownerId: e.id,
3768
1154
  ...n.visibility ? { visibility: n.visibility } : {},
@@ -3771,45 +1157,45 @@ var qn = () => _e({
3771
1157
  ...n.alt === void 0 ? {} : { alt: n.alt },
3772
1158
  ...n.caption === void 0 ? {} : { caption: n.caption },
3773
1159
  ...n.key === void 0 ? {} : { key: n.key }
3774
- })), v.flatMap((e) => N.getUrl(e.id).pipe(v.map((t) => ({
1160
+ })), U.flatMap((e) => C.getUrl(e.id).pipe(U.map((t) => ({
3775
1161
  id: e.id,
3776
1162
  url: t
3777
1163
  })))));
3778
1164
  }
3779
1165
  },
3780
1166
  {
3781
- ...h,
1167
+ ...Ve,
3782
1168
  execute: (e, t) => {
3783
1169
  let n = e, r = n.expiresInDays ? new Date(Date.now() + n.expiresInDays * 864e5) : null;
3784
- return ur(N, n.refId, t).pipe(v.flatMap(() => N.grant({
1170
+ return X(C, n.refId, t).pipe(U.flatMap(() => C.grant({
3785
1171
  refId: n.refId,
3786
1172
  principalType: n.principalType,
3787
1173
  principalId: n.principalId,
3788
1174
  ...n.permission ? { permission: n.permission } : {},
3789
1175
  expiresAt: r,
3790
1176
  createdBy: t.request.subject.id
3791
- })), v.map((e) => ({ grantId: e.id })));
1177
+ })), U.map((e) => ({ grantId: e.id })));
3792
1178
  }
3793
1179
  },
3794
1180
  {
3795
- ...ne,
1181
+ ...Be,
3796
1182
  execute: (e, t) => {
3797
1183
  let n = e;
3798
- return N.getGrant(n.grantId).pipe(v.flatMap((e) => e === null ? v.fail(lr()) : ur(N, e.refId, t)), v.flatMap(() => N.revoke(n.grantId)), v.map(() => ({ ok: !0 })));
1184
+ return C.getGrant(n.grantId).pipe(U.flatMap((e) => e === null ? U.fail(Y()) : X(C, e.refId, t)), U.flatMap(() => C.revoke(n.grantId)), U.map(() => ({ ok: !0 })));
3799
1185
  }
3800
1186
  },
3801
1187
  {
3802
- ...d,
1188
+ ...Pe,
3803
1189
  execute: (e, t) => {
3804
1190
  let n = e;
3805
- return ur(N, n.refId, t).pipe(v.flatMap(() => N.listGrants(n.refId)), v.map((e) => ({ grants: e.map(mr) })));
1191
+ return X(C, n.refId, t).pipe(U.flatMap(() => C.listGrants(n.refId)), U.map((e) => ({ grants: e.map(Q) })));
3806
1192
  }
3807
1193
  },
3808
1194
  {
3809
- ...f,
1195
+ ...Fe,
3810
1196
  execute: (e, t) => {
3811
1197
  let n = e;
3812
- return N.listRefs({
1198
+ return C.listRefs({
3813
1199
  tenantId: t.request.subject.tenantId,
3814
1200
  ...n.folder === void 0 ? {} : { folder: n.folder },
3815
1201
  ...n.tags === void 0 ? {} : { tags: n.tags },
@@ -3817,61 +1203,61 @@ var qn = () => _e({
3817
1203
  ...n.includeDerived === void 0 ? {} : { includeDerived: n.includeDerived },
3818
1204
  ...n.limit === void 0 ? {} : { limit: n.limit },
3819
1205
  ...n.offset === void 0 ? {} : { offset: n.offset }
3820
- }).pipe(v.map((e) => ({
3821
- refs: e.refs.map(cr),
1206
+ }).pipe(U.map((e) => ({
1207
+ refs: e.refs.map(ht),
3822
1208
  nextOffset: e.nextOffset
3823
1209
  })));
3824
1210
  }
3825
1211
  }
3826
1212
  ];
3827
- return oe({
3828
- name: w({
3829
- base: hr,
3830
- alias: i.alias,
3831
- instance: i.name
1213
+ return at({
1214
+ name: G({
1215
+ base: $,
1216
+ alias: e.alias,
1217
+ instance: e.name
3832
1218
  }),
3833
- baseName: hr,
1219
+ baseName: $,
3834
1220
  description: "File storage — StorageService over S3 / MinIO / filesystem / memory. Public objects served direct from bucket/CDN; private objects gated by an access policy + per-object grants. Checksums, tenant key-prefixing, _voltro_storage_refs + _voltro_storage_grants, retry.",
3835
1221
  permissions: [
3836
1222
  "network:outbound:*",
3837
1223
  "inspect:read",
3838
1224
  "inspect:write"
3839
1225
  ],
3840
- declaredEnv: U.declared,
3841
- egress: ar(i),
3842
- services: ve,
3843
- inspectEndpoints: Ae,
1226
+ declaredEnv: w.declared,
1227
+ egress: pt(e),
1228
+ services: ie,
1229
+ inspectEndpoints: De,
3844
1230
  httpRoutes: [
3845
- L,
3846
- De,
3847
- Oe
1231
+ pe,
1232
+ he,
1233
+ I
3848
1234
  ],
3849
- routes: je,
3850
- rpcClientDescriptors: _,
1235
+ routes: Ge,
1236
+ rpcClientDescriptors: Ue,
3851
1237
  errorSchemas: [
3852
1238
  {
3853
- schema: t,
1239
+ schema: p,
3854
1240
  import: {
3855
1241
  module: "@voltro/plugin-storage/errors",
3856
1242
  name: "StorageError"
3857
1243
  }
3858
1244
  },
3859
1245
  {
3860
- schema: e,
1246
+ schema: te,
3861
1247
  import: {
3862
1248
  module: "@voltro/plugin-storage/errors",
3863
1249
  name: "StorageAccessDenied"
3864
1250
  }
3865
1251
  },
3866
1252
  {
3867
- schema: n,
1253
+ schema: ne,
3868
1254
  import: {
3869
1255
  module: "@voltro/plugin-storage/errors",
3870
1256
  name: "StorageRejected"
3871
1257
  }
3872
1258
  },
3873
1259
  {
3874
- schema: r,
1260
+ schema: re,
3875
1261
  import: {
3876
1262
  module: "@voltro/plugin-storage/errors",
3877
1263
  name: "StorageScanRejected"
@@ -3880,7 +1266,7 @@ var qn = () => _e({
3880
1266
  ],
3881
1267
  capabilities: { mediaPersist: {
3882
1268
  put: async ({ bytes: e, mediaType: t, tenantId: n, operationId: r, ownerId: i, visibility: a, tags: o }) => {
3883
- let s = await v.runPromise(N.put({
1269
+ let s = await U.runPromise(C.put({
3884
1270
  bytes: e,
3885
1271
  contentType: t,
3886
1272
  tenantId: n,
@@ -3888,40 +1274,50 @@ var qn = () => _e({
3888
1274
  ...i === void 0 ? {} : { ownerId: i },
3889
1275
  ...a === void 0 ? {} : { visibility: a },
3890
1276
  ...o === void 0 ? {} : { tags: o },
3891
- ...me.current === void 0 ? {} : { operationId: r }
1277
+ ...y.current === void 0 ? {} : { operationId: r }
3892
1278
  }));
3893
1279
  return {
3894
- url: await v.runPromise(N.getUrl(s.id, { tenantId: n })),
1280
+ url: await U.runPromise(C.getUrl(s.id, { tenantId: n })),
3895
1281
  refId: s.id
3896
1282
  };
3897
1283
  },
3898
1284
  ingestUrl: async ({ url: e, tenantId: t, operationId: n, ownerId: r, visibility: i, tags: a }) => {
3899
- let o = await v.runPromise(N.ingestUrl(e, {
1285
+ let o = await U.runPromise(C.ingestUrl(e, {
3900
1286
  tenantId: t,
3901
1287
  ...r === void 0 ? {} : { ownerId: r },
3902
1288
  ...i === void 0 ? {} : { visibility: i },
3903
1289
  ...a === void 0 ? {} : { tags: a },
3904
- ...me.current === void 0 ? {} : { operationId: n }
1290
+ ...y.current === void 0 ? {} : { operationId: n }
3905
1291
  }));
3906
1292
  return {
3907
- url: await v.runPromise(N.getUrl(o.id, { tenantId: t })),
1293
+ url: await U.runPromise(C.getUrl(o.id, { tenantId: t })),
3908
1294
  refId: o.id
3909
1295
  };
3910
1296
  }
3911
1297
  } },
3912
- bindDataStore: (e) => {
3913
- k && (j.current = ln(e)), pe && (M.current = fn(e)), k && pe && (me.current = zn(e)), x.bindDataStore?.(e);
1298
+ bindDataStore: async (e) => {
1299
+ let r = await U.runPromise(i.objectNamespace);
1300
+ (f || m) && await ee(e), (f || m) && await _(e), f && await n(e), f && (g.current = Ce(e, {
1301
+ storageInstance: t,
1302
+ objectNamespace: r
1303
+ })), m && (v.current = Se(e, {
1304
+ storageInstance: t,
1305
+ objectNamespace: r
1306
+ })), f && m && (y.current = Ee(e, {
1307
+ storageInstance: t,
1308
+ objectNamespace: r
1309
+ })), i.bindDataStore?.(e);
3914
1310
  },
3915
- onActivate: (e) => v.sync(() => {
3916
- let t = !!T || !!U.read("STORAGE_CDN_URL", i.cdnBaseUrl);
3917
- e.logger.info(`storage: provider=${x.name} presign=${x.presigns ? "yes" : "no"} publicUrl=${t ? "yes" : "no"} transforms=yes`, {
3918
- provider: x.name,
3919
- bucket: ue,
3920
- refStore: k ? "memory" : "custom"
3921
- }), x.name === "memory" && process.env.NODE_ENV !== "test" && e.logger.warn("storage: provider=memory — uploads are IN-MEMORY and LOST on restart. Set STORAGE_PROVIDER (filesystem / s3 / r2 / azure / gcs) for anything but throwaway dev. (Empty/placeholder storage env silently falls back to memory.)"), !t && !x.presigns && e.logger.warn("storage: no VOLTRO_PUBLIC_URL / STORAGE_CDN_URL and this provider can't presign — serve URLs are RELATIVE and will not resolve cross-origin (browser <img> / server-to-server AI fetches). Set VOLTRO_PUBLIC_URL to this api's absolute base URL.");
1311
+ onActivate: (t) => U.sync(() => {
1312
+ let n = !!o || !!w.read("STORAGE_CDN_URL", e.cdnBaseUrl);
1313
+ t.logger.info(`storage: provider=${i.name} presign=${i.presigns ? "yes" : "no"} publicUrl=${n ? "yes" : "no"} transforms=yes`, {
1314
+ provider: i.name,
1315
+ bucket: a,
1316
+ refStore: f ? "memory" : "custom"
1317
+ }), i.name === "memory" && process.env.NODE_ENV !== "test" && t.logger.warn("storage: provider=memory — uploads are IN-MEMORY and LOST on restart. Set STORAGE_PROVIDER (filesystem / s3 / r2 / azure / gcs) for anything but throwaway dev. (Empty/placeholder storage env silently falls back to memory.)"), !n && !i.presigns && t.logger.warn("storage: no VOLTRO_PUBLIC_URL / STORAGE_CDN_URL and this provider can't presign — serve URLs are RELATIVE and will not resolve cross-origin (browser <img> / server-to-server AI fetches). Set VOLTRO_PUBLIC_URL to this api's absolute base URL.");
3922
1318
  }),
3923
- onDeactivate: () => v.void
1319
+ onDeactivate: () => U.void
3924
1320
  });
3925
1321
  };
3926
1322
  //#endregion
3927
- export { H as STORAGE_BLOBS_TABLE, V as STORAGE_GRANTS_TABLE, B as STORAGE_REFS_TABLE, Ue as STORAGE_USAGE_TABLE, e as StorageAccessDenied, t as StorageError, n as StorageRejected, r as StorageScanRejected, i as StorageService, qe as _voltroStorageBlobsTable, Ge as _voltroStorageGrantsTable, We as _voltroStorageRefsTable, Ke as _voltroStorageUsageTable, nr as appStorageProvider, Kn as assetRef, at as azureProvider, hn as buildStorageService, Le as bytesToStream, Kt as checkLimits, Un as clamavScanner, $e as clearStorageBuffer, Re as collectStream, Ie as concatBytes, rr as configuredStorageProvider, Ut as contentTypeAllowed, fn as dataStoreGrantStore, ln as dataStoreRefStore, it as databaseProvider, Yn as decodeDataUri, Qn as durabilityNotice, ht as editImage, Bn as encodeInstream, Gn as ffmpegTranscoder, tt as filesystemProvider, ze as fromNodeReadable, Ve as getObjectStream, yt as hashPassword, zn as makeStorageObjectMetadata, un as memoryGrantStore, et as memoryProvider, on as memoryRefStore, Vn as parseClamavResponse, lt as parseTransformParams, Zn as pathDurability, Xn as putAvatar, He as putObjectStream, Qe as readStorageBuffer, rn as refMatchesListQuery, ir as resolveStorageProvider, q as resolveStorageSecret, nt as s3Provider, tr as setActiveStorageProvider, Lt as signFinalizeTicket, Mt as signGrant, Vt as signMultipartTicket, zt as signResumableTicket, Ft as signUploadTicket, Gt as sniffMatches, ar as storageEgressOf, gr as storageInstanceName, bn as storageObjectLifecycleTables, _r as storagePlugin, In as storagePutIntentsTable, gn as storageServiceLayer, Be as toNodeReadable, vt as transformCached, pt as transformFallbackReason, mt as transformImage, Rt as verifyFinalizeTicket, Nt as verifyGrant, Ht as verifyMultipartTicket, bt as verifyPassword, Bt as verifyResumableTicket, It as verifyUploadTicket, qn as withStorage };
1323
+ export { i as STORAGE_BLOBS_TABLE, a as STORAGE_GRANTS_TABLE, t as STORAGE_REFERENCE_CATALOGUE_TABLE, o as STORAGE_REFS_TABLE, s as STORAGE_USAGE_TABLE, te as StorageAccessDenied, p as StorageError, ne as StorageRejected, re as StorageScanRejected, m as StorageService, c as _voltroStorageBlobsTable, l as _voltroStorageGrantsTable, u as _voltroStorageRefsTable, d as _voltroStorageUsageTable, dt as appStorageProvider, Ye as assetRef, g as assignStorageObjectNamespacesInTransaction, f as assignStorageReferenceInstancesInTransaction, T as azureProvider, xe as buildStorageService, v as bytesToStream, I as checkLimits, Ge as clamavScanner, E as clearStorageBuffer, y as collectStream, b as concatBytes, ft as configuredStorageProvider, L as contentTypeAllowed, Se as dataStoreGrantStore, Ce as dataStoreRefStore, D as databaseProvider, Ze as decodeDataUri, $e as durabilityNotice, j as editImage, Ke as encodeInstream, n as ensureStorageReferenceCatalogue, z as fetchIngestBody, Je as ffmpegTranscoder, O as filesystemProvider, x as fromNodeReadable, S as getObjectStream, M as hashPassword, Ee as makeStorageObjectMetadata, we as memoryGrantStore, k as memoryProvider, B as memoryRefStore, qe as parseClamavResponse, se as parseTransformParams, et as pathDurability, Qe as putAvatar, ie as putObjectStream, ae as readStorageBuffer, V as refMatchesListQuery, _ as requireStorageObjectNamespaces, q as resolveStorageProvider, pe as resolveStorageSecret, A as s3Provider, ut as setActiveStorageProvider, me as signFinalizeTicket, he as signGrant, ge as signMultipartTicket, _e as signResumableTicket, N as signUploadTicket, R as sniffMatches, pt as storageEgressOf, vt as storageInstanceName, h as storageObjectLifecycleTables, e as storageObjectNamespace, bt as storagePlugin, De as storagePutIntentsTable, r as storageReferenceCatalogueTable, Te as storageServiceLayer, C as toNodeReadable, ce as transformCached, le as transformFallbackReason, ue as transformImage, ve as verifyFinalizeTicket, ye as verifyGrant, P as verifyMultipartTicket, fe as verifyPassword, be as verifyResumableTicket, F as verifyUploadTicket, Xe as withStorage };