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