@rljson/db 0.0.10 → 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.
package/dist/db.js CHANGED
@@ -184,7 +184,6 @@ class CakeController extends BaseController {
184
184
  this._refs = _refs;
185
185
  this._contentType = "cakes";
186
186
  }
187
- _table = null;
188
187
  _baseLayers = {};
189
188
  async init() {
190
189
  if (this._tableKey.endsWith("Cake") === false) {
@@ -192,9 +191,8 @@ class CakeController extends BaseController {
192
191
  `Table ${this._tableKey} is not supported by CakeController.`
193
192
  );
194
193
  }
195
- const rljson = await this._core.dumpTable(this._tableKey);
196
- this._table = rljson[this._tableKey];
197
- if (this._table._type !== "cakes") {
194
+ const contentType = await this._core.contentType(this._tableKey);
195
+ if (contentType !== "cakes") {
198
196
  throw new Error(`Table ${this._tableKey} is not of type cakes.`);
199
197
  }
200
198
  this._tableCfg = await this._core.tableCfg(this._tableKey);
@@ -207,19 +205,10 @@ class CakeController extends BaseController {
207
205
  }
208
206
  const baseCake = baseCakes[0];
209
207
  this._baseLayers = rmhsh(baseCake.layers);
210
- } else {
211
- const cake = this._table._data[0];
212
- if (!!cake) {
213
- this._refs = {
214
- sliceIdsTable: cake.sliceIdsTable,
215
- sliceIdsRow: cake.sliceIdsRow
216
- };
217
- this._baseLayers = rmhsh(cake.layers);
218
- }
219
208
  }
220
209
  }
221
210
  async getChildRefs(where, filter) {
222
- if (!this._table) {
211
+ if (!this._tableCfg) {
223
212
  throw new Error(`Controller not initialized.`);
224
213
  }
225
214
  const childRefs = [];
@@ -310,9 +299,8 @@ class ComponentController extends BaseController {
310
299
  if (!!this._refs && !this._refs.base) {
311
300
  throw new Error(`Refs are not required on ComponentController.`);
312
301
  }
313
- const rljson = await this._core.dumpTable(this._tableKey);
314
- const table = rljson[this._tableKey];
315
- if (this._allowedContentTypes.indexOf(table._type) === -1) {
302
+ const contentType = await this._core.contentType(this._tableKey);
303
+ if (this._allowedContentTypes.indexOf(contentType) === -1) {
316
304
  throw new Error(`Table ${this._tableKey} is not of type components.`);
317
305
  }
318
306
  this._tableCfg = await this._core.tableCfg(this._tableKey);
@@ -653,9 +641,8 @@ class SliceIdController extends BaseController {
653
641
  `Table ${this._tableKey} is not supported by SliceIdController.`
654
642
  );
655
643
  }
656
- const rljson = await this._core.dumpTable(this._tableKey);
657
- const table = rljson[this._tableKey];
658
- if (table._type !== "sliceIds") {
644
+ const contentType = await this._core.contentType(this._tableKey);
645
+ if (contentType !== "sliceIds") {
659
646
  throw new Error(`Table ${this._tableKey} is not of type sliceIds.`);
660
647
  }
661
648
  this._tableCfg = await this._core.tableCfg(this._tableKey);
@@ -666,13 +653,6 @@ class SliceIdController extends BaseController {
666
653
  if (SliceIds2.length === 0) {
667
654
  throw new Error(`Base sliceId ${this._refs.base} does not exist.`);
668
655
  }
669
- } else {
670
- const sliceId = table._data[0];
671
- if (!!sliceId) {
672
- this._refs = {
673
- base: sliceId.base
674
- };
675
- }
676
656
  }
677
657
  }
678
658
  async insert(command, value, origin, refs) {
@@ -771,9 +751,8 @@ class LayerController extends BaseController {
771
751
  `Table ${this._tableKey} is not supported by LayerController.`
772
752
  );
773
753
  }
774
- const rljson = await this._core.dumpTable(this._tableKey);
775
- const table = rljson[this._tableKey];
776
- if (table._type !== "layers") {
754
+ const contentType = await this._core.contentType(this._tableKey);
755
+ if (contentType !== "layers") {
777
756
  throw new Error(`Table ${this._tableKey} is not of type layers.`);
778
757
  }
779
758
  this._tableCfg = await this._core.tableCfg(this._tableKey);
@@ -792,15 +771,6 @@ class LayerController extends BaseController {
792
771
  componentsTable: baseLayer.componentsTable
793
772
  };
794
773
  }
795
- } else {
796
- const layer = table._data[0];
797
- if (!!layer) {
798
- this._refs = {
799
- sliceIdsTable: layer.sliceIdsTable,
800
- sliceIdsTableRow: layer.sliceIdsTableRow,
801
- componentsTable: layer.componentsTable
802
- };
803
- }
804
774
  }
805
775
  }
806
776
  async insert(command, value, origin, refs) {
@@ -1071,17 +1041,8 @@ class Core {
1071
1041
  }
1072
1042
  // ...........................................................................
1073
1043
  async tableCfg(table) {
1074
- const { [table]: dump } = await this._io.dumpTable({ table });
1075
- const tableCfgRef = dump._tableCfg;
1076
1044
  const tableCfgs = await this._io.rawTableCfgs();
1077
- let tableCfg;
1078
- if (!tableCfgRef) {
1079
- tableCfg = tableCfgs.find((tc) => tc.key === table);
1080
- } else {
1081
- tableCfg = tableCfgs.find(
1082
- (tc) => tc.key === table && tc._hash === tableCfgRef
1083
- );
1084
- }
1045
+ const tableCfg = tableCfgs.find((tc) => tc.key === table);
1085
1046
  return tableCfg;
1086
1047
  }
1087
1048
  // ...........................................................................
@@ -2731,7 +2692,7 @@ class Db {
2731
2692
  * @returns An array of Rljson objects matching the route and filter
2732
2693
  * @throws {Error} If the route is not valid or if any controller cannot be created
2733
2694
  */
2734
- async get(route, where, filter, sliceIds) {
2695
+ async get(route, where, filter, sliceIds, options) {
2735
2696
  if (!route.isValid) throw new Error(`Route ${route.flat} is not valid.`);
2736
2697
  const isolatedRoute = await this.isolatePropertyKeyFromRoute(route);
2737
2698
  const controllers = await this.indexedControllers(isolatedRoute);
@@ -2740,7 +2701,9 @@ class Db {
2740
2701
  where,
2741
2702
  controllers,
2742
2703
  filter,
2743
- sliceIds
2704
+ sliceIds,
2705
+ void 0,
2706
+ options
2744
2707
  );
2745
2708
  const dataWithControllers = {
2746
2709
  ...data,
@@ -2758,20 +2721,30 @@ class Db {
2758
2721
  * @param controllers - The controllers to use for fetching data
2759
2722
  * @param filter - Optional filter to apply to the data at the current route segment
2760
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
2761
2726
  * @returns - An Rljson object matching the route and filters
2762
2727
  */
2763
- async _get(route, where, controllers, filter, sliceIds, routeAccumulator) {
2764
- const params = {
2765
- route: route.flat,
2766
- where,
2767
- filter,
2768
- sliceIds,
2769
- routeAccumulator: routeAccumulator ? routeAccumulator.flat : ""
2770
- };
2771
- const cacheHash = hsh(rmhsh(params))._hash;
2772
- const isCached = this._cache.has(cacheHash);
2773
- if (isCached) {
2774
- 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
+ }
2775
2748
  }
2776
2749
  const nodeTableKey = route.top.tableKey;
2777
2750
  const nodeRoute = route;
@@ -2791,10 +2764,57 @@ class Db {
2791
2764
  [nodeTableKey]: { _data: nodeRows, _type: nodeType, _hash: nodeHash }
2792
2765
  } = await nodeController.get(nodeWhere);
2793
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
+ }
2794
2816
  const nodeRowsFiltered = [];
2795
2817
  for (const nodeRow of nodeRows) {
2796
- const filterActive = filter && filter.length > 0;
2797
- const sliceIdActive = nodeSliceIds && nodeSliceIds.length > 0;
2798
2818
  if (!filterActive && !sliceIdActive) {
2799
2819
  nodeRowsFiltered.push(nodeRow);
2800
2820
  continue;
@@ -2802,12 +2822,10 @@ class Db {
2802
2822
  let filterResult = false;
2803
2823
  const filterProperties = [];
2804
2824
  if (filterActive) {
2805
- for (const f of filter) {
2806
- if (f.tableKey !== nodeTableKey) continue;
2807
- if (nodeRow._hash === f.ref) {
2808
- filterProperties.push(f);
2809
- filterResult = true;
2810
- }
2825
+ const rowFilters = filterMap.get(nodeRow._hash);
2826
+ if (rowFilters) {
2827
+ filterProperties.push(...rowFilters);
2828
+ filterResult = true;
2811
2829
  }
2812
2830
  } else {
2813
2831
  filterResult = true;
@@ -2817,36 +2835,36 @@ class Db {
2817
2835
  switch (nodeType) {
2818
2836
  case "cakes":
2819
2837
  const cake = nodeRow;
2820
- const cakeSliceIds = await this._resolveSliceIds(
2821
- cake.sliceIdsTable,
2822
- cake.sliceIdsRow
2823
- );
2824
- const cakeMatchesSliceIds = nodeSliceIds.filter(
2825
- (sId) => cakeSliceIds.includes(sId)
2826
- );
2827
- 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
+ }
2828
2846
  break;
2829
2847
  case "layers":
2830
2848
  const layer = nodeRow;
2831
- const layerSliceIds = await this._resolveSliceIds(
2832
- layer.sliceIdsTable,
2833
- layer.sliceIdsTableRow
2834
- );
2835
- const layerMatchesSliceIds = nodeSliceIds.filter(
2836
- (sId) => layerSliceIds.includes(sId)
2837
- );
2838
- 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
+ }
2839
2857
  break;
2840
2858
  case "components":
2841
2859
  if (filterProperties.length > 0) {
2842
- const componentSliceIds = filterProperties.flatMap(
2843
- (f) => f.sliceIds
2844
- );
2845
- const componentMatchesSliceIds = nodeSliceIds.filter(
2846
- (sId) => componentSliceIds.includes(sId)
2860
+ const componentSliceIdSet = new Set(
2861
+ filterProperties.flatMap((f) => f.sliceIds)
2847
2862
  );
2848
- if (componentMatchesSliceIds.length > 0) {
2849
- sliceIdResult = true;
2863
+ for (const sId of nodeSliceIdSet) {
2864
+ if (componentSliceIdSet.has(sId)) {
2865
+ sliceIdResult = true;
2866
+ break;
2867
+ }
2850
2868
  }
2851
2869
  }
2852
2870
  break;
@@ -2867,47 +2885,49 @@ class Db {
2867
2885
  _hash: nodeHash
2868
2886
  }
2869
2887
  };
2870
- const nodeValue = node[nodeTableKey]._data.filter(
2871
- (v) => v !== void 0 && v !== null
2872
- );
2873
2888
  if (route.isRoot) {
2889
+ const baseRouteStr = (routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "");
2874
2890
  if (route.hasPropertyKey) {
2875
- const isolatedNode = this.isolatePropertyFromComponents(
2876
- node,
2877
- 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
+ })
2878
2903
  );
2879
2904
  const result3 = {
2880
2905
  rljson: isolatedNode,
2881
- tree: { [nodeTableKey]: node[nodeTableKey] },
2882
- cell: nodeValue.map(
2883
- (v, idx) => ({
2884
- value: v[route.propertyKey] ?? null,
2885
- row: v,
2886
- route: Route.fromFlat(
2887
- (routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "") + `/${route.propertyKey}`
2888
- ).toRouteWithProperty(),
2889
- path: [[nodeTableKey, "_data", idx, route.propertyKey]]
2890
- })
2891
- )
2906
+ tree: tree3,
2907
+ cell: cell3
2892
2908
  };
2893
2909
  this._cache.set(cacheHash, result3);
2894
2910
  return result3;
2895
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
+ );
2896
2923
  const result2 = {
2897
- rljson: node,
2898
- tree: { [nodeTableKey]: node[nodeTableKey] },
2899
- cell: nodeValue.map(
2900
- (v, idx) => ({
2901
- value: v[route.propertyKey] ?? null,
2902
- row: v,
2903
- route: Route.fromFlat(
2904
- (routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "")
2905
- ),
2906
- path: [[nodeTableKey, "_data", idx]]
2907
- })
2908
- )
2924
+ rljson: rljson2,
2925
+ tree: tree2,
2926
+ cell: cell2
2909
2927
  };
2910
- this._cache.set(cacheHash, result2);
2928
+ if (cacheable) {
2929
+ this._cache.set(cacheHash, result2);
2930
+ }
2911
2931
  return result2;
2912
2932
  }
2913
2933
  const childrenRoute = route.deeper();
@@ -2916,12 +2936,20 @@ class Db {
2916
2936
  const childrenThroughProperty = childrenWhere?._through;
2917
2937
  const nodeChildrenArray = [];
2918
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);
2919
2949
  for (let i = 0; i < nodeRowsFiltered.length; i++) {
2920
2950
  const nodeRow = nodeRowsFiltered[i];
2921
- const nodeRowObj = { ...{}, ...nodeRow };
2922
- const childrenRefs = await nodeController.getChildRefs(
2923
- nodeRow._hash
2924
- );
2951
+ const nodeRowHash = nodeRow._hash;
2952
+ const childrenRefs = allChildRefs[i];
2925
2953
  const childrenRefTypes = /* @__PURE__ */ new Map();
2926
2954
  const childrenRefSliceIds = /* @__PURE__ */ new Set();
2927
2955
  for (const cr of childrenRefs) {
@@ -2942,13 +2970,19 @@ class Db {
2942
2970
  }
2943
2971
  }
2944
2972
  }
2945
- if (childrenRefTypes.size > 1) {
2973
+ const childrenRefTypesSet = /* @__PURE__ */ new Set([
2974
+ ...childrenRefTypes.values()
2975
+ ]);
2976
+ if (childrenRefTypesSet.size > 1) {
2946
2977
  throw new Error(
2947
- `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(", ")}.`
2948
2981
  );
2949
2982
  }
2950
- const cakeIsReferenced = childrenRefTypes.size === 1 && [...childrenRefTypes.values()][0] === "cakes";
2951
- 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";
2952
2986
  const childrenSliceIds = cakeIsReferenced ? [...childrenRefSliceIds] : componentIsReferenced ? void 0 : nodeSliceIds;
2953
2987
  const {
2954
2988
  rljson: rowChildrenRljson,
@@ -2962,29 +2996,43 @@ class Db {
2962
2996
  childrenSliceIds,
2963
2997
  Route.fromFlat(
2964
2998
  (routeAccumulator ? routeAccumulator.flat : nodeTableKey) + (nodeHash ? `@${nodeHash}` : "") + "/" + childrenTableKey
2965
- )
2999
+ ),
3000
+ opts
2966
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 };
2967
3014
  if (cakeIsReferenced) {
2968
3015
  const refKey = [...childrenRefTypes.keys()][0];
2969
3016
  nodeRowObj[refKey] = rowChildrenTree;
2970
3017
  }
2971
- if (rowChildrenRljson[childrenTableKey]._data.length === 0) continue;
2972
- nodeChildrenArray.push(rowChildrenRljson);
2973
3018
  if (childrenThroughProperty) {
2974
- 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
+ );
2975
3024
  for (const nr of nodeRowsFiltered) {
2976
- {
2977
- const throughHashesInRowCouldBeArray = nr[childrenThroughProperty];
2978
- const throughHashesInRow = Array.isArray(
2979
- throughHashesInRowCouldBeArray
2980
- ) ? throughHashesInRowCouldBeArray : [throughHashesInRowCouldBeArray];
2981
- for (const th of throughHashesInRow) {
2982
- if (resolvedChildrenHashes.includes(th)) {
2983
- nodeRowObj[childrenThroughProperty] = {
2984
- ...rowChildrenTree[childrenTableKey],
2985
- ...{ _tableKey: childrenTableKey }
2986
- };
2987
- }
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;
2988
3036
  }
2989
3037
  }
2990
3038
  }
@@ -2993,8 +3041,14 @@ class Db {
2993
3041
  const childrenRefsOfRow = childrenRefs.filter(
2994
3042
  (cr) => cr.tableKey == childrenTableKey
2995
3043
  );
3044
+ const resolvedChildrenHashSet = new Set(
3045
+ resolvedChildren.map((ch) => ch._hash)
3046
+ );
2996
3047
  const matchingChildrenRefs = childrenRefsOfRow.filter(
2997
- (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])
2998
3052
  );
2999
3053
  if (nodeType === "layers") {
3000
3054
  const compChildrenTrees = rowChildrenTree[childrenTableKey]._data;
@@ -3006,9 +3060,8 @@ class Db {
3006
3060
  };
3007
3061
  });
3008
3062
  const layerTreesAndPaths = components.map(({ tree: comp, path }) => {
3009
- const sliceIds2 = matchingChildrenRefs.find(
3010
- (cr) => cr.ref === comp._hash
3011
- )?.sliceIds;
3063
+ const matchedRef = matchingRefsMap.get(comp._hash);
3064
+ const sliceIds2 = matchedRef?.sliceIds;
3012
3065
  if (!sliceIds2 || sliceIds2.length === 0) {
3013
3066
  throw new Error(
3014
3067
  `Db._get: No sliceIds found for component ${comp._hash} of layer ${nodeRow._hash}.`
@@ -3020,99 +3073,90 @@ class Db {
3020
3073
  );
3021
3074
  }
3022
3075
  const sliceId = sliceIds2[0];
3023
- const pathsForSliceId = [
3024
- ...path.map((p) => p[0]).map((p) => {
3025
- const newPath = [...p];
3026
- newPath[2] = 0;
3027
- return ["add", sliceId, ...newPath];
3028
- })
3029
- ];
3076
+ const pathsForSliceId = path.map((p) => {
3077
+ const newPath = [...p[0]];
3078
+ newPath[2] = 0;
3079
+ return ["add", sliceId, ...newPath];
3080
+ });
3030
3081
  return {
3031
3082
  [sliceId]: {
3032
3083
  tree: {
3033
3084
  [childrenTableKey]: {
3034
- ...{ _data: [comp] },
3035
- ...{ _type: "components" }
3085
+ _data: [comp],
3086
+ _type: "components"
3036
3087
  }
3037
3088
  },
3038
3089
  path: pathsForSliceId
3039
3090
  }
3040
3091
  };
3041
3092
  });
3042
- const layer = layerTreesAndPaths.flatMap(
3043
- (ltap) => Object.entries(ltap).map(([sliceId, { tree }]) => ({
3044
- [sliceId]: tree
3045
- }))
3046
- ).reduce((a, b) => ({ ...a, ...b }), {});
3047
- const paths = layerTreesAndPaths.map(
3048
- (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
+ })
3049
3113
  );
3050
- nodeRowsMatchingChildrenRefs.set(nodeRow._hash, {
3051
- rljson: nodeRow,
3052
- tree: {
3053
- ...nodeRowObj,
3054
- add: { ...nodeRowObj.add, ...layer }
3055
- },
3056
- cell: rowChildrenCell.map(
3057
- (c, idx) => ({
3058
- ...c,
3059
- ...{
3060
- path: [paths.flat()[idx]]
3061
- }
3062
- })
3063
- )
3114
+ nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
3115
+ rljson: rljson2,
3116
+ tree: tree2,
3117
+ cell: cell2
3064
3118
  });
3065
3119
  } else if (nodeType === "cakes") {
3066
- nodeRowsMatchingChildrenRefs.set(nodeRow._hash, {
3120
+ nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
3067
3121
  rljson: nodeRow,
3068
- tree: {
3122
+ tree: opts.skipTree ? {} : {
3069
3123
  ...nodeRowObj,
3070
3124
  layers: { ...nodeRowObj.layers, ...rowChildrenTree }
3071
3125
  },
3072
- cell: rowChildrenCell.map((c) => ({
3126
+ cell: opts.skipCell ? [] : rowChildrenCell.map((c) => ({
3073
3127
  ...c,
3074
- ...{
3075
- path: c.path.map((p) => ["layers", ...p])
3076
- }
3128
+ path: c.path.map((p) => ["layers", ...p])
3077
3129
  }))
3078
3130
  });
3079
3131
  } else if (nodeType === "components") {
3080
3132
  if (rowChildrenTree && Object.keys(rowChildrenTree).length > 0) {
3081
- const columnReferenceMap = nodeColumnCfgs.filter(
3082
- (c) => c.ref && ["components", "cakes"].includes(c.ref.type)
3083
- ).reduce((acc, curr) => {
3084
- acc.set(curr.key, curr.ref.tableKey);
3085
- return acc;
3086
- }, /* @__PURE__ */ new Map());
3087
- const resolvedRefs = {};
3133
+ const resolvedProperties = {};
3134
+ const allCells = [];
3088
3135
  for (const [colKey, childTableKey] of columnReferenceMap) {
3089
- const tree = {
3090
- ...rowChildrenTree[childTableKey],
3091
- ...{ _tableKey: childTableKey }
3092
- };
3093
- const cell = rowChildrenCell.map((c) => ({
3094
- ...c,
3095
- ...{
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,
3096
3145
  path: c.path.filter((p) => p[0] === childTableKey).map((p) => [colKey, ...p.slice(1)])
3097
- }
3098
- }));
3099
- resolvedRefs[colKey] = { tree, cell };
3146
+ }));
3147
+ allCells.push(...cell2);
3148
+ }
3100
3149
  }
3101
- const resolvedProperties = Object.entries(resolvedRefs).map(([colKey, { tree }]) => ({
3102
- [colKey]: tree
3103
- })).reduce((a, b) => ({ ...a, ...b }), {});
3104
- const resolvedTree = {
3105
- ...nodeRowObj,
3106
- ...resolvedProperties
3107
- };
3108
- const resolvedCell = Object.values(resolvedRefs).map((r) => r.cell).flat();
3109
- nodeRowsMatchingChildrenRefs.set(nodeRow._hash, {
3150
+ nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
3110
3151
  rljson: nodeRow,
3111
- tree: resolvedTree,
3112
- cell: resolvedCell
3152
+ tree: opts.skipTree ? {} : {
3153
+ ...nodeRowObj,
3154
+ ...resolvedProperties
3155
+ },
3156
+ cell: allCells
3113
3157
  });
3114
3158
  } else {
3115
- nodeRowsMatchingChildrenRefs.set(nodeRow._hash, {
3159
+ nodeRowsMatchingChildrenRefs.set(nodeRowHash, {
3116
3160
  rljson: nodeRow,
3117
3161
  tree: { ...nodeRowObj },
3118
3162
  cell: rowChildrenCell
@@ -3124,43 +3168,46 @@ class Db {
3124
3168
  );
3125
3169
  }
3126
3170
  }
3127
- const nodeChildren = makeUnique(
3128
- merge(...nodeChildrenArray)
3129
- );
3171
+ const nodeChildren = opts.skipRljson ? {} : makeUnique(merge(...nodeChildrenArray));
3130
3172
  const matchedNodeRows = Array.from(nodeRowsMatchingChildrenRefs.values());
3131
- const result = {
3132
- rljson: {
3133
- ...node,
3134
- ...{
3135
- [nodeTableKey]: {
3136
- ...{
3137
- _data: matchedNodeRows.map((mr) => mr.rljson),
3138
- _type: nodeType
3139
- },
3140
- ...{
3141
- ...nodeHash ? { _hash: nodeHash } : {}
3142
- }
3143
- }
3144
- },
3145
- ...nodeChildren
3173
+ const rljson = opts.skipRljson ? {} : {
3174
+ ...node,
3175
+ [nodeTableKey]: {
3176
+ _data: matchedNodeRows.map((mr) => mr.rljson),
3177
+ _type: nodeType,
3178
+ ...nodeHash ? { _hash: nodeHash } : {}
3146
3179
  },
3147
- tree: {
3148
- [nodeTableKey]: {
3149
- ...{
3150
- _data: matchedNodeRows.map((mr) => mr.tree),
3151
- _type: nodeType
3152
- },
3153
- ...{
3154
- ...nodeHash ? { _hash: nodeHash } : {}
3155
- }
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
+ };
3156
3203
  }
3157
- },
3158
- cell: matchedNodeRows.map(
3159
- (mr, idx) => mr.cell.map((c) => ({
3160
- ...c,
3161
- ...{ path: c.path.map((p) => [nodeTableKey, "_data", idx, ...p]) }
3162
- }))
3163
- ).flat()
3204
+ }
3205
+ return cells;
3206
+ })();
3207
+ const result = {
3208
+ rljson,
3209
+ tree,
3210
+ cell
3164
3211
  };
3165
3212
  this._cache.set(cacheHash, result);
3166
3213
  return result;
@@ -3192,7 +3239,13 @@ class Db {
3192
3239
  async join(columnSelection, cakeKey, cakeRef) {
3193
3240
  const {
3194
3241
  tree: { [cakeKey]: cakesTable }
3195
- } = 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
+ );
3196
3249
  const cakes = cakesTable._data;
3197
3250
  if (cakes.length === 0) {
3198
3251
  throw new Error(
@@ -4192,7 +4245,11 @@ class MultiEditProcessor {
4192
4245
  multiEdit.previous
4193
4246
  );
4194
4247
  const previousMultiEdit = previousMultiEdits[0];
4195
- return this._resolve(previousMultiEdit);
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
+ }
4196
4253
  }
4197
4254
  }
4198
4255
  //...........................................................................
@@ -4329,6 +4386,14 @@ class MultiEditProcessor {
4329
4386
  }
4330
4387
  return this._join;
4331
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
+ }
4332
4397
  }
4333
4398
  class MultiEditManager {
4334
4399
  constructor(_cakeKey, _db) {