@nsshunt/stsmessaging 1.0.68 → 1.0.69
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.cjs +15 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +15 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
package/dist/index.cjs
CHANGED
|
@@ -255,7 +255,7 @@ var RedisMessageHandler = class extends tiny_emitter.TinyEmitter {
|
|
|
255
255
|
if (removeIndex !== -1) this.#options.groups.splice(removeIndex, 1);
|
|
256
256
|
};
|
|
257
257
|
SetupPrimary = () => {
|
|
258
|
-
|
|
258
|
+
const ipcMessageManagerOptions = {
|
|
259
259
|
logger: this.#options.logger,
|
|
260
260
|
requestResponseMessageTimeout: 5e3,
|
|
261
261
|
namespace: this.#options.namespace,
|
|
@@ -270,7 +270,8 @@ var RedisMessageHandler = class extends tiny_emitter.TinyEmitter {
|
|
|
270
270
|
messageReceiverStop: (options) => {
|
|
271
271
|
this.#ioredisSubscriber.off("message", this.#processRawMessage);
|
|
272
272
|
}
|
|
273
|
-
}
|
|
273
|
+
};
|
|
274
|
+
this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);
|
|
274
275
|
};
|
|
275
276
|
#messageSender = (payload, options) => {
|
|
276
277
|
if (payload.messageType.localeCompare("REQUEST") === 0 || payload.messageType.localeCompare("REQUEST_NO_RESPONSE") === 0) this.#ioredisPublisher.publish(this.#requestChannel, JSON.stringify(payload));
|
|
@@ -441,7 +442,7 @@ var IPCMessageHandler = class extends tiny_emitter.TinyEmitter {
|
|
|
441
442
|
return this.#clients;
|
|
442
443
|
}
|
|
443
444
|
SetupPrimary = () => {
|
|
444
|
-
|
|
445
|
+
const ipcMessageManagerOptions = {
|
|
445
446
|
logger: _nsshunt_stsutils.defaultLogger,
|
|
446
447
|
requestResponseMessageTimeout: 5e3,
|
|
447
448
|
namespace: this.#options.namespace,
|
|
@@ -455,13 +456,14 @@ var IPCMessageHandler = class extends tiny_emitter.TinyEmitter {
|
|
|
455
456
|
messageReceiverStart: (options) => {},
|
|
456
457
|
messageReceiverStop: (options) => {},
|
|
457
458
|
groups: []
|
|
458
|
-
}
|
|
459
|
+
};
|
|
460
|
+
this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);
|
|
459
461
|
};
|
|
460
462
|
#ProcessWorkerMessageRaw = (payload) => {
|
|
461
463
|
this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);
|
|
462
464
|
};
|
|
463
465
|
SetupWorker = () => {
|
|
464
|
-
|
|
466
|
+
const ipcMessageManagerOptions = {
|
|
465
467
|
logger: _nsshunt_stsutils.defaultLogger,
|
|
466
468
|
requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,
|
|
467
469
|
namespace: this.#options.namespace,
|
|
@@ -480,7 +482,8 @@ var IPCMessageHandler = class extends tiny_emitter.TinyEmitter {
|
|
|
480
482
|
process.off("message", this.#ProcessWorkerMessageRaw);
|
|
481
483
|
},
|
|
482
484
|
groups: []
|
|
483
|
-
}
|
|
485
|
+
};
|
|
486
|
+
this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);
|
|
484
487
|
};
|
|
485
488
|
SendMessage = async (payload) => {
|
|
486
489
|
if (this.#messagingManager) if (this.#options.role.localeCompare("CLIENT") === 0) return this.#messagingManager?.SendMessage(payload, {});
|
|
@@ -592,7 +595,7 @@ var IPCMessageHandlerPair = class extends tiny_emitter.TinyEmitter {
|
|
|
592
595
|
this.#messagingManager?.ProcessMessage(payload, { worker: this.#startPrimaryWorker });
|
|
593
596
|
};
|
|
594
597
|
SetupPrimary = () => {
|
|
595
|
-
|
|
598
|
+
const ipcMessageManagerOptions = {
|
|
596
599
|
logger: _nsshunt_stsutils.defaultLogger,
|
|
597
600
|
requestResponseMessageTimeout: 5e3,
|
|
598
601
|
namespace: this.#options.namespace,
|
|
@@ -612,13 +615,14 @@ var IPCMessageHandlerPair = class extends tiny_emitter.TinyEmitter {
|
|
|
612
615
|
options.worker.off("message", this.#ProcessPrimaryMessageRaw);
|
|
613
616
|
},
|
|
614
617
|
groups: []
|
|
615
|
-
}
|
|
618
|
+
};
|
|
619
|
+
this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);
|
|
616
620
|
};
|
|
617
621
|
#ProcessWorkerMessageRaw = (payload) => {
|
|
618
622
|
this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);
|
|
619
623
|
};
|
|
620
624
|
SetupWorker = () => {
|
|
621
|
-
|
|
625
|
+
const ipcMessageManagerOptions = {
|
|
622
626
|
logger: _nsshunt_stsutils.defaultLogger,
|
|
623
627
|
requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,
|
|
624
628
|
namespace: this.#options.namespace,
|
|
@@ -637,7 +641,8 @@ var IPCMessageHandlerPair = class extends tiny_emitter.TinyEmitter {
|
|
|
637
641
|
process.off("message", this.#ProcessWorkerMessageRaw);
|
|
638
642
|
},
|
|
639
643
|
groups: []
|
|
640
|
-
}
|
|
644
|
+
};
|
|
645
|
+
this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);
|
|
641
646
|
};
|
|
642
647
|
SendMessage = async (payload) => {
|
|
643
648
|
if (this.#messagingManager) if (this.#worker) return this.#messagingManager?.SendMessage(payload, { worker: this.#worker });
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["#id","#options","#messageHeader","#SendMessageNoResponse","#SendMessage","#inflightMessages","#ProcessMessage","#options","#requestChannel","#responseChannel","#ioredisSubscriber","#ioredisPublisher","#LogError","#LogInfo","#pingTimeout","#messagingManager","#clients","#messageSender","#ProcessResponseMessage","#processPayload","#processRawMessage","#events","#options","#events","#messagingManager","#clients","#processPayload","#startWorkerOptions","#ProcessWorkerMessageRaw","#options","#events","#messagingManager","#startPrimaryWorker","#processPayload","#ProcessPrimaryMessageRaw","#startWorkerOptions","#ProcessWorkerMessageRaw","#worker"],"sources":["../src/messagingManager.ts","../src/redisMessageHandler.ts","../src/ipcMessageHandler.ts","../src/ipcMessageHandlerPair.ts"],"sourcesContent":["/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF\nimport { ISTSLogger, JSONObject } from '@nsshunt/stsutils'\n\n//import { randomUUID } from 'node:crypto';\n\nimport { IIPCMessageProcessorIPCPayload, IIPCMessageProcessorWorkerRecord } from './commonTypes.js'\n\nexport interface MessagingManagerOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n groups: string[]\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => void\n ProcessRequestMessage: (payload: IIPCMessageProcessorIPCPayload, options: any) => Promise<JSONObject>\n ProcessResponseMessage?: (reesponses: Record<string, IIPCMessageProcessorIPCPayload>, options: any) => Promise<boolean>\n messageReceiverStart: (options: any) => void\n messageReceiverStop: (options: any) => void\n}\n/**\n * todo\n * @typedef {Object} options - todo\n * @property {boolean} [wssServer=false] - Create a web socket server on this worker instance\n */\nexport class MessagingManager {\n #id: string;\n #options: MessagingManagerOptions;\n #inflightMessages: Record<string, IIPCMessageProcessorWorkerRecord> = { };\n #messageHeader: string;\n\n constructor(options: MessagingManagerOptions) {\n this.#id = globalThis.crypto.randomUUID(); // randomUUID();\n this.#options = options;\n this.#messageHeader = `__STS__${this.#options.namespace}__${globalThis.crypto.randomUUID()}`; // randomUUID();\n }\n\n get id() {\n return this.#id;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ReceivedMessageFromMaster(msg: any) {\n // Override in subclass if required\n }\n\n SendMessageNoResponse = (payload: JSONObject, options?: any): void => {\n this.#SendMessageNoResponse(payload, options);\n };\n\n SendMessage = (payload: JSONObject, options?: any): Promise<JSONObject> => {\n return new Promise((resolve, reject) => {\n this.#SendMessage(payload, options,\n (payload: IIPCMessageProcessorIPCPayload) => {\n resolve(payload.responsePayload);\n },\n (payload: IIPCMessageProcessorIPCPayload) => {\n reject(payload.requestPayload);\n })\n })\n }\n\n #SendMessageNoResponse = (payload: JSONObject, options: any): void => {\n const messageId: string = globalThis.crypto.randomUUID(); // randomUUID();\n const requestPayload: IIPCMessageProcessorIPCPayload = {\n header: this.#messageHeader,\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload: payload,\n responsePayload: { },\n pid: process.pid.toString(),\n messageType: 'REQUEST_NO_RESPONSE'\n }\n\n //console.log(chalk.blue(`#SendMessageNoResponse: [${JSON.stringify(requestPayload)}]`))\n this.#options.messageSender(requestPayload, options);\n }\n\n #SendMessage = (payload: JSONObject, options: any,\n callBack: (payload: IIPCMessageProcessorIPCPayload) => void, \n errorCallBack: (payload: IIPCMessageProcessorIPCPayload) => void\n ): void => {\n const messageId: string = globalThis.crypto.randomUUID(); // randomUUID();\n const requestPayload: IIPCMessageProcessorIPCPayload = {\n header: this.#messageHeader,\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload: payload,\n responsePayload: { },\n pid: process.pid.toString(),\n messageType: 'REQUEST'\n }\n const messageRecord = {\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload,\n responses: { }, // record\n startTime: performance.now(),\n endTime: 0,\n timeout: setTimeout(() => {\n //this.#LogDebugMessage(chalk.red(`Timeout has occurred after: [${this.#options.requestResponseMessageTimeout}]ms with message id: [${messageRecord.messageId}]. Details: [${JSON.stringify(this.#inflightMessages[messageRecord.messageId].requestPayload)}]`));\n setTimeout(() => {\n delete this.#inflightMessages[messageRecord.messageId];\n }, 0).unref();\n errorCallBack(requestPayload);\n }, this.#options.requestResponseMessageTimeout).unref(),// max message timeout allowed\n callBack,\n errorCallBack\n }\n this.#inflightMessages[messageRecord.messageId] = messageRecord;\n //this.#LogDebugMessage(chalk.cyan(`sending: [${JSON.stringify(requestPayload)}]`));\n //console.log(chalk.blue(`#SendMessage: [${JSON.stringify(requestPayload)}]`))\n\n this.#options.messageSender(requestPayload, options);\n }\n\n #ProcessMessage = async (msg: any, options: any): Promise<void> => {\n if (msg.header && msg.header.localeCompare(this.#messageHeader) === 0) {\n const message = (msg as IIPCMessageProcessorIPCPayload);\n if (this.#inflightMessages[message.messageId]) {\n const inFlightMessageRecord: IIPCMessageProcessorWorkerRecord = this.#inflightMessages[message.messageId];\n inFlightMessageRecord.responses[message.senderId ] = { ...message };\n let completed = true; // Defaults to true\n if (this.#options.ProcessResponseMessage) {\n completed = await this.#options.ProcessResponseMessage(inFlightMessageRecord.responses, options);\n if (completed) {\n inFlightMessageRecord.endTime = performance.now();\n clearTimeout(inFlightMessageRecord.timeout as NodeJS.Timeout);\n inFlightMessageRecord.callBack({\n responsePayload: Object.values(inFlightMessageRecord.responses).map(r => r.responsePayload)\n } as any, options) // \n delete this.#inflightMessages[message.messageId];\n }\n } else if (completed) {\n inFlightMessageRecord.endTime = performance.now();\n clearTimeout(inFlightMessageRecord.timeout as NodeJS.Timeout);\n inFlightMessageRecord.callBack(message, options) // inFlightMessageRecord.responses\n //@@inFlightMessageRecord.callBack(Object.values(inFlightMessageRecord.responses), options) // \n delete this.#inflightMessages[message.messageId];\n } else {\n //console.log(chalk.grey(`#ProcessMessage:5`));\n }\n } else {\n //throw new Error(`Could not find Request/Response message with id: [${message.messageId}]`); //@@\n }\n }\n }\n\n Start = (options?: any) => {\n this.#messageHeader = `__STS__${this.#options.namespace}__${globalThis.crypto.randomUUID()}`; // randomUUID()\n this.#options.messageReceiverStart(options);\n }\n\n Stop = (options?: any) => {\n // Kill in-flight messages\n this.#options.messageReceiverStop(options);\n\n for (const [, iPCMessageProcessorWorkerRecord] of Object.entries(this.#inflightMessages)) {\n if (iPCMessageProcessorWorkerRecord.timeout) {\n clearTimeout(iPCMessageProcessorWorkerRecord.timeout);\n }\n }\n this.#inflightMessages = { };\n }\n\n // Process a message recieved from a worker\n ProcessMessage = async (msg: any, options: any) => {\n if (msg.header) {\n const checkName = `__STS__${this.#options.namespace}__`; //@@ this is a broadcast becuase the unique uuid is not part of the header test\n if ((msg.header as string).includes(checkName)) {\n const message = (msg as IIPCMessageProcessorIPCPayload);\n if (msg.messageType.localeCompare('REQUEST') === 0 || msg.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n let processMessage = true;\n if (message.requestPayload.args && message.requestPayload.args.length > 0 && message.requestPayload.args[0].group) {\n const group = message.requestPayload.args[0].group;\n processMessage = (this.#options.groups.indexOf(group) === -1) ? false : true;\n }\n if (processMessage) {\n if (msg.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#options.ProcessRequestMessage(message, options);\n } else {\n message.responsePayload = await this.#options.ProcessRequestMessage(message, options);\n message.senderId = this.#id;\n message.messageType = 'RESPONSE';\n this.#options.messageSender(message, options);\n }\n }\n } else {\n // Received a response (to my request)\n this.#ProcessMessage(msg, options);\n }\n }\n }\n }\n}\n","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\nimport { Redis, RedisOptions } from \"ioredis\";\n\nimport chalk from 'chalk';\n\nconst REQUEST_CHANNEL = '__STS__SVC_stsappframework_request'\nconst RESPONSE_CHANNEL = '__STS__SVC_stsappframework_response'\n\nexport interface IRedisAdminManagerOptions {\n redisUrl: string\n logger: ISTSLogger\n role: 'SERVER' | 'CLIENT'\n namespace: string\n groups: string[]\n ignoreEvents?: string[]\n extraData?: JSONObject\n}\n\nexport interface IClientRecord {\n id: string\n clientConnected: Date\n pingCount: number\n timeout: NodeJS.Timeout\n groups: string[]\n extraData?: JSONObject\n}\n\nexport interface IEventRecord {\n event: string\n callback: any,\n ctx?: any\n}\n\nexport interface IPingData {\n id: string\n groups: string[]\n extraData?: JSONObject\n}\n\nexport class RedisMessageHandler extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IRedisAdminManagerOptions;\n #events: Record<string, IEventRecord> = { };\n #requestChannel: string;\n #responseChannel: string;\n #ioredisSubscriber: Redis;\n #ioredisPublisher: Redis;\n #clients: Record<string, IClientRecord> = { };\n #pingTimeout: NodeJS.Timeout | null = null;\n\n constructor(options: IRedisAdminManagerOptions) {\n super();\n this.#options = options;\n\n this.#requestChannel = REQUEST_CHANNEL\n this.#responseChannel = RESPONSE_CHANNEL\n\n const redisOptions: RedisOptions = {\n showFriendlyErrorStack: true,\n maxRetriesPerRequest: 20\n }\n\n this.#ioredisSubscriber = new Redis(this.#options.redisUrl, redisOptions);\n this.#ioredisPublisher = new Redis(this.#options.redisUrl, redisOptions);\n\n this.#ioredisSubscriber.on(\"error\", (error: Error) => {\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error (redisSubscriber on error): [${error}]`));\n });\n\n this.#ioredisPublisher.on(\"error\", (error: Error) => {\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error (redisPublisher on error): [${error}]`));\n });\n\n this.#ioredisSubscriber.subscribe(this.#requestChannel, this.#responseChannel, (error, count) => {\n if (error) {\n // Just like other commands, subscribe() can fail for some reasons, // ex network issues.\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error - Failed to subscribe: [${error}]`));\n } else {\n // `count` represents the number of channels this client is currently subscribed to.\n this.#LogInfo(chalk.white(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Subscribed successfully! This client is currently subscribed to ${count} channels.`));\n }\n });\n\n this.SetupPrimary();\n\n /*\n const ping = () => {\n this.#pingTimeout = setTimeout(() => {\n const pingData: IPingData = {\n id: (this.#messagingManager as MessagingManager).id,\n groups: this.#options.groups,\n }\n if (this.#options.extraData) {\n pingData.extraData = this.#options.extraData;\n }\n this.emit('ping', pingData, (response: any) => { });\n ping();\n }, 1000).unref();\n }\n ping();\n\n this.on('ping', (pingData: IPingData, callback: any) => {\n const { id, groups, extraData } = pingData;\n if (this.#clients[id]) {\n clearTimeout(this.#clients[id].timeout);\n this.#clients[id].pingCount++;\n this.#clients[id].timeout = setTimeout(() => {\n delete this.#clients[id];\n }, 2000);\n this.#clients[id].groups = groups;\n this.#clients[id].extraData = extraData;\n } else {\n this.#clients[id] = {\n id,\n clientConnected: new Date(),\n pingCount: 0,\n timeout: setTimeout(() => {\n delete this.#clients[id];\n }, 2000),\n groups,\n extraData\n }\n }\n callback('ok');\n });\n */\n\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n const ping = () => {\n this.#pingTimeout = setTimeout(() => {\n const pingData: IPingData = {\n id: (this.#messagingManager as MessagingManager).id,\n groups: this.#options.groups,\n }\n if (this.#options.extraData) {\n pingData.extraData = this.#options.extraData;\n }\n //this.emit('ping', pingData, (response: any) => { });\n this.emitNoResponse('ping', pingData);\n ping();\n }, 1000).unref();\n }\n ping();\n } else {\n this.on('ping', (pingData: IPingData, callback: any) => {\n const { id, groups, extraData } = pingData;\n if (this.#clients[id]) {\n clearTimeout(this.#clients[id].timeout);\n this.#clients[id].pingCount++;\n this.#clients[id].timeout = setTimeout(() => {\n delete this.#clients[id];\n }, 2000);\n this.#clients[id].groups = groups;\n this.#clients[id].extraData = extraData;\n } else {\n this.#clients[id] = {\n id,\n clientConnected: new Date(),\n pingCount: 0,\n timeout: setTimeout(() => {\n delete this.#clients[id];\n }, 2000),\n groups,\n extraData\n }\n }\n //callback('ok');\n });\n }\n }\n\n #LogInfo(message: any) {\n this.#options.logger.info(message);\n }\n\n #LogError(message: any) {\n this.#options.logger.error(message);\n }\n\n #processRawMessage = (channel: string, rawmessage: string) => {\n const message = JSON.parse(rawmessage);\n\n /*\n if (message.requestPayload.__eventName.localeCompare('ping') !== 0) {\n console.log(chalk.cyan(`RedisMessageHandler:#processRawMessage(): Role: [${this.#options.role}] Channel: [${channel}] Message: [${JSON.stringify(message)}]`));\n }\n */\n\n this.#messagingManager?.ProcessMessage(message, { channel });\n }\n\n get clients(): Record<string, IClientRecord> {\n return this.#clients;\n }\n\n get groups(): string[] {\n return this.#options.groups;\n }\n \n AddGroup = (group: string) => {\n const index = this.#options.groups.indexOf(group);\n if (index === -1) {\n this.#options.groups.push(group);\n }\n }\n\n RemoveGroup = (group: string) => {\n const removeIndex = this.#options.groups.indexOf(group);\n if (removeIndex !== -1) {\n this.#options.groups.splice(removeIndex, 1);\n }\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: this.#options.logger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: this.#options.role,\n groups: this.#options.groups,\n messageSender: this.#messageSender,\n // This method is used to calculate if all responses have been received from multiple clients (broadcast)\n // returns true/false.\n ProcessResponseMessage: this.#ProcessResponseMessage,\n // This gets called when an event is received from a message receiver (when ProcessMessage is invoked from the receiver event handler)\n ProcessRequestMessage: this.#processPayload,\n \n messageReceiverStart: (options: any) => {\n this.#ioredisSubscriber.on(\"message\", this.#processRawMessage);\n },\n \n messageReceiverStop: (options: any) => {\n this.#ioredisSubscriber.off(\"message\", this.#processRawMessage);\n }\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n \n #messageSender = (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n\n\n //console.log(chalk.grey(JSON.stringify(payload)));\n\n\n this.#ioredisPublisher.publish(this.#requestChannel, JSON.stringify(payload));\n } else if (payload.messageType.localeCompare('RESPONSE') === 0) {\n this.#ioredisPublisher.publish(this.#responseChannel, JSON.stringify(payload));\n }\n }\n\n \n #ProcessResponseMessage = async (responses: Record<string, IIPCMessageProcessorIPCPayload>, options: any): Promise<boolean> => {\n // Now check if we have all responses ...\n\n /*\n let allFound = false;\n\n for (const [responseId, response] of Object.entries(responses)) {\n if (response.senderRole.localeCompare('CLIENT') === 0) {\n allFound = true;\n break;\n }\n }\n if (allFound) {\n return allFound;\n }\n */\n\n let found = true;\n\n // Sender role here is SERVER\n let requestGroup = null;\n for (const [responseId, response] of Object.entries(responses)) {\n if (response.requestPayload.args.length > 0 && response.requestPayload.args[0].group) {\n requestGroup = response.requestPayload.args[0].group;\n break;\n }\n }\n\n if (requestGroup) {\n const clientsInGroup = Object.values(this.#clients).filter(c => {\n if (c.groups.indexOf(requestGroup) === -1) {\n return false;\n }\n return true;\n });\n\n // Now make sure that all clients are in the responses\n found = true;\n clientsInGroup.forEach(c => {\n if (!responses[c.id]) {\n found = false;\n }\n })\n } else {\n const clientsInGroup = Object.values(this.#clients)\n\n // Now make sure that all clients are in the responses\n found = true;\n clientsInGroup.forEach(c => {\n if (!responses[c.id]) {\n found = false;\n }\n })\n }\n\n return found;\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject: IEventRecord = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n }\n\n Start = () => {\n this.#messagingManager?.Start();\n }\n\n Stop = () => {\n if (this.#pingTimeout) {\n clearTimeout(this.#pingTimeout);\n this.#pingTimeout = null;\n }\n\n this.#messagingManager?.Stop();\n\n this.#ioredisSubscriber.quit();\n this.#ioredisSubscriber.disconnect();\n\n this.#ioredisPublisher.quit();\n this.#ioredisPublisher.disconnect();\n }\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n const retVal = await this.#messagingManager?.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload); \n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n this.#options.logger.error(chalk.red(`RedisMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitWithError(event: string, args: JSONObject, responseCb: (response: JSONObject | undefined) => void, errorCb: (error: any) => void): this {\n (async () => {\n try {\n const retVal = await this.#messagingManager?.SendMessage({\n __eventName: event,\n args: [ args ]\n } as IEventPayload); \n // Invoke the response callback\n responseCb(retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n //this.#options.logger.error(chalk.red(`RedisMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n errorCb(error);\n }\n })();\n return this;\n }\n\n emitex = async(event: string, ...args: any[]): Promise<JSONObject> => {\n return (this.#messagingManager as MessagingManager).SendMessage({\n __eventName: event,\n args\n } as IEventPayload); \n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n }\n}","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\n\nimport chalk from 'chalk';\n\n//import { randomUUID } from 'node:crypto';\n\nexport interface IPCMessageHandlerOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n ignoreEvents?: string[]\n}\n\ndeclare interface IClientRecord {\n client: any\n processMessage: (client: any) => void\n}\n\n/**\n * IPC Message Handling.\n * \n * This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.\n * This class can be used for both tghe cluster primary and the cluster worker.\n * Note: Currently groups handling is not supported. Use the redis version for this capability.\n */\nexport class IPCMessageHandler extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IPCMessageHandlerOptions;\n #clients: Record<string, IClientRecord> = { };\n #events: JSONObject = { };\n #startWorkerOptions: any;\n\n constructor(options: IPCMessageHandlerOptions) {\n super();\n this.#options = options;\n if (options.role.localeCompare('CLIENT') === 0) {\n this.SetupWorker();\n } else {\n this.SetupPrimary();\n }\n }\n\n get __events() {\n return this.#events;\n }\n\n AddClient = (client: any): string => {\n const id = globalThis.crypto.randomUUID(); // randomUUID();\n\n const processMessage = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, { client });\n };\n\n client.on('message', processMessage);\n this.#clients[id] = {\n client,\n processMessage\n }\n return id;\n }\n\n RemoveClient = (id: string) => {\n const clientRecord = this.#clients[id];\n if (clientRecord) {\n clientRecord.client.off('message', clientRecord.processMessage);\n delete this.#clients[id];\n }\n }\n\n get clients() {\n return this.#clients;\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: 'SERVER',\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n (options.client as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n\n\n //@@ also need way to add/remove a worker/child to the collection\n //@@ the ping should also auto remove (such as a failed worker)\n \n\n messageReceiverStart: (options: any) => { //@@ options should be complete collection of workers\n // Receive a message to process from a worker\n },\n messageReceiverStop: (options: any) => { //@@ options should be complete collection of workers\n\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n #ProcessWorkerMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);\n }\n\n SetupWorker = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,\n namespace: this.#options.namespace,\n role: 'CLIENT',\n \n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n // Options not required for sending payloads to the master process\n (process as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n messageReceiverStart: (options: any) => {\n // Receive a message response back from the primary thread\n this.#startWorkerOptions = { ...options };\n process.on('message', this.#ProcessWorkerMessageRaw);\n },\n messageReceiverStop: (options: any) => { \n process.off('message', this.#ProcessWorkerMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n SendMessage = async (payload: JSONObject): Promise<JSONObject> => {\n if (this.#messagingManager) {\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n return this.#messagingManager?.SendMessage(payload, { });\n } else {\n //@@ send to all clients\n const promArray: Promise<JSONObject>[] = [ ];\n for (const [clientId, clientRecord] of Object.entries(this.#clients)) {\n promArray.push(this.#messagingManager?.SendMessage(payload, { client: clientRecord.client }));\n }\n\n try {\n const retVal = await Promise.all(promArray);\n return {\n result: retVal\n };\n } catch (error) {\n return { };\n }\n }\n } else {\n // Error state - no #ipcMessageManager set\n return { };\n }\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n //return super.on(event, callback, ctx);\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n //return super.off(event, callback);\n }\n\n // Supply complete collection of workers\n Start = () => {\n this.#messagingManager?.Start({ });\n }\n\n // Supply complete collection of workers\n Stop = () => {\n this.#messagingManager?.Stop({ });\n }\n\n /*\n override emit(event: string, ...args: any[]): this {\n const sendMessage = async () => {\n const retVal = await this.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n });\n // Invoke the response callback\n args[args.length-1](retVal);\n };\n sendMessage();\n return this;\n //return super.emit(event, ...args);\n }\n */\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n //const retVal = await this.#messagingManager?.SendMessage({\n const retVal = await this.SendMessage({ \n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload);\n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n console.log(error);\n this.#options.logger.error(chalk.red(`IPCMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n } else {\n //@@ send to all clients\n for (const [clientId, clientRecord] of Object.entries(this.#clients)) {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload, { client: clientRecord.client });\n }\n }\n }\n}","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\n\nimport chalk from 'chalk';\n\nexport interface IPCMessageHandlerPairOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n ignoreEvents?: string[]\n}\n\n/**\n * IPC Message Handling.\n * \n * This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.\n * This class can be used for both tghe cluster primary and the cluster worker.\n * Note: Currently groups handling is not supported. Use the redis version for this capability.\n */\nexport class IPCMessageHandlerPair extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IPCMessageHandlerPairOptions;\n #worker: any = null;\n #events: JSONObject = { };\n #startWorkerOptions: any;\n #startPrimaryWorker: Worker | null = null;\n\n constructor(options: IPCMessageHandlerPairOptions) {\n super();\n this.#options = options;\n if (options.role.localeCompare('CLIENT') === 0) {\n this.SetupWorker();\n } else {\n this.SetupPrimary();\n }\n }\n\n get __events() {\n return this.#events;\n }\n\n #ProcessPrimaryMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, { worker: this.#startPrimaryWorker as Worker });\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: 'SERVER',\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n (options.worker as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n\n\n //@@ also need way to add/remove a worker/child to the collection\n //@@ the ping should also auto remove (such as a failed worker)\n \n\n messageReceiverStart: (options: any) => { //@@ options should be complete collection of workers\n // Receive a message to process from a worker\n const worker = (options.worker as any);\n this.#startPrimaryWorker = worker;\n worker.on('message', this.#ProcessPrimaryMessageRaw);\n },\n messageReceiverStop: (options: any) => { //@@ options should be complete collection of workers\n const worker = (options.worker as any);\n worker.off('message', this.#ProcessPrimaryMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n #ProcessWorkerMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);\n }\n\n SetupWorker = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,\n namespace: this.#options.namespace,\n role: 'CLIENT',\n \n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n // Options not required for sending payloads to the master process\n (process as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n messageReceiverStart: (options: any) => {\n // Receive a message response back from the primary thread\n this.#startWorkerOptions = { ...options };\n process.on('message', this.#ProcessWorkerMessageRaw);\n },\n messageReceiverStop: (options: any) => { \n process.off('message', this.#ProcessWorkerMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n SendMessage = async (payload: JSONObject): Promise<JSONObject> => {\n if (this.#messagingManager) {\n if (this.#worker) {\n return this.#messagingManager?.SendMessage(payload, { worker: this.#worker });\n } else {\n return this.#messagingManager?.SendMessage(payload, { });\n }\n } else {\n // Error state - no #ipcMessageManager set\n return { };\n }\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n //return super.on(event, callback, ctx);\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n //return super.off(event, callback);\n }\n\n // Supply complete collection of workers\n Start = (worker?: any) => {\n if (worker) {\n this.#messagingManager?.Start({ worker });\n this.#worker = worker;\n } else {\n this.#messagingManager?.Start({ });\n }\n }\n\n // Supply complete collection of workers\n Stop = () => {\n if (this.#worker) {\n this.#messagingManager?.Stop({ worker: this.#worker });\n this.#worker = null;\n } else {\n this.#messagingManager?.Stop({ });\n }\n }\n\n get worker(): Worker | null {\n return this.#worker;\n }\n\n /*\n override emit(event: string, ...args: any[]): this {\n const sendMessage = async () => {\n const retVal = await this.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n });\n // Invoke the response callback\n args[args.length-1](retVal);\n };\n sendMessage();\n return this;\n //return super.emit(event, ...args);\n }\n */\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n //const retVal = await this.#messagingManager?.SendMessage({\n const retVal = await this.SendMessage({ \n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload);\n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n console.log(error);\n this.#options.logger.error(chalk.red(`IPCMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n }\n}"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["#id","#options","#messageHeader","#SendMessageNoResponse","#SendMessage","#inflightMessages","#ProcessMessage","#options","#requestChannel","#responseChannel","#ioredisSubscriber","#ioredisPublisher","#LogError","#LogInfo","#pingTimeout","#messagingManager","#clients","#messageSender","#ProcessResponseMessage","#processPayload","#processRawMessage","#events","#options","#events","#messagingManager","#clients","#processPayload","#startWorkerOptions","#ProcessWorkerMessageRaw","#options","#events","#messagingManager","#startPrimaryWorker","#processPayload","#ProcessPrimaryMessageRaw","#startWorkerOptions","#ProcessWorkerMessageRaw","#worker"],"sources":["../src/messagingManager.ts","../src/redisMessageHandler.ts","../src/ipcMessageHandler.ts","../src/ipcMessageHandlerPair.ts"],"sourcesContent":["/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF\nimport { ISTSLogger, JSONObject } from '@nsshunt/stsutils'\n\n//import { randomUUID } from 'node:crypto';\n\nimport { IIPCMessageProcessorIPCPayload, IIPCMessageProcessorWorkerRecord } from './commonTypes.js'\n\nexport interface MessagingManagerOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n groups: string[]\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => void\n ProcessRequestMessage: (payload: IIPCMessageProcessorIPCPayload, options: any) => Promise<JSONObject>\n ProcessResponseMessage?: (reesponses: Record<string, IIPCMessageProcessorIPCPayload>, options: any) => Promise<boolean>\n messageReceiverStart: (options: any) => void\n messageReceiverStop: (options: any) => void\n}\n/**\n * todo\n * @typedef {Object} options - todo\n * @property {boolean} [wssServer=false] - Create a web socket server on this worker instance\n */\nexport class MessagingManager {\n #id: string;\n #options: MessagingManagerOptions;\n #inflightMessages: Record<string, IIPCMessageProcessorWorkerRecord> = { };\n #messageHeader: string;\n\n constructor(options: MessagingManagerOptions) {\n this.#id = globalThis.crypto.randomUUID(); // randomUUID();\n this.#options = options;\n this.#messageHeader = `__STS__${this.#options.namespace}__${globalThis.crypto.randomUUID()}`; // randomUUID();\n }\n\n get id() {\n return this.#id;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ReceivedMessageFromMaster(msg: any) {\n // Override in subclass if required\n }\n\n SendMessageNoResponse = (payload: JSONObject, options?: any): void => {\n this.#SendMessageNoResponse(payload, options);\n };\n\n SendMessage = (payload: JSONObject, options?: any): Promise<JSONObject> => {\n return new Promise((resolve, reject) => {\n this.#SendMessage(payload, options,\n (payload: IIPCMessageProcessorIPCPayload) => {\n resolve(payload.responsePayload);\n },\n (payload: IIPCMessageProcessorIPCPayload) => {\n reject(payload.requestPayload);\n })\n })\n }\n\n #SendMessageNoResponse = (payload: JSONObject, options: any): void => {\n const messageId: string = globalThis.crypto.randomUUID(); // randomUUID();\n const requestPayload: IIPCMessageProcessorIPCPayload = {\n header: this.#messageHeader,\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload: payload,\n responsePayload: { },\n pid: process.pid.toString(),\n messageType: 'REQUEST_NO_RESPONSE'\n }\n\n //console.log(chalk.blue(`#SendMessageNoResponse: [${JSON.stringify(requestPayload)}]`))\n this.#options.messageSender(requestPayload, options);\n }\n\n #SendMessage = (payload: JSONObject, options: any,\n callBack: (payload: IIPCMessageProcessorIPCPayload) => void, \n errorCallBack: (payload: IIPCMessageProcessorIPCPayload) => void\n ): void => {\n const messageId: string = globalThis.crypto.randomUUID(); // randomUUID();\n const requestPayload: IIPCMessageProcessorIPCPayload = {\n header: this.#messageHeader,\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload: payload,\n responsePayload: { },\n pid: process.pid.toString(),\n messageType: 'REQUEST'\n }\n const messageRecord = {\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload,\n responses: { }, // record\n startTime: performance.now(),\n endTime: 0,\n timeout: setTimeout(() => {\n //this.#LogDebugMessage(chalk.red(`Timeout has occurred after: [${this.#options.requestResponseMessageTimeout}]ms with message id: [${messageRecord.messageId}]. Details: [${JSON.stringify(this.#inflightMessages[messageRecord.messageId].requestPayload)}]`));\n setTimeout(() => {\n delete this.#inflightMessages[messageRecord.messageId];\n }, 0).unref();\n errorCallBack(requestPayload);\n }, this.#options.requestResponseMessageTimeout).unref(),// max message timeout allowed\n callBack,\n errorCallBack\n }\n this.#inflightMessages[messageRecord.messageId] = messageRecord;\n //this.#LogDebugMessage(chalk.cyan(`sending: [${JSON.stringify(requestPayload)}]`));\n //console.log(chalk.blue(`#SendMessage: [${JSON.stringify(requestPayload)}]`))\n\n this.#options.messageSender(requestPayload, options);\n }\n\n #ProcessMessage = async (msg: any, options: any): Promise<void> => {\n if (msg.header && msg.header.localeCompare(this.#messageHeader) === 0) {\n const message = (msg as IIPCMessageProcessorIPCPayload);\n if (this.#inflightMessages[message.messageId]) {\n const inFlightMessageRecord: IIPCMessageProcessorWorkerRecord = this.#inflightMessages[message.messageId];\n inFlightMessageRecord.responses[message.senderId ] = { ...message };\n let completed = true; // Defaults to true\n if (this.#options.ProcessResponseMessage) {\n completed = await this.#options.ProcessResponseMessage(inFlightMessageRecord.responses, options);\n if (completed) {\n inFlightMessageRecord.endTime = performance.now();\n clearTimeout(inFlightMessageRecord.timeout as NodeJS.Timeout);\n inFlightMessageRecord.callBack({\n responsePayload: Object.values(inFlightMessageRecord.responses).map(r => r.responsePayload)\n } as any, options) // \n delete this.#inflightMessages[message.messageId];\n }\n } else if (completed) {\n inFlightMessageRecord.endTime = performance.now();\n clearTimeout(inFlightMessageRecord.timeout as NodeJS.Timeout);\n inFlightMessageRecord.callBack(message, options) // inFlightMessageRecord.responses\n //@@inFlightMessageRecord.callBack(Object.values(inFlightMessageRecord.responses), options) // \n delete this.#inflightMessages[message.messageId];\n } else {\n //console.log(chalk.grey(`#ProcessMessage:5`));\n }\n } else {\n //throw new Error(`Could not find Request/Response message with id: [${message.messageId}]`); //@@\n }\n }\n }\n\n Start = (options?: any) => {\n this.#messageHeader = `__STS__${this.#options.namespace}__${globalThis.crypto.randomUUID()}`; // randomUUID()\n this.#options.messageReceiverStart(options);\n }\n\n Stop = (options?: any) => {\n // Kill in-flight messages\n this.#options.messageReceiverStop(options);\n\n for (const [, iPCMessageProcessorWorkerRecord] of Object.entries(this.#inflightMessages)) {\n if (iPCMessageProcessorWorkerRecord.timeout) {\n clearTimeout(iPCMessageProcessorWorkerRecord.timeout);\n }\n }\n this.#inflightMessages = { };\n }\n\n // Process a message recieved from a worker\n ProcessMessage = async (msg: any, options: any) => {\n if (msg.header) {\n const checkName = `__STS__${this.#options.namespace}__`; //@@ this is a broadcast becuase the unique uuid is not part of the header test\n if ((msg.header as string).includes(checkName)) {\n const message = (msg as IIPCMessageProcessorIPCPayload);\n if (msg.messageType.localeCompare('REQUEST') === 0 || msg.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n let processMessage = true;\n if (message.requestPayload.args && message.requestPayload.args.length > 0 && message.requestPayload.args[0].group) {\n const group = message.requestPayload.args[0].group;\n processMessage = (this.#options.groups.indexOf(group) === -1) ? false : true;\n }\n if (processMessage) {\n if (msg.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#options.ProcessRequestMessage(message, options);\n } else {\n message.responsePayload = await this.#options.ProcessRequestMessage(message, options);\n message.senderId = this.#id;\n message.messageType = 'RESPONSE';\n this.#options.messageSender(message, options);\n }\n }\n } else {\n // Received a response (to my request)\n this.#ProcessMessage(msg, options);\n }\n }\n }\n }\n}\n","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\nimport { Redis, RedisOptions } from \"ioredis\";\n\nimport chalk from 'chalk';\n\nconst REQUEST_CHANNEL = '__STS__SVC_stsappframework_request'\nconst RESPONSE_CHANNEL = '__STS__SVC_stsappframework_response'\n\nexport interface IRedisAdminManagerOptions {\n redisUrl: string\n logger: ISTSLogger\n role: 'SERVER' | 'CLIENT'\n namespace: string\n groups: string[]\n ignoreEvents?: string[]\n extraData?: JSONObject\n}\n\nexport interface IClientRecord {\n id: string\n clientConnected: Date\n pingCount: number\n timeout: NodeJS.Timeout\n groups: string[]\n extraData?: JSONObject\n}\n\nexport interface IEventRecord {\n event: string\n callback: any,\n ctx?: any\n}\n\nexport interface IPingData {\n id: string\n groups: string[]\n extraData?: JSONObject\n}\n\nexport class RedisMessageHandler extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IRedisAdminManagerOptions;\n #events: Record<string, IEventRecord> = { };\n #requestChannel: string;\n #responseChannel: string;\n #ioredisSubscriber: Redis;\n #ioredisPublisher: Redis;\n #clients: Record<string, IClientRecord> = { };\n #pingTimeout: NodeJS.Timeout | null = null;\n\n constructor(options: IRedisAdminManagerOptions) {\n super();\n this.#options = options;\n\n this.#requestChannel = REQUEST_CHANNEL\n this.#responseChannel = RESPONSE_CHANNEL\n\n const redisOptions: RedisOptions = {\n showFriendlyErrorStack: true,\n maxRetriesPerRequest: 20\n }\n\n this.#ioredisSubscriber = new Redis(this.#options.redisUrl, redisOptions);\n this.#ioredisPublisher = new Redis(this.#options.redisUrl, redisOptions);\n\n this.#ioredisSubscriber.on(\"error\", (error: Error) => {\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error (redisSubscriber on error): [${error}]`));\n });\n\n this.#ioredisPublisher.on(\"error\", (error: Error) => {\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error (redisPublisher on error): [${error}]`));\n });\n\n this.#ioredisSubscriber.subscribe(this.#requestChannel, this.#responseChannel, (error, count) => {\n if (error) {\n // Just like other commands, subscribe() can fail for some reasons, // ex network issues.\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error - Failed to subscribe: [${error}]`));\n } else {\n // `count` represents the number of channels this client is currently subscribed to.\n this.#LogInfo(chalk.white(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Subscribed successfully! This client is currently subscribed to ${count} channels.`));\n }\n });\n\n this.SetupPrimary();\n\n /*\n const ping = () => {\n this.#pingTimeout = setTimeout(() => {\n const pingData: IPingData = {\n id: (this.#messagingManager as MessagingManager).id,\n groups: this.#options.groups,\n }\n if (this.#options.extraData) {\n pingData.extraData = this.#options.extraData;\n }\n this.emit('ping', pingData, (response: any) => { });\n ping();\n }, 1000).unref();\n }\n ping();\n\n this.on('ping', (pingData: IPingData, callback: any) => {\n const { id, groups, extraData } = pingData;\n if (this.#clients[id]) {\n clearTimeout(this.#clients[id].timeout);\n this.#clients[id].pingCount++;\n this.#clients[id].timeout = setTimeout(() => {\n delete this.#clients[id];\n }, 2000);\n this.#clients[id].groups = groups;\n this.#clients[id].extraData = extraData;\n } else {\n this.#clients[id] = {\n id,\n clientConnected: new Date(),\n pingCount: 0,\n timeout: setTimeout(() => {\n delete this.#clients[id];\n }, 2000),\n groups,\n extraData\n }\n }\n callback('ok');\n });\n */\n\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n const ping = () => {\n this.#pingTimeout = setTimeout(() => {\n const pingData: IPingData = {\n id: (this.#messagingManager as MessagingManager).id,\n groups: this.#options.groups,\n }\n if (this.#options.extraData) {\n pingData.extraData = this.#options.extraData;\n }\n //this.emit('ping', pingData, (response: any) => { });\n this.emitNoResponse('ping', pingData);\n ping();\n }, 1000).unref();\n }\n ping();\n } else {\n this.on('ping', (pingData: IPingData, callback: any) => {\n const { id, groups, extraData } = pingData;\n if (this.#clients[id]) {\n clearTimeout(this.#clients[id].timeout);\n this.#clients[id].pingCount++;\n this.#clients[id].timeout = setTimeout(() => {\n delete this.#clients[id];\n }, 2000);\n this.#clients[id].groups = groups;\n this.#clients[id].extraData = extraData;\n } else {\n this.#clients[id] = {\n id,\n clientConnected: new Date(),\n pingCount: 0,\n timeout: setTimeout(() => {\n delete this.#clients[id];\n }, 2000),\n groups,\n extraData\n }\n }\n //callback('ok');\n });\n }\n }\n\n #LogInfo(message: any) {\n this.#options.logger.info(message);\n }\n\n #LogError(message: any) {\n this.#options.logger.error(message);\n }\n\n #processRawMessage = (channel: string, rawmessage: string) => {\n const message = JSON.parse(rawmessage);\n\n /*\n if (message.requestPayload.__eventName.localeCompare('ping') !== 0) {\n console.log(chalk.cyan(`RedisMessageHandler:#processRawMessage(): Role: [${this.#options.role}] Channel: [${channel}] Message: [${JSON.stringify(message)}]`));\n }\n */\n\n this.#messagingManager?.ProcessMessage(message, { channel });\n }\n\n get clients(): Record<string, IClientRecord> {\n return this.#clients;\n }\n\n get groups(): string[] {\n return this.#options.groups;\n }\n \n AddGroup = (group: string) => {\n const index = this.#options.groups.indexOf(group);\n if (index === -1) {\n this.#options.groups.push(group);\n }\n }\n\n RemoveGroup = (group: string) => {\n const removeIndex = this.#options.groups.indexOf(group);\n if (removeIndex !== -1) {\n this.#options.groups.splice(removeIndex, 1);\n }\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: this.#options.logger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: this.#options.role,\n groups: this.#options.groups,\n messageSender: this.#messageSender,\n // This method is used to calculate if all responses have been received from multiple clients (broadcast)\n // returns true/false.\n ProcessResponseMessage: this.#ProcessResponseMessage,\n // This gets called when an event is received from a message receiver (when ProcessMessage is invoked from the receiver event handler)\n ProcessRequestMessage: this.#processPayload,\n \n messageReceiverStart: (options: any) => {\n this.#ioredisSubscriber.on(\"message\", this.#processRawMessage);\n },\n \n messageReceiverStop: (options: any) => {\n this.#ioredisSubscriber.off(\"message\", this.#processRawMessage);\n }\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n \n #messageSender = (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n\n\n //console.log(chalk.grey(JSON.stringify(payload)));\n\n\n this.#ioredisPublisher.publish(this.#requestChannel, JSON.stringify(payload));\n } else if (payload.messageType.localeCompare('RESPONSE') === 0) {\n this.#ioredisPublisher.publish(this.#responseChannel, JSON.stringify(payload));\n }\n }\n\n \n #ProcessResponseMessage = async (responses: Record<string, IIPCMessageProcessorIPCPayload>, options: any): Promise<boolean> => {\n // Now check if we have all responses ...\n\n /*\n let allFound = false;\n\n for (const [responseId, response] of Object.entries(responses)) {\n if (response.senderRole.localeCompare('CLIENT') === 0) {\n allFound = true;\n break;\n }\n }\n if (allFound) {\n return allFound;\n }\n */\n\n let found = true;\n\n // Sender role here is SERVER\n let requestGroup = null;\n for (const [responseId, response] of Object.entries(responses)) {\n if (response.requestPayload.args.length > 0 && response.requestPayload.args[0].group) {\n requestGroup = response.requestPayload.args[0].group;\n break;\n }\n }\n\n if (requestGroup) {\n const clientsInGroup = Object.values(this.#clients).filter(c => {\n if (c.groups.indexOf(requestGroup) === -1) {\n return false;\n }\n return true;\n });\n\n // Now make sure that all clients are in the responses\n found = true;\n clientsInGroup.forEach(c => {\n if (!responses[c.id]) {\n found = false;\n }\n })\n } else {\n const clientsInGroup = Object.values(this.#clients)\n\n // Now make sure that all clients are in the responses\n found = true;\n clientsInGroup.forEach(c => {\n if (!responses[c.id]) {\n found = false;\n }\n })\n }\n\n return found;\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject: IEventRecord = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n }\n\n Start = () => {\n this.#messagingManager?.Start();\n }\n\n Stop = () => {\n if (this.#pingTimeout) {\n clearTimeout(this.#pingTimeout);\n this.#pingTimeout = null;\n }\n\n this.#messagingManager?.Stop();\n\n this.#ioredisSubscriber.quit();\n this.#ioredisSubscriber.disconnect();\n\n this.#ioredisPublisher.quit();\n this.#ioredisPublisher.disconnect();\n }\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n const retVal = await this.#messagingManager?.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload); \n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n this.#options.logger.error(chalk.red(`RedisMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitWithError(event: string, args: JSONObject, responseCb: (response: JSONObject | undefined) => void, errorCb: (error: any) => void): this {\n (async () => {\n try {\n const retVal = await this.#messagingManager?.SendMessage({\n __eventName: event,\n args: [ args ]\n } as IEventPayload); \n // Invoke the response callback\n responseCb(retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n //this.#options.logger.error(chalk.red(`RedisMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n errorCb(error);\n }\n })();\n return this;\n }\n\n emitex = async(event: string, ...args: any[]): Promise<JSONObject> => {\n return (this.#messagingManager as MessagingManager).SendMessage({\n __eventName: event,\n args\n } as IEventPayload); \n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n }\n}","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\n\nimport chalk from 'chalk';\n\n//import { randomUUID } from 'node:crypto';\n\nexport interface IPCMessageHandlerOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n ignoreEvents?: string[]\n}\n\ndeclare interface IClientRecord {\n client: any\n processMessage: (client: any) => void\n}\n\n/**\n * IPC Message Handling.\n * \n * This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.\n * This class can be used for both tghe cluster primary and the cluster worker.\n * Note: Currently groups handling is not supported. Use the redis version for this capability.\n */\nexport class IPCMessageHandler extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IPCMessageHandlerOptions;\n #clients: Record<string, IClientRecord> = { };\n #events: JSONObject = { };\n #startWorkerOptions: any;\n\n constructor(options: IPCMessageHandlerOptions) {\n super();\n this.#options = options;\n if (options.role.localeCompare('CLIENT') === 0) {\n this.SetupWorker();\n } else {\n this.SetupPrimary();\n }\n }\n\n get __events() {\n return this.#events;\n }\n\n AddClient = (client: any): string => {\n const id = globalThis.crypto.randomUUID(); // randomUUID();\n\n const processMessage = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, { client });\n };\n\n client.on('message', processMessage);\n this.#clients[id] = {\n client,\n processMessage\n }\n return id;\n }\n\n RemoveClient = (id: string) => {\n const clientRecord = this.#clients[id];\n if (clientRecord) {\n clientRecord.client.off('message', clientRecord.processMessage);\n delete this.#clients[id];\n }\n }\n\n get clients() {\n return this.#clients;\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: 'SERVER',\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n (options.client as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n\n\n //@@ also need way to add/remove a worker/child to the collection\n //@@ the ping should also auto remove (such as a failed worker)\n \n\n messageReceiverStart: (options: any) => { //@@ options should be complete collection of workers\n // Receive a message to process from a worker\n },\n messageReceiverStop: (options: any) => { //@@ options should be complete collection of workers\n\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n #ProcessWorkerMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);\n }\n\n SetupWorker = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,\n namespace: this.#options.namespace,\n role: 'CLIENT',\n \n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n // Options not required for sending payloads to the master process\n (process as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n messageReceiverStart: (options: any) => {\n // Receive a message response back from the primary thread\n this.#startWorkerOptions = { ...options };\n process.on('message', this.#ProcessWorkerMessageRaw);\n },\n messageReceiverStop: (options: any) => { \n process.off('message', this.#ProcessWorkerMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n SendMessage = async (payload: JSONObject): Promise<JSONObject> => {\n if (this.#messagingManager) {\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n return this.#messagingManager?.SendMessage(payload, { });\n } else {\n //@@ send to all clients\n const promArray: Promise<JSONObject>[] = [ ];\n for (const [clientId, clientRecord] of Object.entries(this.#clients)) {\n promArray.push(this.#messagingManager?.SendMessage(payload, { client: clientRecord.client }));\n }\n\n try {\n const retVal = await Promise.all(promArray);\n return {\n result: retVal\n };\n } catch (error) {\n return { };\n }\n }\n } else {\n // Error state - no #ipcMessageManager set\n return { };\n }\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n //return super.on(event, callback, ctx);\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n //return super.off(event, callback);\n }\n\n // Supply complete collection of workers\n Start = () => {\n this.#messagingManager?.Start({ });\n }\n\n // Supply complete collection of workers\n Stop = () => {\n this.#messagingManager?.Stop({ });\n }\n\n /*\n override emit(event: string, ...args: any[]): this {\n const sendMessage = async () => {\n const retVal = await this.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n });\n // Invoke the response callback\n args[args.length-1](retVal);\n };\n sendMessage();\n return this;\n //return super.emit(event, ...args);\n }\n */\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n //const retVal = await this.#messagingManager?.SendMessage({\n const retVal = await this.SendMessage({ \n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload);\n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n console.log(error);\n this.#options.logger.error(chalk.red(`IPCMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n } else {\n //@@ send to all clients\n for (const [clientId, clientRecord] of Object.entries(this.#clients)) {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload, { client: clientRecord.client });\n }\n }\n }\n}","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\n\nimport chalk from 'chalk';\n\nexport interface IPCMessageHandlerPairOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n ignoreEvents?: string[]\n}\n\n/**\n * IPC Message Handling.\n * \n * This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.\n * This class can be used for both tghe cluster primary and the cluster worker.\n * Note: Currently groups handling is not supported. Use the redis version for this capability.\n */\nexport class IPCMessageHandlerPair extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IPCMessageHandlerPairOptions;\n #worker: any = null;\n #events: JSONObject = { };\n #startWorkerOptions: any;\n #startPrimaryWorker: Worker | null = null;\n\n constructor(options: IPCMessageHandlerPairOptions) {\n super();\n this.#options = options;\n if (options.role.localeCompare('CLIENT') === 0) {\n this.SetupWorker();\n } else {\n this.SetupPrimary();\n }\n }\n\n get __events() {\n return this.#events;\n }\n\n #ProcessPrimaryMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, { worker: this.#startPrimaryWorker as Worker });\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: 'SERVER',\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n (options.worker as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n\n\n //@@ also need way to add/remove a worker/child to the collection\n //@@ the ping should also auto remove (such as a failed worker)\n \n\n messageReceiverStart: (options: any) => { //@@ options should be complete collection of workers\n // Receive a message to process from a worker\n const worker = (options.worker as any);\n this.#startPrimaryWorker = worker;\n worker.on('message', this.#ProcessPrimaryMessageRaw);\n },\n messageReceiverStop: (options: any) => { //@@ options should be complete collection of workers\n const worker = (options.worker as any);\n worker.off('message', this.#ProcessPrimaryMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n #ProcessWorkerMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);\n }\n\n SetupWorker = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,\n namespace: this.#options.namespace,\n role: 'CLIENT',\n \n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n // Options not required for sending payloads to the master process\n (process as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n messageReceiverStart: (options: any) => {\n // Receive a message response back from the primary thread\n this.#startWorkerOptions = { ...options };\n process.on('message', this.#ProcessWorkerMessageRaw);\n },\n messageReceiverStop: (options: any) => { \n process.off('message', this.#ProcessWorkerMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n SendMessage = async (payload: JSONObject): Promise<JSONObject> => {\n if (this.#messagingManager) {\n if (this.#worker) {\n return this.#messagingManager?.SendMessage(payload, { worker: this.#worker });\n } else {\n return this.#messagingManager?.SendMessage(payload, { });\n }\n } else {\n // Error state - no #ipcMessageManager set\n return { };\n }\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n //return super.on(event, callback, ctx);\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n //return super.off(event, callback);\n }\n\n // Supply complete collection of workers\n Start = (worker?: any) => {\n if (worker) {\n this.#messagingManager?.Start({ worker });\n this.#worker = worker;\n } else {\n this.#messagingManager?.Start({ });\n }\n }\n\n // Supply complete collection of workers\n Stop = () => {\n if (this.#worker) {\n this.#messagingManager?.Stop({ worker: this.#worker });\n this.#worker = null;\n } else {\n this.#messagingManager?.Stop({ });\n }\n }\n\n get worker(): Worker | null {\n return this.#worker;\n }\n\n /*\n override emit(event: string, ...args: any[]): this {\n const sendMessage = async () => {\n const retVal = await this.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n });\n // Invoke the response callback\n args[args.length-1](retVal);\n };\n sendMessage();\n return this;\n //return super.emit(event, ...args);\n }\n */\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n //const retVal = await this.#messagingManager?.SendMessage({\n const retVal = await this.SendMessage({ \n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload);\n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n console.log(error);\n this.#options.logger.error(chalk.red(`IPCMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n }\n}"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -231,7 +231,7 @@ var RedisMessageHandler = class extends TinyEmitter {
|
|
|
231
231
|
if (removeIndex !== -1) this.#options.groups.splice(removeIndex, 1);
|
|
232
232
|
};
|
|
233
233
|
SetupPrimary = () => {
|
|
234
|
-
|
|
234
|
+
const ipcMessageManagerOptions = {
|
|
235
235
|
logger: this.#options.logger,
|
|
236
236
|
requestResponseMessageTimeout: 5e3,
|
|
237
237
|
namespace: this.#options.namespace,
|
|
@@ -246,7 +246,8 @@ var RedisMessageHandler = class extends TinyEmitter {
|
|
|
246
246
|
messageReceiverStop: (options) => {
|
|
247
247
|
this.#ioredisSubscriber.off("message", this.#processRawMessage);
|
|
248
248
|
}
|
|
249
|
-
}
|
|
249
|
+
};
|
|
250
|
+
this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);
|
|
250
251
|
};
|
|
251
252
|
#messageSender = (payload, options) => {
|
|
252
253
|
if (payload.messageType.localeCompare("REQUEST") === 0 || payload.messageType.localeCompare("REQUEST_NO_RESPONSE") === 0) this.#ioredisPublisher.publish(this.#requestChannel, JSON.stringify(payload));
|
|
@@ -417,7 +418,7 @@ var IPCMessageHandler = class extends TinyEmitter {
|
|
|
417
418
|
return this.#clients;
|
|
418
419
|
}
|
|
419
420
|
SetupPrimary = () => {
|
|
420
|
-
|
|
421
|
+
const ipcMessageManagerOptions = {
|
|
421
422
|
logger: defaultLogger,
|
|
422
423
|
requestResponseMessageTimeout: 5e3,
|
|
423
424
|
namespace: this.#options.namespace,
|
|
@@ -431,13 +432,14 @@ var IPCMessageHandler = class extends TinyEmitter {
|
|
|
431
432
|
messageReceiverStart: (options) => {},
|
|
432
433
|
messageReceiverStop: (options) => {},
|
|
433
434
|
groups: []
|
|
434
|
-
}
|
|
435
|
+
};
|
|
436
|
+
this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);
|
|
435
437
|
};
|
|
436
438
|
#ProcessWorkerMessageRaw = (payload) => {
|
|
437
439
|
this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);
|
|
438
440
|
};
|
|
439
441
|
SetupWorker = () => {
|
|
440
|
-
|
|
442
|
+
const ipcMessageManagerOptions = {
|
|
441
443
|
logger: defaultLogger,
|
|
442
444
|
requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,
|
|
443
445
|
namespace: this.#options.namespace,
|
|
@@ -456,7 +458,8 @@ var IPCMessageHandler = class extends TinyEmitter {
|
|
|
456
458
|
process.off("message", this.#ProcessWorkerMessageRaw);
|
|
457
459
|
},
|
|
458
460
|
groups: []
|
|
459
|
-
}
|
|
461
|
+
};
|
|
462
|
+
this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);
|
|
460
463
|
};
|
|
461
464
|
SendMessage = async (payload) => {
|
|
462
465
|
if (this.#messagingManager) if (this.#options.role.localeCompare("CLIENT") === 0) return this.#messagingManager?.SendMessage(payload, {});
|
|
@@ -568,7 +571,7 @@ var IPCMessageHandlerPair = class extends TinyEmitter {
|
|
|
568
571
|
this.#messagingManager?.ProcessMessage(payload, { worker: this.#startPrimaryWorker });
|
|
569
572
|
};
|
|
570
573
|
SetupPrimary = () => {
|
|
571
|
-
|
|
574
|
+
const ipcMessageManagerOptions = {
|
|
572
575
|
logger: defaultLogger,
|
|
573
576
|
requestResponseMessageTimeout: 5e3,
|
|
574
577
|
namespace: this.#options.namespace,
|
|
@@ -588,13 +591,14 @@ var IPCMessageHandlerPair = class extends TinyEmitter {
|
|
|
588
591
|
options.worker.off("message", this.#ProcessPrimaryMessageRaw);
|
|
589
592
|
},
|
|
590
593
|
groups: []
|
|
591
|
-
}
|
|
594
|
+
};
|
|
595
|
+
this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);
|
|
592
596
|
};
|
|
593
597
|
#ProcessWorkerMessageRaw = (payload) => {
|
|
594
598
|
this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);
|
|
595
599
|
};
|
|
596
600
|
SetupWorker = () => {
|
|
597
|
-
|
|
601
|
+
const ipcMessageManagerOptions = {
|
|
598
602
|
logger: defaultLogger,
|
|
599
603
|
requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,
|
|
600
604
|
namespace: this.#options.namespace,
|
|
@@ -613,7 +617,8 @@ var IPCMessageHandlerPair = class extends TinyEmitter {
|
|
|
613
617
|
process.off("message", this.#ProcessWorkerMessageRaw);
|
|
614
618
|
},
|
|
615
619
|
groups: []
|
|
616
|
-
}
|
|
620
|
+
};
|
|
621
|
+
this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);
|
|
617
622
|
};
|
|
618
623
|
SendMessage = async (payload) => {
|
|
619
624
|
if (this.#messagingManager) if (this.#worker) return this.#messagingManager?.SendMessage(payload, { worker: this.#worker });
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["#id","#options","#messageHeader","#SendMessageNoResponse","#SendMessage","#inflightMessages","#ProcessMessage","#options","#requestChannel","#responseChannel","#ioredisSubscriber","#ioredisPublisher","#LogError","#LogInfo","#pingTimeout","#messagingManager","#clients","#messageSender","#ProcessResponseMessage","#processPayload","#processRawMessage","#events","#options","#events","#messagingManager","#clients","#processPayload","#startWorkerOptions","#ProcessWorkerMessageRaw","#options","#events","#messagingManager","#startPrimaryWorker","#processPayload","#ProcessPrimaryMessageRaw","#startWorkerOptions","#ProcessWorkerMessageRaw","#worker"],"sources":["../src/messagingManager.ts","../src/redisMessageHandler.ts","../src/ipcMessageHandler.ts","../src/ipcMessageHandlerPair.ts"],"sourcesContent":["/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF\nimport { ISTSLogger, JSONObject } from '@nsshunt/stsutils'\n\n//import { randomUUID } from 'node:crypto';\n\nimport { IIPCMessageProcessorIPCPayload, IIPCMessageProcessorWorkerRecord } from './commonTypes.js'\n\nexport interface MessagingManagerOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n groups: string[]\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => void\n ProcessRequestMessage: (payload: IIPCMessageProcessorIPCPayload, options: any) => Promise<JSONObject>\n ProcessResponseMessage?: (reesponses: Record<string, IIPCMessageProcessorIPCPayload>, options: any) => Promise<boolean>\n messageReceiverStart: (options: any) => void\n messageReceiverStop: (options: any) => void\n}\n/**\n * todo\n * @typedef {Object} options - todo\n * @property {boolean} [wssServer=false] - Create a web socket server on this worker instance\n */\nexport class MessagingManager {\n #id: string;\n #options: MessagingManagerOptions;\n #inflightMessages: Record<string, IIPCMessageProcessorWorkerRecord> = { };\n #messageHeader: string;\n\n constructor(options: MessagingManagerOptions) {\n this.#id = globalThis.crypto.randomUUID(); // randomUUID();\n this.#options = options;\n this.#messageHeader = `__STS__${this.#options.namespace}__${globalThis.crypto.randomUUID()}`; // randomUUID();\n }\n\n get id() {\n return this.#id;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ReceivedMessageFromMaster(msg: any) {\n // Override in subclass if required\n }\n\n SendMessageNoResponse = (payload: JSONObject, options?: any): void => {\n this.#SendMessageNoResponse(payload, options);\n };\n\n SendMessage = (payload: JSONObject, options?: any): Promise<JSONObject> => {\n return new Promise((resolve, reject) => {\n this.#SendMessage(payload, options,\n (payload: IIPCMessageProcessorIPCPayload) => {\n resolve(payload.responsePayload);\n },\n (payload: IIPCMessageProcessorIPCPayload) => {\n reject(payload.requestPayload);\n })\n })\n }\n\n #SendMessageNoResponse = (payload: JSONObject, options: any): void => {\n const messageId: string = globalThis.crypto.randomUUID(); // randomUUID();\n const requestPayload: IIPCMessageProcessorIPCPayload = {\n header: this.#messageHeader,\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload: payload,\n responsePayload: { },\n pid: process.pid.toString(),\n messageType: 'REQUEST_NO_RESPONSE'\n }\n\n //console.log(chalk.blue(`#SendMessageNoResponse: [${JSON.stringify(requestPayload)}]`))\n this.#options.messageSender(requestPayload, options);\n }\n\n #SendMessage = (payload: JSONObject, options: any,\n callBack: (payload: IIPCMessageProcessorIPCPayload) => void, \n errorCallBack: (payload: IIPCMessageProcessorIPCPayload) => void\n ): void => {\n const messageId: string = globalThis.crypto.randomUUID(); // randomUUID();\n const requestPayload: IIPCMessageProcessorIPCPayload = {\n header: this.#messageHeader,\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload: payload,\n responsePayload: { },\n pid: process.pid.toString(),\n messageType: 'REQUEST'\n }\n const messageRecord = {\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload,\n responses: { }, // record\n startTime: performance.now(),\n endTime: 0,\n timeout: setTimeout(() => {\n //this.#LogDebugMessage(chalk.red(`Timeout has occurred after: [${this.#options.requestResponseMessageTimeout}]ms with message id: [${messageRecord.messageId}]. Details: [${JSON.stringify(this.#inflightMessages[messageRecord.messageId].requestPayload)}]`));\n setTimeout(() => {\n delete this.#inflightMessages[messageRecord.messageId];\n }, 0).unref();\n errorCallBack(requestPayload);\n }, this.#options.requestResponseMessageTimeout).unref(),// max message timeout allowed\n callBack,\n errorCallBack\n }\n this.#inflightMessages[messageRecord.messageId] = messageRecord;\n //this.#LogDebugMessage(chalk.cyan(`sending: [${JSON.stringify(requestPayload)}]`));\n //console.log(chalk.blue(`#SendMessage: [${JSON.stringify(requestPayload)}]`))\n\n this.#options.messageSender(requestPayload, options);\n }\n\n #ProcessMessage = async (msg: any, options: any): Promise<void> => {\n if (msg.header && msg.header.localeCompare(this.#messageHeader) === 0) {\n const message = (msg as IIPCMessageProcessorIPCPayload);\n if (this.#inflightMessages[message.messageId]) {\n const inFlightMessageRecord: IIPCMessageProcessorWorkerRecord = this.#inflightMessages[message.messageId];\n inFlightMessageRecord.responses[message.senderId ] = { ...message };\n let completed = true; // Defaults to true\n if (this.#options.ProcessResponseMessage) {\n completed = await this.#options.ProcessResponseMessage(inFlightMessageRecord.responses, options);\n if (completed) {\n inFlightMessageRecord.endTime = performance.now();\n clearTimeout(inFlightMessageRecord.timeout as NodeJS.Timeout);\n inFlightMessageRecord.callBack({\n responsePayload: Object.values(inFlightMessageRecord.responses).map(r => r.responsePayload)\n } as any, options) // \n delete this.#inflightMessages[message.messageId];\n }\n } else if (completed) {\n inFlightMessageRecord.endTime = performance.now();\n clearTimeout(inFlightMessageRecord.timeout as NodeJS.Timeout);\n inFlightMessageRecord.callBack(message, options) // inFlightMessageRecord.responses\n //@@inFlightMessageRecord.callBack(Object.values(inFlightMessageRecord.responses), options) // \n delete this.#inflightMessages[message.messageId];\n } else {\n //console.log(chalk.grey(`#ProcessMessage:5`));\n }\n } else {\n //throw new Error(`Could not find Request/Response message with id: [${message.messageId}]`); //@@\n }\n }\n }\n\n Start = (options?: any) => {\n this.#messageHeader = `__STS__${this.#options.namespace}__${globalThis.crypto.randomUUID()}`; // randomUUID()\n this.#options.messageReceiverStart(options);\n }\n\n Stop = (options?: any) => {\n // Kill in-flight messages\n this.#options.messageReceiverStop(options);\n\n for (const [, iPCMessageProcessorWorkerRecord] of Object.entries(this.#inflightMessages)) {\n if (iPCMessageProcessorWorkerRecord.timeout) {\n clearTimeout(iPCMessageProcessorWorkerRecord.timeout);\n }\n }\n this.#inflightMessages = { };\n }\n\n // Process a message recieved from a worker\n ProcessMessage = async (msg: any, options: any) => {\n if (msg.header) {\n const checkName = `__STS__${this.#options.namespace}__`; //@@ this is a broadcast becuase the unique uuid is not part of the header test\n if ((msg.header as string).includes(checkName)) {\n const message = (msg as IIPCMessageProcessorIPCPayload);\n if (msg.messageType.localeCompare('REQUEST') === 0 || msg.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n let processMessage = true;\n if (message.requestPayload.args && message.requestPayload.args.length > 0 && message.requestPayload.args[0].group) {\n const group = message.requestPayload.args[0].group;\n processMessage = (this.#options.groups.indexOf(group) === -1) ? false : true;\n }\n if (processMessage) {\n if (msg.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#options.ProcessRequestMessage(message, options);\n } else {\n message.responsePayload = await this.#options.ProcessRequestMessage(message, options);\n message.senderId = this.#id;\n message.messageType = 'RESPONSE';\n this.#options.messageSender(message, options);\n }\n }\n } else {\n // Received a response (to my request)\n this.#ProcessMessage(msg, options);\n }\n }\n }\n }\n}\n","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\nimport { Redis, RedisOptions } from \"ioredis\";\n\nimport chalk from 'chalk';\n\nconst REQUEST_CHANNEL = '__STS__SVC_stsappframework_request'\nconst RESPONSE_CHANNEL = '__STS__SVC_stsappframework_response'\n\nexport interface IRedisAdminManagerOptions {\n redisUrl: string\n logger: ISTSLogger\n role: 'SERVER' | 'CLIENT'\n namespace: string\n groups: string[]\n ignoreEvents?: string[]\n extraData?: JSONObject\n}\n\nexport interface IClientRecord {\n id: string\n clientConnected: Date\n pingCount: number\n timeout: NodeJS.Timeout\n groups: string[]\n extraData?: JSONObject\n}\n\nexport interface IEventRecord {\n event: string\n callback: any,\n ctx?: any\n}\n\nexport interface IPingData {\n id: string\n groups: string[]\n extraData?: JSONObject\n}\n\nexport class RedisMessageHandler extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IRedisAdminManagerOptions;\n #events: Record<string, IEventRecord> = { };\n #requestChannel: string;\n #responseChannel: string;\n #ioredisSubscriber: Redis;\n #ioredisPublisher: Redis;\n #clients: Record<string, IClientRecord> = { };\n #pingTimeout: NodeJS.Timeout | null = null;\n\n constructor(options: IRedisAdminManagerOptions) {\n super();\n this.#options = options;\n\n this.#requestChannel = REQUEST_CHANNEL\n this.#responseChannel = RESPONSE_CHANNEL\n\n const redisOptions: RedisOptions = {\n showFriendlyErrorStack: true,\n maxRetriesPerRequest: 20\n }\n\n this.#ioredisSubscriber = new Redis(this.#options.redisUrl, redisOptions);\n this.#ioredisPublisher = new Redis(this.#options.redisUrl, redisOptions);\n\n this.#ioredisSubscriber.on(\"error\", (error: Error) => {\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error (redisSubscriber on error): [${error}]`));\n });\n\n this.#ioredisPublisher.on(\"error\", (error: Error) => {\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error (redisPublisher on error): [${error}]`));\n });\n\n this.#ioredisSubscriber.subscribe(this.#requestChannel, this.#responseChannel, (error, count) => {\n if (error) {\n // Just like other commands, subscribe() can fail for some reasons, // ex network issues.\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error - Failed to subscribe: [${error}]`));\n } else {\n // `count` represents the number of channels this client is currently subscribed to.\n this.#LogInfo(chalk.white(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Subscribed successfully! This client is currently subscribed to ${count} channels.`));\n }\n });\n\n this.SetupPrimary();\n\n /*\n const ping = () => {\n this.#pingTimeout = setTimeout(() => {\n const pingData: IPingData = {\n id: (this.#messagingManager as MessagingManager).id,\n groups: this.#options.groups,\n }\n if (this.#options.extraData) {\n pingData.extraData = this.#options.extraData;\n }\n this.emit('ping', pingData, (response: any) => { });\n ping();\n }, 1000).unref();\n }\n ping();\n\n this.on('ping', (pingData: IPingData, callback: any) => {\n const { id, groups, extraData } = pingData;\n if (this.#clients[id]) {\n clearTimeout(this.#clients[id].timeout);\n this.#clients[id].pingCount++;\n this.#clients[id].timeout = setTimeout(() => {\n delete this.#clients[id];\n }, 2000);\n this.#clients[id].groups = groups;\n this.#clients[id].extraData = extraData;\n } else {\n this.#clients[id] = {\n id,\n clientConnected: new Date(),\n pingCount: 0,\n timeout: setTimeout(() => {\n delete this.#clients[id];\n }, 2000),\n groups,\n extraData\n }\n }\n callback('ok');\n });\n */\n\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n const ping = () => {\n this.#pingTimeout = setTimeout(() => {\n const pingData: IPingData = {\n id: (this.#messagingManager as MessagingManager).id,\n groups: this.#options.groups,\n }\n if (this.#options.extraData) {\n pingData.extraData = this.#options.extraData;\n }\n //this.emit('ping', pingData, (response: any) => { });\n this.emitNoResponse('ping', pingData);\n ping();\n }, 1000).unref();\n }\n ping();\n } else {\n this.on('ping', (pingData: IPingData, callback: any) => {\n const { id, groups, extraData } = pingData;\n if (this.#clients[id]) {\n clearTimeout(this.#clients[id].timeout);\n this.#clients[id].pingCount++;\n this.#clients[id].timeout = setTimeout(() => {\n delete this.#clients[id];\n }, 2000);\n this.#clients[id].groups = groups;\n this.#clients[id].extraData = extraData;\n } else {\n this.#clients[id] = {\n id,\n clientConnected: new Date(),\n pingCount: 0,\n timeout: setTimeout(() => {\n delete this.#clients[id];\n }, 2000),\n groups,\n extraData\n }\n }\n //callback('ok');\n });\n }\n }\n\n #LogInfo(message: any) {\n this.#options.logger.info(message);\n }\n\n #LogError(message: any) {\n this.#options.logger.error(message);\n }\n\n #processRawMessage = (channel: string, rawmessage: string) => {\n const message = JSON.parse(rawmessage);\n\n /*\n if (message.requestPayload.__eventName.localeCompare('ping') !== 0) {\n console.log(chalk.cyan(`RedisMessageHandler:#processRawMessage(): Role: [${this.#options.role}] Channel: [${channel}] Message: [${JSON.stringify(message)}]`));\n }\n */\n\n this.#messagingManager?.ProcessMessage(message, { channel });\n }\n\n get clients(): Record<string, IClientRecord> {\n return this.#clients;\n }\n\n get groups(): string[] {\n return this.#options.groups;\n }\n \n AddGroup = (group: string) => {\n const index = this.#options.groups.indexOf(group);\n if (index === -1) {\n this.#options.groups.push(group);\n }\n }\n\n RemoveGroup = (group: string) => {\n const removeIndex = this.#options.groups.indexOf(group);\n if (removeIndex !== -1) {\n this.#options.groups.splice(removeIndex, 1);\n }\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: this.#options.logger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: this.#options.role,\n groups: this.#options.groups,\n messageSender: this.#messageSender,\n // This method is used to calculate if all responses have been received from multiple clients (broadcast)\n // returns true/false.\n ProcessResponseMessage: this.#ProcessResponseMessage,\n // This gets called when an event is received from a message receiver (when ProcessMessage is invoked from the receiver event handler)\n ProcessRequestMessage: this.#processPayload,\n \n messageReceiverStart: (options: any) => {\n this.#ioredisSubscriber.on(\"message\", this.#processRawMessage);\n },\n \n messageReceiverStop: (options: any) => {\n this.#ioredisSubscriber.off(\"message\", this.#processRawMessage);\n }\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n \n #messageSender = (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n\n\n //console.log(chalk.grey(JSON.stringify(payload)));\n\n\n this.#ioredisPublisher.publish(this.#requestChannel, JSON.stringify(payload));\n } else if (payload.messageType.localeCompare('RESPONSE') === 0) {\n this.#ioredisPublisher.publish(this.#responseChannel, JSON.stringify(payload));\n }\n }\n\n \n #ProcessResponseMessage = async (responses: Record<string, IIPCMessageProcessorIPCPayload>, options: any): Promise<boolean> => {\n // Now check if we have all responses ...\n\n /*\n let allFound = false;\n\n for (const [responseId, response] of Object.entries(responses)) {\n if (response.senderRole.localeCompare('CLIENT') === 0) {\n allFound = true;\n break;\n }\n }\n if (allFound) {\n return allFound;\n }\n */\n\n let found = true;\n\n // Sender role here is SERVER\n let requestGroup = null;\n for (const [responseId, response] of Object.entries(responses)) {\n if (response.requestPayload.args.length > 0 && response.requestPayload.args[0].group) {\n requestGroup = response.requestPayload.args[0].group;\n break;\n }\n }\n\n if (requestGroup) {\n const clientsInGroup = Object.values(this.#clients).filter(c => {\n if (c.groups.indexOf(requestGroup) === -1) {\n return false;\n }\n return true;\n });\n\n // Now make sure that all clients are in the responses\n found = true;\n clientsInGroup.forEach(c => {\n if (!responses[c.id]) {\n found = false;\n }\n })\n } else {\n const clientsInGroup = Object.values(this.#clients)\n\n // Now make sure that all clients are in the responses\n found = true;\n clientsInGroup.forEach(c => {\n if (!responses[c.id]) {\n found = false;\n }\n })\n }\n\n return found;\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject: IEventRecord = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n }\n\n Start = () => {\n this.#messagingManager?.Start();\n }\n\n Stop = () => {\n if (this.#pingTimeout) {\n clearTimeout(this.#pingTimeout);\n this.#pingTimeout = null;\n }\n\n this.#messagingManager?.Stop();\n\n this.#ioredisSubscriber.quit();\n this.#ioredisSubscriber.disconnect();\n\n this.#ioredisPublisher.quit();\n this.#ioredisPublisher.disconnect();\n }\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n const retVal = await this.#messagingManager?.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload); \n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n this.#options.logger.error(chalk.red(`RedisMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitWithError(event: string, args: JSONObject, responseCb: (response: JSONObject | undefined) => void, errorCb: (error: any) => void): this {\n (async () => {\n try {\n const retVal = await this.#messagingManager?.SendMessage({\n __eventName: event,\n args: [ args ]\n } as IEventPayload); \n // Invoke the response callback\n responseCb(retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n //this.#options.logger.error(chalk.red(`RedisMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n errorCb(error);\n }\n })();\n return this;\n }\n\n emitex = async(event: string, ...args: any[]): Promise<JSONObject> => {\n return (this.#messagingManager as MessagingManager).SendMessage({\n __eventName: event,\n args\n } as IEventPayload); \n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n }\n}","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\n\nimport chalk from 'chalk';\n\n//import { randomUUID } from 'node:crypto';\n\nexport interface IPCMessageHandlerOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n ignoreEvents?: string[]\n}\n\ndeclare interface IClientRecord {\n client: any\n processMessage: (client: any) => void\n}\n\n/**\n * IPC Message Handling.\n * \n * This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.\n * This class can be used for both tghe cluster primary and the cluster worker.\n * Note: Currently groups handling is not supported. Use the redis version for this capability.\n */\nexport class IPCMessageHandler extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IPCMessageHandlerOptions;\n #clients: Record<string, IClientRecord> = { };\n #events: JSONObject = { };\n #startWorkerOptions: any;\n\n constructor(options: IPCMessageHandlerOptions) {\n super();\n this.#options = options;\n if (options.role.localeCompare('CLIENT') === 0) {\n this.SetupWorker();\n } else {\n this.SetupPrimary();\n }\n }\n\n get __events() {\n return this.#events;\n }\n\n AddClient = (client: any): string => {\n const id = globalThis.crypto.randomUUID(); // randomUUID();\n\n const processMessage = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, { client });\n };\n\n client.on('message', processMessage);\n this.#clients[id] = {\n client,\n processMessage\n }\n return id;\n }\n\n RemoveClient = (id: string) => {\n const clientRecord = this.#clients[id];\n if (clientRecord) {\n clientRecord.client.off('message', clientRecord.processMessage);\n delete this.#clients[id];\n }\n }\n\n get clients() {\n return this.#clients;\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: 'SERVER',\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n (options.client as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n\n\n //@@ also need way to add/remove a worker/child to the collection\n //@@ the ping should also auto remove (such as a failed worker)\n \n\n messageReceiverStart: (options: any) => { //@@ options should be complete collection of workers\n // Receive a message to process from a worker\n },\n messageReceiverStop: (options: any) => { //@@ options should be complete collection of workers\n\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n #ProcessWorkerMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);\n }\n\n SetupWorker = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,\n namespace: this.#options.namespace,\n role: 'CLIENT',\n \n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n // Options not required for sending payloads to the master process\n (process as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n messageReceiverStart: (options: any) => {\n // Receive a message response back from the primary thread\n this.#startWorkerOptions = { ...options };\n process.on('message', this.#ProcessWorkerMessageRaw);\n },\n messageReceiverStop: (options: any) => { \n process.off('message', this.#ProcessWorkerMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n SendMessage = async (payload: JSONObject): Promise<JSONObject> => {\n if (this.#messagingManager) {\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n return this.#messagingManager?.SendMessage(payload, { });\n } else {\n //@@ send to all clients\n const promArray: Promise<JSONObject>[] = [ ];\n for (const [clientId, clientRecord] of Object.entries(this.#clients)) {\n promArray.push(this.#messagingManager?.SendMessage(payload, { client: clientRecord.client }));\n }\n\n try {\n const retVal = await Promise.all(promArray);\n return {\n result: retVal\n };\n } catch (error) {\n return { };\n }\n }\n } else {\n // Error state - no #ipcMessageManager set\n return { };\n }\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n //return super.on(event, callback, ctx);\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n //return super.off(event, callback);\n }\n\n // Supply complete collection of workers\n Start = () => {\n this.#messagingManager?.Start({ });\n }\n\n // Supply complete collection of workers\n Stop = () => {\n this.#messagingManager?.Stop({ });\n }\n\n /*\n override emit(event: string, ...args: any[]): this {\n const sendMessage = async () => {\n const retVal = await this.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n });\n // Invoke the response callback\n args[args.length-1](retVal);\n };\n sendMessage();\n return this;\n //return super.emit(event, ...args);\n }\n */\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n //const retVal = await this.#messagingManager?.SendMessage({\n const retVal = await this.SendMessage({ \n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload);\n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n console.log(error);\n this.#options.logger.error(chalk.red(`IPCMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n } else {\n //@@ send to all clients\n for (const [clientId, clientRecord] of Object.entries(this.#clients)) {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload, { client: clientRecord.client });\n }\n }\n }\n}","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\n\nimport chalk from 'chalk';\n\nexport interface IPCMessageHandlerPairOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n ignoreEvents?: string[]\n}\n\n/**\n * IPC Message Handling.\n * \n * This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.\n * This class can be used for both tghe cluster primary and the cluster worker.\n * Note: Currently groups handling is not supported. Use the redis version for this capability.\n */\nexport class IPCMessageHandlerPair extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IPCMessageHandlerPairOptions;\n #worker: any = null;\n #events: JSONObject = { };\n #startWorkerOptions: any;\n #startPrimaryWorker: Worker | null = null;\n\n constructor(options: IPCMessageHandlerPairOptions) {\n super();\n this.#options = options;\n if (options.role.localeCompare('CLIENT') === 0) {\n this.SetupWorker();\n } else {\n this.SetupPrimary();\n }\n }\n\n get __events() {\n return this.#events;\n }\n\n #ProcessPrimaryMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, { worker: this.#startPrimaryWorker as Worker });\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: 'SERVER',\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n (options.worker as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n\n\n //@@ also need way to add/remove a worker/child to the collection\n //@@ the ping should also auto remove (such as a failed worker)\n \n\n messageReceiverStart: (options: any) => { //@@ options should be complete collection of workers\n // Receive a message to process from a worker\n const worker = (options.worker as any);\n this.#startPrimaryWorker = worker;\n worker.on('message', this.#ProcessPrimaryMessageRaw);\n },\n messageReceiverStop: (options: any) => { //@@ options should be complete collection of workers\n const worker = (options.worker as any);\n worker.off('message', this.#ProcessPrimaryMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n #ProcessWorkerMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);\n }\n\n SetupWorker = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,\n namespace: this.#options.namespace,\n role: 'CLIENT',\n \n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n // Options not required for sending payloads to the master process\n (process as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n messageReceiverStart: (options: any) => {\n // Receive a message response back from the primary thread\n this.#startWorkerOptions = { ...options };\n process.on('message', this.#ProcessWorkerMessageRaw);\n },\n messageReceiverStop: (options: any) => { \n process.off('message', this.#ProcessWorkerMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n SendMessage = async (payload: JSONObject): Promise<JSONObject> => {\n if (this.#messagingManager) {\n if (this.#worker) {\n return this.#messagingManager?.SendMessage(payload, { worker: this.#worker });\n } else {\n return this.#messagingManager?.SendMessage(payload, { });\n }\n } else {\n // Error state - no #ipcMessageManager set\n return { };\n }\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n //return super.on(event, callback, ctx);\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n //return super.off(event, callback);\n }\n\n // Supply complete collection of workers\n Start = (worker?: any) => {\n if (worker) {\n this.#messagingManager?.Start({ worker });\n this.#worker = worker;\n } else {\n this.#messagingManager?.Start({ });\n }\n }\n\n // Supply complete collection of workers\n Stop = () => {\n if (this.#worker) {\n this.#messagingManager?.Stop({ worker: this.#worker });\n this.#worker = null;\n } else {\n this.#messagingManager?.Stop({ });\n }\n }\n\n get worker(): Worker | null {\n return this.#worker;\n }\n\n /*\n override emit(event: string, ...args: any[]): this {\n const sendMessage = async () => {\n const retVal = await this.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n });\n // Invoke the response callback\n args[args.length-1](retVal);\n };\n sendMessage();\n return this;\n //return super.emit(event, ...args);\n }\n */\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n //const retVal = await this.#messagingManager?.SendMessage({\n const retVal = await this.SendMessage({ \n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload);\n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n console.log(error);\n this.#options.logger.error(chalk.red(`IPCMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n }\n}"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["#id","#options","#messageHeader","#SendMessageNoResponse","#SendMessage","#inflightMessages","#ProcessMessage","#options","#requestChannel","#responseChannel","#ioredisSubscriber","#ioredisPublisher","#LogError","#LogInfo","#pingTimeout","#messagingManager","#clients","#messageSender","#ProcessResponseMessage","#processPayload","#processRawMessage","#events","#options","#events","#messagingManager","#clients","#processPayload","#startWorkerOptions","#ProcessWorkerMessageRaw","#options","#events","#messagingManager","#startPrimaryWorker","#processPayload","#ProcessPrimaryMessageRaw","#startWorkerOptions","#ProcessWorkerMessageRaw","#worker"],"sources":["../src/messagingManager.ts","../src/redisMessageHandler.ts","../src/ipcMessageHandler.ts","../src/ipcMessageHandlerPair.ts"],"sourcesContent":["/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF\nimport { ISTSLogger, JSONObject } from '@nsshunt/stsutils'\n\n//import { randomUUID } from 'node:crypto';\n\nimport { IIPCMessageProcessorIPCPayload, IIPCMessageProcessorWorkerRecord } from './commonTypes.js'\n\nexport interface MessagingManagerOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n groups: string[]\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => void\n ProcessRequestMessage: (payload: IIPCMessageProcessorIPCPayload, options: any) => Promise<JSONObject>\n ProcessResponseMessage?: (reesponses: Record<string, IIPCMessageProcessorIPCPayload>, options: any) => Promise<boolean>\n messageReceiverStart: (options: any) => void\n messageReceiverStop: (options: any) => void\n}\n/**\n * todo\n * @typedef {Object} options - todo\n * @property {boolean} [wssServer=false] - Create a web socket server on this worker instance\n */\nexport class MessagingManager {\n #id: string;\n #options: MessagingManagerOptions;\n #inflightMessages: Record<string, IIPCMessageProcessorWorkerRecord> = { };\n #messageHeader: string;\n\n constructor(options: MessagingManagerOptions) {\n this.#id = globalThis.crypto.randomUUID(); // randomUUID();\n this.#options = options;\n this.#messageHeader = `__STS__${this.#options.namespace}__${globalThis.crypto.randomUUID()}`; // randomUUID();\n }\n\n get id() {\n return this.#id;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ReceivedMessageFromMaster(msg: any) {\n // Override in subclass if required\n }\n\n SendMessageNoResponse = (payload: JSONObject, options?: any): void => {\n this.#SendMessageNoResponse(payload, options);\n };\n\n SendMessage = (payload: JSONObject, options?: any): Promise<JSONObject> => {\n return new Promise((resolve, reject) => {\n this.#SendMessage(payload, options,\n (payload: IIPCMessageProcessorIPCPayload) => {\n resolve(payload.responsePayload);\n },\n (payload: IIPCMessageProcessorIPCPayload) => {\n reject(payload.requestPayload);\n })\n })\n }\n\n #SendMessageNoResponse = (payload: JSONObject, options: any): void => {\n const messageId: string = globalThis.crypto.randomUUID(); // randomUUID();\n const requestPayload: IIPCMessageProcessorIPCPayload = {\n header: this.#messageHeader,\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload: payload,\n responsePayload: { },\n pid: process.pid.toString(),\n messageType: 'REQUEST_NO_RESPONSE'\n }\n\n //console.log(chalk.blue(`#SendMessageNoResponse: [${JSON.stringify(requestPayload)}]`))\n this.#options.messageSender(requestPayload, options);\n }\n\n #SendMessage = (payload: JSONObject, options: any,\n callBack: (payload: IIPCMessageProcessorIPCPayload) => void, \n errorCallBack: (payload: IIPCMessageProcessorIPCPayload) => void\n ): void => {\n const messageId: string = globalThis.crypto.randomUUID(); // randomUUID();\n const requestPayload: IIPCMessageProcessorIPCPayload = {\n header: this.#messageHeader,\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload: payload,\n responsePayload: { },\n pid: process.pid.toString(),\n messageType: 'REQUEST'\n }\n const messageRecord = {\n messageId,\n senderId: this.#id,\n senderRole: this.#options.role,\n requestPayload,\n responses: { }, // record\n startTime: performance.now(),\n endTime: 0,\n timeout: setTimeout(() => {\n //this.#LogDebugMessage(chalk.red(`Timeout has occurred after: [${this.#options.requestResponseMessageTimeout}]ms with message id: [${messageRecord.messageId}]. Details: [${JSON.stringify(this.#inflightMessages[messageRecord.messageId].requestPayload)}]`));\n setTimeout(() => {\n delete this.#inflightMessages[messageRecord.messageId];\n }, 0).unref();\n errorCallBack(requestPayload);\n }, this.#options.requestResponseMessageTimeout).unref(),// max message timeout allowed\n callBack,\n errorCallBack\n }\n this.#inflightMessages[messageRecord.messageId] = messageRecord;\n //this.#LogDebugMessage(chalk.cyan(`sending: [${JSON.stringify(requestPayload)}]`));\n //console.log(chalk.blue(`#SendMessage: [${JSON.stringify(requestPayload)}]`))\n\n this.#options.messageSender(requestPayload, options);\n }\n\n #ProcessMessage = async (msg: any, options: any): Promise<void> => {\n if (msg.header && msg.header.localeCompare(this.#messageHeader) === 0) {\n const message = (msg as IIPCMessageProcessorIPCPayload);\n if (this.#inflightMessages[message.messageId]) {\n const inFlightMessageRecord: IIPCMessageProcessorWorkerRecord = this.#inflightMessages[message.messageId];\n inFlightMessageRecord.responses[message.senderId ] = { ...message };\n let completed = true; // Defaults to true\n if (this.#options.ProcessResponseMessage) {\n completed = await this.#options.ProcessResponseMessage(inFlightMessageRecord.responses, options);\n if (completed) {\n inFlightMessageRecord.endTime = performance.now();\n clearTimeout(inFlightMessageRecord.timeout as NodeJS.Timeout);\n inFlightMessageRecord.callBack({\n responsePayload: Object.values(inFlightMessageRecord.responses).map(r => r.responsePayload)\n } as any, options) // \n delete this.#inflightMessages[message.messageId];\n }\n } else if (completed) {\n inFlightMessageRecord.endTime = performance.now();\n clearTimeout(inFlightMessageRecord.timeout as NodeJS.Timeout);\n inFlightMessageRecord.callBack(message, options) // inFlightMessageRecord.responses\n //@@inFlightMessageRecord.callBack(Object.values(inFlightMessageRecord.responses), options) // \n delete this.#inflightMessages[message.messageId];\n } else {\n //console.log(chalk.grey(`#ProcessMessage:5`));\n }\n } else {\n //throw new Error(`Could not find Request/Response message with id: [${message.messageId}]`); //@@\n }\n }\n }\n\n Start = (options?: any) => {\n this.#messageHeader = `__STS__${this.#options.namespace}__${globalThis.crypto.randomUUID()}`; // randomUUID()\n this.#options.messageReceiverStart(options);\n }\n\n Stop = (options?: any) => {\n // Kill in-flight messages\n this.#options.messageReceiverStop(options);\n\n for (const [, iPCMessageProcessorWorkerRecord] of Object.entries(this.#inflightMessages)) {\n if (iPCMessageProcessorWorkerRecord.timeout) {\n clearTimeout(iPCMessageProcessorWorkerRecord.timeout);\n }\n }\n this.#inflightMessages = { };\n }\n\n // Process a message recieved from a worker\n ProcessMessage = async (msg: any, options: any) => {\n if (msg.header) {\n const checkName = `__STS__${this.#options.namespace}__`; //@@ this is a broadcast becuase the unique uuid is not part of the header test\n if ((msg.header as string).includes(checkName)) {\n const message = (msg as IIPCMessageProcessorIPCPayload);\n if (msg.messageType.localeCompare('REQUEST') === 0 || msg.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n let processMessage = true;\n if (message.requestPayload.args && message.requestPayload.args.length > 0 && message.requestPayload.args[0].group) {\n const group = message.requestPayload.args[0].group;\n processMessage = (this.#options.groups.indexOf(group) === -1) ? false : true;\n }\n if (processMessage) {\n if (msg.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#options.ProcessRequestMessage(message, options);\n } else {\n message.responsePayload = await this.#options.ProcessRequestMessage(message, options);\n message.senderId = this.#id;\n message.messageType = 'RESPONSE';\n this.#options.messageSender(message, options);\n }\n }\n } else {\n // Received a response (to my request)\n this.#ProcessMessage(msg, options);\n }\n }\n }\n }\n}\n","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\nimport { Redis, RedisOptions } from \"ioredis\";\n\nimport chalk from 'chalk';\n\nconst REQUEST_CHANNEL = '__STS__SVC_stsappframework_request'\nconst RESPONSE_CHANNEL = '__STS__SVC_stsappframework_response'\n\nexport interface IRedisAdminManagerOptions {\n redisUrl: string\n logger: ISTSLogger\n role: 'SERVER' | 'CLIENT'\n namespace: string\n groups: string[]\n ignoreEvents?: string[]\n extraData?: JSONObject\n}\n\nexport interface IClientRecord {\n id: string\n clientConnected: Date\n pingCount: number\n timeout: NodeJS.Timeout\n groups: string[]\n extraData?: JSONObject\n}\n\nexport interface IEventRecord {\n event: string\n callback: any,\n ctx?: any\n}\n\nexport interface IPingData {\n id: string\n groups: string[]\n extraData?: JSONObject\n}\n\nexport class RedisMessageHandler extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IRedisAdminManagerOptions;\n #events: Record<string, IEventRecord> = { };\n #requestChannel: string;\n #responseChannel: string;\n #ioredisSubscriber: Redis;\n #ioredisPublisher: Redis;\n #clients: Record<string, IClientRecord> = { };\n #pingTimeout: NodeJS.Timeout | null = null;\n\n constructor(options: IRedisAdminManagerOptions) {\n super();\n this.#options = options;\n\n this.#requestChannel = REQUEST_CHANNEL\n this.#responseChannel = RESPONSE_CHANNEL\n\n const redisOptions: RedisOptions = {\n showFriendlyErrorStack: true,\n maxRetriesPerRequest: 20\n }\n\n this.#ioredisSubscriber = new Redis(this.#options.redisUrl, redisOptions);\n this.#ioredisPublisher = new Redis(this.#options.redisUrl, redisOptions);\n\n this.#ioredisSubscriber.on(\"error\", (error: Error) => {\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error (redisSubscriber on error): [${error}]`));\n });\n\n this.#ioredisPublisher.on(\"error\", (error: Error) => {\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error (redisPublisher on error): [${error}]`));\n });\n\n this.#ioredisSubscriber.subscribe(this.#requestChannel, this.#responseChannel, (error, count) => {\n if (error) {\n // Just like other commands, subscribe() can fail for some reasons, // ex network issues.\n this.#LogError(chalk.red(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Error - Failed to subscribe: [${error}]`));\n } else {\n // `count` represents the number of channels this client is currently subscribed to.\n this.#LogInfo(chalk.white(`RedisMessageHandler:constructor(): PID: [${process.pid}] Role: [${this.#options.role}] Subscribed successfully! This client is currently subscribed to ${count} channels.`));\n }\n });\n\n this.SetupPrimary();\n\n /*\n const ping = () => {\n this.#pingTimeout = setTimeout(() => {\n const pingData: IPingData = {\n id: (this.#messagingManager as MessagingManager).id,\n groups: this.#options.groups,\n }\n if (this.#options.extraData) {\n pingData.extraData = this.#options.extraData;\n }\n this.emit('ping', pingData, (response: any) => { });\n ping();\n }, 1000).unref();\n }\n ping();\n\n this.on('ping', (pingData: IPingData, callback: any) => {\n const { id, groups, extraData } = pingData;\n if (this.#clients[id]) {\n clearTimeout(this.#clients[id].timeout);\n this.#clients[id].pingCount++;\n this.#clients[id].timeout = setTimeout(() => {\n delete this.#clients[id];\n }, 2000);\n this.#clients[id].groups = groups;\n this.#clients[id].extraData = extraData;\n } else {\n this.#clients[id] = {\n id,\n clientConnected: new Date(),\n pingCount: 0,\n timeout: setTimeout(() => {\n delete this.#clients[id];\n }, 2000),\n groups,\n extraData\n }\n }\n callback('ok');\n });\n */\n\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n const ping = () => {\n this.#pingTimeout = setTimeout(() => {\n const pingData: IPingData = {\n id: (this.#messagingManager as MessagingManager).id,\n groups: this.#options.groups,\n }\n if (this.#options.extraData) {\n pingData.extraData = this.#options.extraData;\n }\n //this.emit('ping', pingData, (response: any) => { });\n this.emitNoResponse('ping', pingData);\n ping();\n }, 1000).unref();\n }\n ping();\n } else {\n this.on('ping', (pingData: IPingData, callback: any) => {\n const { id, groups, extraData } = pingData;\n if (this.#clients[id]) {\n clearTimeout(this.#clients[id].timeout);\n this.#clients[id].pingCount++;\n this.#clients[id].timeout = setTimeout(() => {\n delete this.#clients[id];\n }, 2000);\n this.#clients[id].groups = groups;\n this.#clients[id].extraData = extraData;\n } else {\n this.#clients[id] = {\n id,\n clientConnected: new Date(),\n pingCount: 0,\n timeout: setTimeout(() => {\n delete this.#clients[id];\n }, 2000),\n groups,\n extraData\n }\n }\n //callback('ok');\n });\n }\n }\n\n #LogInfo(message: any) {\n this.#options.logger.info(message);\n }\n\n #LogError(message: any) {\n this.#options.logger.error(message);\n }\n\n #processRawMessage = (channel: string, rawmessage: string) => {\n const message = JSON.parse(rawmessage);\n\n /*\n if (message.requestPayload.__eventName.localeCompare('ping') !== 0) {\n console.log(chalk.cyan(`RedisMessageHandler:#processRawMessage(): Role: [${this.#options.role}] Channel: [${channel}] Message: [${JSON.stringify(message)}]`));\n }\n */\n\n this.#messagingManager?.ProcessMessage(message, { channel });\n }\n\n get clients(): Record<string, IClientRecord> {\n return this.#clients;\n }\n\n get groups(): string[] {\n return this.#options.groups;\n }\n \n AddGroup = (group: string) => {\n const index = this.#options.groups.indexOf(group);\n if (index === -1) {\n this.#options.groups.push(group);\n }\n }\n\n RemoveGroup = (group: string) => {\n const removeIndex = this.#options.groups.indexOf(group);\n if (removeIndex !== -1) {\n this.#options.groups.splice(removeIndex, 1);\n }\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: this.#options.logger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: this.#options.role,\n groups: this.#options.groups,\n messageSender: this.#messageSender,\n // This method is used to calculate if all responses have been received from multiple clients (broadcast)\n // returns true/false.\n ProcessResponseMessage: this.#ProcessResponseMessage,\n // This gets called when an event is received from a message receiver (when ProcessMessage is invoked from the receiver event handler)\n ProcessRequestMessage: this.#processPayload,\n \n messageReceiverStart: (options: any) => {\n this.#ioredisSubscriber.on(\"message\", this.#processRawMessage);\n },\n \n messageReceiverStop: (options: any) => {\n this.#ioredisSubscriber.off(\"message\", this.#processRawMessage);\n }\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n \n #messageSender = (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n\n\n //console.log(chalk.grey(JSON.stringify(payload)));\n\n\n this.#ioredisPublisher.publish(this.#requestChannel, JSON.stringify(payload));\n } else if (payload.messageType.localeCompare('RESPONSE') === 0) {\n this.#ioredisPublisher.publish(this.#responseChannel, JSON.stringify(payload));\n }\n }\n\n \n #ProcessResponseMessage = async (responses: Record<string, IIPCMessageProcessorIPCPayload>, options: any): Promise<boolean> => {\n // Now check if we have all responses ...\n\n /*\n let allFound = false;\n\n for (const [responseId, response] of Object.entries(responses)) {\n if (response.senderRole.localeCompare('CLIENT') === 0) {\n allFound = true;\n break;\n }\n }\n if (allFound) {\n return allFound;\n }\n */\n\n let found = true;\n\n // Sender role here is SERVER\n let requestGroup = null;\n for (const [responseId, response] of Object.entries(responses)) {\n if (response.requestPayload.args.length > 0 && response.requestPayload.args[0].group) {\n requestGroup = response.requestPayload.args[0].group;\n break;\n }\n }\n\n if (requestGroup) {\n const clientsInGroup = Object.values(this.#clients).filter(c => {\n if (c.groups.indexOf(requestGroup) === -1) {\n return false;\n }\n return true;\n });\n\n // Now make sure that all clients are in the responses\n found = true;\n clientsInGroup.forEach(c => {\n if (!responses[c.id]) {\n found = false;\n }\n })\n } else {\n const clientsInGroup = Object.values(this.#clients)\n\n // Now make sure that all clients are in the responses\n found = true;\n clientsInGroup.forEach(c => {\n if (!responses[c.id]) {\n found = false;\n }\n })\n }\n\n return found;\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject: IEventRecord = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n }\n\n Start = () => {\n this.#messagingManager?.Start();\n }\n\n Stop = () => {\n if (this.#pingTimeout) {\n clearTimeout(this.#pingTimeout);\n this.#pingTimeout = null;\n }\n\n this.#messagingManager?.Stop();\n\n this.#ioredisSubscriber.quit();\n this.#ioredisSubscriber.disconnect();\n\n this.#ioredisPublisher.quit();\n this.#ioredisPublisher.disconnect();\n }\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n const retVal = await this.#messagingManager?.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload); \n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n this.#options.logger.error(chalk.red(`RedisMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitWithError(event: string, args: JSONObject, responseCb: (response: JSONObject | undefined) => void, errorCb: (error: any) => void): this {\n (async () => {\n try {\n const retVal = await this.#messagingManager?.SendMessage({\n __eventName: event,\n args: [ args ]\n } as IEventPayload); \n // Invoke the response callback\n responseCb(retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n //this.#options.logger.error(chalk.red(`RedisMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n errorCb(error);\n }\n })();\n return this;\n }\n\n emitex = async(event: string, ...args: any[]): Promise<JSONObject> => {\n return (this.#messagingManager as MessagingManager).SendMessage({\n __eventName: event,\n args\n } as IEventPayload); \n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n }\n}","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\n\nimport chalk from 'chalk';\n\n//import { randomUUID } from 'node:crypto';\n\nexport interface IPCMessageHandlerOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n ignoreEvents?: string[]\n}\n\ndeclare interface IClientRecord {\n client: any\n processMessage: (client: any) => void\n}\n\n/**\n * IPC Message Handling.\n * \n * This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.\n * This class can be used for both tghe cluster primary and the cluster worker.\n * Note: Currently groups handling is not supported. Use the redis version for this capability.\n */\nexport class IPCMessageHandler extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IPCMessageHandlerOptions;\n #clients: Record<string, IClientRecord> = { };\n #events: JSONObject = { };\n #startWorkerOptions: any;\n\n constructor(options: IPCMessageHandlerOptions) {\n super();\n this.#options = options;\n if (options.role.localeCompare('CLIENT') === 0) {\n this.SetupWorker();\n } else {\n this.SetupPrimary();\n }\n }\n\n get __events() {\n return this.#events;\n }\n\n AddClient = (client: any): string => {\n const id = globalThis.crypto.randomUUID(); // randomUUID();\n\n const processMessage = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, { client });\n };\n\n client.on('message', processMessage);\n this.#clients[id] = {\n client,\n processMessage\n }\n return id;\n }\n\n RemoveClient = (id: string) => {\n const clientRecord = this.#clients[id];\n if (clientRecord) {\n clientRecord.client.off('message', clientRecord.processMessage);\n delete this.#clients[id];\n }\n }\n\n get clients() {\n return this.#clients;\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: 'SERVER',\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n (options.client as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n\n\n //@@ also need way to add/remove a worker/child to the collection\n //@@ the ping should also auto remove (such as a failed worker)\n \n\n messageReceiverStart: (options: any) => { //@@ options should be complete collection of workers\n // Receive a message to process from a worker\n },\n messageReceiverStop: (options: any) => { //@@ options should be complete collection of workers\n\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n #ProcessWorkerMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);\n }\n\n SetupWorker = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,\n namespace: this.#options.namespace,\n role: 'CLIENT',\n \n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n // Options not required for sending payloads to the master process\n (process as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n messageReceiverStart: (options: any) => {\n // Receive a message response back from the primary thread\n this.#startWorkerOptions = { ...options };\n process.on('message', this.#ProcessWorkerMessageRaw);\n },\n messageReceiverStop: (options: any) => { \n process.off('message', this.#ProcessWorkerMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n SendMessage = async (payload: JSONObject): Promise<JSONObject> => {\n if (this.#messagingManager) {\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n return this.#messagingManager?.SendMessage(payload, { });\n } else {\n //@@ send to all clients\n const promArray: Promise<JSONObject>[] = [ ];\n for (const [clientId, clientRecord] of Object.entries(this.#clients)) {\n promArray.push(this.#messagingManager?.SendMessage(payload, { client: clientRecord.client }));\n }\n\n try {\n const retVal = await Promise.all(promArray);\n return {\n result: retVal\n };\n } catch (error) {\n return { };\n }\n }\n } else {\n // Error state - no #ipcMessageManager set\n return { };\n }\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n //return super.on(event, callback, ctx);\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n //return super.off(event, callback);\n }\n\n // Supply complete collection of workers\n Start = () => {\n this.#messagingManager?.Start({ });\n }\n\n // Supply complete collection of workers\n Stop = () => {\n this.#messagingManager?.Stop({ });\n }\n\n /*\n override emit(event: string, ...args: any[]): this {\n const sendMessage = async () => {\n const retVal = await this.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n });\n // Invoke the response callback\n args[args.length-1](retVal);\n };\n sendMessage();\n return this;\n //return super.emit(event, ...args);\n }\n */\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n //const retVal = await this.#messagingManager?.SendMessage({\n const retVal = await this.SendMessage({ \n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload);\n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n console.log(error);\n this.#options.logger.error(chalk.red(`IPCMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n if (this.#options.role.localeCompare('CLIENT') === 0) {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n } else {\n //@@ send to all clients\n for (const [clientId, clientRecord] of Object.entries(this.#clients)) {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload, { client: clientRecord.client });\n }\n }\n }\n}","/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF\nimport { TinyEmitter } from \"tiny-emitter\";\nimport { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'\n\nimport { IIPCMessageProcessorIPCPayload, IEventPayload } from './commonTypes.js'\n\nimport { MessagingManager, MessagingManagerOptions } from './messagingManager.js'\n\nimport chalk from 'chalk';\n\nexport interface IPCMessageHandlerPairOptions {\n logger: ISTSLogger\n requestResponseMessageTimeout: number\n namespace: string\n role: 'SERVER' | 'CLIENT'\n ignoreEvents?: string[]\n}\n\n/**\n * IPC Message Handling.\n * \n * This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.\n * This class can be used for both tghe cluster primary and the cluster worker.\n * Note: Currently groups handling is not supported. Use the redis version for this capability.\n */\nexport class IPCMessageHandlerPair extends TinyEmitter {\n #messagingManager: MessagingManager | null = null;\n #options: IPCMessageHandlerPairOptions;\n #worker: any = null;\n #events: JSONObject = { };\n #startWorkerOptions: any;\n #startPrimaryWorker: Worker | null = null;\n\n constructor(options: IPCMessageHandlerPairOptions) {\n super();\n this.#options = options;\n if (options.role.localeCompare('CLIENT') === 0) {\n this.SetupWorker();\n } else {\n this.SetupPrimary();\n }\n }\n\n get __events() {\n return this.#events;\n }\n\n #ProcessPrimaryMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, { worker: this.#startPrimaryWorker as Worker });\n }\n\n SetupPrimary = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: 5000,\n namespace: this.#options.namespace,\n role: 'SERVER',\n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n (options.worker as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n\n\n //@@ also need way to add/remove a worker/child to the collection\n //@@ the ping should also auto remove (such as a failed worker)\n \n\n messageReceiverStart: (options: any) => { //@@ options should be complete collection of workers\n // Receive a message to process from a worker\n const worker = (options.worker as any);\n this.#startPrimaryWorker = worker;\n worker.on('message', this.#ProcessPrimaryMessageRaw);\n },\n messageReceiverStop: (options: any) => { //@@ options should be complete collection of workers\n const worker = (options.worker as any);\n worker.off('message', this.#ProcessPrimaryMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n #ProcessWorkerMessageRaw = (payload: any) => {\n this.#messagingManager?.ProcessMessage(payload, this.#startWorkerOptions);\n }\n\n SetupWorker = () => {\n const ipcMessageManagerOptions: MessagingManagerOptions = {\n logger: defaultLogger,\n requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,\n namespace: this.#options.namespace,\n role: 'CLIENT',\n \n messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {\n // Options not required for sending payloads to the master process\n (process as any).send(payload);\n },\n ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n return this.#processPayload(payload, options);\n },\n messageReceiverStart: (options: any) => {\n // Receive a message response back from the primary thread\n this.#startWorkerOptions = { ...options };\n process.on('message', this.#ProcessWorkerMessageRaw);\n },\n messageReceiverStop: (options: any) => { \n process.off('message', this.#ProcessWorkerMessageRaw);\n },\n groups: [ ]\n }\n this.#messagingManager = new MessagingManager(ipcMessageManagerOptions);\n }\n\n SendMessage = async (payload: JSONObject): Promise<JSONObject> => {\n if (this.#messagingManager) {\n if (this.#worker) {\n return this.#messagingManager?.SendMessage(payload, { worker: this.#worker });\n } else {\n return this.#messagingManager?.SendMessage(payload, { });\n }\n } else {\n // Error state - no #ipcMessageManager set\n return { };\n }\n }\n\n #processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {\n // check the event name from the collection and invoke that function\n return new Promise<JSONObject>((resolve, reject) => {\n if (payload.messageType.localeCompare('REQUEST') === 0 || payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n if (payload.requestPayload['__eventName']) {\n const eventName = payload.requestPayload['__eventName'];\n // Only process events that I have registered interest in (using .on)\n if (this.#events[eventName]) {\n try {\n if (payload.messageType.localeCompare('REQUEST_NO_RESPONSE') === 0) {\n this.#events[eventName].callback(...payload.requestPayload.args);\n resolve({});\n } else {\n this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {\n resolve(responseMessage);\n });\n }\n } catch (error) {\n reject(error);\n }\n }\n }\n }\n });\n }\n\n // p.on('fromworker', (arg1: number, arg2: string, callback: any) => {\n override on(event: string, callback: any, ctx?: any): this {\n if (this.#events[event]) {\n // Update the event with the same name\n delete this.#events[event];\n }\n const eventObject = {\n event,\n callback,\n ctx\n }\n this.#events[eventObject.event] = eventObject;\n return this;\n //return super.on(event, callback, ctx);\n }\n\n override off(event: string, callback?: any): this {\n if (this.#events[event]) {\n delete this.#events[event];\n }\n return this;\n //return super.off(event, callback);\n }\n\n // Supply complete collection of workers\n Start = (worker?: any) => {\n if (worker) {\n this.#messagingManager?.Start({ worker });\n this.#worker = worker;\n } else {\n this.#messagingManager?.Start({ });\n }\n }\n\n // Supply complete collection of workers\n Stop = () => {\n if (this.#worker) {\n this.#messagingManager?.Stop({ worker: this.#worker });\n this.#worker = null;\n } else {\n this.#messagingManager?.Stop({ });\n }\n }\n\n get worker(): Worker | null {\n return this.#worker;\n }\n\n /*\n override emit(event: string, ...args: any[]): this {\n const sendMessage = async () => {\n const retVal = await this.SendMessage({\n __eventName: event,\n args: args.slice(0, args.length-1)\n });\n // Invoke the response callback\n args[args.length-1](retVal);\n };\n sendMessage();\n return this;\n //return super.emit(event, ...args);\n }\n */\n\n override emit(event: string, ...args: any[]): this {\n (async () => {\n try {\n //const retVal = await this.#messagingManager?.SendMessage({\n const retVal = await this.SendMessage({ \n __eventName: event,\n args: args.slice(0, args.length-1)\n } as IEventPayload);\n // Invoke the response callback\n args[args.length-1](retVal);\n } catch (error) {\n if (this.#options.ignoreEvents) {\n //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))\n if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {\n return;\n }\n }\n console.log(error);\n this.#options.logger.error(chalk.red(`IPCMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));\n }\n })();\n return this;\n }\n\n emitNoResponse = async(event: string, ...args: any[]): Promise<void> => {\n (this.#messagingManager as MessagingManager).SendMessageNoResponse({\n __eventName: event,\n args\n } as IEventPayload); \n }\n}"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nsshunt/stsmessaging",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.69",
|
|
4
4
|
"description": "STS Messeging",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -41,19 +41,19 @@
|
|
|
41
41
|
},
|
|
42
42
|
"homepage": "https://github.com/nsshunt/stsmessaging#readme",
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@types/node": "^25.
|
|
45
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
46
|
-
"@typescript-eslint/parser": "8.
|
|
47
|
-
"eslint": "^10.2.
|
|
48
|
-
"globals": "17.
|
|
44
|
+
"@types/node": "^25.6.0",
|
|
45
|
+
"@typescript-eslint/eslint-plugin": "8.59.1",
|
|
46
|
+
"@typescript-eslint/parser": "8.59.1",
|
|
47
|
+
"eslint": "^10.2.1",
|
|
48
|
+
"globals": "17.5.0",
|
|
49
49
|
"testcontainers": "11.14.0",
|
|
50
50
|
"ts-node": "^10.9.2",
|
|
51
|
-
"typescript": "^6.0.
|
|
52
|
-
"vite": "8.0.
|
|
53
|
-
"vitest": "4.1.
|
|
51
|
+
"typescript": "^6.0.3",
|
|
52
|
+
"vite": "8.0.10",
|
|
53
|
+
"vitest": "4.1.5"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@nsshunt/stsutils": "^1.19.
|
|
56
|
+
"@nsshunt/stsutils": "^1.19.103",
|
|
57
57
|
"chalk": "^5.6.2",
|
|
58
58
|
"ioredis": "^5.10.1",
|
|
59
59
|
"tiny-emitter": "^2.1.0"
|