doxum 0.1.4 → 0.1.6
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 +46 -5
- package/dist/{contract-BsY1XLiG.d.ts → contract-I99DUMbN.d.ts} +53 -40
- package/dist/{contract-D8kjdfqT.d.cts → contract-uYJTmT8o.d.cts} +53 -40
- package/dist/index.cjs +244 -630
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -64
- package/dist/index.d.ts +3 -64
- package/dist/index.js +182 -569
- package/dist/index.js.map +1 -1
- package/dist/integration-Bs3pOk65.cjs +35 -0
- package/dist/integration-Bs3pOk65.cjs.map +1 -0
- package/dist/integration-xupBIKjU.js +30 -0
- package/dist/integration-xupBIKjU.js.map +1 -0
- package/dist/integration.cjs +4 -14
- package/dist/integration.d.cts +3 -2
- package/dist/integration.d.ts +3 -2
- package/dist/integration.js +3 -14
- package/dist/local-sync.cjs +1 -1
- package/dist/local-sync.d.cts +1 -1
- package/dist/local-sync.d.ts +1 -1
- package/dist/local-sync.js +1 -1
- package/dist/{ownership-CU-9DKJQ.cjs → ownership-CY0nPXGF.cjs} +4 -1
- package/dist/ownership-CY0nPXGF.cjs.map +1 -0
- package/dist/{ownership-B-VAPcce.js → ownership-CduRygE7.js} +4 -1
- package/dist/ownership-CduRygE7.js.map +1 -0
- package/dist/react.cjs +1 -1
- package/dist/react.js +1 -1
- package/dist/runtime-BJRXF0gq.js +1735 -0
- package/dist/runtime-BJRXF0gq.js.map +1 -0
- package/dist/runtime-CRijXjYp.cjs +1991 -0
- package/dist/runtime-CRijXjYp.cjs.map +1 -0
- package/dist/runtime-CUcvhFNP.d.ts +152 -0
- package/dist/runtime-C_vKHmhy.d.cts +152 -0
- package/package.json +1 -1
- package/skills/doxum-runtime/references/guide.en.md +35 -18
- package/skills/doxum-runtime/references/guide.zh-CN.md +26 -14
- package/skills/doxum-runtime/references/invariants.en.md +12 -9
- package/skills/doxum-runtime/references/invariants.zh-CN.md +2 -2
- package/skills/doxum-runtime/references/patterns.en.md +36 -56
- package/skills/doxum-runtime/references/patterns.zh-CN.md +27 -45
- package/dist/dependency-C5_R1tvQ.js +0 -496
- package/dist/dependency-C5_R1tvQ.js.map +0 -1
- package/dist/dependency-Dfzs3khk.cjs +0 -722
- package/dist/dependency-Dfzs3khk.cjs.map +0 -1
- package/dist/integration.cjs.map +0 -1
- package/dist/integration.js.map +0 -1
- package/dist/ownership-B-VAPcce.js.map +0 -1
- package/dist/ownership-CU-9DKJQ.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
import { a as isStablePayload, c as snapshotPayload, i as isRecord, l as transferPayload, n as deepEqual, o as ownPayload, r as isPlainObject, s as sameStructuralValue, t as cloneValue, u as profile } from "./ownership-
|
|
1
|
+
import { A as dict, B as tree, C as debugKey, D as resolveAddress, E as read, F as optional, I as record, L as schema, M as list, N as map, O as resolveLocated, P as object, R as single, S as contains, T as overlaps, V as variant, _ as address$2, a as createNotification, b as impact_target_exports, c as shareNotification, d as accessOf, f as bindRuntimeAccess, g as documentReader, h as DocumentReentrancyError, i as ProjectionError, j as field, k as set$1, l as subscribeRoot, m as DocumentDisposedError, o as disposeNotification, p as readWith, r as ProjectionDisposedError, s as notify, t as createProjectionRuntime, u as subscribeTargets, v as belongs, w as locate, y as id, z as table } from "./runtime-BJRXF0gq.js";
|
|
2
|
+
import { a as isStablePayload, c as snapshotPayload, i as isRecord, l as transferPayload, n as deepEqual, o as ownPayload, r as isPlainObject, s as sameStructuralValue, t as cloneValue, u as profile } from "./ownership-CduRygE7.js";
|
|
3
3
|
import { n as bindRuntimeDriver, r as disposeRuntimeDriver, t as assertRuntimeWritable } from "./driver-CbzfW5MR.js";
|
|
4
4
|
//#region core/src/impact.ts
|
|
5
5
|
const emptyCollectionImpact = Object.freeze({
|
|
@@ -195,7 +195,11 @@ const writerFor = (node, inputAddress, sink) => {
|
|
|
195
195
|
type: "dict.replace",
|
|
196
196
|
at: address,
|
|
197
197
|
value
|
|
198
|
-
})
|
|
198
|
+
}),
|
|
199
|
+
...node.optional ? { clear: () => emit(sink, {
|
|
200
|
+
type: "value.clear",
|
|
201
|
+
at: address
|
|
202
|
+
}) } : {}
|
|
199
203
|
};
|
|
200
204
|
if (node.kind === "list") return {
|
|
201
205
|
insert: (value, anchor) => emit(sink, {
|
|
@@ -221,7 +225,11 @@ const writerFor = (node, inputAddress, sink) => {
|
|
|
221
225
|
at: address,
|
|
222
226
|
value,
|
|
223
227
|
keys: value.map(node.keyOf)
|
|
224
|
-
})
|
|
228
|
+
}),
|
|
229
|
+
...node.optional ? { clear: () => emit(sink, {
|
|
230
|
+
type: "value.clear",
|
|
231
|
+
at: address
|
|
232
|
+
}) } : {}
|
|
225
233
|
};
|
|
226
234
|
if (node.kind === "tree") return {
|
|
227
235
|
insert: (treeNodeId, value, parentId, index) => emit(sink, {
|
|
@@ -254,7 +262,11 @@ const writerFor = (node, inputAddress, sink) => {
|
|
|
254
262
|
type: "tree.replace",
|
|
255
263
|
at: address,
|
|
256
264
|
value
|
|
257
|
-
})
|
|
265
|
+
}),
|
|
266
|
+
...node.optional ? { clear: () => emit(sink, {
|
|
267
|
+
type: "value.clear",
|
|
268
|
+
at: address
|
|
269
|
+
}) } : {}
|
|
258
270
|
};
|
|
259
271
|
if (node.kind === "table") {
|
|
260
272
|
let items;
|
|
@@ -318,11 +330,17 @@ const writerFor = (node, inputAddress, sink) => {
|
|
|
318
330
|
};
|
|
319
331
|
}
|
|
320
332
|
if (node.kind === "single") return writerFor(node.value, address, sink);
|
|
321
|
-
if (node.kind === "variant") return {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
333
|
+
if (node.kind === "variant") return {
|
|
334
|
+
replace: (value) => emit(sink, {
|
|
335
|
+
type: "variant.replace",
|
|
336
|
+
at: address,
|
|
337
|
+
value
|
|
338
|
+
}),
|
|
339
|
+
...node.optional ? { clear: () => emit(sink, {
|
|
340
|
+
type: "value.clear",
|
|
341
|
+
at: address
|
|
342
|
+
}) } : {}
|
|
343
|
+
};
|
|
326
344
|
let children;
|
|
327
345
|
return new Proxy({}, { get: (_target, property) => {
|
|
328
346
|
if (typeof property !== "string" || !node.shape[property]) return void 0;
|
|
@@ -540,8 +558,11 @@ const rejected$3 = (operation, code, message) => ({
|
|
|
540
558
|
issue: from(operation, code, message)
|
|
541
559
|
});
|
|
542
560
|
const executeList = (target, operation, copyPayload) => {
|
|
543
|
-
if (
|
|
544
|
-
const
|
|
561
|
+
if (target.node.kind !== "list") return rejected$3(operation, "invalid-address", "List target is invalid.");
|
|
562
|
+
const absent = target.value === void 0 && "optional" in target.node && target.node.optional === true;
|
|
563
|
+
if (!Array.isArray(target.value) && !absent) return rejected$3(operation, "invalid-address", "List target is invalid.");
|
|
564
|
+
if (absent && operation.type !== "list.replace") return rejected$3(operation, "invalid-address", "Only list replacement can initialize an optional list.");
|
|
565
|
+
const list = Array.isArray(target.value) ? target.value : [];
|
|
545
566
|
const orderedKeys = keys(list, target.node.keyOf);
|
|
546
567
|
const own = (value) => copyPayload ? ownPayload(value) : value;
|
|
547
568
|
if (operation.type === "list.replace") {
|
|
@@ -552,18 +573,23 @@ const executeList = (target, operation, copyPayload) => {
|
|
|
552
573
|
if (seen.has(key) || target.node.keyOf(operation.value[index]) !== key) return rejected$3(operation, "invalid-list-keys", "List replacement keys are invalid.");
|
|
553
574
|
seen.add(key);
|
|
554
575
|
}
|
|
555
|
-
if (sameStructuralValue(list, operation.value)) return { status: "unchanged" };
|
|
556
|
-
const keys =
|
|
557
|
-
|
|
558
|
-
|
|
576
|
+
if (!absent && sameStructuralValue(list, operation.value)) return { status: "unchanged" };
|
|
577
|
+
const keys = list.map(target.node.keyOf);
|
|
578
|
+
const inverse = absent ? {
|
|
579
|
+
type: "value.clear",
|
|
580
|
+
at: operation.at
|
|
581
|
+
} : {
|
|
559
582
|
type: "list.replace",
|
|
560
583
|
at: operation.at,
|
|
561
584
|
value: cloneValue(list, "inverse"),
|
|
562
585
|
keys
|
|
563
586
|
};
|
|
564
587
|
const owned = own(operation.value);
|
|
565
|
-
|
|
566
|
-
|
|
588
|
+
if (absent) target.parent[target.key] = owned;
|
|
589
|
+
else {
|
|
590
|
+
list.length = owned.length;
|
|
591
|
+
for (let index = 0; index < owned.length; index += 1) list[index] = owned[index];
|
|
592
|
+
}
|
|
567
593
|
return {
|
|
568
594
|
status: "changed",
|
|
569
595
|
inverse: [inverse]
|
|
@@ -1023,16 +1049,39 @@ const outcome = (operation, value) => value.status === "rejected" ? {
|
|
|
1023
1049
|
issue: from(operation, value.code, value.message)
|
|
1024
1050
|
} : value;
|
|
1025
1051
|
const executeTree = (root, target, operation, copyPayload) => {
|
|
1026
|
-
if (
|
|
1052
|
+
if (target.node.kind !== "tree") return {
|
|
1027
1053
|
status: "rejected",
|
|
1028
1054
|
issue: from(operation, "invalid-address", "Tree target is invalid.")
|
|
1029
1055
|
};
|
|
1030
1056
|
const own = (value) => copyPayload ? ownPayload(value) : value;
|
|
1057
|
+
const absent = target.value === void 0 && "optional" in target.node && target.node.optional === true;
|
|
1031
1058
|
if (operation.type === "tree.replace") {
|
|
1059
|
+
if (absent) {
|
|
1060
|
+
if (!validate(operation.value)) return {
|
|
1061
|
+
status: "rejected",
|
|
1062
|
+
issue: from(operation, "invalid-tree", "Tree replacement is malformed.")
|
|
1063
|
+
};
|
|
1064
|
+
target.parent[target.key] = own(operation.value);
|
|
1065
|
+
return {
|
|
1066
|
+
status: "changed",
|
|
1067
|
+
inverse: [{
|
|
1068
|
+
type: "value.clear",
|
|
1069
|
+
at: operation.at
|
|
1070
|
+
}]
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
if (!is(target.value)) return {
|
|
1074
|
+
status: "rejected",
|
|
1075
|
+
issue: from(operation, "invalid-address", "Tree target is invalid.")
|
|
1076
|
+
};
|
|
1032
1077
|
const result = replace(target.value, operation);
|
|
1033
1078
|
if (result.status === "changed") set$1(root, operation.at, ownPayload(operation.value));
|
|
1034
1079
|
return outcome(operation, result);
|
|
1035
1080
|
}
|
|
1081
|
+
if (!is(target.value)) return {
|
|
1082
|
+
status: "rejected",
|
|
1083
|
+
issue: from(operation, "invalid-address", "Tree target is invalid.")
|
|
1084
|
+
};
|
|
1036
1085
|
if (operation.type === "tree.insert") return outcome(operation, insert(target.value, operation, own(operation.value)));
|
|
1037
1086
|
if (operation.type === "tree.set") return outcome(operation, set(target.value, operation, own(operation.value)));
|
|
1038
1087
|
if (operation.type === "tree.remove") return outcome(operation, remove(target.value, operation));
|
|
@@ -1090,6 +1139,18 @@ const executeValue = (target, operation, copyPayload) => {
|
|
|
1090
1139
|
inverse: [inverse]
|
|
1091
1140
|
};
|
|
1092
1141
|
}
|
|
1142
|
+
if (operation.type === "dict.replace" && target.value === void 0) {
|
|
1143
|
+
if (!("optional" in target.node) || !target.node.optional) return rejected$1(operation, "invalid-address", "Dictionary target is invalid.");
|
|
1144
|
+
const inverse = {
|
|
1145
|
+
type: "value.clear",
|
|
1146
|
+
at: operation.at
|
|
1147
|
+
};
|
|
1148
|
+
target.parent[target.key] = own(operation.value);
|
|
1149
|
+
return {
|
|
1150
|
+
status: "changed",
|
|
1151
|
+
inverse: [inverse]
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1093
1154
|
if (!isRecord(target.value)) return rejected$1(operation, "invalid-address", "Dictionary target is invalid.");
|
|
1094
1155
|
if (operation.type === "dict.replace") {
|
|
1095
1156
|
if (sameStructuralValue(target.value, operation.value)) return { status: "unchanged" };
|
|
@@ -1138,11 +1199,67 @@ const executeValue = (target, operation, copyPayload) => {
|
|
|
1138
1199
|
};
|
|
1139
1200
|
//#endregion
|
|
1140
1201
|
//#region core/src/mutation/execute.ts
|
|
1202
|
+
const hasOwn$1 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
1203
|
+
const executeClear = (target, operation) => {
|
|
1204
|
+
if (!("optional" in target.node) || !target.node.optional) return {
|
|
1205
|
+
status: "rejected",
|
|
1206
|
+
issue: from(operation, "required-field", "Only optional values can be cleared.")
|
|
1207
|
+
};
|
|
1208
|
+
if (!hasOwn$1(target.parent, target.key)) return { status: "unchanged" };
|
|
1209
|
+
if (target.node.kind !== "field" && target.node.kind !== "variant" && target.node.kind !== "dict" && target.node.kind !== "record" && target.node.kind !== "list" && target.node.kind !== "tree") return {
|
|
1210
|
+
status: "rejected",
|
|
1211
|
+
issue: from(operation, "invalid-operation", "This optional value has no clear operation.")
|
|
1212
|
+
};
|
|
1213
|
+
const inverse = (() => {
|
|
1214
|
+
switch (target.node.kind) {
|
|
1215
|
+
case "field": return {
|
|
1216
|
+
type: "field.set",
|
|
1217
|
+
at: operation.at,
|
|
1218
|
+
value: target.value
|
|
1219
|
+
};
|
|
1220
|
+
case "variant": return {
|
|
1221
|
+
type: "variant.replace",
|
|
1222
|
+
at: operation.at,
|
|
1223
|
+
value: cloneValue(target.value, "inverse")
|
|
1224
|
+
};
|
|
1225
|
+
case "dict":
|
|
1226
|
+
case "record": return {
|
|
1227
|
+
type: "dict.replace",
|
|
1228
|
+
at: operation.at,
|
|
1229
|
+
value: cloneValue(target.value, "inverse")
|
|
1230
|
+
};
|
|
1231
|
+
case "list":
|
|
1232
|
+
if (!Array.isArray(target.value)) return {
|
|
1233
|
+
type: "list.replace",
|
|
1234
|
+
at: operation.at,
|
|
1235
|
+
value: [],
|
|
1236
|
+
keys: []
|
|
1237
|
+
};
|
|
1238
|
+
return {
|
|
1239
|
+
type: "list.replace",
|
|
1240
|
+
at: operation.at,
|
|
1241
|
+
value: cloneValue(target.value, "inverse"),
|
|
1242
|
+
keys: target.value.map(target.node.keyOf)
|
|
1243
|
+
};
|
|
1244
|
+
case "tree": return {
|
|
1245
|
+
type: "tree.replace",
|
|
1246
|
+
at: operation.at,
|
|
1247
|
+
value: cloneValue(target.value, "inverse")
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
})();
|
|
1251
|
+
delete target.parent[target.key];
|
|
1252
|
+
return {
|
|
1253
|
+
status: "changed",
|
|
1254
|
+
inverse: [inverse]
|
|
1255
|
+
};
|
|
1256
|
+
};
|
|
1141
1257
|
const invalidTarget = (operation) => ({
|
|
1142
1258
|
status: "rejected",
|
|
1143
1259
|
issue: from(operation, "invalid-address", `Operation '${operation.type}' does not match the schema address.`)
|
|
1144
1260
|
});
|
|
1145
1261
|
const execute = (root, operation, target, copyPayload) => {
|
|
1262
|
+
if (operation.type === "value.clear") return !target ? invalidTarget(operation) : executeClear(target, operation);
|
|
1146
1263
|
if (operation.type === "field.set" || operation.type === "field.clear") return !target || target.node.kind !== "field" ? invalidTarget(operation) : executeValue(target, operation, copyPayload);
|
|
1147
1264
|
if (operation.type === "variant.replace") return !target || target.node.kind !== "variant" ? invalidTarget(operation) : executeValue(target, operation, copyPayload);
|
|
1148
1265
|
if (operation.type === "dict.set" || operation.type === "dict.delete" || operation.type === "dict.replace") return !target || target.node.kind !== "dict" && target.node.kind !== "record" ? invalidTarget(operation) : executeValue(target, operation, copyPayload);
|
|
@@ -1532,11 +1649,12 @@ const createChangeJournal = (root) => {
|
|
|
1532
1649
|
const recordValue = (resolved, operation, inverse) => {
|
|
1533
1650
|
if (find("value", operation.at, resolved.addressHash)) return;
|
|
1534
1651
|
const first = inverse[0];
|
|
1535
|
-
if (first?.type !== "field.set" && first?.type !== "field.clear") return inverseMismatch(operation);
|
|
1652
|
+
if (first?.type !== "field.set" && first?.type !== "field.clear" && first?.type !== "value.clear" && !("value" in (first ?? {}))) return inverseMismatch(operation);
|
|
1653
|
+
const before = first.type === "field.clear" || first.type === "value.clear" ? absent : "value" in first ? present(first.value) : inverseMismatch(operation);
|
|
1536
1654
|
add({
|
|
1537
1655
|
...base(resolved, operation),
|
|
1538
1656
|
kind: "value",
|
|
1539
|
-
before
|
|
1657
|
+
before
|
|
1540
1658
|
});
|
|
1541
1659
|
};
|
|
1542
1660
|
const recordVariant = (resolved, operation, inverse) => {
|
|
@@ -1579,6 +1697,18 @@ const createChangeJournal = (root) => {
|
|
|
1579
1697
|
if (!first) return inverseMismatch(operation);
|
|
1580
1698
|
let subject = find("list", operation.at, resolved.addressHash);
|
|
1581
1699
|
if (!subject) {
|
|
1700
|
+
if (first.type === "value.clear") {
|
|
1701
|
+
add({
|
|
1702
|
+
...base(resolved, operation),
|
|
1703
|
+
kind: "list",
|
|
1704
|
+
node: resolved.node,
|
|
1705
|
+
state: {
|
|
1706
|
+
mode: "whole",
|
|
1707
|
+
value: void 0
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1710
|
+
return;
|
|
1711
|
+
}
|
|
1582
1712
|
if (first.type === "list.replace") {
|
|
1583
1713
|
add({
|
|
1584
1714
|
...base(resolved, operation),
|
|
@@ -1666,6 +1796,22 @@ const createChangeJournal = (root) => {
|
|
|
1666
1796
|
};
|
|
1667
1797
|
const recordTree = (resolved, operation, inverse) => {
|
|
1668
1798
|
const current = read(root, operation.at);
|
|
1799
|
+
if (inverse.length === 1 && inverse[0].type === "value.clear" && operation.type === "tree.replace") {
|
|
1800
|
+
const subject = find("tree", operation.at, resolved.addressHash);
|
|
1801
|
+
if (subject) subject.state = {
|
|
1802
|
+
mode: "whole",
|
|
1803
|
+
value: void 0
|
|
1804
|
+
};
|
|
1805
|
+
else add({
|
|
1806
|
+
...base(resolved, operation),
|
|
1807
|
+
kind: "tree",
|
|
1808
|
+
state: {
|
|
1809
|
+
mode: "whole",
|
|
1810
|
+
value: void 0
|
|
1811
|
+
}
|
|
1812
|
+
});
|
|
1813
|
+
return;
|
|
1814
|
+
}
|
|
1669
1815
|
if (!is(current)) return inverseMismatch(operation);
|
|
1670
1816
|
const inverses = inverse.filter(treeOperation);
|
|
1671
1817
|
if (inverses.length === 0 || inverses.length !== inverse.length) return inverseMismatch(operation);
|
|
@@ -1682,7 +1828,7 @@ const createChangeJournal = (root) => {
|
|
|
1682
1828
|
record: (resolved, operation, inverse) => {
|
|
1683
1829
|
profile.batch.journalRecord();
|
|
1684
1830
|
if (ownerOf(operation.at)) return;
|
|
1685
|
-
if (operation.type === "field.set" || operation.type === "field.clear") {
|
|
1831
|
+
if (operation.type === "field.set" || operation.type === "field.clear" || operation.type === "value.clear") {
|
|
1686
1832
|
recordValue(resolved, operation, inverse);
|
|
1687
1833
|
return;
|
|
1688
1834
|
}
|
|
@@ -1691,7 +1837,8 @@ const createChangeJournal = (root) => {
|
|
|
1691
1837
|
return;
|
|
1692
1838
|
}
|
|
1693
1839
|
if (operation.type === "dict.set" || operation.type === "dict.delete" || operation.type === "dict.replace") {
|
|
1694
|
-
|
|
1840
|
+
if (operation.type === "dict.replace" && inverse[0]?.type === "value.clear") recordValue(resolved, operation, inverse);
|
|
1841
|
+
else recordDict(resolved, operation, inverse);
|
|
1695
1842
|
return;
|
|
1696
1843
|
}
|
|
1697
1844
|
if (operation.type === "entity.create" || operation.type === "entity.remove" || operation.type === "entity.move") {
|
|
@@ -1792,7 +1939,8 @@ const decode = (input) => {
|
|
|
1792
1939
|
switch (input.type) {
|
|
1793
1940
|
case "field.set":
|
|
1794
1941
|
case "variant.replace": return has(input, "value") ? decoded(input) : rejected("invalid-operation", "Operation value is required.");
|
|
1795
|
-
case "field.clear":
|
|
1942
|
+
case "field.clear":
|
|
1943
|
+
case "value.clear": return decoded(input);
|
|
1796
1944
|
case "dict.set": return typeof input.key === "string" && has(input, "value") ? decoded(input) : rejected("invalid-operation", "Dictionary set requires a string key and value.");
|
|
1797
1945
|
case "dict.delete": return typeof input.key === "string" ? decoded(input) : rejected("invalid-operation", "Dictionary delete requires a string key.");
|
|
1798
1946
|
case "dict.replace": return isRecord(input.value) ? decoded(input) : rejected("invalid-operation", "Dictionary replacement must be an object.");
|
|
@@ -1985,6 +2133,7 @@ const commandFootprint = (operations) => {
|
|
|
1985
2133
|
for (const operation of operations) switch (operation.type) {
|
|
1986
2134
|
case "field.set":
|
|
1987
2135
|
case "field.clear":
|
|
2136
|
+
case "value.clear":
|
|
1988
2137
|
case "variant.replace":
|
|
1989
2138
|
add(targets, {
|
|
1990
2139
|
kind: "value",
|
|
@@ -2147,166 +2296,6 @@ const decodeCommandFootprint = (value) => {
|
|
|
2147
2296
|
return Object.freeze(Array.from(targets.values()));
|
|
2148
2297
|
};
|
|
2149
2298
|
//#endregion
|
|
2150
|
-
//#region core/src/runtime/notification.ts
|
|
2151
|
-
const ROOT_BUCKET = Symbol("document-root");
|
|
2152
|
-
const notifications = /* @__PURE__ */ new WeakMap();
|
|
2153
|
-
const key = (value) => bucket(value) ?? ROOT_BUCKET;
|
|
2154
|
-
const createNotification = (runtime) => {
|
|
2155
|
-
const notification = {
|
|
2156
|
-
root: /* @__PURE__ */ new Set(),
|
|
2157
|
-
filtered: /* @__PURE__ */ new Set(),
|
|
2158
|
-
buckets: /* @__PURE__ */ new Map(),
|
|
2159
|
-
processors: [],
|
|
2160
|
-
candidates: /* @__PURE__ */ new Set(),
|
|
2161
|
-
rootSnapshot: [],
|
|
2162
|
-
notifying: false
|
|
2163
|
-
};
|
|
2164
|
-
notifications.set(runtime, notification);
|
|
2165
|
-
return notification;
|
|
2166
|
-
};
|
|
2167
|
-
const notificationOf = (runtime) => {
|
|
2168
|
-
const value = notifications.get(runtime);
|
|
2169
|
-
if (!value) throw new Error("Unknown Doxum runtime.");
|
|
2170
|
-
return value;
|
|
2171
|
-
};
|
|
2172
|
-
const shareNotification = (source, target) => {
|
|
2173
|
-
notifications.set(target, notificationOf(source));
|
|
2174
|
-
};
|
|
2175
|
-
const registerProcessor = (runtime, processor) => {
|
|
2176
|
-
const notification = notificationOf(runtime);
|
|
2177
|
-
const entry = {
|
|
2178
|
-
processor,
|
|
2179
|
-
active: true
|
|
2180
|
-
};
|
|
2181
|
-
notification.processors.push(entry);
|
|
2182
|
-
return () => {
|
|
2183
|
-
if (!entry.active) return;
|
|
2184
|
-
entry.active = false;
|
|
2185
|
-
if (!notification.notifying) {
|
|
2186
|
-
const index = notification.processors.indexOf(entry);
|
|
2187
|
-
if (index >= 0) notification.processors.splice(index, 1);
|
|
2188
|
-
}
|
|
2189
|
-
};
|
|
2190
|
-
};
|
|
2191
|
-
const subscribeRoot = (notification, listener) => {
|
|
2192
|
-
const entry = {
|
|
2193
|
-
listener,
|
|
2194
|
-
active: true
|
|
2195
|
-
};
|
|
2196
|
-
notification.root.add(entry);
|
|
2197
|
-
return () => {
|
|
2198
|
-
entry.active = false;
|
|
2199
|
-
if (!notification.notifying) notification.root.delete(entry);
|
|
2200
|
-
};
|
|
2201
|
-
};
|
|
2202
|
-
const subscribeTargets = (notification, targets, listener) => {
|
|
2203
|
-
const entry = {
|
|
2204
|
-
targets: Object.freeze(targets.slice()),
|
|
2205
|
-
listener,
|
|
2206
|
-
active: true
|
|
2207
|
-
};
|
|
2208
|
-
notification.filtered.add(entry);
|
|
2209
|
-
const keys = new Set(targets.map(key));
|
|
2210
|
-
keys.forEach((key) => {
|
|
2211
|
-
const bucket = notification.buckets.get(key) ?? /* @__PURE__ */ new Set();
|
|
2212
|
-
bucket.add(entry);
|
|
2213
|
-
notification.buckets.set(key, bucket);
|
|
2214
|
-
});
|
|
2215
|
-
return () => {
|
|
2216
|
-
if (!entry.active) return;
|
|
2217
|
-
entry.active = false;
|
|
2218
|
-
if (notification.notifying) return;
|
|
2219
|
-
notification.filtered.delete(entry);
|
|
2220
|
-
keys.forEach((key) => {
|
|
2221
|
-
const bucket = notification.buckets.get(key);
|
|
2222
|
-
bucket?.delete(entry);
|
|
2223
|
-
if (bucket?.size === 0) notification.buckets.delete(key);
|
|
2224
|
-
});
|
|
2225
|
-
};
|
|
2226
|
-
};
|
|
2227
|
-
const notify = (notification, commit) => {
|
|
2228
|
-
notification.notifying = true;
|
|
2229
|
-
const errors = [];
|
|
2230
|
-
const call = (listener) => {
|
|
2231
|
-
try {
|
|
2232
|
-
listener(commit);
|
|
2233
|
-
} catch (error) {
|
|
2234
|
-
errors.push(Object.freeze({
|
|
2235
|
-
phase: "listener",
|
|
2236
|
-
error
|
|
2237
|
-
}));
|
|
2238
|
-
}
|
|
2239
|
-
};
|
|
2240
|
-
try {
|
|
2241
|
-
const processorCount = notification.processors.length;
|
|
2242
|
-
for (let index = 0; index < processorCount; index += 1) {
|
|
2243
|
-
const entry = notification.processors[index];
|
|
2244
|
-
if (!entry?.active) continue;
|
|
2245
|
-
try {
|
|
2246
|
-
entry.processor.process(commit);
|
|
2247
|
-
} catch (error) {
|
|
2248
|
-
errors.push(Object.freeze({
|
|
2249
|
-
phase: "processor",
|
|
2250
|
-
error
|
|
2251
|
-
}));
|
|
2252
|
-
}
|
|
2253
|
-
}
|
|
2254
|
-
for (let index = 0; index < processorCount; index += 1) {
|
|
2255
|
-
const entry = notification.processors[index];
|
|
2256
|
-
if (!entry?.active) continue;
|
|
2257
|
-
try {
|
|
2258
|
-
entry.processor.flush();
|
|
2259
|
-
} catch (error) {
|
|
2260
|
-
errors.push(Object.freeze({
|
|
2261
|
-
phase: "flush",
|
|
2262
|
-
error
|
|
2263
|
-
}));
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
const candidates = notification.candidates;
|
|
2267
|
-
candidates.clear();
|
|
2268
|
-
if (commit.impact.kind === "reset") notification.filtered.forEach((entry) => candidates.add(entry));
|
|
2269
|
-
else for (const operation of commit.operations) {
|
|
2270
|
-
const key = operation.at[0] ?? ROOT_BUCKET;
|
|
2271
|
-
notification.buckets.get(key)?.forEach((entry) => candidates.add(entry));
|
|
2272
|
-
notification.buckets.get(ROOT_BUCKET)?.forEach((entry) => candidates.add(entry));
|
|
2273
|
-
}
|
|
2274
|
-
candidates.forEach((entry) => {
|
|
2275
|
-
if (entry.active && entry.targets.some(commit.impact.affects)) call(entry.listener);
|
|
2276
|
-
});
|
|
2277
|
-
const rootSnapshot = notification.rootSnapshot;
|
|
2278
|
-
rootSnapshot.length = 0;
|
|
2279
|
-
notification.root.forEach((entry) => rootSnapshot.push(entry));
|
|
2280
|
-
for (const entry of rootSnapshot) if (entry.active) call(entry.listener);
|
|
2281
|
-
} finally {
|
|
2282
|
-
notification.notifying = false;
|
|
2283
|
-
let writeIndex = 0;
|
|
2284
|
-
for (const entry of notification.processors) if (entry.active) notification.processors[writeIndex++] = entry;
|
|
2285
|
-
notification.processors.length = writeIndex;
|
|
2286
|
-
notification.root.forEach((entry) => {
|
|
2287
|
-
if (!entry.active) notification.root.delete(entry);
|
|
2288
|
-
});
|
|
2289
|
-
notification.filtered.forEach((entry) => {
|
|
2290
|
-
if (!entry.active) notification.filtered.delete(entry);
|
|
2291
|
-
});
|
|
2292
|
-
notification.buckets.forEach((bucket, key) => {
|
|
2293
|
-
bucket.forEach((entry) => {
|
|
2294
|
-
if (!entry.active) bucket.delete(entry);
|
|
2295
|
-
});
|
|
2296
|
-
if (bucket.size === 0) notification.buckets.delete(key);
|
|
2297
|
-
});
|
|
2298
|
-
}
|
|
2299
|
-
return Object.freeze(errors);
|
|
2300
|
-
};
|
|
2301
|
-
const disposeNotification = (notification) => {
|
|
2302
|
-
notification.root.clear();
|
|
2303
|
-
notification.filtered.clear();
|
|
2304
|
-
notification.buckets.clear();
|
|
2305
|
-
notification.processors.length = 0;
|
|
2306
|
-
notification.candidates.clear();
|
|
2307
|
-
notification.rootSnapshot.length = 0;
|
|
2308
|
-
};
|
|
2309
|
-
//#endregion
|
|
2310
2299
|
//#region core/src/runtime.ts
|
|
2311
2300
|
var RejectedUpdate = class extends Error {
|
|
2312
2301
|
issues;
|
|
@@ -2336,6 +2325,7 @@ const createDocument = (input) => {
|
|
|
2336
2325
|
const assertWritable = (intent) => {
|
|
2337
2326
|
if (state.disposed) throw new DocumentDisposedError();
|
|
2338
2327
|
if (busy) throw new DocumentReentrancyError();
|
|
2328
|
+
if (accessOf(runtime).projectionLocks) throw new DocumentReentrancyError();
|
|
2339
2329
|
assertRuntimeWritable(runtime, intent);
|
|
2340
2330
|
};
|
|
2341
2331
|
const runTransaction = (session, run) => {
|
|
@@ -2567,10 +2557,14 @@ const createDocument = (input) => {
|
|
|
2567
2557
|
history: history.api,
|
|
2568
2558
|
dispose: () => {
|
|
2569
2559
|
if (state.disposed) return;
|
|
2560
|
+
if (busy || accessOf(runtime).projectionLocks) throw new DocumentReentrancyError();
|
|
2570
2561
|
state.disposed = true;
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2562
|
+
try {
|
|
2563
|
+
disposeNotification(notification);
|
|
2564
|
+
} finally {
|
|
2565
|
+
history.api.clear();
|
|
2566
|
+
disposeRuntimeDriver(runtime);
|
|
2567
|
+
}
|
|
2574
2568
|
}
|
|
2575
2569
|
};
|
|
2576
2570
|
bindRuntimeAccess(runtime, state);
|
|
@@ -2594,387 +2588,6 @@ const asReadable = (runtime) => {
|
|
|
2594
2588
|
//#region core/src/projection/select.ts
|
|
2595
2589
|
const select = (runtime, selector) => readWith(runtime, selector);
|
|
2596
2590
|
//#endregion
|
|
2597
|
-
|
|
2598
|
-
const createCollectionView = (input) => {
|
|
2599
|
-
if (schemaOf(input.runtime) !== input.source.schema) throw new Error("Collection selector belongs to another schema.");
|
|
2600
|
-
const idsListeners = /* @__PURE__ */ new Set();
|
|
2601
|
-
const allListeners = /* @__PURE__ */ new Set();
|
|
2602
|
-
const itemListeners = /* @__PURE__ */ new Map();
|
|
2603
|
-
const itemReadables = /* @__PURE__ */ new Map();
|
|
2604
|
-
let disposed = false;
|
|
2605
|
-
const sourceNode = nodeAt$1(input.source.schema, input.source.address);
|
|
2606
|
-
const entryNode = sourceNode?.kind === "table" || sourceNode?.kind === "map" ? sourceNode.value : {
|
|
2607
|
-
kind: "object",
|
|
2608
|
-
shape: {}
|
|
2609
|
-
};
|
|
2610
|
-
const mapEntry = (document, id) => {
|
|
2611
|
-
profile.collectionView.mapped();
|
|
2612
|
-
const address = [...input.source.address, String(id)];
|
|
2613
|
-
let active = true;
|
|
2614
|
-
try {
|
|
2615
|
-
return input.map(id, readerFor(entryNode, {
|
|
2616
|
-
root: () => document,
|
|
2617
|
-
active: () => active
|
|
2618
|
-
}, address));
|
|
2619
|
-
} finally {
|
|
2620
|
-
active = false;
|
|
2621
|
-
}
|
|
2622
|
-
};
|
|
2623
|
-
const build = (previous, changed) => {
|
|
2624
|
-
const document = documentOf(input.runtime);
|
|
2625
|
-
const collection = read(document, input.source.address);
|
|
2626
|
-
const ids = collection && typeof collection === "object" && "ids" in collection && Array.isArray(collection.ids) ? [...collection.ids] : Object.keys(collection ?? {});
|
|
2627
|
-
profile.collectionView.idsScanned(ids.length);
|
|
2628
|
-
const values = previous && changed ? previous.values : /* @__PURE__ */ new Map();
|
|
2629
|
-
if (previous && changed) {
|
|
2630
|
-
const nextIds = new Set(ids);
|
|
2631
|
-
for (const id of previous.ids) if (!nextIds.has(id)) values.delete(id);
|
|
2632
|
-
}
|
|
2633
|
-
for (const id of ids) {
|
|
2634
|
-
if (previous && changed && previous.values.has(id) && !changed.has(id)) continue;
|
|
2635
|
-
const next = mapEntry(document, id);
|
|
2636
|
-
if (previous && changed && previous.values.has(id)) {
|
|
2637
|
-
const before = previous.values.get(id);
|
|
2638
|
-
if (input.isEqual ? input.isEqual(before, next) : Object.is(before, next)) {
|
|
2639
|
-
changed.delete(id);
|
|
2640
|
-
continue;
|
|
2641
|
-
}
|
|
2642
|
-
}
|
|
2643
|
-
values.set(id, next);
|
|
2644
|
-
}
|
|
2645
|
-
return {
|
|
2646
|
-
ids: Object.freeze(ids),
|
|
2647
|
-
values,
|
|
2648
|
-
all: void 0,
|
|
2649
|
-
allDirty: true
|
|
2650
|
-
};
|
|
2651
|
-
};
|
|
2652
|
-
let state = build();
|
|
2653
|
-
const ensureAll = () => {
|
|
2654
|
-
if (!state.allDirty && state.all) return state.all;
|
|
2655
|
-
profile.collectionView.arrayCopied();
|
|
2656
|
-
const all = new Array(state.ids.length);
|
|
2657
|
-
for (let index = 0; index < state.ids.length; index += 1) all[index] = state.values.get(state.ids[index]);
|
|
2658
|
-
const stable = Object.freeze(all);
|
|
2659
|
-
state.all = stable;
|
|
2660
|
-
state.allDirty = false;
|
|
2661
|
-
return stable;
|
|
2662
|
-
};
|
|
2663
|
-
const emit = (listeners) => {
|
|
2664
|
-
Array.from(listeners).forEach((listener) => listener());
|
|
2665
|
-
};
|
|
2666
|
-
const unsubscribe = input.runtime.subscribe(input.source, (commit) => {
|
|
2667
|
-
if (disposed) return;
|
|
2668
|
-
const impact = commit.impact.collection(input.source);
|
|
2669
|
-
if (impact.kind === "incremental" && impact.added.size === 0 && impact.removed.size === 0 && !impact.orderChanged) {
|
|
2670
|
-
const previous = state;
|
|
2671
|
-
const changes = [];
|
|
2672
|
-
const document = documentOf(input.runtime);
|
|
2673
|
-
impact.updated.forEach((id) => {
|
|
2674
|
-
if (!previous.values.has(id)) return;
|
|
2675
|
-
const before = previous.values.get(id);
|
|
2676
|
-
const after = mapEntry(document, id);
|
|
2677
|
-
if (input.isEqual ? input.isEqual(before, after) : Object.is(before, after)) return;
|
|
2678
|
-
changes.push([id, after]);
|
|
2679
|
-
});
|
|
2680
|
-
if (changes.length === 0) return;
|
|
2681
|
-
for (const [id, value] of changes) previous.values.set(id, value);
|
|
2682
|
-
previous.all = void 0;
|
|
2683
|
-
previous.allDirty = true;
|
|
2684
|
-
emit(allListeners);
|
|
2685
|
-
for (const [id] of changes) {
|
|
2686
|
-
const listeners = itemListeners.get(id);
|
|
2687
|
-
if (listeners) emit(listeners);
|
|
2688
|
-
}
|
|
2689
|
-
return;
|
|
2690
|
-
}
|
|
2691
|
-
const changed = impact.kind === "reset" ? void 0 : new Set([...impact.added, ...impact.updated]);
|
|
2692
|
-
const previous = state;
|
|
2693
|
-
const next = build(previous, changed);
|
|
2694
|
-
const changedIds = /* @__PURE__ */ new Set();
|
|
2695
|
-
if (changed) {
|
|
2696
|
-
changed.forEach((id) => changedIds.add(id));
|
|
2697
|
-
previous.ids.forEach((id) => {
|
|
2698
|
-
if (!next.values.has(id)) changedIds.add(id);
|
|
2699
|
-
});
|
|
2700
|
-
next.ids.forEach((id) => {
|
|
2701
|
-
if (!previous.values.has(id)) changedIds.add(id);
|
|
2702
|
-
});
|
|
2703
|
-
} else {
|
|
2704
|
-
previous.ids.forEach((id) => {
|
|
2705
|
-
if (!next.values.has(id)) changedIds.add(id);
|
|
2706
|
-
else if (!(input.isEqual ? input.isEqual(previous.values.get(id), next.values.get(id)) : Object.is(previous.values.get(id), next.values.get(id)))) changedIds.add(id);
|
|
2707
|
-
});
|
|
2708
|
-
next.ids.forEach((id) => {
|
|
2709
|
-
if (!previous.values.has(id)) changedIds.add(id);
|
|
2710
|
-
});
|
|
2711
|
-
}
|
|
2712
|
-
const idsChanged = impact.kind === "incremental" ? impact.added.size > 0 || impact.removed.size > 0 || impact.orderChanged : previous.ids.length !== next.ids.length || previous.ids.some((id, index) => next.ids[index] !== id);
|
|
2713
|
-
state = idsChanged || changedIds.size ? next : previous;
|
|
2714
|
-
if (idsChanged) emit(idsListeners);
|
|
2715
|
-
if (idsChanged || changedIds.size) emit(allListeners);
|
|
2716
|
-
changedIds.forEach((id) => {
|
|
2717
|
-
const listeners = itemListeners.get(id);
|
|
2718
|
-
if (listeners) emit(listeners);
|
|
2719
|
-
});
|
|
2720
|
-
});
|
|
2721
|
-
return {
|
|
2722
|
-
ids: {
|
|
2723
|
-
current: () => state.ids,
|
|
2724
|
-
revision: () => input.runtime.revision(),
|
|
2725
|
-
subscribe: (listener) => {
|
|
2726
|
-
if (disposed) return () => void 0;
|
|
2727
|
-
idsListeners.add(listener);
|
|
2728
|
-
return () => idsListeners.delete(listener);
|
|
2729
|
-
}
|
|
2730
|
-
},
|
|
2731
|
-
all: {
|
|
2732
|
-
current: ensureAll,
|
|
2733
|
-
revision: () => input.runtime.revision(),
|
|
2734
|
-
subscribe: (listener) => {
|
|
2735
|
-
if (disposed) return () => void 0;
|
|
2736
|
-
allListeners.add(listener);
|
|
2737
|
-
return () => allListeners.delete(listener);
|
|
2738
|
-
}
|
|
2739
|
-
},
|
|
2740
|
-
item: (id) => {
|
|
2741
|
-
const cached = itemReadables.get(id);
|
|
2742
|
-
if (cached) return cached;
|
|
2743
|
-
const readable = {
|
|
2744
|
-
current: () => state.values.get(id),
|
|
2745
|
-
revision: () => input.runtime.revision(),
|
|
2746
|
-
subscribe: (listener) => {
|
|
2747
|
-
if (disposed) return () => void 0;
|
|
2748
|
-
const listeners = itemListeners.get(id) ?? /* @__PURE__ */ new Set();
|
|
2749
|
-
itemListeners.set(id, listeners);
|
|
2750
|
-
listeners.add(listener);
|
|
2751
|
-
return () => {
|
|
2752
|
-
listeners.delete(listener);
|
|
2753
|
-
if (listeners.size === 0) itemListeners.delete(id);
|
|
2754
|
-
};
|
|
2755
|
-
}
|
|
2756
|
-
};
|
|
2757
|
-
itemReadables.set(id, readable);
|
|
2758
|
-
return readable;
|
|
2759
|
-
},
|
|
2760
|
-
revision: () => input.runtime.revision(),
|
|
2761
|
-
dispose: () => {
|
|
2762
|
-
if (disposed) return;
|
|
2763
|
-
disposed = true;
|
|
2764
|
-
unsubscribe();
|
|
2765
|
-
idsListeners.clear();
|
|
2766
|
-
allListeners.clear();
|
|
2767
|
-
itemListeners.clear();
|
|
2768
|
-
itemReadables.clear();
|
|
2769
|
-
state.values.clear();
|
|
2770
|
-
state = {
|
|
2771
|
-
ids: Object.freeze([]),
|
|
2772
|
-
values: /* @__PURE__ */ new Map(),
|
|
2773
|
-
all: Object.freeze([]),
|
|
2774
|
-
allDirty: false
|
|
2775
|
-
};
|
|
2776
|
-
}
|
|
2777
|
-
};
|
|
2778
|
-
};
|
|
2779
|
-
//#endregion
|
|
2780
|
-
//#region core/src/projection/materialized-view.ts
|
|
2781
|
-
const materializedMeta = /* @__PURE__ */ new WeakMap();
|
|
2782
|
-
const createMaterializedView = (runtime, spec) => {
|
|
2783
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
2784
|
-
let disposed = false;
|
|
2785
|
-
let fault;
|
|
2786
|
-
let revision = runtime.revision();
|
|
2787
|
-
let instance;
|
|
2788
|
-
let currentValue;
|
|
2789
|
-
let pendingEmit = false;
|
|
2790
|
-
const dependencies = createDependencyTracker();
|
|
2791
|
-
const sources = spec.sources ?? {};
|
|
2792
|
-
const sourceEntries = Object.keys(sources).map((key) => [key, sources[key]]);
|
|
2793
|
-
sourceEntries.forEach(([, source]) => {
|
|
2794
|
-
const meta = materializedMeta.get(source);
|
|
2795
|
-
if (!meta || meta.runtime !== runtime) throw new Error("Materialized sources must belong to the same runtime and be created first.");
|
|
2796
|
-
});
|
|
2797
|
-
const sourceValuesRecord = {};
|
|
2798
|
-
let sourceChanged = false;
|
|
2799
|
-
for (const [key] of sourceEntries) sourceValuesRecord[key] = {
|
|
2800
|
-
value: void 0,
|
|
2801
|
-
change: void 0
|
|
2802
|
-
};
|
|
2803
|
-
const sourceValues = (commitRevision) => {
|
|
2804
|
-
sourceChanged = false;
|
|
2805
|
-
for (const [key, source] of sourceEntries) {
|
|
2806
|
-
const meta = materializedMeta.get(source);
|
|
2807
|
-
const entry = sourceValuesRecord[key];
|
|
2808
|
-
entry.value = meta?.value ?? source.current();
|
|
2809
|
-
entry.change = meta?.change;
|
|
2810
|
-
if (commitRevision !== void 0 && meta?.changedRevision === commitRevision) {
|
|
2811
|
-
sourceChanged = true;
|
|
2812
|
-
profile.materialized.sourceChanged();
|
|
2813
|
-
}
|
|
2814
|
-
}
|
|
2815
|
-
return sourceValuesRecord;
|
|
2816
|
-
};
|
|
2817
|
-
let activeImpact;
|
|
2818
|
-
const assertImpact = () => {
|
|
2819
|
-
if (!activeImpact) throw new Error("Materialized impact is no longer active.");
|
|
2820
|
-
return activeImpact;
|
|
2821
|
-
};
|
|
2822
|
-
const trackedImpact = {
|
|
2823
|
-
get kind() {
|
|
2824
|
-
return assertImpact().kind;
|
|
2825
|
-
},
|
|
2826
|
-
affects: (target) => {
|
|
2827
|
-
dependencies.record(target);
|
|
2828
|
-
return assertImpact().affects(target);
|
|
2829
|
-
},
|
|
2830
|
-
collection: (selector) => {
|
|
2831
|
-
dependencies.record(selector);
|
|
2832
|
-
return assertImpact().collection(selector);
|
|
2833
|
-
},
|
|
2834
|
-
get operations() {
|
|
2835
|
-
dependencies.record({
|
|
2836
|
-
kind: "value",
|
|
2837
|
-
at: []
|
|
2838
|
-
});
|
|
2839
|
-
return assertImpact().operations;
|
|
2840
|
-
}
|
|
2841
|
-
};
|
|
2842
|
-
let view;
|
|
2843
|
-
const writeMeta = (change, value, nextRevision, changed) => {
|
|
2844
|
-
const meta = materializedMeta.get(view);
|
|
2845
|
-
if (meta) {
|
|
2846
|
-
meta.value = value;
|
|
2847
|
-
meta.change = change;
|
|
2848
|
-
meta.revision = nextRevision;
|
|
2849
|
-
if (changed) meta.changedRevision = nextRevision;
|
|
2850
|
-
} else materializedMeta.set(view, {
|
|
2851
|
-
runtime,
|
|
2852
|
-
value,
|
|
2853
|
-
change,
|
|
2854
|
-
revision: nextRevision,
|
|
2855
|
-
changedRevision: changed ? nextRevision : -1
|
|
2856
|
-
});
|
|
2857
|
-
};
|
|
2858
|
-
const build = () => {
|
|
2859
|
-
profile.materialized.rebuilt();
|
|
2860
|
-
dependencies.clear();
|
|
2861
|
-
let active = true;
|
|
2862
|
-
try {
|
|
2863
|
-
instance = spec.build({
|
|
2864
|
-
read: documentReader(schemaOf(runtime), () => documentOf(runtime), () => active),
|
|
2865
|
-
sources: sourceValues()
|
|
2866
|
-
});
|
|
2867
|
-
currentValue = instance.value;
|
|
2868
|
-
fault = void 0;
|
|
2869
|
-
revision = runtime.revision();
|
|
2870
|
-
} finally {
|
|
2871
|
-
active = false;
|
|
2872
|
-
}
|
|
2873
|
-
};
|
|
2874
|
-
build();
|
|
2875
|
-
const emit = () => {
|
|
2876
|
-
profile.materialized.notification();
|
|
2877
|
-
Array.from(listeners).forEach((listener) => listener());
|
|
2878
|
-
};
|
|
2879
|
-
const process = (commit) => {
|
|
2880
|
-
if (disposed) return;
|
|
2881
|
-
try {
|
|
2882
|
-
if (commit.kind === "replace" || fault) {
|
|
2883
|
-
build();
|
|
2884
|
-
writeMeta(void 0, currentValue, commit.revision, true);
|
|
2885
|
-
pendingEmit = true;
|
|
2886
|
-
return;
|
|
2887
|
-
}
|
|
2888
|
-
const sourceSnapshot = sourceValues(commit.revision);
|
|
2889
|
-
if (!sourceChanged && dependencies.size() > 0 && !dependencies.some(commit.impact.affects)) {
|
|
2890
|
-
profile.materialized.skipped();
|
|
2891
|
-
revision = commit.revision;
|
|
2892
|
-
writeMeta(void 0, currentValue, commit.revision, false);
|
|
2893
|
-
return;
|
|
2894
|
-
}
|
|
2895
|
-
dependencies.clear();
|
|
2896
|
-
profile.materialized.updated();
|
|
2897
|
-
let active = true;
|
|
2898
|
-
let result;
|
|
2899
|
-
try {
|
|
2900
|
-
activeImpact = commit.impact;
|
|
2901
|
-
result = instance.update({
|
|
2902
|
-
read: documentReader(schemaOf(runtime), () => documentOf(runtime), () => active),
|
|
2903
|
-
revision: commit.revision,
|
|
2904
|
-
source: commit.source,
|
|
2905
|
-
impact: trackedImpact,
|
|
2906
|
-
sources: sourceSnapshot
|
|
2907
|
-
});
|
|
2908
|
-
} finally {
|
|
2909
|
-
activeImpact = void 0;
|
|
2910
|
-
active = false;
|
|
2911
|
-
}
|
|
2912
|
-
if (result.kind === "rebuild") {
|
|
2913
|
-
build();
|
|
2914
|
-
writeMeta(void 0, currentValue, commit.revision, true);
|
|
2915
|
-
pendingEmit = true;
|
|
2916
|
-
} else if (result.kind === "changed") {
|
|
2917
|
-
currentValue = result.value;
|
|
2918
|
-
revision = commit.revision;
|
|
2919
|
-
writeMeta(result.change, currentValue, commit.revision, true);
|
|
2920
|
-
pendingEmit = true;
|
|
2921
|
-
} else {
|
|
2922
|
-
revision = commit.revision;
|
|
2923
|
-
writeMeta(void 0, currentValue, commit.revision, false);
|
|
2924
|
-
}
|
|
2925
|
-
} catch (error) {
|
|
2926
|
-
try {
|
|
2927
|
-
build();
|
|
2928
|
-
writeMeta(void 0, currentValue, commit.revision, true);
|
|
2929
|
-
pendingEmit = true;
|
|
2930
|
-
} catch (rebuildError) {
|
|
2931
|
-
fault = rebuildError;
|
|
2932
|
-
throw rebuildError;
|
|
2933
|
-
}
|
|
2934
|
-
throw error;
|
|
2935
|
-
}
|
|
2936
|
-
};
|
|
2937
|
-
view = {
|
|
2938
|
-
current: () => {
|
|
2939
|
-
if (fault) throw fault;
|
|
2940
|
-
return currentValue;
|
|
2941
|
-
},
|
|
2942
|
-
revision: () => revision,
|
|
2943
|
-
subscribe: (listener) => {
|
|
2944
|
-
listeners.add(listener);
|
|
2945
|
-
return () => listeners.delete(listener);
|
|
2946
|
-
},
|
|
2947
|
-
rebuild: () => {
|
|
2948
|
-
build();
|
|
2949
|
-
writeMeta(void 0, currentValue, runtime.revision(), true);
|
|
2950
|
-
emit();
|
|
2951
|
-
},
|
|
2952
|
-
dispose: () => {
|
|
2953
|
-
if (disposed) return;
|
|
2954
|
-
disposed = true;
|
|
2955
|
-
unregister();
|
|
2956
|
-
listeners.clear();
|
|
2957
|
-
materializedMeta.delete(view);
|
|
2958
|
-
}
|
|
2959
|
-
};
|
|
2960
|
-
materializedMeta.set(view, {
|
|
2961
|
-
runtime,
|
|
2962
|
-
value: currentValue,
|
|
2963
|
-
change: void 0,
|
|
2964
|
-
revision,
|
|
2965
|
-
changedRevision: -1
|
|
2966
|
-
});
|
|
2967
|
-
const unregister = registerProcessor(runtime, {
|
|
2968
|
-
process,
|
|
2969
|
-
flush: () => {
|
|
2970
|
-
if (!pendingEmit) return;
|
|
2971
|
-
pendingEmit = false;
|
|
2972
|
-
emit();
|
|
2973
|
-
}
|
|
2974
|
-
});
|
|
2975
|
-
return view;
|
|
2976
|
-
};
|
|
2977
|
-
//#endregion
|
|
2978
|
-
export { DocumentDisposedError, DocumentReentrancyError, asReadable, commandFootprint, contains, createCollectionView, createDocument, createMaterializedView, debugKey, decodeCommandFootprint, dict, field, footprintsOverlap, list, map, object, optional, overlaps, read as readAddress, record, resolveAddress, schema, select, single, table, impact_target_exports as target, tree, variant };
|
|
2591
|
+
export { DocumentDisposedError, DocumentReentrancyError, ProjectionDisposedError, ProjectionError, asReadable, commandFootprint, contains, createDocument, createProjectionRuntime, debugKey, decodeCommandFootprint, dict, field, footprintsOverlap, list, map, object, optional, overlaps, read as readAddress, record, resolveAddress, schema, select, single, table, impact_target_exports as target, tree, variant };
|
|
2979
2592
|
|
|
2980
2593
|
//# sourceMappingURL=index.js.map
|