wexa-chat 0.2.2 → 0.2.3

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.d.cts CHANGED
@@ -261,6 +261,8 @@ interface IConversation extends Document {
261
261
  lastMessageSenderModel?: string;
262
262
  lastLinkedInId?: string;
263
263
  lastWhatsAppId?: string;
264
+ linkedinChatId?: string;
265
+ whatsappChatId?: string;
264
266
  metadata?: Record<string, any>;
265
267
  createdAt: Date;
266
268
  updatedAt: Date;
package/dist/index.d.ts CHANGED
@@ -261,6 +261,8 @@ interface IConversation extends Document {
261
261
  lastMessageSenderModel?: string;
262
262
  lastLinkedInId?: string;
263
263
  lastWhatsAppId?: string;
264
+ linkedinChatId?: string;
265
+ whatsappChatId?: string;
264
266
  metadata?: Record<string, any>;
265
267
  createdAt: Date;
266
268
  updatedAt: Date;
package/dist/index.js CHANGED
@@ -72,6 +72,8 @@ function createConversationModel(options, conn) {
72
72
  lastMessageSenderModel: String,
73
73
  lastLinkedInId: String,
74
74
  lastWhatsAppId: String,
75
+ linkedinChatId: String,
76
+ whatsappChatId: String,
75
77
  metadata: Schema.Types.Mixed
76
78
  },
77
79
  { timestamps: true }
@@ -599,14 +601,17 @@ function createMessagesService(models, hooks = {}) {
599
601
  if (res.status === "fulfilled") {
600
602
  success_source.push(name);
601
603
  } else {
602
- const err = res.reason.response.data.detail || res.reason.response.data || "Unknown error";
604
+ const err = success_source;
605
+ res.reason.response.data.detail || res.reason.response.data || "Unknown error";
603
606
  failed_source.push({
604
607
  source: name,
605
608
  message: typeof err === "string" ? err : JSON.stringify(err)
606
609
  });
607
610
  }
608
611
  });
612
+ console.log("results", results);
609
613
  }
614
+ console.log("success_source", success_source);
610
615
  const message = new Message({
611
616
  organizationId,
612
617
  conversationId,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/models/Conversation.model.ts","../src/models/Message.model.ts","../src/models/connection.ts","../src/utils/pagination.ts","../src/services/search/search.conversations.ts","../src/services/conversations.service.ts","../src/services/search/search.messages.ts","../src/config/paths.ts","../src/config/runtime.ts","../src/config/axios.ts","../src/services/messages.service.ts","../src/transport/localSubs.ts","../src/transport/redis.ts","../src/transport/socket.ts","../src/transport/index.ts","../src/models/indexes.ts","../src/config/env.ts","../src/utils/ids.ts","../src/utils/validators.ts","../src/index.ts"],"names":["axios","Redis","WebSocketServer","url","ws","WebSocket"],"mappings":"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","file":"index.js","sourcesContent":["import type { Schema as MongooseSchema, Document, Model, Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { modelRegistry } from './connection';\n\nexport interface IConversation extends Document {\n organizationId: string;\n participants: Array<{\n entityModel: string;\n entityId: string;\n role: string;\n }>;\n lastMessageId?: string;\n lastMessageAt?: Date;\n lastMessagePreview?: string;\n lastMessageSenderId?: string;\n lastMessageSenderModel?: string;\n lastLinkedInId?: string;\n lastWhatsAppId?: string;\n metadata?: Record<string, any>;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * Create (or retrieve) Conversation model safely\n */\nexport function createConversationModel(\n options: InitOptions,\n conn: Connection,\n): Model<IConversation> {\n // Generate a unique key for the model registry\n const connectionId = conn.id || conn.name || 'default';\n const registryKey = `${connectionId}:Conversation`;\n\n // Return from registry if exists\n if (modelRegistry.has(registryKey)) {\n return modelRegistry.get(registryKey) as Model<IConversation>;\n }\n\n // Check if model already exists on the connection\n const name = 'Conversation';\n if (conn.models[name]) {\n const existingModel = conn.models[name] as Model<IConversation>;\n modelRegistry.set(registryKey, existingModel);\n return existingModel;\n }\n\n // Participant schema (use the Schema from the same mongoose instance as the connection)\n const Schema: typeof MongooseSchema = (conn as any).base.Schema;\n const ParticipantSchema = new Schema(\n {\n entityModel: {\n type: String,\n enum: options.participantModels,\n required: true,\n },\n entityId: {\n type: String,\n required: true,\n },\n role: {\n type: String,\n enum: options.memberRoles,\n required: true,\n },\n },\n { _id: false },\n );\n\n // Conversation schema\n const ConversationSchema = new Schema<IConversation>(\n {\n organizationId: {\n type: String,\n required: true,\n },\n participants: {\n type: [ParticipantSchema],\n required: true,\n validate: {\n validator: function (participants: any[]) {\n return participants.length === 2;\n },\n message: 'Conversations must have exactly 2 participants',\n },\n },\n lastMessageId: {\n type: String,\n ref: 'Message',\n },\n lastMessageAt: {\n type: Date,\n },\n lastMessagePreview: String,\n lastMessageSenderId: String,\n lastMessageSenderModel: String,\n lastLinkedInId: String,\n lastWhatsAppId: String,\n metadata: (Schema as any).Types.Mixed,\n },\n { timestamps: true },\n );\n\n // Create the model\n const model = conn.model<IConversation>(name, ConversationSchema);\n\n // Register the model\n modelRegistry.set(registryKey, model);\n\n return model;\n}\n","import type { Schema as MongooseSchema, Document, Model, Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { modelRegistry } from './connection';\n\nexport const sourceType = {\n LINKEDIN: 'linkedin',\n WHATSAPP: 'whatsapp',\n EMAIL: 'email',\n CORE: 'core',\n} as const;\n\nexport type SourceType = (typeof sourceType)[keyof typeof sourceType];\n\nexport interface IMessage extends Document {\n organizationId: string;\n conversationId: string;\n senderModel: string;\n senderId: string;\n text: string;\n kind: 'text' | 'system';\n source: SourceType[];\n failed_source?: Array<{ source: string; message: string }>;\n parentMessageId?: string;\n rootThreadId?: string;\n editedAt?: Date;\n deletedAt?: Date;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * Create (or retrieve) Message model safely\n */\nexport function createMessageModel(options: InitOptions, conn: Connection): Model<IMessage> {\n // Generate a unique key for the model registry\n const connectionId = conn.id || conn.name || 'default';\n const registryKey = `${connectionId}:Message`;\n\n // Return from registry if exists\n if (modelRegistry.has(registryKey)) {\n return modelRegistry.get(registryKey) as Model<IMessage>;\n }\n\n // Check if model already exists on the connection\n const name = 'Message';\n if (conn.models[name]) {\n const existingModel = conn.models[name] as Model<IMessage>;\n modelRegistry.set(registryKey, existingModel);\n return existingModel;\n }\n\n // Build Schema from the same mongoose instance as the connection\n const Schema: typeof MongooseSchema = (conn as any).base.Schema;\n const MessageSchema = new Schema<IMessage>(\n {\n organizationId: {\n type: String,\n required: true,\n index: true,\n },\n conversationId: {\n type: String,\n required: true,\n index: true,\n },\n senderModel: {\n type: String,\n enum: options.participantModels,\n required: true,\n },\n senderId: {\n type: String,\n required: true,\n index: true,\n },\n kind: {\n type: String,\n enum: ['text', 'system'],\n default: 'text',\n index: true,\n },\n source: {\n type: [String],\n enum: Object.values(sourceType),\n required: true,\n },\n text: {\n type: String,\n trim: true,\n },\n parentMessageId: {\n type: String,\n ref: 'Message',\n },\n rootThreadId: {\n type: String,\n ref: 'Message',\n },\n editedAt: {\n type: Date,\n },\n deletedAt: {\n type: Date,\n },\n },\n { timestamps: true },\n );\n\n // Indexes\n MessageSchema.index({\n organizationId: 1,\n conversationId: 1,\n createdAt: -1,\n });\n\n // Create text search index if enabled\n if (options.enableTextSearch) {\n MessageSchema.index(\n { text: 'text' },\n {\n name: 'text_search',\n weights: { text: 10 },\n },\n );\n }\n\n // Create the model\n const model = conn.model<IMessage>(name, MessageSchema);\n\n // Register the model\n modelRegistry.set(registryKey, model);\n\n return model;\n}\n","import mongoose, { Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { createConversationModel } from './Conversation.model';\nimport { createMessageModel } from './Message.model';\n\n// Global model registry to prevent duplicate compilations\nexport const modelRegistry = new Map<string, mongoose.Model<any>>();\n\n/**\n * Create Mongoose models with applied configuration\n * @param mongooseInstance Mongoose instance\n * @param options Initialization options\n * @returns Object containing Conversation and Message models\n */\nexport function createModels(mongooseInstance: typeof mongoose, options: InitOptions) {\n // Get the connection instance\n const conn: Connection = mongooseInstance.connection;\n\n // Generate a unique connection identifier for this connection\n const connectionId = conn.id || conn.name || 'default';\n \n // Check if models are already registered for this connection\n const registryKey = `${connectionId}:Conversation`;\n const messageRegistryKey = `${connectionId}:Message`;\n \n // Create or reuse models\n const Conversation = modelRegistry.get(registryKey) || createConversationModel(options, conn);\n const Message = modelRegistry.get(messageRegistryKey) || createMessageModel(options, conn);\n \n // Register models if they're new\n if (!modelRegistry.has(registryKey)) {\n modelRegistry.set(registryKey, Conversation);\n }\n \n if (!modelRegistry.has(messageRegistryKey)) {\n modelRegistry.set(messageRegistryKey, Message);\n }\n \n return {\n Conversation,\n Message\n };\n}\n\n/**\n * Connection state enum\n */\nenum ConnectionState {\n Disconnected = 0,\n Connected = 1,\n Connecting = 2,\n Disconnecting = 3,\n}","/**\n * Pagination result interface\n */\nexport interface PaginatedResult<T> {\n items: T[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n/**\n * Creates a pagination cursor from a timestamp and ID\n * @param timestamp Timestamp to encode in the cursor\n * @param id ID to encode in the cursor\n * @returns An encoded cursor string\n */\nexport function createCursor(timestamp: number, id: string): string {\n const cursorData = `${timestamp}:${id}`;\n return Buffer.from(cursorData).toString('base64');\n}\n\n/**\n * Parses a pagination cursor into its timestamp and ID components\n * @param cursor The cursor string to parse\n * @returns An object containing the timestamp and ID, or null if invalid\n */\nexport function parseCursor(cursor: string): { timestamp: number; id: string } | null {\n try {\n const decoded = Buffer.from(cursor, 'base64').toString('utf-8');\n const [timestampStr, id] = decoded.split(':');\n \n const timestamp = parseInt(timestampStr, 10);\n \n if (isNaN(timestamp) || !id) {\n return null;\n }\n \n return { timestamp, id };\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Creates a paginated response\n * @param items The items for the current page\n * @param limit The requested page size\n * @param getNextCursor Function to get the next cursor from the last item\n * @returns A paginated result object\n */\nexport function createPaginatedResponse<T>(\n items: T[],\n limit: number,\n getNextCursor: (lastItem: T) => string\n): PaginatedResult<T> {\n const hasMore = items.length > limit;\n \n // If we have more items than the limit, remove the extra item\n // that we used to determine if there are more pages\n const paginatedItems = hasMore ? items.slice(0, limit) : items;\n \n // Get the next cursor from the last item if we have more items\n const nextCursor = hasMore && paginatedItems.length > 0\n ? getNextCursor(paginatedItems[paginatedItems.length - 1])\n : null;\n \n return {\n items: paginatedItems,\n nextCursor,\n hasMore,\n };\n}\n\n\n\n\n","import { Model } from 'mongoose';\nimport { IConversation } from '../../models/Conversation.model';\nimport { SearchConversationsArgs } from '../../types';\nimport { createCursor, parseCursor, PaginatedResult } from '../../utils/pagination';\n\n/**\n * Search conversations with pagination\n */\nexport async function searchConversations(\n model: Model<IConversation>,\n params: SearchConversationsArgs\n): Promise<PaginatedResult<IConversation>> {\n const { \n organizationId, \n participantModel, \n participantId,\n limit = 20, \n cursor \n } = params;\n \n // Base query with required organizationId\n const baseQuery: Record<string, any> = { \n organizationId \n };\n \n // Add participant filter if provided\n if (participantModel && participantId) {\n baseQuery['participants'] = {\n $elemMatch: {\n entityModel: participantModel,\n entityId: participantId\n }\n };\n }\n \n // Handle cursor-based pagination\n if (cursor) {\n const parsedCursor = parseCursor(cursor);\n \n if (parsedCursor) {\n const { timestamp, id } = parsedCursor;\n const cursorDate = new Date(timestamp);\n \n baseQuery.$or = [\n { lastMessageAt: { $lt: cursorDate } },\n { lastMessageAt: cursorDate, _id: { $lt: id } }\n ];\n }\n }\n \n // Find conversations and sort by lastMessageAt\n const conversations = await model.find(baseQuery)\n .sort({ lastMessageAt: -1 })\n .limit(limit + 1)\n .exec();\n \n // Check if we have more results\n const hasMore = conversations.length > limit;\n const items = hasMore ? conversations.slice(0, limit) : conversations;\n \n // Create next cursor if we have more results\n let nextCursor: string | null = null;\n \n if (hasMore && items.length > 0) {\n const lastItem = items[items.length - 1];\n // Use lastMessageAt if available, otherwise use createdAt\n const timestamp = lastItem.lastMessageAt ? \n lastItem.lastMessageAt.getTime() : \n lastItem.createdAt.getTime();\n \n nextCursor = createCursor(timestamp, lastItem._id.toString());\n }\n \n return {\n items,\n nextCursor,\n hasMore\n };\n}\n\n/**\n * Find a conversation between two specific participants\n */\nexport async function searchByParticipantPair(\n model: Model<IConversation>,\n params: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }\n): Promise<IConversation | null> {\n const { organizationId, a, b } = params;\n \n const conversation = await model.findOne({\n organizationId,\n $and: [\n {\n participants: {\n $elemMatch: {\n entityModel: a.model,\n entityId: a.id\n }\n }\n },\n {\n participants: {\n $elemMatch: {\n entityModel: b.model,\n entityId: b.id\n }\n }\n },\n {\n $expr: {\n $eq: [{ $size: \"$participants\" }, 2]\n }\n }\n ]\n });\n \n return conversation;\n}","import { Model } from 'mongoose';\nimport { IConversation } from '../models/Conversation.model';\nimport { IMessage } from '../models/Message.model';\nimport { CreateConversationArgs, SearchConversationsArgs } from '../types';\nimport { searchConversations, searchByParticipantPair } from './search/search.conversations';\nimport { PaginatedResult } from '../utils/pagination';\n\n/**\n * Service for managing conversations\n */\nexport interface ConversationsService {\n createOrFindConversation(args: CreateConversationArgs): Promise<IConversation>;\n getConversation(organizationId: string, conversationId: string): Promise<IConversation | null>;\n searchConversations(args: SearchConversationsArgs): Promise<PaginatedResult<IConversation>>;\n searchByParticipantPair(args: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }): Promise<IConversation | null>;\n}\n\n/**\n * Create conversations service\n * @param models MongoDB models\n * @returns Conversations service instance\n */\nexport function createConversationsService(models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n}): ConversationsService {\n const { Conversation } = models;\n\n return {\n /**\n * Create a new conversation or find existing one between participants\n */\n async createOrFindConversation(args: CreateConversationArgs): Promise<IConversation> {\n console.log('Creating or finding conversation for users:', {\n args,\n });\n const { organizationId, a, b } = args;\n console.log('Creating or finding conversation for users:', {\n organizationId,\n a,\n b,\n });\n\n try {\n console.log('asdfa');\n // Check if conversation already exists between these participants\n const existingConversation = await searchByParticipantPair(Conversation, {\n organizationId,\n a,\n b,\n });\n\n console.log('Existing conversation:', existingConversation);\n if (existingConversation) {\n return existingConversation;\n }\n\n // Create new conversation\n const newConversation = new Conversation({\n organizationId,\n participants: [\n {\n entityModel: a.model,\n entityId: a.id,\n role: 'member', // Default role\n },\n {\n entityModel: b.model,\n entityId: b.id,\n role: 'member', // Default role\n },\n ],\n lastMessageAt: new Date(), // Set initial lastMessageAt\n });\n\n console.log('New conversation:', newConversation);\n\n await newConversation.save();\n console.log('Saved conversation:', newConversation);\n return newConversation;\n } catch (error) {\n console.error('Error in createOrFindConversation:', error);\n throw error;\n }\n },\n\n /**\n * Get a conversation by ID\n */\n async getConversation(\n organizationId: string,\n conversationId: string,\n ): Promise<IConversation | null> {\n try {\n return await Conversation.findOne({\n organizationId,\n _id: conversationId,\n });\n } catch (error) {\n console.error('Error in getConversation:', error);\n throw error;\n }\n },\n\n /**\n * Search conversations with pagination\n */\n async searchConversations(\n args: SearchConversationsArgs,\n ): Promise<PaginatedResult<IConversation>> {\n try {\n return await searchConversations(Conversation, args);\n } catch (error) {\n console.error('Error in searchConversations:', error);\n throw error;\n }\n },\n\n /**\n * Find a conversation between two specific participants\n */\n async searchByParticipantPair(args: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }): Promise<IConversation | null> {\n try {\n return await searchByParticipantPair(Conversation, args);\n } catch (error) {\n console.error('Error in searchByParticipantPair:', error);\n throw error;\n }\n },\n };\n}\n","import { Model } from 'mongoose';\nimport { IMessage } from '../../models/Message.model';\nimport { SearchMessagesArgs } from '../../types';\nimport { createCursor, parseCursor, PaginatedResult } from '../../utils/pagination';\n\n/**\n * Search messages based on various criteria\n * @param model Message model\n * @param params Search parameters\n * @returns Paginated messages with optional text search results\n */\nexport async function searchMessages(\n model: Model<IMessage>,\n params: SearchMessagesArgs\n): Promise<PaginatedResult<IMessage>> {\n const { \n organizationId,\n query,\n conversationId,\n senderModel,\n senderId,\n kind,\n dateFrom,\n dateTo,\n threadRootId,\n limit = 20,\n cursor\n } = params;\n \n // Base query with required organizationId\n const baseQuery: Record<string, any> = { \n organizationId\n };\n\n // Add optional filters if provided\n if (conversationId) {\n baseQuery.conversationId = conversationId;\n }\n \n if (senderModel && senderId) {\n baseQuery.senderModel = senderModel;\n baseQuery.senderId = senderId;\n } else if (senderModel) {\n baseQuery.senderModel = senderModel;\n }\n \n if (kind) {\n baseQuery.kind = kind;\n }\n \n // Date range filters\n if (dateFrom || dateTo) {\n baseQuery.createdAt = {};\n \n if (dateFrom) {\n baseQuery.createdAt.$gte = new Date(dateFrom);\n }\n \n if (dateTo) {\n baseQuery.createdAt.$lte = new Date(dateTo);\n }\n }\n \n // Thread filter\n if (threadRootId) {\n baseQuery.rootThreadId = threadRootId;\n }\n \n // Handle cursor-based pagination\n if (cursor) {\n const parsedCursor = parseCursor(cursor);\n \n if (parsedCursor) {\n const { timestamp, id } = parsedCursor;\n \n baseQuery.$or = [\n { createdAt: { $lt: new Date(timestamp) } },\n { createdAt: new Date(timestamp), _id: { $lt: id } }\n ];\n }\n }\n \n // Determine sort order and query approach\n let sort: Record<string, number> = { createdAt: -1 };\n let pipeline: any[] = [];\n \n // Use text search if query provided\n if (query && query.trim()) {\n // Set up text search with score and appropriate sort\n pipeline = [\n { $match: { $text: { $search: query }, ...baseQuery } },\n { $addFields: { score: { $meta: 'textScore' } } },\n { $sort: { score: { $meta: 'textScore' }, createdAt: -1 } },\n { $limit: limit + 1 } // Get one extra for pagination\n ];\n } else {\n // Use standard query\n pipeline = [\n { $match: baseQuery },\n { $sort: sort },\n { $limit: limit + 1 } // Get one extra for pagination\n ];\n }\n \n // Execute query\n const items = await model.aggregate(pipeline);\n \n // Check if we have more results\n const hasMore = items.length > limit;\n const limitedItems = hasMore ? items.slice(0, limit) : items;\n \n // Create next cursor if we have more results\n const nextCursor = hasMore && limitedItems.length > 0\n ? createCursor(\n new Date(limitedItems[limitedItems.length - 1].createdAt).getTime(),\n limitedItems[limitedItems.length - 1]._id.toString()\n )\n : null;\n \n return {\n items: limitedItems,\n nextCursor,\n hasMore\n };\n}\n","// Centralized path builders for external data service endpoints\n\nexport const paths = {\n linkedin: {\n startChat: (connectorId: string) => `/actions/linkedin/start_chat/${connectorId}`,\n },\n whatsapp: {\n startChat: (connectorId: string) => `/actions/whatsapp/start_chat/${connectorId}`,\n },\n // Add more services here as needed\n};\n","export type RuntimeConfig = {\n dataServiceEndpoint?: string;\n secretId?: string;\n};\n\nlet runtimeConfig: RuntimeConfig = {};\n\nexport function setRuntimeConfig(cfg: RuntimeConfig) {\n runtimeConfig = { ...runtimeConfig, ...cfg };\n}\n\nexport function getRuntimeConfig(): RuntimeConfig {\n return runtimeConfig;\n}\n","import axios, { AxiosInstance } from 'axios';\nimport { getRuntimeConfig } from './runtime';\n\nlet cachedInstance: AxiosInstance | null = null;\nlet cachedBaseUrl: string | null = null;\nlet cachedSecret: string | null = null;\n\nexport function getAxios(): AxiosInstance {\n const { dataServiceEndpoint, secretId } = getRuntimeConfig();\n if (!dataServiceEndpoint) {\n throw new Error('Data service endpoint not configured');\n }\n\n const baseURL = dataServiceEndpoint.replace(/\\/$/, '');\n\n // Recreate if config changed\n if (!cachedInstance || cachedBaseUrl !== baseURL || cachedSecret !== (secretId || null)) {\n cachedBaseUrl = baseURL;\n cachedSecret = secretId || null;\n\n console.log('Creating axios instance', { baseURL, secretId });\n\n cachedInstance = axios.create({\n baseURL,\n headers: {\n 'Content-Type': 'application/json',\n ...(secretId ? { 'x-api-key': secretId } : {}),\n },\n });\n }\n\n return cachedInstance;\n}\n","import { Model } from 'mongoose';\nimport { IConversation } from '../models/Conversation.model';\nimport { IMessage } from '../models/Message.model';\nimport type { SourceType } from '../models';\nimport { SendMessageArgs, ListMessagesArgs, MarkReadArgs } from '../types';\nimport { searchMessages } from './search/search.messages';\nimport {\n createPaginatedResponse,\n PaginatedResult,\n createCursor,\n parseCursor,\n} from '../utils/pagination';\nimport { paths } from '../config/paths';\nimport { getAxios } from '../config/axios';\n\n/**\n * Message service hooks interface\n */\nexport interface MessageServiceHooks {\n onMessageCreated?: (message: IMessage) => void;\n onMessageRead?: (args: MarkReadArgs & { at: Date }) => void;\n}\n\n/**\n * Message with populated sender information\n */\nexport interface MessageWithSender extends IMessage {\n sender?: Record<string, any>;\n}\n\n/**\n * Service for managing messages\n */\nexport interface MessagesService {\n sendMessage(args: SendMessageArgs): Promise<IMessage>;\n listMessages(args: ListMessagesArgs): Promise<PaginatedResult<IMessage>>;\n listMessagesWithSenders(\n args: ListMessagesArgs & { populateSenders: true },\n ): Promise<PaginatedResult<MessageWithSender>>;\n markRead(args: MarkReadArgs): Promise<void>;\n}\n\n/**\n * Create messages service\n * @param models MongoDB models\n * @param hooks Service hooks\n * @returns Messages service instance\n */\nexport function createMessagesService(\n models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n },\n hooks: MessageServiceHooks = {},\n): MessagesService {\n const { Message, Conversation } = models;\n const { onMessageCreated, onMessageRead } = hooks;\n\n return {\n /**\n * Send a new message\n * @param args Message sending arguments\n * @returns The created message\n */\n async sendMessage(args: SendMessageArgs): Promise<IMessage> {\n const {\n organizationId,\n conversationId,\n senderModel,\n senderId,\n text,\n kind = 'text',\n source,\n parentMessageId,\n rootThreadId,\n connectorIds,\n } = args;\n\n const success_source: SourceType[] = ['core'];\n const failed_source: Array<{ source: string; message: string }> = [];\n\n // Build external calls and run them concurrently\n const tasks: Array<{ name: SourceType; run: () => Promise<any> }> = [];\n\n let lastLinkedInId: string | undefined;\n let lastWhatsAppId: string | undefined;\n\n if (Array.isArray(source) && source.includes('linkedin')) {\n const LinkedinConnector = connectorIds && (connectorIds as any).linkedin;\n lastLinkedInId = LinkedinConnector?.connectorId;\n if (LinkedinConnector) {\n tasks.push({\n name: 'linkedin' as SourceType,\n run: async () => {\n const path = paths.linkedin.startChat(String(LinkedinConnector.connectorId));\n await getAxios().post(path, {\n linkedin_url: LinkedinConnector.contactId,\n text,\n });\n },\n });\n } else {\n failed_source.push({ source: 'linkedin', message: 'Missing connector configuration' });\n }\n }\n\n if (Array.isArray(source) && source.includes('whatsapp')) {\n const whatsappConnector = connectorIds && (connectorIds as any).whatsapp;\n lastWhatsAppId = whatsappConnector?.connectorId;\n\n if (whatsappConnector) {\n tasks.push({\n name: 'whatsapp' as SourceType,\n run: async () => {\n const path = paths.whatsapp.startChat(String(whatsappConnector.connectorId));\n const sanitize = (v: string) => String(v).replace(/\\s+/g, '').replace(/^\\+/, '');\n const raw = whatsappConnector.contactId;\n const body = {\n phone_numbers: sanitize(raw),\n text,\n } as any;\n await getAxios().post(path, body);\n },\n });\n } else {\n failed_source.push({ source: 'whatsapp', message: 'Missing connector configuration' });\n }\n }\n\n if (tasks.length > 0) {\n const results = await Promise.allSettled(tasks.map((t) => t.run()));\n results.forEach((res, idx) => {\n const name = tasks[idx].name;\n if (res.status === 'fulfilled') {\n success_source.push(name);\n } else {\n const err =\n res.reason.response.data.detail || res.reason.response.data || 'Unknown error';\n failed_source.push({\n source: name,\n message: typeof err === 'string' ? err : JSON.stringify(err),\n });\n }\n });\n }\n\n const message = new Message({\n organizationId,\n conversationId,\n senderModel,\n senderId,\n text,\n kind,\n source: success_source,\n parentMessageId,\n rootThreadId: rootThreadId || parentMessageId,\n });\n\n await message.save();\n\n const conversationUpdate: Record<string, any> = {\n lastMessageAt: message.createdAt,\n lastMessagePreview: text.substring(0, 100),\n lastMessageSenderId: senderId,\n lastMessageSenderModel: senderModel,\n };\n\n if (lastLinkedInId) conversationUpdate.lastLinkedInId = lastLinkedInId;\n if (lastWhatsAppId) conversationUpdate.lastWhatsAppId = lastWhatsAppId;\n\n await Conversation.findByIdAndUpdate(conversationId, {\n $set: conversationUpdate,\n });\n if (onMessageCreated) {\n onMessageCreated(message);\n }\n\n (message as any).failed_source = failed_source;\n\n return message;\n },\n\n /**\n * List messages for a conversation with pagination\n * @param args Message listing arguments\n * @returns Paginated list of messages\n */\n async listMessages(args: ListMessagesArgs): Promise<PaginatedResult<IMessage>> {\n const {\n organizationId,\n conversationId,\n limit = 20,\n cursor,\n populateSenders,\n populateOptions,\n } = args;\n\n // If population is requested, delegate to the specialized method\n if (populateSenders) {\n return this.listMessagesWithSenders({\n ...args,\n populateSenders: true,\n });\n }\n\n return searchMessages(Message, {\n organizationId,\n conversationId,\n limit,\n cursor,\n });\n },\n\n /**\n * List messages with populated sender information optimized for infinite scroll\n * @param args Message listing arguments with populate options\n * @returns Paginated list of messages with sender details\n */\n async listMessagesWithSenders(\n args: ListMessagesArgs & { populateSenders: true },\n ): Promise<PaginatedResult<MessageWithSender>> {\n const { organizationId, conversationId, limit = 20, cursor, populateOptions = {} } = args;\n const { fields = '_id name', modelMapping = {} } = populateOptions;\n\n // Create base query for message filtering\n const baseQuery: Record<string, any> = {\n organizationId,\n conversationId,\n };\n\n // Handle cursor-based pagination for infinite scroll\n if (cursor) {\n try {\n const decodedCursor = parseCursor(cursor);\n if (decodedCursor) {\n const { timestamp, id } = decodedCursor;\n\n // Query for messages older than the cursor position\n // This works well for chat interfaces where newer messages are at the bottom\n baseQuery.$or = [\n { createdAt: { $lt: new Date(timestamp) } },\n { createdAt: new Date(timestamp), _id: { $lt: id } },\n ];\n }\n } catch (error) {\n console.error('Failed to parse cursor:', error);\n }\n }\n\n // Get an extra item to determine if there are more messages to load\n const fetchLimit = limit + 1;\n\n // Directly query with sort to efficiently implement infinite scroll\n const messages = await Message.find(baseQuery)\n .sort({ createdAt: -1 })\n .limit(fetchLimit)\n .lean();\n\n // No messages found\n if (messages.length === 0) {\n return {\n items: [],\n hasMore: false,\n nextCursor: null,\n };\n }\n\n // Check if we have more messages available\n const hasMore = messages.length > limit;\n const items = hasMore ? messages.slice(0, limit) : messages;\n\n // Create the next cursor for infinite scroll\n const lastItem = items[items.length - 1];\n const nextCursor = hasMore\n ? createCursor(new Date(lastItem.createdAt).getTime(), lastItem._id.toString())\n : null;\n\n // Extract unique sender IDs by model type\n const sendersByModel: Record<string, Set<string>> = {};\n\n items.forEach((message) => {\n const { senderModel, senderId } = message;\n\n if (!sendersByModel[senderModel]) {\n sendersByModel[senderModel] = new Set<string>();\n }\n\n sendersByModel[senderModel].add(senderId);\n });\n\n // Load all senders in parallel by model type (1 query per model type)\n const mongoose = Message.base;\n const senders: Record<string, Record<string, any>> = {};\n\n await Promise.all(\n Object.entries(sendersByModel).map(async ([senderModel, senderIdsSet]) => {\n const modelName = modelMapping[senderModel] || senderModel;\n const senderIds = Array.from(senderIdsSet);\n\n // Skip if model doesn't exist\n if (!mongoose.modelNames().includes(modelName)) {\n console.warn(`Model ${modelName} not found for sender population`);\n return;\n }\n\n try {\n const SenderModel = mongoose.model(modelName);\n const modelSenders = await SenderModel.find({ _id: { $in: senderIds } })\n .select(fields)\n .lean()\n .exec();\n\n // Create lookup map for this model\n senders[senderModel] = {};\n modelSenders.forEach((sender) => {\n if (sender?._id) senders[senderModel][String(sender._id)] = sender;\n });\n } catch (error) {\n console.error(`Error loading senders for model ${modelName}:`, error);\n }\n }),\n );\n\n // Attach sender data to each message\n const populatedItems = items.map((message) => ({\n ...message,\n sender: senders[message.senderModel]?.[message.senderId] || null,\n })) as MessageWithSender[];\n\n return {\n items: populatedItems,\n hasMore,\n nextCursor,\n };\n },\n\n /**\n * Mark a message as read by a participant\n * @param args Read marking arguments\n */\n async markRead(args: MarkReadArgs): Promise<void> {\n const { organizationId, conversationId, participantModel, participantId, messageId } = args;\n\n const at = new Date();\n\n // Update the message read receipts\n await Message.findOneAndUpdate(\n {\n organizationId,\n conversationId,\n _id: messageId,\n // Ensure read receipt doesn't exist for this participant\n 'readBy.participantId': { $ne: participantId },\n },\n {\n $push: {\n readBy: {\n participantModel,\n participantId,\n readAt: at,\n },\n },\n },\n );\n\n // Update participant last read in conversation\n await Conversation.findOneAndUpdate(\n {\n organizationId,\n _id: conversationId,\n 'participants.entityModel': participantModel,\n 'participants.entityId': participantId,\n },\n {\n $set: {\n 'participants.$.lastReadMessageId': messageId,\n 'participants.$.lastReadAt': at,\n },\n },\n );\n\n // Trigger hook\n if (onMessageRead) {\n onMessageRead({ ...args, at });\n }\n },\n };\n}\n","/**\n * In-memory subscription maps for conversations and sockets\n */\n\n// Maps conversation IDs to sets of socket IDs\nconst convSubs: Map<string, Set<string>> = new Map();\n\n// Maps socket IDs to sets of conversation IDs\nconst socketSubs: Map<string, Set<string>> = new Map();\n\n/**\n * Subscribe a socket to a conversation\n * @param conversationId The conversation ID to subscribe to\n * @param socketId The socket ID to subscribe\n */\nexport function subscribeLocal(conversationId: string, socketId: string): void {\n // Add socket to conversation subscribers\n if (!convSubs.has(conversationId)) {\n convSubs.set(conversationId, new Set());\n }\n convSubs.get(conversationId)?.add(socketId);\n \n // Add conversation to socket subscriptions\n if (!socketSubs.has(socketId)) {\n socketSubs.set(socketId, new Set());\n }\n socketSubs.get(socketId)?.add(conversationId);\n}\n\n/**\n * Unsubscribe a socket from a conversation\n * @param conversationId The conversation ID to unsubscribe from\n * @param socketId The socket ID to unsubscribe\n */\nexport function unsubscribeLocal(conversationId: string, socketId: string): void {\n // Remove socket from conversation subscribers\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n sockets.delete(socketId);\n if (sockets.size === 0) {\n convSubs.delete(conversationId);\n }\n }\n \n // Remove conversation from socket subscriptions\n const conversations = socketSubs.get(socketId);\n if (conversations) {\n conversations.delete(conversationId);\n if (conversations.size === 0) {\n socketSubs.delete(socketId);\n }\n }\n}\n\n/**\n * Clean up all subscriptions for a socket\n * @param socketId The socket ID to clean up\n */\nexport function cleanupLocal(socketId: string): void {\n // Get all conversations this socket is subscribed to\n const conversations = socketSubs.get(socketId);\n if (conversations) {\n // Unsubscribe from each conversation\n for (const conversationId of conversations) {\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n sockets.delete(socketId);\n if (sockets.size === 0) {\n convSubs.delete(conversationId);\n }\n }\n }\n \n // Remove socket from socket subscriptions\n socketSubs.delete(socketId);\n }\n}\n\n/**\n * Fan out a message to all local subscribers of a conversation\n * @param conversationId The conversation ID to fan out to\n * @param payload The payload to send\n * @param emitter Function to emit events to socket IDs\n */\nexport function fanoutLocal(\n conversationId: string,\n payload: any,\n emitter: (toSocketId: string, event: any) => void\n): void {\n // Get all sockets subscribed to this conversation\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n // Emit to each socket\n for (const socketId of sockets) {\n try {\n emitter(socketId, payload);\n } catch (error) {\n console.error(`Error emitting to socket ${socketId}:`, error);\n }\n }\n }\n}","import Redis from 'ioredis';\nimport { RedisConfig } from '../config/env';\n\n// Cache a single Redis client per process to avoid multiple connections under HMR/re-inits\nlet SHARED_CLIENT: Redis | null = null;\nlet SHARED_CFG_FINGERPRINT: string | null = null;\n\n/**\n * Create a Redis client based on provided configuration\n * @param config Redis configuration\n * @returns Redis client instance or null if configuration is missing\n */\nexport function createRedisClient(config?: RedisConfig): Redis | null {\n if (!config) {\n console.warn('Redis configuration not found. Redis features will be disabled.');\n return null;\n }\n \n try {\n // Reuse existing client if config didn't change\n const fingerprint = JSON.stringify({\n url: config.url || null,\n host: config.host || null,\n port: config.port || null,\n db: config.db || null,\n password: Boolean(config.password),\n });\n\n if (SHARED_CLIENT && SHARED_CFG_FINGERPRINT === fingerprint) {\n return SHARED_CLIENT;\n }\n\n let client: Redis;\n \n // Use either URL or granular connection options\n if (config.url) {\n client = new Redis(config.url);\n } else if (config.host) {\n client = new Redis({\n host: config.host,\n port: config.port,\n password: config.password,\n db: config.db,\n connectTimeout: config.socketConnectTimeout, // Changed \n enableReadyCheck: true,\n enableOfflineQueue: true,\n retryStrategy(times) {\n const delay = Math.min(times * 50, 2000);\n return delay;\n }\n });\n } else {\n console.warn('Invalid Redis configuration. Redis features will be disabled.');\n return null;\n }\n \n // Log Redis connection events\n client.on('connect', () => {\n console.info('Redis client connected');\n });\n \n client.on('error', (err) => {\n console.error('Redis client error:', err);\n });\n \n client.on('reconnecting', () => {\n console.info('Redis client reconnecting');\n });\n \n // Cache and return\n SHARED_CLIENT = client;\n SHARED_CFG_FINGERPRINT = fingerprint;\n return SHARED_CLIENT;\n } catch (error) {\n console.error('Failed to create Redis client:', error);\n return null;\n }\n}\n\n/**\n * Publish a message to a conversation channel\n * @param client Redis client\n * @param conversationId Conversation ID\n * @param payload Message payload\n * @returns Promise resolving to number of clients that received the message\n */\nexport async function publishToConversation(\n client: Redis | null,\n conversationId: string,\n payload: any\n): Promise<number> {\n if (!client) return 0;\n \n try {\n const channel = `conv:${conversationId}`;\n const message = JSON.stringify(payload);\n return await client.publish(channel, message);\n } catch (error) {\n console.error(`Failed to publish to conversation ${conversationId}:`, error);\n return 0;\n }\n}\n\n/**\n * Start Redis subscription listener\n * @param client Redis client\n * @param onEvent Callback function for received events\n * @returns Function to stop the listener\n */\nexport function startRedisListener(\n client: Redis | null,\n onEvent: (conversationId: string, payload: any) => void\n): (() => void) | null {\n if (!client) return null;\n \n try {\n // Create a duplicate client for subscribing\n // (Redis clients in subscribe mode cannot be used for other commands)\n const subClient = client.duplicate();\n \n // Subscribe to conversation channels\n subClient.psubscribe('conv:*');\n \n // Handle incoming messages\n subClient.on('pmessage', (_pattern, channel, message) => {\n try {\n // Extract conversation ID from channel\n const conversationId = channel.slice(5); // Remove 'conv:' prefix\n \n // Parse message payload\n const payload = JSON.parse(message);\n \n // Call event handler\n onEvent(conversationId, payload);\n } catch (error) {\n console.error('Error processing Redis message:', error);\n }\n });\n \n // Return function to stop listening\n return () => {\n subClient.punsubscribe('conv:*');\n subClient.quit();\n };\n } catch (error) {\n console.error('Failed to start Redis listener:', error);\n return null;\n }\n}","import type { Server as HTTPServer, IncomingMessage } from 'http';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport type { RawData } from 'ws';\nimport url from 'url';\nimport { Transport } from './index';\n\nexport interface SocketConfig {\n path?: string;\n}\n\nexport interface SocketUser {\n id: string;\n model: string;\n}\n\nexport class SocketTransport {\n // Native WS server and state\n private wss: WebSocketServer;\n private transport: Transport;\n private sockets: Map<string, WebSocket> = new Map();\n private users: Map<string, SocketUser> = new Map();\n private joinedConversations: Map<string, Set<string>> = new Map(); // socketId -> convIds\n\n // Auth handler compatibility shim\n private authenticate?: (socket: any) => Promise<SocketUser | null>;\n\n // Socket.IO-like shim for getIO().sockets.sockets.get(id).emit('chat-event', payload)\n private ioShim = {\n sockets: {\n sockets: new Map<string, { emit: (event: string, payload: any) => void }>(),\n },\n to: (_room: string) => ({\n emit: (_event: string, _payload: any) => {\n // no-op room emitter in shim; we fanout via localSubs instead\n },\n }),\n } as any;\n\n constructor(server: HTTPServer, transport: Transport, config?: SocketConfig) {\n this.wss = new WebSocketServer({ noServer: true });\n this.transport = transport;\n\n const upgradePath = config?.path || '/api/socket';\n const srvAny = server as any;\n if (!srvAny.__wexaWsUpgradeAttached) {\n srvAny.on('upgrade', (request: IncomingMessage, socket: any, head: any) => {\n try {\n const { pathname } = url.parse(request.url || '');\n // Match path and allow query string; ignore other upgrades (HMR, etc.)\n if (!pathname || !pathname.startsWith(upgradePath)) return;\n\n // Only process real WebSocket upgrade requests\n const upgradeHeader = String((request.headers as any)['upgrade'] || '').toLowerCase();\n if (upgradeHeader !== 'websocket') return;\n\n // Ensure we don't crash on socket errors during upgrade\n socket.on?.('error', () => {\n try {\n socket.destroy();\n } catch {}\n });\n\n this.wss.handleUpgrade(request, socket, head, (ws: WebSocket) => {\n this.wss.emit('connection', ws, request);\n });\n } catch {\n try {\n socket?.destroy();\n } catch {}\n }\n });\n srvAny.__wexaWsUpgradeAttached = true;\n }\n\n // Keep ioShim map in sync with sockets map\n const syncShim = () => {\n const m = new Map<string, { emit: (event: string, payload: any) => void }>();\n for (const [id, ws] of this.sockets.entries()) {\n m.set(id, {\n emit: (event: string, payload: any) => {\n if (event !== 'chat-event') return;\n if (ws.readyState === WebSocket.OPEN) {\n try {\n ws.send(JSON.stringify(payload));\n } catch {\n // ignore\n }\n }\n },\n });\n }\n (this.ioShim.sockets as any).sockets = m;\n };\n\n // Heartbeat to keep connections healthy and detect dead peers\n const HEARTBEAT_MS = 30_000;\n const interval = setInterval(() => {\n this.wss.clients.forEach((client) => {\n const c = client as WebSocket & { isAlive?: boolean };\n if (c.isAlive === false) {\n try {\n c.terminate();\n } catch {}\n return;\n }\n c.isAlive = false;\n try {\n c.ping();\n } catch {}\n });\n }, HEARTBEAT_MS);\n this.wss.on('close', () => clearInterval(interval));\n\n // Listen for Redis events and broadcast to local subscribers\n this.transport.startRedisListener((conversationId: string, payload: any) => {\n this.transport.fanoutLocal(conversationId, payload, (toSocketId) => {\n const ws = this.sockets.get(toSocketId);\n if (ws && ws.readyState === WebSocket.OPEN) {\n try {\n ws.send(JSON.stringify(payload));\n } catch {}\n }\n });\n });\n\n // Handle new WS connections\n this.wss.on('connection', (ws: WebSocket, request: IncomingMessage) => {\n const hbWs = ws as WebSocket & { isAlive?: boolean };\n hbWs.isAlive = true;\n hbWs.on('pong', () => {\n hbWs.isAlive = true;\n });\n const parsed = url.parse(request.url || '', true);\n const q = parsed.query || {};\n const userId = typeof q.userId === 'string' ? q.userId : undefined;\n const userModel = typeof q.userModel === 'string' ? q.userModel : 'User';\n\n const socketId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n\n // Build a minimal Socket.IO-like object for authenticate()\n const shimSocket: any = {\n id: socketId,\n handshake: { auth: { userId, userModel } },\n data: {},\n };\n\n const doAccept = (user: SocketUser) => {\n this.sockets.set(socketId, ws);\n this.users.set(socketId, user);\n this.joinedConversations.set(socketId, new Set());\n syncShim();\n\n ws.on('message', (raw: RawData) => {\n try {\n const msg = JSON.parse(raw.toString());\n const type = msg?.type;\n if (type === 'join-conversation' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n this.transport.subscribeLocal(convId, socketId);\n this.joinedConversations.get(socketId)!.add(convId);\n // presence join to others\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'presence:join',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n } else if (type === 'leave-conversation' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n this.transport.unsubscribeLocal(convId, socketId);\n this.joinedConversations.get(socketId)!.delete(convId);\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'presence:leave',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n } else if (type === 'typing' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n const isTyping = !!msg.isTyping;\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'typing',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n state: isTyping ? 'start' : 'stop',\n at: new Date().toISOString(),\n };\n // Emit to others and publish to Redis\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n this.transport.publishToConversation(convId, payload);\n }\n } catch {\n // ignore\n }\n });\n\n ws.on('close', () => {\n const joined = this.joinedConversations.get(socketId);\n if (joined) {\n const u = this.users.get(socketId)!;\n for (const convId of joined) {\n // presence leave to others\n const payload = {\n type: 'presence:leave',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n }\n }\n this.transport.cleanupLocal(socketId);\n this.sockets.delete(socketId);\n this.users.delete(socketId);\n this.joinedConversations.delete(socketId);\n syncShim();\n });\n };\n\n const doReject = () => {\n try {\n ws.close(1008, 'Unauthorized');\n } catch {}\n };\n\n if (this.authenticate) {\n this.authenticate(shimSocket)\n .then((user) => {\n if (user) doAccept(user);\n else doReject();\n })\n .catch(() => doReject());\n } else {\n // If no auth handler, accept only if userId provided\n if (userId) doAccept({ id: userId, model: userModel });\n else doReject();\n }\n });\n }\n\n /**\n * Handle socket authentication\n */\n public handleAuth(authenticate: (socket: any) => Promise<SocketUser | null>) {\n this.authenticate = authenticate;\n }\n\n /**\n * Initialize socket event handlers\n */\n public initialize() {\n // No-op: handlers are set up in constructor for WS server\n }\n\n /**\n * Get Socket.IO server instance\n */\n public getIO(): any {\n return this.ioShim;\n }\n\n /**\n * Close Socket.IO server\n */\n public close(): Promise<void> {\n return new Promise((resolve) => {\n try {\n this.wss.close(() => resolve());\n } catch {\n resolve();\n }\n });\n }\n}\n","import * as localSubs from './localSubs';\nimport { createRedisClient, publishToConversation, startRedisListener } from './redis';\nimport { SocketTransport, SocketConfig } from './socket';\nimport { InitOptions } from '../types';\nimport type { Server as HTTPServer } from 'http';\n\n/**\n * Transport configuration type\n */\nexport interface TransportConfig {\n redis?: InitOptions['redis'];\n socket?: SocketConfig;\n}\n\n/**\n * Transport instance type\n */\nexport interface Transport {\n subscribeLocal: typeof localSubs.subscribeLocal;\n unsubscribeLocal: typeof localSubs.unsubscribeLocal;\n cleanupLocal: typeof localSubs.cleanupLocal;\n fanoutLocal: typeof localSubs.fanoutLocal;\n publishToConversation: (conversationId: string, payload: any) => Promise<number>;\n startRedisListener: (onEvent: (conversationId: string, payload: any) => void) => (() => void) | null;\n}\n\n/**\n * Create transport system with optional Redis and Socket.IO support\n */\nexport function createTransport(\n config?: TransportConfig,\n server?: HTTPServer\n): Transport & { socket?: SocketTransport } {\n // Initialize Redis client if configuration is provided\n const redisClient = config?.redis ? createRedisClient(config.redis) : null;\n \n // Create base transport\n const transport: Transport = {\n // Local subscription methods\n subscribeLocal: localSubs.subscribeLocal,\n unsubscribeLocal: localSubs.unsubscribeLocal,\n cleanupLocal: localSubs.cleanupLocal,\n fanoutLocal: localSubs.fanoutLocal,\n \n // Redis methods\n publishToConversation: (conversationId: string, payload: any) => \n publishToConversation(redisClient, conversationId, payload),\n \n startRedisListener: (onEvent: (conversationId: string, payload: any) => void) => \n startRedisListener(redisClient, onEvent),\n };\n\n // Initialize Socket.IO if server is provided\n if (server) {\n const socketTransport = new SocketTransport(server, transport, config?.socket);\n return {\n ...transport,\n socket: socketTransport\n };\n }\n\n return transport;\n}","import mongoose, { Model } from 'mongoose';\nimport { IConversation } from './Conversation.model';\nimport { IMessage } from './Message.model';\n\n/**\n * Ensure all indexes are created on models\n * @param models Object containing Mongoose models\n */\nexport async function ensureIndexes(models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n}): Promise<void> {\n // Create indexes\n await Promise.all([\n models.Message.ensureIndexes(),\n models.Conversation.ensureIndexes(),\n ]);\n}","/**\n * Redis configuration type\n */\nexport type RedisConfig = {\n url?: string;\n host?: string;\n port?: number;\n password?: string;\n db?: number;\n socketConnectTimeout?: number;\n keepAlive?: number;\n};\n\n/**\n * Environment configuration\n */\nexport interface EnvironmentConfig {\n /** MongoDB connection URI */\n mongoUri: string;\n /** Redis configuration (optional) */\n redis?: RedisConfig;\n}\n/**\n * Get Redis configuration from provided options\n */\nexport function getRedisConfig(config: { redis?: RedisConfig }): RedisConfig | null {\n if (!config.redis) {\n return null;\n }\n\n // Return the full configuration\n return {\n host: config.redis.host || undefined,\n port: config.redis.port || undefined,\n password: config.redis.password || undefined,\n db: config.redis.db || undefined,\n socketConnectTimeout: config.redis.socketConnectTimeout || undefined,\n keepAlive: config.redis.keepAlive || undefined\n };\n}\n","/**\n * Generates a random string ID with the specified length\n * @param length The length of the ID to generate (default: 24)\n * @returns A random string ID\n */\nexport function generateId(length = 24): string {\n const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n const charactersLength = characters.length;\n \n for (let i = 0; i < length; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n \n return result;\n}\n\n/**\n * Creates a conversation ID from two participant identifiers\n * @param a First participant (model:id)\n * @param b Second participant (model:id)\n * @returns A deterministic conversation ID\n */\nexport function createConversationId(\n a: { model: string; id: string },\n b: { model: string; id: string }\n): string {\n // Sort participants to ensure the same ID regardless of order\n const participants = [\n `${a.model}:${a.id}`,\n `${b.model}:${b.id}`,\n ].sort();\n \n return `conv_${participants.join('_')}`;\n}\n\n/**\n * Creates a thread ID\n * @returns A unique thread ID\n */\nexport function createThreadId(): string {\n return `thread_${generateId(16)}`;\n}\n\n/**\n * Creates a message ID\n * @returns A unique message ID\n */\nexport function createMessageId(): string {\n return `msg_${generateId(16)}`;\n}\n\n\n\n\n","import { InitOptions, SendMessageArgs, CreateConversationArgs, MarkReadArgs } from '../types';\n\n/**\n * Validates initialization options\n * @param options Options to validate\n * @returns Validation error message or null if valid\n */\nexport function validateInitOptions(options: InitOptions): string | null {\n if (!options.participantModels || !Array.isArray(options.participantModels) || options.participantModels.length === 0) {\n return 'participantModels must be a non-empty array of strings';\n }\n\n if (!options.memberRoles || !Array.isArray(options.memberRoles) || options.memberRoles.length === 0) {\n return 'memberRoles must be a non-empty array of strings';\n }\n\n // Validate Redis options if provided\n if (options.redis) {\n if (options.redis.url) {\n if (typeof options.redis.url !== 'string') {\n return 'redis.url must be a string';\n }\n } else if (!options.redis.host) {\n return 'Either redis.url or redis.host must be provided';\n }\n }\n\n return null;\n}\n\n/**\n * Validates message sending arguments\n * @param args Message sending arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateSendMessageArgs(args: SendMessageArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.conversationId) {\n return 'conversationId is required';\n }\n\n if (!args.senderModel) {\n return 'senderModel is required';\n }\n\n if (!args.senderId) {\n return 'senderId is required';\n }\n\n if (!args.text || args.text.trim() === '') {\n return 'text is required and cannot be empty';\n }\n\n // If kind is provided, validate it's a valid value\n if (args.kind && !['text', 'system'].includes(args.kind)) {\n return 'kind must be either \"text\" or \"system\"';\n }\n\n // If this is a reply, ensure all thread fields are present\n if (args.parentMessageId && !args.rootThreadId) {\n return 'rootThreadId is required when parentMessageId is provided';\n }\n\n return null;\n}\n\n/**\n * Validates conversation creation arguments\n * @param args Conversation creation arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateCreateConversationArgs(args: CreateConversationArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.a || !args.a.model || !args.a.id) {\n return 'a.model and a.id are required';\n }\n\n if (!args.b || !args.b.model || !args.b.id) {\n return 'b.model and b.id are required';\n }\n\n // Prevent creating a conversation between the same participant\n if (args.a.model === args.b.model && args.a.id === args.b.id) {\n return 'Cannot create a conversation between the same participant';\n }\n\n return null;\n}\n\n/**\n * Validates mark read arguments\n * @param args Mark read arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateMarkReadArgs(args: MarkReadArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.conversationId) {\n return 'conversationId is required';\n }\n\n if (!args.participantModel) {\n return 'participantModel is required';\n }\n\n if (!args.participantId) {\n return 'participantId is required';\n }\n\n if (!args.messageId) {\n return 'messageId is required';\n }\n\n return null;\n}\n\n/**\n * Validates pagination parameters\n * @param limit Pagination limit\n * @param cursor Pagination cursor\n * @returns Validated limit and cursor\n */\nexport function validatePagination(\n limit?: number,\n cursor?: string\n): { limit: number; cursor: string | undefined } {\n // Default limit to 20, max to 100\n let validLimit = limit ? Math.min(Math.max(1, limit), 100) : 20;\n \n // If cursor is provided but empty string, set to undefined\n let validCursor = cursor && cursor.trim() !== '' ? cursor : undefined;\n \n return { limit: validLimit, cursor: validCursor };\n}\n\n\n\n\n","import mongoose from 'mongoose';\nimport type { Server as HTTPServer } from 'http';\nimport { createModels } from './models/connection';\nimport { createConversationsService, ConversationsService } from './services/conversations.service';\nimport { createMessagesService, MessagesService } from './services/messages.service';\nimport { createTransport, Transport } from './transport';\nimport { InitOptions } from './types';\nimport { ensureIndexes } from './models/indexes';\nimport { getRedisConfig } from './config/env';\nimport { SocketTransport } from './transport/socket';\nimport type { IConversation, IMessage } from './models';\nimport { setRuntimeConfig } from './config/runtime';\n\n/**\n * Chat services container\n */\nexport interface ChatServices {\n models: {\n Conversation: mongoose.Model<IConversation>;\n Message: mongoose.Model<IMessage>;\n };\n services: {\n conversations: ConversationsService;\n messages: MessagesService;\n };\n transport: Transport & { socket?: SocketTransport };\n}\n\n/**\n * Initialize the chat system\n * @param mongooseInstance Mongoose instance\n * @param options Initialization options\n * @param server Optional HTTP server for Socket.IO integration\n * @returns Chat services\n */\nexport async function initChat(\n mongooseInstance: typeof mongoose,\n options: InitOptions,\n server?: HTTPServer,\n): Promise<ChatServices> {\n // Persist runtime configuration for global access\n setRuntimeConfig({\n dataServiceEndpoint: options.dataServiceEndpoint,\n secretId: options.secretId,\n });\n\n const models = createModels(mongooseInstance, options);\n\n // Ensure indexes are created\n await ensureIndexes(models);\n\n // Create transport system with optional Socket.IO support\n const transport = createTransport(\n {\n redis: getRedisConfig(options) || undefined,\n socket: options.socket || undefined,\n },\n server,\n );\n\n // Initialize Socket.IO if server was provided\n if (server && transport.socket) {\n // Set up authentication handler\n transport.socket.handleAuth(async (socket) => {\n // Get user info from socket handshake auth\n const userId = socket.handshake.auth.userId;\n const userModel = socket.handshake.auth.userModel || 'User';\n\n if (!userId || !options.participantModels.includes(userModel)) {\n return null;\n }\n\n return { id: userId, model: userModel };\n });\n\n // Initialize socket event handlers\n transport.socket.initialize();\n }\n\n // Create services with hooks\n const services = {\n conversations: createConversationsService(models),\n messages: createMessagesService(models, {\n onMessageCreated: (message) => {\n const payload = { type: 'message:created', message };\n\n // Fan out to local subscribers\n transport.fanoutLocal(message.conversationId.toString(), payload, (socketId, event) => {\n if (transport.socket) {\n const socket = transport.socket.getIO().sockets.sockets.get(socketId);\n if (socket) {\n socket.emit('chat-event', event);\n }\n }\n });\n\n // Publish to Redis for cross-instance communication\n transport.publishToConversation(message.conversationId.toString(), payload);\n },\n\n onMessageRead: (args) => {\n const payload = {\n type: 'conversation:read',\n conversationId: args.conversationId,\n messageId: args.messageId,\n participantModel: args.participantModel,\n participantId: args.participantId,\n at: args.at.toISOString(),\n };\n\n // Fan out to local subscribers\n transport.fanoutLocal(args.conversationId, payload, (socketId, event) => {\n if (transport.socket) {\n const socket = transport.socket.getIO().sockets.sockets.get(socketId);\n if (socket) {\n socket.emit('chat-event', event);\n }\n }\n });\n\n // Publish to Redis for cross-instance communication\n transport.publishToConversation(args.conversationId, payload);\n },\n }),\n };\n\n return { models, services, transport };\n}\n\n// Re-export types\nexport * from './types';\nexport * from './utils';\nexport * from './models';\nexport * from './services';\nexport * from './transport';\nexport * from './config/env';\nexport * from './config/runtime';\n\n// Export Conversation and Message model types for direct access\nexport type { ConversationModel, MessageModel } from './models';\n\n// Export MessageWithSender interface\nexport type { MessageWithSender } from './services/messages.service';\n"]}
1
+ {"version":3,"sources":["../src/models/Conversation.model.ts","../src/models/Message.model.ts","../src/models/connection.ts","../src/utils/pagination.ts","../src/services/search/search.conversations.ts","../src/services/conversations.service.ts","../src/services/search/search.messages.ts","../src/config/paths.ts","../src/config/runtime.ts","../src/config/axios.ts","../src/services/messages.service.ts","../src/transport/localSubs.ts","../src/transport/redis.ts","../src/transport/socket.ts","../src/transport/index.ts","../src/models/indexes.ts","../src/config/env.ts","../src/utils/ids.ts","../src/utils/validators.ts","../src/index.ts"],"names":["axios","Redis","WebSocketServer","url","ws","WebSocket"],"mappings":"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","file":"index.js","sourcesContent":["import type { Schema as MongooseSchema, Document, Model, Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { modelRegistry } from './connection';\n\nexport interface IConversation extends Document {\n organizationId: string;\n participants: Array<{\n entityModel: string;\n entityId: string;\n role: string;\n }>;\n lastMessageId?: string;\n lastMessageAt?: Date;\n lastMessagePreview?: string;\n lastMessageSenderId?: string;\n lastMessageSenderModel?: string;\n lastLinkedInId?: string;\n lastWhatsAppId?: string;\n linkedinChatId?: string;\n whatsappChatId?: string;\n metadata?: Record<string, any>;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * Create (or retrieve) Conversation model safely\n */\nexport function createConversationModel(\n options: InitOptions,\n conn: Connection,\n): Model<IConversation> {\n // Generate a unique key for the model registry\n const connectionId = conn.id || conn.name || 'default';\n const registryKey = `${connectionId}:Conversation`;\n\n // Return from registry if exists\n if (modelRegistry.has(registryKey)) {\n return modelRegistry.get(registryKey) as Model<IConversation>;\n }\n\n // Check if model already exists on the connection\n const name = 'Conversation';\n if (conn.models[name]) {\n const existingModel = conn.models[name] as Model<IConversation>;\n modelRegistry.set(registryKey, existingModel);\n return existingModel;\n }\n\n // Participant schema (use the Schema from the same mongoose instance as the connection)\n const Schema: typeof MongooseSchema = (conn as any).base.Schema;\n const ParticipantSchema = new Schema(\n {\n entityModel: {\n type: String,\n enum: options.participantModels,\n required: true,\n },\n entityId: {\n type: String,\n required: true,\n },\n role: {\n type: String,\n enum: options.memberRoles,\n required: true,\n },\n },\n { _id: false },\n );\n\n // Conversation schema\n const ConversationSchema = new Schema<IConversation>(\n {\n organizationId: {\n type: String,\n required: true,\n },\n participants: {\n type: [ParticipantSchema],\n required: true,\n validate: {\n validator: function (participants: any[]) {\n return participants.length === 2;\n },\n message: 'Conversations must have exactly 2 participants',\n },\n },\n lastMessageId: {\n type: String,\n ref: 'Message',\n },\n lastMessageAt: {\n type: Date,\n },\n lastMessagePreview: String,\n lastMessageSenderId: String,\n lastMessageSenderModel: String,\n lastLinkedInId: String,\n lastWhatsAppId: String,\n linkedinChatId: String,\n whatsappChatId: String,\n metadata: (Schema as any).Types.Mixed,\n },\n { timestamps: true },\n );\n\n // Create the model\n const model = conn.model<IConversation>(name, ConversationSchema);\n\n // Register the model\n modelRegistry.set(registryKey, model);\n\n return model;\n}\n","import type { Schema as MongooseSchema, Document, Model, Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { modelRegistry } from './connection';\n\nexport const sourceType = {\n LINKEDIN: 'linkedin',\n WHATSAPP: 'whatsapp',\n EMAIL: 'email',\n CORE: 'core',\n} as const;\n\nexport type SourceType = (typeof sourceType)[keyof typeof sourceType];\n\nexport interface IMessage extends Document {\n organizationId: string;\n conversationId: string;\n senderModel: string;\n senderId: string;\n text: string;\n kind: 'text' | 'system';\n source: SourceType[];\n failed_source?: Array<{ source: string; message: string }>;\n parentMessageId?: string;\n rootThreadId?: string;\n editedAt?: Date;\n deletedAt?: Date;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * Create (or retrieve) Message model safely\n */\nexport function createMessageModel(options: InitOptions, conn: Connection): Model<IMessage> {\n // Generate a unique key for the model registry\n const connectionId = conn.id || conn.name || 'default';\n const registryKey = `${connectionId}:Message`;\n\n // Return from registry if exists\n if (modelRegistry.has(registryKey)) {\n return modelRegistry.get(registryKey) as Model<IMessage>;\n }\n\n // Check if model already exists on the connection\n const name = 'Message';\n if (conn.models[name]) {\n const existingModel = conn.models[name] as Model<IMessage>;\n modelRegistry.set(registryKey, existingModel);\n return existingModel;\n }\n\n // Build Schema from the same mongoose instance as the connection\n const Schema: typeof MongooseSchema = (conn as any).base.Schema;\n const MessageSchema = new Schema<IMessage>(\n {\n organizationId: {\n type: String,\n required: true,\n index: true,\n },\n conversationId: {\n type: String,\n required: true,\n index: true,\n },\n senderModel: {\n type: String,\n enum: options.participantModels,\n required: true,\n },\n senderId: {\n type: String,\n required: true,\n index: true,\n },\n kind: {\n type: String,\n enum: ['text', 'system'],\n default: 'text',\n index: true,\n },\n source: {\n type: [String],\n enum: Object.values(sourceType),\n required: true,\n },\n text: {\n type: String,\n trim: true,\n },\n parentMessageId: {\n type: String,\n ref: 'Message',\n },\n rootThreadId: {\n type: String,\n ref: 'Message',\n },\n editedAt: {\n type: Date,\n },\n deletedAt: {\n type: Date,\n },\n },\n { timestamps: true },\n );\n\n // Indexes\n MessageSchema.index({\n organizationId: 1,\n conversationId: 1,\n createdAt: -1,\n });\n\n // Create text search index if enabled\n if (options.enableTextSearch) {\n MessageSchema.index(\n { text: 'text' },\n {\n name: 'text_search',\n weights: { text: 10 },\n },\n );\n }\n\n // Create the model\n const model = conn.model<IMessage>(name, MessageSchema);\n\n // Register the model\n modelRegistry.set(registryKey, model);\n\n return model;\n}\n","import mongoose, { Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { createConversationModel } from './Conversation.model';\nimport { createMessageModel } from './Message.model';\n\n// Global model registry to prevent duplicate compilations\nexport const modelRegistry = new Map<string, mongoose.Model<any>>();\n\n/**\n * Create Mongoose models with applied configuration\n * @param mongooseInstance Mongoose instance\n * @param options Initialization options\n * @returns Object containing Conversation and Message models\n */\nexport function createModels(mongooseInstance: typeof mongoose, options: InitOptions) {\n // Get the connection instance\n const conn: Connection = mongooseInstance.connection;\n\n // Generate a unique connection identifier for this connection\n const connectionId = conn.id || conn.name || 'default';\n \n // Check if models are already registered for this connection\n const registryKey = `${connectionId}:Conversation`;\n const messageRegistryKey = `${connectionId}:Message`;\n \n // Create or reuse models\n const Conversation = modelRegistry.get(registryKey) || createConversationModel(options, conn);\n const Message = modelRegistry.get(messageRegistryKey) || createMessageModel(options, conn);\n \n // Register models if they're new\n if (!modelRegistry.has(registryKey)) {\n modelRegistry.set(registryKey, Conversation);\n }\n \n if (!modelRegistry.has(messageRegistryKey)) {\n modelRegistry.set(messageRegistryKey, Message);\n }\n \n return {\n Conversation,\n Message\n };\n}\n\n/**\n * Connection state enum\n */\nenum ConnectionState {\n Disconnected = 0,\n Connected = 1,\n Connecting = 2,\n Disconnecting = 3,\n}","/**\n * Pagination result interface\n */\nexport interface PaginatedResult<T> {\n items: T[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n/**\n * Creates a pagination cursor from a timestamp and ID\n * @param timestamp Timestamp to encode in the cursor\n * @param id ID to encode in the cursor\n * @returns An encoded cursor string\n */\nexport function createCursor(timestamp: number, id: string): string {\n const cursorData = `${timestamp}:${id}`;\n return Buffer.from(cursorData).toString('base64');\n}\n\n/**\n * Parses a pagination cursor into its timestamp and ID components\n * @param cursor The cursor string to parse\n * @returns An object containing the timestamp and ID, or null if invalid\n */\nexport function parseCursor(cursor: string): { timestamp: number; id: string } | null {\n try {\n const decoded = Buffer.from(cursor, 'base64').toString('utf-8');\n const [timestampStr, id] = decoded.split(':');\n \n const timestamp = parseInt(timestampStr, 10);\n \n if (isNaN(timestamp) || !id) {\n return null;\n }\n \n return { timestamp, id };\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Creates a paginated response\n * @param items The items for the current page\n * @param limit The requested page size\n * @param getNextCursor Function to get the next cursor from the last item\n * @returns A paginated result object\n */\nexport function createPaginatedResponse<T>(\n items: T[],\n limit: number,\n getNextCursor: (lastItem: T) => string\n): PaginatedResult<T> {\n const hasMore = items.length > limit;\n \n // If we have more items than the limit, remove the extra item\n // that we used to determine if there are more pages\n const paginatedItems = hasMore ? items.slice(0, limit) : items;\n \n // Get the next cursor from the last item if we have more items\n const nextCursor = hasMore && paginatedItems.length > 0\n ? getNextCursor(paginatedItems[paginatedItems.length - 1])\n : null;\n \n return {\n items: paginatedItems,\n nextCursor,\n hasMore,\n };\n}\n\n\n\n\n","import { Model } from 'mongoose';\nimport { IConversation } from '../../models/Conversation.model';\nimport { SearchConversationsArgs } from '../../types';\nimport { createCursor, parseCursor, PaginatedResult } from '../../utils/pagination';\n\n/**\n * Search conversations with pagination\n */\nexport async function searchConversations(\n model: Model<IConversation>,\n params: SearchConversationsArgs\n): Promise<PaginatedResult<IConversation>> {\n const { \n organizationId, \n participantModel, \n participantId,\n limit = 20, \n cursor \n } = params;\n \n // Base query with required organizationId\n const baseQuery: Record<string, any> = { \n organizationId \n };\n \n // Add participant filter if provided\n if (participantModel && participantId) {\n baseQuery['participants'] = {\n $elemMatch: {\n entityModel: participantModel,\n entityId: participantId\n }\n };\n }\n \n // Handle cursor-based pagination\n if (cursor) {\n const parsedCursor = parseCursor(cursor);\n \n if (parsedCursor) {\n const { timestamp, id } = parsedCursor;\n const cursorDate = new Date(timestamp);\n \n baseQuery.$or = [\n { lastMessageAt: { $lt: cursorDate } },\n { lastMessageAt: cursorDate, _id: { $lt: id } }\n ];\n }\n }\n \n // Find conversations and sort by lastMessageAt\n const conversations = await model.find(baseQuery)\n .sort({ lastMessageAt: -1 })\n .limit(limit + 1)\n .exec();\n \n // Check if we have more results\n const hasMore = conversations.length > limit;\n const items = hasMore ? conversations.slice(0, limit) : conversations;\n \n // Create next cursor if we have more results\n let nextCursor: string | null = null;\n \n if (hasMore && items.length > 0) {\n const lastItem = items[items.length - 1];\n // Use lastMessageAt if available, otherwise use createdAt\n const timestamp = lastItem.lastMessageAt ? \n lastItem.lastMessageAt.getTime() : \n lastItem.createdAt.getTime();\n \n nextCursor = createCursor(timestamp, lastItem._id.toString());\n }\n \n return {\n items,\n nextCursor,\n hasMore\n };\n}\n\n/**\n * Find a conversation between two specific participants\n */\nexport async function searchByParticipantPair(\n model: Model<IConversation>,\n params: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }\n): Promise<IConversation | null> {\n const { organizationId, a, b } = params;\n \n const conversation = await model.findOne({\n organizationId,\n $and: [\n {\n participants: {\n $elemMatch: {\n entityModel: a.model,\n entityId: a.id\n }\n }\n },\n {\n participants: {\n $elemMatch: {\n entityModel: b.model,\n entityId: b.id\n }\n }\n },\n {\n $expr: {\n $eq: [{ $size: \"$participants\" }, 2]\n }\n }\n ]\n });\n \n return conversation;\n}","import { Model } from 'mongoose';\nimport { IConversation } from '../models/Conversation.model';\nimport { IMessage } from '../models/Message.model';\nimport { CreateConversationArgs, SearchConversationsArgs } from '../types';\nimport { searchConversations, searchByParticipantPair } from './search/search.conversations';\nimport { PaginatedResult } from '../utils/pagination';\n\n/**\n * Service for managing conversations\n */\nexport interface ConversationsService {\n createOrFindConversation(args: CreateConversationArgs): Promise<IConversation>;\n getConversation(organizationId: string, conversationId: string): Promise<IConversation | null>;\n searchConversations(args: SearchConversationsArgs): Promise<PaginatedResult<IConversation>>;\n searchByParticipantPair(args: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }): Promise<IConversation | null>;\n}\n\n/**\n * Create conversations service\n * @param models MongoDB models\n * @returns Conversations service instance\n */\nexport function createConversationsService(models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n}): ConversationsService {\n const { Conversation } = models;\n\n return {\n /**\n * Create a new conversation or find existing one between participants\n */\n async createOrFindConversation(args: CreateConversationArgs): Promise<IConversation> {\n console.log('Creating or finding conversation for users:', {\n args,\n });\n const { organizationId, a, b } = args;\n console.log('Creating or finding conversation for users:', {\n organizationId,\n a,\n b,\n });\n\n try {\n console.log('asdfa');\n // Check if conversation already exists between these participants\n const existingConversation = await searchByParticipantPair(Conversation, {\n organizationId,\n a,\n b,\n });\n\n console.log('Existing conversation:', existingConversation);\n if (existingConversation) {\n return existingConversation;\n }\n\n // Create new conversation\n const newConversation = new Conversation({\n organizationId,\n participants: [\n {\n entityModel: a.model,\n entityId: a.id,\n role: 'member', // Default role\n },\n {\n entityModel: b.model,\n entityId: b.id,\n role: 'member', // Default role\n },\n ],\n lastMessageAt: new Date(), // Set initial lastMessageAt\n });\n\n console.log('New conversation:', newConversation);\n\n await newConversation.save();\n console.log('Saved conversation:', newConversation);\n return newConversation;\n } catch (error) {\n console.error('Error in createOrFindConversation:', error);\n throw error;\n }\n },\n\n /**\n * Get a conversation by ID\n */\n async getConversation(\n organizationId: string,\n conversationId: string,\n ): Promise<IConversation | null> {\n try {\n return await Conversation.findOne({\n organizationId,\n _id: conversationId,\n });\n } catch (error) {\n console.error('Error in getConversation:', error);\n throw error;\n }\n },\n\n /**\n * Search conversations with pagination\n */\n async searchConversations(\n args: SearchConversationsArgs,\n ): Promise<PaginatedResult<IConversation>> {\n try {\n return await searchConversations(Conversation, args);\n } catch (error) {\n console.error('Error in searchConversations:', error);\n throw error;\n }\n },\n\n /**\n * Find a conversation between two specific participants\n */\n async searchByParticipantPair(args: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }): Promise<IConversation | null> {\n try {\n return await searchByParticipantPair(Conversation, args);\n } catch (error) {\n console.error('Error in searchByParticipantPair:', error);\n throw error;\n }\n },\n };\n}\n","import { Model } from 'mongoose';\nimport { IMessage } from '../../models/Message.model';\nimport { SearchMessagesArgs } from '../../types';\nimport { createCursor, parseCursor, PaginatedResult } from '../../utils/pagination';\n\n/**\n * Search messages based on various criteria\n * @param model Message model\n * @param params Search parameters\n * @returns Paginated messages with optional text search results\n */\nexport async function searchMessages(\n model: Model<IMessage>,\n params: SearchMessagesArgs\n): Promise<PaginatedResult<IMessage>> {\n const { \n organizationId,\n query,\n conversationId,\n senderModel,\n senderId,\n kind,\n dateFrom,\n dateTo,\n threadRootId,\n limit = 20,\n cursor\n } = params;\n \n // Base query with required organizationId\n const baseQuery: Record<string, any> = { \n organizationId\n };\n\n // Add optional filters if provided\n if (conversationId) {\n baseQuery.conversationId = conversationId;\n }\n \n if (senderModel && senderId) {\n baseQuery.senderModel = senderModel;\n baseQuery.senderId = senderId;\n } else if (senderModel) {\n baseQuery.senderModel = senderModel;\n }\n \n if (kind) {\n baseQuery.kind = kind;\n }\n \n // Date range filters\n if (dateFrom || dateTo) {\n baseQuery.createdAt = {};\n \n if (dateFrom) {\n baseQuery.createdAt.$gte = new Date(dateFrom);\n }\n \n if (dateTo) {\n baseQuery.createdAt.$lte = new Date(dateTo);\n }\n }\n \n // Thread filter\n if (threadRootId) {\n baseQuery.rootThreadId = threadRootId;\n }\n \n // Handle cursor-based pagination\n if (cursor) {\n const parsedCursor = parseCursor(cursor);\n \n if (parsedCursor) {\n const { timestamp, id } = parsedCursor;\n \n baseQuery.$or = [\n { createdAt: { $lt: new Date(timestamp) } },\n { createdAt: new Date(timestamp), _id: { $lt: id } }\n ];\n }\n }\n \n // Determine sort order and query approach\n let sort: Record<string, number> = { createdAt: -1 };\n let pipeline: any[] = [];\n \n // Use text search if query provided\n if (query && query.trim()) {\n // Set up text search with score and appropriate sort\n pipeline = [\n { $match: { $text: { $search: query }, ...baseQuery } },\n { $addFields: { score: { $meta: 'textScore' } } },\n { $sort: { score: { $meta: 'textScore' }, createdAt: -1 } },\n { $limit: limit + 1 } // Get one extra for pagination\n ];\n } else {\n // Use standard query\n pipeline = [\n { $match: baseQuery },\n { $sort: sort },\n { $limit: limit + 1 } // Get one extra for pagination\n ];\n }\n \n // Execute query\n const items = await model.aggregate(pipeline);\n \n // Check if we have more results\n const hasMore = items.length > limit;\n const limitedItems = hasMore ? items.slice(0, limit) : items;\n \n // Create next cursor if we have more results\n const nextCursor = hasMore && limitedItems.length > 0\n ? createCursor(\n new Date(limitedItems[limitedItems.length - 1].createdAt).getTime(),\n limitedItems[limitedItems.length - 1]._id.toString()\n )\n : null;\n \n return {\n items: limitedItems,\n nextCursor,\n hasMore\n };\n}\n","// Centralized path builders for external data service endpoints\n\nexport const paths = {\n linkedin: {\n startChat: (connectorId: string) => `/actions/linkedin/start_chat/${connectorId}`,\n },\n whatsapp: {\n startChat: (connectorId: string) => `/actions/whatsapp/start_chat/${connectorId}`,\n },\n // Add more services here as needed\n};\n","export type RuntimeConfig = {\n dataServiceEndpoint?: string;\n secretId?: string;\n};\n\nlet runtimeConfig: RuntimeConfig = {};\n\nexport function setRuntimeConfig(cfg: RuntimeConfig) {\n runtimeConfig = { ...runtimeConfig, ...cfg };\n}\n\nexport function getRuntimeConfig(): RuntimeConfig {\n return runtimeConfig;\n}\n","import axios, { AxiosInstance } from 'axios';\nimport { getRuntimeConfig } from './runtime';\n\nlet cachedInstance: AxiosInstance | null = null;\nlet cachedBaseUrl: string | null = null;\nlet cachedSecret: string | null = null;\n\nexport function getAxios(): AxiosInstance {\n const { dataServiceEndpoint, secretId } = getRuntimeConfig();\n if (!dataServiceEndpoint) {\n throw new Error('Data service endpoint not configured');\n }\n\n const baseURL = dataServiceEndpoint.replace(/\\/$/, '');\n\n // Recreate if config changed\n if (!cachedInstance || cachedBaseUrl !== baseURL || cachedSecret !== (secretId || null)) {\n cachedBaseUrl = baseURL;\n cachedSecret = secretId || null;\n\n console.log('Creating axios instance', { baseURL, secretId });\n\n cachedInstance = axios.create({\n baseURL,\n headers: {\n 'Content-Type': 'application/json',\n ...(secretId ? { 'x-api-key': secretId } : {}),\n },\n });\n }\n\n return cachedInstance;\n}\n","import { Model } from 'mongoose';\nimport { IConversation } from '../models/Conversation.model';\nimport { IMessage } from '../models/Message.model';\nimport type { SourceType } from '../models';\nimport { SendMessageArgs, ListMessagesArgs, MarkReadArgs } from '../types';\nimport { searchMessages } from './search/search.messages';\nimport {\n createPaginatedResponse,\n PaginatedResult,\n createCursor,\n parseCursor,\n} from '../utils/pagination';\nimport { paths } from '../config/paths';\nimport { getAxios } from '../config/axios';\n\n/**\n * Message service hooks interface\n */\nexport interface MessageServiceHooks {\n onMessageCreated?: (message: IMessage) => void;\n onMessageRead?: (args: MarkReadArgs & { at: Date }) => void;\n}\n\n/**\n * Message with populated sender information\n */\nexport interface MessageWithSender extends IMessage {\n sender?: Record<string, any>;\n}\n\n/**\n * Service for managing messages\n */\nexport interface MessagesService {\n sendMessage(args: SendMessageArgs): Promise<IMessage>;\n listMessages(args: ListMessagesArgs): Promise<PaginatedResult<IMessage>>;\n listMessagesWithSenders(\n args: ListMessagesArgs & { populateSenders: true },\n ): Promise<PaginatedResult<MessageWithSender>>;\n markRead(args: MarkReadArgs): Promise<void>;\n}\n\n/**\n * Create messages service\n * @param models MongoDB models\n * @param hooks Service hooks\n * @returns Messages service instance\n */\nexport function createMessagesService(\n models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n },\n hooks: MessageServiceHooks = {},\n): MessagesService {\n const { Message, Conversation } = models;\n const { onMessageCreated, onMessageRead } = hooks;\n\n return {\n /**\n * Send a new message\n * @param args Message sending arguments\n * @returns The created message\n */\n async sendMessage(args: SendMessageArgs): Promise<IMessage> {\n const {\n organizationId,\n conversationId,\n senderModel,\n senderId,\n text,\n kind = 'text',\n source,\n parentMessageId,\n rootThreadId,\n connectorIds,\n } = args;\n\n const success_source: SourceType[] = ['core'];\n const failed_source: Array<{ source: string; message: string }> = [];\n\n // Build external calls and run them concurrently\n const tasks: Array<{ name: SourceType; run: () => Promise<any> }> = [];\n\n let lastLinkedInId: string | undefined;\n let lastWhatsAppId: string | undefined;\n\n if (Array.isArray(source) && source.includes('linkedin')) {\n const LinkedinConnector = connectorIds && (connectorIds as any).linkedin;\n lastLinkedInId = LinkedinConnector?.connectorId;\n if (LinkedinConnector) {\n tasks.push({\n name: 'linkedin' as SourceType,\n run: async () => {\n const path = paths.linkedin.startChat(String(LinkedinConnector.connectorId));\n await getAxios().post(path, {\n linkedin_url: LinkedinConnector.contactId,\n text,\n });\n },\n });\n } else {\n failed_source.push({ source: 'linkedin', message: 'Missing connector configuration' });\n }\n }\n\n if (Array.isArray(source) && source.includes('whatsapp')) {\n const whatsappConnector = connectorIds && (connectorIds as any).whatsapp;\n lastWhatsAppId = whatsappConnector?.connectorId;\n\n if (whatsappConnector) {\n tasks.push({\n name: 'whatsapp' as SourceType,\n run: async () => {\n const path = paths.whatsapp.startChat(String(whatsappConnector.connectorId));\n const sanitize = (v: string) => String(v).replace(/\\s+/g, '').replace(/^\\+/, '');\n const raw = whatsappConnector.contactId;\n const body = {\n phone_numbers: sanitize(raw),\n text,\n } as any;\n await getAxios().post(path, body);\n },\n });\n } else {\n failed_source.push({ source: 'whatsapp', message: 'Missing connector configuration' });\n }\n }\n\n if (tasks.length > 0) {\n const results = await Promise.allSettled(tasks.map((t) => t.run()));\n results.forEach((res, idx) => {\n const name = tasks[idx].name;\n if (res.status === 'fulfilled') {\n success_source.push(name);\n } else {\n const err = success_source;\n res.reason.response.data.detail || res.reason.response.data || 'Unknown error';\n failed_source.push({\n source: name,\n message: typeof err === 'string' ? err : JSON.stringify(err),\n });\n }\n });\n console.log('results', results);\n }\n\n console.log('success_source', success_source);\n const message = new Message({\n organizationId,\n conversationId,\n senderModel,\n senderId,\n text,\n kind,\n source: success_source,\n parentMessageId,\n rootThreadId: rootThreadId || parentMessageId,\n });\n\n await message.save();\n\n const conversationUpdate: Record<string, any> = {\n lastMessageAt: message.createdAt,\n lastMessagePreview: text.substring(0, 100),\n lastMessageSenderId: senderId,\n lastMessageSenderModel: senderModel,\n };\n\n if (lastLinkedInId) conversationUpdate.lastLinkedInId = lastLinkedInId;\n if (lastWhatsAppId) conversationUpdate.lastWhatsAppId = lastWhatsAppId;\n\n await Conversation.findByIdAndUpdate(conversationId, {\n $set: conversationUpdate,\n });\n if (onMessageCreated) {\n onMessageCreated(message);\n }\n\n (message as any).failed_source = failed_source;\n\n return message;\n },\n\n /**\n * List messages for a conversation with pagination\n * @param args Message listing arguments\n * @returns Paginated list of messages\n */\n async listMessages(args: ListMessagesArgs): Promise<PaginatedResult<IMessage>> {\n const {\n organizationId,\n conversationId,\n limit = 20,\n cursor,\n populateSenders,\n populateOptions,\n } = args;\n\n // If population is requested, delegate to the specialized method\n if (populateSenders) {\n return this.listMessagesWithSenders({\n ...args,\n populateSenders: true,\n });\n }\n\n return searchMessages(Message, {\n organizationId,\n conversationId,\n limit,\n cursor,\n });\n },\n\n /**\n * List messages with populated sender information optimized for infinite scroll\n * @param args Message listing arguments with populate options\n * @returns Paginated list of messages with sender details\n */\n async listMessagesWithSenders(\n args: ListMessagesArgs & { populateSenders: true },\n ): Promise<PaginatedResult<MessageWithSender>> {\n const { organizationId, conversationId, limit = 20, cursor, populateOptions = {} } = args;\n const { fields = '_id name', modelMapping = {} } = populateOptions;\n\n // Create base query for message filtering\n const baseQuery: Record<string, any> = {\n organizationId,\n conversationId,\n };\n\n // Handle cursor-based pagination for infinite scroll\n if (cursor) {\n try {\n const decodedCursor = parseCursor(cursor);\n if (decodedCursor) {\n const { timestamp, id } = decodedCursor;\n\n // Query for messages older than the cursor position\n // This works well for chat interfaces where newer messages are at the bottom\n baseQuery.$or = [\n { createdAt: { $lt: new Date(timestamp) } },\n { createdAt: new Date(timestamp), _id: { $lt: id } },\n ];\n }\n } catch (error) {\n console.error('Failed to parse cursor:', error);\n }\n }\n\n // Get an extra item to determine if there are more messages to load\n const fetchLimit = limit + 1;\n\n // Directly query with sort to efficiently implement infinite scroll\n const messages = await Message.find(baseQuery)\n .sort({ createdAt: -1 })\n .limit(fetchLimit)\n .lean();\n\n // No messages found\n if (messages.length === 0) {\n return {\n items: [],\n hasMore: false,\n nextCursor: null,\n };\n }\n\n // Check if we have more messages available\n const hasMore = messages.length > limit;\n const items = hasMore ? messages.slice(0, limit) : messages;\n\n // Create the next cursor for infinite scroll\n const lastItem = items[items.length - 1];\n const nextCursor = hasMore\n ? createCursor(new Date(lastItem.createdAt).getTime(), lastItem._id.toString())\n : null;\n\n // Extract unique sender IDs by model type\n const sendersByModel: Record<string, Set<string>> = {};\n\n items.forEach((message) => {\n const { senderModel, senderId } = message;\n\n if (!sendersByModel[senderModel]) {\n sendersByModel[senderModel] = new Set<string>();\n }\n\n sendersByModel[senderModel].add(senderId);\n });\n\n // Load all senders in parallel by model type (1 query per model type)\n const mongoose = Message.base;\n const senders: Record<string, Record<string, any>> = {};\n\n await Promise.all(\n Object.entries(sendersByModel).map(async ([senderModel, senderIdsSet]) => {\n const modelName = modelMapping[senderModel] || senderModel;\n const senderIds = Array.from(senderIdsSet);\n\n // Skip if model doesn't exist\n if (!mongoose.modelNames().includes(modelName)) {\n console.warn(`Model ${modelName} not found for sender population`);\n return;\n }\n\n try {\n const SenderModel = mongoose.model(modelName);\n const modelSenders = await SenderModel.find({ _id: { $in: senderIds } })\n .select(fields)\n .lean()\n .exec();\n\n // Create lookup map for this model\n senders[senderModel] = {};\n modelSenders.forEach((sender) => {\n if (sender?._id) senders[senderModel][String(sender._id)] = sender;\n });\n } catch (error) {\n console.error(`Error loading senders for model ${modelName}:`, error);\n }\n }),\n );\n\n // Attach sender data to each message\n const populatedItems = items.map((message) => ({\n ...message,\n sender: senders[message.senderModel]?.[message.senderId] || null,\n })) as MessageWithSender[];\n\n return {\n items: populatedItems,\n hasMore,\n nextCursor,\n };\n },\n\n /**\n * Mark a message as read by a participant\n * @param args Read marking arguments\n */\n async markRead(args: MarkReadArgs): Promise<void> {\n const { organizationId, conversationId, participantModel, participantId, messageId } = args;\n\n const at = new Date();\n\n // Update the message read receipts\n await Message.findOneAndUpdate(\n {\n organizationId,\n conversationId,\n _id: messageId,\n // Ensure read receipt doesn't exist for this participant\n 'readBy.participantId': { $ne: participantId },\n },\n {\n $push: {\n readBy: {\n participantModel,\n participantId,\n readAt: at,\n },\n },\n },\n );\n\n // Update participant last read in conversation\n await Conversation.findOneAndUpdate(\n {\n organizationId,\n _id: conversationId,\n 'participants.entityModel': participantModel,\n 'participants.entityId': participantId,\n },\n {\n $set: {\n 'participants.$.lastReadMessageId': messageId,\n 'participants.$.lastReadAt': at,\n },\n },\n );\n\n // Trigger hook\n if (onMessageRead) {\n onMessageRead({ ...args, at });\n }\n },\n };\n}\n","/**\n * In-memory subscription maps for conversations and sockets\n */\n\n// Maps conversation IDs to sets of socket IDs\nconst convSubs: Map<string, Set<string>> = new Map();\n\n// Maps socket IDs to sets of conversation IDs\nconst socketSubs: Map<string, Set<string>> = new Map();\n\n/**\n * Subscribe a socket to a conversation\n * @param conversationId The conversation ID to subscribe to\n * @param socketId The socket ID to subscribe\n */\nexport function subscribeLocal(conversationId: string, socketId: string): void {\n // Add socket to conversation subscribers\n if (!convSubs.has(conversationId)) {\n convSubs.set(conversationId, new Set());\n }\n convSubs.get(conversationId)?.add(socketId);\n \n // Add conversation to socket subscriptions\n if (!socketSubs.has(socketId)) {\n socketSubs.set(socketId, new Set());\n }\n socketSubs.get(socketId)?.add(conversationId);\n}\n\n/**\n * Unsubscribe a socket from a conversation\n * @param conversationId The conversation ID to unsubscribe from\n * @param socketId The socket ID to unsubscribe\n */\nexport function unsubscribeLocal(conversationId: string, socketId: string): void {\n // Remove socket from conversation subscribers\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n sockets.delete(socketId);\n if (sockets.size === 0) {\n convSubs.delete(conversationId);\n }\n }\n \n // Remove conversation from socket subscriptions\n const conversations = socketSubs.get(socketId);\n if (conversations) {\n conversations.delete(conversationId);\n if (conversations.size === 0) {\n socketSubs.delete(socketId);\n }\n }\n}\n\n/**\n * Clean up all subscriptions for a socket\n * @param socketId The socket ID to clean up\n */\nexport function cleanupLocal(socketId: string): void {\n // Get all conversations this socket is subscribed to\n const conversations = socketSubs.get(socketId);\n if (conversations) {\n // Unsubscribe from each conversation\n for (const conversationId of conversations) {\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n sockets.delete(socketId);\n if (sockets.size === 0) {\n convSubs.delete(conversationId);\n }\n }\n }\n \n // Remove socket from socket subscriptions\n socketSubs.delete(socketId);\n }\n}\n\n/**\n * Fan out a message to all local subscribers of a conversation\n * @param conversationId The conversation ID to fan out to\n * @param payload The payload to send\n * @param emitter Function to emit events to socket IDs\n */\nexport function fanoutLocal(\n conversationId: string,\n payload: any,\n emitter: (toSocketId: string, event: any) => void\n): void {\n // Get all sockets subscribed to this conversation\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n // Emit to each socket\n for (const socketId of sockets) {\n try {\n emitter(socketId, payload);\n } catch (error) {\n console.error(`Error emitting to socket ${socketId}:`, error);\n }\n }\n }\n}","import Redis from 'ioredis';\nimport { RedisConfig } from '../config/env';\n\n// Cache a single Redis client per process to avoid multiple connections under HMR/re-inits\nlet SHARED_CLIENT: Redis | null = null;\nlet SHARED_CFG_FINGERPRINT: string | null = null;\n\n/**\n * Create a Redis client based on provided configuration\n * @param config Redis configuration\n * @returns Redis client instance or null if configuration is missing\n */\nexport function createRedisClient(config?: RedisConfig): Redis | null {\n if (!config) {\n console.warn('Redis configuration not found. Redis features will be disabled.');\n return null;\n }\n \n try {\n // Reuse existing client if config didn't change\n const fingerprint = JSON.stringify({\n url: config.url || null,\n host: config.host || null,\n port: config.port || null,\n db: config.db || null,\n password: Boolean(config.password),\n });\n\n if (SHARED_CLIENT && SHARED_CFG_FINGERPRINT === fingerprint) {\n return SHARED_CLIENT;\n }\n\n let client: Redis;\n \n // Use either URL or granular connection options\n if (config.url) {\n client = new Redis(config.url);\n } else if (config.host) {\n client = new Redis({\n host: config.host,\n port: config.port,\n password: config.password,\n db: config.db,\n connectTimeout: config.socketConnectTimeout, // Changed \n enableReadyCheck: true,\n enableOfflineQueue: true,\n retryStrategy(times) {\n const delay = Math.min(times * 50, 2000);\n return delay;\n }\n });\n } else {\n console.warn('Invalid Redis configuration. Redis features will be disabled.');\n return null;\n }\n \n // Log Redis connection events\n client.on('connect', () => {\n console.info('Redis client connected');\n });\n \n client.on('error', (err) => {\n console.error('Redis client error:', err);\n });\n \n client.on('reconnecting', () => {\n console.info('Redis client reconnecting');\n });\n \n // Cache and return\n SHARED_CLIENT = client;\n SHARED_CFG_FINGERPRINT = fingerprint;\n return SHARED_CLIENT;\n } catch (error) {\n console.error('Failed to create Redis client:', error);\n return null;\n }\n}\n\n/**\n * Publish a message to a conversation channel\n * @param client Redis client\n * @param conversationId Conversation ID\n * @param payload Message payload\n * @returns Promise resolving to number of clients that received the message\n */\nexport async function publishToConversation(\n client: Redis | null,\n conversationId: string,\n payload: any\n): Promise<number> {\n if (!client) return 0;\n \n try {\n const channel = `conv:${conversationId}`;\n const message = JSON.stringify(payload);\n return await client.publish(channel, message);\n } catch (error) {\n console.error(`Failed to publish to conversation ${conversationId}:`, error);\n return 0;\n }\n}\n\n/**\n * Start Redis subscription listener\n * @param client Redis client\n * @param onEvent Callback function for received events\n * @returns Function to stop the listener\n */\nexport function startRedisListener(\n client: Redis | null,\n onEvent: (conversationId: string, payload: any) => void\n): (() => void) | null {\n if (!client) return null;\n \n try {\n // Create a duplicate client for subscribing\n // (Redis clients in subscribe mode cannot be used for other commands)\n const subClient = client.duplicate();\n \n // Subscribe to conversation channels\n subClient.psubscribe('conv:*');\n \n // Handle incoming messages\n subClient.on('pmessage', (_pattern, channel, message) => {\n try {\n // Extract conversation ID from channel\n const conversationId = channel.slice(5); // Remove 'conv:' prefix\n \n // Parse message payload\n const payload = JSON.parse(message);\n \n // Call event handler\n onEvent(conversationId, payload);\n } catch (error) {\n console.error('Error processing Redis message:', error);\n }\n });\n \n // Return function to stop listening\n return () => {\n subClient.punsubscribe('conv:*');\n subClient.quit();\n };\n } catch (error) {\n console.error('Failed to start Redis listener:', error);\n return null;\n }\n}","import type { Server as HTTPServer, IncomingMessage } from 'http';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport type { RawData } from 'ws';\nimport url from 'url';\nimport { Transport } from './index';\n\nexport interface SocketConfig {\n path?: string;\n}\n\nexport interface SocketUser {\n id: string;\n model: string;\n}\n\nexport class SocketTransport {\n // Native WS server and state\n private wss: WebSocketServer;\n private transport: Transport;\n private sockets: Map<string, WebSocket> = new Map();\n private users: Map<string, SocketUser> = new Map();\n private joinedConversations: Map<string, Set<string>> = new Map(); // socketId -> convIds\n\n // Auth handler compatibility shim\n private authenticate?: (socket: any) => Promise<SocketUser | null>;\n\n // Socket.IO-like shim for getIO().sockets.sockets.get(id).emit('chat-event', payload)\n private ioShim = {\n sockets: {\n sockets: new Map<string, { emit: (event: string, payload: any) => void }>(),\n },\n to: (_room: string) => ({\n emit: (_event: string, _payload: any) => {\n // no-op room emitter in shim; we fanout via localSubs instead\n },\n }),\n } as any;\n\n constructor(server: HTTPServer, transport: Transport, config?: SocketConfig) {\n this.wss = new WebSocketServer({ noServer: true });\n this.transport = transport;\n\n const upgradePath = config?.path || '/api/socket';\n const srvAny = server as any;\n if (!srvAny.__wexaWsUpgradeAttached) {\n srvAny.on('upgrade', (request: IncomingMessage, socket: any, head: any) => {\n try {\n const { pathname } = url.parse(request.url || '');\n // Match path and allow query string; ignore other upgrades (HMR, etc.)\n if (!pathname || !pathname.startsWith(upgradePath)) return;\n\n // Only process real WebSocket upgrade requests\n const upgradeHeader = String((request.headers as any)['upgrade'] || '').toLowerCase();\n if (upgradeHeader !== 'websocket') return;\n\n // Ensure we don't crash on socket errors during upgrade\n socket.on?.('error', () => {\n try {\n socket.destroy();\n } catch {}\n });\n\n this.wss.handleUpgrade(request, socket, head, (ws: WebSocket) => {\n this.wss.emit('connection', ws, request);\n });\n } catch {\n try {\n socket?.destroy();\n } catch {}\n }\n });\n srvAny.__wexaWsUpgradeAttached = true;\n }\n\n // Keep ioShim map in sync with sockets map\n const syncShim = () => {\n const m = new Map<string, { emit: (event: string, payload: any) => void }>();\n for (const [id, ws] of this.sockets.entries()) {\n m.set(id, {\n emit: (event: string, payload: any) => {\n if (event !== 'chat-event') return;\n if (ws.readyState === WebSocket.OPEN) {\n try {\n ws.send(JSON.stringify(payload));\n } catch {\n // ignore\n }\n }\n },\n });\n }\n (this.ioShim.sockets as any).sockets = m;\n };\n\n // Heartbeat to keep connections healthy and detect dead peers\n const HEARTBEAT_MS = 30_000;\n const interval = setInterval(() => {\n this.wss.clients.forEach((client) => {\n const c = client as WebSocket & { isAlive?: boolean };\n if (c.isAlive === false) {\n try {\n c.terminate();\n } catch {}\n return;\n }\n c.isAlive = false;\n try {\n c.ping();\n } catch {}\n });\n }, HEARTBEAT_MS);\n this.wss.on('close', () => clearInterval(interval));\n\n // Listen for Redis events and broadcast to local subscribers\n this.transport.startRedisListener((conversationId: string, payload: any) => {\n this.transport.fanoutLocal(conversationId, payload, (toSocketId) => {\n const ws = this.sockets.get(toSocketId);\n if (ws && ws.readyState === WebSocket.OPEN) {\n try {\n ws.send(JSON.stringify(payload));\n } catch {}\n }\n });\n });\n\n // Handle new WS connections\n this.wss.on('connection', (ws: WebSocket, request: IncomingMessage) => {\n const hbWs = ws as WebSocket & { isAlive?: boolean };\n hbWs.isAlive = true;\n hbWs.on('pong', () => {\n hbWs.isAlive = true;\n });\n const parsed = url.parse(request.url || '', true);\n const q = parsed.query || {};\n const userId = typeof q.userId === 'string' ? q.userId : undefined;\n const userModel = typeof q.userModel === 'string' ? q.userModel : 'User';\n\n const socketId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n\n // Build a minimal Socket.IO-like object for authenticate()\n const shimSocket: any = {\n id: socketId,\n handshake: { auth: { userId, userModel } },\n data: {},\n };\n\n const doAccept = (user: SocketUser) => {\n this.sockets.set(socketId, ws);\n this.users.set(socketId, user);\n this.joinedConversations.set(socketId, new Set());\n syncShim();\n\n ws.on('message', (raw: RawData) => {\n try {\n const msg = JSON.parse(raw.toString());\n const type = msg?.type;\n if (type === 'join-conversation' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n this.transport.subscribeLocal(convId, socketId);\n this.joinedConversations.get(socketId)!.add(convId);\n // presence join to others\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'presence:join',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n } else if (type === 'leave-conversation' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n this.transport.unsubscribeLocal(convId, socketId);\n this.joinedConversations.get(socketId)!.delete(convId);\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'presence:leave',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n } else if (type === 'typing' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n const isTyping = !!msg.isTyping;\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'typing',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n state: isTyping ? 'start' : 'stop',\n at: new Date().toISOString(),\n };\n // Emit to others and publish to Redis\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n this.transport.publishToConversation(convId, payload);\n }\n } catch {\n // ignore\n }\n });\n\n ws.on('close', () => {\n const joined = this.joinedConversations.get(socketId);\n if (joined) {\n const u = this.users.get(socketId)!;\n for (const convId of joined) {\n // presence leave to others\n const payload = {\n type: 'presence:leave',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n }\n }\n this.transport.cleanupLocal(socketId);\n this.sockets.delete(socketId);\n this.users.delete(socketId);\n this.joinedConversations.delete(socketId);\n syncShim();\n });\n };\n\n const doReject = () => {\n try {\n ws.close(1008, 'Unauthorized');\n } catch {}\n };\n\n if (this.authenticate) {\n this.authenticate(shimSocket)\n .then((user) => {\n if (user) doAccept(user);\n else doReject();\n })\n .catch(() => doReject());\n } else {\n // If no auth handler, accept only if userId provided\n if (userId) doAccept({ id: userId, model: userModel });\n else doReject();\n }\n });\n }\n\n /**\n * Handle socket authentication\n */\n public handleAuth(authenticate: (socket: any) => Promise<SocketUser | null>) {\n this.authenticate = authenticate;\n }\n\n /**\n * Initialize socket event handlers\n */\n public initialize() {\n // No-op: handlers are set up in constructor for WS server\n }\n\n /**\n * Get Socket.IO server instance\n */\n public getIO(): any {\n return this.ioShim;\n }\n\n /**\n * Close Socket.IO server\n */\n public close(): Promise<void> {\n return new Promise((resolve) => {\n try {\n this.wss.close(() => resolve());\n } catch {\n resolve();\n }\n });\n }\n}\n","import * as localSubs from './localSubs';\nimport { createRedisClient, publishToConversation, startRedisListener } from './redis';\nimport { SocketTransport, SocketConfig } from './socket';\nimport { InitOptions } from '../types';\nimport type { Server as HTTPServer } from 'http';\n\n/**\n * Transport configuration type\n */\nexport interface TransportConfig {\n redis?: InitOptions['redis'];\n socket?: SocketConfig;\n}\n\n/**\n * Transport instance type\n */\nexport interface Transport {\n subscribeLocal: typeof localSubs.subscribeLocal;\n unsubscribeLocal: typeof localSubs.unsubscribeLocal;\n cleanupLocal: typeof localSubs.cleanupLocal;\n fanoutLocal: typeof localSubs.fanoutLocal;\n publishToConversation: (conversationId: string, payload: any) => Promise<number>;\n startRedisListener: (onEvent: (conversationId: string, payload: any) => void) => (() => void) | null;\n}\n\n/**\n * Create transport system with optional Redis and Socket.IO support\n */\nexport function createTransport(\n config?: TransportConfig,\n server?: HTTPServer\n): Transport & { socket?: SocketTransport } {\n // Initialize Redis client if configuration is provided\n const redisClient = config?.redis ? createRedisClient(config.redis) : null;\n \n // Create base transport\n const transport: Transport = {\n // Local subscription methods\n subscribeLocal: localSubs.subscribeLocal,\n unsubscribeLocal: localSubs.unsubscribeLocal,\n cleanupLocal: localSubs.cleanupLocal,\n fanoutLocal: localSubs.fanoutLocal,\n \n // Redis methods\n publishToConversation: (conversationId: string, payload: any) => \n publishToConversation(redisClient, conversationId, payload),\n \n startRedisListener: (onEvent: (conversationId: string, payload: any) => void) => \n startRedisListener(redisClient, onEvent),\n };\n\n // Initialize Socket.IO if server is provided\n if (server) {\n const socketTransport = new SocketTransport(server, transport, config?.socket);\n return {\n ...transport,\n socket: socketTransport\n };\n }\n\n return transport;\n}","import mongoose, { Model } from 'mongoose';\nimport { IConversation } from './Conversation.model';\nimport { IMessage } from './Message.model';\n\n/**\n * Ensure all indexes are created on models\n * @param models Object containing Mongoose models\n */\nexport async function ensureIndexes(models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n}): Promise<void> {\n // Create indexes\n await Promise.all([\n models.Message.ensureIndexes(),\n models.Conversation.ensureIndexes(),\n ]);\n}","/**\n * Redis configuration type\n */\nexport type RedisConfig = {\n url?: string;\n host?: string;\n port?: number;\n password?: string;\n db?: number;\n socketConnectTimeout?: number;\n keepAlive?: number;\n};\n\n/**\n * Environment configuration\n */\nexport interface EnvironmentConfig {\n /** MongoDB connection URI */\n mongoUri: string;\n /** Redis configuration (optional) */\n redis?: RedisConfig;\n}\n/**\n * Get Redis configuration from provided options\n */\nexport function getRedisConfig(config: { redis?: RedisConfig }): RedisConfig | null {\n if (!config.redis) {\n return null;\n }\n\n // Return the full configuration\n return {\n host: config.redis.host || undefined,\n port: config.redis.port || undefined,\n password: config.redis.password || undefined,\n db: config.redis.db || undefined,\n socketConnectTimeout: config.redis.socketConnectTimeout || undefined,\n keepAlive: config.redis.keepAlive || undefined\n };\n}\n","/**\n * Generates a random string ID with the specified length\n * @param length The length of the ID to generate (default: 24)\n * @returns A random string ID\n */\nexport function generateId(length = 24): string {\n const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n const charactersLength = characters.length;\n \n for (let i = 0; i < length; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n \n return result;\n}\n\n/**\n * Creates a conversation ID from two participant identifiers\n * @param a First participant (model:id)\n * @param b Second participant (model:id)\n * @returns A deterministic conversation ID\n */\nexport function createConversationId(\n a: { model: string; id: string },\n b: { model: string; id: string }\n): string {\n // Sort participants to ensure the same ID regardless of order\n const participants = [\n `${a.model}:${a.id}`,\n `${b.model}:${b.id}`,\n ].sort();\n \n return `conv_${participants.join('_')}`;\n}\n\n/**\n * Creates a thread ID\n * @returns A unique thread ID\n */\nexport function createThreadId(): string {\n return `thread_${generateId(16)}`;\n}\n\n/**\n * Creates a message ID\n * @returns A unique message ID\n */\nexport function createMessageId(): string {\n return `msg_${generateId(16)}`;\n}\n\n\n\n\n","import { InitOptions, SendMessageArgs, CreateConversationArgs, MarkReadArgs } from '../types';\n\n/**\n * Validates initialization options\n * @param options Options to validate\n * @returns Validation error message or null if valid\n */\nexport function validateInitOptions(options: InitOptions): string | null {\n if (!options.participantModels || !Array.isArray(options.participantModels) || options.participantModels.length === 0) {\n return 'participantModels must be a non-empty array of strings';\n }\n\n if (!options.memberRoles || !Array.isArray(options.memberRoles) || options.memberRoles.length === 0) {\n return 'memberRoles must be a non-empty array of strings';\n }\n\n // Validate Redis options if provided\n if (options.redis) {\n if (options.redis.url) {\n if (typeof options.redis.url !== 'string') {\n return 'redis.url must be a string';\n }\n } else if (!options.redis.host) {\n return 'Either redis.url or redis.host must be provided';\n }\n }\n\n return null;\n}\n\n/**\n * Validates message sending arguments\n * @param args Message sending arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateSendMessageArgs(args: SendMessageArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.conversationId) {\n return 'conversationId is required';\n }\n\n if (!args.senderModel) {\n return 'senderModel is required';\n }\n\n if (!args.senderId) {\n return 'senderId is required';\n }\n\n if (!args.text || args.text.trim() === '') {\n return 'text is required and cannot be empty';\n }\n\n // If kind is provided, validate it's a valid value\n if (args.kind && !['text', 'system'].includes(args.kind)) {\n return 'kind must be either \"text\" or \"system\"';\n }\n\n // If this is a reply, ensure all thread fields are present\n if (args.parentMessageId && !args.rootThreadId) {\n return 'rootThreadId is required when parentMessageId is provided';\n }\n\n return null;\n}\n\n/**\n * Validates conversation creation arguments\n * @param args Conversation creation arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateCreateConversationArgs(args: CreateConversationArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.a || !args.a.model || !args.a.id) {\n return 'a.model and a.id are required';\n }\n\n if (!args.b || !args.b.model || !args.b.id) {\n return 'b.model and b.id are required';\n }\n\n // Prevent creating a conversation between the same participant\n if (args.a.model === args.b.model && args.a.id === args.b.id) {\n return 'Cannot create a conversation between the same participant';\n }\n\n return null;\n}\n\n/**\n * Validates mark read arguments\n * @param args Mark read arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateMarkReadArgs(args: MarkReadArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.conversationId) {\n return 'conversationId is required';\n }\n\n if (!args.participantModel) {\n return 'participantModel is required';\n }\n\n if (!args.participantId) {\n return 'participantId is required';\n }\n\n if (!args.messageId) {\n return 'messageId is required';\n }\n\n return null;\n}\n\n/**\n * Validates pagination parameters\n * @param limit Pagination limit\n * @param cursor Pagination cursor\n * @returns Validated limit and cursor\n */\nexport function validatePagination(\n limit?: number,\n cursor?: string\n): { limit: number; cursor: string | undefined } {\n // Default limit to 20, max to 100\n let validLimit = limit ? Math.min(Math.max(1, limit), 100) : 20;\n \n // If cursor is provided but empty string, set to undefined\n let validCursor = cursor && cursor.trim() !== '' ? cursor : undefined;\n \n return { limit: validLimit, cursor: validCursor };\n}\n\n\n\n\n","import mongoose from 'mongoose';\nimport type { Server as HTTPServer } from 'http';\nimport { createModels } from './models/connection';\nimport { createConversationsService, ConversationsService } from './services/conversations.service';\nimport { createMessagesService, MessagesService } from './services/messages.service';\nimport { createTransport, Transport } from './transport';\nimport { InitOptions } from './types';\nimport { ensureIndexes } from './models/indexes';\nimport { getRedisConfig } from './config/env';\nimport { SocketTransport } from './transport/socket';\nimport type { IConversation, IMessage } from './models';\nimport { setRuntimeConfig } from './config/runtime';\n\n/**\n * Chat services container\n */\nexport interface ChatServices {\n models: {\n Conversation: mongoose.Model<IConversation>;\n Message: mongoose.Model<IMessage>;\n };\n services: {\n conversations: ConversationsService;\n messages: MessagesService;\n };\n transport: Transport & { socket?: SocketTransport };\n}\n\n/**\n * Initialize the chat system\n * @param mongooseInstance Mongoose instance\n * @param options Initialization options\n * @param server Optional HTTP server for Socket.IO integration\n * @returns Chat services\n */\nexport async function initChat(\n mongooseInstance: typeof mongoose,\n options: InitOptions,\n server?: HTTPServer,\n): Promise<ChatServices> {\n // Persist runtime configuration for global access\n setRuntimeConfig({\n dataServiceEndpoint: options.dataServiceEndpoint,\n secretId: options.secretId,\n });\n\n const models = createModels(mongooseInstance, options);\n\n // Ensure indexes are created\n await ensureIndexes(models);\n\n // Create transport system with optional Socket.IO support\n const transport = createTransport(\n {\n redis: getRedisConfig(options) || undefined,\n socket: options.socket || undefined,\n },\n server,\n );\n\n // Initialize Socket.IO if server was provided\n if (server && transport.socket) {\n // Set up authentication handler\n transport.socket.handleAuth(async (socket) => {\n // Get user info from socket handshake auth\n const userId = socket.handshake.auth.userId;\n const userModel = socket.handshake.auth.userModel || 'User';\n\n if (!userId || !options.participantModels.includes(userModel)) {\n return null;\n }\n\n return { id: userId, model: userModel };\n });\n\n // Initialize socket event handlers\n transport.socket.initialize();\n }\n\n // Create services with hooks\n const services = {\n conversations: createConversationsService(models),\n messages: createMessagesService(models, {\n onMessageCreated: (message) => {\n const payload = { type: 'message:created', message };\n\n // Fan out to local subscribers\n transport.fanoutLocal(message.conversationId.toString(), payload, (socketId, event) => {\n if (transport.socket) {\n const socket = transport.socket.getIO().sockets.sockets.get(socketId);\n if (socket) {\n socket.emit('chat-event', event);\n }\n }\n });\n\n // Publish to Redis for cross-instance communication\n transport.publishToConversation(message.conversationId.toString(), payload);\n },\n\n onMessageRead: (args) => {\n const payload = {\n type: 'conversation:read',\n conversationId: args.conversationId,\n messageId: args.messageId,\n participantModel: args.participantModel,\n participantId: args.participantId,\n at: args.at.toISOString(),\n };\n\n // Fan out to local subscribers\n transport.fanoutLocal(args.conversationId, payload, (socketId, event) => {\n if (transport.socket) {\n const socket = transport.socket.getIO().sockets.sockets.get(socketId);\n if (socket) {\n socket.emit('chat-event', event);\n }\n }\n });\n\n // Publish to Redis for cross-instance communication\n transport.publishToConversation(args.conversationId, payload);\n },\n }),\n };\n\n return { models, services, transport };\n}\n\n// Re-export types\nexport * from './types';\nexport * from './utils';\nexport * from './models';\nexport * from './services';\nexport * from './transport';\nexport * from './config/env';\nexport * from './config/runtime';\n\n// Export Conversation and Message model types for direct access\nexport type { ConversationModel, MessageModel } from './models';\n\n// Export MessageWithSender interface\nexport type { MessageWithSender } from './services/messages.service';\n"]}
package/dist/index.mjs CHANGED
@@ -64,6 +64,8 @@ function createConversationModel(options, conn) {
64
64
  lastMessageSenderModel: String,
65
65
  lastLinkedInId: String,
66
66
  lastWhatsAppId: String,
67
+ linkedinChatId: String,
68
+ whatsappChatId: String,
67
69
  metadata: Schema.Types.Mixed
68
70
  },
69
71
  { timestamps: true }
@@ -591,14 +593,17 @@ function createMessagesService(models, hooks = {}) {
591
593
  if (res.status === "fulfilled") {
592
594
  success_source.push(name);
593
595
  } else {
594
- const err = res.reason.response.data.detail || res.reason.response.data || "Unknown error";
596
+ const err = success_source;
597
+ res.reason.response.data.detail || res.reason.response.data || "Unknown error";
595
598
  failed_source.push({
596
599
  source: name,
597
600
  message: typeof err === "string" ? err : JSON.stringify(err)
598
601
  });
599
602
  }
600
603
  });
604
+ console.log("results", results);
601
605
  }
606
+ console.log("success_source", success_source);
602
607
  const message = new Message({
603
608
  organizationId,
604
609
  conversationId,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/models/Conversation.model.ts","../src/models/Message.model.ts","../src/models/connection.ts","../src/utils/pagination.ts","../src/services/search/search.conversations.ts","../src/services/conversations.service.ts","../src/services/search/search.messages.ts","../src/config/paths.ts","../src/config/runtime.ts","../src/config/axios.ts","../src/services/messages.service.ts","../src/transport/localSubs.ts","../src/transport/redis.ts","../src/transport/socket.ts","../src/transport/index.ts","../src/models/indexes.ts","../src/config/env.ts","../src/utils/ids.ts","../src/utils/validators.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Schema as MongooseSchema, Document, Model, Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { modelRegistry } from './connection';\n\nexport interface IConversation extends Document {\n organizationId: string;\n participants: Array<{\n entityModel: string;\n entityId: string;\n role: string;\n }>;\n lastMessageId?: string;\n lastMessageAt?: Date;\n lastMessagePreview?: string;\n lastMessageSenderId?: string;\n lastMessageSenderModel?: string;\n lastLinkedInId?: string;\n lastWhatsAppId?: string;\n metadata?: Record<string, any>;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * Create (or retrieve) Conversation model safely\n */\nexport function createConversationModel(\n options: InitOptions,\n conn: Connection,\n): Model<IConversation> {\n // Generate a unique key for the model registry\n const connectionId = conn.id || conn.name || 'default';\n const registryKey = `${connectionId}:Conversation`;\n\n // Return from registry if exists\n if (modelRegistry.has(registryKey)) {\n return modelRegistry.get(registryKey) as Model<IConversation>;\n }\n\n // Check if model already exists on the connection\n const name = 'Conversation';\n if (conn.models[name]) {\n const existingModel = conn.models[name] as Model<IConversation>;\n modelRegistry.set(registryKey, existingModel);\n return existingModel;\n }\n\n // Participant schema (use the Schema from the same mongoose instance as the connection)\n const Schema: typeof MongooseSchema = (conn as any).base.Schema;\n const ParticipantSchema = new Schema(\n {\n entityModel: {\n type: String,\n enum: options.participantModels,\n required: true,\n },\n entityId: {\n type: String,\n required: true,\n },\n role: {\n type: String,\n enum: options.memberRoles,\n required: true,\n },\n },\n { _id: false },\n );\n\n // Conversation schema\n const ConversationSchema = new Schema<IConversation>(\n {\n organizationId: {\n type: String,\n required: true,\n },\n participants: {\n type: [ParticipantSchema],\n required: true,\n validate: {\n validator: function (participants: any[]) {\n return participants.length === 2;\n },\n message: 'Conversations must have exactly 2 participants',\n },\n },\n lastMessageId: {\n type: String,\n ref: 'Message',\n },\n lastMessageAt: {\n type: Date,\n },\n lastMessagePreview: String,\n lastMessageSenderId: String,\n lastMessageSenderModel: String,\n lastLinkedInId: String,\n lastWhatsAppId: String,\n metadata: (Schema as any).Types.Mixed,\n },\n { timestamps: true },\n );\n\n // Create the model\n const model = conn.model<IConversation>(name, ConversationSchema);\n\n // Register the model\n modelRegistry.set(registryKey, model);\n\n return model;\n}\n","import type { Schema as MongooseSchema, Document, Model, Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { modelRegistry } from './connection';\n\nexport const sourceType = {\n LINKEDIN: 'linkedin',\n WHATSAPP: 'whatsapp',\n EMAIL: 'email',\n CORE: 'core',\n} as const;\n\nexport type SourceType = (typeof sourceType)[keyof typeof sourceType];\n\nexport interface IMessage extends Document {\n organizationId: string;\n conversationId: string;\n senderModel: string;\n senderId: string;\n text: string;\n kind: 'text' | 'system';\n source: SourceType[];\n failed_source?: Array<{ source: string; message: string }>;\n parentMessageId?: string;\n rootThreadId?: string;\n editedAt?: Date;\n deletedAt?: Date;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * Create (or retrieve) Message model safely\n */\nexport function createMessageModel(options: InitOptions, conn: Connection): Model<IMessage> {\n // Generate a unique key for the model registry\n const connectionId = conn.id || conn.name || 'default';\n const registryKey = `${connectionId}:Message`;\n\n // Return from registry if exists\n if (modelRegistry.has(registryKey)) {\n return modelRegistry.get(registryKey) as Model<IMessage>;\n }\n\n // Check if model already exists on the connection\n const name = 'Message';\n if (conn.models[name]) {\n const existingModel = conn.models[name] as Model<IMessage>;\n modelRegistry.set(registryKey, existingModel);\n return existingModel;\n }\n\n // Build Schema from the same mongoose instance as the connection\n const Schema: typeof MongooseSchema = (conn as any).base.Schema;\n const MessageSchema = new Schema<IMessage>(\n {\n organizationId: {\n type: String,\n required: true,\n index: true,\n },\n conversationId: {\n type: String,\n required: true,\n index: true,\n },\n senderModel: {\n type: String,\n enum: options.participantModels,\n required: true,\n },\n senderId: {\n type: String,\n required: true,\n index: true,\n },\n kind: {\n type: String,\n enum: ['text', 'system'],\n default: 'text',\n index: true,\n },\n source: {\n type: [String],\n enum: Object.values(sourceType),\n required: true,\n },\n text: {\n type: String,\n trim: true,\n },\n parentMessageId: {\n type: String,\n ref: 'Message',\n },\n rootThreadId: {\n type: String,\n ref: 'Message',\n },\n editedAt: {\n type: Date,\n },\n deletedAt: {\n type: Date,\n },\n },\n { timestamps: true },\n );\n\n // Indexes\n MessageSchema.index({\n organizationId: 1,\n conversationId: 1,\n createdAt: -1,\n });\n\n // Create text search index if enabled\n if (options.enableTextSearch) {\n MessageSchema.index(\n { text: 'text' },\n {\n name: 'text_search',\n weights: { text: 10 },\n },\n );\n }\n\n // Create the model\n const model = conn.model<IMessage>(name, MessageSchema);\n\n // Register the model\n modelRegistry.set(registryKey, model);\n\n return model;\n}\n","import mongoose, { Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { createConversationModel } from './Conversation.model';\nimport { createMessageModel } from './Message.model';\n\n// Global model registry to prevent duplicate compilations\nexport const modelRegistry = new Map<string, mongoose.Model<any>>();\n\n/**\n * Create Mongoose models with applied configuration\n * @param mongooseInstance Mongoose instance\n * @param options Initialization options\n * @returns Object containing Conversation and Message models\n */\nexport function createModels(mongooseInstance: typeof mongoose, options: InitOptions) {\n // Get the connection instance\n const conn: Connection = mongooseInstance.connection;\n\n // Generate a unique connection identifier for this connection\n const connectionId = conn.id || conn.name || 'default';\n \n // Check if models are already registered for this connection\n const registryKey = `${connectionId}:Conversation`;\n const messageRegistryKey = `${connectionId}:Message`;\n \n // Create or reuse models\n const Conversation = modelRegistry.get(registryKey) || createConversationModel(options, conn);\n const Message = modelRegistry.get(messageRegistryKey) || createMessageModel(options, conn);\n \n // Register models if they're new\n if (!modelRegistry.has(registryKey)) {\n modelRegistry.set(registryKey, Conversation);\n }\n \n if (!modelRegistry.has(messageRegistryKey)) {\n modelRegistry.set(messageRegistryKey, Message);\n }\n \n return {\n Conversation,\n Message\n };\n}\n\n/**\n * Connection state enum\n */\nenum ConnectionState {\n Disconnected = 0,\n Connected = 1,\n Connecting = 2,\n Disconnecting = 3,\n}","/**\n * Pagination result interface\n */\nexport interface PaginatedResult<T> {\n items: T[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n/**\n * Creates a pagination cursor from a timestamp and ID\n * @param timestamp Timestamp to encode in the cursor\n * @param id ID to encode in the cursor\n * @returns An encoded cursor string\n */\nexport function createCursor(timestamp: number, id: string): string {\n const cursorData = `${timestamp}:${id}`;\n return Buffer.from(cursorData).toString('base64');\n}\n\n/**\n * Parses a pagination cursor into its timestamp and ID components\n * @param cursor The cursor string to parse\n * @returns An object containing the timestamp and ID, or null if invalid\n */\nexport function parseCursor(cursor: string): { timestamp: number; id: string } | null {\n try {\n const decoded = Buffer.from(cursor, 'base64').toString('utf-8');\n const [timestampStr, id] = decoded.split(':');\n \n const timestamp = parseInt(timestampStr, 10);\n \n if (isNaN(timestamp) || !id) {\n return null;\n }\n \n return { timestamp, id };\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Creates a paginated response\n * @param items The items for the current page\n * @param limit The requested page size\n * @param getNextCursor Function to get the next cursor from the last item\n * @returns A paginated result object\n */\nexport function createPaginatedResponse<T>(\n items: T[],\n limit: number,\n getNextCursor: (lastItem: T) => string\n): PaginatedResult<T> {\n const hasMore = items.length > limit;\n \n // If we have more items than the limit, remove the extra item\n // that we used to determine if there are more pages\n const paginatedItems = hasMore ? items.slice(0, limit) : items;\n \n // Get the next cursor from the last item if we have more items\n const nextCursor = hasMore && paginatedItems.length > 0\n ? getNextCursor(paginatedItems[paginatedItems.length - 1])\n : null;\n \n return {\n items: paginatedItems,\n nextCursor,\n hasMore,\n };\n}\n\n\n\n\n","import { Model } from 'mongoose';\nimport { IConversation } from '../../models/Conversation.model';\nimport { SearchConversationsArgs } from '../../types';\nimport { createCursor, parseCursor, PaginatedResult } from '../../utils/pagination';\n\n/**\n * Search conversations with pagination\n */\nexport async function searchConversations(\n model: Model<IConversation>,\n params: SearchConversationsArgs\n): Promise<PaginatedResult<IConversation>> {\n const { \n organizationId, \n participantModel, \n participantId,\n limit = 20, \n cursor \n } = params;\n \n // Base query with required organizationId\n const baseQuery: Record<string, any> = { \n organizationId \n };\n \n // Add participant filter if provided\n if (participantModel && participantId) {\n baseQuery['participants'] = {\n $elemMatch: {\n entityModel: participantModel,\n entityId: participantId\n }\n };\n }\n \n // Handle cursor-based pagination\n if (cursor) {\n const parsedCursor = parseCursor(cursor);\n \n if (parsedCursor) {\n const { timestamp, id } = parsedCursor;\n const cursorDate = new Date(timestamp);\n \n baseQuery.$or = [\n { lastMessageAt: { $lt: cursorDate } },\n { lastMessageAt: cursorDate, _id: { $lt: id } }\n ];\n }\n }\n \n // Find conversations and sort by lastMessageAt\n const conversations = await model.find(baseQuery)\n .sort({ lastMessageAt: -1 })\n .limit(limit + 1)\n .exec();\n \n // Check if we have more results\n const hasMore = conversations.length > limit;\n const items = hasMore ? conversations.slice(0, limit) : conversations;\n \n // Create next cursor if we have more results\n let nextCursor: string | null = null;\n \n if (hasMore && items.length > 0) {\n const lastItem = items[items.length - 1];\n // Use lastMessageAt if available, otherwise use createdAt\n const timestamp = lastItem.lastMessageAt ? \n lastItem.lastMessageAt.getTime() : \n lastItem.createdAt.getTime();\n \n nextCursor = createCursor(timestamp, lastItem._id.toString());\n }\n \n return {\n items,\n nextCursor,\n hasMore\n };\n}\n\n/**\n * Find a conversation between two specific participants\n */\nexport async function searchByParticipantPair(\n model: Model<IConversation>,\n params: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }\n): Promise<IConversation | null> {\n const { organizationId, a, b } = params;\n \n const conversation = await model.findOne({\n organizationId,\n $and: [\n {\n participants: {\n $elemMatch: {\n entityModel: a.model,\n entityId: a.id\n }\n }\n },\n {\n participants: {\n $elemMatch: {\n entityModel: b.model,\n entityId: b.id\n }\n }\n },\n {\n $expr: {\n $eq: [{ $size: \"$participants\" }, 2]\n }\n }\n ]\n });\n \n return conversation;\n}","import { Model } from 'mongoose';\nimport { IConversation } from '../models/Conversation.model';\nimport { IMessage } from '../models/Message.model';\nimport { CreateConversationArgs, SearchConversationsArgs } from '../types';\nimport { searchConversations, searchByParticipantPair } from './search/search.conversations';\nimport { PaginatedResult } from '../utils/pagination';\n\n/**\n * Service for managing conversations\n */\nexport interface ConversationsService {\n createOrFindConversation(args: CreateConversationArgs): Promise<IConversation>;\n getConversation(organizationId: string, conversationId: string): Promise<IConversation | null>;\n searchConversations(args: SearchConversationsArgs): Promise<PaginatedResult<IConversation>>;\n searchByParticipantPair(args: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }): Promise<IConversation | null>;\n}\n\n/**\n * Create conversations service\n * @param models MongoDB models\n * @returns Conversations service instance\n */\nexport function createConversationsService(models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n}): ConversationsService {\n const { Conversation } = models;\n\n return {\n /**\n * Create a new conversation or find existing one between participants\n */\n async createOrFindConversation(args: CreateConversationArgs): Promise<IConversation> {\n console.log('Creating or finding conversation for users:', {\n args,\n });\n const { organizationId, a, b } = args;\n console.log('Creating or finding conversation for users:', {\n organizationId,\n a,\n b,\n });\n\n try {\n console.log('asdfa');\n // Check if conversation already exists between these participants\n const existingConversation = await searchByParticipantPair(Conversation, {\n organizationId,\n a,\n b,\n });\n\n console.log('Existing conversation:', existingConversation);\n if (existingConversation) {\n return existingConversation;\n }\n\n // Create new conversation\n const newConversation = new Conversation({\n organizationId,\n participants: [\n {\n entityModel: a.model,\n entityId: a.id,\n role: 'member', // Default role\n },\n {\n entityModel: b.model,\n entityId: b.id,\n role: 'member', // Default role\n },\n ],\n lastMessageAt: new Date(), // Set initial lastMessageAt\n });\n\n console.log('New conversation:', newConversation);\n\n await newConversation.save();\n console.log('Saved conversation:', newConversation);\n return newConversation;\n } catch (error) {\n console.error('Error in createOrFindConversation:', error);\n throw error;\n }\n },\n\n /**\n * Get a conversation by ID\n */\n async getConversation(\n organizationId: string,\n conversationId: string,\n ): Promise<IConversation | null> {\n try {\n return await Conversation.findOne({\n organizationId,\n _id: conversationId,\n });\n } catch (error) {\n console.error('Error in getConversation:', error);\n throw error;\n }\n },\n\n /**\n * Search conversations with pagination\n */\n async searchConversations(\n args: SearchConversationsArgs,\n ): Promise<PaginatedResult<IConversation>> {\n try {\n return await searchConversations(Conversation, args);\n } catch (error) {\n console.error('Error in searchConversations:', error);\n throw error;\n }\n },\n\n /**\n * Find a conversation between two specific participants\n */\n async searchByParticipantPair(args: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }): Promise<IConversation | null> {\n try {\n return await searchByParticipantPair(Conversation, args);\n } catch (error) {\n console.error('Error in searchByParticipantPair:', error);\n throw error;\n }\n },\n };\n}\n","import { Model } from 'mongoose';\nimport { IMessage } from '../../models/Message.model';\nimport { SearchMessagesArgs } from '../../types';\nimport { createCursor, parseCursor, PaginatedResult } from '../../utils/pagination';\n\n/**\n * Search messages based on various criteria\n * @param model Message model\n * @param params Search parameters\n * @returns Paginated messages with optional text search results\n */\nexport async function searchMessages(\n model: Model<IMessage>,\n params: SearchMessagesArgs\n): Promise<PaginatedResult<IMessage>> {\n const { \n organizationId,\n query,\n conversationId,\n senderModel,\n senderId,\n kind,\n dateFrom,\n dateTo,\n threadRootId,\n limit = 20,\n cursor\n } = params;\n \n // Base query with required organizationId\n const baseQuery: Record<string, any> = { \n organizationId\n };\n\n // Add optional filters if provided\n if (conversationId) {\n baseQuery.conversationId = conversationId;\n }\n \n if (senderModel && senderId) {\n baseQuery.senderModel = senderModel;\n baseQuery.senderId = senderId;\n } else if (senderModel) {\n baseQuery.senderModel = senderModel;\n }\n \n if (kind) {\n baseQuery.kind = kind;\n }\n \n // Date range filters\n if (dateFrom || dateTo) {\n baseQuery.createdAt = {};\n \n if (dateFrom) {\n baseQuery.createdAt.$gte = new Date(dateFrom);\n }\n \n if (dateTo) {\n baseQuery.createdAt.$lte = new Date(dateTo);\n }\n }\n \n // Thread filter\n if (threadRootId) {\n baseQuery.rootThreadId = threadRootId;\n }\n \n // Handle cursor-based pagination\n if (cursor) {\n const parsedCursor = parseCursor(cursor);\n \n if (parsedCursor) {\n const { timestamp, id } = parsedCursor;\n \n baseQuery.$or = [\n { createdAt: { $lt: new Date(timestamp) } },\n { createdAt: new Date(timestamp), _id: { $lt: id } }\n ];\n }\n }\n \n // Determine sort order and query approach\n let sort: Record<string, number> = { createdAt: -1 };\n let pipeline: any[] = [];\n \n // Use text search if query provided\n if (query && query.trim()) {\n // Set up text search with score and appropriate sort\n pipeline = [\n { $match: { $text: { $search: query }, ...baseQuery } },\n { $addFields: { score: { $meta: 'textScore' } } },\n { $sort: { score: { $meta: 'textScore' }, createdAt: -1 } },\n { $limit: limit + 1 } // Get one extra for pagination\n ];\n } else {\n // Use standard query\n pipeline = [\n { $match: baseQuery },\n { $sort: sort },\n { $limit: limit + 1 } // Get one extra for pagination\n ];\n }\n \n // Execute query\n const items = await model.aggregate(pipeline);\n \n // Check if we have more results\n const hasMore = items.length > limit;\n const limitedItems = hasMore ? items.slice(0, limit) : items;\n \n // Create next cursor if we have more results\n const nextCursor = hasMore && limitedItems.length > 0\n ? createCursor(\n new Date(limitedItems[limitedItems.length - 1].createdAt).getTime(),\n limitedItems[limitedItems.length - 1]._id.toString()\n )\n : null;\n \n return {\n items: limitedItems,\n nextCursor,\n hasMore\n };\n}\n","// Centralized path builders for external data service endpoints\n\nexport const paths = {\n linkedin: {\n startChat: (connectorId: string) => `/actions/linkedin/start_chat/${connectorId}`,\n },\n whatsapp: {\n startChat: (connectorId: string) => `/actions/whatsapp/start_chat/${connectorId}`,\n },\n // Add more services here as needed\n};\n","export type RuntimeConfig = {\n dataServiceEndpoint?: string;\n secretId?: string;\n};\n\nlet runtimeConfig: RuntimeConfig = {};\n\nexport function setRuntimeConfig(cfg: RuntimeConfig) {\n runtimeConfig = { ...runtimeConfig, ...cfg };\n}\n\nexport function getRuntimeConfig(): RuntimeConfig {\n return runtimeConfig;\n}\n","import axios, { AxiosInstance } from 'axios';\nimport { getRuntimeConfig } from './runtime';\n\nlet cachedInstance: AxiosInstance | null = null;\nlet cachedBaseUrl: string | null = null;\nlet cachedSecret: string | null = null;\n\nexport function getAxios(): AxiosInstance {\n const { dataServiceEndpoint, secretId } = getRuntimeConfig();\n if (!dataServiceEndpoint) {\n throw new Error('Data service endpoint not configured');\n }\n\n const baseURL = dataServiceEndpoint.replace(/\\/$/, '');\n\n // Recreate if config changed\n if (!cachedInstance || cachedBaseUrl !== baseURL || cachedSecret !== (secretId || null)) {\n cachedBaseUrl = baseURL;\n cachedSecret = secretId || null;\n\n console.log('Creating axios instance', { baseURL, secretId });\n\n cachedInstance = axios.create({\n baseURL,\n headers: {\n 'Content-Type': 'application/json',\n ...(secretId ? { 'x-api-key': secretId } : {}),\n },\n });\n }\n\n return cachedInstance;\n}\n","import { Model } from 'mongoose';\nimport { IConversation } from '../models/Conversation.model';\nimport { IMessage } from '../models/Message.model';\nimport type { SourceType } from '../models';\nimport { SendMessageArgs, ListMessagesArgs, MarkReadArgs } from '../types';\nimport { searchMessages } from './search/search.messages';\nimport {\n createPaginatedResponse,\n PaginatedResult,\n createCursor,\n parseCursor,\n} from '../utils/pagination';\nimport { paths } from '../config/paths';\nimport { getAxios } from '../config/axios';\n\n/**\n * Message service hooks interface\n */\nexport interface MessageServiceHooks {\n onMessageCreated?: (message: IMessage) => void;\n onMessageRead?: (args: MarkReadArgs & { at: Date }) => void;\n}\n\n/**\n * Message with populated sender information\n */\nexport interface MessageWithSender extends IMessage {\n sender?: Record<string, any>;\n}\n\n/**\n * Service for managing messages\n */\nexport interface MessagesService {\n sendMessage(args: SendMessageArgs): Promise<IMessage>;\n listMessages(args: ListMessagesArgs): Promise<PaginatedResult<IMessage>>;\n listMessagesWithSenders(\n args: ListMessagesArgs & { populateSenders: true },\n ): Promise<PaginatedResult<MessageWithSender>>;\n markRead(args: MarkReadArgs): Promise<void>;\n}\n\n/**\n * Create messages service\n * @param models MongoDB models\n * @param hooks Service hooks\n * @returns Messages service instance\n */\nexport function createMessagesService(\n models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n },\n hooks: MessageServiceHooks = {},\n): MessagesService {\n const { Message, Conversation } = models;\n const { onMessageCreated, onMessageRead } = hooks;\n\n return {\n /**\n * Send a new message\n * @param args Message sending arguments\n * @returns The created message\n */\n async sendMessage(args: SendMessageArgs): Promise<IMessage> {\n const {\n organizationId,\n conversationId,\n senderModel,\n senderId,\n text,\n kind = 'text',\n source,\n parentMessageId,\n rootThreadId,\n connectorIds,\n } = args;\n\n const success_source: SourceType[] = ['core'];\n const failed_source: Array<{ source: string; message: string }> = [];\n\n // Build external calls and run them concurrently\n const tasks: Array<{ name: SourceType; run: () => Promise<any> }> = [];\n\n let lastLinkedInId: string | undefined;\n let lastWhatsAppId: string | undefined;\n\n if (Array.isArray(source) && source.includes('linkedin')) {\n const LinkedinConnector = connectorIds && (connectorIds as any).linkedin;\n lastLinkedInId = LinkedinConnector?.connectorId;\n if (LinkedinConnector) {\n tasks.push({\n name: 'linkedin' as SourceType,\n run: async () => {\n const path = paths.linkedin.startChat(String(LinkedinConnector.connectorId));\n await getAxios().post(path, {\n linkedin_url: LinkedinConnector.contactId,\n text,\n });\n },\n });\n } else {\n failed_source.push({ source: 'linkedin', message: 'Missing connector configuration' });\n }\n }\n\n if (Array.isArray(source) && source.includes('whatsapp')) {\n const whatsappConnector = connectorIds && (connectorIds as any).whatsapp;\n lastWhatsAppId = whatsappConnector?.connectorId;\n\n if (whatsappConnector) {\n tasks.push({\n name: 'whatsapp' as SourceType,\n run: async () => {\n const path = paths.whatsapp.startChat(String(whatsappConnector.connectorId));\n const sanitize = (v: string) => String(v).replace(/\\s+/g, '').replace(/^\\+/, '');\n const raw = whatsappConnector.contactId;\n const body = {\n phone_numbers: sanitize(raw),\n text,\n } as any;\n await getAxios().post(path, body);\n },\n });\n } else {\n failed_source.push({ source: 'whatsapp', message: 'Missing connector configuration' });\n }\n }\n\n if (tasks.length > 0) {\n const results = await Promise.allSettled(tasks.map((t) => t.run()));\n results.forEach((res, idx) => {\n const name = tasks[idx].name;\n if (res.status === 'fulfilled') {\n success_source.push(name);\n } else {\n const err =\n res.reason.response.data.detail || res.reason.response.data || 'Unknown error';\n failed_source.push({\n source: name,\n message: typeof err === 'string' ? err : JSON.stringify(err),\n });\n }\n });\n }\n\n const message = new Message({\n organizationId,\n conversationId,\n senderModel,\n senderId,\n text,\n kind,\n source: success_source,\n parentMessageId,\n rootThreadId: rootThreadId || parentMessageId,\n });\n\n await message.save();\n\n const conversationUpdate: Record<string, any> = {\n lastMessageAt: message.createdAt,\n lastMessagePreview: text.substring(0, 100),\n lastMessageSenderId: senderId,\n lastMessageSenderModel: senderModel,\n };\n\n if (lastLinkedInId) conversationUpdate.lastLinkedInId = lastLinkedInId;\n if (lastWhatsAppId) conversationUpdate.lastWhatsAppId = lastWhatsAppId;\n\n await Conversation.findByIdAndUpdate(conversationId, {\n $set: conversationUpdate,\n });\n if (onMessageCreated) {\n onMessageCreated(message);\n }\n\n (message as any).failed_source = failed_source;\n\n return message;\n },\n\n /**\n * List messages for a conversation with pagination\n * @param args Message listing arguments\n * @returns Paginated list of messages\n */\n async listMessages(args: ListMessagesArgs): Promise<PaginatedResult<IMessage>> {\n const {\n organizationId,\n conversationId,\n limit = 20,\n cursor,\n populateSenders,\n populateOptions,\n } = args;\n\n // If population is requested, delegate to the specialized method\n if (populateSenders) {\n return this.listMessagesWithSenders({\n ...args,\n populateSenders: true,\n });\n }\n\n return searchMessages(Message, {\n organizationId,\n conversationId,\n limit,\n cursor,\n });\n },\n\n /**\n * List messages with populated sender information optimized for infinite scroll\n * @param args Message listing arguments with populate options\n * @returns Paginated list of messages with sender details\n */\n async listMessagesWithSenders(\n args: ListMessagesArgs & { populateSenders: true },\n ): Promise<PaginatedResult<MessageWithSender>> {\n const { organizationId, conversationId, limit = 20, cursor, populateOptions = {} } = args;\n const { fields = '_id name', modelMapping = {} } = populateOptions;\n\n // Create base query for message filtering\n const baseQuery: Record<string, any> = {\n organizationId,\n conversationId,\n };\n\n // Handle cursor-based pagination for infinite scroll\n if (cursor) {\n try {\n const decodedCursor = parseCursor(cursor);\n if (decodedCursor) {\n const { timestamp, id } = decodedCursor;\n\n // Query for messages older than the cursor position\n // This works well for chat interfaces where newer messages are at the bottom\n baseQuery.$or = [\n { createdAt: { $lt: new Date(timestamp) } },\n { createdAt: new Date(timestamp), _id: { $lt: id } },\n ];\n }\n } catch (error) {\n console.error('Failed to parse cursor:', error);\n }\n }\n\n // Get an extra item to determine if there are more messages to load\n const fetchLimit = limit + 1;\n\n // Directly query with sort to efficiently implement infinite scroll\n const messages = await Message.find(baseQuery)\n .sort({ createdAt: -1 })\n .limit(fetchLimit)\n .lean();\n\n // No messages found\n if (messages.length === 0) {\n return {\n items: [],\n hasMore: false,\n nextCursor: null,\n };\n }\n\n // Check if we have more messages available\n const hasMore = messages.length > limit;\n const items = hasMore ? messages.slice(0, limit) : messages;\n\n // Create the next cursor for infinite scroll\n const lastItem = items[items.length - 1];\n const nextCursor = hasMore\n ? createCursor(new Date(lastItem.createdAt).getTime(), lastItem._id.toString())\n : null;\n\n // Extract unique sender IDs by model type\n const sendersByModel: Record<string, Set<string>> = {};\n\n items.forEach((message) => {\n const { senderModel, senderId } = message;\n\n if (!sendersByModel[senderModel]) {\n sendersByModel[senderModel] = new Set<string>();\n }\n\n sendersByModel[senderModel].add(senderId);\n });\n\n // Load all senders in parallel by model type (1 query per model type)\n const mongoose = Message.base;\n const senders: Record<string, Record<string, any>> = {};\n\n await Promise.all(\n Object.entries(sendersByModel).map(async ([senderModel, senderIdsSet]) => {\n const modelName = modelMapping[senderModel] || senderModel;\n const senderIds = Array.from(senderIdsSet);\n\n // Skip if model doesn't exist\n if (!mongoose.modelNames().includes(modelName)) {\n console.warn(`Model ${modelName} not found for sender population`);\n return;\n }\n\n try {\n const SenderModel = mongoose.model(modelName);\n const modelSenders = await SenderModel.find({ _id: { $in: senderIds } })\n .select(fields)\n .lean()\n .exec();\n\n // Create lookup map for this model\n senders[senderModel] = {};\n modelSenders.forEach((sender) => {\n if (sender?._id) senders[senderModel][String(sender._id)] = sender;\n });\n } catch (error) {\n console.error(`Error loading senders for model ${modelName}:`, error);\n }\n }),\n );\n\n // Attach sender data to each message\n const populatedItems = items.map((message) => ({\n ...message,\n sender: senders[message.senderModel]?.[message.senderId] || null,\n })) as MessageWithSender[];\n\n return {\n items: populatedItems,\n hasMore,\n nextCursor,\n };\n },\n\n /**\n * Mark a message as read by a participant\n * @param args Read marking arguments\n */\n async markRead(args: MarkReadArgs): Promise<void> {\n const { organizationId, conversationId, participantModel, participantId, messageId } = args;\n\n const at = new Date();\n\n // Update the message read receipts\n await Message.findOneAndUpdate(\n {\n organizationId,\n conversationId,\n _id: messageId,\n // Ensure read receipt doesn't exist for this participant\n 'readBy.participantId': { $ne: participantId },\n },\n {\n $push: {\n readBy: {\n participantModel,\n participantId,\n readAt: at,\n },\n },\n },\n );\n\n // Update participant last read in conversation\n await Conversation.findOneAndUpdate(\n {\n organizationId,\n _id: conversationId,\n 'participants.entityModel': participantModel,\n 'participants.entityId': participantId,\n },\n {\n $set: {\n 'participants.$.lastReadMessageId': messageId,\n 'participants.$.lastReadAt': at,\n },\n },\n );\n\n // Trigger hook\n if (onMessageRead) {\n onMessageRead({ ...args, at });\n }\n },\n };\n}\n","/**\n * In-memory subscription maps for conversations and sockets\n */\n\n// Maps conversation IDs to sets of socket IDs\nconst convSubs: Map<string, Set<string>> = new Map();\n\n// Maps socket IDs to sets of conversation IDs\nconst socketSubs: Map<string, Set<string>> = new Map();\n\n/**\n * Subscribe a socket to a conversation\n * @param conversationId The conversation ID to subscribe to\n * @param socketId The socket ID to subscribe\n */\nexport function subscribeLocal(conversationId: string, socketId: string): void {\n // Add socket to conversation subscribers\n if (!convSubs.has(conversationId)) {\n convSubs.set(conversationId, new Set());\n }\n convSubs.get(conversationId)?.add(socketId);\n \n // Add conversation to socket subscriptions\n if (!socketSubs.has(socketId)) {\n socketSubs.set(socketId, new Set());\n }\n socketSubs.get(socketId)?.add(conversationId);\n}\n\n/**\n * Unsubscribe a socket from a conversation\n * @param conversationId The conversation ID to unsubscribe from\n * @param socketId The socket ID to unsubscribe\n */\nexport function unsubscribeLocal(conversationId: string, socketId: string): void {\n // Remove socket from conversation subscribers\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n sockets.delete(socketId);\n if (sockets.size === 0) {\n convSubs.delete(conversationId);\n }\n }\n \n // Remove conversation from socket subscriptions\n const conversations = socketSubs.get(socketId);\n if (conversations) {\n conversations.delete(conversationId);\n if (conversations.size === 0) {\n socketSubs.delete(socketId);\n }\n }\n}\n\n/**\n * Clean up all subscriptions for a socket\n * @param socketId The socket ID to clean up\n */\nexport function cleanupLocal(socketId: string): void {\n // Get all conversations this socket is subscribed to\n const conversations = socketSubs.get(socketId);\n if (conversations) {\n // Unsubscribe from each conversation\n for (const conversationId of conversations) {\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n sockets.delete(socketId);\n if (sockets.size === 0) {\n convSubs.delete(conversationId);\n }\n }\n }\n \n // Remove socket from socket subscriptions\n socketSubs.delete(socketId);\n }\n}\n\n/**\n * Fan out a message to all local subscribers of a conversation\n * @param conversationId The conversation ID to fan out to\n * @param payload The payload to send\n * @param emitter Function to emit events to socket IDs\n */\nexport function fanoutLocal(\n conversationId: string,\n payload: any,\n emitter: (toSocketId: string, event: any) => void\n): void {\n // Get all sockets subscribed to this conversation\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n // Emit to each socket\n for (const socketId of sockets) {\n try {\n emitter(socketId, payload);\n } catch (error) {\n console.error(`Error emitting to socket ${socketId}:`, error);\n }\n }\n }\n}","import Redis from 'ioredis';\nimport { RedisConfig } from '../config/env';\n\n// Cache a single Redis client per process to avoid multiple connections under HMR/re-inits\nlet SHARED_CLIENT: Redis | null = null;\nlet SHARED_CFG_FINGERPRINT: string | null = null;\n\n/**\n * Create a Redis client based on provided configuration\n * @param config Redis configuration\n * @returns Redis client instance or null if configuration is missing\n */\nexport function createRedisClient(config?: RedisConfig): Redis | null {\n if (!config) {\n console.warn('Redis configuration not found. Redis features will be disabled.');\n return null;\n }\n \n try {\n // Reuse existing client if config didn't change\n const fingerprint = JSON.stringify({\n url: config.url || null,\n host: config.host || null,\n port: config.port || null,\n db: config.db || null,\n password: Boolean(config.password),\n });\n\n if (SHARED_CLIENT && SHARED_CFG_FINGERPRINT === fingerprint) {\n return SHARED_CLIENT;\n }\n\n let client: Redis;\n \n // Use either URL or granular connection options\n if (config.url) {\n client = new Redis(config.url);\n } else if (config.host) {\n client = new Redis({\n host: config.host,\n port: config.port,\n password: config.password,\n db: config.db,\n connectTimeout: config.socketConnectTimeout, // Changed \n enableReadyCheck: true,\n enableOfflineQueue: true,\n retryStrategy(times) {\n const delay = Math.min(times * 50, 2000);\n return delay;\n }\n });\n } else {\n console.warn('Invalid Redis configuration. Redis features will be disabled.');\n return null;\n }\n \n // Log Redis connection events\n client.on('connect', () => {\n console.info('Redis client connected');\n });\n \n client.on('error', (err) => {\n console.error('Redis client error:', err);\n });\n \n client.on('reconnecting', () => {\n console.info('Redis client reconnecting');\n });\n \n // Cache and return\n SHARED_CLIENT = client;\n SHARED_CFG_FINGERPRINT = fingerprint;\n return SHARED_CLIENT;\n } catch (error) {\n console.error('Failed to create Redis client:', error);\n return null;\n }\n}\n\n/**\n * Publish a message to a conversation channel\n * @param client Redis client\n * @param conversationId Conversation ID\n * @param payload Message payload\n * @returns Promise resolving to number of clients that received the message\n */\nexport async function publishToConversation(\n client: Redis | null,\n conversationId: string,\n payload: any\n): Promise<number> {\n if (!client) return 0;\n \n try {\n const channel = `conv:${conversationId}`;\n const message = JSON.stringify(payload);\n return await client.publish(channel, message);\n } catch (error) {\n console.error(`Failed to publish to conversation ${conversationId}:`, error);\n return 0;\n }\n}\n\n/**\n * Start Redis subscription listener\n * @param client Redis client\n * @param onEvent Callback function for received events\n * @returns Function to stop the listener\n */\nexport function startRedisListener(\n client: Redis | null,\n onEvent: (conversationId: string, payload: any) => void\n): (() => void) | null {\n if (!client) return null;\n \n try {\n // Create a duplicate client for subscribing\n // (Redis clients in subscribe mode cannot be used for other commands)\n const subClient = client.duplicate();\n \n // Subscribe to conversation channels\n subClient.psubscribe('conv:*');\n \n // Handle incoming messages\n subClient.on('pmessage', (_pattern, channel, message) => {\n try {\n // Extract conversation ID from channel\n const conversationId = channel.slice(5); // Remove 'conv:' prefix\n \n // Parse message payload\n const payload = JSON.parse(message);\n \n // Call event handler\n onEvent(conversationId, payload);\n } catch (error) {\n console.error('Error processing Redis message:', error);\n }\n });\n \n // Return function to stop listening\n return () => {\n subClient.punsubscribe('conv:*');\n subClient.quit();\n };\n } catch (error) {\n console.error('Failed to start Redis listener:', error);\n return null;\n }\n}","import type { Server as HTTPServer, IncomingMessage } from 'http';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport type { RawData } from 'ws';\nimport url from 'url';\nimport { Transport } from './index';\n\nexport interface SocketConfig {\n path?: string;\n}\n\nexport interface SocketUser {\n id: string;\n model: string;\n}\n\nexport class SocketTransport {\n // Native WS server and state\n private wss: WebSocketServer;\n private transport: Transport;\n private sockets: Map<string, WebSocket> = new Map();\n private users: Map<string, SocketUser> = new Map();\n private joinedConversations: Map<string, Set<string>> = new Map(); // socketId -> convIds\n\n // Auth handler compatibility shim\n private authenticate?: (socket: any) => Promise<SocketUser | null>;\n\n // Socket.IO-like shim for getIO().sockets.sockets.get(id).emit('chat-event', payload)\n private ioShim = {\n sockets: {\n sockets: new Map<string, { emit: (event: string, payload: any) => void }>(),\n },\n to: (_room: string) => ({\n emit: (_event: string, _payload: any) => {\n // no-op room emitter in shim; we fanout via localSubs instead\n },\n }),\n } as any;\n\n constructor(server: HTTPServer, transport: Transport, config?: SocketConfig) {\n this.wss = new WebSocketServer({ noServer: true });\n this.transport = transport;\n\n const upgradePath = config?.path || '/api/socket';\n const srvAny = server as any;\n if (!srvAny.__wexaWsUpgradeAttached) {\n srvAny.on('upgrade', (request: IncomingMessage, socket: any, head: any) => {\n try {\n const { pathname } = url.parse(request.url || '');\n // Match path and allow query string; ignore other upgrades (HMR, etc.)\n if (!pathname || !pathname.startsWith(upgradePath)) return;\n\n // Only process real WebSocket upgrade requests\n const upgradeHeader = String((request.headers as any)['upgrade'] || '').toLowerCase();\n if (upgradeHeader !== 'websocket') return;\n\n // Ensure we don't crash on socket errors during upgrade\n socket.on?.('error', () => {\n try {\n socket.destroy();\n } catch {}\n });\n\n this.wss.handleUpgrade(request, socket, head, (ws: WebSocket) => {\n this.wss.emit('connection', ws, request);\n });\n } catch {\n try {\n socket?.destroy();\n } catch {}\n }\n });\n srvAny.__wexaWsUpgradeAttached = true;\n }\n\n // Keep ioShim map in sync with sockets map\n const syncShim = () => {\n const m = new Map<string, { emit: (event: string, payload: any) => void }>();\n for (const [id, ws] of this.sockets.entries()) {\n m.set(id, {\n emit: (event: string, payload: any) => {\n if (event !== 'chat-event') return;\n if (ws.readyState === WebSocket.OPEN) {\n try {\n ws.send(JSON.stringify(payload));\n } catch {\n // ignore\n }\n }\n },\n });\n }\n (this.ioShim.sockets as any).sockets = m;\n };\n\n // Heartbeat to keep connections healthy and detect dead peers\n const HEARTBEAT_MS = 30_000;\n const interval = setInterval(() => {\n this.wss.clients.forEach((client) => {\n const c = client as WebSocket & { isAlive?: boolean };\n if (c.isAlive === false) {\n try {\n c.terminate();\n } catch {}\n return;\n }\n c.isAlive = false;\n try {\n c.ping();\n } catch {}\n });\n }, HEARTBEAT_MS);\n this.wss.on('close', () => clearInterval(interval));\n\n // Listen for Redis events and broadcast to local subscribers\n this.transport.startRedisListener((conversationId: string, payload: any) => {\n this.transport.fanoutLocal(conversationId, payload, (toSocketId) => {\n const ws = this.sockets.get(toSocketId);\n if (ws && ws.readyState === WebSocket.OPEN) {\n try {\n ws.send(JSON.stringify(payload));\n } catch {}\n }\n });\n });\n\n // Handle new WS connections\n this.wss.on('connection', (ws: WebSocket, request: IncomingMessage) => {\n const hbWs = ws as WebSocket & { isAlive?: boolean };\n hbWs.isAlive = true;\n hbWs.on('pong', () => {\n hbWs.isAlive = true;\n });\n const parsed = url.parse(request.url || '', true);\n const q = parsed.query || {};\n const userId = typeof q.userId === 'string' ? q.userId : undefined;\n const userModel = typeof q.userModel === 'string' ? q.userModel : 'User';\n\n const socketId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n\n // Build a minimal Socket.IO-like object for authenticate()\n const shimSocket: any = {\n id: socketId,\n handshake: { auth: { userId, userModel } },\n data: {},\n };\n\n const doAccept = (user: SocketUser) => {\n this.sockets.set(socketId, ws);\n this.users.set(socketId, user);\n this.joinedConversations.set(socketId, new Set());\n syncShim();\n\n ws.on('message', (raw: RawData) => {\n try {\n const msg = JSON.parse(raw.toString());\n const type = msg?.type;\n if (type === 'join-conversation' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n this.transport.subscribeLocal(convId, socketId);\n this.joinedConversations.get(socketId)!.add(convId);\n // presence join to others\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'presence:join',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n } else if (type === 'leave-conversation' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n this.transport.unsubscribeLocal(convId, socketId);\n this.joinedConversations.get(socketId)!.delete(convId);\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'presence:leave',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n } else if (type === 'typing' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n const isTyping = !!msg.isTyping;\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'typing',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n state: isTyping ? 'start' : 'stop',\n at: new Date().toISOString(),\n };\n // Emit to others and publish to Redis\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n this.transport.publishToConversation(convId, payload);\n }\n } catch {\n // ignore\n }\n });\n\n ws.on('close', () => {\n const joined = this.joinedConversations.get(socketId);\n if (joined) {\n const u = this.users.get(socketId)!;\n for (const convId of joined) {\n // presence leave to others\n const payload = {\n type: 'presence:leave',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n }\n }\n this.transport.cleanupLocal(socketId);\n this.sockets.delete(socketId);\n this.users.delete(socketId);\n this.joinedConversations.delete(socketId);\n syncShim();\n });\n };\n\n const doReject = () => {\n try {\n ws.close(1008, 'Unauthorized');\n } catch {}\n };\n\n if (this.authenticate) {\n this.authenticate(shimSocket)\n .then((user) => {\n if (user) doAccept(user);\n else doReject();\n })\n .catch(() => doReject());\n } else {\n // If no auth handler, accept only if userId provided\n if (userId) doAccept({ id: userId, model: userModel });\n else doReject();\n }\n });\n }\n\n /**\n * Handle socket authentication\n */\n public handleAuth(authenticate: (socket: any) => Promise<SocketUser | null>) {\n this.authenticate = authenticate;\n }\n\n /**\n * Initialize socket event handlers\n */\n public initialize() {\n // No-op: handlers are set up in constructor for WS server\n }\n\n /**\n * Get Socket.IO server instance\n */\n public getIO(): any {\n return this.ioShim;\n }\n\n /**\n * Close Socket.IO server\n */\n public close(): Promise<void> {\n return new Promise((resolve) => {\n try {\n this.wss.close(() => resolve());\n } catch {\n resolve();\n }\n });\n }\n}\n","import * as localSubs from './localSubs';\nimport { createRedisClient, publishToConversation, startRedisListener } from './redis';\nimport { SocketTransport, SocketConfig } from './socket';\nimport { InitOptions } from '../types';\nimport type { Server as HTTPServer } from 'http';\n\n/**\n * Transport configuration type\n */\nexport interface TransportConfig {\n redis?: InitOptions['redis'];\n socket?: SocketConfig;\n}\n\n/**\n * Transport instance type\n */\nexport interface Transport {\n subscribeLocal: typeof localSubs.subscribeLocal;\n unsubscribeLocal: typeof localSubs.unsubscribeLocal;\n cleanupLocal: typeof localSubs.cleanupLocal;\n fanoutLocal: typeof localSubs.fanoutLocal;\n publishToConversation: (conversationId: string, payload: any) => Promise<number>;\n startRedisListener: (onEvent: (conversationId: string, payload: any) => void) => (() => void) | null;\n}\n\n/**\n * Create transport system with optional Redis and Socket.IO support\n */\nexport function createTransport(\n config?: TransportConfig,\n server?: HTTPServer\n): Transport & { socket?: SocketTransport } {\n // Initialize Redis client if configuration is provided\n const redisClient = config?.redis ? createRedisClient(config.redis) : null;\n \n // Create base transport\n const transport: Transport = {\n // Local subscription methods\n subscribeLocal: localSubs.subscribeLocal,\n unsubscribeLocal: localSubs.unsubscribeLocal,\n cleanupLocal: localSubs.cleanupLocal,\n fanoutLocal: localSubs.fanoutLocal,\n \n // Redis methods\n publishToConversation: (conversationId: string, payload: any) => \n publishToConversation(redisClient, conversationId, payload),\n \n startRedisListener: (onEvent: (conversationId: string, payload: any) => void) => \n startRedisListener(redisClient, onEvent),\n };\n\n // Initialize Socket.IO if server is provided\n if (server) {\n const socketTransport = new SocketTransport(server, transport, config?.socket);\n return {\n ...transport,\n socket: socketTransport\n };\n }\n\n return transport;\n}","import mongoose, { Model } from 'mongoose';\nimport { IConversation } from './Conversation.model';\nimport { IMessage } from './Message.model';\n\n/**\n * Ensure all indexes are created on models\n * @param models Object containing Mongoose models\n */\nexport async function ensureIndexes(models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n}): Promise<void> {\n // Create indexes\n await Promise.all([\n models.Message.ensureIndexes(),\n models.Conversation.ensureIndexes(),\n ]);\n}","/**\n * Redis configuration type\n */\nexport type RedisConfig = {\n url?: string;\n host?: string;\n port?: number;\n password?: string;\n db?: number;\n socketConnectTimeout?: number;\n keepAlive?: number;\n};\n\n/**\n * Environment configuration\n */\nexport interface EnvironmentConfig {\n /** MongoDB connection URI */\n mongoUri: string;\n /** Redis configuration (optional) */\n redis?: RedisConfig;\n}\n/**\n * Get Redis configuration from provided options\n */\nexport function getRedisConfig(config: { redis?: RedisConfig }): RedisConfig | null {\n if (!config.redis) {\n return null;\n }\n\n // Return the full configuration\n return {\n host: config.redis.host || undefined,\n port: config.redis.port || undefined,\n password: config.redis.password || undefined,\n db: config.redis.db || undefined,\n socketConnectTimeout: config.redis.socketConnectTimeout || undefined,\n keepAlive: config.redis.keepAlive || undefined\n };\n}\n","/**\n * Generates a random string ID with the specified length\n * @param length The length of the ID to generate (default: 24)\n * @returns A random string ID\n */\nexport function generateId(length = 24): string {\n const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n const charactersLength = characters.length;\n \n for (let i = 0; i < length; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n \n return result;\n}\n\n/**\n * Creates a conversation ID from two participant identifiers\n * @param a First participant (model:id)\n * @param b Second participant (model:id)\n * @returns A deterministic conversation ID\n */\nexport function createConversationId(\n a: { model: string; id: string },\n b: { model: string; id: string }\n): string {\n // Sort participants to ensure the same ID regardless of order\n const participants = [\n `${a.model}:${a.id}`,\n `${b.model}:${b.id}`,\n ].sort();\n \n return `conv_${participants.join('_')}`;\n}\n\n/**\n * Creates a thread ID\n * @returns A unique thread ID\n */\nexport function createThreadId(): string {\n return `thread_${generateId(16)}`;\n}\n\n/**\n * Creates a message ID\n * @returns A unique message ID\n */\nexport function createMessageId(): string {\n return `msg_${generateId(16)}`;\n}\n\n\n\n\n","import { InitOptions, SendMessageArgs, CreateConversationArgs, MarkReadArgs } from '../types';\n\n/**\n * Validates initialization options\n * @param options Options to validate\n * @returns Validation error message or null if valid\n */\nexport function validateInitOptions(options: InitOptions): string | null {\n if (!options.participantModels || !Array.isArray(options.participantModels) || options.participantModels.length === 0) {\n return 'participantModels must be a non-empty array of strings';\n }\n\n if (!options.memberRoles || !Array.isArray(options.memberRoles) || options.memberRoles.length === 0) {\n return 'memberRoles must be a non-empty array of strings';\n }\n\n // Validate Redis options if provided\n if (options.redis) {\n if (options.redis.url) {\n if (typeof options.redis.url !== 'string') {\n return 'redis.url must be a string';\n }\n } else if (!options.redis.host) {\n return 'Either redis.url or redis.host must be provided';\n }\n }\n\n return null;\n}\n\n/**\n * Validates message sending arguments\n * @param args Message sending arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateSendMessageArgs(args: SendMessageArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.conversationId) {\n return 'conversationId is required';\n }\n\n if (!args.senderModel) {\n return 'senderModel is required';\n }\n\n if (!args.senderId) {\n return 'senderId is required';\n }\n\n if (!args.text || args.text.trim() === '') {\n return 'text is required and cannot be empty';\n }\n\n // If kind is provided, validate it's a valid value\n if (args.kind && !['text', 'system'].includes(args.kind)) {\n return 'kind must be either \"text\" or \"system\"';\n }\n\n // If this is a reply, ensure all thread fields are present\n if (args.parentMessageId && !args.rootThreadId) {\n return 'rootThreadId is required when parentMessageId is provided';\n }\n\n return null;\n}\n\n/**\n * Validates conversation creation arguments\n * @param args Conversation creation arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateCreateConversationArgs(args: CreateConversationArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.a || !args.a.model || !args.a.id) {\n return 'a.model and a.id are required';\n }\n\n if (!args.b || !args.b.model || !args.b.id) {\n return 'b.model and b.id are required';\n }\n\n // Prevent creating a conversation between the same participant\n if (args.a.model === args.b.model && args.a.id === args.b.id) {\n return 'Cannot create a conversation between the same participant';\n }\n\n return null;\n}\n\n/**\n * Validates mark read arguments\n * @param args Mark read arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateMarkReadArgs(args: MarkReadArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.conversationId) {\n return 'conversationId is required';\n }\n\n if (!args.participantModel) {\n return 'participantModel is required';\n }\n\n if (!args.participantId) {\n return 'participantId is required';\n }\n\n if (!args.messageId) {\n return 'messageId is required';\n }\n\n return null;\n}\n\n/**\n * Validates pagination parameters\n * @param limit Pagination limit\n * @param cursor Pagination cursor\n * @returns Validated limit and cursor\n */\nexport function validatePagination(\n limit?: number,\n cursor?: string\n): { limit: number; cursor: string | undefined } {\n // Default limit to 20, max to 100\n let validLimit = limit ? Math.min(Math.max(1, limit), 100) : 20;\n \n // If cursor is provided but empty string, set to undefined\n let validCursor = cursor && cursor.trim() !== '' ? cursor : undefined;\n \n return { limit: validLimit, cursor: validCursor };\n}\n\n\n\n\n","import mongoose from 'mongoose';\nimport type { Server as HTTPServer } from 'http';\nimport { createModels } from './models/connection';\nimport { createConversationsService, ConversationsService } from './services/conversations.service';\nimport { createMessagesService, MessagesService } from './services/messages.service';\nimport { createTransport, Transport } from './transport';\nimport { InitOptions } from './types';\nimport { ensureIndexes } from './models/indexes';\nimport { getRedisConfig } from './config/env';\nimport { SocketTransport } from './transport/socket';\nimport type { IConversation, IMessage } from './models';\nimport { setRuntimeConfig } from './config/runtime';\n\n/**\n * Chat services container\n */\nexport interface ChatServices {\n models: {\n Conversation: mongoose.Model<IConversation>;\n Message: mongoose.Model<IMessage>;\n };\n services: {\n conversations: ConversationsService;\n messages: MessagesService;\n };\n transport: Transport & { socket?: SocketTransport };\n}\n\n/**\n * Initialize the chat system\n * @param mongooseInstance Mongoose instance\n * @param options Initialization options\n * @param server Optional HTTP server for Socket.IO integration\n * @returns Chat services\n */\nexport async function initChat(\n mongooseInstance: typeof mongoose,\n options: InitOptions,\n server?: HTTPServer,\n): Promise<ChatServices> {\n // Persist runtime configuration for global access\n setRuntimeConfig({\n dataServiceEndpoint: options.dataServiceEndpoint,\n secretId: options.secretId,\n });\n\n const models = createModels(mongooseInstance, options);\n\n // Ensure indexes are created\n await ensureIndexes(models);\n\n // Create transport system with optional Socket.IO support\n const transport = createTransport(\n {\n redis: getRedisConfig(options) || undefined,\n socket: options.socket || undefined,\n },\n server,\n );\n\n // Initialize Socket.IO if server was provided\n if (server && transport.socket) {\n // Set up authentication handler\n transport.socket.handleAuth(async (socket) => {\n // Get user info from socket handshake auth\n const userId = socket.handshake.auth.userId;\n const userModel = socket.handshake.auth.userModel || 'User';\n\n if (!userId || !options.participantModels.includes(userModel)) {\n return null;\n }\n\n return { id: userId, model: userModel };\n });\n\n // Initialize socket event handlers\n transport.socket.initialize();\n }\n\n // Create services with hooks\n const services = {\n conversations: createConversationsService(models),\n messages: createMessagesService(models, {\n onMessageCreated: (message) => {\n const payload = { type: 'message:created', message };\n\n // Fan out to local subscribers\n transport.fanoutLocal(message.conversationId.toString(), payload, (socketId, event) => {\n if (transport.socket) {\n const socket = transport.socket.getIO().sockets.sockets.get(socketId);\n if (socket) {\n socket.emit('chat-event', event);\n }\n }\n });\n\n // Publish to Redis for cross-instance communication\n transport.publishToConversation(message.conversationId.toString(), payload);\n },\n\n onMessageRead: (args) => {\n const payload = {\n type: 'conversation:read',\n conversationId: args.conversationId,\n messageId: args.messageId,\n participantModel: args.participantModel,\n participantId: args.participantId,\n at: args.at.toISOString(),\n };\n\n // Fan out to local subscribers\n transport.fanoutLocal(args.conversationId, payload, (socketId, event) => {\n if (transport.socket) {\n const socket = transport.socket.getIO().sockets.sockets.get(socketId);\n if (socket) {\n socket.emit('chat-event', event);\n }\n }\n });\n\n // Publish to Redis for cross-instance communication\n transport.publishToConversation(args.conversationId, payload);\n },\n }),\n };\n\n return { models, services, transport };\n}\n\n// Re-export types\nexport * from './types';\nexport * from './utils';\nexport * from './models';\nexport * from './services';\nexport * from './transport';\nexport * from './config/env';\nexport * from './config/runtime';\n\n// Export Conversation and Message model types for direct access\nexport type { ConversationModel, MessageModel } from './models';\n\n// Export MessageWithSender interface\nexport type { MessageWithSender } from './services/messages.service';\n"]}
1
+ {"version":3,"sources":["../src/models/Conversation.model.ts","../src/models/Message.model.ts","../src/models/connection.ts","../src/utils/pagination.ts","../src/services/search/search.conversations.ts","../src/services/conversations.service.ts","../src/services/search/search.messages.ts","../src/config/paths.ts","../src/config/runtime.ts","../src/config/axios.ts","../src/services/messages.service.ts","../src/transport/localSubs.ts","../src/transport/redis.ts","../src/transport/socket.ts","../src/transport/index.ts","../src/models/indexes.ts","../src/config/env.ts","../src/utils/ids.ts","../src/utils/validators.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Schema as MongooseSchema, Document, Model, Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { modelRegistry } from './connection';\n\nexport interface IConversation extends Document {\n organizationId: string;\n participants: Array<{\n entityModel: string;\n entityId: string;\n role: string;\n }>;\n lastMessageId?: string;\n lastMessageAt?: Date;\n lastMessagePreview?: string;\n lastMessageSenderId?: string;\n lastMessageSenderModel?: string;\n lastLinkedInId?: string;\n lastWhatsAppId?: string;\n linkedinChatId?: string;\n whatsappChatId?: string;\n metadata?: Record<string, any>;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * Create (or retrieve) Conversation model safely\n */\nexport function createConversationModel(\n options: InitOptions,\n conn: Connection,\n): Model<IConversation> {\n // Generate a unique key for the model registry\n const connectionId = conn.id || conn.name || 'default';\n const registryKey = `${connectionId}:Conversation`;\n\n // Return from registry if exists\n if (modelRegistry.has(registryKey)) {\n return modelRegistry.get(registryKey) as Model<IConversation>;\n }\n\n // Check if model already exists on the connection\n const name = 'Conversation';\n if (conn.models[name]) {\n const existingModel = conn.models[name] as Model<IConversation>;\n modelRegistry.set(registryKey, existingModel);\n return existingModel;\n }\n\n // Participant schema (use the Schema from the same mongoose instance as the connection)\n const Schema: typeof MongooseSchema = (conn as any).base.Schema;\n const ParticipantSchema = new Schema(\n {\n entityModel: {\n type: String,\n enum: options.participantModels,\n required: true,\n },\n entityId: {\n type: String,\n required: true,\n },\n role: {\n type: String,\n enum: options.memberRoles,\n required: true,\n },\n },\n { _id: false },\n );\n\n // Conversation schema\n const ConversationSchema = new Schema<IConversation>(\n {\n organizationId: {\n type: String,\n required: true,\n },\n participants: {\n type: [ParticipantSchema],\n required: true,\n validate: {\n validator: function (participants: any[]) {\n return participants.length === 2;\n },\n message: 'Conversations must have exactly 2 participants',\n },\n },\n lastMessageId: {\n type: String,\n ref: 'Message',\n },\n lastMessageAt: {\n type: Date,\n },\n lastMessagePreview: String,\n lastMessageSenderId: String,\n lastMessageSenderModel: String,\n lastLinkedInId: String,\n lastWhatsAppId: String,\n linkedinChatId: String,\n whatsappChatId: String,\n metadata: (Schema as any).Types.Mixed,\n },\n { timestamps: true },\n );\n\n // Create the model\n const model = conn.model<IConversation>(name, ConversationSchema);\n\n // Register the model\n modelRegistry.set(registryKey, model);\n\n return model;\n}\n","import type { Schema as MongooseSchema, Document, Model, Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { modelRegistry } from './connection';\n\nexport const sourceType = {\n LINKEDIN: 'linkedin',\n WHATSAPP: 'whatsapp',\n EMAIL: 'email',\n CORE: 'core',\n} as const;\n\nexport type SourceType = (typeof sourceType)[keyof typeof sourceType];\n\nexport interface IMessage extends Document {\n organizationId: string;\n conversationId: string;\n senderModel: string;\n senderId: string;\n text: string;\n kind: 'text' | 'system';\n source: SourceType[];\n failed_source?: Array<{ source: string; message: string }>;\n parentMessageId?: string;\n rootThreadId?: string;\n editedAt?: Date;\n deletedAt?: Date;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * Create (or retrieve) Message model safely\n */\nexport function createMessageModel(options: InitOptions, conn: Connection): Model<IMessage> {\n // Generate a unique key for the model registry\n const connectionId = conn.id || conn.name || 'default';\n const registryKey = `${connectionId}:Message`;\n\n // Return from registry if exists\n if (modelRegistry.has(registryKey)) {\n return modelRegistry.get(registryKey) as Model<IMessage>;\n }\n\n // Check if model already exists on the connection\n const name = 'Message';\n if (conn.models[name]) {\n const existingModel = conn.models[name] as Model<IMessage>;\n modelRegistry.set(registryKey, existingModel);\n return existingModel;\n }\n\n // Build Schema from the same mongoose instance as the connection\n const Schema: typeof MongooseSchema = (conn as any).base.Schema;\n const MessageSchema = new Schema<IMessage>(\n {\n organizationId: {\n type: String,\n required: true,\n index: true,\n },\n conversationId: {\n type: String,\n required: true,\n index: true,\n },\n senderModel: {\n type: String,\n enum: options.participantModels,\n required: true,\n },\n senderId: {\n type: String,\n required: true,\n index: true,\n },\n kind: {\n type: String,\n enum: ['text', 'system'],\n default: 'text',\n index: true,\n },\n source: {\n type: [String],\n enum: Object.values(sourceType),\n required: true,\n },\n text: {\n type: String,\n trim: true,\n },\n parentMessageId: {\n type: String,\n ref: 'Message',\n },\n rootThreadId: {\n type: String,\n ref: 'Message',\n },\n editedAt: {\n type: Date,\n },\n deletedAt: {\n type: Date,\n },\n },\n { timestamps: true },\n );\n\n // Indexes\n MessageSchema.index({\n organizationId: 1,\n conversationId: 1,\n createdAt: -1,\n });\n\n // Create text search index if enabled\n if (options.enableTextSearch) {\n MessageSchema.index(\n { text: 'text' },\n {\n name: 'text_search',\n weights: { text: 10 },\n },\n );\n }\n\n // Create the model\n const model = conn.model<IMessage>(name, MessageSchema);\n\n // Register the model\n modelRegistry.set(registryKey, model);\n\n return model;\n}\n","import mongoose, { Connection } from 'mongoose';\nimport { InitOptions } from '../types';\nimport { createConversationModel } from './Conversation.model';\nimport { createMessageModel } from './Message.model';\n\n// Global model registry to prevent duplicate compilations\nexport const modelRegistry = new Map<string, mongoose.Model<any>>();\n\n/**\n * Create Mongoose models with applied configuration\n * @param mongooseInstance Mongoose instance\n * @param options Initialization options\n * @returns Object containing Conversation and Message models\n */\nexport function createModels(mongooseInstance: typeof mongoose, options: InitOptions) {\n // Get the connection instance\n const conn: Connection = mongooseInstance.connection;\n\n // Generate a unique connection identifier for this connection\n const connectionId = conn.id || conn.name || 'default';\n \n // Check if models are already registered for this connection\n const registryKey = `${connectionId}:Conversation`;\n const messageRegistryKey = `${connectionId}:Message`;\n \n // Create or reuse models\n const Conversation = modelRegistry.get(registryKey) || createConversationModel(options, conn);\n const Message = modelRegistry.get(messageRegistryKey) || createMessageModel(options, conn);\n \n // Register models if they're new\n if (!modelRegistry.has(registryKey)) {\n modelRegistry.set(registryKey, Conversation);\n }\n \n if (!modelRegistry.has(messageRegistryKey)) {\n modelRegistry.set(messageRegistryKey, Message);\n }\n \n return {\n Conversation,\n Message\n };\n}\n\n/**\n * Connection state enum\n */\nenum ConnectionState {\n Disconnected = 0,\n Connected = 1,\n Connecting = 2,\n Disconnecting = 3,\n}","/**\n * Pagination result interface\n */\nexport interface PaginatedResult<T> {\n items: T[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n/**\n * Creates a pagination cursor from a timestamp and ID\n * @param timestamp Timestamp to encode in the cursor\n * @param id ID to encode in the cursor\n * @returns An encoded cursor string\n */\nexport function createCursor(timestamp: number, id: string): string {\n const cursorData = `${timestamp}:${id}`;\n return Buffer.from(cursorData).toString('base64');\n}\n\n/**\n * Parses a pagination cursor into its timestamp and ID components\n * @param cursor The cursor string to parse\n * @returns An object containing the timestamp and ID, or null if invalid\n */\nexport function parseCursor(cursor: string): { timestamp: number; id: string } | null {\n try {\n const decoded = Buffer.from(cursor, 'base64').toString('utf-8');\n const [timestampStr, id] = decoded.split(':');\n \n const timestamp = parseInt(timestampStr, 10);\n \n if (isNaN(timestamp) || !id) {\n return null;\n }\n \n return { timestamp, id };\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Creates a paginated response\n * @param items The items for the current page\n * @param limit The requested page size\n * @param getNextCursor Function to get the next cursor from the last item\n * @returns A paginated result object\n */\nexport function createPaginatedResponse<T>(\n items: T[],\n limit: number,\n getNextCursor: (lastItem: T) => string\n): PaginatedResult<T> {\n const hasMore = items.length > limit;\n \n // If we have more items than the limit, remove the extra item\n // that we used to determine if there are more pages\n const paginatedItems = hasMore ? items.slice(0, limit) : items;\n \n // Get the next cursor from the last item if we have more items\n const nextCursor = hasMore && paginatedItems.length > 0\n ? getNextCursor(paginatedItems[paginatedItems.length - 1])\n : null;\n \n return {\n items: paginatedItems,\n nextCursor,\n hasMore,\n };\n}\n\n\n\n\n","import { Model } from 'mongoose';\nimport { IConversation } from '../../models/Conversation.model';\nimport { SearchConversationsArgs } from '../../types';\nimport { createCursor, parseCursor, PaginatedResult } from '../../utils/pagination';\n\n/**\n * Search conversations with pagination\n */\nexport async function searchConversations(\n model: Model<IConversation>,\n params: SearchConversationsArgs\n): Promise<PaginatedResult<IConversation>> {\n const { \n organizationId, \n participantModel, \n participantId,\n limit = 20, \n cursor \n } = params;\n \n // Base query with required organizationId\n const baseQuery: Record<string, any> = { \n organizationId \n };\n \n // Add participant filter if provided\n if (participantModel && participantId) {\n baseQuery['participants'] = {\n $elemMatch: {\n entityModel: participantModel,\n entityId: participantId\n }\n };\n }\n \n // Handle cursor-based pagination\n if (cursor) {\n const parsedCursor = parseCursor(cursor);\n \n if (parsedCursor) {\n const { timestamp, id } = parsedCursor;\n const cursorDate = new Date(timestamp);\n \n baseQuery.$or = [\n { lastMessageAt: { $lt: cursorDate } },\n { lastMessageAt: cursorDate, _id: { $lt: id } }\n ];\n }\n }\n \n // Find conversations and sort by lastMessageAt\n const conversations = await model.find(baseQuery)\n .sort({ lastMessageAt: -1 })\n .limit(limit + 1)\n .exec();\n \n // Check if we have more results\n const hasMore = conversations.length > limit;\n const items = hasMore ? conversations.slice(0, limit) : conversations;\n \n // Create next cursor if we have more results\n let nextCursor: string | null = null;\n \n if (hasMore && items.length > 0) {\n const lastItem = items[items.length - 1];\n // Use lastMessageAt if available, otherwise use createdAt\n const timestamp = lastItem.lastMessageAt ? \n lastItem.lastMessageAt.getTime() : \n lastItem.createdAt.getTime();\n \n nextCursor = createCursor(timestamp, lastItem._id.toString());\n }\n \n return {\n items,\n nextCursor,\n hasMore\n };\n}\n\n/**\n * Find a conversation between two specific participants\n */\nexport async function searchByParticipantPair(\n model: Model<IConversation>,\n params: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }\n): Promise<IConversation | null> {\n const { organizationId, a, b } = params;\n \n const conversation = await model.findOne({\n organizationId,\n $and: [\n {\n participants: {\n $elemMatch: {\n entityModel: a.model,\n entityId: a.id\n }\n }\n },\n {\n participants: {\n $elemMatch: {\n entityModel: b.model,\n entityId: b.id\n }\n }\n },\n {\n $expr: {\n $eq: [{ $size: \"$participants\" }, 2]\n }\n }\n ]\n });\n \n return conversation;\n}","import { Model } from 'mongoose';\nimport { IConversation } from '../models/Conversation.model';\nimport { IMessage } from '../models/Message.model';\nimport { CreateConversationArgs, SearchConversationsArgs } from '../types';\nimport { searchConversations, searchByParticipantPair } from './search/search.conversations';\nimport { PaginatedResult } from '../utils/pagination';\n\n/**\n * Service for managing conversations\n */\nexport interface ConversationsService {\n createOrFindConversation(args: CreateConversationArgs): Promise<IConversation>;\n getConversation(organizationId: string, conversationId: string): Promise<IConversation | null>;\n searchConversations(args: SearchConversationsArgs): Promise<PaginatedResult<IConversation>>;\n searchByParticipantPair(args: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }): Promise<IConversation | null>;\n}\n\n/**\n * Create conversations service\n * @param models MongoDB models\n * @returns Conversations service instance\n */\nexport function createConversationsService(models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n}): ConversationsService {\n const { Conversation } = models;\n\n return {\n /**\n * Create a new conversation or find existing one between participants\n */\n async createOrFindConversation(args: CreateConversationArgs): Promise<IConversation> {\n console.log('Creating or finding conversation for users:', {\n args,\n });\n const { organizationId, a, b } = args;\n console.log('Creating or finding conversation for users:', {\n organizationId,\n a,\n b,\n });\n\n try {\n console.log('asdfa');\n // Check if conversation already exists between these participants\n const existingConversation = await searchByParticipantPair(Conversation, {\n organizationId,\n a,\n b,\n });\n\n console.log('Existing conversation:', existingConversation);\n if (existingConversation) {\n return existingConversation;\n }\n\n // Create new conversation\n const newConversation = new Conversation({\n organizationId,\n participants: [\n {\n entityModel: a.model,\n entityId: a.id,\n role: 'member', // Default role\n },\n {\n entityModel: b.model,\n entityId: b.id,\n role: 'member', // Default role\n },\n ],\n lastMessageAt: new Date(), // Set initial lastMessageAt\n });\n\n console.log('New conversation:', newConversation);\n\n await newConversation.save();\n console.log('Saved conversation:', newConversation);\n return newConversation;\n } catch (error) {\n console.error('Error in createOrFindConversation:', error);\n throw error;\n }\n },\n\n /**\n * Get a conversation by ID\n */\n async getConversation(\n organizationId: string,\n conversationId: string,\n ): Promise<IConversation | null> {\n try {\n return await Conversation.findOne({\n organizationId,\n _id: conversationId,\n });\n } catch (error) {\n console.error('Error in getConversation:', error);\n throw error;\n }\n },\n\n /**\n * Search conversations with pagination\n */\n async searchConversations(\n args: SearchConversationsArgs,\n ): Promise<PaginatedResult<IConversation>> {\n try {\n return await searchConversations(Conversation, args);\n } catch (error) {\n console.error('Error in searchConversations:', error);\n throw error;\n }\n },\n\n /**\n * Find a conversation between two specific participants\n */\n async searchByParticipantPair(args: {\n organizationId: string;\n a: { model: string; id: string };\n b: { model: string; id: string };\n }): Promise<IConversation | null> {\n try {\n return await searchByParticipantPair(Conversation, args);\n } catch (error) {\n console.error('Error in searchByParticipantPair:', error);\n throw error;\n }\n },\n };\n}\n","import { Model } from 'mongoose';\nimport { IMessage } from '../../models/Message.model';\nimport { SearchMessagesArgs } from '../../types';\nimport { createCursor, parseCursor, PaginatedResult } from '../../utils/pagination';\n\n/**\n * Search messages based on various criteria\n * @param model Message model\n * @param params Search parameters\n * @returns Paginated messages with optional text search results\n */\nexport async function searchMessages(\n model: Model<IMessage>,\n params: SearchMessagesArgs\n): Promise<PaginatedResult<IMessage>> {\n const { \n organizationId,\n query,\n conversationId,\n senderModel,\n senderId,\n kind,\n dateFrom,\n dateTo,\n threadRootId,\n limit = 20,\n cursor\n } = params;\n \n // Base query with required organizationId\n const baseQuery: Record<string, any> = { \n organizationId\n };\n\n // Add optional filters if provided\n if (conversationId) {\n baseQuery.conversationId = conversationId;\n }\n \n if (senderModel && senderId) {\n baseQuery.senderModel = senderModel;\n baseQuery.senderId = senderId;\n } else if (senderModel) {\n baseQuery.senderModel = senderModel;\n }\n \n if (kind) {\n baseQuery.kind = kind;\n }\n \n // Date range filters\n if (dateFrom || dateTo) {\n baseQuery.createdAt = {};\n \n if (dateFrom) {\n baseQuery.createdAt.$gte = new Date(dateFrom);\n }\n \n if (dateTo) {\n baseQuery.createdAt.$lte = new Date(dateTo);\n }\n }\n \n // Thread filter\n if (threadRootId) {\n baseQuery.rootThreadId = threadRootId;\n }\n \n // Handle cursor-based pagination\n if (cursor) {\n const parsedCursor = parseCursor(cursor);\n \n if (parsedCursor) {\n const { timestamp, id } = parsedCursor;\n \n baseQuery.$or = [\n { createdAt: { $lt: new Date(timestamp) } },\n { createdAt: new Date(timestamp), _id: { $lt: id } }\n ];\n }\n }\n \n // Determine sort order and query approach\n let sort: Record<string, number> = { createdAt: -1 };\n let pipeline: any[] = [];\n \n // Use text search if query provided\n if (query && query.trim()) {\n // Set up text search with score and appropriate sort\n pipeline = [\n { $match: { $text: { $search: query }, ...baseQuery } },\n { $addFields: { score: { $meta: 'textScore' } } },\n { $sort: { score: { $meta: 'textScore' }, createdAt: -1 } },\n { $limit: limit + 1 } // Get one extra for pagination\n ];\n } else {\n // Use standard query\n pipeline = [\n { $match: baseQuery },\n { $sort: sort },\n { $limit: limit + 1 } // Get one extra for pagination\n ];\n }\n \n // Execute query\n const items = await model.aggregate(pipeline);\n \n // Check if we have more results\n const hasMore = items.length > limit;\n const limitedItems = hasMore ? items.slice(0, limit) : items;\n \n // Create next cursor if we have more results\n const nextCursor = hasMore && limitedItems.length > 0\n ? createCursor(\n new Date(limitedItems[limitedItems.length - 1].createdAt).getTime(),\n limitedItems[limitedItems.length - 1]._id.toString()\n )\n : null;\n \n return {\n items: limitedItems,\n nextCursor,\n hasMore\n };\n}\n","// Centralized path builders for external data service endpoints\n\nexport const paths = {\n linkedin: {\n startChat: (connectorId: string) => `/actions/linkedin/start_chat/${connectorId}`,\n },\n whatsapp: {\n startChat: (connectorId: string) => `/actions/whatsapp/start_chat/${connectorId}`,\n },\n // Add more services here as needed\n};\n","export type RuntimeConfig = {\n dataServiceEndpoint?: string;\n secretId?: string;\n};\n\nlet runtimeConfig: RuntimeConfig = {};\n\nexport function setRuntimeConfig(cfg: RuntimeConfig) {\n runtimeConfig = { ...runtimeConfig, ...cfg };\n}\n\nexport function getRuntimeConfig(): RuntimeConfig {\n return runtimeConfig;\n}\n","import axios, { AxiosInstance } from 'axios';\nimport { getRuntimeConfig } from './runtime';\n\nlet cachedInstance: AxiosInstance | null = null;\nlet cachedBaseUrl: string | null = null;\nlet cachedSecret: string | null = null;\n\nexport function getAxios(): AxiosInstance {\n const { dataServiceEndpoint, secretId } = getRuntimeConfig();\n if (!dataServiceEndpoint) {\n throw new Error('Data service endpoint not configured');\n }\n\n const baseURL = dataServiceEndpoint.replace(/\\/$/, '');\n\n // Recreate if config changed\n if (!cachedInstance || cachedBaseUrl !== baseURL || cachedSecret !== (secretId || null)) {\n cachedBaseUrl = baseURL;\n cachedSecret = secretId || null;\n\n console.log('Creating axios instance', { baseURL, secretId });\n\n cachedInstance = axios.create({\n baseURL,\n headers: {\n 'Content-Type': 'application/json',\n ...(secretId ? { 'x-api-key': secretId } : {}),\n },\n });\n }\n\n return cachedInstance;\n}\n","import { Model } from 'mongoose';\nimport { IConversation } from '../models/Conversation.model';\nimport { IMessage } from '../models/Message.model';\nimport type { SourceType } from '../models';\nimport { SendMessageArgs, ListMessagesArgs, MarkReadArgs } from '../types';\nimport { searchMessages } from './search/search.messages';\nimport {\n createPaginatedResponse,\n PaginatedResult,\n createCursor,\n parseCursor,\n} from '../utils/pagination';\nimport { paths } from '../config/paths';\nimport { getAxios } from '../config/axios';\n\n/**\n * Message service hooks interface\n */\nexport interface MessageServiceHooks {\n onMessageCreated?: (message: IMessage) => void;\n onMessageRead?: (args: MarkReadArgs & { at: Date }) => void;\n}\n\n/**\n * Message with populated sender information\n */\nexport interface MessageWithSender extends IMessage {\n sender?: Record<string, any>;\n}\n\n/**\n * Service for managing messages\n */\nexport interface MessagesService {\n sendMessage(args: SendMessageArgs): Promise<IMessage>;\n listMessages(args: ListMessagesArgs): Promise<PaginatedResult<IMessage>>;\n listMessagesWithSenders(\n args: ListMessagesArgs & { populateSenders: true },\n ): Promise<PaginatedResult<MessageWithSender>>;\n markRead(args: MarkReadArgs): Promise<void>;\n}\n\n/**\n * Create messages service\n * @param models MongoDB models\n * @param hooks Service hooks\n * @returns Messages service instance\n */\nexport function createMessagesService(\n models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n },\n hooks: MessageServiceHooks = {},\n): MessagesService {\n const { Message, Conversation } = models;\n const { onMessageCreated, onMessageRead } = hooks;\n\n return {\n /**\n * Send a new message\n * @param args Message sending arguments\n * @returns The created message\n */\n async sendMessage(args: SendMessageArgs): Promise<IMessage> {\n const {\n organizationId,\n conversationId,\n senderModel,\n senderId,\n text,\n kind = 'text',\n source,\n parentMessageId,\n rootThreadId,\n connectorIds,\n } = args;\n\n const success_source: SourceType[] = ['core'];\n const failed_source: Array<{ source: string; message: string }> = [];\n\n // Build external calls and run them concurrently\n const tasks: Array<{ name: SourceType; run: () => Promise<any> }> = [];\n\n let lastLinkedInId: string | undefined;\n let lastWhatsAppId: string | undefined;\n\n if (Array.isArray(source) && source.includes('linkedin')) {\n const LinkedinConnector = connectorIds && (connectorIds as any).linkedin;\n lastLinkedInId = LinkedinConnector?.connectorId;\n if (LinkedinConnector) {\n tasks.push({\n name: 'linkedin' as SourceType,\n run: async () => {\n const path = paths.linkedin.startChat(String(LinkedinConnector.connectorId));\n await getAxios().post(path, {\n linkedin_url: LinkedinConnector.contactId,\n text,\n });\n },\n });\n } else {\n failed_source.push({ source: 'linkedin', message: 'Missing connector configuration' });\n }\n }\n\n if (Array.isArray(source) && source.includes('whatsapp')) {\n const whatsappConnector = connectorIds && (connectorIds as any).whatsapp;\n lastWhatsAppId = whatsappConnector?.connectorId;\n\n if (whatsappConnector) {\n tasks.push({\n name: 'whatsapp' as SourceType,\n run: async () => {\n const path = paths.whatsapp.startChat(String(whatsappConnector.connectorId));\n const sanitize = (v: string) => String(v).replace(/\\s+/g, '').replace(/^\\+/, '');\n const raw = whatsappConnector.contactId;\n const body = {\n phone_numbers: sanitize(raw),\n text,\n } as any;\n await getAxios().post(path, body);\n },\n });\n } else {\n failed_source.push({ source: 'whatsapp', message: 'Missing connector configuration' });\n }\n }\n\n if (tasks.length > 0) {\n const results = await Promise.allSettled(tasks.map((t) => t.run()));\n results.forEach((res, idx) => {\n const name = tasks[idx].name;\n if (res.status === 'fulfilled') {\n success_source.push(name);\n } else {\n const err = success_source;\n res.reason.response.data.detail || res.reason.response.data || 'Unknown error';\n failed_source.push({\n source: name,\n message: typeof err === 'string' ? err : JSON.stringify(err),\n });\n }\n });\n console.log('results', results);\n }\n\n console.log('success_source', success_source);\n const message = new Message({\n organizationId,\n conversationId,\n senderModel,\n senderId,\n text,\n kind,\n source: success_source,\n parentMessageId,\n rootThreadId: rootThreadId || parentMessageId,\n });\n\n await message.save();\n\n const conversationUpdate: Record<string, any> = {\n lastMessageAt: message.createdAt,\n lastMessagePreview: text.substring(0, 100),\n lastMessageSenderId: senderId,\n lastMessageSenderModel: senderModel,\n };\n\n if (lastLinkedInId) conversationUpdate.lastLinkedInId = lastLinkedInId;\n if (lastWhatsAppId) conversationUpdate.lastWhatsAppId = lastWhatsAppId;\n\n await Conversation.findByIdAndUpdate(conversationId, {\n $set: conversationUpdate,\n });\n if (onMessageCreated) {\n onMessageCreated(message);\n }\n\n (message as any).failed_source = failed_source;\n\n return message;\n },\n\n /**\n * List messages for a conversation with pagination\n * @param args Message listing arguments\n * @returns Paginated list of messages\n */\n async listMessages(args: ListMessagesArgs): Promise<PaginatedResult<IMessage>> {\n const {\n organizationId,\n conversationId,\n limit = 20,\n cursor,\n populateSenders,\n populateOptions,\n } = args;\n\n // If population is requested, delegate to the specialized method\n if (populateSenders) {\n return this.listMessagesWithSenders({\n ...args,\n populateSenders: true,\n });\n }\n\n return searchMessages(Message, {\n organizationId,\n conversationId,\n limit,\n cursor,\n });\n },\n\n /**\n * List messages with populated sender information optimized for infinite scroll\n * @param args Message listing arguments with populate options\n * @returns Paginated list of messages with sender details\n */\n async listMessagesWithSenders(\n args: ListMessagesArgs & { populateSenders: true },\n ): Promise<PaginatedResult<MessageWithSender>> {\n const { organizationId, conversationId, limit = 20, cursor, populateOptions = {} } = args;\n const { fields = '_id name', modelMapping = {} } = populateOptions;\n\n // Create base query for message filtering\n const baseQuery: Record<string, any> = {\n organizationId,\n conversationId,\n };\n\n // Handle cursor-based pagination for infinite scroll\n if (cursor) {\n try {\n const decodedCursor = parseCursor(cursor);\n if (decodedCursor) {\n const { timestamp, id } = decodedCursor;\n\n // Query for messages older than the cursor position\n // This works well for chat interfaces where newer messages are at the bottom\n baseQuery.$or = [\n { createdAt: { $lt: new Date(timestamp) } },\n { createdAt: new Date(timestamp), _id: { $lt: id } },\n ];\n }\n } catch (error) {\n console.error('Failed to parse cursor:', error);\n }\n }\n\n // Get an extra item to determine if there are more messages to load\n const fetchLimit = limit + 1;\n\n // Directly query with sort to efficiently implement infinite scroll\n const messages = await Message.find(baseQuery)\n .sort({ createdAt: -1 })\n .limit(fetchLimit)\n .lean();\n\n // No messages found\n if (messages.length === 0) {\n return {\n items: [],\n hasMore: false,\n nextCursor: null,\n };\n }\n\n // Check if we have more messages available\n const hasMore = messages.length > limit;\n const items = hasMore ? messages.slice(0, limit) : messages;\n\n // Create the next cursor for infinite scroll\n const lastItem = items[items.length - 1];\n const nextCursor = hasMore\n ? createCursor(new Date(lastItem.createdAt).getTime(), lastItem._id.toString())\n : null;\n\n // Extract unique sender IDs by model type\n const sendersByModel: Record<string, Set<string>> = {};\n\n items.forEach((message) => {\n const { senderModel, senderId } = message;\n\n if (!sendersByModel[senderModel]) {\n sendersByModel[senderModel] = new Set<string>();\n }\n\n sendersByModel[senderModel].add(senderId);\n });\n\n // Load all senders in parallel by model type (1 query per model type)\n const mongoose = Message.base;\n const senders: Record<string, Record<string, any>> = {};\n\n await Promise.all(\n Object.entries(sendersByModel).map(async ([senderModel, senderIdsSet]) => {\n const modelName = modelMapping[senderModel] || senderModel;\n const senderIds = Array.from(senderIdsSet);\n\n // Skip if model doesn't exist\n if (!mongoose.modelNames().includes(modelName)) {\n console.warn(`Model ${modelName} not found for sender population`);\n return;\n }\n\n try {\n const SenderModel = mongoose.model(modelName);\n const modelSenders = await SenderModel.find({ _id: { $in: senderIds } })\n .select(fields)\n .lean()\n .exec();\n\n // Create lookup map for this model\n senders[senderModel] = {};\n modelSenders.forEach((sender) => {\n if (sender?._id) senders[senderModel][String(sender._id)] = sender;\n });\n } catch (error) {\n console.error(`Error loading senders for model ${modelName}:`, error);\n }\n }),\n );\n\n // Attach sender data to each message\n const populatedItems = items.map((message) => ({\n ...message,\n sender: senders[message.senderModel]?.[message.senderId] || null,\n })) as MessageWithSender[];\n\n return {\n items: populatedItems,\n hasMore,\n nextCursor,\n };\n },\n\n /**\n * Mark a message as read by a participant\n * @param args Read marking arguments\n */\n async markRead(args: MarkReadArgs): Promise<void> {\n const { organizationId, conversationId, participantModel, participantId, messageId } = args;\n\n const at = new Date();\n\n // Update the message read receipts\n await Message.findOneAndUpdate(\n {\n organizationId,\n conversationId,\n _id: messageId,\n // Ensure read receipt doesn't exist for this participant\n 'readBy.participantId': { $ne: participantId },\n },\n {\n $push: {\n readBy: {\n participantModel,\n participantId,\n readAt: at,\n },\n },\n },\n );\n\n // Update participant last read in conversation\n await Conversation.findOneAndUpdate(\n {\n organizationId,\n _id: conversationId,\n 'participants.entityModel': participantModel,\n 'participants.entityId': participantId,\n },\n {\n $set: {\n 'participants.$.lastReadMessageId': messageId,\n 'participants.$.lastReadAt': at,\n },\n },\n );\n\n // Trigger hook\n if (onMessageRead) {\n onMessageRead({ ...args, at });\n }\n },\n };\n}\n","/**\n * In-memory subscription maps for conversations and sockets\n */\n\n// Maps conversation IDs to sets of socket IDs\nconst convSubs: Map<string, Set<string>> = new Map();\n\n// Maps socket IDs to sets of conversation IDs\nconst socketSubs: Map<string, Set<string>> = new Map();\n\n/**\n * Subscribe a socket to a conversation\n * @param conversationId The conversation ID to subscribe to\n * @param socketId The socket ID to subscribe\n */\nexport function subscribeLocal(conversationId: string, socketId: string): void {\n // Add socket to conversation subscribers\n if (!convSubs.has(conversationId)) {\n convSubs.set(conversationId, new Set());\n }\n convSubs.get(conversationId)?.add(socketId);\n \n // Add conversation to socket subscriptions\n if (!socketSubs.has(socketId)) {\n socketSubs.set(socketId, new Set());\n }\n socketSubs.get(socketId)?.add(conversationId);\n}\n\n/**\n * Unsubscribe a socket from a conversation\n * @param conversationId The conversation ID to unsubscribe from\n * @param socketId The socket ID to unsubscribe\n */\nexport function unsubscribeLocal(conversationId: string, socketId: string): void {\n // Remove socket from conversation subscribers\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n sockets.delete(socketId);\n if (sockets.size === 0) {\n convSubs.delete(conversationId);\n }\n }\n \n // Remove conversation from socket subscriptions\n const conversations = socketSubs.get(socketId);\n if (conversations) {\n conversations.delete(conversationId);\n if (conversations.size === 0) {\n socketSubs.delete(socketId);\n }\n }\n}\n\n/**\n * Clean up all subscriptions for a socket\n * @param socketId The socket ID to clean up\n */\nexport function cleanupLocal(socketId: string): void {\n // Get all conversations this socket is subscribed to\n const conversations = socketSubs.get(socketId);\n if (conversations) {\n // Unsubscribe from each conversation\n for (const conversationId of conversations) {\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n sockets.delete(socketId);\n if (sockets.size === 0) {\n convSubs.delete(conversationId);\n }\n }\n }\n \n // Remove socket from socket subscriptions\n socketSubs.delete(socketId);\n }\n}\n\n/**\n * Fan out a message to all local subscribers of a conversation\n * @param conversationId The conversation ID to fan out to\n * @param payload The payload to send\n * @param emitter Function to emit events to socket IDs\n */\nexport function fanoutLocal(\n conversationId: string,\n payload: any,\n emitter: (toSocketId: string, event: any) => void\n): void {\n // Get all sockets subscribed to this conversation\n const sockets = convSubs.get(conversationId);\n if (sockets) {\n // Emit to each socket\n for (const socketId of sockets) {\n try {\n emitter(socketId, payload);\n } catch (error) {\n console.error(`Error emitting to socket ${socketId}:`, error);\n }\n }\n }\n}","import Redis from 'ioredis';\nimport { RedisConfig } from '../config/env';\n\n// Cache a single Redis client per process to avoid multiple connections under HMR/re-inits\nlet SHARED_CLIENT: Redis | null = null;\nlet SHARED_CFG_FINGERPRINT: string | null = null;\n\n/**\n * Create a Redis client based on provided configuration\n * @param config Redis configuration\n * @returns Redis client instance or null if configuration is missing\n */\nexport function createRedisClient(config?: RedisConfig): Redis | null {\n if (!config) {\n console.warn('Redis configuration not found. Redis features will be disabled.');\n return null;\n }\n \n try {\n // Reuse existing client if config didn't change\n const fingerprint = JSON.stringify({\n url: config.url || null,\n host: config.host || null,\n port: config.port || null,\n db: config.db || null,\n password: Boolean(config.password),\n });\n\n if (SHARED_CLIENT && SHARED_CFG_FINGERPRINT === fingerprint) {\n return SHARED_CLIENT;\n }\n\n let client: Redis;\n \n // Use either URL or granular connection options\n if (config.url) {\n client = new Redis(config.url);\n } else if (config.host) {\n client = new Redis({\n host: config.host,\n port: config.port,\n password: config.password,\n db: config.db,\n connectTimeout: config.socketConnectTimeout, // Changed \n enableReadyCheck: true,\n enableOfflineQueue: true,\n retryStrategy(times) {\n const delay = Math.min(times * 50, 2000);\n return delay;\n }\n });\n } else {\n console.warn('Invalid Redis configuration. Redis features will be disabled.');\n return null;\n }\n \n // Log Redis connection events\n client.on('connect', () => {\n console.info('Redis client connected');\n });\n \n client.on('error', (err) => {\n console.error('Redis client error:', err);\n });\n \n client.on('reconnecting', () => {\n console.info('Redis client reconnecting');\n });\n \n // Cache and return\n SHARED_CLIENT = client;\n SHARED_CFG_FINGERPRINT = fingerprint;\n return SHARED_CLIENT;\n } catch (error) {\n console.error('Failed to create Redis client:', error);\n return null;\n }\n}\n\n/**\n * Publish a message to a conversation channel\n * @param client Redis client\n * @param conversationId Conversation ID\n * @param payload Message payload\n * @returns Promise resolving to number of clients that received the message\n */\nexport async function publishToConversation(\n client: Redis | null,\n conversationId: string,\n payload: any\n): Promise<number> {\n if (!client) return 0;\n \n try {\n const channel = `conv:${conversationId}`;\n const message = JSON.stringify(payload);\n return await client.publish(channel, message);\n } catch (error) {\n console.error(`Failed to publish to conversation ${conversationId}:`, error);\n return 0;\n }\n}\n\n/**\n * Start Redis subscription listener\n * @param client Redis client\n * @param onEvent Callback function for received events\n * @returns Function to stop the listener\n */\nexport function startRedisListener(\n client: Redis | null,\n onEvent: (conversationId: string, payload: any) => void\n): (() => void) | null {\n if (!client) return null;\n \n try {\n // Create a duplicate client for subscribing\n // (Redis clients in subscribe mode cannot be used for other commands)\n const subClient = client.duplicate();\n \n // Subscribe to conversation channels\n subClient.psubscribe('conv:*');\n \n // Handle incoming messages\n subClient.on('pmessage', (_pattern, channel, message) => {\n try {\n // Extract conversation ID from channel\n const conversationId = channel.slice(5); // Remove 'conv:' prefix\n \n // Parse message payload\n const payload = JSON.parse(message);\n \n // Call event handler\n onEvent(conversationId, payload);\n } catch (error) {\n console.error('Error processing Redis message:', error);\n }\n });\n \n // Return function to stop listening\n return () => {\n subClient.punsubscribe('conv:*');\n subClient.quit();\n };\n } catch (error) {\n console.error('Failed to start Redis listener:', error);\n return null;\n }\n}","import type { Server as HTTPServer, IncomingMessage } from 'http';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport type { RawData } from 'ws';\nimport url from 'url';\nimport { Transport } from './index';\n\nexport interface SocketConfig {\n path?: string;\n}\n\nexport interface SocketUser {\n id: string;\n model: string;\n}\n\nexport class SocketTransport {\n // Native WS server and state\n private wss: WebSocketServer;\n private transport: Transport;\n private sockets: Map<string, WebSocket> = new Map();\n private users: Map<string, SocketUser> = new Map();\n private joinedConversations: Map<string, Set<string>> = new Map(); // socketId -> convIds\n\n // Auth handler compatibility shim\n private authenticate?: (socket: any) => Promise<SocketUser | null>;\n\n // Socket.IO-like shim for getIO().sockets.sockets.get(id).emit('chat-event', payload)\n private ioShim = {\n sockets: {\n sockets: new Map<string, { emit: (event: string, payload: any) => void }>(),\n },\n to: (_room: string) => ({\n emit: (_event: string, _payload: any) => {\n // no-op room emitter in shim; we fanout via localSubs instead\n },\n }),\n } as any;\n\n constructor(server: HTTPServer, transport: Transport, config?: SocketConfig) {\n this.wss = new WebSocketServer({ noServer: true });\n this.transport = transport;\n\n const upgradePath = config?.path || '/api/socket';\n const srvAny = server as any;\n if (!srvAny.__wexaWsUpgradeAttached) {\n srvAny.on('upgrade', (request: IncomingMessage, socket: any, head: any) => {\n try {\n const { pathname } = url.parse(request.url || '');\n // Match path and allow query string; ignore other upgrades (HMR, etc.)\n if (!pathname || !pathname.startsWith(upgradePath)) return;\n\n // Only process real WebSocket upgrade requests\n const upgradeHeader = String((request.headers as any)['upgrade'] || '').toLowerCase();\n if (upgradeHeader !== 'websocket') return;\n\n // Ensure we don't crash on socket errors during upgrade\n socket.on?.('error', () => {\n try {\n socket.destroy();\n } catch {}\n });\n\n this.wss.handleUpgrade(request, socket, head, (ws: WebSocket) => {\n this.wss.emit('connection', ws, request);\n });\n } catch {\n try {\n socket?.destroy();\n } catch {}\n }\n });\n srvAny.__wexaWsUpgradeAttached = true;\n }\n\n // Keep ioShim map in sync with sockets map\n const syncShim = () => {\n const m = new Map<string, { emit: (event: string, payload: any) => void }>();\n for (const [id, ws] of this.sockets.entries()) {\n m.set(id, {\n emit: (event: string, payload: any) => {\n if (event !== 'chat-event') return;\n if (ws.readyState === WebSocket.OPEN) {\n try {\n ws.send(JSON.stringify(payload));\n } catch {\n // ignore\n }\n }\n },\n });\n }\n (this.ioShim.sockets as any).sockets = m;\n };\n\n // Heartbeat to keep connections healthy and detect dead peers\n const HEARTBEAT_MS = 30_000;\n const interval = setInterval(() => {\n this.wss.clients.forEach((client) => {\n const c = client as WebSocket & { isAlive?: boolean };\n if (c.isAlive === false) {\n try {\n c.terminate();\n } catch {}\n return;\n }\n c.isAlive = false;\n try {\n c.ping();\n } catch {}\n });\n }, HEARTBEAT_MS);\n this.wss.on('close', () => clearInterval(interval));\n\n // Listen for Redis events and broadcast to local subscribers\n this.transport.startRedisListener((conversationId: string, payload: any) => {\n this.transport.fanoutLocal(conversationId, payload, (toSocketId) => {\n const ws = this.sockets.get(toSocketId);\n if (ws && ws.readyState === WebSocket.OPEN) {\n try {\n ws.send(JSON.stringify(payload));\n } catch {}\n }\n });\n });\n\n // Handle new WS connections\n this.wss.on('connection', (ws: WebSocket, request: IncomingMessage) => {\n const hbWs = ws as WebSocket & { isAlive?: boolean };\n hbWs.isAlive = true;\n hbWs.on('pong', () => {\n hbWs.isAlive = true;\n });\n const parsed = url.parse(request.url || '', true);\n const q = parsed.query || {};\n const userId = typeof q.userId === 'string' ? q.userId : undefined;\n const userModel = typeof q.userModel === 'string' ? q.userModel : 'User';\n\n const socketId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n\n // Build a minimal Socket.IO-like object for authenticate()\n const shimSocket: any = {\n id: socketId,\n handshake: { auth: { userId, userModel } },\n data: {},\n };\n\n const doAccept = (user: SocketUser) => {\n this.sockets.set(socketId, ws);\n this.users.set(socketId, user);\n this.joinedConversations.set(socketId, new Set());\n syncShim();\n\n ws.on('message', (raw: RawData) => {\n try {\n const msg = JSON.parse(raw.toString());\n const type = msg?.type;\n if (type === 'join-conversation' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n this.transport.subscribeLocal(convId, socketId);\n this.joinedConversations.get(socketId)!.add(convId);\n // presence join to others\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'presence:join',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n } else if (type === 'leave-conversation' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n this.transport.unsubscribeLocal(convId, socketId);\n this.joinedConversations.get(socketId)!.delete(convId);\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'presence:leave',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n } else if (type === 'typing' && typeof msg.conversationId === 'string') {\n const convId = msg.conversationId as string;\n const isTyping = !!msg.isTyping;\n const u = this.users.get(socketId)!;\n const payload = {\n type: 'typing',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n state: isTyping ? 'start' : 'stop',\n at: new Date().toISOString(),\n };\n // Emit to others and publish to Redis\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n this.transport.publishToConversation(convId, payload);\n }\n } catch {\n // ignore\n }\n });\n\n ws.on('close', () => {\n const joined = this.joinedConversations.get(socketId);\n if (joined) {\n const u = this.users.get(socketId)!;\n for (const convId of joined) {\n // presence leave to others\n const payload = {\n type: 'presence:leave',\n conversationId: convId,\n participantModel: u.model,\n participantId: u.id,\n at: new Date().toISOString(),\n };\n this.transport.fanoutLocal(convId, payload, (toSocketId) => {\n if (toSocketId === socketId) return;\n const to = this.sockets.get(toSocketId);\n if (to && to.readyState === WebSocket.OPEN) {\n try {\n to.send(JSON.stringify(payload));\n } catch {}\n }\n });\n }\n }\n this.transport.cleanupLocal(socketId);\n this.sockets.delete(socketId);\n this.users.delete(socketId);\n this.joinedConversations.delete(socketId);\n syncShim();\n });\n };\n\n const doReject = () => {\n try {\n ws.close(1008, 'Unauthorized');\n } catch {}\n };\n\n if (this.authenticate) {\n this.authenticate(shimSocket)\n .then((user) => {\n if (user) doAccept(user);\n else doReject();\n })\n .catch(() => doReject());\n } else {\n // If no auth handler, accept only if userId provided\n if (userId) doAccept({ id: userId, model: userModel });\n else doReject();\n }\n });\n }\n\n /**\n * Handle socket authentication\n */\n public handleAuth(authenticate: (socket: any) => Promise<SocketUser | null>) {\n this.authenticate = authenticate;\n }\n\n /**\n * Initialize socket event handlers\n */\n public initialize() {\n // No-op: handlers are set up in constructor for WS server\n }\n\n /**\n * Get Socket.IO server instance\n */\n public getIO(): any {\n return this.ioShim;\n }\n\n /**\n * Close Socket.IO server\n */\n public close(): Promise<void> {\n return new Promise((resolve) => {\n try {\n this.wss.close(() => resolve());\n } catch {\n resolve();\n }\n });\n }\n}\n","import * as localSubs from './localSubs';\nimport { createRedisClient, publishToConversation, startRedisListener } from './redis';\nimport { SocketTransport, SocketConfig } from './socket';\nimport { InitOptions } from '../types';\nimport type { Server as HTTPServer } from 'http';\n\n/**\n * Transport configuration type\n */\nexport interface TransportConfig {\n redis?: InitOptions['redis'];\n socket?: SocketConfig;\n}\n\n/**\n * Transport instance type\n */\nexport interface Transport {\n subscribeLocal: typeof localSubs.subscribeLocal;\n unsubscribeLocal: typeof localSubs.unsubscribeLocal;\n cleanupLocal: typeof localSubs.cleanupLocal;\n fanoutLocal: typeof localSubs.fanoutLocal;\n publishToConversation: (conversationId: string, payload: any) => Promise<number>;\n startRedisListener: (onEvent: (conversationId: string, payload: any) => void) => (() => void) | null;\n}\n\n/**\n * Create transport system with optional Redis and Socket.IO support\n */\nexport function createTransport(\n config?: TransportConfig,\n server?: HTTPServer\n): Transport & { socket?: SocketTransport } {\n // Initialize Redis client if configuration is provided\n const redisClient = config?.redis ? createRedisClient(config.redis) : null;\n \n // Create base transport\n const transport: Transport = {\n // Local subscription methods\n subscribeLocal: localSubs.subscribeLocal,\n unsubscribeLocal: localSubs.unsubscribeLocal,\n cleanupLocal: localSubs.cleanupLocal,\n fanoutLocal: localSubs.fanoutLocal,\n \n // Redis methods\n publishToConversation: (conversationId: string, payload: any) => \n publishToConversation(redisClient, conversationId, payload),\n \n startRedisListener: (onEvent: (conversationId: string, payload: any) => void) => \n startRedisListener(redisClient, onEvent),\n };\n\n // Initialize Socket.IO if server is provided\n if (server) {\n const socketTransport = new SocketTransport(server, transport, config?.socket);\n return {\n ...transport,\n socket: socketTransport\n };\n }\n\n return transport;\n}","import mongoose, { Model } from 'mongoose';\nimport { IConversation } from './Conversation.model';\nimport { IMessage } from './Message.model';\n\n/**\n * Ensure all indexes are created on models\n * @param models Object containing Mongoose models\n */\nexport async function ensureIndexes(models: {\n Conversation: Model<IConversation>;\n Message: Model<IMessage>;\n}): Promise<void> {\n // Create indexes\n await Promise.all([\n models.Message.ensureIndexes(),\n models.Conversation.ensureIndexes(),\n ]);\n}","/**\n * Redis configuration type\n */\nexport type RedisConfig = {\n url?: string;\n host?: string;\n port?: number;\n password?: string;\n db?: number;\n socketConnectTimeout?: number;\n keepAlive?: number;\n};\n\n/**\n * Environment configuration\n */\nexport interface EnvironmentConfig {\n /** MongoDB connection URI */\n mongoUri: string;\n /** Redis configuration (optional) */\n redis?: RedisConfig;\n}\n/**\n * Get Redis configuration from provided options\n */\nexport function getRedisConfig(config: { redis?: RedisConfig }): RedisConfig | null {\n if (!config.redis) {\n return null;\n }\n\n // Return the full configuration\n return {\n host: config.redis.host || undefined,\n port: config.redis.port || undefined,\n password: config.redis.password || undefined,\n db: config.redis.db || undefined,\n socketConnectTimeout: config.redis.socketConnectTimeout || undefined,\n keepAlive: config.redis.keepAlive || undefined\n };\n}\n","/**\n * Generates a random string ID with the specified length\n * @param length The length of the ID to generate (default: 24)\n * @returns A random string ID\n */\nexport function generateId(length = 24): string {\n const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n const charactersLength = characters.length;\n \n for (let i = 0; i < length; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n \n return result;\n}\n\n/**\n * Creates a conversation ID from two participant identifiers\n * @param a First participant (model:id)\n * @param b Second participant (model:id)\n * @returns A deterministic conversation ID\n */\nexport function createConversationId(\n a: { model: string; id: string },\n b: { model: string; id: string }\n): string {\n // Sort participants to ensure the same ID regardless of order\n const participants = [\n `${a.model}:${a.id}`,\n `${b.model}:${b.id}`,\n ].sort();\n \n return `conv_${participants.join('_')}`;\n}\n\n/**\n * Creates a thread ID\n * @returns A unique thread ID\n */\nexport function createThreadId(): string {\n return `thread_${generateId(16)}`;\n}\n\n/**\n * Creates a message ID\n * @returns A unique message ID\n */\nexport function createMessageId(): string {\n return `msg_${generateId(16)}`;\n}\n\n\n\n\n","import { InitOptions, SendMessageArgs, CreateConversationArgs, MarkReadArgs } from '../types';\n\n/**\n * Validates initialization options\n * @param options Options to validate\n * @returns Validation error message or null if valid\n */\nexport function validateInitOptions(options: InitOptions): string | null {\n if (!options.participantModels || !Array.isArray(options.participantModels) || options.participantModels.length === 0) {\n return 'participantModels must be a non-empty array of strings';\n }\n\n if (!options.memberRoles || !Array.isArray(options.memberRoles) || options.memberRoles.length === 0) {\n return 'memberRoles must be a non-empty array of strings';\n }\n\n // Validate Redis options if provided\n if (options.redis) {\n if (options.redis.url) {\n if (typeof options.redis.url !== 'string') {\n return 'redis.url must be a string';\n }\n } else if (!options.redis.host) {\n return 'Either redis.url or redis.host must be provided';\n }\n }\n\n return null;\n}\n\n/**\n * Validates message sending arguments\n * @param args Message sending arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateSendMessageArgs(args: SendMessageArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.conversationId) {\n return 'conversationId is required';\n }\n\n if (!args.senderModel) {\n return 'senderModel is required';\n }\n\n if (!args.senderId) {\n return 'senderId is required';\n }\n\n if (!args.text || args.text.trim() === '') {\n return 'text is required and cannot be empty';\n }\n\n // If kind is provided, validate it's a valid value\n if (args.kind && !['text', 'system'].includes(args.kind)) {\n return 'kind must be either \"text\" or \"system\"';\n }\n\n // If this is a reply, ensure all thread fields are present\n if (args.parentMessageId && !args.rootThreadId) {\n return 'rootThreadId is required when parentMessageId is provided';\n }\n\n return null;\n}\n\n/**\n * Validates conversation creation arguments\n * @param args Conversation creation arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateCreateConversationArgs(args: CreateConversationArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.a || !args.a.model || !args.a.id) {\n return 'a.model and a.id are required';\n }\n\n if (!args.b || !args.b.model || !args.b.id) {\n return 'b.model and b.id are required';\n }\n\n // Prevent creating a conversation between the same participant\n if (args.a.model === args.b.model && args.a.id === args.b.id) {\n return 'Cannot create a conversation between the same participant';\n }\n\n return null;\n}\n\n/**\n * Validates mark read arguments\n * @param args Mark read arguments to validate\n * @returns Validation error message or null if valid\n */\nexport function validateMarkReadArgs(args: MarkReadArgs): string | null {\n if (!args.organizationId) {\n return 'organizationId is required';\n }\n\n if (!args.conversationId) {\n return 'conversationId is required';\n }\n\n if (!args.participantModel) {\n return 'participantModel is required';\n }\n\n if (!args.participantId) {\n return 'participantId is required';\n }\n\n if (!args.messageId) {\n return 'messageId is required';\n }\n\n return null;\n}\n\n/**\n * Validates pagination parameters\n * @param limit Pagination limit\n * @param cursor Pagination cursor\n * @returns Validated limit and cursor\n */\nexport function validatePagination(\n limit?: number,\n cursor?: string\n): { limit: number; cursor: string | undefined } {\n // Default limit to 20, max to 100\n let validLimit = limit ? Math.min(Math.max(1, limit), 100) : 20;\n \n // If cursor is provided but empty string, set to undefined\n let validCursor = cursor && cursor.trim() !== '' ? cursor : undefined;\n \n return { limit: validLimit, cursor: validCursor };\n}\n\n\n\n\n","import mongoose from 'mongoose';\nimport type { Server as HTTPServer } from 'http';\nimport { createModels } from './models/connection';\nimport { createConversationsService, ConversationsService } from './services/conversations.service';\nimport { createMessagesService, MessagesService } from './services/messages.service';\nimport { createTransport, Transport } from './transport';\nimport { InitOptions } from './types';\nimport { ensureIndexes } from './models/indexes';\nimport { getRedisConfig } from './config/env';\nimport { SocketTransport } from './transport/socket';\nimport type { IConversation, IMessage } from './models';\nimport { setRuntimeConfig } from './config/runtime';\n\n/**\n * Chat services container\n */\nexport interface ChatServices {\n models: {\n Conversation: mongoose.Model<IConversation>;\n Message: mongoose.Model<IMessage>;\n };\n services: {\n conversations: ConversationsService;\n messages: MessagesService;\n };\n transport: Transport & { socket?: SocketTransport };\n}\n\n/**\n * Initialize the chat system\n * @param mongooseInstance Mongoose instance\n * @param options Initialization options\n * @param server Optional HTTP server for Socket.IO integration\n * @returns Chat services\n */\nexport async function initChat(\n mongooseInstance: typeof mongoose,\n options: InitOptions,\n server?: HTTPServer,\n): Promise<ChatServices> {\n // Persist runtime configuration for global access\n setRuntimeConfig({\n dataServiceEndpoint: options.dataServiceEndpoint,\n secretId: options.secretId,\n });\n\n const models = createModels(mongooseInstance, options);\n\n // Ensure indexes are created\n await ensureIndexes(models);\n\n // Create transport system with optional Socket.IO support\n const transport = createTransport(\n {\n redis: getRedisConfig(options) || undefined,\n socket: options.socket || undefined,\n },\n server,\n );\n\n // Initialize Socket.IO if server was provided\n if (server && transport.socket) {\n // Set up authentication handler\n transport.socket.handleAuth(async (socket) => {\n // Get user info from socket handshake auth\n const userId = socket.handshake.auth.userId;\n const userModel = socket.handshake.auth.userModel || 'User';\n\n if (!userId || !options.participantModels.includes(userModel)) {\n return null;\n }\n\n return { id: userId, model: userModel };\n });\n\n // Initialize socket event handlers\n transport.socket.initialize();\n }\n\n // Create services with hooks\n const services = {\n conversations: createConversationsService(models),\n messages: createMessagesService(models, {\n onMessageCreated: (message) => {\n const payload = { type: 'message:created', message };\n\n // Fan out to local subscribers\n transport.fanoutLocal(message.conversationId.toString(), payload, (socketId, event) => {\n if (transport.socket) {\n const socket = transport.socket.getIO().sockets.sockets.get(socketId);\n if (socket) {\n socket.emit('chat-event', event);\n }\n }\n });\n\n // Publish to Redis for cross-instance communication\n transport.publishToConversation(message.conversationId.toString(), payload);\n },\n\n onMessageRead: (args) => {\n const payload = {\n type: 'conversation:read',\n conversationId: args.conversationId,\n messageId: args.messageId,\n participantModel: args.participantModel,\n participantId: args.participantId,\n at: args.at.toISOString(),\n };\n\n // Fan out to local subscribers\n transport.fanoutLocal(args.conversationId, payload, (socketId, event) => {\n if (transport.socket) {\n const socket = transport.socket.getIO().sockets.sockets.get(socketId);\n if (socket) {\n socket.emit('chat-event', event);\n }\n }\n });\n\n // Publish to Redis for cross-instance communication\n transport.publishToConversation(args.conversationId, payload);\n },\n }),\n };\n\n return { models, services, transport };\n}\n\n// Re-export types\nexport * from './types';\nexport * from './utils';\nexport * from './models';\nexport * from './services';\nexport * from './transport';\nexport * from './config/env';\nexport * from './config/runtime';\n\n// Export Conversation and Message model types for direct access\nexport type { ConversationModel, MessageModel } from './models';\n\n// Export MessageWithSender interface\nexport type { MessageWithSender } from './services/messages.service';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wexa-chat",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Chat core library with MongoDB and Redis support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",