@venizia/ignis-helpers 0.2.0-4 → 0.2.0-5

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.
Files changed (33) hide show
  1. package/dist/cjs/modules/socket/websocket/server/delivery.d.ts +48 -0
  2. package/dist/cjs/modules/socket/websocket/server/delivery.d.ts.map +1 -0
  3. package/dist/cjs/modules/socket/websocket/server/delivery.js +206 -0
  4. package/dist/cjs/modules/socket/websocket/server/delivery.js.map +1 -0
  5. package/dist/cjs/modules/socket/websocket/server/helper.d.ts +2 -7
  6. package/dist/cjs/modules/socket/websocket/server/helper.d.ts.map +1 -1
  7. package/dist/cjs/modules/socket/websocket/server/helper.js +14 -181
  8. package/dist/cjs/modules/socket/websocket/server/helper.js.map +1 -1
  9. package/dist/cjs/utilities/index.d.ts +1 -0
  10. package/dist/cjs/utilities/index.d.ts.map +1 -1
  11. package/dist/cjs/utilities/index.js +1 -0
  12. package/dist/cjs/utilities/index.js.map +1 -1
  13. package/dist/cjs/utilities/slug.utility.d.ts +7 -0
  14. package/dist/cjs/utilities/slug.utility.d.ts.map +1 -0
  15. package/dist/cjs/utilities/slug.utility.js +21 -0
  16. package/dist/cjs/utilities/slug.utility.js.map +1 -0
  17. package/dist/esm/modules/socket/websocket/server/delivery.d.ts +48 -0
  18. package/dist/esm/modules/socket/websocket/server/delivery.d.ts.map +1 -0
  19. package/dist/esm/modules/socket/websocket/server/delivery.js +202 -0
  20. package/dist/esm/modules/socket/websocket/server/delivery.js.map +1 -0
  21. package/dist/esm/modules/socket/websocket/server/helper.d.ts +2 -7
  22. package/dist/esm/modules/socket/websocket/server/helper.d.ts.map +1 -1
  23. package/dist/esm/modules/socket/websocket/server/helper.js +14 -181
  24. package/dist/esm/modules/socket/websocket/server/helper.js.map +1 -1
  25. package/dist/esm/utilities/index.d.ts +1 -0
  26. package/dist/esm/utilities/index.d.ts.map +1 -1
  27. package/dist/esm/utilities/index.js +1 -0
  28. package/dist/esm/utilities/index.js.map +1 -1
  29. package/dist/esm/utilities/slug.utility.d.ts +7 -0
  30. package/dist/esm/utilities/slug.utility.d.ts.map +1 -0
  31. package/dist/esm/utilities/slug.utility.js +17 -0
  32. package/dist/esm/utilities/slug.utility.js.map +1 -0
  33. package/package.json +2 -2
@@ -0,0 +1,48 @@
1
+ import { BaseHelper } from '../../../../modules/base';
2
+ import { IBunServer, IWebSocketClient, TWebSocketOutboundTransformer } from '../common';
3
+ export interface IWebSocketDeliveryHelperOptions<MetadataType extends Record<string, unknown> = Record<string, unknown>> {
4
+ server: IBunServer;
5
+ /** Shared by reference with WebSocketServerHelper - never copy, both sides must see the same live maps. */
6
+ clients: Map<string, IWebSocketClient<MetadataType>>;
7
+ users: Map<string, Set<string>>;
8
+ rooms: Map<string, Set<string>>;
9
+ outboundTransformer?: TWebSocketOutboundTransformer<unknown, MetadataType>;
10
+ encryptedBatchLimit: number;
11
+ }
12
+ /** Local delivery and fan-out for the WebSocket server: single client, per-user, per-room, and broadcast. */
13
+ export declare class WebSocketDeliveryHelper<MetadataType extends Record<string, unknown> = Record<string, unknown>> extends BaseHelper {
14
+ private server;
15
+ private clients;
16
+ private users;
17
+ private rooms;
18
+ private outboundTransformer?;
19
+ private encryptedBatchLimit;
20
+ constructor(opts: IWebSocketDeliveryHelperOptions<MetadataType>);
21
+ sendToClient(opts: {
22
+ clientId: string;
23
+ event: string;
24
+ data: unknown;
25
+ doLog?: boolean;
26
+ }): void;
27
+ private sendToClientAsync;
28
+ private deliverToSocket;
29
+ sendToUser(opts: {
30
+ userId: string;
31
+ event: string;
32
+ data: unknown;
33
+ }): void;
34
+ private sendToRoomExcluding;
35
+ sendToRoom(opts: {
36
+ room: string;
37
+ event: string;
38
+ data: unknown;
39
+ exclude?: string[];
40
+ }): void;
41
+ private broadcastExcluding;
42
+ broadcast(opts: {
43
+ event: string;
44
+ data: unknown;
45
+ exclude?: string[];
46
+ }): void;
47
+ }
48
+ //# sourceMappingURL=delivery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../../../../../src/modules/socket/websocket/server/delivery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EACL,UAAU,EACV,gBAAgB,EAEhB,6BAA6B,EAG9B,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,+BAA+B,CAC9C,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEtE,MAAM,EAAE,UAAU,CAAC;IACnB,2GAA2G;IAC3G,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC;IACrD,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAChC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAChC,mBAAmB,CAAC,EAAE,6BAA6B,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC3E,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,6GAA6G;AAC7G,qBAAa,uBAAuB,CAClC,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CACtE,SAAQ,UAAU;IAClB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,OAAO,CAA8C;IAC7D,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,mBAAmB,CAAC,CAAuD;IACnF,OAAO,CAAC,mBAAmB,CAAS;gBAExB,IAAI,EAAE,+BAA+B,CAAC,YAAY,CAAC;IAW/D,YAAY,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;YAiCxE,iBAAiB;IAuB/B,OAAO,CAAC,eAAe;IA8BvB,UAAU,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE;IAYjE,OAAO,CAAC,mBAAmB;IA2C3B,UAAU,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;IAoCnF,OAAO,CAAC,kBAAkB;IAiB1B,SAAS,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;CAiCrE"}
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebSocketDeliveryHelper = void 0;
4
+ const base_1 = require("../../../../modules/base");
5
+ const utilities_1 = require("../../../../utilities");
6
+ const promise_utility_1 = require("../../../../utilities/promise.utility");
7
+ const common_1 = require("../common");
8
+ /** Local delivery and fan-out for the WebSocket server: single client, per-user, per-room, and broadcast. */
9
+ class WebSocketDeliveryHelper extends base_1.BaseHelper {
10
+ constructor(opts) {
11
+ super({ scope: WebSocketDeliveryHelper.name });
12
+ this.server = opts.server;
13
+ this.clients = opts.clients;
14
+ this.users = opts.users;
15
+ this.rooms = opts.rooms;
16
+ this.outboundTransformer = opts.outboundTransformer;
17
+ this.encryptedBatchLimit = opts.encryptedBatchLimit;
18
+ }
19
+ sendToClient(opts) {
20
+ const logger = this.logger.for(this.sendToClient.name);
21
+ const { clientId, event, data, doLog } = opts;
22
+ const client = this.clients.get(clientId);
23
+ if (!client) {
24
+ return;
25
+ }
26
+ // Async path - transformer intercepts before socket.send()
27
+ const outboundTransformer = this.outboundTransformer;
28
+ if (outboundTransformer && client.encrypted) {
29
+ Promise.resolve()
30
+ .then(() => outboundTransformer({ client, event, data }))
31
+ .then(transformed => {
32
+ const outboundMessage = transformed ?? { event, data };
33
+ this.deliverToSocket({
34
+ client,
35
+ payload: JSON.stringify(outboundMessage),
36
+ doLog,
37
+ event,
38
+ data,
39
+ });
40
+ })
41
+ .catch(error => {
42
+ logger.error('Outbound transformer error | id: %s | error: %s', clientId, error);
43
+ });
44
+ return;
45
+ }
46
+ // Sync path (unchanged, zero overhead when no transformer)
47
+ this.deliverToSocket({ client, payload: JSON.stringify({ event, data }), doLog, event, data });
48
+ }
49
+ async sendToClientAsync(opts) {
50
+ const { clientId, event, data } = opts;
51
+ const client = this.clients.get(clientId);
52
+ if (!client) {
53
+ return Promise.resolve();
54
+ }
55
+ if (!this.outboundTransformer || !client.encrypted) {
56
+ this.deliverToSocket({ client, payload: JSON.stringify({ event, data }), event, data });
57
+ return Promise.resolve();
58
+ }
59
+ try {
60
+ const transformed = await Promise.resolve(this.outboundTransformer({ client, event, data }));
61
+ const outboundMessage = transformed ?? { event, data };
62
+ this.deliverToSocket({ client, payload: JSON.stringify(outboundMessage), event, data });
63
+ }
64
+ catch (error) {
65
+ this.logger
66
+ .for(this.sendToClientAsync.name)
67
+ .error('Outbound transformer error | id: %s | error: %s', clientId, error);
68
+ }
69
+ }
70
+ deliverToSocket(opts) {
71
+ const logger = this.logger.for(this.deliverToSocket.name);
72
+ const { client, payload, doLog, event, data } = opts;
73
+ try {
74
+ const result = client.socket.send(payload);
75
+ if (result === 0) {
76
+ logger.warn('Message dropped (socket closed) | id: %s', client.id);
77
+ }
78
+ if (result === -1) {
79
+ client.backpressured = true;
80
+ logger.warn('Backpressure detected | id: %s', client.id);
81
+ }
82
+ }
83
+ catch (error) {
84
+ logger.error('Failed to send | id: %s | error: %s', client.id, error);
85
+ }
86
+ if (doLog) {
87
+ logger.info('Message sent | id: %s | event: %s | data: %j', client.id, event, data);
88
+ }
89
+ }
90
+ sendToUser(opts) {
91
+ const { userId, event, data } = opts;
92
+ const clientIds = this.users.get(userId);
93
+ if (!clientIds) {
94
+ return;
95
+ }
96
+ for (const clientId of clientIds) {
97
+ this.sendToClient({ clientId, event, data });
98
+ }
99
+ }
100
+ sendToRoomExcluding(opts) {
101
+ const { room, event, data, exclude } = opts;
102
+ const excludeSet = new Set(exclude);
103
+ const roomClientIds = this.rooms.get(room);
104
+ if (!roomClientIds) {
105
+ return;
106
+ }
107
+ // Serialised ONCE when there is no transformer, because the payload is then identical for every
108
+ // recipient - `sendToClient` would otherwise run `JSON.stringify` per client on a message that
109
+ // never differs. With a transformer each client's payload really is different, so that path
110
+ // still goes through `sendToClient`. The non-excluding fan-out already works this way.
111
+ if (!this.outboundTransformer) {
112
+ const payload = JSON.stringify({ event, data });
113
+ for (const clientId of roomClientIds) {
114
+ if (excludeSet.has(clientId)) {
115
+ continue;
116
+ }
117
+ const client = this.clients.get(clientId);
118
+ if (client) {
119
+ this.deliverToSocket({ client, payload, event, data });
120
+ }
121
+ }
122
+ return;
123
+ }
124
+ for (const clientId of roomClientIds) {
125
+ if (excludeSet.has(clientId)) {
126
+ continue;
127
+ }
128
+ this.sendToClient({ clientId, event, data });
129
+ }
130
+ }
131
+ sendToRoom(opts) {
132
+ const { room, event, data, exclude } = opts;
133
+ // When exclude is present, must iterate - can't exclude from Bun native pub/sub
134
+ if (exclude?.length) {
135
+ this.sendToRoomExcluding({ room, event, data, exclude });
136
+ return;
137
+ }
138
+ // No encryption - Bun native pub/sub O(1) C++ fan-out
139
+ if (!this.outboundTransformer) {
140
+ const payload = JSON.stringify({ event, data });
141
+ this.server.publish(room, payload);
142
+ return;
143
+ }
144
+ // Encryption enabled - iterate all clients individually with concurrency limit
145
+ const roomClientIds = this.rooms.get(room);
146
+ if (!roomClientIds) {
147
+ return;
148
+ }
149
+ const tasks = [];
150
+ for (const clientId of roomClientIds) {
151
+ tasks.push(() => this.sendToClientAsync({ clientId, event, data }));
152
+ }
153
+ if (tasks.length) {
154
+ (0, promise_utility_1.voidExecution)({
155
+ logger: this.logger,
156
+ scope: this.sendToRoom.name,
157
+ execution: (0, utilities_1.executePromiseWithLimit)({ tasks, limit: this.encryptedBatchLimit }),
158
+ });
159
+ }
160
+ }
161
+ broadcastExcluding(opts) {
162
+ const { event, data, exclude } = opts;
163
+ const excludeSet = new Set(exclude);
164
+ for (const [clientId, client] of this.clients) {
165
+ if (excludeSet.has(clientId)) {
166
+ continue;
167
+ }
168
+ // Only broadcast to authenticated clients (consistent with non-exclude path which uses BROADCAST_TOPIC)
169
+ if (client.state !== common_1.WebSocketClientStates.AUTHENTICATED) {
170
+ continue;
171
+ }
172
+ this.sendToClient({ clientId, event, data });
173
+ }
174
+ }
175
+ broadcast(opts) {
176
+ const { event, data, exclude } = opts;
177
+ // When exclude is present, must iterate - can't exclude from Bun native pub/sub
178
+ if (exclude?.length) {
179
+ this.broadcastExcluding({ event, data, exclude });
180
+ return;
181
+ }
182
+ // No encryption - Bun native pub/sub O(1) C++ fan-out
183
+ if (!this.outboundTransformer) {
184
+ const payload = JSON.stringify({ event, data });
185
+ this.server.publish(common_1.WebSocketDefaults.BROADCAST_TOPIC, payload);
186
+ return;
187
+ }
188
+ // Encryption enabled - iterate all clients individually with concurrency limit
189
+ const tasks = [];
190
+ for (const [clientId, client] of this.clients) {
191
+ if (client.state !== common_1.WebSocketClientStates.AUTHENTICATED) {
192
+ continue;
193
+ }
194
+ tasks.push(() => this.sendToClientAsync({ clientId, event, data }));
195
+ }
196
+ if (tasks.length) {
197
+ (0, promise_utility_1.voidExecution)({
198
+ logger: this.logger,
199
+ scope: this.broadcast.name,
200
+ execution: (0, utilities_1.executePromiseWithLimit)({ tasks, limit: this.encryptedBatchLimit }),
201
+ });
202
+ }
203
+ }
204
+ }
205
+ exports.WebSocketDeliveryHelper = WebSocketDeliveryHelper;
206
+ //# sourceMappingURL=delivery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../../../../../src/modules/socket/websocket/server/delivery.ts"],"names":[],"mappings":"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"}
@@ -12,11 +12,11 @@ export declare class WebSocketServerHelper<AuthDataType extends Record<string, u
12
12
  */
13
13
  private static toRoomList;
14
14
  private path;
15
- private server;
16
15
  private serverId;
17
16
  private clients;
18
17
  private users;
19
18
  private rooms;
19
+ private delivery;
20
20
  private redisPub;
21
21
  private redisSub;
22
22
  private authenticateFn;
@@ -24,7 +24,6 @@ export declare class WebSocketServerHelper<AuthDataType extends Record<string, u
24
24
  private onClientConnected?;
25
25
  private onClientDisconnected?;
26
26
  private messageHandler?;
27
- private outboundTransformer?;
28
27
  private handshakeFn?;
29
28
  private defaultRooms;
30
29
  private serverOptions;
@@ -32,7 +31,6 @@ export declare class WebSocketServerHelper<AuthDataType extends Record<string, u
32
31
  private heartbeatInterval;
33
32
  private heartbeatTimeout;
34
33
  private heartbeatTimer;
35
- private encryptedBatchLimit;
36
34
  private requireEncryption;
37
35
  constructor(opts: IWebSocketServerOptions<AuthDataType, MetadataType>);
38
36
  private initRedisClients;
@@ -82,27 +80,24 @@ export declare class WebSocketServerHelper<AuthDataType extends Record<string, u
82
80
  private handleAuthenticate;
83
81
  private handleJoin;
84
82
  private handleLeave;
83
+ /** Local delivery and fan-out live in WebSocketDeliveryHelper - kept public here by delegation. */
85
84
  sendToClient(opts: {
86
85
  clientId: string;
87
86
  event: string;
88
87
  data: unknown;
89
88
  doLog?: boolean;
90
89
  }): void;
91
- private sendToClientAsync;
92
- private deliverToSocket;
93
90
  sendToUser(opts: {
94
91
  userId: string;
95
92
  event: string;
96
93
  data: unknown;
97
94
  }): void;
98
- private sendToRoomExcluding;
99
95
  sendToRoom(opts: {
100
96
  room: string;
101
97
  event: string;
102
98
  data: unknown;
103
99
  exclude?: string[];
104
100
  }): void;
105
- private broadcastExcluding;
106
101
  broadcast(opts: {
107
102
  event: string;
108
103
  data: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../../../../../src/modules/socket/websocket/server/helper.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../../../../../src/modules/socket/websocket/server/helper.ts"],"names":[],"mappings":"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"}
@@ -5,9 +5,9 @@ const common_1 = require("../../../../common");
5
5
  const base_1 = require("../../../../modules/base");
6
6
  const error_1 = require("../../../../modules/error");
7
7
  const redis_1 = require("../../../../modules/redis");
8
- const utilities_1 = require("../../../../utilities");
9
8
  const promise_utility_1 = require("../../../../utilities/promise.utility");
10
9
  const common_2 = require("../common");
10
+ const delivery_1 = require("./delivery");
11
11
  class WebSocketServerHelper extends base_1.BaseHelper {
12
12
  /**
13
13
  * Narrows an untrusted room payload to the strings it actually contains.
@@ -31,14 +31,12 @@ class WebSocketServerHelper extends base_1.BaseHelper {
31
31
  this.heartbeatTimer = null;
32
32
  this.identifier = opts.identifier;
33
33
  this.path = opts.path ?? common_2.WebSocketDefaults.PATH;
34
- this.server = opts.server;
35
34
  this.serverId = crypto.randomUUID();
36
35
  this.authenticateFn = opts.authenticateFn;
37
36
  this.validateRoomFn = opts.validateRoomFn;
38
37
  this.onClientConnected = opts.clientConnectedFn;
39
38
  this.onClientDisconnected = opts.clientDisconnectedFn;
40
39
  this.messageHandler = opts.messageHandler;
41
- this.outboundTransformer = opts.outboundTransformer;
42
40
  this.handshakeFn = opts.handshakeFn;
43
41
  this.defaultRooms = opts.defaultRooms ?? [
44
42
  common_2.WebSocketDefaults.ROOM,
@@ -53,8 +51,15 @@ class WebSocketServerHelper extends base_1.BaseHelper {
53
51
  this.authTimeout = opts.authTimeout ?? common_2.WebSocketDefaults.AUTH_TIMEOUT;
54
52
  this.heartbeatInterval = opts.heartbeatInterval ?? common_2.WebSocketDefaults.HEARTBEAT_INTERVAL;
55
53
  this.heartbeatTimeout = opts.heartbeatTimeout ?? common_2.WebSocketDefaults.HEARTBEAT_TIMEOUT;
56
- this.encryptedBatchLimit = opts.encryptedBatchLimit ?? common_2.WebSocketDefaults.ENCRYPTED_BATCH_LIMIT;
57
54
  this.requireEncryption = opts.requireEncryption ?? false;
55
+ this.delivery = new delivery_1.WebSocketDeliveryHelper({
56
+ server: opts.server,
57
+ clients: this.clients,
58
+ users: this.users,
59
+ rooms: this.rooms,
60
+ outboundTransformer: opts.outboundTransformer,
61
+ encryptedBatchLimit: opts.encryptedBatchLimit ?? common_2.WebSocketDefaults.ENCRYPTED_BATCH_LIMIT,
62
+ });
58
63
  this.initRedisClients(opts.redisConnection);
59
64
  }
60
65
  initRedisClients(redisConnection) {
@@ -644,190 +649,18 @@ class WebSocketServerHelper extends base_1.BaseHelper {
644
649
  }
645
650
  logger.info('Left rooms | id: %s | rooms: %j', clientId, validRooms);
646
651
  }
652
+ /** Local delivery and fan-out live in WebSocketDeliveryHelper - kept public here by delegation. */
647
653
  sendToClient(opts) {
648
- const logger = this.logger.for(this.sendToClient.name);
649
- const { clientId, event, data, doLog } = opts;
650
- const client = this.clients.get(clientId);
651
- if (!client) {
652
- return;
653
- }
654
- // Async path - transformer intercepts before socket.send()
655
- const outboundTransformer = this.outboundTransformer;
656
- if (outboundTransformer && client.encrypted) {
657
- Promise.resolve()
658
- .then(() => outboundTransformer({ client, event, data }))
659
- .then(transformed => {
660
- const outboundMessage = transformed ?? { event, data };
661
- this.deliverToSocket({
662
- client,
663
- payload: JSON.stringify(outboundMessage),
664
- doLog,
665
- event,
666
- data,
667
- });
668
- })
669
- .catch(error => {
670
- logger.error('Outbound transformer error | id: %s | error: %s', clientId, error);
671
- });
672
- return;
673
- }
674
- // Sync path (unchanged, zero overhead when no transformer)
675
- this.deliverToSocket({ client, payload: JSON.stringify({ event, data }), doLog, event, data });
676
- }
677
- async sendToClientAsync(opts) {
678
- const { clientId, event, data } = opts;
679
- const client = this.clients.get(clientId);
680
- if (!client) {
681
- return Promise.resolve();
682
- }
683
- if (!this.outboundTransformer || !client.encrypted) {
684
- this.deliverToSocket({ client, payload: JSON.stringify({ event, data }), event, data });
685
- return Promise.resolve();
686
- }
687
- try {
688
- const transformed = await Promise.resolve(this.outboundTransformer({ client, event, data }));
689
- const outboundMessage = transformed ?? { event, data };
690
- this.deliverToSocket({ client, payload: JSON.stringify(outboundMessage), event, data });
691
- }
692
- catch (error) {
693
- this.logger
694
- .for(this.sendToClientAsync.name)
695
- .error('Outbound transformer error | id: %s | error: %s', clientId, error);
696
- }
697
- }
698
- deliverToSocket(opts) {
699
- const logger = this.logger.for(this.deliverToSocket.name);
700
- const { client, payload, doLog, event, data } = opts;
701
- try {
702
- const result = client.socket.send(payload);
703
- if (result === 0) {
704
- logger.warn('Message dropped (socket closed) | id: %s', client.id);
705
- }
706
- if (result === -1) {
707
- client.backpressured = true;
708
- logger.warn('Backpressure detected | id: %s', client.id);
709
- }
710
- }
711
- catch (error) {
712
- logger.error('Failed to send | id: %s | error: %s', client.id, error);
713
- }
714
- if (doLog) {
715
- logger.info('Message sent | id: %s | event: %s | data: %j', client.id, event, data);
716
- }
654
+ this.delivery.sendToClient(opts);
717
655
  }
718
656
  sendToUser(opts) {
719
- const { userId, event, data } = opts;
720
- const clientIds = this.users.get(userId);
721
- if (!clientIds) {
722
- return;
723
- }
724
- for (const clientId of clientIds) {
725
- this.sendToClient({ clientId, event, data });
726
- }
727
- }
728
- sendToRoomExcluding(opts) {
729
- const { room, event, data, exclude } = opts;
730
- const excludeSet = new Set(exclude);
731
- const roomClientIds = this.rooms.get(room);
732
- if (!roomClientIds) {
733
- return;
734
- }
735
- // Serialised ONCE when there is no transformer, because the payload is then identical for every
736
- // recipient - `sendToClient` would otherwise run `JSON.stringify` per client on a message that
737
- // never differs. With a transformer each client's payload really is different, so that path
738
- // still goes through `sendToClient`. The non-excluding fan-out already works this way.
739
- if (!this.outboundTransformer) {
740
- const payload = JSON.stringify({ event, data });
741
- for (const clientId of roomClientIds) {
742
- if (excludeSet.has(clientId)) {
743
- continue;
744
- }
745
- const client = this.clients.get(clientId);
746
- if (client) {
747
- this.deliverToSocket({ client, payload, event, data });
748
- }
749
- }
750
- return;
751
- }
752
- for (const clientId of roomClientIds) {
753
- if (excludeSet.has(clientId)) {
754
- continue;
755
- }
756
- this.sendToClient({ clientId, event, data });
757
- }
657
+ this.delivery.sendToUser(opts);
758
658
  }
759
659
  sendToRoom(opts) {
760
- const { room, event, data, exclude } = opts;
761
- // When exclude is present, must iterate - can't exclude from Bun native pub/sub
762
- if (exclude?.length) {
763
- this.sendToRoomExcluding({ room, event, data, exclude });
764
- return;
765
- }
766
- // No encryption - Bun native pub/sub O(1) C++ fan-out
767
- if (!this.outboundTransformer) {
768
- const payload = JSON.stringify({ event, data });
769
- this.server.publish(room, payload);
770
- return;
771
- }
772
- // Encryption enabled - iterate all clients individually with concurrency limit
773
- const roomClientIds = this.rooms.get(room);
774
- if (!roomClientIds) {
775
- return;
776
- }
777
- const tasks = [];
778
- for (const clientId of roomClientIds) {
779
- tasks.push(() => this.sendToClientAsync({ clientId, event, data }));
780
- }
781
- if (tasks.length) {
782
- (0, promise_utility_1.voidExecution)({
783
- logger: this.logger,
784
- scope: this.sendToRoom.name,
785
- execution: (0, utilities_1.executePromiseWithLimit)({ tasks, limit: this.encryptedBatchLimit }),
786
- });
787
- }
788
- }
789
- broadcastExcluding(opts) {
790
- const { event, data, exclude } = opts;
791
- const excludeSet = new Set(exclude);
792
- for (const [clientId, client] of this.clients) {
793
- if (excludeSet.has(clientId)) {
794
- continue;
795
- }
796
- // Only broadcast to authenticated clients (consistent with non-exclude path which uses BROADCAST_TOPIC)
797
- if (client.state !== common_2.WebSocketClientStates.AUTHENTICATED) {
798
- continue;
799
- }
800
- this.sendToClient({ clientId, event, data });
801
- }
660
+ this.delivery.sendToRoom(opts);
802
661
  }
803
662
  broadcast(opts) {
804
- const { event, data, exclude } = opts;
805
- // When exclude is present, must iterate - can't exclude from Bun native pub/sub
806
- if (exclude?.length) {
807
- this.broadcastExcluding({ event, data, exclude });
808
- return;
809
- }
810
- // No encryption - Bun native pub/sub O(1) C++ fan-out
811
- if (!this.outboundTransformer) {
812
- const payload = JSON.stringify({ event, data });
813
- this.server.publish(common_2.WebSocketDefaults.BROADCAST_TOPIC, payload);
814
- return;
815
- }
816
- // Encryption enabled - iterate all clients individually with concurrency limit
817
- const tasks = [];
818
- for (const [clientId, client] of this.clients) {
819
- if (client.state !== common_2.WebSocketClientStates.AUTHENTICATED) {
820
- continue;
821
- }
822
- tasks.push(() => this.sendToClientAsync({ clientId, event, data }));
823
- }
824
- if (tasks.length) {
825
- (0, promise_utility_1.voidExecution)({
826
- logger: this.logger,
827
- scope: this.broadcast.name,
828
- execution: (0, utilities_1.executePromiseWithLimit)({ tasks, limit: this.encryptedBatchLimit }),
829
- });
830
- }
663
+ this.delivery.broadcast(opts);
831
664
  }
832
665
  send(opts) {
833
666
  const logger = this.logger.for(this.send.name);