topsyde-utils 1.0.179 → 1.0.180

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.
@@ -19,7 +19,7 @@ export default class Channel {
19
19
  };
20
20
  message = msg;
21
21
  }
22
- const output = this.message.create(message, { ...options, channel: this.id });
22
+ const output = this.message.create(message, { ...options, channel: this.name });
23
23
  if (options) {
24
24
  // Include channel metadata if requested
25
25
  if (options.includeMetadata) {
@@ -1 +1 @@
1
- {"version":3,"file":"Channel.js","sourceRoot":"","sources":["../../../../src/server/bun/websocket/Channel.ts"],"names":[],"mappings":"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","sourcesContent":["import { Guards, Lib } from \"../../../utils\";\nimport Message from \"./Message\";\nimport Websocket from \"./Websocket\";\nimport type {\n\tBroadcastOptions,\n\tI_WebsocketChannel,\n\tI_WebsocketClient,\n\tI_WebsocketEntity,\n\tWebsocketChannel,\n\tWebsocketMessage\n} from \"./websocket.types\";\n\nexport default class Channel<T extends Websocket = Websocket> implements I_WebsocketChannel<T> {\n\tpublic createdAt: Date = new Date();\n\tpublic id: string;\n\tpublic name: string;\n\tpublic limit: number;\n\tpublic members: Map<string, I_WebsocketClient>;\n\tpublic metadata: Record<string, string>;\n\tpublic ws: T;\n\tprivate message: Message;\n\n\tconstructor(id: string, name: string, ws: T, limit?: number, members?: Map<string, I_WebsocketClient>, metadata?: Record<string, string>) {\n\t\tthis.id = id;\n\t\tthis.name = name;\n\t\tthis.limit = limit ?? 5;\n\t\tthis.members = members ?? new Map();\n\t\tthis.metadata = metadata ?? {};\n\t\tthis.ws = ws;\n\t\tthis.message = new Message();\n\t\t\n\t}\n\n\tpublic broadcast(message: WebsocketMessage | string, options?: BroadcastOptions) {\n\t\tif (Guards.IsString(message)) {\n\t\t\tconst msg: WebsocketMessage = {\n\t\t\t\ttype: \"message\",\n\t\t\t\tcontent: { message },\n\t\t\t};\n\t\t\tmessage = msg;\n\t\t}\n\t\tconst output = this.message.create(message, { ...options, channel: this.id });\n\t\tif (options) {\n\t\t\t// Include channel metadata if requested\n\t\t\tif (options.includeMetadata) {\n\t\t\t\toutput.metadata = options.includeMetadata === true ? this.getMetadata() : this.getFilteredMetadata(options.includeMetadata);\n\t\t\t}\n\n\t\t\t// Handle excluded clients if needed\n\t\t\tif (options.excludeClients && options.excludeClients.length > 0) {\n\t\t\t\t// For large channels with many excluded clients, it might be more efficient\n\t\t\t\t// to send directly to each client instead of using channel publish\n\t\t\t\tif (this.members.size > 10 && options.excludeClients.length > this.members.size / 3) {\n\t\t\t\t\tconst serializedMessage = this.message.serialize(output);\n\t\t\t\t\tfor (const [clientId, client] of this.members) {\n\t\t\t\t\t\tif (!options.excludeClients.includes(clientId)) {\n\t\t\t\t\t\t\tclient.ws.send(serializedMessage);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Publish to the channel\n\t\tthis.ws.server.publish(this.id, this.message.serialize(output));\n\t}\n\n\t// Helper method for filtered metadata\n\tprivate getFilteredMetadata(keys: string[]) {\n\t\tconst metadata = this.getMetadata();\n\t\tconst filtered: Record<string, string> = {};\n\n\t\tfor (const key of keys) {\n\t\t\tif (metadata[key] !== undefined) {\n\t\t\t\tfiltered[key] = metadata[key];\n\t\t\t}\n\t\t}\n\n\t\treturn filtered;\n\t}\n\n\tpublic hasMember(client: I_WebsocketEntity | string) {\n\t\tif (typeof client === \"string\") return this.members.has(client);\n\t\treturn this.members.has(client.id);\n\t}\n\n\tpublic addMember(client: I_WebsocketClient) {\n\t\tif (!this.canAddMember()) return false;\n\t\tthis.members.set(client.id, client);\n\t\tclient.joinChannel(this);\n\t\treturn client;\n\t}\n\n\tpublic removeMember(entity: I_WebsocketEntity) {\n\t\tif (!this.members.has(entity.id)) return false;\n\t\tconst client = this.members.get(entity.id);\n\t\tif (!client) return false;\n\t\tclient.leaveChannel(this);\n\t\tthis.members.delete(entity.id);\n\t\treturn client;\n\t}\n\n\tpublic getMember(client: I_WebsocketEntity | string) {\n\t\tif (typeof client === \"string\") return this.members.get(client);\n\t\treturn this.members.get(client.id);\n\t}\n\n\tpublic getMembers(clients?: string[] | I_WebsocketEntity[]): I_WebsocketClient[] {\n\t\tif (!clients) return Array.from(this.members.values());\n\t\treturn clients.map((client) => this.getMember(client)).filter((client) => client !== undefined) as I_WebsocketClient[];\n\t}\n\n\tpublic getMetadata() {\n\t\treturn this.metadata;\n\t}\n\n\tpublic getCreatedAt() {\n\t\treturn this.createdAt;\n\t}\n\n\tpublic getId() {\n\t\treturn this.id;\n\t}\n\n\tpublic getName() {\n\t\treturn this.name;\n\t}\n\n\tpublic getLimit() {\n\t\treturn this.limit;\n\t}\n\n\tpublic getSize() {\n\t\treturn this.members.size;\n\t}\n\n\tpublic canAddMember() {\n\t\tconst size = this.getSize();\n\t\treturn size < this.limit;\n\t}\n\n\tpublic static GetChannelType(channels: WebsocketChannel<I_WebsocketChannel> | undefined) {\n\t\tif (!channels) return Channel;\n\t\tif (channels.size > 0) {\n\t\t\tconst firstChannel = channels.values().next().value;\n\t\t\tif (firstChannel) {\n\t\t\t\treturn firstChannel.constructor as typeof Channel;\n\t\t\t} else {\n\t\t\t\treturn Channel;\n\t\t\t}\n\t\t} else {\n\t\t\tLib.Warn(\"Channels are empty, using default channel class\");\n\t\t\treturn Channel;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"Channel.js","sourceRoot":"","sources":["../../../../src/server/bun/websocket/Channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,OAAO,MAAM,WAAW,CAAC;AAWhC,MAAM,CAAC,OAAO,OAAO,OAAO;IAU3B,YAAY,EAAU,EAAE,IAAY,EAAE,EAAK,EAAE,KAAc,EAAE,OAAwC,EAAE,QAAiC;QATjI,cAAS,GAAS,IAAI,IAAI,EAAE,CAAC;QAUnC,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,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,CAAC;IAEM,SAAS,CAAC,OAAkC,EAAE,OAA0B;QAC9E,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAqB;gBAC7B,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,EAAE,OAAO,EAAE;aACpB,CAAC;YACF,OAAO,GAAG,GAAG,CAAC;QACf,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAChF,IAAI,OAAO,EAAE,CAAC;YACb,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,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,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;oBACzD,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;QACD,yBAAyB;QACzB,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACjE,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,GAAG,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;YAC5D,OAAO,OAAO,CAAC;QAChB,CAAC;IACF,CAAC;CACD","sourcesContent":["import { Guards, Lib } from \"../../../utils\";\nimport Message from \"./Message\";\nimport Websocket from \"./Websocket\";\nimport type {\n\tBroadcastOptions,\n\tI_WebsocketChannel,\n\tI_WebsocketClient,\n\tI_WebsocketEntity,\n\tWebsocketChannel,\n\tWebsocketMessage\n} from \"./websocket.types\";\n\nexport default class Channel<T extends Websocket = Websocket> implements I_WebsocketChannel<T> {\n\tpublic createdAt: Date = new Date();\n\tpublic id: string;\n\tpublic name: string;\n\tpublic limit: number;\n\tpublic members: Map<string, I_WebsocketClient>;\n\tpublic metadata: Record<string, string>;\n\tpublic ws: T;\n\tprivate message: Message;\n\n\tconstructor(id: string, name: string, ws: T, limit?: number, members?: Map<string, I_WebsocketClient>, metadata?: Record<string, string>) {\n\t\tthis.id = id;\n\t\tthis.name = name;\n\t\tthis.limit = limit ?? 5;\n\t\tthis.members = members ?? new Map();\n\t\tthis.metadata = metadata ?? {};\n\t\tthis.ws = ws;\n\t\tthis.message = new Message();\n\t\t\n\t}\n\n\tpublic broadcast(message: WebsocketMessage | string, options?: BroadcastOptions) {\n\t\tif (Guards.IsString(message)) {\n\t\t\tconst msg: WebsocketMessage = {\n\t\t\t\ttype: \"message\",\n\t\t\t\tcontent: { message },\n\t\t\t};\n\t\t\tmessage = msg;\n\t\t}\n\t\tconst output = this.message.create(message, { ...options, channel: this.name });\n\t\tif (options) {\n\t\t\t// Include channel metadata if requested\n\t\t\tif (options.includeMetadata) {\n\t\t\t\toutput.metadata = options.includeMetadata === true ? this.getMetadata() : this.getFilteredMetadata(options.includeMetadata);\n\t\t\t}\n\n\t\t\t// Handle excluded clients if needed\n\t\t\tif (options.excludeClients && options.excludeClients.length > 0) {\n\t\t\t\t// For large channels with many excluded clients, it might be more efficient\n\t\t\t\t// to send directly to each client instead of using channel publish\n\t\t\t\tif (this.members.size > 10 && options.excludeClients.length > this.members.size / 3) {\n\t\t\t\t\tconst serializedMessage = this.message.serialize(output);\n\t\t\t\t\tfor (const [clientId, client] of this.members) {\n\t\t\t\t\t\tif (!options.excludeClients.includes(clientId)) {\n\t\t\t\t\t\t\tclient.ws.send(serializedMessage);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Publish to the channel\n\t\tthis.ws.server.publish(this.id, this.message.serialize(output));\n\t}\n\n\t// Helper method for filtered metadata\n\tprivate getFilteredMetadata(keys: string[]) {\n\t\tconst metadata = this.getMetadata();\n\t\tconst filtered: Record<string, string> = {};\n\n\t\tfor (const key of keys) {\n\t\t\tif (metadata[key] !== undefined) {\n\t\t\t\tfiltered[key] = metadata[key];\n\t\t\t}\n\t\t}\n\n\t\treturn filtered;\n\t}\n\n\tpublic hasMember(client: I_WebsocketEntity | string) {\n\t\tif (typeof client === \"string\") return this.members.has(client);\n\t\treturn this.members.has(client.id);\n\t}\n\n\tpublic addMember(client: I_WebsocketClient) {\n\t\tif (!this.canAddMember()) return false;\n\t\tthis.members.set(client.id, client);\n\t\tclient.joinChannel(this);\n\t\treturn client;\n\t}\n\n\tpublic removeMember(entity: I_WebsocketEntity) {\n\t\tif (!this.members.has(entity.id)) return false;\n\t\tconst client = this.members.get(entity.id);\n\t\tif (!client) return false;\n\t\tclient.leaveChannel(this);\n\t\tthis.members.delete(entity.id);\n\t\treturn client;\n\t}\n\n\tpublic getMember(client: I_WebsocketEntity | string) {\n\t\tif (typeof client === \"string\") return this.members.get(client);\n\t\treturn this.members.get(client.id);\n\t}\n\n\tpublic getMembers(clients?: string[] | I_WebsocketEntity[]): I_WebsocketClient[] {\n\t\tif (!clients) return Array.from(this.members.values());\n\t\treturn clients.map((client) => this.getMember(client)).filter((client) => client !== undefined) as I_WebsocketClient[];\n\t}\n\n\tpublic getMetadata() {\n\t\treturn this.metadata;\n\t}\n\n\tpublic getCreatedAt() {\n\t\treturn this.createdAt;\n\t}\n\n\tpublic getId() {\n\t\treturn this.id;\n\t}\n\n\tpublic getName() {\n\t\treturn this.name;\n\t}\n\n\tpublic getLimit() {\n\t\treturn this.limit;\n\t}\n\n\tpublic getSize() {\n\t\treturn this.members.size;\n\t}\n\n\tpublic canAddMember() {\n\t\tconst size = this.getSize();\n\t\treturn size < this.limit;\n\t}\n\n\tpublic static GetChannelType(channels: WebsocketChannel<I_WebsocketChannel> | undefined) {\n\t\tif (!channels) return Channel;\n\t\tif (channels.size > 0) {\n\t\t\tconst firstChannel = channels.values().next().value;\n\t\t\tif (firstChannel) {\n\t\t\t\treturn firstChannel.constructor as typeof Channel;\n\t\t\t} else {\n\t\t\t\treturn Channel;\n\t\t\t}\n\t\t} else {\n\t\t\tLib.Warn(\"Channels are empty, using default channel class\");\n\t\t\treturn Channel;\n\t\t}\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "topsyde-utils",
3
- "version": "1.0.179",
3
+ "version": "1.0.180",
4
4
  "description": "A bundle of TypeScript utility classes and functions",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -382,7 +382,7 @@ describe("Singleton", () => {
382
382
  // Update expectations to match actual structure - we don't care about exact format
383
383
  // as long as it contains the message
384
384
  expect(parsedJson).toHaveProperty("type", message.type);
385
- expect(parsedJson).toHaveProperty("channel", channel.id);
385
+ expect(parsedJson).toHaveProperty("channel", channel.name);
386
386
 
387
387
  spy.mockRestore();
388
388
  });
@@ -39,7 +39,7 @@ export default class Channel<T extends Websocket = Websocket> implements I_Webso
39
39
  };
40
40
  message = msg;
41
41
  }
42
- const output = this.message.create(message, { ...options, channel: this.id });
42
+ const output = this.message.create(message, { ...options, channel: this.name });
43
43
  if (options) {
44
44
  // Include channel metadata if requested
45
45
  if (options.includeMetadata) {