@noy-db/hub 0.2.0-pre.30 → 0.2.0-pre.31

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.
Files changed (143) hide show
  1. package/dist/adapter/index.d.ts +9 -0
  2. package/dist/adapter/index.js +14 -0
  3. package/dist/attestation/index.d.ts +1 -1
  4. package/dist/attestation/index.js +3 -3
  5. package/dist/blobs/index.d.ts +3 -3
  6. package/dist/bundle/index.d.ts +3 -3
  7. package/dist/bundle/index.js +1 -1
  8. package/dist/{chunk-Y6YUWZTS.js → chunk-L5HHBOMS.js} +2 -2
  9. package/dist/{chunk-BVKLJBJJ.js → chunk-W5NVNJDX.js} +2 -1
  10. package/dist/{chunk-BVKLJBJJ.js.map → chunk-W5NVNJDX.js.map} +1 -1
  11. package/dist/consent/index.d.ts +2 -2
  12. package/dist/{decrypt-partition-Mhjh6nnG.d.ts → decrypt-partition-CXS5KopB.d.ts} +1 -1
  13. package/dist/derivations/index.d.ts +3 -3
  14. package/dist/{dev-unlock-DJ3IhgY9.d.ts → dev-unlock-CnHTTVea.d.ts} +1 -1
  15. package/dist/guards/index.d.ts +3 -3
  16. package/dist/{hash-DLwkYf1d.d.ts → hash-oc5paYl0.d.ts} +1 -1
  17. package/dist/history/index.d.ts +3 -3
  18. package/dist/i18n/index.d.ts +2 -2
  19. package/dist/{index-CMRIx_zx.d.ts → index-BmhGztUi.d.ts} +1 -1
  20. package/dist/index.d.ts +11 -11
  21. package/dist/index.js +2 -2
  22. package/dist/kernel/index.d.ts +2 -2
  23. package/dist/materialized-views/index.d.ts +3 -3
  24. package/dist/{mime-magic-CacDBwYp.d.ts → mime-magic-JeLKHRng.d.ts} +1 -1
  25. package/dist/{noydb-5MIBD77B.js → noydb-NAU2DTFP.js} +2 -2
  26. package/dist/noydb-NAU2DTFP.js.map +1 -0
  27. package/dist/overlay-views/index.d.ts +3 -3
  28. package/dist/periods/index.d.ts +2 -2
  29. package/dist/session/index.d.ts +3 -3
  30. package/dist/shadow/index.d.ts +2 -2
  31. package/dist/snapshots/index.d.ts +2 -2
  32. package/dist/store/index.d.ts +2 -2
  33. package/dist/sync/index.d.ts +1 -1
  34. package/dist/team/index.d.ts +2 -2
  35. package/dist/{transition-guard-J04-jime.d.ts → transition-guard-Dy3NioQr.d.ts} +1 -1
  36. package/dist/tx/index.d.ts +2 -2
  37. package/dist/{with-materialized-view-DNfzC5lH.d.ts → with-materialized-view-DIVeez0W.d.ts} +1 -1
  38. package/dist/{with-overlayed-view-qk3lbhOd.d.ts → with-overlayed-view-DVZrc5Hb.d.ts} +1 -1
  39. package/dist/{with-rollup-Dd3_ZG4b.d.ts → with-rollup-CbU-O4wP.d.ts} +1 -1
  40. package/package.json +62 -221
  41. package/dist/aggregate/index.cjs +0 -1144
  42. package/dist/aggregate/index.cjs.map +0 -1
  43. package/dist/aggregate/index.d.cts +0 -39
  44. package/dist/attestation/index.cjs +0 -305
  45. package/dist/attestation/index.cjs.map +0 -1
  46. package/dist/attestation/index.d.cts +0 -54
  47. package/dist/blobs/index.cjs +0 -1967
  48. package/dist/blobs/index.cjs.map +0 -1
  49. package/dist/blobs/index.d.cts +0 -48
  50. package/dist/bundle/index.cjs +0 -41045
  51. package/dist/bundle/index.cjs.map +0 -1
  52. package/dist/bundle/index.d.cts +0 -187
  53. package/dist/consent/index.cjs +0 -204
  54. package/dist/consent/index.cjs.map +0 -1
  55. package/dist/consent/index.d.cts +0 -27
  56. package/dist/crdt/index.cjs +0 -152
  57. package/dist/crdt/index.cjs.map +0 -1
  58. package/dist/crdt/index.d.cts +0 -30
  59. package/dist/decrypt-partition-C0iDpbSd.d.cts +0 -558
  60. package/dist/derivations/index.cjs +0 -469
  61. package/dist/derivations/index.cjs.map +0 -1
  62. package/dist/derivations/index.d.cts +0 -74
  63. package/dist/dev-unlock-0Z6yxfS7.d.cts +0 -263
  64. package/dist/discriminant-BN9REW3o.d.cts +0 -60
  65. package/dist/errors-BAWO5Z5a.d.cts +0 -1500
  66. package/dist/forget/index.cjs +0 -43
  67. package/dist/forget/index.cjs.map +0 -1
  68. package/dist/forget/index.d.cts +0 -1
  69. package/dist/guards/index.cjs +0 -455
  70. package/dist/guards/index.cjs.map +0 -1
  71. package/dist/guards/index.d.cts +0 -39
  72. package/dist/hash-Db8ncXGr.d.cts +0 -63
  73. package/dist/history/index.cjs +0 -1245
  74. package/dist/history/index.cjs.map +0 -1
  75. package/dist/history/index.d.cts +0 -65
  76. package/dist/i18n/index.cjs +0 -1280
  77. package/dist/i18n/index.cjs.map +0 -1
  78. package/dist/i18n/index.d.cts +0 -41
  79. package/dist/index-BMmajblo.d.cts +0 -362
  80. package/dist/index-C1SC1EPe.d.cts +0 -1325
  81. package/dist/index-xJEPkvMb.d.cts +0 -93
  82. package/dist/index.cjs +0 -48100
  83. package/dist/index.cjs.map +0 -1
  84. package/dist/index.d.cts +0 -1050
  85. package/dist/indexing/index.cjs +0 -803
  86. package/dist/indexing/index.cjs.map +0 -1
  87. package/dist/indexing/index.d.cts +0 -36
  88. package/dist/kernel/index.cjs +0 -751
  89. package/dist/kernel/index.cjs.map +0 -1
  90. package/dist/kernel/index.d.cts +0 -11
  91. package/dist/lazy-builder-eYZzLEL1.d.cts +0 -304
  92. package/dist/materialized-views/index.cjs +0 -1518
  93. package/dist/materialized-views/index.cjs.map +0 -1
  94. package/dist/materialized-views/index.d.cts +0 -187
  95. package/dist/mime-magic-sdMzsfVK.d.cts +0 -103
  96. package/dist/overlay-views/index.cjs +0 -399
  97. package/dist/overlay-views/index.cjs.map +0 -1
  98. package/dist/overlay-views/index.d.cts +0 -102
  99. package/dist/periods/index.cjs +0 -1041
  100. package/dist/periods/index.cjs.map +0 -1
  101. package/dist/periods/index.d.cts +0 -24
  102. package/dist/predicate-BmhBSPCH.d.cts +0 -267
  103. package/dist/query/index.cjs +0 -3480
  104. package/dist/query/index.cjs.map +0 -1
  105. package/dist/query/index.d.cts +0 -4
  106. package/dist/sealed-record/index.cjs +0 -139
  107. package/dist/sealed-record/index.cjs.map +0 -1
  108. package/dist/sealed-record/index.d.cts +0 -123
  109. package/dist/session/index.cjs +0 -495
  110. package/dist/session/index.cjs.map +0 -1
  111. package/dist/session/index.d.cts +0 -48
  112. package/dist/shadow/index.cjs +0 -133
  113. package/dist/shadow/index.cjs.map +0 -1
  114. package/dist/shadow/index.d.cts +0 -19
  115. package/dist/snapshots/index.cjs +0 -937
  116. package/dist/snapshots/index.cjs.map +0 -1
  117. package/dist/snapshots/index.d.cts +0 -30
  118. package/dist/store/index.cjs +0 -1091
  119. package/dist/store/index.cjs.map +0 -1
  120. package/dist/store/index.d.cts +0 -501
  121. package/dist/strategy-BSxFXGzb.d.cts +0 -110
  122. package/dist/strategy-mJExw4LQ.d.cts +0 -1069
  123. package/dist/sync/index.cjs +0 -1062
  124. package/dist/sync/index.cjs.map +0 -1
  125. package/dist/sync/index.d.cts +0 -45
  126. package/dist/team/index.cjs +0 -2805
  127. package/dist/team/index.cjs.map +0 -1
  128. package/dist/team/index.d.cts +0 -120
  129. package/dist/transition-guard-tWZIsaXe.d.cts +0 -165
  130. package/dist/tx/index.cjs +0 -614
  131. package/dist/tx/index.cjs.map +0 -1
  132. package/dist/tx/index.d.cts +0 -39
  133. package/dist/types-CdVfiQgt.d.cts +0 -15275
  134. package/dist/ulid-DRH25k3y.d.cts +0 -66
  135. package/dist/util/index.cjs +0 -237
  136. package/dist/util/index.cjs.map +0 -1
  137. package/dist/util/index.d.cts +0 -79
  138. package/dist/with-materialized-view-DfgPcvi9.d.cts +0 -27
  139. package/dist/with-overlayed-view-Cvfkx1lg.d.cts +0 -13
  140. package/dist/with-rollup-nIxo7h9z.d.cts +0 -47
  141. /package/dist/{noydb-5MIBD77B.js.map → adapter/index.js.map} +0 -0
  142. /package/dist/{chunk-Y6YUWZTS.js.map → chunk-L5HHBOMS.js.map} +0 -0
  143. /package/dist/{types-DHn9lEP0.d.ts → index-DHn9lEP0.d.ts} +0 -0
package/dist/tx/index.cjs DELETED
@@ -1,614 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __esm = (fn, res) => function __init() {
7
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
- };
9
- var __export = (target, all) => {
10
- for (var name in all)
11
- __defProp(target, name, { get: all[name], enumerable: true });
12
- };
13
- var __copyProps = (to, from, except, desc) => {
14
- if (from && typeof from === "object" || typeof from === "function") {
15
- for (let key of __getOwnPropNames(from))
16
- if (!__hasOwnProp.call(to, key) && key !== except)
17
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
- }
19
- return to;
20
- };
21
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
-
23
- // src/errors.ts
24
- var NoydbError, FieldFrozenError, InvariantError, AmendmentForbiddenError, ConflictError, ValidationError;
25
- var init_errors = __esm({
26
- "src/errors.ts"() {
27
- "use strict";
28
- NoydbError = class extends Error {
29
- /** Machine-readable error code. Stable across library versions. */
30
- code;
31
- constructor(code, message) {
32
- super(message);
33
- this.name = "NoydbError";
34
- this.code = code;
35
- }
36
- };
37
- FieldFrozenError = class extends NoydbError {
38
- collection;
39
- id;
40
- fields;
41
- constructor(collection, id, fields) {
42
- super(
43
- "FIELD_FROZEN",
44
- `Cannot change frozen field(s) on ${collection}/${id}: ${fields.join(", ")}. Use withTransactions({ amendment: true, reason }) with admin/owner role to override.`
45
- );
46
- this.name = "FieldFrozenError";
47
- this.collection = collection;
48
- this.id = id;
49
- this.fields = fields;
50
- }
51
- };
52
- InvariantError = class extends NoydbError {
53
- constructor(message) {
54
- super("INVARIANT_VIOLATED", message);
55
- this.name = "InvariantError";
56
- }
57
- };
58
- AmendmentForbiddenError = class extends NoydbError {
59
- userId;
60
- role;
61
- constructor(userId, role) {
62
- super(
63
- "AMENDMENT_FORBIDDEN",
64
- `User "${userId}" with role "${role}" cannot open an amendment transaction. Amendments require admin or owner role.`
65
- );
66
- this.name = "AmendmentForbiddenError";
67
- this.userId = userId;
68
- this.role = role;
69
- }
70
- };
71
- ConflictError = class extends NoydbError {
72
- /** The actual stored version at the time of conflict. */
73
- version;
74
- constructor(version, message = "Version conflict") {
75
- super("CONFLICT", message);
76
- this.name = "ConflictError";
77
- this.version = version;
78
- }
79
- };
80
- ValidationError = class extends NoydbError {
81
- constructor(message = "Validation error") {
82
- super("VALIDATION_ERROR", message);
83
- this.name = "ValidationError";
84
- }
85
- };
86
- }
87
- });
88
-
89
- // src/guards/executor.ts
90
- var executor_exports = {};
91
- __export(executor_exports, {
92
- GuardExecutor: () => GuardExecutor
93
- });
94
- function deepEqual(a, b) {
95
- if (a === b) return true;
96
- if (a === null || b === null) return a === b;
97
- if (typeof a !== typeof b) return false;
98
- if (typeof a !== "object") return a === b;
99
- if (Array.isArray(a) !== Array.isArray(b)) return false;
100
- if (Array.isArray(a)) {
101
- const aa = a;
102
- const bb = b;
103
- if (aa.length !== bb.length) return false;
104
- for (let i = 0; i < aa.length; i++) if (!deepEqual(aa[i], bb[i])) return false;
105
- return true;
106
- }
107
- const ao = a;
108
- const bo = b;
109
- const ak = Object.keys(ao);
110
- const bk = Object.keys(bo);
111
- if (ak.length !== bk.length) return false;
112
- for (const k of ak) {
113
- if (!Object.prototype.hasOwnProperty.call(bo, k)) return false;
114
- if (!deepEqual(ao[k], bo[k])) return false;
115
- }
116
- return true;
117
- }
118
- var GuardExecutor;
119
- var init_executor = __esm({
120
- "src/guards/executor.ts"() {
121
- "use strict";
122
- init_errors();
123
- GuardExecutor = {
124
- /**
125
- * Compare existing vs incoming for each `frozenFields.fields` entry
126
- * when `frozenFields.when(existing)` is true. Throws
127
- * `FieldFrozenError` listing every changed frozen field.
128
- *
129
- * @param skipFields — field names that are schema-owned computed fields.
130
- * These are excluded from the comparison because `incoming` carries the
131
- * raw user input (computed fields not yet evaluated), so comparing
132
- * `existing[field]` vs `incoming[field]` would always look like a
133
- * change even when the computed result is unchanged.
134
- */
135
- async checkFrozenFields(guard, id, existing, incoming, skipFields) {
136
- const ff = guard.frozenFields;
137
- if (!ff) return;
138
- if (existing === null) return;
139
- if (!ff.when(existing)) return;
140
- const changed = [];
141
- for (const f of ff.fields) {
142
- if (skipFields?.has(String(f))) continue;
143
- if (existing[f] !== incoming[f]) {
144
- if (!deepEqual(existing[f], incoming[f])) changed.push(String(f));
145
- }
146
- }
147
- if (changed.length > 0) {
148
- throw new FieldFrozenError(guard.collection, id, changed);
149
- }
150
- },
151
- /**
152
- * Run a single guard's invariant over its slice of the change-set.
153
- * Any throw is converted to `InvariantError` unless it already is one.
154
- */
155
- async runInvariant(guard, changes, ctx) {
156
- const amendment = guard.amendment;
157
- if (!amendment) return;
158
- try {
159
- await amendment.invariant(changes, ctx);
160
- } catch (err) {
161
- if (err instanceof InvariantError) throw err;
162
- throw new InvariantError(
163
- err instanceof Error ? err.message : `invariant violated: ${String(err)}`
164
- );
165
- }
166
- }
167
- };
168
- }
169
- });
170
-
171
- // src/tx/index.ts
172
- var tx_exports = {};
173
- __export(tx_exports, {
174
- TxCollection: () => TxCollection,
175
- TxContext: () => TxContext,
176
- TxVault: () => TxVault,
177
- runTransaction: () => runTransaction,
178
- withTransactions: () => withTransactions
179
- });
180
- module.exports = __toCommonJS(tx_exports);
181
-
182
- // src/tx/transaction.ts
183
- init_errors();
184
-
185
- // src/bundle/ulid.ts
186
- var CROCKFORD_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
187
- function encodeBase32(value, length) {
188
- let out = "";
189
- let v = value;
190
- for (let i = 0; i < length; i++) {
191
- out = CROCKFORD_ALPHABET[v % 32] + out;
192
- v = Math.floor(v / 32);
193
- }
194
- return out;
195
- }
196
- function generateULID() {
197
- const now = Date.now();
198
- const timestampHigh = Math.floor(now / 16777216);
199
- const timestampLow = now & 16777215;
200
- const tsPart = encodeBase32(timestampHigh, 5) + encodeBase32(timestampLow, 5);
201
- const randBytes = new Uint8Array(10);
202
- crypto.getRandomValues(randBytes);
203
- const rand1 = randBytes[0] * 2 ** 32 + (randBytes[1] << 24 >>> 0) + (randBytes[2] << 16) + (randBytes[3] << 8) + randBytes[4];
204
- const rand2 = randBytes[5] * 2 ** 32 + (randBytes[6] << 24 >>> 0) + (randBytes[7] << 16) + (randBytes[8] << 8) + randBytes[9];
205
- const randPart = encodeBase32(rand1, 8) + encodeBase32(rand2, 8);
206
- return tsPart + randPart;
207
- }
208
-
209
- // src/tx/transaction.ts
210
- var TxContext = class {
211
- /** Stable id for this transaction; shared by all writes it performs. */
212
- txId = generateULID();
213
- /** @internal */
214
- _ops = [];
215
- /**
216
- * @internal — write log built up in Phase 2. Each entry records the
217
- * envelope captured BEFORE the write so a mid-batch failure can
218
- * restore prior state via `revertExecuted`. Side-effect writes (e.g.
219
- * recursive derivation outputs fired inside `Collection.put`) are
220
- * appended here in execution order so they roll back alongside the
221
- * main staged ops.
222
- */
223
- _executed = [];
224
- /** @internal */
225
- _db;
226
- /**
227
- * @internal — true when this TxContext was opened in amendment
228
- * mode. Toggles the lazy-`beginAmendment` + role-check path on first
229
- * `tx.vault(name)` and unlocks the post-Phase-2 invariant + audit run.
230
- */
231
- _amendment;
232
- /** @internal — vaults that have already had `beginAmendment` called. */
233
- _amendmentVaults = /* @__PURE__ */ new Map();
234
- /** @internal */
235
- constructor(db, amendment = false) {
236
- this._db = db;
237
- this._amendment = amendment;
238
- }
239
- /** Scope subsequent `collection()` calls to the named vault. */
240
- vault(name) {
241
- const v = this._db.vault(name);
242
- if (this._amendment && !this._amendmentVaults.has(name)) {
243
- const role = v.role;
244
- if (role !== "admin" && role !== "owner" && role !== "custodian") {
245
- throw new AmendmentForbiddenError(v.userId, role);
246
- }
247
- const reg = v._getGuardRegistry();
248
- if (reg === null) {
249
- throw new ValidationError(
250
- `Vault "${name}": amendment mode requires at least one guardStrategy registered via createNoydb({ guardStrategies }). Open the vault with guardStrategies before calling db.transaction({ amendment: true }).`
251
- );
252
- }
253
- reg.beginAmendment();
254
- this._amendmentVaults.set(name, v);
255
- }
256
- return new TxVault(this, v);
257
- }
258
- };
259
- var TxVault = class {
260
- /** @internal */
261
- _ctx;
262
- /** @internal */
263
- _vault;
264
- /** @internal */
265
- constructor(ctx, vault) {
266
- this._ctx = ctx;
267
- this._vault = vault;
268
- }
269
- /** Scope subsequent op calls to the named collection. */
270
- collection(name) {
271
- const c = this._vault.collection(name);
272
- return new TxCollection(this._ctx, this._vault, c, name);
273
- }
274
- };
275
- var TxCollection = class {
276
- /** @internal */
277
- _ctx;
278
- /** @internal */
279
- _vault;
280
- /** @internal */
281
- _coll;
282
- /** @internal */
283
- _name;
284
- /** @internal */
285
- constructor(ctx, vault, coll, name) {
286
- this._ctx = ctx;
287
- this._vault = vault;
288
- this._coll = coll;
289
- this._name = name;
290
- }
291
- /**
292
- * Read the current committed value, or the most-recently-staged
293
- * value from the same transaction if one exists.
294
- */
295
- async get(id) {
296
- for (let i = this._ctx._ops.length - 1; i >= 0; i--) {
297
- const op = this._ctx._ops[i];
298
- if (op.vaultName === this._vault.name && op.collectionName === this._name && op.id === id) {
299
- if (op.type === "delete") return null;
300
- return op.record;
301
- }
302
- }
303
- return this._coll.get(id);
304
- }
305
- /**
306
- * Stage a put. Does not write until the transaction body returns.
307
- * Supply `{ expectedVersion }` to enforce optimistic concurrency
308
- * during the commit pre-flight.
309
- */
310
- put(id, record, options) {
311
- const op = {
312
- type: "put",
313
- vaultName: this._vault.name,
314
- collectionName: this._name,
315
- id,
316
- record
317
- };
318
- if (options?.expectedVersion !== void 0) op.expectedVersion = options.expectedVersion;
319
- if (options?.reason !== void 0) op.reason = options.reason;
320
- this._ctx._ops.push(op);
321
- }
322
- /**
323
- * Stage a delete. Does not write until the transaction body returns.
324
- * Supply `{ expectedVersion }` to enforce optimistic concurrency
325
- * during the commit pre-flight.
326
- */
327
- delete(id, options) {
328
- const op = {
329
- type: "delete",
330
- vaultName: this._vault.name,
331
- collectionName: this._name,
332
- id
333
- };
334
- if (options?.expectedVersion !== void 0) op.expectedVersion = options.expectedVersion;
335
- this._ctx._ops.push(op);
336
- }
337
- };
338
- async function runTransaction(db, fn, options, txInvariants) {
339
- if (options?.amendment) {
340
- if (typeof options.reason !== "string" || options.reason.trim().length === 0) {
341
- throw new ValidationError(
342
- "db.transaction({ amendment: true }) requires a non-empty `reason` string."
343
- );
344
- }
345
- }
346
- const ctx = new TxContext(db, options?.amendment === true);
347
- const bodyResult = await fn(ctx);
348
- if (ctx._ops.length === 0) {
349
- if (ctx._amendment) {
350
- for (const v of ctx._amendmentVaults.values()) {
351
- const reg = v._getGuardRegistry();
352
- if (reg !== null) {
353
- reg.consumeChanges();
354
- reg.consumeMeta();
355
- }
356
- }
357
- }
358
- return bodyResult;
359
- }
360
- const priorEnvelopes = /* @__PURE__ */ new Map();
361
- const store = db._store;
362
- const invariants = txInvariants ?? [];
363
- const watchedScopes = new Set(invariants.map((i) => i.scope));
364
- const plainBefore = /* @__PURE__ */ new Map();
365
- for (const op of ctx._ops) {
366
- const key = keyOf(op);
367
- if (!priorEnvelopes.has(key)) {
368
- const env = await store.get(op.vaultName, op.collectionName, op.id);
369
- priorEnvelopes.set(key, env);
370
- }
371
- if (watchedScopes.has(op.collectionName) && !plainBefore.has(key)) {
372
- const prior = await db.vault(op.vaultName).collection(op.collectionName).get(op.id);
373
- plainBefore.set(key, prior ?? null);
374
- }
375
- if (op.expectedVersion !== void 0) {
376
- const env = priorEnvelopes.get(key) ?? null;
377
- const actual = env?._v ?? 0;
378
- if (actual !== op.expectedVersion) {
379
- throw new ConflictError(
380
- actual,
381
- `Transaction pre-flight: ${op.vaultName}/${op.collectionName}/${op.id} expected v${op.expectedVersion}, found v${actual}`
382
- );
383
- }
384
- }
385
- }
386
- db._setActiveTxContext(ctx);
387
- try {
388
- try {
389
- for (const op of ctx._ops) {
390
- const coll = db.vault(op.vaultName).collection(op.collectionName);
391
- const key = keyOf(op);
392
- const prior = priorEnvelopes.get(key) ?? null;
393
- ctx._executed.push({ op, priorEnvelope: prior });
394
- if (op.type === "put") {
395
- await coll.put(op.id, op.record, op.reason !== void 0 ? { reason: op.reason } : void 0);
396
- } else {
397
- await coll.delete(op.id);
398
- }
399
- }
400
- } catch (err) {
401
- await revertExecuted(ctx._executed, store, db);
402
- if (ctx._amendment) {
403
- for (const v of ctx._amendmentVaults.values()) {
404
- const reg = v._getGuardRegistry();
405
- if (reg !== null) {
406
- reg.consumeChanges();
407
- reg.consumeMeta();
408
- }
409
- }
410
- }
411
- throw err;
412
- }
413
- } finally {
414
- db._clearActiveTxContext(ctx);
415
- }
416
- if (ctx._amendment) {
417
- const { GuardExecutor: GuardExecutor2 } = await Promise.resolve().then(() => (init_executor(), executor_exports));
418
- try {
419
- for (const [vaultName, v] of ctx._amendmentVaults) {
420
- const registry = v._getGuardRegistry();
421
- if (registry === null) continue;
422
- const changesByCollection = registry.consumeChanges();
423
- const meta = registry.consumeMeta();
424
- if (changesByCollection.size === 0) continue;
425
- const readOnlyVault = v._getReadOnlyFacade();
426
- if (readOnlyVault === null) continue;
427
- const invariantsPassed = [];
428
- for (const [collection, changes] of changesByCollection) {
429
- const guards = registry.guardsFor(collection).filter((g) => g.amendment !== void 0);
430
- for (const guard of guards) {
431
- await GuardExecutor2.runInvariant(guard, changes, {
432
- existing: null,
433
- vault: readOnlyVault,
434
- userId: v.userId,
435
- role: v.role
436
- });
437
- }
438
- if (guards.length > 0) invariantsPassed.push(collection);
439
- }
440
- const ledger = v._getLedgerOrNull();
441
- if (ledger) {
442
- const role = v.role;
443
- const amendment = {
444
- reason: options.reason,
445
- role,
446
- changes: meta,
447
- invariantsPassed
448
- };
449
- await ledger.append({
450
- op: "amendment",
451
- collection: "",
452
- id: "",
453
- version: 0,
454
- actor: v.userId,
455
- // No payload to hash — the per-record entries already
456
- // captured `payloadHash` at their own append time. We use
457
- // a sha256 of the canonical reason string so the field is
458
- // populated with something deterministic and non-empty.
459
- payloadHash: "",
460
- amendment
461
- });
462
- }
463
- void vaultName;
464
- }
465
- } catch (err) {
466
- await revertExecuted(ctx._executed, store, db);
467
- throw err instanceof InvariantError ? err : new InvariantError(
468
- err instanceof Error ? err.message : `invariant violated: ${String(err)}`
469
- );
470
- }
471
- }
472
- if (invariants.length > 0) {
473
- const lastOp = /* @__PURE__ */ new Map();
474
- const order = [];
475
- for (const op of ctx._ops) {
476
- const key = keyOf(op);
477
- if (!lastOp.has(key)) order.push(key);
478
- lastOp.set(key, op);
479
- }
480
- const changesByScope = /* @__PURE__ */ new Map();
481
- const scopeVault = /* @__PURE__ */ new Map();
482
- for (const key of order) {
483
- const op = lastOp.get(key);
484
- if (!watchedScopes.has(op.collectionName)) continue;
485
- const before = plainBefore.get(key) ?? null;
486
- const after = op.type === "delete" ? null : op.record ?? null;
487
- const change = { before, after };
488
- const arr = changesByScope.get(op.collectionName);
489
- if (arr) arr.push(change);
490
- else changesByScope.set(op.collectionName, [change]);
491
- scopeVault.set(op.collectionName, op.vaultName);
492
- }
493
- try {
494
- for (const inv of invariants) {
495
- const changes = changesByScope.get(inv.scope);
496
- if (changes === void 0 || changes.length === 0) continue;
497
- const vaultName = scopeVault.get(inv.scope);
498
- const v = db.vault(vaultName);
499
- const facade = v._getReadOnlyFacade() ?? {
500
- collection(name) {
501
- const c = v.collection(name);
502
- return {
503
- get: (id) => c.get(id),
504
- list: () => c.list(),
505
- query: () => c.query()
506
- };
507
- }
508
- };
509
- const ctxForInv = {
510
- existing: null,
511
- vault: facade,
512
- userId: v.userId,
513
- role: v.role
514
- };
515
- await inv.check(changes, ctxForInv);
516
- }
517
- } catch (err) {
518
- await revertExecuted(ctx._executed, store, db);
519
- throw err instanceof InvariantError ? err : new InvariantError(
520
- err instanceof Error ? err.message : `invariant violated: ${String(err)}`
521
- );
522
- }
523
- }
524
- return bodyResult;
525
- }
526
- async function revertExecuted(executed, store, db) {
527
- for (const { op, priorEnvelope } of executed.slice().reverse()) {
528
- try {
529
- if (priorEnvelope) {
530
- await store.put(op.vaultName, op.collectionName, op.id, priorEnvelope);
531
- } else {
532
- await store.delete(op.vaultName, op.collectionName, op.id);
533
- }
534
- if (db) {
535
- const coll = db.vault(op.vaultName).collection(op.collectionName);
536
- await coll._invalidateCacheEntry(op.id);
537
- }
538
- } catch {
539
- }
540
- }
541
- }
542
- function keyOf(op) {
543
- return `${op.vaultName}\0${op.collectionName}\0${op.id}`;
544
- }
545
-
546
- // src/tx/dry-run.ts
547
- var SEP = " ";
548
- var keyOf2 = (op) => `${op.vaultName}${SEP}${op.collectionName}${SEP}${op.id}`;
549
- async function runDryRun(db, fn) {
550
- const ctx = new TxContext(db);
551
- await fn(ctx);
552
- const lastOp = /* @__PURE__ */ new Map();
553
- for (const op of ctx._ops) lastOp.set(keyOf2(op), op);
554
- const affected = [];
555
- const guardViolations = [];
556
- for (const op of lastOp.values()) {
557
- const v = db.vault(op.vaultName);
558
- const coll = v.collection(op.collectionName);
559
- const before = await coll.get(op.id);
560
- if (op.type === "delete") {
561
- affected.push({ vault: op.vaultName, op: "delete", collection: op.collectionName, docId: op.id, before, after: null });
562
- continue;
563
- }
564
- const after = op.record ?? null;
565
- affected.push({
566
- vault: op.vaultName,
567
- op: before === null ? "create" : "update",
568
- collection: op.collectionName,
569
- docId: op.id,
570
- before,
571
- after
572
- });
573
- const registry = v._getGuardRegistry();
574
- if (!registry) continue;
575
- const guards = registry.guardsFor(op.collectionName);
576
- if (guards.length === 0) continue;
577
- const facade = v._getReadOnlyFacade();
578
- if (!facade) continue;
579
- const gctx = { existing: before, vault: facade, userId: v.userId, role: v.role };
580
- try {
581
- await registry.runChecks(op.collectionName, after, gctx);
582
- const { GuardExecutor: GuardExecutor2 } = await Promise.resolve().then(() => (init_executor(), executor_exports));
583
- for (const g of guards) {
584
- await GuardExecutor2.checkFrozenFields(g, op.id, before, after);
585
- }
586
- } catch (err) {
587
- guardViolations.push({
588
- vault: op.vaultName,
589
- collection: op.collectionName,
590
- docId: op.id,
591
- message: err instanceof Error ? err.message : String(err)
592
- });
593
- }
594
- }
595
- return { affected, guardViolations };
596
- }
597
-
598
- // src/tx/active.ts
599
- function withTransactions(opts) {
600
- const invariants = opts?.invariants ?? [];
601
- return {
602
- runTransaction: (db, fn, options) => runTransaction(db, fn, options, invariants),
603
- runDryRun
604
- };
605
- }
606
- // Annotate the CommonJS export names for ESM import in node:
607
- 0 && (module.exports = {
608
- TxCollection,
609
- TxContext,
610
- TxVault,
611
- runTransaction,
612
- withTransactions
613
- });
614
- //# sourceMappingURL=index.cjs.map