fast-tree-builder 1.0.0-alpha.0 → 1.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/index.cjs +22 -9
- package/index.d.ts +1 -0
- package/index.js +22 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -251,6 +251,7 @@ Parameters
|
|
|
251
251
|
- `nodeChildrenKey`: (Optional) The key used to store the children nodes in each node. It can be a `string`, `number`, `symbol`. Defaults to `'children'`.
|
|
252
252
|
- `mapNodeData`: (Optional) A function that maps an item to its corresponding node data. It allows transforming the item before assigning it to the node. Defaults to `undefined`.
|
|
253
253
|
- `validRootKeys`: (Optional) An iterable containing key values that can be accepted as root nodes. If provided, any item with a key not present in this iterable will cause an error to be thrown. Defaults to `undefined`.
|
|
254
|
+
- `validRootParentKeys`: (Optional) Only available when `mode` is set to `parent`. An iterable containing key values that can be accepted the parent field values of root nodes. If provided, any root node with a parent key not present in this iterable will cause an error to be thrown. Defaults to `undefined`.
|
|
254
255
|
- `validateTree`: (Optional) A boolean flag that determines whether to validate the resulting data structure. If the structure is a cyclic graph, an `Error` will be thrown. Requires additional `O(n)` time to compute. Defaults to `false`.
|
|
255
256
|
|
|
256
257
|
Returns
|
|
@@ -263,7 +264,8 @@ An object with the following properties:
|
|
|
263
264
|
Throws `Error` when:
|
|
264
265
|
|
|
265
266
|
- A duplicate identifier is recieved,
|
|
266
|
-
- or `validRootKeys` is set and an invalid
|
|
267
|
+
- or `validRootKeys` is set and an invalid key is recieved,
|
|
268
|
+
- or `validRootParentKeys` is set and an invalid parent key is recieved,
|
|
267
269
|
- or `validateTree` is set to `true` and a cyclic graph is the result.
|
|
268
270
|
|
|
269
271
|
## Comparison with other tree building libraries
|
package/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
function buildTree(items, options = {}) {
|
|
4
|
-
const { mode = 'parent', key = 'id', parentKey = 'parent', childrenKey = 'children', nodeDataKey = 'data', nodeParentKey = 'parent', nodeChildrenKey = 'children', mapNodeData, validRootKeys, validateTree = false, } = options;
|
|
4
|
+
const { mode = 'parent', key = 'id', parentKey = 'parent', childrenKey = 'children', nodeDataKey = 'data', nodeParentKey = 'parent', nodeChildrenKey = 'children', mapNodeData, validRootKeys, validRootParentKeys, validateTree = false, } = options;
|
|
5
5
|
const roots = [];
|
|
6
6
|
const nodes = new Map();
|
|
7
7
|
const danglingNodes = new Map();
|
|
@@ -49,11 +49,11 @@ function buildTree(items, options = {}) {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
// Children of dangling nodes will become the root nodes
|
|
52
|
-
if (
|
|
53
|
-
const validParentKeys = new Set(
|
|
54
|
-
for (const [
|
|
55
|
-
if (!validParentKeys.has(
|
|
56
|
-
throw new Error(`Invalid parent key "${
|
|
52
|
+
if (validRootParentKeys) {
|
|
53
|
+
const validParentKeys = new Set(validRootParentKeys);
|
|
54
|
+
for (const [parentKey, node] of danglingNodes.entries()) {
|
|
55
|
+
if (!validParentKeys.has(parentKey)) {
|
|
56
|
+
throw new Error(`Invalid parent key "${parentKey}" found for a root node.`);
|
|
57
57
|
}
|
|
58
58
|
for (const root of node[nodeChildrenKey]) {
|
|
59
59
|
// Root nodes does not have a parent, unlink the dangling node
|
|
@@ -75,8 +75,21 @@ function buildTree(items, options = {}) {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
+
// TODO: this could be optimized
|
|
79
|
+
if (validRootKeys) {
|
|
80
|
+
const rootsSet = new Set(roots);
|
|
81
|
+
const validKeys = new Set(validRootKeys);
|
|
82
|
+
for (const [key, node] of nodes) {
|
|
83
|
+
if (rootsSet.has(node) && !validKeys.has(key)) {
|
|
84
|
+
throw new Error(`A root node has an invalid key "${key}"`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
78
88
|
}
|
|
79
89
|
else {
|
|
90
|
+
if (validRootParentKeys) {
|
|
91
|
+
throw new Error(`Option "validRootParentKeys" cannot be used when mode is set to "children".`);
|
|
92
|
+
}
|
|
80
93
|
const knownNodes = new Set();
|
|
81
94
|
const incompleteNodes = new Set();
|
|
82
95
|
for (const item of items) {
|
|
@@ -134,10 +147,10 @@ function buildTree(items, options = {}) {
|
|
|
134
147
|
throw new Error(`Some nodes miss their referenced children (${incompleteNodes.size}).`);
|
|
135
148
|
}
|
|
136
149
|
if (validRootKeys) {
|
|
137
|
-
const
|
|
150
|
+
const validKeys = new Set(validRootKeys);
|
|
138
151
|
for (const [key, node] of danglingNodes.entries()) {
|
|
139
|
-
if (!
|
|
140
|
-
throw new Error(`
|
|
152
|
+
if (!validKeys.has(key)) {
|
|
153
|
+
throw new Error(`A root node has an invalid key "${key}"`);
|
|
141
154
|
}
|
|
142
155
|
roots.push(node);
|
|
143
156
|
nodes.set(key, node);
|
package/index.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ declare function buildTree<T extends (D extends false ? object : unknown), K ext
|
|
|
28
28
|
(item: T): M;
|
|
29
29
|
};
|
|
30
30
|
validRootKeys?: Iterable<unknown>;
|
|
31
|
+
validRootParentKeys?: Iterable<unknown>;
|
|
31
32
|
validateTree?: boolean;
|
|
32
33
|
}): {
|
|
33
34
|
roots: TreeNode<M extends undefined ? T : M, D, P, C>[];
|
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
function buildTree(items, options = {}) {
|
|
2
|
-
const { mode = 'parent', key = 'id', parentKey = 'parent', childrenKey = 'children', nodeDataKey = 'data', nodeParentKey = 'parent', nodeChildrenKey = 'children', mapNodeData, validRootKeys, validateTree = false, } = options;
|
|
2
|
+
const { mode = 'parent', key = 'id', parentKey = 'parent', childrenKey = 'children', nodeDataKey = 'data', nodeParentKey = 'parent', nodeChildrenKey = 'children', mapNodeData, validRootKeys, validRootParentKeys, validateTree = false, } = options;
|
|
3
3
|
const roots = [];
|
|
4
4
|
const nodes = new Map();
|
|
5
5
|
const danglingNodes = new Map();
|
|
@@ -47,11 +47,11 @@ function buildTree(items, options = {}) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
// Children of dangling nodes will become the root nodes
|
|
50
|
-
if (
|
|
51
|
-
const validParentKeys = new Set(
|
|
52
|
-
for (const [
|
|
53
|
-
if (!validParentKeys.has(
|
|
54
|
-
throw new Error(`Invalid parent key "${
|
|
50
|
+
if (validRootParentKeys) {
|
|
51
|
+
const validParentKeys = new Set(validRootParentKeys);
|
|
52
|
+
for (const [parentKey, node] of danglingNodes.entries()) {
|
|
53
|
+
if (!validParentKeys.has(parentKey)) {
|
|
54
|
+
throw new Error(`Invalid parent key "${parentKey}" found for a root node.`);
|
|
55
55
|
}
|
|
56
56
|
for (const root of node[nodeChildrenKey]) {
|
|
57
57
|
// Root nodes does not have a parent, unlink the dangling node
|
|
@@ -73,8 +73,21 @@ function buildTree(items, options = {}) {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
// TODO: this could be optimized
|
|
77
|
+
if (validRootKeys) {
|
|
78
|
+
const rootsSet = new Set(roots);
|
|
79
|
+
const validKeys = new Set(validRootKeys);
|
|
80
|
+
for (const [key, node] of nodes) {
|
|
81
|
+
if (rootsSet.has(node) && !validKeys.has(key)) {
|
|
82
|
+
throw new Error(`A root node has an invalid key "${key}"`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
76
86
|
}
|
|
77
87
|
else {
|
|
88
|
+
if (validRootParentKeys) {
|
|
89
|
+
throw new Error(`Option "validRootParentKeys" cannot be used when mode is set to "children".`);
|
|
90
|
+
}
|
|
78
91
|
const knownNodes = new Set();
|
|
79
92
|
const incompleteNodes = new Set();
|
|
80
93
|
for (const item of items) {
|
|
@@ -132,10 +145,10 @@ function buildTree(items, options = {}) {
|
|
|
132
145
|
throw new Error(`Some nodes miss their referenced children (${incompleteNodes.size}).`);
|
|
133
146
|
}
|
|
134
147
|
if (validRootKeys) {
|
|
135
|
-
const
|
|
148
|
+
const validKeys = new Set(validRootKeys);
|
|
136
149
|
for (const [key, node] of danglingNodes.entries()) {
|
|
137
|
-
if (!
|
|
138
|
-
throw new Error(`
|
|
150
|
+
if (!validKeys.has(key)) {
|
|
151
|
+
throw new Error(`A root node has an invalid key "${key}"`);
|
|
139
152
|
}
|
|
140
153
|
roots.push(node);
|
|
141
154
|
nodes.set(key, node);
|
package/package.json
CHANGED