@xbg.solutions/utils-realtime-connector 1.0.0

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/lib/index.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Realtime Connector Barrel Export
3
+ */
4
+ export * from './types';
5
+ export * from './realtime-connector';
6
+ export * from './providers/sse-provider';
7
+ export * from './providers/websocket-provider';
8
+ import { RealtimeConnector } from './realtime-connector';
9
+ export declare function initializeRealtimeConnector(config: any): void;
10
+ export declare function createRealtimeConnector(): RealtimeConnector | null;
11
+ export declare function getRealtimeConnector(): RealtimeConnector | null;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAOzD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAI7D;AAED,wBAAgB,uBAAuB,IAAI,iBAAiB,GAAG,IAAI,CAwBlE;AAID,wBAAgB,oBAAoB,IAAI,iBAAiB,GAAG,IAAI,CAK/D"}
package/lib/index.js ADDED
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ /**
3
+ * Realtime Connector Barrel Export
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
17
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.initializeRealtimeConnector = initializeRealtimeConnector;
21
+ exports.createRealtimeConnector = createRealtimeConnector;
22
+ exports.getRealtimeConnector = getRealtimeConnector;
23
+ __exportStar(require("./types"), exports);
24
+ __exportStar(require("./realtime-connector"), exports);
25
+ __exportStar(require("./providers/sse-provider"), exports);
26
+ __exportStar(require("./providers/websocket-provider"), exports);
27
+ const realtime_connector_1 = require("./realtime-connector");
28
+ const sse_provider_1 = require("./providers/sse-provider");
29
+ const websocket_provider_1 = require("./providers/websocket-provider");
30
+ // Config is provided via initializeRealtimeConnector() at app startup
31
+ let connectorConfig = null;
32
+ function initializeRealtimeConnector(config) {
33
+ connectorConfig = config;
34
+ // Reset singleton so it gets re-created with new config
35
+ realtimeConnectorInstance = undefined;
36
+ }
37
+ function createRealtimeConnector() {
38
+ if (!connectorConfig) {
39
+ throw new Error('Realtime connector not initialized. Call initializeRealtimeConnector() first.');
40
+ }
41
+ if (!connectorConfig.realtime.enabled) {
42
+ return null;
43
+ }
44
+ const provider = connectorConfig.realtime.provider;
45
+ if (provider === 'sse') {
46
+ const config = connectorConfig.realtime.providers.sse;
47
+ return new realtime_connector_1.RealtimeConnector(new sse_provider_1.SSEProvider(config === null || config === void 0 ? void 0 : config.heartbeatInterval));
48
+ }
49
+ if (provider === 'websocket') {
50
+ const config = connectorConfig.realtime.providers.websocket;
51
+ return new realtime_connector_1.RealtimeConnector(new websocket_provider_1.WebSocketProvider((config === null || config === void 0 ? void 0 : config.port) || 8080, config === null || config === void 0 ? void 0 : config.path));
52
+ }
53
+ throw new Error(`Unsupported realtime provider: ${provider}`);
54
+ }
55
+ let realtimeConnectorInstance;
56
+ function getRealtimeConnector() {
57
+ if (realtimeConnectorInstance === undefined) {
58
+ realtimeConnectorInstance = createRealtimeConnector();
59
+ }
60
+ return realtimeConnectorInstance;
61
+ }
62
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAcH,kEAIC;AAED,0DAwBC;AAID,oDAKC;AAnDD,0CAAwB;AACxB,uDAAqC;AACrC,2DAAyC;AACzC,iEAA+C;AAE/C,6DAAyD;AACzD,2DAAuD;AACvD,uEAAmE;AAEnE,sEAAsE;AACtE,IAAI,eAAe,GAAQ,IAAI,CAAC;AAEhC,SAAgB,2BAA2B,CAAC,MAAW;IACrD,eAAe,GAAG,MAAM,CAAC;IACzB,wDAAwD;IACxD,yBAAyB,GAAG,SAAS,CAAC;AACxC,CAAC;AAED,SAAgB,uBAAuB;IACrC,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC;IACnG,CAAC;IAED,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAEnD,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC;QACtD,OAAO,IAAI,sCAAiB,CAAC,IAAI,0BAAW,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,iBAAiB,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC;QAC5D,OAAO,IAAI,sCAAiB,CAC1B,IAAI,sCAAiB,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,KAAI,IAAI,EAAE,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,CAAC,CAC1D,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,IAAI,yBAA+D,CAAC;AAEpE,SAAgB,oBAAoB;IAClC,IAAI,yBAAyB,KAAK,SAAS,EAAE,CAAC;QAC5C,yBAAyB,GAAG,uBAAuB,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,yBAAyB,CAAC;AACnC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * SSE (Server-Sent Events) Provider
3
+ */
4
+ import { Response } from 'express';
5
+ import { RealtimeProvider } from '../realtime-connector';
6
+ import { RealtimeMessage, RealtimeClient, BroadcastOptions } from '../types';
7
+ export declare class SSEProvider implements RealtimeProvider {
8
+ private clients;
9
+ private heartbeatInterval;
10
+ constructor(heartbeatInterval?: number);
11
+ addClient(clientId: string, res: Response, client: RealtimeClient): void;
12
+ broadcast(message: RealtimeMessage, options?: BroadcastOptions): Promise<void>;
13
+ sendToClient(clientId: string, message: RealtimeMessage): Promise<void>;
14
+ sendToUser(userId: string, message: RealtimeMessage): Promise<void>;
15
+ sendToChannel(channel: string, message: RealtimeMessage): Promise<void>;
16
+ getConnectedClients(): RealtimeClient[];
17
+ disconnect(clientId: string): Promise<void>;
18
+ private formatSSE;
19
+ private startHeartbeat;
20
+ }
21
+ //# sourceMappingURL=sse-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-provider.d.ts","sourceRoot":"","sources":["../../src/providers/sse-provider.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE7E,qBAAa,WAAY,YAAW,gBAAgB;IAClD,OAAO,CAAC,OAAO,CAAqE;IACpF,OAAO,CAAC,iBAAiB,CAAS;gBAEtB,iBAAiB,SAAQ;IAKrC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI;IASlE,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9E,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvE,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IASnE,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7E,mBAAmB,IAAI,cAAc,EAAE;IAIjC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjD,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,cAAc;CAOvB"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ /**
3
+ * SSE (Server-Sent Events) Provider
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SSEProvider = void 0;
7
+ class SSEProvider {
8
+ constructor(heartbeatInterval = 30000) {
9
+ this.clients = new Map();
10
+ this.heartbeatInterval = heartbeatInterval;
11
+ this.startHeartbeat();
12
+ }
13
+ addClient(clientId, res, client) {
14
+ this.clients.set(clientId, { res, client });
15
+ res.writeHead(200, {
16
+ 'Content-Type': 'text/event-stream',
17
+ 'Cache-Control': 'no-cache',
18
+ 'Connection': 'keep-alive',
19
+ });
20
+ }
21
+ async broadcast(message, options) {
22
+ const formatted = this.formatSSE(message);
23
+ for (const [clientId, { res, client }] of this.clients.entries()) {
24
+ if ((options === null || options === void 0 ? void 0 : options.excludeClient) && clientId === options.excludeClient)
25
+ continue;
26
+ if ((options === null || options === void 0 ? void 0 : options.channel) && !client.channels.includes(options.channel))
27
+ continue;
28
+ if ((options === null || options === void 0 ? void 0 : options.userId) && client.userId !== options.userId)
29
+ continue;
30
+ res.write(formatted);
31
+ }
32
+ }
33
+ async sendToClient(clientId, message) {
34
+ const entry = this.clients.get(clientId);
35
+ if (entry) {
36
+ entry.res.write(this.formatSSE(message));
37
+ }
38
+ }
39
+ async sendToUser(userId, message) {
40
+ const formatted = this.formatSSE(message);
41
+ for (const { res, client } of this.clients.values()) {
42
+ if (client.userId === userId) {
43
+ res.write(formatted);
44
+ }
45
+ }
46
+ }
47
+ async sendToChannel(channel, message) {
48
+ const formatted = this.formatSSE(message);
49
+ for (const { res, client } of this.clients.values()) {
50
+ if (client.channels.includes(channel)) {
51
+ res.write(formatted);
52
+ }
53
+ }
54
+ }
55
+ getConnectedClients() {
56
+ return Array.from(this.clients.values()).map(({ client }) => client);
57
+ }
58
+ async disconnect(clientId) {
59
+ const entry = this.clients.get(clientId);
60
+ if (entry) {
61
+ entry.res.end();
62
+ this.clients.delete(clientId);
63
+ }
64
+ }
65
+ formatSSE(message) {
66
+ return `id: ${message.id}\nevent: ${message.type}\ndata: ${JSON.stringify(message.data)}\n\n`;
67
+ }
68
+ startHeartbeat() {
69
+ setInterval(() => {
70
+ for (const { res } of this.clients.values()) {
71
+ res.write(':heartbeat\n\n');
72
+ }
73
+ }, this.heartbeatInterval);
74
+ }
75
+ }
76
+ exports.SSEProvider = SSEProvider;
77
+ //# sourceMappingURL=sse-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-provider.js","sourceRoot":"","sources":["../../src/providers/sse-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * WebSocket Provider
3
+ */
4
+ import { RealtimeProvider } from '../realtime-connector';
5
+ import { RealtimeMessage, RealtimeClient, BroadcastOptions } from '../types';
6
+ export declare class WebSocketProvider implements RealtimeProvider {
7
+ private wss;
8
+ private clients;
9
+ constructor(port: number, path?: string);
10
+ private setupServer;
11
+ private handleMessage;
12
+ broadcast(message: RealtimeMessage, options?: BroadcastOptions): Promise<void>;
13
+ sendToClient(clientId: string, message: RealtimeMessage): Promise<void>;
14
+ sendToUser(userId: string, message: RealtimeMessage): Promise<void>;
15
+ sendToChannel(channel: string, message: RealtimeMessage): Promise<void>;
16
+ getConnectedClients(): RealtimeClient[];
17
+ disconnect(clientId: string): Promise<void>;
18
+ private generateClientId;
19
+ }
20
+ //# sourceMappingURL=websocket-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-provider.d.ts","sourceRoot":"","sources":["../../src/providers/websocket-provider.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE7E,qBAAa,iBAAkB,YAAW,gBAAgB;IACxD,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,OAAO,CAAqE;gBAExE,IAAI,EAAE,MAAM,EAAE,IAAI,SAAQ;IAKtC,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,aAAa;IAcf,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAY9E,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvE,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IASnE,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7E,mBAAmB,IAAI,cAAc,EAAE;IAIjC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjD,OAAO,CAAC,gBAAgB;CAGzB"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ /**
3
+ * WebSocket Provider
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WebSocketProvider = void 0;
7
+ const ws_1 = require("ws");
8
+ class WebSocketProvider {
9
+ constructor(port, path = '/ws') {
10
+ this.clients = new Map();
11
+ this.wss = new ws_1.WebSocketServer({ port, path });
12
+ this.setupServer();
13
+ }
14
+ setupServer() {
15
+ this.wss.on('connection', (ws) => {
16
+ const clientId = this.generateClientId();
17
+ const client = { id: clientId, channels: [] };
18
+ this.clients.set(clientId, { ws, client });
19
+ ws.on('message', (data) => this.handleMessage(clientId, data.toString()));
20
+ ws.on('close', () => this.clients.delete(clientId));
21
+ ws.send(JSON.stringify({ type: 'connected', clientId }));
22
+ });
23
+ }
24
+ handleMessage(clientId, data) {
25
+ try {
26
+ const message = JSON.parse(data);
27
+ if (message.type === 'subscribe' && message.channel) {
28
+ const entry = this.clients.get(clientId);
29
+ if (entry && !entry.client.channels.includes(message.channel)) {
30
+ entry.client.channels.push(message.channel);
31
+ }
32
+ }
33
+ }
34
+ catch (error) {
35
+ // Invalid message
36
+ }
37
+ }
38
+ async broadcast(message, options) {
39
+ const data = JSON.stringify(message);
40
+ for (const [clientId, { ws, client }] of this.clients.entries()) {
41
+ if ((options === null || options === void 0 ? void 0 : options.excludeClient) && clientId === options.excludeClient)
42
+ continue;
43
+ if ((options === null || options === void 0 ? void 0 : options.channel) && !client.channels.includes(options.channel))
44
+ continue;
45
+ if ((options === null || options === void 0 ? void 0 : options.userId) && client.userId !== options.userId)
46
+ continue;
47
+ if (ws.readyState === ws_1.WebSocket.OPEN) {
48
+ ws.send(data);
49
+ }
50
+ }
51
+ }
52
+ async sendToClient(clientId, message) {
53
+ const entry = this.clients.get(clientId);
54
+ if (entry && entry.ws.readyState === ws_1.WebSocket.OPEN) {
55
+ entry.ws.send(JSON.stringify(message));
56
+ }
57
+ }
58
+ async sendToUser(userId, message) {
59
+ const data = JSON.stringify(message);
60
+ for (const { ws, client } of this.clients.values()) {
61
+ if (client.userId === userId && ws.readyState === ws_1.WebSocket.OPEN) {
62
+ ws.send(data);
63
+ }
64
+ }
65
+ }
66
+ async sendToChannel(channel, message) {
67
+ const data = JSON.stringify(message);
68
+ for (const { ws, client } of this.clients.values()) {
69
+ if (client.channels.includes(channel) && ws.readyState === ws_1.WebSocket.OPEN) {
70
+ ws.send(data);
71
+ }
72
+ }
73
+ }
74
+ getConnectedClients() {
75
+ return Array.from(this.clients.values()).map(({ client }) => client);
76
+ }
77
+ async disconnect(clientId) {
78
+ const entry = this.clients.get(clientId);
79
+ if (entry) {
80
+ entry.ws.close();
81
+ this.clients.delete(clientId);
82
+ }
83
+ }
84
+ generateClientId() {
85
+ return `client_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
86
+ }
87
+ }
88
+ exports.WebSocketProvider = WebSocketProvider;
89
+ //# sourceMappingURL=websocket-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-provider.js","sourceRoot":"","sources":["../../src/providers/websocket-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Realtime Connector
3
+ * Manages real-time connections via SSE or WebSocket
4
+ */
5
+ import { RealtimeMessage, RealtimeClient, BroadcastOptions } from './types';
6
+ export interface RealtimeProvider {
7
+ broadcast(message: RealtimeMessage, options?: BroadcastOptions): Promise<void>;
8
+ sendToClient(clientId: string, message: RealtimeMessage): Promise<void>;
9
+ sendToUser(userId: string, message: RealtimeMessage): Promise<void>;
10
+ sendToChannel(channel: string, message: RealtimeMessage): Promise<void>;
11
+ getConnectedClients(): RealtimeClient[];
12
+ disconnect(clientId: string): Promise<void>;
13
+ }
14
+ export declare class RealtimeConnector {
15
+ private provider;
16
+ constructor(provider: RealtimeProvider);
17
+ broadcast(message: RealtimeMessage, options?: BroadcastOptions): Promise<void>;
18
+ sendToClient(clientId: string, message: RealtimeMessage): Promise<void>;
19
+ sendToUser(userId: string, message: RealtimeMessage): Promise<void>;
20
+ sendToChannel(channel: string, message: RealtimeMessage): Promise<void>;
21
+ getConnectedClients(): RealtimeClient[];
22
+ disconnect(clientId: string): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=realtime-connector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-connector.d.ts","sourceRoot":"","sources":["../src/realtime-connector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG5E,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,mBAAmB,IAAI,cAAc,EAAE,CAAC;IACxC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAmB;gBAEvB,QAAQ,EAAE,gBAAgB;IAIhC,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9E,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7E,mBAAmB,IAAI,cAAc,EAAE;IAIjC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGlD"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * Realtime Connector
4
+ * Manages real-time connections via SSE or WebSocket
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.RealtimeConnector = void 0;
8
+ const utils_logger_1 = require("@xbg/utils-logger");
9
+ class RealtimeConnector {
10
+ constructor(provider) {
11
+ this.provider = provider;
12
+ }
13
+ async broadcast(message, options) {
14
+ utils_logger_1.logger.info('Broadcasting message', { type: message.type, options });
15
+ return this.provider.broadcast(message, options);
16
+ }
17
+ async sendToClient(clientId, message) {
18
+ return this.provider.sendToClient(clientId, message);
19
+ }
20
+ async sendToUser(userId, message) {
21
+ return this.provider.sendToUser(userId, message);
22
+ }
23
+ async sendToChannel(channel, message) {
24
+ return this.provider.sendToChannel(channel, message);
25
+ }
26
+ getConnectedClients() {
27
+ return this.provider.getConnectedClients();
28
+ }
29
+ async disconnect(clientId) {
30
+ return this.provider.disconnect(clientId);
31
+ }
32
+ }
33
+ exports.RealtimeConnector = RealtimeConnector;
34
+ //# sourceMappingURL=realtime-connector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-connector.js","sourceRoot":"","sources":["../src/realtime-connector.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,oDAA2C;AAW3C,MAAa,iBAAiB;IAG5B,YAAY,QAA0B;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,OAAwB,EAAE,OAA0B;QAClE,qBAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE,OAAwB;QAC3D,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,OAAwB;QACvD,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAe,EAAE,OAAwB;QAC3D,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAED,mBAAmB;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,QAAgB;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;CACF;AA/BD,8CA+BC"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Realtime Connector Types
3
+ * For SSE and WebSocket real-time communication
4
+ */
5
+ export interface RealtimeMessage {
6
+ id: string;
7
+ type: string;
8
+ data: any;
9
+ timestamp: Date;
10
+ }
11
+ export interface RealtimeClient {
12
+ id: string;
13
+ userId?: string;
14
+ channels: string[];
15
+ metadata?: Record<string, any>;
16
+ }
17
+ export interface BroadcastOptions {
18
+ channel?: string;
19
+ userId?: string;
20
+ excludeClient?: string;
21
+ }
22
+ export interface SSEResponse {
23
+ write: (data: string) => void;
24
+ end: () => void;
25
+ }
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,GAAG,CAAC;IACV,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB"}
package/lib/types.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Realtime Connector Types
4
+ * For SSE and WebSocket real-time communication
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@xbg.solutions/utils-realtime-connector",
3
+ "version": "1.0.0",
4
+ "description": "SSE and WebSocket providers",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "files": [
8
+ "lib"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "build:watch": "tsc --watch",
13
+ "clean": "rm -rf lib",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "dependencies": {
17
+ "@xbg/utils-logger": "^1.0.0",
18
+ "ws": "^8.15.0"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^20.11.0",
22
+ "@types/ws": "^8.5.10",
23
+ "typescript": "^5.3.3"
24
+ },
25
+ "engines": {
26
+ "node": "22"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ }
31
+ }