@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/dist/ingest.js ADDED
@@ -0,0 +1,81 @@
1
+ import { StorageError as e, StorageRejected as t } from "./types.js";
2
+ import { Effect as n } from "effect";
3
+ //#region src/ingest.ts
4
+ var r = 67108864, i = (e) => new t({
5
+ reason: "too-large",
6
+ detail: `remote body exceeds the ${e}-byte ingest limit`
7
+ }), a = (e, n) => new t({
8
+ reason: "blocked-source",
9
+ detail: `will not fetch ${e}: ${n}`
10
+ }), o = (o, s, c = {}) => n.suspend(() => {
11
+ let l = s ?? r;
12
+ return !Number.isSafeInteger(l) || l < 0 ? n.fail(new e({
13
+ provider: "ingest",
14
+ message: "limits.maxBytes must be a non-negative safe integer",
15
+ transient: !1
16
+ })) : n.tryPromise({
17
+ try: async (t) => {
18
+ let { ssrfReason: n } = await import("./ingestPolicy.js");
19
+ t.throwIfAborted();
20
+ let r = o, s;
21
+ for (let e = 0;; e++) {
22
+ let i = n(r, { ...c.allowHosts === void 0 ? {} : { allowHosts: c.allowHosts } });
23
+ if (i !== null) throw a(r, i);
24
+ s = await fetch(r, {
25
+ signal: t,
26
+ redirect: "manual"
27
+ });
28
+ let o = s.headers.get("location");
29
+ if (s.status < 300 || s.status >= 400 || o === null) break;
30
+ if (await s.body?.cancel().catch(() => {}), e >= (c.maxRedirects ?? 5)) throw a(r, "too many redirects");
31
+ r = new URL(o, r).toString();
32
+ }
33
+ let u;
34
+ try {
35
+ if (!s.ok) throw new e({
36
+ provider: "ingest",
37
+ message: `remote server returned HTTP ${s.status}`,
38
+ transient: s.status === 429 || s.status >= 500,
39
+ status: s.status
40
+ });
41
+ let t = s.headers.get("content-length"), n = s.headers.get("content-encoding")?.trim().toLowerCase();
42
+ if ((!n || n === "identity") && t !== null && /^\d+$/.test(t) && BigInt(t) > BigInt(l)) throw i(l);
43
+ let r = /* @__PURE__ */ new Uint8Array(), a = 0;
44
+ if (s.body !== null) for (u = s.body.getReader();;) {
45
+ let e = await u.read();
46
+ if (e.done) break;
47
+ if (e.value.byteLength > l - a) throw i(l);
48
+ if (e.value.byteLength !== 0) {
49
+ let t = a + e.value.byteLength;
50
+ if (t > r.byteLength) {
51
+ let e = Math.min(l, Math.max(65536, r.byteLength * 2, t)), n = new Uint8Array(e);
52
+ n.set(r), r = n;
53
+ }
54
+ r.set(e.value, a), a = t;
55
+ }
56
+ }
57
+ return {
58
+ bytes: a === r.byteLength ? r : r.slice(0, a),
59
+ contentType: s.headers.get("content-type")?.split(";")[0]?.trim() || "application/octet-stream"
60
+ };
61
+ } finally {
62
+ u === void 0 ? await s.body?.cancel().catch(() => {}) : (await u.cancel().catch(() => {}), u.releaseLock());
63
+ }
64
+ },
65
+ catch: (n) => n instanceof t || n instanceof e ? n : new e({
66
+ provider: "ingest",
67
+ message: "remote fetch or body read failed",
68
+ transient: !0
69
+ })
70
+ });
71
+ }), s = (e, t) => n.suspend(() => {
72
+ if (t === void 0) return e;
73
+ if (t.aborted) return n.interrupt;
74
+ let r = n.callback((e) => {
75
+ let r = () => e(n.interrupt);
76
+ return t.addEventListener("abort", r, { once: !0 }), t.aborted && r(), n.sync(() => t.removeEventListener("abort", r));
77
+ });
78
+ return n.raceFirst(e, r);
79
+ });
80
+ //#endregion
81
+ export { o as fetchIngestBody, s as withIngestAbort };
@@ -0,0 +1 @@
1
+ export { ssrfReason } from "@voltro/runtime";
@@ -0,0 +1,19 @@
1
+ import { StorageError as e, StorageRejected as t } from "./types.js";
2
+ import { causeBranches as n, extractDbCause as r, isTransientContention as i, wireSafeCause as a } from "@voltro/database";
3
+ import { Schema as o } from "effect";
4
+ //#region src/metadataError.ts
5
+ var s = (t, s, c = !1) => {
6
+ let l = n(t).find(o.is(e));
7
+ if (l !== void 0) return l;
8
+ let u = r(t), d = u.dbCode === "22003" || u.dbSqlState === "22003" || u.dbCode === "ER_WARN_DATA_OUT_OF_RANGE" || u.dbErrno === 1264 || u.dbNumber === 8115 || u.dbNumber === 248, f = new e({
9
+ provider: s,
10
+ message: `${d ? "Storage metadata numeric value out of range: " : ""}${a(t)}`,
11
+ transient: d ? !1 : i(t) || c
12
+ });
13
+ return Object.defineProperty(f, "cause", {
14
+ value: t,
15
+ configurable: !0
16
+ }), f;
17
+ }, c = (e) => n(e).find(o.is(t));
18
+ //#endregion
19
+ export { s as storageMetadataError, c as storageRejectedCause };
@@ -0,0 +1,209 @@
1
+ import { requireStorageReferenceScope as e } from "./storageNamespaces.js";
2
+ import { StorageRejected as t } from "./types.js";
3
+ import { storageInteger as n, storageIntegerSum as r } from "./storageNumbers.js";
4
+ import { createHash as i, randomUUID as a } from "node:crypto";
5
+ import { and as o, bigint as s, eq as c, neq as l, table as u, text as d } from "@voltro/database";
6
+ import { Schema as f } from "effect";
7
+ //#region src/objectLifecycle.ts
8
+ var p = "_voltro_storage_operation_locks", m = "_voltro_storage_object_heads", h = "_voltro_storage_operations", g = "_voltro_storage_object_claims", _ = [
9
+ u(p, {
10
+ id: d().maxLength(64),
11
+ nonce: d()
12
+ }).primaryKey(["id"]).nonReactive(),
13
+ u(m, {
14
+ id: d().maxLength(64),
15
+ objectNamespace: d().maxLength(64).nullable(),
16
+ generation: d(),
17
+ key: d(),
18
+ reservations: s()
19
+ }).primaryKey(["id"]).nonReactive(),
20
+ u(h, {
21
+ id: d().maxLength(64),
22
+ storageInstance: d().nullable(),
23
+ objectNamespace: d().maxLength(64).nullable(),
24
+ objectId: d().maxLength(64),
25
+ fingerprint: d().maxLength(64),
26
+ generation: d(),
27
+ key: d(),
28
+ refId: d(),
29
+ state: d(),
30
+ deleteKey: d().nullable()
31
+ }).primaryKey(["id"]).nonReactive(),
32
+ u(g, {
33
+ id: d().maxLength(64),
34
+ operationId: d().maxLength(64),
35
+ claim: d()
36
+ }).primaryKey(["id"]).nonReactive()
37
+ ], v = f.Struct({
38
+ id: f.String,
39
+ storageInstance: f.String,
40
+ objectNamespace: f.String,
41
+ objectId: f.String,
42
+ fingerprint: f.String,
43
+ generation: f.String,
44
+ key: f.String,
45
+ refId: f.String,
46
+ state: f.Literals([
47
+ "reserved",
48
+ "ready",
49
+ "deleting",
50
+ "deleted"
51
+ ]),
52
+ deleteKey: f.NullOr(f.String)
53
+ }), y = f.Struct({
54
+ id: f.String,
55
+ objectNamespace: f.String,
56
+ generation: f.String,
57
+ key: f.String,
58
+ reservations: f.Int.pipe(f.check(f.isGreaterThanOrEqualTo(0)))
59
+ }), b = (e) => f.decodeUnknownSync(y)({
60
+ ...e,
61
+ reservations: n(e.reservations, "shared-object reservation count")
62
+ }), x = (e) => i("sha256").update(JSON.stringify(e)).digest("hex"), S = (e, t) => x([e, t]), C = (t) => {
63
+ if (e(t), !t.bucket || !t.operationId || !t.logicalKey || !/^[a-f0-9]{64}$/.test(t.fingerprint) || !/^[a-f0-9]{64}$/.test(t.checksum)) throw Error("Storage operation requires a bucket, operation identity, key and SHA-256 fingerprint");
64
+ return {
65
+ id: x([
66
+ t.storageInstance,
67
+ t.objectNamespace,
68
+ t.bucket,
69
+ t.tenantId,
70
+ t.operationId
71
+ ]),
72
+ objectId: x([
73
+ t.objectNamespace,
74
+ t.bucket,
75
+ t.tenantId,
76
+ t.logicalKey,
77
+ t.checksum
78
+ ]),
79
+ lockId: x([t.tenantId])
80
+ };
81
+ }, w = async (e, t, n) => {
82
+ let { lockId: r } = C(t);
83
+ return await e.insertIgnoreWithOutcome(p, {
84
+ id: r,
85
+ nonce: a()
86
+ }, { conflictColumns: ["id"] }), e.transactional(async (e) => {
87
+ if ((await e.query({
88
+ table: p,
89
+ predicate: c("id", r),
90
+ lock: "update",
91
+ order: [],
92
+ take: 1,
93
+ skip: void 0,
94
+ projection: void 0
95
+ })).length !== 1 || await e.update(p, r, { nonce: a() }) === null) throw Error("Storage operation lock is unavailable");
96
+ return n(e);
97
+ });
98
+ }, T = async (e, n) => {
99
+ let r = C(n), i = await e.query({
100
+ table: h,
101
+ predicate: c("id", r.id),
102
+ order: [],
103
+ take: 1,
104
+ skip: void 0,
105
+ projection: void 0
106
+ });
107
+ if (!i[0]) return;
108
+ let a = f.decodeUnknownSync(v)(i[0]);
109
+ if (a.storageInstance !== n.storageInstance || a.objectNamespace !== n.objectNamespace || a.fingerprint !== n.fingerprint || a.objectId !== r.objectId) throw new t({
110
+ reason: "operation-identity-reused",
111
+ detail: `storage operation '${n.operationId}' was already used with different inputs`
112
+ });
113
+ return a;
114
+ }, E = async (e, t) => {
115
+ let n = await T(e, t);
116
+ if (n) return n;
117
+ let { id: i, objectId: o } = C(t), s = await e.query({
118
+ table: m,
119
+ predicate: c("id", o),
120
+ order: [],
121
+ take: 1,
122
+ skip: void 0,
123
+ projection: void 0
124
+ }), l = s[0] ? b(s[0]) : void 0, u = l?.generation ?? a(), d = l?.key ?? `${t.logicalKey}/g-${u}`;
125
+ l ? await e.update(m, o, { reservations: String(r(l.reservations, 1, "shared-object reservation count")) }) : await e.insert(m, {
126
+ id: o,
127
+ objectNamespace: t.objectNamespace,
128
+ generation: u,
129
+ key: d,
130
+ reservations: "1"
131
+ });
132
+ let f = {
133
+ id: i,
134
+ storageInstance: t.storageInstance,
135
+ objectNamespace: t.objectNamespace,
136
+ objectId: o,
137
+ fingerprint: t.fingerprint,
138
+ generation: u,
139
+ key: d,
140
+ refId: `file_${a()}`,
141
+ state: "reserved",
142
+ deleteKey: null
143
+ };
144
+ return await e.insert(h, f), f;
145
+ }, D = async (e, t) => {
146
+ let n = await T(e, t);
147
+ if (!n) throw Error("Storage operation is missing");
148
+ if (n.state === "deleting" || n.state === "deleted") throw Error("Deleted storage operation cannot be confirmed by a late put");
149
+ return await e.update(h, n.id, { state: "ready" }), {
150
+ ...n,
151
+ state: "ready"
152
+ };
153
+ }, O = async (e, t) => {
154
+ let n = await T(e, t);
155
+ if (!n) throw Error("Storage operation is missing");
156
+ if (n.state === "deleting" || n.state === "deleted") return n;
157
+ if (n.state !== "ready") throw Error("An unconfirmed put cannot be deleted");
158
+ let r = await e.query({
159
+ table: m,
160
+ predicate: c("id", n.objectId),
161
+ order: [],
162
+ take: 1,
163
+ skip: void 0,
164
+ projection: void 0
165
+ }), i = r[0] ? b(r[0]) : void 0;
166
+ if (!i || i.generation !== n.generation || i.reservations < 1) throw Error("Storage object generation does not own its reservation");
167
+ let a = i.reservations === 1 ? i.key : null;
168
+ return a === null ? await e.update(m, i.id, { reservations: String(i.reservations - 1) }) : await e.delete(m, i.id), a !== null && (await e.query({
169
+ table: m,
170
+ predicate: o(c("objectNamespace", t.objectNamespace), c("key", a)),
171
+ order: [],
172
+ take: 1,
173
+ skip: void 0,
174
+ projection: ["id"]
175
+ })).length && (a = null), await e.update(h, n.id, {
176
+ state: "deleting",
177
+ deleteKey: a
178
+ }), {
179
+ ...n,
180
+ state: "deleting",
181
+ deleteKey: a
182
+ };
183
+ }, k = async (e, t) => {
184
+ let n = await T(e, t);
185
+ if (!n || n.state !== "deleting" && n.state !== "deleted") throw Error("Storage deletion has not been accepted");
186
+ return n.state !== "deleted" && (await e.update(h, n.id, { state: "deleted" }), !0);
187
+ }, A = async (e, t, n) => {
188
+ if (!n) throw Error("Storage object claim must be a non-empty string");
189
+ await e.insertIgnoreWithOutcome(g, {
190
+ id: S(t, n),
191
+ operationId: t,
192
+ claim: n
193
+ }, { conflictColumns: ["id"] });
194
+ }, j = async (e, t, n) => {
195
+ let r = S(t, n);
196
+ return {
197
+ held: await e.delete(g, r),
198
+ others: (await e.query({
199
+ table: g,
200
+ predicate: o(c("operationId", t), l("claim", n)),
201
+ order: [],
202
+ take: 1,
203
+ skip: void 0,
204
+ projection: void 0
205
+ })).length > 0
206
+ };
207
+ }, M = (e, t) => e.deleteMany(g, { where: c("operationId", t) });
208
+ //#endregion
209
+ export { O as beginStorageObjectDeleteInTransaction, A as claimStorageObjectInTransaction, M as clearStorageObjectClaimsInTransaction, k as confirmStorageObjectDeleteInTransaction, D as confirmStorageObjectInTransaction, T as readStorageObjectOperationInTransaction, j as releaseStorageObjectClaimInTransaction, E as reserveStorageObjectInTransaction, S as storageObjectClaimId, C as storageObjectIdentifiers, _ as storageObjectLifecycleTables, w as withStorageOperationTransaction };
@@ -0,0 +1,150 @@
1
+ import { requireStorageReferenceScope as e } from "./storageNamespaces.js";
2
+ import { StorageRejected as t } from "./types.js";
3
+ import { beginStorageObjectDeleteInTransaction as n, claimStorageObjectInTransaction as r, clearStorageObjectClaimsInTransaction as i, confirmStorageObjectDeleteInTransaction as a, confirmStorageObjectInTransaction as o, readStorageObjectOperationInTransaction as s, releaseStorageObjectClaimInTransaction as c, reserveStorageObjectInTransaction as l, withStorageOperationTransaction as u } from "./objectLifecycle.js";
4
+ import { dataStoreGrantStore as d, dataStoreRefStore as f, toRef as p } from "./service.js";
5
+ import { and as m, eq as h, json as g, table as _, text as v } from "@voltro/database";
6
+ import { Effect as y, Schema as b } from "effect";
7
+ //#region src/objectMetadata.ts
8
+ var x = "_voltro_storage_put_intents", S = _(x, {
9
+ id: v().maxLength(64),
10
+ refId: v().maxLength(64),
11
+ storageInstance: v().nullable(),
12
+ objectNamespace: v().maxLength(64).nullable(),
13
+ identity: g(),
14
+ ref: g()
15
+ }).primaryKey(["id"]).unique("storagePutRef", ["refId"]).nonReactive(), C = b.Struct({
16
+ storageInstance: b.String,
17
+ objectNamespace: b.String,
18
+ tenantId: b.NullOr(b.String),
19
+ bucket: b.String,
20
+ operationId: b.String,
21
+ fingerprint: b.String,
22
+ checksum: b.String,
23
+ logicalKey: b.String
24
+ }), w = async (e, t, n) => {
25
+ let r = await e.query({
26
+ table: x,
27
+ predicate: m(h("storageInstance", n.storageInstance), h("objectNamespace", n.objectNamespace), h("refId", t)),
28
+ order: [],
29
+ take: 2,
30
+ skip: void 0,
31
+ projection: void 0
32
+ });
33
+ if (r.length === 0) return;
34
+ if (r.length !== 1) throw Error("Storage reference has ambiguous operation ownership");
35
+ let i = r[0], a = b.decodeUnknownSync(C)(i.identity);
36
+ if (a.storageInstance !== n.storageInstance || a.objectNamespace !== n.objectNamespace) throw Error("Storage put intent does not match its bound storage scope");
37
+ if (typeof i.ref != "object" || i.ref === null || Array.isArray(i.ref)) throw Error("Storage operation reference is unreadable");
38
+ let o = p(i.ref);
39
+ if (o.id !== t || o.bucket !== a.bucket || o.tenantId !== a.tenantId || o.checksum !== a.checksum || !Number.isSafeInteger(o.size) || o.size < 0 || !Number.isFinite(o.createdAt.getTime())) throw Error("Storage operation reference does not match its identity");
40
+ return {
41
+ identity: a,
42
+ ref: o
43
+ };
44
+ }, T = (m, h) => {
45
+ let g = Object.freeze({ ...h });
46
+ e(g);
47
+ let _ = (e) => ({
48
+ ...e,
49
+ ...g
50
+ });
51
+ return {
52
+ scope: g,
53
+ intent: (e) => w(m, e, g),
54
+ reserve: (e, n, i, a) => u(m, _(e), async (o) => {
55
+ if (n.tenantId !== e.tenantId || n.bucket !== e.bucket || n.checksum !== e.checksum || !Number.isSafeInteger(n.size) || n.size < 0) throw Error("Storage put metadata does not match its identity");
56
+ let c = await s(o, _(e));
57
+ if (c) {
58
+ if (c.state === "deleting" || c.state === "deleted") throw Error("Storage put identity has already been deleted");
59
+ let e = await w(o, c.refId, g);
60
+ if (!e) throw Error("Storage operation lost its put intent");
61
+ let t = c.state === "ready";
62
+ return t && a !== void 0 && await r(o, c.id, a), {
63
+ ref: e.ref,
64
+ ready: t,
65
+ outcome: t ? "joined" : "resumed"
66
+ };
67
+ }
68
+ let u = await l(o, _(e)), d = f(o, g);
69
+ if (!(await y.runPromise(d.consumeUsage(e.tenantId, {
70
+ bytes: n.size,
71
+ count: 1
72
+ }, i))).allowed) throw new t({
73
+ reason: "quota-exceeded",
74
+ detail: "Storage operation exceeds tenant quota"
75
+ });
76
+ let m = p({
77
+ ...n,
78
+ id: u.refId,
79
+ key: u.key
80
+ });
81
+ return await o.insert(x, {
82
+ id: u.id,
83
+ refId: m.id,
84
+ ...g,
85
+ identity: _(e),
86
+ ref: m
87
+ }), {
88
+ ref: m,
89
+ ready: !1,
90
+ outcome: "created"
91
+ };
92
+ }),
93
+ confirm: (e, t) => u(m, _(e), async (n) => {
94
+ let i = await s(n, _(e));
95
+ if (!i) throw Error("Storage put operation is missing");
96
+ let a = await w(n, i.refId, g);
97
+ if (!a) throw Error("Storage put intent is missing");
98
+ if (t !== void 0 && await r(n, i.id, t), i.state === "ready") {
99
+ let t = await y.runPromise(f(n, g).getById(i.refId));
100
+ if (!t || t.key !== i.key || t.checksum !== e.checksum) throw Error("Confirmed storage operation lost its reference");
101
+ return t;
102
+ }
103
+ return await o(n, _(e)), await y.runPromise(f(n, g).insert(a.ref)), a.ref;
104
+ }),
105
+ beginDelete: async (e, r, a) => {
106
+ let o = await w(m, e, g);
107
+ if (!o) throw Error("Storage delete operation is missing");
108
+ if (r !== void 0 && o.identity.tenantId !== r) throw Error("Storage delete tenant mismatch");
109
+ return u(m, o.identity, async (r) => {
110
+ let o = await w(r, e, g);
111
+ if (!o) throw Error("Storage delete intent disappeared");
112
+ let l = await s(r, o.identity);
113
+ if (!l) throw Error("Storage delete lost its operation");
114
+ let u = l.state === "ready", p = l.state !== "deleting" && l.state !== "deleted";
115
+ if (a === void 0) p && await i(r, l.id);
116
+ else if (p) {
117
+ let n = await c(r, l.id, a);
118
+ if (n.others) return {
119
+ released: !0,
120
+ identity: o.identity
121
+ };
122
+ if (!n.held) throw new t({
123
+ reason: "claim-not-held",
124
+ detail: `claim '${a}' is not held on storage reference '${e}'; a reference put without a claim is deleted as a whole by a delete that names none`
125
+ });
126
+ }
127
+ let m = await n(r, o.identity);
128
+ if (u) {
129
+ let t = f(r, g);
130
+ if (await y.runPromise(d(r, g).deleteByRef(e)), !await y.runPromise(t.delete(e))) throw Error("Storage deletion lost its confirmed reference");
131
+ await y.runPromise(t.releaseUsage(o.identity.tenantId, {
132
+ bytes: o.ref.size,
133
+ count: 1
134
+ }));
135
+ }
136
+ return m.deleteKey !== null && await y.runPromise(f(r, g).countByKey(o.ref.bucket, m.deleteKey)) > 0 && (await r.update("_voltro_storage_operations", m.id, { deleteKey: null }), m = {
137
+ ...m,
138
+ deleteKey: null
139
+ }), {
140
+ released: !0,
141
+ operation: m,
142
+ identity: o.identity
143
+ };
144
+ });
145
+ },
146
+ confirmDelete: (e) => u(m, _(e), (t) => a(t, _(e)))
147
+ };
148
+ };
149
+ //#endregion
150
+ export { T as makeStorageObjectMetadata, S as storagePutIntentsTable };
@@ -0,0 +1,58 @@
1
+ import { StorageError as e, StorageRejected as t } from "./types.js";
2
+ import { storageMetadataError as n, storageRejectedCause as r } from "./metadataError.js";
3
+ import { createHash as i } from "node:crypto";
4
+ import { Effect as a } from "effect";
5
+ //#region src/objectWriter.ts
6
+ var o = (o) => {
7
+ let s = a.gen(function* () {
8
+ (yield* o.provider.objectNamespace) !== o.metadata.scope.objectNamespace && (yield* a.fail(new e({
9
+ provider: "metadata",
10
+ message: "Storage metadata is bound to another physical object namespace",
11
+ transient: !1,
12
+ status: 409
13
+ })));
14
+ }), c = (t, i) => a.tryPromise({
15
+ try: i,
16
+ catch: (i) => {
17
+ let a = r(i);
18
+ if (a !== void 0) return a;
19
+ let o = n(i, "metadata"), s = new e({
20
+ provider: "metadata",
21
+ message: `Storage ${t} was not confirmed: ${o.message}; retain the operation identity for recovery`,
22
+ transient: o.transient,
23
+ ...o.status === void 0 ? {} : { status: o.status }
24
+ });
25
+ return Object.defineProperty(s, "cause", {
26
+ value: i,
27
+ configurable: !0
28
+ }), s;
29
+ }
30
+ });
31
+ return {
32
+ put: (e) => a.gen(function* () {
33
+ if (e.bytes.byteLength !== e.ref.size || i("sha256").update(e.bytes).digest("hex") !== e.identity.checksum) return yield* a.fail(new t({
34
+ reason: "operation-content-mismatch",
35
+ detail: "Storage operation bytes do not match their reserved identity"
36
+ }));
37
+ yield* s;
38
+ let n = yield* c("put reservation", () => o.metadata.reserve(e.identity, e.ref, e.quota, e.claim)), r = n.outcome;
39
+ return n.ready ? {
40
+ ref: n.ref,
41
+ outcome: r
42
+ } : (yield* o.provider.put(n.ref.key, e.bytes, {
43
+ contentType: n.ref.contentType,
44
+ public: n.ref.visibility === "public"
45
+ }), {
46
+ ref: yield* c("put confirmation", () => o.metadata.confirm(e.identity, e.claim)),
47
+ outcome: r
48
+ });
49
+ }),
50
+ delete: (e, t, n) => a.gen(function* () {
51
+ yield* s;
52
+ let r = yield* c("delete acceptance", () => o.metadata.beginDelete(e, t, n));
53
+ "operation" in r && (r.operation.deleteKey !== null && (yield* o.provider.delete(r.operation.deleteKey)), yield* c("delete confirmation", () => o.metadata.confirmDelete(r.identity)));
54
+ })
55
+ };
56
+ };
57
+ //#endregion
58
+ export { o as makeStorageObjectWriter };
@@ -0,0 +1,16 @@
1
+ import { statSync as e } from "node:fs";
2
+ //#region src/pathDurability.ts
3
+ var t = (t) => {
4
+ try {
5
+ let n = e(t), r = e("/");
6
+ return typeof n.dev != "number" || typeof r.dev != "number" ? "unknown" : n.dev === r.dev ? "same-device-as-root" : "separate-mount";
7
+ } catch {
8
+ return "unknown";
9
+ }
10
+ }, n = (e) => {
11
+ if (t(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
12
+ dies with it — which is the exact failure it exists for. On a development machine this is normal
13
+ and can be ignored.`;
14
+ };
15
+ //#endregion
16
+ export { n as durabilityNotice, t as pathDurability };