@rljson/db 0.0.9 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/connector/connector.d.ts +30 -0
  2. package/dist/controller/base-controller.d.ts +49 -0
  3. package/dist/controller/cake-controller.d.ts +29 -0
  4. package/dist/controller/component-controller.d.ts +68 -0
  5. package/dist/controller/controller.d.ts +48 -0
  6. package/dist/controller/layer-controller.d.ts +26 -0
  7. package/dist/controller/slice-id-controller.d.ts +22 -0
  8. package/dist/db.d.ts +24 -2
  9. package/dist/db.js +2488 -263
  10. package/dist/db.js.map +1 -0
  11. package/dist/edit/edit-action.d.ts +53 -0
  12. package/dist/edit/edit.d.ts +23 -0
  13. package/dist/edit/multi-edit-manager.d.ts +30 -0
  14. package/dist/edit/multi-edit-processor.d.ts +80 -0
  15. package/dist/example-static/example-static.d.ts +45 -0
  16. package/dist/example-static/mass-data/convert-mass-data.d.ts +5 -0
  17. package/dist/index.d.ts +7 -1
  18. package/dist/join/filter/boolean-filter-processor.d.ts +13 -0
  19. package/dist/join/filter/boolean-filter.d.ts +15 -0
  20. package/dist/join/filter/column-filter-processor.d.ts +9 -0
  21. package/dist/join/filter/column-filter.d.ts +18 -0
  22. package/dist/join/filter/number-filter-processor.d.ts +16 -0
  23. package/dist/join/filter/number-filter.d.ts +7 -0
  24. package/dist/join/filter/row-filter-processor.d.ts +19 -0
  25. package/dist/join/filter/row-filter.d.ts +19 -0
  26. package/dist/join/filter/string-filter-processor.d.ts +15 -0
  27. package/dist/join/filter/string-filter.d.ts +8 -0
  28. package/dist/join/join.d.ts +141 -0
  29. package/dist/join/selection/column-selection.d.ts +48 -0
  30. package/dist/join/set-value/set-value.d.ts +11 -0
  31. package/dist/join/sort/row-sort.d.ts +18 -0
  32. package/dist/notify.d.ts +5 -0
  33. package/dist/tools/inject.d.ts +1 -0
  34. package/dist/tools/isolate.d.ts +1 -0
  35. package/dist/tools/make-unique.d.ts +4 -0
  36. package/dist/tools/merge-trees.d.ts +5 -0
  37. package/package.json +12 -11
package/dist/db.js CHANGED
@@ -1,9 +1,93 @@
1
+ import { timeId, createInsertHistoryTableCfg, Validate, BaseValidator, Route, isTimeId, getTimeIdTimestamp, createSliceIdsTableCfg, createLayerTableCfg, createCakeTableCfg, createHeadsTableCfg } from "@rljson/rljson";
1
2
  import { rmhsh, hsh, Hash, hip } from "@rljson/hash";
2
3
  import { equals, merge } from "@rljson/json";
3
- import { timeId, createInsertHistoryTableCfg, Validate, BaseValidator, Route, isTimeId } from "@rljson/rljson";
4
4
  import { IoMem } from "@rljson/io";
5
5
  import { traverse } from "object-traversal";
6
6
  import { compileExpression } from "filtrex";
7
+ class Connector {
8
+ constructor(_db, _route, _socket) {
9
+ this._db = _db;
10
+ this._route = _route;
11
+ this._socket = _socket;
12
+ this._origin = timeId();
13
+ this._init();
14
+ }
15
+ _origin;
16
+ _callbacks = [];
17
+ _isListening = false;
18
+ _sentRefs = /* @__PURE__ */ new Set();
19
+ _receivedRefs = /* @__PURE__ */ new Set();
20
+ send(ref) {
21
+ if (this._sentRefs.has(ref) || this._receivedRefs.has(ref)) return;
22
+ this._sentRefs.add(ref);
23
+ this.socket.emit(this.route.flat, {
24
+ o: this._origin,
25
+ r: ref
26
+ });
27
+ }
28
+ listen(callback) {
29
+ this._socket.on(this._route.flat, async (payload) => {
30
+ try {
31
+ await callback(payload.r);
32
+ } catch (error) {
33
+ console.error("Error in connector listener callback:", error);
34
+ }
35
+ });
36
+ }
37
+ _init() {
38
+ this._registerSocketObserver();
39
+ this._registerDbObserver();
40
+ this._isListening = true;
41
+ }
42
+ teardown() {
43
+ this._socket.removeAllListeners(this._route.flat);
44
+ this._db.unregisterAllObservers(this._route);
45
+ this._isListening = false;
46
+ }
47
+ _notifyCallbacks(ref) {
48
+ Promise.all(this._callbacks.map((cb) => cb(ref))).catch((err) => {
49
+ console.error(`Error notifying connector callbacks for ref ${ref}:`, err);
50
+ });
51
+ }
52
+ _registerSocketObserver() {
53
+ this.socket.on(this.route.flat, (p) => {
54
+ if (p.o === this._origin) {
55
+ return;
56
+ }
57
+ const ref = p.r;
58
+ if (this._receivedRefs.has(ref)) {
59
+ return;
60
+ }
61
+ this._receivedRefs.add(p.r);
62
+ this._notifyCallbacks(p.r);
63
+ });
64
+ }
65
+ _registerDbObserver() {
66
+ this._db.registerObserver(this._route, (ins) => {
67
+ return new Promise((resolve) => {
68
+ const ref = ins[this.route.root.tableKey + "Ref"];
69
+ if (this._sentRefs.has(ref)) {
70
+ resolve();
71
+ return;
72
+ }
73
+ this.send(ref);
74
+ resolve();
75
+ });
76
+ });
77
+ }
78
+ get socket() {
79
+ return this._socket;
80
+ }
81
+ get route() {
82
+ return this._route;
83
+ }
84
+ get origin() {
85
+ return this._origin;
86
+ }
87
+ get isListening() {
88
+ return this._isListening;
89
+ }
90
+ }
7
91
  class BaseController {
8
92
  constructor(_core, _tableKey) {
9
93
  this._core = _core;
@@ -100,7 +184,6 @@ class CakeController extends BaseController {
100
184
  this._refs = _refs;
101
185
  this._contentType = "cakes";
102
186
  }
103
- _table = null;
104
187
  _baseLayers = {};
105
188
  async init() {
106
189
  if (this._tableKey.endsWith("Cake") === false) {
@@ -108,9 +191,8 @@ class CakeController extends BaseController {
108
191
  `Table ${this._tableKey} is not supported by CakeController.`
109
192
  );
110
193
  }
111
- const rljson = await this._core.dumpTable(this._tableKey);
112
- this._table = rljson[this._tableKey];
113
- if (this._table._type !== "cakes") {
194
+ const contentType = await this._core.contentType(this._tableKey);
195
+ if (contentType !== "cakes") {
114
196
  throw new Error(`Table ${this._tableKey} is not of type cakes.`);
115
197
  }
116
198
  this._tableCfg = await this._core.tableCfg(this._tableKey);
@@ -123,19 +205,10 @@ class CakeController extends BaseController {
123
205
  }
124
206
  const baseCake = baseCakes[0];
125
207
  this._baseLayers = rmhsh(baseCake.layers);
126
- } else {
127
- const cake = this._table._data[0];
128
- if (!!cake) {
129
- this._refs = {
130
- sliceIdsTable: cake.sliceIdsTable,
131
- sliceIdsRow: cake.sliceIdsRow
132
- };
133
- this._baseLayers = rmhsh(cake.layers);
134
- }
135
208
  }
136
209
  }
137
210
  async getChildRefs(where, filter) {
138
- if (!this._table) {
211
+ if (!this._tableCfg) {
139
212
  throw new Error(`Controller not initialized.`);
140
213
  }
141
214
  const childRefs = [];
@@ -226,9 +299,8 @@ class ComponentController extends BaseController {
226
299
  if (!!this._refs && !this._refs.base) {
227
300
  throw new Error(`Refs are not required on ComponentController.`);
228
301
  }
229
- const rljson = await this._core.dumpTable(this._tableKey);
230
- const table = rljson[this._tableKey];
231
- if (this._allowedContentTypes.indexOf(table._type) === -1) {
302
+ const contentType = await this._core.contentType(this._tableKey);
303
+ if (this._allowedContentTypes.indexOf(contentType) === -1) {
232
304
  throw new Error(`Table ${this._tableKey} is not of type components.`);
233
305
  }
234
306
  this._tableCfg = await this._core.tableCfg(this._tableKey);
@@ -569,9 +641,8 @@ class SliceIdController extends BaseController {
569
641
  `Table ${this._tableKey} is not supported by SliceIdController.`
570
642
  );
571
643
  }
572
- const rljson = await this._core.dumpTable(this._tableKey);
573
- const table = rljson[this._tableKey];
574
- if (table._type !== "sliceIds") {
644
+ const contentType = await this._core.contentType(this._tableKey);
645
+ if (contentType !== "sliceIds") {
575
646
  throw new Error(`Table ${this._tableKey} is not of type sliceIds.`);
576
647
  }
577
648
  this._tableCfg = await this._core.tableCfg(this._tableKey);
@@ -582,13 +653,6 @@ class SliceIdController extends BaseController {
582
653
  if (SliceIds2.length === 0) {
583
654
  throw new Error(`Base sliceId ${this._refs.base} does not exist.`);
584
655
  }
585
- } else {
586
- const sliceId = table._data[0];
587
- if (!!sliceId) {
588
- this._refs = {
589
- base: sliceId.base
590
- };
591
- }
592
656
  }
593
657
  }
594
658
  async insert(command, value, origin, refs) {
@@ -687,9 +751,8 @@ class LayerController extends BaseController {
687
751
  `Table ${this._tableKey} is not supported by LayerController.`
688
752
  );
689
753
  }
690
- const rljson = await this._core.dumpTable(this._tableKey);
691
- const table = rljson[this._tableKey];
692
- if (table._type !== "layers") {
754
+ const contentType = await this._core.contentType(this._tableKey);
755
+ if (contentType !== "layers") {
693
756
  throw new Error(`Table ${this._tableKey} is not of type layers.`);
694
757
  }
695
758
  this._tableCfg = await this._core.tableCfg(this._tableKey);
@@ -708,15 +771,6 @@ class LayerController extends BaseController {
708
771
  componentsTable: baseLayer.componentsTable
709
772
  };
710
773
  }
711
- } else {
712
- const layer = table._data[0];
713
- if (!!layer) {
714
- this._refs = {
715
- sliceIdsTable: layer.sliceIdsTable,
716
- sliceIdsTableRow: layer.sliceIdsTableRow,
717
- componentsTable: layer.componentsTable
718
- };
719
- }
720
774
  }
721
775
  }
722
776
  async insert(command, value, origin, refs) {
@@ -952,8 +1006,8 @@ class Core {
952
1006
  * @returns a dump of a table.
953
1007
  * @throws when table name does not exist
954
1008
  */
955
- dumpTable(table) {
956
- return this._io.dumpTable({ table });
1009
+ async dumpTable(table) {
1010
+ return await this._io.dumpTable({ table });
957
1011
  }
958
1012
  // ...........................................................................
959
1013
  /**
@@ -982,33 +1036,23 @@ class Core {
982
1036
  }
983
1037
  // ...........................................................................
984
1038
  async contentType(table) {
985
- const t = await this._io.dumpTable({ table });
986
- const contentType = t[table]?._type;
1039
+ const contentType = await this._io.contentType({ table });
987
1040
  return contentType;
988
1041
  }
989
1042
  // ...........................................................................
990
1043
  async tableCfg(table) {
991
- const { [table]: dump } = await this._io.dumpTable({ table });
992
- const tableCfgRef = dump._tableCfg;
993
1044
  const tableCfgs = await this._io.rawTableCfgs();
994
- let tableCfg;
995
- if (!tableCfgRef) {
996
- tableCfg = tableCfgs.find((tc) => tc.key === table);
997
- } else {
998
- tableCfg = tableCfgs.find(
999
- (tc) => tc.key === table && tc._hash === tableCfgRef
1000
- );
1001
- }
1045
+ const tableCfg = tableCfgs.find((tc) => tc.key === table);
1002
1046
  return tableCfg;
1003
1047
  }
1004
1048
  // ...........................................................................
1005
1049
  /** Reads a specific row from a database table */
1006
- readRow(table, rowHash) {
1007
- return this._io.readRows({ table, where: { _hash: rowHash } });
1050
+ async readRow(table, rowHash) {
1051
+ return await this._io.readRows({ table, where: { _hash: rowHash } });
1008
1052
  }
1009
1053
  // ...........................................................................
1010
- readRows(table, where) {
1011
- return this._io.readRows({ table, where });
1054
+ async readRows(table, where) {
1055
+ return await this._io.readRows({ table, where });
1012
1056
  }
1013
1057
  }
1014
1058
  const inject = (tree, path, value) => {
@@ -2558,6 +2602,14 @@ class Notify {
2558
2602
  }
2559
2603
  }
2560
2604
  // ...........................................................................
2605
+ /**
2606
+ * Unregisters all callbacks for a specific route.
2607
+ * @param route The route to unregister all callbacks from.
2608
+ */
2609
+ unregisterAll(route) {
2610
+ this._callbacks.delete(route.flat);
2611
+ }
2612
+ // ...........................................................................
2561
2613
  /**
2562
2614
  * Notifies all registered callbacks for a specific route with the provided edit protocol row.
2563
2615
  * @param route The route to notify callbacks for.
@@ -2640,7 +2692,7 @@ class Db {
2640
2692
  * @returns An array of Rljson objects matching the route and filter
2641
2693
  * @throws {Error} If the route is not valid or if any controller cannot be created
2642
2694
  */
2643
- async get(route, where, filter, sliceIds) {
2695
+ async get(route, where, filter, sliceIds, options) {
2644
2696
  if (!route.isValid) throw new Error(`Route ${route.flat} is not valid.`);
2645
2697
  const isolatedRoute = await this.isolatePropertyKeyFromRoute(route);
2646
2698
  const controllers = await this.indexedControllers(isolatedRoute);
@@ -2649,7 +2701,9 @@ class Db {
2649
2701
  where,
2650
2702
  controllers,
2651
2703
  filter,
2652
- sliceIds
2704
+ sliceIds,
2705
+ void 0,
2706
+ options
2653
2707
  );
2654
2708
  const dataWithControllers = {
2655
2709
  ...data,
@@ -2667,20 +2721,30 @@ class Db {
2667
2721
  * @param controllers - The controllers to use for fetching data
2668
2722
  * @param filter - Optional filter to apply to the data at the current route segment
2669
2723
  * @param sliceIds - Optional slice IDs to filter the data at the current route segment
2724
+ * @param routeAccumulator - The accumulated route up to the current segment
2725
+ * @param options - Additional options for fetching data
2670
2726
  * @returns - An Rljson object matching the route and filters
2671
2727
  */
2672
- async _get(route, where, controllers, filter, sliceIds, routeAccumulator) {
2673
- const params = {
2674
- route: route.flat,
2675
- where,
2676
- filter,
2677
- sliceIds,
2678
- routeAccumulator: routeAccumulator ? routeAccumulator.flat : ""
2679
- };
2680
- const cacheHash = hsh(rmhsh(params))._hash;
2681
- const isCached = this._cache.has(cacheHash);
2682
- if (isCached) {
2683
- return this._cache.get(cacheHash);
2728
+ async _get(route, where, controllers, filter, sliceIds, routeAccumulator, options) {
2729
+ const opts = options ?? {};
2730
+ const routeHasRefs = route.flat != route.flatWithoutRefs;
2731
+ const hasFilter = filter !== void 0 && filter.length > 0;
2732
+ const cacheable = !!routeHasRefs || !!hasFilter;
2733
+ let cacheHash = "";
2734
+ if (cacheable) {
2735
+ const params = {
2736
+ route: route.flat,
2737
+ where,
2738
+ filter,
2739
+ sliceIds,
2740
+ routeAccumulator: routeAccumulator ? routeAccumulator.flat : "",
2741
+ options: opts
2742
+ };
2743
+ cacheHash = hsh(rmhsh(params))._hash;
2744
+ const isCached = this._cache.has(cacheHash);
2745
+ if (isCached) {
2746
+ return this._cache.get(cacheHash);
2747
+ }
2684
2748
  }
2685
2749
  const nodeTableKey = route.top.tableKey;
2686
2750
  const nodeRoute = route;
@@ -2700,10 +2764,57 @@ class Db {
2700
2764
  [nodeTableKey]: { _data: nodeRows, _type: nodeType, _hash: nodeHash }
2701
2765
  } = await nodeController.get(nodeWhere);
2702
2766
  const nodeColumnCfgs = nodeController.tableCfg().columns;
2767
+ const filterActive = filter && filter.length > 0;
2768
+ const sliceIdActive = nodeSliceIds && nodeSliceIds.length > 0;
2769
+ const filterMap = filterActive ? /* @__PURE__ */ new Map() : null;
2770
+ if (filterActive) {
2771
+ for (const f of filter) {
2772
+ if (f.tableKey === nodeTableKey) {
2773
+ if (!filterMap.has(f.ref)) {
2774
+ filterMap.set(f.ref, []);
2775
+ }
2776
+ filterMap.get(f.ref).push(f);
2777
+ }
2778
+ }
2779
+ }
2780
+ const sliceIdResolvePromises = /* @__PURE__ */ new Map();
2781
+ const nodeSliceIdSet = sliceIdActive ? new Set(nodeSliceIds) : null;
2782
+ if (sliceIdActive) {
2783
+ for (const nodeRow of nodeRows) {
2784
+ if (nodeType === "cakes") {
2785
+ const cake = nodeRow;
2786
+ const key = `${cake.sliceIdsTable}:${cake.sliceIdsRow}`;
2787
+ if (!sliceIdResolvePromises.has(key)) {
2788
+ sliceIdResolvePromises.set(
2789
+ key,
2790
+ this._resolveSliceIds(cake.sliceIdsTable, cake.sliceIdsRow)
2791
+ );
2792
+ }
2793
+ } else if (nodeType === "layers") {
2794
+ const layer = nodeRow;
2795
+ const key = `${layer.sliceIdsTable}:${layer.sliceIdsTableRow}`;
2796
+ if (!sliceIdResolvePromises.has(key)) {
2797
+ sliceIdResolvePromises.set(
2798
+ key,
2799
+ this._resolveSliceIds(
2800
+ layer.sliceIdsTable,
2801
+ layer.sliceIdsTableRow
2802
+ )
2803
+ );
2804
+ }
2805
+ }
2806
+ }
2807
+ }
2808
+ const resolvedSliceIds = /* @__PURE__ */ new Map();
2809
+ if (sliceIdResolvePromises.size > 0) {
2810
+ const entries = Array.from(sliceIdResolvePromises.entries());
2811
+ const results = await Promise.all(entries.map(([, p]) => p));
2812
+ entries.forEach(([key], idx) => {
2813
+ resolvedSliceIds.set(key, new Set(results[idx]));
2814
+ });
2815
+ }
2703
2816
  const nodeRowsFiltered = [];
2704
2817
  for (const nodeRow of nodeRows) {
2705
- const filterActive = filter && filter.length > 0;
2706
- const sliceIdActive = nodeSliceIds && nodeSliceIds.length > 0;
2707
2818
  if (!filterActive && !sliceIdActive) {
2708
2819
  nodeRowsFiltered.push(nodeRow);
2709
2820
  continue;
@@ -2711,12 +2822,10 @@ class Db {
2711
2822
  let filterResult = false;
2712
2823
  const filterProperties = [];
2713
2824
  if (filterActive) {
2714
- for (const f of filter) {
2715
- if (f.tableKey !== nodeTableKey) continue;
2716
- if (nodeRow._hash === f.ref) {
2717
- filterProperties.push(f);
2718
- filterResult = true;
2719
- }
2825
+ const rowFilters = filterMap.get(nodeRow._hash);
2826
+ if (rowFilters) {
2827
+ filterProperties.push(...rowFilters);
2828
+ filterResult = true;
2720
2829
  }
2721
2830
  } else {
2722
2831
  filterResult = true;
@@ -2726,36 +2835,36 @@ class Db {
2726
2835
  switch (nodeType) {
2727
2836
  case "cakes":
2728
2837
  const cake = nodeRow;
2729
- const cakeSliceIds = await this._resolveSliceIds(
2730
- cake.sliceIdsTable,
2731
- cake.sliceIdsRow
2732
- );
2733
- const cakeMatchesSliceIds = nodeSliceIds.filter(
2734
- (sId) => cakeSliceIds.includes(sId)
2735
- );
2736
- if (cakeMatchesSliceIds.length > 0) sliceIdResult = true;
2838
+ const cakeKey = `${cake.sliceIdsTable}:${cake.sliceIdsRow}`;
2839
+ const cakeSliceIdSet = resolvedSliceIds.get(cakeKey);
2840
+ for (const sId of nodeSliceIdSet) {
2841
+ if (cakeSliceIdSet.has(sId)) {
2842
+ sliceIdResult = true;
2843
+ break;
2844
+ }
2845
+ }
2737
2846
  break;
2738
2847
  case "layers":
2739
2848
  const layer = nodeRow;
2740
- const layerSliceIds = await this._resolveSliceIds(
2741
- layer.sliceIdsTable,
2742
- layer.sliceIdsTableRow
2743
- );
2744
- const layerMatchesSliceIds = nodeSliceIds.filter(
2745
- (sId) => layerSliceIds.includes(sId)
2746
- );
2747
- if (layerMatchesSliceIds.length > 0) sliceIdResult = true;
2849
+ const layerKey = `${layer.sliceIdsTable}:${layer.sliceIdsTableRow}`;
2850
+ const layerSliceIdSet = resolvedSliceIds.get(layerKey);
2851
+ for (const sId of nodeSliceIdSet) {
2852
+ if (layerSliceIdSet.has(sId)) {
2853
+ sliceIdResult = true;
2854
+ break;
2855
+ }
2856
+ }
2748
2857
  break;
2749
2858
  case "components":
2750
2859
  if (filterProperties.length > 0) {
2751
- const componentSliceIds = filterProperties.flatMap(
2752
- (f) => f.sliceIds
2753
- );
2754
- const componentMatchesSliceIds = nodeSliceIds.filter(
2755
- (sId) => componentSliceIds.includes(sId)
2860
+ const componentSliceIdSet = new Set(
2861
+ filterProperties.flatMap((f) => f.sliceIds)
2756
2862
  );
2757
- if (componentMatchesSliceIds.length > 0) {
2758
- sliceIdResult = true;
2863
+ for (const sId of nodeSliceIdSet) {
2864
+ if (componentSliceIdSet.has(sId)) {
2865
+ sliceIdResult = true;
2866
+ break;
2867
+ }
2759
2868
  }
2760
2869
  }
2761
2870
  break;
@@ -2776,47 +2885,49 @@ class Db {
2776
2885
  _hash: nodeHash
2777
2886
  }
2778
2887
  };
2779
- const nodeValue = node[nodeTableKey]._data.filter(
2780
- (v) => v !== void 0 && v !== null
2781
- );
2782
2888
  if (route.isRoot) {
2889
+ const baseRouteStr = (routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "");
2783
2890
  if (route.hasPropertyKey) {
2784
- const isolatedNode = this.isolatePropertyFromComponents(
2785
- node,
2786
- route.propertyKey
2891
+ const isolatedNode = opts.skipRljson ? {} : this.isolatePropertyFromComponents(node, route.propertyKey);
2892
+ const routeWithProperty = opts.skipCell ? null : Route.fromFlat(
2893
+ baseRouteStr + `/${route.propertyKey}`
2894
+ ).toRouteWithProperty();
2895
+ const tree3 = opts.skipTree ? {} : { [nodeTableKey]: node[nodeTableKey] };
2896
+ const cell3 = opts.skipCell ? [] : nodeRowsFiltered.map(
2897
+ (v, idx) => ({
2898
+ value: v[route.propertyKey] ?? null,
2899
+ row: v,
2900
+ route: routeWithProperty,
2901
+ path: [[nodeTableKey, "_data", idx, route.propertyKey]]
2902
+ })
2787
2903
  );
2788
2904
  const result3 = {
2789
2905
  rljson: isolatedNode,
2790
- tree: { [nodeTableKey]: node[nodeTableKey] },
2791
- cell: nodeValue.map(
2792
- (v, idx) => ({
2793
- value: v[route.propertyKey] ?? null,
2794
- row: v,
2795
- route: Route.fromFlat(
2796
- (routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "") + `/${route.propertyKey}`
2797
- ).toRouteWithProperty(),
2798
- path: [[nodeTableKey, "_data", idx, route.propertyKey]]
2799
- })
2800
- )
2906
+ tree: tree3,
2907
+ cell: cell3
2801
2908
  };
2802
2909
  this._cache.set(cacheHash, result3);
2803
2910
  return result3;
2804
2911
  }
2912
+ const routeObj = opts.skipCell ? null : Route.fromFlat(baseRouteStr);
2913
+ const rljson2 = opts.skipRljson ? {} : node;
2914
+ const tree2 = opts.skipTree ? {} : { [nodeTableKey]: node[nodeTableKey] };
2915
+ const cell2 = opts.skipCell ? [] : nodeRowsFiltered.map(
2916
+ (v, idx) => ({
2917
+ value: v[route.propertyKey] ?? null,
2918
+ row: v,
2919
+ route: routeObj,
2920
+ path: [[nodeTableKey, "_data", idx]]
2921
+ })
2922
+ );
2805
2923
  const result2 = {
2806
- rljson: node,
2807
- tree: { [nodeTableKey]: node[nodeTableKey] },
2808
- cell: nodeValue.map(
2809
- (v, idx) => ({
2810
- value: v[route.propertyKey] ?? null,
2811
- row: v,
2812
- route: Route.fromFlat(
2813
- (routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "")
2814
- ),
2815
- path: [[nodeTableKey, "_data", idx]]
2816
- })
2817
- )
2924
+ rljson: rljson2,
2925
+ tree: tree2,
2926
+ cell: cell2
2818
2927
  };
2819
- this._cache.set(cacheHash, result2);
2928
+ if (cacheable) {
2929
+ this._cache.set(cacheHash, result2);
2930
+ }
2820
2931
  return result2;
2821
2932
  }
2822
2933
  const childrenRoute = route.deeper();
@@ -2825,12 +2936,20 @@ class Db {
2825
2936
  const childrenThroughProperty = childrenWhere?._through;
2826
2937
  const nodeChildrenArray = [];
2827
2938
  const nodeRowsMatchingChildrenRefs = /* @__PURE__ */ new Map();
2939
+ const columnReferenceMap = nodeType === "components" ? nodeColumnCfgs.filter((c) => c.ref?.tableKey === childrenTableKey).filter(
2940
+ (c) => c.ref && ["components", "cakes"].includes(c.ref.type)
2941
+ ).reduce((acc, curr) => {
2942
+ acc.set(curr.key, curr.ref.tableKey);
2943
+ return acc;
2944
+ }, /* @__PURE__ */ new Map()) : null;
2945
+ const childRefsPromises = nodeRowsFiltered.map(
2946
+ (nodeRow) => nodeController.getChildRefs(nodeRow._hash)
2947
+ );
2948
+ const allChildRefs = await Promise.all(childRefsPromises);
2828
2949
  for (let i = 0; i < nodeRowsFiltered.length; i++) {
2829
2950
  const nodeRow = nodeRowsFiltered[i];
2830
- const nodeRowObj = { ...{}, ...nodeRow };
2831
- const childrenRefs = await nodeController.getChildRefs(
2832
- nodeRow._hash
2833
- );
2951
+ const nodeRowHash = nodeRow._hash;
2952
+ const childrenRefs = allChildRefs[i];
2834
2953
  const childrenRefTypes = /* @__PURE__ */ new Map();
2835
2954
  const childrenRefSliceIds = /* @__PURE__ */ new Set();
2836
2955
  for (const cr of childrenRefs) {
@@ -2851,13 +2970,19 @@ class Db {
2851
2970
  }
2852
2971
  }
2853
2972
  }
2854
- if (childrenRefTypes.size > 1) {
2973
+ const childrenRefTypesSet = /* @__PURE__ */ new Set([
2974
+ ...childrenRefTypes.values()
2975
+ ]);
2976
+ if (childrenRefTypesSet.size > 1) {
2855
2977
  throw new Error(
2856
- `Db._get: Multiple reference types found for children of table ${nodeTableKey}.`
2978
+ `Db._get: Multiple reference types found for children of node table "${nodeTableKey}" and row "${nodeRowHash}". Found types: ${[
2979
+ ...childrenRefTypesSet
2980
+ ].join(", ")}.`
2857
2981
  );
2858
2982
  }
2859
- const cakeIsReferenced = childrenRefTypes.size === 1 && [...childrenRefTypes.values()][0] === "cakes";
2860
- const componentIsReferenced = childrenRefTypes.size === 1 && nodeType === "components" && [...childrenRefTypes.values()][0] === "components";
2983
+ const childrenRefType = childrenRefTypesSet.size > 0 ? [...childrenRefTypesSet][0] : null;
2984
+ const cakeIsReferenced = childrenRefTypes.size > 0 && childrenRefType === "cakes";
2985
+ const componentIsReferenced = childrenRefTypes.size > 0 && nodeType === "components" && childrenRefType === "components";
2861
2986
  const childrenSliceIds = cakeIsReferenced ? [...childrenRefSliceIds] : componentIsReferenced ? void 0 : nodeSliceIds;
2862
2987
  const {
2863
2988
  rljson: rowChildrenRljson,
@@ -2871,29 +2996,43 @@ class Db {
2871
2996
  childrenSliceIds,
2872
2997
  Route.fromFlat(
2873
2998
  (routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "") + "/" + childrenTableKey
2874
- )
2999
+ ),
3000
+ opts
2875
3001
  );
3002
+ if (!rowChildrenRljson[childrenTableKey] || rowChildrenRljson[childrenTableKey]._data.length === 0)
3003
+ continue;
3004
+ nodeChildrenArray.push(rowChildrenRljson);
3005
+ if (opts.skipTree && opts.skipCell) {
3006
+ nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
3007
+ rljson: nodeRow,
3008
+ tree: {},
3009
+ cell: []
3010
+ });
3011
+ continue;
3012
+ }
3013
+ const nodeRowObj = { ...nodeRow };
2876
3014
  if (cakeIsReferenced) {
2877
3015
  const refKey = [...childrenRefTypes.keys()][0];
2878
3016
  nodeRowObj[refKey] = rowChildrenTree;
2879
3017
  }
2880
- if (rowChildrenRljson[childrenTableKey]._data.length === 0) continue;
2881
- nodeChildrenArray.push(rowChildrenRljson);
2882
3018
  if (childrenThroughProperty) {
2883
- const resolvedChildrenHashes = rowChildrenRljson[childrenTableKey]._data.map((rc) => rc._hash);
3019
+ const resolvedChildrenHashesSet = new Set(
3020
+ rowChildrenRljson[childrenTableKey]._data.map(
3021
+ (rc) => rc._hash
3022
+ )
3023
+ );
2884
3024
  for (const nr of nodeRowsFiltered) {
2885
- {
2886
- const throughHashesInRowCouldBeArray = nr[childrenThroughProperty];
2887
- const throughHashesInRow = Array.isArray(
2888
- throughHashesInRowCouldBeArray
2889
- ) ? throughHashesInRowCouldBeArray : [throughHashesInRowCouldBeArray];
2890
- for (const th of throughHashesInRow) {
2891
- if (resolvedChildrenHashes.includes(th)) {
2892
- nodeRowObj[childrenThroughProperty] = {
2893
- ...rowChildrenTree[childrenTableKey],
2894
- ...{ _tableKey: childrenTableKey }
2895
- };
2896
- }
3025
+ const throughHashesInRowCouldBeArray = nr[childrenThroughProperty];
3026
+ const throughHashesInRow = Array.isArray(
3027
+ throughHashesInRowCouldBeArray
3028
+ ) ? throughHashesInRowCouldBeArray : [throughHashesInRowCouldBeArray];
3029
+ for (const th of throughHashesInRow) {
3030
+ if (resolvedChildrenHashesSet.has(th)) {
3031
+ nodeRowObj[childrenThroughProperty] = {
3032
+ ...rowChildrenTree[childrenTableKey],
3033
+ _tableKey: childrenTableKey
3034
+ };
3035
+ break;
2897
3036
  }
2898
3037
  }
2899
3038
  }
@@ -2902,8 +3041,14 @@ class Db {
2902
3041
  const childrenRefsOfRow = childrenRefs.filter(
2903
3042
  (cr) => cr.tableKey == childrenTableKey
2904
3043
  );
3044
+ const resolvedChildrenHashSet = new Set(
3045
+ resolvedChildren.map((ch) => ch._hash)
3046
+ );
2905
3047
  const matchingChildrenRefs = childrenRefsOfRow.filter(
2906
- (cr) => !!resolvedChildren.find((ch) => cr.ref === ch._hash)
3048
+ (cr) => resolvedChildrenHashSet.has(cr.ref)
3049
+ );
3050
+ const matchingRefsMap = new Map(
3051
+ matchingChildrenRefs.map((cr) => [cr.ref, cr])
2907
3052
  );
2908
3053
  if (nodeType === "layers") {
2909
3054
  const compChildrenTrees = rowChildrenTree[childrenTableKey]._data;
@@ -2915,9 +3060,8 @@ class Db {
2915
3060
  };
2916
3061
  });
2917
3062
  const layerTreesAndPaths = components.map(({ tree: comp, path }) => {
2918
- const sliceIds2 = matchingChildrenRefs.find(
2919
- (cr) => cr.ref === comp._hash
2920
- )?.sliceIds;
3063
+ const matchedRef = matchingRefsMap.get(comp._hash);
3064
+ const sliceIds2 = matchedRef?.sliceIds;
2921
3065
  if (!sliceIds2 || sliceIds2.length === 0) {
2922
3066
  throw new Error(
2923
3067
  `Db._get: No sliceIds found for component ${comp._hash} of layer ${nodeRow._hash}.`
@@ -2929,99 +3073,90 @@ class Db {
2929
3073
  );
2930
3074
  }
2931
3075
  const sliceId = sliceIds2[0];
2932
- const pathsForSliceId = [
2933
- ...path.map((p) => p[0]).map((p) => {
2934
- const newPath = [...p];
2935
- newPath[2] = 0;
2936
- return ["add", sliceId, ...newPath];
2937
- })
2938
- ];
3076
+ const pathsForSliceId = path.map((p) => {
3077
+ const newPath = [...p[0]];
3078
+ newPath[2] = 0;
3079
+ return ["add", sliceId, ...newPath];
3080
+ });
2939
3081
  return {
2940
3082
  [sliceId]: {
2941
3083
  tree: {
2942
3084
  [childrenTableKey]: {
2943
- ...{ _data: [comp] },
2944
- ...{ _type: "components" }
3085
+ _data: [comp],
3086
+ _type: "components"
2945
3087
  }
2946
3088
  },
2947
3089
  path: pathsForSliceId
2948
3090
  }
2949
3091
  };
2950
3092
  });
2951
- const layer = layerTreesAndPaths.flatMap(
2952
- (ltap) => Object.entries(ltap).map(([sliceId, { tree }]) => ({
2953
- [sliceId]: tree
2954
- }))
2955
- ).reduce((a, b) => ({ ...a, ...b }), {});
2956
- const paths = layerTreesAndPaths.map(
2957
- (ltap) => Object.values(ltap)[0].path
3093
+ const layer = {};
3094
+ const paths = [];
3095
+ for (const ltap of layerTreesAndPaths) {
3096
+ for (const [sliceId, value] of Object.entries(ltap)) {
3097
+ layer[sliceId] = value.tree;
3098
+ if (!opts.skipCell) {
3099
+ paths.push(value.path);
3100
+ }
3101
+ }
3102
+ }
3103
+ const rljson2 = nodeRow;
3104
+ const tree2 = opts.skipTree ? {} : {
3105
+ ...nodeRowObj,
3106
+ add: { ...nodeRowObj.add, ...layer }
3107
+ };
3108
+ const cell2 = opts.skipCell ? [] : rowChildrenCell.map(
3109
+ (c, idx) => ({
3110
+ ...c,
3111
+ path: [paths.flat()[idx]]
3112
+ })
2958
3113
  );
2959
- nodeRowsMatchingChildrenRefs.set(nodeRow._hash, {
2960
- rljson: nodeRow,
2961
- tree: {
2962
- ...nodeRowObj,
2963
- add: { ...nodeRowObj.add, ...layer }
2964
- },
2965
- cell: rowChildrenCell.map(
2966
- (c, idx) => ({
2967
- ...c,
2968
- ...{
2969
- path: [paths.flat()[idx]]
2970
- }
2971
- })
2972
- )
3114
+ nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
3115
+ rljson: rljson2,
3116
+ tree: tree2,
3117
+ cell: cell2
2973
3118
  });
2974
3119
  } else if (nodeType === "cakes") {
2975
- nodeRowsMatchingChildrenRefs.set(nodeRow._hash, {
3120
+ nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
2976
3121
  rljson: nodeRow,
2977
- tree: {
3122
+ tree: opts.skipTree ? {} : {
2978
3123
  ...nodeRowObj,
2979
3124
  layers: { ...nodeRowObj.layers, ...rowChildrenTree }
2980
3125
  },
2981
- cell: rowChildrenCell.map((c) => ({
3126
+ cell: opts.skipCell ? [] : rowChildrenCell.map((c) => ({
2982
3127
  ...c,
2983
- ...{
2984
- path: c.path.map((p) => ["layers", ...p])
2985
- }
3128
+ path: c.path.map((p) => ["layers", ...p])
2986
3129
  }))
2987
3130
  });
2988
3131
  } else if (nodeType === "components") {
2989
3132
  if (rowChildrenTree && Object.keys(rowChildrenTree).length > 0) {
2990
- const columnReferenceMap = nodeColumnCfgs.filter(
2991
- (c) => c.ref && ["components", "cakes"].includes(c.ref.type)
2992
- ).reduce((acc, curr) => {
2993
- acc.set(curr.key, curr.ref.tableKey);
2994
- return acc;
2995
- }, /* @__PURE__ */ new Map());
2996
- const resolvedRefs = {};
3133
+ const resolvedProperties = {};
3134
+ const allCells = [];
2997
3135
  for (const [colKey, childTableKey] of columnReferenceMap) {
2998
- const tree = {
2999
- ...rowChildrenTree[childTableKey],
3000
- ...{ _tableKey: childTableKey }
3001
- };
3002
- const cell = rowChildrenCell.map((c) => ({
3003
- ...c,
3004
- ...{
3136
+ if (!opts.skipTree) {
3137
+ resolvedProperties[colKey] = {
3138
+ ...rowChildrenTree[childTableKey],
3139
+ _tableKey: childTableKey
3140
+ };
3141
+ }
3142
+ if (!opts.skipCell) {
3143
+ const cell2 = rowChildrenCell.map((c) => ({
3144
+ ...c,
3005
3145
  path: c.path.filter((p) => p[0] === childTableKey).map((p) => [colKey, ...p.slice(1)])
3006
- }
3007
- }));
3008
- resolvedRefs[colKey] = { tree, cell };
3146
+ }));
3147
+ allCells.push(...cell2);
3148
+ }
3009
3149
  }
3010
- const resolvedProperties = Object.entries(resolvedRefs).map(([colKey, { tree }]) => ({
3011
- [colKey]: tree
3012
- })).reduce((a, b) => ({ ...a, ...b }), {});
3013
- const resolvedTree = {
3014
- ...nodeRowObj,
3015
- ...resolvedProperties
3016
- };
3017
- const resolvedCell = Object.values(resolvedRefs).map((r) => r.cell).flat();
3018
- nodeRowsMatchingChildrenRefs.set(nodeRow._hash, {
3150
+ nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
3019
3151
  rljson: nodeRow,
3020
- tree: resolvedTree,
3021
- cell: resolvedCell
3152
+ tree: opts.skipTree ? {} : {
3153
+ ...nodeRowObj,
3154
+ ...resolvedProperties
3155
+ },
3156
+ cell: allCells
3022
3157
  });
3023
3158
  } else {
3024
- nodeRowsMatchingChildrenRefs.set(nodeRow._hash, {
3159
+ nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
3025
3160
  rljson: nodeRow,
3026
3161
  tree: { ...nodeRowObj },
3027
3162
  cell: rowChildrenCell
@@ -3033,43 +3168,46 @@ class Db {
3033
3168
  );
3034
3169
  }
3035
3170
  }
3036
- const nodeChildren = makeUnique(
3037
- merge(...nodeChildrenArray)
3038
- );
3171
+ const nodeChildren = opts.skipRljson ? {} : makeUnique(merge(...nodeChildrenArray));
3039
3172
  const matchedNodeRows = Array.from(nodeRowsMatchingChildrenRefs.values());
3040
- const result = {
3041
- rljson: {
3042
- ...node,
3043
- ...{
3044
- [nodeTableKey]: {
3045
- ...{
3046
- _data: matchedNodeRows.map((mr) => mr.rljson),
3047
- _type: nodeType
3048
- },
3049
- ...{
3050
- ...nodeHash ? { _hash: nodeHash } : {}
3051
- }
3052
- }
3053
- },
3054
- ...nodeChildren
3173
+ const rljson = opts.skipRljson ? {} : {
3174
+ ...node,
3175
+ [nodeTableKey]: {
3176
+ _data: matchedNodeRows.map((mr) => mr.rljson),
3177
+ _type: nodeType,
3178
+ ...nodeHash ? { _hash: nodeHash } : {}
3055
3179
  },
3056
- tree: {
3057
- [nodeTableKey]: {
3058
- ...{
3059
- _data: matchedNodeRows.map((mr) => mr.tree),
3060
- _type: nodeType
3061
- },
3062
- ...{
3063
- ...nodeHash ? { _hash: nodeHash } : {}
3064
- }
3180
+ ...nodeChildren
3181
+ };
3182
+ const tree = opts.skipTree ? {} : {
3183
+ [nodeTableKey]: {
3184
+ _data: matchedNodeRows.map((mr) => mr.tree),
3185
+ _type: nodeType,
3186
+ ...nodeHash ? { _hash: nodeHash } : {}
3187
+ }
3188
+ };
3189
+ const cell = opts.skipCell ? [] : (() => {
3190
+ let totalSize = 0;
3191
+ for (const mr of matchedNodeRows) {
3192
+ totalSize += mr.cell.length;
3193
+ }
3194
+ const cells = new Array(totalSize);
3195
+ let cellIdx = 0;
3196
+ for (let rowIdx = 0; rowIdx < matchedNodeRows.length; rowIdx++) {
3197
+ const mr = matchedNodeRows[rowIdx];
3198
+ for (const c of mr.cell) {
3199
+ cells[cellIdx++] = {
3200
+ ...c,
3201
+ path: c.path.map((p) => [nodeTableKey, "_data", rowIdx, ...p])
3202
+ };
3065
3203
  }
3066
- },
3067
- cell: matchedNodeRows.map(
3068
- (mr, idx) => mr.cell.map((c) => ({
3069
- ...c,
3070
- ...{ path: c.path.map((p) => [nodeTableKey, "_data", idx, ...p]) }
3071
- }))
3072
- ).flat()
3204
+ }
3205
+ return cells;
3206
+ })();
3207
+ const result = {
3208
+ rljson,
3209
+ tree,
3210
+ cell
3073
3211
  };
3074
3212
  this._cache.set(cacheHash, result);
3075
3213
  return result;
@@ -3101,7 +3239,13 @@ class Db {
3101
3239
  async join(columnSelection, cakeKey, cakeRef) {
3102
3240
  const {
3103
3241
  tree: { [cakeKey]: cakesTable }
3104
- } = await this.get(Route.fromFlat(`${cakeKey}@${cakeRef}`), {});
3242
+ } = await this.get(
3243
+ Route.fromFlat(`${cakeKey}@${cakeRef}`),
3244
+ {},
3245
+ void 0,
3246
+ void 0,
3247
+ { skipCell: true, skipRljson: true }
3248
+ );
3105
3249
  const cakes = cakesTable._data;
3106
3250
  if (cakes.length === 0) {
3107
3251
  throw new Error(
@@ -3400,6 +3544,13 @@ class Db {
3400
3544
  this.notify.unregister(route, callback);
3401
3545
  }
3402
3546
  // ...........................................................................
3547
+ /**
3548
+ * Unregisters all observers from all routes
3549
+ */
3550
+ unregisterAllObservers(route) {
3551
+ this.notify.unregisterAll(route);
3552
+ }
3553
+ // ...........................................................................
3403
3554
  /**
3404
3555
  * Get a controller for a specific table
3405
3556
  * @param tableKey - The key of the table to get the controller for
@@ -3553,7 +3704,9 @@ class Db {
3553
3704
  cakeKey + "EditHistory"
3554
3705
  );
3555
3706
  const { [cakeKey + "EditHistory"]: result } = await editHistoryController.get(where);
3556
- return result._data;
3707
+ return result._data.sort(
3708
+ (h1, h2) => getTimeIdTimestamp(h2.timeId) - getTimeIdTimestamp(h1.timeId)
3709
+ );
3557
3710
  }
3558
3711
  // ...........................................................................
3559
3712
  /**
@@ -3702,13 +3855,2085 @@ class Db {
3702
3855
  return result;
3703
3856
  }
3704
3857
  // ...........................................................................
3858
+ /**
3859
+ * Clone the Db instance with a new Io instance
3860
+ * @param io - The new Io instance
3861
+ * @returns A new Db instance with the same cache as the current instance
3862
+ */
3863
+ clone(io) {
3864
+ const newDb = new Db(io);
3865
+ newDb.setCache(new Map(this._cache));
3866
+ return newDb;
3867
+ }
3868
+ // ...........................................................................
3705
3869
  /**
3706
3870
  * Get the current cache of the Db instance
3707
3871
  */
3708
3872
  get cache() {
3709
3873
  return this._cache;
3710
3874
  }
3875
+ // ...........................................................................
3876
+ /**
3877
+ * Set the cache of the Db instance
3878
+ * @param cache - The new cache to set
3879
+ */
3880
+ setCache(cache) {
3881
+ this._cache = cache;
3882
+ }
3883
+ }
3884
+ const exampleEditActionColumnSelection = () => ({
3885
+ name: "Car Selection",
3886
+ type: "selection",
3887
+ data: {
3888
+ columns: ColumnSelection.exampleCarsColumnSelection().columns
3889
+ },
3890
+ _hash: ""
3891
+ });
3892
+ const exampleEditActionColumnSelectionOnlySomeColumns = () => ({
3893
+ name: "Car Selection - Some Columns",
3894
+ type: "selection",
3895
+ data: {
3896
+ columns: ColumnSelection.exampleCarsColumnSelectionOnlySomeColumns().columns
3897
+ },
3898
+ _hash: ""
3899
+ });
3900
+ const exampleEditActionRowFilter = () => ({
3901
+ name: "Electric Cars Filter",
3902
+ type: "filter",
3903
+ data: {
3904
+ columnFilters: [
3905
+ {
3906
+ type: "boolean",
3907
+ column: "carCake/carGeneralLayer/carGeneral/isElectric",
3908
+ operator: "equals",
3909
+ search: true,
3910
+ _hash: ""
3911
+ },
3912
+ {
3913
+ type: "number",
3914
+ column: "carCake/carTechnicalLayer/carTechnical/carDimensions/length",
3915
+ operator: "greaterThan",
3916
+ search: 4e3,
3917
+ _hash: ""
3918
+ }
3919
+ ],
3920
+ operator: "and",
3921
+ value: true,
3922
+ _hash: ""
3923
+ },
3924
+ _hash: ""
3925
+ });
3926
+ const exampleEditActionSetValue = () => ({
3927
+ name: "Set: Service Intervals to [15000, 30000, 45000, 60000]",
3928
+ type: "setValue",
3929
+ data: {
3930
+ route: "carCake/carGeneralLayer/carGeneral/serviceIntervals",
3931
+ value: [15e3, 3e4, 45e3, 6e4],
3932
+ _hash: ""
3933
+ },
3934
+ _hash: ""
3935
+ });
3936
+ const exampleEditSetValueReferenced = () => ({
3937
+ name: "Set: Length to 4200",
3938
+ type: "setValue",
3939
+ data: {
3940
+ route: "carCake/carTechnicalLayer/carTechnical/carDimensions/length",
3941
+ value: 4800,
3942
+ _hash: ""
3943
+ },
3944
+ _hash: ""
3945
+ });
3946
+ const exampleEditActionRowSort = () => ({
3947
+ name: "Sort By Brand Edit",
3948
+ type: "sort",
3949
+ data: {
3950
+ ["carCake/carGeneralLayer/carGeneral/brand"]: "asc"
3951
+ },
3952
+ _hash: ""
3953
+ });
3954
+ class RowSort {
3955
+ constructor(columnSorts) {
3956
+ this._columnSorts = this._initColumnSorts(columnSorts);
3957
+ }
3958
+ // ...........................................................................
3959
+ /**
3960
+ * Sorts the rows of a join according to the sort configuration.
3961
+ * @param join - The join to be sorted
3962
+ * @returns Returns the row indices in a sorted manner
3963
+ */
3964
+ applyTo(join) {
3965
+ if (join.rowCount === 0) {
3966
+ return join.rowIndices;
3967
+ }
3968
+ this._throwOnWrongRoutes(join);
3969
+ const routeHashes = join.columnSelection.routeHashes;
3970
+ const sortIndices = [];
3971
+ const sortOrders = [];
3972
+ let hasSorts = false;
3973
+ for (const item of this._columnSorts) {
3974
+ const index = routeHashes.indexOf(item.routeHash);
3975
+ sortIndices.push(index);
3976
+ sortOrders.push(item.order);
3977
+ hasSorts = true;
3978
+ }
3979
+ if (!hasSorts) {
3980
+ return join.rowIndices;
3981
+ }
3982
+ return this._sortRows(join, sortIndices, sortOrders);
3983
+ }
3984
+ // ...........................................................................
3985
+ /* v8 ignore next -- @preserve */
3986
+ get columnSorts() {
3987
+ const result = {};
3988
+ for (const sort of this._columnSorts) {
3989
+ result[sort.route] = sort.order;
3990
+ }
3991
+ return result;
3992
+ }
3993
+ // ######################
3994
+ // Private
3995
+ // ######################
3996
+ _columnSorts;
3997
+ // ...........................................................................
3998
+ _initColumnSorts(columnSorts) {
3999
+ const result = [];
4000
+ const columns = Object.keys(columnSorts);
4001
+ const columnSelection = ColumnSelection.fromRoutes(
4002
+ columns.map((c) => Route.fromFlat(c))
4003
+ );
4004
+ const routes = columnSelection.routes;
4005
+ const routeHashes = columnSelection.routeHashes;
4006
+ for (let i = 0; i < routes.length; i++) {
4007
+ const route = routes[i];
4008
+ const routeHash = routeHashes[i];
4009
+ result.push({
4010
+ route,
4011
+ routeHash,
4012
+ order: columnSorts[route]
4013
+ });
4014
+ }
4015
+ return result;
4016
+ }
4017
+ // ...........................................................................
4018
+ _sortRows(join, sortIndices, sortOrders) {
4019
+ const result = [...join.rowIndices];
4020
+ return result.sort((a, b) => {
4021
+ const rowA = join.row(a);
4022
+ const rowB = join.row(b);
4023
+ let i = 0;
4024
+ for (const index of sortIndices) {
4025
+ const sort = sortOrders[i++];
4026
+ const rowAInsertValues = rowA[index].inserts ? Array.isArray(rowA[index].inserts[0].cell[0].value) ? rowA[index].inserts[0].cell[0].value : [rowA[index].inserts[0].cell[0].value] : null;
4027
+ const rowAValue = rowA[index].value.cell[0].value ? Array.isArray(rowA[index].value?.cell[0].value) ? rowA[index].value.cell[0].value : [rowA[index].value.cell[0].value] : null;
4028
+ const rowBInsertValues = rowB[index].inserts ? Array.isArray(rowB[index].inserts[0].cell[0].value) ? rowB[index].inserts[0].cell[0].value : [rowB[index].inserts[0].cell[0].value] : null;
4029
+ const rowBValue = rowB[index].value.cell[0].value ? Array.isArray(rowB[index].value?.cell[0].value) ? rowB[index].value.cell[0].value : [rowB[index].value.cell[0].value] : null;
4030
+ const vA = rowAInsertValues && rowAInsertValues[0] ? rowAInsertValues[0] : rowAValue ? rowAValue[0] : null;
4031
+ const vB = rowBInsertValues && rowBInsertValues[0] ? rowBInsertValues[0] : rowBValue ? rowBValue[0] : null;
4032
+ if (vA === vB) {
4033
+ continue;
4034
+ }
4035
+ if (sort === "asc") {
4036
+ return vA < vB ? -1 : 1;
4037
+ } else {
4038
+ return vA < vB ? 1 : -1;
4039
+ }
4040
+ }
4041
+ return 0;
4042
+ });
4043
+ }
4044
+ // ...........................................................................
4045
+ _throwOnWrongRoutes(join) {
4046
+ const availableRoutes = join.columnSelection.routes;
4047
+ for (const item of Object.values(this._columnSorts)) {
4048
+ const route = item.route;
4049
+ if (availableRoutes.includes(route) === false) {
4050
+ throw new Error(
4051
+ `RowFilterProcessor: Error while applying sort to join: There is a sort entry for route "${route}", but the join does not have a column with this route.
4052
+
4053
+ Available routes:
4054
+ ${availableRoutes.map((a) => `- ${a}`).join("\n")}`
4055
+ );
4056
+ }
4057
+ }
4058
+ }
3711
4059
  }
4060
+ class MultiEditProcessor {
4061
+ constructor(_db, _cakeKey, _cakeRef) {
4062
+ this._db = _db;
4063
+ this._cakeKey = _cakeKey;
4064
+ this._cakeRef = _cakeRef;
4065
+ }
4066
+ _multiEdit = null;
4067
+ _edits = [];
4068
+ _join = null;
4069
+ //...........................................................................
4070
+ /**
4071
+ * Create MultiEditProcessor from EditHistory
4072
+ * @param db - Db instance
4073
+ * @param cakeKey - Cake key
4074
+ * @param editHistory - EditHistory
4075
+ * @returns MultiEditProcessor
4076
+ */
4077
+ static async fromEditHistory(db, cakeKey, editHistory) {
4078
+ if (!editHistory || !editHistory.multiEditRef) {
4079
+ throw new Error("MultiEditProcessor: Invalid EditHistory provided.");
4080
+ }
4081
+ const cakeRef = editHistory.dataRef;
4082
+ const multiEdits = await db.getMultiEdits(
4083
+ cakeKey,
4084
+ editHistory.multiEditRef
4085
+ );
4086
+ if (!multiEdits || multiEdits.length === 0) {
4087
+ throw new Error(
4088
+ `MultiEditProcessor: MultiEdit not found for ref ${editHistory.multiEditRef}`
4089
+ );
4090
+ }
4091
+ if (multiEdits.length > 1) {
4092
+ throw new Error(
4093
+ `MultiEditProcessor: Multiple MultiEdits found for ref ${editHistory.multiEditRef}`
4094
+ );
4095
+ }
4096
+ const multiEdit = multiEdits[0];
4097
+ return MultiEditProcessor.fromMultiEdit(db, cakeKey, cakeRef, multiEdit);
4098
+ }
4099
+ //...........................................................................
4100
+ /**
4101
+ * Create MultiEditProcessor from MultiEdit
4102
+ * @param db - Db instance
4103
+ * @param cakeKey - Cake key
4104
+ * @param cakeRef - Cake ref
4105
+ * @param multiEdit - MultiEdit
4106
+ * @returns MultiEditProcessor
4107
+ */
4108
+ static async fromMultiEdit(db, cakeKey, cakeRef, multiEdit) {
4109
+ const processor = new MultiEditProcessor(db, cakeKey, cakeRef);
4110
+ await processor._resolve(multiEdit);
4111
+ await processor._processAll();
4112
+ return processor;
4113
+ }
4114
+ get join() {
4115
+ if (!this._join) {
4116
+ throw new Error("MultiEditProcessor: Join not processed yet.");
4117
+ }
4118
+ return this._join;
4119
+ }
4120
+ get multiEdit() {
4121
+ if (!this._multiEdit) {
4122
+ throw new Error("MultiEditProcessor: MultiEdit not resolved yet.");
4123
+ }
4124
+ return this._multiEdit;
4125
+ }
4126
+ get cakeRef() {
4127
+ return this._cakeRef;
4128
+ }
4129
+ //...........................................................................
4130
+ /**
4131
+ * Apply an Edit to the MultiEditProcessor
4132
+ * @param edit - Edit to apply
4133
+ * @returns MultiEditProcessor
4134
+ */
4135
+ async edit(edit) {
4136
+ this._edits.push(edit);
4137
+ this._join = await this._process(edit);
4138
+ this._multiEdit = hip({
4139
+ _hash: "",
4140
+ edit: edit._hash,
4141
+ previous: this.multiEdit ? this.multiEdit._hash : null
4142
+ });
4143
+ return this;
4144
+ }
4145
+ async applyEditHistory(editHistory) {
4146
+ if (!editHistory || !editHistory.multiEditRef) {
4147
+ throw new Error("MultiEditProcessor: Invalid EditHistory provided.");
4148
+ }
4149
+ const multiEdits = await this._db.getMultiEdits(
4150
+ this._cakeKey,
4151
+ editHistory.multiEditRef
4152
+ );
4153
+ if (!multiEdits || multiEdits.length === 0) {
4154
+ throw new Error(
4155
+ `MultiEditProcessor: MultiEdit not found for ref ${editHistory.multiEditRef}`
4156
+ );
4157
+ }
4158
+ if (multiEdits.length > 1) {
4159
+ throw new Error(
4160
+ `MultiEditProcessor: Multiple MultiEdits found for ref ${editHistory.multiEditRef}`
4161
+ );
4162
+ }
4163
+ const multiEdit = multiEdits[0];
4164
+ await this._resolve(multiEdit);
4165
+ await this._processAll();
4166
+ return this;
4167
+ }
4168
+ //...........................................................................
4169
+ /**
4170
+ * Publish the MultiEditProcessor. Inserts the resulting Join as new data,
4171
+ * updates the head revision, and saves the resulting MultiEdit.
4172
+ * @param options - Publish options
4173
+ * @returns MultiEditProcessor
4174
+ */
4175
+ async publish(options) {
4176
+ const inserts = this.join.insert();
4177
+ if (inserts.length === 0) {
4178
+ throw new Error("MultiEditProcessor: No inserts to publish.");
4179
+ }
4180
+ if (inserts.length > 1) {
4181
+ throw new Error(
4182
+ "MultiEditProcessor: Multiple inserts not supported yet."
4183
+ );
4184
+ }
4185
+ const insert = inserts[0];
4186
+ const inserteds = await this._db.insert(insert.route, insert.tree);
4187
+ if (inserteds.length === 0) {
4188
+ throw new Error("MultiEditProcessor: No rows inserted.");
4189
+ }
4190
+ if (inserteds.length > 1) {
4191
+ throw new Error(
4192
+ "MultiEditProcessor: Multiple inserted rows not supported yet."
4193
+ );
4194
+ }
4195
+ const inserted = inserteds[0];
4196
+ const writtenCakeRef = inserted[this._cakeKey + "Ref"];
4197
+ if (!options?.skipHeadUpdate) {
4198
+ await this._db.addHeadRevision(this._cakeKey, writtenCakeRef);
4199
+ }
4200
+ if (!options?.skipSaveMultiEdit) {
4201
+ await this._db.addMultiEdit(this._cakeKey, this._multiEdit);
4202
+ }
4203
+ return new MultiEditProcessor(this._db, this._cakeKey, writtenCakeRef);
4204
+ }
4205
+ //...........................................................................
4206
+ /**
4207
+ * Clone the MultiEditProcessor
4208
+ * @returns Cloned MultiEditProcessor
4209
+ */
4210
+ clone() {
4211
+ const clone = new MultiEditProcessor(
4212
+ this._db,
4213
+ this._cakeKey,
4214
+ this._cakeRef
4215
+ );
4216
+ clone._multiEdit = this._multiEdit;
4217
+ clone._edits = [...this._edits];
4218
+ clone._join = this._join;
4219
+ return clone;
4220
+ }
4221
+ //...........................................................................
4222
+ /**
4223
+ * Resolve MultiEdit chain recursively
4224
+ * @param multiEdit - MultiEdit to resolve
4225
+ * @returns Promise<void>
4226
+ */
4227
+ async _resolve(multiEdit) {
4228
+ this._multiEdit = multiEdit;
4229
+ const edits = await this._db.getEdits(this._cakeKey, multiEdit.edit);
4230
+ if (edits.length === 0) {
4231
+ throw new Error(
4232
+ `MultiEditProcessor: Edit not found for ref ${multiEdit.edit}`
4233
+ );
4234
+ }
4235
+ if (edits.length > 1) {
4236
+ throw new Error(
4237
+ `MultiEditProcessor: Multiple Edits found for ref ${multiEdit.edit}`
4238
+ );
4239
+ }
4240
+ const edit = edits[0];
4241
+ this._edits.push(edit);
4242
+ if (multiEdit.previous) {
4243
+ const previousMultiEdits = await this._db.getMultiEdits(
4244
+ this._cakeKey,
4245
+ multiEdit.previous
4246
+ );
4247
+ const previousMultiEdit = previousMultiEdits[0];
4248
+ const previousEditFromMultiEdit = previousMultiEdit.edit;
4249
+ const previousEdit = this._edits[this._edits.length - 2] ? this._edits[this._edits.length - 2]._hash : null;
4250
+ if (previousEdit !== previousEditFromMultiEdit) {
4251
+ return await this._resolve(previousMultiEdit);
4252
+ }
4253
+ }
4254
+ }
4255
+ //...........................................................................
4256
+ /**
4257
+ * Process all Edits in the MultiEditProcessor
4258
+ * @returns Resulting Join
4259
+ */
4260
+ async _processAll() {
4261
+ for (let i = this._edits.length - 1; i >= 0; i--) {
4262
+ const edit = this._edits[i];
4263
+ this._join = await this._process(edit);
4264
+ }
4265
+ return this._join;
4266
+ }
4267
+ //...........................................................................
4268
+ /**
4269
+ * Process a single Edit and update the Join
4270
+ * @param edit - Edit to process
4271
+ * @returns Resulting Join
4272
+ */
4273
+ async _process(edit) {
4274
+ const action = edit.action;
4275
+ if (!this._join) {
4276
+ switch (action.type) {
4277
+ case "selection":
4278
+ const editColInfos = edit.action.data.columns;
4279
+ const editColSelection = new ColumnSelection(editColInfos);
4280
+ this._join = await this._db.join(
4281
+ editColSelection,
4282
+ this._cakeKey,
4283
+ this._cakeRef
4284
+ );
4285
+ break;
4286
+ case "setValue":
4287
+ const editSetValue = edit.action.data;
4288
+ const editSetValueKey = Route.fromFlat(editSetValue.route).segment().tableKey;
4289
+ const editSetValueColumnInfo = {
4290
+ key: editSetValueKey,
4291
+ route: editSetValue.route,
4292
+ alias: editSetValueKey,
4293
+ titleLong: "",
4294
+ titleShort: "",
4295
+ type: "jsonValue",
4296
+ _hash: ""
4297
+ };
4298
+ const editSetValueColSelection = new ColumnSelection([
4299
+ editSetValueColumnInfo
4300
+ ]);
4301
+ this._join = (await this._db.join(
4302
+ editSetValueColSelection,
4303
+ this._cakeKey,
4304
+ this._cakeRef
4305
+ )).setValue(editSetValue);
4306
+ break;
4307
+ case "sort":
4308
+ const editRowSort = rmhsh(edit).action.data;
4309
+ const editRowSortColumnInfos = [];
4310
+ for (const routeStr of Object.keys(editRowSort)) {
4311
+ const route = Route.fromFlat(routeStr);
4312
+ const tableKey = route.segment().tableKey;
4313
+ const columnInfo = {
4314
+ key: tableKey,
4315
+ route: routeStr,
4316
+ alias: tableKey,
4317
+ titleLong: "",
4318
+ titleShort: "",
4319
+ type: "jsonValue",
4320
+ _hash: ""
4321
+ };
4322
+ editRowSortColumnInfos.push(columnInfo);
4323
+ }
4324
+ const editRowSortColSelection = new ColumnSelection(
4325
+ editRowSortColumnInfos
4326
+ );
4327
+ this._join = (await this._db.join(
4328
+ editRowSortColSelection,
4329
+ this._cakeKey,
4330
+ this._cakeRef
4331
+ )).sort(new RowSort(editRowSort));
4332
+ break;
4333
+ case "filter":
4334
+ const editRowFilter = edit.action.data;
4335
+ const editRowFilterColumnInfos = [];
4336
+ for (const colFilter of editRowFilter.columnFilters) {
4337
+ const route = Route.fromFlat(colFilter.column);
4338
+ const tableKey = route.segment().tableKey;
4339
+ const columnInfo = {
4340
+ key: tableKey,
4341
+ route: colFilter.column,
4342
+ alias: tableKey,
4343
+ titleLong: "",
4344
+ titleShort: "",
4345
+ type: "jsonValue",
4346
+ _hash: ""
4347
+ };
4348
+ editRowFilterColumnInfos.push(columnInfo);
4349
+ }
4350
+ const editRowFilterColSelection = new ColumnSelection(
4351
+ editRowFilterColumnInfos
4352
+ );
4353
+ this._join = (await this._db.join(
4354
+ editRowFilterColSelection,
4355
+ this._cakeKey,
4356
+ this._cakeRef
4357
+ )).filter(editRowFilter);
4358
+ break;
4359
+ }
4360
+ } else {
4361
+ switch (action.type) {
4362
+ case "selection":
4363
+ const editColInfos = edit.action.data.columns;
4364
+ const editColSelection = new ColumnSelection(editColInfos);
4365
+ this._join = this._join.select(editColSelection);
4366
+ break;
4367
+ case "setValue":
4368
+ const editSetValue = rmhsh(
4369
+ edit.action.data
4370
+ );
4371
+ this._join = this._join.setValue(editSetValue);
4372
+ break;
4373
+ case "sort":
4374
+ const editRowSort = rmhsh(
4375
+ edit.action.data
4376
+ );
4377
+ this._join = this._join.sort(new RowSort(editRowSort));
4378
+ break;
4379
+ case "filter":
4380
+ const editRowFilter = rmhsh(
4381
+ edit.action.data
4382
+ );
4383
+ this._join = this._join.filter(editRowFilter);
4384
+ break;
4385
+ }
4386
+ }
4387
+ return this._join;
4388
+ }
4389
+ //...........................................................................
4390
+ /**
4391
+ * Get the list of Edits applied in this MultiEditProcessor
4392
+ * @returns Array of Edits
4393
+ */
4394
+ get edits() {
4395
+ return this._edits;
4396
+ }
4397
+ }
4398
+ class MultiEditManager {
4399
+ constructor(_cakeKey, _db) {
4400
+ this._cakeKey = _cakeKey;
4401
+ this._db = _db;
4402
+ }
4403
+ _head = null;
4404
+ _headListener = [];
4405
+ _processors = /* @__PURE__ */ new Map();
4406
+ _isListening = false;
4407
+ init() {
4408
+ const editHistoryKey = `${this._cakeKey}EditHistory`;
4409
+ this._db.registerObserver(
4410
+ Route.fromFlat(editHistoryKey),
4411
+ (ins) => {
4412
+ const editHistoryRef = ins[editHistoryKey + "Ref"];
4413
+ return this.editHistoryRef(editHistoryRef);
4414
+ }
4415
+ );
4416
+ this._isListening = true;
4417
+ }
4418
+ tearDown() {
4419
+ const editHistoryKey = `${this._cakeKey}EditHistory`;
4420
+ this._db.unregisterAllObservers(Route.fromFlat(editHistoryKey));
4421
+ this._isListening = false;
4422
+ }
4423
+ async edit(edit, cakeRef) {
4424
+ if (!this.head && !cakeRef) {
4425
+ throw new Error(
4426
+ "No head MultiEditProcessor available. Provide a cakeRef."
4427
+ );
4428
+ }
4429
+ if (this.head && cakeRef) {
4430
+ throw new Error(
4431
+ "Head MultiEditProcessor already exists. Do not provide a cakeRef."
4432
+ );
4433
+ }
4434
+ await this._persistEdit(edit);
4435
+ let multiEditProc;
4436
+ if (!this.head) {
4437
+ const multiEdit = {
4438
+ _hash: "",
4439
+ edit: hsh(edit)._hash,
4440
+ previous: null
4441
+ };
4442
+ await this._persistMultiEdit(multiEdit);
4443
+ multiEditProc = await MultiEditProcessor.fromMultiEdit(
4444
+ this._db,
4445
+ this._cakeKey,
4446
+ cakeRef,
4447
+ multiEdit
4448
+ );
4449
+ } else {
4450
+ multiEditProc = await this.head.processor.edit(edit);
4451
+ }
4452
+ const multiEditRef = await this._persistMultiEdit(multiEditProc.multiEdit);
4453
+ const editHistoryRef = await this._persistEditHistory({
4454
+ _hash: "",
4455
+ dataRef: multiEditProc.cakeRef,
4456
+ multiEditRef: await multiEditRef,
4457
+ timeId: timeId(),
4458
+ previous: !!this.head && this.head.editHistoryRef ? [this.head.editHistoryRef] : null
4459
+ });
4460
+ this._processors.set(editHistoryRef, multiEditProc);
4461
+ this._head = {
4462
+ editHistoryRef,
4463
+ processor: multiEditProc
4464
+ };
4465
+ await this._notifyHeadListener(editHistoryRef);
4466
+ }
4467
+ async publish() {
4468
+ if (!this.head) {
4469
+ throw new Error("No head MultiEditProcessor available.");
4470
+ }
4471
+ return await this.head.processor.publish();
4472
+ }
4473
+ listenToHeadChanges(callback) {
4474
+ this._headListener.push(callback);
4475
+ }
4476
+ _notifyHeadListener(editHistoryRef) {
4477
+ return Promise.all(
4478
+ this._headListener.map((cb) => cb(editHistoryRef))
4479
+ ).catch((err) => {
4480
+ console.error(
4481
+ `Error notifying head observers for editHistoryRef ${editHistoryRef}:`,
4482
+ err
4483
+ );
4484
+ });
4485
+ }
4486
+ async editHistoryRef(editHistoryRef) {
4487
+ const editHistories = await this._db.getEditHistories(
4488
+ this._cakeKey,
4489
+ editHistoryRef
4490
+ );
4491
+ if (editHistories.length === 0) {
4492
+ throw new Error(`EditHistory with ref ${editHistoryRef} not found.`);
4493
+ }
4494
+ if (editHistories.length > 1) {
4495
+ throw new Error(
4496
+ `Multiple EditHistories with ref ${editHistoryRef} found.`
4497
+ );
4498
+ }
4499
+ const editHistory = editHistories[0];
4500
+ if (this._processors.has(editHistoryRef)) {
4501
+ const processor2 = this._processors.get(editHistoryRef);
4502
+ this._head = {
4503
+ editHistoryRef,
4504
+ processor: processor2
4505
+ };
4506
+ await this._notifyHeadListener(editHistoryRef);
4507
+ return processor2;
4508
+ }
4509
+ if (editHistory.previous && editHistory.previous.length > 0) {
4510
+ if (editHistory.previous.length > 1) {
4511
+ throw new Error(
4512
+ `EditHistory with ref ${editHistoryRef} has multiple previous refs. Not supported.`
4513
+ );
4514
+ }
4515
+ const previousEditHistoryRef = editHistory.previous[0];
4516
+ const previousProcessor = await this.editHistoryRef(
4517
+ previousEditHistoryRef
4518
+ );
4519
+ const previousProcessorCloned = previousProcessor.clone();
4520
+ const processor2 = await previousProcessorCloned.applyEditHistory(
4521
+ editHistory
4522
+ );
4523
+ this._processors.set(editHistoryRef, processor2);
4524
+ this._head = {
4525
+ editHistoryRef,
4526
+ processor: processor2
4527
+ };
4528
+ await this._notifyHeadListener(editHistoryRef);
4529
+ return processor2;
4530
+ }
4531
+ const processor = await MultiEditProcessor.fromEditHistory(
4532
+ this._db,
4533
+ this._cakeKey,
4534
+ editHistory
4535
+ );
4536
+ this._processors.set(editHistoryRef, processor);
4537
+ this._head = {
4538
+ editHistoryRef,
4539
+ processor
4540
+ };
4541
+ await this._notifyHeadListener(editHistoryRef);
4542
+ return processor;
4543
+ }
4544
+ async _persistEdit(edit) {
4545
+ const { [this._cakeKey + "EditsRef"]: editRef } = (await this._db.addEdit(this._cakeKey, edit))[0];
4546
+ if (!editRef) {
4547
+ throw new Error("MultiEditManager: Failed to create EditRef.");
4548
+ }
4549
+ return editRef;
4550
+ }
4551
+ async _persistMultiEdit(multiEdit) {
4552
+ const { [this._cakeKey + "MultiEditsRef"]: multiEditRef } = (await this._db.addMultiEdit(this._cakeKey, multiEdit))[0];
4553
+ if (!multiEditRef) {
4554
+ throw new Error("MultiEditManager: Failed to create MultiEditRef.");
4555
+ }
4556
+ return multiEditRef;
4557
+ }
4558
+ async _persistEditHistory(editHistory) {
4559
+ const { [this._cakeKey + "EditHistoryRef"]: editHistoryRef } = (await this._db.addEditHistory(this._cakeKey, editHistory))[0];
4560
+ if (!editHistoryRef) {
4561
+ throw new Error("MultiEditManager: Failed to create EditHistoryRef.");
4562
+ }
4563
+ return editHistoryRef;
4564
+ }
4565
+ get processors() {
4566
+ return this._processors;
4567
+ }
4568
+ get head() {
4569
+ return this._head;
4570
+ }
4571
+ get join() {
4572
+ if (!this.head) {
4573
+ throw new Error("No head MultiEditProcessor available.");
4574
+ }
4575
+ return this.head.processor.join;
4576
+ }
4577
+ get isListening() {
4578
+ return this._isListening;
4579
+ }
4580
+ }
4581
+ const chainLayers = (layers) => {
4582
+ const chainedLayers = [];
4583
+ for (let i = 0; i < layers.length; i++) {
4584
+ const newLayer = { ...rmhsh(layers[i]) };
4585
+ if (i == 0) {
4586
+ chainedLayers.push(hsh(newLayer));
4587
+ continue;
4588
+ }
4589
+ if (chainedLayers[i - 1]._hash) {
4590
+ newLayer.base = chainedLayers[i - 1]._hash;
4591
+ }
4592
+ chainedLayers.push(hsh(newLayer));
4593
+ }
4594
+ return chainedLayers;
4595
+ };
4596
+ const chainSliceIds = (sliceIds) => {
4597
+ const chainedSliceIds = [];
4598
+ for (let i = 0; i < sliceIds.length; i++) {
4599
+ const newSliceIds = { ...rmhsh(sliceIds[i]) };
4600
+ if (i == 0) {
4601
+ chainedSliceIds.push(hsh(newSliceIds));
4602
+ continue;
4603
+ }
4604
+ if (chainedSliceIds[i - 1]._hash) {
4605
+ newSliceIds.base = chainedSliceIds[i - 1]._hash;
4606
+ }
4607
+ chainedSliceIds.push(hsh(newSliceIds));
4608
+ }
4609
+ return chainedSliceIds;
4610
+ };
4611
+ const staticExample = () => {
4612
+ const carSliceIdTableCfg = hip(
4613
+ createSliceIdsTableCfg("carSliceId")
4614
+ );
4615
+ const carSliceIdData = [
4616
+ {
4617
+ add: ["VIN1", "VIN2", "VIN3", "VIN4", "VIN5", "VIN6", "VIN7", "VIN8"],
4618
+ _hash: ""
4619
+ },
4620
+ {
4621
+ add: ["VIN9", "VIN10"],
4622
+ _hash: ""
4623
+ },
4624
+ {
4625
+ add: ["VIN11", "VIN12"],
4626
+ _hash: ""
4627
+ }
4628
+ ].map((sliceIds) => hsh(sliceIds));
4629
+ const carSliceId = hip({
4630
+ _tableCfg: carSliceIdTableCfg._hash,
4631
+ _type: "sliceIds",
4632
+ _data: chainSliceIds(carSliceIdData),
4633
+ _hash: ""
4634
+ });
4635
+ const carGeneralTableCfg = hip({
4636
+ key: "carGeneral",
4637
+ type: "components",
4638
+ columns: [
4639
+ { key: "_hash", type: "string", titleLong: "Hash", titleShort: "Hash" },
4640
+ { key: "brand", type: "string", titleLong: "Brand", titleShort: "Brand" },
4641
+ { key: "type", type: "string", titleLong: "Type", titleShort: "Type" },
4642
+ { key: "doors", type: "number", titleLong: "Doors", titleShort: "Doors" },
4643
+ {
4644
+ key: "energyConsumption",
4645
+ type: "number",
4646
+ titleLong: "Energy Consumption",
4647
+ titleShort: "Energy"
4648
+ },
4649
+ {
4650
+ key: "units",
4651
+ type: "json",
4652
+ titleLong: "Energy Unit",
4653
+ titleShort: "Unit"
4654
+ },
4655
+ {
4656
+ key: "serviceIntervals",
4657
+ type: "jsonArray",
4658
+ titleLong: "Service Intervals",
4659
+ titleShort: "Intervals"
4660
+ },
4661
+ {
4662
+ key: "isElectric",
4663
+ type: "boolean",
4664
+ titleLong: "Is Electric",
4665
+ titleShort: "Electric"
4666
+ },
4667
+ {
4668
+ key: "meta",
4669
+ type: "jsonValue",
4670
+ titleLong: "Meta Information",
4671
+ titleShort: "Meta"
4672
+ }
4673
+ ],
4674
+ isHead: false,
4675
+ isRoot: false,
4676
+ isShared: true
4677
+ });
4678
+ const carGeneral = hip({
4679
+ _tableCfg: carGeneralTableCfg._hash,
4680
+ _type: "components",
4681
+ _data: [
4682
+ {
4683
+ brand: "Volkswagen",
4684
+ type: "Polo",
4685
+ doors: 5,
4686
+ energyConsumption: 7.4,
4687
+ units: {
4688
+ energy: "l/100km",
4689
+ _hash: ""
4690
+ },
4691
+ serviceIntervals: [15e3, 3e4, 45e3],
4692
+ isElectric: false,
4693
+ meta: {
4694
+ pressText: "A popular compact car.",
4695
+ _hash: ""
4696
+ },
4697
+ _hash: ""
4698
+ },
4699
+ {
4700
+ brand: "Volkswagen",
4701
+ type: "Golf",
4702
+ doors: 3,
4703
+ energyConsumption: 6.2,
4704
+ units: {
4705
+ energy: "l/100km",
4706
+ _hash: ""
4707
+ },
4708
+ serviceIntervals: [15e3, 3e4, 45e3],
4709
+ isElectric: false,
4710
+ meta: {
4711
+ pressText: "A well-known hatchback.",
4712
+ _hash: ""
4713
+ },
4714
+ _hash: ""
4715
+ },
4716
+ {
4717
+ brand: "Audi",
4718
+ type: "Q4 E-tron",
4719
+ doors: 5,
4720
+ energyConsumption: 18,
4721
+ units: {
4722
+ energy: "kWh/100km",
4723
+ _hash: ""
4724
+ },
4725
+ serviceIntervals: [2e4, 4e4, 6e4],
4726
+ isElectric: true,
4727
+ meta: [
4728
+ {
4729
+ pressText: "A stylish electric SUV.",
4730
+ _hash: ""
4731
+ },
4732
+ {
4733
+ pressText: "Combines performance with sustainability.",
4734
+ _hash: ""
4735
+ }
4736
+ ],
4737
+ _hash: ""
4738
+ },
4739
+ {
4740
+ brand: "Audi",
4741
+ type: "Q6 E-tron",
4742
+ doors: 5,
4743
+ energyConsumption: 16,
4744
+ units: {
4745
+ energy: "kWh/100km",
4746
+ _hash: ""
4747
+ },
4748
+ serviceIntervals: [2e4, 4e4, 6e4],
4749
+ isElectric: true,
4750
+ meta: [
4751
+ {
4752
+ pressText: "A premium electric SUV with advanced features.",
4753
+ _hash: ""
4754
+ },
4755
+ {
4756
+ pressText: "Offers a blend of luxury and eco-friendliness.",
4757
+ _hash: ""
4758
+ }
4759
+ ],
4760
+ _hash: ""
4761
+ },
4762
+ {
4763
+ brand: "BMW",
4764
+ type: "i4",
4765
+ doors: 5,
4766
+ energyConsumption: 19.5,
4767
+ units: {
4768
+ energy: "kWh/100km",
4769
+ _hash: ""
4770
+ },
4771
+ serviceIntervals: [2e4, 4e4, 6e4],
4772
+ isElectric: true,
4773
+ meta: [
4774
+ {
4775
+ pressText: "A sporty electric sedan.",
4776
+ _hash: ""
4777
+ },
4778
+ {
4779
+ pressText: "Delivers dynamic performance with zero emissions.",
4780
+ _hash: ""
4781
+ }
4782
+ ],
4783
+ _hash: ""
4784
+ },
4785
+ {
4786
+ brand: "BMW",
4787
+ type: "3 Series",
4788
+ doors: 4,
4789
+ energyConsumption: 5.8,
4790
+ units: {
4791
+ energy: "l/100km",
4792
+ _hash: ""
4793
+ },
4794
+ serviceIntervals: [15e3, 3e4, 45e3],
4795
+ isElectric: false,
4796
+ meta: {
4797
+ pressText: "A classic executive car.",
4798
+ _hash: ""
4799
+ },
4800
+ _hash: ""
4801
+ },
4802
+ {
4803
+ brand: "Tesla",
4804
+ type: "Model 3",
4805
+ doors: 4,
4806
+ energyConsumption: 15,
4807
+ units: {
4808
+ energy: "kWh/100km",
4809
+ _hash: ""
4810
+ },
4811
+ serviceIntervals: [25e3, 5e4, 75e3],
4812
+ isElectric: true,
4813
+ meta: {
4814
+ pressText: "A revolutionary electric sedan.",
4815
+ _hash: ""
4816
+ },
4817
+ _hash: ""
4818
+ },
4819
+ {
4820
+ brand: "Tesla",
4821
+ type: "Model Y",
4822
+ doors: 5,
4823
+ energyConsumption: 16.5,
4824
+ units: {
4825
+ energy: "kWh/100km",
4826
+ _hash: ""
4827
+ },
4828
+ serviceIntervals: [25e3, 5e4, 75e3],
4829
+ isElectric: true,
4830
+ meta: {
4831
+ pressText: "A versatile electric SUV.",
4832
+ _hash: ""
4833
+ },
4834
+ _hash: ""
4835
+ },
4836
+ {
4837
+ brand: "Ford",
4838
+ type: "Mustang Mach-E",
4839
+ doors: 5,
4840
+ energyConsumption: 17,
4841
+ units: {
4842
+ energy: "kWh/100km",
4843
+ _hash: ""
4844
+ },
4845
+ serviceIntervals: [2e4, 4e4, 6e4],
4846
+ isElectric: true,
4847
+ meta: {
4848
+ pressText: "An electric SUV with Mustang heritage.",
4849
+ _hash: ""
4850
+ },
4851
+ _hash: ""
4852
+ },
4853
+ {
4854
+ brand: "Chevrolet",
4855
+ type: "Bolt EV",
4856
+ doors: 5,
4857
+ energyConsumption: 14,
4858
+ units: {
4859
+ energy: "kWh/100km",
4860
+ _hash: ""
4861
+ },
4862
+ serviceIntervals: [2e4, 4e4, 6e4],
4863
+ isElectric: true,
4864
+ meta: {
4865
+ pressText: "An affordable electric hatchback.",
4866
+ _hash: ""
4867
+ },
4868
+ _hash: ""
4869
+ },
4870
+ {
4871
+ brand: "Nissan",
4872
+ type: "Leaf",
4873
+ doors: 5,
4874
+ energyConsumption: 15.5,
4875
+ units: {
4876
+ energy: "kWh/100km",
4877
+ _hash: ""
4878
+ },
4879
+ serviceIntervals: [2e4, 4e4, 6e4],
4880
+ isElectric: true,
4881
+ meta: {
4882
+ pressText: "A pioneering electric vehicle.",
4883
+ _hash: ""
4884
+ },
4885
+ _hash: ""
4886
+ },
4887
+ {
4888
+ brand: "Hyundai",
4889
+ type: "Kona Electric",
4890
+ doors: 5,
4891
+ energyConsumption: 14.5,
4892
+ units: {
4893
+ energy: "kWh/100km",
4894
+ _hash: ""
4895
+ },
4896
+ serviceIntervals: [2e4, 4e4, 6e4],
4897
+ isElectric: true,
4898
+ meta: {
4899
+ pressText: "A compact electric SUV.",
4900
+ _hash: ""
4901
+ },
4902
+ _hash: ""
4903
+ }
4904
+ ],
4905
+ _hash: ""
4906
+ });
4907
+ const carDimensionsTableCfg = hip({
4908
+ key: "carDimensions",
4909
+ type: "components",
4910
+ columns: [
4911
+ { key: "_hash", type: "string" },
4912
+ { key: "height", type: "number" },
4913
+ { key: "width", type: "number" },
4914
+ { key: "length", type: "number" }
4915
+ ],
4916
+ isHead: false,
4917
+ isRoot: false,
4918
+ isShared: true
4919
+ });
4920
+ const carDimensions = hip({
4921
+ _tableCfg: carDimensionsTableCfg._hash,
4922
+ _type: "components",
4923
+ _data: [
4924
+ {
4925
+ height: 1400,
4926
+ width: 1800,
4927
+ length: 4e3,
4928
+ _hash: ""
4929
+ },
4930
+ {
4931
+ height: 1450,
4932
+ width: 1850,
4933
+ length: 4100,
4934
+ _hash: ""
4935
+ },
4936
+ {
4937
+ height: 1600,
4938
+ width: 1900,
4939
+ length: 4500,
4940
+ _hash: ""
4941
+ },
4942
+ {
4943
+ height: 1650,
4944
+ width: 1950,
4945
+ length: 4700,
4946
+ _hash: ""
4947
+ },
4948
+ {
4949
+ height: 1500,
4950
+ width: 1820,
4951
+ length: 4200,
4952
+ _hash: ""
4953
+ },
4954
+ {
4955
+ height: 1550,
4956
+ width: 1880,
4957
+ length: 4300,
4958
+ _hash: ""
4959
+ },
4960
+ {
4961
+ height: 1450,
4962
+ width: 1830,
4963
+ length: 4150,
4964
+ _hash: ""
4965
+ },
4966
+ {
4967
+ height: 1700,
4968
+ width: 2e3,
4969
+ length: 4800,
4970
+ _hash: ""
4971
+ },
4972
+ {
4973
+ height: 1350,
4974
+ width: 1750,
4975
+ length: 3900,
4976
+ _hash: ""
4977
+ },
4978
+ {
4979
+ height: 1750,
4980
+ width: 2050,
4981
+ length: 4900,
4982
+ _hash: ""
4983
+ },
4984
+ {
4985
+ height: 1600,
4986
+ width: 1920,
4987
+ length: 4600,
4988
+ _hash: ""
4989
+ }
4990
+ ],
4991
+ _hash: ""
4992
+ });
4993
+ const carTechnicalTableCfg = hip({
4994
+ key: "carTechnical",
4995
+ type: "components",
4996
+ columns: [
4997
+ { key: "_hash", type: "string" },
4998
+ { key: "engine", type: "string" },
4999
+ { key: "transmission", type: "string" },
5000
+ { key: "gears", type: "number" },
5001
+ {
5002
+ key: "dimensions",
5003
+ type: "jsonValue",
5004
+ ref: {
5005
+ tableKey: "carDimensions",
5006
+ type: "components"
5007
+ }
5008
+ },
5009
+ { key: "repairedByWorkshop", type: "string" }
5010
+ ],
5011
+ isHead: false,
5012
+ isRoot: false,
5013
+ isShared: true
5014
+ });
5015
+ const carTechnical = hip({
5016
+ _tableCfg: carTechnicalTableCfg._hash,
5017
+ _type: "components",
5018
+ _data: [
5019
+ {
5020
+ engine: "Diesel",
5021
+ transmission: "Manual",
5022
+ gears: 6,
5023
+ dimensions: carDimensions._data[0]._hash,
5024
+ _hash: ""
5025
+ },
5026
+ {
5027
+ engine: "Petrol",
5028
+ transmission: "Automatic",
5029
+ gears: 7,
5030
+ dimensions: carDimensions._data[1]._hash,
5031
+ repairedByWorkshop: "Workshop A",
5032
+ _hash: ""
5033
+ },
5034
+ {
5035
+ engine: "Electric",
5036
+ transmission: "Single-Speed",
5037
+ gears: 1,
5038
+ dimensions: [
5039
+ carDimensions._data[1]._hash,
5040
+ carDimensions._data[2]._hash
5041
+ ],
5042
+ _hash: ""
5043
+ },
5044
+ {
5045
+ engine: "Electric",
5046
+ transmission: "Single-Speed",
5047
+ gears: 1,
5048
+ dimensions: carDimensions._data[3]._hash,
5049
+ repairedByWorkshop: "Workshop B",
5050
+ _hash: ""
5051
+ },
5052
+ {
5053
+ engine: "Electric",
5054
+ transmission: "Single-Speed",
5055
+ gears: 1,
5056
+ dimensions: carDimensions._data[4]._hash,
5057
+ _hash: ""
5058
+ },
5059
+ {
5060
+ engine: "Petrol",
5061
+ transmission: "Manual",
5062
+ gears: 6,
5063
+ dimensions: carDimensions._data[5]._hash,
5064
+ repairedByWorkshop: "Workshop A",
5065
+ _hash: ""
5066
+ },
5067
+ {
5068
+ engine: "Electric",
5069
+ transmission: "Single-Speed",
5070
+ gears: 1,
5071
+ dimensions: carDimensions._data[6]._hash,
5072
+ _hash: ""
5073
+ },
5074
+ {
5075
+ engine: "Electric",
5076
+ transmission: "Single-Speed",
5077
+ gears: 1,
5078
+ dimensions: carDimensions._data[7]._hash,
5079
+ repairedByWorkshop: "Workshop C",
5080
+ _hash: ""
5081
+ },
5082
+ {
5083
+ engine: "Electric",
5084
+ transmission: "Single-Speed",
5085
+ gears: 1,
5086
+ dimensions: carDimensions._data[8]._hash,
5087
+ _hash: ""
5088
+ },
5089
+ {
5090
+ engine: "Electric",
5091
+ transmission: "Single-Speed",
5092
+ gears: 1,
5093
+ dimensions: carDimensions._data[9]._hash,
5094
+ repairedByWorkshop: "Workshop B",
5095
+ _hash: ""
5096
+ },
5097
+ {
5098
+ engine: "Electric",
5099
+ transmission: "Single-Speed",
5100
+ gears: 1,
5101
+ dimensions: carDimensions._data[10]._hash,
5102
+ _hash: ""
5103
+ }
5104
+ ],
5105
+ _hash: ""
5106
+ });
5107
+ const carColorTableCfg = hip({
5108
+ key: "carColor",
5109
+ type: "components",
5110
+ columns: [
5111
+ { key: "_hash", type: "string" },
5112
+ { key: "sides", type: "string" },
5113
+ { key: "roof", type: "string" },
5114
+ { key: "highlights", type: "string" }
5115
+ ],
5116
+ isHead: false,
5117
+ isRoot: false,
5118
+ isShared: true
5119
+ });
5120
+ const carColor = hip({
5121
+ _tableCfg: carColorTableCfg._hash,
5122
+ _type: "components",
5123
+ _data: [
5124
+ {
5125
+ sides: "green",
5126
+ roof: "white",
5127
+ highlights: "chrome",
5128
+ _hash: ""
5129
+ },
5130
+ {
5131
+ sides: "blue",
5132
+ roof: "black",
5133
+ highlights: "chrome",
5134
+ _hash: ""
5135
+ },
5136
+ {
5137
+ sides: "red",
5138
+ roof: "red",
5139
+ highlights: "black",
5140
+ _hash: ""
5141
+ },
5142
+ {
5143
+ sides: "silver",
5144
+ roof: "silver",
5145
+ highlights: "chrome",
5146
+ _hash: ""
5147
+ },
5148
+ {
5149
+ sides: "black",
5150
+ roof: "black",
5151
+ highlights: "black",
5152
+ _hash: ""
5153
+ },
5154
+ {
5155
+ sides: "white",
5156
+ roof: "white",
5157
+ highlights: "chrome",
5158
+ _hash: ""
5159
+ },
5160
+ {
5161
+ sides: "grey",
5162
+ roof: "black",
5163
+ highlights: "chrome",
5164
+ _hash: ""
5165
+ },
5166
+ {
5167
+ sides: "red",
5168
+ roof: "white",
5169
+ highlights: "black",
5170
+ _hash: ""
5171
+ }
5172
+ ],
5173
+ _hash: ""
5174
+ });
5175
+ const carGeneralLayerTableCfg = hip(
5176
+ createLayerTableCfg("carGeneralLayer")
5177
+ );
5178
+ const carGeneralLayerData = [
5179
+ {
5180
+ add: {
5181
+ VIN1: carGeneral._data[0]._hash,
5182
+ VIN2: carGeneral._data[1]._hash,
5183
+ VIN3: carGeneral._data[2]._hash,
5184
+ VIN4: carGeneral._data[3]._hash,
5185
+ VIN5: carGeneral._data[4]._hash,
5186
+ VIN6: carGeneral._data[5]._hash,
5187
+ VIN7: carGeneral._data[6]._hash,
5188
+ VIN8: carGeneral._data[7]._hash,
5189
+ _hash: ""
5190
+ },
5191
+ sliceIdsTable: "carSliceId",
5192
+ sliceIdsTableRow: carSliceId._data[0]._hash,
5193
+ componentsTable: "carGeneral",
5194
+ _hash: ""
5195
+ },
5196
+ {
5197
+ add: {
5198
+ VIN9: carGeneral._data[8]._hash,
5199
+ VIN10: carGeneral._data[9]._hash,
5200
+ _hash: ""
5201
+ },
5202
+ sliceIdsTable: "carSliceId",
5203
+ sliceIdsTableRow: carSliceId._data[1]._hash,
5204
+ componentsTable: "carGeneral",
5205
+ _hash: ""
5206
+ },
5207
+ {
5208
+ add: {
5209
+ VIN11: carGeneral._data[10]._hash,
5210
+ VIN12: carGeneral._data[11]._hash,
5211
+ _hash: ""
5212
+ },
5213
+ sliceIdsTable: "carSliceId",
5214
+ sliceIdsTableRow: carSliceId._data[2]._hash,
5215
+ componentsTable: "carGeneral",
5216
+ _hash: ""
5217
+ }
5218
+ ].map((layer) => hsh(layer));
5219
+ const carGeneralLayer = hip({
5220
+ _tableCfg: carGeneralLayerTableCfg._hash,
5221
+ _type: "layers",
5222
+ _data: chainLayers(carGeneralLayerData),
5223
+ _hash: ""
5224
+ });
5225
+ const carTechnicalLayerTableCfg = hip(
5226
+ createLayerTableCfg("carTechnicalLayer")
5227
+ );
5228
+ const carTechnicalLayerData = [
5229
+ {
5230
+ add: {
5231
+ VIN1: carTechnical._data[0]._hash,
5232
+ VIN2: carTechnical._data[1]._hash,
5233
+ VIN3: carTechnical._data[2]._hash,
5234
+ VIN4: carTechnical._data[2]._hash,
5235
+ VIN5: carTechnical._data[4]._hash,
5236
+ VIN6: carTechnical._data[5]._hash,
5237
+ VIN7: carTechnical._data[6]._hash,
5238
+ VIN8: carTechnical._data[2]._hash,
5239
+ _hash: ""
5240
+ },
5241
+ sliceIdsTable: "carSliceId",
5242
+ sliceIdsTableRow: carSliceId._data[0]._hash,
5243
+ componentsTable: "carTechnical",
5244
+ _hash: ""
5245
+ },
5246
+ {
5247
+ add: {
5248
+ VIN9: carTechnical._data[7]._hash,
5249
+ VIN10: carTechnical._data[8]._hash,
5250
+ _hash: ""
5251
+ },
5252
+ sliceIdsTable: "carSliceId",
5253
+ sliceIdsTableRow: carSliceId._data[1]._hash,
5254
+ componentsTable: "carTechnical",
5255
+ _hash: ""
5256
+ },
5257
+ {
5258
+ add: {
5259
+ VIN11: carTechnical._data[9]._hash,
5260
+ VIN12: carTechnical._data[10]._hash,
5261
+ _hash: ""
5262
+ },
5263
+ sliceIdsTable: "carSliceId",
5264
+ sliceIdsTableRow: carSliceId._data[2]._hash,
5265
+ componentsTable: "carTechnical",
5266
+ _hash: ""
5267
+ }
5268
+ ].map((layer) => hsh(layer));
5269
+ const carTechnicalLayer = hip({
5270
+ _tableCfg: carTechnicalLayerTableCfg._hash,
5271
+ _type: "layers",
5272
+ _data: chainLayers(carTechnicalLayerData),
5273
+ _hash: ""
5274
+ });
5275
+ const carColorLayerTableCfg = hip(
5276
+ createLayerTableCfg("carColorLayer")
5277
+ );
5278
+ const carColorLayerData = [
5279
+ {
5280
+ add: {
5281
+ VIN1: carColor._data[0]._hash,
5282
+ VIN2: carColor._data[1]._hash,
5283
+ VIN3: carColor._data[2]._hash,
5284
+ VIN4: carColor._data[3]._hash,
5285
+ VIN5: carColor._data[4]._hash,
5286
+ VIN6: carColor._data[5]._hash,
5287
+ VIN7: carColor._data[6]._hash,
5288
+ VIN8: carColor._data[7]._hash,
5289
+ _hash: ""
5290
+ },
5291
+ sliceIdsTable: "carSliceId",
5292
+ sliceIdsTableRow: carSliceId._data[0]._hash,
5293
+ componentsTable: "carColor",
5294
+ _hash: ""
5295
+ },
5296
+ {
5297
+ add: {
5298
+ VIN9: carColor._data[3]._hash,
5299
+ VIN10: carColor._data[3]._hash,
5300
+ _hash: ""
5301
+ },
5302
+ sliceIdsTable: "carSliceId",
5303
+ sliceIdsTableRow: carSliceId._data[1]._hash,
5304
+ componentsTable: "carColor",
5305
+ _hash: ""
5306
+ },
5307
+ {
5308
+ add: {
5309
+ VIN11: carColor._data[7]._hash,
5310
+ VIN12: carColor._data[4]._hash,
5311
+ _hash: ""
5312
+ },
5313
+ sliceIdsTable: "carSliceId",
5314
+ sliceIdsTableRow: carSliceId._data[2]._hash,
5315
+ componentsTable: "carColor",
5316
+ _hash: ""
5317
+ }
5318
+ ].map((layer) => hsh(layer));
5319
+ const carColorLayer = hip({
5320
+ _tableCfg: carColorLayerTableCfg._hash,
5321
+ _type: "layers",
5322
+ _data: chainLayers(carColorLayerData),
5323
+ _hash: ""
5324
+ });
5325
+ const carCakeTableCfg = hip(
5326
+ createCakeTableCfg("carCake")
5327
+ );
5328
+ const carCake = hip({
5329
+ _tableCfg: carCakeTableCfg._hash,
5330
+ _type: "cakes",
5331
+ _data: [
5332
+ {
5333
+ sliceIdsTable: "carSliceId",
5334
+ sliceIdsRow: carSliceId._data[0]._hash,
5335
+ layers: {
5336
+ carGeneralLayer: carGeneralLayer._data[0]._hash,
5337
+ carTechnicalLayer: carTechnicalLayer._data[0]._hash,
5338
+ carColorLayer: carColorLayer._data[0]._hash
5339
+ }
5340
+ },
5341
+ {
5342
+ sliceIdsTable: "carSliceId",
5343
+ sliceIdsRow: carSliceId._data[1]._hash,
5344
+ layers: {
5345
+ carGeneralLayer: carGeneralLayer._data[1]._hash,
5346
+ carTechnicalLayer: carTechnicalLayer._data[1]._hash,
5347
+ carColorLayer: carColorLayer._data[1]._hash
5348
+ }
5349
+ },
5350
+ {
5351
+ sliceIdsTable: "carSliceId",
5352
+ sliceIdsRow: carSliceId._data[2]._hash,
5353
+ layers: {
5354
+ carGeneralLayer: carGeneralLayer._data[2]._hash,
5355
+ carTechnicalLayer: carTechnicalLayer._data[2]._hash,
5356
+ carColorLayer: carColorLayer._data[2]._hash
5357
+ }
5358
+ }
5359
+ ]
5360
+ });
5361
+ const carCakeHeadTableCfg = hip(
5362
+ createHeadsTableCfg("carCake")
5363
+ );
5364
+ const carCakeHeads = hip({
5365
+ _tableCfg: carCakeHeadTableCfg._hash,
5366
+ _type: "head",
5367
+ _data: [
5368
+ {
5369
+ timeId: "1764756756311:jkCG",
5370
+ cakeRef: carCake._data[0]._hash
5371
+ },
5372
+ {
5373
+ timeId: "1764756756312:1AGV",
5374
+ cakeRef: carCake._data[1]._hash
5375
+ },
5376
+ {
5377
+ timeId: "1764756756312:g8nh",
5378
+ cakeRef: carCake._data[2]._hash
5379
+ }
5380
+ ]
5381
+ });
5382
+ const seriesSliceIdTableCfg = hip(
5383
+ createSliceIdsTableCfg("seriesSliceId")
5384
+ );
5385
+ const seriesSliceIdData = [
5386
+ {
5387
+ add: ["Serie0", "Serie1", "Serie2", "Serie3"],
5388
+ _hash: ""
5389
+ },
5390
+ {
5391
+ add: ["Serie4", "Serie5", "Serie6", "Serie7"],
5392
+ _hash: ""
5393
+ },
5394
+ {
5395
+ add: ["Serie8", "Serie9", "Serie10", "Serie11"],
5396
+ _hash: ""
5397
+ }
5398
+ ].map((sliceIds) => hsh(sliceIds));
5399
+ const seriesSliceId = hip({
5400
+ _tableCfg: seriesSliceIdTableCfg._hash,
5401
+ _type: "sliceIds",
5402
+ _data: chainSliceIds(seriesSliceIdData),
5403
+ _hash: ""
5404
+ });
5405
+ const seriesGeneralTableCfg = hip({
5406
+ key: "seriesGeneral",
5407
+ type: "components",
5408
+ columns: [
5409
+ { key: "_hash", type: "string", titleShort: "Hash", titleLong: "Hash" },
5410
+ { key: "name", type: "string", titleShort: "Name", titleLong: "Name" }
5411
+ ],
5412
+ isHead: false,
5413
+ isRoot: false,
5414
+ isShared: true
5415
+ });
5416
+ const seriesGeneral = hip({
5417
+ _tableCfg: seriesGeneralTableCfg._hash,
5418
+ _type: "components",
5419
+ _data: [
5420
+ {
5421
+ name: "Polo",
5422
+ _hash: ""
5423
+ },
5424
+ {
5425
+ name: "Golf",
5426
+ _hash: ""
5427
+ },
5428
+ {
5429
+ name: "Q4",
5430
+ _hash: ""
5431
+ },
5432
+ {
5433
+ name: "Q6",
5434
+ _hash: ""
5435
+ },
5436
+ {
5437
+ name: "i4",
5438
+ _hash: ""
5439
+ },
5440
+ {
5441
+ name: "3",
5442
+ _hash: ""
5443
+ },
5444
+ {
5445
+ name: "Model 3",
5446
+ _hash: ""
5447
+ },
5448
+ {
5449
+ name: "Model Y",
5450
+ _hash: ""
5451
+ },
5452
+ {
5453
+ name: "Mustang",
5454
+ _hash: ""
5455
+ },
5456
+ {
5457
+ name: "Bolt",
5458
+ _hash: ""
5459
+ },
5460
+ {
5461
+ name: "Leaf",
5462
+ _hash: ""
5463
+ },
5464
+ {
5465
+ name: "Kona",
5466
+ _hash: ""
5467
+ }
5468
+ ],
5469
+ _hash: ""
5470
+ });
5471
+ const seriesCarsTableCfg = hip({
5472
+ key: "seriesCars",
5473
+ type: "components",
5474
+ columns: [
5475
+ { key: "_hash", type: "string", titleShort: "Hash", titleLong: "Hash" },
5476
+ {
5477
+ key: "cars",
5478
+ type: "jsonArray",
5479
+ titleShort: "Cars",
5480
+ titleLong: "Cars References",
5481
+ ref: {
5482
+ tableKey: "carCake",
5483
+ type: "cakes"
5484
+ }
5485
+ }
5486
+ ],
5487
+ isHead: false,
5488
+ isRoot: false,
5489
+ isShared: true
5490
+ });
5491
+ const seriesCars = hip({
5492
+ _tableCfg: seriesCarsTableCfg._hash,
5493
+ _type: "components",
5494
+ _data: [
5495
+ {
5496
+ cars: [
5497
+ {
5498
+ ref: carCake._data[2]._hash,
5499
+ sliceIds: ["VIN1"]
5500
+ }
5501
+ ],
5502
+ _hash: ""
5503
+ },
5504
+ {
5505
+ cars: [
5506
+ {
5507
+ ref: carCake._data[2]._hash,
5508
+ sliceIds: ["VIN2"]
5509
+ }
5510
+ ],
5511
+ _hash: ""
5512
+ },
5513
+ {
5514
+ cars: [
5515
+ {
5516
+ ref: carCake._data[0]._hash,
5517
+ sliceIds: ["VIN3"]
5518
+ }
5519
+ ],
5520
+ _hash: ""
5521
+ },
5522
+ {
5523
+ cars: [
5524
+ {
5525
+ ref: carCake._data[0]._hash,
5526
+ sliceIds: ["VIN4"]
5527
+ }
5528
+ ],
5529
+ _hash: ""
5530
+ },
5531
+ {
5532
+ cars: [
5533
+ {
5534
+ ref: carCake._data[1]._hash,
5535
+ sliceIds: ["VIN5"]
5536
+ }
5537
+ ],
5538
+ _hash: ""
5539
+ },
5540
+ {
5541
+ cars: [
5542
+ {
5543
+ ref: carCake._data[1]._hash,
5544
+ sliceIds: ["VIN6"]
5545
+ }
5546
+ ],
5547
+ _hash: ""
5548
+ },
5549
+ {
5550
+ cars: [
5551
+ {
5552
+ ref: carCake._data[2]._hash,
5553
+ sliceIds: ["VIN7"]
5554
+ }
5555
+ ],
5556
+ _hash: ""
5557
+ },
5558
+ {
5559
+ cars: [
5560
+ {
5561
+ ref: carCake._data[2]._hash,
5562
+ sliceIds: ["VIN8"]
5563
+ }
5564
+ ],
5565
+ _hash: ""
5566
+ },
5567
+ {
5568
+ cars: [
5569
+ {
5570
+ ref: carCake._data[2]._hash,
5571
+ sliceIds: ["VIN9"]
5572
+ }
5573
+ ],
5574
+ _hash: ""
5575
+ },
5576
+ {
5577
+ cars: [
5578
+ {
5579
+ ref: carCake._data[2]._hash,
5580
+ sliceIds: ["VIN10"]
5581
+ }
5582
+ ],
5583
+ _hash: ""
5584
+ },
5585
+ {
5586
+ cars: [
5587
+ {
5588
+ ref: carCake._data[2]._hash,
5589
+ sliceIds: ["VIN11"]
5590
+ }
5591
+ ],
5592
+ _hash: ""
5593
+ },
5594
+ {
5595
+ cars: [
5596
+ {
5597
+ ref: carCake._data[2]._hash,
5598
+ sliceIds: ["VIN12"]
5599
+ }
5600
+ ],
5601
+ _hash: ""
5602
+ }
5603
+ ],
5604
+ _hash: ""
5605
+ });
5606
+ const seriesGeneralLayerTableCfg = hip(
5607
+ createLayerTableCfg("seriesGeneralLayer")
5608
+ );
5609
+ const seriesGeneralLayerData = [
5610
+ {
5611
+ add: {
5612
+ Serie0: seriesGeneral._data[0]._hash,
5613
+ Serie1: seriesGeneral._data[1]._hash,
5614
+ Serie2: seriesGeneral._data[2]._hash,
5615
+ Serie3: seriesGeneral._data[3]._hash,
5616
+ _hash: ""
5617
+ },
5618
+ sliceIdsTable: "seriesSliceId",
5619
+ sliceIdsTableRow: seriesSliceId._data[0]._hash,
5620
+ componentsTable: "seriesGeneral",
5621
+ _hash: ""
5622
+ },
5623
+ {
5624
+ add: {
5625
+ Serie4: seriesGeneral._data[4]._hash,
5626
+ Serie5: seriesGeneral._data[5]._hash,
5627
+ Serie6: seriesGeneral._data[6]._hash,
5628
+ Serie7: seriesGeneral._data[7]._hash,
5629
+ _hash: ""
5630
+ },
5631
+ sliceIdsTable: "seriesSliceId",
5632
+ sliceIdsTableRow: seriesSliceId._data[1]._hash,
5633
+ componentsTable: "seriesGeneral",
5634
+ _hash: ""
5635
+ },
5636
+ {
5637
+ add: {
5638
+ Serie8: seriesGeneral._data[8]._hash,
5639
+ Serie9: seriesGeneral._data[9]._hash,
5640
+ Serie10: seriesGeneral._data[10]._hash,
5641
+ Serie11: seriesGeneral._data[11]._hash,
5642
+ _hash: ""
5643
+ },
5644
+ sliceIdsTable: "seriesSliceId",
5645
+ sliceIdsTableRow: seriesSliceId._data[2]._hash,
5646
+ componentsTable: "seriesGeneral",
5647
+ _hash: ""
5648
+ }
5649
+ ].map((layer) => hsh(layer));
5650
+ const seriesGeneralLayer = hip({
5651
+ _tableCfg: seriesGeneralLayerTableCfg._hash,
5652
+ _type: "layers",
5653
+ _data: chainLayers(seriesGeneralLayerData),
5654
+ _hash: ""
5655
+ });
5656
+ const seriesCarsLayerTableCfg = hip(
5657
+ createLayerTableCfg("seriesCarsLayer")
5658
+ );
5659
+ const seriesCarsLayerData = [
5660
+ {
5661
+ add: {
5662
+ Serie0: seriesCars._data[0]._hash,
5663
+ Serie1: seriesCars._data[1]._hash,
5664
+ Serie2: seriesCars._data[2]._hash,
5665
+ Serie3: seriesCars._data[3]._hash,
5666
+ _hash: ""
5667
+ },
5668
+ sliceIdsTable: "seriesSliceId",
5669
+ sliceIdsTableRow: seriesSliceId._data[0]._hash,
5670
+ componentsTable: "seriesCars",
5671
+ _hash: ""
5672
+ },
5673
+ {
5674
+ add: {
5675
+ Serie4: seriesCars._data[4]._hash,
5676
+ Serie5: seriesCars._data[5]._hash,
5677
+ Serie6: seriesCars._data[6]._hash,
5678
+ Serie7: seriesCars._data[7]._hash,
5679
+ _hash: ""
5680
+ },
5681
+ sliceIdsTable: "seriesSliceId",
5682
+ sliceIdsTableRow: seriesSliceId._data[1]._hash,
5683
+ componentsTable: "seriesCars",
5684
+ _hash: ""
5685
+ },
5686
+ {
5687
+ add: {
5688
+ Serie8: seriesCars._data[8]._hash,
5689
+ Serie9: seriesCars._data[9]._hash,
5690
+ Serie10: seriesCars._data[10]._hash,
5691
+ Serie11: seriesCars._data[11]._hash,
5692
+ _hash: ""
5693
+ },
5694
+ sliceIdsTable: "seriesSliceId",
5695
+ sliceIdsTableRow: seriesSliceId._data[2]._hash,
5696
+ componentsTable: "seriesCars",
5697
+ _hash: ""
5698
+ }
5699
+ ].map((layer) => hsh(layer));
5700
+ const seriesCarsLayer = hip({
5701
+ _tableCfg: seriesCarsLayerTableCfg._hash,
5702
+ _type: "layers",
5703
+ _data: chainLayers(seriesCarsLayerData)
5704
+ });
5705
+ const seriesCakeTableCfg = hip(
5706
+ createCakeTableCfg("seriesCake")
5707
+ );
5708
+ const seriesCake = hip({
5709
+ _tableCfg: seriesCakeTableCfg._hash,
5710
+ _type: "cakes",
5711
+ _data: [
5712
+ {
5713
+ sliceIdsTable: "seriesSliceId",
5714
+ sliceIdsRow: seriesSliceId._data[0]._hash,
5715
+ layers: {
5716
+ seriesGeneralLayer: seriesGeneralLayer._data[0]._hash,
5717
+ seriesCarsLayer: seriesCarsLayer._data[0]._hash
5718
+ }
5719
+ },
5720
+ {
5721
+ sliceIdsTable: "seriesSliceId",
5722
+ sliceIdsRow: seriesSliceId._data[1]._hash,
5723
+ layers: {
5724
+ seriesGeneralLayer: seriesGeneralLayer._data[1]._hash,
5725
+ seriesCarsLayer: seriesCarsLayer._data[1]._hash
5726
+ }
5727
+ },
5728
+ {
5729
+ sliceIdsTable: "seriesSliceId",
5730
+ sliceIdsRow: seriesSliceId._data[2]._hash,
5731
+ layers: {
5732
+ seriesGeneralLayer: seriesGeneralLayer._data[2]._hash,
5733
+ seriesCarsLayer: seriesCarsLayer._data[2]._hash
5734
+ }
5735
+ }
5736
+ ]
5737
+ });
5738
+ const seriesCakeHeadTableCfg = hip(
5739
+ createHeadsTableCfg("seriesCake")
5740
+ );
5741
+ const seriesCakeHeads = hip({
5742
+ _tableCfg: seriesCakeHeadTableCfg._hash,
5743
+ _type: "head",
5744
+ _data: [
5745
+ {
5746
+ timeId: "1764756756315:L14y",
5747
+ cakeRef: seriesCake._data[0]._hash
5748
+ },
5749
+ {
5750
+ timeId: "1764756756315:xCXT",
5751
+ cakeRef: seriesCake._data[1]._hash
5752
+ },
5753
+ {
5754
+ timeId: "1764756756315:fZwA",
5755
+ cakeRef: seriesCake._data[2]._hash
5756
+ }
5757
+ ]
5758
+ });
5759
+ const catalogSliceIdTableCfg = hip(
5760
+ createSliceIdsTableCfg("catalogSliceId")
5761
+ );
5762
+ const catalogSliceIdData = [
5763
+ {
5764
+ add: ["Catalog0", "Catalog1"],
5765
+ _hash: ""
5766
+ }
5767
+ ].map((sliceIds) => hsh(sliceIds));
5768
+ const catalogSliceId = hip({
5769
+ _tableCfg: catalogSliceIdTableCfg._hash,
5770
+ _type: "sliceIds",
5771
+ _data: chainSliceIds(catalogSliceIdData),
5772
+ _hash: ""
5773
+ });
5774
+ const catalogSeriesTableCfg = hip({
5775
+ key: "catalogSeries",
5776
+ type: "components",
5777
+ columns: [
5778
+ { key: "_hash", type: "string", titleShort: "Hash", titleLong: "Hash" },
5779
+ {
5780
+ key: "series",
5781
+ type: "jsonArray",
5782
+ titleShort: "Series",
5783
+ titleLong: "Series References",
5784
+ ref: {
5785
+ tableKey: "seriesCake",
5786
+ type: "cakes"
5787
+ }
5788
+ }
5789
+ ],
5790
+ isHead: false,
5791
+ isRoot: false,
5792
+ isShared: true
5793
+ });
5794
+ const catalogSeries = hip({
5795
+ _tableCfg: catalogSeriesTableCfg._hash,
5796
+ _type: "components",
5797
+ _data: [
5798
+ {
5799
+ series: [
5800
+ {
5801
+ ref: seriesCake._data[0]._hash,
5802
+ sliceIds: ["Serie0", "Serie1", "Serie2", "Serie3"]
5803
+ },
5804
+ {
5805
+ ref: seriesCake._data[1]._hash,
5806
+ sliceIds: ["Serie4", "Serie5", "Serie6", "Serie7"]
5807
+ }
5808
+ ],
5809
+ _hash: ""
5810
+ },
5811
+ {
5812
+ series: [
5813
+ {
5814
+ ref: seriesCake._data[2]._hash
5815
+ }
5816
+ ],
5817
+ _hash: ""
5818
+ }
5819
+ ],
5820
+ _hash: ""
5821
+ });
5822
+ const catalogSeriesLayerTableCfg = hip(
5823
+ createLayerTableCfg("catalogSeriesLayer")
5824
+ );
5825
+ const catalogSeriesLayerData = [
5826
+ {
5827
+ add: {
5828
+ Catalog0: catalogSeries._data[0]._hash,
5829
+ Catalog1: catalogSeries._data[1]._hash,
5830
+ _hash: ""
5831
+ },
5832
+ sliceIdsTable: "catalogSliceId",
5833
+ sliceIdsTableRow: catalogSliceId._data[0]._hash,
5834
+ componentsTable: "catalogSeries",
5835
+ _hash: ""
5836
+ }
5837
+ ].map((layer) => hsh(layer));
5838
+ const catalogSeriesLayer = hip({
5839
+ _tableCfg: catalogSeriesLayerTableCfg._hash,
5840
+ _type: "layers",
5841
+ _data: chainLayers(catalogSeriesLayerData),
5842
+ _hash: ""
5843
+ });
5844
+ const catalogCakeTableCfg = hip(
5845
+ createCakeTableCfg("catalogCake")
5846
+ );
5847
+ const catalogCake = hip({
5848
+ _tableCfg: catalogCakeTableCfg._hash,
5849
+ _type: "cakes",
5850
+ _data: [
5851
+ {
5852
+ sliceIdsTable: "catalogSliceId",
5853
+ sliceIdsRow: catalogSliceId._data[0]._hash,
5854
+ layers: {
5855
+ catalogSeriesLayer: catalogSeriesLayer._data[0]._hash
5856
+ }
5857
+ }
5858
+ ]
5859
+ });
5860
+ const catalogCakeHeadTableCfg = hip(
5861
+ createHeadsTableCfg("catalogCake")
5862
+ );
5863
+ const catalogCakeHeads = hip({
5864
+ _tableCfg: catalogCakeHeadTableCfg._hash,
5865
+ _type: "head",
5866
+ _data: [
5867
+ {
5868
+ timeId: "1764756756317:5UTy",
5869
+ cakeRef: catalogCake._data[0]._hash
5870
+ }
5871
+ ]
5872
+ });
5873
+ const tableCfgs = {
5874
+ _data: [
5875
+ carSliceIdTableCfg,
5876
+ carGeneralTableCfg,
5877
+ carDimensionsTableCfg,
5878
+ carTechnicalTableCfg,
5879
+ carColorTableCfg,
5880
+ carGeneralLayerTableCfg,
5881
+ carTechnicalLayerTableCfg,
5882
+ carColorLayerTableCfg,
5883
+ carCakeTableCfg,
5884
+ carCakeHeadTableCfg,
5885
+ seriesSliceIdTableCfg,
5886
+ seriesGeneralTableCfg,
5887
+ seriesCarsTableCfg,
5888
+ seriesGeneralLayerTableCfg,
5889
+ seriesCarsLayerTableCfg,
5890
+ seriesCakeTableCfg,
5891
+ seriesCakeHeadTableCfg,
5892
+ catalogSliceIdTableCfg,
5893
+ catalogSeriesTableCfg,
5894
+ catalogSeriesLayerTableCfg,
5895
+ catalogCakeTableCfg,
5896
+ catalogCakeHeadTableCfg
5897
+ ]
5898
+ };
5899
+ const staticExample2 = {
5900
+ carSliceId,
5901
+ carGeneral,
5902
+ carDimensions,
5903
+ carTechnical,
5904
+ carColor,
5905
+ carGeneralLayer,
5906
+ carTechnicalLayer,
5907
+ carColorLayer,
5908
+ carCake,
5909
+ carCakeHeads,
5910
+ seriesSliceId,
5911
+ seriesGeneral,
5912
+ seriesCars,
5913
+ seriesGeneralLayer,
5914
+ seriesCarsLayer,
5915
+ seriesCake,
5916
+ seriesCakeHeads,
5917
+ catalogSliceId,
5918
+ catalogSeries,
5919
+ catalogSeriesLayer,
5920
+ catalogCake,
5921
+ catalogCakeHeads,
5922
+ tableCfgs
5923
+ };
5924
+ return staticExample2;
5925
+ };
3712
5926
  export {
3713
- Db as RljsonDb
5927
+ Connector,
5928
+ Db,
5929
+ Join,
5930
+ MultiEditManager,
5931
+ exampleEditActionColumnSelection,
5932
+ exampleEditActionColumnSelectionOnlySomeColumns,
5933
+ exampleEditActionRowFilter,
5934
+ exampleEditActionRowSort,
5935
+ exampleEditActionSetValue,
5936
+ exampleEditSetValueReferenced,
5937
+ staticExample
3714
5938
  };
5939
+ //# sourceMappingURL=db.js.map