@vuu-ui/vuu-data-remote 2.1.19-beta.1 → 2.1.19-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -10
- package/src/ConnectionManager.js +134 -0
- package/src/DedicatedWorker.js +44 -0
- package/src/LostConnectionHandler.js +89 -0
- package/src/VuuAuthProvider.js +78 -0
- package/src/VuuAuthenticator.js +36 -0
- package/src/VuuDataSource.js +514 -0
- package/src/WebSocketConnection.js +149 -0
- package/src/authenticate.js +50 -0
- package/src/constants.js +45 -0
- package/src/data-source.js +57 -0
- package/src/index.js +11 -0
- package/src/message-utils.js +44 -0
- package/src/server-proxy/array-backed-moving-window.js +172 -0
- package/src/server-proxy/messages.js +34 -0
- package/src/server-proxy/server-proxy.js +808 -0
- package/src/server-proxy/viewport.js +591 -0
- package/src/worker.js +65 -0
|
@@ -0,0 +1,808 @@
|
|
|
1
|
+
import { hasViewPortContext, isCreateVpSuccess, isErrorMessage, isOpenDialogAction, isRpcServiceRequest, isSelectRequest, isSessionTable, isSessionTableActionMessage, isViewportMessage, isVisualLinkMessage, isVuuMenuRpcRequest, logger, partition } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { createSchemaFromTableMetadata, groupRowsByViewport, hasRequestId, stripRequestId } from "../message-utils.js";
|
|
3
|
+
import { NO_DATA_UPDATE, Viewport } from "./viewport.js";
|
|
4
|
+
import { isLoginRejectedMessage } from "../WebSocketConnection.js";
|
|
5
|
+
import * as __rspack_external__messages_js_85065717 from "./messages.js";
|
|
6
|
+
let _requestId = 1;
|
|
7
|
+
const TEST_setRequestId = (id)=>_requestId = id;
|
|
8
|
+
const { debug: debug, debugEnabled: debugEnabled, error: server_proxy_error, info: info, infoEnabled: infoEnabled, warn: warn } = logger("ServerProxy");
|
|
9
|
+
const nextRequestId = ()=>`${_requestId++}`;
|
|
10
|
+
const DEFAULT_OPTIONS = {};
|
|
11
|
+
const isActiveViewport = (viewPort)=>true !== viewPort.disabled && true !== viewPort.suspended;
|
|
12
|
+
const addTitleToLinks = (links, serverViewportId, label)=>links.map((link)=>link.parentVpId === serverViewportId ? {
|
|
13
|
+
...link,
|
|
14
|
+
label
|
|
15
|
+
} : link);
|
|
16
|
+
function addLabelsToLinks(links, viewports) {
|
|
17
|
+
return links.map((linkDescriptor)=>{
|
|
18
|
+
const { parentVpId } = linkDescriptor;
|
|
19
|
+
const viewport = viewports.get(parentVpId);
|
|
20
|
+
if (viewport) return {
|
|
21
|
+
...linkDescriptor,
|
|
22
|
+
parentClientVpId: viewport.clientViewportId,
|
|
23
|
+
label: viewport.title
|
|
24
|
+
};
|
|
25
|
+
throw Error("addLabelsToLinks viewport not found");
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
class ServerProxy {
|
|
29
|
+
connection;
|
|
30
|
+
postMessageToClient;
|
|
31
|
+
viewports;
|
|
32
|
+
mapClientToServerViewport;
|
|
33
|
+
authToken = "";
|
|
34
|
+
pendingLogin;
|
|
35
|
+
pendingRequests = new Map();
|
|
36
|
+
sessionId;
|
|
37
|
+
queuedRequests = [];
|
|
38
|
+
cachedTableMetaRequests = new Map();
|
|
39
|
+
cachedTableSchemas = new Map();
|
|
40
|
+
tableList;
|
|
41
|
+
constructor(connection, callback){
|
|
42
|
+
this.connection = connection;
|
|
43
|
+
this.postMessageToClient = callback;
|
|
44
|
+
this.viewports = new Map();
|
|
45
|
+
this.mapClientToServerViewport = new Map();
|
|
46
|
+
connection.on("connection-status", this.connectionStatusChanged);
|
|
47
|
+
}
|
|
48
|
+
connectionStatusChanged = (status)=>{
|
|
49
|
+
if ("disconnected" === status) {
|
|
50
|
+
this.sessionId = void 0;
|
|
51
|
+
this.clearAllViewports();
|
|
52
|
+
} else if ("reconnected" === status) this.reconnect();
|
|
53
|
+
};
|
|
54
|
+
reconnect = async ()=>{
|
|
55
|
+
const [activeViewports, inactiveViewports] = partition(Array.from(this.viewports.values()), isActiveViewport);
|
|
56
|
+
this.viewports.clear();
|
|
57
|
+
this.mapClientToServerViewport.clear();
|
|
58
|
+
const reconnectViewports = (viewports)=>{
|
|
59
|
+
viewports.forEach((viewport)=>{
|
|
60
|
+
const { clientViewportId } = viewport;
|
|
61
|
+
this.awaitResponseToMessage(viewport.subscribe(), clientViewportId).then((msg)=>{
|
|
62
|
+
if ("CREATE_VP_SUCCESS" === msg.type) {
|
|
63
|
+
this.mapClientToServerViewport.set(clientViewportId, msg.viewPortId);
|
|
64
|
+
this.viewports.set(msg.viewPortId, viewport);
|
|
65
|
+
viewport.status = "subscribed";
|
|
66
|
+
viewport.serverViewportId = msg.viewPortId;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
reconnectViewports(activeViewports);
|
|
72
|
+
setTimeout(()=>{
|
|
73
|
+
reconnectViewports(inactiveViewports);
|
|
74
|
+
}, 2000);
|
|
75
|
+
};
|
|
76
|
+
async login(authToken) {
|
|
77
|
+
if (authToken) {
|
|
78
|
+
this.authToken = authToken;
|
|
79
|
+
return new Promise((resolve, reject)=>{
|
|
80
|
+
this.sendMessageToServer({
|
|
81
|
+
type: "LOGIN",
|
|
82
|
+
token: this.authToken
|
|
83
|
+
}, "");
|
|
84
|
+
this.pendingLogin = {
|
|
85
|
+
resolve,
|
|
86
|
+
reject
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if ("" === this.authToken) server_proxy_error("login, cannot login until auth token has been obtained");
|
|
91
|
+
}
|
|
92
|
+
clearAllViewports() {
|
|
93
|
+
this.viewports.forEach((viewport)=>{
|
|
94
|
+
viewport.clearCache();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
disconnect() {
|
|
98
|
+
this.viewports.forEach((viewport)=>{
|
|
99
|
+
const { clientViewportId } = viewport;
|
|
100
|
+
this.unsubscribe(clientViewportId);
|
|
101
|
+
this.postMessageToClient({
|
|
102
|
+
clientViewportId,
|
|
103
|
+
type: "viewport-clear"
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async subscribe(message) {
|
|
108
|
+
if (this.mapClientToServerViewport.has(message.viewport)) server_proxy_error(`spurious subscribe call ${message.viewport}`);
|
|
109
|
+
else {
|
|
110
|
+
const pendingTableSchema = this.getTableMeta(message.table);
|
|
111
|
+
const viewport = new Viewport(message, this.postMessageToClient);
|
|
112
|
+
this.viewports.set(message.viewport, viewport);
|
|
113
|
+
const pendingSubscription = this.awaitResponseToMessage(viewport.subscribe(), message.viewport);
|
|
114
|
+
const [subscribeResponse, tableSchema] = await Promise.all([
|
|
115
|
+
pendingSubscription,
|
|
116
|
+
pendingTableSchema
|
|
117
|
+
]);
|
|
118
|
+
if (isErrorMessage(tableSchema)) this.postMessageToClient({
|
|
119
|
+
clientViewportId: message.viewport,
|
|
120
|
+
type: "subscribe-failed",
|
|
121
|
+
msg: `failed to fetch schema for table ${message.table.table}: ${tableSchema.msg}`
|
|
122
|
+
});
|
|
123
|
+
else if (isCreateVpSuccess(subscribeResponse)) {
|
|
124
|
+
const { viewPortId: serverViewportId } = subscribeResponse;
|
|
125
|
+
const { status: previousViewportStatus } = viewport;
|
|
126
|
+
if (message.viewport !== serverViewportId) {
|
|
127
|
+
this.viewports.delete(message.viewport);
|
|
128
|
+
this.viewports.set(serverViewportId, viewport);
|
|
129
|
+
}
|
|
130
|
+
this.mapClientToServerViewport.set(message.viewport, serverViewportId);
|
|
131
|
+
const clientResponse = viewport.handleSubscribed(subscribeResponse, tableSchema);
|
|
132
|
+
if (clientResponse) {
|
|
133
|
+
this.postMessageToClient(clientResponse);
|
|
134
|
+
if (debugEnabled) debug(`post DataSourceSubscribedMessage to client: ${JSON.stringify(clientResponse)}`);
|
|
135
|
+
}
|
|
136
|
+
if (viewport.disabled) this.disableViewport(viewport);
|
|
137
|
+
if (this.queuedRequests.length > 0) this.processQueuedRequests();
|
|
138
|
+
if ("subscribing" === previousViewportStatus && !isSessionTable(viewport.table)) {
|
|
139
|
+
this.sendMessageToServer({
|
|
140
|
+
type: __rspack_external__messages_js_85065717.GET_VP_VISUAL_LINKS,
|
|
141
|
+
vpId: serverViewportId
|
|
142
|
+
});
|
|
143
|
+
this.sendMessageToServer({
|
|
144
|
+
type: __rspack_external__messages_js_85065717.GET_VIEW_PORT_MENUS,
|
|
145
|
+
vpId: serverViewportId
|
|
146
|
+
});
|
|
147
|
+
Array.from(this.viewports.entries()).filter(([id, { disabled, status }])=>id !== serverViewportId && !disabled && "subscribed" === status).forEach(([vpId])=>{
|
|
148
|
+
this.sendMessageToServer({
|
|
149
|
+
type: __rspack_external__messages_js_85065717.GET_VP_VISUAL_LINKS,
|
|
150
|
+
vpId
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
} else this.postMessageToClient({
|
|
155
|
+
clientViewportId: message.viewport,
|
|
156
|
+
type: "subscribe-failed",
|
|
157
|
+
msg: `failed to open subscription on table ${message.table.table}: ${subscribeResponse.msg}`
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
addRequestToQueue(queuedRequest) {
|
|
162
|
+
const isDifferentTypeViewport = (qr)=>qr.clientViewportId !== queuedRequest.clientViewportId || queuedRequest.message.type !== qr.message.type;
|
|
163
|
+
if (!this.queuedRequests.every(isDifferentTypeViewport)) this.queuedRequests = this.queuedRequests.filter(isDifferentTypeViewport);
|
|
164
|
+
this.queuedRequests.push(queuedRequest);
|
|
165
|
+
}
|
|
166
|
+
processQueuedRequests() {
|
|
167
|
+
const newQueue = [];
|
|
168
|
+
for (const queuedRequest of this.queuedRequests){
|
|
169
|
+
const { clientViewportId, message, requestId } = queuedRequest;
|
|
170
|
+
const serverViewportId = this.mapClientToServerViewport.get(clientViewportId);
|
|
171
|
+
if (serverViewportId) this.sendMessageToServer({
|
|
172
|
+
...message,
|
|
173
|
+
viewPortId: serverViewportId
|
|
174
|
+
}, requestId);
|
|
175
|
+
else if (this.viewports.has(clientViewportId)) newQueue.push(queuedRequest);
|
|
176
|
+
else console.warn(`ServerProxy processQueuedRequests, ${message.type} request not found ${clientViewportId}`);
|
|
177
|
+
}
|
|
178
|
+
this.queuedRequests = newQueue;
|
|
179
|
+
}
|
|
180
|
+
unsubscribe(clientViewportId) {
|
|
181
|
+
const serverViewportId = this.mapClientToServerViewport.get(clientViewportId);
|
|
182
|
+
if (serverViewportId) {
|
|
183
|
+
info?.(`Unsubscribe Message (Client to Server):
|
|
184
|
+
${serverViewportId}`);
|
|
185
|
+
this.sendMessageToServer({
|
|
186
|
+
type: __rspack_external__messages_js_85065717.REMOVE_VP,
|
|
187
|
+
viewPortId: serverViewportId
|
|
188
|
+
});
|
|
189
|
+
} else server_proxy_error(`failed to unsubscribe client viewport ${clientViewportId}, viewport not found`);
|
|
190
|
+
}
|
|
191
|
+
getViewportForClient(clientViewportId, throws = true) {
|
|
192
|
+
const serverViewportId = this.mapClientToServerViewport.get(clientViewportId);
|
|
193
|
+
if (serverViewportId) {
|
|
194
|
+
const viewport = this.viewports.get(serverViewportId);
|
|
195
|
+
if (viewport) return viewport;
|
|
196
|
+
if (!throws) return null;
|
|
197
|
+
throw Error(`Viewport not found for client viewport ${clientViewportId}`);
|
|
198
|
+
}
|
|
199
|
+
if (this.viewports.has(clientViewportId)) return this.viewports.get(clientViewportId);
|
|
200
|
+
if (!throws) return null;
|
|
201
|
+
throw Error(`Viewport server id not found for client viewport ${clientViewportId}`);
|
|
202
|
+
}
|
|
203
|
+
setViewRange(viewport, message) {
|
|
204
|
+
const requestId = nextRequestId();
|
|
205
|
+
infoEnabled && info(`setViewRange (${message.range.from}:${message.range.to})`);
|
|
206
|
+
const [serverRequest, rows, debounceRequest] = viewport.rangeRequest(requestId, message.range);
|
|
207
|
+
if ("subscribed" === viewport.status) {
|
|
208
|
+
info?.(`setViewRange ${message.range.from} - ${message.range.to}`);
|
|
209
|
+
if (serverRequest) {
|
|
210
|
+
if ("development" === process.env.NODE_ENV) info?.(`CHANGE_VP_RANGE (${message.range.from}-${message.range.to}) => (${serverRequest.from}-${serverRequest.to})`);
|
|
211
|
+
infoEnabled && info(`setViewRange send CHANGE_VP_RANGE<#${requestId}> (${serverRequest.from}-${serverRequest.to})`);
|
|
212
|
+
this.sendMessageToServer(serverRequest, requestId);
|
|
213
|
+
}
|
|
214
|
+
if (rows) {
|
|
215
|
+
info?.(`setViewRange ${rows.length} rows returned from cache`);
|
|
216
|
+
this.postMessageToClient({
|
|
217
|
+
mode: "update",
|
|
218
|
+
type: "viewport-update",
|
|
219
|
+
clientViewportId: viewport.clientViewportId,
|
|
220
|
+
range: message.range,
|
|
221
|
+
rows
|
|
222
|
+
});
|
|
223
|
+
} else if (debounceRequest) this.postMessageToClient(debounceRequest);
|
|
224
|
+
} else if (serverRequest) this.addRequestToQueue({
|
|
225
|
+
clientViewportId: message.viewport,
|
|
226
|
+
message: serverRequest,
|
|
227
|
+
requestId
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
setConfig(viewport, message) {
|
|
231
|
+
const requestId = nextRequestId();
|
|
232
|
+
const request = viewport.setConfig(requestId, message.config);
|
|
233
|
+
this.sendIfReady(request, requestId, "subscribed" === viewport.status);
|
|
234
|
+
}
|
|
235
|
+
setTitle(viewport, message) {
|
|
236
|
+
if (viewport) {
|
|
237
|
+
viewport.title = message.title;
|
|
238
|
+
this.updateTitleOnVisualLinks(viewport);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
select(viewport, message) {
|
|
242
|
+
const [requestId, selectRequest] = stripRequestId(message);
|
|
243
|
+
const request = viewport.selectRequest(selectRequest);
|
|
244
|
+
this.sendMessageToServer(request, requestId);
|
|
245
|
+
}
|
|
246
|
+
disableAllActiveViewports() {
|
|
247
|
+
console.log("[ServerProxy] disableAllActiveViewports");
|
|
248
|
+
this.viewports.forEach((vp)=>{
|
|
249
|
+
if (isActiveViewport(vp)) this.disableViewport(vp, true);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
enableAllActiveViewports() {
|
|
253
|
+
this.viewports.forEach((vp)=>{
|
|
254
|
+
if (vp.disabledActive) this.enableViewport(vp);
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
disableViewport(viewport, disableActive = false) {
|
|
258
|
+
const requestId = nextRequestId();
|
|
259
|
+
const request = viewport.disable(requestId, disableActive);
|
|
260
|
+
this.sendIfReady(request, requestId, "subscribed" === viewport.status);
|
|
261
|
+
}
|
|
262
|
+
enableViewport(viewport) {
|
|
263
|
+
if (viewport.disabled) {
|
|
264
|
+
const requestId = nextRequestId();
|
|
265
|
+
const request = viewport.enable(requestId);
|
|
266
|
+
this.sendIfReady(request, requestId, "subscribed" === viewport.status);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
freezeViewport(viewport) {
|
|
270
|
+
const requestId = nextRequestId();
|
|
271
|
+
const request = viewport.freeze(requestId);
|
|
272
|
+
this.sendIfReady(request, requestId, "subscribed" === viewport.status);
|
|
273
|
+
}
|
|
274
|
+
unfreezeViewport(viewport) {
|
|
275
|
+
if (viewport.frozen) {
|
|
276
|
+
const requestId = nextRequestId();
|
|
277
|
+
const request = viewport.unfreeze(requestId);
|
|
278
|
+
this.sendIfReady(request, requestId, "subscribed" === viewport.status);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
suspendViewport(viewport, escalateToDisable = true, escalateDelay = 3000) {
|
|
282
|
+
viewport.suspend();
|
|
283
|
+
if (escalateToDisable) viewport.suspendTimer = setTimeout(()=>{
|
|
284
|
+
info?.("suspendTimer expired, escalate suspend to disable");
|
|
285
|
+
this.disableViewport(viewport);
|
|
286
|
+
}, escalateDelay);
|
|
287
|
+
}
|
|
288
|
+
resumeViewport(viewport) {
|
|
289
|
+
if (viewport.suspendTimer) {
|
|
290
|
+
debug?.("clear suspend timer");
|
|
291
|
+
clearTimeout(viewport.suspendTimer);
|
|
292
|
+
viewport.suspendTimer = null;
|
|
293
|
+
}
|
|
294
|
+
const [size, rows] = viewport.resume();
|
|
295
|
+
debug?.(`resumeViewport size ${size}, ${rows.length} rows sent to client`);
|
|
296
|
+
this.postMessageToClient({
|
|
297
|
+
clientViewportId: viewport.clientViewportId,
|
|
298
|
+
mode: "update",
|
|
299
|
+
rows,
|
|
300
|
+
size,
|
|
301
|
+
type: "viewport-update"
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
openTreeNode(viewport, message) {
|
|
305
|
+
if (viewport.serverViewportId) {
|
|
306
|
+
const requestId = nextRequestId();
|
|
307
|
+
this.sendIfReady(viewport.openTreeNode(requestId, message), requestId, "subscribed" === viewport.status);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
closeTreeNode(viewport, message) {
|
|
311
|
+
if (viewport.serverViewportId) {
|
|
312
|
+
const requestId = nextRequestId();
|
|
313
|
+
this.sendIfReady(viewport.closeTreeNode(requestId, message), requestId, "subscribed" === viewport.status);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
createLink(viewport, message) {
|
|
317
|
+
const [requestId, visualLinkRequest] = stripRequestId(message);
|
|
318
|
+
const parentVpId = this.mapClientToServerViewport.get(message.parentVpId);
|
|
319
|
+
if (parentVpId) {
|
|
320
|
+
const request = viewport.createLink(requestId, {
|
|
321
|
+
...visualLinkRequest,
|
|
322
|
+
parentVpId
|
|
323
|
+
});
|
|
324
|
+
this.sendMessageToServer(request, requestId);
|
|
325
|
+
} else throw Error(`createLink parent viewport not found ${message.parentVpId}`);
|
|
326
|
+
}
|
|
327
|
+
removeLink(viewport, message) {
|
|
328
|
+
const { requestId } = message;
|
|
329
|
+
const request = viewport.removeLink(requestId);
|
|
330
|
+
this.sendMessageToServer(request, requestId);
|
|
331
|
+
}
|
|
332
|
+
updateTitleOnVisualLinks(viewport) {
|
|
333
|
+
const { serverViewportId, title } = viewport;
|
|
334
|
+
for (const vp of this.viewports.values())if (vp !== viewport && vp.links && serverViewportId && title) {
|
|
335
|
+
if (vp.links?.some((link)=>link.parentVpId === serverViewportId)) {
|
|
336
|
+
const [messageToClient] = vp.setLinks(addTitleToLinks(vp.links, serverViewportId, title));
|
|
337
|
+
this.postMessageToClient(messageToClient);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
removeViewportFromVisualLinks(serverViewportId) {
|
|
342
|
+
for (const vp of this.viewports.values())if (vp.links?.some(({ parentVpId })=>parentVpId === serverViewportId)) {
|
|
343
|
+
const [messageToClient] = vp.setLinks(vp.links.filter(({ parentVpId })=>parentVpId !== serverViewportId));
|
|
344
|
+
this.postMessageToClient(messageToClient);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
menuRpcCall(message) {
|
|
348
|
+
const viewport = this.getViewportForClient(message.vpId, false);
|
|
349
|
+
if (viewport?.serverViewportId) {
|
|
350
|
+
const [requestId, rpcRequest] = stripRequestId(message);
|
|
351
|
+
this.sendMessageToServer({
|
|
352
|
+
...rpcRequest,
|
|
353
|
+
vpId: viewport.serverViewportId
|
|
354
|
+
}, requestId);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
rpcRequest(message) {
|
|
358
|
+
if (hasViewPortContext(message)) {
|
|
359
|
+
const viewport = this.getViewportForClient(message.context.viewPortId, false);
|
|
360
|
+
if (viewport?.serverViewportId) {
|
|
361
|
+
const [requestId, rpcRequest] = stripRequestId(message);
|
|
362
|
+
this.sendMessageToServer({
|
|
363
|
+
...rpcRequest,
|
|
364
|
+
context: {
|
|
365
|
+
type: "VIEWPORT_CONTEXT",
|
|
366
|
+
viewPortId: viewport.serverViewportId
|
|
367
|
+
}
|
|
368
|
+
}, requestId);
|
|
369
|
+
}
|
|
370
|
+
} else throw Error("[ServerProxy] rpcRequest only supports VIEWPORT_CONTEXT at present");
|
|
371
|
+
}
|
|
372
|
+
handleMessageFromClient(message) {
|
|
373
|
+
if (isViewportMessage(message) || isVisualLinkMessage(message)) if ("disable" === message.type) {
|
|
374
|
+
const viewport = this.getViewportForClient(message.viewport, false);
|
|
375
|
+
if (null !== viewport) return this.disableViewport(viewport);
|
|
376
|
+
return;
|
|
377
|
+
} else {
|
|
378
|
+
const viewport = isVisualLinkMessage(message) ? this.getViewportForClient(message.childVpId) : this.getViewportForClient(message.viewport);
|
|
379
|
+
switch(message.type){
|
|
380
|
+
case "setViewRange":
|
|
381
|
+
return this.setViewRange(viewport, message);
|
|
382
|
+
case "config":
|
|
383
|
+
return this.setConfig(viewport, message);
|
|
384
|
+
case "suspend":
|
|
385
|
+
{
|
|
386
|
+
const { escalateToDisable, escalateDelay } = message;
|
|
387
|
+
return this.suspendViewport(viewport, escalateToDisable, escalateDelay);
|
|
388
|
+
}
|
|
389
|
+
case "resume":
|
|
390
|
+
return this.resumeViewport(viewport);
|
|
391
|
+
case "enable":
|
|
392
|
+
return this.enableViewport(viewport);
|
|
393
|
+
case "FREEZE_VP":
|
|
394
|
+
return this.freezeViewport(viewport);
|
|
395
|
+
case "UNFREEZE_VP":
|
|
396
|
+
return this.unfreezeViewport(viewport);
|
|
397
|
+
case "openTreeNode":
|
|
398
|
+
return this.openTreeNode(viewport, message);
|
|
399
|
+
case "closeTreeNode":
|
|
400
|
+
return this.closeTreeNode(viewport, message);
|
|
401
|
+
case "CREATE_VISUAL_LINK":
|
|
402
|
+
return this.createLink(viewport, message);
|
|
403
|
+
case "REMOVE_VISUAL_LINK":
|
|
404
|
+
return this.removeLink(viewport, message);
|
|
405
|
+
case "setTitle":
|
|
406
|
+
return this.setTitle(viewport, message);
|
|
407
|
+
default:
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (isSelectRequest(message)) if (hasRequestId(message)) {
|
|
411
|
+
const viewport = this.getViewportForClient(message.vpId);
|
|
412
|
+
return this.select(viewport, message);
|
|
413
|
+
} else console.warn("selectRequest must have requestId");
|
|
414
|
+
else {
|
|
415
|
+
if (isRpcServiceRequest(message)) return this.rpcRequest(message);
|
|
416
|
+
if (isVuuMenuRpcRequest(message)) return this.menuRpcCall(message);
|
|
417
|
+
if ("disconnect" === message.type) return this.disconnect();
|
|
418
|
+
if ("disable-all-active" === message.type) return this.disableAllActiveViewports();
|
|
419
|
+
if ("enable-all-active" === message.type) return this.enableAllActiveViewports();
|
|
420
|
+
const { type, requestId } = message;
|
|
421
|
+
switch(type){
|
|
422
|
+
case "GET_TABLE_LIST":
|
|
423
|
+
this.tableList ??= this.awaitResponseToMessage({
|
|
424
|
+
type
|
|
425
|
+
}, requestId);
|
|
426
|
+
this.tableList.then((response)=>{
|
|
427
|
+
this.postMessageToClient({
|
|
428
|
+
type: "TABLE_LIST_RESP",
|
|
429
|
+
tables: response.tables,
|
|
430
|
+
requestId
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
return;
|
|
434
|
+
case "GET_TABLE_META":
|
|
435
|
+
return void this.getTableMeta(message.table, requestId).then((tableSchema)=>{
|
|
436
|
+
if (isErrorMessage(tableSchema)) ;
|
|
437
|
+
else if (tableSchema) this.postMessageToClient({
|
|
438
|
+
type: "TABLE_META_RESP",
|
|
439
|
+
tableSchema,
|
|
440
|
+
requestId
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
default:
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
server_proxy_error(`Vuu ServerProxy Unexpected message from client ${JSON.stringify(message)}`);
|
|
447
|
+
}
|
|
448
|
+
getTableMeta(table, requestId = nextRequestId()) {
|
|
449
|
+
if (isSessionTable(table)) return this.awaitResponseToMessage({
|
|
450
|
+
type: "GET_TABLE_META",
|
|
451
|
+
table
|
|
452
|
+
}, requestId).then((resp)=>isErrorMessage(resp) ? resp : createSchemaFromTableMetadata(resp));
|
|
453
|
+
const key = `${table.module}:${table.table}`;
|
|
454
|
+
let tableMetaRequest = this.cachedTableMetaRequests.get(key);
|
|
455
|
+
if (!tableMetaRequest) {
|
|
456
|
+
tableMetaRequest = this.awaitResponseToMessage({
|
|
457
|
+
type: "GET_TABLE_META",
|
|
458
|
+
table
|
|
459
|
+
}, requestId);
|
|
460
|
+
this.cachedTableMetaRequests.set(key, tableMetaRequest);
|
|
461
|
+
}
|
|
462
|
+
return tableMetaRequest?.then((response)=>{
|
|
463
|
+
if (isErrorMessage(response)) return response;
|
|
464
|
+
return this.cacheTableMeta(response);
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
awaitResponseToMessage(message, requestId = nextRequestId()) {
|
|
468
|
+
return new Promise((resolve, reject)=>{
|
|
469
|
+
this.sendMessageToServer(message, requestId);
|
|
470
|
+
this.pendingRequests.set(requestId, {
|
|
471
|
+
reject,
|
|
472
|
+
resolve
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
sendIfReady(message, requestId, isReady = true) {
|
|
477
|
+
if (isReady) this.sendMessageToServer(message, requestId);
|
|
478
|
+
return isReady;
|
|
479
|
+
}
|
|
480
|
+
sendMessageToServer(body, requestId = `${_requestId++}`, options = DEFAULT_OPTIONS) {
|
|
481
|
+
const { module = "CORE" } = options;
|
|
482
|
+
if (this.authToken) this.connection.send({
|
|
483
|
+
requestId,
|
|
484
|
+
sessionId: this.sessionId,
|
|
485
|
+
module,
|
|
486
|
+
body
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
handleMessageFromServer(message) {
|
|
490
|
+
if (isLoginRejectedMessage(message)) {
|
|
491
|
+
if (this.pendingLogin) {
|
|
492
|
+
this.pendingLogin.reject(message.reason);
|
|
493
|
+
this.pendingLogin = void 0;
|
|
494
|
+
this.authToken = "";
|
|
495
|
+
}
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const { body, requestId, sessionId } = message;
|
|
499
|
+
const pendingRequest = this.pendingRequests.get(requestId);
|
|
500
|
+
if (pendingRequest) {
|
|
501
|
+
const { resolve } = pendingRequest;
|
|
502
|
+
this.pendingRequests.delete(requestId);
|
|
503
|
+
resolve(body);
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
const { viewports } = this;
|
|
507
|
+
switch(body.type){
|
|
508
|
+
case __rspack_external__messages_js_85065717.HB:
|
|
509
|
+
this.sendMessageToServer({
|
|
510
|
+
type: __rspack_external__messages_js_85065717.HB_RESP,
|
|
511
|
+
ts: +new Date()
|
|
512
|
+
}, "NA");
|
|
513
|
+
break;
|
|
514
|
+
case "LOGIN_SUCCESS":
|
|
515
|
+
if (sessionId) {
|
|
516
|
+
this.sessionId = sessionId;
|
|
517
|
+
this.pendingLogin?.resolve(sessionId);
|
|
518
|
+
this.pendingLogin = void 0;
|
|
519
|
+
this.postMessageToClient({
|
|
520
|
+
...body,
|
|
521
|
+
sessionId
|
|
522
|
+
});
|
|
523
|
+
} else throw Error("LOGIN_SUCCESS did not provide sessionId");
|
|
524
|
+
break;
|
|
525
|
+
case "REMOVE_VP_SUCCESS":
|
|
526
|
+
{
|
|
527
|
+
const viewport = viewports.get(body.viewPortId);
|
|
528
|
+
if (viewport) {
|
|
529
|
+
this.mapClientToServerViewport.delete(viewport.clientViewportId);
|
|
530
|
+
viewports.delete(body.viewPortId);
|
|
531
|
+
this.removeViewportFromVisualLinks(body.viewPortId);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
break;
|
|
535
|
+
case "SELECT_ALL_SUCCESS":
|
|
536
|
+
case "SELECT_ROW_SUCCESS":
|
|
537
|
+
case "SELECT_ROW_RANGE_SUCCESS":
|
|
538
|
+
case "DESELECT_ROW_SUCCESS":
|
|
539
|
+
{
|
|
540
|
+
const { type, selectedRowCount } = body;
|
|
541
|
+
this.postMessageToClient({
|
|
542
|
+
requestId,
|
|
543
|
+
type,
|
|
544
|
+
selectedRowCount
|
|
545
|
+
});
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
case "DESELECT_ALL_SUCCESS":
|
|
549
|
+
{
|
|
550
|
+
const { type } = body;
|
|
551
|
+
this.postMessageToClient({
|
|
552
|
+
requestId,
|
|
553
|
+
type,
|
|
554
|
+
selectedRowCount: 0
|
|
555
|
+
});
|
|
556
|
+
break;
|
|
557
|
+
}
|
|
558
|
+
case "SELECT_ROW_REJECT":
|
|
559
|
+
case "DESELECT_ROW_REJECT":
|
|
560
|
+
case "SELECT_ROW_RANGE_REJECT":
|
|
561
|
+
case "SELECT_ALL_REJECT":
|
|
562
|
+
case "DESELECT_ALL_REJECT":
|
|
563
|
+
console.warn(`select error ${body.type} ${body.errorMsg}`);
|
|
564
|
+
break;
|
|
565
|
+
case __rspack_external__messages_js_85065717.CHANGE_VP_SUCCESS:
|
|
566
|
+
case __rspack_external__messages_js_85065717.DISABLE_VP_SUCCESS:
|
|
567
|
+
if (viewports.has(body.viewPortId)) {
|
|
568
|
+
const viewport = this.viewports.get(body.viewPortId);
|
|
569
|
+
if (viewport) {
|
|
570
|
+
const response = viewport.completeOperation(requestId);
|
|
571
|
+
if (void 0 !== response) {
|
|
572
|
+
this.postMessageToClient(response);
|
|
573
|
+
if (debugEnabled) debug(`postMessageToClient ${JSON.stringify(response)}`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
break;
|
|
578
|
+
case __rspack_external__messages_js_85065717.ENABLE_VP_SUCCESS:
|
|
579
|
+
{
|
|
580
|
+
const viewport = this.viewports.get(body.viewPortId);
|
|
581
|
+
if (viewport) {
|
|
582
|
+
const response = viewport.completeOperation(requestId);
|
|
583
|
+
if (response) {
|
|
584
|
+
this.postMessageToClient(response);
|
|
585
|
+
const [size, rows] = viewport.resume();
|
|
586
|
+
this.postMessageToClient({
|
|
587
|
+
clientViewportId: viewport.clientViewportId,
|
|
588
|
+
mode: "update",
|
|
589
|
+
rows,
|
|
590
|
+
size,
|
|
591
|
+
type: "viewport-update"
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
break;
|
|
597
|
+
case "FREEZE_VP_SUCCESS":
|
|
598
|
+
{
|
|
599
|
+
const viewport = this.viewports.get(body.viewPortId);
|
|
600
|
+
if (viewport) {
|
|
601
|
+
const response = viewport.completeOperation(requestId);
|
|
602
|
+
if (response) this.postMessageToClient(response);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
break;
|
|
606
|
+
case "UNFREEZE_VP_SUCCESS":
|
|
607
|
+
{
|
|
608
|
+
const viewport = this.viewports.get(body.viewPortId);
|
|
609
|
+
if (viewport) {
|
|
610
|
+
const response = viewport.completeOperation(requestId);
|
|
611
|
+
if (response) this.postMessageToClient(response);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
break;
|
|
615
|
+
case "TABLE_ROW":
|
|
616
|
+
{
|
|
617
|
+
const viewportRowMap = groupRowsByViewport(body.rows);
|
|
618
|
+
if ("development" === process.env.NODE_ENV && debugEnabled) {
|
|
619
|
+
const [firstRow] = body.rows;
|
|
620
|
+
if (0 === body.rows.length) infoEnabled && info("<=== TABLE_ROW 0 rows");
|
|
621
|
+
else if (firstRow?.rowIndex === -1) if (1 === body.rows.length) if ("SIZE" === firstRow.updateType) infoEnabled && info(`<=== [${firstRow.viewPortId}] TABLE_ROW SIZE ONLY ${firstRow.vpSize}`);
|
|
622
|
+
else infoEnabled && info(`<=== [${firstRow.viewPortId}] TABLE_ROW SIZE ${firstRow.vpSize} rowIdx ${firstRow.rowIndex}`);
|
|
623
|
+
else infoEnabled && info(`<=== TABLE_ROW ${body.rows.length} rows, SIZE ${firstRow.vpSize}, [${body.rows.map((r)=>r.rowIndex).join(",")}]`);
|
|
624
|
+
else infoEnabled && info(`<=== TABLE_ROW ${body.rows.length} rows [${body.rows.map((r)=>r.rowIndex).join(",")}]`);
|
|
625
|
+
}
|
|
626
|
+
for (const [viewportId, rows] of Object.entries(viewportRowMap)){
|
|
627
|
+
const viewport = viewports.get(viewportId);
|
|
628
|
+
if (viewport) viewport.updateRows(rows);
|
|
629
|
+
else warn?.(`TABLE_ROW message received for non registered viewport ${viewportId}`);
|
|
630
|
+
}
|
|
631
|
+
this.processUpdates();
|
|
632
|
+
}
|
|
633
|
+
break;
|
|
634
|
+
case "CHANGE_VP_RANGE_SUCCESS":
|
|
635
|
+
{
|
|
636
|
+
const viewport = this.viewports.get(body.viewPortId);
|
|
637
|
+
if (viewport) {
|
|
638
|
+
const { from, to } = body;
|
|
639
|
+
infoEnabled && info(`<=== CHANGE_VP_RANGE_SUCCESS<#${requestId}> ${from} - ${to}`);
|
|
640
|
+
viewport.completeOperation(requestId, from, to);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
break;
|
|
644
|
+
case __rspack_external__messages_js_85065717.OPEN_TREE_SUCCESS:
|
|
645
|
+
case __rspack_external__messages_js_85065717.CLOSE_TREE_SUCCESS:
|
|
646
|
+
break;
|
|
647
|
+
case "CREATE_VISUAL_LINK_SUCCESS":
|
|
648
|
+
{
|
|
649
|
+
const viewport = this.viewports.get(body.childVpId);
|
|
650
|
+
const parentViewport = this.viewports.get(body.parentVpId);
|
|
651
|
+
if (viewport && parentViewport) {
|
|
652
|
+
const { childColumnName, parentColumnName } = body;
|
|
653
|
+
const response = viewport.completeOperation(requestId, childColumnName, parentViewport.clientViewportId, parentColumnName);
|
|
654
|
+
if (response) this.postMessageToClient(response);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
break;
|
|
658
|
+
case "REMOVE_VISUAL_LINK_SUCCESS":
|
|
659
|
+
{
|
|
660
|
+
const viewport = this.viewports.get(body.childVpId);
|
|
661
|
+
if (viewport) {
|
|
662
|
+
const response = viewport.completeOperation(requestId);
|
|
663
|
+
if (response) this.postMessageToClient(response);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
break;
|
|
667
|
+
case "VP_VISUAL_LINKS_RESP":
|
|
668
|
+
{
|
|
669
|
+
const activeLinkDescriptors = this.getActiveLinks(body.links);
|
|
670
|
+
const viewport = this.viewports.get(body.vpId);
|
|
671
|
+
if (activeLinkDescriptors.length && viewport) {
|
|
672
|
+
const linkDescriptorsWithLabels = addLabelsToLinks(activeLinkDescriptors, this.viewports);
|
|
673
|
+
const [clientMessage, pendingLink] = viewport.setLinks(linkDescriptorsWithLabels);
|
|
674
|
+
this.postMessageToClient(clientMessage);
|
|
675
|
+
if (pendingLink) {
|
|
676
|
+
const { link, parentClientVpId } = pendingLink;
|
|
677
|
+
const requestId = nextRequestId();
|
|
678
|
+
const parentVpId = this.mapClientToServerViewport.get(parentClientVpId);
|
|
679
|
+
if (parentVpId) {
|
|
680
|
+
const message = viewport.createLink(requestId, {
|
|
681
|
+
childVpId: body.vpId,
|
|
682
|
+
childColumnName: link.fromColumn,
|
|
683
|
+
parentColumnName: link.toColumn,
|
|
684
|
+
parentVpId,
|
|
685
|
+
type: "CREATE_VISUAL_LINK"
|
|
686
|
+
});
|
|
687
|
+
this.sendMessageToServer(message, requestId);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
break;
|
|
693
|
+
case "VIEW_PORT_MENUS_RESP":
|
|
694
|
+
if (body.menu?.name) {
|
|
695
|
+
const viewport = this.viewports.get(body.vpId);
|
|
696
|
+
if (viewport) {
|
|
697
|
+
const clientMessage = viewport.setMenu(body.menu);
|
|
698
|
+
this.postMessageToClient(clientMessage);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
break;
|
|
702
|
+
case "VIEW_PORT_MENU_REJ":
|
|
703
|
+
{
|
|
704
|
+
const { error, rpcName, vpId } = body;
|
|
705
|
+
const viewport = this.viewports.get(vpId);
|
|
706
|
+
if (viewport) this.postMessageToClient({
|
|
707
|
+
clientViewportId: viewport.clientViewportId,
|
|
708
|
+
error,
|
|
709
|
+
rpcName,
|
|
710
|
+
type: "VIEW_PORT_MENU_REJ",
|
|
711
|
+
requestId
|
|
712
|
+
});
|
|
713
|
+
break;
|
|
714
|
+
}
|
|
715
|
+
case "VIEW_PORT_MENU_RESP":
|
|
716
|
+
if (isSessionTableActionMessage(body)) {
|
|
717
|
+
const { action, rpcName } = body;
|
|
718
|
+
this.awaitResponseToMessage({
|
|
719
|
+
type: "GET_TABLE_META",
|
|
720
|
+
table: action.table
|
|
721
|
+
}).then((response)=>{
|
|
722
|
+
const tableSchema = createSchemaFromTableMetadata(response);
|
|
723
|
+
this.postMessageToClient({
|
|
724
|
+
rpcName,
|
|
725
|
+
type: "VIEW_PORT_MENU_RESP",
|
|
726
|
+
action: {
|
|
727
|
+
...action,
|
|
728
|
+
tableSchema
|
|
729
|
+
},
|
|
730
|
+
tableAlreadyOpen: this.isTableOpen(action.table),
|
|
731
|
+
requestId
|
|
732
|
+
});
|
|
733
|
+
});
|
|
734
|
+
} else {
|
|
735
|
+
const { action, rpcName } = body;
|
|
736
|
+
this.postMessageToClient({
|
|
737
|
+
action,
|
|
738
|
+
rpcName,
|
|
739
|
+
requestId,
|
|
740
|
+
tableAlreadyOpen: isOpenDialogAction(action) && this.isTableOpen(action.table),
|
|
741
|
+
type: "VIEW_PORT_MENU_RESP"
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
break;
|
|
745
|
+
case "RPC_RESPONSE":
|
|
746
|
+
{
|
|
747
|
+
const { action, error, result } = body;
|
|
748
|
+
this.postMessageToClient({
|
|
749
|
+
action,
|
|
750
|
+
type: "RPC_RESPONSE",
|
|
751
|
+
error,
|
|
752
|
+
result,
|
|
753
|
+
requestId
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
break;
|
|
757
|
+
case "ERROR":
|
|
758
|
+
server_proxy_error(body.msg);
|
|
759
|
+
break;
|
|
760
|
+
default:
|
|
761
|
+
infoEnabled && info(`<=== ${body["type"]}.`);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
cacheTableMeta(messageBody) {
|
|
765
|
+
const { module, table } = messageBody.table;
|
|
766
|
+
const key = `${module}:${table}`;
|
|
767
|
+
let tableSchema = this.cachedTableSchemas.get(key);
|
|
768
|
+
if (!tableSchema) {
|
|
769
|
+
tableSchema = createSchemaFromTableMetadata(messageBody);
|
|
770
|
+
this.cachedTableSchemas.set(key, tableSchema);
|
|
771
|
+
}
|
|
772
|
+
return tableSchema;
|
|
773
|
+
}
|
|
774
|
+
isTableOpen(table) {
|
|
775
|
+
if (table) {
|
|
776
|
+
const tableName = table.table;
|
|
777
|
+
for (const viewport of this.viewports.values())if (!viewport.suspended && viewport.table.table === tableName) return true;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
getActiveLinks(linkDescriptors) {
|
|
781
|
+
return linkDescriptors.filter((linkDescriptor)=>{
|
|
782
|
+
const viewport = this.viewports.get(linkDescriptor.parentVpId);
|
|
783
|
+
return viewport && !viewport.suspended;
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
processUpdates() {
|
|
787
|
+
this.viewports.forEach((viewport)=>{
|
|
788
|
+
if (viewport.hasUpdatesToProcess) {
|
|
789
|
+
const result = viewport.getClientRows();
|
|
790
|
+
if (result !== NO_DATA_UPDATE) {
|
|
791
|
+
const [rows, mode] = result;
|
|
792
|
+
const size = viewport.getNewRowCount();
|
|
793
|
+
if (void 0 !== size || rows && rows.length > 0) {
|
|
794
|
+
debugEnabled && debug(`===> #${viewport.clientViewportId} viewport-update ${mode}, ${rows?.length ?? "no"} rows, size ${size}`);
|
|
795
|
+
if (mode) this.postMessageToClient({
|
|
796
|
+
clientViewportId: viewport.clientViewportId,
|
|
797
|
+
mode,
|
|
798
|
+
rows,
|
|
799
|
+
size,
|
|
800
|
+
type: "viewport-update"
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
export { ServerProxy, TEST_setRequestId };
|