@lyxa.ai/core 1.0.374 → 1.0.376

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.
@@ -13,6 +13,7 @@ const amqplib_1 = __importDefault(require("amqplib"));
13
13
  const instance_utils_1 = require("../../utilities/instance.utils");
14
14
  const index_1 = require("../../index");
15
15
  const LocalSubscriptionRegistry_1 = require("../socket/LocalSubscriptionRegistry");
16
+ const socket_redis_connections_1 = require("../socket/socket-redis-connections");
16
17
  let connection;
17
18
  let channel;
18
19
  const EXCHANGE_NAME = 'lyxa.events';
@@ -57,8 +58,6 @@ async function subscribeToEvent(eventId, onMessage) {
57
58
  }, { noAck: false });
58
59
  console.log(`Subscribed to event [${eventId}] on queue [${queueName}] for instance [${(0, instance_utils_1.getInstanceId)()}]`);
59
60
  }
60
- const kEntityEvents = (entityId) => `socket:events:entity:${entityId}`;
61
- const kEntityInstances = (entityId) => `socket:instances:entity:${entityId}`;
62
61
  async function subscribeToSocketEvent() {
63
62
  const queueName = `socket-events-${(0, instance_utils_1.getInstanceId)()}`;
64
63
  await channel.assertQueue(queueName, { durable: true });
@@ -83,15 +82,18 @@ async function publishSocketEvent(event, recipients) {
83
82
  const localKey = event.getIdentifier();
84
83
  const payload = event.payload();
85
84
  for (const recipient of recipients) {
86
- const isSub = await redisService.isMemberOfSet(kEntityEvents(recipient), localKey);
85
+ const isSub = await (0, socket_redis_connections_1.isEntitySubscribed)(recipient, localKey);
86
+ console.log(isSub);
87
87
  if (isSub) {
88
- const instanceNames = await redisService.getSetMembers(kEntityInstances(recipient));
88
+ const instanceNames = await redisService.getSetMembers((0, socket_redis_connections_1.kEntityInstances)(recipient));
89
+ console.log(instanceNames);
89
90
  if (!instanceNames.length) {
90
91
  continue;
91
92
  }
92
93
  for (const instanceName of instanceNames) {
93
94
  const routingKey = `${INSTANCE_ROUTE_PREFIX}.${instanceName}`;
94
95
  const messageBuffer = Buffer.from(JSON.stringify({ localKey, payload, recipient }), 'utf8');
96
+ console.log("published on routing key", routingKey);
95
97
  channel.publish(EXCHANGE_NAME, routingKey, messageBuffer, {
96
98
  contentType: 'application/json',
97
99
  persistent: true,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"/","sources":["libraries/event/index.ts"],"names":[],"mappings":"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","sourcesContent":["import amqp from 'amqplib';\nimport { BaseEvent } from './BaseEvent';\nimport { getInstanceId } from '../../utilities/instance.utils';\nimport { BaseSocketEvent } from '../socket/BaseSocketEvent';\nimport { getLibraries } from '../../index';\nimport { LocalSubs } from '../socket/LocalSubscriptionRegistry';\n\nlet connection: amqp.ChannelModel;\nlet channel: amqp.Channel;\nconst EXCHANGE_NAME = 'lyxa.events';\nconst INSTANCE_ROUTE_PREFIX = 'instance'; // routing key: instance.{instanceName}.{eventType}\n\nexport async function initEventBus(rabbitUrl: string) {\n\tconnection = await amqp.connect(rabbitUrl);\n\tchannel = await connection.createChannel();\n\tawait channel.assertExchange(EXCHANGE_NAME, 'topic', { durable: true });\n\tconsole.log(`EventBus initialized with instance ID: ${getInstanceId()}`);\n}\n\nexport async function publishEvent<TPayload extends Record<string, unknown>>(\n\tevent: BaseEvent<TPayload>\n): Promise<void> {\n\tif (!channel) throw new Error('Channel not initialized. Call initEventBus first.');\n\tconst messageBuffer = Buffer.from(JSON.stringify(event.payload));\n\tchannel.publish(EXCHANGE_NAME, event.eventId, messageBuffer, {\n\t\tcontentType: 'application/json',\n\t});\n\tconsole.log(`Published event [${event.eventId}] with payload`, event.payload);\n}\n\nexport async function subscribeToEvent(\n\teventId: string,\n\tonMessage: (payload: any) => Promise<void>\n): Promise<void> {\n\tif (!channel) throw new Error('Channel not initialized. Call initEventBus first.');\n\tconst queueName = `${eventId}-${getInstanceId()}`;\n\tawait channel.assertQueue(queueName, {\n\t\tdurable: false,\n\t\texclusive: true,\n\t\tautoDelete: true,\n\t});\n\tawait channel.bindQueue(queueName, EXCHANGE_NAME, eventId);\n\tawait channel.consume(\n\t\tqueueName,\n\t\tasync msg => {\n\t\t\tif (msg !== null) {\n\t\t\t\tconst payloadString = msg.content.toString();\n\t\t\t\tconst payload = JSON.parse(payloadString);\n\t\t\t\ttry {\n\t\t\t\t\tawait onMessage(payload);\n\t\t\t\t\tchannel.ack(msg);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`Error handling event [${eventId}] on instance [${getInstanceId()}]`, err);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{ noAck: false }\n\t);\n\tconsole.log(`Subscribed to event [${eventId}] on queue [${queueName}] for instance [${getInstanceId()}]`);\n}\n\nconst kEntityEvents = (entityId: string) => `socket:events:entity:${entityId}`;\nconst kEntityInstances = (entityId: string) => `socket:instances:entity:${entityId}`;\n\nexport async function subscribeToSocketEvent() {\n\tconst queueName = `socket-events-${getInstanceId()}`;\n\tawait channel.assertQueue(queueName, { durable: true });\n\tawait channel.bindQueue(queueName, EXCHANGE_NAME, `instance.${getInstanceId()}.*`);\n\n\tawait channel.consume(queueName, msg => {\n\t\tif (!msg) return;\n\t\ttry {\n\t\t\tconst { localKey, payload, recipient } = JSON.parse(msg.content.toString('utf8'));\n\t\t\tLocalSubs.emit(recipient, localKey, payload);\n\t\t\tchannel.ack(msg);\n\t\t} catch (e) {\n\t\t\tconsole.error('Failed to handle instance event', e);\n\t\t\tchannel.nack(msg, false, false);\n\t\t}\n\t});\n\n\treturn channel;\n}\nexport async function publishSocketEvent(\n\tevent: BaseSocketEvent<any, any>,\n\trecipients: string[]\n): Promise<void> {\n\tconst redisService = getLibraries().getRedisService();\n\tconst localKey = event.getIdentifier(); // e.g. \"CHAT_UPSERT_MESSAGE:123123\"\n\tconst payload = event.payload();\n\n\tfor (const recipient of recipients) {\n\t\t// 1) Is this user subscribed to *this* event key?\n\t\tconst isSub = await redisService.isMemberOfSet(kEntityEvents(recipient), localKey);\n\n\t\tif (isSub) {\n\t\t\t// 2) Get all instances where this user is connected\n\t\t\tconst instanceNames = await redisService.getSetMembers(kEntityInstances(recipient));\n\n\t\t\tif (!instanceNames.length) {\n\t\t\t\t// No active instances → push notification fallback\n\t\t\t\t// TODO: queue push notification for { recipient, eventType, payload }\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// 3) Publish to every instance with routing\n\t\t\tfor (const instanceName of instanceNames) {\n\t\t\t\tconst routingKey = `${INSTANCE_ROUTE_PREFIX}.${instanceName}`; // remove event type\n\t\t\t\tconst messageBuffer = Buffer.from(JSON.stringify({ localKey, payload, recipient }), 'utf8');\n\n\t\t\t\tchannel.publish(EXCHANGE_NAME, routingKey, messageBuffer, {\n\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\tpersistent: true,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\t// Not subscribed → push notification fallback\n\t\t\t// TODO: queue push notification for { recipient, eventType, payload }\n\t\t}\n\t}\n}\n\nexport async function closeEventBus(): Promise<void> {\n\tif (channel) await channel.close();\n\tif (connection) await connection.close();\n\tconsole.log(`EventBus closed for instance [${getInstanceId()}]`);\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"/","sources":["libraries/event/index.ts"],"names":[],"mappings":"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","sourcesContent":["import amqp from 'amqplib';\nimport { BaseEvent } from './BaseEvent';\nimport { getInstanceId } from '../../utilities/instance.utils';\nimport { BaseSocketEvent } from '../socket/BaseSocketEvent';\nimport { getLibraries } from '../../index';\nimport { LocalSubs } from '../socket/LocalSubscriptionRegistry';\nimport { isEntitySubscribed, kEntityEvents, kEntityInstances } from '../socket/socket-redis-connections';\n\nlet connection: amqp.ChannelModel;\nlet channel: amqp.Channel;\nconst EXCHANGE_NAME = 'lyxa.events';\nconst INSTANCE_ROUTE_PREFIX = 'instance'; // routing key: instance.{instanceName}.{eventType}\n\nexport async function initEventBus(rabbitUrl: string) {\n\tconnection = await amqp.connect(rabbitUrl);\n\tchannel = await connection.createChannel();\n\tawait channel.assertExchange(EXCHANGE_NAME, 'topic', { durable: true });\n\tconsole.log(`EventBus initialized with instance ID: ${getInstanceId()}`);\n}\n\nexport async function publishEvent<TPayload extends Record<string, unknown>>(\n\tevent: BaseEvent<TPayload>\n): Promise<void> {\n\tif (!channel) throw new Error('Channel not initialized. Call initEventBus first.');\n\tconst messageBuffer = Buffer.from(JSON.stringify(event.payload));\n\tchannel.publish(EXCHANGE_NAME, event.eventId, messageBuffer, {\n\t\tcontentType: 'application/json',\n\t});\n\tconsole.log(`Published event [${event.eventId}] with payload`, event.payload);\n}\n\nexport async function subscribeToEvent(\n\teventId: string,\n\tonMessage: (payload: any) => Promise<void>\n): Promise<void> {\n\tif (!channel) throw new Error('Channel not initialized. Call initEventBus first.');\n\tconst queueName = `${eventId}-${getInstanceId()}`;\n\tawait channel.assertQueue(queueName, {\n\t\tdurable: false,\n\t\texclusive: true,\n\t\tautoDelete: true,\n\t});\n\tawait channel.bindQueue(queueName, EXCHANGE_NAME, eventId);\n\tawait channel.consume(\n\t\tqueueName,\n\t\tasync msg => {\n\t\t\tif (msg !== null) {\n\t\t\t\tconst payloadString = msg.content.toString();\n\t\t\t\tconst payload = JSON.parse(payloadString);\n\t\t\t\ttry {\n\t\t\t\t\tawait onMessage(payload);\n\t\t\t\t\tchannel.ack(msg);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`Error handling event [${eventId}] on instance [${getInstanceId()}]`, err);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{ noAck: false }\n\t);\n\tconsole.log(`Subscribed to event [${eventId}] on queue [${queueName}] for instance [${getInstanceId()}]`);\n}\n\nexport async function subscribeToSocketEvent() {\n\tconst queueName = `socket-events-${getInstanceId()}`;\n\tawait channel.assertQueue(queueName, { durable: true });\n\tawait channel.bindQueue(queueName, EXCHANGE_NAME, `instance.${getInstanceId()}.*`);\n\n\tawait channel.consume(queueName, msg => {\n\t\tif (!msg) return;\n\t\ttry {\n\t\t\tconst { localKey, payload, recipient } = JSON.parse(msg.content.toString('utf8'));\n\t\t\tLocalSubs.emit(recipient, localKey, payload);\n\t\t\tchannel.ack(msg);\n\t\t} catch (e) {\n\t\t\tconsole.error('Failed to handle instance event', e);\n\t\t\tchannel.nack(msg, false, false);\n\t\t}\n\t});\n\n\treturn channel;\n}\nexport async function publishSocketEvent(\n\tevent: BaseSocketEvent<any, any>,\n\trecipients: string[]\n): Promise<void> {\n\tconst redisService = getLibraries().getRedisService();\n\tconst localKey = event.getIdentifier(); // e.g. \"CHAT_UPSERT_MESSAGE:123123\"\n\tconst payload = event.payload();\n\n\tfor (const recipient of recipients) {\n\t\t// 1) Is this user subscribed to *this* event key?\n\t\tconst isSub = await isEntitySubscribed(recipient, localKey);\n\n\t\tconsole.log(isSub)\n\t\tif (isSub) {\n\t\t\t// 2) Get all instances where this user is connected\n\t\t\tconst instanceNames = await redisService.getSetMembers(kEntityInstances(recipient));\n\n\t\t\tconsole.log(instanceNames)\n\t\t\tif (!instanceNames.length) {\n\t\t\t\t// No active instances → push notification fallback\n\t\t\t\t// TODO: queue push notification for { recipient, eventType, payload }\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// 3) Publish to every instance with routing\n\t\t\tfor (const instanceName of instanceNames) {\n\t\t\t\tconst routingKey = `${INSTANCE_ROUTE_PREFIX}.${instanceName}`; // remove event type\n\t\t\t\tconst messageBuffer = Buffer.from(JSON.stringify({ localKey, payload, recipient }), 'utf8');\n\n\t\t\t\tconsole.log(\"published on routing key\", routingKey)\n\t\t\t\tchannel.publish(EXCHANGE_NAME, routingKey, messageBuffer, {\n\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\tpersistent: true,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\t// Not subscribed → push notification fallback\n\t\t\t// TODO: queue push notification for { recipient, eventType, payload }\n\t\t}\n\t}\n}\n\nexport async function closeEventBus(): Promise<void> {\n\tif (channel) await channel.close();\n\tif (connection) await connection.close();\n\tconsole.log(`EventBus closed for instance [${getInstanceId()}]`);\n}\n"]}
@@ -1,10 +1,18 @@
1
1
  import EventEmitter from 'events';
2
2
  type EventKey = string;
3
3
  type EntityId = string;
4
+ type SocketId = string;
5
+ export declare class LocalEventEmitter {
6
+ private _ee;
7
+ private _socketId;
8
+ constructor(socketId: SocketId);
9
+ get socketId(): string;
10
+ get ee(): EventEmitter<[never]>;
11
+ }
4
12
  declare class LocalSubscriptionRegistry {
5
13
  private byEntity;
6
- bind(entityId: EntityId, eventKey: EventKey, ee: EventEmitter): void;
7
- unbind(entityId: EntityId, eventKey: EventKey): void;
14
+ bind(entityId: EntityId, eventKey: EventKey, ee: LocalEventEmitter): void;
15
+ unbind(entityId: EntityId, eventKey: EventKey, ee: LocalEventEmitter): void;
8
16
  emit(entityId: EntityId, eventKey: EventKey, payload: unknown): void;
9
17
  }
10
18
  export declare const LocalSubs: LocalSubscriptionRegistry;
@@ -1,6 +1,25 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LocalSubs = void 0;
6
+ exports.LocalSubs = exports.LocalEventEmitter = void 0;
7
+ const events_1 = __importDefault(require("events"));
8
+ class LocalEventEmitter {
9
+ _ee;
10
+ _socketId;
11
+ constructor(socketId) {
12
+ this._ee = new events_1.default();
13
+ this._socketId = socketId;
14
+ }
15
+ get socketId() {
16
+ return this._socketId;
17
+ }
18
+ get ee() {
19
+ return this._ee;
20
+ }
21
+ }
22
+ exports.LocalEventEmitter = LocalEventEmitter;
4
23
  class LocalSubscriptionRegistry {
5
24
  byEntity = new Map();
6
25
  bind(entityId, eventKey, ee) {
@@ -9,13 +28,22 @@ class LocalSubscriptionRegistry {
9
28
  m = new Map();
10
29
  this.byEntity.set(entityId, m);
11
30
  }
12
- m.set(eventKey, ee);
31
+ const s = m.get(eventKey);
32
+ if (!s) {
33
+ m.set(eventKey, new Set());
34
+ }
35
+ m.get(eventKey)?.add(ee);
13
36
  }
14
- unbind(entityId, eventKey) {
37
+ unbind(entityId, eventKey, ee) {
15
38
  const m = this.byEntity.get(entityId);
16
39
  if (!m)
17
40
  return;
18
- m.delete(eventKey);
41
+ const s = m.get(eventKey);
42
+ if (s) {
43
+ s.delete(ee);
44
+ if (s.size === 0)
45
+ m.delete(eventKey);
46
+ }
19
47
  if (m.size === 0)
20
48
  this.byEntity.delete(entityId);
21
49
  }
@@ -23,7 +51,7 @@ class LocalSubscriptionRegistry {
23
51
  const m = this.byEntity.get(entityId);
24
52
  const ee = m?.get(eventKey);
25
53
  if (ee)
26
- ee.emit(eventKey, payload);
54
+ ee.forEach(e => e.ee.emit(eventKey, payload));
27
55
  }
28
56
  }
29
57
  exports.LocalSubs = new LocalSubscriptionRegistry();
@@ -1 +1 @@
1
- {"version":3,"file":"LocalSubscriptionRegistry.js","sourceRoot":"/","sources":["libraries/socket/LocalSubscriptionRegistry.ts"],"names":[],"mappings":";;;AAKA,MAAM,yBAAyB;IACtB,QAAQ,GAAG,IAAI,GAAG,EAAyC,CAAC;IAEpE,IAAI,CAAC,QAAkB,EAAE,QAAkB,EAAE,EAAgB;QAC5D,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,CAAC,EAAE,CAAC;YACR,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAChC,CAAC;QACD,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,QAAkB,EAAE,QAAkB;QAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnB,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;YAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,CAAC,QAAkB,EAAE,QAAkB,EAAE,OAAgB;QAC5D,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5B,IAAI,EAAE;YAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;CACD;AAEY,QAAA,SAAS,GAAG,IAAI,yBAAyB,EAAE,CAAC","sourcesContent":["import EventEmitter from 'events';\n\ntype EventKey = string; // \"EVENT_TYPE:identifier\"\ntype EntityId = string;\n\nclass LocalSubscriptionRegistry {\n\tprivate byEntity = new Map<EntityId, Map<EventKey, EventEmitter>>();\n\n\tbind(entityId: EntityId, eventKey: EventKey, ee: EventEmitter) {\n\t\tlet m = this.byEntity.get(entityId);\n\t\tif (!m) {\n\t\t\tm = new Map();\n\t\t\tthis.byEntity.set(entityId, m);\n\t\t}\n\t\tm.set(eventKey, ee);\n\t}\n\n\tunbind(entityId: EntityId, eventKey: EventKey) {\n\t\tconst m = this.byEntity.get(entityId);\n\t\tif (!m) return;\n\t\tm.delete(eventKey);\n\t\tif (m.size === 0) this.byEntity.delete(entityId);\n\t}\n\n\temit(entityId: EntityId, eventKey: EventKey, payload: unknown) {\n\t\tconst m = this.byEntity.get(entityId);\n\t\tconst ee = m?.get(eventKey);\n\t\tif (ee) ee.emit(eventKey, payload);\n\t}\n}\n\nexport const LocalSubs = new LocalSubscriptionRegistry();\n"]}
1
+ {"version":3,"file":"LocalSubscriptionRegistry.js","sourceRoot":"/","sources":["libraries/socket/LocalSubscriptionRegistry.ts"],"names":[],"mappings":";;;;;;AAAA,oDAAkC;AAMlC,MAAa,iBAAiB;IACrB,GAAG,CAAe;IAClB,SAAS,CAAW;IAE5B,YAAY,QAAkB;QAC7B,IAAI,CAAC,GAAG,GAAG,IAAI,gBAAY,EAAE,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,IAAI,EAAE;QACL,OAAO,IAAI,CAAC,GAAG,CAAC;IACjB,CAAC;CACD;AAhBD,8CAgBC;AAED,MAAM,yBAAyB;IACtB,QAAQ,GAAG,IAAI,GAAG,EAAmD,CAAC;IAE9E,IAAI,CAAC,QAAkB,EAAE,QAAkB,EAAE,EAAqB;QACjE,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,CAAC,EAAE,CAAC;YACR,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAChC,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1B,IAAI,CAAC,CAAC,EAAE,CAAC;YACR,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QAC5B,CAAC;QACD,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,QAAkB,EAAE,QAAkB,EAAE,EAAqB;QACnE,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1B,IAAI,CAAC,EAAE,CAAC;YACP,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACb,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;gBAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;YAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,CAAC,QAAkB,EAAE,QAAkB,EAAE,OAAgB;QAC5D,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5B,IAAI,EAAE;YAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD,CAAC;CACD;AAEY,QAAA,SAAS,GAAG,IAAI,yBAAyB,EAAE,CAAC","sourcesContent":["import EventEmitter from 'events';\n\ntype EventKey = string; // \"EVENT_TYPE:identifier\"\ntype EntityId = string;\ntype SocketId = string;\n\nexport class LocalEventEmitter {\n\tprivate _ee: EventEmitter;\n\tprivate _socketId: SocketId;\n\n\tconstructor(socketId: SocketId) {\n\t\tthis._ee = new EventEmitter();\n\t\tthis._socketId = socketId;\n\t}\n\n\tget socketId() {\n\t\treturn this._socketId;\n\t}\n\n\tget ee() {\n\t\treturn this._ee;\n\t}\n}\n\nclass LocalSubscriptionRegistry {\n\tprivate byEntity = new Map<EntityId, Map<EventKey, Set<LocalEventEmitter>>>();\n\n\tbind(entityId: EntityId, eventKey: EventKey, ee: LocalEventEmitter) {\n\t\tlet m = this.byEntity.get(entityId);\n\t\tif (!m) {\n\t\t\tm = new Map();\n\t\t\tthis.byEntity.set(entityId, m);\n\t\t}\n\t\tconst s = m.get(eventKey);\n\t\tif (!s) {\n\t\t\tm.set(eventKey, new Set());\n\t\t}\n\t\tm.get(eventKey)?.add(ee);\n\t}\n\n\tunbind(entityId: EntityId, eventKey: EventKey, ee: LocalEventEmitter) {\n\t\tconst m = this.byEntity.get(entityId);\n\t\tif (!m) return;\n\t\tconst s = m.get(eventKey);\n\t\tif (s) {\n\t\t\ts.delete(ee);\n\t\t\tif (s.size === 0) m.delete(eventKey);\n\t\t}\n\t\tif (m.size === 0) this.byEntity.delete(entityId);\n\t}\n\n\temit(entityId: EntityId, eventKey: EventKey, payload: unknown) {\n\t\tconst m = this.byEntity.get(entityId);\n\t\tconst ee = m?.get(eventKey);\n\t\tif (ee) ee.forEach(e => e.ee.emit(eventKey, payload));\n\t}\n}\n\nexport const LocalSubs = new LocalSubscriptionRegistry();\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"/","sources":["libraries/socket/events/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uEAAqD","sourcesContent":["export * from './chatroom-message-send-socket.event';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"/","sources":["libraries/socket/events/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uEAAqD","sourcesContent":["export * from './chatroom-message-send-socket.event';"]}
@@ -0,0 +1,11 @@
1
+ export declare const kEntityEvents: (entityId: string) => string;
2
+ export declare const kEntityInstances: (entityId: string) => string;
3
+ export declare const kEntityConnection: () => string;
4
+ export interface SocketRedisEventInformation {
5
+ eventKey: string;
6
+ instanceId: string;
7
+ socketId: string;
8
+ }
9
+ export declare function connectEntityToSocketEvent(entityId: string, socketRedisEventInformation: SocketRedisEventInformation): Promise<void>;
10
+ export declare function disconnectEntityFromSocketEvent(entityId: string, socketRedisEventInformation: SocketRedisEventInformation): Promise<void>;
11
+ export declare function isEntitySubscribed(entityId: string, eventKey: string): Promise<boolean>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.kEntityConnection = exports.kEntityInstances = exports.kEntityEvents = void 0;
4
+ exports.connectEntityToSocketEvent = connectEntityToSocketEvent;
5
+ exports.disconnectEntityFromSocketEvent = disconnectEntityFromSocketEvent;
6
+ exports.isEntitySubscribed = isEntitySubscribed;
7
+ const __1 = require("../..");
8
+ const kEntityEvents = (entityId) => `socket:events:entity:${entityId}`;
9
+ exports.kEntityEvents = kEntityEvents;
10
+ const kEntityInstances = (entityId) => `socket:instances:entity:${entityId}`;
11
+ exports.kEntityInstances = kEntityInstances;
12
+ const kEntityConnection = () => `socket:connections`;
13
+ exports.kEntityConnection = kEntityConnection;
14
+ async function connectEntityToSocketEvent(entityId, socketRedisEventInformation) {
15
+ const redis = (0, __1.getLibraries)().getRedisService();
16
+ await redis.addToSet((0, exports.kEntityEvents)(entityId), JSON.stringify(socketRedisEventInformation));
17
+ await redis.addToSet((0, exports.kEntityInstances)(entityId), socketRedisEventInformation.instanceId);
18
+ await redis.addToSet((0, exports.kEntityConnection)(), entityId);
19
+ }
20
+ async function disconnectEntityFromSocketEvent(entityId, socketRedisEventInformation) {
21
+ const redis = (0, __1.getLibraries)().getRedisService();
22
+ await redis.removeFromSet((0, exports.kEntityEvents)(entityId), JSON.stringify(socketRedisEventInformation));
23
+ const remainingEvents = (await redis.getSetMembers((0, exports.kEntityEvents)(entityId))).map(r => JSON.parse(r));
24
+ if (remainingEvents.filter(e => e.instanceId === socketRedisEventInformation.instanceId).length === 0) {
25
+ await redis.removeFromSet((0, exports.kEntityInstances)(entityId), socketRedisEventInformation.instanceId);
26
+ }
27
+ if (remainingEvents.length === 0) {
28
+ await redis.removeFromSet((0, exports.kEntityConnection)(), entityId);
29
+ }
30
+ }
31
+ async function isEntitySubscribed(entityId, eventKey) {
32
+ const redis = (0, __1.getLibraries)().getRedisService();
33
+ const events = await redis.getSetMembers((0, exports.kEntityEvents)(entityId));
34
+ return events
35
+ .map(e => JSON.parse(e))
36
+ .some(e => e.eventKey === eventKey);
37
+ }
38
+ //# sourceMappingURL=socket-redis-connections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket-redis-connections.js","sourceRoot":"/","sources":["libraries/socket/socket-redis-connections.ts"],"names":[],"mappings":";;;AAYA,gEASC;AAED,0EAmBC;AAED,gDAMC;AAlDD,6BAAqC;AAE9B,MAAM,aAAa,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,wBAAwB,QAAQ,EAAE,CAAC;AAAzE,QAAA,aAAa,iBAA4D;AAC/E,MAAM,gBAAgB,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,2BAA2B,QAAQ,EAAE,CAAC;AAA/E,QAAA,gBAAgB,oBAA+D;AACrF,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,oBAAoB,CAAC;AAA/C,QAAA,iBAAiB,qBAA8B;AAQrD,KAAK,UAAU,0BAA0B,CAC/C,QAAgB,EAChB,2BAAwD;IAExD,MAAM,KAAK,GAAG,IAAA,gBAAY,GAAE,CAAC,eAAe,EAAE,CAAC;IAE/C,MAAM,KAAK,CAAC,QAAQ,CAAC,IAAA,qBAAa,EAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAC3F,MAAM,KAAK,CAAC,QAAQ,CAAC,IAAA,wBAAgB,EAAC,QAAQ,CAAC,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAC;IACzF,MAAM,KAAK,CAAC,QAAQ,CAAC,IAAA,yBAAiB,GAAE,EAAE,QAAQ,CAAC,CAAC;AACrD,CAAC;AAEM,KAAK,UAAU,+BAA+B,CACpD,QAAgB,EAChB,2BAAwD;IAExD,MAAM,KAAK,GAAG,IAAA,gBAAY,GAAE,CAAC,eAAe,EAAE,CAAC;IAE/C,MAAM,KAAK,CAAC,aAAa,CAAC,IAAA,qBAAa,EAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAEhG,MAAM,eAAe,GAAG,CAAC,MAAM,KAAK,CAAC,aAAa,CAAC,IAAA,qBAAa,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAC/E,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAgC,CACjD,CAAC;IAEF,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,2BAA2B,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvG,MAAM,KAAK,CAAC,aAAa,CAAC,IAAA,wBAAgB,EAAC,QAAQ,CAAC,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,KAAK,CAAC,aAAa,CAAC,IAAA,yBAAiB,GAAE,EAAE,QAAQ,CAAC,CAAC;IAC1D,CAAC;AACF,CAAC;AAEM,KAAK,UAAU,kBAAkB,CAAC,QAAgB,EAAE,QAAgB;IAC1E,MAAM,KAAK,GAAG,IAAA,gBAAY,GAAE,CAAC,eAAe,EAAE,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,IAAA,qBAAa,EAAC,QAAQ,CAAC,CAAC,CAAC;IAClE,OAAO,MAAM;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAgC,CAAC;SACtD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;AACtC,CAAC","sourcesContent":["import { getLibraries } from '../..';\n\nexport const kEntityEvents = (entityId: string) => `socket:events:entity:${entityId}`;\nexport const kEntityInstances = (entityId: string) => `socket:instances:entity:${entityId}`;\nexport const kEntityConnection = () => `socket:connections`;\n\nexport interface SocketRedisEventInformation {\n\teventKey: string;\n\tinstanceId: string;\n\tsocketId: string;\n}\n\nexport async function connectEntityToSocketEvent(\n\tentityId: string,\n\tsocketRedisEventInformation: SocketRedisEventInformation\n) {\n\tconst redis = getLibraries().getRedisService();\n\n\tawait redis.addToSet(kEntityEvents(entityId), JSON.stringify(socketRedisEventInformation));\n\tawait redis.addToSet(kEntityInstances(entityId), socketRedisEventInformation.instanceId);\n\tawait redis.addToSet(kEntityConnection(), entityId);\n}\n\nexport async function disconnectEntityFromSocketEvent(\n\tentityId: string,\n\tsocketRedisEventInformation: SocketRedisEventInformation\n) {\n\tconst redis = getLibraries().getRedisService();\n\n\tawait redis.removeFromSet(kEntityEvents(entityId), JSON.stringify(socketRedisEventInformation));\n\n\tconst remainingEvents = (await redis.getSetMembers(kEntityEvents(entityId))).map(\n\t\tr => JSON.parse(r) as SocketRedisEventInformation\n\t);\n\n\tif (remainingEvents.filter(e => e.instanceId === socketRedisEventInformation.instanceId).length === 0) {\n\t\tawait redis.removeFromSet(kEntityInstances(entityId), socketRedisEventInformation.instanceId);\n\t}\n\n\tif (remainingEvents.length === 0) {\n\t\tawait redis.removeFromSet(kEntityConnection(), entityId);\n\t}\n}\n\nexport async function isEntitySubscribed(entityId: string, eventKey: string): Promise<boolean> {\n\tconst redis = getLibraries().getRedisService();\n\tconst events = await redis.getSetMembers(kEntityEvents(entityId));\n\treturn events\n\t\t.map(e => JSON.parse(e) as SocketRedisEventInformation)\n\t\t.some(e => e.eventKey === eventKey);\n}"]}
@@ -22,7 +22,7 @@ Perfect for sharing types between frontend and backend applications.
22
22
 
23
23
  ## Version
24
24
 
25
- Version: 1.0.374
25
+ Version: 1.0.375
26
26
 
27
27
  ## Dependencies
28
28
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyxa.ai/types",
3
- "version": "1.0.374",
3
+ "version": "1.0.375",
4
4
  "description": "Lyxa type definitions and validation schemas for both frontend and backend",
5
5
  "author": "elie <42282499+Internalizable@users.noreply.github.com>",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyxa.ai/core",
3
- "version": "1.0.374",
3
+ "version": "1.0.376",
4
4
  "description": "The Core system of the Lyxa services.",
5
5
  "author": "elie <42282499+Internalizable@users.noreply.github.com>",
6
6
  "license": "MIT",