@decaf-ts/for-http 0.3.51 → 0.3.53
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/for-http.cjs +1 -1
- package/dist/for-http.cjs.map +1 -1
- package/dist/for-http.js +1 -1
- package/dist/for-http.js.map +1 -1
- package/lib/HttpDispatcher.cjs +4 -10
- package/lib/HttpDispatcher.d.ts +1 -0
- package/lib/HttpDispatcher.js.map +1 -1
- package/lib/esm/HttpDispatcher.d.ts +1 -0
- package/lib/esm/HttpDispatcher.js +4 -10
- package/lib/esm/HttpDispatcher.js.map +1 -1
- package/lib/esm/event/ServerEventConnector.d.ts +8 -6
- package/lib/esm/event/ServerEventConnector.js +66 -32
- package/lib/esm/event/ServerEventConnector.js.map +1 -1
- package/lib/esm/event/types.d.ts +11 -4
- package/lib/esm/index.d.ts +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/event/ServerEventConnector.cjs +66 -32
- package/lib/event/ServerEventConnector.d.ts +8 -6
- package/lib/event/ServerEventConnector.js.map +1 -1
- package/lib/event/types.d.ts +11 -4
- package/lib/index.cjs +1 -1
- package/lib/index.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpDispatcher.js","sourceRoot":"","sources":["../src/HttpDispatcher.ts"],"names":[],"mappings":";;;AAAA,yCAQwB;AACxB,6CAA4D;
|
|
1
|
+
{"version":3,"file":"HttpDispatcher.js","sourceRoot":"","sources":["../src/HttpDispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { Adapter, Context, ContextualArgs, Dispatch, MaybeContextualArg, Prepare
|
|
|
2
2
|
import { HttpConfig, HttpFlags } from "./types";
|
|
3
3
|
export declare class HttpDispatcher extends Dispatch<Adapter<HttpConfig, any, PreparedStatement<any>, Context<HttpFlags>>> {
|
|
4
4
|
private connector?;
|
|
5
|
+
protected initialized: boolean;
|
|
5
6
|
private listening;
|
|
6
7
|
/**
|
|
7
8
|
* Called by the base Dispatch after observe(adapter).
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Dispatch, PersistenceKeys, } from "@decaf-ts/core";
|
|
2
2
|
import { ServerEventConnector } from "./event/index.js";
|
|
3
|
-
import { KeepAliveOperation } from "./constants.js";
|
|
4
3
|
export class HttpDispatcher extends Dispatch {
|
|
5
4
|
constructor() {
|
|
6
5
|
super(...arguments);
|
|
6
|
+
this.initialized = false;
|
|
7
7
|
this.listening = false;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
@@ -54,14 +54,10 @@ export class HttpDispatcher extends Dispatch {
|
|
|
54
54
|
log.info(`Opening ServerEventConnector for url: ${listeningUrl}`);
|
|
55
55
|
this.connector = ServerEventConnector.open(listeningUrl);
|
|
56
56
|
log.debug(`ServerEventConnector opened successfully for url: ${listeningUrl}`);
|
|
57
|
-
this.connector.
|
|
57
|
+
this.connector.addListener({
|
|
58
58
|
onEvent: async (event) => {
|
|
59
59
|
const [tableName, operation, id, ...args] = event;
|
|
60
60
|
const { log, ctxArgs } = (await this.logCtx(args, operation, true)).for("onEvent");
|
|
61
|
-
if (operation === KeepAliveOperation) {
|
|
62
|
-
log.debug(`keep alive received - discarding`);
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
61
|
super
|
|
66
62
|
.updateObservers(tableName, operation, id, ...ctxArgs)
|
|
67
63
|
.catch((e) => log.error(`ServerEventConnector failed to updateObservers`, e));
|
|
@@ -77,9 +73,7 @@ export class HttpDispatcher extends Dispatch {
|
|
|
77
73
|
this.listening = true;
|
|
78
74
|
log.info(`HttpDispatcher is now listening at ${listeningUrl}.`);
|
|
79
75
|
}
|
|
80
|
-
async close(
|
|
81
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
82
|
-
...args) {
|
|
76
|
+
async close(...args) {
|
|
83
77
|
// const { log } = this.logCtx(args, this.close);
|
|
84
78
|
//
|
|
85
79
|
// log.debug(`Closing HttpDispatcher`, {
|
|
@@ -88,7 +82,7 @@ export class HttpDispatcher extends Dispatch {
|
|
|
88
82
|
// initialized: this.initialized,
|
|
89
83
|
// adapter: this.adapter ? String(this.adapter) : undefined,
|
|
90
84
|
// });
|
|
91
|
-
this.connector?.close();
|
|
85
|
+
this.connector?.close(true);
|
|
92
86
|
this.listening = false;
|
|
93
87
|
}
|
|
94
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpDispatcher.js","sourceRoot":"","sources":["../../src/HttpDispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,QAAQ,EAER,eAAe,GAEhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAe,oBAAoB,EAAE,yBAAgB;
|
|
1
|
+
{"version":3,"file":"HttpDispatcher.js","sourceRoot":"","sources":["../../src/HttpDispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { EventHandlers } from "./types";
|
|
2
2
|
import { Context, ContextualLoggedClass } from "@decaf-ts/core";
|
|
3
|
+
export type ServerEventConnectorHeaders = Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
|
|
3
4
|
export declare class ServerEventConnector extends ContextualLoggedClass<Context<any>> {
|
|
4
5
|
private readonly url;
|
|
6
|
+
private readonly headers?;
|
|
5
7
|
private static readonly cache;
|
|
6
8
|
static get(url: string): ServerEventConnector;
|
|
7
|
-
static open(url: string): ServerEventConnector;
|
|
9
|
+
static open(url: string, headers?: ServerEventConnectorHeaders): ServerEventConnector;
|
|
8
10
|
static close(url: string): void;
|
|
9
11
|
private static parseReceivedEvent;
|
|
10
12
|
/** Shared connection state (cached singleton instance). */
|
|
11
13
|
private es?;
|
|
12
14
|
private controller?;
|
|
13
15
|
private listeners;
|
|
14
|
-
constructor(url: string);
|
|
16
|
+
constructor(url: string, headers?: ServerEventConnectorHeaders | undefined);
|
|
15
17
|
isOpen(): boolean;
|
|
16
|
-
close(): void;
|
|
18
|
+
close(force?: boolean): void;
|
|
17
19
|
/**
|
|
18
20
|
* Increments refCount and ensures EventSource is created.
|
|
19
21
|
* This method must be called only on the shared singleton instance.
|
|
20
22
|
*/
|
|
21
|
-
startListening
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
private startListening;
|
|
24
|
+
addListener(handlers: EventHandlers): () => void;
|
|
25
|
+
removeListener(handlers: EventHandlers): void;
|
|
24
26
|
}
|
|
@@ -8,10 +8,10 @@ export class ServerEventConnector extends ContextualLoggedClass {
|
|
|
8
8
|
return this.cache.get(url);
|
|
9
9
|
throw new Error(`Server event connector not found for URL '${url}'. Did you forget to call open()?`);
|
|
10
10
|
}
|
|
11
|
-
static open(url) {
|
|
11
|
+
static open(url, headers) {
|
|
12
12
|
if (this.cache.has(url))
|
|
13
13
|
return this.cache.get(url);
|
|
14
|
-
const connector = new ServerEventConnector(url);
|
|
14
|
+
const connector = new ServerEventConnector(url, headers);
|
|
15
15
|
this.cache.set(url, connector);
|
|
16
16
|
return this.cache.get(url);
|
|
17
17
|
}
|
|
@@ -29,39 +29,44 @@ export class ServerEventConnector extends ContextualLoggedClass {
|
|
|
29
29
|
const [eventName, operationKey, objectId, rawPayload] = data;
|
|
30
30
|
if (typeof eventName !== "string")
|
|
31
31
|
return null;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
:
|
|
32
|
+
let payload;
|
|
33
|
+
if (Array.isArray(rawPayload)) {
|
|
34
|
+
payload = rawPayload.map((item) => typeof item === "string" ? Serialization.deserialize(item) : item);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
payload =
|
|
38
|
+
typeof rawPayload === "string"
|
|
39
|
+
? Serialization.deserialize(rawPayload)
|
|
40
|
+
: rawPayload;
|
|
41
|
+
}
|
|
35
42
|
return [eventName, String(operationKey), objectId, payload];
|
|
36
43
|
}
|
|
37
44
|
catch {
|
|
38
45
|
return null;
|
|
39
46
|
}
|
|
40
47
|
}
|
|
41
|
-
constructor(url) {
|
|
48
|
+
constructor(url, headers) {
|
|
42
49
|
super();
|
|
43
50
|
this.url = url;
|
|
51
|
+
this.headers = headers;
|
|
44
52
|
this.listeners = new Set();
|
|
45
53
|
}
|
|
46
54
|
isOpen() {
|
|
47
55
|
return this.es !== undefined;
|
|
48
56
|
}
|
|
49
|
-
close() {
|
|
57
|
+
close(force = false) {
|
|
50
58
|
const log = this.log.for(this.close);
|
|
51
59
|
if (!this.es) {
|
|
52
|
-
log.debug(`Skipping
|
|
60
|
+
log.debug(`Skipping EventSource close — no open connection to ${this.url}`);
|
|
53
61
|
return;
|
|
54
62
|
}
|
|
55
|
-
if (this.listeners.size > 0) {
|
|
56
|
-
log.warn(`Skipping
|
|
57
|
-
url: this.url,
|
|
58
|
-
listeners: this.listeners.size,
|
|
59
|
-
});
|
|
63
|
+
if (this.listeners.size > 0 && !force) {
|
|
64
|
+
log.warn(`Skipping EventSource connection close ${this.url} — ${this.listeners.size} active listener(s) remaining.`);
|
|
60
65
|
return;
|
|
61
66
|
}
|
|
62
67
|
// Close and drop from cache.
|
|
63
68
|
try {
|
|
64
|
-
log.info(`
|
|
69
|
+
log.info(`Closing EventSource connection for listening URL ${this.url}`);
|
|
65
70
|
this.controller?.abort();
|
|
66
71
|
}
|
|
67
72
|
finally {
|
|
@@ -69,49 +74,51 @@ export class ServerEventConnector extends ContextualLoggedClass {
|
|
|
69
74
|
this.es = undefined;
|
|
70
75
|
this.listeners.clear();
|
|
71
76
|
ServerEventConnector.cache.delete(this.url);
|
|
72
|
-
log.info(`
|
|
77
|
+
log.info(`EventSource connection ${this.url} closed and removed from pool`);
|
|
73
78
|
}
|
|
74
79
|
}
|
|
75
80
|
/**
|
|
76
81
|
* Increments refCount and ensures EventSource is created.
|
|
77
82
|
* This method must be called only on the shared singleton instance.
|
|
78
83
|
*/
|
|
79
|
-
startListening(
|
|
84
|
+
startListening() {
|
|
80
85
|
const log = this.log.for(this.startListening);
|
|
81
86
|
if (this.es) {
|
|
82
|
-
log.info(`
|
|
83
|
-
url: this.url,
|
|
84
|
-
listeners: this.listeners.size,
|
|
85
|
-
});
|
|
87
|
+
log.info(`Listening address ${this.url} is already in the pool and listening. Skipping opening a new connection.`, { url: this.url, listeners: this.listeners.size });
|
|
86
88
|
return;
|
|
87
89
|
}
|
|
88
|
-
log.info(`Opening
|
|
90
|
+
log.info(`Opening EventSource connection to ${this.url}`);
|
|
89
91
|
this.es = new EventSourcePlus(this.url, {
|
|
90
|
-
headers,
|
|
92
|
+
...(this.headers && { headers: this.headers }),
|
|
91
93
|
credentials: "include",
|
|
92
94
|
});
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
96
|
+
const self = this;
|
|
93
97
|
this.controller = this.es.listen({
|
|
94
98
|
onResponse: () => {
|
|
95
|
-
log.info(`
|
|
99
|
+
log.info(`Connected to ${this.url}. Ready to receive events`);
|
|
96
100
|
},
|
|
97
101
|
onRequestError: ({ error }) => {
|
|
98
|
-
log.error(
|
|
102
|
+
log.error("Failed to establish EventSource connection", {
|
|
99
103
|
url: this.url,
|
|
100
104
|
error,
|
|
101
105
|
});
|
|
102
|
-
|
|
106
|
+
self.listeners.forEach((handler) => handler.onError(String(error?.message ?? error)));
|
|
103
107
|
},
|
|
104
108
|
onResponseError: ({ response }) => {
|
|
105
|
-
|
|
109
|
+
const status = response?.status;
|
|
110
|
+
const statusText = response?.statusText;
|
|
111
|
+
log.error("Listening failed with HTTP error response", {
|
|
106
112
|
url: this.url,
|
|
107
|
-
status
|
|
108
|
-
statusText
|
|
113
|
+
status,
|
|
114
|
+
statusText,
|
|
109
115
|
});
|
|
110
|
-
|
|
116
|
+
const err = new Error(`HTTP ${status ?? "unknown"} ${statusText ?? "error"}`);
|
|
117
|
+
self.listeners.forEach((handler) => handler.onError(err));
|
|
111
118
|
},
|
|
112
119
|
onMessage: (message) => {
|
|
113
120
|
if (message.event === "heartbeat") {
|
|
114
|
-
log.
|
|
121
|
+
log.debug(`Refresh connection. Heartbeat received.`);
|
|
115
122
|
return;
|
|
116
123
|
}
|
|
117
124
|
const raw = message && typeof message === "object" && "data" in message
|
|
@@ -125,15 +132,42 @@ export class ServerEventConnector extends ContextualLoggedClass {
|
|
|
125
132
|
});
|
|
126
133
|
return;
|
|
127
134
|
}
|
|
128
|
-
|
|
135
|
+
for (const handler of self.listeners) {
|
|
136
|
+
try {
|
|
137
|
+
handler.onEvent(event);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
log.error("Listener handler failed on event", { err });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
129
143
|
},
|
|
130
144
|
});
|
|
131
145
|
}
|
|
132
146
|
addListener(handlers) {
|
|
147
|
+
const log = this.log.for(this.addListener);
|
|
148
|
+
log.info(`Registering listener for connection ${this.url} — ${this.listeners.size} active listener(s)`);
|
|
149
|
+
this.startListening();
|
|
133
150
|
this.listeners.add(handlers);
|
|
151
|
+
log.info(`Listener registered for connection ${this.url} — total listener(s): ${this.listeners.size}`);
|
|
152
|
+
return () => this.removeListener(handlers);
|
|
134
153
|
}
|
|
135
154
|
removeListener(handlers) {
|
|
136
|
-
this.
|
|
155
|
+
const log = this.log.for(this.removeListener);
|
|
156
|
+
const existed = this.listeners.has(handlers);
|
|
157
|
+
log.info(`Unregistering listener for connection ${this.url}. Current active listeners: ${this.listeners.size}`, {
|
|
158
|
+
listenerFound: existed,
|
|
159
|
+
});
|
|
160
|
+
if (existed) {
|
|
161
|
+
this.listeners.delete(handlers);
|
|
162
|
+
log.debug(`Listener unregistered for connection ${this.url} — total listener(s): ${this.listeners.size}`);
|
|
163
|
+
}
|
|
164
|
+
if (this.listeners.size === 0) {
|
|
165
|
+
log.info(`No listeners remaining. Closing EventSource connection ${this.url}.`, {
|
|
166
|
+
url: this.url,
|
|
167
|
+
listeners: this.listeners.size,
|
|
168
|
+
});
|
|
169
|
+
this.close();
|
|
170
|
+
}
|
|
137
171
|
}
|
|
138
172
|
}
|
|
139
173
|
//# sourceMappingURL=ServerEventConnector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerEventConnector.js","sourceRoot":"","sources":["../../../src/event/ServerEventConnector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAW,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"ServerEventConnector.js","sourceRoot":"","sources":["../../../src/event/ServerEventConnector.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/event/types.d.ts
CHANGED
|
@@ -7,13 +7,20 @@ export type ServerRawMessage = SseMessage & {
|
|
|
7
7
|
data: string;
|
|
8
8
|
retry?: number;
|
|
9
9
|
};
|
|
10
|
-
export type
|
|
10
|
+
export type SingleServerEvent<T> = readonly [
|
|
11
11
|
modelName: string,
|
|
12
|
-
operation: OperationKeys |
|
|
12
|
+
operation: OperationKeys | string,
|
|
13
13
|
id: string,
|
|
14
|
-
payload:
|
|
14
|
+
payload: T
|
|
15
15
|
];
|
|
16
|
+
export type BulkServerEvent<T> = readonly [
|
|
17
|
+
modelName: string,
|
|
18
|
+
operation: BulkCrudOperationKeys,
|
|
19
|
+
id: string[],
|
|
20
|
+
payload: T[]
|
|
21
|
+
];
|
|
22
|
+
export type ServerEvent<T> = SingleServerEvent<T> | BulkServerEvent<T>;
|
|
16
23
|
export type EventHandlers = {
|
|
17
|
-
onEvent: ([tableName, operation, id]: ServerEvent) => void;
|
|
24
|
+
onEvent: ([tableName, operation, id]: ServerEvent<any>) => void;
|
|
18
25
|
onError: (err: unknown) => void;
|
|
19
26
|
};
|
package/lib/esm/index.d.ts
CHANGED
package/lib/esm/index.js
CHANGED
|
@@ -22,7 +22,7 @@ export * from "./event/index.js";
|
|
|
22
22
|
* @summary Version identifier for the module
|
|
23
23
|
* @const VERSION
|
|
24
24
|
*/
|
|
25
|
-
export const VERSION = "0.3.
|
|
25
|
+
export const VERSION = "0.3.53";
|
|
26
26
|
export const PACKAGE_NAME = "@decaf-ts/for-http";
|
|
27
27
|
Metadata.registerLibrary(PACKAGE_NAME, VERSION);
|
|
28
28
|
//# sourceMappingURL=index.js.map
|
|
@@ -11,10 +11,10 @@ class ServerEventConnector extends core_1.ContextualLoggedClass {
|
|
|
11
11
|
return this.cache.get(url);
|
|
12
12
|
throw new Error(`Server event connector not found for URL '${url}'. Did you forget to call open()?`);
|
|
13
13
|
}
|
|
14
|
-
static open(url) {
|
|
14
|
+
static open(url, headers) {
|
|
15
15
|
if (this.cache.has(url))
|
|
16
16
|
return this.cache.get(url);
|
|
17
|
-
const connector = new ServerEventConnector(url);
|
|
17
|
+
const connector = new ServerEventConnector(url, headers);
|
|
18
18
|
this.cache.set(url, connector);
|
|
19
19
|
return this.cache.get(url);
|
|
20
20
|
}
|
|
@@ -32,39 +32,44 @@ class ServerEventConnector extends core_1.ContextualLoggedClass {
|
|
|
32
32
|
const [eventName, operationKey, objectId, rawPayload] = data;
|
|
33
33
|
if (typeof eventName !== "string")
|
|
34
34
|
return null;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
:
|
|
35
|
+
let payload;
|
|
36
|
+
if (Array.isArray(rawPayload)) {
|
|
37
|
+
payload = rawPayload.map((item) => typeof item === "string" ? decorator_validation_1.Serialization.deserialize(item) : item);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
payload =
|
|
41
|
+
typeof rawPayload === "string"
|
|
42
|
+
? decorator_validation_1.Serialization.deserialize(rawPayload)
|
|
43
|
+
: rawPayload;
|
|
44
|
+
}
|
|
38
45
|
return [eventName, String(operationKey), objectId, payload];
|
|
39
46
|
}
|
|
40
47
|
catch {
|
|
41
48
|
return null;
|
|
42
49
|
}
|
|
43
50
|
}
|
|
44
|
-
constructor(url) {
|
|
51
|
+
constructor(url, headers) {
|
|
45
52
|
super();
|
|
46
53
|
this.url = url;
|
|
54
|
+
this.headers = headers;
|
|
47
55
|
this.listeners = new Set();
|
|
48
56
|
}
|
|
49
57
|
isOpen() {
|
|
50
58
|
return this.es !== undefined;
|
|
51
59
|
}
|
|
52
|
-
close() {
|
|
60
|
+
close(force = false) {
|
|
53
61
|
const log = this.log.for(this.close);
|
|
54
62
|
if (!this.es) {
|
|
55
|
-
log.debug(`Skipping
|
|
63
|
+
log.debug(`Skipping EventSource close — no open connection to ${this.url}`);
|
|
56
64
|
return;
|
|
57
65
|
}
|
|
58
|
-
if (this.listeners.size > 0) {
|
|
59
|
-
log.warn(`Skipping
|
|
60
|
-
url: this.url,
|
|
61
|
-
listeners: this.listeners.size,
|
|
62
|
-
});
|
|
66
|
+
if (this.listeners.size > 0 && !force) {
|
|
67
|
+
log.warn(`Skipping EventSource connection close ${this.url} — ${this.listeners.size} active listener(s) remaining.`);
|
|
63
68
|
return;
|
|
64
69
|
}
|
|
65
70
|
// Close and drop from cache.
|
|
66
71
|
try {
|
|
67
|
-
log.info(`
|
|
72
|
+
log.info(`Closing EventSource connection for listening URL ${this.url}`);
|
|
68
73
|
this.controller?.abort();
|
|
69
74
|
}
|
|
70
75
|
finally {
|
|
@@ -72,49 +77,51 @@ class ServerEventConnector extends core_1.ContextualLoggedClass {
|
|
|
72
77
|
this.es = undefined;
|
|
73
78
|
this.listeners.clear();
|
|
74
79
|
ServerEventConnector.cache.delete(this.url);
|
|
75
|
-
log.info(`
|
|
80
|
+
log.info(`EventSource connection ${this.url} closed and removed from pool`);
|
|
76
81
|
}
|
|
77
82
|
}
|
|
78
83
|
/**
|
|
79
84
|
* Increments refCount and ensures EventSource is created.
|
|
80
85
|
* This method must be called only on the shared singleton instance.
|
|
81
86
|
*/
|
|
82
|
-
startListening(
|
|
87
|
+
startListening() {
|
|
83
88
|
const log = this.log.for(this.startListening);
|
|
84
89
|
if (this.es) {
|
|
85
|
-
log.info(`
|
|
86
|
-
url: this.url,
|
|
87
|
-
listeners: this.listeners.size,
|
|
88
|
-
});
|
|
90
|
+
log.info(`Listening address ${this.url} is already in the pool and listening. Skipping opening a new connection.`, { url: this.url, listeners: this.listeners.size });
|
|
89
91
|
return;
|
|
90
92
|
}
|
|
91
|
-
log.info(`Opening
|
|
93
|
+
log.info(`Opening EventSource connection to ${this.url}`);
|
|
92
94
|
this.es = new event_source_plus_1.EventSourcePlus(this.url, {
|
|
93
|
-
headers,
|
|
95
|
+
...(this.headers && { headers: this.headers }),
|
|
94
96
|
credentials: "include",
|
|
95
97
|
});
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
99
|
+
const self = this;
|
|
96
100
|
this.controller = this.es.listen({
|
|
97
101
|
onResponse: () => {
|
|
98
|
-
log.info(`
|
|
102
|
+
log.info(`Connected to ${this.url}. Ready to receive events`);
|
|
99
103
|
},
|
|
100
104
|
onRequestError: ({ error }) => {
|
|
101
|
-
log.error(
|
|
105
|
+
log.error("Failed to establish EventSource connection", {
|
|
102
106
|
url: this.url,
|
|
103
107
|
error,
|
|
104
108
|
});
|
|
105
|
-
|
|
109
|
+
self.listeners.forEach((handler) => handler.onError(String(error?.message ?? error)));
|
|
106
110
|
},
|
|
107
111
|
onResponseError: ({ response }) => {
|
|
108
|
-
|
|
112
|
+
const status = response?.status;
|
|
113
|
+
const statusText = response?.statusText;
|
|
114
|
+
log.error("Listening failed with HTTP error response", {
|
|
109
115
|
url: this.url,
|
|
110
|
-
status
|
|
111
|
-
statusText
|
|
116
|
+
status,
|
|
117
|
+
statusText,
|
|
112
118
|
});
|
|
113
|
-
|
|
119
|
+
const err = new Error(`HTTP ${status ?? "unknown"} ${statusText ?? "error"}`);
|
|
120
|
+
self.listeners.forEach((handler) => handler.onError(err));
|
|
114
121
|
},
|
|
115
122
|
onMessage: (message) => {
|
|
116
123
|
if (message.event === "heartbeat") {
|
|
117
|
-
log.
|
|
124
|
+
log.debug(`Refresh connection. Heartbeat received.`);
|
|
118
125
|
return;
|
|
119
126
|
}
|
|
120
127
|
const raw = message && typeof message === "object" && "data" in message
|
|
@@ -128,15 +135,42 @@ class ServerEventConnector extends core_1.ContextualLoggedClass {
|
|
|
128
135
|
});
|
|
129
136
|
return;
|
|
130
137
|
}
|
|
131
|
-
|
|
138
|
+
for (const handler of self.listeners) {
|
|
139
|
+
try {
|
|
140
|
+
handler.onEvent(event);
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
log.error("Listener handler failed on event", { err });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
132
146
|
},
|
|
133
147
|
});
|
|
134
148
|
}
|
|
135
149
|
addListener(handlers) {
|
|
150
|
+
const log = this.log.for(this.addListener);
|
|
151
|
+
log.info(`Registering listener for connection ${this.url} — ${this.listeners.size} active listener(s)`);
|
|
152
|
+
this.startListening();
|
|
136
153
|
this.listeners.add(handlers);
|
|
154
|
+
log.info(`Listener registered for connection ${this.url} — total listener(s): ${this.listeners.size}`);
|
|
155
|
+
return () => this.removeListener(handlers);
|
|
137
156
|
}
|
|
138
157
|
removeListener(handlers) {
|
|
139
|
-
this.
|
|
158
|
+
const log = this.log.for(this.removeListener);
|
|
159
|
+
const existed = this.listeners.has(handlers);
|
|
160
|
+
log.info(`Unregistering listener for connection ${this.url}. Current active listeners: ${this.listeners.size}`, {
|
|
161
|
+
listenerFound: existed,
|
|
162
|
+
});
|
|
163
|
+
if (existed) {
|
|
164
|
+
this.listeners.delete(handlers);
|
|
165
|
+
log.debug(`Listener unregistered for connection ${this.url} — total listener(s): ${this.listeners.size}`);
|
|
166
|
+
}
|
|
167
|
+
if (this.listeners.size === 0) {
|
|
168
|
+
log.info(`No listeners remaining. Closing EventSource connection ${this.url}.`, {
|
|
169
|
+
url: this.url,
|
|
170
|
+
listeners: this.listeners.size,
|
|
171
|
+
});
|
|
172
|
+
this.close();
|
|
173
|
+
}
|
|
140
174
|
}
|
|
141
175
|
}
|
|
142
176
|
exports.ServerEventConnector = ServerEventConnector;
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { EventHandlers } from "./types";
|
|
2
2
|
import { Context, ContextualLoggedClass } from "@decaf-ts/core";
|
|
3
|
+
export type ServerEventConnectorHeaders = Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
|
|
3
4
|
export declare class ServerEventConnector extends ContextualLoggedClass<Context<any>> {
|
|
4
5
|
private readonly url;
|
|
6
|
+
private readonly headers?;
|
|
5
7
|
private static readonly cache;
|
|
6
8
|
static get(url: string): ServerEventConnector;
|
|
7
|
-
static open(url: string): ServerEventConnector;
|
|
9
|
+
static open(url: string, headers?: ServerEventConnectorHeaders): ServerEventConnector;
|
|
8
10
|
static close(url: string): void;
|
|
9
11
|
private static parseReceivedEvent;
|
|
10
12
|
/** Shared connection state (cached singleton instance). */
|
|
11
13
|
private es?;
|
|
12
14
|
private controller?;
|
|
13
15
|
private listeners;
|
|
14
|
-
constructor(url: string);
|
|
16
|
+
constructor(url: string, headers?: ServerEventConnectorHeaders | undefined);
|
|
15
17
|
isOpen(): boolean;
|
|
16
|
-
close(): void;
|
|
18
|
+
close(force?: boolean): void;
|
|
17
19
|
/**
|
|
18
20
|
* Increments refCount and ensures EventSource is created.
|
|
19
21
|
* This method must be called only on the shared singleton instance.
|
|
20
22
|
*/
|
|
21
|
-
startListening
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
private startListening;
|
|
24
|
+
addListener(handlers: EventHandlers): () => void;
|
|
25
|
+
removeListener(handlers: EventHandlers): void;
|
|
24
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerEventConnector.js","sourceRoot":"","sources":["../../src/event/ServerEventConnector.ts"],"names":[],"mappings":";;;AACA,yDAAoD;AACpD,yEAA+D;AAC/D,yCAAgE;
|
|
1
|
+
{"version":3,"file":"ServerEventConnector.js","sourceRoot":"","sources":["../../src/event/ServerEventConnector.ts"],"names":[],"mappings":"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"}
|