@rljson/db 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.architecture.md +859 -1
- package/README.contributors.md +534 -20
- package/README.public.md +943 -4
- package/README.trouble.md +49 -0
- package/dist/README.architecture.md +859 -1
- package/dist/README.contributors.md +534 -20
- package/dist/README.public.md +943 -4
- package/dist/README.trouble.md +49 -0
- package/dist/db.js +58 -8
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/package.json +13 -13
package/dist/README.trouble.md
CHANGED
|
@@ -6,9 +6,58 @@
|
|
|
6
6
|
|
|
7
7
|
## Table of contents <!-- omit in toc -->
|
|
8
8
|
|
|
9
|
+
- [Tree INSERT operations failing with empty results](#tree-insert-operations-failing-with-empty-results)
|
|
9
10
|
- [Vscode Windows: Debugging is not working](#vscode-windows-debugging-is-not-working)
|
|
10
11
|
- [GitHub actions: Cannot find module @rollup/rollup-linux-x64-gnu](#github-actions-cannot-find-module-rolluprollup-linux-x64-gnu)
|
|
11
12
|
|
|
13
|
+
## Tree INSERT operations failing with empty results
|
|
14
|
+
|
|
15
|
+
Date: 2026-01-28
|
|
16
|
+
|
|
17
|
+
### Symptoms
|
|
18
|
+
|
|
19
|
+
- Tree INSERT operations complete without errors
|
|
20
|
+
- GET queries after INSERT return empty results or only root node
|
|
21
|
+
- Cell length is 1 instead of expected count
|
|
22
|
+
- Navigation stops at root level
|
|
23
|
+
|
|
24
|
+
### Root Cause
|
|
25
|
+
|
|
26
|
+
The `treeFromObject` function from `@rljson/rljson` v0.0.74+ creates an explicit root node with `id='root'` at the end of the tree array. When inserting an already-isolated subtree (from `isolate()`), this created a double-root structure:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
Auto-root (id='root')
|
|
30
|
+
└─ User-root (id='root')
|
|
31
|
+
└─ actual data nodes
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
When `TreeController` navigates the tree, it stops at the first node with `id='root'` (the auto-root), which has no meaningful data.
|
|
35
|
+
|
|
36
|
+
### Solution
|
|
37
|
+
|
|
38
|
+
✅ **Fixed in current version**: The `db.ts` file now calls `treeFromObject` with `skipRootCreation: true` parameter:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
const trees = treeFromObject(treeObject, true);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This prevents the automatic root wrapper from being created during INSERT operations.
|
|
45
|
+
|
|
46
|
+
### Verification
|
|
47
|
+
|
|
48
|
+
Run the tree INSERT tests:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pnpm test --run --grep "insert on tree"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
All tree INSERT tests should pass:
|
|
55
|
+
|
|
56
|
+
- "insert on tree root node"
|
|
57
|
+
- "insert on tree deeper leaf"
|
|
58
|
+
- "insert on tree simple branch"
|
|
59
|
+
- "insert new child on branch"
|
|
60
|
+
|
|
12
61
|
## Vscode Windows: Debugging is not working
|
|
13
62
|
|
|
14
63
|
Date: 2025-03-08
|
package/dist/db.js
CHANGED
|
@@ -984,6 +984,15 @@ class TreeController extends BaseController {
|
|
|
984
984
|
if (treeId && treeId !== tree.id) {
|
|
985
985
|
return { [this._tableKey]: { _data: [], _type: "trees" } };
|
|
986
986
|
}
|
|
987
|
+
const shouldExpandChildren = path !== void 0;
|
|
988
|
+
if (!shouldExpandChildren) {
|
|
989
|
+
return {
|
|
990
|
+
[this._tableKey]: {
|
|
991
|
+
_data: [tree],
|
|
992
|
+
_type: "trees"
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
}
|
|
987
996
|
const children = [];
|
|
988
997
|
for (const childRef of tree.children ?? []) {
|
|
989
998
|
const child = await this.get(
|
|
@@ -1005,21 +1014,47 @@ class TreeController extends BaseController {
|
|
|
1005
1014
|
if (trees.length === 0) {
|
|
1006
1015
|
return {};
|
|
1007
1016
|
}
|
|
1017
|
+
if (trees.length > 1e5) {
|
|
1018
|
+
throw new Error(
|
|
1019
|
+
`TreeController.buildTreeFromTrees: Tree size exceeds limit (${trees.length} > 100000 nodes). This may indicate a performance issue or data structure problem.`
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1008
1022
|
const treeMap = /* @__PURE__ */ new Map();
|
|
1009
1023
|
for (const tree of trees) {
|
|
1010
1024
|
treeMap.set(tree._hash, tree);
|
|
1011
1025
|
}
|
|
1012
|
-
const
|
|
1026
|
+
const memo = /* @__PURE__ */ new Map();
|
|
1027
|
+
let buildObjectCallCount = 0;
|
|
1028
|
+
const MAX_ITERATIONS = 1e6;
|
|
1029
|
+
const buildObject = (tree, depth = 0) => {
|
|
1030
|
+
buildObjectCallCount++;
|
|
1031
|
+
if (buildObjectCallCount > MAX_ITERATIONS) {
|
|
1032
|
+
throw new Error(
|
|
1033
|
+
`TreeController.buildTreeFromTrees: Maximum iterations (${MAX_ITERATIONS}) exceeded. This likely indicates a bug. Processed ${buildObjectCallCount} nodes from ${trees.length} total.`
|
|
1034
|
+
);
|
|
1035
|
+
}
|
|
1036
|
+
if (depth > 1e4) {
|
|
1037
|
+
throw new Error(
|
|
1038
|
+
`TreeController.buildTreeFromTrees: Tree depth exceeds limit (${depth} > 10000). This may indicate a circular reference or extremely deep structure.`
|
|
1039
|
+
);
|
|
1040
|
+
}
|
|
1041
|
+
const hash = tree._hash;
|
|
1042
|
+
if (memo.has(hash)) {
|
|
1043
|
+
return memo.get(hash);
|
|
1044
|
+
}
|
|
1013
1045
|
if (!tree.isParent || !tree.children || tree.children.length === 0) {
|
|
1014
|
-
|
|
1046
|
+
const result3 = tree;
|
|
1047
|
+
memo.set(hash, result3);
|
|
1048
|
+
return result3;
|
|
1015
1049
|
}
|
|
1016
1050
|
const result2 = {};
|
|
1017
1051
|
for (const childHash of tree.children) {
|
|
1018
1052
|
const childTree = treeMap.get(childHash);
|
|
1019
1053
|
if (childTree && childTree.id) {
|
|
1020
|
-
result2[childTree.id] = buildObject(childTree);
|
|
1054
|
+
result2[childTree.id] = buildObject(childTree, depth + 1);
|
|
1021
1055
|
}
|
|
1022
1056
|
}
|
|
1057
|
+
memo.set(hash, result2);
|
|
1023
1058
|
return result2;
|
|
1024
1059
|
};
|
|
1025
1060
|
const referencedHashes = /* @__PURE__ */ new Set();
|
|
@@ -1105,6 +1140,9 @@ class TreeController extends BaseController {
|
|
|
1105
1140
|
return cells;
|
|
1106
1141
|
}
|
|
1107
1142
|
async getChildRefs(where, filter) {
|
|
1143
|
+
if (typeof where === "string") {
|
|
1144
|
+
return [];
|
|
1145
|
+
}
|
|
1108
1146
|
const childRefs = [];
|
|
1109
1147
|
const { [this._tableKey]: table } = await this.get(where, filter);
|
|
1110
1148
|
const trees = table._data;
|
|
@@ -1241,7 +1279,11 @@ class Core {
|
|
|
1241
1279
|
// ...........................................................................
|
|
1242
1280
|
/** Reads a specific row from a database table */
|
|
1243
1281
|
async readRow(table, rowHash) {
|
|
1244
|
-
|
|
1282
|
+
const result = await this._io.readRows({
|
|
1283
|
+
table,
|
|
1284
|
+
where: { _hash: rowHash }
|
|
1285
|
+
});
|
|
1286
|
+
return result;
|
|
1245
1287
|
}
|
|
1246
1288
|
// ...........................................................................
|
|
1247
1289
|
async readRows(table, where) {
|
|
@@ -2919,6 +2961,12 @@ class Db {
|
|
|
2919
2961
|
* @returns - An Rljson object matching the route and filters
|
|
2920
2962
|
*/
|
|
2921
2963
|
async _get(route, where, controllers, filter, sliceIds, routeAccumulator, options) {
|
|
2964
|
+
const depth = routeAccumulator ? routeAccumulator.flat.split("/").length : 1;
|
|
2965
|
+
if (depth > 100) {
|
|
2966
|
+
throw new Error(
|
|
2967
|
+
`Db._get: Maximum recursion depth (100) exceeded. This likely indicates a bug in route resolution or where clause construction. Current route: ${route.flat}, routeAccumulator: ${routeAccumulator?.flat}`
|
|
2968
|
+
);
|
|
2969
|
+
}
|
|
2922
2970
|
const opts = options ?? {};
|
|
2923
2971
|
const routeHasRefs = route.flat != route.flatWithoutRefs;
|
|
2924
2972
|
const hasFilter = filter !== void 0 && filter.length > 0;
|
|
@@ -3738,7 +3786,7 @@ class Db {
|
|
|
3738
3786
|
`Db._insert: No tree data found for table "${nodeTableKey}" in route "${route.flat}".`
|
|
3739
3787
|
);
|
|
3740
3788
|
}
|
|
3741
|
-
const trees = treeFromObject(treeObject);
|
|
3789
|
+
const trees = treeFromObject(treeObject, true);
|
|
3742
3790
|
const writePromises = trees.map(
|
|
3743
3791
|
(tree2) => runFn("add", tree2, "db.insert")
|
|
3744
3792
|
);
|
|
@@ -3862,9 +3910,7 @@ class Db {
|
|
|
3862
3910
|
const multiEditController = await this.getController(
|
|
3863
3911
|
cakeKey + "MultiEdits"
|
|
3864
3912
|
);
|
|
3865
|
-
const { [cakeKey + "MultiEdits"]: result } = await multiEditController.get(
|
|
3866
|
-
where
|
|
3867
|
-
);
|
|
3913
|
+
const { [cakeKey + "MultiEdits"]: result } = await multiEditController.get(where);
|
|
3868
3914
|
return result._data;
|
|
3869
3915
|
}
|
|
3870
3916
|
// ...........................................................................
|
|
@@ -6091,6 +6137,10 @@ export {
|
|
|
6091
6137
|
exampleEditActionRowSort,
|
|
6092
6138
|
exampleEditActionSetValue,
|
|
6093
6139
|
exampleEditSetValueReferenced,
|
|
6140
|
+
inject,
|
|
6141
|
+
isolate,
|
|
6142
|
+
makeUnique,
|
|
6143
|
+
mergeTrees,
|
|
6094
6144
|
staticExample
|
|
6095
6145
|
};
|
|
6096
6146
|
//# sourceMappingURL=db.js.map
|