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.
- package/README.md +35 -7
- package/dist/{advanced-FgdTwu5b.d.ts → advanced-CLJCWkHa.d.cts} +3 -3
- package/dist/{advanced-COFJtWMT.js → advanced-CRNHfJBu.js} +482 -446
- package/dist/advanced-CRNHfJBu.js.map +1 -0
- package/dist/{advanced-BRL5pN0y.cjs → advanced-Cle5g3B4.cjs} +615 -459
- package/dist/advanced-Cle5g3B4.cjs.map +1 -0
- package/dist/{advanced-DfKc7TZR.d.cts → advanced-d6J61er9.d.ts} +3 -3
- package/dist/advanced.cjs +1 -1
- package/dist/advanced.d.cts +1 -1
- package/dist/advanced.d.ts +1 -1
- package/dist/advanced.js +1 -1
- package/dist/context-BcLKGfq8.cjs +149 -0
- package/dist/context-BcLKGfq8.cjs.map +1 -0
- package/dist/context-DFEaDUv5.js +84 -0
- package/dist/context-DFEaDUv5.js.map +1 -0
- package/dist/{contract-CdmDHRUq.d.cts → contract-SYJFP0lM.d.cts} +62 -88
- package/dist/{contract-KG5XnQZt.d.ts → contract-ULPQmiEs.d.ts} +62 -88
- package/dist/driver-BD3DQOW6.cjs +382 -0
- package/dist/driver-BD3DQOW6.cjs.map +1 -0
- package/dist/{driver-CLYJOGDQ.js → driver-yFfvDMX5.js} +155 -26
- package/dist/driver-yFfvDMX5.js.map +1 -0
- package/dist/index.cjs +2370 -406
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -5
- package/dist/index.d.ts +6 -5
- package/dist/index.js +2293 -330
- package/dist/index.js.map +1 -1
- package/dist/local-sync.cjs +5 -5
- package/dist/local-sync.cjs.map +1 -1
- package/dist/local-sync.d.cts +1 -1
- package/dist/local-sync.d.ts +1 -1
- package/dist/local-sync.js +2 -2
- package/dist/local-sync.js.map +1 -1
- package/dist/react.cjs +2 -69
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +0 -1
- package/dist/react.d.ts +1 -2
- package/dist/react.js +3 -70
- package/dist/react.js.map +1 -1
- package/package.json +1 -6
- package/skills/doxum-runtime/SKILL.md +7 -1
- package/skills/doxum-runtime/references/guide.en.md +17 -6
- package/skills/doxum-runtime/references/guide.zh-CN.md +15 -5
- package/skills/doxum-runtime/references/invariants.en.md +5 -3
- package/skills/doxum-runtime/references/invariants.zh-CN.md +4 -3
- package/skills/doxum-runtime/references/projections.en.md +5 -0
- package/skills/doxum-runtime/references/projections.zh-CN.md +5 -0
- package/dist/access-BeSV5ve-.js +0 -816
- package/dist/access-BeSV5ve-.js.map +0 -1
- package/dist/access-Bienf28h.cjs +0 -911
- package/dist/access-Bienf28h.cjs.map +0 -1
- package/dist/advanced-BRL5pN0y.cjs.map +0 -1
- package/dist/advanced-COFJtWMT.js.map +0 -1
- package/dist/driver-CLYJOGDQ.js.map +0 -1
- package/dist/driver-Djr3BVvo.cjs +0 -241
- package/dist/driver-Djr3BVvo.cjs.map +0 -1
- package/dist/integration-C4Isp8lJ.js +0 -26
- package/dist/integration-C4Isp8lJ.js.map +0 -1
- package/dist/integration-Z6MsfFI7.cjs +0 -31
- package/dist/integration-Z6MsfFI7.cjs.map +0 -1
- package/dist/integration.cjs +0 -12
- package/dist/integration.d.cts +0 -17
- package/dist/integration.d.ts +0 -17
- package/dist/integration.js +0 -4
- package/dist/issue-DjK1xp5K.cjs +0 -881
- package/dist/issue-DjK1xp5K.cjs.map +0 -1
- package/dist/issue-W0hT8u8D.js +0 -642
- package/dist/issue-W0hT8u8D.js.map +0 -1
- package/dist/notification-Bkjau6B6.js +0 -232
- package/dist/notification-Bkjau6B6.js.map +0 -1
- package/dist/notification-DJfouMEb.cjs +0 -309
- 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":";;AA8BA,MAAa,MACX,SACA,MACA,YAEA,OAAO,OAAO;CAAE,QAAQ;CAAY;CAAM,SAAS,OAAO,OAAO,CAAC,GAAG,QAAQ,CAAC;CAAE;CAAS,CAAC;AAC5F,IAAa,mBAAb,cAAsC,MAAM;CAC1C,YAAY,OAA+B;AACzC,QAAM,MAAM,QAAQ;AADD,OAAA,QAAA;;;AAIvB,MAAa,QAAQ,SAA0B,MAAyB,YAA2B;AACjG,OAAM,IAAI,iBAAiB,GAAG,SAAS,MAAM,QAAQ,CAAC;;AAGxD,MAAa,gBAAgB,OAAmB,UAAU,MAAM,YAC9D,KAAK,SAAS,MAAM,SAAS,sBAAsB,kBAAkB,MAAM,MAAM,MAAM,QAAQ;;;ACvCjG,IAAa,eAAb,MAA6B;CAC3B,OAA6C;EAAE,0BAAU,IAAI,KAAK;EAAE,wBAAQ,IAAI,KAAK;EAAE;CAEvF,IAAI,SAA0B,OAAU,QAAuB;EAC7D,IAAI,OAAO,KAAK;AAChB,OAAK,IAAI,QAAQ,GAAG,QAAQ,QAAQ,UAAU,WAAW,KAAA,IAAY,IAAI,IAAI,SAAS;GACpF,MAAM,UAAU,QAAQ,QAAQ,SAAS,QAAQ,SAAS;GAC1D,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ;AACtC,OAAI,CAAC,OAAO;AACV,YAAQ;KAAE,0BAAU,IAAI,KAAK;KAAE,wBAAQ,IAAI,KAAK;KAAE;AAClD,SAAK,SAAS,IAAI,SAAS,MAAM;;AAEnC,UAAO;;AAET,OAAK,OAAO,IAAI,MAAM;;CAGxB,OAAO,SAA0B,OAAU,QAAuB;EAChE,MAAM,UAAiC,EAAE;EACzC,IAAI,OAAO,KAAK;EAChB,MAAM,WAAW,WAAW,KAAA,IAAY,UAAU,CAAC,GAAG,SAAS,OAAO;AACtE,OAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,QAAQ,KAAK,SAAS,IAAI,QAAQ;AACxC,OAAI,CAAC,MAAO;AACZ,WAAQ,KAAK,KAAK;AAClB,UAAO;;AAET,OAAK,OAAO,OAAO,MAAM;AACzB,OACE,IAAI,QAAQ,SAAS,SAAS,GAC9B,SAAS,KAAK,CAAC,KAAK,OAAO,QAAQ,CAAC,KAAK,SAAS,MAClD,SACA;AACA,UAAO,QAAQ;AACf,QAAK,SAAS,OAAO,SAAS,OAAO;;;CAIzC,MAAM,SAAsD;EAC1D,IAAI,OAAO,KAAK;AAChB,OAAK,MAAM,WAAW,SAAS;GAC7B,MAAM,QAAQ,KAAK,SAAS,IAAI,QAAQ;AACxC,OAAI,CAAC,MAAO,QAAO,KAAA;AACnB,UAAO;;AAET,SAAO,KAAK;;CAGd,YAAY,SAA0B,SAAS,OAAgB;EAC7D,IAAI,OAAO,KAAK;AAChB,OAAK,IAAI,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS;AACnD,OAAI,KAAK,OAAO,KAAM,QAAO;GAC7B,MAAM,QAAQ,KAAK,SAAS,IAAI,QAAQ,OAAO;AAC/C,OAAI,CAAC,MAAO,QAAO;AACnB,UAAO;;AAET,SAAO,CAAC,UAAU,KAAK,OAAO,OAAO;;CAGvC,aAAa,SAA0B,WAA2C;EAChF,IAAI,OAAO,KAAK;AAChB,OAAK,IAAI,QAAQ,IAAK,SAAS;AAC7B,QAAK,MAAM,SAAS,KAAK,OAAQ,KAAI,UAAU,MAAM,CAAE,QAAO;AAC9D,OAAI,UAAU,QAAQ,OAAQ,QAAO;GACrC,MAAM,QAAQ,KAAK,SAAS,IAAI,QAAQ,OAAO;AAC/C,OAAI,CAAC,MAAO,QAAO;AACnB,UAAO;;;CAIX,SAAS,SAAmC;EAC1C,IAAI,OAAO,KAAK;AAChB,OAAK,MAAM,WAAW,SAAS;AAC7B,OAAI,KAAK,OAAO,KAAM,QAAO;GAC7B,MAAM,QAAQ,KAAK,SAAS,IAAI,QAAQ;AACxC,OAAI,CAAC,MAAO,QAAO;AACnB,UAAO;;AAET,SAAO,KAAK,OAAO,OAAO,KAAK,KAAK,SAAS,OAAO;;CAGtD,cAAc,SAAmC;EAC/C,IAAI,OAAO,KAAK;AAChB,OAAK,MAAM,WAAW,SAAS;GAC7B,MAAM,QAAQ,KAAK,SAAS,IAAI,QAAQ;AACxC,OAAI,CAAC,MAAO,QAAO;AACnB,UAAO;;AAET,SAAO,KAAK,OAAO,OAAO,KAAK,KAAK,SAAS,OAAO;;CAGtD,MACE,OACA,WAAoD,WAC+B;EACnF,MAAM,0BAAU,IAAI,KAA0B;EAC9C,MAAM,2BAAW,IAAI,KAA0B;EAC/C,MAAM,UAAU,SAA8B;AAC5C,OAAI,QAAQ,IAAI,KAAK,CAAE;AACvB,WAAQ,IAAI,KAAK;AACjB,QAAK,OAAO,QAAQ,MAAM;;EAE5B,MAAM,WAAW,YAAuC;AACtD,OAAI,SAAS,IAAI,QAAQ,CAAE;AAC3B,YAAS,IAAI,QAAQ;AACrB,UAAO,QAAQ;AACf,WAAQ,SAAS,QAAQ,QAAQ;;EAEnC,MAAM,YAAY,SAChB,aAAa,cAAc,OAAO,KAAK,GAAG,QAAQ,KAAK;AACzD,UAAQ,SAAS,YAAY;GAC3B,IAAI,OAAO,KAAK;AAChB,QAAK,MAAM,WAAW,SAAS;AAC7B,QAAI,SAAS,IAAI,KAAK,CAAE;AACxB,QAAI,aAAa,cAAe,QAAO,KAAK;IAC5C,MAAM,QAAQ,KAAK,SAAS,IAAI,QAAQ;AACxC,QAAI,CAAC,MAAO;AACZ,WAAO;;AAET,OAAI,CAAC,QAAS,UAAS,KAAK;QACvB;AACH,QAAI,aAAa,cAAe,QAAO,KAAK;AAC5C,SAAK,MAAM,UAAU,SAAS;KAC5B,MAAM,QAAQ,KAAK,SAAS,IAAI,OAAO,IAAI;AAC3C,SAAI,MAAO,UAAS,MAAM;;;;;CAMlC,QAAc;AACZ,OAAK,KAAK,OAAO,OAAO;AACxB,OAAK,KAAK,SAAS,OAAO;;;;;ACrI9B,MAAM,4BAAY,IAAI,SAAoB;AAE1C,MAAM,kBAAkB,GAAW,MAAsB;AACvD,KAAI,EAAE,SAAS,WAAW,EAAE,SAAS,QACnC,QAAO,EAAE,SAAS,EAAE,OAAO,IAAI,EAAE,SAAS,UAAU,KAAK;CAC3D,MAAM,SAAS,KAAK,IAAI,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO;AACjD,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,IAAK,KAAI,EAAE,GAAG,OAAO,EAAE,GAAG,GAAI,QAAO,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG;AAC1F,QAAO,EAAE,GAAG,SAAS,EAAE,GAAG,UAAU,QAAQ,EAAE,MAAM,EAAE,KAAK;;AAG7D,MAAM,eAAe,YAAiC;CACpD,MAAM,SAAS,EAAE,SAAS;AAC1B,WAAU,IAAI,OAAO;AACrB,QAAO;;;AAIT,MAAa,eAAe,YAAiC;AAC3D,SAAQ,KAAK,eAAe;AAC5B,QAAO,YAAY,QAAQ;;AAG7B,MAAM,QAAQ,OAAgC,aAC5C,OAAO,KAAK,MAAM,CAAC,OAAM,QAAO,SAAS,SAAS,IAAI,CAAC;AACzD,MAAM,WAAW,UAA+C;AAC9D,KAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO;AAClC,MAAK,MAAM,QAAQ,MAAO,KAAI,OAAO,SAAS,SAAU,QAAO;AAC/D,QAAO;;AAET,MAAM,SAAS,UACb,QAAQ,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,SAAS,MAAM;AAClD,MAAM,cACJ,OACA,QACuD;AACvD,KAAI,CAACA,gBAAAA,cAAc,MAAM,IAAI,OAAO,MAAM,SAAS,SAAU,QAAO;AACpE,KAAI,MAAM,SAAS,QACjB,QAAO,KAAK,OAAO;EAAC;EAAQ;EAAK;EAAQ,CAAC,IAAI,OAAO,OAAO,OAAO,QAAQ;AAC7E,KAAI,MAAM,SAAS,UACjB,QAAO,KAAK,OAAO;EAAC;EAAQ;EAAK;EAAS,CAAC,IAAI,OAAO,OAAO,OAAO,SAAS;AAC/E,QACE,MAAM,SAAS,aACf,KAAK,OAAO;EAAC;EAAQ;EAAK;EAAU;EAAQ,CAAC,IAC7C,OAAO,OAAO,OAAO,SAAS,IAC9B,OAAO,OAAO,OAAO,QAAQ;;AAGjC,MAAM,WAAW,GAAW,MAAe,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI;;AAGtE,MAAa,iBAAiB,UAA8B;AAC1D,KAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,IAAI,MAAmB,CAClF,QAAO;AACT,KAAI,CAACA,gBAAAA,cAAc,MAAM,IAAI,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,QAAQ,MAAM,QAAQ,CACrF,QAAOC,KAAW,EAAE,EAAE,mBAAmB,wBAAwB;CACnE,MAAM,SAAmB,EAAE;AAC3B,MAAK,MAAM,SAAS,MAAM,SAAS;AACjC,MAAI,CAACD,gBAAAA,cAAc,MAAM,CAAE,QAAOC,KAAW,EAAE,EAAE,mBAAmB,qBAAqB;AACzF,MAAI,MAAM,SAAS,SAAS;AAC1B,OACE,MAAM,QAAQ,WAAW,KACzB,CAAC,KAAK,OAAO;IAAC;IAAQ;IAAU;IAAQ,CAAC,IACzC,CAAC,OAAO,OAAO,OAAO,SAAS,IAC/B,CAAC,OAAO,OAAO,OAAO,QAAQ,CAE9B,QAAOA,KACL,EAAE,EACF,mBACA,2DACD;AACH,UAAO,YAAY,CAAC;IAAE,MAAM;IAAS,QAAQ,MAAM;IAAQ,OAAO,MAAM;IAAO,CAAC,CAAC;;AAEnF,MAAI,CAAC,QAAQ,MAAM,GAAG,CACpB,QAAOA,KAAW,EAAE,EAAE,mBAAmB,yCAAyC;EACpF,MAAM,KAAK,MAAM;AACjB,MACE,MAAM,SAAS,aACf,KAAK,OAAO;GAAC;GAAQ;GAAM;GAAW;GAAQ,CAAC,IAC/C,MAAM,QAAQ,MAAM,QAAQ,KAC3B,MAAM,QAAQ,UAAU,OAAO,OAAO,OAAO,QAAQ,GACtD;GACA,MAAM,uBAAO,IAAI,KAAa;GAC9B,MAAM,UAA0B,EAAE;AAClC,QAAK,MAAM,UAAU,MAAM,SAAS;AAClC,QAAI,CAAC,WAAW,QAAQ,MAAM,IAAI,OAAO,OAAO,QAAQ,YAAY,KAAK,IAAI,OAAO,IAAI,CACtF,QAAOA,KAAW,IAAI,mBAAmB,4CAA4C;AACvF,SAAK,IAAI,OAAO,IAAI;AACpB,YAAQ,KAAK;KAAE,GAAG;KAAQ,KAAK,OAAO;KAAK,CAAC;;GAE9C,MAAM,SAA+C;IACnD,MAAM;IACN;IACA,SAAS,QAAQ,MAAM,GAAG,MAAM,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC;IACvD;AACD,OAAI,OAAO,OAAO,OAAO,QAAQ,EAAE;AACjC,QACE,CAACD,gBAAAA,cAAc,MAAM,MAAM,IAC3B,CAAC,KAAK,MAAM,OAAO,CAAC,UAAU,QAAQ,CAAC,IACvC,CAAC,MAAM,MAAM,MAAM,OAAO,IAC1B,CAAC,MAAM,MAAM,MAAM,MAAM,CAEzB,QAAOC,KAAW,IAAI,mBAAmB,6BAA6B;AACxE,WAAO,KAAK;KAAE,GAAG;KAAQ,OAAO;MAAE,QAAQ,MAAM,MAAM;MAAQ,OAAO,MAAM,MAAM;MAAO;KAAE,CAAC;SACtF,QAAO,KAAK,OAAO;aAE1B,MAAM,SAAS,UACf,KAAK,OAAO;GAAC;GAAQ;GAAM;GAAU;GAAS;GAAQ,CAAC,KACtD,MAAM,WAAW,QAAQ,OAAO,MAAM,WAAW,cACjD,MAAM,UAAU,QAAQ,OAAO,MAAM,UAAU,aAChD,MAAM,QAAQ,MAAM,MAAM,EAC1B;GACA,MAAM,uBAAO,IAAI,KAAa;AAC9B,QAAK,MAAM,QAAQ,MAAM,OAAO;AAC9B,QACE,CAAC,WAAW,MAAM,KAAK,IACvB,OAAO,KAAK,OAAO,YACnB,KAAK,IAAI,KAAK,GAAG,IAChB,KAAK,SAAS,WAAW,CAAA,gBAAA,UAAgB,KAAK,OAAO,IACrD,KAAK,SAAS,aAAa,CAAA,gBAAA,UAAgB,KAAK,MAAM,CAEvD,QAAOA,KAAW,IAAI,mBAAmB,0CAA0C;AACrF,SAAK,IAAI,KAAK,GAAG;;GAEnB,MAAM,QAAQ,MAAM;AACpB,UAAO,KAAK;IACV,MAAM;IACN;IACA,QAAQ,MAAM;IACd,OAAO,MAAM;IACb,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC;IACtD,CAAC;QACG,QAAOA,KAAW,IAAI,mBAAmB,+BAA+B;;AAEjF,QAAO,YAAY,iBAAiB,OAAO,CAAC;;AAG9C,MAAM,oBAAoB,YAAgC;CACxD,MAAM,SAAS,QAAQ,KAAK,eAAe;CAC3C,MAAM,SAAS,IAAI,cAAoB;CACvC,MAAM,eAAe,IAAI,cAAoB;CAC7C,MAAM,SAAS,IAAI,cAAoB;AACvC,MAAK,MAAM,UAAU,QAAQ;AAC3B,MAAI,OAAO,SAAS,QAAS;AAC7B,MAAI,OAAO,SAAS,WAAW;AAC7B,OAAI,OAAO,MAAM,OAAO,GAAG,EAAE,KAC3B,QAAOA,KAAW,OAAO,IAAI,mBAAmB,0BAA0B;AAC5E,UAAO,IAAI,OAAO,IAAI,KAAK;AAC3B,OAAI,OAAO,OAAO;AAChB,QAAI,aAAa,YAAY,OAAO,GAAG,CACrC,QAAOA,KAAW,OAAO,IAAI,mBAAmB,+BAA+B;AACjF,WAAO,IAAI,OAAO,IAAI,KAAK;;AAE7B,QAAK,MAAM,UAAU,OAAO,SAAS;IACnC,MAAM,KAAK,OAAO,GAAG,OAAO,OAAO,IAAI;AACvC,QAAI,aAAa,SAAS,GAAG,IAAI,OAAO,cAAc,GAAG,CACvD,QAAOA,KAAW,IAAI,mBAAmB,kCAAkC;AAC7E,iBAAa,IAAI,IAAI,KAAK;;aAEnB,OAAO,SAAS,QAAQ;AACjC,OAAI,aAAa,SAAS,OAAO,GAAG,IAAI,OAAO,cAAc,OAAO,GAAG,CACrE,QAAOA,KAAW,OAAO,IAAI,mBAAmB,gCAAgC;AAClF,gBAAa,IAAI,OAAO,IAAI,KAAK;;;AAGrC,QAAO;;AAGT,MAAa,eAAe,YAA+B;CACzD,IAAI,QAAQ;AACZ,MAAK,MAAM,UAAU,QAAQ,QAC3B,UACE,OAAO,SAAS,YACZ,OAAO,QAAQ,UAAU,OAAO,QAAQ,IAAI,KAC5C,OAAO,SAAS,SACd,IAAI,OAAO,MAAM,SACjB;AACV,QAAO;;;;ACpKT,MAAa,yBAAyB,SAAiB,WAAqC;CAC1F,MAAM,UAAUC,gBAAAA,UAAU,QAAQ;AAClC,KAAI,QAAQ,gBAAgB,EAAG,SAAQ,QAAQ,eAAe,OAAO;;AAGvE,MAAa,6BACX,SACA,WAC4B;CAC5B,MAAM,UAAUA,gBAAAA,UAAU,QAAQ;AAClC,KAAI,QAAQ,OAAQ,OAAM,IAAI,MAAM,4CAA4C;AAChF,SAAQ,SAAS;CACjB,IAAI,SAAS;AACb,QAAO,OAAO,OAAO;EACnB,MAAe,QAAgC;AAC7C,OAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,kDAAkD;AAC/E,WAAQ,eAAe;AACvB,OAAI;AACF,WAAO,KAAK;aACJ;AACR,YAAQ,eAAe;;;EAG3B,eAAqB;AACnB,OAAI,CAAC,OAAQ;AACb,YAAS;AACT,OAAI,QAAQ,WAAW,OAAQ,SAAQ,SAAS,KAAA;;EAEnD,CAAC"}
|
|
@@ -1,4 +1,148 @@
|
|
|
1
|
-
import {
|
|
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
|
|
170
|
-
if (
|
|
301
|
+
const context = contextOf(runtime);
|
|
302
|
+
if (context.bypassDepth === 0) context.driver?.assertWritable(intent);
|
|
171
303
|
};
|
|
172
304
|
const installRuntimeWriteDriver = (runtime, driver) => {
|
|
173
|
-
const
|
|
174
|
-
if (
|
|
175
|
-
|
|
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
|
-
|
|
312
|
+
context.bypassDepth += 1;
|
|
181
313
|
try {
|
|
182
314
|
return run();
|
|
183
315
|
} finally {
|
|
184
|
-
|
|
316
|
+
context.bypassDepth -= 1;
|
|
185
317
|
}
|
|
186
318
|
},
|
|
187
319
|
dispose: () => {
|
|
188
320
|
if (!active) return;
|
|
189
321
|
active = false;
|
|
190
|
-
if (
|
|
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 {
|
|
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-
|
|
329
|
+
//# sourceMappingURL=driver-yFfvDMX5.js.map
|