wexa-chat 0.1.21 → 0.1.23

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.mjs CHANGED
@@ -498,7 +498,7 @@ function createMessagesService(models, hooks = {}) {
498
498
  }
499
499
  );
500
500
  if (onMessageCreated) {
501
- onMessageCreated(message);
501
+ await onMessageCreated(message);
502
502
  }
503
503
  return message;
504
504
  },
@@ -657,6 +657,8 @@ function createMessagesService(models, hooks = {}) {
657
657
  // src/transport/localSubs.ts
658
658
  var convSubs = /* @__PURE__ */ new Map();
659
659
  var socketSubs = /* @__PURE__ */ new Map();
660
+ var userSubs = /* @__PURE__ */ new Map();
661
+ var socketUserSubs = /* @__PURE__ */ new Map();
660
662
  function subscribeLocal(conversationId, socketId) {
661
663
  var _a, _b;
662
664
  if (!convSubs.has(conversationId)) {
@@ -698,6 +700,19 @@ function cleanupLocal(socketId) {
698
700
  }
699
701
  socketSubs.delete(socketId);
700
702
  }
703
+ const users = socketUserSubs.get(socketId);
704
+ if (users) {
705
+ for (const userId of users) {
706
+ const sockets = userSubs.get(userId);
707
+ if (sockets) {
708
+ sockets.delete(socketId);
709
+ if (sockets.size === 0) {
710
+ userSubs.delete(userId);
711
+ }
712
+ }
713
+ }
714
+ socketUserSubs.delete(socketId);
715
+ }
701
716
  }
702
717
  function fanoutLocal(conversationId, payload, emitter) {
703
718
  const sockets = convSubs.get(conversationId);
@@ -711,6 +726,52 @@ function fanoutLocal(conversationId, payload, emitter) {
711
726
  }
712
727
  }
713
728
  }
729
+ function subscribeToUser(userId, socketId) {
730
+ var _a, _b;
731
+ if (!userSubs.has(userId)) {
732
+ userSubs.set(userId, /* @__PURE__ */ new Set());
733
+ }
734
+ (_a = userSubs.get(userId)) == null ? void 0 : _a.add(socketId);
735
+ if (!socketUserSubs.has(socketId)) {
736
+ socketUserSubs.set(socketId, /* @__PURE__ */ new Set());
737
+ }
738
+ (_b = socketUserSubs.get(socketId)) == null ? void 0 : _b.add(userId);
739
+ }
740
+ function unsubscribeFromUser(userId, socketId) {
741
+ const sockets = userSubs.get(userId);
742
+ if (sockets) {
743
+ sockets.delete(socketId);
744
+ if (sockets.size === 0) {
745
+ userSubs.delete(userId);
746
+ }
747
+ }
748
+ const users = socketUserSubs.get(socketId);
749
+ if (users) {
750
+ users.delete(userId);
751
+ if (users.size === 0) {
752
+ socketUserSubs.delete(socketId);
753
+ }
754
+ }
755
+ }
756
+ function isSubscribedToUser(userId, socketId) {
757
+ var _a;
758
+ return ((_a = socketUserSubs.get(socketId)) == null ? void 0 : _a.has(userId)) || false;
759
+ }
760
+ function getSocketsForUser(userId) {
761
+ return userSubs.get(userId) || /* @__PURE__ */ new Set();
762
+ }
763
+ function fanoutToUser(userId, payload, emitter) {
764
+ const sockets = userSubs.get(userId);
765
+ if (sockets) {
766
+ for (const socketId of sockets) {
767
+ try {
768
+ emitter(socketId, payload);
769
+ } catch (error) {
770
+ console.error(`Error emitting to socket ${socketId}:`, error);
771
+ }
772
+ }
773
+ }
774
+ }
714
775
  var SHARED_CLIENT = null;
715
776
  var SHARED_CFG_FINGERPRINT = null;
716
777
  function createRedisClient(config) {
@@ -807,6 +868,8 @@ var SocketTransport = class {
807
868
  this.sockets = /* @__PURE__ */ new Map();
808
869
  this.users = /* @__PURE__ */ new Map();
809
870
  this.joinedConversations = /* @__PURE__ */ new Map();
871
+ // socketId -> convIds
872
+ this.subscribedToUsers = /* @__PURE__ */ new Map();
810
873
  // Socket.IO-like shim for getIO().sockets.sockets.get(id).emit('chat-event', payload)
811
874
  this.ioShim = {
812
875
  sockets: {
@@ -916,6 +979,7 @@ var SocketTransport = class {
916
979
  this.joinedConversations.set(socketId, /* @__PURE__ */ new Set());
917
980
  syncShim();
918
981
  ws.on("message", (raw) => {
982
+ var _a;
919
983
  try {
920
984
  const msg = JSON.parse(raw.toString());
921
985
  const type = msg == null ? void 0 : msg.type;
@@ -986,6 +1050,17 @@ var SocketTransport = class {
986
1050
  }
987
1051
  });
988
1052
  this.transport.publishToConversation(convId, payload);
1053
+ } else if (type === "subscribe-to-user" && typeof msg.userId === "string") {
1054
+ const userId2 = msg.userId;
1055
+ this.transport.subscribeToUser(userId2, socketId);
1056
+ if (!this.subscribedToUsers.has(socketId)) {
1057
+ this.subscribedToUsers.set(socketId, /* @__PURE__ */ new Set());
1058
+ }
1059
+ this.subscribedToUsers.get(socketId).add(userId2);
1060
+ } else if (type === "unsubscribe-from-user" && typeof msg.userId === "string") {
1061
+ const userId2 = msg.userId;
1062
+ this.transport.unsubscribeFromUser(userId2, socketId);
1063
+ (_a = this.subscribedToUsers.get(socketId)) == null ? void 0 : _a.delete(userId2);
989
1064
  }
990
1065
  } catch {
991
1066
  }
@@ -1014,6 +1089,13 @@ var SocketTransport = class {
1014
1089
  });
1015
1090
  }
1016
1091
  }
1092
+ const subscribedUsers = this.subscribedToUsers.get(socketId);
1093
+ if (subscribedUsers) {
1094
+ for (const userId2 of subscribedUsers) {
1095
+ this.transport.unsubscribeFromUser(userId2, socketId);
1096
+ }
1097
+ this.subscribedToUsers.delete(socketId);
1098
+ }
1017
1099
  this.transport.cleanupLocal(socketId);
1018
1100
  this.sockets.delete(socketId);
1019
1101
  this.users.delete(socketId);
@@ -1078,6 +1160,12 @@ function createTransport(config, server) {
1078
1160
  unsubscribeLocal,
1079
1161
  cleanupLocal,
1080
1162
  fanoutLocal,
1163
+ // User subscription methods
1164
+ subscribeToUser,
1165
+ unsubscribeFromUser,
1166
+ isSubscribedToUser,
1167
+ getSocketsForUser,
1168
+ fanoutToUser,
1081
1169
  // Redis methods
1082
1170
  publishToConversation: (conversationId, payload) => publishToConversation(redisClient, conversationId, payload),
1083
1171
  startRedisListener: (onEvent) => startRedisListener(redisClient, onEvent)
@@ -1246,7 +1334,7 @@ async function initChat(mongooseInstance, options, server) {
1246
1334
  const services = {
1247
1335
  conversations: createConversationsService(models),
1248
1336
  messages: createMessagesService(models, {
1249
- onMessageCreated: (message) => {
1337
+ onMessageCreated: async (message) => {
1250
1338
  const payload = { type: "message:created", message };
1251
1339
  transport.fanoutLocal(message.conversationId.toString(), payload, (socketId, event) => {
1252
1340
  if (transport.socket) {
@@ -1256,6 +1344,26 @@ async function initChat(mongooseInstance, options, server) {
1256
1344
  }
1257
1345
  }
1258
1346
  });
1347
+ try {
1348
+ const ConversationModel = models.Conversation;
1349
+ const conversation = await ConversationModel.findById(message.conversationId);
1350
+ if (conversation && conversation.participants) {
1351
+ for (const participant of conversation.participants) {
1352
+ if (participant.entityModel === "User") {
1353
+ transport.fanoutToUser(participant.entityId, payload, (socketId, event) => {
1354
+ if (transport.socket) {
1355
+ const socket = transport.socket.getIO().sockets.sockets.get(socketId);
1356
+ if (socket) {
1357
+ socket.emit("chat-event", event);
1358
+ }
1359
+ }
1360
+ });
1361
+ }
1362
+ }
1363
+ }
1364
+ } catch (error) {
1365
+ console.error("Error fanning out to user subscribers:", error);
1366
+ }
1259
1367
  transport.publishToConversation(message.conversationId.toString(), payload);
1260
1368
  },
1261
1369
  onMessageRead: (args) => {