wexa-chat 0.2.9 → 0.2.10
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/README.md +25 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +82 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/client/index.d.ts +0 -49
package/README.md
CHANGED
|
@@ -125,6 +125,8 @@ export type InitOptions = {
|
|
|
125
125
|
- `listMessages({ organizationId, conversationId, limit?, cursor? })`
|
|
126
126
|
- `listMessagesWithSenders({ organizationId, conversationId, limit?, cursor?, populateSenders: true, populateOptions? })`
|
|
127
127
|
- `markRead({ organizationId, conversationId, participantModel, participantId, messageId })`
|
|
128
|
+
- `receiveWhatsappMessage({ whatsappChatId, message })`
|
|
129
|
+
- `receiveLinkedinMessage({ linkedinChatId, message })`
|
|
128
130
|
|
|
129
131
|
DTO types live in `src/types/dto.ts`.
|
|
130
132
|
|
|
@@ -254,6 +256,29 @@ Under the hood (`src/services/messages.service.ts`):
|
|
|
254
256
|
|
|
255
257
|
This allows subsequent UI actions to prefill the last known contact handles for LinkedIn and WhatsApp.
|
|
256
258
|
|
|
259
|
+
### Receiving inbound connector messages
|
|
260
|
+
|
|
261
|
+
When an external connector delivers a new inbound message, you can persist it directly using the chat ID stored on the conversation:
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
await chat.services.messages.receiveWhatsappMessage({
|
|
265
|
+
whatsappChatId: 'wa-chat-123',
|
|
266
|
+
message: 'Hello from WhatsApp',
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
await chat.services.messages.receiveLinkedinMessage({
|
|
270
|
+
linkedinChatId: 'li-chat-456',
|
|
271
|
+
message: 'Hello from LinkedIn',
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Both helpers will:
|
|
276
|
+
|
|
277
|
+
1. Locate the conversation by the given chat ID.
|
|
278
|
+
2. Use the `Application` participant from the conversation as the sender.
|
|
279
|
+
3. Create a new message with `kind: 'text'` and `source` set to the respective connector.
|
|
280
|
+
4. Update the conversation summary fields (`lastMessageAt`, `lastMessagePreview`, `lastMessageSenderId`, `lastMessageSenderModel`).
|
|
281
|
+
|
|
257
282
|
## Models
|
|
258
283
|
|
|
259
284
|
The package exports the following model types which can be imported directly:
|
package/dist/index.d.cts
CHANGED
|
@@ -375,6 +375,14 @@ interface MessagesService {
|
|
|
375
375
|
populateSenders: true;
|
|
376
376
|
}): Promise<PaginatedResult<MessageWithSender>>;
|
|
377
377
|
markRead(args: MarkReadArgs): Promise<void>;
|
|
378
|
+
receiveWhatsappMessage(args: {
|
|
379
|
+
whatsappChatId: string;
|
|
380
|
+
message: string;
|
|
381
|
+
}): Promise<IMessage>;
|
|
382
|
+
receiveLinkedinMessage(args: {
|
|
383
|
+
linkedinChatId: string;
|
|
384
|
+
message: string;
|
|
385
|
+
}): Promise<IMessage>;
|
|
378
386
|
}
|
|
379
387
|
/**
|
|
380
388
|
* Create messages service
|
package/dist/index.d.ts
CHANGED
|
@@ -375,6 +375,14 @@ interface MessagesService {
|
|
|
375
375
|
populateSenders: true;
|
|
376
376
|
}): Promise<PaginatedResult<MessageWithSender>>;
|
|
377
377
|
markRead(args: MarkReadArgs): Promise<void>;
|
|
378
|
+
receiveWhatsappMessage(args: {
|
|
379
|
+
whatsappChatId: string;
|
|
380
|
+
message: string;
|
|
381
|
+
}): Promise<IMessage>;
|
|
382
|
+
receiveLinkedinMessage(args: {
|
|
383
|
+
linkedinChatId: string;
|
|
384
|
+
message: string;
|
|
385
|
+
}): Promise<IMessage>;
|
|
378
386
|
}
|
|
379
387
|
/**
|
|
380
388
|
* Create messages service
|
package/dist/index.js
CHANGED
|
@@ -78,6 +78,8 @@ function createConversationModel(options, conn) {
|
|
|
78
78
|
},
|
|
79
79
|
{ timestamps: true }
|
|
80
80
|
);
|
|
81
|
+
ConversationSchema.index({ linkedinChatId: 1 }, { unique: false, sparse: true });
|
|
82
|
+
ConversationSchema.index({ whatsappChatId: 1 }, { unique: false, sparse: true });
|
|
81
83
|
const model = conn.model(name, ConversationSchema);
|
|
82
84
|
modelRegistry.set(registryKey, model);
|
|
83
85
|
return model;
|
|
@@ -659,6 +661,86 @@ function createMessagesService(models, hooks = {}) {
|
|
|
659
661
|
message.failed_source = failed_source;
|
|
660
662
|
return message;
|
|
661
663
|
},
|
|
664
|
+
/**
|
|
665
|
+
* Receive a new message by whatsappChatId
|
|
666
|
+
*/
|
|
667
|
+
async receiveWhatsappMessage({ whatsappChatId, message }) {
|
|
668
|
+
const conversation = await Conversation.findOne({ whatsappChatId }).lean();
|
|
669
|
+
if (!conversation) {
|
|
670
|
+
throw new Error("Conversation not found for given whatsappChatId");
|
|
671
|
+
}
|
|
672
|
+
const applicationParticipant = conversation.participants.find(
|
|
673
|
+
(p) => p.entityModel === "Application"
|
|
674
|
+
);
|
|
675
|
+
if (!applicationParticipant) {
|
|
676
|
+
throw new Error("Application participant not found in conversation");
|
|
677
|
+
}
|
|
678
|
+
const orgId = conversation.organizationId;
|
|
679
|
+
const senderModel = "Application";
|
|
680
|
+
const senderId = applicationParticipant.entityId;
|
|
681
|
+
const msgDoc = new Message({
|
|
682
|
+
organizationId: orgId,
|
|
683
|
+
conversationId: String(conversation._id),
|
|
684
|
+
senderModel,
|
|
685
|
+
senderId,
|
|
686
|
+
text: message,
|
|
687
|
+
kind: "text",
|
|
688
|
+
source: ["whatsapp"],
|
|
689
|
+
parentMessageId: void 0,
|
|
690
|
+
rootThreadId: void 0
|
|
691
|
+
});
|
|
692
|
+
await msgDoc.save();
|
|
693
|
+
await Conversation.findByIdAndUpdate(conversation._id, {
|
|
694
|
+
$set: {
|
|
695
|
+
lastMessageAt: msgDoc.createdAt,
|
|
696
|
+
lastMessagePreview: message.substring(0, 100),
|
|
697
|
+
lastMessageSenderId: senderId,
|
|
698
|
+
lastMessageSenderModel: senderModel
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
if (onMessageCreated) onMessageCreated(msgDoc);
|
|
702
|
+
return msgDoc;
|
|
703
|
+
},
|
|
704
|
+
/**
|
|
705
|
+
* Receive a new message by linkedinChatId
|
|
706
|
+
*/
|
|
707
|
+
async receiveLinkedinMessage({ linkedinChatId, message }) {
|
|
708
|
+
const conversation = await Conversation.findOne({ linkedinChatId }).lean();
|
|
709
|
+
if (!conversation) {
|
|
710
|
+
throw new Error("Conversation not found for given linkedinChatId");
|
|
711
|
+
}
|
|
712
|
+
const applicationParticipant = conversation.participants.find(
|
|
713
|
+
(p) => p.entityModel === "Application"
|
|
714
|
+
);
|
|
715
|
+
if (!applicationParticipant) {
|
|
716
|
+
throw new Error("Application participant not found in conversation");
|
|
717
|
+
}
|
|
718
|
+
const orgId = conversation.organizationId;
|
|
719
|
+
const senderModel = "Application";
|
|
720
|
+
const senderId = applicationParticipant.entityId;
|
|
721
|
+
const msgDoc = new Message({
|
|
722
|
+
organizationId: orgId,
|
|
723
|
+
conversationId: String(conversation._id),
|
|
724
|
+
senderModel,
|
|
725
|
+
senderId,
|
|
726
|
+
text: message,
|
|
727
|
+
kind: "text",
|
|
728
|
+
source: ["linkedin"],
|
|
729
|
+
parentMessageId: void 0,
|
|
730
|
+
rootThreadId: void 0
|
|
731
|
+
});
|
|
732
|
+
await msgDoc.save();
|
|
733
|
+
await Conversation.findByIdAndUpdate(conversation._id, {
|
|
734
|
+
$set: {
|
|
735
|
+
lastMessageAt: msgDoc.createdAt,
|
|
736
|
+
lastMessagePreview: message.substring(0, 100),
|
|
737
|
+
lastMessageSenderId: senderId,
|
|
738
|
+
lastMessageSenderModel: senderModel
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
if (onMessageCreated) onMessageCreated(msgDoc);
|
|
742
|
+
return msgDoc;
|
|
743
|
+
},
|
|
662
744
|
/**
|
|
663
745
|
* List messages for a conversation with pagination
|
|
664
746
|
* @param args Message listing arguments
|