@genesislcap/foundation-comms 15.7.1 → 15.7.2-FUI-2595.1
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/dist/dts/connect/socket.d.ts +4 -0
- package/dist/dts/connect/socket.d.ts.map +1 -1
- package/dist/dts/connect/socket.types.d.ts +8 -0
- package/dist/dts/connect/socket.types.d.ts.map +1 -1
- package/dist/esm/connect/socket.js +74 -23
- package/dist/foundation-comms.api.json +1 -1
- package/dist/foundation-comms.d.ts +12 -0
- package/package.json +14 -14
|
@@ -114,6 +114,7 @@ export declare class DefaultSocket implements Socket {
|
|
|
114
114
|
protected config: ConnectConfig;
|
|
115
115
|
private readonly defaultInterval;
|
|
116
116
|
private readonly secondsMultiplier;
|
|
117
|
+
private readonly heartbeatTimeoutMultiplier;
|
|
117
118
|
private websocket;
|
|
118
119
|
private wsMessages;
|
|
119
120
|
private wsMessageHandlers;
|
|
@@ -134,6 +135,7 @@ export declare class DefaultSocket implements Socket {
|
|
|
134
135
|
private heartbeatIsEnabled;
|
|
135
136
|
private heartbeatInterval;
|
|
136
137
|
private heartbeatTicker;
|
|
138
|
+
private connectionEpoch;
|
|
137
139
|
private url;
|
|
138
140
|
private connectOptions;
|
|
139
141
|
private reconnectOptions;
|
|
@@ -156,7 +158,9 @@ export declare class DefaultSocket implements Socket {
|
|
|
156
158
|
private handleCookieBasedReauth;
|
|
157
159
|
private updateSessionAndSubscriptions;
|
|
158
160
|
private prepareHeartbeat;
|
|
161
|
+
private sendHeartbeat;
|
|
159
162
|
private reconnect;
|
|
163
|
+
private forceReconnect;
|
|
160
164
|
reset(): void;
|
|
161
165
|
private cleanMessages;
|
|
162
166
|
send<T>(message: Message<T | any>, needsHandling?: boolean): Promise<Message | any>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../../src/connect/socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAsB,cAAc,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAGzF,OAAO,EAAE,UAAU,EAAgB,OAAO,EAAE,YAAY,EAAc,MAAM,MAAM,CAAC;AAGnF,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAEL,OAAO,EACP,cAAc,EAIf,MAAM,WAAW,CAAC;AACnB,OAAO,EAKL,sBAAsB,EAEvB,MAAM,qBAAqB,CAAC;AAM7B,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG3D;;;;GAIG;AACH,qBAAa,aAAa,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;;CAI/C;AAED;;;;GAIG;AACH,qBAAa,gBAAgB,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAC;gBACxC,GAAG,IAAI,EAAE,GAAG,EAAE;CAG3B;AAED;;;GAGG;AACH,OAAO,EAAE,YAAY,IAAI,kBAAkB,EAAE,CAAC;AAE9C;;;GAGG;AACH,qBAAa,oBAAoB;gBACnB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO;IAO7F;;;OAGG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;;OAGG;IACH,IAAI,iBAAiB,IAAI,QAAQ,CAEhC;IAED;;;OAGG;IACH,IAAI,eAAe,IAAI,QAAQ,CAE9B;IAED;;;OAGG;IACH,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAU;IAE1B;;OAEG;IACH,OAAO,CAAC,UAAU,CAAW;IAE7B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAW;IAE3B;;OAEG;IACH,OAAO,CAAC,eAAe,CAAU;CAClC;AAED;;;;GAIG;AACH,MAAM,WAAW,MAAO,SAAQ,IAAI,CAClC,YAAY,EACV,WAAW,GACX,SAAS,GACT,0BAA0B,GAC1B,YAAY,GACZ,cAAc,GACd,aAAa,CAChB;IACC,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,oBAAoB,EAC9B,gBAAgB,CAAC,EAAE,sBAAsB,GACxC,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,aAAa,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC;IAEpF,aAAa,CAAC,CAAC,EACb,OAAO,EAAE,OAAO,CAAC,CAAC,GAAG,GAAG,CAAC,EACzB,SAAS,EAAE,QAAQ,EACnB,OAAO,EAAE,QAAQ,EACjB,UAAU,CAAC,EAAE,QAAQ,GACpB,UAAU,CAAC,OAAO,CAAC,CAAC;IAEvB;;;;;;;OAOG;IACH,4BAA4B,CAAC,CAAC,EAC5B,OAAO,EAAE,OAAO,CAAC,CAAC,GAAG,GAAG,CAAC,EACzB,SAAS,EAAE,QAAQ,EACnB,OAAO,EAAE,QAAQ,GAChB,UAAU,CAAC,OAAO,CAAC,CAAC;IAEvB,cAAc,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,qBAAa,aAAc,YAAW,MAAM;
|
|
1
|
+
{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../../src/connect/socket.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,6 +35,14 @@ export type SocketConnectOptions = {
|
|
|
35
35
|
* Time in milliseconds
|
|
36
36
|
*/
|
|
37
37
|
heartbeatInterval?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Maximum time to wait for a heartbeat pong before treating the connection as
|
|
40
|
+
* unresponsive and forcing a reconnect.
|
|
41
|
+
* @remarks
|
|
42
|
+
* Time in milliseconds. If not set, defaults to the effective heartbeat interval
|
|
43
|
+
* multiplied by a fixed factor.
|
|
44
|
+
*/
|
|
45
|
+
heartbeatTimeout?: number;
|
|
38
46
|
/**
|
|
39
47
|
* Server will send resource level information
|
|
40
48
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket.types.d.ts","sourceRoot":"","sources":["../../../src/connect/socket.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,eAAe,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEpC;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;OAEG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACvD;;;OAGG;IACH,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACvD;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC"}
|
|
1
|
+
{"version":3,"file":"socket.types.d.ts","sourceRoot":"","sources":["../../../src/connect/socket.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,eAAe,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEpC;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;OAEG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACvD;;;OAGG;IACH,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACvD;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC"}
|
|
@@ -130,8 +130,47 @@ let DefaultSocket = class DefaultSocket {
|
|
|
130
130
|
this.config = config;
|
|
131
131
|
this.defaultInterval = 10000;
|
|
132
132
|
this.secondsMultiplier = 1000;
|
|
133
|
+
this.heartbeatTimeoutMultiplier = 2;
|
|
133
134
|
this.heartbeatIsEnabled = true;
|
|
134
135
|
this.heartbeatInterval = this.defaultInterval;
|
|
136
|
+
this.connectionEpoch = 0;
|
|
137
|
+
this.sendHeartbeat = () => __awaiter(this, void 0, void 0, function* () {
|
|
138
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
139
|
+
if (!this.isConnected)
|
|
140
|
+
return;
|
|
141
|
+
const epoch = this.connectionEpoch;
|
|
142
|
+
const ping = this.messageBuilder.createHeartbeatPingMessage((_a = this.connectOptions) === null || _a === void 0 ? void 0 : _a.verboseHeartbeat);
|
|
143
|
+
if ((_b = this.connectOptions) === null || _b === void 0 ? void 0 : _b.heartbeatPingCallback) {
|
|
144
|
+
this.connectOptions.heartbeatPingCallback(ping);
|
|
145
|
+
}
|
|
146
|
+
const heartbeatTimeoutMs = (_d = (_c = this.connectOptions) === null || _c === void 0 ? void 0 : _c.heartbeatTimeout) !== null && _d !== void 0 ? _d : ((_f = (_e = this.connectOptions) === null || _e === void 0 ? void 0 : _e.heartbeatInterval) !== null && _f !== void 0 ? _f : this.heartbeatInterval) *
|
|
147
|
+
this.heartbeatTimeoutMultiplier;
|
|
148
|
+
let timeoutHandle;
|
|
149
|
+
const timeout = new Promise((_, reject) => {
|
|
150
|
+
timeoutHandle = setTimeout(() => reject(new Error(`Heartbeat pong not received within ${heartbeatTimeoutMs}ms`)), heartbeatTimeoutMs);
|
|
151
|
+
});
|
|
152
|
+
try {
|
|
153
|
+
const pong = yield Promise.race([this.send(ping), timeout]);
|
|
154
|
+
// when heartbeat runs before user logs in (connected to websocket but
|
|
155
|
+
// not authenticated) we don't extend session as it doesn't exist yet
|
|
156
|
+
if (this.user.isAuthenticated && !pong.IS_AUTHENTICATED) {
|
|
157
|
+
this.handleExpiredSession();
|
|
158
|
+
}
|
|
159
|
+
if ((_g = this.connectOptions) === null || _g === void 0 ? void 0 : _g.heartbeatPongCallback) {
|
|
160
|
+
this.connectOptions.heartbeatPongCallback(pong);
|
|
161
|
+
}
|
|
162
|
+
this.heartbeatIsEnabled =
|
|
163
|
+
pong.MESSAGE_TYPE === MessageType.HEARTBEAT_PONG && pong.SOURCE_REF === ping.SOURCE_REF;
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
logger.debug('Heartbeat failed, forcing reconnect: ', error);
|
|
167
|
+
this.removeMessageHandler(ping.SOURCE_REF);
|
|
168
|
+
this.forceReconnect(epoch, error);
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
clearTimeout(timeoutHandle);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
135
174
|
this.socketMessages = () => this.wsMessages;
|
|
136
175
|
}
|
|
137
176
|
get heartbeatLoggingIsEnabled() {
|
|
@@ -161,12 +200,20 @@ let DefaultSocket = class DefaultSocket {
|
|
|
161
200
|
this.cleanMessages();
|
|
162
201
|
}
|
|
163
202
|
(_b = this.socketSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
|
|
164
|
-
|
|
203
|
+
// Captured so openObserver/closeObserver below can tell whether they're
|
|
204
|
+
// still reporting on the currently active socket - a heartbeat-forced
|
|
205
|
+
// close resolves asynchronously and can otherwise land after a newer
|
|
206
|
+
// reconnect has already succeeded, incorrectly flipping it back to
|
|
207
|
+
// disconnected.
|
|
208
|
+
const socket = (this.websocket = new WebSocketSubject({
|
|
165
209
|
url: this.url,
|
|
166
210
|
openObserver: {
|
|
167
211
|
next: () => {
|
|
212
|
+
if (this.websocket !== socket)
|
|
213
|
+
return;
|
|
168
214
|
this.session.setSessionStorageItem('hostUrl', this.url);
|
|
169
215
|
this.status.isConnected = true;
|
|
216
|
+
this.connectionEpoch += 1;
|
|
170
217
|
this.prepareHeartbeat();
|
|
171
218
|
logger.info(`WebSocket connection is now open`);
|
|
172
219
|
resolve(this.isConnected);
|
|
@@ -174,6 +221,8 @@ let DefaultSocket = class DefaultSocket {
|
|
|
174
221
|
},
|
|
175
222
|
closeObserver: {
|
|
176
223
|
next: (closeEvent) => {
|
|
224
|
+
if (this.websocket !== socket)
|
|
225
|
+
return;
|
|
177
226
|
this.status.onClose(closeEvent);
|
|
178
227
|
if (this.isDisconnectedByServer) {
|
|
179
228
|
logger.info(`WebSocket connection was closed due an error - Code: ${closeEvent.code} ${closeEvent.reason ? ' | Reason: ' + closeEvent.reason : ''}`);
|
|
@@ -183,7 +232,7 @@ let DefaultSocket = class DefaultSocket {
|
|
|
183
232
|
},
|
|
184
233
|
serializer: (object) => this.serializer.serialize(object),
|
|
185
234
|
deserializer: (event) => this.serializer.deserialize(event),
|
|
186
|
-
});
|
|
235
|
+
}));
|
|
187
236
|
const onNextMessage = (receivedMessage) => __awaiter(this, void 0, void 0, function* () {
|
|
188
237
|
var _a;
|
|
189
238
|
const responseMessageReceivedLog = `Response Message received for SourceRef: ${receivedMessage.SOURCE_REF} | MessageType: ${receivedMessage.MESSAGE_TYPE}`;
|
|
@@ -318,32 +367,12 @@ let DefaultSocket = class DefaultSocket {
|
|
|
318
367
|
if (this.heartbeatTicker) {
|
|
319
368
|
this.heartbeatTicker.stop();
|
|
320
369
|
}
|
|
321
|
-
const sendHeartbeat = () => __awaiter(this, void 0, void 0, function* () {
|
|
322
|
-
var _a, _b, _c;
|
|
323
|
-
if (!this.isConnected)
|
|
324
|
-
return;
|
|
325
|
-
const ping = this.messageBuilder.createHeartbeatPingMessage((_a = this.connectOptions) === null || _a === void 0 ? void 0 : _a.verboseHeartbeat);
|
|
326
|
-
if ((_b = this.connectOptions) === null || _b === void 0 ? void 0 : _b.heartbeatPingCallback) {
|
|
327
|
-
this.connectOptions.heartbeatPingCallback(ping);
|
|
328
|
-
}
|
|
329
|
-
const pong = yield this.send(ping);
|
|
330
|
-
// when heartbeat runs before user logs in (connected to websocket but
|
|
331
|
-
// not authenticated) we don't extend session as it doesn't exist yet
|
|
332
|
-
if (this.user.isAuthenticated && !pong.IS_AUTHENTICATED) {
|
|
333
|
-
this.handleExpiredSession();
|
|
334
|
-
}
|
|
335
|
-
if ((_c = this.connectOptions) === null || _c === void 0 ? void 0 : _c.heartbeatPongCallback) {
|
|
336
|
-
this.connectOptions.heartbeatPongCallback(pong);
|
|
337
|
-
}
|
|
338
|
-
this.heartbeatIsEnabled =
|
|
339
|
-
pong.MESSAGE_TYPE === MessageType.HEARTBEAT_PONG && pong.SOURCE_REF === ping.SOURCE_REF;
|
|
340
|
-
});
|
|
341
370
|
if ((_b = (_a = this.connectOptions) === null || _a === void 0 ? void 0 : _a.enableHeartbeat) !== null && _b !== void 0 ? _b : this.heartbeatIsEnabled) {
|
|
342
371
|
const intervalInMillisecocnds = (_d = (_c = this.connectOptions) === null || _c === void 0 ? void 0 : _c.heartbeatInterval) !== null && _d !== void 0 ? _d : this.heartbeatInterval;
|
|
343
372
|
this.heartbeatTicker = new Ticker(intervalInMillisecocnds);
|
|
344
373
|
this.heartbeatTicker.start(() => {
|
|
345
374
|
if (this.websocket && this.isConnected) {
|
|
346
|
-
sendHeartbeat();
|
|
375
|
+
this.sendHeartbeat().catch((error) => logger.debug('Unhandled heartbeat error: ', error));
|
|
347
376
|
if (this.heartbeatLoggingIsEnabled) {
|
|
348
377
|
logger.debug(`Sending a heartbeat ping every ${intervalInMillisecocnds} ms`);
|
|
349
378
|
}
|
|
@@ -402,6 +431,28 @@ let DefaultSocket = class DefaultSocket {
|
|
|
402
431
|
},
|
|
403
432
|
});
|
|
404
433
|
}
|
|
434
|
+
forceReconnect(epoch, reason) {
|
|
435
|
+
if (epoch !== this.connectionEpoch || !this.websocket) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
const error = reason instanceof Error ? reason : new Error(String(reason));
|
|
439
|
+
logger.debug('Forcing socket closed due to heartbeat timeout: ', error);
|
|
440
|
+
// Flip connection status synchronously so reconnect()'s retry pipeline
|
|
441
|
+
// (gated on isConnectedSubject/isConnected) reacts immediately. We can't
|
|
442
|
+
// wait for the underlying native WebSocket's 'close' event below - it
|
|
443
|
+
// lands asynchronously, and by the time it does, a reconnect() call made
|
|
444
|
+
// now would already have seen a stale isConnected===true and completed
|
|
445
|
+
// as a no-op. Marking wasClean:false also guarantees isDisconnectedByServer
|
|
446
|
+
// is true, so this doesn't depend on CloseEvent.wasClean (which is not
|
|
447
|
+
// deterministic for a programmatic close, and which the external
|
|
448
|
+
// subscribe's onError/onComplete branching - socket.ts ~425-437 - relies
|
|
449
|
+
// on: onComplete only reconnects when isDisconnectedByServer is true).
|
|
450
|
+
this.status.onClose({ code: 4000, reason: 'Heartbeat timeout', wasClean: false });
|
|
451
|
+
// Also force the underlying native WebSocket closed so the dead
|
|
452
|
+
// connection is actually torn down.
|
|
453
|
+
this.websocket.error({ code: 4000, reason: 'Heartbeat timeout' });
|
|
454
|
+
this.reconnect();
|
|
455
|
+
}
|
|
405
456
|
reset() {
|
|
406
457
|
this.status.isConnected = false;
|
|
407
458
|
this.status.isConfigured = false;
|
|
@@ -36325,7 +36325,7 @@
|
|
|
36325
36325
|
},
|
|
36326
36326
|
{
|
|
36327
36327
|
"kind": "Content",
|
|
36328
|
-
"text": ">;\n enableHeartbeat?: boolean;\n enableHeartbeatLogging?: boolean;\n enableMessageLogging?: boolean;\n heartbeatInterval?: number;\n verboseHeartbeat?: boolean;\n heartbeatPingCallback?: (message: "
|
|
36328
|
+
"text": ">;\n enableHeartbeat?: boolean;\n enableHeartbeatLogging?: boolean;\n enableMessageLogging?: boolean;\n heartbeatInterval?: number;\n heartbeatTimeout?: number;\n verboseHeartbeat?: boolean;\n heartbeatPingCallback?: (message: "
|
|
36329
36329
|
},
|
|
36330
36330
|
{
|
|
36331
36331
|
"kind": "Reference",
|
|
@@ -2628,6 +2628,7 @@ export declare class DefaultSocket implements Socket {
|
|
|
2628
2628
|
protected config: ConnectConfig;
|
|
2629
2629
|
private readonly defaultInterval;
|
|
2630
2630
|
private readonly secondsMultiplier;
|
|
2631
|
+
private readonly heartbeatTimeoutMultiplier;
|
|
2631
2632
|
private websocket;
|
|
2632
2633
|
private wsMessages;
|
|
2633
2634
|
private wsMessageHandlers;
|
|
@@ -2648,6 +2649,7 @@ export declare class DefaultSocket implements Socket {
|
|
|
2648
2649
|
private heartbeatIsEnabled;
|
|
2649
2650
|
private heartbeatInterval;
|
|
2650
2651
|
private heartbeatTicker;
|
|
2652
|
+
private connectionEpoch;
|
|
2651
2653
|
private url;
|
|
2652
2654
|
private connectOptions;
|
|
2653
2655
|
private reconnectOptions;
|
|
@@ -2670,7 +2672,9 @@ export declare class DefaultSocket implements Socket {
|
|
|
2670
2672
|
private handleCookieBasedReauth;
|
|
2671
2673
|
private updateSessionAndSubscriptions;
|
|
2672
2674
|
private prepareHeartbeat;
|
|
2675
|
+
private sendHeartbeat;
|
|
2673
2676
|
private reconnect;
|
|
2677
|
+
private forceReconnect;
|
|
2674
2678
|
reset(): void;
|
|
2675
2679
|
private cleanMessages;
|
|
2676
2680
|
send<T>(message: Message<T | any>, needsHandling?: boolean): Promise<Message | any>;
|
|
@@ -4864,6 +4868,14 @@ export declare type SocketConnectOptions = {
|
|
|
4864
4868
|
* Time in milliseconds
|
|
4865
4869
|
*/
|
|
4866
4870
|
heartbeatInterval?: number;
|
|
4871
|
+
/**
|
|
4872
|
+
* Maximum time to wait for a heartbeat pong before treating the connection as
|
|
4873
|
+
* unresponsive and forcing a reconnect.
|
|
4874
|
+
* @remarks
|
|
4875
|
+
* Time in milliseconds. If not set, defaults to the effective heartbeat interval
|
|
4876
|
+
* multiplied by a fixed factor.
|
|
4877
|
+
*/
|
|
4878
|
+
heartbeatTimeout?: number;
|
|
4867
4879
|
/**
|
|
4868
4880
|
* Server will send resource level information
|
|
4869
4881
|
*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genesislcap/foundation-comms",
|
|
3
3
|
"description": "Genesis Foundation UI Comms",
|
|
4
|
-
"version": "15.7.1",
|
|
4
|
+
"version": "15.7.2-FUI-2595.1",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "SEE LICENSE IN license.txt",
|
|
7
7
|
"main": "dist/esm/index.js",
|
|
@@ -77,24 +77,24 @@
|
|
|
77
77
|
}
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
|
-
"@genesislcap/foundation-testing": "15.7.1",
|
|
81
|
-
"@genesislcap/genx": "15.7.1",
|
|
82
|
-
"@genesislcap/rollup-builder": "15.7.1",
|
|
83
|
-
"@genesislcap/ts-builder": "15.7.1",
|
|
84
|
-
"@genesislcap/uvu-playwright-builder": "15.7.1",
|
|
85
|
-
"@genesislcap/vite-builder": "15.7.1",
|
|
86
|
-
"@genesislcap/webpack-builder": "15.7.1",
|
|
80
|
+
"@genesislcap/foundation-testing": "15.7.2-FUI-2595.1",
|
|
81
|
+
"@genesislcap/genx": "15.7.2-FUI-2595.1",
|
|
82
|
+
"@genesislcap/rollup-builder": "15.7.2-FUI-2595.1",
|
|
83
|
+
"@genesislcap/ts-builder": "15.7.2-FUI-2595.1",
|
|
84
|
+
"@genesislcap/uvu-playwright-builder": "15.7.2-FUI-2595.1",
|
|
85
|
+
"@genesislcap/vite-builder": "15.7.2-FUI-2595.1",
|
|
86
|
+
"@genesislcap/webpack-builder": "15.7.2-FUI-2595.1",
|
|
87
87
|
"@types/js-cookie": "^3.0.2",
|
|
88
88
|
"@types/json-schema": "^7.0.11",
|
|
89
89
|
"@types/webappsec-credential-management": "^0.6.2",
|
|
90
90
|
"sinon": "^17.0.1"
|
|
91
91
|
},
|
|
92
92
|
"dependencies": {
|
|
93
|
-
"@genesislcap/foundation-broadcast-channel": "15.7.1",
|
|
94
|
-
"@genesislcap/foundation-logger": "15.7.1",
|
|
95
|
-
"@genesislcap/foundation-user": "15.7.1",
|
|
96
|
-
"@genesislcap/foundation-utils": "15.7.1",
|
|
97
|
-
"@genesislcap/web-core": "15.7.1",
|
|
93
|
+
"@genesislcap/foundation-broadcast-channel": "15.7.2-FUI-2595.1",
|
|
94
|
+
"@genesislcap/foundation-logger": "15.7.2-FUI-2595.1",
|
|
95
|
+
"@genesislcap/foundation-user": "15.7.2-FUI-2595.1",
|
|
96
|
+
"@genesislcap/foundation-utils": "15.7.2-FUI-2595.1",
|
|
97
|
+
"@genesislcap/web-core": "15.7.2-FUI-2595.1",
|
|
98
98
|
"@microsoft/fast-element": "1.14.0",
|
|
99
99
|
"@microsoft/fast-foundation": "2.50.0",
|
|
100
100
|
"bowser": "^2.11.0",
|
|
@@ -112,5 +112,5 @@
|
|
|
112
112
|
"publishConfig": {
|
|
113
113
|
"access": "public"
|
|
114
114
|
},
|
|
115
|
-
"gitHead": "
|
|
115
|
+
"gitHead": "ce9d754c91394fafee6f1892d4b95ccb7606e977"
|
|
116
116
|
}
|