doxum 0.1.1 → 0.1.3
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 +77 -2
- package/dist/{contract-DwNiKioc.d.ts → contract-BsY1XLiG.d.ts} +64 -5
- package/dist/{contract-Otb5W6cQ.d.cts → contract-D8kjdfqT.d.cts} +64 -5
- package/dist/{dependency-BdEMyquf.js → dependency-C5_R1tvQ.js} +24 -263
- package/dist/dependency-C5_R1tvQ.js.map +1 -0
- package/dist/{dependency-DLcCvNKq.cjs → dependency-Dfzs3khk.cjs} +48 -341
- package/dist/dependency-Dfzs3khk.cjs.map +1 -0
- package/dist/driver-CNxqMVFH.cjs +69 -0
- package/dist/driver-CNxqMVFH.cjs.map +1 -0
- package/dist/driver-CbzfW5MR.js +46 -0
- package/dist/driver-CbzfW5MR.js.map +1 -0
- package/dist/index.cjs +428 -133
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -5
- package/dist/index.d.ts +8 -5
- package/dist/index.js +352 -61
- package/dist/index.js.map +1 -1
- package/dist/integration.cjs +1 -1
- package/dist/integration.cjs.map +1 -1
- package/dist/integration.d.cts +2 -2
- package/dist/integration.d.ts +2 -2
- package/dist/integration.js +1 -1
- package/dist/integration.js.map +1 -1
- package/dist/local-sync.cjs +485 -0
- package/dist/local-sync.cjs.map +1 -0
- package/dist/local-sync.d.cts +74 -0
- package/dist/local-sync.d.ts +74 -0
- package/dist/local-sync.js +476 -0
- package/dist/local-sync.js.map +1 -0
- package/dist/ownership-B-VAPcce.js +242 -0
- package/dist/ownership-B-VAPcce.js.map +1 -0
- package/dist/ownership-CU-9DKJQ.cjs +301 -0
- package/dist/ownership-CU-9DKJQ.cjs.map +1 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js.map +1 -1
- package/package.json +14 -8
- package/skills/doxum-runtime/references/guide.en.md +60 -5
- package/skills/doxum-runtime/references/guide.zh-CN.md +48 -2
- package/skills/doxum-runtime/references/invariants.en.md +23 -8
- package/skills/doxum-runtime/references/invariants.zh-CN.md +2 -2
- package/dist/dependency-BdEMyquf.js.map +0 -1
- package/dist/dependency-DLcCvNKq.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dependency = require("./dependency-
|
|
2
|
+
const require_dependency = require("./dependency-Dfzs3khk.cjs");
|
|
3
|
+
const require_ownership = require("./ownership-CU-9DKJQ.cjs");
|
|
4
|
+
const require_driver = require("./driver-CNxqMVFH.cjs");
|
|
3
5
|
//#region core/src/impact.ts
|
|
4
6
|
const emptyCollectionImpact = Object.freeze({
|
|
5
7
|
kind: "incremental",
|
|
@@ -34,7 +36,7 @@ const createImpact = (input) => {
|
|
|
34
36
|
kind,
|
|
35
37
|
operations: input.operations,
|
|
36
38
|
affects: (value) => {
|
|
37
|
-
|
|
39
|
+
require_ownership.profile.impact.affects();
|
|
38
40
|
if (kind === "reset") return true;
|
|
39
41
|
if (!require_dependency.belongs(value, input.schema)) return false;
|
|
40
42
|
if (pathsAffect(require_dependency.address(value))) return true;
|
|
@@ -403,7 +405,7 @@ const restore = (keys, inserted, positions) => {
|
|
|
403
405
|
//#region core/src/mutation/execute-entity.ts
|
|
404
406
|
const resolveEntityCollection = (node, value) => {
|
|
405
407
|
if (node.kind === "table") {
|
|
406
|
-
if (!
|
|
408
|
+
if (!require_ownership.isRecord(value) || !Array.isArray(value.ids) || !require_ownership.isRecord(value.byId)) return { status: "invalid" };
|
|
407
409
|
return {
|
|
408
410
|
status: "resolved",
|
|
409
411
|
collection: {
|
|
@@ -413,7 +415,7 @@ const resolveEntityCollection = (node, value) => {
|
|
|
413
415
|
}
|
|
414
416
|
};
|
|
415
417
|
}
|
|
416
|
-
return
|
|
418
|
+
return require_ownership.isRecord(value) ? {
|
|
417
419
|
status: "resolved",
|
|
418
420
|
collection: {
|
|
419
421
|
kind: "map",
|
|
@@ -445,7 +447,7 @@ const executeEntity = (target, operation, copyPayload) => {
|
|
|
445
447
|
if (ids && operation.positions) {
|
|
446
448
|
if (operation.positions.length !== operation.entries.length || !validPositions(ids.length, operation.positions)) return rejected$4(operation, "invalid-operation", "Entity restore positions are invalid.");
|
|
447
449
|
} else if (ids && !valid(ids, operation.anchor)) return rejected$4(operation, "invalid-anchor", "Collection anchor is invalid.");
|
|
448
|
-
for (const entry of operation.entries) byId[entry.id] = copyPayload ?
|
|
450
|
+
for (const entry of operation.entries) byId[entry.id] = copyPayload ? require_ownership.cloneValue(entry.value, "canonical") : require_ownership.transferPayload(entry.value);
|
|
449
451
|
if (ids) if (operation.positions) restore(ids, operation.entries.map((entry) => entry.id), operation.positions);
|
|
450
452
|
else if (!operation.anchor || "at" in operation.anchor && operation.anchor.at === "end") for (const entry of operation.entries) ids.push(entry.id);
|
|
451
453
|
else {
|
|
@@ -487,7 +489,7 @@ const executeEntity = (target, operation, copyPayload) => {
|
|
|
487
489
|
if (seen.has(id)) {
|
|
488
490
|
entries.push({
|
|
489
491
|
id,
|
|
490
|
-
value:
|
|
492
|
+
value: require_ownership.cloneValue(byId[id], "inverse")
|
|
491
493
|
});
|
|
492
494
|
positions.push(index);
|
|
493
495
|
delete byId[id];
|
|
@@ -497,7 +499,7 @@ const executeEntity = (target, operation, copyPayload) => {
|
|
|
497
499
|
} else for (const id of operation.ids) {
|
|
498
500
|
entries.push({
|
|
499
501
|
id,
|
|
500
|
-
value:
|
|
502
|
+
value: require_ownership.cloneValue(byId[id], "inverse")
|
|
501
503
|
});
|
|
502
504
|
delete byId[id];
|
|
503
505
|
}
|
|
@@ -542,7 +544,7 @@ const executeList = (target, operation, copyPayload) => {
|
|
|
542
544
|
if (!Array.isArray(target.value) || target.node.kind !== "list") return rejected$3(operation, "invalid-address", "List target is invalid.");
|
|
543
545
|
const list = target.value;
|
|
544
546
|
const orderedKeys = keys(list, target.node.keyOf);
|
|
545
|
-
const own = (value) => copyPayload ?
|
|
547
|
+
const own = (value) => copyPayload ? require_ownership.ownPayload(value) : value;
|
|
546
548
|
if (operation.type === "list.replace") {
|
|
547
549
|
if (operation.keys.length !== operation.value.length) return rejected$3(operation, "invalid-list-keys", "List replacement keys are invalid.");
|
|
548
550
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -551,13 +553,13 @@ const executeList = (target, operation, copyPayload) => {
|
|
|
551
553
|
if (seen.has(key) || target.node.keyOf(operation.value[index]) !== key) return rejected$3(operation, "invalid-list-keys", "List replacement keys are invalid.");
|
|
552
554
|
seen.add(key);
|
|
553
555
|
}
|
|
554
|
-
if (
|
|
556
|
+
if (require_ownership.sameStructuralValue(list, operation.value)) return { status: "unchanged" };
|
|
555
557
|
const keys = new Array(list.length);
|
|
556
558
|
for (let index = 0; index < list.length; index += 1) keys[index] = target.node.keyOf(list[index]);
|
|
557
559
|
const inverse = {
|
|
558
560
|
type: "list.replace",
|
|
559
561
|
at: operation.at,
|
|
560
|
-
value:
|
|
562
|
+
value: require_ownership.cloneValue(list, "inverse"),
|
|
561
563
|
keys
|
|
562
564
|
};
|
|
563
565
|
const owned = own(operation.value);
|
|
@@ -589,7 +591,7 @@ const executeList = (target, operation, copyPayload) => {
|
|
|
589
591
|
type: "list.insert",
|
|
590
592
|
at: operation.at,
|
|
591
593
|
key: operation.key,
|
|
592
|
-
value:
|
|
594
|
+
value: require_ownership.cloneValue(list[position], "inverse"),
|
|
593
595
|
anchor: at(orderedKeys, position)
|
|
594
596
|
};
|
|
595
597
|
list.splice(position, 1);
|
|
@@ -679,7 +681,7 @@ const restoreIncremental = (value, change) => {
|
|
|
679
681
|
}
|
|
680
682
|
return value;
|
|
681
683
|
};
|
|
682
|
-
const restoreChange = (value, change) => change.mode === "whole" ?
|
|
684
|
+
const restoreChange = (value, change) => change.mode === "whole" ? require_ownership.ownPayload(change.value, "journal") : restoreIncremental(value, change);
|
|
683
685
|
const wholeChange = (inverse, previous) => {
|
|
684
686
|
if (!previous) return {
|
|
685
687
|
mode: "whole",
|
|
@@ -688,7 +690,7 @@ const wholeChange = (inverse, previous) => {
|
|
|
688
690
|
if (previous.mode === "whole") return previous;
|
|
689
691
|
return {
|
|
690
692
|
mode: "whole",
|
|
691
|
-
value: restoreIncremental(
|
|
693
|
+
value: restoreIncremental(require_ownership.ownPayload(inverse.value, "journal"), previous)
|
|
692
694
|
};
|
|
693
695
|
};
|
|
694
696
|
const removedNodePresences = (inverses) => {
|
|
@@ -779,16 +781,16 @@ const recordChange = (previous, current, forward, inverses) => {
|
|
|
779
781
|
};
|
|
780
782
|
const sameNodePresence = (before, value) => {
|
|
781
783
|
if (before.status === "absent") return value === void 0;
|
|
782
|
-
return value !== void 0 && before.parentId === value.parentId && sameOrder$1(before.children, value.children) &&
|
|
784
|
+
return value !== void 0 && before.parentId === value.parentId && sameOrder$1(before.children, value.children) && require_ownership.sameStructuralValue(before.value, value.value);
|
|
783
785
|
};
|
|
784
786
|
const changeChanged = (change, value) => {
|
|
785
|
-
if (change.mode === "whole") return !
|
|
787
|
+
if (change.mode === "whole") return !require_ownership.sameStructuralValue(change.value, value);
|
|
786
788
|
if (!is(value)) return true;
|
|
787
789
|
if ((change.root.status === "present" ? change.root.id : void 0) !== value.rootId) return true;
|
|
788
790
|
for (const [id, before] of change.nodes) if (!sameNodePresence(before, node(value, id))) return true;
|
|
789
791
|
return false;
|
|
790
792
|
};
|
|
791
|
-
const is = (value) =>
|
|
793
|
+
const is = (value) => require_ownership.isRecord(value) && require_ownership.isRecord(value.nodes);
|
|
792
794
|
const contains$1 = (tree, id) => has$1(tree.nodes, id);
|
|
793
795
|
const validate = (value) => {
|
|
794
796
|
if (!is(value)) return false;
|
|
@@ -797,7 +799,7 @@ const validate = (value) => {
|
|
|
797
799
|
if (typeof value.rootId !== "string" || !has$1(value.nodes, value.rootId)) return false;
|
|
798
800
|
for (const id of ids) {
|
|
799
801
|
const entry = value.nodes[id];
|
|
800
|
-
if (!
|
|
802
|
+
if (!require_ownership.isRecord(entry) || !Array.isArray(entry.children)) return false;
|
|
801
803
|
if (entry.children.some((child) => typeof child !== "string") || new Set(entry.children).size !== entry.children.length) return false;
|
|
802
804
|
if (entry.parentId !== void 0 && typeof entry.parentId !== "string") return false;
|
|
803
805
|
if (id === value.rootId) {
|
|
@@ -824,7 +826,7 @@ const documentTreeError = (node, value, address) => {
|
|
|
824
826
|
if ("optional" in node && node.optional && value === void 0) return void 0;
|
|
825
827
|
if (node.kind === "tree") return validate(value) ? void 0 : address;
|
|
826
828
|
if (node.kind === "object") {
|
|
827
|
-
if (!
|
|
829
|
+
if (!require_ownership.isRecord(value)) return void 0;
|
|
828
830
|
for (const [key, child] of Object.entries(node.shape)) {
|
|
829
831
|
const error = documentTreeError(child, value[key], [...address, key]);
|
|
830
832
|
if (error) return error;
|
|
@@ -833,12 +835,12 @@ const documentTreeError = (node, value, address) => {
|
|
|
833
835
|
}
|
|
834
836
|
if (node.kind === "single") return documentTreeError(node.value, value, address);
|
|
835
837
|
if (node.kind === "variant") {
|
|
836
|
-
if (!
|
|
838
|
+
if (!require_ownership.isRecord(value) || typeof value[node.tag] !== "string") return void 0;
|
|
837
839
|
const variant = node.variants[value[node.tag]];
|
|
838
840
|
return variant ? documentTreeError(variant, value, address) : void 0;
|
|
839
841
|
}
|
|
840
842
|
if (node.kind === "table") {
|
|
841
|
-
if (!
|
|
843
|
+
if (!require_ownership.isRecord(value) || !require_ownership.isRecord(value.byId)) return void 0;
|
|
842
844
|
for (const [id, entry] of Object.entries(value.byId)) {
|
|
843
845
|
const error = documentTreeError(node.value, entry, [...address, id]);
|
|
844
846
|
if (error) return error;
|
|
@@ -846,7 +848,7 @@ const documentTreeError = (node, value, address) => {
|
|
|
846
848
|
return;
|
|
847
849
|
}
|
|
848
850
|
if (node.kind === "map") {
|
|
849
|
-
if (!
|
|
851
|
+
if (!require_ownership.isRecord(value)) return void 0;
|
|
850
852
|
for (const [id, entry] of Object.entries(value)) {
|
|
851
853
|
const error = documentTreeError(node.value, entry, [...address, id]);
|
|
852
854
|
if (error) return error;
|
|
@@ -859,13 +861,13 @@ const invalidDocument = (schema, value) => documentTreeError({
|
|
|
859
861
|
}, value, []);
|
|
860
862
|
const replace = (current, operation) => {
|
|
861
863
|
if (!validate(operation.value)) return rejected$2("invalid-tree", "Tree replacement is malformed.");
|
|
862
|
-
if (
|
|
864
|
+
if (require_ownership.sameStructuralValue(current, operation.value)) return { status: "unchanged" };
|
|
863
865
|
return {
|
|
864
866
|
status: "changed",
|
|
865
867
|
inverse: [{
|
|
866
868
|
type: "tree.replace",
|
|
867
869
|
at: operation.at,
|
|
868
|
-
value:
|
|
870
|
+
value: require_ownership.cloneValue(current, "inverse")
|
|
869
871
|
}]
|
|
870
872
|
};
|
|
871
873
|
};
|
|
@@ -907,7 +909,7 @@ const set = (tree, operation, value) => {
|
|
|
907
909
|
type: "tree.set",
|
|
908
910
|
at: operation.at,
|
|
909
911
|
treeNodeId: operation.treeNodeId,
|
|
910
|
-
value:
|
|
912
|
+
value: require_ownership.cloneValue(entry.value, "inverse")
|
|
911
913
|
};
|
|
912
914
|
entry.value = value;
|
|
913
915
|
return {
|
|
@@ -938,7 +940,7 @@ const remove = (tree, operation) => {
|
|
|
938
940
|
id: frame.id,
|
|
939
941
|
parentId: frame.parentId,
|
|
940
942
|
index: frame.index,
|
|
941
|
-
value:
|
|
943
|
+
value: require_ownership.cloneValue(entry.value, "inverse")
|
|
942
944
|
});
|
|
943
945
|
for (let index = entry.children.length - 1; index >= 0; index -= 1) {
|
|
944
946
|
const childId = entry.children[index];
|
|
@@ -1026,10 +1028,10 @@ const executeTree = (root, target, operation, copyPayload) => {
|
|
|
1026
1028
|
status: "rejected",
|
|
1027
1029
|
issue: from(operation, "invalid-address", "Tree target is invalid.")
|
|
1028
1030
|
};
|
|
1029
|
-
const own = (value) => copyPayload ?
|
|
1031
|
+
const own = (value) => copyPayload ? require_ownership.ownPayload(value) : value;
|
|
1030
1032
|
if (operation.type === "tree.replace") {
|
|
1031
1033
|
const result = replace(target.value, operation);
|
|
1032
|
-
if (result.status === "changed") require_dependency.set(root, operation.at,
|
|
1034
|
+
if (result.status === "changed") require_dependency.set(root, operation.at, require_ownership.ownPayload(operation.value));
|
|
1033
1035
|
return outcome(operation, result);
|
|
1034
1036
|
}
|
|
1035
1037
|
if (operation.type === "tree.insert") return outcome(operation, insert(target.value, operation, own(operation.value)));
|
|
@@ -1044,7 +1046,7 @@ const rejected$1 = (operation, code, message) => ({
|
|
|
1044
1046
|
issue: from(operation, code, message)
|
|
1045
1047
|
});
|
|
1046
1048
|
const executeValue = (target, operation, copyPayload) => {
|
|
1047
|
-
const own = (value) => copyPayload ?
|
|
1049
|
+
const own = (value) => copyPayload ? require_ownership.ownPayload(value) : value;
|
|
1048
1050
|
if (operation.type === "field.set" || operation.type === "field.clear") {
|
|
1049
1051
|
const existed = Object.prototype.hasOwnProperty.call(target.parent, target.key);
|
|
1050
1052
|
if (operation.type === "field.clear") {
|
|
@@ -1077,11 +1079,11 @@ const executeValue = (target, operation, copyPayload) => {
|
|
|
1077
1079
|
};
|
|
1078
1080
|
}
|
|
1079
1081
|
if (operation.type === "variant.replace") {
|
|
1080
|
-
if (
|
|
1082
|
+
if (require_ownership.sameStructuralValue(target.value, operation.value)) return { status: "unchanged" };
|
|
1081
1083
|
const inverse = {
|
|
1082
1084
|
type: "variant.replace",
|
|
1083
1085
|
at: operation.at,
|
|
1084
|
-
value:
|
|
1086
|
+
value: require_ownership.ownPayload(target.value, "inverse")
|
|
1085
1087
|
};
|
|
1086
1088
|
target.parent[target.key] = own(operation.value);
|
|
1087
1089
|
return {
|
|
@@ -1089,13 +1091,13 @@ const executeValue = (target, operation, copyPayload) => {
|
|
|
1089
1091
|
inverse: [inverse]
|
|
1090
1092
|
};
|
|
1091
1093
|
}
|
|
1092
|
-
if (!
|
|
1094
|
+
if (!require_ownership.isRecord(target.value)) return rejected$1(operation, "invalid-address", "Dictionary target is invalid.");
|
|
1093
1095
|
if (operation.type === "dict.replace") {
|
|
1094
|
-
if (
|
|
1096
|
+
if (require_ownership.sameStructuralValue(target.value, operation.value)) return { status: "unchanged" };
|
|
1095
1097
|
const inverse = {
|
|
1096
1098
|
type: "dict.replace",
|
|
1097
1099
|
at: operation.at,
|
|
1098
|
-
value:
|
|
1100
|
+
value: require_ownership.cloneValue(target.value, "inverse")
|
|
1099
1101
|
};
|
|
1100
1102
|
target.parent[target.key] = own(operation.value);
|
|
1101
1103
|
return {
|
|
@@ -1157,7 +1159,7 @@ const execute = (root, operation, target, copyPayload) => {
|
|
|
1157
1159
|
//#region core/src/mutation/journal.ts
|
|
1158
1160
|
const indexNode = () => ({ children: /* @__PURE__ */ new Map() });
|
|
1159
1161
|
const hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
1160
|
-
const sameAddress = (left, right) => {
|
|
1162
|
+
const sameAddress$1 = (left, right) => {
|
|
1161
1163
|
if (left.length !== right.length) return false;
|
|
1162
1164
|
for (let index = 0; index < left.length; index += 1) if (left[index] !== right[index]) return false;
|
|
1163
1165
|
return true;
|
|
@@ -1258,7 +1260,7 @@ const restoreRootSubject = (value, subject) => {
|
|
|
1258
1260
|
if (subject.kind === "value") return subject.before.status === "present" ? subject.before.value : void 0;
|
|
1259
1261
|
if (subject.kind === "variant") return subject.before;
|
|
1260
1262
|
if (subject.kind === "dict") {
|
|
1261
|
-
if (
|
|
1263
|
+
if (require_ownership.isRecord(value)) restoreDict(value, subject.state);
|
|
1262
1264
|
return value;
|
|
1263
1265
|
}
|
|
1264
1266
|
if (subject.kind === "entity") {
|
|
@@ -1272,7 +1274,7 @@ const restoreRootSubject = (value, subject) => {
|
|
|
1272
1274
|
return restoreChange(value, subject.state);
|
|
1273
1275
|
};
|
|
1274
1276
|
const restoreSubject = (value, prefix, subject) => {
|
|
1275
|
-
if (sameAddress(prefix, subject.address)) return restoreRootSubject(value, subject);
|
|
1277
|
+
if (sameAddress$1(prefix, subject.address)) return restoreRootSubject(value, subject);
|
|
1276
1278
|
const address = subject.address.slice(prefix.length);
|
|
1277
1279
|
if (subject.kind === "value") {
|
|
1278
1280
|
writePresence(value, address, subject.before);
|
|
@@ -1284,7 +1286,7 @@ const restoreSubject = (value, prefix, subject) => {
|
|
|
1284
1286
|
}
|
|
1285
1287
|
const current = require_dependency.read(value, address);
|
|
1286
1288
|
if (subject.kind === "dict") {
|
|
1287
|
-
if (
|
|
1289
|
+
if (require_ownership.isRecord(current)) restoreDict(current, subject.state);
|
|
1288
1290
|
return value;
|
|
1289
1291
|
}
|
|
1290
1292
|
if (subject.kind === "entity") {
|
|
@@ -1307,8 +1309,8 @@ const valueChanged = (root, subject) => {
|
|
|
1307
1309
|
};
|
|
1308
1310
|
const dictChanged = (root, subject) => {
|
|
1309
1311
|
const value = require_dependency.read(root, subject.address);
|
|
1310
|
-
if (!
|
|
1311
|
-
if (subject.state.mode === "whole") return !
|
|
1312
|
+
if (!require_ownership.isRecord(value)) return true;
|
|
1313
|
+
if (subject.state.mode === "whole") return !require_ownership.sameStructuralValue(subject.state.value, value);
|
|
1312
1314
|
for (const [key, before] of subject.state.entries) {
|
|
1313
1315
|
const exists = hasOwn(value, key);
|
|
1314
1316
|
if (before.status === "absent" ? exists : !exists || !Object.is(before.value, value[key])) return true;
|
|
@@ -1318,7 +1320,7 @@ const dictChanged = (root, subject) => {
|
|
|
1318
1320
|
const listChanged = (root, subject) => {
|
|
1319
1321
|
const value = require_dependency.read(root, subject.address);
|
|
1320
1322
|
if (!Array.isArray(value)) return true;
|
|
1321
|
-
if (subject.state.mode === "whole") return !
|
|
1323
|
+
if (subject.state.mode === "whole") return !require_ownership.sameStructuralValue(subject.state.value, value);
|
|
1322
1324
|
const positions = /* @__PURE__ */ new Map();
|
|
1323
1325
|
const order = new Array(value.length);
|
|
1324
1326
|
for (let index = 0; index < value.length; index += 1) {
|
|
@@ -1331,7 +1333,7 @@ const listChanged = (root, subject) => {
|
|
|
1331
1333
|
const position = positions.get(key);
|
|
1332
1334
|
if (before.status === "absent") {
|
|
1333
1335
|
if (position !== void 0) return true;
|
|
1334
|
-
} else if (position === void 0 || !
|
|
1336
|
+
} else if (position === void 0 || !require_ownership.sameStructuralValue(before.value, value[position])) return true;
|
|
1335
1337
|
}
|
|
1336
1338
|
return false;
|
|
1337
1339
|
};
|
|
@@ -1365,7 +1367,7 @@ const analyzeEntity = (root, subject) => {
|
|
|
1365
1367
|
if (before.status === "absent") {
|
|
1366
1368
|
if (exists) added.add(id);
|
|
1367
1369
|
} else if (!exists) removed.add(id);
|
|
1368
|
-
else if (!
|
|
1370
|
+
else if (!require_ownership.sameStructuralValue(before.value, collection.byId[id])) updated.add(id);
|
|
1369
1371
|
}
|
|
1370
1372
|
const beforeOrder = subject.order.kind === "tracked" ? subject.order.before : void 0;
|
|
1371
1373
|
const finalOrder = collection.kind === "table" ? collection.ids : [];
|
|
@@ -1380,7 +1382,7 @@ const analyzeEntity = (root, subject) => {
|
|
|
1380
1382
|
};
|
|
1381
1383
|
const subjectChanged = (root, subject) => {
|
|
1382
1384
|
if (subject.kind === "value") return valueChanged(root, subject);
|
|
1383
|
-
if (subject.kind === "variant") return !
|
|
1385
|
+
if (subject.kind === "variant") return !require_ownership.sameStructuralValue(subject.before, require_dependency.read(root, subject.address));
|
|
1384
1386
|
if (subject.kind === "dict") return dictChanged(root, subject);
|
|
1385
1387
|
if (subject.kind === "list") return listChanged(root, subject);
|
|
1386
1388
|
return changeChanged(subject.state, require_dependency.read(root, subject.address));
|
|
@@ -1469,7 +1471,7 @@ const createChangeJournal = (root) => {
|
|
|
1469
1471
|
}
|
|
1470
1472
|
if (node.subject) throw new Error(`Change journal already owns '${subject.address.join(".")}'.`);
|
|
1471
1473
|
node.subject = subject;
|
|
1472
|
-
|
|
1474
|
+
require_ownership.profile.journal.subject();
|
|
1473
1475
|
return subject;
|
|
1474
1476
|
};
|
|
1475
1477
|
const remove = (subject) => {
|
|
@@ -1498,8 +1500,8 @@ const createChangeJournal = (root) => {
|
|
|
1498
1500
|
function find(kind, address, addressHash) {
|
|
1499
1501
|
const candidates = buckets.get(addressHash) ?? [];
|
|
1500
1502
|
for (const subject of candidates) {
|
|
1501
|
-
|
|
1502
|
-
if (subject.kind === kind && sameAddress(subject.address, address)) return subject;
|
|
1503
|
+
require_ownership.profile.journal.comparison();
|
|
1504
|
+
if (subject.kind === kind && sameAddress$1(subject.address, address)) return subject;
|
|
1503
1505
|
}
|
|
1504
1506
|
}
|
|
1505
1507
|
const ownerOf = (address) => {
|
|
@@ -1515,11 +1517,11 @@ const createChangeJournal = (root) => {
|
|
|
1515
1517
|
const subjects = indexedSubjects(index, address);
|
|
1516
1518
|
if (subjects.length === 0) return value;
|
|
1517
1519
|
subjects.sort((left, right) => left.address.length - right.address.length);
|
|
1518
|
-
let before =
|
|
1520
|
+
let before = require_ownership.ownPayload(value, "journal");
|
|
1519
1521
|
for (const subject of subjects) before = restoreSubject(before, address, subject);
|
|
1520
1522
|
for (const subject of subjects) {
|
|
1521
1523
|
remove(subject);
|
|
1522
|
-
|
|
1524
|
+
require_ownership.profile.journal.absorbed();
|
|
1523
1525
|
}
|
|
1524
1526
|
return before;
|
|
1525
1527
|
};
|
|
@@ -1561,7 +1563,7 @@ const createChangeJournal = (root) => {
|
|
|
1561
1563
|
});
|
|
1562
1564
|
if (subject.state.mode === "whole") return;
|
|
1563
1565
|
if (first.type === "dict.replace") {
|
|
1564
|
-
const value =
|
|
1566
|
+
const value = require_ownership.ownPayload(first.value, "journal");
|
|
1565
1567
|
restoreDict(value, subject.state);
|
|
1566
1568
|
subject.state = {
|
|
1567
1569
|
mode: "whole",
|
|
@@ -1605,7 +1607,7 @@ const createChangeJournal = (root) => {
|
|
|
1605
1607
|
}
|
|
1606
1608
|
if (subject.state.mode === "whole") return;
|
|
1607
1609
|
if (first.type === "list.replace") {
|
|
1608
|
-
const value = Array.from(
|
|
1610
|
+
const value = Array.from(require_ownership.ownPayload(first.value, "journal"));
|
|
1609
1611
|
restoreList(value, subject);
|
|
1610
1612
|
subject.state = {
|
|
1611
1613
|
mode: "whole",
|
|
@@ -1618,7 +1620,7 @@ const createChangeJournal = (root) => {
|
|
|
1618
1620
|
};
|
|
1619
1621
|
const trackEntityOrder = (subject, collection) => {
|
|
1620
1622
|
if (subject.order.kind !== "stable") return;
|
|
1621
|
-
|
|
1623
|
+
require_ownership.profile.journal.orderSnapshot(collection.ids.length);
|
|
1622
1624
|
const before = [...collection.ids];
|
|
1623
1625
|
restoreEntityOrder(before, subject.order.inverses);
|
|
1624
1626
|
subject.order = {
|
|
@@ -1679,7 +1681,7 @@ const createChangeJournal = (root) => {
|
|
|
1679
1681
|
};
|
|
1680
1682
|
return {
|
|
1681
1683
|
record: (resolved, operation, inverse) => {
|
|
1682
|
-
|
|
1684
|
+
require_ownership.profile.batch.journalRecord();
|
|
1683
1685
|
if (ownerOf(operation.at)) return;
|
|
1684
1686
|
if (operation.type === "field.set" || operation.type === "field.clear") {
|
|
1685
1687
|
recordValue(resolved, operation, inverse);
|
|
@@ -1707,7 +1709,7 @@ const createChangeJournal = (root) => {
|
|
|
1707
1709
|
const changed = [];
|
|
1708
1710
|
const entityChanges = /* @__PURE__ */ new Map();
|
|
1709
1711
|
for (const subject of active) {
|
|
1710
|
-
|
|
1712
|
+
require_ownership.profile.journal.comparison();
|
|
1711
1713
|
if (subject.kind === "entity") {
|
|
1712
1714
|
const analysis = analyzeEntity(root, subject);
|
|
1713
1715
|
if (!analysis.changed) continue;
|
|
@@ -1721,7 +1723,7 @@ const createChangeJournal = (root) => {
|
|
|
1721
1723
|
const changeAt = (address, addressHash) => {
|
|
1722
1724
|
const candidates = collectionBuckets.get(addressHash) ?? [];
|
|
1723
1725
|
collectionBuckets.set(addressHash, candidates);
|
|
1724
|
-
let change = candidates.find((entry) => sameAddress(entry.address, address));
|
|
1726
|
+
let change = candidates.find((entry) => sameAddress$1(entry.address, address));
|
|
1725
1727
|
if (!change) {
|
|
1726
1728
|
change = {
|
|
1727
1729
|
address,
|
|
@@ -1765,9 +1767,9 @@ const createChangeJournal = (root) => {
|
|
|
1765
1767
|
const has = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
1766
1768
|
const stringArray = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
1767
1769
|
const positions = (value) => Array.isArray(value) && value.every((entry) => Number.isInteger(entry) && entry >= 0);
|
|
1768
|
-
const address = (value) => stringArray(value);
|
|
1770
|
+
const address$1 = (value) => stringArray(value);
|
|
1769
1771
|
const anchor = (value) => {
|
|
1770
|
-
if (!
|
|
1772
|
+
if (!require_ownership.isRecord(value)) return false;
|
|
1771
1773
|
if (Number(has(value, "at")) + Number(has(value, "before")) + Number(has(value, "after")) !== 1) return false;
|
|
1772
1774
|
if (has(value, "at")) return value.at === "start" || value.at === "end";
|
|
1773
1775
|
return typeof (has(value, "before") ? value.before : value.after) === "string";
|
|
@@ -1775,7 +1777,7 @@ const anchor = (value) => {
|
|
|
1775
1777
|
const optionalAnchor = (value) => !has(value, "anchor") || value.anchor === void 0 || anchor(value.anchor);
|
|
1776
1778
|
const optionalParent = (value) => !has(value, "parentId") || value.parentId === void 0 || typeof value.parentId === "string";
|
|
1777
1779
|
const optionalIndex = (value) => !has(value, "index") || value.index === void 0 || Number.isInteger(value.index) && value.index >= 0;
|
|
1778
|
-
const entries = (value) => Array.isArray(value) && value.every((entry) =>
|
|
1780
|
+
const entries = (value) => Array.isArray(value) && value.every((entry) => require_ownership.isRecord(entry) && typeof entry.id === "string" && has(entry, "value"));
|
|
1779
1781
|
const decoded = (operation) => ({
|
|
1780
1782
|
status: "decoded",
|
|
1781
1783
|
operation
|
|
@@ -1785,8 +1787,8 @@ const rejected = (code, message) => ({
|
|
|
1785
1787
|
issue: input(code, message)
|
|
1786
1788
|
});
|
|
1787
1789
|
const decode = (input) => {
|
|
1788
|
-
if (!
|
|
1789
|
-
if (!address(input.at)) return rejected("invalid-address", "Operation address is malformed.");
|
|
1790
|
+
if (!require_ownership.isRecord(input)) return rejected("invalid-operation", "Operation must be an object.");
|
|
1791
|
+
if (!address$1(input.at)) return rejected("invalid-address", "Operation address is malformed.");
|
|
1790
1792
|
if (typeof input.type !== "string") return rejected("invalid-operation", "Operation type must be a string.");
|
|
1791
1793
|
switch (input.type) {
|
|
1792
1794
|
case "field.set":
|
|
@@ -1794,7 +1796,7 @@ const decode = (input) => {
|
|
|
1794
1796
|
case "field.clear": return decoded(input);
|
|
1795
1797
|
case "dict.set": return typeof input.key === "string" && has(input, "value") ? decoded(input) : rejected("invalid-operation", "Dictionary set requires a string key and value.");
|
|
1796
1798
|
case "dict.delete": return typeof input.key === "string" ? decoded(input) : rejected("invalid-operation", "Dictionary delete requires a string key.");
|
|
1797
|
-
case "dict.replace": return
|
|
1799
|
+
case "dict.replace": return require_ownership.isRecord(input.value) ? decoded(input) : rejected("invalid-operation", "Dictionary replacement must be an object.");
|
|
1798
1800
|
case "entity.create": return entries(input.entries) && optionalAnchor(input) && (!has(input, "positions") || input.positions === void 0 || positions(input.positions)) ? decoded(input) : rejected("invalid-operation", "Entity create payload is malformed.");
|
|
1799
1801
|
case "entity.remove": return stringArray(input.ids) ? decoded(input) : rejected("invalid-operation", "Entity remove requires string ids.");
|
|
1800
1802
|
case "entity.move": return typeof input.id === "string" && optionalAnchor(input) ? decoded(input) : rejected("invalid-operation", "Entity move payload is malformed.");
|
|
@@ -1819,11 +1821,12 @@ const decodeBatch = (input$1) => Array.isArray(input$1) ? {
|
|
|
1819
1821
|
};
|
|
1820
1822
|
const ownAddress = (value) => {
|
|
1821
1823
|
if (Object.isFrozen(value)) return value;
|
|
1822
|
-
|
|
1824
|
+
require_ownership.profile.address.arrayCopied();
|
|
1823
1825
|
return Object.freeze(value.slice());
|
|
1824
1826
|
};
|
|
1827
|
+
const structuralPayload = (value) => Array.isArray(value) || require_ownership.isPlainObject(value);
|
|
1825
1828
|
const normalize = (operation) => {
|
|
1826
|
-
|
|
1829
|
+
require_ownership.profile.mutation.normalized();
|
|
1827
1830
|
const copy = {
|
|
1828
1831
|
...operation,
|
|
1829
1832
|
at: ownAddress(operation.at)
|
|
@@ -1836,23 +1839,34 @@ const normalize = (operation) => {
|
|
|
1836
1839
|
return Object.freeze(copy);
|
|
1837
1840
|
};
|
|
1838
1841
|
const publish = (operation) => {
|
|
1839
|
-
if (!
|
|
1840
|
-
if (
|
|
1842
|
+
if (operation.type === "entity.create" && operation.entries.every((entry) => !structuralPayload(entry.value) || require_ownership.isStablePayload(entry.value))) return operation;
|
|
1843
|
+
if ("value" in operation && (!structuralPayload(operation.value) || require_ownership.isStablePayload(operation.value))) return operation;
|
|
1841
1844
|
const copy = { ...operation };
|
|
1842
1845
|
if (copy.entries) copy.entries = Object.freeze(copy.entries.map((entry) => Object.freeze({
|
|
1843
1846
|
id: entry.id,
|
|
1844
|
-
value:
|
|
1847
|
+
value: structuralPayload(entry.value) ? require_ownership.isStablePayload(entry.value) ? entry.value : require_ownership.snapshotPayload(entry.value, "commit") : entry.value
|
|
1845
1848
|
})));
|
|
1846
|
-
else if ("value" in copy) copy.value =
|
|
1849
|
+
else if ("value" in copy && structuralPayload(copy.value)) copy.value = require_ownership.isStablePayload(copy.value) ? copy.value : require_ownership.snapshotPayload(copy.value, "commit");
|
|
1847
1850
|
return Object.freeze(copy);
|
|
1848
1851
|
};
|
|
1852
|
+
const requiresPayloadCopy = (operation) => {
|
|
1853
|
+
if (operation.type === "entity.create") return operation.entries.some((entry) => require_ownership.isStablePayload(entry.value));
|
|
1854
|
+
return "value" in operation && require_ownership.isStablePayload(operation.value);
|
|
1855
|
+
};
|
|
1849
1856
|
const inverse = (operation) => {
|
|
1850
1857
|
const copy = { ...operation };
|
|
1851
1858
|
if (copy.anchor) copy.anchor = Object.freeze({ ...copy.anchor });
|
|
1852
1859
|
if (copy.keys) copy.keys = Object.freeze([...copy.keys]);
|
|
1853
|
-
if (copy.entries) copy.entries = Object.freeze(copy.entries.map((entry) => Object.freeze({
|
|
1860
|
+
if (copy.entries) copy.entries = Object.freeze(copy.entries.map((entry) => Object.freeze({
|
|
1861
|
+
id: entry.id,
|
|
1862
|
+
value: structuralPayload(entry.value) ? require_ownership.isStablePayload(entry.value) ? entry.value : require_ownership.snapshotPayload(entry.value, "inverse") : entry.value
|
|
1863
|
+
})));
|
|
1854
1864
|
if (copy.ids) copy.ids = Object.freeze([...copy.ids]);
|
|
1855
1865
|
if (copy.positions) copy.positions = Object.freeze([...copy.positions]);
|
|
1866
|
+
if ("value" in copy && structuralPayload(copy.value)) {
|
|
1867
|
+
const payload = copy;
|
|
1868
|
+
payload.value = require_ownership.isStablePayload(payload.value) ? payload.value : require_ownership.snapshotPayload(payload.value, "inverse");
|
|
1869
|
+
}
|
|
1856
1870
|
return Object.freeze(copy);
|
|
1857
1871
|
};
|
|
1858
1872
|
//#endregion
|
|
@@ -1860,32 +1874,32 @@ const inverse = (operation) => {
|
|
|
1860
1874
|
const createMutationSession = (root, schema, options = {}) => {
|
|
1861
1875
|
const steps = [];
|
|
1862
1876
|
const journal = createChangeJournal(root);
|
|
1863
|
-
let
|
|
1877
|
+
let state = "active";
|
|
1864
1878
|
const rollback = () => {
|
|
1865
|
-
if (
|
|
1879
|
+
if (state === "rolled-back") return;
|
|
1866
1880
|
for (let stepIndex = steps.length - 1; stepIndex >= 0; stepIndex -= 1) for (const inverse of steps[stepIndex].inverse) {
|
|
1867
1881
|
const result = execute(root, inverse, require_dependency.resolveLocated(schema, root, inverse.at), true);
|
|
1868
1882
|
if (result.status === "rejected") throw new Error(`Document rollback failed: ${result.issue.message}`);
|
|
1869
1883
|
}
|
|
1870
|
-
|
|
1884
|
+
state = "rolled-back";
|
|
1871
1885
|
};
|
|
1872
1886
|
return {
|
|
1873
1887
|
apply: (input) => {
|
|
1874
|
-
if (
|
|
1875
|
-
|
|
1888
|
+
if (state !== "active") throw new Error("Mutation session is closed.");
|
|
1889
|
+
require_ownership.profile.batch.operation();
|
|
1876
1890
|
const decoded = decode(input);
|
|
1877
1891
|
if (decoded.status === "rejected") {
|
|
1878
|
-
|
|
1892
|
+
require_ownership.profile.batch.rejected();
|
|
1879
1893
|
return decoded.issue;
|
|
1880
1894
|
}
|
|
1881
1895
|
const normalized = normalize(decoded.operation);
|
|
1882
|
-
|
|
1896
|
+
require_ownership.profile.batch.entry(normalized.type === "entity.create" ? normalized.entries.length : normalized.type === "entity.remove" ? normalized.ids.length : 1);
|
|
1883
1897
|
const resolved = require_dependency.resolveLocated(schema, root, normalized.at);
|
|
1884
|
-
if (resolved?.collection)
|
|
1885
|
-
|
|
1886
|
-
const result = execute(root, normalized, resolved, options.copyPayload === true);
|
|
1898
|
+
if (resolved?.collection) require_ownership.profile.batch.collectionResolved();
|
|
1899
|
+
require_ownership.profile.mutation.executed();
|
|
1900
|
+
const result = execute(root, normalized, resolved, options.copyPayload === true || requiresPayloadCopy(normalized));
|
|
1887
1901
|
if (result.status === "rejected") {
|
|
1888
|
-
|
|
1902
|
+
require_ownership.profile.batch.rejected();
|
|
1889
1903
|
return result.issue;
|
|
1890
1904
|
}
|
|
1891
1905
|
if (result.status === "unchanged") return void 0;
|
|
@@ -1894,8 +1908,8 @@ const createMutationSession = (root, schema, options = {}) => {
|
|
|
1894
1908
|
for (const rawInverse of result.inverse) {
|
|
1895
1909
|
const inverse$1 = inverse(rawInverse);
|
|
1896
1910
|
group.push(inverse$1);
|
|
1897
|
-
|
|
1898
|
-
|
|
1911
|
+
require_ownership.profile.mutation.inverse();
|
|
1912
|
+
require_ownership.profile.batch.inverse();
|
|
1899
1913
|
}
|
|
1900
1914
|
steps.push({
|
|
1901
1915
|
forward: published,
|
|
@@ -1910,9 +1924,9 @@ const createMutationSession = (root, schema, options = {}) => {
|
|
|
1910
1924
|
}
|
|
1911
1925
|
},
|
|
1912
1926
|
finish: () => {
|
|
1913
|
-
if (
|
|
1914
|
-
closed = true;
|
|
1927
|
+
if (state !== "active") throw new Error("Mutation session is closed.");
|
|
1915
1928
|
const changes = journal.finish();
|
|
1929
|
+
state = "finished";
|
|
1916
1930
|
if (changes.status === "unchanged") return { status: "unchanged" };
|
|
1917
1931
|
let inverseCount = 0;
|
|
1918
1932
|
for (const step of steps) inverseCount += step.inverse.length;
|
|
@@ -1949,6 +1963,191 @@ const mutateOperations = (root, schema, operations, options = {}) => {
|
|
|
1949
1963
|
return session.finish();
|
|
1950
1964
|
};
|
|
1951
1965
|
//#endregion
|
|
1966
|
+
//#region core/src/mutation/footprint.ts
|
|
1967
|
+
const sameAddress = (left, right) => left.length === right.length && left.every((segment, index) => segment === right[index]);
|
|
1968
|
+
const containsAddress = (parent, child) => parent.length <= child.length && parent.every((segment, index) => segment === child[index]);
|
|
1969
|
+
const address = (value) => Array.isArray(value) && value.every((segment) => typeof segment === "string") ? Object.freeze(value.slice()) : void 0;
|
|
1970
|
+
const targetKey = (target) => {
|
|
1971
|
+
const at = target.at.join("\0");
|
|
1972
|
+
if (target.kind === "dictionary-key" || target.kind === "list-item") return `${target.kind}:${at}:${target.key}`;
|
|
1973
|
+
if (target.kind === "entity" || target.kind === "tree-node") return `${target.kind}:${at}:${target.id}`;
|
|
1974
|
+
return `${target.kind}:${at}`;
|
|
1975
|
+
};
|
|
1976
|
+
const freezeTarget = (target) => Object.freeze({
|
|
1977
|
+
...target,
|
|
1978
|
+
at: Object.freeze(target.at.slice())
|
|
1979
|
+
});
|
|
1980
|
+
const add = (targets, target) => {
|
|
1981
|
+
const stable = freezeTarget(target);
|
|
1982
|
+
targets.set(targetKey(stable), stable);
|
|
1983
|
+
};
|
|
1984
|
+
const commandFootprint = (operations) => {
|
|
1985
|
+
const targets = /* @__PURE__ */ new Map();
|
|
1986
|
+
for (const operation of operations) switch (operation.type) {
|
|
1987
|
+
case "field.set":
|
|
1988
|
+
case "field.clear":
|
|
1989
|
+
case "variant.replace":
|
|
1990
|
+
add(targets, {
|
|
1991
|
+
kind: "value",
|
|
1992
|
+
at: operation.at
|
|
1993
|
+
});
|
|
1994
|
+
break;
|
|
1995
|
+
case "dict.replace":
|
|
1996
|
+
add(targets, {
|
|
1997
|
+
kind: "dictionary",
|
|
1998
|
+
at: operation.at
|
|
1999
|
+
});
|
|
2000
|
+
break;
|
|
2001
|
+
case "dict.set":
|
|
2002
|
+
case "dict.delete":
|
|
2003
|
+
add(targets, {
|
|
2004
|
+
kind: "dictionary-key",
|
|
2005
|
+
at: operation.at,
|
|
2006
|
+
key: operation.key
|
|
2007
|
+
});
|
|
2008
|
+
break;
|
|
2009
|
+
case "entity.create":
|
|
2010
|
+
add(targets, {
|
|
2011
|
+
kind: "collection",
|
|
2012
|
+
at: operation.at
|
|
2013
|
+
});
|
|
2014
|
+
for (const entry of operation.entries) add(targets, {
|
|
2015
|
+
kind: "entity",
|
|
2016
|
+
at: operation.at,
|
|
2017
|
+
id: entry.id
|
|
2018
|
+
});
|
|
2019
|
+
break;
|
|
2020
|
+
case "entity.remove":
|
|
2021
|
+
add(targets, {
|
|
2022
|
+
kind: "collection",
|
|
2023
|
+
at: operation.at
|
|
2024
|
+
});
|
|
2025
|
+
for (const id of operation.ids) add(targets, {
|
|
2026
|
+
kind: "entity",
|
|
2027
|
+
at: operation.at,
|
|
2028
|
+
id
|
|
2029
|
+
});
|
|
2030
|
+
break;
|
|
2031
|
+
case "entity.move":
|
|
2032
|
+
add(targets, {
|
|
2033
|
+
kind: "collection",
|
|
2034
|
+
at: operation.at
|
|
2035
|
+
});
|
|
2036
|
+
add(targets, {
|
|
2037
|
+
kind: "entity",
|
|
2038
|
+
at: operation.at,
|
|
2039
|
+
id: operation.id
|
|
2040
|
+
});
|
|
2041
|
+
break;
|
|
2042
|
+
case "list.insert":
|
|
2043
|
+
case "list.move":
|
|
2044
|
+
case "list.remove":
|
|
2045
|
+
add(targets, {
|
|
2046
|
+
kind: "list",
|
|
2047
|
+
at: operation.at
|
|
2048
|
+
});
|
|
2049
|
+
add(targets, {
|
|
2050
|
+
kind: "list-item",
|
|
2051
|
+
at: operation.at,
|
|
2052
|
+
key: operation.key
|
|
2053
|
+
});
|
|
2054
|
+
break;
|
|
2055
|
+
case "list.replace":
|
|
2056
|
+
add(targets, {
|
|
2057
|
+
kind: "list",
|
|
2058
|
+
at: operation.at
|
|
2059
|
+
});
|
|
2060
|
+
for (const key of operation.keys) add(targets, {
|
|
2061
|
+
kind: "list-item",
|
|
2062
|
+
at: operation.at,
|
|
2063
|
+
key
|
|
2064
|
+
});
|
|
2065
|
+
break;
|
|
2066
|
+
case "tree.insert":
|
|
2067
|
+
case "tree.move":
|
|
2068
|
+
case "tree.remove":
|
|
2069
|
+
case "tree.set":
|
|
2070
|
+
add(targets, {
|
|
2071
|
+
kind: "tree",
|
|
2072
|
+
at: operation.at
|
|
2073
|
+
});
|
|
2074
|
+
add(targets, {
|
|
2075
|
+
kind: "tree-node",
|
|
2076
|
+
at: operation.at,
|
|
2077
|
+
id: operation.treeNodeId
|
|
2078
|
+
});
|
|
2079
|
+
break;
|
|
2080
|
+
case "tree.replace":
|
|
2081
|
+
add(targets, {
|
|
2082
|
+
kind: "tree",
|
|
2083
|
+
at: operation.at
|
|
2084
|
+
});
|
|
2085
|
+
break;
|
|
2086
|
+
}
|
|
2087
|
+
return Object.freeze(Array.from(targets.values()));
|
|
2088
|
+
};
|
|
2089
|
+
const overlapsValueAndEntity = (value, entity) => containsAddress([...entity.at, entity.id], value.at) || containsAddress(value.at, [...entity.at, entity.id]);
|
|
2090
|
+
const targetsOverlap = (left, right) => {
|
|
2091
|
+
if (left.kind === "value" && right.kind === "value") return containsAddress(left.at, right.at) || containsAddress(right.at, left.at);
|
|
2092
|
+
if (left.kind === "value" && right.kind === "entity") return overlapsValueAndEntity(left, right);
|
|
2093
|
+
if (left.kind === "entity" && right.kind === "value") return overlapsValueAndEntity(right, left);
|
|
2094
|
+
if (left.kind === "dictionary" && right.kind === "dictionary") return sameAddress(left.at, right.at);
|
|
2095
|
+
if (left.kind === "dictionary" && right.kind === "dictionary-key") return sameAddress(left.at, right.at);
|
|
2096
|
+
if (left.kind === "dictionary-key" && right.kind === "dictionary") return sameAddress(left.at, right.at);
|
|
2097
|
+
if (left.kind === "dictionary-key" && right.kind === "dictionary-key") return sameAddress(left.at, right.at) && left.key === right.key;
|
|
2098
|
+
if (left.kind === "collection" && right.kind === "collection") return sameAddress(left.at, right.at);
|
|
2099
|
+
if (left.kind === "collection" && right.kind === "entity") return sameAddress(left.at, right.at);
|
|
2100
|
+
if (left.kind === "entity" && right.kind === "collection") return sameAddress(left.at, right.at);
|
|
2101
|
+
if (left.kind === "entity" && right.kind === "entity") return sameAddress(left.at, right.at) && left.id === right.id;
|
|
2102
|
+
if (left.kind === "list" && (right.kind === "list" || right.kind === "list-item")) return sameAddress(left.at, right.at);
|
|
2103
|
+
if (right.kind === "list" && left.kind === "list-item") return sameAddress(left.at, right.at);
|
|
2104
|
+
if (left.kind === "list-item" && right.kind === "list-item") return sameAddress(left.at, right.at) && left.key === right.key;
|
|
2105
|
+
if (left.kind === "tree" && (right.kind === "tree" || right.kind === "tree-node")) return sameAddress(left.at, right.at);
|
|
2106
|
+
if (right.kind === "tree" && left.kind === "tree-node") return sameAddress(left.at, right.at);
|
|
2107
|
+
if (left.kind === "tree-node" && right.kind === "tree-node") return sameAddress(left.at, right.at) && left.id === right.id;
|
|
2108
|
+
return false;
|
|
2109
|
+
};
|
|
2110
|
+
const footprintsOverlap = (left, right) => left.some((leftTarget) => right.some((rightTarget) => targetsOverlap(leftTarget, rightTarget)));
|
|
2111
|
+
const decodedTarget = (value) => {
|
|
2112
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
2113
|
+
const record = value;
|
|
2114
|
+
const at = address(record.at);
|
|
2115
|
+
if (!at || typeof record.kind !== "string") return void 0;
|
|
2116
|
+
switch (record.kind) {
|
|
2117
|
+
case "value":
|
|
2118
|
+
case "dictionary":
|
|
2119
|
+
case "collection":
|
|
2120
|
+
case "list":
|
|
2121
|
+
case "tree": return freezeTarget({
|
|
2122
|
+
kind: record.kind,
|
|
2123
|
+
at
|
|
2124
|
+
});
|
|
2125
|
+
case "dictionary-key":
|
|
2126
|
+
case "list-item": return typeof record.key === "string" ? freezeTarget({
|
|
2127
|
+
kind: record.kind,
|
|
2128
|
+
at,
|
|
2129
|
+
key: record.key
|
|
2130
|
+
}) : void 0;
|
|
2131
|
+
case "entity":
|
|
2132
|
+
case "tree-node": return typeof record.id === "string" ? freezeTarget({
|
|
2133
|
+
kind: record.kind,
|
|
2134
|
+
at,
|
|
2135
|
+
id: record.id
|
|
2136
|
+
}) : void 0;
|
|
2137
|
+
default: return;
|
|
2138
|
+
}
|
|
2139
|
+
};
|
|
2140
|
+
const decodeCommandFootprint = (value) => {
|
|
2141
|
+
if (!Array.isArray(value)) return void 0;
|
|
2142
|
+
const targets = /* @__PURE__ */ new Map();
|
|
2143
|
+
for (const entry of value) {
|
|
2144
|
+
const target = decodedTarget(entry);
|
|
2145
|
+
if (!target) return void 0;
|
|
2146
|
+
targets.set(targetKey(target), target);
|
|
2147
|
+
}
|
|
2148
|
+
return Object.freeze(Array.from(targets.values()));
|
|
2149
|
+
};
|
|
2150
|
+
//#endregion
|
|
1952
2151
|
//#region core/src/runtime/notification.ts
|
|
1953
2152
|
const ROOT_BUCKET = Symbol("document-root");
|
|
1954
2153
|
const notifications = /* @__PURE__ */ new WeakMap();
|
|
@@ -1971,6 +2170,9 @@ const notificationOf = (runtime) => {
|
|
|
1971
2170
|
if (!value) throw new Error("Unknown Doxum runtime.");
|
|
1972
2171
|
return value;
|
|
1973
2172
|
};
|
|
2173
|
+
const shareNotification = (source, target) => {
|
|
2174
|
+
notifications.set(target, notificationOf(source));
|
|
2175
|
+
};
|
|
1974
2176
|
const registerProcessor = (runtime, processor) => {
|
|
1975
2177
|
const notification = notificationOf(runtime);
|
|
1976
2178
|
const entry = {
|
|
@@ -2122,20 +2324,57 @@ const publishDiagnostic = (value) => Object.freeze({
|
|
|
2122
2324
|
const createDocument = (input) => {
|
|
2123
2325
|
const initialTreeError = invalidDocument(input.schema, input.initial);
|
|
2124
2326
|
if (initialTreeError) throw new TypeError(`Initial document contains an invalid tree at '${initialTreeError.join(".")}'.`);
|
|
2125
|
-
|
|
2327
|
+
require_ownership.profile.clone.initialDocument();
|
|
2126
2328
|
const state = {
|
|
2127
2329
|
schema: input.schema,
|
|
2128
|
-
document:
|
|
2330
|
+
document: require_ownership.cloneValue(input.initial, "initial"),
|
|
2129
2331
|
disposed: false
|
|
2130
2332
|
};
|
|
2131
2333
|
let revision = 0;
|
|
2132
2334
|
let busy = false;
|
|
2133
2335
|
let runtime;
|
|
2134
2336
|
let notification;
|
|
2135
|
-
const assertWritable = () => {
|
|
2337
|
+
const assertWritable = (intent) => {
|
|
2136
2338
|
if (state.disposed) throw new require_dependency.DocumentDisposedError();
|
|
2137
2339
|
if (busy) throw new require_dependency.DocumentReentrancyError();
|
|
2340
|
+
require_driver.assertRuntimeWritable(runtime, intent);
|
|
2341
|
+
};
|
|
2342
|
+
const runTransaction = (session, run) => {
|
|
2343
|
+
let reports;
|
|
2344
|
+
let active = true;
|
|
2345
|
+
const transaction = {
|
|
2346
|
+
read: require_dependency.documentReader(input.schema, () => state.document, () => active),
|
|
2347
|
+
write: documentWriter(input.schema, (operation) => {
|
|
2348
|
+
if (!active) throw new Error("Document writer is no longer active.");
|
|
2349
|
+
const rejected = session.apply(operation);
|
|
2350
|
+
if (rejected) throw new RejectedUpdate([rejected]);
|
|
2351
|
+
}),
|
|
2352
|
+
reject: (diagnostic) => {
|
|
2353
|
+
throw new RejectedUpdate((Array.isArray(diagnostic) ? diagnostic : [diagnostic]).map((entry) => publishDiagnostic(entry)));
|
|
2354
|
+
},
|
|
2355
|
+
report: (diagnostic) => {
|
|
2356
|
+
if (!active) throw new Error("Document transaction is no longer active.");
|
|
2357
|
+
(reports ??= []).push(publishDiagnostic(diagnostic));
|
|
2358
|
+
}
|
|
2359
|
+
};
|
|
2360
|
+
try {
|
|
2361
|
+
const value = run(transaction);
|
|
2362
|
+
if (value !== null && typeof value === "object" && typeof value.then === "function") throw new TypeError("Document update callback must be synchronous.");
|
|
2363
|
+
return {
|
|
2364
|
+
value,
|
|
2365
|
+
reports: Object.freeze(reports ? reports.slice() : EMPTY)
|
|
2366
|
+
};
|
|
2367
|
+
} finally {
|
|
2368
|
+
active = false;
|
|
2369
|
+
}
|
|
2138
2370
|
};
|
|
2371
|
+
const impactFor = (batch, kind) => createImpact({
|
|
2372
|
+
schema: input.schema,
|
|
2373
|
+
operations: batch.operations,
|
|
2374
|
+
paths: batch.paths,
|
|
2375
|
+
collections: batch.collections,
|
|
2376
|
+
reset: kind === "replace"
|
|
2377
|
+
});
|
|
2139
2378
|
const history = createHistory({
|
|
2140
2379
|
capacity: input.history === false ? 0 : Math.max(0, input.history?.capacity ?? 100),
|
|
2141
2380
|
revision: () => revision,
|
|
@@ -2149,13 +2388,7 @@ const createDocument = (input) => {
|
|
|
2149
2388
|
source,
|
|
2150
2389
|
operations: batch.operations,
|
|
2151
2390
|
inverse: batch.inverse,
|
|
2152
|
-
impact:
|
|
2153
|
-
schema: input.schema,
|
|
2154
|
-
operations: batch.operations,
|
|
2155
|
-
paths: batch.paths,
|
|
2156
|
-
collections: batch.collections,
|
|
2157
|
-
reset: kind === "replace"
|
|
2158
|
-
})
|
|
2391
|
+
impact: impactFor(batch, kind)
|
|
2159
2392
|
});
|
|
2160
2393
|
if (kind === "replace" || source === "remote") history.invalidate();
|
|
2161
2394
|
else if (recordHistory && (source === "local" || source === "system")) history.record(batch.operations, batch.inverse);
|
|
@@ -2173,7 +2406,10 @@ const createDocument = (input) => {
|
|
|
2173
2406
|
};
|
|
2174
2407
|
};
|
|
2175
2408
|
function applyBatch(operations, source, recordHistory) {
|
|
2176
|
-
assertWritable(
|
|
2409
|
+
assertWritable({
|
|
2410
|
+
kind: "apply",
|
|
2411
|
+
source
|
|
2412
|
+
});
|
|
2177
2413
|
const batch = mutateOperations(state.document, input.schema, operations, { copyPayload: source === "history" });
|
|
2178
2414
|
if (batch.status === "rejected") return {
|
|
2179
2415
|
status: "rejected",
|
|
@@ -2187,6 +2423,7 @@ const createDocument = (input) => {
|
|
|
2187
2423
|
return publish(batch, source, "operations", recordHistory);
|
|
2188
2424
|
}
|
|
2189
2425
|
runtime = {
|
|
2426
|
+
schema: input.schema,
|
|
2190
2427
|
address: {
|
|
2191
2428
|
resolve: (address) => require_dependency.resolveAddress(input.schema, address, state.document),
|
|
2192
2429
|
read: (address) => require_dependency.read(state.document, address),
|
|
@@ -2196,55 +2433,40 @@ const createDocument = (input) => {
|
|
|
2196
2433
|
},
|
|
2197
2434
|
revision: () => revision,
|
|
2198
2435
|
update: (run, options) => {
|
|
2199
|
-
|
|
2436
|
+
const source = options?.source ?? "local";
|
|
2437
|
+
assertWritable({
|
|
2438
|
+
kind: "update",
|
|
2439
|
+
source
|
|
2440
|
+
});
|
|
2200
2441
|
busy = true;
|
|
2201
2442
|
const session = createMutationSession(state.document, input.schema);
|
|
2202
|
-
let
|
|
2203
|
-
let active = true;
|
|
2204
|
-
const transaction = {
|
|
2205
|
-
read: require_dependency.documentReader(input.schema, () => state.document, () => active),
|
|
2206
|
-
write: documentWriter(input.schema, (operation) => {
|
|
2207
|
-
if (!active) throw new Error("Document writer is no longer active.");
|
|
2208
|
-
const rejected = session.apply(operation);
|
|
2209
|
-
if (rejected) throw new RejectedUpdate([rejected]);
|
|
2210
|
-
}),
|
|
2211
|
-
reject: (diagnostic) => {
|
|
2212
|
-
throw new RejectedUpdate((Array.isArray(diagnostic) ? diagnostic : [diagnostic]).map((entry) => publishDiagnostic(entry)));
|
|
2213
|
-
},
|
|
2214
|
-
report: (diagnostic) => {
|
|
2215
|
-
if (!active) throw new Error("Document transaction is no longer active.");
|
|
2216
|
-
(reports ??= []).push(publishDiagnostic(diagnostic));
|
|
2217
|
-
}
|
|
2218
|
-
};
|
|
2443
|
+
let committed = false;
|
|
2219
2444
|
try {
|
|
2220
|
-
const value = run
|
|
2221
|
-
if (value !== null && typeof value === "object" && typeof value.then === "function") throw new TypeError("Document update callback must be synchronous.");
|
|
2222
|
-
active = false;
|
|
2223
|
-
busy = false;
|
|
2445
|
+
const { value, reports } = runTransaction(session, run);
|
|
2224
2446
|
const batch = session.finish();
|
|
2225
2447
|
if (batch.status === "unchanged") return {
|
|
2226
2448
|
status: "unchanged",
|
|
2227
2449
|
value,
|
|
2228
2450
|
revision,
|
|
2229
|
-
reports
|
|
2451
|
+
reports
|
|
2230
2452
|
};
|
|
2231
2453
|
if (batch.status === "rejected") return {
|
|
2232
2454
|
status: "rejected",
|
|
2233
2455
|
issues: batch.issues,
|
|
2234
2456
|
revision
|
|
2235
2457
|
};
|
|
2236
|
-
const result = publish(batch,
|
|
2458
|
+
const result = publish(batch, source, "operations", options?.history ?? true);
|
|
2459
|
+
committed = true;
|
|
2237
2460
|
return {
|
|
2238
2461
|
status: "committed",
|
|
2239
2462
|
value,
|
|
2240
2463
|
commit: result.commit,
|
|
2241
|
-
reports
|
|
2464
|
+
reports,
|
|
2242
2465
|
observerErrors: result.observerErrors
|
|
2243
2466
|
};
|
|
2244
2467
|
} catch (error) {
|
|
2245
|
-
active = false;
|
|
2246
2468
|
try {
|
|
2247
|
-
session.rollback();
|
|
2469
|
+
if (!committed) session.rollback();
|
|
2248
2470
|
} finally {
|
|
2249
2471
|
busy = false;
|
|
2250
2472
|
}
|
|
@@ -2255,31 +2477,86 @@ const createDocument = (input) => {
|
|
|
2255
2477
|
};
|
|
2256
2478
|
throw error;
|
|
2257
2479
|
} finally {
|
|
2258
|
-
|
|
2480
|
+
busy = false;
|
|
2481
|
+
}
|
|
2482
|
+
},
|
|
2483
|
+
prepare: (run) => {
|
|
2484
|
+
assertWritable({ kind: "prepare" });
|
|
2485
|
+
busy = true;
|
|
2486
|
+
const session = createMutationSession(state.document, input.schema);
|
|
2487
|
+
try {
|
|
2488
|
+
const { value, reports } = runTransaction(session, run);
|
|
2489
|
+
const batch = session.finish();
|
|
2490
|
+
if (batch.status === "unchanged") {
|
|
2491
|
+
session.rollback();
|
|
2492
|
+
return {
|
|
2493
|
+
status: "unchanged",
|
|
2494
|
+
value,
|
|
2495
|
+
reports
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
if (batch.status === "rejected") {
|
|
2499
|
+
session.rollback();
|
|
2500
|
+
return {
|
|
2501
|
+
status: "rejected",
|
|
2502
|
+
issues: batch.issues
|
|
2503
|
+
};
|
|
2504
|
+
}
|
|
2505
|
+
const impact = impactFor(batch, "operations");
|
|
2506
|
+
session.rollback();
|
|
2507
|
+
return {
|
|
2508
|
+
status: "prepared",
|
|
2509
|
+
value,
|
|
2510
|
+
operations: batch.operations,
|
|
2511
|
+
inverse: batch.inverse,
|
|
2512
|
+
impact,
|
|
2513
|
+
footprint: commandFootprint(batch.operations),
|
|
2514
|
+
reports
|
|
2515
|
+
};
|
|
2516
|
+
} catch (error) {
|
|
2517
|
+
try {
|
|
2518
|
+
session.rollback();
|
|
2519
|
+
} finally {
|
|
2520
|
+
busy = false;
|
|
2521
|
+
}
|
|
2522
|
+
if (error instanceof RejectedUpdate) return {
|
|
2523
|
+
status: "rejected",
|
|
2524
|
+
issues: error.issues
|
|
2525
|
+
};
|
|
2526
|
+
throw error;
|
|
2527
|
+
} finally {
|
|
2259
2528
|
busy = false;
|
|
2260
2529
|
}
|
|
2261
2530
|
},
|
|
2262
2531
|
apply: (operations, options) => applyBatch(operations, options?.source ?? "local", options?.history ?? true),
|
|
2263
2532
|
replace: (document, options) => {
|
|
2264
|
-
|
|
2533
|
+
const source = options?.source ?? "system";
|
|
2534
|
+
assertWritable({
|
|
2535
|
+
kind: "replace",
|
|
2536
|
+
source
|
|
2537
|
+
});
|
|
2265
2538
|
const invalidTree = invalidDocument(input.schema, document);
|
|
2266
2539
|
if (invalidTree) return {
|
|
2267
2540
|
status: "rejected",
|
|
2268
2541
|
issues: [at$1(invalidTree, "invalid-tree", "Document replacement contains an invalid tree.")],
|
|
2269
2542
|
revision
|
|
2270
2543
|
};
|
|
2271
|
-
if (
|
|
2544
|
+
if (require_ownership.deepEqual(state.document, document)) return {
|
|
2272
2545
|
status: "unchanged",
|
|
2273
2546
|
revision
|
|
2274
2547
|
};
|
|
2275
|
-
state.document =
|
|
2548
|
+
state.document = require_ownership.cloneValue(document, "replace");
|
|
2276
2549
|
return publish({
|
|
2277
2550
|
status: "changed",
|
|
2278
2551
|
operations: EMPTY,
|
|
2279
2552
|
inverse: EMPTY,
|
|
2280
2553
|
paths: EMPTY,
|
|
2281
2554
|
collections: EMPTY
|
|
2282
|
-
},
|
|
2555
|
+
}, source, "replace", false);
|
|
2556
|
+
},
|
|
2557
|
+
snapshot: () => {
|
|
2558
|
+
if (state.disposed) throw new require_dependency.DocumentDisposedError();
|
|
2559
|
+
return require_ownership.cloneValue(state.document, "snapshot");
|
|
2283
2560
|
},
|
|
2284
2561
|
subscribe: ((targetOrListener, listener) => {
|
|
2285
2562
|
if (state.disposed) throw new require_dependency.DocumentDisposedError();
|
|
@@ -2294,13 +2571,27 @@ const createDocument = (input) => {
|
|
|
2294
2571
|
state.disposed = true;
|
|
2295
2572
|
disposeNotification(notification);
|
|
2296
2573
|
history.api.clear();
|
|
2574
|
+
require_driver.disposeRuntimeDriver(runtime);
|
|
2297
2575
|
}
|
|
2298
2576
|
};
|
|
2299
2577
|
require_dependency.bindRuntimeAccess(runtime, state);
|
|
2578
|
+
require_driver.bindRuntimeDriver(runtime);
|
|
2300
2579
|
notification = createNotification(runtime);
|
|
2301
2580
|
return runtime;
|
|
2302
2581
|
};
|
|
2303
2582
|
//#endregion
|
|
2583
|
+
//#region core/src/runtime/readable.ts
|
|
2584
|
+
const asReadable = (runtime) => {
|
|
2585
|
+
const readable = {
|
|
2586
|
+
address: runtime.address,
|
|
2587
|
+
revision: runtime.revision,
|
|
2588
|
+
subscribe: runtime.subscribe
|
|
2589
|
+
};
|
|
2590
|
+
require_dependency.bindRuntimeAccess(readable, require_dependency.accessOf(runtime));
|
|
2591
|
+
shareNotification(runtime, readable);
|
|
2592
|
+
return Object.freeze(readable);
|
|
2593
|
+
};
|
|
2594
|
+
//#endregion
|
|
2304
2595
|
//#region core/src/projection/select.ts
|
|
2305
2596
|
const select = (runtime, selector) => require_dependency.readWith(runtime, selector);
|
|
2306
2597
|
//#endregion
|
|
@@ -2318,7 +2609,7 @@ const createCollectionView = (input) => {
|
|
|
2318
2609
|
shape: {}
|
|
2319
2610
|
};
|
|
2320
2611
|
const mapEntry = (document, id) => {
|
|
2321
|
-
|
|
2612
|
+
require_ownership.profile.collectionView.mapped();
|
|
2322
2613
|
const address = [...input.source.address, String(id)];
|
|
2323
2614
|
let active = true;
|
|
2324
2615
|
try {
|
|
@@ -2334,7 +2625,7 @@ const createCollectionView = (input) => {
|
|
|
2334
2625
|
const document = require_dependency.documentOf(input.runtime);
|
|
2335
2626
|
const collection = require_dependency.read(document, input.source.address);
|
|
2336
2627
|
const ids = collection && typeof collection === "object" && "ids" in collection && Array.isArray(collection.ids) ? [...collection.ids] : Object.keys(collection ?? {});
|
|
2337
|
-
|
|
2628
|
+
require_ownership.profile.collectionView.idsScanned(ids.length);
|
|
2338
2629
|
const values = previous && changed ? previous.values : /* @__PURE__ */ new Map();
|
|
2339
2630
|
if (previous && changed) {
|
|
2340
2631
|
const nextIds = new Set(ids);
|
|
@@ -2362,7 +2653,7 @@ const createCollectionView = (input) => {
|
|
|
2362
2653
|
let state = build();
|
|
2363
2654
|
const ensureAll = () => {
|
|
2364
2655
|
if (!state.allDirty && state.all) return state.all;
|
|
2365
|
-
|
|
2656
|
+
require_ownership.profile.collectionView.arrayCopied();
|
|
2366
2657
|
const all = new Array(state.ids.length);
|
|
2367
2658
|
for (let index = 0; index < state.ids.length; index += 1) all[index] = state.values.get(state.ids[index]);
|
|
2368
2659
|
const stable = Object.freeze(all);
|
|
@@ -2519,7 +2810,7 @@ const createMaterializedView = (runtime, spec) => {
|
|
|
2519
2810
|
entry.change = meta?.change;
|
|
2520
2811
|
if (commitRevision !== void 0 && meta?.changedRevision === commitRevision) {
|
|
2521
2812
|
sourceChanged = true;
|
|
2522
|
-
|
|
2813
|
+
require_ownership.profile.materialized.sourceChanged();
|
|
2523
2814
|
}
|
|
2524
2815
|
}
|
|
2525
2816
|
return sourceValuesRecord;
|
|
@@ -2566,7 +2857,7 @@ const createMaterializedView = (runtime, spec) => {
|
|
|
2566
2857
|
});
|
|
2567
2858
|
};
|
|
2568
2859
|
const build = () => {
|
|
2569
|
-
|
|
2860
|
+
require_ownership.profile.materialized.rebuilt();
|
|
2570
2861
|
dependencies.clear();
|
|
2571
2862
|
let active = true;
|
|
2572
2863
|
try {
|
|
@@ -2583,7 +2874,7 @@ const createMaterializedView = (runtime, spec) => {
|
|
|
2583
2874
|
};
|
|
2584
2875
|
build();
|
|
2585
2876
|
const emit = () => {
|
|
2586
|
-
|
|
2877
|
+
require_ownership.profile.materialized.notification();
|
|
2587
2878
|
Array.from(listeners).forEach((listener) => listener());
|
|
2588
2879
|
};
|
|
2589
2880
|
const process = (commit) => {
|
|
@@ -2597,13 +2888,13 @@ const createMaterializedView = (runtime, spec) => {
|
|
|
2597
2888
|
}
|
|
2598
2889
|
const sourceSnapshot = sourceValues(commit.revision);
|
|
2599
2890
|
if (!sourceChanged && dependencies.size() > 0 && !dependencies.some(commit.impact.affects)) {
|
|
2600
|
-
|
|
2891
|
+
require_ownership.profile.materialized.skipped();
|
|
2601
2892
|
revision = commit.revision;
|
|
2602
2893
|
writeMeta(void 0, currentValue, commit.revision, false);
|
|
2603
2894
|
return;
|
|
2604
2895
|
}
|
|
2605
2896
|
dependencies.clear();
|
|
2606
|
-
|
|
2897
|
+
require_ownership.profile.materialized.updated();
|
|
2607
2898
|
let active = true;
|
|
2608
2899
|
let result;
|
|
2609
2900
|
try {
|
|
@@ -2687,13 +2978,17 @@ const createMaterializedView = (runtime, spec) => {
|
|
|
2687
2978
|
//#endregion
|
|
2688
2979
|
exports.DocumentDisposedError = require_dependency.DocumentDisposedError;
|
|
2689
2980
|
exports.DocumentReentrancyError = require_dependency.DocumentReentrancyError;
|
|
2981
|
+
exports.asReadable = asReadable;
|
|
2982
|
+
exports.commandFootprint = commandFootprint;
|
|
2690
2983
|
exports.contains = require_dependency.contains;
|
|
2691
2984
|
exports.createCollectionView = createCollectionView;
|
|
2692
2985
|
exports.createDocument = createDocument;
|
|
2693
2986
|
exports.createMaterializedView = createMaterializedView;
|
|
2694
2987
|
exports.debugKey = require_dependency.debugKey;
|
|
2988
|
+
exports.decodeCommandFootprint = decodeCommandFootprint;
|
|
2695
2989
|
exports.dict = require_dependency.dict;
|
|
2696
2990
|
exports.field = require_dependency.field;
|
|
2991
|
+
exports.footprintsOverlap = footprintsOverlap;
|
|
2697
2992
|
exports.list = require_dependency.list;
|
|
2698
2993
|
exports.map = require_dependency.map;
|
|
2699
2994
|
exports.object = require_dependency.object;
|