wexa-chat 0.2.6 → 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 +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.js +112 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +112 -12
- 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
|
@@ -247,6 +247,22 @@ type SearchConversationsArgs = {
|
|
|
247
247
|
cursor?: string;
|
|
248
248
|
};
|
|
249
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Represents a successful chat start response
|
|
252
|
+
*/
|
|
253
|
+
interface ChatStartedResponse {
|
|
254
|
+
object: 'ChatStarted';
|
|
255
|
+
chat_id: string;
|
|
256
|
+
message_id: string;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Common response type for chat API operations
|
|
260
|
+
*/
|
|
261
|
+
type ChatApiResponse = ChatStartedResponse | {
|
|
262
|
+
error: string;
|
|
263
|
+
details?: unknown;
|
|
264
|
+
};
|
|
265
|
+
|
|
250
266
|
interface IConversation extends Document {
|
|
251
267
|
organizationId: string;
|
|
252
268
|
participants: Array<{
|
|
@@ -359,6 +375,14 @@ interface MessagesService {
|
|
|
359
375
|
populateSenders: true;
|
|
360
376
|
}): Promise<PaginatedResult<MessageWithSender>>;
|
|
361
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>;
|
|
362
386
|
}
|
|
363
387
|
/**
|
|
364
388
|
* Create messages service
|
|
@@ -582,4 +606,4 @@ interface ChatServices {
|
|
|
582
606
|
*/
|
|
583
607
|
declare function initChat(mongooseInstance: typeof mongoose, options: InitOptions, server?: Server): Promise<ChatServices>;
|
|
584
608
|
|
|
585
|
-
export { type Actor, type ChatServices, type ConversationModel, type ConversationReadEvent, type ConversationsService, type CreateConversationArgs, type EnvironmentConfig, type IConversation, type IMessage, type InitOptions, type ListMessagesArgs, type MarkReadArgs, type MessageCreatedEvent, type MessageModel, type MessageServiceHooks, type MessageWithSender, type MessagesService, type PaginatedResult, type PresenceEvent, type RedisConfig, type RuntimeConfig, type SearchConversationsArgs, type SearchMessagesArgs, type SendMessageArgs, type SocketConfig$1 as SocketConfig, type SourceType, type Transport, type TransportConfig, type TypingEvent, createConversationId, createConversationModel, createConversationsService, createCursor, createMessageId, createMessageModel, createMessagesService, createModels, createPaginatedResponse, createThreadId, createTransport, ensureIndexes, generateId, getRedisConfig, getRuntimeConfig, initChat, modelRegistry, parseCursor, searchByParticipantPair, searchConversations, searchMessages, setRuntimeConfig, sourceType, validateCreateConversationArgs, validateInitOptions, validateMarkReadArgs, validatePagination, validateSendMessageArgs };
|
|
609
|
+
export { type Actor, type ChatApiResponse, type ChatServices, type ChatStartedResponse, type ConversationModel, type ConversationReadEvent, type ConversationsService, type CreateConversationArgs, type EnvironmentConfig, type IConversation, type IMessage, type InitOptions, type ListMessagesArgs, type MarkReadArgs, type MessageCreatedEvent, type MessageModel, type MessageServiceHooks, type MessageWithSender, type MessagesService, type PaginatedResult, type PresenceEvent, type RedisConfig, type RuntimeConfig, type SearchConversationsArgs, type SearchMessagesArgs, type SendMessageArgs, type SocketConfig$1 as SocketConfig, type SourceType, type Transport, type TransportConfig, type TypingEvent, createConversationId, createConversationModel, createConversationsService, createCursor, createMessageId, createMessageModel, createMessagesService, createModels, createPaginatedResponse, createThreadId, createTransport, ensureIndexes, generateId, getRedisConfig, getRuntimeConfig, initChat, modelRegistry, parseCursor, searchByParticipantPair, searchConversations, searchMessages, setRuntimeConfig, sourceType, validateCreateConversationArgs, validateInitOptions, validateMarkReadArgs, validatePagination, validateSendMessageArgs };
|
package/dist/index.d.ts
CHANGED
|
@@ -247,6 +247,22 @@ type SearchConversationsArgs = {
|
|
|
247
247
|
cursor?: string;
|
|
248
248
|
};
|
|
249
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Represents a successful chat start response
|
|
252
|
+
*/
|
|
253
|
+
interface ChatStartedResponse {
|
|
254
|
+
object: 'ChatStarted';
|
|
255
|
+
chat_id: string;
|
|
256
|
+
message_id: string;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Common response type for chat API operations
|
|
260
|
+
*/
|
|
261
|
+
type ChatApiResponse = ChatStartedResponse | {
|
|
262
|
+
error: string;
|
|
263
|
+
details?: unknown;
|
|
264
|
+
};
|
|
265
|
+
|
|
250
266
|
interface IConversation extends Document {
|
|
251
267
|
organizationId: string;
|
|
252
268
|
participants: Array<{
|
|
@@ -359,6 +375,14 @@ interface MessagesService {
|
|
|
359
375
|
populateSenders: true;
|
|
360
376
|
}): Promise<PaginatedResult<MessageWithSender>>;
|
|
361
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>;
|
|
362
386
|
}
|
|
363
387
|
/**
|
|
364
388
|
* Create messages service
|
|
@@ -582,4 +606,4 @@ interface ChatServices {
|
|
|
582
606
|
*/
|
|
583
607
|
declare function initChat(mongooseInstance: typeof mongoose, options: InitOptions, server?: Server): Promise<ChatServices>;
|
|
584
608
|
|
|
585
|
-
export { type Actor, type ChatServices, type ConversationModel, type ConversationReadEvent, type ConversationsService, type CreateConversationArgs, type EnvironmentConfig, type IConversation, type IMessage, type InitOptions, type ListMessagesArgs, type MarkReadArgs, type MessageCreatedEvent, type MessageModel, type MessageServiceHooks, type MessageWithSender, type MessagesService, type PaginatedResult, type PresenceEvent, type RedisConfig, type RuntimeConfig, type SearchConversationsArgs, type SearchMessagesArgs, type SendMessageArgs, type SocketConfig$1 as SocketConfig, type SourceType, type Transport, type TransportConfig, type TypingEvent, createConversationId, createConversationModel, createConversationsService, createCursor, createMessageId, createMessageModel, createMessagesService, createModels, createPaginatedResponse, createThreadId, createTransport, ensureIndexes, generateId, getRedisConfig, getRuntimeConfig, initChat, modelRegistry, parseCursor, searchByParticipantPair, searchConversations, searchMessages, setRuntimeConfig, sourceType, validateCreateConversationArgs, validateInitOptions, validateMarkReadArgs, validatePagination, validateSendMessageArgs };
|
|
609
|
+
export { type Actor, type ChatApiResponse, type ChatServices, type ChatStartedResponse, type ConversationModel, type ConversationReadEvent, type ConversationsService, type CreateConversationArgs, type EnvironmentConfig, type IConversation, type IMessage, type InitOptions, type ListMessagesArgs, type MarkReadArgs, type MessageCreatedEvent, type MessageModel, type MessageServiceHooks, type MessageWithSender, type MessagesService, type PaginatedResult, type PresenceEvent, type RedisConfig, type RuntimeConfig, type SearchConversationsArgs, type SearchMessagesArgs, type SendMessageArgs, type SocketConfig$1 as SocketConfig, type SourceType, type Transport, type TransportConfig, type TypingEvent, createConversationId, createConversationModel, createConversationsService, createCursor, createMessageId, createMessageModel, createMessagesService, createModels, createPaginatedResponse, createThreadId, createTransport, ensureIndexes, generateId, getRedisConfig, getRuntimeConfig, initChat, modelRegistry, parseCursor, searchByParticipantPair, searchConversations, searchMessages, setRuntimeConfig, sourceType, validateCreateConversationArgs, validateInitOptions, validateMarkReadArgs, validatePagination, validateSendMessageArgs };
|
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;
|
|
@@ -555,6 +557,8 @@ function createMessagesService(models, hooks = {}) {
|
|
|
555
557
|
const tasks = [];
|
|
556
558
|
let lastLinkedInId;
|
|
557
559
|
let lastWhatsAppId;
|
|
560
|
+
let linkedinChatId;
|
|
561
|
+
let whatsappChatId;
|
|
558
562
|
if (Array.isArray(source) && source.includes("linkedin")) {
|
|
559
563
|
const LinkedinConnector = connectorIds && connectorIds.linkedin;
|
|
560
564
|
lastLinkedInId = LinkedinConnector == null ? void 0 : LinkedinConnector.connectorId;
|
|
@@ -563,10 +567,18 @@ function createMessagesService(models, hooks = {}) {
|
|
|
563
567
|
name: "linkedin",
|
|
564
568
|
run: async () => {
|
|
565
569
|
const path = paths.linkedin.startChat(String(LinkedinConnector.connectorId));
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
+
try {
|
|
571
|
+
const res = await getAxios().post(path, {
|
|
572
|
+
linkedin_url: LinkedinConnector.contactId,
|
|
573
|
+
text
|
|
574
|
+
});
|
|
575
|
+
const data = res.data;
|
|
576
|
+
console.log("linkedinChatId", data);
|
|
577
|
+
linkedinChatId = data.chat_data.chat_id;
|
|
578
|
+
return { status: "fulfilled", value: data };
|
|
579
|
+
} catch (error) {
|
|
580
|
+
return { status: "rejected", reason: error };
|
|
581
|
+
}
|
|
570
582
|
}
|
|
571
583
|
});
|
|
572
584
|
} else {
|
|
@@ -587,7 +599,14 @@ function createMessagesService(models, hooks = {}) {
|
|
|
587
599
|
phone_numbers: sanitize(raw),
|
|
588
600
|
text
|
|
589
601
|
};
|
|
590
|
-
|
|
602
|
+
try {
|
|
603
|
+
const res = await getAxios().post(path, body);
|
|
604
|
+
const data = res.data;
|
|
605
|
+
whatsappChatId = data.chat_id;
|
|
606
|
+
return { status: "fulfilled", value: data };
|
|
607
|
+
} catch (error) {
|
|
608
|
+
return { status: "rejected", reason: error };
|
|
609
|
+
}
|
|
591
610
|
}
|
|
592
611
|
});
|
|
593
612
|
} else {
|
|
@@ -596,22 +615,21 @@ function createMessagesService(models, hooks = {}) {
|
|
|
596
615
|
}
|
|
597
616
|
if (tasks.length > 0) {
|
|
598
617
|
const results = await Promise.allSettled(tasks.map((t) => t.run()));
|
|
599
|
-
results.forEach((
|
|
618
|
+
results.forEach((result, idx) => {
|
|
619
|
+
var _a, _b, _c, _d, _e, _f;
|
|
600
620
|
const name = tasks[idx].name;
|
|
601
|
-
if (
|
|
621
|
+
if (result.status === "fulfilled") {
|
|
602
622
|
success_source.push(name);
|
|
603
623
|
} else {
|
|
604
|
-
const
|
|
605
|
-
res.reason.response.data.detail || res.reason.response.data || "Unknown error";
|
|
624
|
+
const error = ((_c = (_b = (_a = result.reason) == null ? void 0 : _a.response) == null ? void 0 : _b.data) == null ? void 0 : _c.detail) || ((_e = (_d = result.reason) == null ? void 0 : _d.response) == null ? void 0 : _e.data) || ((_f = result.reason) == null ? void 0 : _f.message) || "Unknown error";
|
|
606
625
|
failed_source.push({
|
|
607
626
|
source: name,
|
|
608
|
-
message: typeof
|
|
627
|
+
message: typeof error === "string" ? error : JSON.stringify(error)
|
|
609
628
|
});
|
|
629
|
+
console.error(`${name} failed:`, error);
|
|
610
630
|
}
|
|
611
631
|
});
|
|
612
|
-
console.log("results", results);
|
|
613
632
|
}
|
|
614
|
-
console.log("success_source", success_source);
|
|
615
633
|
const message = new Message({
|
|
616
634
|
organizationId,
|
|
617
635
|
conversationId,
|
|
@@ -632,6 +650,8 @@ function createMessagesService(models, hooks = {}) {
|
|
|
632
650
|
};
|
|
633
651
|
if (lastLinkedInId) conversationUpdate.lastLinkedInId = lastLinkedInId;
|
|
634
652
|
if (lastWhatsAppId) conversationUpdate.lastWhatsAppId = lastWhatsAppId;
|
|
653
|
+
if (linkedinChatId) conversationUpdate.linkedinChatId = linkedinChatId;
|
|
654
|
+
if (whatsappChatId) conversationUpdate.whatsappChatId = whatsappChatId;
|
|
635
655
|
await Conversation.findByIdAndUpdate(conversationId, {
|
|
636
656
|
$set: conversationUpdate
|
|
637
657
|
});
|
|
@@ -641,6 +661,86 @@ function createMessagesService(models, hooks = {}) {
|
|
|
641
661
|
message.failed_source = failed_source;
|
|
642
662
|
return message;
|
|
643
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
|
+
},
|
|
644
744
|
/**
|
|
645
745
|
* List messages for a conversation with pagination
|
|
646
746
|
* @param args Message listing arguments
|