@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,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;
|