@flowcore/sdk 1.10.3 → 1.11.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/CHANGELOG.md +113 -83
- package/README.md +655 -18
- package/esm/_dnt.shims.d.ts +9 -0
- package/esm/_dnt.shims.d.ts.map +1 -0
- package/esm/_dnt.shims.js +64 -0
- package/esm/common/notification-client.d.ts +80 -0
- package/esm/common/notification-client.d.ts.map +1 -0
- package/esm/common/notification-client.js +213 -0
- package/esm/mod.d.ts +1 -0
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +1 -0
- package/esm/utils/logger.d.ts +8 -0
- package/esm/utils/logger.d.ts.map +1 -0
- package/esm/utils/logger.js +14 -0
- package/package.json +7 -3
- package/script/_dnt.shims.d.ts +9 -0
- package/script/_dnt.shims.d.ts.map +1 -0
- package/script/_dnt.shims.js +72 -0
- package/script/common/notification-client.d.ts +80 -0
- package/script/common/notification-client.d.ts.map +1 -0
- package/script/common/notification-client.js +240 -0
- package/script/mod.d.ts +1 -0
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +1 -0
- package/script/utils/logger.d.ts +8 -0
- package/script/utils/logger.d.ts.map +1 -0
- package/script/utils/logger.js +17 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.NotificationClient = void 0;
|
|
27
|
+
const dntShim = __importStar(require("../_dnt.shims.js"));
|
|
28
|
+
const mod_js_1 = require("../mod.js");
|
|
29
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
30
|
+
const flowcore_client_js_1 = require("./flowcore-client.js");
|
|
31
|
+
const node_buffer_1 = require("node:buffer");
|
|
32
|
+
// Maximum reconnection interval in milliseconds
|
|
33
|
+
const MAX_RECONNECT_INTERVAL = 30_000;
|
|
34
|
+
/**
|
|
35
|
+
* Client for handling WebSocket connections to the Flowcore notification system.
|
|
36
|
+
* Manages connection lifecycle, authentication, and event handling.
|
|
37
|
+
*/
|
|
38
|
+
class NotificationClient {
|
|
39
|
+
/**
|
|
40
|
+
* Creates a new NotificationClient instance
|
|
41
|
+
* @param observer - RxJS Subject for emitting notification events
|
|
42
|
+
* @param oidcClient - Client for handling OIDC authentication
|
|
43
|
+
* @param subscriptionSpec - Specification for what notifications to subscribe to
|
|
44
|
+
* @param options - Configuration options for the client
|
|
45
|
+
*/
|
|
46
|
+
constructor(observer, oidcClient, subscriptionSpec, options) {
|
|
47
|
+
Object.defineProperty(this, "observer", {
|
|
48
|
+
enumerable: true,
|
|
49
|
+
configurable: true,
|
|
50
|
+
writable: true,
|
|
51
|
+
value: observer
|
|
52
|
+
});
|
|
53
|
+
Object.defineProperty(this, "oidcClient", {
|
|
54
|
+
enumerable: true,
|
|
55
|
+
configurable: true,
|
|
56
|
+
writable: true,
|
|
57
|
+
value: oidcClient
|
|
58
|
+
});
|
|
59
|
+
Object.defineProperty(this, "subscriptionSpec", {
|
|
60
|
+
enumerable: true,
|
|
61
|
+
configurable: true,
|
|
62
|
+
writable: true,
|
|
63
|
+
value: subscriptionSpec
|
|
64
|
+
});
|
|
65
|
+
Object.defineProperty(this, "url", {
|
|
66
|
+
enumerable: true,
|
|
67
|
+
configurable: true,
|
|
68
|
+
writable: true,
|
|
69
|
+
value: "wss://tenant.api.flowcore.io/notifications"
|
|
70
|
+
});
|
|
71
|
+
Object.defineProperty(this, "webSocket", {
|
|
72
|
+
enumerable: true,
|
|
73
|
+
configurable: true,
|
|
74
|
+
writable: true,
|
|
75
|
+
value: void 0
|
|
76
|
+
});
|
|
77
|
+
Object.defineProperty(this, "options", {
|
|
78
|
+
enumerable: true,
|
|
79
|
+
configurable: true,
|
|
80
|
+
writable: true,
|
|
81
|
+
value: void 0
|
|
82
|
+
});
|
|
83
|
+
Object.defineProperty(this, "logger", {
|
|
84
|
+
enumerable: true,
|
|
85
|
+
configurable: true,
|
|
86
|
+
writable: true,
|
|
87
|
+
value: void 0
|
|
88
|
+
});
|
|
89
|
+
Object.defineProperty(this, "eventCount", {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
configurable: true,
|
|
92
|
+
writable: true,
|
|
93
|
+
value: 0
|
|
94
|
+
});
|
|
95
|
+
Object.defineProperty(this, "reconnectInterval", {
|
|
96
|
+
enumerable: true,
|
|
97
|
+
configurable: true,
|
|
98
|
+
writable: true,
|
|
99
|
+
value: void 0
|
|
100
|
+
});
|
|
101
|
+
Object.defineProperty(this, "reconnectAttempts", {
|
|
102
|
+
enumerable: true,
|
|
103
|
+
configurable: true,
|
|
104
|
+
writable: true,
|
|
105
|
+
value: 0
|
|
106
|
+
});
|
|
107
|
+
this.options = {
|
|
108
|
+
reconnectInterval: 1000,
|
|
109
|
+
...options,
|
|
110
|
+
};
|
|
111
|
+
this.logger = options?.logger ?? logger_js_1.defaultLogger;
|
|
112
|
+
this.reconnectInterval = options?.reconnectInterval ?? 1000;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Establishes WebSocket connection and sets up event handlers
|
|
116
|
+
*/
|
|
117
|
+
async connect() {
|
|
118
|
+
const token = await this.oidcClient.getToken();
|
|
119
|
+
const flowcoreClient = new flowcore_client_js_1.FlowcoreClient({
|
|
120
|
+
getBearerToken: () => Promise.resolve(token.accessToken),
|
|
121
|
+
});
|
|
122
|
+
const tenant = await flowcoreClient.execute(new mod_js_1.TenantFetchCommand({
|
|
123
|
+
tenant: this.subscriptionSpec.tenant,
|
|
124
|
+
}));
|
|
125
|
+
const dataCore = await flowcoreClient.execute(new mod_js_1.DataCoreFetchCommand({
|
|
126
|
+
tenantId: tenant.id,
|
|
127
|
+
dataCore: this.subscriptionSpec.dataCore,
|
|
128
|
+
}));
|
|
129
|
+
let flowType;
|
|
130
|
+
let eventType;
|
|
131
|
+
if (this.subscriptionSpec.flowType) {
|
|
132
|
+
flowType = await flowcoreClient.execute(new mod_js_1.FlowTypeFetchCommand({
|
|
133
|
+
dataCoreId: dataCore.id,
|
|
134
|
+
flowType: this.subscriptionSpec.flowType,
|
|
135
|
+
}));
|
|
136
|
+
if (this.subscriptionSpec.eventType) {
|
|
137
|
+
eventType = await flowcoreClient.execute(new mod_js_1.EventTypeFetchCommand({
|
|
138
|
+
flowTypeId: flowType?.id,
|
|
139
|
+
eventType: this.subscriptionSpec.eventType,
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
this.webSocket = new dntShim.WebSocket(`${this.url}?token=${encodeURIComponent(token.accessToken)}`);
|
|
144
|
+
this.webSocket.onopen = () => {
|
|
145
|
+
this.logger.info("WebSocket connection opened.");
|
|
146
|
+
this.reconnectInterval = this.options.reconnectInterval;
|
|
147
|
+
this.reconnectAttempts = 0;
|
|
148
|
+
this.webSocket.send(JSON.stringify({
|
|
149
|
+
tenant: this.subscriptionSpec.tenant,
|
|
150
|
+
dataCoreId: dataCore.id,
|
|
151
|
+
flowTypeId: flowType?.id,
|
|
152
|
+
eventTypeId: eventType?.id,
|
|
153
|
+
}));
|
|
154
|
+
};
|
|
155
|
+
this.webSocket.onmessage = (event) => {
|
|
156
|
+
let parsedData;
|
|
157
|
+
if (event.data instanceof ArrayBuffer) {
|
|
158
|
+
parsedData = new TextDecoder().decode(event.data);
|
|
159
|
+
}
|
|
160
|
+
else if (node_buffer_1.Buffer.isBuffer(event.data)) {
|
|
161
|
+
parsedData = event.data.toString();
|
|
162
|
+
}
|
|
163
|
+
else if (Array.isArray(event.data)) {
|
|
164
|
+
// Handle Buffer arrays by concatenating them
|
|
165
|
+
parsedData = node_buffer_1.Buffer.concat(event.data).toString();
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
parsedData = event.data;
|
|
169
|
+
}
|
|
170
|
+
const data = JSON.parse(parsedData);
|
|
171
|
+
if (data.type === "validation") {
|
|
172
|
+
this.logger.error(`Bad request: ${data.summary} - ${data.message} - ${data.found} - ${data.errors}`);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const parsed = JSON.parse(data.message);
|
|
176
|
+
this.logger.debug(`Received event: ${parsed.pattern}`);
|
|
177
|
+
this.observer.next({
|
|
178
|
+
pattern: parsed.pattern,
|
|
179
|
+
data: {
|
|
180
|
+
tenant: parsed.data.tenantId,
|
|
181
|
+
eventId: parsed.data.eventId,
|
|
182
|
+
dataCoreId: parsed.data.dataCore,
|
|
183
|
+
flowType: parsed.data.aggregator,
|
|
184
|
+
eventType: parsed.data.eventType,
|
|
185
|
+
validTime: parsed.data.validTime,
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
this.eventCount++;
|
|
189
|
+
if (this.options.maxEvents && this.options.maxEvents <= this.eventCount) {
|
|
190
|
+
this.observer.complete();
|
|
191
|
+
this.eventCount = 0;
|
|
192
|
+
this.webSocket.close(1000, "Max events received");
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
this.webSocket.onclose = (event) => {
|
|
196
|
+
this.logger.info(`Connection closed: Code [${event.code}], Reason: ${event.reason}`);
|
|
197
|
+
if (event.code !== 1000) {
|
|
198
|
+
this.attemptReconnect();
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
this.observer.complete();
|
|
202
|
+
};
|
|
203
|
+
this.webSocket.onerror = (error) => {
|
|
204
|
+
this.logger.error(`WebSocket encountered error: ${error}`);
|
|
205
|
+
this.observer.error(error);
|
|
206
|
+
this.webSocket.close();
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Attempts to reconnect to the WebSocket server using exponential backoff
|
|
211
|
+
*/
|
|
212
|
+
attemptReconnect() {
|
|
213
|
+
if (this.options.maxReconnects && this.reconnectAttempts >= this.options.maxReconnects) {
|
|
214
|
+
this.logger.error(`Max reconnect attempts ${this.reconnectAttempts}/${this.options.maxReconnects} reached. Giving up.`);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
this.reconnectAttempts++;
|
|
218
|
+
this.logger.info(`Attempting reconnection ${this.reconnectAttempts}${this.options.maxReconnects ? `/${this.options.maxReconnects}` : ""} in ${this.reconnectInterval} ms...`);
|
|
219
|
+
setTimeout(() => {
|
|
220
|
+
this.connect();
|
|
221
|
+
}, this.reconnectInterval);
|
|
222
|
+
this.reconnectInterval = Math.min(MAX_RECONNECT_INTERVAL, this.reconnectInterval * 2);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Closes the WebSocket connection
|
|
226
|
+
*/
|
|
227
|
+
disconnect() {
|
|
228
|
+
if (this.webSocket) {
|
|
229
|
+
this.webSocket.close();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Overrides the base WebSocket URL for testing or different environments
|
|
234
|
+
* @param url - The new base URL to use
|
|
235
|
+
*/
|
|
236
|
+
overrideBaseUrl(url) {
|
|
237
|
+
this.url = url;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
exports.NotificationClient = NotificationClient;
|
package/script/mod.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./commands/index.js";
|
|
2
2
|
export * from "./common/command.js";
|
|
3
3
|
export * from "./common/flowcore-client.js";
|
|
4
|
+
export * from "./common/notification-client.js";
|
|
4
5
|
export * from "./contracts/index.js";
|
|
5
6
|
export * from "./exceptions/index.js";
|
|
6
7
|
export * from "./utils/parse-response-helper.js";
|
package/script/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,kCAAkC,CAAA"}
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,kCAAkC,CAAA"}
|
package/script/mod.js
CHANGED
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./commands/index.js"), exports);
|
|
18
18
|
__exportStar(require("./common/command.js"), exports);
|
|
19
19
|
__exportStar(require("./common/flowcore-client.js"), exports);
|
|
20
|
+
__exportStar(require("./common/notification-client.js"), exports);
|
|
20
21
|
__exportStar(require("./contracts/index.js"), exports);
|
|
21
22
|
__exportStar(require("./exceptions/index.js"), exports);
|
|
22
23
|
__exportStar(require("./utils/parse-response-helper.js"), exports);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type Logger = {
|
|
2
|
+
debug: (message: string, meta?: Record<string, unknown>) => void;
|
|
3
|
+
info: (message: string, meta?: Record<string, unknown>) => void;
|
|
4
|
+
warn: (message: string, meta?: Record<string, unknown>) => void;
|
|
5
|
+
error: (message: string | Error, meta?: Record<string, unknown>) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare const defaultLogger: Logger;
|
|
8
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IAChE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IAC/D,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IAC/D,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;CACzE,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,MAa3B,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultLogger = void 0;
|
|
4
|
+
exports.defaultLogger = {
|
|
5
|
+
debug: (message, meta) => {
|
|
6
|
+
console.debug(message, meta);
|
|
7
|
+
},
|
|
8
|
+
info: (message, meta) => {
|
|
9
|
+
console.info(message, meta);
|
|
10
|
+
},
|
|
11
|
+
warn: (message, meta) => {
|
|
12
|
+
console.warn(message, meta);
|
|
13
|
+
},
|
|
14
|
+
error: (message, meta) => {
|
|
15
|
+
console.error(message, meta);
|
|
16
|
+
},
|
|
17
|
+
};
|