@sisense/sdk-pivot-query-client 2.17.0
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/LICENSE.md +35 -0
- package/README.md +2 -0
- package/dist/__test-helpers__/testUtils.d.ts +30 -0
- package/dist/__test-helpers__/testUtils.js +89 -0
- package/dist/builders/index.d.ts +2 -0
- package/dist/builders/index.js +2 -0
- package/dist/builders/pivot-data-builder.d.ts +34 -0
- package/dist/builders/pivot-data-builder.js +182 -0
- package/dist/builders/socket-builder.d.ts +18 -0
- package/dist/builders/socket-builder.js +72 -0
- package/dist/cjs/__test-helpers__/testUtils.d.ts +30 -0
- package/dist/cjs/__test-helpers__/testUtils.js +104 -0
- package/dist/cjs/builders/index.d.ts +2 -0
- package/dist/cjs/builders/index.js +7 -0
- package/dist/cjs/builders/pivot-data-builder.d.ts +34 -0
- package/dist/cjs/builders/pivot-data-builder.js +186 -0
- package/dist/cjs/builders/socket-builder.d.ts +18 -0
- package/dist/cjs/builders/socket-builder.js +79 -0
- package/dist/cjs/data-handling/DataService.d.ts +672 -0
- package/dist/cjs/data-handling/DataService.js +1364 -0
- package/dist/cjs/data-handling/DivergenceComparator.d.ts +7 -0
- package/dist/cjs/data-handling/DivergenceComparator.js +20 -0
- package/dist/cjs/data-handling/constants.d.ts +44 -0
- package/dist/cjs/data-handling/constants.js +43 -0
- package/dist/cjs/data-handling/index.d.ts +3 -0
- package/dist/cjs/data-handling/index.js +23 -0
- package/dist/cjs/data-handling/types.d.ts +104 -0
- package/dist/cjs/data-handling/types.js +2 -0
- package/dist/cjs/data-handling/utils/createPivotTreeNode.d.ts +13 -0
- package/dist/cjs/data-handling/utils/createPivotTreeNode.js +21 -0
- package/dist/cjs/data-handling/utils/index.d.ts +4 -0
- package/dist/cjs/data-handling/utils/index.js +14 -0
- package/dist/cjs/data-handling/utils/jaqlProcessor.d.ts +122 -0
- package/dist/cjs/data-handling/utils/jaqlProcessor.js +661 -0
- package/dist/cjs/data-handling/utils/pivotTransforms.d.ts +74 -0
- package/dist/cjs/data-handling/utils/pivotTransforms.js +373 -0
- package/dist/cjs/data-handling/utils/plugins/PluginService.d.ts +135 -0
- package/dist/cjs/data-handling/utils/plugins/PluginService.js +383 -0
- package/dist/cjs/data-handling/utils/plugins/getters.d.ts +23 -0
- package/dist/cjs/data-handling/utils/plugins/getters.js +70 -0
- package/dist/cjs/data-handling/utils/plugins/types.d.ts +75 -0
- package/dist/cjs/data-handling/utils/plugins/types.js +2 -0
- package/dist/cjs/data-handling/utils/plugins/validator.d.ts +13 -0
- package/dist/cjs/data-handling/utils/plugins/validator.js +169 -0
- package/dist/cjs/data-load/AbstractDataLoadService.d.ts +256 -0
- package/dist/cjs/data-load/AbstractDataLoadService.js +473 -0
- package/dist/cjs/data-load/DataLoadService.d.ts +63 -0
- package/dist/cjs/data-load/DataLoadService.js +152 -0
- package/dist/cjs/data-load/SisenseDataLoadService.d.ts +44 -0
- package/dist/cjs/data-load/SisenseDataLoadService.js +87 -0
- package/dist/cjs/data-load/TestDataLoadService.d.ts +27 -0
- package/dist/cjs/data-load/TestDataLoadService.js +76 -0
- package/dist/cjs/data-load/constants.d.ts +13 -0
- package/dist/cjs/data-load/constants.js +28 -0
- package/dist/cjs/data-load/index.d.ts +6 -0
- package/dist/cjs/data-load/index.js +14 -0
- package/dist/cjs/data-load/sockets/SisenseSocket.d.ts +81 -0
- package/dist/cjs/data-load/sockets/SisenseSocket.js +162 -0
- package/dist/cjs/data-load/sockets/TestSocket.d.ts +61 -0
- package/dist/cjs/data-load/sockets/TestSocket.js +90 -0
- package/dist/cjs/data-load/sockets/helpers.d.ts +4 -0
- package/dist/cjs/data-load/sockets/helpers.js +27 -0
- package/dist/cjs/data-load/sockets/index.d.ts +2 -0
- package/dist/cjs/data-load/sockets/index.js +8 -0
- package/dist/cjs/data-load/types.d.ts +90 -0
- package/dist/cjs/data-load/types.js +2 -0
- package/dist/cjs/errors/LoadingCanceledError.d.ts +7 -0
- package/dist/cjs/errors/LoadingCanceledError.js +24 -0
- package/dist/cjs/errors/index.d.ts +1 -0
- package/dist/cjs/errors/index.js +6 -0
- package/dist/cjs/index.d.ts +17 -0
- package/dist/cjs/index.js +32 -0
- package/dist/cjs/package.json +12 -0
- package/dist/cjs/pivot-query-client.d.ts +13 -0
- package/dist/cjs/pivot-query-client.js +26 -0
- package/dist/cjs/tree-structure/AbstractTreeService.d.ts +308 -0
- package/dist/cjs/tree-structure/AbstractTreeService.js +716 -0
- package/dist/cjs/tree-structure/HeaderTreeService.d.ts +180 -0
- package/dist/cjs/tree-structure/HeaderTreeService.js +280 -0
- package/dist/cjs/tree-structure/TreeCellMap.d.ts +104 -0
- package/dist/cjs/tree-structure/TreeCellMap.js +145 -0
- package/dist/cjs/tree-structure/TreeService.d.ts +8 -0
- package/dist/cjs/tree-structure/TreeService.js +12 -0
- package/dist/cjs/tree-structure/constants.d.ts +6 -0
- package/dist/cjs/tree-structure/constants.js +10 -0
- package/dist/cjs/tree-structure/index.d.ts +5 -0
- package/dist/cjs/tree-structure/index.js +10 -0
- package/dist/cjs/tree-structure/types.d.ts +93 -0
- package/dist/cjs/tree-structure/types.js +2 -0
- package/dist/cjs/tree-structure/utils/index.d.ts +1 -0
- package/dist/cjs/tree-structure/utils/index.js +9 -0
- package/dist/cjs/tree-structure/utils/treeNode.d.ts +147 -0
- package/dist/cjs/tree-structure/utils/treeNode.js +534 -0
- package/dist/cjs/utils/array.d.ts +13 -0
- package/dist/cjs/utils/array.js +25 -0
- package/dist/cjs/utils/cloneObject.d.ts +30 -0
- package/dist/cjs/utils/cloneObject.js +225 -0
- package/dist/cjs/utils/index.d.ts +3 -0
- package/dist/cjs/utils/index.js +9 -0
- package/dist/cjs/utils/throttle.d.ts +12 -0
- package/dist/cjs/utils/throttle.js +39 -0
- package/dist/cjs/utils/types.d.ts +12 -0
- package/dist/cjs/utils/types.js +2 -0
- package/dist/data-handling/DataService.d.ts +672 -0
- package/dist/data-handling/DataService.js +1357 -0
- package/dist/data-handling/DivergenceComparator.d.ts +7 -0
- package/dist/data-handling/DivergenceComparator.js +16 -0
- package/dist/data-handling/constants.d.ts +44 -0
- package/dist/data-handling/constants.js +40 -0
- package/dist/data-handling/index.d.ts +3 -0
- package/dist/data-handling/index.js +4 -0
- package/dist/data-handling/types.d.ts +104 -0
- package/dist/data-handling/types.js +1 -0
- package/dist/data-handling/utils/createPivotTreeNode.d.ts +13 -0
- package/dist/data-handling/utils/createPivotTreeNode.js +17 -0
- package/dist/data-handling/utils/index.d.ts +4 -0
- package/dist/data-handling/utils/index.js +4 -0
- package/dist/data-handling/utils/jaqlProcessor.d.ts +122 -0
- package/dist/data-handling/utils/jaqlProcessor.js +621 -0
- package/dist/data-handling/utils/pivotTransforms.d.ts +74 -0
- package/dist/data-handling/utils/pivotTransforms.js +335 -0
- package/dist/data-handling/utils/plugins/PluginService.d.ts +135 -0
- package/dist/data-handling/utils/plugins/PluginService.js +379 -0
- package/dist/data-handling/utils/plugins/getters.d.ts +23 -0
- package/dist/data-handling/utils/plugins/getters.js +65 -0
- package/dist/data-handling/utils/plugins/types.d.ts +75 -0
- package/dist/data-handling/utils/plugins/types.js +1 -0
- package/dist/data-handling/utils/plugins/validator.d.ts +13 -0
- package/dist/data-handling/utils/plugins/validator.js +165 -0
- package/dist/data-load/AbstractDataLoadService.d.ts +256 -0
- package/dist/data-load/AbstractDataLoadService.js +466 -0
- package/dist/data-load/DataLoadService.d.ts +63 -0
- package/dist/data-load/DataLoadService.js +148 -0
- package/dist/data-load/SisenseDataLoadService.d.ts +44 -0
- package/dist/data-load/SisenseDataLoadService.js +83 -0
- package/dist/data-load/TestDataLoadService.d.ts +27 -0
- package/dist/data-load/TestDataLoadService.js +69 -0
- package/dist/data-load/constants.d.ts +13 -0
- package/dist/data-load/constants.js +25 -0
- package/dist/data-load/index.d.ts +6 -0
- package/dist/data-load/index.js +6 -0
- package/dist/data-load/sockets/SisenseSocket.d.ts +81 -0
- package/dist/data-load/sockets/SisenseSocket.js +155 -0
- package/dist/data-load/sockets/TestSocket.d.ts +61 -0
- package/dist/data-load/sockets/TestSocket.js +83 -0
- package/dist/data-load/sockets/helpers.d.ts +4 -0
- package/dist/data-load/sockets/helpers.js +23 -0
- package/dist/data-load/sockets/index.d.ts +2 -0
- package/dist/data-load/sockets/index.js +3 -0
- package/dist/data-load/types.d.ts +90 -0
- package/dist/data-load/types.js +1 -0
- package/dist/errors/LoadingCanceledError.d.ts +7 -0
- package/dist/errors/LoadingCanceledError.js +20 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +2 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +9 -0
- package/dist/pivot-query-client.d.ts +13 -0
- package/dist/pivot-query-client.js +22 -0
- package/dist/tree-structure/AbstractTreeService.d.ts +308 -0
- package/dist/tree-structure/AbstractTreeService.js +712 -0
- package/dist/tree-structure/HeaderTreeService.d.ts +180 -0
- package/dist/tree-structure/HeaderTreeService.js +276 -0
- package/dist/tree-structure/TreeCellMap.d.ts +104 -0
- package/dist/tree-structure/TreeCellMap.js +141 -0
- package/dist/tree-structure/TreeService.d.ts +8 -0
- package/dist/tree-structure/TreeService.js +8 -0
- package/dist/tree-structure/constants.d.ts +6 -0
- package/dist/tree-structure/constants.js +7 -0
- package/dist/tree-structure/index.d.ts +5 -0
- package/dist/tree-structure/index.js +4 -0
- package/dist/tree-structure/types.d.ts +93 -0
- package/dist/tree-structure/types.js +1 -0
- package/dist/tree-structure/utils/index.d.ts +1 -0
- package/dist/tree-structure/utils/index.js +1 -0
- package/dist/tree-structure/utils/treeNode.d.ts +147 -0
- package/dist/tree-structure/utils/treeNode.js +515 -0
- package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
- package/dist/utils/array.d.ts +13 -0
- package/dist/utils/array.js +21 -0
- package/dist/utils/cloneObject.d.ts +30 -0
- package/dist/utils/cloneObject.js +221 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/throttle.d.ts +12 -0
- package/dist/utils/throttle.js +35 -0
- package/dist/utils/types.d.ts +12 -0
- package/dist/utils/types.js +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
import { cloneObject } from '../../utils/index.js';
|
|
2
|
+
class ChunksList extends Array {
|
|
3
|
+
constructor(items) {
|
|
4
|
+
super(...items);
|
|
5
|
+
Object.setPrototypeOf(this, Object.create(ChunksList.prototype));
|
|
6
|
+
this.isHandled = false;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export const ROOT = '$*$root$*$';
|
|
10
|
+
export function create(value, children, data, index) {
|
|
11
|
+
const res = { value };
|
|
12
|
+
if (children) {
|
|
13
|
+
res.children = children;
|
|
14
|
+
}
|
|
15
|
+
if (data) {
|
|
16
|
+
res.data = data;
|
|
17
|
+
}
|
|
18
|
+
if (typeof index !== 'undefined') {
|
|
19
|
+
res.index = index;
|
|
20
|
+
}
|
|
21
|
+
return res;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Defines if node has child nodes or not
|
|
25
|
+
*
|
|
26
|
+
* @param {TreeNode} node - tree node object
|
|
27
|
+
* @returns {boolean} - true - has children, false - last child
|
|
28
|
+
*/
|
|
29
|
+
export function hasChildren(node) {
|
|
30
|
+
return !!(node && node.children && node.children.length);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Returns list of child nodes
|
|
34
|
+
*
|
|
35
|
+
* @param {TreeNode} node - tree node object
|
|
36
|
+
* @returns {Array<TreeNode>|Array} - list of child nodes or empty array
|
|
37
|
+
*/
|
|
38
|
+
export function getChildren(node) {
|
|
39
|
+
return (node && node.children) || [];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Set new list of child nodes
|
|
43
|
+
*
|
|
44
|
+
* @param {TreeNode} node - tree node object
|
|
45
|
+
* @param {Array<TreeNode>} list - new list of child nodes
|
|
46
|
+
* @returns {void}
|
|
47
|
+
*/
|
|
48
|
+
export function setChildren(node, list) {
|
|
49
|
+
if (node && list && Array.isArray(list)) {
|
|
50
|
+
node.children = list;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Set node deep level in tree hierarchy
|
|
55
|
+
*
|
|
56
|
+
* @param {TreeNode} node - tree node object
|
|
57
|
+
* @param {number} level - hierarchy level
|
|
58
|
+
* @returns {void}
|
|
59
|
+
*/
|
|
60
|
+
export function setLevel(node, level) {
|
|
61
|
+
if (node) {
|
|
62
|
+
node.level = level;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Returns node deep level in tree hierarchy
|
|
67
|
+
*
|
|
68
|
+
* @param {TreeNode} node - tree node object
|
|
69
|
+
* @returns {number} hierarchy level
|
|
70
|
+
*/
|
|
71
|
+
export function getLevel(node) {
|
|
72
|
+
if (node && typeof node.level !== 'undefined') {
|
|
73
|
+
return node.level || 0;
|
|
74
|
+
}
|
|
75
|
+
return -1;
|
|
76
|
+
}
|
|
77
|
+
export function wrapInRootNode(data) {
|
|
78
|
+
if (!data) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
if (data && !Array.isArray(data) && data.value === ROOT) {
|
|
82
|
+
return data;
|
|
83
|
+
}
|
|
84
|
+
const node = { value: ROOT, children: [] };
|
|
85
|
+
if (Array.isArray(data)) {
|
|
86
|
+
node.children = data;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
(node.children || [])[0] = data;
|
|
90
|
+
}
|
|
91
|
+
return node;
|
|
92
|
+
}
|
|
93
|
+
function findNode(rootNode, checkCb, level = 0) {
|
|
94
|
+
let res;
|
|
95
|
+
if (!rootNode || !checkCb) {
|
|
96
|
+
return res;
|
|
97
|
+
}
|
|
98
|
+
if (checkCb(rootNode, level)) {
|
|
99
|
+
res = rootNode;
|
|
100
|
+
}
|
|
101
|
+
if (hasChildren(rootNode)) {
|
|
102
|
+
const children = getChildren(rootNode);
|
|
103
|
+
const childCount = children.length;
|
|
104
|
+
for (let i = 0; i < childCount; i += 1) {
|
|
105
|
+
const childRes = findNode(children[i], checkCb, level + 1);
|
|
106
|
+
if (childRes) {
|
|
107
|
+
res = childRes;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return res;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Merge two root trees into one
|
|
116
|
+
*
|
|
117
|
+
* @param {TreeNode} [firstNode] - first tree
|
|
118
|
+
* @param {TreeNode} [secondNode] - second tree
|
|
119
|
+
* @returns {TreeNode} - merged tree
|
|
120
|
+
*/
|
|
121
|
+
export function merge(firstNode, secondNode) {
|
|
122
|
+
if (!firstNode && !secondNode) {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
if (!firstNode && secondNode) {
|
|
126
|
+
return wrapInRootNode(secondNode);
|
|
127
|
+
}
|
|
128
|
+
if (firstNode && !secondNode) {
|
|
129
|
+
return wrapInRootNode(firstNode);
|
|
130
|
+
}
|
|
131
|
+
const firstRootNode = wrapInRootNode(firstNode);
|
|
132
|
+
const secondRootNode = wrapInRootNode(secondNode);
|
|
133
|
+
const firstChildrens = (firstRootNode && firstRootNode.children) || [];
|
|
134
|
+
const secondChildrens = (secondRootNode && secondRootNode.children) || [];
|
|
135
|
+
const children = firstChildrens.concat(secondChildrens);
|
|
136
|
+
return wrapInRootNode(children);
|
|
137
|
+
}
|
|
138
|
+
const findLastCut = (node, level = 0) => {
|
|
139
|
+
if (!node || !node.isPart) {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
node.level = level;
|
|
143
|
+
const childs = getChildren(node);
|
|
144
|
+
const lastChild = childs[childs.length - 1];
|
|
145
|
+
if (!lastChild) {
|
|
146
|
+
return node;
|
|
147
|
+
}
|
|
148
|
+
const childCut = findLastCut(lastChild, level + 1);
|
|
149
|
+
return childCut || node;
|
|
150
|
+
};
|
|
151
|
+
const findFirstCut = (node, lastCut, level = 0) => {
|
|
152
|
+
if (!node || !node.isPart) {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
node.level = level;
|
|
156
|
+
if (node && lastCut && node.value === lastCut.value && node.level === lastCut.level) {
|
|
157
|
+
return node;
|
|
158
|
+
}
|
|
159
|
+
const childs = getChildren(node);
|
|
160
|
+
const firstChild = childs[0];
|
|
161
|
+
if (!firstChild) {
|
|
162
|
+
return node;
|
|
163
|
+
}
|
|
164
|
+
const childCut = findFirstCut(firstChild, lastCut, level + 1);
|
|
165
|
+
return childCut || node;
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Merging two partial pivot trees into one (mutate first argument).
|
|
169
|
+
*
|
|
170
|
+
* @param {TreeNode} targetTree - main part of pivot table model (looks like 'tree' data structure)
|
|
171
|
+
* @param {TreeNode} sourceTree - part of pivot table model (looks like 'tree' data structure) which
|
|
172
|
+
* we want merge in main part
|
|
173
|
+
* @returns {TreeNode} - merged tree
|
|
174
|
+
*/
|
|
175
|
+
export function deepMerge(targetTree, sourceTree) {
|
|
176
|
+
/**
|
|
177
|
+
* The node to which we plan to add children
|
|
178
|
+
*
|
|
179
|
+
* @type {?TreeNode}
|
|
180
|
+
*/
|
|
181
|
+
let targetNode = findLastCut(targetTree);
|
|
182
|
+
/**
|
|
183
|
+
* The node from where we plan to copy the children
|
|
184
|
+
*
|
|
185
|
+
* @type {?TreeNode}
|
|
186
|
+
*/
|
|
187
|
+
let sourceNode = findFirstCut(sourceTree, targetNode);
|
|
188
|
+
// This long logical expression
|
|
189
|
+
// needed for the flow type checker
|
|
190
|
+
// to infer non nullable type
|
|
191
|
+
// of a nested `.children` property
|
|
192
|
+
// and I can't move it out to a function
|
|
193
|
+
if (targetNode &&
|
|
194
|
+
targetNode.children &&
|
|
195
|
+
Array.isArray(targetNode.children) &&
|
|
196
|
+
sourceNode &&
|
|
197
|
+
sourceNode.children &&
|
|
198
|
+
Array.isArray(sourceNode.children) &&
|
|
199
|
+
sourceNode.children.length > 0) {
|
|
200
|
+
targetNode.children = targetNode.children.concat(sourceNode.children);
|
|
201
|
+
sourceNode.isHandled = true;
|
|
202
|
+
}
|
|
203
|
+
let hasReachedFirstCutNode = false;
|
|
204
|
+
targetNode = targetTree;
|
|
205
|
+
sourceNode = sourceTree;
|
|
206
|
+
// This long logical expression
|
|
207
|
+
// needed for the flow type checker
|
|
208
|
+
// to infer non nullable type
|
|
209
|
+
// of a nested `.children` property
|
|
210
|
+
// and I can't move it out to a function
|
|
211
|
+
while (targetNode &&
|
|
212
|
+
targetNode.children &&
|
|
213
|
+
Array.isArray(targetNode.children) &&
|
|
214
|
+
sourceNode &&
|
|
215
|
+
sourceNode.children &&
|
|
216
|
+
Array.isArray(sourceNode.children) &&
|
|
217
|
+
!sourceNode.isHandled) {
|
|
218
|
+
const preservedTargetChildren = targetNode.children;
|
|
219
|
+
targetNode = targetNode.children[targetNode.children.length - 1];
|
|
220
|
+
let i = 0;
|
|
221
|
+
if (sourceNode.children[0] && !hasReachedFirstCutNode) {
|
|
222
|
+
hasReachedFirstCutNode = !getChildren(sourceNode.children[0]).some((obj) => obj.isPart);
|
|
223
|
+
i = 1;
|
|
224
|
+
}
|
|
225
|
+
while (i < sourceNode.children.length) {
|
|
226
|
+
preservedTargetChildren.push(sourceNode.children[i]);
|
|
227
|
+
i += 1;
|
|
228
|
+
}
|
|
229
|
+
// eslint-disable-next-line prefer-destructuring
|
|
230
|
+
sourceNode = sourceNode.children[0];
|
|
231
|
+
}
|
|
232
|
+
return targetTree;
|
|
233
|
+
}
|
|
234
|
+
export function iterateThroughTree(nodes, callback, parent) {
|
|
235
|
+
if (!nodes || !callback) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
nodes.forEach((node) => {
|
|
239
|
+
callback(node, parent);
|
|
240
|
+
if (hasChildren(node)) {
|
|
241
|
+
iterateThroughTree(getChildren(node), callback, node);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
export function getLastLevelNodes(nodes, lastLevelNodes = [], level = 0, options = { maxLevel: 0 }) {
|
|
246
|
+
nodes.forEach((item) => {
|
|
247
|
+
if (options.maxLevel < level) {
|
|
248
|
+
options.maxLevel = level;
|
|
249
|
+
}
|
|
250
|
+
if (hasChildren(item)) {
|
|
251
|
+
getLastLevelNodes(getChildren(item), lastLevelNodes, level + 1, options);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
lastLevelNodes.push(item);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
return lastLevelNodes;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Returns number of last children for the tree
|
|
261
|
+
*
|
|
262
|
+
* @param {Array<TreeNode> | TreeNode} item - tree node or list of nodes
|
|
263
|
+
* @param {object} options - additional options
|
|
264
|
+
* @param {number} options.callCount - inner state for recursive calls count
|
|
265
|
+
* @param {boolean} options.clearCache - define if use cached value or recalculate new one
|
|
266
|
+
* @returns {number} - count of last children
|
|
267
|
+
*/
|
|
268
|
+
export function getChildLength(item, options = {}) {
|
|
269
|
+
if (!options) {
|
|
270
|
+
// eslint-disable-next-line no-param-reassign
|
|
271
|
+
options = {};
|
|
272
|
+
}
|
|
273
|
+
if (typeof options.callCount !== 'number') {
|
|
274
|
+
options.callCount = 1;
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
options.callCount += 1;
|
|
278
|
+
}
|
|
279
|
+
if (!item) {
|
|
280
|
+
return 0;
|
|
281
|
+
}
|
|
282
|
+
let clearCache = options.clearCache || false;
|
|
283
|
+
if (!Array.isArray(item) && item.value === ROOT) {
|
|
284
|
+
// do not use cache from 'root' node
|
|
285
|
+
clearCache = true;
|
|
286
|
+
}
|
|
287
|
+
let count = 1;
|
|
288
|
+
let children = [];
|
|
289
|
+
if (Array.isArray(item)) {
|
|
290
|
+
count = 0;
|
|
291
|
+
children = item;
|
|
292
|
+
}
|
|
293
|
+
else if (item.children) {
|
|
294
|
+
children = getChildren(item);
|
|
295
|
+
}
|
|
296
|
+
if (children && children.length) {
|
|
297
|
+
if (!clearCache && !Array.isArray(item) && typeof item.childCount === 'number') {
|
|
298
|
+
// get cached value
|
|
299
|
+
count = item.childCount;
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
count = 0;
|
|
303
|
+
// recalculate new value
|
|
304
|
+
children.forEach((child) => {
|
|
305
|
+
count += getChildLength(child, options);
|
|
306
|
+
});
|
|
307
|
+
if (!Array.isArray(item)) {
|
|
308
|
+
// cache value
|
|
309
|
+
item.childCount = count;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return count;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Returns deep level of the tree
|
|
317
|
+
*
|
|
318
|
+
* @param {Array<TreeNode> | TreeNode} item - tree node or list of nodes
|
|
319
|
+
* @param {object} options - additional options
|
|
320
|
+
* @param {number} options.callCount - inner state for recursive calls count
|
|
321
|
+
* @param {boolean} options.clearCache - define if use cached value or recalculate new one
|
|
322
|
+
* @returns {number} - count of last children
|
|
323
|
+
*/
|
|
324
|
+
export function getDeepLength(item, options = {}) {
|
|
325
|
+
if (!options) {
|
|
326
|
+
// eslint-disable-next-line no-param-reassign
|
|
327
|
+
options = {};
|
|
328
|
+
}
|
|
329
|
+
if (typeof options.callCount !== 'number') {
|
|
330
|
+
options.callCount = 1;
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
options.callCount += 1;
|
|
334
|
+
}
|
|
335
|
+
if (!item) {
|
|
336
|
+
return 0;
|
|
337
|
+
}
|
|
338
|
+
let clearCache = options.clearCache || false;
|
|
339
|
+
if (!Array.isArray(item) && item.value === ROOT) {
|
|
340
|
+
// do not use cache from 'root' node
|
|
341
|
+
clearCache = true;
|
|
342
|
+
}
|
|
343
|
+
let count = 0;
|
|
344
|
+
let children = [];
|
|
345
|
+
if (item && !Array.isArray(item) && typeof item.value !== 'undefined') {
|
|
346
|
+
count = 1;
|
|
347
|
+
}
|
|
348
|
+
if (Array.isArray(item)) {
|
|
349
|
+
count = 0;
|
|
350
|
+
children = item;
|
|
351
|
+
}
|
|
352
|
+
else if (item.children) {
|
|
353
|
+
children = getChildren(item);
|
|
354
|
+
}
|
|
355
|
+
if (children && children.length) {
|
|
356
|
+
if (!clearCache && !Array.isArray(item) && typeof item.childDeep === 'number') {
|
|
357
|
+
// get cached value
|
|
358
|
+
count += item.childDeep;
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
let maxCount = 0;
|
|
362
|
+
children.forEach((child) => {
|
|
363
|
+
const childCount = getDeepLength(child, options);
|
|
364
|
+
if (childCount > maxCount) {
|
|
365
|
+
maxCount = childCount;
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
count += maxCount;
|
|
369
|
+
if (!Array.isArray(item)) {
|
|
370
|
+
// cache value
|
|
371
|
+
item.childDeep = maxCount;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return count;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Returns part of tree nodes list according to children indexes "from" - "to"
|
|
379
|
+
* return result is not strict, and start/stop in returns object show returned node position
|
|
380
|
+
*
|
|
381
|
+
* @param {Array<TreeNode>} rootNodes - list of nodes
|
|
382
|
+
* @param {number} [from=0] - start index to for partial tree
|
|
383
|
+
* @param {number} [to] - end index for partial tree
|
|
384
|
+
* @returns {{nodes: Array<TreeNode>, start: number, stop: number}} - partial tree nodes and
|
|
385
|
+
* start/stop indexes of it in scope of initial list
|
|
386
|
+
*/
|
|
387
|
+
export function getNodesByChildCount(rootNodes = [], from = 0, to) {
|
|
388
|
+
const nodes = [];
|
|
389
|
+
let index = 0;
|
|
390
|
+
let startIndex = -1;
|
|
391
|
+
let stopIndex = -1;
|
|
392
|
+
const count = rootNodes.length;
|
|
393
|
+
if (typeof from === 'number' && typeof to === 'number' && from > to) {
|
|
394
|
+
throw new Error('Wrong "getNodesByChildCount" diapason');
|
|
395
|
+
}
|
|
396
|
+
if (typeof from === 'number' && from < 0) {
|
|
397
|
+
throw new Error('Wrong "from" index for "getNodesByChildCount"');
|
|
398
|
+
}
|
|
399
|
+
for (let i = 0; i < count; i += 1) {
|
|
400
|
+
const rootNode = rootNodes[i];
|
|
401
|
+
const childCount = getChildLength(rootNode);
|
|
402
|
+
// start index
|
|
403
|
+
if (index + childCount > from) {
|
|
404
|
+
if (startIndex < 0) {
|
|
405
|
+
startIndex = index;
|
|
406
|
+
}
|
|
407
|
+
nodes.push(rootNode);
|
|
408
|
+
// stop index
|
|
409
|
+
if (typeof to === 'number' && index + childCount >= to) {
|
|
410
|
+
stopIndex = index + childCount;
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
stopIndex = index + childCount;
|
|
415
|
+
index += childCount;
|
|
416
|
+
}
|
|
417
|
+
return {
|
|
418
|
+
nodes,
|
|
419
|
+
start: startIndex,
|
|
420
|
+
stop: stopIndex,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Clear tree node internal cache
|
|
425
|
+
*
|
|
426
|
+
* @param {TreeNode} node - node to clear
|
|
427
|
+
* @returns {void}
|
|
428
|
+
*/
|
|
429
|
+
export function clearNodeCache(node) {
|
|
430
|
+
if (node.isMapped !== undefined) {
|
|
431
|
+
node.isMapped = undefined;
|
|
432
|
+
}
|
|
433
|
+
if (node.minLevel !== undefined) {
|
|
434
|
+
node.minLevel = undefined;
|
|
435
|
+
}
|
|
436
|
+
if (node.childCount !== undefined) {
|
|
437
|
+
node.childCount = undefined;
|
|
438
|
+
}
|
|
439
|
+
if (node.childDeep !== undefined) {
|
|
440
|
+
node.childDeep = undefined;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Returns cut cloned part of tree nodes list according to children indexes "from" - "to"
|
|
445
|
+
*
|
|
446
|
+
* @param {Array<TreeNode>} rootNodes - list of nodes
|
|
447
|
+
* @param {number} [from=0] - start index to for cut tree
|
|
448
|
+
* @param {number} [to] - end index for cut tree
|
|
449
|
+
* @param {object} [options] - additional options
|
|
450
|
+
* @param {Array<string>} [options.cloneIncludeKeys] - clone node include keys
|
|
451
|
+
* @param {Array<string>} [options.cloneExcludeKeys] - clone node exclude keys
|
|
452
|
+
* @returns {Array<TreeNode>} - cut cloned list of nodes
|
|
453
|
+
*/
|
|
454
|
+
export function getCutNodesByChildCount(rootNodes = [], from = 0, to, options) {
|
|
455
|
+
const { cloneFn = cloneObject } = options || {};
|
|
456
|
+
const result = [];
|
|
457
|
+
const { nodes, start, stop } = getNodesByChildCount(rootNodes, from, to);
|
|
458
|
+
const count = nodes.length;
|
|
459
|
+
let firstItem;
|
|
460
|
+
let lastItem;
|
|
461
|
+
let handleLast = true;
|
|
462
|
+
if (start < from) {
|
|
463
|
+
const firstOriginalItem = nodes[0] || {};
|
|
464
|
+
const newFrom = from - start;
|
|
465
|
+
let newTo;
|
|
466
|
+
if (count === 1 && typeof to === 'number') {
|
|
467
|
+
newTo = to - start;
|
|
468
|
+
handleLast = false;
|
|
469
|
+
}
|
|
470
|
+
firstItem = cloneFn(firstOriginalItem, true);
|
|
471
|
+
const firstItemChilds = getCutNodesByChildCount(getChildren(firstOriginalItem), newFrom, newTo, options);
|
|
472
|
+
setChildren(firstItem, firstItemChilds);
|
|
473
|
+
}
|
|
474
|
+
if (typeof to === 'number' && stop > to && handleLast) {
|
|
475
|
+
const lastOriginalItem = nodes[count - 1] || {};
|
|
476
|
+
const newFrom = 0;
|
|
477
|
+
const newTo = getChildLength(lastOriginalItem) - (stop - to);
|
|
478
|
+
lastItem = cloneFn(lastOriginalItem, true);
|
|
479
|
+
const lastItemChilds = getCutNodesByChildCount(getChildren(lastOriginalItem), newFrom, newTo, options);
|
|
480
|
+
setChildren(lastItem, lastItemChilds);
|
|
481
|
+
}
|
|
482
|
+
nodes.forEach((node, index) => {
|
|
483
|
+
if (firstItem && index === 0) {
|
|
484
|
+
result.push(firstItem);
|
|
485
|
+
}
|
|
486
|
+
else if (lastItem && index === count - 1) {
|
|
487
|
+
result.push(lastItem);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
const clonedNode = cloneFn(node);
|
|
491
|
+
result.push(clonedNode);
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
return result;
|
|
495
|
+
}
|
|
496
|
+
export default {
|
|
497
|
+
ROOT,
|
|
498
|
+
create,
|
|
499
|
+
hasChildren,
|
|
500
|
+
getChildren,
|
|
501
|
+
setChildren,
|
|
502
|
+
setLevel,
|
|
503
|
+
getLevel,
|
|
504
|
+
getLastLevelNodes,
|
|
505
|
+
iterateThroughTree,
|
|
506
|
+
wrapInRootNode,
|
|
507
|
+
findNode,
|
|
508
|
+
merge,
|
|
509
|
+
deepMerge,
|
|
510
|
+
getChildLength,
|
|
511
|
+
getDeepLength,
|
|
512
|
+
getNodesByChildCount,
|
|
513
|
+
getCutNodesByChildCount,
|
|
514
|
+
clearNodeCache,
|
|
515
|
+
};
|