@voltro/plugin-storage 0.69.1 → 0.71.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,86 +1,86 @@
1
1
  import { StorageAccessDenied as e, StorageError as t, StorageRejected as n, StorageScanRejected as r, StorageService as i } from "./types.js";
2
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 h, revokeDescriptor as g, shareDescriptor as _, signMultipartPartDescriptor as te, storageRpcClientImports as ne, uploadDescriptor as v } from "./rpc.js";
3
- import { Chunk as y, Effect as b, Exit as x, Layer as S, Schedule as C, Stream as w } from "effect";
4
- import { definePlugin as T, pluginInstanceName as re } from "@voltro/protocol";
5
- import { readCookie as E, resolveSessionSecret as ie, verifySession as ae } from "@voltro/protocol/session";
6
- import { and as D, bytes as oe, eq as O, generateId as k, id as A, integer as j, json as M, mixin as se, reference as ce, table as N, text as P, timestamp as F } from "@voltro/database";
7
- import { pluginEnv as I } from "@voltro/env";
8
- import { createHmac as L, randomBytes as le, randomUUID as ue, scryptSync as R, timingSafeEqual as z } from "node:crypto";
9
- import { spawn as de } from "node:child_process";
10
- import { mkdtemp as fe, readFile as pe, rm as me, writeFile as B } from "node:fs/promises";
11
- import { tmpdir as V } from "node:os";
12
- import { join as he } from "node:path";
13
- import { statSync as ge } from "node:fs";
3
+ import { Chunk as y, Effect as b, Exit as x, Layer as S, Schedule as C, Schema as w, Stream as T } from "effect";
4
+ import { definePlugin as re, pluginInstanceName as E } from "@voltro/protocol";
5
+ import { readCookie as ie, resolveSessionSecret as ae, verifySession as oe } from "@voltro/protocol/session";
6
+ import { and as D, bytes as se, contains as O, eq as k, generateId as A, id as j, integer as M, json as N, mixin as P, or as F, reference as ce, table as I, text as L, timestamp as le } from "@voltro/database";
7
+ import { pluginEnv as R } from "@voltro/env";
8
+ import { createHmac as z, randomBytes as B, randomUUID as ue, scryptSync as de, timingSafeEqual as V } from "node:crypto";
9
+ import { spawn as fe } from "node:child_process";
10
+ import { mkdtemp as pe, readFile as me, rm as he, writeFile as ge } from "node:fs/promises";
11
+ import { tmpdir as _e } from "node:os";
12
+ import { join as H } from "node:path";
13
+ import { statSync as U } from "node:fs";
14
14
  //#region src/streamBridge.ts
15
- var _e = 1 << 20, ve = (e, n, r = !1) => new t({
15
+ var ve = 1 << 20, ye = (e, n, r = !1) => new t({
16
16
  provider: e,
17
17
  message: n,
18
18
  transient: r
19
- }), ye = (e) => {
19
+ }), be = (e) => {
20
20
  let t = 0;
21
21
  for (let n of e) t += n.byteLength;
22
22
  let n = new Uint8Array(t), r = 0;
23
23
  for (let t of e) n.set(t, r), r += t.byteLength;
24
24
  return n;
25
- }, be = (e, t = _e) => {
25
+ }, xe = (e, t = ve) => {
26
26
  let n = [];
27
27
  for (let r = 0; r < e.byteLength; r += t) n.push(e.subarray(r, Math.min(r + t, e.byteLength)));
28
- return w.fromIterable(n);
29
- }, xe = (e) => e.pipe(w.runCollect, b.map((e) => ye(y.toReadonlyArray(e)))), Se = (e, t) => w.suspend(() => w.fromAsyncIterable(t(), (t) => ve(e, `read stream failed: ${String(t?.message ?? t)}`, !0))).pipe(w.map((e) => e instanceof Uint8Array ? e : new Uint8Array(e))), Ce = async (e) => {
28
+ return T.fromIterable(n);
29
+ }, Se = (e) => e.pipe(T.runCollect, b.map((e) => be(y.toReadonlyArray(e)))), Ce = (e, t) => T.suspend(() => T.fromAsyncIterable(t(), (t) => ye(e, `read stream failed: ${String(t?.message ?? t)}`, !0))).pipe(T.map((e) => e instanceof Uint8Array ? e : new Uint8Array(e))), we = async (e) => {
30
30
  let { Readable: t } = await import("node:stream");
31
- return t.fromWeb(w.toReadableStream(e));
32
- }, we = (e, t) => e.getStream ? e.getStream(t) : e.get(t).pipe(b.map((e) => ({
33
- stream: be(e.bytes),
31
+ return t.fromWeb(T.toReadableStream(e));
32
+ }, Te = (e, t) => e.getStream ? e.getStream(t) : e.get(t).pipe(b.map((e) => ({
33
+ stream: xe(e.bytes),
34
34
  contentType: e.contentType,
35
35
  size: e.bytes.byteLength
36
- }))), Te = (e, t, n, r) => e.putStream ? e.putStream(t, n, r) : xe(n).pipe(b.flatMap((n) => e.put(t, n, {
36
+ }))), Ee = (e, t, n, r) => e.putStream ? e.putStream(t, n, r) : Se(n).pipe(b.flatMap((n) => e.put(t, n, {
37
37
  contentType: r.contentType,
38
38
  ...r.public === void 0 ? {} : { public: r.public }
39
- }))), H = "_voltro_storage_refs", U = "_voltro_storage_grants", W = "_voltro_storage_blobs", Ee = "_voltro_storage_usage", De = N(H, {
40
- id: A({ prefix: "file" }),
41
- tenantId: P().nullable(),
42
- ownerId: P().nullable(),
43
- bucket: P(),
44
- key: P(),
45
- contentType: P(),
46
- size: j(),
47
- checksum: P(),
48
- visibility: P(),
49
- accessPolicy: M().nullable(),
50
- passwordHash: P().nullable(),
51
- width: j().nullable(),
52
- height: j().nullable(),
53
- duration: j().nullable(),
54
- placeholder: P().nullable(),
55
- folder: P().nullable(),
56
- tags: M().nullable(),
57
- alt: P().nullable(),
58
- caption: P().nullable(),
59
- derivedFrom: P().nullable(),
60
- kind: P().nullable(),
61
- createdAt: F()
62
- }).index(["key"]).index(["tenantId"]).index(["ownerId"]).index(["folder"]).index(["derivedFrom"]), Oe = N(U, {
63
- id: A({ prefix: "sgrant" }),
64
- refId: P(),
65
- principalType: P(),
66
- principalId: P(),
67
- permission: P(),
68
- createdAt: F(),
69
- expiresAt: F().nullable(),
70
- createdBy: P().nullable()
71
- }).index(["refId"]).index(["principalId"]), ke = N(Ee, {
72
- id: A({ prefix: "susage" }),
73
- tenantId: P().maxLength(191),
74
- bytes: j().default(0),
75
- count: j().default(0),
76
- updatedAt: F()
77
- }).unique("byStorageUsageTenant", ["tenantId"]), Ae = N(W, {
78
- id: A({ prefix: "blob" }),
79
- key: P(),
80
- data: oe(),
81
- contentType: P(),
82
- size: j()
83
- }).index(["key"]), G = I([
39
+ }))), W = "_voltro_storage_refs", G = "_voltro_storage_grants", K = "_voltro_storage_blobs", De = "_voltro_storage_usage", Oe = I(W, {
40
+ id: j({ prefix: "file" }),
41
+ tenantId: L().nullable(),
42
+ ownerId: L().nullable(),
43
+ bucket: L(),
44
+ key: L(),
45
+ contentType: L(),
46
+ size: M(),
47
+ checksum: L(),
48
+ visibility: L(),
49
+ accessPolicy: N().nullable(),
50
+ passwordHash: L().nullable(),
51
+ width: M().nullable(),
52
+ height: M().nullable(),
53
+ duration: M().nullable(),
54
+ placeholder: L().nullable(),
55
+ folder: L().nullable(),
56
+ tags: N().nullable(),
57
+ alt: L().nullable(),
58
+ caption: L().nullable(),
59
+ derivedFrom: L().nullable(),
60
+ kind: L().nullable(),
61
+ createdAt: le()
62
+ }).index(["key"]).index(["tenantId"]).index(["ownerId"]).index(["folder"]).index(["derivedFrom"]), ke = I(G, {
63
+ id: j({ prefix: "sgrant" }),
64
+ refId: L(),
65
+ principalType: L(),
66
+ principalId: L(),
67
+ permission: L(),
68
+ createdAt: le(),
69
+ expiresAt: le().nullable(),
70
+ createdBy: L().nullable()
71
+ }).index(["refId"]).index(["principalId"]), Ae = I(De, {
72
+ id: j({ prefix: "susage" }),
73
+ tenantId: L().maxLength(191),
74
+ bytes: M().default(0),
75
+ count: M().default(0),
76
+ updatedAt: le()
77
+ }).unique("byStorageUsageTenant", ["tenantId"]), je = I(K, {
78
+ id: j({ prefix: "blob" }),
79
+ key: L(),
80
+ data: se(),
81
+ contentType: L(),
82
+ size: M()
83
+ }).index(["key"]), q = R([
84
84
  {
85
85
  name: "STORAGE_PROVIDER",
86
86
  required: !1,
@@ -231,16 +231,16 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
231
231
  secret: !1,
232
232
  description: "clamd port for the optional clamav virus scanner. Default 3310."
233
233
  }
234
- ]), K = (e, n, r, i) => new t({
234
+ ]), J = (e, n, r, i) => new t({
235
235
  provider: e,
236
236
  message: n,
237
237
  transient: r,
238
238
  ...i === void 0 ? {} : { status: i }
239
- }), je = (e) => e === void 0 || e === 408 || e === 429 || e >= 500, Me = /* @__PURE__ */ new Map(), Ne = (e, t) => Me.get(e)?.get(t)?.bytes, Pe = (e) => {
240
- Me.get(e)?.clear();
241
- }, Fe = (e = "default") => {
242
- let t = Me.get(e) ?? /* @__PURE__ */ new Map();
243
- return Me.set(e, t), {
239
+ }), Me = (e) => e === void 0 || e === 408 || e === 429 || e >= 500, Ne = /* @__PURE__ */ new Map(), Pe = (e, t) => Ne.get(e)?.get(t)?.bytes, Fe = (e) => {
240
+ Ne.get(e)?.clear();
241
+ }, Ie = (e = "default") => {
242
+ let t = Ne.get(e) ?? /* @__PURE__ */ new Map();
243
+ return Ne.set(e, t), {
244
244
  name: "memory",
245
245
  presigns: !1,
246
246
  put: (e, n, r) => b.sync(() => (t.set(e, {
@@ -252,7 +252,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
252
252
  return n ? b.succeed({
253
253
  bytes: n.bytes,
254
254
  contentType: n.contentType
255
- }) : b.fail(K("memory", `no object at key '${e}'`, !1, 404));
255
+ }) : b.fail(J("memory", `no object at key '${e}'`, !1, 404));
256
256
  }),
257
257
  delete: (e) => b.sync(() => {
258
258
  t.delete(e);
@@ -264,14 +264,14 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
264
264
  return n ? { size: n.bytes.byteLength } : null;
265
265
  })
266
266
  };
267
- }, Ie = (e) => {
267
+ }, Le = (e) => {
268
268
  let t = e.root, n = async (e) => {
269
269
  let { join: n, resolve: r, sep: i } = await import("node:path"), a = r(t), o = r(a, e);
270
270
  if (o !== a && !o.startsWith(a + i)) throw Error(`key '${e}' escapes the storage root`);
271
271
  return n(o);
272
272
  }, r = (e, t, n = !1) => b.tryPromise({
273
273
  try: e,
274
- catch: (e) => e?.code === "ENOENT" ? K("filesystem", `no object at key '${t}'`, !1, 404) : K("filesystem", String(e?.message ?? e), n)
274
+ catch: (e) => e?.code === "ENOENT" ? J("filesystem", `no object at key '${t}'`, !1, 404) : J("filesystem", String(e?.message ?? e), n)
275
275
  });
276
276
  return {
277
277
  root: t,
@@ -310,12 +310,12 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
310
310
  throw e;
311
311
  }
312
312
  },
313
- catch: (e) => K("filesystem", String(e?.message ?? e), !1)
313
+ catch: (e) => J("filesystem", String(e?.message ?? e), !1)
314
314
  }),
315
315
  getStream: (e) => r(async () => {
316
316
  let t = await import("node:fs/promises"), { createReadStream: r } = await import("node:fs"), i = await n(e), a = await t.stat(i);
317
317
  return {
318
- stream: Se("filesystem", () => r(i)),
318
+ stream: Ce("filesystem", () => r(i)),
319
319
  contentType: "application/octet-stream",
320
320
  size: a.size
321
321
  };
@@ -325,7 +325,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
325
325
  await r.mkdir(i(c), { recursive: !0 });
326
326
  let l = `${c}.tmp-${a()}`;
327
327
  try {
328
- await s(await Ce(t), o(l));
328
+ await s(await we(t), o(l));
329
329
  let e = await r.stat(l);
330
330
  return await r.rename(l, c), { size: e.size };
331
331
  } catch (e) {
@@ -340,10 +340,10 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
340
340
  end: i
341
341
  });
342
342
  s.on("data", (e) => o.push(e)), s.on("end", () => e()), s.on("error", n);
343
- }), ye(o);
343
+ }), be(o);
344
344
  }, e)
345
345
  };
346
- }, Le = (e) => {
346
+ }, Re = (e) => {
347
347
  let t = e.name ?? "s3", n = e.publicAcl ?? !0, r = null, i = () => r || (r = (async () => {
348
348
  let t, n;
349
349
  try {
@@ -368,7 +368,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
368
368
  try: e,
369
369
  catch: (e) => {
370
370
  let n = e?.$metadata?.httpStatusCode;
371
- return K(t, String(e?.message ?? e), je(n), n);
371
+ return J(t, String(e?.message ?? e), Me(n), n);
372
372
  }
373
373
  }), o = async (e) => {
374
374
  let t = e;
@@ -483,7 +483,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
483
483
  },
484
484
  catch: (e) => {
485
485
  let n = e?.$metadata?.httpStatusCode;
486
- return K(t, String(e?.message ?? e), je(n), n);
486
+ return J(t, String(e?.message ?? e), Me(n), n);
487
487
  }
488
488
  }),
489
489
  getStream: (n) => a(async () => {
@@ -492,7 +492,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
492
492
  Key: n
493
493
  })), s = o.Body;
494
494
  return {
495
- stream: Se(t, () => s),
495
+ stream: Ce(t, () => s),
496
496
  contentType: o.ContentType ?? "application/octet-stream",
497
497
  ...o.ContentLength === void 0 ? {} : { size: o.ContentLength }
498
498
  };
@@ -504,7 +504,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
504
504
  } catch (e) {
505
505
  throw Error("s3/minio `putStream` requires the '@aws-sdk/lib-storage' optional dependency (multipart upload). Install it to enable streamed uploads.", { cause: e });
506
506
  }
507
- let l = await Ce(r);
507
+ let l = await we(r);
508
508
  return await new c.Upload({
509
509
  client: a,
510
510
  params: {
@@ -528,15 +528,15 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
528
528
  return o(c.Body);
529
529
  })
530
530
  };
531
- }, Re = (e) => e instanceof Uint8Array ? e : typeof e == "string" ? new Uint8Array(Buffer.from(e, "base64")) : new Uint8Array(e), ze = () => {
531
+ }, ze = (e) => e instanceof Uint8Array ? e : typeof e == "string" ? new Uint8Array(Buffer.from(e, "base64")) : new Uint8Array(e), Be = () => {
532
532
  let e = null, t = () => {
533
533
  if (!e) throw Error("the 'database' storage provider isn't bound to a DataStore yet");
534
534
  return e;
535
535
  }, n = (e) => b.tryPromise({
536
536
  try: e,
537
- catch: (e) => K("database", String(e?.message ?? e), !0)
537
+ catch: (e) => J("database", String(e?.message ?? e), !0)
538
538
  }), r = async (e) => (await t().query({
539
- table: W,
539
+ table: K,
540
540
  predicate: {
541
541
  column: "key",
542
542
  op: "eq",
@@ -555,15 +555,15 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
555
555
  },
556
556
  put: (e, i, a) => n(async () => {
557
557
  let n = await r(e);
558
- return n ? await t().update(W, String(n.id), {
558
+ return n ? await t().update(K, String(n.id), {
559
559
  data: i,
560
560
  contentType: a.contentType,
561
561
  size: i.byteLength
562
- }) : await t().insert(W, {
563
- id: k({
562
+ }) : await t().insert(K, {
563
+ id: A({
564
564
  kind: "typeid",
565
565
  prefix: "blob"
566
- }, W),
566
+ }, K),
567
567
  key: e,
568
568
  data: i,
569
569
  contentType: a.contentType,
@@ -571,12 +571,12 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
571
571
  }), { size: i.byteLength };
572
572
  }),
573
573
  get: (e) => b.suspend(() => n(() => r(e)).pipe(b.flatMap((t) => t ? b.succeed({
574
- bytes: Re(t.data),
574
+ bytes: ze(t.data),
575
575
  contentType: String(t.contentType)
576
- }) : b.fail(K("database", `no object at key '${e}'`, !1, 404))))),
576
+ }) : b.fail(J("database", `no object at key '${e}'`, !1, 404))))),
577
577
  delete: (e) => n(async () => {
578
578
  let n = await r(e);
579
- n && await t().delete(W, String(n.id));
579
+ n && await t().delete(K, String(n.id));
580
580
  }),
581
581
  publicUrl: () => null,
582
582
  getUrl: () => b.succeed(""),
@@ -585,7 +585,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
585
585
  return t ? { size: Number(t.size) } : null;
586
586
  })
587
587
  };
588
- }, Be = (e) => {
588
+ }, Ve = (e) => {
589
589
  let t = null, n = () => t || (t = (async () => {
590
590
  let t;
591
591
  try {
@@ -593,7 +593,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
593
593
  } catch (e) {
594
594
  throw Error("the 'azure' storage provider requires the '@azure/storage-blob' optional dependency. Install it to enable it.", { cause: e });
595
595
  }
596
- let n = G.read("AZURE_STORAGE_ACCOUNT", e.accountName), r = G.read("AZURE_STORAGE_KEY", e.accountKey), i = n && r ? new t.StorageSharedKeyCredential(n, r) : null, a = G.read("AZURE_STORAGE_CONNECTION_STRING", e.connectionString);
596
+ let n = q.read("AZURE_STORAGE_ACCOUNT", e.accountName), r = q.read("AZURE_STORAGE_KEY", e.accountKey), i = n && r ? new t.StorageSharedKeyCredential(n, r) : null, a = q.read("AZURE_STORAGE_CONNECTION_STRING", e.connectionString);
597
597
  return {
598
598
  container: (a ? t.BlobServiceClient.fromConnectionString(a) : new t.BlobServiceClient(e.endpoint ?? `https://${n}.blob.core.windows.net`, i ?? void 0)).getContainerClient(e.container),
599
599
  sdk: t,
@@ -603,7 +603,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
603
603
  try: e,
604
604
  catch: (e) => {
605
605
  let t = e?.statusCode;
606
- return K("azure", String(e?.message ?? e), je(t), t);
606
+ return J("azure", String(e?.message ?? e), Me(t), t);
607
607
  }
608
608
  }), i = async (e) => {
609
609
  if (!e) return /* @__PURE__ */ new Uint8Array();
@@ -661,19 +661,19 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
661
661
  },
662
662
  catch: (e) => {
663
663
  let t = e?.statusCode;
664
- return K("azure", String(e?.message ?? e), je(t), t);
664
+ return J("azure", String(e?.message ?? e), Me(t), t);
665
665
  }
666
666
  }),
667
667
  getStream: (e) => r(async () => {
668
668
  let { container: t } = await n(), r = await t.getBlockBlobClient(e).download();
669
669
  return {
670
- stream: Se("azure", () => r.readableStreamBody),
670
+ stream: Ce("azure", () => r.readableStreamBody),
671
671
  contentType: r.contentType ?? "application/octet-stream",
672
672
  ...r.contentLength === void 0 ? {} : { size: r.contentLength }
673
673
  };
674
674
  }),
675
675
  putStream: (e, t, i) => r(async () => {
676
- let { container: r } = await n(), a = await Ce(t);
676
+ let { container: r } = await n(), a = await we(t);
677
677
  return await r.getBlockBlobClient(e).uploadStream(a, 4194304, 5, { blobHTTPHeaders: { blobContentType: i.contentType } }), { size: i.totalSize ?? (await r.getBlockBlobClient(e).getProperties()).contentLength ?? 0 };
678
678
  }),
679
679
  getRange: (e, t, a) => r(async () => {
@@ -681,13 +681,13 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
681
681
  return i(o.readableStreamBody);
682
682
  })
683
683
  };
684
- }, Ve = {
684
+ }, He = {
685
685
  webp: "image/webp",
686
686
  avif: "image/avif",
687
687
  jpeg: "image/jpeg",
688
688
  jpg: "image/jpeg",
689
689
  png: "image/png"
690
- }, He = (e) => {
690
+ }, Ue = (e) => {
691
691
  if (!e) return null;
692
692
  let t = new URLSearchParams(e), n = (e) => {
693
693
  let n = t.get(e);
@@ -702,18 +702,18 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
702
702
  ...a === void 0 ? {} : { q: a },
703
703
  ...s ? { fit: s } : {}
704
704
  };
705
- }, Ue = (e) => e.startsWith("image/") && !e.includes("svg"), q, We = async () => {
706
- if (q !== void 0) return q;
705
+ }, We = (e) => e.startsWith("image/") && !e.includes("svg"), Ge, Ke = async () => {
706
+ if (Ge !== void 0) return Ge;
707
707
  try {
708
708
  let e = await import("sharp");
709
- q = e.default ?? e;
709
+ Ge = e.default ?? e;
710
710
  } catch {
711
- q = null;
711
+ Ge = null;
712
712
  }
713
- return q;
714
- }, Ge = async (e, t, n) => {
715
- if (!Ue(t)) return null;
716
- let r = await We();
713
+ return Ge;
714
+ }, qe = async (e, t, n) => {
715
+ if (!We(t)) return null;
716
+ let r = await Ke();
717
717
  if (!r) return null;
718
718
  try {
719
719
  let i = r(Buffer.from(e), { failOn: "none" });
@@ -723,10 +723,10 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
723
723
  fit: n.fit ?? "cover",
724
724
  withoutEnlargement: !0
725
725
  }));
726
- let a = n.format && Ve[n.format] ? n.format : void 0, o = t;
726
+ let a = n.format && He[n.format] ? n.format : void 0, o = t;
727
727
  if (a) {
728
728
  let e = a === "jpg" ? "jpeg" : a;
729
- i = i.toFormat(e, n.q === void 0 ? {} : { quality: n.q }), o = Ve[a];
729
+ i = i.toFormat(e, n.q === void 0 ? {} : { quality: n.q }), o = He[a];
730
730
  } else n.q !== void 0 && (t === "image/jpeg" || t === "image/webp") && (i = i.toFormat(t === "image/webp" ? "webp" : "jpeg", { quality: n.q }));
731
731
  let s = await i.toBuffer();
732
732
  return {
@@ -736,43 +736,43 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
736
736
  } catch {
737
737
  return null;
738
738
  }
739
- }, Ke = 200, J = /* @__PURE__ */ new Map(), qe = async (e, t, n, r) => {
740
- let i = `${e}::${JSON.stringify(r)}`, a = J.get(i);
739
+ }, Je = 200, Ye = /* @__PURE__ */ new Map(), Xe = async (e, t, n, r) => {
740
+ let i = `${e}::${JSON.stringify(r)}`, a = Ye.get(i);
741
741
  if (a) return a;
742
- let o = await Ge(t, n, r);
743
- if (o && (J.set(i, o), J.size > Ke)) {
744
- let e = J.keys().next().value;
745
- e !== void 0 && J.delete(e);
742
+ let o = await qe(t, n, r);
743
+ if (o && (Ye.set(i, o), Ye.size > Je)) {
744
+ let e = Ye.keys().next().value;
745
+ e !== void 0 && Ye.delete(e);
746
746
  }
747
747
  return o;
748
- }, Je = (e) => {
749
- let t = le(16).toString("hex");
750
- return `${t}:${R(e, t, 32).toString("hex")}`;
751
- }, Ye = (e, t) => {
748
+ }, Ze = (e) => {
749
+ let t = B(16).toString("hex");
750
+ return `${t}:${de(e, t, 32).toString("hex")}`;
751
+ }, Qe = (e, t) => {
752
752
  if (!e || !t) return !1;
753
753
  let [n, r] = t.split(":");
754
754
  if (!n || !r) return !1;
755
- let i = Buffer.from(r, "hex"), a = R(e, n, i.length);
756
- return a.length === i.length && z(a, i);
757
- }, Xe = (e) => Array.isArray(e) ? e.filter((e) => typeof e == "string") : [], Ze = (e) => Xe(e.metadata?.roles), Qe = (e) => Xe(e.scopes), $e = (e, t) => e.some((e) => t.includes(e)), et = (e) => Xe(e.metadata?.groups), tt = (e) => typeof e == "boolean" ? b.succeed(e) : b.isEffect(e) ? e : b.promise(() => e), nt = (e, t, n = {}) => b.gen(function* () {
755
+ let i = Buffer.from(r, "hex"), a = de(e, n, i.length);
756
+ return a.length === i.length && V(a, i);
757
+ }, $e = (e) => Array.isArray(e) ? e.filter((e) => typeof e == "string") : [], et = (e) => $e(e.metadata?.roles), tt = (e) => $e(e.scopes), nt = (e, t) => e.some((e) => t.includes(e)), rt = (e) => $e(e.metadata?.groups), it = (e) => typeof e == "boolean" ? b.succeed(e) : b.isEffect(e) ? e : b.promise(() => e), at = (e, t, n = {}) => b.gen(function* () {
758
758
  if (t.id && e.ownerId && t.id === e.ownerId) return !0;
759
759
  let r = e.accessPolicy ?? [];
760
760
  if (r.length === 0) return !1;
761
- let i = n.resolveGroups ? yield* b.promise(async () => await n.resolveGroups(t)) : et(t);
762
- for (let a of r) if (yield* rt(a, e, t, i, n)) return !0;
761
+ let i = n.resolveGroups ? yield* b.promise(async () => await n.resolveGroups(t)) : rt(t);
762
+ for (let a of r) if (yield* ot(a, e, t, i, n)) return !0;
763
763
  return !1;
764
- }), rt = (e, t, n, r, i) => b.gen(function* () {
764
+ }), ot = (e, t, n, r, i) => b.gen(function* () {
765
765
  let a = !1, o = (e) => (a = !0, e);
766
- 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($e(Ze(n), e.roles)) || e.groups && e.groups.length > 0 && !o($e(r, e.groups)) || e.scopes && e.scopes.length > 0 && !o($e(Qe(n), e.scopes)) || e.password !== void 0 && e.password && !o(Ye(i.password, t.passwordHash))) return !1;
766
+ 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(nt(et(n), e.roles)) || e.groups && e.groups.length > 0 && !o(nt(r, e.groups)) || e.scopes && e.scopes.length > 0 && !o(nt(tt(n), e.scopes)) || e.password !== void 0 && e.password && !o(Qe(i.password, t.passwordHash))) return !1;
767
767
  if (e.guard) {
768
768
  let r = i.guards?.[e.guard];
769
- if (!o(r ? yield* tt(r({
769
+ if (!o(r ? yield* it(r({
770
770
  subject: n,
771
771
  ref: t
772
772
  })) : !1)) return !1;
773
773
  }
774
774
  return a;
775
- }), it = (e, t) => {
775
+ }), st = (e, t) => {
776
776
  let n = [];
777
777
  e.id && n.push({
778
778
  type: e.type === "apiKey" ? "apiKey" : "user",
@@ -783,115 +783,115 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
783
783
  id: e
784
784
  });
785
785
  return n;
786
- }, at = (e, t, n, r, i) => {
787
- let a = it(t, n);
786
+ }, ct = (e, t, n, r, i) => {
787
+ let a = st(t, n);
788
788
  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));
789
- }, ot = (e, t) => t.resolveGroups ? b.promise(async () => await t.resolveGroups(e)) : b.succeed(et(e)), Y = () => G.read("VOLTRO_STORAGE_SECRET") ?? ie(), X = (e) => (typeof e == "string" ? Buffer.from(e, "utf8") : e).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""), Z = (e) => {
789
+ }, lt = (e, t) => t.resolveGroups ? b.promise(async () => await t.resolveGroups(e)) : b.succeed(rt(e)), Y = () => q.read("VOLTRO_STORAGE_SECRET") ?? ae(), X = (e) => (typeof e == "string" ? Buffer.from(e, "utf8") : e).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""), Z = (e) => {
790
790
  let t = e.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - e.length % 4) % 4);
791
791
  return Buffer.from(t, "base64");
792
- }, st = (e, t, n = Y()) => {
792
+ }, ut = (e, t, n = Y()) => {
793
793
  if (!n) throw Error("signGrant: secret must be a non-empty string");
794
794
  let r = {
795
795
  refId: e,
796
796
  exp: Math.floor(Date.now() / 1e3) + Math.floor(t)
797
797
  }, i = X(JSON.stringify(r));
798
- return `${i}.${X(L("sha256", n).update(i).digest())}`;
799
- }, ct = (e, t = Y()) => {
798
+ return `${i}.${X(z("sha256", n).update(i).digest())}`;
799
+ }, dt = (e, t = Y()) => {
800
800
  if (!e || !t) return null;
801
801
  let n = e.indexOf(".");
802
802
  if (n <= 0 || n === e.length - 1) return null;
803
- let r = e.slice(0, n), i = e.slice(n + 1), a = L("sha256", t).update(r).digest(), o = Z(i);
804
- if (o.length !== a.length || !z(o, a)) return null;
803
+ let r = e.slice(0, n), i = e.slice(n + 1), a = z("sha256", t).update(r).digest(), o = Z(i);
804
+ if (o.length !== a.length || !V(o, a)) return null;
805
805
  try {
806
806
  let e = JSON.parse(Z(r).toString("utf8"));
807
807
  return typeof e.refId != "string" || typeof e.exp != "number" || e.exp < Math.floor(Date.now() / 1e3) ? null : e;
808
808
  } catch {
809
809
  return null;
810
810
  }
811
- }, lt = (e, t, n = Y()) => {
811
+ }, ft = (e, t, n = Y()) => {
812
812
  if (!n) throw Error("signUploadTicket: secret must be a non-empty string");
813
813
  let r = {
814
814
  ...e,
815
815
  exp: Math.floor(Date.now() / 1e3) + Math.floor(t)
816
816
  }, i = X(JSON.stringify(r));
817
- return `${i}.${X(L("sha256", n).update(`u:${i}`).digest())}`;
818
- }, ut = (e, t = Y()) => {
817
+ return `${i}.${X(z("sha256", n).update(`u:${i}`).digest())}`;
818
+ }, pt = (e, t = Y()) => {
819
819
  if (!e || !t) return null;
820
820
  let n = e.indexOf(".");
821
821
  if (n <= 0 || n === e.length - 1) return null;
822
- let r = e.slice(0, n), i = e.slice(n + 1), a = L("sha256", t).update(`u:${r}`).digest(), o = Z(i);
823
- if (o.length !== a.length || !z(o, a)) return null;
822
+ let r = e.slice(0, n), i = e.slice(n + 1), a = z("sha256", t).update(`u:${r}`).digest(), o = Z(i);
823
+ if (o.length !== a.length || !V(o, a)) return null;
824
824
  try {
825
825
  let e = JSON.parse(Z(r).toString("utf8"));
826
- return typeof e.ct != "string" || typeof e.exp != "number" || e.vis !== "public" && e.vis !== "private" || e.exp < Math.floor(Date.now() / 1e3) ? null : e;
826
+ return 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;
827
827
  } catch {
828
828
  return null;
829
829
  }
830
- }, dt = (e, t, n = Y()) => {
830
+ }, mt = (e, t, n = Y()) => {
831
831
  if (!n) throw Error("signFinalizeTicket: secret must be a non-empty string");
832
832
  let r = {
833
833
  ...e,
834
834
  exp: Math.floor(Date.now() / 1e3) + Math.floor(t)
835
835
  }, i = X(JSON.stringify(r));
836
- return `${i}.${X(L("sha256", n).update(`f:${i}`).digest())}`;
837
- }, ft = (e, t = Y()) => {
836
+ return `${i}.${X(z("sha256", n).update(`f:${i}`).digest())}`;
837
+ }, ht = (e, t = Y()) => {
838
838
  if (!e || !t) return null;
839
839
  let n = e.indexOf(".");
840
840
  if (n <= 0 || n === e.length - 1) return null;
841
- let r = e.slice(0, n), i = e.slice(n + 1), a = L("sha256", t).update(`f:${r}`).digest(), o = Z(i);
842
- if (o.length !== a.length || !z(o, a)) return null;
841
+ let r = e.slice(0, n), i = e.slice(n + 1), a = z("sha256", t).update(`f:${r}`).digest(), o = Z(i);
842
+ if (o.length !== a.length || !V(o, a)) return null;
843
843
  try {
844
844
  let e = JSON.parse(Z(r).toString("utf8"));
845
- return typeof e.key != "string" || e.key.length === 0 || typeof e.ct != "string" || typeof e.exp != "number" || e.vis !== "public" && e.vis !== "private" || e.exp < Math.floor(Date.now() / 1e3) ? null : e;
845
+ return 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;
846
846
  } catch {
847
847
  return null;
848
848
  }
849
- }, pt = (e, t, n = Y()) => {
849
+ }, gt = (e, t, n = Y()) => {
850
850
  if (!n) throw Error("signResumableTicket: secret must be a non-empty string");
851
851
  let r = {
852
852
  ...e,
853
853
  exp: Math.floor(Date.now() / 1e3) + Math.floor(t)
854
854
  }, i = X(JSON.stringify(r));
855
- return `${i}.${X(L("sha256", n).update(`r:${i}`).digest())}`;
856
- }, mt = (e, t = Y()) => {
855
+ return `${i}.${X(z("sha256", n).update(`r:${i}`).digest())}`;
856
+ }, _t = (e, t = Y()) => {
857
857
  if (!e || !t) return null;
858
858
  let n = e.indexOf(".");
859
859
  if (n <= 0 || n === e.length - 1) return null;
860
- let r = e.slice(0, n), i = e.slice(n + 1), a = L("sha256", t).update(`r:${r}`).digest(), o = Z(i);
861
- if (o.length !== a.length || !z(o, a)) return null;
860
+ let r = e.slice(0, n), i = e.slice(n + 1), a = z("sha256", t).update(`r:${r}`).digest(), o = Z(i);
861
+ if (o.length !== a.length || !V(o, a)) return null;
862
862
  try {
863
863
  let e = JSON.parse(Z(r).toString("utf8"));
864
- return typeof e.id != "string" || e.id.length === 0 || typeof e.size != "number" || e.size < 0 || typeof e.ct != "string" || typeof e.exp != "number" || e.vis !== "public" && e.vis !== "private" || e.exp < Math.floor(Date.now() / 1e3) ? null : e;
864
+ return 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;
865
865
  } catch {
866
866
  return null;
867
867
  }
868
- }, ht = (e, t, n = Y()) => {
868
+ }, vt = (e, t, n = Y()) => {
869
869
  if (!n) throw Error("signMultipartTicket: secret must be a non-empty string");
870
870
  let r = {
871
871
  ...e,
872
872
  exp: Math.floor(Date.now() / 1e3) + Math.floor(t)
873
873
  }, i = X(JSON.stringify(r));
874
- return `${i}.${X(L("sha256", n).update(`m:${i}`).digest())}`;
875
- }, gt = (e, t = Y()) => {
874
+ return `${i}.${X(z("sha256", n).update(`m:${i}`).digest())}`;
875
+ }, yt = (e, t = Y()) => {
876
876
  if (!e || !t) return null;
877
877
  let n = e.indexOf(".");
878
878
  if (n <= 0 || n === e.length - 1) return null;
879
- let r = e.slice(0, n), i = e.slice(n + 1), a = L("sha256", t).update(`m:${r}`).digest(), o = Z(i);
880
- if (o.length !== a.length || !z(o, a)) return null;
879
+ let r = e.slice(0, n), i = e.slice(n + 1), a = z("sha256", t).update(`m:${r}`).digest(), o = Z(i);
880
+ if (o.length !== a.length || !V(o, a)) return null;
881
881
  try {
882
882
  let e = JSON.parse(Z(r).toString("utf8"));
883
- return typeof e.key != "string" || e.key.length === 0 || typeof e.uploadId != "string" || e.uploadId.length === 0 || typeof e.ct != "string" || typeof e.exp != "number" || e.vis !== "public" && e.vis !== "private" || e.exp < Math.floor(Date.now() / 1e3) ? null : e;
883
+ return 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;
884
884
  } catch {
885
885
  return null;
886
886
  }
887
- }, _t = (e, t) => {
887
+ }, bt = (e, t) => {
888
888
  if (!t || t.length === 0) return !0;
889
889
  let n = e.toLowerCase();
890
890
  return t.some((e) => {
891
891
  let t = e.toLowerCase();
892
892
  return t.endsWith("/*") ? n.startsWith(t.slice(0, -1)) : n === t;
893
893
  });
894
- }, vt = [
894
+ }, xt = [
895
895
  {
896
896
  ct: /^image\/png$/,
897
897
  offset: 0,
@@ -961,21 +961,21 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
961
961
  offset: 0,
962
962
  magic: [31, 139]
963
963
  }
964
- ], yt = (e, t) => {
965
- let n = t.toLowerCase(), r = vt.find((e) => e.ct.test(n));
964
+ ], St = (e, t) => {
965
+ let n = t.toLowerCase(), r = xt.find((e) => e.ct.test(n));
966
966
  return r ? e.length < r.offset + r.magic.length ? !1 : r.magic.every((t, n) => e[r.offset + n] === t) : !0;
967
- }, bt = (e, t, n) => n ? n.maxBytes !== void 0 && e.byteLength > n.maxBytes ? {
967
+ }, Ct = (e, t, n) => n ? n.maxBytes !== void 0 && e.byteLength > n.maxBytes ? {
968
968
  reason: "too-large",
969
969
  detail: `${e.byteLength} bytes exceeds the ${n.maxBytes}-byte limit`
970
- } : _t(t, n.allowedContentTypes) ? n.sniff && !yt(e, t) ? {
970
+ } : bt(t, n.allowedContentTypes) ? n.sniff && !St(e, t) ? {
971
971
  reason: "content-mismatch",
972
972
  detail: `bytes do not match the declared content type '${t}'`
973
973
  } : null : {
974
974
  reason: "content-type-not-allowed",
975
975
  detail: `content type '${t}' is not in the allow-list`
976
- } : null, xt = async (e, t, n) => {
977
- if (!Ue(t)) return { bytes: e };
978
- let r = await We();
976
+ } : null, wt = async (e, t, n) => {
977
+ if (!We(t)) return { bytes: e };
978
+ let r = await Ke();
979
979
  if (!r) return { bytes: e };
980
980
  try {
981
981
  let t = e;
@@ -998,11 +998,90 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
998
998
  } catch {
999
999
  return { bytes: e };
1000
1000
  }
1001
- }, St = async (e) => {
1001
+ }, Tt = 67108864, Et = (e) => new n({
1002
+ reason: "too-large",
1003
+ detail: `remote body exceeds the ${e}-byte ingest limit`
1004
+ }), Dt = (e, r) => b.suspend(() => {
1005
+ let i = r ?? Tt;
1006
+ return !Number.isSafeInteger(i) || i < 0 ? b.fail(new t({
1007
+ provider: "ingest",
1008
+ message: "limits.maxBytes must be a non-negative safe integer",
1009
+ transient: !1
1010
+ })) : b.tryPromise({
1011
+ try: async (n) => {
1012
+ let r = await fetch(e, { signal: n }), a;
1013
+ try {
1014
+ if (!r.ok) throw new t({
1015
+ provider: "ingest",
1016
+ message: `remote server returned HTTP ${r.status}`,
1017
+ transient: r.status === 429 || r.status >= 500,
1018
+ status: r.status
1019
+ });
1020
+ let e = r.headers.get("content-length"), n = r.headers.get("content-encoding")?.trim().toLowerCase();
1021
+ if ((!n || n === "identity") && e !== null && /^\d+$/.test(e) && BigInt(e) > BigInt(i)) throw Et(i);
1022
+ let o = /* @__PURE__ */ new Uint8Array(), s = 0;
1023
+ if (r.body !== null) for (a = r.body.getReader();;) {
1024
+ let e = await a.read();
1025
+ if (e.done) break;
1026
+ if (e.value.byteLength > i - s) throw Et(i);
1027
+ if (e.value.byteLength !== 0) {
1028
+ let t = s + e.value.byteLength;
1029
+ if (t > o.byteLength) {
1030
+ let e = Math.min(i, Math.max(65536, o.byteLength * 2, t)), n = new Uint8Array(e);
1031
+ n.set(o), o = n;
1032
+ }
1033
+ o.set(e.value, s), s = t;
1034
+ }
1035
+ }
1036
+ return {
1037
+ bytes: s === o.byteLength ? o : o.slice(0, s),
1038
+ contentType: r.headers.get("content-type")?.split(";")[0]?.trim() || "application/octet-stream"
1039
+ };
1040
+ } finally {
1041
+ a === void 0 ? await r.body?.cancel().catch(() => {}) : (await a.cancel().catch(() => {}), a.releaseLock());
1042
+ }
1043
+ },
1044
+ catch: (e) => e instanceof n || e instanceof t ? e : new t({
1045
+ provider: "ingest",
1046
+ message: "remote fetch or body read failed",
1047
+ transient: !0
1048
+ })
1049
+ });
1050
+ }), Ot = (e, t) => b.suspend(() => {
1051
+ if (t === void 0) return e;
1052
+ if (t.aborted) return b.interrupt;
1053
+ let n = b.async((e) => {
1054
+ let n = () => e(b.interrupt);
1055
+ return t.addEventListener("abort", n, { once: !0 }), t.aborted && n(), b.sync(() => t.removeEventListener("abort", n));
1056
+ });
1057
+ return b.raceFirst(e, n);
1058
+ }), kt = async (e) => {
1002
1059
  let { createHash: t } = await import("node:crypto");
1003
1060
  return t("sha256").update(e).digest("hex");
1004
- }, Ct = (e, t) => e ? `${e.replace(/\/+$/, "")}/_voltro/storage/${t}` : `/_voltro/storage/${t}`, wt = (e, t) => {
1005
- if (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;
1061
+ }, At = (e, t, n) => `${e?.replace(/\/+$/, "") ?? ""}${n}/${t}`, jt = (e) => {
1062
+ let t = /* @__PURE__ */ new Map(), n = {
1063
+ public: 0,
1064
+ private: 0
1065
+ };
1066
+ for (let r of e) {
1067
+ let e = r.tenantId ?? "(global)", i = t.get(e) ?? {
1068
+ count: 0,
1069
+ bytes: 0
1070
+ };
1071
+ i.count += r.count, i.bytes += r.bytes, t.set(e, i), r.visibility === "public" ? n.public += r.count : n.private += r.count;
1072
+ }
1073
+ return {
1074
+ byTenant: Object.fromEntries(t),
1075
+ visibility: n
1076
+ };
1077
+ }, Mt = (e, t) => {
1078
+ if (t.search && ![
1079
+ e.id,
1080
+ e.key,
1081
+ e.contentType,
1082
+ e.ownerId,
1083
+ e.tenantId
1084
+ ].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;
1006
1085
  if (t.folder !== void 0) {
1007
1086
  let n = t.folder.replace(/\/+$/, ""), r = (e.folder ?? "").replace(/\/+$/, "");
1008
1087
  if (r !== n && !r.startsWith(`${n}/`)) return !1;
@@ -1012,15 +1091,23 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1012
1091
  if (!t.tags.every((e) => n.includes(e))) return !1;
1013
1092
  }
1014
1093
  return !0;
1015
- }, Tt = (e) => e ?? "global", Et = () => {
1094
+ }, Nt = (e) => e ?? "global", Pt = () => {
1016
1095
  let e = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Map();
1017
1096
  return {
1097
+ statistics: () => b.sync(() => jt((function* () {
1098
+ for (let t of e.values()) yield {
1099
+ tenantId: t.tenantId,
1100
+ visibility: t.visibility,
1101
+ count: 1,
1102
+ bytes: t.size
1103
+ };
1104
+ })())),
1018
1105
  insert: (t) => b.sync(() => {
1019
1106
  e.set(t.id, t);
1020
1107
  }),
1021
1108
  getById: (t) => b.sync(() => e.get(t) ?? null),
1022
1109
  delete: (t) => b.sync(() => e.delete(t)),
1023
- listRecent: (t) => b.sync(() => [...e.values()].sort((e, t) => t.createdAt.getTime() - e.createdAt.getTime()).slice(0, t)),
1110
+ listRecent: (t) => b.sync(() => [...e.values()].sort((e, t) => t.createdAt.getTime() - e.createdAt.getTime() || t.id.localeCompare(e.id)).slice(0, t)),
1024
1111
  countByKey: (t, n) => b.sync(() => [...e.values()].filter((e) => e.bucket === t && e.key === n).length),
1025
1112
  usageByTenant: (t) => b.sync(() => {
1026
1113
  let n = 0, r = 0;
@@ -1031,7 +1118,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1031
1118
  };
1032
1119
  }),
1033
1120
  consumeUsage: (e, n, r) => b.sync(() => {
1034
- let i = Tt(e), a = t.get(i) ?? {
1121
+ let i = Nt(e), a = t.get(i) ?? {
1035
1122
  bytes: 0,
1036
1123
  count: 0
1037
1124
  }, o = (r?.maxBytes === void 0 || a.bytes + n.bytes <= r.maxBytes) && (r?.maxCount === void 0 || a.count + n.count <= r.maxCount);
@@ -1045,16 +1132,16 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1045
1132
  };
1046
1133
  }),
1047
1134
  releaseUsage: (e, n) => b.sync(() => {
1048
- let r = Tt(e), i = t.get(r);
1135
+ let r = Nt(e), i = t.get(r);
1049
1136
  i && t.set(r, {
1050
1137
  bytes: Math.max(0, i.bytes - n.bytes),
1051
1138
  count: Math.max(0, i.count - n.count)
1052
1139
  });
1053
1140
  }),
1054
1141
  listByDerivedFrom: (t) => b.sync(() => [...e.values()].filter((e) => (e.derivedFrom ?? null) === t)),
1055
- listRefs: (t) => b.sync(() => [...e.values()].filter((e) => wt(e, t)).sort((e, t) => t.createdAt.getTime() - e.createdAt.getTime()).slice(t.offset, t.offset + t.limit))
1142
+ listRefs: (t) => b.sync(() => [...e.values()].filter((e) => Mt(e, t)).sort((e, t) => t.createdAt.getTime() - e.createdAt.getTime() || t.id.localeCompare(e.id)).slice(t.offset, t.offset + t.limit))
1056
1143
  };
1057
- }, Dt = (e) => Array.isArray(e) && e.every((e) => typeof e == "string") ? e : null, Ot = (e) => ({
1144
+ }, Ft = (e) => Array.isArray(e) && e.every((e) => typeof e == "string") ? e : null, It = (e) => ({
1058
1145
  id: String(e.id),
1059
1146
  tenantId: e.tenantId ?? null,
1060
1147
  ownerId: e.ownerId ?? null,
@@ -1072,7 +1159,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1072
1159
  duration: e.duration ?? null,
1073
1160
  placeholder: e.placeholder ?? null,
1074
1161
  folder: e.folder ?? null,
1075
- tags: Dt(e.tags),
1162
+ tags: Ft(e.tags),
1076
1163
  alt: e.alt ?? null,
1077
1164
  caption: e.caption ?? null,
1078
1165
  derivedFrom: e.derivedFrom ?? null,
@@ -1084,7 +1171,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1084
1171
  message: String(e?.message ?? e),
1085
1172
  transient: !0
1086
1173
  })
1087
- }), kt = async (e, t) => (await e.query({
1174
+ }), Lt = async (e, t) => (await e.query({
1088
1175
  table: "_voltro_storage_usage",
1089
1176
  predicate: {
1090
1177
  column: "tenantId",
@@ -1095,11 +1182,33 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1095
1182
  take: 1,
1096
1183
  skip: void 0,
1097
1184
  projection: void 0
1098
- }))[0] ?? null, At = (e) => ({
1099
- insert: (t) => Q(() => e.insert(H, { ...t })),
1185
+ }))[0] ?? null, Rt = (e) => ({
1186
+ statistics: () => Q(async () => jt((await e.query({
1187
+ table: W,
1188
+ predicate: void 0,
1189
+ order: [],
1190
+ take: void 0,
1191
+ skip: void 0,
1192
+ projection: void 0,
1193
+ groupBy: ["tenantId", "visibility"],
1194
+ aggregations: [{
1195
+ op: "count",
1196
+ alias: "count"
1197
+ }, {
1198
+ op: "sum",
1199
+ column: "size",
1200
+ alias: "bytes"
1201
+ }]
1202
+ })).map((e) => ({
1203
+ tenantId: e.tenantId == null ? null : String(e.tenantId),
1204
+ visibility: String(e.visibility),
1205
+ count: Number(e.count),
1206
+ bytes: Number(e.bytes ?? 0)
1207
+ })))),
1208
+ insert: (t) => Q(() => e.insert(W, { ...t })),
1100
1209
  getById: (t) => Q(async () => {
1101
1210
  let n = await e.query({
1102
- table: H,
1211
+ table: W,
1103
1212
  predicate: {
1104
1213
  column: "id",
1105
1214
  op: "eq",
@@ -1110,11 +1219,11 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1110
1219
  skip: void 0,
1111
1220
  projection: void 0
1112
1221
  });
1113
- return n[0] ? Ot(n[0]) : null;
1222
+ return n[0] ? It(n[0]) : null;
1114
1223
  }),
1115
- delete: (t) => Q(() => e.delete(H, t)),
1224
+ delete: (t) => Q(() => e.delete(W, t)),
1116
1225
  listRecent: (t) => Q(async () => (await e.query({
1117
- table: H,
1226
+ table: W,
1118
1227
  predicate: void 0,
1119
1228
  order: [{
1120
1229
  column: "createdAt",
@@ -1123,9 +1232,9 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1123
1232
  take: t,
1124
1233
  skip: void 0,
1125
1234
  projection: void 0
1126
- })).map(Ot)),
1235
+ })).map(It)),
1127
1236
  countByKey: (t, n) => Q(async () => (await e.query({
1128
- table: H,
1237
+ table: W,
1129
1238
  predicate: { and: [{
1130
1239
  column: "bucket",
1131
1240
  op: "eq",
@@ -1142,7 +1251,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1142
1251
  })).length),
1143
1252
  usageByTenant: (t) => Q(async () => {
1144
1253
  let n = await e.query({
1145
- table: H,
1254
+ table: W,
1146
1255
  predicate: {
1147
1256
  column: "tenantId",
1148
1257
  op: "eq",
@@ -1160,10 +1269,10 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1160
1269
  };
1161
1270
  }),
1162
1271
  consumeUsage: (t, n, r) => Q(async () => {
1163
- let i = Tt(t);
1272
+ let i = Nt(t);
1164
1273
  for (let t = 0; t < 32; t++) {
1165
1274
  t > 0 && await new Promise((e) => setTimeout(e, t));
1166
- let a = await kt(e, i), o = a ? Number(a.bytes ?? 0) : 0, s = a ? Number(a.count ?? 0) : 0;
1275
+ let a = await Lt(e, i), o = a ? Number(a.bytes ?? 0) : 0, s = a ? Number(a.count ?? 0) : 0;
1167
1276
  if (!((r?.maxBytes === void 0 || o + n.bytes <= r.maxBytes) && (r?.maxCount === void 0 || s + n.count <= r.maxCount))) return {
1168
1277
  allowed: !1,
1169
1278
  bytes: o,
@@ -1174,16 +1283,16 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1174
1283
  bytes: o + n.bytes,
1175
1284
  count: s + n.count,
1176
1285
  updatedAt: /* @__PURE__ */ new Date()
1177
- }, { where: D(O("id", String(a.id)), O("bytes", o), O("count", s)) }) === 1) return {
1286
+ }, { where: D(k("id", String(a.id)), k("bytes", o), k("count", s)) }) === 1) return {
1178
1287
  allowed: !0,
1179
1288
  bytes: o,
1180
1289
  count: s
1181
1290
  };
1182
1291
  } else {
1183
- let t = k({
1292
+ let t = A({
1184
1293
  kind: "typeid",
1185
1294
  prefix: "susage"
1186
- }, Ee), r = await e.insertIgnore(Ee, {
1295
+ }, De), r = await e.insertIgnore(De, {
1187
1296
  id: t,
1188
1297
  tenantId: i,
1189
1298
  bytes: n.bytes,
@@ -1200,22 +1309,22 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1200
1309
  throw Error(`storage usage consume: contention on tenant '${i}' exceeded 32 attempts`);
1201
1310
  }),
1202
1311
  releaseUsage: (t, n) => Q(async () => {
1203
- let r = Tt(t);
1312
+ let r = Nt(t);
1204
1313
  for (let t = 0; t < 32; t++) {
1205
1314
  t > 0 && await new Promise((e) => setTimeout(e, t));
1206
- let i = await kt(e, r);
1315
+ let i = await Lt(e, r);
1207
1316
  if (!i) return;
1208
1317
  let a = Number(i.bytes ?? 0), o = Number(i.count ?? 0);
1209
1318
  if (await e.updateMany("_voltro_storage_usage", {
1210
1319
  bytes: Math.max(0, a - n.bytes),
1211
1320
  count: Math.max(0, o - n.count),
1212
1321
  updatedAt: /* @__PURE__ */ new Date()
1213
- }, { where: D(O("id", String(i.id)), O("bytes", a), O("count", o)) }) === 1) return;
1322
+ }, { where: D(k("id", String(i.id)), k("bytes", a), k("count", o)) }) === 1) return;
1214
1323
  }
1215
1324
  throw Error(`storage usage release: contention on tenant '${r}' exceeded 32 attempts`);
1216
1325
  }),
1217
1326
  listByDerivedFrom: (t) => Q(async () => (await e.query({
1218
- table: H,
1327
+ table: W,
1219
1328
  predicate: {
1220
1329
  column: "derivedFrom",
1221
1330
  op: "eq",
@@ -1228,32 +1337,33 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1228
1337
  take: void 0,
1229
1338
  skip: void 0,
1230
1339
  projection: void 0
1231
- })).map(Ot)),
1340
+ })).map(It)),
1232
1341
  listRefs: (t) => Q(async () => {
1233
1342
  let n = [];
1234
- t.tenantId !== void 0 && n.push({
1235
- column: "tenantId",
1236
- op: "eq",
1237
- value: t.tenantId
1238
- }), t.ownerId !== void 0 && n.push({
1239
- column: "ownerId",
1240
- op: "eq",
1241
- value: t.ownerId
1242
- });
1243
- let r = n.length === 0 ? void 0 : n.length === 1 ? n[0] : { and: n };
1244
- return (await e.query({
1245
- table: H,
1246
- predicate: r,
1343
+ t.tenantId !== void 0 && n.push(k("tenantId", t.tenantId)), t.ownerId !== void 0 && n.push(k("ownerId", t.ownerId)), t.search && n.push(F(...[
1344
+ "id",
1345
+ "key",
1346
+ "contentType",
1347
+ "ownerId",
1348
+ "tenantId"
1349
+ ].map((e) => O(e, t.search))));
1350
+ let r = t.folder === void 0 && t.tags.length === 0 && t.includeDerived, i = n.length ? D(...n) : void 0, a = await e.query({
1351
+ table: W,
1352
+ predicate: i,
1247
1353
  order: [{
1248
1354
  column: "createdAt",
1249
1355
  direction: "desc"
1356
+ }, {
1357
+ column: "id",
1358
+ direction: "desc"
1250
1359
  }],
1251
- take: void 0,
1252
- skip: void 0,
1360
+ take: r ? t.limit : void 0,
1361
+ skip: r ? t.offset : void 0,
1253
1362
  projection: void 0
1254
- })).map(Ot).filter((e) => wt(e, t)).slice(t.offset, t.offset + t.limit);
1363
+ });
1364
+ return r ? a.map(It) : a.map(It).filter((e) => Mt(e, t)).slice(t.offset, t.offset + t.limit);
1255
1365
  })
1256
- }), jt = () => {
1366
+ }), zt = () => {
1257
1367
  let e = /* @__PURE__ */ new Map();
1258
1368
  return {
1259
1369
  insert: (t) => b.sync(() => {
@@ -1268,7 +1378,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1268
1378
  for (let [n, r] of e) r.refId === t && e.delete(n);
1269
1379
  })
1270
1380
  };
1271
- }, Mt = (e) => ({
1381
+ }, Bt = (e) => ({
1272
1382
  id: String(e.id),
1273
1383
  refId: String(e.refId),
1274
1384
  principalType: e.principalType,
@@ -1277,12 +1387,12 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1277
1387
  createdAt: e.createdAt instanceof Date ? e.createdAt : new Date(String(e.createdAt)),
1278
1388
  expiresAt: e.expiresAt ? e.expiresAt instanceof Date ? e.expiresAt : new Date(String(e.expiresAt)) : null,
1279
1389
  createdBy: e.createdBy ?? null
1280
- }), Nt = (e) => ({
1281
- insert: (t) => Q(() => e.insert(U, { ...t })),
1282
- delete: (t) => Q(() => e.delete(U, t)),
1390
+ }), Vt = (e) => ({
1391
+ insert: (t) => Q(() => e.insert(G, { ...t })),
1392
+ delete: (t) => Q(() => e.delete(G, t)),
1283
1393
  getById: (t) => Q(async () => {
1284
1394
  let n = (await e.query({
1285
- table: U,
1395
+ table: G,
1286
1396
  predicate: {
1287
1397
  column: "id",
1288
1398
  op: "eq",
@@ -1293,10 +1403,10 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1293
1403
  skip: void 0,
1294
1404
  projection: void 0
1295
1405
  }))[0];
1296
- return n ? Mt(n) : null;
1406
+ return n ? Bt(n) : null;
1297
1407
  }),
1298
1408
  listByRef: (t) => Q(async () => (await e.query({
1299
- table: U,
1409
+ table: G,
1300
1410
  predicate: {
1301
1411
  column: "refId",
1302
1412
  op: "eq",
@@ -1309,10 +1419,10 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1309
1419
  take: void 0,
1310
1420
  skip: void 0,
1311
1421
  projection: void 0
1312
- })).map(Mt)),
1422
+ })).map(Bt)),
1313
1423
  deleteByRef: (t) => Q(async () => {
1314
1424
  let n = await e.query({
1315
- table: U,
1425
+ table: G,
1316
1426
  predicate: {
1317
1427
  column: "refId",
1318
1428
  op: "eq",
@@ -1323,16 +1433,16 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1323
1433
  skip: void 0,
1324
1434
  projection: void 0
1325
1435
  });
1326
- for (let t of n) await e.delete(U, String(t.id));
1436
+ for (let t of n) await e.delete(G, String(t.id));
1327
1437
  })
1328
- }), Pt = () => k({
1438
+ }), Ht = () => A({
1329
1439
  kind: "typeid",
1330
1440
  prefix: "file"
1331
- }, H), Ft = () => k({
1441
+ }, W), Ut = () => A({
1332
1442
  kind: "typeid",
1333
1443
  prefix: "grant"
1334
- }, U), It = (i) => {
1335
- let { provider: a, refStore: o, grantStore: s, bucket: c } = i, l = i.access ?? {}, u = i.attempts ?? 3, d = i.urlExpiresInSec ?? 3600, f = (e) => Ct(i.publicBaseUrl, e), p = C.recurs(Math.max(0, u - 1)).pipe(C.intersect(C.exponential("100 millis")), C.whileInput((e) => e.transient)), m = (e, t, n) => [
1444
+ }, G), Wt = (i) => {
1445
+ let { provider: a, refStore: o, grantStore: s, bucket: c } = i, l = i.access ?? {}, u = i.attempts ?? 3, d = i.urlExpiresInSec ?? 3600, f = (e) => At(i.publicBaseUrl, e, i.httpPath ?? "/_voltro/storage"), p = C.recurs(Math.max(0, u - 1)).pipe(C.intersect(C.exponential("100 millis")), C.whileInput((e) => e.transient)), m = (e, t, n) => [
1336
1446
  i.tenantPrefix,
1337
1447
  e ?? "global",
1338
1448
  n ?? t
@@ -1385,7 +1495,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1385
1495
  catch: () => null
1386
1496
  }).pipe(b.catchAll(() => b.succeed(null)));
1387
1497
  }), v = (e) => b.gen(function* () {
1388
- let t = bt(e.bytes, e.contentType, i.limits);
1498
+ let t = Ct(e.bytes, e.contentType, i.limits);
1389
1499
  if (t) return yield* b.fail(new n(t));
1390
1500
  if (i.scan) {
1391
1501
  let t = yield* te({
@@ -1395,10 +1505,10 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1395
1505
  });
1396
1506
  if (!t.clean) return yield* b.fail(new r({ threat: t.threat ?? "unknown" }));
1397
1507
  }
1398
- let s = yield* b.promise(() => xt(e.bytes, e.contentType, { normalize: i.normalizeImages ?? !1 })), l = s.bytes, u = yield* ne({
1508
+ let s = yield* b.promise(() => wt(e.bytes, e.contentType, { normalize: i.normalizeImages ?? !1 })), l = s.bytes, u = yield* ne({
1399
1509
  bytes: l,
1400
1510
  contentType: e.contentType
1401
- }), d = s.width ?? u?.width, f = s.height ?? u?.height, h = s.placeholder ?? u?.poster, g = e.duration ?? u?.duration, _ = yield* b.promise(() => St(l)), v = e.tenantId ?? null, y = e.visibility ?? "private", C = m(v, _, yield* ee(e.key)), w = {
1511
+ }), d = s.width ?? u?.width, f = s.height ?? u?.height, h = s.placeholder ?? u?.poster, g = e.duration ?? u?.duration, _ = yield* b.promise(() => kt(l)), v = e.tenantId ?? null, y = e.visibility ?? "private", C = m(v, _, yield* ee(e.key)), w = {
1402
1512
  bytes: l.byteLength,
1403
1513
  count: 1
1404
1514
  }, T = yield* o.consumeUsage(v, w, i.quota);
@@ -1409,8 +1519,8 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1409
1519
  detail: t
1410
1520
  }));
1411
1521
  }
1412
- let re = e.password ? yield* b.sync(() => Je(e.password)) : null, E = {
1413
- id: Pt(),
1522
+ let re = e.password ? yield* b.sync(() => Ze(e.password)) : null, E = {
1523
+ id: Ht(),
1414
1524
  tenantId: v,
1415
1525
  ownerId: e.ownerId ?? null,
1416
1526
  bucket: c,
@@ -1471,13 +1581,13 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1471
1581
  }
1472
1582
  return r;
1473
1583
  }), w = (e, t, n) => b.gen(function* () {
1474
- if (e.visibility === "public" || (yield* nt(e, t, {
1584
+ if (e.visibility === "public" || (yield* at(e, t, {
1475
1585
  ...l,
1476
1586
  ...n?.password === void 0 ? {} : { password: n.password }
1477
1587
  }))) return !0;
1478
- let r = yield* ot(t, l);
1479
- return at(yield* s.listByRef(e.id), t, r, n?.permission ?? "read", Date.now());
1480
- }), T = (e) => {
1588
+ let r = yield* lt(t, l);
1589
+ return ct(yield* s.listByRef(e.id), t, r, n?.permission ?? "read", Date.now());
1590
+ }), re = (e) => {
1481
1591
  if (e.visibility === "public") {
1482
1592
  let t = a.publicUrl?.(e.key);
1483
1593
  if (t != null) return t;
@@ -1490,6 +1600,10 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1490
1600
  bytes: t.bytes,
1491
1601
  ref: e
1492
1602
  }))))),
1603
+ getStream: (e, t) => _(e, t?.tenantId).pipe(b.map((e) => ({
1604
+ ref: e,
1605
+ stream: T.unwrap(b.suspend(() => a.getStream ? a.getStream(e.key).pipe(b.retry(p), b.map((e) => e.stream)) : a.get(e.key).pipe(b.retry(p), b.map((e) => T.make(e.bytes)))))
1606
+ }))),
1493
1607
  getRange: (e, n, r) => _(e, r?.tenantId).pipe(b.flatMap((e) => {
1494
1608
  let r = e.size, i = Math.max(0, Math.trunc(n.start));
1495
1609
  if (r > 0 && i >= r) return b.fail(new t({
@@ -1510,7 +1624,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1510
1624
  totalSize: r
1511
1625
  })));
1512
1626
  })),
1513
- getUrl: (e, t) => _(e, t?.tenantId).pipe(b.flatMap((e) => e.visibility === "public" ? b.succeed(T(e)) : a.presigns ? a.getUrl(e.key, t?.expiresInSec ?? d) : b.succeed(f(e.id)))),
1627
+ getUrl: (e, t) => _(e, t?.tenantId).pipe(b.flatMap((e) => e.visibility === "public" ? b.succeed(re(e)) : a.presigns ? a.getUrl(e.key, t?.expiresInSec ?? d) : b.succeed(f(e.id)))),
1514
1628
  head: (e, t) => o.getById(e).pipe(b.flatMap((e) => e ? g(e, t?.tenantId).pipe(b.map((e) => e)) : b.succeed(null))),
1515
1629
  delete: (e, t) => _(e, t?.tenantId).pipe(b.flatMap((t) => s.deleteByRef(e).pipe(b.flatMap(() => o.delete(e)), b.flatMap((e) => e ? o.countByKey(t.bucket, t.key).pipe(b.flatMap((e) => e === 0 ? a.delete(t.key).pipe(b.retry(p)) : b.void), b.flatMap(() => o.releaseUsage(t.tenantId, {
1516
1630
  bytes: t.size,
@@ -1523,14 +1637,14 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1523
1637
  transient: !1,
1524
1638
  status: 404
1525
1639
  }))));
1526
- if (s.visibility === "public") return T(s);
1640
+ if (s.visibility === "public") return re(s);
1527
1641
  if (!(yield* w(s, r, i?.password === void 0 ? {} : { password: i.password }))) return yield* b.fail(new e({
1528
1642
  refId: n,
1529
1643
  reason: "access denied"
1530
1644
  }));
1531
1645
  let c = i?.expiresInSec ?? d;
1532
1646
  if (a.presigns) return yield* a.getUrl(s.key, c);
1533
- let l = yield* b.sync(() => st(s.id, c));
1647
+ let l = yield* b.sync(() => ut(s.id, c));
1534
1648
  return `${f(s.id)}?t=${l}`;
1535
1649
  }),
1536
1650
  mintUploadUrl: (e) => b.gen(function* () {
@@ -1546,7 +1660,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1546
1660
  checkAccess: w,
1547
1661
  grant: (e) => b.gen(function* () {
1548
1662
  let t = {
1549
- id: Ft(),
1663
+ id: Ut(),
1550
1664
  refId: e.refId,
1551
1665
  principalType: e.principalType,
1552
1666
  principalId: e.principalId,
@@ -1581,51 +1695,36 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1581
1695
  usage: (e) => o.usageByTenant(e),
1582
1696
  sweepOrphans: (e) => b.gen(function* () {
1583
1697
  let t = e?.limit ?? 1e3, n = e?.dryRun ?? !1, r = yield* o.listRecent(t), i = [];
1584
- for (let e of r) (yield* a.head(e.key).pipe(b.catchAll(() => b.succeed(null)))) === null && (n || (yield* o.delete(e.id).pipe(b.catchAll(() => b.succeed(!1)))) && (yield* o.releaseUsage(e.tenantId, {
1585
- bytes: e.size,
1586
- count: 1
1587
- }).pipe(b.ignore)), i.push(e.id));
1698
+ for (let e of r) if ((yield* a.head(e.key)) === null) {
1699
+ if (!n) {
1700
+ if (!(yield* o.delete(e.id))) continue;
1701
+ yield* o.releaseUsage(e.tenantId, {
1702
+ bytes: e.size,
1703
+ count: 1
1704
+ });
1705
+ }
1706
+ i.push(e.id);
1707
+ }
1588
1708
  return {
1589
1709
  scanned: r.length,
1590
1710
  removed: i
1591
1711
  };
1592
1712
  }),
1593
- ingestUrl: (e, n) => b.gen(function* () {
1594
- let r = yield* b.tryPromise({
1595
- try: () => fetch(e),
1596
- catch: (e) => new t({
1597
- provider: "ingest",
1598
- message: `fetch failed: ${String(e?.message ?? e)}`,
1599
- transient: !0
1600
- })
1601
- });
1602
- if (!r.ok) return yield* b.fail(new t({
1603
- provider: "ingest",
1604
- message: `fetch ${e} → ${r.status}`,
1605
- transient: r.status >= 500,
1606
- status: r.status
1607
- }));
1608
- let i = yield* b.tryPromise({
1609
- try: () => r.arrayBuffer(),
1610
- catch: (e) => new t({
1611
- provider: "ingest",
1612
- message: `read body failed: ${String(e?.message ?? e)}`,
1613
- transient: !0
1614
- })
1615
- }), a = n?.contentType ?? r.headers.get("content-type")?.split(";")[0]?.trim() ?? "application/octet-stream";
1713
+ ingestUrl: (e, t) => Ot(b.gen(function* () {
1714
+ let n = yield* Dt(e, i.limits?.maxBytes);
1616
1715
  return yield* v({
1617
- bytes: new Uint8Array(i),
1618
- contentType: a,
1619
- ...n?.tenantId === void 0 ? {} : { tenantId: n.tenantId },
1620
- ...n?.ownerId === void 0 ? {} : { ownerId: n.ownerId },
1621
- ...n?.visibility === void 0 ? {} : { visibility: n.visibility },
1622
- ...n?.key === void 0 ? {} : { key: n.key },
1623
- ...n?.folder === void 0 ? {} : { folder: n.folder },
1624
- ...n?.tags === void 0 ? {} : { tags: n.tags },
1625
- ...n?.alt === void 0 ? {} : { alt: n.alt },
1626
- ...n?.caption === void 0 ? {} : { caption: n.caption }
1716
+ bytes: n.bytes,
1717
+ contentType: t?.contentType ?? n.contentType,
1718
+ ...t?.tenantId === void 0 ? {} : { tenantId: t.tenantId },
1719
+ ...t?.ownerId === void 0 ? {} : { ownerId: t.ownerId },
1720
+ ...t?.visibility === void 0 ? {} : { visibility: t.visibility },
1721
+ ...t?.key === void 0 ? {} : { key: t.key },
1722
+ ...t?.folder === void 0 ? {} : { folder: t.folder },
1723
+ ...t?.tags === void 0 ? {} : { tags: t.tags },
1724
+ ...t?.alt === void 0 ? {} : { alt: t.alt },
1725
+ ...t?.caption === void 0 ? {} : { caption: t.caption }
1627
1726
  });
1628
- }),
1727
+ }), t?.abortSignal),
1629
1728
  mintPresignedUpload: (e) => b.gen(function* () {
1630
1729
  if (!a.getUploadUrl) return yield* b.fail(new t({
1631
1730
  provider: a.name,
@@ -1633,10 +1732,10 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1633
1732
  transient: !1,
1634
1733
  status: 400
1635
1734
  }));
1636
- let n = e.expiresInSec ?? d, r = `_incoming/${k({
1735
+ let n = e.expiresInSec ?? d, r = `_incoming/${A({
1637
1736
  kind: "typeid",
1638
1737
  prefix: "up"
1639
- }, H)}`, i = m(e.tenantId ?? null, "", r);
1738
+ }, W)}`, i = m(e.tenantId ?? null, "", r);
1640
1739
  return {
1641
1740
  uploadUrl: yield* a.getUploadUrl(i, n, e.contentType),
1642
1741
  key: i,
@@ -1697,10 +1796,10 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1697
1796
  transient: !1,
1698
1797
  status: 400
1699
1798
  }));
1700
- let n = m(e.tenantId ?? null, "", `multipart/${k({
1799
+ let n = m(e.tenantId ?? null, "", `multipart/${A({
1701
1800
  kind: "typeid",
1702
1801
  prefix: "mp"
1703
- }, H)}`);
1802
+ }, W)}`);
1704
1803
  return {
1705
1804
  uploadId: (yield* a.createMultipartUpload(n, e.contentType, { public: (e.visibility ?? "private") === "public" })).uploadId,
1706
1805
  key: n
@@ -1728,7 +1827,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1728
1827
  detail: `multipart upload of ${l} bytes exceeds tenant quota`
1729
1828
  }));
1730
1829
  let m = {
1731
- id: Pt(),
1830
+ id: Ht(),
1732
1831
  tenantId: e.tenantId ?? null,
1733
1832
  ownerId: e.ownerId ?? null,
1734
1833
  bucket: c,
@@ -1749,7 +1848,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1749
1848
  }),
1750
1849
  abortMultipart: (e) => b.suspend(() => a.abortMultipartUpload ? a.abortMultipartUpload(e.key, e.uploadId).pipe(b.retry(p)) : b.void)
1751
1850
  };
1752
- }, Lt = (e) => S.succeed(i, It(e)), Rt = (e, t = 65536) => {
1851
+ }, Gt = (e) => S.succeed(i, Wt(e)), Kt = (e, t = 65536) => {
1753
1852
  let n = [Buffer.from("zINSTREAM\0", "utf8")];
1754
1853
  for (let r = 0; r < e.length; r += t) {
1755
1854
  let i = e.subarray(r, Math.min(r + t, e.length)), a = Buffer.alloc(4);
@@ -1757,7 +1856,7 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1757
1856
  }
1758
1857
  let r = Buffer.alloc(4);
1759
1858
  return r.writeUInt32BE(0, 0), n.push(r), Buffer.concat(n);
1760
- }, zt = (e) => {
1859
+ }, qt = (e) => {
1761
1860
  let t = e.replace(/\0+$/, "").trim();
1762
1861
  if (/\bOK$/.test(t)) return { clean: !0 };
1763
1862
  let n = /:\s*(.+?)\s+FOUND$/.exec(t);
@@ -1766,8 +1865,8 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1766
1865
  threat: n[1] ?? "unknown"
1767
1866
  };
1768
1867
  throw Error(`clamav: unexpected response: ${t}`);
1769
- }, Bt = async (e, t) => {
1770
- let n = await import("node:net"), r = G.read("CLAMAV_HOST", t.host) ?? "127.0.0.1", i = G.read("CLAMAV_PORT"), a = t.port ?? (i ? Number(i) : 3310), o = t.timeoutMs ?? 3e4;
1868
+ }, Jt = async (e, t) => {
1869
+ let n = await import("node:net"), r = q.read("CLAMAV_HOST", t.host) ?? "127.0.0.1", i = q.read("CLAMAV_PORT"), a = t.port ?? (i ? Number(i) : 3310), o = t.timeoutMs ?? 3e4;
1771
1870
  return new Promise((i, s) => {
1772
1871
  let c = n.createConnection({
1773
1872
  host: r,
@@ -1778,20 +1877,20 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1778
1877
  c.on("error", (e) => {
1779
1878
  clearTimeout(u), s(e);
1780
1879
  }), c.on("connect", () => {
1781
- c.end(Rt(e, t.chunkSize));
1880
+ c.end(Kt(e, t.chunkSize));
1782
1881
  }), c.on("data", (e) => {
1783
1882
  l += e.toString("utf8");
1784
1883
  }), c.on("close", () => {
1785
1884
  clearTimeout(u);
1786
1885
  try {
1787
- i(zt(l));
1886
+ i(qt(l));
1788
1887
  } catch (e) {
1789
1888
  s(e);
1790
1889
  }
1791
1890
  });
1792
1891
  });
1793
- }, Vt = (e = {}) => (t) => Bt(t.bytes, e), Ht = (e, t, n) => new Promise((r, i) => {
1794
- let a = de(e, [...t], { stdio: [
1892
+ }, Yt = (e = {}) => (t) => Jt(t.bytes, e), Xt = (e, t, n) => new Promise((r, i) => {
1893
+ let a = fe(e, [...t], { stdio: [
1795
1894
  "ignore",
1796
1895
  "ignore",
1797
1896
  "pipe"
@@ -1805,31 +1904,31 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1805
1904
  }), a.on("close", (e) => {
1806
1905
  clearTimeout(s), e === 0 ? r() : i(/* @__PURE__ */ Error(`ffmpeg exited ${String(e)}: ${o.slice(-400)}`));
1807
1906
  });
1808
- }), Ut = (e) => async ({ bytes: t }) => {
1809
- let n = e.ffmpegPath ?? "ffmpeg", r = e.timeoutMs ?? 3e5, i = await fe(he(V(), "voltro-tc-")), a = he(i, "in"), o = [];
1907
+ }), Zt = (e) => async ({ bytes: t }) => {
1908
+ let n = e.ffmpegPath ?? "ffmpeg", r = e.timeoutMs ?? 3e5, i = await pe(H(_e(), "voltro-tc-")), a = H(i, "in"), o = [];
1810
1909
  try {
1811
- await B(a, t);
1910
+ await ge(a, t);
1812
1911
  for (let t of e.renditions) {
1813
- let e = he(i, `out.${t.ext}`);
1912
+ let e = H(i, `out.${t.ext}`);
1814
1913
  try {
1815
- await Ht(n, [
1914
+ await Xt(n, [
1816
1915
  "-y",
1817
1916
  "-i",
1818
1917
  a,
1819
1918
  ...t.args,
1820
1919
  e
1821
1920
  ], r);
1822
- let i = await pe(e);
1921
+ let i = await me(e);
1823
1922
  o.push({
1824
1923
  bytes: new Uint8Array(i),
1825
1924
  contentType: t.contentType,
1826
1925
  kind: t.kind,
1827
1926
  ...t.label === void 0 ? {} : { label: t.label }
1828
- }), await me(e, { force: !0 });
1927
+ }), await he(e, { force: !0 });
1829
1928
  } catch {}
1830
1929
  }
1831
1930
  } finally {
1832
- await me(i, {
1931
+ await he(i, {
1833
1932
  recursive: !0,
1834
1933
  force: !0
1835
1934
  }).catch(() => void 0);
@@ -1838,21 +1937,21 @@ var _e = 1 << 20, ve = (e, n, r = !1) => new t({
1838
1937
  };
1839
1938
  //#endregion
1840
1939
  //#region src/assetRef.ts
1841
- function Wt(e = {}) {
1842
- let t = e.nullable ?? !0, n = e.fk === !1 ? P().externalId() : ce(() => De, { onDelete: e.onDelete ?? "setNull" });
1940
+ function Qt(e = {}) {
1941
+ let t = e.nullable ?? !0, n = e.fk === !1 ? L().externalId() : ce(() => Oe, { onDelete: e.onDelete ?? "setNull" });
1843
1942
  return t ? n.nullable() : n;
1844
1943
  }
1845
- var Gt = () => se({
1944
+ var $t = () => P({
1846
1945
  id: "@voltro/plugin-storage/withStorage",
1847
- fields: { asset: Wt() }
1848
- }), Kt = {
1946
+ fields: { asset: Qt() }
1947
+ }), en = {
1849
1948
  "image/png": "png",
1850
1949
  "image/jpeg": "jpg",
1851
1950
  "image/jpg": "jpg",
1852
1951
  "image/gif": "gif",
1853
1952
  "image/webp": "webp",
1854
1953
  "image/svg+xml": "svg"
1855
- }, qt = (e) => {
1954
+ }, tn = (e) => {
1856
1955
  let t = /^data:([^;,]+)(;base64)?,(.*)$/s.exec(e);
1857
1956
  if (!t) throw Error("not a data URI");
1858
1957
  let n = t[1] || "application/octet-stream", r = !!t[2], i = t[3] ?? "";
@@ -1860,16 +1959,16 @@ var Gt = () => se({
1860
1959
  bytes: r ? new Uint8Array(Buffer.from(i, "base64")) : new Uint8Array(Buffer.from(decodeURIComponent(i), "utf8")),
1861
1960
  contentType: n
1862
1961
  };
1863
- }, Jt = (e, n) => b.gen(function* () {
1962
+ }, nn = (e, n) => b.gen(function* () {
1864
1963
  let r = yield* b.try({
1865
- try: () => qt(n.dataUri),
1964
+ try: () => tn(n.dataUri),
1866
1965
  catch: (e) => new t({
1867
1966
  provider: "avatar",
1868
1967
  message: String(e?.message ?? e),
1869
1968
  transient: !1,
1870
1969
  status: 400
1871
1970
  })
1872
- }), i = Kt[r.contentType] ?? "bin";
1971
+ }), i = en[r.contentType] ?? "bin";
1873
1972
  return yield* e.put({
1874
1973
  bytes: r.bytes,
1875
1974
  contentType: r.contentType,
@@ -1878,27 +1977,43 @@ var Gt = () => se({
1878
1977
  visibility: "public",
1879
1978
  key: `avatars/${n.userId}/avatar.${i}`
1880
1979
  });
1881
- }), Yt = (e) => {
1980
+ }), rn = I("_voltro_storage_put_intents", {
1981
+ id: L().maxLength(64),
1982
+ refId: L().maxLength(64),
1983
+ identity: N(),
1984
+ ref: N()
1985
+ }).primaryKey(["id"]).unique("storagePutRef", ["refId"]).nonReactive();
1986
+ w.Struct({
1987
+ tenantId: w.NullOr(w.String),
1988
+ bucket: w.String,
1989
+ operationId: w.String,
1990
+ fingerprint: w.String,
1991
+ checksum: w.String,
1992
+ logicalKey: w.String
1993
+ });
1994
+ //#endregion
1995
+ //#region src/pathDurability.ts
1996
+ var an = (e) => {
1882
1997
  try {
1883
- let t = ge(e), n = ge("/");
1998
+ let t = U(e), n = U("/");
1884
1999
  return typeof t.dev != "number" || typeof n.dev != "number" ? "unknown" : t.dev === n.dev ? "same-device-as-root" : "separate-mount";
1885
2000
  } catch {
1886
2001
  return "unknown";
1887
2002
  }
1888
- }, Xt = (e) => {
1889
- if (Yt(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
2003
+ }, on = (e) => {
2004
+ if (an(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
1890
2005
  dies with it — which is the exact failure it exists for. On a development machine this is normal
1891
2006
  and can be ignored.`;
1892
- }, Zt = G.read("VOLTRO_SESSION_COOKIE") ?? "voltro:session", Qt, $t = (e) => {
1893
- Qt = e;
1894
- }, en = () => Qt ?? nn({}), tn = () => Qt === void 0 ? G.read("STORAGE_PROVIDER") === void 0 ? void 0 : nn({}) : Qt, nn = (e) => {
2007
+ }, sn = q.read("VOLTRO_SESSION_COOKIE") ?? "voltro:session", cn, ln = (e) => {
2008
+ cn = e;
2009
+ }, un = () => cn ?? fn({}), dn = () => cn === void 0 ? q.read("STORAGE_PROVIDER") === void 0 ? void 0 : fn({}) : cn, fn = (e) => {
1895
2010
  if (e.provider && typeof e.provider == "object") return e.provider;
1896
- let t = (e.provider ?? G.read("STORAGE_PROVIDER") ?? "memory").toLowerCase(), n = G.read("S3_BUCKET", e.bucket) ?? G.read("STORAGE_BUCKET") ?? "voltro";
2011
+ let t = (e.provider ?? q.read("STORAGE_PROVIDER") ?? "memory").toLowerCase(), n = q.read("S3_BUCKET", e.bucket) ?? q.read("STORAGE_BUCKET") ?? "voltro";
1897
2012
  switch (t) {
1898
2013
  case "s3":
1899
2014
  case "minio": {
1900
- let r = G.read("S3_REGION", e.region) ?? G.read("AWS_REGION"), i = G.read("S3_ENDPOINT", e.endpoint) ?? G.read("MINIO_ENDPOINT"), a = G.read("S3_ACCESS_KEY_ID", e.accessKeyId) ?? G.read("AWS_ACCESS_KEY_ID"), o = G.read("S3_SECRET_ACCESS_KEY", e.secretAccessKey) ?? G.read("AWS_SECRET_ACCESS_KEY"), s = G.read("STORAGE_CDN_URL", e.cdnBaseUrl);
1901
- return Le({
2015
+ let r = q.read("S3_REGION", e.region) ?? q.read("AWS_REGION"), i = q.read("S3_ENDPOINT", e.endpoint) ?? q.read("MINIO_ENDPOINT"), a = q.read("S3_ACCESS_KEY_ID", e.accessKeyId) ?? q.read("AWS_ACCESS_KEY_ID"), o = q.read("S3_SECRET_ACCESS_KEY", e.secretAccessKey) ?? q.read("AWS_SECRET_ACCESS_KEY"), s = q.read("STORAGE_CDN_URL", e.cdnBaseUrl);
2016
+ return Re({
1902
2017
  bucket: n,
1903
2018
  name: t,
1904
2019
  ...r ? { region: r } : {},
@@ -1907,13 +2022,13 @@ var Gt = () => se({
1907
2022
  ...o ? { secretAccessKey: o } : {},
1908
2023
  ...s ? { cdnBaseUrl: s } : {},
1909
2024
  ...e.publicAcl === void 0 ? {} : { publicAcl: e.publicAcl },
1910
- ...t === "minio" || G.read("S3_FORCE_PATH_STYLE") === "1" ? { forcePathStyle: !0 } : {}
2025
+ ...t === "minio" || q.read("S3_FORCE_PATH_STYLE") === "1" ? { forcePathStyle: !0 } : {}
1911
2026
  });
1912
2027
  }
1913
2028
  case "azure": {
1914
- let t = G.read("AZURE_STORAGE_ACCOUNT", e.accountName), r = G.read("AZURE_STORAGE_KEY", e.accountKey), i = G.read("AZURE_STORAGE_CONNECTION_STRING", e.connectionString), a = G.read("AZURE_STORAGE_ENDPOINT", e.endpoint), o = G.read("STORAGE_CDN_URL", e.cdnBaseUrl);
1915
- return Be({
1916
- container: G.read("AZURE_STORAGE_CONTAINER", e.bucket) ?? n,
2029
+ let t = q.read("AZURE_STORAGE_ACCOUNT", e.accountName), r = q.read("AZURE_STORAGE_KEY", e.accountKey), i = q.read("AZURE_STORAGE_CONNECTION_STRING", e.connectionString), a = q.read("AZURE_STORAGE_ENDPOINT", e.endpoint), o = q.read("STORAGE_CDN_URL", e.cdnBaseUrl);
2030
+ return Ve({
2031
+ container: q.read("AZURE_STORAGE_CONTAINER", e.bucket) ?? n,
1917
2032
  ...t ? { accountName: t } : {},
1918
2033
  ...r ? { accountKey: r } : {},
1919
2034
  ...i ? { connectionString: i } : {},
@@ -1921,15 +2036,15 @@ var Gt = () => se({
1921
2036
  ...o ? { cdnBaseUrl: o } : {}
1922
2037
  });
1923
2038
  }
1924
- case "database": return ze();
1925
- case "filesystem": return Ie({ root: G.read("STORAGE_ROOT", e.root) ?? ".voltro-storage" });
1926
- default: return Fe(e.name ?? "default");
2039
+ case "database": return Be();
2040
+ case "filesystem": return Le({ root: q.read("STORAGE_ROOT", e.root) ?? ".voltro-storage" });
2041
+ default: return Ie(e.name ?? "default");
1927
2042
  }
1928
- }, rn = (e) => {
2043
+ }, pn = (e) => {
1929
2044
  if (e !== void 0) return e;
1930
- let t = G.read("STORAGE_ALLOWED_ORIGINS");
2045
+ let t = q.read("STORAGE_ALLOWED_ORIGINS");
1931
2046
  return t ? t.trim() === "*" ? "*" : t.split(",").map((e) => e.trim()).filter(Boolean) : [];
1932
- }, an = (e, t) => {
2047
+ }, mn = (e, t) => {
1933
2048
  if (!e || t !== "*" && !t.includes(e)) return {};
1934
2049
  let n = {
1935
2050
  "access-control-allow-origin": t === "*" ? "*" : e,
@@ -1939,7 +2054,7 @@ var Gt = () => se({
1939
2054
  vary: "Origin"
1940
2055
  };
1941
2056
  return t !== "*" && (n["access-control-allow-credentials"] = "true"), n;
1942
- }, on = (e) => ({
2057
+ }, hn = (e) => ({
1943
2058
  id: e.id,
1944
2059
  tenantId: e.tenantId,
1945
2060
  ownerId: e.ownerId,
@@ -1962,29 +2077,29 @@ var Gt = () => se({
1962
2077
  caption: e.caption ?? null,
1963
2078
  derivedFrom: e.derivedFrom ?? null,
1964
2079
  kind: e.kind ?? null
1965
- }), sn = () => new t({
2080
+ }), gn = () => new t({
1966
2081
  provider: "storage",
1967
2082
  message: "not permitted to administer sharing for this object",
1968
2083
  transient: !1,
1969
2084
  status: 403
1970
- }), cn = (e, t, n) => {
2085
+ }), _n = (e, t, n) => {
1971
2086
  let r = n.request.subject;
1972
- return (r.scopes ?? []).includes("admin:full") ? b.void : e.head(t, { tenantId: r.tenantId ?? null }).pipe(b.catchAll(() => b.fail(sn())), b.flatMap((e) => {
2087
+ return (r.scopes ?? []).includes("admin:full") ? b.void : e.head(t, { tenantId: r.tenantId ?? null }).pipe(b.catchAll(() => b.fail(gn())), b.flatMap((e) => {
1973
2088
  let t = e?.ownerId;
1974
- return t != null && t === r.id ? b.void : b.fail(sn());
2089
+ return t != null && t === r.id ? b.void : b.fail(gn());
1975
2090
  }));
1976
- }, ln = () => new t({
2091
+ }, vn = () => new t({
1977
2092
  provider: "storage",
1978
2093
  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.",
1979
2094
  transient: !1,
1980
2095
  status: 401
1981
2096
  }), $ = (e, t) => {
1982
2097
  let n = e.request.subject.id ?? null, r = e.request.subject.tenantId ?? null;
1983
- return n === null && !t ? b.fail(ln()) : b.succeed({
2098
+ return n === null && !t ? b.fail(vn()) : b.succeed({
1984
2099
  id: n,
1985
2100
  tenantId: r
1986
2101
  });
1987
- }, un = (e, t) => e !== null && e !== (t ?? null), dn = (e) => ({
2102
+ }, yn = (e, t) => e !== null && e !== (t ?? null), bn = (e) => ({
1988
2103
  id: e.id,
1989
2104
  refId: e.refId,
1990
2105
  principalType: e.principalType,
@@ -1993,31 +2108,37 @@ var Gt = () => se({
1993
2108
  createdAt: e.createdAt.toISOString(),
1994
2109
  expiresAt: e.expiresAt ? e.expiresAt.toISOString() : null,
1995
2110
  createdBy: e.createdBy
1996
- }), fn = "@voltro/plugin-storage", pn = (i = {}) => {
1997
- let y = nn(i);
1998
- $t(y);
1999
- let x = G.read("S3_BUCKET", i.bucket) ?? G.read("STORAGE_BUCKET") ?? "voltro", S = G.read("VOLTRO_PUBLIC_URL", i.publicBaseUrl), C = rn(i.allowedOrigins), w = i.limits?.maxBytes, D = i.anonymousUploads === !0, oe = 5242880, O = 21600, k = i.refStore === void 0 || i.refStore === "memory", A = i.grantStore === void 0 || i.grantStore === "memory", j = { current: k ? Et() : i.refStore }, M = { current: A ? jt() : i.grantStore }, se = {
2000
- insert: (e) => j.current.insert(e),
2001
- getById: (e) => j.current.getById(e),
2002
- delete: (e) => j.current.delete(e),
2003
- listRecent: (e) => j.current.listRecent(e),
2004
- countByKey: (e, t) => j.current.countByKey(e, t),
2005
- usageByTenant: (e) => j.current.usageByTenant(e),
2006
- consumeUsage: (e, t, n) => j.current.consumeUsage(e, t, n),
2007
- releaseUsage: (e, t) => j.current.releaseUsage(e, t),
2008
- listByDerivedFrom: (e) => j.current.listByDerivedFrom(e),
2009
- listRefs: (e) => j.current.listRefs(e)
2010
- }, ce = {
2011
- insert: (e) => M.current.insert(e),
2012
- delete: (e) => M.current.delete(e),
2013
- getById: (e) => M.current.getById(e),
2014
- listByRef: (e) => M.current.listByRef(e),
2015
- deleteByRef: (e) => M.current.deleteByRef(e)
2016
- }, N = {
2017
- provider: y,
2018
- refStore: se,
2019
- grantStore: ce,
2020
- bucket: x,
2111
+ }), xn = "@voltro/plugin-storage", Sn = (i = {}) => {
2112
+ let y = E({
2113
+ base: xn,
2114
+ alias: i.alias,
2115
+ instance: i.name
2116
+ }), x = y === xn ? "/_voltro/storage" : `/_voltro/storage/i/${Buffer.from(y).toString("hex")}`, S = fn(i);
2117
+ ln(S);
2118
+ let C = q.read("S3_BUCKET", i.bucket) ?? q.read("STORAGE_BUCKET") ?? "voltro", D = q.read("VOLTRO_PUBLIC_URL", i.publicBaseUrl), se = pn(i.allowedOrigins), O = i.limits?.maxBytes, k = i.anonymousUploads === !0, A = 5242880, j = 21600, M = i.refStore === void 0 || i.refStore === "memory", N = i.grantStore === void 0 || i.grantStore === "memory", P = { current: M ? Pt() : i.refStore }, F = { current: N ? zt() : i.grantStore }, ce = {
2119
+ insert: (e) => P.current.insert(e),
2120
+ getById: (e) => P.current.getById(e),
2121
+ delete: (e) => P.current.delete(e),
2122
+ statistics: () => P.current.statistics(),
2123
+ listRecent: (e) => P.current.listRecent(e),
2124
+ countByKey: (e, t) => P.current.countByKey(e, t),
2125
+ usageByTenant: (e) => P.current.usageByTenant(e),
2126
+ consumeUsage: (e, t, n) => P.current.consumeUsage(e, t, n),
2127
+ releaseUsage: (e, t) => P.current.releaseUsage(e, t),
2128
+ listByDerivedFrom: (e) => P.current.listByDerivedFrom(e),
2129
+ listRefs: (e) => P.current.listRefs(e)
2130
+ }, I = {
2131
+ insert: (e) => F.current.insert(e),
2132
+ delete: (e) => F.current.delete(e),
2133
+ getById: (e) => F.current.getById(e),
2134
+ listByRef: (e) => F.current.listByRef(e),
2135
+ deleteByRef: (e) => F.current.deleteByRef(e)
2136
+ }, L = {
2137
+ httpPath: x,
2138
+ provider: S,
2139
+ refStore: ce,
2140
+ grantStore: I,
2141
+ bucket: C,
2021
2142
  ...i.tenantPrefix === void 0 ? {} : { tenantPrefix: i.tenantPrefix },
2022
2143
  ...i.attempts === void 0 ? {} : { attempts: i.attempts },
2023
2144
  ...i.urlExpiresInSec === void 0 ? {} : { urlExpiresInSec: i.urlExpiresInSec },
@@ -2027,10 +2148,10 @@ var Gt = () => se({
2027
2148
  ...i.videoProbe === void 0 ? {} : { videoProbe: i.videoProbe },
2028
2149
  ...i.transcode === void 0 ? {} : { transcode: i.transcode },
2029
2150
  ...i.autoTranscode === void 0 ? {} : { autoTranscode: i.autoTranscode },
2030
- ...S ? { publicBaseUrl: S } : {},
2151
+ ...D ? { publicBaseUrl: D } : {},
2031
2152
  ...i.normalizeImages === void 0 ? {} : { normalizeImages: i.normalizeImages },
2032
2153
  ...i.quota === void 0 ? {} : { quota: i.quota }
2033
- }, P = Lt(N), F = It(N), I = (e) => b.runPromise(e.pipe(b.catchAll(() => b.succeed(null)))), L = (e, t) => {
2154
+ }, le = Gt(L), R = Wt(L), z = `${x}/`, B = (e) => b.runPromise(e.pipe(b.catchAll(() => b.succeed(null)))), de = (e, t) => {
2034
2155
  if (!e) return "invalid";
2035
2156
  let n = /^bytes=(\d*)-(\d*)$/.exec(e.trim());
2036
2157
  if (!n) return "invalid";
@@ -2051,30 +2172,30 @@ var Gt = () => se({
2051
2172
  start: a,
2052
2173
  endInclusive: o
2053
2174
  };
2054
- }, le = /^(?:image\/(?!svg)|video\/|audio\/|application\/pdf(?:;|$)|text\/plain(?:;|$))/i, R = (e) => ({
2175
+ }, V = /^(?:image\/(?!svg)|video\/|audio\/|application\/pdf(?:;|$)|text\/plain(?:;|$))/i, fe = (e) => ({
2055
2176
  "x-content-type-options": "nosniff",
2056
- "content-disposition": le.test(e) ? "inline" : "attachment"
2057
- }), z = async (e, t, n, r) => {
2177
+ "content-disposition": V.test(e) ? "inline" : "attachment"
2178
+ }), pe = async (e, t, n, r) => {
2058
2179
  if (n) {
2059
- let r = await I(F.get(e.id));
2180
+ let r = await B(R.get(e.id));
2060
2181
  if (!r) return {
2061
2182
  status: 404,
2062
2183
  body: "not found",
2063
2184
  contentType: "text/plain"
2064
2185
  };
2065
- let i = await qe(e.id, r.bytes, e.contentType, n).catch(() => null), a = i ? i.bytes : r.bytes, o = i ? i.contentType : e.contentType;
2186
+ let i = await Xe(e.id, r.bytes, e.contentType, n).catch(() => null), a = i ? i.bytes : r.bytes, o = i ? i.contentType : e.contentType;
2066
2187
  return {
2067
2188
  status: 200,
2068
2189
  body: a,
2069
2190
  contentType: o,
2070
2191
  headers: {
2071
- ...R(o),
2192
+ ...fe(o),
2072
2193
  "cache-control": t,
2073
2194
  "accept-ranges": "none"
2074
2195
  }
2075
2196
  };
2076
2197
  }
2077
- let i = r === void 0 ? "invalid" : L(r, e.size);
2198
+ let i = r === void 0 ? "invalid" : de(r, e.size);
2078
2199
  if (i === "unsatisfiable") return {
2079
2200
  status: 416,
2080
2201
  body: "range not satisfiable",
@@ -2085,13 +2206,13 @@ var Gt = () => se({
2085
2206
  }
2086
2207
  };
2087
2208
  if (i !== "invalid") {
2088
- let n = await I(F.getRange(e.id, i));
2209
+ let n = await B(R.getRange(e.id, i));
2089
2210
  return n ? {
2090
2211
  status: 206,
2091
2212
  body: n.bytes,
2092
2213
  contentType: e.contentType,
2093
2214
  headers: {
2094
- ...R(e.contentType),
2215
+ ...fe(e.contentType),
2095
2216
  "cache-control": t,
2096
2217
  "accept-ranges": "bytes",
2097
2218
  "content-range": `bytes ${i.start}-${i.endInclusive}/${n.totalSize}`
@@ -2102,75 +2223,64 @@ var Gt = () => se({
2102
2223
  contentType: "text/plain"
2103
2224
  };
2104
2225
  }
2105
- let a = await I(F.get(e.id));
2106
- if (!a) return {
2107
- status: 404,
2108
- body: "not found",
2109
- contentType: "text/plain"
2110
- };
2111
- let o = 1048576;
2112
- return {
2226
+ let a = await B(R.getStream(e.id));
2227
+ return a ? {
2113
2228
  status: 200,
2114
2229
  contentType: e.contentType,
2115
2230
  headers: {
2116
- ...R(e.contentType),
2231
+ ...fe(e.contentType),
2117
2232
  "cache-control": t,
2118
2233
  "accept-ranges": "bytes"
2119
2234
  },
2120
2235
  byteStream: {
2121
- contentLength: a.bytes.length,
2122
- stream: () => {
2123
- let e = 0;
2124
- return new ReadableStream({ pull(t) {
2125
- if (e >= a.bytes.length) {
2126
- t.close();
2127
- return;
2128
- }
2129
- t.enqueue(a.bytes.subarray(e, e + o)), e += o;
2130
- } });
2131
- }
2236
+ contentLength: e.size,
2237
+ stream: () => T.toReadableStream(a.stream)
2132
2238
  }
2239
+ } : {
2240
+ status: 404,
2241
+ body: "not found",
2242
+ contentType: "text/plain"
2133
2243
  };
2134
- }, de = async (e) => {
2135
- let t = e.path.startsWith("/_voltro/storage/") ? e.path.slice(17).split("/")[0] ?? "" : "";
2244
+ }, me = async (e) => {
2245
+ let t = e.path.startsWith(z) ? e.path.slice(z.length).split("/")[0] ?? "" : "";
2136
2246
  if (!t) return {
2137
2247
  status: 404,
2138
2248
  body: "not found",
2139
2249
  contentType: "text/plain"
2140
2250
  };
2141
- let n = await I(F.head(t));
2251
+ let n = await B(R.head(t));
2142
2252
  if (!n) return {
2143
2253
  status: 404,
2144
2254
  body: "not found",
2145
2255
  contentType: "text/plain"
2146
2256
  };
2147
- let r = He(e.query), i = e.headers.range;
2257
+ let r = Ue(e.query), i = e.headers.range;
2148
2258
  if (n.visibility === "public") {
2149
- let e = y.publicUrl?.(n.key) ?? null;
2259
+ let e = S.publicUrl?.(n.key) ?? null;
2150
2260
  return e && !r ? {
2151
2261
  status: 302,
2152
2262
  headers: {
2153
2263
  location: e,
2154
2264
  "cache-control": "public, max-age=300"
2155
2265
  }
2156
- } : z(n, "public, max-age=31536000, immutable", r, i);
2266
+ } : pe(n, "public, max-age=31536000, immutable", r, i);
2157
2267
  }
2158
2268
  let a = !1, o = e.query ? new URLSearchParams(e.query).get("t") : null;
2159
2269
  if (o) {
2160
- let e = ct(o);
2270
+ let e = dt(o);
2161
2271
  a = !!e && e.refId === t;
2162
2272
  }
2163
2273
  if (!a) {
2164
- let t = E(e.headers.cookie, Zt), r = t ? ae(t, ie()) : null;
2165
- r && (a = await I(F.checkAccess(n, r)) === !0);
2274
+ let t = ie(e.headers.cookie, sn), r = t ? oe(t, ae()) : null;
2275
+ r && (a = await B(R.checkAccess(n, r)) === !0);
2166
2276
  }
2167
2277
  if (!a) return {
2168
2278
  status: 403,
2169
2279
  body: "forbidden",
2170
2280
  contentType: "text/plain"
2171
2281
  };
2172
- if (y.presigns && !r) {
2173
- let e = await I(y.getUrl(n.key, 300));
2282
+ if (S.presigns && !r) {
2283
+ let e = await B(S.getUrl(n.key, 300));
2174
2284
  if (e && /^https?:/.test(e)) return {
2175
2285
  status: 302,
2176
2286
  headers: {
@@ -2179,12 +2289,12 @@ var Gt = () => se({
2179
2289
  }
2180
2290
  };
2181
2291
  }
2182
- return z(n, "private, no-store", r, i);
2183
- }, fe = {
2292
+ return pe(n, "private, no-store", r, i);
2293
+ }, he = {
2184
2294
  method: "GET",
2185
- path: "/_voltro/storage",
2295
+ path: x,
2186
2296
  handle: async (e) => {
2187
- let t = await de(e), n = an(e.headers.origin, C);
2297
+ let t = await me(e), n = mn(e.headers.origin, se);
2188
2298
  return Object.keys(n).length === 0 ? t : {
2189
2299
  ...t,
2190
2300
  headers: {
@@ -2193,12 +2303,12 @@ var Gt = () => se({
2193
2303
  }
2194
2304
  };
2195
2305
  }
2196
- }, pe = {
2306
+ }, ge = {
2197
2307
  method: "*",
2198
- path: "/_voltro/storage/upload",
2308
+ path: `${x}/upload`,
2199
2309
  originGuard: "exempt",
2200
2310
  handle: async (e) => {
2201
- let t = an(e.headers.origin, C);
2311
+ let t = mn(e.headers.origin, se);
2202
2312
  if (e.method === "OPTIONS") return {
2203
2313
  status: 204,
2204
2314
  headers: t
@@ -2209,8 +2319,8 @@ var Gt = () => se({
2209
2319
  contentType: "text/plain",
2210
2320
  headers: t
2211
2321
  };
2212
- let n = e.query ? new URLSearchParams(e.query).get("ticket") : null, r = n ? ut(n) : null;
2213
- if (!r) return {
2322
+ let n = e.query ? new URLSearchParams(e.query).get("ticket") : null, r = n ? pt(n) : null;
2323
+ if (!r || r.instance !== y) return {
2214
2324
  status: 401,
2215
2325
  body: "invalid or expired upload ticket",
2216
2326
  contentType: "text/plain",
@@ -2228,7 +2338,7 @@ var Gt = () => se({
2228
2338
  contentType: "text/plain",
2229
2339
  headers: t
2230
2340
  };
2231
- let i = await b.runPromise(F.put({
2341
+ let i = await b.runPromise(R.put({
2232
2342
  bytes: e.rawBody,
2233
2343
  contentType: r.ct,
2234
2344
  tenantId: r.tenant,
@@ -2239,7 +2349,7 @@ var Gt = () => se({
2239
2349
  ...r.tags === void 0 ? {} : { tags: r.tags },
2240
2350
  ...r.alt === void 0 ? {} : { alt: r.alt },
2241
2351
  ...r.caption === void 0 ? {} : { caption: r.caption }
2242
- }).pipe(b.flatMap((e) => F.getUrl(e.id).pipe(b.map((t) => ({
2352
+ }).pipe(b.flatMap((e) => R.getUrl(e.id).pipe(b.map((t) => ({
2243
2353
  kind: "ok",
2244
2354
  ref: e,
2245
2355
  url: t
@@ -2285,25 +2395,25 @@ var Gt = () => se({
2285
2395
  headers: t
2286
2396
  };
2287
2397
  }
2288
- }, me = {
2398
+ }, _e = {
2289
2399
  method: "*",
2290
- path: "/_voltro/storage/upload/resumable",
2400
+ path: `${x}/upload/resumable`,
2291
2401
  originGuard: "exempt",
2292
2402
  handle: async (e) => {
2293
- let t = an(e.headers.origin, C);
2403
+ let t = mn(e.headers.origin, se);
2294
2404
  if (e.method === "OPTIONS") return {
2295
2405
  status: 204,
2296
2406
  headers: t
2297
2407
  };
2298
- let n = new URLSearchParams(e.query || ""), r = mt(n.get("token") ?? "");
2299
- if (!r) return {
2408
+ let n = new URLSearchParams(e.query || ""), r = _t(n.get("token") ?? "");
2409
+ if (!r || r.instance !== y) return {
2300
2410
  status: 401,
2301
2411
  body: "invalid or expired resumable token",
2302
2412
  contentType: "text/plain",
2303
2413
  headers: t
2304
2414
  };
2305
2415
  if (e.method === "GET" || e.method === "HEAD") {
2306
- let e = await b.runPromise(F.resumableStatus({
2416
+ let e = await b.runPromise(R.resumableStatus({
2307
2417
  uploadId: r.id,
2308
2418
  tenantId: r.tenant
2309
2419
  }).pipe(b.match({
@@ -2344,12 +2454,12 @@ var Gt = () => se({
2344
2454
  contentType: "text/plain",
2345
2455
  headers: t
2346
2456
  };
2347
- let a = n.get("final") === "1", o = await b.runPromise(F.putResumableChunk({
2457
+ let a = n.get("final") === "1", o = await b.runPromise(R.putResumableChunk({
2348
2458
  uploadId: r.id,
2349
2459
  tenantId: r.tenant,
2350
2460
  index: i,
2351
2461
  bytes: e.rawBody
2352
- }).pipe(b.flatMap(() => a ? F.finalizeResumable({
2462
+ }).pipe(b.flatMap(() => a ? R.finalizeResumable({
2353
2463
  uploadId: r.id,
2354
2464
  count: i + 1,
2355
2465
  contentType: r.ct,
@@ -2360,7 +2470,7 @@ var Gt = () => se({
2360
2470
  ...r.tags === void 0 ? {} : { tags: r.tags },
2361
2471
  ...r.alt === void 0 ? {} : { alt: r.alt },
2362
2472
  ...r.caption === void 0 ? {} : { caption: r.caption }
2363
- }).pipe(b.flatMap((e) => F.getUrl(e.id).pipe(b.map((t) => ({
2473
+ }).pipe(b.flatMap((e) => R.getUrl(e.id).pipe(b.map((t) => ({
2364
2474
  kind: "done",
2365
2475
  ref: e,
2366
2476
  url: t
@@ -2412,57 +2522,117 @@ var Gt = () => se({
2412
2522
  headers: t
2413
2523
  };
2414
2524
  }
2415
- }, B = (e) => ({
2525
+ }, H = (e) => ({
2416
2526
  kind: "json",
2417
2527
  data: e
2418
- }), V = (e, t) => ({
2528
+ }), U = (e, t) => ({
2419
2529
  kind: "json",
2420
2530
  status: e,
2421
2531
  data: { error: t }
2422
- }), he = (e, t) => {
2532
+ }), ve = (e, t) => {
2423
2533
  try {
2424
2534
  return new URL(e, "http://localhost").searchParams.get(t);
2425
2535
  } catch {
2426
2536
  return null;
2427
2537
  }
2428
- }, ge = [
2538
+ }, ye = [
2539
+ {
2540
+ method: "POST",
2541
+ path: "/upload-ticket",
2542
+ description: "Authorize a binary upload with explicit tenant and owner attribution",
2543
+ handler: (e) => b.gen(function* () {
2544
+ let n = w.String.pipe(w.filter((e) => e.trim().length > 0)), r = yield* w.decodeUnknown(w.parseJson(w.Struct({
2545
+ tenantId: w.NullOr(n),
2546
+ ownerId: w.NullOr(n),
2547
+ key: n.pipe(w.maxLength(1024)),
2548
+ contentType: n.pipe(w.maxLength(255), w.filter((e) => !/[\r\n]/.test(e))),
2549
+ size: w.Number.pipe(w.int(), w.positive(), w.filter(Number.isSafeInteger)),
2550
+ visibility: w.optional(w.Literal("public", "private"))
2551
+ })))(e.body).pipe(b.mapError(() => new t({
2552
+ provider: "inspect",
2553
+ message: "Provide explicit tenantId and ownerId (or null), key, contentType and a positive file size",
2554
+ transient: !1,
2555
+ status: 400
2556
+ })));
2557
+ if (O !== void 0 && r.size > O) return U(413, "File exceeds the configured upload limit");
2558
+ let i = ft({
2559
+ instance: y,
2560
+ sub: r.ownerId,
2561
+ tenant: r.tenantId,
2562
+ ct: r.contentType,
2563
+ key: r.key,
2564
+ vis: r.visibility ?? "private",
2565
+ max: r.size
2566
+ }, 300);
2567
+ return H({
2568
+ uploadPath: `${x}/upload?ticket=${encodeURIComponent(i)}`,
2569
+ expiresInSec: 300,
2570
+ maxBytes: r.size
2571
+ });
2572
+ }).pipe(b.catchAll((e) => b.succeed(U(e.status ?? 500, e.message))))
2573
+ },
2574
+ {
2575
+ method: "GET",
2576
+ path: "/download",
2577
+ description: "Stream a stored file as an attachment for authorized inspect readers",
2578
+ handler: (e) => b.gen(function* () {
2579
+ let t = ve(e.url, "refId");
2580
+ if (!t?.trim()) return U(400, "A non-empty refId is required");
2581
+ let { ref: n, stream: r } = yield* R.getStream(t), i = n.key.split("/").pop() || n.id, a = encodeURIComponent(i).replace(/[!'()*]/g, (e) => `%${e.charCodeAt(0).toString(16).toUpperCase()}`);
2582
+ return {
2583
+ kind: "bytes",
2584
+ contentType: n.contentType,
2585
+ byteStream: {
2586
+ stream: () => T.toReadableStream(r),
2587
+ contentLength: n.size,
2588
+ contentDisposition: `attachment; filename="download"; filename*=UTF-8''${a}`
2589
+ },
2590
+ headers: { "cache-control": "no-store" }
2591
+ };
2592
+ }).pipe(b.catchAll((e) => b.succeed(U(e.status ?? 500, e.message))))
2593
+ },
2429
2594
  {
2430
2595
  method: "GET",
2431
2596
  path: "/refs",
2432
- description: "Recent storage refs (newest first)",
2433
- handler: () => se.listRecent(100).pipe(b.map((e) => B({ refs: e.map(on) })), b.catchAll((e) => b.succeed(V(500, e.message))))
2597
+ description: "Searchable storage refs, newest first, paginated",
2598
+ handler: (e) => {
2599
+ let t = Number(ve(e.url, "offset") ?? 0), n = Number.isSafeInteger(t) && t >= 0 ? t : 0, r = (ve(e.url, "search") ?? "").trim().slice(0, 200);
2600
+ return ce.listRefs({
2601
+ tenantId: void 0,
2602
+ ownerId: void 0,
2603
+ folder: void 0,
2604
+ tags: [],
2605
+ includeDerived: !0,
2606
+ search: r,
2607
+ limit: 51,
2608
+ offset: n
2609
+ }).pipe(b.map((e) => H({
2610
+ refs: e.slice(0, 50).map(hn),
2611
+ page: {
2612
+ search: r,
2613
+ offset: n,
2614
+ nextOffset: e.length > 50 ? n + 50 : null
2615
+ }
2616
+ })), b.catchAll((e) => b.succeed(U(500, e.message))));
2617
+ }
2434
2618
  },
2435
2619
  {
2436
2620
  method: "GET",
2437
2621
  path: "/stats",
2438
2622
  description: "Object count + total bytes per tenant + visibility split",
2439
- handler: () => se.listRecent(1e4).pipe(b.map((e) => {
2440
- let t = {}, n = 0, r = 0;
2441
- for (let i of e) {
2442
- let e = i.tenantId ?? "(global)", a = t[e] ?? {
2443
- count: 0,
2444
- bytes: 0
2445
- };
2446
- a.count++, a.bytes += i.size, t[e] = a, i.visibility === "public" ? n++ : r++;
2447
- }
2448
- return B({
2449
- provider: y.name,
2450
- bucket: x,
2451
- byTenant: t,
2452
- visibility: {
2453
- public: n,
2454
- private: r
2455
- }
2456
- });
2457
- }), b.catchAll((e) => b.succeed(V(500, e.message))))
2623
+ handler: () => ce.statistics().pipe(b.map((e) => H({
2624
+ provider: S.name,
2625
+ bucket: C,
2626
+ ...e
2627
+ })), b.catchAll((e) => b.succeed(U(500, e.message))))
2458
2628
  },
2459
2629
  {
2460
2630
  method: "GET",
2461
2631
  path: "/grants",
2462
2632
  description: "Grants for a ref (?refId=…)",
2463
2633
  handler: (e) => {
2464
- let t = he(e.url, "refId");
2465
- return t ? ce.listByRef(t).pipe(b.map((e) => B({ grants: e.map(dn) })), b.catchAll((e) => b.succeed(V(500, e.message)))) : b.succeed(V(400, "refId query param required"));
2634
+ let t = ve(e.url, "refId");
2635
+ return t ? I.listByRef(t).pipe(b.map((e) => H({ grants: e.map(bn) })), b.catchAll((e) => b.succeed(U(500, e.message)))) : b.succeed(U(400, "refId query param required"));
2466
2636
  }
2467
2637
  },
2468
2638
  {
@@ -2470,49 +2640,63 @@ var Gt = () => se({
2470
2640
  path: "/share",
2471
2641
  description: "Grant a principal access to a ref",
2472
2642
  handler: (e) => b.gen(function* () {
2473
- let n = yield* b.try({
2474
- try: () => JSON.parse(e.body || "{}"),
2475
- catch: () => new t({
2476
- provider: "inspect",
2477
- message: "invalid JSON body",
2478
- transient: !1,
2479
- status: 400
2480
- })
2481
- });
2482
- if (!n.refId || !n.principalType || !n.principalId) return V(400, "refId, principalType, principalId required");
2483
- let r = n.expiresInDays ? new Date(Date.now() + n.expiresInDays * 864e5) : null, i = yield* F.grant({
2643
+ let n = yield* w.decodeUnknown(w.parseJson(w.Struct({
2644
+ refId: w.String.pipe(w.filter((e) => e.trim().length > 0)),
2645
+ principalType: w.Literal("user", "group", "apiKey"),
2646
+ principalId: w.String.pipe(w.filter((e) => e.trim().length > 0)),
2647
+ permission: w.optional(w.Literal("read", "write")),
2648
+ expiresInDays: w.optional(w.Number.pipe(w.finite(), w.positive()))
2649
+ })))(e.body).pipe(b.mapError(() => new t({
2650
+ provider: "inspect",
2651
+ message: "Invalid share input: provide refId, principalType, principalId, read/write permission and a positive finite expiry if set",
2652
+ transient: !1,
2653
+ status: 400
2654
+ }))), r = n.expiresInDays === void 0 ? null : new Date(Date.now() + n.expiresInDays * 864e5);
2655
+ if (r !== null && !Number.isFinite(r.getTime())) return U(400, "Expiry exceeds the supported date range");
2656
+ let i = yield* R.grant({
2484
2657
  refId: n.refId,
2485
2658
  principalType: n.principalType,
2486
2659
  principalId: n.principalId,
2487
2660
  ...n.permission ? { permission: n.permission } : {},
2488
2661
  expiresAt: r
2489
2662
  });
2490
- return B({ grant: dn(i) });
2491
- }).pipe(b.catchAll((e) => b.succeed(V(e.status ?? 500, e.message ?? "share failed"))))
2663
+ return H({ grant: bn(i) });
2664
+ }).pipe(b.catchAll((e) => b.succeed(U(e.status ?? 500, e.message ?? "share failed"))))
2665
+ },
2666
+ {
2667
+ method: "POST",
2668
+ path: "/delete",
2669
+ description: "Delete an object reference and its grants; release unreferenced bytes",
2670
+ handler: (e) => b.gen(function* () {
2671
+ let n = yield* w.decodeUnknown(w.parseJson(w.Struct({ refId: w.String.pipe(w.filter((e) => e.trim().length > 0)) })))(e.body).pipe(b.mapError(() => new t({
2672
+ provider: "inspect",
2673
+ message: "A non-empty refId is required",
2674
+ transient: !1,
2675
+ status: 400
2676
+ })));
2677
+ return yield* R.delete(n.refId), H({ ok: !0 });
2678
+ }).pipe(b.catchAll((e) => b.succeed(U(e.status ?? 500, e.message))))
2492
2679
  },
2493
2680
  {
2494
2681
  method: "POST",
2495
2682
  path: "/revoke",
2496
2683
  description: "Revoke a grant by id",
2497
2684
  handler: (e) => b.gen(function* () {
2498
- let n = yield* b.try({
2499
- try: () => JSON.parse(e.body || "{}"),
2500
- catch: () => new t({
2501
- provider: "inspect",
2502
- message: "invalid JSON body",
2503
- transient: !1,
2504
- status: 400
2505
- })
2506
- });
2507
- return n.grantId ? (yield* F.revoke(n.grantId), B({ ok: !0 })) : V(400, "grantId required");
2508
- }).pipe(b.catchAll((e) => b.succeed(V(e.status ?? 500, e.message ?? "revoke failed"))))
2685
+ let n = yield* w.decodeUnknown(w.parseJson(w.Struct({ grantId: w.String.pipe(w.filter((e) => e.trim().length > 0)) })))(e.body).pipe(b.mapError(() => new t({
2686
+ provider: "inspect",
2687
+ message: "A non-empty grantId is required",
2688
+ transient: !1,
2689
+ status: 400
2690
+ })));
2691
+ return yield* R.revoke(n.grantId), H({ ok: !0 });
2692
+ }).pipe(b.catchAll((e) => b.succeed(U(e.status ?? 500, e.message ?? "revoke failed"))))
2509
2693
  }
2510
- ], _e = [
2694
+ ], be = [
2511
2695
  {
2512
2696
  ...h,
2513
2697
  execute: (e, t) => {
2514
2698
  let n = e;
2515
- return F.mintUrl(n.id, t.request.subject, {
2699
+ return R.mintUrl(n.id, t.request.subject, {
2516
2700
  ...n.password === void 0 ? {} : { password: n.password },
2517
2701
  ...n.expiresInSec === void 0 ? {} : { expiresInSec: n.expiresInSec }
2518
2702
  }).pipe(b.map((e) => ({ url: e })));
@@ -2522,7 +2706,7 @@ var Gt = () => se({
2522
2706
  ...ee,
2523
2707
  execute: (e, t) => {
2524
2708
  let n = e;
2525
- return F.mintUploadUrl({
2709
+ return R.mintUploadUrl({
2526
2710
  key: n.key,
2527
2711
  contentType: n.contentType,
2528
2712
  tenantId: t.request.subject.tenantId,
@@ -2534,8 +2718,9 @@ var Gt = () => se({
2534
2718
  ...m,
2535
2719
  execute: (e, t) => {
2536
2720
  let n = e;
2537
- return $(t, D).pipe(b.map((e) => {
2538
- let t = n.expiresInSec ?? 900, r = lt({
2721
+ return $(t, k).pipe(b.map((e) => {
2722
+ let t = n.expiresInSec ?? 900, r = ft({
2723
+ instance: y,
2539
2724
  sub: e.id,
2540
2725
  tenant: e.tenantId,
2541
2726
  ct: n.contentType,
@@ -2545,10 +2730,10 @@ var Gt = () => se({
2545
2730
  ...n.tags === void 0 ? {} : { tags: n.tags },
2546
2731
  ...n.alt === void 0 ? {} : { alt: n.alt },
2547
2732
  ...n.caption === void 0 ? {} : { caption: n.caption },
2548
- ...w === void 0 ? {} : { max: w }
2733
+ ...O === void 0 ? {} : { max: O }
2549
2734
  }, t);
2550
2735
  return {
2551
- uploadUrl: `${S ? S.replace(/\/+$/, "") : ""}/_voltro/storage/upload?ticket=${encodeURIComponent(r)}`,
2736
+ uploadUrl: `${D ? D.replace(/\/+$/, "") : ""}${x}/upload?ticket=${encodeURIComponent(r)}`,
2552
2737
  expiresInSec: t
2553
2738
  };
2554
2739
  }));
@@ -2558,12 +2743,13 @@ var Gt = () => se({
2558
2743
  ...p,
2559
2744
  execute: (e, t) => {
2560
2745
  let n = e;
2561
- return $(t, D).pipe(b.flatMap((e) => F.mintPresignedUpload({
2746
+ return $(t, k).pipe(b.flatMap((e) => R.mintPresignedUpload({
2562
2747
  contentType: n.contentType,
2563
2748
  tenantId: e.tenantId,
2564
2749
  ...n.expiresInSec === void 0 ? {} : { expiresInSec: n.expiresInSec }
2565
2750
  }).pipe(b.map((t) => {
2566
- let r = dt({
2751
+ let r = mt({
2752
+ instance: y,
2567
2753
  key: t.key,
2568
2754
  sub: e.id,
2569
2755
  tenant: e.tenantId,
@@ -2573,7 +2759,7 @@ var Gt = () => se({
2573
2759
  ...n.tags === void 0 ? {} : { tags: n.tags },
2574
2760
  ...n.alt === void 0 ? {} : { alt: n.alt },
2575
2761
  ...n.caption === void 0 ? {} : { caption: n.caption },
2576
- ...w === void 0 ? {} : { max: w }
2762
+ ...O === void 0 ? {} : { max: O }
2577
2763
  }, t.expiresInSec);
2578
2764
  return {
2579
2765
  uploadUrl: t.uploadUrl,
@@ -2586,13 +2772,18 @@ var Gt = () => se({
2586
2772
  {
2587
2773
  ...l,
2588
2774
  execute: (e, n) => {
2589
- let r = ft(e.finalizeToken);
2590
- return r ? un(r.sub, n.request.subject.id) ? b.fail(new t({
2775
+ let r = ht(e.finalizeToken);
2776
+ return !r || r.instance !== y ? b.fail(new t({
2777
+ provider: "storage",
2778
+ message: "invalid or expired finalize token",
2779
+ transient: !1,
2780
+ status: 401
2781
+ })) : yn(r.sub, n.request.subject.id) ? b.fail(new t({
2591
2782
  provider: "storage",
2592
2783
  message: "finalize token belongs to another subject",
2593
2784
  transient: !1,
2594
2785
  status: 403
2595
- })) : F.finalizeUpload({
2786
+ })) : R.finalizeUpload({
2596
2787
  key: r.key,
2597
2788
  contentType: r.ct,
2598
2789
  tenantId: r.tenant,
@@ -2602,30 +2793,26 @@ var Gt = () => se({
2602
2793
  ...r.tags === void 0 ? {} : { tags: r.tags },
2603
2794
  ...r.alt === void 0 ? {} : { alt: r.alt },
2604
2795
  ...r.caption === void 0 ? {} : { caption: r.caption }
2605
- }).pipe(b.flatMap((e) => F.getUrl(e.id).pipe(b.map((t) => ({
2796
+ }).pipe(b.flatMap((e) => R.getUrl(e.id).pipe(b.map((t) => ({
2606
2797
  id: e.id,
2607
2798
  url: t,
2608
2799
  contentType: e.contentType,
2609
2800
  size: e.size,
2610
2801
  ...e.width == null ? {} : { width: e.width },
2611
2802
  ...e.height == null ? {} : { height: e.height }
2612
- }))))) : b.fail(new t({
2613
- provider: "storage",
2614
- message: "invalid or expired finalize token",
2615
- transient: !1,
2616
- status: 401
2617
- }));
2803
+ })))));
2618
2804
  }
2619
2805
  },
2620
2806
  {
2621
2807
  ...s,
2622
2808
  execute: (e, t) => {
2623
2809
  let n = e;
2624
- return $(t, D).pipe(b.map((e) => {
2625
- let t = n.expiresInSec ?? O, r = ue(), i = n.chunkSize && n.chunkSize > 0 ? n.chunkSize : oe;
2810
+ return $(t, k).pipe(b.map((e) => {
2811
+ let t = n.expiresInSec ?? j, r = ue(), i = n.chunkSize && n.chunkSize > 0 ? n.chunkSize : A;
2626
2812
  return {
2627
2813
  uploadId: r,
2628
- resumableToken: pt({
2814
+ resumableToken: gt({
2815
+ instance: y,
2629
2816
  id: r,
2630
2817
  sub: e.id,
2631
2818
  tenant: e.tenantId,
@@ -2636,9 +2823,9 @@ var Gt = () => se({
2636
2823
  ...n.tags === void 0 ? {} : { tags: n.tags },
2637
2824
  ...n.alt === void 0 ? {} : { alt: n.alt },
2638
2825
  ...n.caption === void 0 ? {} : { caption: n.caption },
2639
- ...w === void 0 ? {} : { max: w }
2826
+ ...O === void 0 ? {} : { max: O }
2640
2827
  }, t),
2641
- uploadUrl: `${S ? S.replace(/\/+$/, "") : ""}/_voltro/storage/upload/resumable`,
2828
+ uploadUrl: `${D ? D.replace(/\/+$/, "") : ""}${x}/upload/resumable`,
2642
2829
  chunkSize: i,
2643
2830
  expiresInSec: t
2644
2831
  };
@@ -2648,14 +2835,15 @@ var Gt = () => se({
2648
2835
  {
2649
2836
  ...o,
2650
2837
  execute: (e, t) => {
2651
- let n = e, r = n.expiresInSec ?? O;
2652
- return $(t, D).pipe(b.flatMap((e) => F.beginMultipartUpload({
2838
+ let n = e, r = n.expiresInSec ?? j;
2839
+ return $(t, k).pipe(b.flatMap((e) => R.beginMultipartUpload({
2653
2840
  contentType: n.contentType,
2654
2841
  tenantId: e.tenantId,
2655
2842
  visibility: n.visibility ?? "private",
2656
2843
  expiresInSec: r
2657
2844
  }).pipe(b.map((t) => ({
2658
- multipartToken: ht({
2845
+ multipartToken: vt({
2846
+ instance: y,
2659
2847
  key: t.key,
2660
2848
  uploadId: t.uploadId,
2661
2849
  sub: e.id,
@@ -2668,7 +2856,7 @@ var Gt = () => se({
2668
2856
  ...n.alt === void 0 ? {} : { alt: n.alt },
2669
2857
  ...n.caption === void 0 ? {} : { caption: n.caption }
2670
2858
  }, r),
2671
- partSize: n.partSize && n.partSize >= oe ? n.partSize : oe,
2859
+ partSize: n.partSize && n.partSize >= A ? n.partSize : A,
2672
2860
  expiresInSec: r
2673
2861
  })))));
2674
2862
  }
@@ -2676,34 +2864,39 @@ var Gt = () => se({
2676
2864
  {
2677
2865
  ...te,
2678
2866
  execute: (e) => {
2679
- let n = e, r = gt(n.multipartToken);
2680
- return r ? !Number.isInteger(n.partNumber) || n.partNumber < 1 ? b.fail(new t({
2867
+ let n = e, r = yt(n.multipartToken);
2868
+ return !r || r.instance !== y ? b.fail(new t({
2869
+ provider: "storage",
2870
+ message: "invalid or expired multipart token",
2871
+ transient: !1,
2872
+ status: 401
2873
+ })) : !Number.isInteger(n.partNumber) || n.partNumber < 1 ? b.fail(new t({
2681
2874
  provider: "storage",
2682
2875
  message: "partNumber must be a positive integer",
2683
2876
  transient: !1,
2684
2877
  status: 400
2685
- })) : F.signMultipartPart({
2878
+ })) : R.signMultipartPart({
2686
2879
  key: r.key,
2687
2880
  uploadId: r.uploadId,
2688
2881
  partNumber: n.partNumber
2689
- }).pipe(b.map((e) => ({ url: e }))) : b.fail(new t({
2690
- provider: "storage",
2691
- message: "invalid or expired multipart token",
2692
- transient: !1,
2693
- status: 401
2694
- }));
2882
+ }).pipe(b.map((e) => ({ url: e })));
2695
2883
  }
2696
2884
  },
2697
2885
  {
2698
2886
  ...c,
2699
2887
  execute: (e, n) => {
2700
- let r = e, i = gt(r.multipartToken);
2701
- return i ? un(i.sub, n.request.subject.id) ? b.fail(new t({
2888
+ let r = e, i = yt(r.multipartToken);
2889
+ return !i || i.instance !== y ? b.fail(new t({
2890
+ provider: "storage",
2891
+ message: "invalid or expired multipart token",
2892
+ transient: !1,
2893
+ status: 401
2894
+ })) : yn(i.sub, n.request.subject.id) ? b.fail(new t({
2702
2895
  provider: "storage",
2703
2896
  message: "multipart token belongs to another subject",
2704
2897
  transient: !1,
2705
2898
  status: 403
2706
- })) : F.completeMultipart({
2899
+ })) : R.completeMultipart({
2707
2900
  key: i.key,
2708
2901
  uploadId: i.uploadId,
2709
2902
  parts: r.parts,
@@ -2715,38 +2908,33 @@ var Gt = () => se({
2715
2908
  ...i.tags === void 0 ? {} : { tags: i.tags },
2716
2909
  ...i.alt === void 0 ? {} : { alt: i.alt },
2717
2910
  ...i.caption === void 0 ? {} : { caption: i.caption }
2718
- }).pipe(b.flatMap((e) => F.getUrl(e.id).pipe(b.map((t) => ({
2911
+ }).pipe(b.flatMap((e) => R.getUrl(e.id).pipe(b.map((t) => ({
2719
2912
  id: e.id,
2720
2913
  url: t,
2721
2914
  size: e.size
2722
- }))))) : b.fail(new t({
2723
- provider: "storage",
2724
- message: "invalid or expired multipart token",
2725
- transient: !1,
2726
- status: 401
2727
- }));
2915
+ })))));
2728
2916
  }
2729
2917
  },
2730
2918
  {
2731
2919
  ...a,
2732
2920
  execute: (e) => {
2733
- let n = gt(e.multipartToken);
2734
- return n ? F.abortMultipart({
2735
- key: n.key,
2736
- uploadId: n.uploadId
2737
- }).pipe(b.as({ ok: !0 })) : b.fail(new t({
2921
+ let n = yt(e.multipartToken);
2922
+ return !n || n.instance !== y ? b.fail(new t({
2738
2923
  provider: "storage",
2739
2924
  message: "invalid or expired multipart token",
2740
2925
  transient: !1,
2741
2926
  status: 401
2742
- }));
2927
+ })) : R.abortMultipart({
2928
+ key: n.key,
2929
+ uploadId: n.uploadId
2930
+ }).pipe(b.as({ ok: !0 }));
2743
2931
  }
2744
2932
  },
2745
2933
  {
2746
2934
  ...v,
2747
2935
  execute: (e, t) => {
2748
2936
  let n = e, r = new Uint8Array(Buffer.from(n.bytesBase64, "base64"));
2749
- return $(t, D).pipe(b.flatMap((e) => F.put({
2937
+ return $(t, k).pipe(b.flatMap((e) => R.put({
2750
2938
  bytes: r,
2751
2939
  contentType: n.contentType,
2752
2940
  tenantId: e.tenantId,
@@ -2754,7 +2942,7 @@ var Gt = () => se({
2754
2942
  ...n.visibility ? { visibility: n.visibility } : {},
2755
2943
  ...n.key ? { key: n.key } : {},
2756
2944
  ...n.password ? { password: n.password } : {}
2757
- })), b.flatMap((e) => F.getUrl(e.id).pipe(b.map((t) => ({
2945
+ })), b.flatMap((e) => R.getUrl(e.id).pipe(b.map((t) => ({
2758
2946
  id: e.id,
2759
2947
  url: t
2760
2948
  })))));
@@ -2764,7 +2952,7 @@ var Gt = () => se({
2764
2952
  ...u,
2765
2953
  execute: (e, t) => {
2766
2954
  let n = e;
2767
- return $(t, D).pipe(b.flatMap((e) => F.ingestUrl(n.url, {
2955
+ return $(t, k).pipe(b.flatMap((e) => R.ingestUrl(n.url, {
2768
2956
  tenantId: e.tenantId,
2769
2957
  ownerId: e.id,
2770
2958
  ...n.visibility ? { visibility: n.visibility } : {},
@@ -2773,7 +2961,7 @@ var Gt = () => se({
2773
2961
  ...n.alt === void 0 ? {} : { alt: n.alt },
2774
2962
  ...n.caption === void 0 ? {} : { caption: n.caption },
2775
2963
  ...n.key === void 0 ? {} : { key: n.key }
2776
- })), b.flatMap((e) => F.getUrl(e.id).pipe(b.map((t) => ({
2964
+ })), b.flatMap((e) => R.getUrl(e.id).pipe(b.map((t) => ({
2777
2965
  id: e.id,
2778
2966
  url: t
2779
2967
  })))));
@@ -2783,7 +2971,7 @@ var Gt = () => se({
2783
2971
  ..._,
2784
2972
  execute: (e, t) => {
2785
2973
  let n = e, r = n.expiresInDays ? new Date(Date.now() + n.expiresInDays * 864e5) : null;
2786
- return cn(F, n.refId, t).pipe(b.flatMap(() => F.grant({
2974
+ return _n(R, n.refId, t).pipe(b.flatMap(() => R.grant({
2787
2975
  refId: n.refId,
2788
2976
  principalType: n.principalType,
2789
2977
  principalId: n.principalId,
@@ -2797,21 +2985,21 @@ var Gt = () => se({
2797
2985
  ...g,
2798
2986
  execute: (e, t) => {
2799
2987
  let n = e;
2800
- return F.getGrant(n.grantId).pipe(b.flatMap((e) => e === null ? b.fail(sn()) : cn(F, e.refId, t)), b.flatMap(() => F.revoke(n.grantId)), b.map(() => ({ ok: !0 })));
2988
+ return R.getGrant(n.grantId).pipe(b.flatMap((e) => e === null ? b.fail(gn()) : _n(R, e.refId, t)), b.flatMap(() => R.revoke(n.grantId)), b.map(() => ({ ok: !0 })));
2801
2989
  }
2802
2990
  },
2803
2991
  {
2804
2992
  ...d,
2805
2993
  execute: (e, t) => {
2806
2994
  let n = e;
2807
- return cn(F, n.refId, t).pipe(b.flatMap(() => F.listGrants(n.refId)), b.map((e) => ({ grants: e.map(dn) })));
2995
+ return _n(R, n.refId, t).pipe(b.flatMap(() => R.listGrants(n.refId)), b.map((e) => ({ grants: e.map(bn) })));
2808
2996
  }
2809
2997
  },
2810
2998
  {
2811
2999
  ...f,
2812
3000
  execute: (e, t) => {
2813
3001
  let n = e;
2814
- return F.listRefs({
3002
+ return R.listRefs({
2815
3003
  tenantId: t.request.subject.tenantId,
2816
3004
  ...n.folder === void 0 ? {} : { folder: n.folder },
2817
3005
  ...n.tags === void 0 ? {} : { tags: n.tags },
@@ -2820,34 +3008,34 @@ var Gt = () => se({
2820
3008
  ...n.limit === void 0 ? {} : { limit: n.limit },
2821
3009
  ...n.offset === void 0 ? {} : { offset: n.offset }
2822
3010
  }).pipe(b.map((e) => ({
2823
- refs: e.refs.map(on),
3011
+ refs: e.refs.map(hn),
2824
3012
  nextOffset: e.nextOffset
2825
3013
  })));
2826
3014
  }
2827
3015
  }
2828
3016
  ];
2829
- return T({
2830
- name: re({
2831
- base: fn,
3017
+ return re({
3018
+ name: E({
3019
+ base: xn,
2832
3020
  alias: i.alias,
2833
3021
  instance: i.name
2834
3022
  }),
2835
- baseName: fn,
3023
+ baseName: xn,
2836
3024
  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.",
2837
3025
  permissions: [
2838
3026
  "network:outbound:*",
2839
3027
  "inspect:read",
2840
3028
  "inspect:write"
2841
3029
  ],
2842
- declaredEnv: G.declared,
2843
- services: P,
2844
- inspectEndpoints: ge,
3030
+ declaredEnv: q.declared,
3031
+ services: le,
3032
+ inspectEndpoints: ye,
2845
3033
  httpRoutes: [
2846
- fe,
2847
- pe,
2848
- me
3034
+ he,
3035
+ ge,
3036
+ _e
2849
3037
  ],
2850
- routes: _e,
3038
+ routes: be,
2851
3039
  rpcClientDescriptors: ne,
2852
3040
  errorSchemas: [
2853
3041
  {
@@ -2880,18 +3068,18 @@ var Gt = () => se({
2880
3068
  }
2881
3069
  ],
2882
3070
  bindDataStore: (e) => {
2883
- k && (j.current = At(e)), A && (M.current = Nt(e)), y.bindDataStore?.(e);
3071
+ M && (P.current = Rt(e)), N && (F.current = Vt(e)), S.bindDataStore?.(e);
2884
3072
  },
2885
3073
  onActivate: (e) => b.sync(() => {
2886
- let t = !!S || !!G.read("STORAGE_CDN_URL", i.cdnBaseUrl);
2887
- e.logger.info(`storage: provider=${y.name} presign=${y.presigns ? "yes" : "no"} publicUrl=${t ? "yes" : "no"} transforms=yes`, {
2888
- provider: y.name,
2889
- bucket: x,
2890
- refStore: k ? "memory" : "custom"
2891
- }), y.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 && !y.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.");
3074
+ let t = !!D || !!q.read("STORAGE_CDN_URL", i.cdnBaseUrl);
3075
+ e.logger.info(`storage: provider=${S.name} presign=${S.presigns ? "yes" : "no"} publicUrl=${t ? "yes" : "no"} transforms=yes`, {
3076
+ provider: S.name,
3077
+ bucket: C,
3078
+ refStore: M ? "memory" : "custom"
3079
+ }), S.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 && !S.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.");
2892
3080
  }),
2893
3081
  onDeactivate: () => b.void
2894
3082
  });
2895
3083
  };
2896
3084
  //#endregion
2897
- export { W as STORAGE_BLOBS_TABLE, U as STORAGE_GRANTS_TABLE, H as STORAGE_REFS_TABLE, Ee as STORAGE_USAGE_TABLE, e as StorageAccessDenied, t as StorageError, n as StorageRejected, r as StorageScanRejected, i as StorageService, Ae as _voltroStorageBlobsTable, Oe as _voltroStorageGrantsTable, De as _voltroStorageRefsTable, ke as _voltroStorageUsageTable, en as appStorageProvider, Wt as assetRef, Be as azureProvider, It as buildStorageService, be as bytesToStream, bt as checkLimits, Vt as clamavScanner, Pe as clearStorageBuffer, xe as collectStream, ye as concatBytes, tn as configuredStorageProvider, _t as contentTypeAllowed, Nt as dataStoreGrantStore, At as dataStoreRefStore, ze as databaseProvider, qt as decodeDataUri, Xt as durabilityNotice, Rt as encodeInstream, Ut as ffmpegTranscoder, Ie as filesystemProvider, Se as fromNodeReadable, we as getObjectStream, Je as hashPassword, jt as memoryGrantStore, Fe as memoryProvider, Et as memoryRefStore, zt as parseClamavResponse, He as parseTransformParams, Yt as pathDurability, Jt as putAvatar, Te as putObjectStream, Ne as readStorageBuffer, wt as refMatchesListQuery, nn as resolveStorageProvider, Y as resolveStorageSecret, Le as s3Provider, $t as setActiveStorageProvider, dt as signFinalizeTicket, st as signGrant, ht as signMultipartTicket, pt as signResumableTicket, lt as signUploadTicket, yt as sniffMatches, pn as storagePlugin, Lt as storageServiceLayer, Ce as toNodeReadable, qe as transformCached, Ge as transformImage, ft as verifyFinalizeTicket, ct as verifyGrant, gt as verifyMultipartTicket, Ye as verifyPassword, mt as verifyResumableTicket, ut as verifyUploadTicket, Gt as withStorage };
3085
+ export { K as STORAGE_BLOBS_TABLE, G as STORAGE_GRANTS_TABLE, W as STORAGE_REFS_TABLE, De as STORAGE_USAGE_TABLE, e as StorageAccessDenied, t as StorageError, n as StorageRejected, r as StorageScanRejected, i as StorageService, je as _voltroStorageBlobsTable, ke as _voltroStorageGrantsTable, Oe as _voltroStorageRefsTable, Ae as _voltroStorageUsageTable, un as appStorageProvider, Qt as assetRef, Ve as azureProvider, Wt as buildStorageService, xe as bytesToStream, Ct as checkLimits, Yt as clamavScanner, Fe as clearStorageBuffer, Se as collectStream, be as concatBytes, dn as configuredStorageProvider, bt as contentTypeAllowed, Vt as dataStoreGrantStore, Rt as dataStoreRefStore, Be as databaseProvider, tn as decodeDataUri, on as durabilityNotice, Kt as encodeInstream, Zt as ffmpegTranscoder, Le as filesystemProvider, Ce as fromNodeReadable, Te as getObjectStream, Ze as hashPassword, zt as memoryGrantStore, Ie as memoryProvider, Pt as memoryRefStore, qt as parseClamavResponse, Ue as parseTransformParams, an as pathDurability, nn as putAvatar, Ee as putObjectStream, Pe as readStorageBuffer, Mt as refMatchesListQuery, fn as resolveStorageProvider, Y as resolveStorageSecret, Re as s3Provider, ln as setActiveStorageProvider, mt as signFinalizeTicket, ut as signGrant, vt as signMultipartTicket, gt as signResumableTicket, ft as signUploadTicket, St as sniffMatches, Sn as storagePlugin, rn as storagePutIntentsTable, Gt as storageServiceLayer, we as toNodeReadable, Xe as transformCached, qe as transformImage, ht as verifyFinalizeTicket, dt as verifyGrant, yt as verifyMultipartTicket, Qe as verifyPassword, _t as verifyResumableTicket, pt as verifyUploadTicket, $t as withStorage };