@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.
Files changed (189) hide show
  1. package/LICENSE.md +35 -0
  2. package/README.md +2 -0
  3. package/dist/__test-helpers__/testUtils.d.ts +30 -0
  4. package/dist/__test-helpers__/testUtils.js +89 -0
  5. package/dist/builders/index.d.ts +2 -0
  6. package/dist/builders/index.js +2 -0
  7. package/dist/builders/pivot-data-builder.d.ts +34 -0
  8. package/dist/builders/pivot-data-builder.js +182 -0
  9. package/dist/builders/socket-builder.d.ts +18 -0
  10. package/dist/builders/socket-builder.js +72 -0
  11. package/dist/cjs/__test-helpers__/testUtils.d.ts +30 -0
  12. package/dist/cjs/__test-helpers__/testUtils.js +104 -0
  13. package/dist/cjs/builders/index.d.ts +2 -0
  14. package/dist/cjs/builders/index.js +7 -0
  15. package/dist/cjs/builders/pivot-data-builder.d.ts +34 -0
  16. package/dist/cjs/builders/pivot-data-builder.js +186 -0
  17. package/dist/cjs/builders/socket-builder.d.ts +18 -0
  18. package/dist/cjs/builders/socket-builder.js +79 -0
  19. package/dist/cjs/data-handling/DataService.d.ts +672 -0
  20. package/dist/cjs/data-handling/DataService.js +1364 -0
  21. package/dist/cjs/data-handling/DivergenceComparator.d.ts +7 -0
  22. package/dist/cjs/data-handling/DivergenceComparator.js +20 -0
  23. package/dist/cjs/data-handling/constants.d.ts +44 -0
  24. package/dist/cjs/data-handling/constants.js +43 -0
  25. package/dist/cjs/data-handling/index.d.ts +3 -0
  26. package/dist/cjs/data-handling/index.js +23 -0
  27. package/dist/cjs/data-handling/types.d.ts +104 -0
  28. package/dist/cjs/data-handling/types.js +2 -0
  29. package/dist/cjs/data-handling/utils/createPivotTreeNode.d.ts +13 -0
  30. package/dist/cjs/data-handling/utils/createPivotTreeNode.js +21 -0
  31. package/dist/cjs/data-handling/utils/index.d.ts +4 -0
  32. package/dist/cjs/data-handling/utils/index.js +14 -0
  33. package/dist/cjs/data-handling/utils/jaqlProcessor.d.ts +122 -0
  34. package/dist/cjs/data-handling/utils/jaqlProcessor.js +661 -0
  35. package/dist/cjs/data-handling/utils/pivotTransforms.d.ts +74 -0
  36. package/dist/cjs/data-handling/utils/pivotTransforms.js +373 -0
  37. package/dist/cjs/data-handling/utils/plugins/PluginService.d.ts +135 -0
  38. package/dist/cjs/data-handling/utils/plugins/PluginService.js +383 -0
  39. package/dist/cjs/data-handling/utils/plugins/getters.d.ts +23 -0
  40. package/dist/cjs/data-handling/utils/plugins/getters.js +70 -0
  41. package/dist/cjs/data-handling/utils/plugins/types.d.ts +75 -0
  42. package/dist/cjs/data-handling/utils/plugins/types.js +2 -0
  43. package/dist/cjs/data-handling/utils/plugins/validator.d.ts +13 -0
  44. package/dist/cjs/data-handling/utils/plugins/validator.js +169 -0
  45. package/dist/cjs/data-load/AbstractDataLoadService.d.ts +256 -0
  46. package/dist/cjs/data-load/AbstractDataLoadService.js +473 -0
  47. package/dist/cjs/data-load/DataLoadService.d.ts +63 -0
  48. package/dist/cjs/data-load/DataLoadService.js +152 -0
  49. package/dist/cjs/data-load/SisenseDataLoadService.d.ts +44 -0
  50. package/dist/cjs/data-load/SisenseDataLoadService.js +87 -0
  51. package/dist/cjs/data-load/TestDataLoadService.d.ts +27 -0
  52. package/dist/cjs/data-load/TestDataLoadService.js +76 -0
  53. package/dist/cjs/data-load/constants.d.ts +13 -0
  54. package/dist/cjs/data-load/constants.js +28 -0
  55. package/dist/cjs/data-load/index.d.ts +6 -0
  56. package/dist/cjs/data-load/index.js +14 -0
  57. package/dist/cjs/data-load/sockets/SisenseSocket.d.ts +81 -0
  58. package/dist/cjs/data-load/sockets/SisenseSocket.js +162 -0
  59. package/dist/cjs/data-load/sockets/TestSocket.d.ts +61 -0
  60. package/dist/cjs/data-load/sockets/TestSocket.js +90 -0
  61. package/dist/cjs/data-load/sockets/helpers.d.ts +4 -0
  62. package/dist/cjs/data-load/sockets/helpers.js +27 -0
  63. package/dist/cjs/data-load/sockets/index.d.ts +2 -0
  64. package/dist/cjs/data-load/sockets/index.js +8 -0
  65. package/dist/cjs/data-load/types.d.ts +90 -0
  66. package/dist/cjs/data-load/types.js +2 -0
  67. package/dist/cjs/errors/LoadingCanceledError.d.ts +7 -0
  68. package/dist/cjs/errors/LoadingCanceledError.js +24 -0
  69. package/dist/cjs/errors/index.d.ts +1 -0
  70. package/dist/cjs/errors/index.js +6 -0
  71. package/dist/cjs/index.d.ts +17 -0
  72. package/dist/cjs/index.js +32 -0
  73. package/dist/cjs/package.json +12 -0
  74. package/dist/cjs/pivot-query-client.d.ts +13 -0
  75. package/dist/cjs/pivot-query-client.js +26 -0
  76. package/dist/cjs/tree-structure/AbstractTreeService.d.ts +308 -0
  77. package/dist/cjs/tree-structure/AbstractTreeService.js +716 -0
  78. package/dist/cjs/tree-structure/HeaderTreeService.d.ts +180 -0
  79. package/dist/cjs/tree-structure/HeaderTreeService.js +280 -0
  80. package/dist/cjs/tree-structure/TreeCellMap.d.ts +104 -0
  81. package/dist/cjs/tree-structure/TreeCellMap.js +145 -0
  82. package/dist/cjs/tree-structure/TreeService.d.ts +8 -0
  83. package/dist/cjs/tree-structure/TreeService.js +12 -0
  84. package/dist/cjs/tree-structure/constants.d.ts +6 -0
  85. package/dist/cjs/tree-structure/constants.js +10 -0
  86. package/dist/cjs/tree-structure/index.d.ts +5 -0
  87. package/dist/cjs/tree-structure/index.js +10 -0
  88. package/dist/cjs/tree-structure/types.d.ts +93 -0
  89. package/dist/cjs/tree-structure/types.js +2 -0
  90. package/dist/cjs/tree-structure/utils/index.d.ts +1 -0
  91. package/dist/cjs/tree-structure/utils/index.js +9 -0
  92. package/dist/cjs/tree-structure/utils/treeNode.d.ts +147 -0
  93. package/dist/cjs/tree-structure/utils/treeNode.js +534 -0
  94. package/dist/cjs/utils/array.d.ts +13 -0
  95. package/dist/cjs/utils/array.js +25 -0
  96. package/dist/cjs/utils/cloneObject.d.ts +30 -0
  97. package/dist/cjs/utils/cloneObject.js +225 -0
  98. package/dist/cjs/utils/index.d.ts +3 -0
  99. package/dist/cjs/utils/index.js +9 -0
  100. package/dist/cjs/utils/throttle.d.ts +12 -0
  101. package/dist/cjs/utils/throttle.js +39 -0
  102. package/dist/cjs/utils/types.d.ts +12 -0
  103. package/dist/cjs/utils/types.js +2 -0
  104. package/dist/data-handling/DataService.d.ts +672 -0
  105. package/dist/data-handling/DataService.js +1357 -0
  106. package/dist/data-handling/DivergenceComparator.d.ts +7 -0
  107. package/dist/data-handling/DivergenceComparator.js +16 -0
  108. package/dist/data-handling/constants.d.ts +44 -0
  109. package/dist/data-handling/constants.js +40 -0
  110. package/dist/data-handling/index.d.ts +3 -0
  111. package/dist/data-handling/index.js +4 -0
  112. package/dist/data-handling/types.d.ts +104 -0
  113. package/dist/data-handling/types.js +1 -0
  114. package/dist/data-handling/utils/createPivotTreeNode.d.ts +13 -0
  115. package/dist/data-handling/utils/createPivotTreeNode.js +17 -0
  116. package/dist/data-handling/utils/index.d.ts +4 -0
  117. package/dist/data-handling/utils/index.js +4 -0
  118. package/dist/data-handling/utils/jaqlProcessor.d.ts +122 -0
  119. package/dist/data-handling/utils/jaqlProcessor.js +621 -0
  120. package/dist/data-handling/utils/pivotTransforms.d.ts +74 -0
  121. package/dist/data-handling/utils/pivotTransforms.js +335 -0
  122. package/dist/data-handling/utils/plugins/PluginService.d.ts +135 -0
  123. package/dist/data-handling/utils/plugins/PluginService.js +379 -0
  124. package/dist/data-handling/utils/plugins/getters.d.ts +23 -0
  125. package/dist/data-handling/utils/plugins/getters.js +65 -0
  126. package/dist/data-handling/utils/plugins/types.d.ts +75 -0
  127. package/dist/data-handling/utils/plugins/types.js +1 -0
  128. package/dist/data-handling/utils/plugins/validator.d.ts +13 -0
  129. package/dist/data-handling/utils/plugins/validator.js +165 -0
  130. package/dist/data-load/AbstractDataLoadService.d.ts +256 -0
  131. package/dist/data-load/AbstractDataLoadService.js +466 -0
  132. package/dist/data-load/DataLoadService.d.ts +63 -0
  133. package/dist/data-load/DataLoadService.js +148 -0
  134. package/dist/data-load/SisenseDataLoadService.d.ts +44 -0
  135. package/dist/data-load/SisenseDataLoadService.js +83 -0
  136. package/dist/data-load/TestDataLoadService.d.ts +27 -0
  137. package/dist/data-load/TestDataLoadService.js +69 -0
  138. package/dist/data-load/constants.d.ts +13 -0
  139. package/dist/data-load/constants.js +25 -0
  140. package/dist/data-load/index.d.ts +6 -0
  141. package/dist/data-load/index.js +6 -0
  142. package/dist/data-load/sockets/SisenseSocket.d.ts +81 -0
  143. package/dist/data-load/sockets/SisenseSocket.js +155 -0
  144. package/dist/data-load/sockets/TestSocket.d.ts +61 -0
  145. package/dist/data-load/sockets/TestSocket.js +83 -0
  146. package/dist/data-load/sockets/helpers.d.ts +4 -0
  147. package/dist/data-load/sockets/helpers.js +23 -0
  148. package/dist/data-load/sockets/index.d.ts +2 -0
  149. package/dist/data-load/sockets/index.js +3 -0
  150. package/dist/data-load/types.d.ts +90 -0
  151. package/dist/data-load/types.js +1 -0
  152. package/dist/errors/LoadingCanceledError.d.ts +7 -0
  153. package/dist/errors/LoadingCanceledError.js +20 -0
  154. package/dist/errors/index.d.ts +1 -0
  155. package/dist/errors/index.js +2 -0
  156. package/dist/index.d.ts +17 -0
  157. package/dist/index.js +9 -0
  158. package/dist/pivot-query-client.d.ts +13 -0
  159. package/dist/pivot-query-client.js +22 -0
  160. package/dist/tree-structure/AbstractTreeService.d.ts +308 -0
  161. package/dist/tree-structure/AbstractTreeService.js +712 -0
  162. package/dist/tree-structure/HeaderTreeService.d.ts +180 -0
  163. package/dist/tree-structure/HeaderTreeService.js +276 -0
  164. package/dist/tree-structure/TreeCellMap.d.ts +104 -0
  165. package/dist/tree-structure/TreeCellMap.js +141 -0
  166. package/dist/tree-structure/TreeService.d.ts +8 -0
  167. package/dist/tree-structure/TreeService.js +8 -0
  168. package/dist/tree-structure/constants.d.ts +6 -0
  169. package/dist/tree-structure/constants.js +7 -0
  170. package/dist/tree-structure/index.d.ts +5 -0
  171. package/dist/tree-structure/index.js +4 -0
  172. package/dist/tree-structure/types.d.ts +93 -0
  173. package/dist/tree-structure/types.js +1 -0
  174. package/dist/tree-structure/utils/index.d.ts +1 -0
  175. package/dist/tree-structure/utils/index.js +1 -0
  176. package/dist/tree-structure/utils/treeNode.d.ts +147 -0
  177. package/dist/tree-structure/utils/treeNode.js +515 -0
  178. package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
  179. package/dist/utils/array.d.ts +13 -0
  180. package/dist/utils/array.js +21 -0
  181. package/dist/utils/cloneObject.d.ts +30 -0
  182. package/dist/utils/cloneObject.js +221 -0
  183. package/dist/utils/index.d.ts +3 -0
  184. package/dist/utils/index.js +3 -0
  185. package/dist/utils/throttle.d.ts +12 -0
  186. package/dist/utils/throttle.js +35 -0
  187. package/dist/utils/types.d.ts +12 -0
  188. package/dist/utils/types.js +1 -0
  189. 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
+ };