@kinotic-ai/core 1.2.2 → 1.3.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/index.cjs +75 -67
- package/dist/index.d.cts +53 -26
- package/dist/index.d.ts +53 -26
- package/dist/index.js +75 -67
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -68,6 +68,7 @@ __export(exports_src, {
|
|
|
68
68
|
Version: () => Version,
|
|
69
69
|
TextEventFactory: () => TextEventFactory,
|
|
70
70
|
Sort: () => Sort,
|
|
71
|
+
SessionKeepAliveMode: () => SessionKeepAliveMode,
|
|
71
72
|
ServiceRegistry: () => ServiceRegistry,
|
|
72
73
|
ServerInfo: () => ServerInfo,
|
|
73
74
|
Scope: () => Scope,
|
|
@@ -95,7 +96,6 @@ __export(exports_src, {
|
|
|
95
96
|
Context: () => Context,
|
|
96
97
|
ConnectionInfo: () => ConnectionInfo,
|
|
97
98
|
ConnectedInfo: () => ConnectedInfo,
|
|
98
|
-
ConnectHeaders: () => ConnectHeaders,
|
|
99
99
|
CONTEXT_METADATA_KEY: () => CONTEXT_METADATA_KEY,
|
|
100
100
|
AuthorizationError: () => AuthorizationError,
|
|
101
101
|
AuthenticationError: () => AuthenticationError,
|
|
@@ -104,19 +104,22 @@ __export(exports_src, {
|
|
|
104
104
|
module.exports = __toCommonJS(exports_src);
|
|
105
105
|
|
|
106
106
|
// packages/core/src/api/ConnectionInfo.ts
|
|
107
|
-
class ConnectHeaders {
|
|
108
|
-
}
|
|
109
|
-
|
|
110
107
|
class ServerInfo {
|
|
111
108
|
host;
|
|
112
109
|
port;
|
|
113
110
|
useSSL;
|
|
114
111
|
}
|
|
112
|
+
var SessionKeepAliveMode;
|
|
113
|
+
((SessionKeepAliveMode2) => {
|
|
114
|
+
SessionKeepAliveMode2["NONE"] = "NONE";
|
|
115
|
+
SessionKeepAliveMode2["ACTIVITY"] = "ACTIVITY";
|
|
116
|
+
SessionKeepAliveMode2["CONNECTION"] = "CONNECTION";
|
|
117
|
+
})(SessionKeepAliveMode ||= {});
|
|
115
118
|
|
|
116
119
|
class ConnectionInfo extends ServerInfo {
|
|
117
|
-
|
|
120
|
+
webSocketFactory;
|
|
118
121
|
maxConnectionAttempts;
|
|
119
|
-
|
|
122
|
+
sessionKeepAlive = "ACTIVITY" /* ACTIVITY */;
|
|
120
123
|
}
|
|
121
124
|
// packages/core/src/api/errors/KinoticError.ts
|
|
122
125
|
class KinoticError extends Error {
|
|
@@ -132,10 +135,8 @@ var EventConstants;
|
|
|
132
135
|
EventConstants2["CONTENT_TYPE_HEADER"] = "content-type";
|
|
133
136
|
EventConstants2["CONTENT_LENGTH_HEADER"] = "content-length";
|
|
134
137
|
EventConstants2["REPLY_TO_HEADER"] = "reply-to";
|
|
135
|
-
EventConstants2["REPLY_TO_ID_HEADER"] = "reply-to-id";
|
|
136
|
-
EventConstants2["SESSION_HEADER"] = "session";
|
|
137
138
|
EventConstants2["CONNECTED_INFO_HEADER"] = "connected-info";
|
|
138
|
-
EventConstants2["
|
|
139
|
+
EventConstants2["SESSION_KEEP_ALIVE_HEADER"] = "session-keep-alive";
|
|
139
140
|
EventConstants2["CORRELATION_ID_HEADER"] = "__correlation-id";
|
|
140
141
|
EventConstants2["ERROR_HEADER"] = "error";
|
|
141
142
|
EventConstants2["COMPLETE_HEADER"] = "complete";
|
|
@@ -148,6 +149,8 @@ var EventConstants;
|
|
|
148
149
|
EventConstants2["SERVICE_DESTINATION_SCHEME"] = "srv";
|
|
149
150
|
EventConstants2["STREAM_DESTINATION_PREFIX"] = "stream://";
|
|
150
151
|
EventConstants2["STREAM_DESTINATION_SCHEME"] = "stream";
|
|
152
|
+
EventConstants2["REPLY_DESTINATION_PREFIX"] = "reply://";
|
|
153
|
+
EventConstants2["REPLY_DESTINATION_SCHEME"] = "reply";
|
|
151
154
|
EventConstants2["CONTENT_JSON"] = "application/json";
|
|
152
155
|
EventConstants2["CONTENT_TEXT"] = "text/plain";
|
|
153
156
|
EventConstants2["TRACEPARENT_HEADER"] = "traceparent";
|
|
@@ -157,8 +160,8 @@ var EventConstants;
|
|
|
157
160
|
// packages/core/src/internal/api/event/StompConnectionManager.ts
|
|
158
161
|
var import_rx_stomp = require("@stomp/rx-stomp");
|
|
159
162
|
var import_stompjs = require("@stomp/stompjs");
|
|
160
|
-
var import_uuid = require("uuid");
|
|
161
163
|
var import_debug = __toESM(require("debug"));
|
|
164
|
+
var import_uuid = require("uuid");
|
|
162
165
|
|
|
163
166
|
class StompConnectionManager {
|
|
164
167
|
lastWebsocketError = null;
|
|
@@ -171,9 +174,10 @@ class StompConnectionManager {
|
|
|
171
174
|
initialConnectionSuccessful = false;
|
|
172
175
|
debugLogger = import_debug.default("kinoitc:stomp");
|
|
173
176
|
uuidv4 = import_uuid.v4();
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
_replyToCri = null;
|
|
178
|
+
serverHeadersSubscription = null;
|
|
176
179
|
deactivationHandler = null;
|
|
180
|
+
replyToCriChangedHandler = null;
|
|
177
181
|
get active() {
|
|
178
182
|
return !!this.rxStomp;
|
|
179
183
|
}
|
|
@@ -201,31 +205,23 @@ class StompConnectionManager {
|
|
|
201
205
|
this.initialConnectionSuccessful = false;
|
|
202
206
|
this.lastWebsocketError = null;
|
|
203
207
|
this.maxConnectionAttemptsReached = false;
|
|
208
|
+
this._replyToCri = null;
|
|
209
|
+
this.serverHeadersSubscription?.unsubscribe();
|
|
210
|
+
this.serverHeadersSubscription = null;
|
|
204
211
|
const url = "ws" + (connectionInfo.useSSL ? "s" : "") + "://" + connectionInfo.host + (connectionInfo.port ? ":" + connectionInfo.port : "") + "/v1";
|
|
205
212
|
this.rxStomp = new import_rx_stomp.RxStomp;
|
|
206
|
-
let
|
|
213
|
+
let preparedSocket = null;
|
|
214
|
+
const userWebSocketFactory = connectionInfo.webSocketFactory;
|
|
207
215
|
const stompConfig = {
|
|
208
216
|
brokerURL: url,
|
|
209
|
-
connectHeaders:
|
|
217
|
+
connectHeaders: {
|
|
218
|
+
["session-keep-alive" /* SESSION_KEEP_ALIVE_HEADER */]: connectionInfo.sessionKeepAlive
|
|
219
|
+
},
|
|
210
220
|
heartbeatIncoming: 120000,
|
|
211
221
|
heartbeatOutgoing: 30000,
|
|
212
222
|
reconnectDelay: this.INITIAL_RECONNECT_DELAY,
|
|
223
|
+
webSocketFactory: userWebSocketFactory ? () => preparedSocket : undefined,
|
|
213
224
|
beforeConnect: async () => {
|
|
214
|
-
if (typeof connectionInfo.connectHeaders === "function") {
|
|
215
|
-
const headers = await connectionInfo.connectHeaders();
|
|
216
|
-
for (const key in headers) {
|
|
217
|
-
connectHeadersInternal[key] = headers[key];
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
if (connectionInfo.disableStickySession) {
|
|
221
|
-
connectHeadersInternal["disable-sticky-session" /* DISABLE_STICKY_SESSION_HEADER */] = "true";
|
|
222
|
-
}
|
|
223
|
-
if (connectHeadersInternal["reply-to-id" /* REPLY_TO_ID_HEADER */]) {
|
|
224
|
-
this.replyToId = connectHeadersInternal["reply-to-id" /* REPLY_TO_ID_HEADER */];
|
|
225
|
-
this._replyToCri = "srv://" /* SERVICE_DESTINATION_PREFIX */ + this.replyToId + ":" + this.uuidv4 + "@kinoitc.js.EventBus/replyHandler";
|
|
226
|
-
} else {
|
|
227
|
-
connectHeadersInternal["reply-to-id" /* REPLY_TO_ID_HEADER */] = this.replyToId;
|
|
228
|
-
}
|
|
229
225
|
if (connectionInfo?.maxConnectionAttempts) {
|
|
230
226
|
this.connectionAttempts++;
|
|
231
227
|
if (this.connectionAttempts > connectionInfo.maxConnectionAttempts) {
|
|
@@ -235,12 +231,23 @@ class StompConnectionManager {
|
|
|
235
231
|
let message = this.lastWebsocketError?.message ? this.lastWebsocketError?.message : "UNKNOWN";
|
|
236
232
|
reject(`Max number of reconnection attempts reached. Last WS Error ${message}`);
|
|
237
233
|
}
|
|
234
|
+
return;
|
|
238
235
|
} else {
|
|
239
236
|
await this.connectionJitterDelay();
|
|
240
237
|
}
|
|
241
238
|
} else {
|
|
242
239
|
await this.connectionJitterDelay();
|
|
243
240
|
}
|
|
241
|
+
if (userWebSocketFactory) {
|
|
242
|
+
try {
|
|
243
|
+
preparedSocket = await userWebSocketFactory();
|
|
244
|
+
} catch (e) {
|
|
245
|
+
await this.deactivate();
|
|
246
|
+
if (!this.initialConnectionSuccessful) {
|
|
247
|
+
reject(e);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
244
251
|
}
|
|
245
252
|
};
|
|
246
253
|
if (this.debugLogger.enabled) {
|
|
@@ -267,36 +274,29 @@ class StompConnectionManager {
|
|
|
267
274
|
this.rxStomp = null;
|
|
268
275
|
reject(message);
|
|
269
276
|
});
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
if (
|
|
275
|
-
|
|
276
|
-
if (connectedInfo.sessionId != null && connectedInfo.replyToId != null) {
|
|
277
|
-
if (connectionInfo.connectHeaders != null) {
|
|
278
|
-
for (let key in connectHeadersInternal) {
|
|
279
|
-
delete connectHeadersInternal[key];
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
connectHeadersInternal["session" /* SESSION_HEADER */] = connectedInfo.sessionId;
|
|
283
|
-
resolve(connectedInfo);
|
|
284
|
-
} else {
|
|
285
|
-
reject("Server did not return proper data for successful login");
|
|
286
|
-
}
|
|
287
|
-
} else if (typeof connectionInfo.connectHeaders === "function") {
|
|
288
|
-
for (let key in connectHeadersInternal) {
|
|
289
|
-
delete connectHeadersInternal[key];
|
|
290
|
-
}
|
|
291
|
-
if (!this.initialConnectionSuccessful) {
|
|
292
|
-
resolve(connectedInfo);
|
|
293
|
-
}
|
|
294
|
-
} else if (typeof connectionInfo.connectHeaders === "object") {
|
|
295
|
-
serverHeadersSubscription.unsubscribe();
|
|
296
|
-
resolve(connectedInfo);
|
|
277
|
+
this.serverHeadersSubscription = this.rxStomp.serverHeaders$.subscribe((value) => {
|
|
278
|
+
const connectedInfoJson = value["connected-info" /* CONNECTED_INFO_HEADER */];
|
|
279
|
+
const firstConnect = this._replyToCri == null;
|
|
280
|
+
if (connectedInfoJson == null) {
|
|
281
|
+
if (firstConnect) {
|
|
282
|
+
reject("Server did not return proper data for successful login");
|
|
297
283
|
}
|
|
298
|
-
|
|
299
|
-
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const connectedInfo = JSON.parse(connectedInfoJson);
|
|
287
|
+
if (connectedInfo.replyToId == null) {
|
|
288
|
+
if (firstConnect) {
|
|
289
|
+
reject("Server did not return a replyToId for successful login");
|
|
290
|
+
}
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const newReplyToCri = "reply://" /* REPLY_DESTINATION_PREFIX */ + connectedInfo.replyToId + ":" + this.uuidv4 + "@kinoitc.js.EventBus/replyHandler";
|
|
294
|
+
if (firstConnect) {
|
|
295
|
+
this._replyToCri = newReplyToCri;
|
|
296
|
+
resolve(connectedInfo);
|
|
297
|
+
} else if (this._replyToCri !== newReplyToCri) {
|
|
298
|
+
this._replyToCri = newReplyToCri;
|
|
299
|
+
this.replyToCriChangedHandler?.(newReplyToCri);
|
|
300
300
|
}
|
|
301
301
|
});
|
|
302
302
|
this.rxStomp.activate();
|
|
@@ -305,6 +305,8 @@ class StompConnectionManager {
|
|
|
305
305
|
async deactivate(force) {
|
|
306
306
|
if (this.rxStomp) {
|
|
307
307
|
await this.rxStomp.deactivate({ force });
|
|
308
|
+
this.serverHeadersSubscription?.unsubscribe();
|
|
309
|
+
this.serverHeadersSubscription = null;
|
|
308
310
|
if (this.deactivationHandler) {
|
|
309
311
|
this.deactivationHandler();
|
|
310
312
|
}
|
|
@@ -385,6 +387,10 @@ class EventBus {
|
|
|
385
387
|
this.stompConnectionManager.deactivationHandler = () => {
|
|
386
388
|
this.cleanup();
|
|
387
389
|
};
|
|
390
|
+
this.stompConnectionManager.replyToCriChangedHandler = (replyToCri) => {
|
|
391
|
+
this.replyToCri = replyToCri;
|
|
392
|
+
this.resetRequestReplies("Reply destination changed");
|
|
393
|
+
};
|
|
388
394
|
}
|
|
389
395
|
isConnectionActive() {
|
|
390
396
|
return this.stompConnectionManager.active;
|
|
@@ -452,7 +458,7 @@ class EventBus {
|
|
|
452
458
|
})).subscribe({
|
|
453
459
|
next(value) {
|
|
454
460
|
if (value.hasHeader("control" /* CONTROL_HEADER */)) {
|
|
455
|
-
if (value.headers.get("control" /* CONTROL_HEADER */) === "complete") {
|
|
461
|
+
if (value.headers.get("control" /* CONTROL_HEADER */) === "complete" /* CONTROL_VALUE_COMPLETE */) {
|
|
456
462
|
serverSignaledCompletion = true;
|
|
457
463
|
subscriber.complete();
|
|
458
464
|
} else {
|
|
@@ -496,8 +502,16 @@ class EventBus {
|
|
|
496
502
|
return this._observe(cri);
|
|
497
503
|
}
|
|
498
504
|
cleanup() {
|
|
505
|
+
this.resetRequestReplies("Connection disconnected");
|
|
506
|
+
if (this.errorSubjectSubscription) {
|
|
507
|
+
this.errorSubjectSubscription.unsubscribe();
|
|
508
|
+
this.errorSubjectSubscription = null;
|
|
509
|
+
}
|
|
510
|
+
this.serverInfo = null;
|
|
511
|
+
}
|
|
512
|
+
resetRequestReplies(reason) {
|
|
499
513
|
if (this.requestRepliesSubject != null) {
|
|
500
|
-
this.requestRepliesSubject.error(new Error(
|
|
514
|
+
this.requestRepliesSubject.error(new Error(reason));
|
|
501
515
|
if (this.requestRepliesSubscription != null) {
|
|
502
516
|
this.requestRepliesSubscription.unsubscribe();
|
|
503
517
|
this.requestRepliesSubscription = null;
|
|
@@ -505,11 +519,6 @@ class EventBus {
|
|
|
505
519
|
this.requestRepliesSubject = null;
|
|
506
520
|
this.requestRepliesObservable = null;
|
|
507
521
|
}
|
|
508
|
-
if (this.errorSubjectSubscription) {
|
|
509
|
-
this.errorSubjectSubscription.unsubscribe();
|
|
510
|
-
this.errorSubjectSubscription = null;
|
|
511
|
-
}
|
|
512
|
-
this.serverInfo = null;
|
|
513
522
|
}
|
|
514
523
|
createSendUnavailableError() {
|
|
515
524
|
let ret = "You must call connect on the event bus before sending any request";
|
|
@@ -993,7 +1002,7 @@ var import_operators2 = require("rxjs/operators");
|
|
|
993
1002
|
// packages/core/package.json
|
|
994
1003
|
var package_default = {
|
|
995
1004
|
name: "@kinotic-ai/core",
|
|
996
|
-
version: "1.
|
|
1005
|
+
version: "1.3.1",
|
|
997
1006
|
type: "module",
|
|
998
1007
|
files: [
|
|
999
1008
|
"dist"
|
|
@@ -1487,7 +1496,6 @@ class AuthorizationError extends KinoticError {
|
|
|
1487
1496
|
}
|
|
1488
1497
|
// packages/core/src/api/security/ConnectedInfo.ts
|
|
1489
1498
|
class ConnectedInfo {
|
|
1490
|
-
sessionId;
|
|
1491
1499
|
replyToId;
|
|
1492
1500
|
participant;
|
|
1493
1501
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,26 +1,54 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Structural shape of a WebSocket used by the underlying STOMP client.
|
|
3
|
+
* Copied from the WebSocket interface to avoid pulling in the DOM typelib,
|
|
4
|
+
* so this type stays usable in Node environments where `lib: dom` is not set.
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
interface IWebSocket {
|
|
7
|
+
url: string;
|
|
8
|
+
binaryType?: string;
|
|
9
|
+
readyState: number;
|
|
10
|
+
onopen: ((ev?: any) => any) | undefined | null;
|
|
11
|
+
onclose: ((ev?: any) => any) | undefined | null;
|
|
12
|
+
onerror: ((ev: any) => any) | undefined | null;
|
|
13
|
+
onmessage: ((ev: any) => any) | undefined | null;
|
|
14
|
+
close(code?: number, reason?: string): void;
|
|
15
|
+
send(data: string | ArrayBuffer): void;
|
|
8
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Factory invoked on every (re)connect to produce the WebSocket the STOMP
|
|
19
|
+
* client will use. Supply this in Node when you need to set headers on the
|
|
20
|
+
* upgrade request (for example, an Authorization header). It may be async —
|
|
21
|
+
* for example, to refresh a short-lived access token before each connect.
|
|
22
|
+
* Browser callers normally leave this unset and rely on the session cookie
|
|
23
|
+
* established by a prior REST login.
|
|
24
|
+
*/
|
|
25
|
+
type WebSocketFactory = () => IWebSocket | Promise<IWebSocket>;
|
|
9
26
|
declare class ServerInfo {
|
|
10
27
|
host: string;
|
|
11
28
|
port?: number | null;
|
|
12
29
|
useSSL?: boolean | null;
|
|
13
30
|
}
|
|
31
|
+
declare enum SessionKeepAliveMode {
|
|
32
|
+
NONE = "NONE",
|
|
33
|
+
ACTIVITY = "ACTIVITY",
|
|
34
|
+
CONNECTION = "CONNECTION"
|
|
35
|
+
}
|
|
14
36
|
/**
|
|
15
|
-
* ConnectionInfo provides the information needed to connect to the kinoitc server
|
|
37
|
+
* ConnectionInfo provides the information needed to connect to the kinoitc server.
|
|
38
|
+
*
|
|
39
|
+
* Authentication is performed during the WebSocket upgrade (handshake), not in
|
|
40
|
+
* the STOMP CONNECT frame. In the browser, log in via the REST endpoints first
|
|
41
|
+
* and the established session cookie will be used. In Node, supply a
|
|
42
|
+
* {@link WebSocketFactory} that attaches the required upgrade headers.
|
|
16
43
|
*/
|
|
17
44
|
declare class ConnectionInfo extends ServerInfo {
|
|
18
45
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
46
|
+
* Optional factory used to create the underlying WebSocket. Use this in
|
|
47
|
+
* Node to attach custom headers (such as Authorization) to the upgrade
|
|
48
|
+
* request. If omitted, a default WebSocket is created and authentication
|
|
49
|
+
* is expected to come from the session cookie.
|
|
22
50
|
*/
|
|
23
|
-
|
|
51
|
+
webSocketFactory?: WebSocketFactory;
|
|
24
52
|
/**
|
|
25
53
|
* The maximum number of connection attempts to make during the {@link IEventBus} initial connection request.
|
|
26
54
|
* If the limit is reached the {@link IEventBus} will return an error to the caller of {@link IEventBus#connect}
|
|
@@ -28,10 +56,11 @@ declare class ConnectionInfo extends ServerInfo {
|
|
|
28
56
|
*/
|
|
29
57
|
maxConnectionAttempts?: number | null;
|
|
30
58
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
59
|
+
* Controls whether session expiration is extended by gateway activity or by an active websocket connection.
|
|
60
|
+
* Defaults to {@link SessionKeepAliveMode.ACTIVITY}.
|
|
61
|
+
* Use {@link SessionKeepAliveMode.NONE} to remove the session when the websocket connection closes.
|
|
33
62
|
*/
|
|
34
|
-
|
|
63
|
+
sessionKeepAlive: SessionKeepAliveMode;
|
|
35
64
|
}
|
|
36
65
|
import { Optional } from "typescript-optional";
|
|
37
66
|
import { Observable } from "rxjs";
|
|
@@ -100,7 +129,6 @@ declare class Participant implements IParticipant {
|
|
|
100
129
|
* Contains information about the connection that was established
|
|
101
130
|
*/
|
|
102
131
|
declare class ConnectedInfo {
|
|
103
|
-
sessionId: string;
|
|
104
132
|
replyToId: string;
|
|
105
133
|
participant: Participant;
|
|
106
134
|
}
|
|
@@ -253,22 +281,13 @@ declare enum EventConstants {
|
|
|
253
281
|
CONTENT_LENGTH_HEADER = "content-length",
|
|
254
282
|
REPLY_TO_HEADER = "reply-to",
|
|
255
283
|
/**
|
|
256
|
-
* This is the replyToId that will be supplied by the client, which will be used when sending replies to the client.
|
|
257
|
-
*/
|
|
258
|
-
REPLY_TO_ID_HEADER = "reply-to-id",
|
|
259
|
-
/**
|
|
260
|
-
* Header provided by the sever on connection to represent the user's session id
|
|
261
|
-
*/
|
|
262
|
-
SESSION_HEADER = "session",
|
|
263
|
-
/**
|
|
264
284
|
* Header provided by the server on connection to provide the {@link ConnectionInfo} as a JSON string
|
|
265
285
|
*/
|
|
266
286
|
CONNECTED_INFO_HEADER = "connected-info",
|
|
267
287
|
/**
|
|
268
|
-
* Header provided by the client on connection request to
|
|
269
|
-
* should not keep the session alive after any network disconnection.
|
|
288
|
+
* Header provided by the client on connection request to choose how the session is kept alive.
|
|
270
289
|
*/
|
|
271
|
-
|
|
290
|
+
SESSION_KEEP_ALIVE_HEADER = "session-keep-alive",
|
|
272
291
|
/**
|
|
273
292
|
* Correlates a response with a given request
|
|
274
293
|
* Headers that start with __ will always be persisted between messages
|
|
@@ -297,6 +316,8 @@ declare enum EventConstants {
|
|
|
297
316
|
SERVICE_DESTINATION_SCHEME = "srv",
|
|
298
317
|
STREAM_DESTINATION_PREFIX = "stream://",
|
|
299
318
|
STREAM_DESTINATION_SCHEME = "stream",
|
|
319
|
+
REPLY_DESTINATION_PREFIX = "reply://",
|
|
320
|
+
REPLY_DESTINATION_SCHEME = "reply",
|
|
300
321
|
CONTENT_JSON = "application/json",
|
|
301
322
|
CONTENT_TEXT = "text/plain",
|
|
302
323
|
/**
|
|
@@ -1094,6 +1115,12 @@ declare class EventBus implements IEventBus {
|
|
|
1094
1115
|
observe(cri: string): Observable3<IEvent>;
|
|
1095
1116
|
private cleanup;
|
|
1096
1117
|
/**
|
|
1118
|
+
* Tears down the shared request-replies stream so the next request rebuilds it against the
|
|
1119
|
+
* current {@link replyToCri}. Any in-flight requests are failed with the given reason since
|
|
1120
|
+
* their replies can no longer be delivered.
|
|
1121
|
+
*/
|
|
1122
|
+
private resetRequestReplies;
|
|
1123
|
+
/**
|
|
1097
1124
|
* Creates the proper error to return if this.stompConnectionManager?.rxStomp is not available on a send request
|
|
1098
1125
|
*/
|
|
1099
1126
|
private createSendUnavailableError;
|
|
@@ -1117,4 +1144,4 @@ declare class ParticipantConstants {
|
|
|
1117
1144
|
static readonly PARTICIPANT_TYPE_NODE: string;
|
|
1118
1145
|
static readonly CLI_PARTICIPANT_ID: string;
|
|
1119
1146
|
}
|
|
1120
|
-
export { createCRI, Version, TextEventFactory, Sort, ServiceRegistry, ServiceContext, ServerInfo, Scope, Publish, ParticipantConstants, Participant, Pageable, Page, Order, OffsetPageable, NullHandling, KinoticSingleton, KinoticPlugin, KinoticError, Kinotic, JsonEventFactory, IterablePage, Identifiable, IServiceRegistry, IServiceProxy, IParticipant, IKinotic, IEventFactory, IEventBus, IEvent, IEditableDataSource, IDataSource, ICrudServiceProxyFactory, ICrudServiceProxy, FunctionalIterablePage, EventConstants, EventBus, Event, Direction, DefaultCRI, DataSourceUtils, CursorPageable, CrudServiceProxyFactory, CrudServiceProxy, ContextInterceptor, Context, ConnectionInfo, ConnectedInfo,
|
|
1147
|
+
export { createCRI, WebSocketFactory, Version, TextEventFactory, Sort, SessionKeepAliveMode, ServiceRegistry, ServiceContext, ServerInfo, Scope, Publish, ParticipantConstants, Participant, Pageable, Page, Order, OffsetPageable, NullHandling, KinoticSingleton, KinoticPlugin, KinoticError, Kinotic, JsonEventFactory, IterablePage, Identifiable, IWebSocket, IServiceRegistry, IServiceProxy, IParticipant, IKinotic, IEventFactory, IEventBus, IEvent, IEditableDataSource, IDataSource, ICrudServiceProxyFactory, ICrudServiceProxy, FunctionalIterablePage, EventConstants, EventBus, Event, Direction, DefaultCRI, DataSourceUtils, CursorPageable, CrudServiceProxyFactory, CrudServiceProxy, ContextInterceptor, Context, ConnectionInfo, ConnectedInfo, CRI, CONTEXT_METADATA_KEY, AuthorizationError, AuthenticationError, AbstractIterablePage };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,26 +1,54 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Structural shape of a WebSocket used by the underlying STOMP client.
|
|
3
|
+
* Copied from the WebSocket interface to avoid pulling in the DOM typelib,
|
|
4
|
+
* so this type stays usable in Node environments where `lib: dom` is not set.
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
interface IWebSocket {
|
|
7
|
+
url: string;
|
|
8
|
+
binaryType?: string;
|
|
9
|
+
readyState: number;
|
|
10
|
+
onopen: ((ev?: any) => any) | undefined | null;
|
|
11
|
+
onclose: ((ev?: any) => any) | undefined | null;
|
|
12
|
+
onerror: ((ev: any) => any) | undefined | null;
|
|
13
|
+
onmessage: ((ev: any) => any) | undefined | null;
|
|
14
|
+
close(code?: number, reason?: string): void;
|
|
15
|
+
send(data: string | ArrayBuffer): void;
|
|
8
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Factory invoked on every (re)connect to produce the WebSocket the STOMP
|
|
19
|
+
* client will use. Supply this in Node when you need to set headers on the
|
|
20
|
+
* upgrade request (for example, an Authorization header). It may be async —
|
|
21
|
+
* for example, to refresh a short-lived access token before each connect.
|
|
22
|
+
* Browser callers normally leave this unset and rely on the session cookie
|
|
23
|
+
* established by a prior REST login.
|
|
24
|
+
*/
|
|
25
|
+
type WebSocketFactory = () => IWebSocket | Promise<IWebSocket>;
|
|
9
26
|
declare class ServerInfo {
|
|
10
27
|
host: string;
|
|
11
28
|
port?: number | null;
|
|
12
29
|
useSSL?: boolean | null;
|
|
13
30
|
}
|
|
31
|
+
declare enum SessionKeepAliveMode {
|
|
32
|
+
NONE = "NONE",
|
|
33
|
+
ACTIVITY = "ACTIVITY",
|
|
34
|
+
CONNECTION = "CONNECTION"
|
|
35
|
+
}
|
|
14
36
|
/**
|
|
15
|
-
* ConnectionInfo provides the information needed to connect to the kinoitc server
|
|
37
|
+
* ConnectionInfo provides the information needed to connect to the kinoitc server.
|
|
38
|
+
*
|
|
39
|
+
* Authentication is performed during the WebSocket upgrade (handshake), not in
|
|
40
|
+
* the STOMP CONNECT frame. In the browser, log in via the REST endpoints first
|
|
41
|
+
* and the established session cookie will be used. In Node, supply a
|
|
42
|
+
* {@link WebSocketFactory} that attaches the required upgrade headers.
|
|
16
43
|
*/
|
|
17
44
|
declare class ConnectionInfo extends ServerInfo {
|
|
18
45
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
46
|
+
* Optional factory used to create the underlying WebSocket. Use this in
|
|
47
|
+
* Node to attach custom headers (such as Authorization) to the upgrade
|
|
48
|
+
* request. If omitted, a default WebSocket is created and authentication
|
|
49
|
+
* is expected to come from the session cookie.
|
|
22
50
|
*/
|
|
23
|
-
|
|
51
|
+
webSocketFactory?: WebSocketFactory;
|
|
24
52
|
/**
|
|
25
53
|
* The maximum number of connection attempts to make during the {@link IEventBus} initial connection request.
|
|
26
54
|
* If the limit is reached the {@link IEventBus} will return an error to the caller of {@link IEventBus#connect}
|
|
@@ -28,10 +56,11 @@ declare class ConnectionInfo extends ServerInfo {
|
|
|
28
56
|
*/
|
|
29
57
|
maxConnectionAttempts?: number | null;
|
|
30
58
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
59
|
+
* Controls whether session expiration is extended by gateway activity or by an active websocket connection.
|
|
60
|
+
* Defaults to {@link SessionKeepAliveMode.ACTIVITY}.
|
|
61
|
+
* Use {@link SessionKeepAliveMode.NONE} to remove the session when the websocket connection closes.
|
|
33
62
|
*/
|
|
34
|
-
|
|
63
|
+
sessionKeepAlive: SessionKeepAliveMode;
|
|
35
64
|
}
|
|
36
65
|
import { Optional } from "typescript-optional";
|
|
37
66
|
import { Observable } from "rxjs";
|
|
@@ -100,7 +129,6 @@ declare class Participant implements IParticipant {
|
|
|
100
129
|
* Contains information about the connection that was established
|
|
101
130
|
*/
|
|
102
131
|
declare class ConnectedInfo {
|
|
103
|
-
sessionId: string;
|
|
104
132
|
replyToId: string;
|
|
105
133
|
participant: Participant;
|
|
106
134
|
}
|
|
@@ -253,22 +281,13 @@ declare enum EventConstants {
|
|
|
253
281
|
CONTENT_LENGTH_HEADER = "content-length",
|
|
254
282
|
REPLY_TO_HEADER = "reply-to",
|
|
255
283
|
/**
|
|
256
|
-
* This is the replyToId that will be supplied by the client, which will be used when sending replies to the client.
|
|
257
|
-
*/
|
|
258
|
-
REPLY_TO_ID_HEADER = "reply-to-id",
|
|
259
|
-
/**
|
|
260
|
-
* Header provided by the sever on connection to represent the user's session id
|
|
261
|
-
*/
|
|
262
|
-
SESSION_HEADER = "session",
|
|
263
|
-
/**
|
|
264
284
|
* Header provided by the server on connection to provide the {@link ConnectionInfo} as a JSON string
|
|
265
285
|
*/
|
|
266
286
|
CONNECTED_INFO_HEADER = "connected-info",
|
|
267
287
|
/**
|
|
268
|
-
* Header provided by the client on connection request to
|
|
269
|
-
* should not keep the session alive after any network disconnection.
|
|
288
|
+
* Header provided by the client on connection request to choose how the session is kept alive.
|
|
270
289
|
*/
|
|
271
|
-
|
|
290
|
+
SESSION_KEEP_ALIVE_HEADER = "session-keep-alive",
|
|
272
291
|
/**
|
|
273
292
|
* Correlates a response with a given request
|
|
274
293
|
* Headers that start with __ will always be persisted between messages
|
|
@@ -297,6 +316,8 @@ declare enum EventConstants {
|
|
|
297
316
|
SERVICE_DESTINATION_SCHEME = "srv",
|
|
298
317
|
STREAM_DESTINATION_PREFIX = "stream://",
|
|
299
318
|
STREAM_DESTINATION_SCHEME = "stream",
|
|
319
|
+
REPLY_DESTINATION_PREFIX = "reply://",
|
|
320
|
+
REPLY_DESTINATION_SCHEME = "reply",
|
|
300
321
|
CONTENT_JSON = "application/json",
|
|
301
322
|
CONTENT_TEXT = "text/plain",
|
|
302
323
|
/**
|
|
@@ -1094,6 +1115,12 @@ declare class EventBus implements IEventBus {
|
|
|
1094
1115
|
observe(cri: string): Observable3<IEvent>;
|
|
1095
1116
|
private cleanup;
|
|
1096
1117
|
/**
|
|
1118
|
+
* Tears down the shared request-replies stream so the next request rebuilds it against the
|
|
1119
|
+
* current {@link replyToCri}. Any in-flight requests are failed with the given reason since
|
|
1120
|
+
* their replies can no longer be delivered.
|
|
1121
|
+
*/
|
|
1122
|
+
private resetRequestReplies;
|
|
1123
|
+
/**
|
|
1097
1124
|
* Creates the proper error to return if this.stompConnectionManager?.rxStomp is not available on a send request
|
|
1098
1125
|
*/
|
|
1099
1126
|
private createSendUnavailableError;
|
|
@@ -1117,4 +1144,4 @@ declare class ParticipantConstants {
|
|
|
1117
1144
|
static readonly PARTICIPANT_TYPE_NODE: string;
|
|
1118
1145
|
static readonly CLI_PARTICIPANT_ID: string;
|
|
1119
1146
|
}
|
|
1120
|
-
export { createCRI, Version, TextEventFactory, Sort, ServiceRegistry, ServiceContext, ServerInfo, Scope, Publish, ParticipantConstants, Participant, Pageable, Page, Order, OffsetPageable, NullHandling, KinoticSingleton, KinoticPlugin, KinoticError, Kinotic, JsonEventFactory, IterablePage, Identifiable, IServiceRegistry, IServiceProxy, IParticipant, IKinotic, IEventFactory, IEventBus, IEvent, IEditableDataSource, IDataSource, ICrudServiceProxyFactory, ICrudServiceProxy, FunctionalIterablePage, EventConstants, EventBus, Event, Direction, DefaultCRI, DataSourceUtils, CursorPageable, CrudServiceProxyFactory, CrudServiceProxy, ContextInterceptor, Context, ConnectionInfo, ConnectedInfo,
|
|
1147
|
+
export { createCRI, WebSocketFactory, Version, TextEventFactory, Sort, SessionKeepAliveMode, ServiceRegistry, ServiceContext, ServerInfo, Scope, Publish, ParticipantConstants, Participant, Pageable, Page, Order, OffsetPageable, NullHandling, KinoticSingleton, KinoticPlugin, KinoticError, Kinotic, JsonEventFactory, IterablePage, Identifiable, IWebSocket, IServiceRegistry, IServiceProxy, IParticipant, IKinotic, IEventFactory, IEventBus, IEvent, IEditableDataSource, IDataSource, ICrudServiceProxyFactory, ICrudServiceProxy, FunctionalIterablePage, EventConstants, EventBus, Event, Direction, DefaultCRI, DataSourceUtils, CursorPageable, CrudServiceProxyFactory, CrudServiceProxy, ContextInterceptor, Context, ConnectionInfo, ConnectedInfo, CRI, CONTEXT_METADATA_KEY, AuthorizationError, AuthenticationError, AbstractIterablePage };
|
package/dist/index.js
CHANGED
|
@@ -2,19 +2,22 @@ import { createRequire } from "node:module";
|
|
|
2
2
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
3
|
|
|
4
4
|
// packages/core/src/api/ConnectionInfo.ts
|
|
5
|
-
class ConnectHeaders {
|
|
6
|
-
}
|
|
7
|
-
|
|
8
5
|
class ServerInfo {
|
|
9
6
|
host;
|
|
10
7
|
port;
|
|
11
8
|
useSSL;
|
|
12
9
|
}
|
|
10
|
+
var SessionKeepAliveMode;
|
|
11
|
+
((SessionKeepAliveMode2) => {
|
|
12
|
+
SessionKeepAliveMode2["NONE"] = "NONE";
|
|
13
|
+
SessionKeepAliveMode2["ACTIVITY"] = "ACTIVITY";
|
|
14
|
+
SessionKeepAliveMode2["CONNECTION"] = "CONNECTION";
|
|
15
|
+
})(SessionKeepAliveMode ||= {});
|
|
13
16
|
|
|
14
17
|
class ConnectionInfo extends ServerInfo {
|
|
15
|
-
|
|
18
|
+
webSocketFactory;
|
|
16
19
|
maxConnectionAttempts;
|
|
17
|
-
|
|
20
|
+
sessionKeepAlive = "ACTIVITY" /* ACTIVITY */;
|
|
18
21
|
}
|
|
19
22
|
// packages/core/src/api/errors/KinoticError.ts
|
|
20
23
|
class KinoticError extends Error {
|
|
@@ -30,10 +33,8 @@ var EventConstants;
|
|
|
30
33
|
EventConstants2["CONTENT_TYPE_HEADER"] = "content-type";
|
|
31
34
|
EventConstants2["CONTENT_LENGTH_HEADER"] = "content-length";
|
|
32
35
|
EventConstants2["REPLY_TO_HEADER"] = "reply-to";
|
|
33
|
-
EventConstants2["REPLY_TO_ID_HEADER"] = "reply-to-id";
|
|
34
|
-
EventConstants2["SESSION_HEADER"] = "session";
|
|
35
36
|
EventConstants2["CONNECTED_INFO_HEADER"] = "connected-info";
|
|
36
|
-
EventConstants2["
|
|
37
|
+
EventConstants2["SESSION_KEEP_ALIVE_HEADER"] = "session-keep-alive";
|
|
37
38
|
EventConstants2["CORRELATION_ID_HEADER"] = "__correlation-id";
|
|
38
39
|
EventConstants2["ERROR_HEADER"] = "error";
|
|
39
40
|
EventConstants2["COMPLETE_HEADER"] = "complete";
|
|
@@ -46,6 +47,8 @@ var EventConstants;
|
|
|
46
47
|
EventConstants2["SERVICE_DESTINATION_SCHEME"] = "srv";
|
|
47
48
|
EventConstants2["STREAM_DESTINATION_PREFIX"] = "stream://";
|
|
48
49
|
EventConstants2["STREAM_DESTINATION_SCHEME"] = "stream";
|
|
50
|
+
EventConstants2["REPLY_DESTINATION_PREFIX"] = "reply://";
|
|
51
|
+
EventConstants2["REPLY_DESTINATION_SCHEME"] = "reply";
|
|
49
52
|
EventConstants2["CONTENT_JSON"] = "application/json";
|
|
50
53
|
EventConstants2["CONTENT_TEXT"] = "text/plain";
|
|
51
54
|
EventConstants2["TRACEPARENT_HEADER"] = "traceparent";
|
|
@@ -55,8 +58,8 @@ var EventConstants;
|
|
|
55
58
|
// packages/core/src/internal/api/event/StompConnectionManager.ts
|
|
56
59
|
import { RxStomp } from "@stomp/rx-stomp";
|
|
57
60
|
import { ReconnectionTimeMode } from "@stomp/stompjs";
|
|
58
|
-
import { v4 as uuidv4 } from "uuid";
|
|
59
61
|
import debug from "debug";
|
|
62
|
+
import { v4 as uuidv4 } from "uuid";
|
|
60
63
|
|
|
61
64
|
class StompConnectionManager {
|
|
62
65
|
lastWebsocketError = null;
|
|
@@ -69,9 +72,10 @@ class StompConnectionManager {
|
|
|
69
72
|
initialConnectionSuccessful = false;
|
|
70
73
|
debugLogger = debug("kinoitc:stomp");
|
|
71
74
|
uuidv4 = uuidv4();
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
_replyToCri = null;
|
|
76
|
+
serverHeadersSubscription = null;
|
|
74
77
|
deactivationHandler = null;
|
|
78
|
+
replyToCriChangedHandler = null;
|
|
75
79
|
get active() {
|
|
76
80
|
return !!this.rxStomp;
|
|
77
81
|
}
|
|
@@ -99,31 +103,23 @@ class StompConnectionManager {
|
|
|
99
103
|
this.initialConnectionSuccessful = false;
|
|
100
104
|
this.lastWebsocketError = null;
|
|
101
105
|
this.maxConnectionAttemptsReached = false;
|
|
106
|
+
this._replyToCri = null;
|
|
107
|
+
this.serverHeadersSubscription?.unsubscribe();
|
|
108
|
+
this.serverHeadersSubscription = null;
|
|
102
109
|
const url = "ws" + (connectionInfo.useSSL ? "s" : "") + "://" + connectionInfo.host + (connectionInfo.port ? ":" + connectionInfo.port : "") + "/v1";
|
|
103
110
|
this.rxStomp = new RxStomp;
|
|
104
|
-
let
|
|
111
|
+
let preparedSocket = null;
|
|
112
|
+
const userWebSocketFactory = connectionInfo.webSocketFactory;
|
|
105
113
|
const stompConfig = {
|
|
106
114
|
brokerURL: url,
|
|
107
|
-
connectHeaders:
|
|
115
|
+
connectHeaders: {
|
|
116
|
+
["session-keep-alive" /* SESSION_KEEP_ALIVE_HEADER */]: connectionInfo.sessionKeepAlive
|
|
117
|
+
},
|
|
108
118
|
heartbeatIncoming: 120000,
|
|
109
119
|
heartbeatOutgoing: 30000,
|
|
110
120
|
reconnectDelay: this.INITIAL_RECONNECT_DELAY,
|
|
121
|
+
webSocketFactory: userWebSocketFactory ? () => preparedSocket : undefined,
|
|
111
122
|
beforeConnect: async () => {
|
|
112
|
-
if (typeof connectionInfo.connectHeaders === "function") {
|
|
113
|
-
const headers = await connectionInfo.connectHeaders();
|
|
114
|
-
for (const key in headers) {
|
|
115
|
-
connectHeadersInternal[key] = headers[key];
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (connectionInfo.disableStickySession) {
|
|
119
|
-
connectHeadersInternal["disable-sticky-session" /* DISABLE_STICKY_SESSION_HEADER */] = "true";
|
|
120
|
-
}
|
|
121
|
-
if (connectHeadersInternal["reply-to-id" /* REPLY_TO_ID_HEADER */]) {
|
|
122
|
-
this.replyToId = connectHeadersInternal["reply-to-id" /* REPLY_TO_ID_HEADER */];
|
|
123
|
-
this._replyToCri = "srv://" /* SERVICE_DESTINATION_PREFIX */ + this.replyToId + ":" + this.uuidv4 + "@kinoitc.js.EventBus/replyHandler";
|
|
124
|
-
} else {
|
|
125
|
-
connectHeadersInternal["reply-to-id" /* REPLY_TO_ID_HEADER */] = this.replyToId;
|
|
126
|
-
}
|
|
127
123
|
if (connectionInfo?.maxConnectionAttempts) {
|
|
128
124
|
this.connectionAttempts++;
|
|
129
125
|
if (this.connectionAttempts > connectionInfo.maxConnectionAttempts) {
|
|
@@ -133,12 +129,23 @@ class StompConnectionManager {
|
|
|
133
129
|
let message = this.lastWebsocketError?.message ? this.lastWebsocketError?.message : "UNKNOWN";
|
|
134
130
|
reject(`Max number of reconnection attempts reached. Last WS Error ${message}`);
|
|
135
131
|
}
|
|
132
|
+
return;
|
|
136
133
|
} else {
|
|
137
134
|
await this.connectionJitterDelay();
|
|
138
135
|
}
|
|
139
136
|
} else {
|
|
140
137
|
await this.connectionJitterDelay();
|
|
141
138
|
}
|
|
139
|
+
if (userWebSocketFactory) {
|
|
140
|
+
try {
|
|
141
|
+
preparedSocket = await userWebSocketFactory();
|
|
142
|
+
} catch (e) {
|
|
143
|
+
await this.deactivate();
|
|
144
|
+
if (!this.initialConnectionSuccessful) {
|
|
145
|
+
reject(e);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
142
149
|
}
|
|
143
150
|
};
|
|
144
151
|
if (this.debugLogger.enabled) {
|
|
@@ -165,36 +172,29 @@ class StompConnectionManager {
|
|
|
165
172
|
this.rxStomp = null;
|
|
166
173
|
reject(message);
|
|
167
174
|
});
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (
|
|
173
|
-
|
|
174
|
-
if (connectedInfo.sessionId != null && connectedInfo.replyToId != null) {
|
|
175
|
-
if (connectionInfo.connectHeaders != null) {
|
|
176
|
-
for (let key in connectHeadersInternal) {
|
|
177
|
-
delete connectHeadersInternal[key];
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
connectHeadersInternal["session" /* SESSION_HEADER */] = connectedInfo.sessionId;
|
|
181
|
-
resolve(connectedInfo);
|
|
182
|
-
} else {
|
|
183
|
-
reject("Server did not return proper data for successful login");
|
|
184
|
-
}
|
|
185
|
-
} else if (typeof connectionInfo.connectHeaders === "function") {
|
|
186
|
-
for (let key in connectHeadersInternal) {
|
|
187
|
-
delete connectHeadersInternal[key];
|
|
188
|
-
}
|
|
189
|
-
if (!this.initialConnectionSuccessful) {
|
|
190
|
-
resolve(connectedInfo);
|
|
191
|
-
}
|
|
192
|
-
} else if (typeof connectionInfo.connectHeaders === "object") {
|
|
193
|
-
serverHeadersSubscription.unsubscribe();
|
|
194
|
-
resolve(connectedInfo);
|
|
175
|
+
this.serverHeadersSubscription = this.rxStomp.serverHeaders$.subscribe((value) => {
|
|
176
|
+
const connectedInfoJson = value["connected-info" /* CONNECTED_INFO_HEADER */];
|
|
177
|
+
const firstConnect = this._replyToCri == null;
|
|
178
|
+
if (connectedInfoJson == null) {
|
|
179
|
+
if (firstConnect) {
|
|
180
|
+
reject("Server did not return proper data for successful login");
|
|
195
181
|
}
|
|
196
|
-
|
|
197
|
-
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const connectedInfo = JSON.parse(connectedInfoJson);
|
|
185
|
+
if (connectedInfo.replyToId == null) {
|
|
186
|
+
if (firstConnect) {
|
|
187
|
+
reject("Server did not return a replyToId for successful login");
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const newReplyToCri = "reply://" /* REPLY_DESTINATION_PREFIX */ + connectedInfo.replyToId + ":" + this.uuidv4 + "@kinoitc.js.EventBus/replyHandler";
|
|
192
|
+
if (firstConnect) {
|
|
193
|
+
this._replyToCri = newReplyToCri;
|
|
194
|
+
resolve(connectedInfo);
|
|
195
|
+
} else if (this._replyToCri !== newReplyToCri) {
|
|
196
|
+
this._replyToCri = newReplyToCri;
|
|
197
|
+
this.replyToCriChangedHandler?.(newReplyToCri);
|
|
198
198
|
}
|
|
199
199
|
});
|
|
200
200
|
this.rxStomp.activate();
|
|
@@ -203,6 +203,8 @@ class StompConnectionManager {
|
|
|
203
203
|
async deactivate(force) {
|
|
204
204
|
if (this.rxStomp) {
|
|
205
205
|
await this.rxStomp.deactivate({ force });
|
|
206
|
+
this.serverHeadersSubscription?.unsubscribe();
|
|
207
|
+
this.serverHeadersSubscription = null;
|
|
206
208
|
if (this.deactivationHandler) {
|
|
207
209
|
this.deactivationHandler();
|
|
208
210
|
}
|
|
@@ -283,6 +285,10 @@ class EventBus {
|
|
|
283
285
|
this.stompConnectionManager.deactivationHandler = () => {
|
|
284
286
|
this.cleanup();
|
|
285
287
|
};
|
|
288
|
+
this.stompConnectionManager.replyToCriChangedHandler = (replyToCri) => {
|
|
289
|
+
this.replyToCri = replyToCri;
|
|
290
|
+
this.resetRequestReplies("Reply destination changed");
|
|
291
|
+
};
|
|
286
292
|
}
|
|
287
293
|
isConnectionActive() {
|
|
288
294
|
return this.stompConnectionManager.active;
|
|
@@ -350,7 +356,7 @@ class EventBus {
|
|
|
350
356
|
})).subscribe({
|
|
351
357
|
next(value) {
|
|
352
358
|
if (value.hasHeader("control" /* CONTROL_HEADER */)) {
|
|
353
|
-
if (value.headers.get("control" /* CONTROL_HEADER */) === "complete") {
|
|
359
|
+
if (value.headers.get("control" /* CONTROL_HEADER */) === "complete" /* CONTROL_VALUE_COMPLETE */) {
|
|
354
360
|
serverSignaledCompletion = true;
|
|
355
361
|
subscriber.complete();
|
|
356
362
|
} else {
|
|
@@ -394,8 +400,16 @@ class EventBus {
|
|
|
394
400
|
return this._observe(cri);
|
|
395
401
|
}
|
|
396
402
|
cleanup() {
|
|
403
|
+
this.resetRequestReplies("Connection disconnected");
|
|
404
|
+
if (this.errorSubjectSubscription) {
|
|
405
|
+
this.errorSubjectSubscription.unsubscribe();
|
|
406
|
+
this.errorSubjectSubscription = null;
|
|
407
|
+
}
|
|
408
|
+
this.serverInfo = null;
|
|
409
|
+
}
|
|
410
|
+
resetRequestReplies(reason) {
|
|
397
411
|
if (this.requestRepliesSubject != null) {
|
|
398
|
-
this.requestRepliesSubject.error(new Error(
|
|
412
|
+
this.requestRepliesSubject.error(new Error(reason));
|
|
399
413
|
if (this.requestRepliesSubscription != null) {
|
|
400
414
|
this.requestRepliesSubscription.unsubscribe();
|
|
401
415
|
this.requestRepliesSubscription = null;
|
|
@@ -403,11 +417,6 @@ class EventBus {
|
|
|
403
417
|
this.requestRepliesSubject = null;
|
|
404
418
|
this.requestRepliesObservable = null;
|
|
405
419
|
}
|
|
406
|
-
if (this.errorSubjectSubscription) {
|
|
407
|
-
this.errorSubjectSubscription.unsubscribe();
|
|
408
|
-
this.errorSubjectSubscription = null;
|
|
409
|
-
}
|
|
410
|
-
this.serverInfo = null;
|
|
411
420
|
}
|
|
412
421
|
createSendUnavailableError() {
|
|
413
422
|
let ret = "You must call connect on the event bus before sending any request";
|
|
@@ -894,7 +903,7 @@ import { first, map as map2 } from "rxjs/operators";
|
|
|
894
903
|
// packages/core/package.json
|
|
895
904
|
var package_default = {
|
|
896
905
|
name: "@kinotic-ai/core",
|
|
897
|
-
version: "1.
|
|
906
|
+
version: "1.3.1",
|
|
898
907
|
type: "module",
|
|
899
908
|
files: [
|
|
900
909
|
"dist"
|
|
@@ -1388,7 +1397,6 @@ class AuthorizationError extends KinoticError {
|
|
|
1388
1397
|
}
|
|
1389
1398
|
// packages/core/src/api/security/ConnectedInfo.ts
|
|
1390
1399
|
class ConnectedInfo {
|
|
1391
|
-
sessionId;
|
|
1392
1400
|
replyToId;
|
|
1393
1401
|
participant;
|
|
1394
1402
|
}
|
|
@@ -1423,6 +1431,7 @@ export {
|
|
|
1423
1431
|
Version,
|
|
1424
1432
|
TextEventFactory,
|
|
1425
1433
|
Sort,
|
|
1434
|
+
SessionKeepAliveMode,
|
|
1426
1435
|
ServiceRegistry,
|
|
1427
1436
|
ServerInfo,
|
|
1428
1437
|
Scope,
|
|
@@ -1450,7 +1459,6 @@ export {
|
|
|
1450
1459
|
Context,
|
|
1451
1460
|
ConnectionInfo,
|
|
1452
1461
|
ConnectedInfo,
|
|
1453
|
-
ConnectHeaders,
|
|
1454
1462
|
CONTEXT_METADATA_KEY,
|
|
1455
1463
|
AuthorizationError,
|
|
1456
1464
|
AuthenticationError,
|