@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,473 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AbstractDataLoadService = void 0;
7
+ /* eslint-disable @typescript-eslint/ban-types */
8
+ const events_1 = __importDefault(require("events"));
9
+ const constants_js_1 = require("../data-handling/constants.js");
10
+ const index_js_1 = require("../utils/index.js");
11
+ const constants_js_2 = require("./constants.js");
12
+ const formattingProps = {
13
+ INCLUDE: [
14
+ 'metadata.$.jaql',
15
+ 'metadata.$.field',
16
+ 'metadata.$.panel',
17
+ 'metadata.$.hierarchies',
18
+ 'metadata.$.format',
19
+ 'metadata.$.disabled',
20
+ 'metadata.$.distinctTotals',
21
+ ],
22
+ EXCLUDE: [
23
+ 'metadata.$.jaql.title',
24
+ 'metadata.$.format.mask',
25
+ 'metadata.$.format.width',
26
+ 'queryGuid',
27
+ 'widget',
28
+ 'dashboard',
29
+ 'grandTotals.title',
30
+ ],
31
+ };
32
+ /**
33
+ * Initiate single socket connection and creates new PivotDataSource for each JAQL request
34
+ */
35
+ class AbstractDataLoadService {
36
+ constructor(events) {
37
+ /**
38
+ * @private
39
+ *
40
+ * jaql request object
41
+ */
42
+ this.jaql = undefined;
43
+ /**
44
+ * @private
45
+ *
46
+ * cache object
47
+ */
48
+ this.data = undefined;
49
+ /**
50
+ * @private
51
+ *
52
+ * state for "load" method
53
+ */
54
+ this.isLoadInProgress = false;
55
+ /**
56
+ @private */
57
+ this.loadPromiseResolve = undefined;
58
+ /**
59
+ *
60
+ * @private
61
+ */
62
+ this.loadPromiseReject = undefined;
63
+ /**
64
+ * @private
65
+ *
66
+ * info about amount of data which already loaded from cache
67
+ */
68
+ this.loadFromCacheState = undefined;
69
+ /**
70
+ @private */
71
+ this.loadFromCacheInitialTimer = undefined;
72
+ /**
73
+ @private */
74
+ this.loadFromCacheTimer = undefined;
75
+ /**
76
+ * @private
77
+ *
78
+ * defines initial pivot data structure
79
+ */
80
+ this.isSingleBranchTree = false;
81
+ /**
82
+ * @private
83
+ *
84
+ * items count loaded on client side
85
+ */
86
+ this.loadedItemsCount = 0;
87
+ /**
88
+ * @private
89
+ *
90
+ * total items count on back-end side
91
+ */
92
+ this.totalItemsCount = 0;
93
+ /**
94
+ * @private
95
+ *
96
+ * defines if amount of data was limited on back-end or not
97
+ */
98
+ this.isLimited = false;
99
+ /**
100
+ * @private
101
+ *
102
+ * detects if finish event was received
103
+ */
104
+ this.isFinishEventReceived = false;
105
+ this.events = events || new events_1.default();
106
+ }
107
+ /**
108
+ * Destroys data load service
109
+ *
110
+ * @returns {void}
111
+ */
112
+ destroy() {
113
+ this.data = undefined;
114
+ this.events.removeAllListeners();
115
+ }
116
+ /**
117
+ * Return copy of load service
118
+ *
119
+ * @returns {DataLoadService} - cloned instance
120
+ */
121
+ clone() {
122
+ throw new Error(`"AbstractDataLoadService.clone" should be overridden in subclass`);
123
+ }
124
+ /**
125
+ * Start data loading according to JAQL request
126
+ *
127
+ * @param {JaqlRequest} jaql - JAQL request
128
+ * @returns {Promise<any>} - whole data loading promise
129
+ */
130
+ load(jaql) {
131
+ if (!jaql) {
132
+ throw new Error(`AbstractDataLoadService "jaql" is not defined for "load" method`);
133
+ }
134
+ const shouldLoadFromCache = !!this.data;
135
+ const prevJaql = this.jaql;
136
+ this.jaql = jaql;
137
+ if (shouldLoadFromCache && prevJaql) {
138
+ // do not overwrite jaql queryGuid if data will be loaded from cache
139
+ // needed for sending cancel-query request with proper jaql queryGuid
140
+ this.jaql.queryGuid = prevJaql.queryGuid;
141
+ }
142
+ this.isLoadInProgress = true;
143
+ const loadPromise = new Promise((resolve, reject) => {
144
+ this.loadPromiseResolve = resolve;
145
+ this.loadPromiseReject = reject;
146
+ });
147
+ if (this.loadFromCacheInitialTimer) {
148
+ clearTimeout(this.loadFromCacheInitialTimer);
149
+ }
150
+ try {
151
+ if (shouldLoadFromCache) {
152
+ this.loadFromCache();
153
+ }
154
+ else {
155
+ this.loadFromServer();
156
+ }
157
+ }
158
+ catch (err) {
159
+ this.notifyAboutDataError(err);
160
+ }
161
+ return loadPromise;
162
+ }
163
+ /**
164
+ * Clear data cache
165
+ *
166
+ * @returns {void}
167
+ */
168
+ clear() {
169
+ this.data = undefined;
170
+ }
171
+ /**
172
+ * Returns current jaql request object
173
+ *
174
+ * @returns {JaqlRequest} - jaql request object
175
+ */
176
+ getJaql() {
177
+ return this.jaql;
178
+ }
179
+ /**
180
+ * Defines data structure
181
+ *
182
+ * @returns {boolean} - true - single branch tree
183
+ */
184
+ isSingleRowTree() {
185
+ return this.isSingleBranchTree;
186
+ }
187
+ /**
188
+ * Returns total amount items count handled on back-end side
189
+ *
190
+ * @returns {number} - items count
191
+ */
192
+ getTotalItemsCount() {
193
+ return this.totalItemsCount;
194
+ }
195
+ /**
196
+ * Defines if new jaql has only formatting changes or it requires new data loading from server
197
+ *
198
+ * @param {JaqlRequest} jaql - jaql request object
199
+ * @returns {boolean} - true - only formatting changes, can use cached data
200
+ */
201
+ isFormattingChanges(jaql) {
202
+ const currentFormatInfo = (0, index_js_1.cloneObject)(this.jaql, {
203
+ include: formattingProps.INCLUDE,
204
+ exclude: formattingProps.EXCLUDE,
205
+ excludeEmpty: true,
206
+ });
207
+ const newFormatInfo = (0, index_js_1.cloneObject)(jaql, {
208
+ include: formattingProps.INCLUDE,
209
+ exclude: formattingProps.EXCLUDE,
210
+ excludeEmpty: true,
211
+ });
212
+ [...((currentFormatInfo === null || currentFormatInfo === void 0 ? void 0 : currentFormatInfo.metadata) || []), ...((newFormatInfo === null || newFormatInfo === void 0 ? void 0 : newFormatInfo.metadata) || [])].forEach((panelItem) => {
213
+ if (panelItem && panelItem.panel === constants_js_1.PanelType.SCOPE) {
214
+ delete panelItem.field;
215
+ }
216
+ });
217
+ return JSON.stringify(currentFormatInfo) === JSON.stringify(newFormatInfo);
218
+ }
219
+ /**
220
+ * Defines if service have some data
221
+ *
222
+ * @returns {boolean} - true - has some data
223
+ */
224
+ hasData() {
225
+ return !!(this.data && this.data[constants_js_2.MessageType.DATA]);
226
+ }
227
+ /**
228
+ * Defines if service have some error
229
+ *
230
+ * @returns {boolean} - true - has some error
231
+ */
232
+ hasError() {
233
+ if (this.data) {
234
+ return !!this.data[constants_js_2.MessageType.ERROR];
235
+ }
236
+ return false;
237
+ }
238
+ /**
239
+ * Start data loading from the server
240
+ *
241
+ * @returns {void}
242
+ * @private
243
+ */
244
+ loadFromServer() {
245
+ throw new Error(`"AbstractDataLoadService.loadFromServer" should be overridden in subclass`);
246
+ }
247
+ /**
248
+ * Method for canceling the processing of query already sent
249
+ *
250
+ * @returns {Promise<void>} - waiting promise
251
+ */
252
+ cancelQuery() {
253
+ const error = new Error(`"AbstractDataLoadService.cancelQuery" should be overridden in subclass.`);
254
+ return Promise.reject(error);
255
+ }
256
+ /**
257
+ * Method for detection if cancel query is still needed
258
+ *
259
+ * @returns {boolean} - is cancel query needed
260
+ */
261
+ isCancelQueryNeeded() {
262
+ return !this.isFinishEventReceived;
263
+ }
264
+ /**
265
+ * Start data loading from the cache
266
+ *
267
+ * @returns {Promise<void>} - waiting promise
268
+ * @private
269
+ */
270
+ loadFromCache() {
271
+ return Promise.resolve()
272
+ .then(() => {
273
+ if (this.loadFromCacheInitialTimer) {
274
+ clearTimeout(this.loadFromCacheInitialTimer);
275
+ }
276
+ return new Promise((resolve) => {
277
+ this.loadFromCacheInitialTimer = setTimeout(resolve);
278
+ // eslint-disable-next-line max-lines
279
+ });
280
+ })
281
+ .then(() => new Promise((resolve) => {
282
+ if (this.loadFromCacheTimer) {
283
+ clearImmediate(this.loadFromCacheTimer);
284
+ }
285
+ this.loadFromCacheState = undefined;
286
+ this.loadMessageFromCache(() => {
287
+ this.loadFromCacheState = undefined;
288
+ if (this.loadFromCacheTimer) {
289
+ clearImmediate(this.loadFromCacheTimer);
290
+ }
291
+ resolve();
292
+ });
293
+ }));
294
+ }
295
+ /**
296
+ * Starts loading data from cache queue
297
+ *
298
+ * @param {Function} onFinish - on finish callback
299
+ * @returns {void}
300
+ * @private
301
+ */
302
+ loadMessageFromCache(onFinish) {
303
+ // Note: removed `setImmediate` as not supported
304
+ this.loadFromCacheState = this.loadFromCacheState || {};
305
+ const state = this.loadFromCacheState;
306
+ let typeToSend = '';
307
+ let indexToSend = 0;
308
+ constants_js_2.MESSAGES_ORDER.forEach((type) => {
309
+ if (typeToSend) {
310
+ return;
311
+ }
312
+ state[type] = state[type] || 0;
313
+ const loadedCount = state[type];
314
+ if (loadedCount < ((this.data || {})[type] || []).length) {
315
+ typeToSend = type;
316
+ indexToSend = state[type];
317
+ }
318
+ });
319
+ if (typeToSend) {
320
+ const payload = ((this.data || {})[typeToSend] || [])[indexToSend];
321
+ this.notifyAboutDataChunk(typeToSend || '', payload, true);
322
+ state[typeToSend] = indexToSend + 1;
323
+ this.loadMessageFromCache(onFinish);
324
+ }
325
+ else if (onFinish) {
326
+ onFinish();
327
+ }
328
+ }
329
+ /**
330
+ * Cache appropriate message
331
+ *
332
+ * @param {string} type - message type
333
+ * @param {any} data - message payload
334
+ * @returns {void}
335
+ * @private
336
+ */
337
+ cacheData(type, data) {
338
+ this.data = this.data || {};
339
+ const cache = this.data;
340
+ if (!cache) {
341
+ return;
342
+ }
343
+ cache[type] = cache[type] || [];
344
+ cache[type].push(data || true);
345
+ }
346
+ /*
347
+ *
348
+ * @private
349
+ */
350
+ /**
351
+ * Notify outside about data chunk with saving to inner cache, applying chunk formatting with
352
+ * saving initial messages queue
353
+ *
354
+ * @param {string} type - data chunk type
355
+ * @param {any} chunk - data chunk data
356
+ * @param {boolean} isFromCache - mark data which already was cached
357
+ * @returns {void}
358
+ * @private
359
+ */
360
+ // eslint-disable-next-line sonarjs/cognitive-complexity
361
+ notifyAboutDataChunk(type, chunk, isFromCache = false) {
362
+ // console.log('notifyAboutDataChunk', type, chunk, isFromCache);
363
+ const data = chunk && chunk.data && type === constants_js_2.MessageType.DATA ? chunk.data : chunk;
364
+ if (!isFromCache) {
365
+ this.cacheData(type, chunk);
366
+ }
367
+ if (!isFromCache && this.loadFromCacheState) {
368
+ // if load original data but new loading from cache started
369
+ return;
370
+ }
371
+ if (type === constants_js_2.MessageType.METADATA) {
372
+ this.isSingleBranchTree = !!(data && data.isSingleBranchTree);
373
+ }
374
+ if (type === constants_js_2.MessageType.ERROR) {
375
+ this.notifyAboutDataError(data);
376
+ }
377
+ if (type === constants_js_2.MessageType.DATA_FINISH) {
378
+ this.loadedItemsCount = data ? data.rowsCount : 0;
379
+ this.notifyAboutDataLoaded(this.data);
380
+ }
381
+ if (type === constants_js_2.MessageType.TOTAL_ROWS) {
382
+ this.totalItemsCount = data ? data.rowsCount : 0;
383
+ if (this.totalItemsCount !== this.loadedItemsCount) {
384
+ this.isLimited = true;
385
+ }
386
+ }
387
+ if (type === constants_js_2.MessageType.FINISH) {
388
+ this.isFinishEventReceived = true;
389
+ }
390
+ const clonedData = (0, index_js_1.cloneObject)(data);
391
+ this.events.emit(type, clonedData);
392
+ }
393
+ /**
394
+ * Resolve "load" method with appropriate data information
395
+ *
396
+ * @param {any} data - data to resolve with
397
+ * @returns {void}
398
+ * @private
399
+ */
400
+ notifyAboutDataLoaded(data) {
401
+ if (!this.isLoadInProgress) {
402
+ return;
403
+ }
404
+ this.isLoadInProgress = false;
405
+ if (typeof this.loadPromiseResolve === 'function') {
406
+ this.loadPromiseResolve(data);
407
+ }
408
+ this.loadPromiseReject = undefined;
409
+ this.loadPromiseResolve = undefined;
410
+ }
411
+ /**
412
+ * Reject "load" method with appropriate data information
413
+ *
414
+ * @param {any} data - data to reject with
415
+ * @returns {void}
416
+ * @private
417
+ */
418
+ notifyAboutDataError(data) {
419
+ if (!this.isLoadInProgress) {
420
+ return;
421
+ }
422
+ this.isLoadInProgress = false;
423
+ if (typeof this.loadPromiseReject === 'function') {
424
+ this.loadPromiseReject(data);
425
+ }
426
+ this.loadPromiseReject = undefined;
427
+ this.loadPromiseResolve = undefined;
428
+ }
429
+ /**
430
+ * Subscribe to event notification
431
+ *
432
+ * @param {string} eventName - event name to subscribe
433
+ * @param {Function} callback - event handler
434
+ * @returns {void}
435
+ */
436
+ on(eventName, callback) {
437
+ this.events.on(eventName, callback);
438
+ }
439
+ /**
440
+ * Unsubscribe from event notification
441
+ *
442
+ * @param {string} eventName - event name to unsubscribe
443
+ * @param {Function} callback - event handler
444
+ * @returns {void}
445
+ */
446
+ off(eventName, callback) {
447
+ this.events.removeListener(eventName, callback);
448
+ }
449
+ /**
450
+ * Unsubscribe from all event notifications
451
+ *
452
+ * @param {string} eventName - event name to unsubscribe
453
+ * @returns {void}
454
+ */
455
+ offAll(eventName) {
456
+ this.events.removeAllListeners(eventName);
457
+ }
458
+ listenerCount(eventName) {
459
+ return this.events.listenerCount(eventName);
460
+ }
461
+ /**
462
+ * Trigger event notification
463
+ *
464
+ * @param {string} eventName - event name to subscribe
465
+ * @param {Array<any>} rest - arguments will be passed to event handler
466
+ * @returns {void}
467
+ */
468
+ emit(eventName, ...rest) {
469
+ this.events.emit(eventName, ...rest);
470
+ }
471
+ }
472
+ exports.AbstractDataLoadService = AbstractDataLoadService;
473
+ exports.default = AbstractDataLoadService;
@@ -0,0 +1,63 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import EventEmitter from 'events';
3
+ import { AbstractDataLoadService } from './AbstractDataLoadService.js';
4
+ import { DataLoadServiceI, SocketI } from './types.js';
5
+ export declare class DataLoadService extends AbstractDataLoadService implements DataLoadServiceI {
6
+ /**
7
+ * @private
8
+ *
9
+ * Active WebSocket connection instance
10
+ */
11
+ socket: SocketI;
12
+ /**
13
+ * @private
14
+ *
15
+ * WebSocket initialization delay promise
16
+ */
17
+ initPromise?: Promise<void>;
18
+ /**
19
+ *
20
+ * @private
21
+ *
22
+ * WebSocket initialization ready flag
23
+ */
24
+ isInitInProgress: boolean;
25
+ /**
26
+ *
27
+ * @private
28
+ *
29
+ * onMessage remove listeners callback
30
+ */
31
+ onMessageCancel?: Function;
32
+ constructor(socket?: SocketI, events?: EventEmitter);
33
+ destroy(): void;
34
+ /**
35
+ * Return copy of load service
36
+ *
37
+ * @returns {DataLoadService} - cloned instance
38
+ */
39
+ clone(): DataLoadServiceI;
40
+ /**
41
+ * Start data loading from the server
42
+ *
43
+ * @returns {void}
44
+ * @private
45
+ */
46
+ loadFromServer(): void;
47
+ /**
48
+ * Method for canceling the processing of query already sent
49
+ *
50
+ * @returns {Promise<void>} - waiting promise
51
+ */
52
+ cancelQuery(): Promise<void>;
53
+ /**
54
+ * Wait for socket connection
55
+ *
56
+ * @returns {Promise<void>} - wait promise
57
+ * @private
58
+ */
59
+ waitForSocketReady(): Promise<void>;
60
+ onSocketError: (error: Error) => void;
61
+ onSocketDisconnect: () => void;
62
+ }
63
+ export default DataLoadService;
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataLoadService = void 0;
4
+ const index_js_1 = require("../utils/index.js");
5
+ const AbstractDataLoadService_js_1 = require("./AbstractDataLoadService.js");
6
+ const constants_js_1 = require("./constants.js");
7
+ class DataLoadService extends AbstractDataLoadService_js_1.AbstractDataLoadService {
8
+ constructor(socket, events) {
9
+ super(events);
10
+ /**
11
+ * @private
12
+ *
13
+ * WebSocket initialization delay promise
14
+ */
15
+ this.initPromise = undefined;
16
+ /**
17
+ *
18
+ * @private
19
+ *
20
+ * WebSocket initialization ready flag
21
+ */
22
+ this.isInitInProgress = false;
23
+ /**
24
+ *
25
+ * @private
26
+ *
27
+ * onMessage remove listeners callback
28
+ */
29
+ this.onMessageCancel = undefined;
30
+ this.onSocketError = (error) => {
31
+ this.emit('error', {
32
+ error: true,
33
+ type: 500,
34
+ details: `Socket error: ${error.message}`,
35
+ });
36
+ };
37
+ this.onSocketDisconnect = () => {
38
+ this.emit('error', {
39
+ error: true,
40
+ type: 500,
41
+ details: 'Socket disconnected',
42
+ });
43
+ };
44
+ if (!socket) {
45
+ throw new Error(`DataLoadService "socket" not defined.`);
46
+ }
47
+ this.socket = socket;
48
+ this.socket.on('error', this.onSocketError);
49
+ this.socket.on('disconnect', this.onSocketDisconnect);
50
+ this.on(constants_js_1.MessageType.ERROR, (data) => {
51
+ const errorMsg = JSON.stringify(data, null, 4);
52
+ if (process.env.NODE_ENV !== 'production') {
53
+ // eslint-disable-next-line no-console
54
+ console.warn(`DataLoadService error message: \n${errorMsg}`);
55
+ }
56
+ });
57
+ }
58
+ destroy() {
59
+ super.destroy();
60
+ if (this.onMessageCancel) {
61
+ this.onMessageCancel();
62
+ this.onMessageCancel = undefined;
63
+ }
64
+ // removed because of duplication of cancel-query request
65
+ // this.cancelQuery();
66
+ this.socket.off('error', this.onSocketError);
67
+ this.socket.off('disconnect', this.onSocketDisconnect);
68
+ }
69
+ /**
70
+ * Return copy of load service
71
+ *
72
+ * @returns {DataLoadService} - cloned instance
73
+ */
74
+ clone() {
75
+ const data = (0, index_js_1.cloneObject)(this.data);
76
+ // restore empty headers object
77
+ if (!data[constants_js_1.MessageType.HEADERS]) {
78
+ data[constants_js_1.MessageType.HEADERS] = [{}];
79
+ }
80
+ const instance = new DataLoadService(this.socket);
81
+ instance.data = data;
82
+ instance.jaql = this.jaql;
83
+ instance.isFinishEventReceived = this.isFinishEventReceived;
84
+ instance.isSingleBranchTree = this.isSingleBranchTree;
85
+ instance.loadedItemsCount = this.loadedItemsCount;
86
+ instance.totalItemsCount = this.totalItemsCount;
87
+ instance.isLimited = this.isLimited;
88
+ return instance;
89
+ }
90
+ /**
91
+ * Start data loading from the server
92
+ *
93
+ * @returns {void}
94
+ * @private
95
+ */
96
+ loadFromServer() {
97
+ // eslint-disable-next-line promise/catch-or-return
98
+ this.waitForSocketReady().then(() => {
99
+ if (this.onMessageCancel) {
100
+ this.onMessageCancel();
101
+ }
102
+ this.onMessageCancel = this.socket.onMessage(undefined, undefined, (type, data) => {
103
+ this.notifyAboutDataChunk(type, data);
104
+ });
105
+ this.socket.send('pivot', this.jaql);
106
+ });
107
+ }
108
+ /**
109
+ * Method for canceling the processing of query already sent
110
+ *
111
+ * @returns {Promise<void>} - waiting promise
112
+ */
113
+ cancelQuery() {
114
+ if (!this.isCancelQueryNeeded()) {
115
+ return Promise.resolve();
116
+ }
117
+ return this.waitForSocketReady().then(() => {
118
+ this.socket.send('pivot/cancel-query', {
119
+ // eslint-disable-next-line promise/always-return
120
+ queryGuid: this.jaql && this.jaql.queryGuid,
121
+ });
122
+ });
123
+ }
124
+ /**
125
+ * Wait for socket connection
126
+ *
127
+ * @returns {Promise<void>} - wait promise
128
+ * @private
129
+ */
130
+ waitForSocketReady() {
131
+ if (this.socket.isReady()) {
132
+ return Promise.resolve();
133
+ }
134
+ if (this.isInitInProgress && this.initPromise) {
135
+ return this.initPromise;
136
+ }
137
+ this.isInitInProgress = true;
138
+ this.initPromise = new Promise((resolve, reject) => {
139
+ this.socket.on('open', () => {
140
+ if (this.socket && this.socket.isReady()) {
141
+ resolve();
142
+ }
143
+ else {
144
+ reject(new Error('Can not open WebSocket connection'));
145
+ }
146
+ });
147
+ });
148
+ return this.initPromise;
149
+ }
150
+ }
151
+ exports.DataLoadService = DataLoadService;
152
+ exports.default = DataLoadService;