@rljson/db 0.0.10 → 0.0.12
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/dist/controller/cake-controller.d.ts +0 -1
- package/dist/controller/controller.d.ts +2 -2
- package/dist/controller/tree-controller.d.ts +18 -0
- package/dist/db.d.ts +9 -8
- package/dist/db.js +565 -343
- package/dist/db.js.map +1 -1
- package/dist/edit/multi-edit-processor.d.ts +5 -0
- package/dist/example-static/mass-data/convert-mass-data.d.ts +5 -0
- package/package.json +16 -15
package/dist/db.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { timeId, createInsertHistoryTableCfg, Validate, BaseValidator,
|
|
1
|
+
import { timeId, Route, createInsertHistoryTableCfg, Validate, BaseValidator, treeFromObject, isTimeId, getTimeIdTimestamp, createSliceIdsTableCfg, createLayerTableCfg, createCakeTableCfg } from "@rljson/rljson";
|
|
2
2
|
import { rmhsh, hsh, Hash, hip } from "@rljson/hash";
|
|
3
3
|
import { equals, merge } from "@rljson/json";
|
|
4
4
|
import { IoMem } from "@rljson/io";
|
|
@@ -184,7 +184,6 @@ class CakeController extends BaseController {
|
|
|
184
184
|
this._refs = _refs;
|
|
185
185
|
this._contentType = "cakes";
|
|
186
186
|
}
|
|
187
|
-
_table = null;
|
|
188
187
|
_baseLayers = {};
|
|
189
188
|
async init() {
|
|
190
189
|
if (this._tableKey.endsWith("Cake") === false) {
|
|
@@ -192,9 +191,8 @@ class CakeController extends BaseController {
|
|
|
192
191
|
`Table ${this._tableKey} is not supported by CakeController.`
|
|
193
192
|
);
|
|
194
193
|
}
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
if (this._table._type !== "cakes") {
|
|
194
|
+
const contentType = await this._core.contentType(this._tableKey);
|
|
195
|
+
if (contentType !== "cakes") {
|
|
198
196
|
throw new Error(`Table ${this._tableKey} is not of type cakes.`);
|
|
199
197
|
}
|
|
200
198
|
this._tableCfg = await this._core.tableCfg(this._tableKey);
|
|
@@ -207,21 +205,9 @@ class CakeController extends BaseController {
|
|
|
207
205
|
}
|
|
208
206
|
const baseCake = baseCakes[0];
|
|
209
207
|
this._baseLayers = rmhsh(baseCake.layers);
|
|
210
|
-
} else {
|
|
211
|
-
const cake = this._table._data[0];
|
|
212
|
-
if (!!cake) {
|
|
213
|
-
this._refs = {
|
|
214
|
-
sliceIdsTable: cake.sliceIdsTable,
|
|
215
|
-
sliceIdsRow: cake.sliceIdsRow
|
|
216
|
-
};
|
|
217
|
-
this._baseLayers = rmhsh(cake.layers);
|
|
218
|
-
}
|
|
219
208
|
}
|
|
220
209
|
}
|
|
221
210
|
async getChildRefs(where, filter) {
|
|
222
|
-
if (!this._table) {
|
|
223
|
-
throw new Error(`Controller not initialized.`);
|
|
224
|
-
}
|
|
225
211
|
const childRefs = [];
|
|
226
212
|
const { [this._tableKey]: table } = await this.get(where, filter);
|
|
227
213
|
const cakes = table._data;
|
|
@@ -302,7 +288,7 @@ class ComponentController extends BaseController {
|
|
|
302
288
|
"edits",
|
|
303
289
|
"editHistory",
|
|
304
290
|
"multiEdits",
|
|
305
|
-
"
|
|
291
|
+
"insertHistory"
|
|
306
292
|
];
|
|
307
293
|
_resolvedColumns = null;
|
|
308
294
|
_refTableKeyToColumnKeyMap = null;
|
|
@@ -310,9 +296,8 @@ class ComponentController extends BaseController {
|
|
|
310
296
|
if (!!this._refs && !this._refs.base) {
|
|
311
297
|
throw new Error(`Refs are not required on ComponentController.`);
|
|
312
298
|
}
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
if (this._allowedContentTypes.indexOf(table._type) === -1) {
|
|
299
|
+
const contentType = await this._core.contentType(this._tableKey);
|
|
300
|
+
if (this._allowedContentTypes.indexOf(contentType) === -1) {
|
|
316
301
|
throw new Error(`Table ${this._tableKey} is not of type components.`);
|
|
317
302
|
}
|
|
318
303
|
this._tableCfg = await this._core.tableCfg(this._tableKey);
|
|
@@ -653,9 +638,8 @@ class SliceIdController extends BaseController {
|
|
|
653
638
|
`Table ${this._tableKey} is not supported by SliceIdController.`
|
|
654
639
|
);
|
|
655
640
|
}
|
|
656
|
-
const
|
|
657
|
-
|
|
658
|
-
if (table._type !== "sliceIds") {
|
|
641
|
+
const contentType = await this._core.contentType(this._tableKey);
|
|
642
|
+
if (contentType !== "sliceIds") {
|
|
659
643
|
throw new Error(`Table ${this._tableKey} is not of type sliceIds.`);
|
|
660
644
|
}
|
|
661
645
|
this._tableCfg = await this._core.tableCfg(this._tableKey);
|
|
@@ -666,13 +650,6 @@ class SliceIdController extends BaseController {
|
|
|
666
650
|
if (SliceIds2.length === 0) {
|
|
667
651
|
throw new Error(`Base sliceId ${this._refs.base} does not exist.`);
|
|
668
652
|
}
|
|
669
|
-
} else {
|
|
670
|
-
const sliceId = table._data[0];
|
|
671
|
-
if (!!sliceId) {
|
|
672
|
-
this._refs = {
|
|
673
|
-
base: sliceId.base
|
|
674
|
-
};
|
|
675
|
-
}
|
|
676
653
|
}
|
|
677
654
|
}
|
|
678
655
|
async insert(command, value, origin, refs) {
|
|
@@ -771,9 +748,8 @@ class LayerController extends BaseController {
|
|
|
771
748
|
`Table ${this._tableKey} is not supported by LayerController.`
|
|
772
749
|
);
|
|
773
750
|
}
|
|
774
|
-
const
|
|
775
|
-
|
|
776
|
-
if (table._type !== "layers") {
|
|
751
|
+
const contentType = await this._core.contentType(this._tableKey);
|
|
752
|
+
if (contentType !== "layers") {
|
|
777
753
|
throw new Error(`Table ${this._tableKey} is not of type layers.`);
|
|
778
754
|
}
|
|
779
755
|
this._tableCfg = await this._core.tableCfg(this._tableKey);
|
|
@@ -792,15 +768,6 @@ class LayerController extends BaseController {
|
|
|
792
768
|
componentsTable: baseLayer.componentsTable
|
|
793
769
|
};
|
|
794
770
|
}
|
|
795
|
-
} else {
|
|
796
|
-
const layer = table._data[0];
|
|
797
|
-
if (!!layer) {
|
|
798
|
-
this._refs = {
|
|
799
|
-
sliceIdsTable: layer.sliceIdsTable,
|
|
800
|
-
sliceIdsTableRow: layer.sliceIdsTableRow,
|
|
801
|
-
componentsTable: layer.componentsTable
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
771
|
}
|
|
805
772
|
}
|
|
806
773
|
async insert(command, value, origin, refs) {
|
|
@@ -963,6 +930,199 @@ class LayerController extends BaseController {
|
|
|
963
930
|
return false;
|
|
964
931
|
}
|
|
965
932
|
}
|
|
933
|
+
class TreeController extends BaseController {
|
|
934
|
+
constructor(_core, _tableKey) {
|
|
935
|
+
super(_core, _tableKey);
|
|
936
|
+
this._core = _core;
|
|
937
|
+
this._tableKey = _tableKey;
|
|
938
|
+
this._contentType = "trees";
|
|
939
|
+
}
|
|
940
|
+
async init() {
|
|
941
|
+
if (this._tableKey.endsWith("Tree") === false) {
|
|
942
|
+
throw new Error(
|
|
943
|
+
`Table ${this._tableKey} is not supported by TreeController.`
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
const contentType = await this._core.contentType(this._tableKey);
|
|
947
|
+
if (contentType !== "trees") {
|
|
948
|
+
throw new Error(`Table ${this._tableKey} is not of type trees.`);
|
|
949
|
+
}
|
|
950
|
+
this._tableCfg = await this._core.tableCfg(this._tableKey);
|
|
951
|
+
}
|
|
952
|
+
async insert(command, value, origin) {
|
|
953
|
+
if (!command.startsWith("add") && !command.startsWith("remove")) {
|
|
954
|
+
throw new Error(`Command ${command} is not supported by TreeController.`);
|
|
955
|
+
}
|
|
956
|
+
const rlJson = { [this._tableKey]: { _data: [value] } };
|
|
957
|
+
await this._core.import(rlJson);
|
|
958
|
+
const result = {
|
|
959
|
+
//Ref to component
|
|
960
|
+
[this._tableKey + "Ref"]: hsh(value)._hash,
|
|
961
|
+
//Data from edit
|
|
962
|
+
route: "",
|
|
963
|
+
origin,
|
|
964
|
+
//Unique id/timestamp
|
|
965
|
+
timeId: timeId()
|
|
966
|
+
};
|
|
967
|
+
return [result];
|
|
968
|
+
}
|
|
969
|
+
async get(where, filter, path) {
|
|
970
|
+
const {
|
|
971
|
+
[this._tableKey]: { _data: trees }
|
|
972
|
+
} = typeof where === "string" ? await this._getByHash(where, filter) : await this._getByWhere(where, filter);
|
|
973
|
+
if (trees.length === 0) {
|
|
974
|
+
return { [this._tableKey]: { _data: [], _type: "trees" } };
|
|
975
|
+
}
|
|
976
|
+
if (trees.length > 1) {
|
|
977
|
+
throw new Error(
|
|
978
|
+
`Multiple trees found for where clause. Please specify a more specific query.`
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
const treeRoute = Route.fromFlat(path || "");
|
|
982
|
+
const treeId = treeRoute.segments.length > 0 ? treeRoute.top.tableKey : null;
|
|
983
|
+
const tree = trees[0];
|
|
984
|
+
if (treeId && treeId !== tree.id) {
|
|
985
|
+
return { [this._tableKey]: { _data: [], _type: "trees" } };
|
|
986
|
+
}
|
|
987
|
+
const children = [];
|
|
988
|
+
for (const childRef of tree.children ?? []) {
|
|
989
|
+
const child = await this.get(
|
|
990
|
+
childRef,
|
|
991
|
+
void 0,
|
|
992
|
+
treeRoute.deeper().flat
|
|
993
|
+
);
|
|
994
|
+
const childData = child[this._tableKey]._data;
|
|
995
|
+
children.push(...childData);
|
|
996
|
+
}
|
|
997
|
+
return {
|
|
998
|
+
[this._tableKey]: {
|
|
999
|
+
_data: [...children, tree],
|
|
1000
|
+
_type: "trees"
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
async buildTreeFromTrees(trees) {
|
|
1005
|
+
if (trees.length === 0) {
|
|
1006
|
+
return {};
|
|
1007
|
+
}
|
|
1008
|
+
const treeMap = /* @__PURE__ */ new Map();
|
|
1009
|
+
for (const tree of trees) {
|
|
1010
|
+
treeMap.set(tree._hash, tree);
|
|
1011
|
+
}
|
|
1012
|
+
const buildObject = (tree) => {
|
|
1013
|
+
if (!tree.isParent || !tree.children || tree.children.length === 0) {
|
|
1014
|
+
return tree;
|
|
1015
|
+
}
|
|
1016
|
+
const result2 = {};
|
|
1017
|
+
for (const childHash of tree.children) {
|
|
1018
|
+
const childTree = treeMap.get(childHash);
|
|
1019
|
+
if (childTree && childTree.id) {
|
|
1020
|
+
result2[childTree.id] = buildObject(childTree);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
return result2;
|
|
1024
|
+
};
|
|
1025
|
+
const referencedHashes = /* @__PURE__ */ new Set();
|
|
1026
|
+
for (const tree of trees) {
|
|
1027
|
+
if (tree.children) {
|
|
1028
|
+
for (const childHash of tree.children) {
|
|
1029
|
+
referencedHashes.add(childHash);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
const rootTrees = trees.filter(
|
|
1034
|
+
(tree) => !referencedHashes.has(tree._hash)
|
|
1035
|
+
);
|
|
1036
|
+
if (rootTrees.length === 0) {
|
|
1037
|
+
return {};
|
|
1038
|
+
}
|
|
1039
|
+
if (rootTrees.length === 1) {
|
|
1040
|
+
const rootTree = rootTrees[0];
|
|
1041
|
+
if (rootTree.id) {
|
|
1042
|
+
return { [rootTree.id]: buildObject(rootTree) };
|
|
1043
|
+
}
|
|
1044
|
+
return buildObject(rootTree);
|
|
1045
|
+
}
|
|
1046
|
+
const result = {};
|
|
1047
|
+
for (const rootTree of rootTrees) {
|
|
1048
|
+
if (rootTree.id) {
|
|
1049
|
+
result[rootTree.id] = buildObject(rootTree);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
return result;
|
|
1053
|
+
}
|
|
1054
|
+
async buildCellsFromTree(trees) {
|
|
1055
|
+
const cells = [];
|
|
1056
|
+
if (trees.length === 0) {
|
|
1057
|
+
return cells;
|
|
1058
|
+
}
|
|
1059
|
+
const treeMap = /* @__PURE__ */ new Map();
|
|
1060
|
+
const childToParentMap = /* @__PURE__ */ new Map();
|
|
1061
|
+
for (const tree of trees) {
|
|
1062
|
+
const treeHash = tree._hash;
|
|
1063
|
+
treeMap.set(treeHash, tree);
|
|
1064
|
+
if (tree.children) {
|
|
1065
|
+
for (const childHash of tree.children) {
|
|
1066
|
+
childToParentMap.set(childHash, treeHash);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
const availableHashes = /* @__PURE__ */ new Set();
|
|
1071
|
+
for (const tree of trees) {
|
|
1072
|
+
availableHashes.add(tree._hash);
|
|
1073
|
+
}
|
|
1074
|
+
const leafNodes = trees.filter((tree) => {
|
|
1075
|
+
if (!tree.children || tree.children.length === 0) {
|
|
1076
|
+
return true;
|
|
1077
|
+
}
|
|
1078
|
+
const hasChildInTrees = tree.children.some(
|
|
1079
|
+
(childHash) => availableHashes.has(childHash)
|
|
1080
|
+
);
|
|
1081
|
+
return !hasChildInTrees;
|
|
1082
|
+
});
|
|
1083
|
+
for (const leaf of leafNodes) {
|
|
1084
|
+
const pathIds = [];
|
|
1085
|
+
let currentHash = leaf._hash;
|
|
1086
|
+
while (currentHash) {
|
|
1087
|
+
const current = treeMap.get(currentHash);
|
|
1088
|
+
if (!current) break;
|
|
1089
|
+
if (current.id) {
|
|
1090
|
+
pathIds.unshift(current.id);
|
|
1091
|
+
}
|
|
1092
|
+
const parentHash = childToParentMap.get(currentHash);
|
|
1093
|
+
if (!parentHash) break;
|
|
1094
|
+
currentHash = parentHash;
|
|
1095
|
+
}
|
|
1096
|
+
const routeStr = "/" + pathIds.join("/");
|
|
1097
|
+
const route = Route.fromFlat(routeStr);
|
|
1098
|
+
cells.push({
|
|
1099
|
+
route,
|
|
1100
|
+
value: leaf,
|
|
1101
|
+
row: leaf,
|
|
1102
|
+
path: [[this._tableKey, "_data", 0, ...pathIds]]
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
return cells;
|
|
1106
|
+
}
|
|
1107
|
+
async getChildRefs(where, filter) {
|
|
1108
|
+
const childRefs = [];
|
|
1109
|
+
const { [this._tableKey]: table } = await this.get(where, filter);
|
|
1110
|
+
const trees = table._data;
|
|
1111
|
+
for (const tree of trees) {
|
|
1112
|
+
for (const treeChildRef of tree.children ?? []) {
|
|
1113
|
+
childRefs.push({
|
|
1114
|
+
tableKey: this._tableKey,
|
|
1115
|
+
ref: treeChildRef
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
return childRefs;
|
|
1120
|
+
}
|
|
1121
|
+
/* v8 ignore next -- @preserve */
|
|
1122
|
+
async filterRow() {
|
|
1123
|
+
return false;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
966
1126
|
const createController = async (type, core, tableKey, refs) => {
|
|
967
1127
|
let ctrl;
|
|
968
1128
|
switch (type) {
|
|
@@ -973,7 +1133,7 @@ const createController = async (type, core, tableKey, refs) => {
|
|
|
973
1133
|
case "edits":
|
|
974
1134
|
case "editHistory":
|
|
975
1135
|
case "multiEdits":
|
|
976
|
-
case "
|
|
1136
|
+
case "insertHistory":
|
|
977
1137
|
ctrl = new ComponentController(core, tableKey, refs);
|
|
978
1138
|
break;
|
|
979
1139
|
case "cakes":
|
|
@@ -986,6 +1146,9 @@ const createController = async (type, core, tableKey, refs) => {
|
|
|
986
1146
|
refs
|
|
987
1147
|
);
|
|
988
1148
|
break;
|
|
1149
|
+
case "trees":
|
|
1150
|
+
ctrl = new TreeController(core, tableKey);
|
|
1151
|
+
break;
|
|
989
1152
|
default:
|
|
990
1153
|
throw new Error(`Controller for type ${type} is not implemented yet.`);
|
|
991
1154
|
}
|
|
@@ -1071,17 +1234,8 @@ class Core {
|
|
|
1071
1234
|
}
|
|
1072
1235
|
// ...........................................................................
|
|
1073
1236
|
async tableCfg(table) {
|
|
1074
|
-
const { [table]: dump } = await this._io.dumpTable({ table });
|
|
1075
|
-
const tableCfgRef = dump._tableCfg;
|
|
1076
1237
|
const tableCfgs = await this._io.rawTableCfgs();
|
|
1077
|
-
|
|
1078
|
-
if (!tableCfgRef) {
|
|
1079
|
-
tableCfg = tableCfgs.find((tc) => tc.key === table);
|
|
1080
|
-
} else {
|
|
1081
|
-
tableCfg = tableCfgs.find(
|
|
1082
|
-
(tc) => tc.key === table && tc._hash === tableCfgRef
|
|
1083
|
-
);
|
|
1084
|
-
}
|
|
1238
|
+
const tableCfg = tableCfgs.find((tc) => tc.key === table);
|
|
1085
1239
|
return tableCfg;
|
|
1086
1240
|
}
|
|
1087
1241
|
// ...........................................................................
|
|
@@ -1101,7 +1255,7 @@ const inject = (tree, path, value) => {
|
|
|
1101
1255
|
tree[segment] = value;
|
|
1102
1256
|
delete tree["_hash"];
|
|
1103
1257
|
} else {
|
|
1104
|
-
if (!tree[segment]) {
|
|
1258
|
+
if (!tree[segment] || typeof tree[segment] !== "object") {
|
|
1105
1259
|
tree[segment] = {};
|
|
1106
1260
|
}
|
|
1107
1261
|
tree = tree[segment];
|
|
@@ -2731,7 +2885,7 @@ class Db {
|
|
|
2731
2885
|
* @returns An array of Rljson objects matching the route and filter
|
|
2732
2886
|
* @throws {Error} If the route is not valid or if any controller cannot be created
|
|
2733
2887
|
*/
|
|
2734
|
-
async get(route, where, filter, sliceIds) {
|
|
2888
|
+
async get(route, where, filter, sliceIds, options) {
|
|
2735
2889
|
if (!route.isValid) throw new Error(`Route ${route.flat} is not valid.`);
|
|
2736
2890
|
const isolatedRoute = await this.isolatePropertyKeyFromRoute(route);
|
|
2737
2891
|
const controllers = await this.indexedControllers(isolatedRoute);
|
|
@@ -2740,7 +2894,9 @@ class Db {
|
|
|
2740
2894
|
where,
|
|
2741
2895
|
controllers,
|
|
2742
2896
|
filter,
|
|
2743
|
-
sliceIds
|
|
2897
|
+
sliceIds,
|
|
2898
|
+
void 0,
|
|
2899
|
+
options
|
|
2744
2900
|
);
|
|
2745
2901
|
const dataWithControllers = {
|
|
2746
2902
|
...data,
|
|
@@ -2758,20 +2914,30 @@ class Db {
|
|
|
2758
2914
|
* @param controllers - The controllers to use for fetching data
|
|
2759
2915
|
* @param filter - Optional filter to apply to the data at the current route segment
|
|
2760
2916
|
* @param sliceIds - Optional slice IDs to filter the data at the current route segment
|
|
2917
|
+
* @param routeAccumulator - The accumulated route up to the current segment
|
|
2918
|
+
* @param options - Additional options for fetching data
|
|
2761
2919
|
* @returns - An Rljson object matching the route and filters
|
|
2762
2920
|
*/
|
|
2763
|
-
async _get(route, where, controllers, filter, sliceIds, routeAccumulator) {
|
|
2764
|
-
const
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2921
|
+
async _get(route, where, controllers, filter, sliceIds, routeAccumulator, options) {
|
|
2922
|
+
const opts = options ?? {};
|
|
2923
|
+
const routeHasRefs = route.flat != route.flatWithoutRefs;
|
|
2924
|
+
const hasFilter = filter !== void 0 && filter.length > 0;
|
|
2925
|
+
const cacheable = !!routeHasRefs || !!hasFilter;
|
|
2926
|
+
let cacheHash = "";
|
|
2927
|
+
if (cacheable) {
|
|
2928
|
+
const params = {
|
|
2929
|
+
route: route.flat,
|
|
2930
|
+
where,
|
|
2931
|
+
filter,
|
|
2932
|
+
sliceIds,
|
|
2933
|
+
routeAccumulator: routeAccumulator ? routeAccumulator.flat : "",
|
|
2934
|
+
options: opts
|
|
2935
|
+
};
|
|
2936
|
+
cacheHash = hsh(rmhsh(params))._hash;
|
|
2937
|
+
const isCached = this._cache.has(cacheHash);
|
|
2938
|
+
if (isCached) {
|
|
2939
|
+
return this._cache.get(cacheHash);
|
|
2940
|
+
}
|
|
2775
2941
|
}
|
|
2776
2942
|
const nodeTableKey = route.top.tableKey;
|
|
2777
2943
|
const nodeRoute = route;
|
|
@@ -2789,12 +2955,59 @@ class Db {
|
|
|
2789
2955
|
delete nodeWhere["_tableKey"];
|
|
2790
2956
|
const {
|
|
2791
2957
|
[nodeTableKey]: { _data: nodeRows, _type: nodeType, _hash: nodeHash }
|
|
2792
|
-
} = await nodeController.get(nodeWhere);
|
|
2958
|
+
} = await nodeController.get(nodeWhere, void 0, route.propertyKey);
|
|
2793
2959
|
const nodeColumnCfgs = nodeController.tableCfg().columns;
|
|
2960
|
+
const filterActive = filter && filter.length > 0;
|
|
2961
|
+
const sliceIdActive = nodeSliceIds && nodeSliceIds.length > 0;
|
|
2962
|
+
const filterMap = filterActive ? /* @__PURE__ */ new Map() : null;
|
|
2963
|
+
if (filterActive) {
|
|
2964
|
+
for (const f of filter) {
|
|
2965
|
+
if (f.tableKey === nodeTableKey) {
|
|
2966
|
+
if (!filterMap.has(f.ref)) {
|
|
2967
|
+
filterMap.set(f.ref, []);
|
|
2968
|
+
}
|
|
2969
|
+
filterMap.get(f.ref).push(f);
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
const sliceIdResolvePromises = /* @__PURE__ */ new Map();
|
|
2974
|
+
const nodeSliceIdSet = sliceIdActive ? new Set(nodeSliceIds) : null;
|
|
2975
|
+
if (sliceIdActive) {
|
|
2976
|
+
for (const nodeRow of nodeRows) {
|
|
2977
|
+
if (nodeType === "cakes") {
|
|
2978
|
+
const cake = nodeRow;
|
|
2979
|
+
const key = `${cake.sliceIdsTable}:${cake.sliceIdsRow}`;
|
|
2980
|
+
if (!sliceIdResolvePromises.has(key)) {
|
|
2981
|
+
sliceIdResolvePromises.set(
|
|
2982
|
+
key,
|
|
2983
|
+
this._resolveSliceIds(cake.sliceIdsTable, cake.sliceIdsRow)
|
|
2984
|
+
);
|
|
2985
|
+
}
|
|
2986
|
+
} else if (nodeType === "layers") {
|
|
2987
|
+
const layer = nodeRow;
|
|
2988
|
+
const key = `${layer.sliceIdsTable}:${layer.sliceIdsTableRow}`;
|
|
2989
|
+
if (!sliceIdResolvePromises.has(key)) {
|
|
2990
|
+
sliceIdResolvePromises.set(
|
|
2991
|
+
key,
|
|
2992
|
+
this._resolveSliceIds(
|
|
2993
|
+
layer.sliceIdsTable,
|
|
2994
|
+
layer.sliceIdsTableRow
|
|
2995
|
+
)
|
|
2996
|
+
);
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
const resolvedSliceIds = /* @__PURE__ */ new Map();
|
|
3002
|
+
if (sliceIdResolvePromises.size > 0) {
|
|
3003
|
+
const entries = Array.from(sliceIdResolvePromises.entries());
|
|
3004
|
+
const results = await Promise.all(entries.map(([, p]) => p));
|
|
3005
|
+
entries.forEach(([key], idx) => {
|
|
3006
|
+
resolvedSliceIds.set(key, new Set(results[idx]));
|
|
3007
|
+
});
|
|
3008
|
+
}
|
|
2794
3009
|
const nodeRowsFiltered = [];
|
|
2795
3010
|
for (const nodeRow of nodeRows) {
|
|
2796
|
-
const filterActive = filter && filter.length > 0;
|
|
2797
|
-
const sliceIdActive = nodeSliceIds && nodeSliceIds.length > 0;
|
|
2798
3011
|
if (!filterActive && !sliceIdActive) {
|
|
2799
3012
|
nodeRowsFiltered.push(nodeRow);
|
|
2800
3013
|
continue;
|
|
@@ -2802,12 +3015,10 @@ class Db {
|
|
|
2802
3015
|
let filterResult = false;
|
|
2803
3016
|
const filterProperties = [];
|
|
2804
3017
|
if (filterActive) {
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
filterResult = true;
|
|
2810
|
-
}
|
|
3018
|
+
const rowFilters = filterMap.get(nodeRow._hash);
|
|
3019
|
+
if (rowFilters) {
|
|
3020
|
+
filterProperties.push(...rowFilters);
|
|
3021
|
+
filterResult = true;
|
|
2811
3022
|
}
|
|
2812
3023
|
} else {
|
|
2813
3024
|
filterResult = true;
|
|
@@ -2817,36 +3028,36 @@ class Db {
|
|
|
2817
3028
|
switch (nodeType) {
|
|
2818
3029
|
case "cakes":
|
|
2819
3030
|
const cake = nodeRow;
|
|
2820
|
-
const
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
3031
|
+
const cakeKey = `${cake.sliceIdsTable}:${cake.sliceIdsRow}`;
|
|
3032
|
+
const cakeSliceIdSet = resolvedSliceIds.get(cakeKey);
|
|
3033
|
+
for (const sId of nodeSliceIdSet) {
|
|
3034
|
+
if (cakeSliceIdSet.has(sId)) {
|
|
3035
|
+
sliceIdResult = true;
|
|
3036
|
+
break;
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
2828
3039
|
break;
|
|
2829
3040
|
case "layers":
|
|
2830
3041
|
const layer = nodeRow;
|
|
2831
|
-
const
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
3042
|
+
const layerKey = `${layer.sliceIdsTable}:${layer.sliceIdsTableRow}`;
|
|
3043
|
+
const layerSliceIdSet = resolvedSliceIds.get(layerKey);
|
|
3044
|
+
for (const sId of nodeSliceIdSet) {
|
|
3045
|
+
if (layerSliceIdSet.has(sId)) {
|
|
3046
|
+
sliceIdResult = true;
|
|
3047
|
+
break;
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
2839
3050
|
break;
|
|
2840
3051
|
case "components":
|
|
2841
3052
|
if (filterProperties.length > 0) {
|
|
2842
|
-
const
|
|
2843
|
-
(f) => f.sliceIds
|
|
3053
|
+
const componentSliceIdSet = new Set(
|
|
3054
|
+
filterProperties.flatMap((f) => f.sliceIds)
|
|
2844
3055
|
);
|
|
2845
|
-
const
|
|
2846
|
-
(
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
3056
|
+
for (const sId of nodeSliceIdSet) {
|
|
3057
|
+
if (componentSliceIdSet.has(sId)) {
|
|
3058
|
+
sliceIdResult = true;
|
|
3059
|
+
break;
|
|
3060
|
+
}
|
|
2850
3061
|
}
|
|
2851
3062
|
}
|
|
2852
3063
|
break;
|
|
@@ -2867,47 +3078,68 @@ class Db {
|
|
|
2867
3078
|
_hash: nodeHash
|
|
2868
3079
|
}
|
|
2869
3080
|
};
|
|
2870
|
-
const nodeValue = node[nodeTableKey]._data.filter(
|
|
2871
|
-
(v) => v !== void 0 && v !== null
|
|
2872
|
-
);
|
|
2873
3081
|
if (route.isRoot) {
|
|
3082
|
+
const baseRouteStr = (routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "");
|
|
2874
3083
|
if (route.hasPropertyKey) {
|
|
2875
|
-
const isolatedNode = this.isolatePropertyFromComponents(
|
|
2876
|
-
|
|
2877
|
-
route.propertyKey
|
|
2878
|
-
);
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
3084
|
+
const isolatedNode = opts.skipRljson ? {} : this.isolatePropertyFromComponents(node, route.propertyKey);
|
|
3085
|
+
const routeWithProperty = opts.skipCell ? null : Route.fromFlat(
|
|
3086
|
+
baseRouteStr + `/${route.propertyKey}`
|
|
3087
|
+
).toRouteWithProperty();
|
|
3088
|
+
let result3;
|
|
3089
|
+
if (nodeType === "trees") {
|
|
3090
|
+
const rljson3 = node;
|
|
3091
|
+
const tree3 = opts.skipTree ? {} : {
|
|
3092
|
+
[nodeTableKey]: {
|
|
3093
|
+
_data: [
|
|
3094
|
+
await nodeController.buildTreeFromTrees(nodeRows)
|
|
3095
|
+
],
|
|
3096
|
+
_type: "trees"
|
|
3097
|
+
}
|
|
3098
|
+
};
|
|
3099
|
+
const cell3 = opts.skipCell ? [] : await nodeController.buildCellsFromTree(nodeRows);
|
|
3100
|
+
result3 = {
|
|
3101
|
+
rljson: rljson3,
|
|
3102
|
+
tree: tree3,
|
|
3103
|
+
cell: cell3
|
|
3104
|
+
};
|
|
3105
|
+
} else {
|
|
3106
|
+
const tree3 = opts.skipTree ? {} : { [nodeTableKey]: node[nodeTableKey] };
|
|
3107
|
+
const cell3 = opts.skipCell ? [] : nodeRowsFiltered.map(
|
|
2883
3108
|
(v, idx) => ({
|
|
2884
3109
|
value: v[route.propertyKey] ?? null,
|
|
2885
3110
|
row: v,
|
|
2886
|
-
route:
|
|
2887
|
-
(routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "") + `/${route.propertyKey}`
|
|
2888
|
-
).toRouteWithProperty(),
|
|
3111
|
+
route: routeWithProperty,
|
|
2889
3112
|
path: [[nodeTableKey, "_data", idx, route.propertyKey]]
|
|
2890
3113
|
})
|
|
2891
|
-
)
|
|
2892
|
-
|
|
3114
|
+
);
|
|
3115
|
+
result3 = {
|
|
3116
|
+
rljson: isolatedNode,
|
|
3117
|
+
tree: tree3,
|
|
3118
|
+
cell: cell3
|
|
3119
|
+
};
|
|
3120
|
+
}
|
|
2893
3121
|
this._cache.set(cacheHash, result3);
|
|
2894
3122
|
return result3;
|
|
2895
3123
|
}
|
|
3124
|
+
const routeObj = opts.skipCell ? null : Route.fromFlat(baseRouteStr);
|
|
3125
|
+
const rljson2 = opts.skipRljson ? {} : node;
|
|
3126
|
+
const tree2 = opts.skipTree ? {} : { [nodeTableKey]: node[nodeTableKey] };
|
|
3127
|
+
const cell2 = opts.skipCell ? [] : nodeRowsFiltered.map(
|
|
3128
|
+
(v, idx) => ({
|
|
3129
|
+
value: v[route.propertyKey] ?? null,
|
|
3130
|
+
row: v,
|
|
3131
|
+
route: routeObj,
|
|
3132
|
+
path: [[nodeTableKey, "_data", idx]]
|
|
3133
|
+
})
|
|
3134
|
+
);
|
|
2896
3135
|
const result2 = {
|
|
2897
|
-
rljson:
|
|
2898
|
-
tree:
|
|
2899
|
-
cell:
|
|
2900
|
-
(v, idx) => ({
|
|
2901
|
-
value: v[route.propertyKey] ?? null,
|
|
2902
|
-
row: v,
|
|
2903
|
-
route: Route.fromFlat(
|
|
2904
|
-
(routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "")
|
|
2905
|
-
),
|
|
2906
|
-
path: [[nodeTableKey, "_data", idx]]
|
|
2907
|
-
})
|
|
2908
|
-
)
|
|
3136
|
+
rljson: rljson2,
|
|
3137
|
+
tree: tree2,
|
|
3138
|
+
cell: cell2
|
|
2909
3139
|
};
|
|
2910
|
-
|
|
3140
|
+
if (cacheable) {
|
|
3141
|
+
this._cache.set(cacheHash, result2);
|
|
3142
|
+
}
|
|
2911
3143
|
return result2;
|
|
2912
3144
|
}
|
|
2913
3145
|
const childrenRoute = route.deeper();
|
|
@@ -2916,12 +3148,20 @@ class Db {
|
|
|
2916
3148
|
const childrenThroughProperty = childrenWhere?._through;
|
|
2917
3149
|
const nodeChildrenArray = [];
|
|
2918
3150
|
const nodeRowsMatchingChildrenRefs = /* @__PURE__ */ new Map();
|
|
3151
|
+
const columnReferenceMap = nodeType === "components" ? nodeColumnCfgs.filter((c) => c.ref?.tableKey === childrenTableKey).filter(
|
|
3152
|
+
(c) => c.ref && ["components", "cakes"].includes(c.ref.type)
|
|
3153
|
+
).reduce((acc, curr) => {
|
|
3154
|
+
acc.set(curr.key, curr.ref.tableKey);
|
|
3155
|
+
return acc;
|
|
3156
|
+
}, /* @__PURE__ */ new Map()) : null;
|
|
3157
|
+
const childRefsPromises = nodeRowsFiltered.map(
|
|
3158
|
+
(nodeRow) => nodeController.getChildRefs(nodeRow._hash)
|
|
3159
|
+
);
|
|
3160
|
+
const allChildRefs = await Promise.all(childRefsPromises);
|
|
2919
3161
|
for (let i = 0; i < nodeRowsFiltered.length; i++) {
|
|
2920
3162
|
const nodeRow = nodeRowsFiltered[i];
|
|
2921
|
-
const
|
|
2922
|
-
const childrenRefs =
|
|
2923
|
-
nodeRow._hash
|
|
2924
|
-
);
|
|
3163
|
+
const nodeRowHash = nodeRow._hash;
|
|
3164
|
+
const childrenRefs = allChildRefs[i];
|
|
2925
3165
|
const childrenRefTypes = /* @__PURE__ */ new Map();
|
|
2926
3166
|
const childrenRefSliceIds = /* @__PURE__ */ new Set();
|
|
2927
3167
|
for (const cr of childrenRefs) {
|
|
@@ -2942,13 +3182,19 @@ class Db {
|
|
|
2942
3182
|
}
|
|
2943
3183
|
}
|
|
2944
3184
|
}
|
|
2945
|
-
|
|
3185
|
+
const childrenRefTypesSet = /* @__PURE__ */ new Set([
|
|
3186
|
+
...childrenRefTypes.values()
|
|
3187
|
+
]);
|
|
3188
|
+
if (childrenRefTypesSet.size > 1) {
|
|
2946
3189
|
throw new Error(
|
|
2947
|
-
`Db._get: Multiple reference types found for children of table ${nodeTableKey}
|
|
3190
|
+
`Db._get: Multiple reference types found for children of node table "${nodeTableKey}" and row "${nodeRowHash}". Found types: ${[
|
|
3191
|
+
...childrenRefTypesSet
|
|
3192
|
+
].join(", ")}.`
|
|
2948
3193
|
);
|
|
2949
3194
|
}
|
|
2950
|
-
const
|
|
2951
|
-
const
|
|
3195
|
+
const childrenRefType = childrenRefTypesSet.size > 0 ? [...childrenRefTypesSet][0] : null;
|
|
3196
|
+
const cakeIsReferenced = childrenRefTypes.size > 0 && childrenRefType === "cakes";
|
|
3197
|
+
const componentIsReferenced = childrenRefTypes.size > 0 && nodeType === "components" && childrenRefType === "components";
|
|
2952
3198
|
const childrenSliceIds = cakeIsReferenced ? [...childrenRefSliceIds] : componentIsReferenced ? void 0 : nodeSliceIds;
|
|
2953
3199
|
const {
|
|
2954
3200
|
rljson: rowChildrenRljson,
|
|
@@ -2962,29 +3208,43 @@ class Db {
|
|
|
2962
3208
|
childrenSliceIds,
|
|
2963
3209
|
Route.fromFlat(
|
|
2964
3210
|
(routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "") + "/" + childrenTableKey
|
|
2965
|
-
)
|
|
3211
|
+
),
|
|
3212
|
+
opts
|
|
2966
3213
|
);
|
|
3214
|
+
if (!rowChildrenRljson[childrenTableKey] || rowChildrenRljson[childrenTableKey]._data.length === 0)
|
|
3215
|
+
continue;
|
|
3216
|
+
nodeChildrenArray.push(rowChildrenRljson);
|
|
3217
|
+
if (opts.skipTree && opts.skipCell) {
|
|
3218
|
+
nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
|
|
3219
|
+
rljson: nodeRow,
|
|
3220
|
+
tree: {},
|
|
3221
|
+
cell: []
|
|
3222
|
+
});
|
|
3223
|
+
continue;
|
|
3224
|
+
}
|
|
3225
|
+
const nodeRowObj = { ...nodeRow };
|
|
2967
3226
|
if (cakeIsReferenced) {
|
|
2968
3227
|
const refKey = [...childrenRefTypes.keys()][0];
|
|
2969
3228
|
nodeRowObj[refKey] = rowChildrenTree;
|
|
2970
3229
|
}
|
|
2971
|
-
if (rowChildrenRljson[childrenTableKey]._data.length === 0) continue;
|
|
2972
|
-
nodeChildrenArray.push(rowChildrenRljson);
|
|
2973
3230
|
if (childrenThroughProperty) {
|
|
2974
|
-
const
|
|
3231
|
+
const resolvedChildrenHashesSet = new Set(
|
|
3232
|
+
rowChildrenRljson[childrenTableKey]._data.map(
|
|
3233
|
+
(rc) => rc._hash
|
|
3234
|
+
)
|
|
3235
|
+
);
|
|
2975
3236
|
for (const nr of nodeRowsFiltered) {
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
}
|
|
3237
|
+
const throughHashesInRowCouldBeArray = nr[childrenThroughProperty];
|
|
3238
|
+
const throughHashesInRow = Array.isArray(
|
|
3239
|
+
throughHashesInRowCouldBeArray
|
|
3240
|
+
) ? throughHashesInRowCouldBeArray : [throughHashesInRowCouldBeArray];
|
|
3241
|
+
for (const th of throughHashesInRow) {
|
|
3242
|
+
if (resolvedChildrenHashesSet.has(th)) {
|
|
3243
|
+
nodeRowObj[childrenThroughProperty] = {
|
|
3244
|
+
...rowChildrenTree[childrenTableKey],
|
|
3245
|
+
_tableKey: childrenTableKey
|
|
3246
|
+
};
|
|
3247
|
+
break;
|
|
2988
3248
|
}
|
|
2989
3249
|
}
|
|
2990
3250
|
}
|
|
@@ -2993,8 +3253,14 @@ class Db {
|
|
|
2993
3253
|
const childrenRefsOfRow = childrenRefs.filter(
|
|
2994
3254
|
(cr) => cr.tableKey == childrenTableKey
|
|
2995
3255
|
);
|
|
3256
|
+
const resolvedChildrenHashSet = new Set(
|
|
3257
|
+
resolvedChildren.map((ch) => ch._hash)
|
|
3258
|
+
);
|
|
2996
3259
|
const matchingChildrenRefs = childrenRefsOfRow.filter(
|
|
2997
|
-
(cr) =>
|
|
3260
|
+
(cr) => resolvedChildrenHashSet.has(cr.ref)
|
|
3261
|
+
);
|
|
3262
|
+
const matchingRefsMap = new Map(
|
|
3263
|
+
matchingChildrenRefs.map((cr) => [cr.ref, cr])
|
|
2998
3264
|
);
|
|
2999
3265
|
if (nodeType === "layers") {
|
|
3000
3266
|
const compChildrenTrees = rowChildrenTree[childrenTableKey]._data;
|
|
@@ -3006,9 +3272,8 @@ class Db {
|
|
|
3006
3272
|
};
|
|
3007
3273
|
});
|
|
3008
3274
|
const layerTreesAndPaths = components.map(({ tree: comp, path }) => {
|
|
3009
|
-
const
|
|
3010
|
-
|
|
3011
|
-
)?.sliceIds;
|
|
3275
|
+
const matchedRef = matchingRefsMap.get(comp._hash);
|
|
3276
|
+
const sliceIds2 = matchedRef?.sliceIds;
|
|
3012
3277
|
if (!sliceIds2 || sliceIds2.length === 0) {
|
|
3013
3278
|
throw new Error(
|
|
3014
3279
|
`Db._get: No sliceIds found for component ${comp._hash} of layer ${nodeRow._hash}.`
|
|
@@ -3020,99 +3285,90 @@ class Db {
|
|
|
3020
3285
|
);
|
|
3021
3286
|
}
|
|
3022
3287
|
const sliceId = sliceIds2[0];
|
|
3023
|
-
const pathsForSliceId =
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
})
|
|
3029
|
-
];
|
|
3288
|
+
const pathsForSliceId = path.map((p) => {
|
|
3289
|
+
const newPath = [...p[0]];
|
|
3290
|
+
newPath[2] = 0;
|
|
3291
|
+
return ["add", sliceId, ...newPath];
|
|
3292
|
+
});
|
|
3030
3293
|
return {
|
|
3031
3294
|
[sliceId]: {
|
|
3032
3295
|
tree: {
|
|
3033
3296
|
[childrenTableKey]: {
|
|
3034
|
-
|
|
3035
|
-
|
|
3297
|
+
_data: [comp],
|
|
3298
|
+
_type: "components"
|
|
3036
3299
|
}
|
|
3037
3300
|
},
|
|
3038
3301
|
path: pathsForSliceId
|
|
3039
3302
|
}
|
|
3040
3303
|
};
|
|
3041
3304
|
});
|
|
3042
|
-
const layer =
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3305
|
+
const layer = {};
|
|
3306
|
+
const paths = [];
|
|
3307
|
+
for (const ltap of layerTreesAndPaths) {
|
|
3308
|
+
for (const [sliceId, value] of Object.entries(ltap)) {
|
|
3309
|
+
layer[sliceId] = value.tree;
|
|
3310
|
+
if (!opts.skipCell) {
|
|
3311
|
+
paths.push(value.path);
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
const rljson2 = nodeRow;
|
|
3316
|
+
const tree2 = opts.skipTree ? {} : {
|
|
3317
|
+
...nodeRowObj,
|
|
3318
|
+
add: { ...nodeRowObj.add, ...layer }
|
|
3319
|
+
};
|
|
3320
|
+
const cell2 = opts.skipCell ? [] : rowChildrenCell.map(
|
|
3321
|
+
(c, idx) => ({
|
|
3322
|
+
...c,
|
|
3323
|
+
path: [paths.flat()[idx]]
|
|
3324
|
+
})
|
|
3049
3325
|
);
|
|
3050
|
-
nodeRowsMatchingChildrenRefs.set(
|
|
3051
|
-
rljson:
|
|
3052
|
-
tree:
|
|
3053
|
-
|
|
3054
|
-
add: { ...nodeRowObj.add, ...layer }
|
|
3055
|
-
},
|
|
3056
|
-
cell: rowChildrenCell.map(
|
|
3057
|
-
(c, idx) => ({
|
|
3058
|
-
...c,
|
|
3059
|
-
...{
|
|
3060
|
-
path: [paths.flat()[idx]]
|
|
3061
|
-
}
|
|
3062
|
-
})
|
|
3063
|
-
)
|
|
3326
|
+
nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
|
|
3327
|
+
rljson: rljson2,
|
|
3328
|
+
tree: tree2,
|
|
3329
|
+
cell: cell2
|
|
3064
3330
|
});
|
|
3065
3331
|
} else if (nodeType === "cakes") {
|
|
3066
|
-
nodeRowsMatchingChildrenRefs.set(
|
|
3332
|
+
nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
|
|
3067
3333
|
rljson: nodeRow,
|
|
3068
|
-
tree: {
|
|
3334
|
+
tree: opts.skipTree ? {} : {
|
|
3069
3335
|
...nodeRowObj,
|
|
3070
3336
|
layers: { ...nodeRowObj.layers, ...rowChildrenTree }
|
|
3071
3337
|
},
|
|
3072
|
-
cell: rowChildrenCell.map((c) => ({
|
|
3338
|
+
cell: opts.skipCell ? [] : rowChildrenCell.map((c) => ({
|
|
3073
3339
|
...c,
|
|
3074
|
-
...
|
|
3075
|
-
path: c.path.map((p) => ["layers", ...p])
|
|
3076
|
-
}
|
|
3340
|
+
path: c.path.map((p) => ["layers", ...p])
|
|
3077
3341
|
}))
|
|
3078
3342
|
});
|
|
3079
3343
|
} else if (nodeType === "components") {
|
|
3080
3344
|
if (rowChildrenTree && Object.keys(rowChildrenTree).length > 0) {
|
|
3081
|
-
const
|
|
3082
|
-
|
|
3083
|
-
).reduce((acc, curr) => {
|
|
3084
|
-
acc.set(curr.key, curr.ref.tableKey);
|
|
3085
|
-
return acc;
|
|
3086
|
-
}, /* @__PURE__ */ new Map());
|
|
3087
|
-
const resolvedRefs = {};
|
|
3345
|
+
const resolvedProperties = {};
|
|
3346
|
+
const allCells = [];
|
|
3088
3347
|
for (const [colKey, childTableKey] of columnReferenceMap) {
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3348
|
+
if (!opts.skipTree) {
|
|
3349
|
+
resolvedProperties[colKey] = {
|
|
3350
|
+
...rowChildrenTree[childTableKey],
|
|
3351
|
+
_tableKey: childTableKey
|
|
3352
|
+
};
|
|
3353
|
+
}
|
|
3354
|
+
if (!opts.skipCell) {
|
|
3355
|
+
const cell2 = rowChildrenCell.map((c) => ({
|
|
3356
|
+
...c,
|
|
3096
3357
|
path: c.path.filter((p) => p[0] === childTableKey).map((p) => [colKey, ...p.slice(1)])
|
|
3097
|
-
}
|
|
3098
|
-
|
|
3099
|
-
|
|
3358
|
+
}));
|
|
3359
|
+
allCells.push(...cell2);
|
|
3360
|
+
}
|
|
3100
3361
|
}
|
|
3101
|
-
|
|
3102
|
-
[colKey]: tree
|
|
3103
|
-
})).reduce((a, b) => ({ ...a, ...b }), {});
|
|
3104
|
-
const resolvedTree = {
|
|
3105
|
-
...nodeRowObj,
|
|
3106
|
-
...resolvedProperties
|
|
3107
|
-
};
|
|
3108
|
-
const resolvedCell = Object.values(resolvedRefs).map((r) => r.cell).flat();
|
|
3109
|
-
nodeRowsMatchingChildrenRefs.set(nodeRow._hash, {
|
|
3362
|
+
nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
|
|
3110
3363
|
rljson: nodeRow,
|
|
3111
|
-
tree:
|
|
3112
|
-
|
|
3364
|
+
tree: opts.skipTree ? {} : {
|
|
3365
|
+
...nodeRowObj,
|
|
3366
|
+
...resolvedProperties
|
|
3367
|
+
},
|
|
3368
|
+
cell: allCells
|
|
3113
3369
|
});
|
|
3114
3370
|
} else {
|
|
3115
|
-
nodeRowsMatchingChildrenRefs.set(
|
|
3371
|
+
nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
|
|
3116
3372
|
rljson: nodeRow,
|
|
3117
3373
|
tree: { ...nodeRowObj },
|
|
3118
3374
|
cell: rowChildrenCell
|
|
@@ -3124,43 +3380,46 @@ class Db {
|
|
|
3124
3380
|
);
|
|
3125
3381
|
}
|
|
3126
3382
|
}
|
|
3127
|
-
const nodeChildren = makeUnique(
|
|
3128
|
-
merge(...nodeChildrenArray)
|
|
3129
|
-
);
|
|
3383
|
+
const nodeChildren = opts.skipRljson ? {} : makeUnique(merge(...nodeChildrenArray));
|
|
3130
3384
|
const matchedNodeRows = Array.from(nodeRowsMatchingChildrenRefs.values());
|
|
3131
|
-
const
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
_data: matchedNodeRows.map((mr) => mr.rljson),
|
|
3138
|
-
_type: nodeType
|
|
3139
|
-
},
|
|
3140
|
-
...{
|
|
3141
|
-
...nodeHash ? { _hash: nodeHash } : {}
|
|
3142
|
-
}
|
|
3143
|
-
}
|
|
3144
|
-
},
|
|
3145
|
-
...nodeChildren
|
|
3385
|
+
const rljson = opts.skipRljson ? {} : {
|
|
3386
|
+
...node,
|
|
3387
|
+
[nodeTableKey]: {
|
|
3388
|
+
_data: matchedNodeRows.map((mr) => mr.rljson),
|
|
3389
|
+
_type: nodeType,
|
|
3390
|
+
...nodeHash ? { _hash: nodeHash } : {}
|
|
3146
3391
|
},
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3392
|
+
...nodeChildren
|
|
3393
|
+
};
|
|
3394
|
+
const tree = opts.skipTree ? {} : {
|
|
3395
|
+
[nodeTableKey]: {
|
|
3396
|
+
_data: matchedNodeRows.map((mr) => mr.tree),
|
|
3397
|
+
_type: nodeType,
|
|
3398
|
+
...nodeHash ? { _hash: nodeHash } : {}
|
|
3399
|
+
}
|
|
3400
|
+
};
|
|
3401
|
+
const cell = opts.skipCell ? [] : (() => {
|
|
3402
|
+
let totalSize = 0;
|
|
3403
|
+
for (const mr of matchedNodeRows) {
|
|
3404
|
+
totalSize += mr.cell.length;
|
|
3405
|
+
}
|
|
3406
|
+
const cells = new Array(totalSize);
|
|
3407
|
+
let cellIdx = 0;
|
|
3408
|
+
for (let rowIdx = 0; rowIdx < matchedNodeRows.length; rowIdx++) {
|
|
3409
|
+
const mr = matchedNodeRows[rowIdx];
|
|
3410
|
+
for (const c of mr.cell) {
|
|
3411
|
+
cells[cellIdx++] = {
|
|
3412
|
+
...c,
|
|
3413
|
+
path: c.path.map((p) => [nodeTableKey, "_data", rowIdx, ...p])
|
|
3414
|
+
};
|
|
3156
3415
|
}
|
|
3157
|
-
}
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3416
|
+
}
|
|
3417
|
+
return cells;
|
|
3418
|
+
})();
|
|
3419
|
+
const result = {
|
|
3420
|
+
rljson,
|
|
3421
|
+
tree,
|
|
3422
|
+
cell
|
|
3164
3423
|
};
|
|
3165
3424
|
this._cache.set(cacheHash, result);
|
|
3166
3425
|
return result;
|
|
@@ -3192,7 +3451,13 @@ class Db {
|
|
|
3192
3451
|
async join(columnSelection, cakeKey, cakeRef) {
|
|
3193
3452
|
const {
|
|
3194
3453
|
tree: { [cakeKey]: cakesTable }
|
|
3195
|
-
} = await this.get(
|
|
3454
|
+
} = await this.get(
|
|
3455
|
+
Route.fromFlat(`${cakeKey}@${cakeRef}`),
|
|
3456
|
+
{},
|
|
3457
|
+
void 0,
|
|
3458
|
+
void 0,
|
|
3459
|
+
{ skipCell: true, skipRljson: true }
|
|
3460
|
+
);
|
|
3196
3461
|
const cakes = cakesTable._data;
|
|
3197
3462
|
if (cakes.length === 0) {
|
|
3198
3463
|
throw new Error(
|
|
@@ -3266,7 +3531,10 @@ class Db {
|
|
|
3266
3531
|
for (const [tableKey, controller] of Object.entries(controllers)) {
|
|
3267
3532
|
runFns[tableKey] = controller.insert.bind(controller);
|
|
3268
3533
|
}
|
|
3269
|
-
|
|
3534
|
+
const insertHistoryRow = await this._insert(route, tree, runFns, options);
|
|
3535
|
+
if (!options?.skipHistory)
|
|
3536
|
+
await this._writeInsertHistory(route.top.tableKey, insertHistoryRow[0]);
|
|
3537
|
+
return insertHistoryRow;
|
|
3270
3538
|
}
|
|
3271
3539
|
// ...........................................................................
|
|
3272
3540
|
/**
|
|
@@ -3292,7 +3560,7 @@ class Db {
|
|
|
3292
3560
|
const previousHash = nodeSegment[nodeTableKey + "Ref"] ?? null;
|
|
3293
3561
|
const previousTimeId = nodeSegment[nodeTableKey + "InsertHistoryRef"] ?? null;
|
|
3294
3562
|
const previous = previousHash ? await this.getTimeIdsForRef(nodeTableKey, previousHash) : previousTimeId ? [previousTimeId] : [];
|
|
3295
|
-
if (!nodeRoute.isRoot) {
|
|
3563
|
+
if (!nodeRoute.isRoot && nodeType != "trees") {
|
|
3296
3564
|
const childRoute = nodeRoute.deeper(1);
|
|
3297
3565
|
const childTableKey = childRoute.top.tableKey;
|
|
3298
3566
|
if (nodeType === "cakes") {
|
|
@@ -3463,10 +3731,31 @@ class Db {
|
|
|
3463
3731
|
);
|
|
3464
3732
|
}
|
|
3465
3733
|
}
|
|
3734
|
+
if (nodeType === "trees") {
|
|
3735
|
+
const treeObject = tree[nodeTableKey]._data[0];
|
|
3736
|
+
if (!treeObject) {
|
|
3737
|
+
throw new Error(
|
|
3738
|
+
`Db._insert: No tree data found for table "${nodeTableKey}" in route "${route.flat}".`
|
|
3739
|
+
);
|
|
3740
|
+
}
|
|
3741
|
+
const trees = treeFromObject(treeObject);
|
|
3742
|
+
const writePromises = trees.map(
|
|
3743
|
+
(tree2) => runFn("add", tree2, "db.insert")
|
|
3744
|
+
);
|
|
3745
|
+
const writeResults = await Promise.all(writePromises);
|
|
3746
|
+
const lastResult = writeResults[writeResults.length - 1];
|
|
3747
|
+
if (lastResult && lastResult.length > 0) {
|
|
3748
|
+
results.push(
|
|
3749
|
+
...lastResult.map((r) => ({
|
|
3750
|
+
...r,
|
|
3751
|
+
...{ previous },
|
|
3752
|
+
...{ route: route.flat }
|
|
3753
|
+
}))
|
|
3754
|
+
);
|
|
3755
|
+
}
|
|
3756
|
+
}
|
|
3466
3757
|
}
|
|
3467
3758
|
for (const result of results) {
|
|
3468
|
-
if (!options?.skipHistory)
|
|
3469
|
-
await this._writeInsertHistory(nodeTableKey, result);
|
|
3470
3759
|
if (!options?.skipNotification)
|
|
3471
3760
|
this.notify.notify(Route.fromFlat(result.route), result);
|
|
3472
3761
|
}
|
|
@@ -3546,21 +3835,6 @@ class Db {
|
|
|
3546
3835
|
});
|
|
3547
3836
|
}
|
|
3548
3837
|
// ...........................................................................
|
|
3549
|
-
/**
|
|
3550
|
-
* Add a head revision for a cake
|
|
3551
|
-
* @param cakeKey - The cake table key
|
|
3552
|
-
* @param cakeRef - The cake reference
|
|
3553
|
-
*/
|
|
3554
|
-
async addHeadRevision(cakeKey, cakeRef) {
|
|
3555
|
-
const cakeHeadKey = cakeKey + "Heads";
|
|
3556
|
-
const cakeHeadController = await this.getController(cakeHeadKey);
|
|
3557
|
-
return await cakeHeadController.insert("add", {
|
|
3558
|
-
cakeRef,
|
|
3559
|
-
timeId: timeId(),
|
|
3560
|
-
_hash: ""
|
|
3561
|
-
});
|
|
3562
|
-
}
|
|
3563
|
-
// ...........................................................................
|
|
3564
3838
|
/**
|
|
3565
3839
|
* Add a multiEdit
|
|
3566
3840
|
* @param cakeKey - The cake table key
|
|
@@ -4141,9 +4415,6 @@ class MultiEditProcessor {
|
|
|
4141
4415
|
}
|
|
4142
4416
|
const inserted = inserteds[0];
|
|
4143
4417
|
const writtenCakeRef = inserted[this._cakeKey + "Ref"];
|
|
4144
|
-
if (!options?.skipHeadUpdate) {
|
|
4145
|
-
await this._db.addHeadRevision(this._cakeKey, writtenCakeRef);
|
|
4146
|
-
}
|
|
4147
4418
|
if (!options?.skipSaveMultiEdit) {
|
|
4148
4419
|
await this._db.addMultiEdit(this._cakeKey, this._multiEdit);
|
|
4149
4420
|
}
|
|
@@ -4192,7 +4463,11 @@ class MultiEditProcessor {
|
|
|
4192
4463
|
multiEdit.previous
|
|
4193
4464
|
);
|
|
4194
4465
|
const previousMultiEdit = previousMultiEdits[0];
|
|
4195
|
-
|
|
4466
|
+
const previousEditFromMultiEdit = previousMultiEdit.edit;
|
|
4467
|
+
const previousEdit = this._edits[this._edits.length - 2] ? this._edits[this._edits.length - 2]._hash : null;
|
|
4468
|
+
if (previousEdit !== previousEditFromMultiEdit) {
|
|
4469
|
+
return await this._resolve(previousMultiEdit);
|
|
4470
|
+
}
|
|
4196
4471
|
}
|
|
4197
4472
|
}
|
|
4198
4473
|
//...........................................................................
|
|
@@ -4329,6 +4604,14 @@ class MultiEditProcessor {
|
|
|
4329
4604
|
}
|
|
4330
4605
|
return this._join;
|
|
4331
4606
|
}
|
|
4607
|
+
//...........................................................................
|
|
4608
|
+
/**
|
|
4609
|
+
* Get the list of Edits applied in this MultiEditProcessor
|
|
4610
|
+
* @returns Array of Edits
|
|
4611
|
+
*/
|
|
4612
|
+
get edits() {
|
|
4613
|
+
return this._edits;
|
|
4614
|
+
}
|
|
4332
4615
|
}
|
|
4333
4616
|
class MultiEditManager {
|
|
4334
4617
|
constructor(_cakeKey, _db) {
|
|
@@ -5293,27 +5576,6 @@ const staticExample = () => {
|
|
|
5293
5576
|
}
|
|
5294
5577
|
]
|
|
5295
5578
|
});
|
|
5296
|
-
const carCakeHeadTableCfg = hip(
|
|
5297
|
-
createHeadsTableCfg("carCake")
|
|
5298
|
-
);
|
|
5299
|
-
const carCakeHeads = hip({
|
|
5300
|
-
_tableCfg: carCakeHeadTableCfg._hash,
|
|
5301
|
-
_type: "head",
|
|
5302
|
-
_data: [
|
|
5303
|
-
{
|
|
5304
|
-
timeId: "1764756756311:jkCG",
|
|
5305
|
-
cakeRef: carCake._data[0]._hash
|
|
5306
|
-
},
|
|
5307
|
-
{
|
|
5308
|
-
timeId: "1764756756312:1AGV",
|
|
5309
|
-
cakeRef: carCake._data[1]._hash
|
|
5310
|
-
},
|
|
5311
|
-
{
|
|
5312
|
-
timeId: "1764756756312:g8nh",
|
|
5313
|
-
cakeRef: carCake._data[2]._hash
|
|
5314
|
-
}
|
|
5315
|
-
]
|
|
5316
|
-
});
|
|
5317
5579
|
const seriesSliceIdTableCfg = hip(
|
|
5318
5580
|
createSliceIdsTableCfg("seriesSliceId")
|
|
5319
5581
|
);
|
|
@@ -5670,27 +5932,6 @@ const staticExample = () => {
|
|
|
5670
5932
|
}
|
|
5671
5933
|
]
|
|
5672
5934
|
});
|
|
5673
|
-
const seriesCakeHeadTableCfg = hip(
|
|
5674
|
-
createHeadsTableCfg("seriesCake")
|
|
5675
|
-
);
|
|
5676
|
-
const seriesCakeHeads = hip({
|
|
5677
|
-
_tableCfg: seriesCakeHeadTableCfg._hash,
|
|
5678
|
-
_type: "head",
|
|
5679
|
-
_data: [
|
|
5680
|
-
{
|
|
5681
|
-
timeId: "1764756756315:L14y",
|
|
5682
|
-
cakeRef: seriesCake._data[0]._hash
|
|
5683
|
-
},
|
|
5684
|
-
{
|
|
5685
|
-
timeId: "1764756756315:xCXT",
|
|
5686
|
-
cakeRef: seriesCake._data[1]._hash
|
|
5687
|
-
},
|
|
5688
|
-
{
|
|
5689
|
-
timeId: "1764756756315:fZwA",
|
|
5690
|
-
cakeRef: seriesCake._data[2]._hash
|
|
5691
|
-
}
|
|
5692
|
-
]
|
|
5693
|
-
});
|
|
5694
5935
|
const catalogSliceIdTableCfg = hip(
|
|
5695
5936
|
createSliceIdsTableCfg("catalogSliceId")
|
|
5696
5937
|
);
|
|
@@ -5792,19 +6033,6 @@ const staticExample = () => {
|
|
|
5792
6033
|
}
|
|
5793
6034
|
]
|
|
5794
6035
|
});
|
|
5795
|
-
const catalogCakeHeadTableCfg = hip(
|
|
5796
|
-
createHeadsTableCfg("catalogCake")
|
|
5797
|
-
);
|
|
5798
|
-
const catalogCakeHeads = hip({
|
|
5799
|
-
_tableCfg: catalogCakeHeadTableCfg._hash,
|
|
5800
|
-
_type: "head",
|
|
5801
|
-
_data: [
|
|
5802
|
-
{
|
|
5803
|
-
timeId: "1764756756317:5UTy",
|
|
5804
|
-
cakeRef: catalogCake._data[0]._hash
|
|
5805
|
-
}
|
|
5806
|
-
]
|
|
5807
|
-
});
|
|
5808
6036
|
const tableCfgs = {
|
|
5809
6037
|
_data: [
|
|
5810
6038
|
carSliceIdTableCfg,
|
|
@@ -5816,19 +6044,16 @@ const staticExample = () => {
|
|
|
5816
6044
|
carTechnicalLayerTableCfg,
|
|
5817
6045
|
carColorLayerTableCfg,
|
|
5818
6046
|
carCakeTableCfg,
|
|
5819
|
-
carCakeHeadTableCfg,
|
|
5820
6047
|
seriesSliceIdTableCfg,
|
|
5821
6048
|
seriesGeneralTableCfg,
|
|
5822
6049
|
seriesCarsTableCfg,
|
|
5823
6050
|
seriesGeneralLayerTableCfg,
|
|
5824
6051
|
seriesCarsLayerTableCfg,
|
|
5825
6052
|
seriesCakeTableCfg,
|
|
5826
|
-
seriesCakeHeadTableCfg,
|
|
5827
6053
|
catalogSliceIdTableCfg,
|
|
5828
6054
|
catalogSeriesTableCfg,
|
|
5829
6055
|
catalogSeriesLayerTableCfg,
|
|
5830
|
-
catalogCakeTableCfg
|
|
5831
|
-
catalogCakeHeadTableCfg
|
|
6056
|
+
catalogCakeTableCfg
|
|
5832
6057
|
]
|
|
5833
6058
|
};
|
|
5834
6059
|
const staticExample2 = {
|
|
@@ -5841,19 +6066,16 @@ const staticExample = () => {
|
|
|
5841
6066
|
carTechnicalLayer,
|
|
5842
6067
|
carColorLayer,
|
|
5843
6068
|
carCake,
|
|
5844
|
-
carCakeHeads,
|
|
5845
6069
|
seriesSliceId,
|
|
5846
6070
|
seriesGeneral,
|
|
5847
6071
|
seriesCars,
|
|
5848
6072
|
seriesGeneralLayer,
|
|
5849
6073
|
seriesCarsLayer,
|
|
5850
6074
|
seriesCake,
|
|
5851
|
-
seriesCakeHeads,
|
|
5852
6075
|
catalogSliceId,
|
|
5853
6076
|
catalogSeries,
|
|
5854
6077
|
catalogSeriesLayer,
|
|
5855
6078
|
catalogCake,
|
|
5856
|
-
catalogCakeHeads,
|
|
5857
6079
|
tableCfgs
|
|
5858
6080
|
};
|
|
5859
6081
|
return staticExample2;
|