topsyde-utils 1.0.87 → 1.0.89

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.d.ts CHANGED
@@ -42,4 +42,4 @@ export { ControllerResponse, ControllerAction, ControllerMap, ControllerOptions
42
42
  export { Routes } from "./server/bun/router/routes";
43
43
  export { I_WebsocketConstructor } from "./server/bun/websocket/Websocket";
44
44
  export { E_WebsocketMessageType } from "./server/bun/websocket/websocket.enums";
45
- export { WebsocketMessage, WebsocketChannel, WebsocketStructuredMessage, WebsocketEntityData, I_WebsocketEntity, I_WebsocketClient, I_WebsocketChannelEntity, I_WebsocketChannel, I_WebsocketInterface, } from "./server/bun/websocket/websocket.types";
45
+ export { WebsocketMessage, WebsocketChannel, WebsocketStructuredMessage, WebsocketEntityData, I_WebsocketEntity, I_WebsocketClient, I_WebsocketChannelEntity, BroadcastOptions, I_WebsocketChannel, I_WebsocketInterface, } from "./server/bun/websocket/websocket.types";
@@ -1,5 +1,5 @@
1
1
  import Websocket from "./Websocket";
2
- import type { I_WebsocketChannel, I_WebsocketClient, I_WebsocketEntity, WebsocketChannel, WebsocketStructuredMessage } from "./websocket.types";
2
+ import type { BroadcastOptions, I_WebsocketChannel, I_WebsocketClient, I_WebsocketEntity, WebsocketChannel, WebsocketStructuredMessage } from "./websocket.types";
3
3
  export default class Channel<T extends Websocket = Websocket> implements I_WebsocketChannel<T> {
4
4
  createdAt: Date;
5
5
  id: string;
@@ -8,8 +8,10 @@ export default class Channel<T extends Websocket = Websocket> implements I_Webso
8
8
  members: Map<string, I_WebsocketClient>;
9
9
  metadata: Record<string, string>;
10
10
  ws: T;
11
+ private messageTemplate;
11
12
  constructor(id: string, name: string, ws: T, limit?: number, members?: Map<string, I_WebsocketClient>, metadata?: Record<string, string>);
12
- broadcast<T = any>(message: WebsocketStructuredMessage, ...args: T[]): void;
13
+ broadcast(message: WebsocketStructuredMessage, options?: BroadcastOptions): void;
14
+ private getFilteredMetadata;
13
15
  hasMember(client: I_WebsocketEntity | string): boolean;
14
16
  addMember(client: I_WebsocketClient): false | I_WebsocketClient;
15
17
  removeMember(entity: I_WebsocketEntity): false | I_WebsocketClient;
@@ -10,9 +10,124 @@ class Channel {
10
10
  this.members = members ?? new Map();
11
11
  this.metadata = metadata ?? {};
12
12
  this.ws = ws;
13
+ // Initialize message template
14
+ this.messageTemplate = {
15
+ type: "",
16
+ content: {},
17
+ channel: this.id,
18
+ timestamp: "",
19
+ };
13
20
  }
14
- broadcast(message, ...args) {
15
- this.ws.server.publish(this.id, JSON.stringify({ message, ...args }));
21
+ broadcast(message, options) {
22
+ // Clone the template (faster than creating new objects)
23
+ const output = Object.assign({}, this.messageTemplate);
24
+ // Set the dynamic properties in a single pass
25
+ output.type = message.type;
26
+ output.channel = this.id;
27
+ // Process message content based on type
28
+ if (typeof message.content === "string") {
29
+ output.content = { message: message.content };
30
+ }
31
+ else if (typeof message.content === "object" && message.content !== null) {
32
+ output.content = { ...message.content };
33
+ }
34
+ else {
35
+ output.content = {};
36
+ }
37
+ // Process options in a single pass if provided
38
+ if (options) {
39
+ // Add data if provided
40
+ if (options.data !== undefined) {
41
+ if (typeof options.data === "object" && options.data !== null && !Array.isArray(options.data)) {
42
+ // Merge object data with content
43
+ Object.assign(output.content, options.data);
44
+ }
45
+ else {
46
+ // Set as data property for other types
47
+ output.content.data = options.data;
48
+ }
49
+ }
50
+ // Add client information if provided
51
+ if (options.client) {
52
+ output.content.client = options.client;
53
+ }
54
+ // Include channel metadata if requested
55
+ if (options.includeMetadata) {
56
+ output.metadata = options.includeMetadata === true ? this.getMetadata() : this.getFilteredMetadata(options.includeMetadata);
57
+ }
58
+ // Add timestamp if requested (default: true)
59
+ if (options.includeTimestamp !== false) {
60
+ output.timestamp = new Date().toISOString();
61
+ }
62
+ else {
63
+ // Remove timestamp if explicitly disabled
64
+ delete output.timestamp;
65
+ }
66
+ // Add sender information if requested
67
+ if (options.includeSender) {
68
+ if (typeof options.includeSender === "boolean") {
69
+ // Use channel as client
70
+ output.client = {
71
+ id: this.id,
72
+ name: this.name,
73
+ };
74
+ }
75
+ else {
76
+ // Use provided sender object as client
77
+ output.client = options.includeSender;
78
+ }
79
+ }
80
+ // Add priority if specified
81
+ if (options.priority !== undefined) {
82
+ output.priority = options.priority;
83
+ }
84
+ // Add expiration if specified
85
+ if (options.expiresAt !== undefined) {
86
+ output.expiresAt = options.expiresAt;
87
+ }
88
+ // Add any custom fields to the root of the message
89
+ if (options.customFields) {
90
+ Object.assign(output, options.customFields);
91
+ }
92
+ // Apply custom transformation if provided
93
+ if (options.transform) {
94
+ const transformed = options.transform(output);
95
+ // Publish the transformed output
96
+ this.ws.server.publish(this.id, JSON.stringify(transformed));
97
+ return;
98
+ }
99
+ // Handle excluded clients if needed
100
+ if (options.excludeClients && options.excludeClients.length > 0) {
101
+ // For large channels with many excluded clients, it might be more efficient
102
+ // to send directly to each client instead of using channel publish
103
+ if (this.members.size > 10 && options.excludeClients.length > this.members.size / 3) {
104
+ const serializedMessage = JSON.stringify(output);
105
+ for (const [clientId, client] of this.members) {
106
+ if (!options.excludeClients.includes(clientId)) {
107
+ client.ws.send(serializedMessage);
108
+ }
109
+ }
110
+ return;
111
+ }
112
+ }
113
+ }
114
+ else {
115
+ // Default timestamp behavior when no options provided
116
+ output.timestamp = new Date().toISOString();
117
+ }
118
+ // Publish to the channel
119
+ this.ws.server.publish(this.id, JSON.stringify(output));
120
+ }
121
+ // Helper method for filtered metadata
122
+ getFilteredMetadata(keys) {
123
+ const metadata = this.getMetadata();
124
+ const filtered = {};
125
+ for (const key of keys) {
126
+ if (metadata[key] !== undefined) {
127
+ filtered[key] = metadata[key];
128
+ }
129
+ }
130
+ return filtered;
16
131
  }
17
132
  hasMember(client) {
18
133
  if (typeof client === "string")
@@ -1 +1 @@
1
- {"version":3,"file":"Channel.js","sourceRoot":"","sources":["../../../../src/server/bun/websocket/Channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Channel.js","sourceRoot":"","sources":["../../../../src/server/bun/websocket/Channel.ts"],"names":[],"mappings":";;AAAA,0CAAqC;AAWrC,MAAqB,OAAO;IAW3B,YAAY,EAAU,EAAE,IAAY,EAAE,EAAK,EAAE,KAAc,EAAE,OAAwC,EAAE,QAAiC;QAVjI,cAAS,GAAS,IAAI,IAAI,EAAE,CAAC;QAWnC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,IAAI,GAAG,EAAE,CAAC;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,IAAI,EAAE,CAAC;QAC/B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,8BAA8B;QAC9B,IAAI,CAAC,eAAe,GAAG;YACtB,IAAI,EAAE,EAAE;YACR,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI,CAAC,EAAE;YAChB,SAAS,EAAE,EAAE;SACb,CAAC;IACH,CAAC;IAEM,SAAS,CAAC,OAAmC,EAAE,OAA0B;QAC/E,wDAAwD;QACxD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAEvD,8CAA8C;QAC9C,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC3B,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;QAEzB,wCAAwC;QACxC,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACzC,MAAM,CAAC,OAAO,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;QAC/C,CAAC;aAAM,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC5E,MAAM,CAAC,OAAO,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QACzC,CAAC;aAAM,CAAC;YACP,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC;QACrB,CAAC;QAED,+CAA+C;QAC/C,IAAI,OAAO,EAAE,CAAC;YACb,uBAAuB;YACvB,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAChC,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/F,iCAAiC;oBACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC7C,CAAC;qBAAM,CAAC;oBACP,uCAAuC;oBACvC,MAAM,CAAC,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;gBACpC,CAAC;YACF,CAAC;YAED,qCAAqC;YACrC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACpB,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YACxC,CAAC;YAED,wCAAwC;YACxC,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;gBAC7B,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YAC7H,CAAC;YAED,6CAA6C;YAC7C,IAAI,OAAO,CAAC,gBAAgB,KAAK,KAAK,EAAE,CAAC;gBACxC,MAAM,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAC7C,CAAC;iBAAM,CAAC;gBACP,0CAA0C;gBAC1C,OAAO,MAAM,CAAC,SAAS,CAAC;YACzB,CAAC;YAED,sCAAsC;YACtC,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC3B,IAAI,OAAO,OAAO,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;oBAChD,wBAAwB;oBACxB,MAAM,CAAC,MAAM,GAAG;wBACf,EAAE,EAAE,IAAI,CAAC,EAAE;wBACX,IAAI,EAAE,IAAI,CAAC,IAAI;qBACf,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACP,uCAAuC;oBACvC,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;gBACvC,CAAC;YACF,CAAC;YAED,4BAA4B;YAC5B,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACpC,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;YACpC,CAAC;YAED,8BAA8B;YAC9B,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBACrC,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;YACtC,CAAC;YAED,mDAAmD;YACnD,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;gBAC1B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;YAC7C,CAAC;YAED,0CAA0C;YAC1C,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACvB,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC9C,iCAAiC;gBACjC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;gBAC7D,OAAO;YACR,CAAC;YAED,oCAAoC;YACpC,IAAI,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjE,4EAA4E;gBAC5E,mEAAmE;gBACnE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,EAAE,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;oBACrF,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;oBACjD,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;wBAC/C,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;4BAChD,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;wBACnC,CAAC;oBACF,CAAC;oBACD,OAAO;gBACR,CAAC;YACF,CAAC;QACF,CAAC;aAAM,CAAC;YACP,sDAAsD;YACtD,MAAM,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC7C,CAAC;QAED,yBAAyB;QACzB,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,sCAAsC;IAC9B,mBAAmB,CAAC,IAAc;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,QAAQ,GAA2B,EAAE,CAAC;QAE5C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;gBACjC,QAAQ,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC/B,CAAC;QACF,CAAC;QAED,OAAO,QAAQ,CAAC;IACjB,CAAC;IAEM,SAAS,CAAC,MAAkC;QAClD,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC;IAEM,SAAS,CAAC,MAAyB;QACzC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YAAE,OAAO,KAAK,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,MAAM,CAAC;IACf,CAAC;IAEM,YAAY,CAAC,MAAyB;QAC5C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC1B,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/B,OAAO,MAAM,CAAC;IACf,CAAC;IAEM,SAAS,CAAC,MAAkC;QAClD,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC;IAEM,UAAU,CAAC,OAAwC;QACzD,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACvD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,SAAS,CAAwB,CAAC;IACxH,CAAC;IAEM,WAAW;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAEM,YAAY;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAEM,KAAK;QACX,OAAO,IAAI,CAAC,EAAE,CAAC;IAChB,CAAC;IAEM,OAAO;QACb,OAAO,IAAI,CAAC,IAAI,CAAC;IAClB,CAAC;IAEM,QAAQ;QACd,OAAO,IAAI,CAAC,KAAK,CAAC;IACnB,CAAC;IAEM,OAAO;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC1B,CAAC;IAEM,YAAY;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,OAAO,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEM,MAAM,CAAC,cAAc,CAAC,QAA0D;QACtF,IAAI,CAAC,QAAQ;YAAE,OAAO,OAAO,CAAC;QAC9B,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YACpD,IAAI,YAAY,EAAE,CAAC;gBAClB,OAAO,YAAY,CAAC,WAA6B,CAAC;YACnD,CAAC;iBAAM,CAAC;gBACP,OAAO,OAAO,CAAC;YAChB,CAAC;QACF,CAAC;aAAM,CAAC;YACP,WAAG,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;YAC5D,OAAO,OAAO,CAAC;QAChB,CAAC;IACF,CAAC;CACD;AA/ND,0BA+NC"}
@@ -4,10 +4,43 @@ import Websocket from "./Websocket";
4
4
  export type WebsocketMessage = string | Buffer<ArrayBufferLike>;
5
5
  export type WebsocketChannel<T extends I_WebsocketChannel = Channel> = Map<string, T>;
6
6
  export type WebsocketStructuredMessage<T = any> = {
7
+ /**
8
+ * Message type identifier used for client-side routing
9
+ */
7
10
  type: string;
11
+ /**
12
+ * Message content - can be any data structure
13
+ * If a string is provided, it will be wrapped in {message: string}
14
+ */
8
15
  content: T;
16
+ /**
17
+ * Optional channel identifier
18
+ * If not provided, the channel ID will be added automatically during broadcast
19
+ */
9
20
  channel?: string;
21
+ /**
22
+ * Optional metadata key-value pairs
23
+ * Can be used to add additional context to the message
24
+ */
10
25
  metadata?: Record<string, string>;
26
+ /**
27
+ * Optional timestamp
28
+ * If not provided, it will be added automatically during broadcast
29
+ */
30
+ timestamp?: string;
31
+ /**
32
+ * Optional sender information
33
+ * Can be used to identify the source of the message
34
+ */
35
+ client?: {
36
+ id: string;
37
+ name?: string;
38
+ [key: string]: any;
39
+ };
40
+ /**
41
+ * Any additional custom fields
42
+ */
43
+ [key: string]: any;
11
44
  };
12
45
  export type WebsocketEntityData = {
13
46
  id: string;
@@ -32,12 +65,73 @@ export interface I_WebsocketClient extends I_WebsocketEntity {
32
65
  export interface I_WebsocketChannelEntity<T extends Websocket = Websocket> extends WebsocketEntityData {
33
66
  ws: T;
34
67
  }
68
+ export type BroadcastOptions = {
69
+ /**
70
+ * Additional data to include in the message content
71
+ * If an object is provided, it will be merged with the content
72
+ * If a primitive value is provided, it will be added as content.data
73
+ */
74
+ data?: any;
75
+ /**
76
+ * Client information to include in the message
77
+ * Will be added as content.client
78
+ */
79
+ client?: Partial<WebsocketEntityData> & {
80
+ [key: string]: any;
81
+ };
82
+ /**
83
+ * Channel metadata to include in the message
84
+ * If true, all metadata will be included
85
+ * If an array of strings, only the specified keys will be included
86
+ */
87
+ includeMetadata?: boolean | string[];
88
+ /**
89
+ * Client IDs to exclude from receiving the broadcast
90
+ * Useful for sending messages to all clients except the sender
91
+ */
92
+ excludeClients?: string[];
93
+ /**
94
+ * Whether to include timestamp in the message
95
+ * Defaults to true
96
+ */
97
+ includeTimestamp?: boolean;
98
+ /**
99
+ * Custom fields to add to the root of the message
100
+ * These will be merged with the message object
101
+ */
102
+ customFields?: Record<string, any>;
103
+ /**
104
+ * Transform function to modify the final message before sending
105
+ * This is applied after all other processing
106
+ */
107
+ transform?: (message: any) => any;
108
+ /**
109
+ * Whether to include sender information in the message
110
+ * If true, the channel's ID and name will be added as client
111
+ * If an object, it will be used as the client value
112
+ */
113
+ includeSender?: boolean | {
114
+ id: string;
115
+ name?: string;
116
+ [key: string]: any;
117
+ };
118
+ /**
119
+ * Priority of the message (higher numbers = higher priority)
120
+ * Can be used by clients to determine processing order
121
+ */
122
+ priority?: number;
123
+ /**
124
+ * Message expiration time in milliseconds since epoch
125
+ * Can be used by clients to ignore outdated messages
126
+ */
127
+ expiresAt?: number;
128
+ };
35
129
  export interface I_WebsocketChannel<T extends Websocket = Websocket> extends I_WebsocketChannelEntity<T> {
36
130
  limit: number;
37
131
  members: Map<string, I_WebsocketClient>;
38
132
  metadata: Record<string, string>;
39
133
  createdAt: Date;
40
- broadcast<T = any, U = any>(message: WebsocketStructuredMessage<U>, ...args: T[]): any;
134
+ broadcast(message: WebsocketStructuredMessage, options?: BroadcastOptions): void;
41
135
  hasMember(client: I_WebsocketEntity | string): boolean;
42
136
  addMember(entity: I_WebsocketClient): I_WebsocketClient | false;
43
137
  removeMember(entity: I_WebsocketEntity): I_WebsocketClient | false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "topsyde-utils",
3
- "version": "1.0.87",
3
+ "version": "1.0.89",
4
4
  "description": "A bundle of TypeScript utility classes and functions",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",