doxum 0.1.21 → 0.1.23

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 (72) hide show
  1. package/README.md +35 -7
  2. package/dist/{advanced-FgdTwu5b.d.ts → advanced-CLJCWkHa.d.cts} +3 -3
  3. package/dist/{advanced-COFJtWMT.js → advanced-CRNHfJBu.js} +482 -446
  4. package/dist/advanced-CRNHfJBu.js.map +1 -0
  5. package/dist/{advanced-BRL5pN0y.cjs → advanced-Cle5g3B4.cjs} +615 -459
  6. package/dist/advanced-Cle5g3B4.cjs.map +1 -0
  7. package/dist/{advanced-DfKc7TZR.d.cts → advanced-d6J61er9.d.ts} +3 -3
  8. package/dist/advanced.cjs +1 -1
  9. package/dist/advanced.d.cts +1 -1
  10. package/dist/advanced.d.ts +1 -1
  11. package/dist/advanced.js +1 -1
  12. package/dist/context-BcLKGfq8.cjs +149 -0
  13. package/dist/context-BcLKGfq8.cjs.map +1 -0
  14. package/dist/context-DFEaDUv5.js +84 -0
  15. package/dist/context-DFEaDUv5.js.map +1 -0
  16. package/dist/{contract-CdmDHRUq.d.cts → contract-SYJFP0lM.d.cts} +62 -88
  17. package/dist/{contract-KG5XnQZt.d.ts → contract-ULPQmiEs.d.ts} +62 -88
  18. package/dist/driver-BD3DQOW6.cjs +382 -0
  19. package/dist/driver-BD3DQOW6.cjs.map +1 -0
  20. package/dist/{driver-CLYJOGDQ.js → driver-yFfvDMX5.js} +155 -26
  21. package/dist/driver-yFfvDMX5.js.map +1 -0
  22. package/dist/index.cjs +2370 -406
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +6 -5
  25. package/dist/index.d.ts +6 -5
  26. package/dist/index.js +2293 -330
  27. package/dist/index.js.map +1 -1
  28. package/dist/local-sync.cjs +5 -5
  29. package/dist/local-sync.cjs.map +1 -1
  30. package/dist/local-sync.d.cts +1 -1
  31. package/dist/local-sync.d.ts +1 -1
  32. package/dist/local-sync.js +2 -2
  33. package/dist/local-sync.js.map +1 -1
  34. package/dist/react.cjs +2 -69
  35. package/dist/react.cjs.map +1 -1
  36. package/dist/react.d.cts +0 -1
  37. package/dist/react.d.ts +1 -2
  38. package/dist/react.js +3 -70
  39. package/dist/react.js.map +1 -1
  40. package/package.json +1 -6
  41. package/skills/doxum-runtime/SKILL.md +7 -1
  42. package/skills/doxum-runtime/references/guide.en.md +17 -6
  43. package/skills/doxum-runtime/references/guide.zh-CN.md +15 -5
  44. package/skills/doxum-runtime/references/invariants.en.md +5 -3
  45. package/skills/doxum-runtime/references/invariants.zh-CN.md +4 -3
  46. package/skills/doxum-runtime/references/projections.en.md +5 -0
  47. package/skills/doxum-runtime/references/projections.zh-CN.md +5 -0
  48. package/dist/access-BeSV5ve-.js +0 -816
  49. package/dist/access-BeSV5ve-.js.map +0 -1
  50. package/dist/access-Bienf28h.cjs +0 -911
  51. package/dist/access-Bienf28h.cjs.map +0 -1
  52. package/dist/advanced-BRL5pN0y.cjs.map +0 -1
  53. package/dist/advanced-COFJtWMT.js.map +0 -1
  54. package/dist/driver-CLYJOGDQ.js.map +0 -1
  55. package/dist/driver-Djr3BVvo.cjs +0 -241
  56. package/dist/driver-Djr3BVvo.cjs.map +0 -1
  57. package/dist/integration-C4Isp8lJ.js +0 -26
  58. package/dist/integration-C4Isp8lJ.js.map +0 -1
  59. package/dist/integration-Z6MsfFI7.cjs +0 -31
  60. package/dist/integration-Z6MsfFI7.cjs.map +0 -1
  61. package/dist/integration.cjs +0 -12
  62. package/dist/integration.d.cts +0 -17
  63. package/dist/integration.d.ts +0 -17
  64. package/dist/integration.js +0 -4
  65. package/dist/issue-DjK1xp5K.cjs +0 -881
  66. package/dist/issue-DjK1xp5K.cjs.map +0 -1
  67. package/dist/issue-W0hT8u8D.js +0 -642
  68. package/dist/issue-W0hT8u8D.js.map +0 -1
  69. package/dist/notification-Bkjau6B6.js +0 -232
  70. package/dist/notification-Bkjau6B6.js.map +0 -1
  71. package/dist/notification-DJfouMEb.cjs +0 -309
  72. package/dist/notification-DJfouMEb.cjs.map +0 -1
@@ -0,0 +1,382 @@
1
+ const require_context = require("./context-BcLKGfq8.cjs");
2
+ //#region core/src/mutation/issue.ts
3
+ const at = (address, code, message) => Object.freeze({
4
+ source: "mutation",
5
+ code,
6
+ address: Object.freeze([...address]),
7
+ message
8
+ });
9
+ var MutationRejected = class extends Error {
10
+ constructor(issue) {
11
+ super(issue.message);
12
+ this.issue = issue;
13
+ }
14
+ };
15
+ const fail = (address, code, message) => {
16
+ throw new MutationRejected(at(address, code, message));
17
+ };
18
+ const invalidValue = (issue, address = issue.address) => fail(address, issue.code === "missing-validator" ? "invalid-value" : issue.code, issue.message);
19
+ //#endregion
20
+ //#region core/src/address/index.ts
21
+ var AddressIndex = class {
22
+ root = {
23
+ children: /* @__PURE__ */ new Map(),
24
+ values: /* @__PURE__ */ new Set()
25
+ };
26
+ add(address, value, member) {
27
+ let node = this.root;
28
+ for (let index = 0; index < address.length + (member === void 0 ? 0 : 1); index++) {
29
+ const segment = index < address.length ? address[index] : member;
30
+ let child = node.children.get(segment);
31
+ if (!child) {
32
+ child = {
33
+ children: /* @__PURE__ */ new Map(),
34
+ values: /* @__PURE__ */ new Set()
35
+ };
36
+ node.children.set(segment, child);
37
+ }
38
+ node = child;
39
+ }
40
+ node.values.add(value);
41
+ }
42
+ delete(address, value, member) {
43
+ const parents = [];
44
+ let node = this.root;
45
+ const segments = member === void 0 ? address : [...address, member];
46
+ for (const segment of segments) {
47
+ const child = node.children.get(segment);
48
+ if (!child) return;
49
+ parents.push(node);
50
+ node = child;
51
+ }
52
+ node.values.delete(value);
53
+ for (let index = segments.length - 1; index >= 0 && !node.values.size && !node.children.size; index--) {
54
+ node = parents[index];
55
+ node.children.delete(segments[index]);
56
+ }
57
+ }
58
+ exact(address) {
59
+ let node = this.root;
60
+ for (const segment of address) {
61
+ const child = node.children.get(segment);
62
+ if (!child) return void 0;
63
+ node = child;
64
+ }
65
+ return node.values;
66
+ }
67
+ hasAncestor(address, strict = false) {
68
+ let node = this.root;
69
+ for (let index = 0; index < address.length; index++) {
70
+ if (node.values.size) return true;
71
+ const child = node.children.get(address[index]);
72
+ if (!child) return false;
73
+ node = child;
74
+ }
75
+ return !strict && node.values.size > 0;
76
+ }
77
+ someAncestor(address, predicate) {
78
+ let node = this.root;
79
+ for (let index = 0;; index++) {
80
+ for (const value of node.values) if (predicate(value)) return true;
81
+ if (index === address.length) return false;
82
+ const child = node.children.get(address[index]);
83
+ if (!child) return false;
84
+ node = child;
85
+ }
86
+ }
87
+ overlaps(address) {
88
+ let node = this.root;
89
+ for (const segment of address) {
90
+ if (node.values.size) return true;
91
+ const child = node.children.get(segment);
92
+ if (!child) return false;
93
+ node = child;
94
+ }
95
+ return node.values.size > 0 || node.children.size > 0;
96
+ }
97
+ hasDescendant(address) {
98
+ let node = this.root;
99
+ for (const segment of address) {
100
+ const child = node.children.get(segment);
101
+ if (!child) return false;
102
+ node = child;
103
+ }
104
+ return node.values.size > 0 || node.children.size > 0;
105
+ }
106
+ query(visit, relation = "overlap") {
107
+ const visited = /* @__PURE__ */ new Set();
108
+ const subtrees = /* @__PURE__ */ new Set();
109
+ const values = (node) => {
110
+ if (visited.has(node)) return;
111
+ visited.add(node);
112
+ node.values.forEach(visit);
113
+ };
114
+ const descend = (current) => {
115
+ if (subtrees.has(current)) return;
116
+ subtrees.add(current);
117
+ values(current);
118
+ current.children.forEach(descend);
119
+ };
120
+ const terminal = (node) => relation === "ancestors" ? values(node) : descend(node);
121
+ return (address, members) => {
122
+ let node = this.root;
123
+ for (const segment of address) {
124
+ if (subtrees.has(node)) return;
125
+ if (relation !== "descendants") values(node);
126
+ const child = node.children.get(segment);
127
+ if (!child) return;
128
+ node = child;
129
+ }
130
+ if (!members) terminal(node);
131
+ else {
132
+ if (relation !== "descendants") values(node);
133
+ for (const member of members) {
134
+ const child = node.children.get(member.key);
135
+ if (child) terminal(child);
136
+ }
137
+ }
138
+ };
139
+ }
140
+ clear() {
141
+ this.root.values.clear();
142
+ this.root.children.clear();
143
+ }
144
+ };
145
+ //#endregion
146
+ //#region core/src/mutation/changes.ts
147
+ const validated = /* @__PURE__ */ new WeakSet();
148
+ const compareChanges = (a, b) => {
149
+ if (a.kind === "reset" || b.kind === "reset") return a.kind === b.kind ? 0 : a.kind === "reset" ? -1 : 1;
150
+ const length = Math.min(a.at.length, b.at.length);
151
+ for (let i = 0; i < length; i++) if (a.at[i] !== b.at[i]) return lexical(a.at[i], b.at[i]);
152
+ return a.at.length - b.at.length || lexical(a.kind, b.kind);
153
+ };
154
+ const publication = (changes) => {
155
+ const result = { changes };
156
+ validated.add(result);
157
+ return result;
158
+ };
159
+ /** Register complete recorder groups; unknown input is validated separately. */
160
+ const sealChanges = (changes) => {
161
+ changes.sort(compareChanges);
162
+ return publication(changes);
163
+ };
164
+ const keys = (value, expected) => Object.keys(value).every((key) => expected.includes(key));
165
+ const strings = (value) => {
166
+ if (!Array.isArray(value)) return false;
167
+ for (const item of value) if (typeof item !== "string") return false;
168
+ return true;
169
+ };
170
+ const order = (value) => strings(value) && new Set(value).size === value.length;
171
+ const transition = (value, key) => {
172
+ if (!require_context.isPlainObject(value) || typeof value[key] !== "string") return false;
173
+ if (value.kind === "added") return keys(value, [
174
+ "kind",
175
+ key,
176
+ "after"
177
+ ]) && Object.hasOwn(value, "after");
178
+ if (value.kind === "removed") return keys(value, [
179
+ "kind",
180
+ key,
181
+ "before"
182
+ ]) && Object.hasOwn(value, "before");
183
+ return value.kind === "updated" && keys(value, [
184
+ "kind",
185
+ key,
186
+ "before",
187
+ "after"
188
+ ]) && Object.hasOwn(value, "before") && Object.hasOwn(value, "after");
189
+ };
190
+ const lexical = (a, b) => a < b ? -1 : a === b ? 0 : 1;
191
+ /** The sole unknown ChangeSet boundary, including normalized logical-address conflicts. */
192
+ const decodeChanges = (input) => {
193
+ if (typeof input === "object" && input !== null && validated.has(input)) return input;
194
+ if (!require_context.isPlainObject(input) || !keys(input, ["changes"]) || !Array.isArray(input.changes)) return fail([], "invalid-changes", "Expected a ChangeSet.");
195
+ const result = [];
196
+ for (const entry of input.changes) {
197
+ if (!require_context.isPlainObject(entry)) return fail([], "invalid-changes", "Expected a change.");
198
+ if (entry.kind === "reset") {
199
+ if (input.changes.length !== 1 || !keys(entry, [
200
+ "kind",
201
+ "before",
202
+ "after"
203
+ ]) || !Object.hasOwn(entry, "before") || !Object.hasOwn(entry, "after")) return fail([], "invalid-changes", "A reset must be the only change and contain both values.");
204
+ return sealChanges([{
205
+ kind: "reset",
206
+ before: entry.before,
207
+ after: entry.after
208
+ }]);
209
+ }
210
+ if (!strings(entry.at)) return fail([], "invalid-changes", "Change addresses must contain strings.");
211
+ const at = entry.at;
212
+ if (entry.kind === "members" && keys(entry, [
213
+ "kind",
214
+ "at",
215
+ "members",
216
+ "order"
217
+ ]) && Array.isArray(entry.members) && (entry.members.length || Object.hasOwn(entry, "order"))) {
218
+ const seen = /* @__PURE__ */ new Set();
219
+ const members = [];
220
+ for (const member of entry.members) {
221
+ if (!transition(member, "key") || typeof member.key !== "string" || seen.has(member.key)) return fail(at, "invalid-changes", "Malformed or duplicate member transition.");
222
+ seen.add(member.key);
223
+ members.push({
224
+ ...member,
225
+ key: member.key
226
+ });
227
+ }
228
+ const change = {
229
+ kind: "members",
230
+ at,
231
+ members: members.sort((a, b) => lexical(a.key, b.key))
232
+ };
233
+ if (Object.hasOwn(entry, "order")) {
234
+ if (!require_context.isPlainObject(entry.order) || !keys(entry.order, ["before", "after"]) || !order(entry.order.before) || !order(entry.order.after)) return fail(at, "invalid-changes", "Malformed container order.");
235
+ result.push({
236
+ ...change,
237
+ order: {
238
+ before: entry.order.before,
239
+ after: entry.order.after
240
+ }
241
+ });
242
+ } else result.push(change);
243
+ } else if (entry.kind === "tree" && keys(entry, [
244
+ "kind",
245
+ "at",
246
+ "before",
247
+ "after",
248
+ "nodes"
249
+ ]) && (entry.before === null || typeof entry.before === "string") && (entry.after === null || typeof entry.after === "string") && Array.isArray(entry.nodes)) {
250
+ const seen = /* @__PURE__ */ new Set();
251
+ for (const node of entry.nodes) {
252
+ if (!transition(node, "id") || typeof node.id !== "string" || seen.has(node.id) || node.kind !== "added" && !require_context.validNode(node.before) || node.kind !== "removed" && !require_context.validNode(node.after)) return fail(at, "invalid-changes", "Malformed or duplicate tree transition.");
253
+ seen.add(node.id);
254
+ }
255
+ const nodes = entry.nodes;
256
+ result.push({
257
+ kind: "tree",
258
+ at,
259
+ before: entry.before,
260
+ after: entry.after,
261
+ nodes: [...nodes].sort((a, b) => lexical(a.id, b.id))
262
+ });
263
+ } else return fail(at, "invalid-changes", "Unknown or malformed change.");
264
+ }
265
+ return publication(normalizeChanges(result));
266
+ };
267
+ const normalizeChanges = (changes) => {
268
+ const sorted = changes.sort(compareChanges);
269
+ const groups = new AddressIndex();
270
+ const replacements = new AddressIndex();
271
+ const orders = new AddressIndex();
272
+ for (const change of sorted) {
273
+ if (change.kind === "reset") continue;
274
+ if (change.kind === "members") {
275
+ if (groups.exact(change.at)?.size) return fail(change.at, "invalid-changes", "Duplicate member group.");
276
+ groups.add(change.at, true);
277
+ if (change.order) {
278
+ if (replacements.hasAncestor(change.at)) return fail(change.at, "invalid-changes", "Overlapping container order.");
279
+ orders.add(change.at, true);
280
+ }
281
+ for (const member of change.members) {
282
+ const at = change.at.concat(member.key);
283
+ if (replacements.overlaps(at) || orders.hasDescendant(at)) return fail(at, "invalid-changes", "Overlapping member transitions.");
284
+ replacements.add(at, true);
285
+ }
286
+ } else if (change.kind === "tree") {
287
+ if (replacements.overlaps(change.at) || orders.hasDescendant(change.at)) return fail(change.at, "invalid-changes", "Overlapping tree transitions.");
288
+ replacements.add(change.at, true);
289
+ }
290
+ }
291
+ return sorted;
292
+ };
293
+ const changeCount = (changes) => {
294
+ let count = 0;
295
+ for (const change of changes.changes) count += change.kind === "members" ? change.members.length + (change.order ? 1 : 0) : change.kind === "tree" ? 1 + change.nodes.length : 1;
296
+ return count;
297
+ };
298
+ //#endregion
299
+ //#region core/src/runtime/driver.ts
300
+ const assertRuntimeWritable = (runtime, intent) => {
301
+ const context = require_context.contextOf(runtime);
302
+ if (context.bypassDepth === 0) context.driver?.assertWritable(intent);
303
+ };
304
+ const installRuntimeWriteDriver = (runtime, driver) => {
305
+ const context = require_context.contextOf(runtime);
306
+ if (context.driver) throw new Error("Doxum runtime already has a write driver.");
307
+ context.driver = driver;
308
+ let active = true;
309
+ return Object.freeze({
310
+ run: (run) => {
311
+ if (!active) throw new Error("Doxum runtime write driver is no longer active.");
312
+ context.bypassDepth += 1;
313
+ try {
314
+ return run();
315
+ } finally {
316
+ context.bypassDepth -= 1;
317
+ }
318
+ },
319
+ dispose: () => {
320
+ if (!active) return;
321
+ active = false;
322
+ if (context.driver === driver) context.driver = void 0;
323
+ }
324
+ });
325
+ };
326
+ //#endregion
327
+ Object.defineProperty(exports, "AddressIndex", {
328
+ enumerable: true,
329
+ get: function() {
330
+ return AddressIndex;
331
+ }
332
+ });
333
+ Object.defineProperty(exports, "MutationRejected", {
334
+ enumerable: true,
335
+ get: function() {
336
+ return MutationRejected;
337
+ }
338
+ });
339
+ Object.defineProperty(exports, "assertRuntimeWritable", {
340
+ enumerable: true,
341
+ get: function() {
342
+ return assertRuntimeWritable;
343
+ }
344
+ });
345
+ Object.defineProperty(exports, "changeCount", {
346
+ enumerable: true,
347
+ get: function() {
348
+ return changeCount;
349
+ }
350
+ });
351
+ Object.defineProperty(exports, "decodeChanges", {
352
+ enumerable: true,
353
+ get: function() {
354
+ return decodeChanges;
355
+ }
356
+ });
357
+ Object.defineProperty(exports, "fail", {
358
+ enumerable: true,
359
+ get: function() {
360
+ return fail;
361
+ }
362
+ });
363
+ Object.defineProperty(exports, "installRuntimeWriteDriver", {
364
+ enumerable: true,
365
+ get: function() {
366
+ return installRuntimeWriteDriver;
367
+ }
368
+ });
369
+ Object.defineProperty(exports, "invalidValue", {
370
+ enumerable: true,
371
+ get: function() {
372
+ return invalidValue;
373
+ }
374
+ });
375
+ Object.defineProperty(exports, "sealChanges", {
376
+ enumerable: true,
377
+ get: function() {
378
+ return sealChanges;
379
+ }
380
+ });
381
+
382
+ //# sourceMappingURL=driver-BD3DQOW6.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver-BD3DQOW6.cjs","names":["isPlainObject","issue.fail","contextOf"],"sources":["../core/src/mutation/issue.ts","../core/src/address/index.ts","../core/src/mutation/changes.ts","../core/src/runtime/driver.ts"],"sourcesContent":["import type { DocumentAddress } from '../schema';\nimport type { ParseIssue } from '../schema/value';\n\nexport type MutationIssueCode =\n | 'invalid-address'\n | 'invalid-value'\n | 'invalid-key'\n | 'invalid-changes'\n | 'baseline-mismatch'\n | 'required-field'\n | 'invalid-anchor'\n | 'duplicate-entity'\n | 'missing-entity'\n | 'invalid-collection'\n | 'invalid-list-keys'\n | 'invalid-list-key'\n | 'duplicate-list-item'\n | 'missing-list-item'\n | 'invalid-tree'\n | 'duplicate-tree-node'\n | 'missing-tree-parent'\n | 'invalid-tree-index'\n | 'missing-tree-node'\n | 'tree-cycle';\nexport type MutationIssue = {\n readonly source: 'mutation';\n readonly code: MutationIssueCode;\n readonly address: DocumentAddress;\n readonly message: string;\n};\nexport const at = (\n address: DocumentAddress,\n code: MutationIssueCode,\n message: string\n): MutationIssue =>\n Object.freeze({ source: 'mutation', code, address: Object.freeze([...address]), message });\nexport class MutationRejected extends Error {\n constructor(readonly issue: MutationIssue) {\n super(issue.message);\n }\n}\nexport const fail = (address: DocumentAddress, code: MutationIssueCode, message: string): never => {\n throw new MutationRejected(at(address, code, message));\n};\n\nexport const invalidValue = (issue: ParseIssue, address = issue.address): never =>\n fail(address, issue.code === 'missing-validator' ? 'invalid-value' : issue.code, issue.message);\n","import type { DocumentAddress } from '../schema';\n\ntype AddressIndexNode<T> = {\n readonly children: Map<string, AddressIndexNode<T>>;\n readonly values: Set<T>;\n};\n\nexport class AddressIndex<T> {\n private readonly root: AddressIndexNode<T> = { children: new Map(), values: new Set() };\n\n add(address: DocumentAddress, value: T, member?: string): void {\n let node = this.root;\n for (let index = 0; index < address.length + (member === undefined ? 0 : 1); index++) {\n const segment = index < address.length ? address[index] : member!;\n let child = node.children.get(segment);\n if (!child) {\n child = { children: new Map(), values: new Set() };\n node.children.set(segment, child);\n }\n node = child;\n }\n node.values.add(value);\n }\n\n delete(address: DocumentAddress, value: T, member?: string): void {\n const parents: AddressIndexNode<T>[] = [];\n let node = this.root;\n const segments = member === undefined ? address : [...address, member];\n for (const segment of segments) {\n const child = node.children.get(segment);\n if (!child) return;\n parents.push(node);\n node = child;\n }\n node.values.delete(value);\n for (\n let index = segments.length - 1;\n index >= 0 && !node.values.size && !node.children.size;\n index--\n ) {\n node = parents[index];\n node.children.delete(segments[index]);\n }\n }\n\n exact(address: DocumentAddress): ReadonlySet<T> | undefined {\n let node = this.root;\n for (const segment of address) {\n const child = node.children.get(segment);\n if (!child) return undefined;\n node = child;\n }\n return node.values;\n }\n\n hasAncestor(address: DocumentAddress, strict = false): boolean {\n let node = this.root;\n for (let index = 0; index < address.length; index++) {\n if (node.values.size) return true;\n const child = node.children.get(address[index]);\n if (!child) return false;\n node = child;\n }\n return !strict && node.values.size > 0;\n }\n\n someAncestor(address: DocumentAddress, predicate: (value: T) => boolean): boolean {\n let node = this.root;\n for (let index = 0; ; index++) {\n for (const value of node.values) if (predicate(value)) return true;\n if (index === address.length) return false;\n const child = node.children.get(address[index]);\n if (!child) return false;\n node = child;\n }\n }\n\n overlaps(address: DocumentAddress): boolean {\n let node = this.root;\n for (const segment of address) {\n if (node.values.size) return true;\n const child = node.children.get(segment);\n if (!child) return false;\n node = child;\n }\n return node.values.size > 0 || node.children.size > 0;\n }\n\n hasDescendant(address: DocumentAddress): boolean {\n let node = this.root;\n for (const segment of address) {\n const child = node.children.get(segment);\n if (!child) return false;\n node = child;\n }\n return node.values.size > 0 || node.children.size > 0;\n }\n\n query(\n visit: (value: T) => void,\n relation: 'overlap' | 'ancestors' | 'descendants' = 'overlap'\n ): (address: DocumentAddress, members?: readonly { readonly key: string }[]) => void {\n const visited = new Set<AddressIndexNode<T>>();\n const subtrees = new Set<AddressIndexNode<T>>();\n const values = (node: AddressIndexNode<T>) => {\n if (visited.has(node)) return;\n visited.add(node);\n node.values.forEach(visit);\n };\n const descend = (current: AddressIndexNode<T>): void => {\n if (subtrees.has(current)) return;\n subtrees.add(current);\n values(current);\n current.children.forEach(descend);\n };\n const terminal = (node: AddressIndexNode<T>) =>\n relation === 'ancestors' ? values(node) : descend(node);\n return (address, members) => {\n let node = this.root;\n for (const segment of address) {\n if (subtrees.has(node)) return;\n if (relation !== 'descendants') values(node);\n const child = node.children.get(segment);\n if (!child) return;\n node = child;\n }\n if (!members) terminal(node);\n else {\n if (relation !== 'descendants') values(node);\n for (const member of members) {\n const child = node.children.get(member.key);\n if (child) terminal(child);\n }\n }\n };\n }\n\n clear(): void {\n this.root.values.clear();\n this.root.children.clear();\n }\n}\n","import type { Change, ChangeSet, MemberChange, ValueTransition } from '../changes';\nimport { AddressIndex } from '../address/index';\nimport { isPlainObject } from '../value/record';\nimport * as issue from './issue';\nimport * as tree from '../tree/topology';\n\nconst validated = new WeakSet<ChangeSet>();\n\nconst compareChanges = (a: Change, b: Change): number => {\n if (a.kind === 'reset' || b.kind === 'reset')\n return a.kind === b.kind ? 0 : a.kind === 'reset' ? -1 : 1;\n const length = Math.min(a.at.length, b.at.length);\n for (let i = 0; i < length; i++) if (a.at[i] !== b.at[i]) return lexical(a.at[i], b.at[i]);\n return a.at.length - b.at.length || lexical(a.kind, b.kind);\n};\n\nconst publication = (changes: Change[]): ChangeSet => {\n const result = { changes };\n validated.add(result);\n return result;\n};\n\n/** Register complete recorder groups; unknown input is validated separately. */\nexport const sealChanges = (changes: Change[]): ChangeSet => {\n changes.sort(compareChanges);\n return publication(changes);\n};\n\nconst keys = (value: Record<string, unknown>, expected: readonly string[]) =>\n Object.keys(value).every(key => expected.includes(key));\nconst strings = (value: unknown): value is readonly string[] => {\n if (!Array.isArray(value)) return false;\n for (const item of value) if (typeof item !== 'string') return false;\n return true;\n};\nconst order = (value: unknown): value is readonly string[] =>\n strings(value) && new Set(value).size === value.length;\nconst transition = (\n value: unknown,\n key: 'key' | 'id'\n): value is ValueTransition & Record<string, unknown> => {\n if (!isPlainObject(value) || typeof value[key] !== 'string') return false;\n if (value.kind === 'added')\n return keys(value, ['kind', key, 'after']) && Object.hasOwn(value, 'after');\n if (value.kind === 'removed')\n return keys(value, ['kind', key, 'before']) && Object.hasOwn(value, 'before');\n return (\n value.kind === 'updated' &&\n keys(value, ['kind', key, 'before', 'after']) &&\n Object.hasOwn(value, 'before') &&\n Object.hasOwn(value, 'after')\n );\n};\nconst lexical = (a: string, b: string) => (a < b ? -1 : a === b ? 0 : 1);\n\n/** The sole unknown ChangeSet boundary, including normalized logical-address conflicts. */\nexport const decodeChanges = (input: unknown): ChangeSet => {\n if (typeof input === 'object' && input !== null && validated.has(input as ChangeSet))\n return input as ChangeSet;\n if (!isPlainObject(input) || !keys(input, ['changes']) || !Array.isArray(input.changes))\n return issue.fail([], 'invalid-changes', 'Expected a ChangeSet.');\n const result: Change[] = [];\n for (const entry of input.changes) {\n if (!isPlainObject(entry)) return issue.fail([], 'invalid-changes', 'Expected a change.');\n if (entry.kind === 'reset') {\n if (\n input.changes.length !== 1 ||\n !keys(entry, ['kind', 'before', 'after']) ||\n !Object.hasOwn(entry, 'before') ||\n !Object.hasOwn(entry, 'after')\n )\n return issue.fail(\n [],\n 'invalid-changes',\n 'A reset must be the only change and contain both values.'\n );\n return sealChanges([{ kind: 'reset', before: entry.before, after: entry.after }]);\n }\n if (!strings(entry.at))\n return issue.fail([], 'invalid-changes', 'Change addresses must contain strings.');\n const at = entry.at;\n if (\n entry.kind === 'members' &&\n keys(entry, ['kind', 'at', 'members', 'order']) &&\n Array.isArray(entry.members) &&\n (entry.members.length || Object.hasOwn(entry, 'order'))\n ) {\n const seen = new Set<string>();\n const members: MemberChange[] = [];\n for (const member of entry.members) {\n if (!transition(member, 'key') || typeof member.key !== 'string' || seen.has(member.key))\n return issue.fail(at, 'invalid-changes', 'Malformed or duplicate member transition.');\n seen.add(member.key);\n members.push({ ...member, key: member.key });\n }\n const change: Extract<Change, { kind: 'members' }> = {\n kind: 'members',\n at,\n members: members.sort((a, b) => lexical(a.key, b.key)),\n };\n if (Object.hasOwn(entry, 'order')) {\n if (\n !isPlainObject(entry.order) ||\n !keys(entry.order, ['before', 'after']) ||\n !order(entry.order.before) ||\n !order(entry.order.after)\n )\n return issue.fail(at, 'invalid-changes', 'Malformed container order.');\n result.push({ ...change, order: { before: entry.order.before, after: entry.order.after } });\n } else result.push(change);\n } else if (\n entry.kind === 'tree' &&\n keys(entry, ['kind', 'at', 'before', 'after', 'nodes']) &&\n (entry.before === null || typeof entry.before === 'string') &&\n (entry.after === null || typeof entry.after === 'string') &&\n Array.isArray(entry.nodes)\n ) {\n const seen = new Set<string>();\n for (const node of entry.nodes) {\n if (\n !transition(node, 'id') ||\n typeof node.id !== 'string' ||\n seen.has(node.id) ||\n (node.kind !== 'added' && !tree.validNode(node.before)) ||\n (node.kind !== 'removed' && !tree.validNode(node.after))\n )\n return issue.fail(at, 'invalid-changes', 'Malformed or duplicate tree transition.');\n seen.add(node.id);\n }\n const nodes = entry.nodes as Extract<Change, { kind: 'tree' }>['nodes'];\n result.push({\n kind: 'tree',\n at,\n before: entry.before,\n after: entry.after,\n nodes: [...nodes].sort((a, b) => lexical(a.id, b.id)),\n });\n } else return issue.fail(at, 'invalid-changes', 'Unknown or malformed change.');\n }\n return publication(normalizeChanges(result));\n};\n\nconst normalizeChanges = (changes: Change[]): Change[] => {\n const sorted = changes.sort(compareChanges);\n const groups = new AddressIndex<true>();\n const replacements = new AddressIndex<true>();\n const orders = new AddressIndex<true>();\n for (const change of sorted) {\n if (change.kind === 'reset') continue;\n if (change.kind === 'members') {\n if (groups.exact(change.at)?.size)\n return issue.fail(change.at, 'invalid-changes', 'Duplicate member group.');\n groups.add(change.at, true);\n if (change.order) {\n if (replacements.hasAncestor(change.at))\n return issue.fail(change.at, 'invalid-changes', 'Overlapping container order.');\n orders.add(change.at, true);\n }\n for (const member of change.members) {\n const at = change.at.concat(member.key);\n if (replacements.overlaps(at) || orders.hasDescendant(at))\n return issue.fail(at, 'invalid-changes', 'Overlapping member transitions.');\n replacements.add(at, true);\n }\n } else if (change.kind === 'tree') {\n if (replacements.overlaps(change.at) || orders.hasDescendant(change.at))\n return issue.fail(change.at, 'invalid-changes', 'Overlapping tree transitions.');\n replacements.add(change.at, true);\n }\n }\n return sorted;\n};\n\nexport const changeCount = (changes: ChangeSet): number => {\n let count = 0;\n for (const change of changes.changes)\n count +=\n change.kind === 'members'\n ? change.members.length + (change.order ? 1 : 0)\n : change.kind === 'tree'\n ? 1 + change.nodes.length\n : 1;\n return count;\n};\n","import type { CommitSource, DocumentRuntime } from './contract';\nimport type { ObjectNode } from '../schema';\nimport { contextOf } from './context';\n\nexport type RuntimeWriteIntent =\n | { readonly kind: 'update'; readonly source: Extract<CommitSource, 'local' | 'system'> }\n | { readonly kind: 'apply'; readonly source: CommitSource }\n | { readonly kind: 'replace'; readonly source: Extract<CommitSource, 'system' | 'remote'> };\n\nexport type RuntimeWriteDriver = {\n readonly assertWritable: (intent: RuntimeWriteIntent) => void;\n};\n\nexport type RuntimeWriteDriverLease = {\n readonly run: <TResult>(run: () => TResult) => TResult;\n readonly dispose: () => void;\n};\n\nexport const assertRuntimeWritable = (runtime: object, intent: RuntimeWriteIntent): void => {\n const context = contextOf(runtime);\n if (context.bypassDepth === 0) context.driver?.assertWritable(intent);\n};\n\nexport const installRuntimeWriteDriver = <TSchema extends ObjectNode>(\n runtime: DocumentRuntime<TSchema>,\n driver: RuntimeWriteDriver\n): RuntimeWriteDriverLease => {\n const context = contextOf(runtime);\n if (context.driver) throw new Error('Doxum runtime already has a write driver.');\n context.driver = driver;\n let active = true;\n return Object.freeze({\n run: <TResult>(run: () => TResult): TResult => {\n if (!active) throw new Error('Doxum runtime write driver is no longer active.');\n context.bypassDepth += 1;\n try {\n return run();\n } finally {\n context.bypassDepth -= 1;\n }\n },\n dispose: (): void => {\n if (!active) return;\n active = false;\n if (context.driver === driver) context.driver = undefined;\n },\n });\n};\n"],"mappings":"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"}
@@ -1,4 +1,148 @@
1
- import { S as validNode, i as AddressIndex, n as fail, w as isPlainObject } from "./issue-W0hT8u8D.js";
1
+ import { n as contextOf, s as validNode, u as isPlainObject } from "./context-DFEaDUv5.js";
2
+ //#region core/src/mutation/issue.ts
3
+ const at = (address, code, message) => Object.freeze({
4
+ source: "mutation",
5
+ code,
6
+ address: Object.freeze([...address]),
7
+ message
8
+ });
9
+ var MutationRejected = class extends Error {
10
+ constructor(issue) {
11
+ super(issue.message);
12
+ this.issue = issue;
13
+ }
14
+ };
15
+ const fail = (address, code, message) => {
16
+ throw new MutationRejected(at(address, code, message));
17
+ };
18
+ const invalidValue = (issue, address = issue.address) => fail(address, issue.code === "missing-validator" ? "invalid-value" : issue.code, issue.message);
19
+ //#endregion
20
+ //#region core/src/address/index.ts
21
+ var AddressIndex = class {
22
+ root = {
23
+ children: /* @__PURE__ */ new Map(),
24
+ values: /* @__PURE__ */ new Set()
25
+ };
26
+ add(address, value, member) {
27
+ let node = this.root;
28
+ for (let index = 0; index < address.length + (member === void 0 ? 0 : 1); index++) {
29
+ const segment = index < address.length ? address[index] : member;
30
+ let child = node.children.get(segment);
31
+ if (!child) {
32
+ child = {
33
+ children: /* @__PURE__ */ new Map(),
34
+ values: /* @__PURE__ */ new Set()
35
+ };
36
+ node.children.set(segment, child);
37
+ }
38
+ node = child;
39
+ }
40
+ node.values.add(value);
41
+ }
42
+ delete(address, value, member) {
43
+ const parents = [];
44
+ let node = this.root;
45
+ const segments = member === void 0 ? address : [...address, member];
46
+ for (const segment of segments) {
47
+ const child = node.children.get(segment);
48
+ if (!child) return;
49
+ parents.push(node);
50
+ node = child;
51
+ }
52
+ node.values.delete(value);
53
+ for (let index = segments.length - 1; index >= 0 && !node.values.size && !node.children.size; index--) {
54
+ node = parents[index];
55
+ node.children.delete(segments[index]);
56
+ }
57
+ }
58
+ exact(address) {
59
+ let node = this.root;
60
+ for (const segment of address) {
61
+ const child = node.children.get(segment);
62
+ if (!child) return void 0;
63
+ node = child;
64
+ }
65
+ return node.values;
66
+ }
67
+ hasAncestor(address, strict = false) {
68
+ let node = this.root;
69
+ for (let index = 0; index < address.length; index++) {
70
+ if (node.values.size) return true;
71
+ const child = node.children.get(address[index]);
72
+ if (!child) return false;
73
+ node = child;
74
+ }
75
+ return !strict && node.values.size > 0;
76
+ }
77
+ someAncestor(address, predicate) {
78
+ let node = this.root;
79
+ for (let index = 0;; index++) {
80
+ for (const value of node.values) if (predicate(value)) return true;
81
+ if (index === address.length) return false;
82
+ const child = node.children.get(address[index]);
83
+ if (!child) return false;
84
+ node = child;
85
+ }
86
+ }
87
+ overlaps(address) {
88
+ let node = this.root;
89
+ for (const segment of address) {
90
+ if (node.values.size) return true;
91
+ const child = node.children.get(segment);
92
+ if (!child) return false;
93
+ node = child;
94
+ }
95
+ return node.values.size > 0 || node.children.size > 0;
96
+ }
97
+ hasDescendant(address) {
98
+ let node = this.root;
99
+ for (const segment of address) {
100
+ const child = node.children.get(segment);
101
+ if (!child) return false;
102
+ node = child;
103
+ }
104
+ return node.values.size > 0 || node.children.size > 0;
105
+ }
106
+ query(visit, relation = "overlap") {
107
+ const visited = /* @__PURE__ */ new Set();
108
+ const subtrees = /* @__PURE__ */ new Set();
109
+ const values = (node) => {
110
+ if (visited.has(node)) return;
111
+ visited.add(node);
112
+ node.values.forEach(visit);
113
+ };
114
+ const descend = (current) => {
115
+ if (subtrees.has(current)) return;
116
+ subtrees.add(current);
117
+ values(current);
118
+ current.children.forEach(descend);
119
+ };
120
+ const terminal = (node) => relation === "ancestors" ? values(node) : descend(node);
121
+ return (address, members) => {
122
+ let node = this.root;
123
+ for (const segment of address) {
124
+ if (subtrees.has(node)) return;
125
+ if (relation !== "descendants") values(node);
126
+ const child = node.children.get(segment);
127
+ if (!child) return;
128
+ node = child;
129
+ }
130
+ if (!members) terminal(node);
131
+ else {
132
+ if (relation !== "descendants") values(node);
133
+ for (const member of members) {
134
+ const child = node.children.get(member.key);
135
+ if (child) terminal(child);
136
+ }
137
+ }
138
+ };
139
+ }
140
+ clear() {
141
+ this.root.values.clear();
142
+ this.root.children.clear();
143
+ }
144
+ };
145
+ //#endregion
2
146
  //#region core/src/mutation/changes.ts
3
147
  const validated = /* @__PURE__ */ new WeakSet();
4
148
  const compareChanges = (a, b) => {
@@ -153,48 +297,33 @@ const changeCount = (changes) => {
153
297
  };
154
298
  //#endregion
155
299
  //#region core/src/runtime/driver.ts
156
- const states = /* @__PURE__ */ new WeakMap();
157
- const stateOf = (runtime) => {
158
- const state = states.get(runtime);
159
- if (!state) throw new Error("Unknown Doxum runtime.");
160
- return state;
161
- };
162
- const bindRuntimeDriver = (runtime) => {
163
- states.set(runtime, {
164
- driver: void 0,
165
- bypassDepth: 0
166
- });
167
- };
168
300
  const assertRuntimeWritable = (runtime, intent) => {
169
- const state = stateOf(runtime);
170
- if (state.bypassDepth === 0) state.driver?.assertWritable(intent);
301
+ const context = contextOf(runtime);
302
+ if (context.bypassDepth === 0) context.driver?.assertWritable(intent);
171
303
  };
172
304
  const installRuntimeWriteDriver = (runtime, driver) => {
173
- const state = stateOf(runtime);
174
- if (state.driver) throw new Error("Doxum runtime already has a write driver.");
175
- state.driver = driver;
305
+ const context = contextOf(runtime);
306
+ if (context.driver) throw new Error("Doxum runtime already has a write driver.");
307
+ context.driver = driver;
176
308
  let active = true;
177
309
  return Object.freeze({
178
310
  run: (run) => {
179
311
  if (!active) throw new Error("Doxum runtime write driver is no longer active.");
180
- state.bypassDepth += 1;
312
+ context.bypassDepth += 1;
181
313
  try {
182
314
  return run();
183
315
  } finally {
184
- state.bypassDepth -= 1;
316
+ context.bypassDepth -= 1;
185
317
  }
186
318
  },
187
319
  dispose: () => {
188
320
  if (!active) return;
189
321
  active = false;
190
- if (state.driver === driver) state.driver = void 0;
322
+ if (context.driver === driver) context.driver = void 0;
191
323
  }
192
324
  });
193
325
  };
194
- const disposeRuntimeDriver = (runtime) => {
195
- states.delete(runtime);
196
- };
197
326
  //#endregion
198
- export { changeCount as a, installRuntimeWriteDriver as i, bindRuntimeDriver as n, decodeChanges as o, disposeRuntimeDriver as r, sealChanges as s, assertRuntimeWritable as t };
327
+ export { sealChanges as a, fail as c, decodeChanges as i, invalidValue as l, installRuntimeWriteDriver as n, AddressIndex as o, changeCount as r, MutationRejected as s, assertRuntimeWritable as t };
199
328
 
200
- //# sourceMappingURL=driver-CLYJOGDQ.js.map
329
+ //# sourceMappingURL=driver-yFfvDMX5.js.map