@bootdesk/js-web-adapter-core 0.4.23 → 0.4.25
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.cjs +72 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +72 -27
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -121,14 +121,6 @@ var HttpClient = class {
|
|
|
121
121
|
const url = this.expandTemplate(endpointTemplate, { id: messageId });
|
|
122
122
|
await this.delete(url);
|
|
123
123
|
}
|
|
124
|
-
async addReaction(messageId, emoji, endpointTemplate = "/api/chat/messages/{id}/reactions") {
|
|
125
|
-
const url = this.expandTemplate(endpointTemplate, { id: messageId });
|
|
126
|
-
await this.post(url, { emoji });
|
|
127
|
-
}
|
|
128
|
-
async removeReaction(messageId, emoji, endpointTemplate = "/api/chat/messages/{id}/reactions/{emoji}") {
|
|
129
|
-
const url = this.expandTemplate(endpointTemplate, { id: messageId, emoji });
|
|
130
|
-
await this.delete(url);
|
|
131
|
-
}
|
|
132
124
|
async postFormData(url, formData, signal) {
|
|
133
125
|
const controller = new AbortController();
|
|
134
126
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
@@ -339,6 +331,8 @@ var WebChatClient = class {
|
|
|
339
331
|
this.streamingMessages = /* @__PURE__ */ new Map();
|
|
340
332
|
this.pendingTyping = null;
|
|
341
333
|
this.subscribers = /* @__PURE__ */ new Map();
|
|
334
|
+
this.sendQueue = [];
|
|
335
|
+
this.isProcessingQueue = false;
|
|
342
336
|
this.config = config;
|
|
343
337
|
this.httpClient = new HttpClient({
|
|
344
338
|
apiUrl: config.apiUrl,
|
|
@@ -467,6 +461,31 @@ var WebChatClient = class {
|
|
|
467
461
|
};
|
|
468
462
|
}
|
|
469
463
|
async sendMessage(text, attachments = []) {
|
|
464
|
+
return new Promise((resolve, reject) => {
|
|
465
|
+
this.sendQueue.push(async () => {
|
|
466
|
+
try {
|
|
467
|
+
await this.executeSend(text, attachments);
|
|
468
|
+
resolve();
|
|
469
|
+
} catch (e) {
|
|
470
|
+
reject(e);
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
this.processQueue();
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
async processQueue() {
|
|
477
|
+
if (this.isProcessingQueue) return;
|
|
478
|
+
this.isProcessingQueue = true;
|
|
479
|
+
try {
|
|
480
|
+
while (this.sendQueue.length > 0) {
|
|
481
|
+
const task = this.sendQueue.shift();
|
|
482
|
+
await task();
|
|
483
|
+
}
|
|
484
|
+
} finally {
|
|
485
|
+
this.isProcessingQueue = false;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
async executeSend(text, attachments = []) {
|
|
470
489
|
const messageId = generateId();
|
|
471
490
|
const userMessage = {
|
|
472
491
|
id: messageId,
|
|
@@ -562,15 +581,39 @@ var WebChatClient = class {
|
|
|
562
581
|
if (!this.config.features?.reactions) {
|
|
563
582
|
throw new Error("Reactions not enabled. Set features.reactions = true in config.");
|
|
564
583
|
}
|
|
565
|
-
|
|
566
|
-
|
|
584
|
+
this.handleReactionAdded(
|
|
585
|
+
new ReactionAddedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId })
|
|
586
|
+
);
|
|
587
|
+
const endpoint = this.config.endpoints?.sendMessage ?? "/api/webhooks/web";
|
|
588
|
+
const response = await this.httpClient.post(endpoint, {
|
|
589
|
+
id: this.conversationId,
|
|
590
|
+
reaction: { messageId, emoji, added: true }
|
|
591
|
+
});
|
|
592
|
+
if (response.events) {
|
|
593
|
+
response.events.forEach((eventData) => {
|
|
594
|
+
const event = parseChatEvent(eventData);
|
|
595
|
+
this.dispatchEvent(event);
|
|
596
|
+
});
|
|
597
|
+
}
|
|
567
598
|
}
|
|
568
599
|
async removeReaction(messageId, emoji) {
|
|
569
600
|
if (!this.config.features?.reactions) {
|
|
570
601
|
throw new Error("Reactions not enabled. Set features.reactions = true in config.");
|
|
571
602
|
}
|
|
572
|
-
|
|
573
|
-
|
|
603
|
+
this.handleReactionRemoved(
|
|
604
|
+
new ReactionRemovedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId })
|
|
605
|
+
);
|
|
606
|
+
const endpoint = this.config.endpoints?.sendMessage ?? "/api/webhooks/web";
|
|
607
|
+
const response = await this.httpClient.post(endpoint, {
|
|
608
|
+
id: this.conversationId,
|
|
609
|
+
reaction: { messageId, emoji, added: false }
|
|
610
|
+
});
|
|
611
|
+
if (response.events) {
|
|
612
|
+
response.events.forEach((eventData) => {
|
|
613
|
+
const event = parseChatEvent(eventData);
|
|
614
|
+
this.dispatchEvent(event);
|
|
615
|
+
});
|
|
616
|
+
}
|
|
574
617
|
}
|
|
575
618
|
onMessagePosted(handler) {
|
|
576
619
|
return this.addEventListener("message.posted", handler);
|
|
@@ -663,26 +706,28 @@ var WebChatClient = class {
|
|
|
663
706
|
}
|
|
664
707
|
handleReactionAdded(event) {
|
|
665
708
|
const message = this.messages.find((m) => m.id === event.messageId);
|
|
666
|
-
if (
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
709
|
+
if (message) {
|
|
710
|
+
if (!message.reactions) message.reactions = [];
|
|
711
|
+
const existing = message.reactions.find((r) => r.emoji === event.emoji);
|
|
712
|
+
if (existing) {
|
|
713
|
+
existing.count++;
|
|
714
|
+
existing.users.push(event.user.id);
|
|
715
|
+
} else {
|
|
716
|
+
message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });
|
|
717
|
+
}
|
|
674
718
|
}
|
|
675
719
|
this.notifySubscribers("reaction:added", event);
|
|
676
720
|
}
|
|
677
721
|
handleReactionRemoved(event) {
|
|
678
722
|
const message = this.messages.find((m) => m.id === event.messageId);
|
|
679
|
-
if (
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
723
|
+
if (message?.reactions) {
|
|
724
|
+
const index = message.reactions.findIndex((r) => r.emoji === event.emoji);
|
|
725
|
+
if (index !== -1) {
|
|
726
|
+
const reaction = message.reactions[index];
|
|
727
|
+
reaction.count--;
|
|
728
|
+
reaction.users = reaction.users.filter((id) => id !== event.user.id);
|
|
729
|
+
if (reaction.count === 0) message.reactions.splice(index, 1);
|
|
730
|
+
}
|
|
686
731
|
}
|
|
687
732
|
this.notifySubscribers("reaction:removed", event);
|
|
688
733
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/client/HttpClient.ts","../src/events/base/ChatEvent.ts","../src/events/MessagePostedEvent.ts","../src/events/MessageEditedEvent.ts","../src/events/MessageDeletedEvent.ts","../src/events/ReactionAddedEvent.ts","../src/events/ReactionRemovedEvent.ts","../src/events/TypingStartedEvent.ts","../src/events/StreamingChunkEvent.ts","../src/events/DMRequestedEvent.ts","../src/events/ChatEventFactory.ts","../src/utils/eventIdGenerator.ts","../src/client/WebChatClient.ts","../src/client/PusherBroadcastClient.ts","../src/client/LaravelEchoBroadcastClient.ts","../src/push/PushManager.ts","../src/push/PushSubscriptionManager.ts"],"sourcesContent":["export { WebChatClient } from \"./client/WebChatClient\";\nexport type {\n WebChatClientConfig,\n ReconfigureConfig,\n LoadMessagesOptions,\n LoadMessagesResult,\n} from \"./client/WebChatClient\";\n\nexport {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./client/BroadcastClient\";\nexport { PusherBroadcastClient } from \"./client/PusherBroadcastClient\";\nexport type { PusherConfig } from \"./client/PusherBroadcastClient\";\nexport { LaravelEchoBroadcastClient } from \"./client/LaravelEchoBroadcastClient\";\n\nexport { HttpClient } from \"./client/HttpClient\";\nexport type { HttpClientConfig, ChatResponse } from \"./client/HttpClient\";\n\nexport * from \"./types\";\n\nexport { ChatEvent, UnknownEvent } from \"./events/base/ChatEvent\";\nexport { parseChatEvent } from \"./events/ChatEventFactory\";\nexport { MessagePostedEvent } from \"./events/MessagePostedEvent\";\nexport { MessageEditedEvent } from \"./events/MessageEditedEvent\";\nexport { MessageDeletedEvent } from \"./events/MessageDeletedEvent\";\nexport { ReactionAddedEvent } from \"./events/ReactionAddedEvent\";\nexport { ReactionRemovedEvent } from \"./events/ReactionRemovedEvent\";\nexport { TypingStartedEvent } from \"./events/TypingStartedEvent\";\nexport { StreamingChunkEvent } from \"./events/StreamingChunkEvent\";\nexport { DMRequestedEvent } from \"./events/DMRequestedEvent\";\n\nexport { generateId, generateConversationId } from \"./utils/eventIdGenerator\";\n\nexport { PushManager } from \"./push/PushManager\";\nexport { createPushSubscriptionHandlers } from \"./push/PushSubscriptionManager\";\nexport type { PushSubscriptionStatus, PushConfig, PushEventData } from \"./push/types\";\n","export interface HttpClientConfig {\n apiUrl: string;\n headers?: Record<string, string>;\n timeout?: number;\n verifyToken?: string;\n}\n\nexport interface ChatResponse {\n id: string;\n role: \"assistant\" | \"user\";\n text: string;\n attachments?: Array<{\n type: string;\n url: string;\n name?: string;\n mime_type?: string;\n size?: number;\n }>;\n events?: Array<Record<string, unknown>>;\n}\n\nexport class HttpClient {\n private config: Required<Pick<HttpClientConfig, \"apiUrl\" | \"timeout\">> & {\n headers: Record<string, string>;\n };\n\n constructor(config: HttpClientConfig) {\n const headers: Record<string, string> = { ...config.headers };\n if (config.verifyToken) {\n headers[\"X-Verify-Token\"] = config.verifyToken;\n }\n this.config = { apiUrl: config.apiUrl, timeout: config.timeout ?? 30000, headers };\n }\n\n async get(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"GET\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async post(url: string, body: unknown, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...this.config.headers },\n signal: combined,\n body: JSON.stringify(body),\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async delete(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"DELETE\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n const text = await response.text();\n return text ? JSON.parse(text) : undefined;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async sendMessage(\n messages: Array<{\n id: string;\n role: string;\n text: string;\n attachments?: Array<{ url: string; name?: string; mime_type?: string; size?: number }>;\n }>,\n endpoint: string = \"/api/webhooks/web\",\n conversationId?: string,\n ): Promise<ChatResponse> {\n return this.post(endpoint, { id: conversationId, messages }) as Promise<ChatResponse>;\n }\n\n async sendAction(\n actionId: string,\n value: string,\n messageId: string,\n conversationId: string,\n endpoint: string = \"/api/webhooks/web\",\n ): Promise<Record<string, unknown>> {\n return this.post(endpoint, {\n id: conversationId,\n action: { actionId, value, messageId },\n }) as Promise<Record<string, unknown>>;\n }\n\n async editMessage(\n messageId: string,\n newText: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/edit\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { text: newText });\n }\n\n async deleteMessage(\n messageId: string,\n endpointTemplate: string = \"/api/chat/messages/{id}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.delete(url);\n }\n\n async addReaction(\n messageId: string,\n emoji: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/reactions\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { emoji });\n }\n\n async removeReaction(\n messageId: string,\n emoji: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/reactions/{emoji}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId, emoji });\n await this.delete(url);\n }\n\n async postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: this.config.headers,\n signal: combined,\n body: formData,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n setHeader(name: string, value: string): void {\n this.config.headers[name] = value;\n }\n\n removeHeader(name: string): void {\n delete this.config.headers[name];\n }\n\n private resolve(url: string): string {\n return /^https?:\\/\\//.test(url) ? url : `${this.config.apiUrl}${url}`;\n }\n\n private expandTemplate(template: string, params: Record<string, string>): string {\n let url = template;\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`{${key}}`, encodeURIComponent(value));\n }\n return this.resolve(url);\n }\n}\n","export abstract class ChatEvent {\n readonly type: string;\n readonly threadId: string;\n readonly timestamp: number;\n\n constructor(type: string, threadId: string, timestamp: number) {\n this.type = type;\n this.threadId = threadId;\n this.timestamp = timestamp;\n }\n\n static fromJSON: ((json: Record<string, unknown>) => ChatEvent) | undefined;\n}\n\nexport class UnknownEvent extends ChatEvent {\n readonly data: Record<string, unknown>;\n\n constructor(type: string, threadId: string, data: Record<string, unknown>, timestamp: number) {\n super(type, threadId, timestamp);\n this.data = data;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User, Card } from \"../types\";\n\nexport class MessagePostedEvent extends ChatEvent {\n readonly messageId: string;\n readonly text: string;\n readonly author: User;\n readonly card?: Card;\n readonly attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>;\n\n constructor(\n threadId: string,\n messageId: string,\n text: string,\n author: User,\n card?: Card,\n attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp?: number,\n ) {\n super(\"message.posted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.text = text;\n this.author = author;\n this.card = card;\n this.attachments = attachments;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { Card } from \"../types\";\n\nexport class MessageEditedEvent extends ChatEvent {\n readonly messageId: string;\n readonly newText: string;\n readonly card?: Card;\n\n constructor(\n threadId: string,\n messageId: string,\n newText: string,\n card?: Card,\n timestamp?: number,\n ) {\n super(\"message.edited\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.newText = newText;\n this.card = card;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class MessageDeletedEvent extends ChatEvent {\n readonly messageId: string;\n\n constructor(threadId: string, messageId: string, timestamp?: number) {\n super(\"message.deleted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionAddedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.added\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionRemovedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.removed\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class TypingStartedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"typing.started\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class StreamingChunkEvent extends ChatEvent {\n readonly messageId: string;\n readonly chunk: string;\n readonly isFinal: boolean;\n\n constructor(\n threadId: string,\n messageId: string,\n chunk: string,\n isFinal: boolean,\n timestamp?: number,\n ) {\n super(\"streaming.chunk\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.chunk = chunk;\n this.isFinal = isFinal;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class DMRequestedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"dm.requested\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent, UnknownEvent } from \"./base/ChatEvent\";\nimport type { Card, User } from \"../types\";\nimport { MessagePostedEvent } from \"./MessagePostedEvent\";\nimport { MessageEditedEvent } from \"./MessageEditedEvent\";\nimport { MessageDeletedEvent } from \"./MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"./ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"./ReactionRemovedEvent\";\nimport { TypingStartedEvent } from \"./TypingStartedEvent\";\nimport { StreamingChunkEvent } from \"./StreamingChunkEvent\";\nimport { DMRequestedEvent } from \"./DMRequestedEvent\";\n\nfunction parseCard(value: unknown): Card | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const obj = value as Record<string, unknown>;\n if (typeof obj.type !== \"string\") return undefined;\n return obj as unknown as Card;\n}\n\nexport function parseChatEvent(json: Record<string, unknown>): ChatEvent {\n const type = json.type as string;\n const threadId = json.threadId as string;\n const timestamp = json.timestamp as number;\n const data = (json.data ?? {}) as Record<string, unknown>;\n\n switch (type) {\n case \"message.posted\":\n return new MessagePostedEvent(\n threadId,\n data.messageId as string,\n data.text as string,\n data.author as User,\n parseCard(data.card),\n data.attachments as Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp,\n );\n case \"message.edited\":\n return new MessageEditedEvent(\n threadId,\n data.messageId as string,\n data.newText as string,\n parseCard(data.card),\n timestamp,\n );\n case \"message.deleted\":\n return new MessageDeletedEvent(threadId, data.messageId as string, timestamp);\n case \"reaction.added\":\n return new ReactionAddedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"reaction.removed\":\n return new ReactionRemovedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"typing.started\":\n return new TypingStartedEvent(threadId, data.userId as string, timestamp);\n case \"streaming.chunk\":\n return new StreamingChunkEvent(\n threadId,\n data.messageId as string,\n data.chunk as string,\n data.isFinal as boolean,\n timestamp,\n );\n case \"dm.requested\":\n return new DMRequestedEvent(threadId, data.userId as string, timestamp);\n default:\n return new UnknownEvent(type, threadId, data, timestamp);\n }\n}\n\n// Wire up the static method\nChatEvent.fromJSON = parseChatEvent;\n","export function generateId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\nexport function generateConversationId(): string {\n return `conv-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n","import { HttpClient } from \"./HttpClient\";\nimport type { BroadcastClient, EventHandlers, Unsubscribe } from \"./BroadcastClient\";\nimport type { Message } from \"../types\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type { MessagePostedEvent } from \"../events/MessagePostedEvent\";\nimport type { MessageEditedEvent } from \"../events/MessageEditedEvent\";\nimport type { MessageDeletedEvent } from \"../events/MessageDeletedEvent\";\nimport type { ReactionAddedEvent } from \"../events/ReactionAddedEvent\";\nimport type { ReactionRemovedEvent } from \"../events/ReactionRemovedEvent\";\nimport type { TypingStartedEvent } from \"../events/TypingStartedEvent\";\nimport type { StreamingChunkEvent } from \"../events/StreamingChunkEvent\";\nimport type { DMRequestedEvent } from \"../events/DMRequestedEvent\";\nimport { generateId, generateConversationId } from \"../utils/eventIdGenerator\";\n\nexport interface ReconfigureConfig {\n userId?: string;\n userName?: string;\n verifyToken?: string;\n conversationId?: string;\n headers?: Record<string, string>;\n}\n\nexport interface WebChatClientConfig {\n apiUrl: string;\n userId: string;\n userName: string;\n broadcastClient?: BroadcastClient;\n headers?: Record<string, string>;\n verifyToken?: string;\n conversationId?: string;\n endpoints?: {\n sendMessage?: string;\n loadMessages?: string;\n editMessage?: string;\n deleteMessage?: string;\n addReaction?: string;\n removeReaction?: string;\n };\n features?: {\n editMessages?: boolean;\n deleteMessages?: boolean;\n reactions?: boolean;\n };\n}\n\ninterface StreamingState {\n messageId: string;\n accumulatedText: string;\n isComplete: boolean;\n}\n\ninterface AttachmentInput {\n url: string;\n name?: string;\n mimeType?: string;\n size?: number;\n}\n\nexport interface LoadMessagesOptions {\n limit?: number;\n before?: number;\n after?: number;\n skipStateSeed?: boolean;\n}\n\nexport interface LoadMessagesResult {\n messages: Message[];\n hasMore: boolean;\n nextCursor?: number;\n prevCursor?: number;\n}\n\nexport class WebChatClient {\n private config: WebChatClientConfig;\n private httpClient: HttpClient;\n private broadcastClient?: BroadcastClient;\n private conversationId: string;\n private messages: Message[] = [];\n private currentUserId: string;\n private eventHandlers: EventHandlers = {};\n private streamingMessages: Map<string, StreamingState> = new Map();\n private pendingTyping: ReturnType<typeof setTimeout> | null = null;\n private subscribers: Map<string, Array<(event: unknown) => void>> = new Map();\n private unsubscribeUserChannel?: Unsubscribe;\n\n constructor(config: WebChatClientConfig) {\n this.config = config;\n this.httpClient = new HttpClient({\n apiUrl: config.apiUrl,\n headers: {\n \"X-User-Id\": config.userId,\n \"X-User-Name\": config.userName,\n ...(config.headers ?? {}),\n },\n verifyToken: config.verifyToken,\n });\n this.broadcastClient = config.broadcastClient;\n this.conversationId = config.conversationId ?? generateConversationId();\n this.currentUserId = config.userId;\n }\n\n reconfigure(config: ReconfigureConfig): void {\n if (config.userId) {\n this.currentUserId = config.userId;\n this.httpClient.setHeader(\"X-User-Id\", config.userId);\n }\n if (config.userName) {\n this.config = { ...this.config, userName: config.userName };\n this.httpClient.setHeader(\"X-User-Name\", config.userName);\n }\n if (config.verifyToken) {\n this.config = { ...this.config, verifyToken: config.verifyToken };\n this.httpClient.setHeader(\"X-Verify-Token\", config.verifyToken);\n }\n if (config.conversationId) {\n this.conversationId = config.conversationId;\n }\n if (config.headers) {\n Object.entries(config.headers).forEach(([key, value]) => {\n this.httpClient.setHeader(key, value);\n });\n }\n }\n\n setLocaleHeader(locale: string): void {\n this.httpClient.setHeader(\"X-Locale\", locale);\n this.httpClient.setHeader(\"X-Language\", locale.split(\"-\")[0] ?? locale);\n }\n\n setTimezoneHeader(timezone: string): void {\n this.httpClient.setHeader(\"X-Timezone\", timezone);\n }\n\n async connect(): Promise<void> {\n if (this.broadcastClient) {\n this.broadcastClient.connect();\n\n const threadId = this.getThreadId();\n const threadEvents: EventHandlers = {\n onMessagePosted: (event) => this.handleMessagePosted(event),\n };\n\n if (this.config.features?.editMessages) {\n threadEvents.onMessageEdited = (event) => this.handleMessageEdited(event);\n }\n if (this.config.features?.deleteMessages) {\n threadEvents.onMessageDeleted = (event) => this.handleMessageDeleted(event);\n }\n if (this.config.features?.reactions) {\n threadEvents.onReactionAdded = (event) => this.handleReactionAdded(event);\n threadEvents.onReactionRemoved = (event) => this.handleReactionRemoved(event);\n }\n\n threadEvents.onTypingStarted = (event) => this.handleTypingStarted(event);\n\n await this.broadcastClient.subscribe(threadId, threadEvents);\n\n this.unsubscribeUserChannel = await this.broadcastClient.subscribeToUser(\n threadId,\n this.currentUserId,\n {\n onStreamingChunk: (event) => this.handleStreamingChunk(event),\n onDMRequested: (event) => this.handleDMRequested(event),\n },\n );\n }\n }\n\n disconnect(): void {\n this.unsubscribeUserChannel?.();\n this.unsubscribeUserChannel = undefined;\n this.broadcastClient?.disconnect();\n this.streamingMessages.clear();\n }\n\n async loadMessages(\n options?: LoadMessagesOptions,\n signal?: AbortSignal,\n ): Promise<LoadMessagesResult> {\n const endpoint = this.config.endpoints?.loadMessages ?? \"/api/chat/messages\";\n const threadId = this.getThreadId();\n const params = new URLSearchParams({\n threadId,\n limit: String(options?.limit ?? 50),\n });\n if (options?.before) params.set(\"before\", String(options.before));\n if (options?.after) params.set(\"after\", String(options.after));\n\n const response = (await this.httpClient.get(\n `${endpoint}?${params.toString()}`,\n signal,\n )) as Record<string, unknown>;\n const rawMessages = (response.messages as Record<string, unknown>[]) ?? [];\n const messages: Message[] = rawMessages.map((msg) => ({\n id: msg.id as string,\n threadId,\n content: {\n text: msg.text as string,\n cards: msg.card ? ([msg.card as Record<string, unknown>] as never[]) : undefined,\n },\n author: {\n id: (msg.author as Record<string, unknown>).id as string,\n name: (msg.author as Record<string, unknown>).name as string,\n isBot: ((msg.author as Record<string, unknown>).isBot as boolean) ?? false,\n isMe: (msg.author as Record<string, unknown>).id === this.currentUserId,\n },\n timestamp: msg.timestamp as number,\n attachments: (msg.attachments as Record<string, unknown>[])?.map((a) => ({\n id: `att-${msg.id as string}-${a.url as string}`,\n url: a.url as string,\n name: a.name as string,\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n reactions: (msg.reactions as { emoji: string; count: number; users: string[] }[]) ?? [],\n }));\n\n if (!options?.before && !options?.after && !options?.skipStateSeed) {\n this.messages = messages;\n this.notifySubscribers(\"messages:loaded\", messages);\n }\n\n return {\n messages,\n hasMore: (response.hasMore as boolean) ?? false,\n nextCursor: response.nextCursor as number | undefined,\n prevCursor: response.prevCursor as number | undefined,\n };\n }\n\n async sendMessage(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n const messageId = generateId();\n\n const userMessage: Message = {\n id: messageId,\n threadId: this.getThreadId(),\n content: { text },\n author: { id: this.currentUserId, name: this.config.userName, isMe: true },\n timestamp: Date.now(),\n attachments:\n attachments.length > 0\n ? attachments.map((a, i) => ({\n id: `att-${messageId}-${i}`,\n name: a.name ?? \"\",\n url: a.url,\n size: a.size,\n mimeType: a.mimeType,\n }))\n : undefined,\n };\n\n this.messages.push(userMessage);\n this.notifySubscribers(\"message:added\", userMessage);\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendMessage(\n [\n {\n id: messageId,\n role: \"user\",\n text,\n attachments: attachments.map((a) => ({\n url: a.url,\n name: a.name,\n mime_type: a.mimeType,\n size: a.size,\n })),\n },\n ],\n endpoint,\n this.conversationId,\n );\n\n if (response.events) {\n response.events.forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n\n if (response.text && !response.events?.some((e) => e.type === \"message.posted\")) {\n const assistantMessage: Message = {\n id: response.id ?? generateId(),\n threadId: this.getThreadId(),\n content: { text: response.text },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: Date.now(),\n attachments: (response.attachments as Record<string, unknown>[])?.map((a, i) => ({\n id: `att-${response.id ?? \"msg\"}-${i}`,\n name: (a.name as string) ?? \"\",\n url: (a.url as string) ?? \"\",\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n };\n this.messages.push(assistantMessage);\n this.notifySubscribers(\"message:added\", assistantMessage);\n }\n }\n\n async sendAction(messageId: string, actionId: string, value: string): Promise<void> {\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendAction(\n actionId,\n value,\n messageId,\n this.conversationId,\n endpoint,\n );\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async editMessage(messageId: string, newText: string): Promise<void> {\n if (!this.config.features?.editMessages) {\n throw new Error(\"Edit messages not enabled. Set features.editMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.editMessage ?? \"/api/chat/messages/{id}/edit\";\n await this.httpClient.editMessage(messageId, newText, endpoint);\n }\n\n async deleteMessage(messageId: string): Promise<void> {\n if (!this.config.features?.deleteMessages) {\n throw new Error(\"Delete messages not enabled. Set features.deleteMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.deleteMessage ?? \"/api/chat/messages/{id}\";\n await this.httpClient.deleteMessage(messageId, endpoint);\n }\n\n async addReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n const endpoint = this.config.endpoints?.addReaction ?? \"/api/chat/messages/{id}/reactions\";\n await this.httpClient.addReaction(messageId, emoji, endpoint);\n }\n\n async removeReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n const endpoint =\n this.config.endpoints?.removeReaction ?? \"/api/chat/messages/{id}/reactions/{emoji}\";\n await this.httpClient.removeReaction(messageId, emoji, endpoint);\n }\n\n onMessagePosted(handler: (event: MessagePostedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message.posted\", handler);\n }\n\n onMessageEdited(handler: (event: MessageEditedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:edited\", handler);\n }\n\n onMessageDeleted(handler: (event: MessageDeletedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:deleted\", handler);\n }\n\n onReactionAdded(handler: (event: ReactionAddedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:added\", handler);\n }\n\n onReactionRemoved(handler: (event: ReactionRemovedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:removed\", handler);\n }\n\n onStreamingChunk(handler: (event: StreamingChunkEvent) => void): Unsubscribe {\n return this.addEventListener(\"streaming:chunk\", handler);\n }\n\n onTypingStarted(handler: (event: TypingStartedEvent) => void): Unsubscribe {\n return this.addEventListener(\"typing:started\", handler);\n }\n\n getConversationId(): string {\n return this.conversationId;\n }\n getMessages(): Message[] {\n return [...this.messages];\n }\n getThreadId(): string {\n return `web:${this.currentUserId}:${this.conversationId}`;\n }\n getCurrentUserId(): string {\n return this.currentUserId;\n }\n getFeatures(): NonNullable<WebChatClientConfig[\"features\"]> {\n return this.config.features ?? {};\n }\n getEndpoints(): NonNullable<WebChatClientConfig[\"endpoints\"]> {\n return this.config.endpoints ?? {};\n }\n getHttpClient(): HttpClient {\n return this.httpClient;\n }\n\n addEventListener<T = unknown>(eventType: string, handler: (event: T) => void): Unsubscribe {\n if (!this.subscribers.has(eventType)) this.subscribers.set(eventType, []);\n this.subscribers.get(eventType)!.push(handler as (event: unknown) => void);\n return () => {\n const handlers = this.subscribers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler as (event: unknown) => void);\n if (index !== -1) handlers.splice(index, 1);\n }\n };\n }\n\n private handleMessagePosted(event: MessagePostedEvent): void {\n if (this.messages.some((m) => m.id === event.messageId)) return;\n if (this.streamingMessages.has(event.messageId)) return;\n\n const message: Message = {\n id: event.messageId,\n threadId: event.threadId,\n content: { text: event.text, cards: event.card ? [event.card] : undefined },\n author: event.author,\n timestamp: event.timestamp,\n attachments: event.attachments?.map((a) => ({\n id: `att-${event.messageId}-${Math.random().toString(36).slice(2, 8)}`,\n name: a.name ?? \"\",\n url: a.url ?? \"\",\n type: a.type,\n mimeType: a.mimeType,\n size: a.size ?? undefined,\n })),\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n this.notifySubscribers(\"message.posted\", event);\n }\n\n private handleMessageEdited(event: MessageEditedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.content) {\n message.content.text = event.newText;\n this.notifySubscribers(\"message:edited\", event);\n }\n }\n\n private handleMessageDeleted(event: MessageDeletedEvent): void {\n const index = this.messages.findIndex((m) => m.id === event.messageId);\n if (index !== -1) {\n this.messages.splice(index, 1);\n this.notifySubscribers(\"message:deleted\", event);\n }\n }\n\n private handleReactionAdded(event: ReactionAddedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (!message) return;\n if (!message.reactions) message.reactions = [];\n\n const existing = message.reactions.find((r) => r.emoji === event.emoji);\n if (existing) {\n existing.count++;\n existing.users.push(event.user.id);\n } else {\n message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });\n }\n this.notifySubscribers(\"reaction:added\", event);\n }\n\n private handleReactionRemoved(event: ReactionRemovedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (!message?.reactions) return;\n\n const index = message.reactions.findIndex((r) => r.emoji === event.emoji);\n if (index !== -1) {\n const reaction = message.reactions[index]!;\n reaction.count--;\n reaction.users = reaction.users.filter((id) => id !== event.user.id);\n if (reaction.count === 0) message.reactions.splice(index, 1);\n }\n this.notifySubscribers(\"reaction:removed\", event);\n }\n\n private handleStreamingChunk(event: StreamingChunkEvent): void {\n const { messageId, chunk, isFinal } = event;\n\n if (!this.streamingMessages.has(messageId)) {\n this.streamingMessages.set(messageId, { messageId, accumulatedText: \"\", isComplete: false });\n this.notifySubscribers(\"streaming:started\", event);\n }\n\n const state = this.streamingMessages.get(messageId)!;\n state.accumulatedText += chunk;\n\n if (isFinal) {\n state.isComplete = true;\n if (!this.messages.some((m) => m.id === messageId)) {\n const message: Message = {\n id: messageId,\n threadId: event.threadId,\n content: { text: state.accumulatedText },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: event.timestamp,\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n }\n this.streamingMessages.delete(messageId);\n this.notifySubscribers(\"streaming:complete\", { messageId, text: state.accumulatedText });\n } else {\n this.notifySubscribers(\"streaming:chunk\", event);\n }\n }\n\n private handleTypingStarted(event: TypingStartedEvent): void {\n if (this.pendingTyping) clearTimeout(this.pendingTyping);\n this.notifySubscribers(\"typing:started\", event);\n this.pendingTyping = setTimeout(() => {\n this.notifySubscribers(\"typing:stopped\", { userId: event.userId });\n }, 3000);\n }\n\n private handleDMRequested(event: DMRequestedEvent): void {\n this.notifySubscribers(\"dm.requested\", event);\n }\n\n private notifySubscribers<T>(eventType: string, data: T): void {\n this.subscribers.get(eventType)?.forEach((handler) => handler(data));\n }\n\n private dispatchEvent(event: ChatEvent): void {\n switch (event.type) {\n case \"message.posted\":\n this.handleMessagePosted(event as MessagePostedEvent);\n break;\n case \"message.edited\":\n this.handleMessageEdited(event as MessageEditedEvent);\n break;\n case \"message.deleted\":\n this.handleMessageDeleted(event as MessageDeletedEvent);\n break;\n case \"reaction.added\":\n this.handleReactionAdded(event as ReactionAddedEvent);\n break;\n case \"reaction.removed\":\n this.handleReactionRemoved(event as ReactionRemovedEvent);\n break;\n case \"typing.started\":\n this.handleTypingStarted(event as TypingStartedEvent);\n break;\n case \"streaming.chunk\":\n this.handleStreamingChunk(event as StreamingChunkEvent);\n break;\n case \"dm.requested\":\n this.handleDMRequested(event as DMRequestedEvent);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel as PusherChannel } from \"pusher-js\";\n\nexport interface PusherConfig {\n key: string;\n cluster?: string;\n host?: string;\n port?: number;\n forceTLS?: boolean;\n authEndpoint?: string;\n}\n\nexport class PusherBroadcastClient implements BroadcastClient {\n private pusher: Pusher;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, PusherChannel> = new Map();\n\n constructor(pusher: Pusher, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(config: PusherConfig, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(\n pusherOrConfig: Pusher | PusherConfig,\n channelPrefix: string = \"chat\",\n channelTypes?: ChannelTypeConfig,\n ) {\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n\n if (\"key\" in pusherOrConfig) {\n const PusherCtor = (globalThis as any).Pusher ?? (globalThis as any).pusherJs;\n if (!PusherCtor) {\n throw new Error(\"pusher-js not found. Install it or pass a Pusher instance.\");\n }\n this.pusher = new PusherCtor((pusherOrConfig as PusherConfig).key, pusherOrConfig) as Pusher;\n } else {\n this.pusher = pusherOrConfig as Pusher;\n }\n }\n\n private buildChannelName(base: string, type: \"public\" | \"private\" | \"presence\"): string {\n switch (type) {\n case \"private\":\n return `private-${base}`;\n case \"presence\":\n return `presence-${base}`;\n default:\n return base;\n }\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n connect(): void {\n if (this.pusher.connection?.state !== \"connected\") {\n this.pusher.connect();\n }\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => channel.unbind_all?.() ?? channel.unsubscribe?.());\n this.subscriptions.clear();\n this.pusher.disconnect?.();\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const baseName = await this.buildResolvedChannelName(threadId);\n const channelName = this.buildChannelName(baseName, this.threadChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents = [\n \"message.posted\",\n \"message.edited\",\n \"message.deleted\",\n \"reaction.added\",\n \"reaction.removed\",\n \"typing.started\",\n ] as const;\n\n threadEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const baseName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channelName = this.buildChannelName(baseName, this.userChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents = [\"typing.started\", \"streaming.chunk\", \"dm.requested\"] as const;\n\n userEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n return this.pusher.connection?.state === \"connected\";\n }\n\n private dispatchToHandler(event: ChatEvent, handlers: EventHandlers): void {\n switch (event.type) {\n case \"message.posted\":\n handlers.onMessagePosted?.(event as any);\n break;\n case \"message.edited\":\n handlers.onMessageEdited?.(event as any);\n break;\n case \"message.deleted\":\n handlers.onMessageDeleted?.(event as any);\n break;\n case \"reaction.added\":\n handlers.onReactionAdded?.(event as any);\n break;\n case \"reaction.removed\":\n handlers.onReactionRemoved?.(event as any);\n break;\n case \"typing.started\":\n handlers.onTypingStarted?.(event as any);\n break;\n case \"streaming.chunk\":\n handlers.onStreamingChunk?.(event as any);\n break;\n case \"dm.requested\":\n handlers.onDMRequested?.(event as any);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Echo from \"laravel-echo\";\n\ninterface EchoChannel {\n listen(event: string, callback: (data: unknown) => void): this;\n unsubscribe(): void;\n stopListening(event?: string, callback?: (data: unknown) => void): this;\n}\n\nexport class LaravelEchoBroadcastClient implements BroadcastClient {\n private echo: Echo<any>;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, EchoChannel> = new Map();\n\n constructor(echo: Echo<any>, channelPrefix: string = \"chat\", channelTypes?: ChannelTypeConfig) {\n this.echo = echo;\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n }\n\n private subscribeToEcho(name: string, type: \"public\" | \"private\" | \"presence\"): EchoChannel {\n switch (type) {\n case \"private\":\n return this.echo.private(name) as unknown as EchoChannel;\n case \"presence\":\n return this.echo.join(name) as unknown as EchoChannel;\n default:\n return this.echo.channel(name) as unknown as EchoChannel;\n }\n }\n\n connect(): void | Promise<void> {\n return Promise.resolve();\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => {\n channel.unsubscribe?.();\n channel.stopListening?.();\n });\n this.subscriptions.clear();\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const channelName = await this.buildResolvedChannelName(threadId);\n const channel = this.subscribeToEcho(channelName, this.threadChannelType);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"message.posted\", handler: \"onMessagePosted\" },\n { type: \"message.edited\", handler: \"onMessageEdited\" },\n { type: \"message.deleted\", handler: \"onMessageDeleted\" },\n { type: \"reaction.added\", handler: \"onReactionAdded\" },\n { type: \"reaction.removed\", handler: \"onReactionRemoved\" },\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n ];\n\n threadEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const channelName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channel = this.subscribeToEcho(channelName, this.userChannelType);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n { type: \"streaming.chunk\", handler: \"onStreamingChunk\" },\n { type: \"dm.requested\", handler: \"onDMRequested\" },\n ];\n\n userEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n try {\n const connector = (this.echo as any).connector;\n if (!connector) return false;\n\n if (connector.pusher?.connection?.state === \"connected\") return true;\n if (connector.socket?.connected) return true;\n\n return false;\n } catch {\n return false;\n }\n }\n}\n","import type { PushConfig, PushSubscriptionStatus, PushEventData } from \"./types\";\n\nexport class PushManager {\n private config: PushConfig;\n private registration: ServiceWorkerRegistration | null = null;\n private status: PushSubscriptionStatus = \"unsupported\";\n private statusListeners: Set<(status: PushSubscriptionStatus) => void> = new Set();\n private messageListeners: Set<(data: PushEventData) => void> = new Set();\n\n constructor(config: PushConfig) {\n this.config = config;\n }\n\n static isSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"serviceWorker\" in navigator &&\n \"PushManager\" in window &&\n \"Notification\" in window\n );\n }\n\n getStatus(): PushSubscriptionStatus {\n return this.status;\n }\n\n onStatusChange(listener: (status: PushSubscriptionStatus) => void): () => void {\n this.statusListeners.add(listener);\n return () => {\n this.statusListeners.delete(listener);\n };\n }\n\n onMessage(listener: (data: PushEventData) => void): () => void {\n this.messageListeners.add(listener);\n return () => {\n this.messageListeners.delete(listener);\n };\n }\n\n async initialize(): Promise<void> {\n if (!PushManager.isSupported()) {\n this.setStatus(\"unsupported\");\n return;\n }\n if (Notification.permission === \"denied\") {\n this.setStatus(\"denied\");\n return;\n }\n\n try {\n this.registration = await navigator.serviceWorker.register(\n this.config.serviceWorkerUrl || \"/chat-service-worker.js\",\n {\n scope: this.config.serviceWorkerScope || \"/\",\n type: this.config.serviceWorkerType,\n },\n );\n await navigator.serviceWorker.ready;\n\n navigator.serviceWorker.addEventListener(\"message\", (event: MessageEvent) => {\n const msg = event.data as Record<string, unknown>;\n if (msg?.type === \"chat-widget:push-data\") {\n const pushData = msg.data as PushEventData;\n this.messageListeners.forEach((listener) => listener(pushData));\n }\n });\n\n const subscription = await this.registration.pushManager.getSubscription();\n this.setStatus(subscription ? \"subscribed\" : \"default\");\n } catch {\n this.setStatus(\"error\");\n }\n }\n\n async subscribe(): Promise<void> {\n if (!this.registration)\n throw new Error(\"PushManager not initialized. Call initialize() first.\");\n\n this.setStatus(\"subscribing\");\n\n try {\n let subscription = await this.registration.pushManager.getSubscription();\n\n if (!subscription) {\n const permission = await Notification.requestPermission();\n if (permission !== \"granted\") {\n this.setStatus(permission === \"denied\" ? \"denied\" : \"default\");\n return;\n }\n\n const vapidPublicKey = await this.config.getVapidPublicKey();\n const convertedKey = this.urlBase64ToUint8Array(vapidPublicKey);\n subscription = await this.registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: convertedKey.buffer as ArrayBuffer,\n });\n }\n\n await this.config.onSubscribe(subscription.toJSON());\n this.setStatus(\"subscribed\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push subscription failed\");\n }\n }\n\n async unsubscribe(): Promise<void> {\n if (!this.registration) return;\n\n try {\n const subscription = await this.registration.pushManager.getSubscription();\n if (subscription) {\n await this.config.onUnsubscribe(subscription.toJSON());\n await subscription.unsubscribe();\n }\n this.setStatus(\"default\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push unsubscription failed\");\n }\n }\n\n private urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));\n }\n\n private setStatus(status: PushSubscriptionStatus): void {\n this.status = status;\n this.statusListeners.forEach((listener) => listener(status));\n }\n}\n","import { HttpClient } from \"../client/HttpClient\";\nimport type { PushConfig } from \"./types\";\n\nexport function createPushSubscriptionHandlers(\n httpClient: HttpClient,\n userId: string,\n): Pick<PushConfig, \"onSubscribe\" | \"onUnsubscribe\"> {\n return {\n onSubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.post(\"/api/push/subscriptions\", {\n userId,\n subscription,\n userAgent: navigator.userAgent,\n });\n },\n onUnsubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.delete(\n `/api/push/subscriptions?userId=${encodeURIComponent(userId)}&endpoint=${encodeURIComponent(subscription.endpoint || \"\")}`,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client/HttpClient.ts","../src/events/base/ChatEvent.ts","../src/events/MessagePostedEvent.ts","../src/events/MessageEditedEvent.ts","../src/events/MessageDeletedEvent.ts","../src/events/ReactionAddedEvent.ts","../src/events/ReactionRemovedEvent.ts","../src/events/TypingStartedEvent.ts","../src/events/StreamingChunkEvent.ts","../src/events/DMRequestedEvent.ts","../src/events/ChatEventFactory.ts","../src/utils/eventIdGenerator.ts","../src/client/WebChatClient.ts","../src/client/PusherBroadcastClient.ts","../src/client/LaravelEchoBroadcastClient.ts","../src/push/PushManager.ts","../src/push/PushSubscriptionManager.ts"],"sourcesContent":["export { WebChatClient } from \"./client/WebChatClient\";\nexport type {\n WebChatClientConfig,\n ReconfigureConfig,\n LoadMessagesOptions,\n LoadMessagesResult,\n} from \"./client/WebChatClient\";\n\nexport {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./client/BroadcastClient\";\nexport { PusherBroadcastClient } from \"./client/PusherBroadcastClient\";\nexport type { PusherConfig } from \"./client/PusherBroadcastClient\";\nexport { LaravelEchoBroadcastClient } from \"./client/LaravelEchoBroadcastClient\";\n\nexport { HttpClient } from \"./client/HttpClient\";\nexport type { HttpClientConfig, ChatResponse } from \"./client/HttpClient\";\n\nexport * from \"./types\";\n\nexport { ChatEvent, UnknownEvent } from \"./events/base/ChatEvent\";\nexport { parseChatEvent } from \"./events/ChatEventFactory\";\nexport { MessagePostedEvent } from \"./events/MessagePostedEvent\";\nexport { MessageEditedEvent } from \"./events/MessageEditedEvent\";\nexport { MessageDeletedEvent } from \"./events/MessageDeletedEvent\";\nexport { ReactionAddedEvent } from \"./events/ReactionAddedEvent\";\nexport { ReactionRemovedEvent } from \"./events/ReactionRemovedEvent\";\nexport { TypingStartedEvent } from \"./events/TypingStartedEvent\";\nexport { StreamingChunkEvent } from \"./events/StreamingChunkEvent\";\nexport { DMRequestedEvent } from \"./events/DMRequestedEvent\";\n\nexport { generateId, generateConversationId } from \"./utils/eventIdGenerator\";\n\nexport { PushManager } from \"./push/PushManager\";\nexport { createPushSubscriptionHandlers } from \"./push/PushSubscriptionManager\";\nexport type { PushSubscriptionStatus, PushConfig, PushEventData } from \"./push/types\";\n","export interface HttpClientConfig {\n apiUrl: string;\n headers?: Record<string, string>;\n timeout?: number;\n verifyToken?: string;\n}\n\nexport interface ChatResponse {\n id: string;\n role: \"assistant\" | \"user\";\n text: string;\n attachments?: Array<{\n type: string;\n url: string;\n name?: string;\n mime_type?: string;\n size?: number;\n }>;\n events?: Array<Record<string, unknown>>;\n}\n\nexport class HttpClient {\n private config: Required<Pick<HttpClientConfig, \"apiUrl\" | \"timeout\">> & {\n headers: Record<string, string>;\n };\n\n constructor(config: HttpClientConfig) {\n const headers: Record<string, string> = { ...config.headers };\n if (config.verifyToken) {\n headers[\"X-Verify-Token\"] = config.verifyToken;\n }\n this.config = { apiUrl: config.apiUrl, timeout: config.timeout ?? 30000, headers };\n }\n\n async get(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"GET\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async post(url: string, body: unknown, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...this.config.headers },\n signal: combined,\n body: JSON.stringify(body),\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async delete(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"DELETE\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n const text = await response.text();\n return text ? JSON.parse(text) : undefined;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async sendMessage(\n messages: Array<{\n id: string;\n role: string;\n text: string;\n attachments?: Array<{ url: string; name?: string; mime_type?: string; size?: number }>;\n }>,\n endpoint: string = \"/api/webhooks/web\",\n conversationId?: string,\n ): Promise<ChatResponse> {\n return this.post(endpoint, { id: conversationId, messages }) as Promise<ChatResponse>;\n }\n\n async sendAction(\n actionId: string,\n value: string,\n messageId: string,\n conversationId: string,\n endpoint: string = \"/api/webhooks/web\",\n ): Promise<Record<string, unknown>> {\n return this.post(endpoint, {\n id: conversationId,\n action: { actionId, value, messageId },\n }) as Promise<Record<string, unknown>>;\n }\n\n async editMessage(\n messageId: string,\n newText: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/edit\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { text: newText });\n }\n\n async deleteMessage(\n messageId: string,\n endpointTemplate: string = \"/api/chat/messages/{id}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.delete(url);\n }\n\n async postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: this.config.headers,\n signal: combined,\n body: formData,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n setHeader(name: string, value: string): void {\n this.config.headers[name] = value;\n }\n\n removeHeader(name: string): void {\n delete this.config.headers[name];\n }\n\n private resolve(url: string): string {\n return /^https?:\\/\\//.test(url) ? url : `${this.config.apiUrl}${url}`;\n }\n\n private expandTemplate(template: string, params: Record<string, string>): string {\n let url = template;\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`{${key}}`, encodeURIComponent(value));\n }\n return this.resolve(url);\n }\n}\n","export abstract class ChatEvent {\n readonly type: string;\n readonly threadId: string;\n readonly timestamp: number;\n\n constructor(type: string, threadId: string, timestamp: number) {\n this.type = type;\n this.threadId = threadId;\n this.timestamp = timestamp;\n }\n\n static fromJSON: ((json: Record<string, unknown>) => ChatEvent) | undefined;\n}\n\nexport class UnknownEvent extends ChatEvent {\n readonly data: Record<string, unknown>;\n\n constructor(type: string, threadId: string, data: Record<string, unknown>, timestamp: number) {\n super(type, threadId, timestamp);\n this.data = data;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User, Card } from \"../types\";\n\nexport class MessagePostedEvent extends ChatEvent {\n readonly messageId: string;\n readonly text: string;\n readonly author: User;\n readonly card?: Card;\n readonly attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>;\n\n constructor(\n threadId: string,\n messageId: string,\n text: string,\n author: User,\n card?: Card,\n attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp?: number,\n ) {\n super(\"message.posted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.text = text;\n this.author = author;\n this.card = card;\n this.attachments = attachments;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { Card } from \"../types\";\n\nexport class MessageEditedEvent extends ChatEvent {\n readonly messageId: string;\n readonly newText: string;\n readonly card?: Card;\n\n constructor(\n threadId: string,\n messageId: string,\n newText: string,\n card?: Card,\n timestamp?: number,\n ) {\n super(\"message.edited\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.newText = newText;\n this.card = card;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class MessageDeletedEvent extends ChatEvent {\n readonly messageId: string;\n\n constructor(threadId: string, messageId: string, timestamp?: number) {\n super(\"message.deleted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionAddedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.added\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionRemovedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.removed\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class TypingStartedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"typing.started\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class StreamingChunkEvent extends ChatEvent {\n readonly messageId: string;\n readonly chunk: string;\n readonly isFinal: boolean;\n\n constructor(\n threadId: string,\n messageId: string,\n chunk: string,\n isFinal: boolean,\n timestamp?: number,\n ) {\n super(\"streaming.chunk\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.chunk = chunk;\n this.isFinal = isFinal;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class DMRequestedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"dm.requested\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent, UnknownEvent } from \"./base/ChatEvent\";\nimport type { Card, User } from \"../types\";\nimport { MessagePostedEvent } from \"./MessagePostedEvent\";\nimport { MessageEditedEvent } from \"./MessageEditedEvent\";\nimport { MessageDeletedEvent } from \"./MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"./ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"./ReactionRemovedEvent\";\nimport { TypingStartedEvent } from \"./TypingStartedEvent\";\nimport { StreamingChunkEvent } from \"./StreamingChunkEvent\";\nimport { DMRequestedEvent } from \"./DMRequestedEvent\";\n\nfunction parseCard(value: unknown): Card | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const obj = value as Record<string, unknown>;\n if (typeof obj.type !== \"string\") return undefined;\n return obj as unknown as Card;\n}\n\nexport function parseChatEvent(json: Record<string, unknown>): ChatEvent {\n const type = json.type as string;\n const threadId = json.threadId as string;\n const timestamp = json.timestamp as number;\n const data = (json.data ?? {}) as Record<string, unknown>;\n\n switch (type) {\n case \"message.posted\":\n return new MessagePostedEvent(\n threadId,\n data.messageId as string,\n data.text as string,\n data.author as User,\n parseCard(data.card),\n data.attachments as Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp,\n );\n case \"message.edited\":\n return new MessageEditedEvent(\n threadId,\n data.messageId as string,\n data.newText as string,\n parseCard(data.card),\n timestamp,\n );\n case \"message.deleted\":\n return new MessageDeletedEvent(threadId, data.messageId as string, timestamp);\n case \"reaction.added\":\n return new ReactionAddedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"reaction.removed\":\n return new ReactionRemovedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"typing.started\":\n return new TypingStartedEvent(threadId, data.userId as string, timestamp);\n case \"streaming.chunk\":\n return new StreamingChunkEvent(\n threadId,\n data.messageId as string,\n data.chunk as string,\n data.isFinal as boolean,\n timestamp,\n );\n case \"dm.requested\":\n return new DMRequestedEvent(threadId, data.userId as string, timestamp);\n default:\n return new UnknownEvent(type, threadId, data, timestamp);\n }\n}\n\n// Wire up the static method\nChatEvent.fromJSON = parseChatEvent;\n","export function generateId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\nexport function generateConversationId(): string {\n return `conv-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n","import { HttpClient } from \"./HttpClient\";\nimport type { BroadcastClient, EventHandlers, Unsubscribe } from \"./BroadcastClient\";\nimport type { Message } from \"../types\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type { MessagePostedEvent } from \"../events/MessagePostedEvent\";\nimport type { MessageEditedEvent } from \"../events/MessageEditedEvent\";\nimport type { MessageDeletedEvent } from \"../events/MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"../events/ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"../events/ReactionRemovedEvent\";\nimport type { TypingStartedEvent } from \"../events/TypingStartedEvent\";\nimport type { StreamingChunkEvent } from \"../events/StreamingChunkEvent\";\nimport type { DMRequestedEvent } from \"../events/DMRequestedEvent\";\nimport { generateId, generateConversationId } from \"../utils/eventIdGenerator\";\n\nexport interface ReconfigureConfig {\n userId?: string;\n userName?: string;\n verifyToken?: string;\n conversationId?: string;\n headers?: Record<string, string>;\n}\n\nexport interface WebChatClientConfig {\n apiUrl: string;\n userId: string;\n userName: string;\n broadcastClient?: BroadcastClient;\n headers?: Record<string, string>;\n verifyToken?: string;\n conversationId?: string;\n endpoints?: {\n sendMessage?: string;\n loadMessages?: string;\n editMessage?: string;\n deleteMessage?: string;\n };\n features?: {\n editMessages?: boolean;\n deleteMessages?: boolean;\n reactions?: boolean;\n };\n}\n\ninterface StreamingState {\n messageId: string;\n accumulatedText: string;\n isComplete: boolean;\n}\n\ninterface AttachmentInput {\n url: string;\n name?: string;\n mimeType?: string;\n size?: number;\n}\n\nexport interface LoadMessagesOptions {\n limit?: number;\n before?: number;\n after?: number;\n skipStateSeed?: boolean;\n}\n\nexport interface LoadMessagesResult {\n messages: Message[];\n hasMore: boolean;\n nextCursor?: number;\n prevCursor?: number;\n}\n\nexport class WebChatClient {\n private config: WebChatClientConfig;\n private httpClient: HttpClient;\n private broadcastClient?: BroadcastClient;\n private conversationId: string;\n private messages: Message[] = [];\n private currentUserId: string;\n private eventHandlers: EventHandlers = {};\n private streamingMessages: Map<string, StreamingState> = new Map();\n private pendingTyping: ReturnType<typeof setTimeout> | null = null;\n private subscribers: Map<string, Array<(event: unknown) => void>> = new Map();\n private sendQueue: Array<() => Promise<void>> = [];\n private isProcessingQueue = false;\n private unsubscribeUserChannel?: Unsubscribe;\n\n constructor(config: WebChatClientConfig) {\n this.config = config;\n this.httpClient = new HttpClient({\n apiUrl: config.apiUrl,\n headers: {\n \"X-User-Id\": config.userId,\n \"X-User-Name\": config.userName,\n ...(config.headers ?? {}),\n },\n verifyToken: config.verifyToken,\n });\n this.broadcastClient = config.broadcastClient;\n this.conversationId = config.conversationId ?? generateConversationId();\n this.currentUserId = config.userId;\n }\n\n reconfigure(config: ReconfigureConfig): void {\n if (config.userId) {\n this.currentUserId = config.userId;\n this.httpClient.setHeader(\"X-User-Id\", config.userId);\n }\n if (config.userName) {\n this.config = { ...this.config, userName: config.userName };\n this.httpClient.setHeader(\"X-User-Name\", config.userName);\n }\n if (config.verifyToken) {\n this.config = { ...this.config, verifyToken: config.verifyToken };\n this.httpClient.setHeader(\"X-Verify-Token\", config.verifyToken);\n }\n if (config.conversationId) {\n this.conversationId = config.conversationId;\n }\n if (config.headers) {\n Object.entries(config.headers).forEach(([key, value]) => {\n this.httpClient.setHeader(key, value);\n });\n }\n }\n\n setLocaleHeader(locale: string): void {\n this.httpClient.setHeader(\"X-Locale\", locale);\n this.httpClient.setHeader(\"X-Language\", locale.split(\"-\")[0] ?? locale);\n }\n\n setTimezoneHeader(timezone: string): void {\n this.httpClient.setHeader(\"X-Timezone\", timezone);\n }\n\n async connect(): Promise<void> {\n if (this.broadcastClient) {\n this.broadcastClient.connect();\n\n const threadId = this.getThreadId();\n const threadEvents: EventHandlers = {\n onMessagePosted: (event) => this.handleMessagePosted(event),\n };\n\n if (this.config.features?.editMessages) {\n threadEvents.onMessageEdited = (event) => this.handleMessageEdited(event);\n }\n if (this.config.features?.deleteMessages) {\n threadEvents.onMessageDeleted = (event) => this.handleMessageDeleted(event);\n }\n if (this.config.features?.reactions) {\n threadEvents.onReactionAdded = (event) => this.handleReactionAdded(event);\n threadEvents.onReactionRemoved = (event) => this.handleReactionRemoved(event);\n }\n\n threadEvents.onTypingStarted = (event) => this.handleTypingStarted(event);\n\n await this.broadcastClient.subscribe(threadId, threadEvents);\n\n this.unsubscribeUserChannel = await this.broadcastClient.subscribeToUser(\n threadId,\n this.currentUserId,\n {\n onStreamingChunk: (event) => this.handleStreamingChunk(event),\n onDMRequested: (event) => this.handleDMRequested(event),\n },\n );\n }\n }\n\n disconnect(): void {\n this.unsubscribeUserChannel?.();\n this.unsubscribeUserChannel = undefined;\n this.broadcastClient?.disconnect();\n this.streamingMessages.clear();\n }\n\n async loadMessages(\n options?: LoadMessagesOptions,\n signal?: AbortSignal,\n ): Promise<LoadMessagesResult> {\n const endpoint = this.config.endpoints?.loadMessages ?? \"/api/chat/messages\";\n const threadId = this.getThreadId();\n const params = new URLSearchParams({\n threadId,\n limit: String(options?.limit ?? 50),\n });\n if (options?.before) params.set(\"before\", String(options.before));\n if (options?.after) params.set(\"after\", String(options.after));\n\n const response = (await this.httpClient.get(\n `${endpoint}?${params.toString()}`,\n signal,\n )) as Record<string, unknown>;\n const rawMessages = (response.messages as Record<string, unknown>[]) ?? [];\n const messages: Message[] = rawMessages.map((msg) => ({\n id: msg.id as string,\n threadId,\n content: {\n text: msg.text as string,\n cards: msg.card ? ([msg.card as Record<string, unknown>] as never[]) : undefined,\n },\n author: {\n id: (msg.author as Record<string, unknown>).id as string,\n name: (msg.author as Record<string, unknown>).name as string,\n isBot: ((msg.author as Record<string, unknown>).isBot as boolean) ?? false,\n isMe: (msg.author as Record<string, unknown>).id === this.currentUserId,\n },\n timestamp: msg.timestamp as number,\n attachments: (msg.attachments as Record<string, unknown>[])?.map((a) => ({\n id: `att-${msg.id as string}-${a.url as string}`,\n url: a.url as string,\n name: a.name as string,\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n reactions: (msg.reactions as { emoji: string; count: number; users: string[] }[]) ?? [],\n }));\n\n if (!options?.before && !options?.after && !options?.skipStateSeed) {\n this.messages = messages;\n this.notifySubscribers(\"messages:loaded\", messages);\n }\n\n return {\n messages,\n hasMore: (response.hasMore as boolean) ?? false,\n nextCursor: response.nextCursor as number | undefined,\n prevCursor: response.prevCursor as number | undefined,\n };\n }\n\n async sendMessage(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push(async () => {\n try {\n await this.executeSend(text, attachments);\n resolve();\n } catch (e) {\n reject(e);\n }\n });\n this.processQueue();\n });\n }\n\n private async processQueue(): Promise<void> {\n if (this.isProcessingQueue) return;\n this.isProcessingQueue = true;\n try {\n while (this.sendQueue.length > 0) {\n const task = this.sendQueue.shift()!;\n await task();\n }\n } finally {\n this.isProcessingQueue = false;\n }\n }\n\n private async executeSend(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n const messageId = generateId();\n\n const userMessage: Message = {\n id: messageId,\n threadId: this.getThreadId(),\n content: { text },\n author: { id: this.currentUserId, name: this.config.userName, isMe: true },\n timestamp: Date.now(),\n attachments:\n attachments.length > 0\n ? attachments.map((a, i) => ({\n id: `att-${messageId}-${i}`,\n name: a.name ?? \"\",\n url: a.url,\n size: a.size,\n mimeType: a.mimeType,\n }))\n : undefined,\n };\n\n this.messages.push(userMessage);\n this.notifySubscribers(\"message:added\", userMessage);\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendMessage(\n [\n {\n id: messageId,\n role: \"user\",\n text,\n attachments: attachments.map((a) => ({\n url: a.url,\n name: a.name,\n mime_type: a.mimeType,\n size: a.size,\n })),\n },\n ],\n endpoint,\n this.conversationId,\n );\n\n if (response.events) {\n response.events.forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n\n if (response.text && !response.events?.some((e) => e.type === \"message.posted\")) {\n const assistantMessage: Message = {\n id: response.id ?? generateId(),\n threadId: this.getThreadId(),\n content: { text: response.text },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: Date.now(),\n attachments: (response.attachments as Record<string, unknown>[])?.map((a, i) => ({\n id: `att-${response.id ?? \"msg\"}-${i}`,\n name: (a.name as string) ?? \"\",\n url: (a.url as string) ?? \"\",\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n };\n this.messages.push(assistantMessage);\n this.notifySubscribers(\"message:added\", assistantMessage);\n }\n }\n\n async sendAction(messageId: string, actionId: string, value: string): Promise<void> {\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendAction(\n actionId,\n value,\n messageId,\n this.conversationId,\n endpoint,\n );\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async editMessage(messageId: string, newText: string): Promise<void> {\n if (!this.config.features?.editMessages) {\n throw new Error(\"Edit messages not enabled. Set features.editMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.editMessage ?? \"/api/chat/messages/{id}/edit\";\n await this.httpClient.editMessage(messageId, newText, endpoint);\n }\n\n async deleteMessage(messageId: string): Promise<void> {\n if (!this.config.features?.deleteMessages) {\n throw new Error(\"Delete messages not enabled. Set features.deleteMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.deleteMessage ?? \"/api/chat/messages/{id}\";\n await this.httpClient.deleteMessage(messageId, endpoint);\n }\n\n async addReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n\n // Optimistic local update\n this.handleReactionAdded(\n new ReactionAddedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId }),\n );\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = (await this.httpClient.post(endpoint, {\n id: this.conversationId,\n reaction: { messageId, emoji, added: true },\n })) as Record<string, unknown>;\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async removeReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n\n // Optimistic local update\n this.handleReactionRemoved(\n new ReactionRemovedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId }),\n );\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = (await this.httpClient.post(endpoint, {\n id: this.conversationId,\n reaction: { messageId, emoji, added: false },\n })) as Record<string, unknown>;\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n onMessagePosted(handler: (event: MessagePostedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message.posted\", handler);\n }\n\n onMessageEdited(handler: (event: MessageEditedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:edited\", handler);\n }\n\n onMessageDeleted(handler: (event: MessageDeletedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:deleted\", handler);\n }\n\n onReactionAdded(handler: (event: ReactionAddedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:added\", handler);\n }\n\n onReactionRemoved(handler: (event: ReactionRemovedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:removed\", handler);\n }\n\n onStreamingChunk(handler: (event: StreamingChunkEvent) => void): Unsubscribe {\n return this.addEventListener(\"streaming:chunk\", handler);\n }\n\n onTypingStarted(handler: (event: TypingStartedEvent) => void): Unsubscribe {\n return this.addEventListener(\"typing:started\", handler);\n }\n\n getConversationId(): string {\n return this.conversationId;\n }\n getMessages(): Message[] {\n return [...this.messages];\n }\n getThreadId(): string {\n return `web:${this.currentUserId}:${this.conversationId}`;\n }\n getCurrentUserId(): string {\n return this.currentUserId;\n }\n getFeatures(): NonNullable<WebChatClientConfig[\"features\"]> {\n return this.config.features ?? {};\n }\n getEndpoints(): NonNullable<WebChatClientConfig[\"endpoints\"]> {\n return this.config.endpoints ?? {};\n }\n getHttpClient(): HttpClient {\n return this.httpClient;\n }\n\n addEventListener<T = unknown>(eventType: string, handler: (event: T) => void): Unsubscribe {\n if (!this.subscribers.has(eventType)) this.subscribers.set(eventType, []);\n this.subscribers.get(eventType)!.push(handler as (event: unknown) => void);\n return () => {\n const handlers = this.subscribers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler as (event: unknown) => void);\n if (index !== -1) handlers.splice(index, 1);\n }\n };\n }\n\n private handleMessagePosted(event: MessagePostedEvent): void {\n if (this.messages.some((m) => m.id === event.messageId)) return;\n if (this.streamingMessages.has(event.messageId)) return;\n\n const message: Message = {\n id: event.messageId,\n threadId: event.threadId,\n content: { text: event.text, cards: event.card ? [event.card] : undefined },\n author: event.author,\n timestamp: event.timestamp,\n attachments: event.attachments?.map((a) => ({\n id: `att-${event.messageId}-${Math.random().toString(36).slice(2, 8)}`,\n name: a.name ?? \"\",\n url: a.url ?? \"\",\n type: a.type,\n mimeType: a.mimeType,\n size: a.size ?? undefined,\n })),\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n this.notifySubscribers(\"message.posted\", event);\n }\n\n private handleMessageEdited(event: MessageEditedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.content) {\n message.content.text = event.newText;\n this.notifySubscribers(\"message:edited\", event);\n }\n }\n\n private handleMessageDeleted(event: MessageDeletedEvent): void {\n const index = this.messages.findIndex((m) => m.id === event.messageId);\n if (index !== -1) {\n this.messages.splice(index, 1);\n this.notifySubscribers(\"message:deleted\", event);\n }\n }\n\n private handleReactionAdded(event: ReactionAddedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message) {\n if (!message.reactions) message.reactions = [];\n\n const existing = message.reactions.find((r) => r.emoji === event.emoji);\n if (existing) {\n existing.count++;\n existing.users.push(event.user.id);\n } else {\n message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });\n }\n }\n this.notifySubscribers(\"reaction:added\", event);\n }\n\n private handleReactionRemoved(event: ReactionRemovedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.reactions) {\n const index = message.reactions.findIndex((r) => r.emoji === event.emoji);\n if (index !== -1) {\n const reaction = message.reactions[index]!;\n reaction.count--;\n reaction.users = reaction.users.filter((id) => id !== event.user.id);\n if (reaction.count === 0) message.reactions.splice(index, 1);\n }\n }\n this.notifySubscribers(\"reaction:removed\", event);\n }\n\n private handleStreamingChunk(event: StreamingChunkEvent): void {\n const { messageId, chunk, isFinal } = event;\n\n if (!this.streamingMessages.has(messageId)) {\n this.streamingMessages.set(messageId, { messageId, accumulatedText: \"\", isComplete: false });\n this.notifySubscribers(\"streaming:started\", event);\n }\n\n const state = this.streamingMessages.get(messageId)!;\n state.accumulatedText += chunk;\n\n if (isFinal) {\n state.isComplete = true;\n if (!this.messages.some((m) => m.id === messageId)) {\n const message: Message = {\n id: messageId,\n threadId: event.threadId,\n content: { text: state.accumulatedText },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: event.timestamp,\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n }\n this.streamingMessages.delete(messageId);\n this.notifySubscribers(\"streaming:complete\", { messageId, text: state.accumulatedText });\n } else {\n this.notifySubscribers(\"streaming:chunk\", event);\n }\n }\n\n private handleTypingStarted(event: TypingStartedEvent): void {\n if (this.pendingTyping) clearTimeout(this.pendingTyping);\n this.notifySubscribers(\"typing:started\", event);\n this.pendingTyping = setTimeout(() => {\n this.notifySubscribers(\"typing:stopped\", { userId: event.userId });\n }, 3000);\n }\n\n private handleDMRequested(event: DMRequestedEvent): void {\n this.notifySubscribers(\"dm.requested\", event);\n }\n\n private notifySubscribers<T>(eventType: string, data: T): void {\n this.subscribers.get(eventType)?.forEach((handler) => handler(data));\n }\n\n private dispatchEvent(event: ChatEvent): void {\n switch (event.type) {\n case \"message.posted\":\n this.handleMessagePosted(event as MessagePostedEvent);\n break;\n case \"message.edited\":\n this.handleMessageEdited(event as MessageEditedEvent);\n break;\n case \"message.deleted\":\n this.handleMessageDeleted(event as MessageDeletedEvent);\n break;\n case \"reaction.added\":\n this.handleReactionAdded(event as ReactionAddedEvent);\n break;\n case \"reaction.removed\":\n this.handleReactionRemoved(event as ReactionRemovedEvent);\n break;\n case \"typing.started\":\n this.handleTypingStarted(event as TypingStartedEvent);\n break;\n case \"streaming.chunk\":\n this.handleStreamingChunk(event as StreamingChunkEvent);\n break;\n case \"dm.requested\":\n this.handleDMRequested(event as DMRequestedEvent);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel as PusherChannel } from \"pusher-js\";\n\nexport interface PusherConfig {\n key: string;\n cluster?: string;\n host?: string;\n port?: number;\n forceTLS?: boolean;\n authEndpoint?: string;\n}\n\nexport class PusherBroadcastClient implements BroadcastClient {\n private pusher: Pusher;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, PusherChannel> = new Map();\n\n constructor(pusher: Pusher, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(config: PusherConfig, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(\n pusherOrConfig: Pusher | PusherConfig,\n channelPrefix: string = \"chat\",\n channelTypes?: ChannelTypeConfig,\n ) {\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n\n if (\"key\" in pusherOrConfig) {\n const PusherCtor = (globalThis as any).Pusher ?? (globalThis as any).pusherJs;\n if (!PusherCtor) {\n throw new Error(\"pusher-js not found. Install it or pass a Pusher instance.\");\n }\n this.pusher = new PusherCtor((pusherOrConfig as PusherConfig).key, pusherOrConfig) as Pusher;\n } else {\n this.pusher = pusherOrConfig as Pusher;\n }\n }\n\n private buildChannelName(base: string, type: \"public\" | \"private\" | \"presence\"): string {\n switch (type) {\n case \"private\":\n return `private-${base}`;\n case \"presence\":\n return `presence-${base}`;\n default:\n return base;\n }\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n connect(): void {\n if (this.pusher.connection?.state !== \"connected\") {\n this.pusher.connect();\n }\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => channel.unbind_all?.() ?? channel.unsubscribe?.());\n this.subscriptions.clear();\n this.pusher.disconnect?.();\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const baseName = await this.buildResolvedChannelName(threadId);\n const channelName = this.buildChannelName(baseName, this.threadChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents = [\n \"message.posted\",\n \"message.edited\",\n \"message.deleted\",\n \"reaction.added\",\n \"reaction.removed\",\n \"typing.started\",\n ] as const;\n\n threadEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const baseName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channelName = this.buildChannelName(baseName, this.userChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents = [\"typing.started\", \"streaming.chunk\", \"dm.requested\"] as const;\n\n userEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n return this.pusher.connection?.state === \"connected\";\n }\n\n private dispatchToHandler(event: ChatEvent, handlers: EventHandlers): void {\n switch (event.type) {\n case \"message.posted\":\n handlers.onMessagePosted?.(event as any);\n break;\n case \"message.edited\":\n handlers.onMessageEdited?.(event as any);\n break;\n case \"message.deleted\":\n handlers.onMessageDeleted?.(event as any);\n break;\n case \"reaction.added\":\n handlers.onReactionAdded?.(event as any);\n break;\n case \"reaction.removed\":\n handlers.onReactionRemoved?.(event as any);\n break;\n case \"typing.started\":\n handlers.onTypingStarted?.(event as any);\n break;\n case \"streaming.chunk\":\n handlers.onStreamingChunk?.(event as any);\n break;\n case \"dm.requested\":\n handlers.onDMRequested?.(event as any);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Echo from \"laravel-echo\";\n\ninterface EchoChannel {\n listen(event: string, callback: (data: unknown) => void): this;\n unsubscribe(): void;\n stopListening(event?: string, callback?: (data: unknown) => void): this;\n}\n\nexport class LaravelEchoBroadcastClient implements BroadcastClient {\n private echo: Echo<any>;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, EchoChannel> = new Map();\n\n constructor(echo: Echo<any>, channelPrefix: string = \"chat\", channelTypes?: ChannelTypeConfig) {\n this.echo = echo;\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n }\n\n private subscribeToEcho(name: string, type: \"public\" | \"private\" | \"presence\"): EchoChannel {\n switch (type) {\n case \"private\":\n return this.echo.private(name) as unknown as EchoChannel;\n case \"presence\":\n return this.echo.join(name) as unknown as EchoChannel;\n default:\n return this.echo.channel(name) as unknown as EchoChannel;\n }\n }\n\n connect(): void | Promise<void> {\n return Promise.resolve();\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => {\n channel.unsubscribe?.();\n channel.stopListening?.();\n });\n this.subscriptions.clear();\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const channelName = await this.buildResolvedChannelName(threadId);\n const channel = this.subscribeToEcho(channelName, this.threadChannelType);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"message.posted\", handler: \"onMessagePosted\" },\n { type: \"message.edited\", handler: \"onMessageEdited\" },\n { type: \"message.deleted\", handler: \"onMessageDeleted\" },\n { type: \"reaction.added\", handler: \"onReactionAdded\" },\n { type: \"reaction.removed\", handler: \"onReactionRemoved\" },\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n ];\n\n threadEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const channelName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channel = this.subscribeToEcho(channelName, this.userChannelType);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n { type: \"streaming.chunk\", handler: \"onStreamingChunk\" },\n { type: \"dm.requested\", handler: \"onDMRequested\" },\n ];\n\n userEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n try {\n const connector = (this.echo as any).connector;\n if (!connector) return false;\n\n if (connector.pusher?.connection?.state === \"connected\") return true;\n if (connector.socket?.connected) return true;\n\n return false;\n } catch {\n return false;\n }\n }\n}\n","import type { PushConfig, PushSubscriptionStatus, PushEventData } from \"./types\";\n\nexport class PushManager {\n private config: PushConfig;\n private registration: ServiceWorkerRegistration | null = null;\n private status: PushSubscriptionStatus = \"unsupported\";\n private statusListeners: Set<(status: PushSubscriptionStatus) => void> = new Set();\n private messageListeners: Set<(data: PushEventData) => void> = new Set();\n\n constructor(config: PushConfig) {\n this.config = config;\n }\n\n static isSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"serviceWorker\" in navigator &&\n \"PushManager\" in window &&\n \"Notification\" in window\n );\n }\n\n getStatus(): PushSubscriptionStatus {\n return this.status;\n }\n\n onStatusChange(listener: (status: PushSubscriptionStatus) => void): () => void {\n this.statusListeners.add(listener);\n return () => {\n this.statusListeners.delete(listener);\n };\n }\n\n onMessage(listener: (data: PushEventData) => void): () => void {\n this.messageListeners.add(listener);\n return () => {\n this.messageListeners.delete(listener);\n };\n }\n\n async initialize(): Promise<void> {\n if (!PushManager.isSupported()) {\n this.setStatus(\"unsupported\");\n return;\n }\n if (Notification.permission === \"denied\") {\n this.setStatus(\"denied\");\n return;\n }\n\n try {\n this.registration = await navigator.serviceWorker.register(\n this.config.serviceWorkerUrl || \"/chat-service-worker.js\",\n {\n scope: this.config.serviceWorkerScope || \"/\",\n type: this.config.serviceWorkerType,\n },\n );\n await navigator.serviceWorker.ready;\n\n navigator.serviceWorker.addEventListener(\"message\", (event: MessageEvent) => {\n const msg = event.data as Record<string, unknown>;\n if (msg?.type === \"chat-widget:push-data\") {\n const pushData = msg.data as PushEventData;\n this.messageListeners.forEach((listener) => listener(pushData));\n }\n });\n\n const subscription = await this.registration.pushManager.getSubscription();\n this.setStatus(subscription ? \"subscribed\" : \"default\");\n } catch {\n this.setStatus(\"error\");\n }\n }\n\n async subscribe(): Promise<void> {\n if (!this.registration)\n throw new Error(\"PushManager not initialized. Call initialize() first.\");\n\n this.setStatus(\"subscribing\");\n\n try {\n let subscription = await this.registration.pushManager.getSubscription();\n\n if (!subscription) {\n const permission = await Notification.requestPermission();\n if (permission !== \"granted\") {\n this.setStatus(permission === \"denied\" ? \"denied\" : \"default\");\n return;\n }\n\n const vapidPublicKey = await this.config.getVapidPublicKey();\n const convertedKey = this.urlBase64ToUint8Array(vapidPublicKey);\n subscription = await this.registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: convertedKey.buffer as ArrayBuffer,\n });\n }\n\n await this.config.onSubscribe(subscription.toJSON());\n this.setStatus(\"subscribed\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push subscription failed\");\n }\n }\n\n async unsubscribe(): Promise<void> {\n if (!this.registration) return;\n\n try {\n const subscription = await this.registration.pushManager.getSubscription();\n if (subscription) {\n await this.config.onUnsubscribe(subscription.toJSON());\n await subscription.unsubscribe();\n }\n this.setStatus(\"default\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push unsubscription failed\");\n }\n }\n\n private urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));\n }\n\n private setStatus(status: PushSubscriptionStatus): void {\n this.status = status;\n this.statusListeners.forEach((listener) => listener(status));\n }\n}\n","import { HttpClient } from \"../client/HttpClient\";\nimport type { PushConfig } from \"./types\";\n\nexport function createPushSubscriptionHandlers(\n httpClient: HttpClient,\n userId: string,\n): Pick<PushConfig, \"onSubscribe\" | \"onUnsubscribe\"> {\n return {\n onSubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.post(\"/api/push/subscriptions\", {\n userId,\n subscription,\n userAgent: navigator.userAgent,\n });\n },\n onUnsubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.delete(\n `/api/push/subscriptions?userId=${encodeURIComponent(userId)}&endpoint=${encodeURIComponent(subscription.endpoint || \"\")}`,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -40,8 +40,6 @@ declare class HttpClient {
|
|
|
40
40
|
sendAction(actionId: string, value: string, messageId: string, conversationId: string, endpoint?: string): Promise<Record<string, unknown>>;
|
|
41
41
|
editMessage(messageId: string, newText: string, endpointTemplate?: string): Promise<void>;
|
|
42
42
|
deleteMessage(messageId: string, endpointTemplate?: string): Promise<void>;
|
|
43
|
-
addReaction(messageId: string, emoji: string, endpointTemplate?: string): Promise<void>;
|
|
44
|
-
removeReaction(messageId: string, emoji: string, endpointTemplate?: string): Promise<void>;
|
|
45
43
|
postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown>;
|
|
46
44
|
setHeader(name: string, value: string): void;
|
|
47
45
|
removeHeader(name: string): void;
|
|
@@ -287,8 +285,6 @@ interface WebChatClientConfig {
|
|
|
287
285
|
loadMessages?: string;
|
|
288
286
|
editMessage?: string;
|
|
289
287
|
deleteMessage?: string;
|
|
290
|
-
addReaction?: string;
|
|
291
|
-
removeReaction?: string;
|
|
292
288
|
};
|
|
293
289
|
features?: {
|
|
294
290
|
editMessages?: boolean;
|
|
@@ -325,6 +321,8 @@ declare class WebChatClient {
|
|
|
325
321
|
private streamingMessages;
|
|
326
322
|
private pendingTyping;
|
|
327
323
|
private subscribers;
|
|
324
|
+
private sendQueue;
|
|
325
|
+
private isProcessingQueue;
|
|
328
326
|
private unsubscribeUserChannel?;
|
|
329
327
|
constructor(config: WebChatClientConfig);
|
|
330
328
|
reconfigure(config: ReconfigureConfig): void;
|
|
@@ -334,6 +332,8 @@ declare class WebChatClient {
|
|
|
334
332
|
disconnect(): void;
|
|
335
333
|
loadMessages(options?: LoadMessagesOptions, signal?: AbortSignal): Promise<LoadMessagesResult>;
|
|
336
334
|
sendMessage(text: string, attachments?: AttachmentInput[]): Promise<void>;
|
|
335
|
+
private processQueue;
|
|
336
|
+
private executeSend;
|
|
337
337
|
sendAction(messageId: string, actionId: string, value: string): Promise<void>;
|
|
338
338
|
editMessage(messageId: string, newText: string): Promise<void>;
|
|
339
339
|
deleteMessage(messageId: string): Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -40,8 +40,6 @@ declare class HttpClient {
|
|
|
40
40
|
sendAction(actionId: string, value: string, messageId: string, conversationId: string, endpoint?: string): Promise<Record<string, unknown>>;
|
|
41
41
|
editMessage(messageId: string, newText: string, endpointTemplate?: string): Promise<void>;
|
|
42
42
|
deleteMessage(messageId: string, endpointTemplate?: string): Promise<void>;
|
|
43
|
-
addReaction(messageId: string, emoji: string, endpointTemplate?: string): Promise<void>;
|
|
44
|
-
removeReaction(messageId: string, emoji: string, endpointTemplate?: string): Promise<void>;
|
|
45
43
|
postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown>;
|
|
46
44
|
setHeader(name: string, value: string): void;
|
|
47
45
|
removeHeader(name: string): void;
|
|
@@ -287,8 +285,6 @@ interface WebChatClientConfig {
|
|
|
287
285
|
loadMessages?: string;
|
|
288
286
|
editMessage?: string;
|
|
289
287
|
deleteMessage?: string;
|
|
290
|
-
addReaction?: string;
|
|
291
|
-
removeReaction?: string;
|
|
292
288
|
};
|
|
293
289
|
features?: {
|
|
294
290
|
editMessages?: boolean;
|
|
@@ -325,6 +321,8 @@ declare class WebChatClient {
|
|
|
325
321
|
private streamingMessages;
|
|
326
322
|
private pendingTyping;
|
|
327
323
|
private subscribers;
|
|
324
|
+
private sendQueue;
|
|
325
|
+
private isProcessingQueue;
|
|
328
326
|
private unsubscribeUserChannel?;
|
|
329
327
|
constructor(config: WebChatClientConfig);
|
|
330
328
|
reconfigure(config: ReconfigureConfig): void;
|
|
@@ -334,6 +332,8 @@ declare class WebChatClient {
|
|
|
334
332
|
disconnect(): void;
|
|
335
333
|
loadMessages(options?: LoadMessagesOptions, signal?: AbortSignal): Promise<LoadMessagesResult>;
|
|
336
334
|
sendMessage(text: string, attachments?: AttachmentInput[]): Promise<void>;
|
|
335
|
+
private processQueue;
|
|
336
|
+
private executeSend;
|
|
337
337
|
sendAction(messageId: string, actionId: string, value: string): Promise<void>;
|
|
338
338
|
editMessage(messageId: string, newText: string): Promise<void>;
|
|
339
339
|
deleteMessage(messageId: string): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -77,14 +77,6 @@ var HttpClient = class {
|
|
|
77
77
|
const url = this.expandTemplate(endpointTemplate, { id: messageId });
|
|
78
78
|
await this.delete(url);
|
|
79
79
|
}
|
|
80
|
-
async addReaction(messageId, emoji, endpointTemplate = "/api/chat/messages/{id}/reactions") {
|
|
81
|
-
const url = this.expandTemplate(endpointTemplate, { id: messageId });
|
|
82
|
-
await this.post(url, { emoji });
|
|
83
|
-
}
|
|
84
|
-
async removeReaction(messageId, emoji, endpointTemplate = "/api/chat/messages/{id}/reactions/{emoji}") {
|
|
85
|
-
const url = this.expandTemplate(endpointTemplate, { id: messageId, emoji });
|
|
86
|
-
await this.delete(url);
|
|
87
|
-
}
|
|
88
80
|
async postFormData(url, formData, signal) {
|
|
89
81
|
const controller = new AbortController();
|
|
90
82
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
@@ -295,6 +287,8 @@ var WebChatClient = class {
|
|
|
295
287
|
this.streamingMessages = /* @__PURE__ */ new Map();
|
|
296
288
|
this.pendingTyping = null;
|
|
297
289
|
this.subscribers = /* @__PURE__ */ new Map();
|
|
290
|
+
this.sendQueue = [];
|
|
291
|
+
this.isProcessingQueue = false;
|
|
298
292
|
this.config = config;
|
|
299
293
|
this.httpClient = new HttpClient({
|
|
300
294
|
apiUrl: config.apiUrl,
|
|
@@ -423,6 +417,31 @@ var WebChatClient = class {
|
|
|
423
417
|
};
|
|
424
418
|
}
|
|
425
419
|
async sendMessage(text, attachments = []) {
|
|
420
|
+
return new Promise((resolve, reject) => {
|
|
421
|
+
this.sendQueue.push(async () => {
|
|
422
|
+
try {
|
|
423
|
+
await this.executeSend(text, attachments);
|
|
424
|
+
resolve();
|
|
425
|
+
} catch (e) {
|
|
426
|
+
reject(e);
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
this.processQueue();
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
async processQueue() {
|
|
433
|
+
if (this.isProcessingQueue) return;
|
|
434
|
+
this.isProcessingQueue = true;
|
|
435
|
+
try {
|
|
436
|
+
while (this.sendQueue.length > 0) {
|
|
437
|
+
const task = this.sendQueue.shift();
|
|
438
|
+
await task();
|
|
439
|
+
}
|
|
440
|
+
} finally {
|
|
441
|
+
this.isProcessingQueue = false;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
async executeSend(text, attachments = []) {
|
|
426
445
|
const messageId = generateId();
|
|
427
446
|
const userMessage = {
|
|
428
447
|
id: messageId,
|
|
@@ -518,15 +537,39 @@ var WebChatClient = class {
|
|
|
518
537
|
if (!this.config.features?.reactions) {
|
|
519
538
|
throw new Error("Reactions not enabled. Set features.reactions = true in config.");
|
|
520
539
|
}
|
|
521
|
-
|
|
522
|
-
|
|
540
|
+
this.handleReactionAdded(
|
|
541
|
+
new ReactionAddedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId })
|
|
542
|
+
);
|
|
543
|
+
const endpoint = this.config.endpoints?.sendMessage ?? "/api/webhooks/web";
|
|
544
|
+
const response = await this.httpClient.post(endpoint, {
|
|
545
|
+
id: this.conversationId,
|
|
546
|
+
reaction: { messageId, emoji, added: true }
|
|
547
|
+
});
|
|
548
|
+
if (response.events) {
|
|
549
|
+
response.events.forEach((eventData) => {
|
|
550
|
+
const event = parseChatEvent(eventData);
|
|
551
|
+
this.dispatchEvent(event);
|
|
552
|
+
});
|
|
553
|
+
}
|
|
523
554
|
}
|
|
524
555
|
async removeReaction(messageId, emoji) {
|
|
525
556
|
if (!this.config.features?.reactions) {
|
|
526
557
|
throw new Error("Reactions not enabled. Set features.reactions = true in config.");
|
|
527
558
|
}
|
|
528
|
-
|
|
529
|
-
|
|
559
|
+
this.handleReactionRemoved(
|
|
560
|
+
new ReactionRemovedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId })
|
|
561
|
+
);
|
|
562
|
+
const endpoint = this.config.endpoints?.sendMessage ?? "/api/webhooks/web";
|
|
563
|
+
const response = await this.httpClient.post(endpoint, {
|
|
564
|
+
id: this.conversationId,
|
|
565
|
+
reaction: { messageId, emoji, added: false }
|
|
566
|
+
});
|
|
567
|
+
if (response.events) {
|
|
568
|
+
response.events.forEach((eventData) => {
|
|
569
|
+
const event = parseChatEvent(eventData);
|
|
570
|
+
this.dispatchEvent(event);
|
|
571
|
+
});
|
|
572
|
+
}
|
|
530
573
|
}
|
|
531
574
|
onMessagePosted(handler) {
|
|
532
575
|
return this.addEventListener("message.posted", handler);
|
|
@@ -619,26 +662,28 @@ var WebChatClient = class {
|
|
|
619
662
|
}
|
|
620
663
|
handleReactionAdded(event) {
|
|
621
664
|
const message = this.messages.find((m) => m.id === event.messageId);
|
|
622
|
-
if (
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
665
|
+
if (message) {
|
|
666
|
+
if (!message.reactions) message.reactions = [];
|
|
667
|
+
const existing = message.reactions.find((r) => r.emoji === event.emoji);
|
|
668
|
+
if (existing) {
|
|
669
|
+
existing.count++;
|
|
670
|
+
existing.users.push(event.user.id);
|
|
671
|
+
} else {
|
|
672
|
+
message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });
|
|
673
|
+
}
|
|
630
674
|
}
|
|
631
675
|
this.notifySubscribers("reaction:added", event);
|
|
632
676
|
}
|
|
633
677
|
handleReactionRemoved(event) {
|
|
634
678
|
const message = this.messages.find((m) => m.id === event.messageId);
|
|
635
|
-
if (
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
679
|
+
if (message?.reactions) {
|
|
680
|
+
const index = message.reactions.findIndex((r) => r.emoji === event.emoji);
|
|
681
|
+
if (index !== -1) {
|
|
682
|
+
const reaction = message.reactions[index];
|
|
683
|
+
reaction.count--;
|
|
684
|
+
reaction.users = reaction.users.filter((id) => id !== event.user.id);
|
|
685
|
+
if (reaction.count === 0) message.reactions.splice(index, 1);
|
|
686
|
+
}
|
|
642
687
|
}
|
|
643
688
|
this.notifySubscribers("reaction:removed", event);
|
|
644
689
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/HttpClient.ts","../src/events/base/ChatEvent.ts","../src/events/MessagePostedEvent.ts","../src/events/MessageEditedEvent.ts","../src/events/MessageDeletedEvent.ts","../src/events/ReactionAddedEvent.ts","../src/events/ReactionRemovedEvent.ts","../src/events/TypingStartedEvent.ts","../src/events/StreamingChunkEvent.ts","../src/events/DMRequestedEvent.ts","../src/events/ChatEventFactory.ts","../src/utils/eventIdGenerator.ts","../src/client/WebChatClient.ts","../src/client/PusherBroadcastClient.ts","../src/client/LaravelEchoBroadcastClient.ts","../src/push/PushManager.ts","../src/push/PushSubscriptionManager.ts"],"sourcesContent":["export interface HttpClientConfig {\n apiUrl: string;\n headers?: Record<string, string>;\n timeout?: number;\n verifyToken?: string;\n}\n\nexport interface ChatResponse {\n id: string;\n role: \"assistant\" | \"user\";\n text: string;\n attachments?: Array<{\n type: string;\n url: string;\n name?: string;\n mime_type?: string;\n size?: number;\n }>;\n events?: Array<Record<string, unknown>>;\n}\n\nexport class HttpClient {\n private config: Required<Pick<HttpClientConfig, \"apiUrl\" | \"timeout\">> & {\n headers: Record<string, string>;\n };\n\n constructor(config: HttpClientConfig) {\n const headers: Record<string, string> = { ...config.headers };\n if (config.verifyToken) {\n headers[\"X-Verify-Token\"] = config.verifyToken;\n }\n this.config = { apiUrl: config.apiUrl, timeout: config.timeout ?? 30000, headers };\n }\n\n async get(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"GET\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async post(url: string, body: unknown, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...this.config.headers },\n signal: combined,\n body: JSON.stringify(body),\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async delete(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"DELETE\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n const text = await response.text();\n return text ? JSON.parse(text) : undefined;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async sendMessage(\n messages: Array<{\n id: string;\n role: string;\n text: string;\n attachments?: Array<{ url: string; name?: string; mime_type?: string; size?: number }>;\n }>,\n endpoint: string = \"/api/webhooks/web\",\n conversationId?: string,\n ): Promise<ChatResponse> {\n return this.post(endpoint, { id: conversationId, messages }) as Promise<ChatResponse>;\n }\n\n async sendAction(\n actionId: string,\n value: string,\n messageId: string,\n conversationId: string,\n endpoint: string = \"/api/webhooks/web\",\n ): Promise<Record<string, unknown>> {\n return this.post(endpoint, {\n id: conversationId,\n action: { actionId, value, messageId },\n }) as Promise<Record<string, unknown>>;\n }\n\n async editMessage(\n messageId: string,\n newText: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/edit\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { text: newText });\n }\n\n async deleteMessage(\n messageId: string,\n endpointTemplate: string = \"/api/chat/messages/{id}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.delete(url);\n }\n\n async addReaction(\n messageId: string,\n emoji: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/reactions\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { emoji });\n }\n\n async removeReaction(\n messageId: string,\n emoji: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/reactions/{emoji}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId, emoji });\n await this.delete(url);\n }\n\n async postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: this.config.headers,\n signal: combined,\n body: formData,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n setHeader(name: string, value: string): void {\n this.config.headers[name] = value;\n }\n\n removeHeader(name: string): void {\n delete this.config.headers[name];\n }\n\n private resolve(url: string): string {\n return /^https?:\\/\\//.test(url) ? url : `${this.config.apiUrl}${url}`;\n }\n\n private expandTemplate(template: string, params: Record<string, string>): string {\n let url = template;\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`{${key}}`, encodeURIComponent(value));\n }\n return this.resolve(url);\n }\n}\n","export abstract class ChatEvent {\n readonly type: string;\n readonly threadId: string;\n readonly timestamp: number;\n\n constructor(type: string, threadId: string, timestamp: number) {\n this.type = type;\n this.threadId = threadId;\n this.timestamp = timestamp;\n }\n\n static fromJSON: ((json: Record<string, unknown>) => ChatEvent) | undefined;\n}\n\nexport class UnknownEvent extends ChatEvent {\n readonly data: Record<string, unknown>;\n\n constructor(type: string, threadId: string, data: Record<string, unknown>, timestamp: number) {\n super(type, threadId, timestamp);\n this.data = data;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User, Card } from \"../types\";\n\nexport class MessagePostedEvent extends ChatEvent {\n readonly messageId: string;\n readonly text: string;\n readonly author: User;\n readonly card?: Card;\n readonly attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>;\n\n constructor(\n threadId: string,\n messageId: string,\n text: string,\n author: User,\n card?: Card,\n attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp?: number,\n ) {\n super(\"message.posted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.text = text;\n this.author = author;\n this.card = card;\n this.attachments = attachments;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { Card } from \"../types\";\n\nexport class MessageEditedEvent extends ChatEvent {\n readonly messageId: string;\n readonly newText: string;\n readonly card?: Card;\n\n constructor(\n threadId: string,\n messageId: string,\n newText: string,\n card?: Card,\n timestamp?: number,\n ) {\n super(\"message.edited\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.newText = newText;\n this.card = card;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class MessageDeletedEvent extends ChatEvent {\n readonly messageId: string;\n\n constructor(threadId: string, messageId: string, timestamp?: number) {\n super(\"message.deleted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionAddedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.added\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionRemovedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.removed\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class TypingStartedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"typing.started\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class StreamingChunkEvent extends ChatEvent {\n readonly messageId: string;\n readonly chunk: string;\n readonly isFinal: boolean;\n\n constructor(\n threadId: string,\n messageId: string,\n chunk: string,\n isFinal: boolean,\n timestamp?: number,\n ) {\n super(\"streaming.chunk\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.chunk = chunk;\n this.isFinal = isFinal;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class DMRequestedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"dm.requested\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent, UnknownEvent } from \"./base/ChatEvent\";\nimport type { Card, User } from \"../types\";\nimport { MessagePostedEvent } from \"./MessagePostedEvent\";\nimport { MessageEditedEvent } from \"./MessageEditedEvent\";\nimport { MessageDeletedEvent } from \"./MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"./ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"./ReactionRemovedEvent\";\nimport { TypingStartedEvent } from \"./TypingStartedEvent\";\nimport { StreamingChunkEvent } from \"./StreamingChunkEvent\";\nimport { DMRequestedEvent } from \"./DMRequestedEvent\";\n\nfunction parseCard(value: unknown): Card | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const obj = value as Record<string, unknown>;\n if (typeof obj.type !== \"string\") return undefined;\n return obj as unknown as Card;\n}\n\nexport function parseChatEvent(json: Record<string, unknown>): ChatEvent {\n const type = json.type as string;\n const threadId = json.threadId as string;\n const timestamp = json.timestamp as number;\n const data = (json.data ?? {}) as Record<string, unknown>;\n\n switch (type) {\n case \"message.posted\":\n return new MessagePostedEvent(\n threadId,\n data.messageId as string,\n data.text as string,\n data.author as User,\n parseCard(data.card),\n data.attachments as Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp,\n );\n case \"message.edited\":\n return new MessageEditedEvent(\n threadId,\n data.messageId as string,\n data.newText as string,\n parseCard(data.card),\n timestamp,\n );\n case \"message.deleted\":\n return new MessageDeletedEvent(threadId, data.messageId as string, timestamp);\n case \"reaction.added\":\n return new ReactionAddedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"reaction.removed\":\n return new ReactionRemovedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"typing.started\":\n return new TypingStartedEvent(threadId, data.userId as string, timestamp);\n case \"streaming.chunk\":\n return new StreamingChunkEvent(\n threadId,\n data.messageId as string,\n data.chunk as string,\n data.isFinal as boolean,\n timestamp,\n );\n case \"dm.requested\":\n return new DMRequestedEvent(threadId, data.userId as string, timestamp);\n default:\n return new UnknownEvent(type, threadId, data, timestamp);\n }\n}\n\n// Wire up the static method\nChatEvent.fromJSON = parseChatEvent;\n","export function generateId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\nexport function generateConversationId(): string {\n return `conv-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n","import { HttpClient } from \"./HttpClient\";\nimport type { BroadcastClient, EventHandlers, Unsubscribe } from \"./BroadcastClient\";\nimport type { Message } from \"../types\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type { MessagePostedEvent } from \"../events/MessagePostedEvent\";\nimport type { MessageEditedEvent } from \"../events/MessageEditedEvent\";\nimport type { MessageDeletedEvent } from \"../events/MessageDeletedEvent\";\nimport type { ReactionAddedEvent } from \"../events/ReactionAddedEvent\";\nimport type { ReactionRemovedEvent } from \"../events/ReactionRemovedEvent\";\nimport type { TypingStartedEvent } from \"../events/TypingStartedEvent\";\nimport type { StreamingChunkEvent } from \"../events/StreamingChunkEvent\";\nimport type { DMRequestedEvent } from \"../events/DMRequestedEvent\";\nimport { generateId, generateConversationId } from \"../utils/eventIdGenerator\";\n\nexport interface ReconfigureConfig {\n userId?: string;\n userName?: string;\n verifyToken?: string;\n conversationId?: string;\n headers?: Record<string, string>;\n}\n\nexport interface WebChatClientConfig {\n apiUrl: string;\n userId: string;\n userName: string;\n broadcastClient?: BroadcastClient;\n headers?: Record<string, string>;\n verifyToken?: string;\n conversationId?: string;\n endpoints?: {\n sendMessage?: string;\n loadMessages?: string;\n editMessage?: string;\n deleteMessage?: string;\n addReaction?: string;\n removeReaction?: string;\n };\n features?: {\n editMessages?: boolean;\n deleteMessages?: boolean;\n reactions?: boolean;\n };\n}\n\ninterface StreamingState {\n messageId: string;\n accumulatedText: string;\n isComplete: boolean;\n}\n\ninterface AttachmentInput {\n url: string;\n name?: string;\n mimeType?: string;\n size?: number;\n}\n\nexport interface LoadMessagesOptions {\n limit?: number;\n before?: number;\n after?: number;\n skipStateSeed?: boolean;\n}\n\nexport interface LoadMessagesResult {\n messages: Message[];\n hasMore: boolean;\n nextCursor?: number;\n prevCursor?: number;\n}\n\nexport class WebChatClient {\n private config: WebChatClientConfig;\n private httpClient: HttpClient;\n private broadcastClient?: BroadcastClient;\n private conversationId: string;\n private messages: Message[] = [];\n private currentUserId: string;\n private eventHandlers: EventHandlers = {};\n private streamingMessages: Map<string, StreamingState> = new Map();\n private pendingTyping: ReturnType<typeof setTimeout> | null = null;\n private subscribers: Map<string, Array<(event: unknown) => void>> = new Map();\n private unsubscribeUserChannel?: Unsubscribe;\n\n constructor(config: WebChatClientConfig) {\n this.config = config;\n this.httpClient = new HttpClient({\n apiUrl: config.apiUrl,\n headers: {\n \"X-User-Id\": config.userId,\n \"X-User-Name\": config.userName,\n ...(config.headers ?? {}),\n },\n verifyToken: config.verifyToken,\n });\n this.broadcastClient = config.broadcastClient;\n this.conversationId = config.conversationId ?? generateConversationId();\n this.currentUserId = config.userId;\n }\n\n reconfigure(config: ReconfigureConfig): void {\n if (config.userId) {\n this.currentUserId = config.userId;\n this.httpClient.setHeader(\"X-User-Id\", config.userId);\n }\n if (config.userName) {\n this.config = { ...this.config, userName: config.userName };\n this.httpClient.setHeader(\"X-User-Name\", config.userName);\n }\n if (config.verifyToken) {\n this.config = { ...this.config, verifyToken: config.verifyToken };\n this.httpClient.setHeader(\"X-Verify-Token\", config.verifyToken);\n }\n if (config.conversationId) {\n this.conversationId = config.conversationId;\n }\n if (config.headers) {\n Object.entries(config.headers).forEach(([key, value]) => {\n this.httpClient.setHeader(key, value);\n });\n }\n }\n\n setLocaleHeader(locale: string): void {\n this.httpClient.setHeader(\"X-Locale\", locale);\n this.httpClient.setHeader(\"X-Language\", locale.split(\"-\")[0] ?? locale);\n }\n\n setTimezoneHeader(timezone: string): void {\n this.httpClient.setHeader(\"X-Timezone\", timezone);\n }\n\n async connect(): Promise<void> {\n if (this.broadcastClient) {\n this.broadcastClient.connect();\n\n const threadId = this.getThreadId();\n const threadEvents: EventHandlers = {\n onMessagePosted: (event) => this.handleMessagePosted(event),\n };\n\n if (this.config.features?.editMessages) {\n threadEvents.onMessageEdited = (event) => this.handleMessageEdited(event);\n }\n if (this.config.features?.deleteMessages) {\n threadEvents.onMessageDeleted = (event) => this.handleMessageDeleted(event);\n }\n if (this.config.features?.reactions) {\n threadEvents.onReactionAdded = (event) => this.handleReactionAdded(event);\n threadEvents.onReactionRemoved = (event) => this.handleReactionRemoved(event);\n }\n\n threadEvents.onTypingStarted = (event) => this.handleTypingStarted(event);\n\n await this.broadcastClient.subscribe(threadId, threadEvents);\n\n this.unsubscribeUserChannel = await this.broadcastClient.subscribeToUser(\n threadId,\n this.currentUserId,\n {\n onStreamingChunk: (event) => this.handleStreamingChunk(event),\n onDMRequested: (event) => this.handleDMRequested(event),\n },\n );\n }\n }\n\n disconnect(): void {\n this.unsubscribeUserChannel?.();\n this.unsubscribeUserChannel = undefined;\n this.broadcastClient?.disconnect();\n this.streamingMessages.clear();\n }\n\n async loadMessages(\n options?: LoadMessagesOptions,\n signal?: AbortSignal,\n ): Promise<LoadMessagesResult> {\n const endpoint = this.config.endpoints?.loadMessages ?? \"/api/chat/messages\";\n const threadId = this.getThreadId();\n const params = new URLSearchParams({\n threadId,\n limit: String(options?.limit ?? 50),\n });\n if (options?.before) params.set(\"before\", String(options.before));\n if (options?.after) params.set(\"after\", String(options.after));\n\n const response = (await this.httpClient.get(\n `${endpoint}?${params.toString()}`,\n signal,\n )) as Record<string, unknown>;\n const rawMessages = (response.messages as Record<string, unknown>[]) ?? [];\n const messages: Message[] = rawMessages.map((msg) => ({\n id: msg.id as string,\n threadId,\n content: {\n text: msg.text as string,\n cards: msg.card ? ([msg.card as Record<string, unknown>] as never[]) : undefined,\n },\n author: {\n id: (msg.author as Record<string, unknown>).id as string,\n name: (msg.author as Record<string, unknown>).name as string,\n isBot: ((msg.author as Record<string, unknown>).isBot as boolean) ?? false,\n isMe: (msg.author as Record<string, unknown>).id === this.currentUserId,\n },\n timestamp: msg.timestamp as number,\n attachments: (msg.attachments as Record<string, unknown>[])?.map((a) => ({\n id: `att-${msg.id as string}-${a.url as string}`,\n url: a.url as string,\n name: a.name as string,\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n reactions: (msg.reactions as { emoji: string; count: number; users: string[] }[]) ?? [],\n }));\n\n if (!options?.before && !options?.after && !options?.skipStateSeed) {\n this.messages = messages;\n this.notifySubscribers(\"messages:loaded\", messages);\n }\n\n return {\n messages,\n hasMore: (response.hasMore as boolean) ?? false,\n nextCursor: response.nextCursor as number | undefined,\n prevCursor: response.prevCursor as number | undefined,\n };\n }\n\n async sendMessage(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n const messageId = generateId();\n\n const userMessage: Message = {\n id: messageId,\n threadId: this.getThreadId(),\n content: { text },\n author: { id: this.currentUserId, name: this.config.userName, isMe: true },\n timestamp: Date.now(),\n attachments:\n attachments.length > 0\n ? attachments.map((a, i) => ({\n id: `att-${messageId}-${i}`,\n name: a.name ?? \"\",\n url: a.url,\n size: a.size,\n mimeType: a.mimeType,\n }))\n : undefined,\n };\n\n this.messages.push(userMessage);\n this.notifySubscribers(\"message:added\", userMessage);\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendMessage(\n [\n {\n id: messageId,\n role: \"user\",\n text,\n attachments: attachments.map((a) => ({\n url: a.url,\n name: a.name,\n mime_type: a.mimeType,\n size: a.size,\n })),\n },\n ],\n endpoint,\n this.conversationId,\n );\n\n if (response.events) {\n response.events.forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n\n if (response.text && !response.events?.some((e) => e.type === \"message.posted\")) {\n const assistantMessage: Message = {\n id: response.id ?? generateId(),\n threadId: this.getThreadId(),\n content: { text: response.text },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: Date.now(),\n attachments: (response.attachments as Record<string, unknown>[])?.map((a, i) => ({\n id: `att-${response.id ?? \"msg\"}-${i}`,\n name: (a.name as string) ?? \"\",\n url: (a.url as string) ?? \"\",\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n };\n this.messages.push(assistantMessage);\n this.notifySubscribers(\"message:added\", assistantMessage);\n }\n }\n\n async sendAction(messageId: string, actionId: string, value: string): Promise<void> {\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendAction(\n actionId,\n value,\n messageId,\n this.conversationId,\n endpoint,\n );\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async editMessage(messageId: string, newText: string): Promise<void> {\n if (!this.config.features?.editMessages) {\n throw new Error(\"Edit messages not enabled. Set features.editMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.editMessage ?? \"/api/chat/messages/{id}/edit\";\n await this.httpClient.editMessage(messageId, newText, endpoint);\n }\n\n async deleteMessage(messageId: string): Promise<void> {\n if (!this.config.features?.deleteMessages) {\n throw new Error(\"Delete messages not enabled. Set features.deleteMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.deleteMessage ?? \"/api/chat/messages/{id}\";\n await this.httpClient.deleteMessage(messageId, endpoint);\n }\n\n async addReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n const endpoint = this.config.endpoints?.addReaction ?? \"/api/chat/messages/{id}/reactions\";\n await this.httpClient.addReaction(messageId, emoji, endpoint);\n }\n\n async removeReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n const endpoint =\n this.config.endpoints?.removeReaction ?? \"/api/chat/messages/{id}/reactions/{emoji}\";\n await this.httpClient.removeReaction(messageId, emoji, endpoint);\n }\n\n onMessagePosted(handler: (event: MessagePostedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message.posted\", handler);\n }\n\n onMessageEdited(handler: (event: MessageEditedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:edited\", handler);\n }\n\n onMessageDeleted(handler: (event: MessageDeletedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:deleted\", handler);\n }\n\n onReactionAdded(handler: (event: ReactionAddedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:added\", handler);\n }\n\n onReactionRemoved(handler: (event: ReactionRemovedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:removed\", handler);\n }\n\n onStreamingChunk(handler: (event: StreamingChunkEvent) => void): Unsubscribe {\n return this.addEventListener(\"streaming:chunk\", handler);\n }\n\n onTypingStarted(handler: (event: TypingStartedEvent) => void): Unsubscribe {\n return this.addEventListener(\"typing:started\", handler);\n }\n\n getConversationId(): string {\n return this.conversationId;\n }\n getMessages(): Message[] {\n return [...this.messages];\n }\n getThreadId(): string {\n return `web:${this.currentUserId}:${this.conversationId}`;\n }\n getCurrentUserId(): string {\n return this.currentUserId;\n }\n getFeatures(): NonNullable<WebChatClientConfig[\"features\"]> {\n return this.config.features ?? {};\n }\n getEndpoints(): NonNullable<WebChatClientConfig[\"endpoints\"]> {\n return this.config.endpoints ?? {};\n }\n getHttpClient(): HttpClient {\n return this.httpClient;\n }\n\n addEventListener<T = unknown>(eventType: string, handler: (event: T) => void): Unsubscribe {\n if (!this.subscribers.has(eventType)) this.subscribers.set(eventType, []);\n this.subscribers.get(eventType)!.push(handler as (event: unknown) => void);\n return () => {\n const handlers = this.subscribers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler as (event: unknown) => void);\n if (index !== -1) handlers.splice(index, 1);\n }\n };\n }\n\n private handleMessagePosted(event: MessagePostedEvent): void {\n if (this.messages.some((m) => m.id === event.messageId)) return;\n if (this.streamingMessages.has(event.messageId)) return;\n\n const message: Message = {\n id: event.messageId,\n threadId: event.threadId,\n content: { text: event.text, cards: event.card ? [event.card] : undefined },\n author: event.author,\n timestamp: event.timestamp,\n attachments: event.attachments?.map((a) => ({\n id: `att-${event.messageId}-${Math.random().toString(36).slice(2, 8)}`,\n name: a.name ?? \"\",\n url: a.url ?? \"\",\n type: a.type,\n mimeType: a.mimeType,\n size: a.size ?? undefined,\n })),\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n this.notifySubscribers(\"message.posted\", event);\n }\n\n private handleMessageEdited(event: MessageEditedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.content) {\n message.content.text = event.newText;\n this.notifySubscribers(\"message:edited\", event);\n }\n }\n\n private handleMessageDeleted(event: MessageDeletedEvent): void {\n const index = this.messages.findIndex((m) => m.id === event.messageId);\n if (index !== -1) {\n this.messages.splice(index, 1);\n this.notifySubscribers(\"message:deleted\", event);\n }\n }\n\n private handleReactionAdded(event: ReactionAddedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (!message) return;\n if (!message.reactions) message.reactions = [];\n\n const existing = message.reactions.find((r) => r.emoji === event.emoji);\n if (existing) {\n existing.count++;\n existing.users.push(event.user.id);\n } else {\n message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });\n }\n this.notifySubscribers(\"reaction:added\", event);\n }\n\n private handleReactionRemoved(event: ReactionRemovedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (!message?.reactions) return;\n\n const index = message.reactions.findIndex((r) => r.emoji === event.emoji);\n if (index !== -1) {\n const reaction = message.reactions[index]!;\n reaction.count--;\n reaction.users = reaction.users.filter((id) => id !== event.user.id);\n if (reaction.count === 0) message.reactions.splice(index, 1);\n }\n this.notifySubscribers(\"reaction:removed\", event);\n }\n\n private handleStreamingChunk(event: StreamingChunkEvent): void {\n const { messageId, chunk, isFinal } = event;\n\n if (!this.streamingMessages.has(messageId)) {\n this.streamingMessages.set(messageId, { messageId, accumulatedText: \"\", isComplete: false });\n this.notifySubscribers(\"streaming:started\", event);\n }\n\n const state = this.streamingMessages.get(messageId)!;\n state.accumulatedText += chunk;\n\n if (isFinal) {\n state.isComplete = true;\n if (!this.messages.some((m) => m.id === messageId)) {\n const message: Message = {\n id: messageId,\n threadId: event.threadId,\n content: { text: state.accumulatedText },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: event.timestamp,\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n }\n this.streamingMessages.delete(messageId);\n this.notifySubscribers(\"streaming:complete\", { messageId, text: state.accumulatedText });\n } else {\n this.notifySubscribers(\"streaming:chunk\", event);\n }\n }\n\n private handleTypingStarted(event: TypingStartedEvent): void {\n if (this.pendingTyping) clearTimeout(this.pendingTyping);\n this.notifySubscribers(\"typing:started\", event);\n this.pendingTyping = setTimeout(() => {\n this.notifySubscribers(\"typing:stopped\", { userId: event.userId });\n }, 3000);\n }\n\n private handleDMRequested(event: DMRequestedEvent): void {\n this.notifySubscribers(\"dm.requested\", event);\n }\n\n private notifySubscribers<T>(eventType: string, data: T): void {\n this.subscribers.get(eventType)?.forEach((handler) => handler(data));\n }\n\n private dispatchEvent(event: ChatEvent): void {\n switch (event.type) {\n case \"message.posted\":\n this.handleMessagePosted(event as MessagePostedEvent);\n break;\n case \"message.edited\":\n this.handleMessageEdited(event as MessageEditedEvent);\n break;\n case \"message.deleted\":\n this.handleMessageDeleted(event as MessageDeletedEvent);\n break;\n case \"reaction.added\":\n this.handleReactionAdded(event as ReactionAddedEvent);\n break;\n case \"reaction.removed\":\n this.handleReactionRemoved(event as ReactionRemovedEvent);\n break;\n case \"typing.started\":\n this.handleTypingStarted(event as TypingStartedEvent);\n break;\n case \"streaming.chunk\":\n this.handleStreamingChunk(event as StreamingChunkEvent);\n break;\n case \"dm.requested\":\n this.handleDMRequested(event as DMRequestedEvent);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel as PusherChannel } from \"pusher-js\";\n\nexport interface PusherConfig {\n key: string;\n cluster?: string;\n host?: string;\n port?: number;\n forceTLS?: boolean;\n authEndpoint?: string;\n}\n\nexport class PusherBroadcastClient implements BroadcastClient {\n private pusher: Pusher;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, PusherChannel> = new Map();\n\n constructor(pusher: Pusher, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(config: PusherConfig, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(\n pusherOrConfig: Pusher | PusherConfig,\n channelPrefix: string = \"chat\",\n channelTypes?: ChannelTypeConfig,\n ) {\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n\n if (\"key\" in pusherOrConfig) {\n const PusherCtor = (globalThis as any).Pusher ?? (globalThis as any).pusherJs;\n if (!PusherCtor) {\n throw new Error(\"pusher-js not found. Install it or pass a Pusher instance.\");\n }\n this.pusher = new PusherCtor((pusherOrConfig as PusherConfig).key, pusherOrConfig) as Pusher;\n } else {\n this.pusher = pusherOrConfig as Pusher;\n }\n }\n\n private buildChannelName(base: string, type: \"public\" | \"private\" | \"presence\"): string {\n switch (type) {\n case \"private\":\n return `private-${base}`;\n case \"presence\":\n return `presence-${base}`;\n default:\n return base;\n }\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n connect(): void {\n if (this.pusher.connection?.state !== \"connected\") {\n this.pusher.connect();\n }\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => channel.unbind_all?.() ?? channel.unsubscribe?.());\n this.subscriptions.clear();\n this.pusher.disconnect?.();\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const baseName = await this.buildResolvedChannelName(threadId);\n const channelName = this.buildChannelName(baseName, this.threadChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents = [\n \"message.posted\",\n \"message.edited\",\n \"message.deleted\",\n \"reaction.added\",\n \"reaction.removed\",\n \"typing.started\",\n ] as const;\n\n threadEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const baseName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channelName = this.buildChannelName(baseName, this.userChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents = [\"typing.started\", \"streaming.chunk\", \"dm.requested\"] as const;\n\n userEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n return this.pusher.connection?.state === \"connected\";\n }\n\n private dispatchToHandler(event: ChatEvent, handlers: EventHandlers): void {\n switch (event.type) {\n case \"message.posted\":\n handlers.onMessagePosted?.(event as any);\n break;\n case \"message.edited\":\n handlers.onMessageEdited?.(event as any);\n break;\n case \"message.deleted\":\n handlers.onMessageDeleted?.(event as any);\n break;\n case \"reaction.added\":\n handlers.onReactionAdded?.(event as any);\n break;\n case \"reaction.removed\":\n handlers.onReactionRemoved?.(event as any);\n break;\n case \"typing.started\":\n handlers.onTypingStarted?.(event as any);\n break;\n case \"streaming.chunk\":\n handlers.onStreamingChunk?.(event as any);\n break;\n case \"dm.requested\":\n handlers.onDMRequested?.(event as any);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Echo from \"laravel-echo\";\n\ninterface EchoChannel {\n listen(event: string, callback: (data: unknown) => void): this;\n unsubscribe(): void;\n stopListening(event?: string, callback?: (data: unknown) => void): this;\n}\n\nexport class LaravelEchoBroadcastClient implements BroadcastClient {\n private echo: Echo<any>;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, EchoChannel> = new Map();\n\n constructor(echo: Echo<any>, channelPrefix: string = \"chat\", channelTypes?: ChannelTypeConfig) {\n this.echo = echo;\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n }\n\n private subscribeToEcho(name: string, type: \"public\" | \"private\" | \"presence\"): EchoChannel {\n switch (type) {\n case \"private\":\n return this.echo.private(name) as unknown as EchoChannel;\n case \"presence\":\n return this.echo.join(name) as unknown as EchoChannel;\n default:\n return this.echo.channel(name) as unknown as EchoChannel;\n }\n }\n\n connect(): void | Promise<void> {\n return Promise.resolve();\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => {\n channel.unsubscribe?.();\n channel.stopListening?.();\n });\n this.subscriptions.clear();\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const channelName = await this.buildResolvedChannelName(threadId);\n const channel = this.subscribeToEcho(channelName, this.threadChannelType);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"message.posted\", handler: \"onMessagePosted\" },\n { type: \"message.edited\", handler: \"onMessageEdited\" },\n { type: \"message.deleted\", handler: \"onMessageDeleted\" },\n { type: \"reaction.added\", handler: \"onReactionAdded\" },\n { type: \"reaction.removed\", handler: \"onReactionRemoved\" },\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n ];\n\n threadEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const channelName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channel = this.subscribeToEcho(channelName, this.userChannelType);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n { type: \"streaming.chunk\", handler: \"onStreamingChunk\" },\n { type: \"dm.requested\", handler: \"onDMRequested\" },\n ];\n\n userEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n try {\n const connector = (this.echo as any).connector;\n if (!connector) return false;\n\n if (connector.pusher?.connection?.state === \"connected\") return true;\n if (connector.socket?.connected) return true;\n\n return false;\n } catch {\n return false;\n }\n }\n}\n","import type { PushConfig, PushSubscriptionStatus, PushEventData } from \"./types\";\n\nexport class PushManager {\n private config: PushConfig;\n private registration: ServiceWorkerRegistration | null = null;\n private status: PushSubscriptionStatus = \"unsupported\";\n private statusListeners: Set<(status: PushSubscriptionStatus) => void> = new Set();\n private messageListeners: Set<(data: PushEventData) => void> = new Set();\n\n constructor(config: PushConfig) {\n this.config = config;\n }\n\n static isSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"serviceWorker\" in navigator &&\n \"PushManager\" in window &&\n \"Notification\" in window\n );\n }\n\n getStatus(): PushSubscriptionStatus {\n return this.status;\n }\n\n onStatusChange(listener: (status: PushSubscriptionStatus) => void): () => void {\n this.statusListeners.add(listener);\n return () => {\n this.statusListeners.delete(listener);\n };\n }\n\n onMessage(listener: (data: PushEventData) => void): () => void {\n this.messageListeners.add(listener);\n return () => {\n this.messageListeners.delete(listener);\n };\n }\n\n async initialize(): Promise<void> {\n if (!PushManager.isSupported()) {\n this.setStatus(\"unsupported\");\n return;\n }\n if (Notification.permission === \"denied\") {\n this.setStatus(\"denied\");\n return;\n }\n\n try {\n this.registration = await navigator.serviceWorker.register(\n this.config.serviceWorkerUrl || \"/chat-service-worker.js\",\n {\n scope: this.config.serviceWorkerScope || \"/\",\n type: this.config.serviceWorkerType,\n },\n );\n await navigator.serviceWorker.ready;\n\n navigator.serviceWorker.addEventListener(\"message\", (event: MessageEvent) => {\n const msg = event.data as Record<string, unknown>;\n if (msg?.type === \"chat-widget:push-data\") {\n const pushData = msg.data as PushEventData;\n this.messageListeners.forEach((listener) => listener(pushData));\n }\n });\n\n const subscription = await this.registration.pushManager.getSubscription();\n this.setStatus(subscription ? \"subscribed\" : \"default\");\n } catch {\n this.setStatus(\"error\");\n }\n }\n\n async subscribe(): Promise<void> {\n if (!this.registration)\n throw new Error(\"PushManager not initialized. Call initialize() first.\");\n\n this.setStatus(\"subscribing\");\n\n try {\n let subscription = await this.registration.pushManager.getSubscription();\n\n if (!subscription) {\n const permission = await Notification.requestPermission();\n if (permission !== \"granted\") {\n this.setStatus(permission === \"denied\" ? \"denied\" : \"default\");\n return;\n }\n\n const vapidPublicKey = await this.config.getVapidPublicKey();\n const convertedKey = this.urlBase64ToUint8Array(vapidPublicKey);\n subscription = await this.registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: convertedKey.buffer as ArrayBuffer,\n });\n }\n\n await this.config.onSubscribe(subscription.toJSON());\n this.setStatus(\"subscribed\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push subscription failed\");\n }\n }\n\n async unsubscribe(): Promise<void> {\n if (!this.registration) return;\n\n try {\n const subscription = await this.registration.pushManager.getSubscription();\n if (subscription) {\n await this.config.onUnsubscribe(subscription.toJSON());\n await subscription.unsubscribe();\n }\n this.setStatus(\"default\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push unsubscription failed\");\n }\n }\n\n private urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));\n }\n\n private setStatus(status: PushSubscriptionStatus): void {\n this.status = status;\n this.statusListeners.forEach((listener) => listener(status));\n }\n}\n","import { HttpClient } from \"../client/HttpClient\";\nimport type { PushConfig } from \"./types\";\n\nexport function createPushSubscriptionHandlers(\n httpClient: HttpClient,\n userId: string,\n): Pick<PushConfig, \"onSubscribe\" | \"onUnsubscribe\"> {\n return {\n onSubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.post(\"/api/push/subscriptions\", {\n userId,\n subscription,\n userAgent: navigator.userAgent,\n });\n },\n onUnsubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.delete(\n `/api/push/subscriptions?userId=${encodeURIComponent(userId)}&endpoint=${encodeURIComponent(subscription.endpoint || \"\")}`,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/client/HttpClient.ts","../src/events/base/ChatEvent.ts","../src/events/MessagePostedEvent.ts","../src/events/MessageEditedEvent.ts","../src/events/MessageDeletedEvent.ts","../src/events/ReactionAddedEvent.ts","../src/events/ReactionRemovedEvent.ts","../src/events/TypingStartedEvent.ts","../src/events/StreamingChunkEvent.ts","../src/events/DMRequestedEvent.ts","../src/events/ChatEventFactory.ts","../src/utils/eventIdGenerator.ts","../src/client/WebChatClient.ts","../src/client/PusherBroadcastClient.ts","../src/client/LaravelEchoBroadcastClient.ts","../src/push/PushManager.ts","../src/push/PushSubscriptionManager.ts"],"sourcesContent":["export interface HttpClientConfig {\n apiUrl: string;\n headers?: Record<string, string>;\n timeout?: number;\n verifyToken?: string;\n}\n\nexport interface ChatResponse {\n id: string;\n role: \"assistant\" | \"user\";\n text: string;\n attachments?: Array<{\n type: string;\n url: string;\n name?: string;\n mime_type?: string;\n size?: number;\n }>;\n events?: Array<Record<string, unknown>>;\n}\n\nexport class HttpClient {\n private config: Required<Pick<HttpClientConfig, \"apiUrl\" | \"timeout\">> & {\n headers: Record<string, string>;\n };\n\n constructor(config: HttpClientConfig) {\n const headers: Record<string, string> = { ...config.headers };\n if (config.verifyToken) {\n headers[\"X-Verify-Token\"] = config.verifyToken;\n }\n this.config = { apiUrl: config.apiUrl, timeout: config.timeout ?? 30000, headers };\n }\n\n async get(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"GET\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async post(url: string, body: unknown, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...this.config.headers },\n signal: combined,\n body: JSON.stringify(body),\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async delete(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"DELETE\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n const text = await response.text();\n return text ? JSON.parse(text) : undefined;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async sendMessage(\n messages: Array<{\n id: string;\n role: string;\n text: string;\n attachments?: Array<{ url: string; name?: string; mime_type?: string; size?: number }>;\n }>,\n endpoint: string = \"/api/webhooks/web\",\n conversationId?: string,\n ): Promise<ChatResponse> {\n return this.post(endpoint, { id: conversationId, messages }) as Promise<ChatResponse>;\n }\n\n async sendAction(\n actionId: string,\n value: string,\n messageId: string,\n conversationId: string,\n endpoint: string = \"/api/webhooks/web\",\n ): Promise<Record<string, unknown>> {\n return this.post(endpoint, {\n id: conversationId,\n action: { actionId, value, messageId },\n }) as Promise<Record<string, unknown>>;\n }\n\n async editMessage(\n messageId: string,\n newText: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/edit\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { text: newText });\n }\n\n async deleteMessage(\n messageId: string,\n endpointTemplate: string = \"/api/chat/messages/{id}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.delete(url);\n }\n\n async postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: this.config.headers,\n signal: combined,\n body: formData,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n setHeader(name: string, value: string): void {\n this.config.headers[name] = value;\n }\n\n removeHeader(name: string): void {\n delete this.config.headers[name];\n }\n\n private resolve(url: string): string {\n return /^https?:\\/\\//.test(url) ? url : `${this.config.apiUrl}${url}`;\n }\n\n private expandTemplate(template: string, params: Record<string, string>): string {\n let url = template;\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`{${key}}`, encodeURIComponent(value));\n }\n return this.resolve(url);\n }\n}\n","export abstract class ChatEvent {\n readonly type: string;\n readonly threadId: string;\n readonly timestamp: number;\n\n constructor(type: string, threadId: string, timestamp: number) {\n this.type = type;\n this.threadId = threadId;\n this.timestamp = timestamp;\n }\n\n static fromJSON: ((json: Record<string, unknown>) => ChatEvent) | undefined;\n}\n\nexport class UnknownEvent extends ChatEvent {\n readonly data: Record<string, unknown>;\n\n constructor(type: string, threadId: string, data: Record<string, unknown>, timestamp: number) {\n super(type, threadId, timestamp);\n this.data = data;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User, Card } from \"../types\";\n\nexport class MessagePostedEvent extends ChatEvent {\n readonly messageId: string;\n readonly text: string;\n readonly author: User;\n readonly card?: Card;\n readonly attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>;\n\n constructor(\n threadId: string,\n messageId: string,\n text: string,\n author: User,\n card?: Card,\n attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp?: number,\n ) {\n super(\"message.posted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.text = text;\n this.author = author;\n this.card = card;\n this.attachments = attachments;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { Card } from \"../types\";\n\nexport class MessageEditedEvent extends ChatEvent {\n readonly messageId: string;\n readonly newText: string;\n readonly card?: Card;\n\n constructor(\n threadId: string,\n messageId: string,\n newText: string,\n card?: Card,\n timestamp?: number,\n ) {\n super(\"message.edited\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.newText = newText;\n this.card = card;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class MessageDeletedEvent extends ChatEvent {\n readonly messageId: string;\n\n constructor(threadId: string, messageId: string, timestamp?: number) {\n super(\"message.deleted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionAddedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.added\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionRemovedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.removed\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class TypingStartedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"typing.started\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class StreamingChunkEvent extends ChatEvent {\n readonly messageId: string;\n readonly chunk: string;\n readonly isFinal: boolean;\n\n constructor(\n threadId: string,\n messageId: string,\n chunk: string,\n isFinal: boolean,\n timestamp?: number,\n ) {\n super(\"streaming.chunk\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.chunk = chunk;\n this.isFinal = isFinal;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class DMRequestedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"dm.requested\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent, UnknownEvent } from \"./base/ChatEvent\";\nimport type { Card, User } from \"../types\";\nimport { MessagePostedEvent } from \"./MessagePostedEvent\";\nimport { MessageEditedEvent } from \"./MessageEditedEvent\";\nimport { MessageDeletedEvent } from \"./MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"./ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"./ReactionRemovedEvent\";\nimport { TypingStartedEvent } from \"./TypingStartedEvent\";\nimport { StreamingChunkEvent } from \"./StreamingChunkEvent\";\nimport { DMRequestedEvent } from \"./DMRequestedEvent\";\n\nfunction parseCard(value: unknown): Card | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const obj = value as Record<string, unknown>;\n if (typeof obj.type !== \"string\") return undefined;\n return obj as unknown as Card;\n}\n\nexport function parseChatEvent(json: Record<string, unknown>): ChatEvent {\n const type = json.type as string;\n const threadId = json.threadId as string;\n const timestamp = json.timestamp as number;\n const data = (json.data ?? {}) as Record<string, unknown>;\n\n switch (type) {\n case \"message.posted\":\n return new MessagePostedEvent(\n threadId,\n data.messageId as string,\n data.text as string,\n data.author as User,\n parseCard(data.card),\n data.attachments as Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp,\n );\n case \"message.edited\":\n return new MessageEditedEvent(\n threadId,\n data.messageId as string,\n data.newText as string,\n parseCard(data.card),\n timestamp,\n );\n case \"message.deleted\":\n return new MessageDeletedEvent(threadId, data.messageId as string, timestamp);\n case \"reaction.added\":\n return new ReactionAddedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"reaction.removed\":\n return new ReactionRemovedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"typing.started\":\n return new TypingStartedEvent(threadId, data.userId as string, timestamp);\n case \"streaming.chunk\":\n return new StreamingChunkEvent(\n threadId,\n data.messageId as string,\n data.chunk as string,\n data.isFinal as boolean,\n timestamp,\n );\n case \"dm.requested\":\n return new DMRequestedEvent(threadId, data.userId as string, timestamp);\n default:\n return new UnknownEvent(type, threadId, data, timestamp);\n }\n}\n\n// Wire up the static method\nChatEvent.fromJSON = parseChatEvent;\n","export function generateId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\nexport function generateConversationId(): string {\n return `conv-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n","import { HttpClient } from \"./HttpClient\";\nimport type { BroadcastClient, EventHandlers, Unsubscribe } from \"./BroadcastClient\";\nimport type { Message } from \"../types\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type { MessagePostedEvent } from \"../events/MessagePostedEvent\";\nimport type { MessageEditedEvent } from \"../events/MessageEditedEvent\";\nimport type { MessageDeletedEvent } from \"../events/MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"../events/ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"../events/ReactionRemovedEvent\";\nimport type { TypingStartedEvent } from \"../events/TypingStartedEvent\";\nimport type { StreamingChunkEvent } from \"../events/StreamingChunkEvent\";\nimport type { DMRequestedEvent } from \"../events/DMRequestedEvent\";\nimport { generateId, generateConversationId } from \"../utils/eventIdGenerator\";\n\nexport interface ReconfigureConfig {\n userId?: string;\n userName?: string;\n verifyToken?: string;\n conversationId?: string;\n headers?: Record<string, string>;\n}\n\nexport interface WebChatClientConfig {\n apiUrl: string;\n userId: string;\n userName: string;\n broadcastClient?: BroadcastClient;\n headers?: Record<string, string>;\n verifyToken?: string;\n conversationId?: string;\n endpoints?: {\n sendMessage?: string;\n loadMessages?: string;\n editMessage?: string;\n deleteMessage?: string;\n };\n features?: {\n editMessages?: boolean;\n deleteMessages?: boolean;\n reactions?: boolean;\n };\n}\n\ninterface StreamingState {\n messageId: string;\n accumulatedText: string;\n isComplete: boolean;\n}\n\ninterface AttachmentInput {\n url: string;\n name?: string;\n mimeType?: string;\n size?: number;\n}\n\nexport interface LoadMessagesOptions {\n limit?: number;\n before?: number;\n after?: number;\n skipStateSeed?: boolean;\n}\n\nexport interface LoadMessagesResult {\n messages: Message[];\n hasMore: boolean;\n nextCursor?: number;\n prevCursor?: number;\n}\n\nexport class WebChatClient {\n private config: WebChatClientConfig;\n private httpClient: HttpClient;\n private broadcastClient?: BroadcastClient;\n private conversationId: string;\n private messages: Message[] = [];\n private currentUserId: string;\n private eventHandlers: EventHandlers = {};\n private streamingMessages: Map<string, StreamingState> = new Map();\n private pendingTyping: ReturnType<typeof setTimeout> | null = null;\n private subscribers: Map<string, Array<(event: unknown) => void>> = new Map();\n private sendQueue: Array<() => Promise<void>> = [];\n private isProcessingQueue = false;\n private unsubscribeUserChannel?: Unsubscribe;\n\n constructor(config: WebChatClientConfig) {\n this.config = config;\n this.httpClient = new HttpClient({\n apiUrl: config.apiUrl,\n headers: {\n \"X-User-Id\": config.userId,\n \"X-User-Name\": config.userName,\n ...(config.headers ?? {}),\n },\n verifyToken: config.verifyToken,\n });\n this.broadcastClient = config.broadcastClient;\n this.conversationId = config.conversationId ?? generateConversationId();\n this.currentUserId = config.userId;\n }\n\n reconfigure(config: ReconfigureConfig): void {\n if (config.userId) {\n this.currentUserId = config.userId;\n this.httpClient.setHeader(\"X-User-Id\", config.userId);\n }\n if (config.userName) {\n this.config = { ...this.config, userName: config.userName };\n this.httpClient.setHeader(\"X-User-Name\", config.userName);\n }\n if (config.verifyToken) {\n this.config = { ...this.config, verifyToken: config.verifyToken };\n this.httpClient.setHeader(\"X-Verify-Token\", config.verifyToken);\n }\n if (config.conversationId) {\n this.conversationId = config.conversationId;\n }\n if (config.headers) {\n Object.entries(config.headers).forEach(([key, value]) => {\n this.httpClient.setHeader(key, value);\n });\n }\n }\n\n setLocaleHeader(locale: string): void {\n this.httpClient.setHeader(\"X-Locale\", locale);\n this.httpClient.setHeader(\"X-Language\", locale.split(\"-\")[0] ?? locale);\n }\n\n setTimezoneHeader(timezone: string): void {\n this.httpClient.setHeader(\"X-Timezone\", timezone);\n }\n\n async connect(): Promise<void> {\n if (this.broadcastClient) {\n this.broadcastClient.connect();\n\n const threadId = this.getThreadId();\n const threadEvents: EventHandlers = {\n onMessagePosted: (event) => this.handleMessagePosted(event),\n };\n\n if (this.config.features?.editMessages) {\n threadEvents.onMessageEdited = (event) => this.handleMessageEdited(event);\n }\n if (this.config.features?.deleteMessages) {\n threadEvents.onMessageDeleted = (event) => this.handleMessageDeleted(event);\n }\n if (this.config.features?.reactions) {\n threadEvents.onReactionAdded = (event) => this.handleReactionAdded(event);\n threadEvents.onReactionRemoved = (event) => this.handleReactionRemoved(event);\n }\n\n threadEvents.onTypingStarted = (event) => this.handleTypingStarted(event);\n\n await this.broadcastClient.subscribe(threadId, threadEvents);\n\n this.unsubscribeUserChannel = await this.broadcastClient.subscribeToUser(\n threadId,\n this.currentUserId,\n {\n onStreamingChunk: (event) => this.handleStreamingChunk(event),\n onDMRequested: (event) => this.handleDMRequested(event),\n },\n );\n }\n }\n\n disconnect(): void {\n this.unsubscribeUserChannel?.();\n this.unsubscribeUserChannel = undefined;\n this.broadcastClient?.disconnect();\n this.streamingMessages.clear();\n }\n\n async loadMessages(\n options?: LoadMessagesOptions,\n signal?: AbortSignal,\n ): Promise<LoadMessagesResult> {\n const endpoint = this.config.endpoints?.loadMessages ?? \"/api/chat/messages\";\n const threadId = this.getThreadId();\n const params = new URLSearchParams({\n threadId,\n limit: String(options?.limit ?? 50),\n });\n if (options?.before) params.set(\"before\", String(options.before));\n if (options?.after) params.set(\"after\", String(options.after));\n\n const response = (await this.httpClient.get(\n `${endpoint}?${params.toString()}`,\n signal,\n )) as Record<string, unknown>;\n const rawMessages = (response.messages as Record<string, unknown>[]) ?? [];\n const messages: Message[] = rawMessages.map((msg) => ({\n id: msg.id as string,\n threadId,\n content: {\n text: msg.text as string,\n cards: msg.card ? ([msg.card as Record<string, unknown>] as never[]) : undefined,\n },\n author: {\n id: (msg.author as Record<string, unknown>).id as string,\n name: (msg.author as Record<string, unknown>).name as string,\n isBot: ((msg.author as Record<string, unknown>).isBot as boolean) ?? false,\n isMe: (msg.author as Record<string, unknown>).id === this.currentUserId,\n },\n timestamp: msg.timestamp as number,\n attachments: (msg.attachments as Record<string, unknown>[])?.map((a) => ({\n id: `att-${msg.id as string}-${a.url as string}`,\n url: a.url as string,\n name: a.name as string,\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n reactions: (msg.reactions as { emoji: string; count: number; users: string[] }[]) ?? [],\n }));\n\n if (!options?.before && !options?.after && !options?.skipStateSeed) {\n this.messages = messages;\n this.notifySubscribers(\"messages:loaded\", messages);\n }\n\n return {\n messages,\n hasMore: (response.hasMore as boolean) ?? false,\n nextCursor: response.nextCursor as number | undefined,\n prevCursor: response.prevCursor as number | undefined,\n };\n }\n\n async sendMessage(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push(async () => {\n try {\n await this.executeSend(text, attachments);\n resolve();\n } catch (e) {\n reject(e);\n }\n });\n this.processQueue();\n });\n }\n\n private async processQueue(): Promise<void> {\n if (this.isProcessingQueue) return;\n this.isProcessingQueue = true;\n try {\n while (this.sendQueue.length > 0) {\n const task = this.sendQueue.shift()!;\n await task();\n }\n } finally {\n this.isProcessingQueue = false;\n }\n }\n\n private async executeSend(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n const messageId = generateId();\n\n const userMessage: Message = {\n id: messageId,\n threadId: this.getThreadId(),\n content: { text },\n author: { id: this.currentUserId, name: this.config.userName, isMe: true },\n timestamp: Date.now(),\n attachments:\n attachments.length > 0\n ? attachments.map((a, i) => ({\n id: `att-${messageId}-${i}`,\n name: a.name ?? \"\",\n url: a.url,\n size: a.size,\n mimeType: a.mimeType,\n }))\n : undefined,\n };\n\n this.messages.push(userMessage);\n this.notifySubscribers(\"message:added\", userMessage);\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendMessage(\n [\n {\n id: messageId,\n role: \"user\",\n text,\n attachments: attachments.map((a) => ({\n url: a.url,\n name: a.name,\n mime_type: a.mimeType,\n size: a.size,\n })),\n },\n ],\n endpoint,\n this.conversationId,\n );\n\n if (response.events) {\n response.events.forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n\n if (response.text && !response.events?.some((e) => e.type === \"message.posted\")) {\n const assistantMessage: Message = {\n id: response.id ?? generateId(),\n threadId: this.getThreadId(),\n content: { text: response.text },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: Date.now(),\n attachments: (response.attachments as Record<string, unknown>[])?.map((a, i) => ({\n id: `att-${response.id ?? \"msg\"}-${i}`,\n name: (a.name as string) ?? \"\",\n url: (a.url as string) ?? \"\",\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n };\n this.messages.push(assistantMessage);\n this.notifySubscribers(\"message:added\", assistantMessage);\n }\n }\n\n async sendAction(messageId: string, actionId: string, value: string): Promise<void> {\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendAction(\n actionId,\n value,\n messageId,\n this.conversationId,\n endpoint,\n );\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async editMessage(messageId: string, newText: string): Promise<void> {\n if (!this.config.features?.editMessages) {\n throw new Error(\"Edit messages not enabled. Set features.editMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.editMessage ?? \"/api/chat/messages/{id}/edit\";\n await this.httpClient.editMessage(messageId, newText, endpoint);\n }\n\n async deleteMessage(messageId: string): Promise<void> {\n if (!this.config.features?.deleteMessages) {\n throw new Error(\"Delete messages not enabled. Set features.deleteMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.deleteMessage ?? \"/api/chat/messages/{id}\";\n await this.httpClient.deleteMessage(messageId, endpoint);\n }\n\n async addReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n\n // Optimistic local update\n this.handleReactionAdded(\n new ReactionAddedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId }),\n );\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = (await this.httpClient.post(endpoint, {\n id: this.conversationId,\n reaction: { messageId, emoji, added: true },\n })) as Record<string, unknown>;\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async removeReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n\n // Optimistic local update\n this.handleReactionRemoved(\n new ReactionRemovedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId }),\n );\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = (await this.httpClient.post(endpoint, {\n id: this.conversationId,\n reaction: { messageId, emoji, added: false },\n })) as Record<string, unknown>;\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n onMessagePosted(handler: (event: MessagePostedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message.posted\", handler);\n }\n\n onMessageEdited(handler: (event: MessageEditedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:edited\", handler);\n }\n\n onMessageDeleted(handler: (event: MessageDeletedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:deleted\", handler);\n }\n\n onReactionAdded(handler: (event: ReactionAddedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:added\", handler);\n }\n\n onReactionRemoved(handler: (event: ReactionRemovedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:removed\", handler);\n }\n\n onStreamingChunk(handler: (event: StreamingChunkEvent) => void): Unsubscribe {\n return this.addEventListener(\"streaming:chunk\", handler);\n }\n\n onTypingStarted(handler: (event: TypingStartedEvent) => void): Unsubscribe {\n return this.addEventListener(\"typing:started\", handler);\n }\n\n getConversationId(): string {\n return this.conversationId;\n }\n getMessages(): Message[] {\n return [...this.messages];\n }\n getThreadId(): string {\n return `web:${this.currentUserId}:${this.conversationId}`;\n }\n getCurrentUserId(): string {\n return this.currentUserId;\n }\n getFeatures(): NonNullable<WebChatClientConfig[\"features\"]> {\n return this.config.features ?? {};\n }\n getEndpoints(): NonNullable<WebChatClientConfig[\"endpoints\"]> {\n return this.config.endpoints ?? {};\n }\n getHttpClient(): HttpClient {\n return this.httpClient;\n }\n\n addEventListener<T = unknown>(eventType: string, handler: (event: T) => void): Unsubscribe {\n if (!this.subscribers.has(eventType)) this.subscribers.set(eventType, []);\n this.subscribers.get(eventType)!.push(handler as (event: unknown) => void);\n return () => {\n const handlers = this.subscribers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler as (event: unknown) => void);\n if (index !== -1) handlers.splice(index, 1);\n }\n };\n }\n\n private handleMessagePosted(event: MessagePostedEvent): void {\n if (this.messages.some((m) => m.id === event.messageId)) return;\n if (this.streamingMessages.has(event.messageId)) return;\n\n const message: Message = {\n id: event.messageId,\n threadId: event.threadId,\n content: { text: event.text, cards: event.card ? [event.card] : undefined },\n author: event.author,\n timestamp: event.timestamp,\n attachments: event.attachments?.map((a) => ({\n id: `att-${event.messageId}-${Math.random().toString(36).slice(2, 8)}`,\n name: a.name ?? \"\",\n url: a.url ?? \"\",\n type: a.type,\n mimeType: a.mimeType,\n size: a.size ?? undefined,\n })),\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n this.notifySubscribers(\"message.posted\", event);\n }\n\n private handleMessageEdited(event: MessageEditedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.content) {\n message.content.text = event.newText;\n this.notifySubscribers(\"message:edited\", event);\n }\n }\n\n private handleMessageDeleted(event: MessageDeletedEvent): void {\n const index = this.messages.findIndex((m) => m.id === event.messageId);\n if (index !== -1) {\n this.messages.splice(index, 1);\n this.notifySubscribers(\"message:deleted\", event);\n }\n }\n\n private handleReactionAdded(event: ReactionAddedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message) {\n if (!message.reactions) message.reactions = [];\n\n const existing = message.reactions.find((r) => r.emoji === event.emoji);\n if (existing) {\n existing.count++;\n existing.users.push(event.user.id);\n } else {\n message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });\n }\n }\n this.notifySubscribers(\"reaction:added\", event);\n }\n\n private handleReactionRemoved(event: ReactionRemovedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.reactions) {\n const index = message.reactions.findIndex((r) => r.emoji === event.emoji);\n if (index !== -1) {\n const reaction = message.reactions[index]!;\n reaction.count--;\n reaction.users = reaction.users.filter((id) => id !== event.user.id);\n if (reaction.count === 0) message.reactions.splice(index, 1);\n }\n }\n this.notifySubscribers(\"reaction:removed\", event);\n }\n\n private handleStreamingChunk(event: StreamingChunkEvent): void {\n const { messageId, chunk, isFinal } = event;\n\n if (!this.streamingMessages.has(messageId)) {\n this.streamingMessages.set(messageId, { messageId, accumulatedText: \"\", isComplete: false });\n this.notifySubscribers(\"streaming:started\", event);\n }\n\n const state = this.streamingMessages.get(messageId)!;\n state.accumulatedText += chunk;\n\n if (isFinal) {\n state.isComplete = true;\n if (!this.messages.some((m) => m.id === messageId)) {\n const message: Message = {\n id: messageId,\n threadId: event.threadId,\n content: { text: state.accumulatedText },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: event.timestamp,\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n }\n this.streamingMessages.delete(messageId);\n this.notifySubscribers(\"streaming:complete\", { messageId, text: state.accumulatedText });\n } else {\n this.notifySubscribers(\"streaming:chunk\", event);\n }\n }\n\n private handleTypingStarted(event: TypingStartedEvent): void {\n if (this.pendingTyping) clearTimeout(this.pendingTyping);\n this.notifySubscribers(\"typing:started\", event);\n this.pendingTyping = setTimeout(() => {\n this.notifySubscribers(\"typing:stopped\", { userId: event.userId });\n }, 3000);\n }\n\n private handleDMRequested(event: DMRequestedEvent): void {\n this.notifySubscribers(\"dm.requested\", event);\n }\n\n private notifySubscribers<T>(eventType: string, data: T): void {\n this.subscribers.get(eventType)?.forEach((handler) => handler(data));\n }\n\n private dispatchEvent(event: ChatEvent): void {\n switch (event.type) {\n case \"message.posted\":\n this.handleMessagePosted(event as MessagePostedEvent);\n break;\n case \"message.edited\":\n this.handleMessageEdited(event as MessageEditedEvent);\n break;\n case \"message.deleted\":\n this.handleMessageDeleted(event as MessageDeletedEvent);\n break;\n case \"reaction.added\":\n this.handleReactionAdded(event as ReactionAddedEvent);\n break;\n case \"reaction.removed\":\n this.handleReactionRemoved(event as ReactionRemovedEvent);\n break;\n case \"typing.started\":\n this.handleTypingStarted(event as TypingStartedEvent);\n break;\n case \"streaming.chunk\":\n this.handleStreamingChunk(event as StreamingChunkEvent);\n break;\n case \"dm.requested\":\n this.handleDMRequested(event as DMRequestedEvent);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel as PusherChannel } from \"pusher-js\";\n\nexport interface PusherConfig {\n key: string;\n cluster?: string;\n host?: string;\n port?: number;\n forceTLS?: boolean;\n authEndpoint?: string;\n}\n\nexport class PusherBroadcastClient implements BroadcastClient {\n private pusher: Pusher;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, PusherChannel> = new Map();\n\n constructor(pusher: Pusher, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(config: PusherConfig, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(\n pusherOrConfig: Pusher | PusherConfig,\n channelPrefix: string = \"chat\",\n channelTypes?: ChannelTypeConfig,\n ) {\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n\n if (\"key\" in pusherOrConfig) {\n const PusherCtor = (globalThis as any).Pusher ?? (globalThis as any).pusherJs;\n if (!PusherCtor) {\n throw new Error(\"pusher-js not found. Install it or pass a Pusher instance.\");\n }\n this.pusher = new PusherCtor((pusherOrConfig as PusherConfig).key, pusherOrConfig) as Pusher;\n } else {\n this.pusher = pusherOrConfig as Pusher;\n }\n }\n\n private buildChannelName(base: string, type: \"public\" | \"private\" | \"presence\"): string {\n switch (type) {\n case \"private\":\n return `private-${base}`;\n case \"presence\":\n return `presence-${base}`;\n default:\n return base;\n }\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n connect(): void {\n if (this.pusher.connection?.state !== \"connected\") {\n this.pusher.connect();\n }\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => channel.unbind_all?.() ?? channel.unsubscribe?.());\n this.subscriptions.clear();\n this.pusher.disconnect?.();\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const baseName = await this.buildResolvedChannelName(threadId);\n const channelName = this.buildChannelName(baseName, this.threadChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents = [\n \"message.posted\",\n \"message.edited\",\n \"message.deleted\",\n \"reaction.added\",\n \"reaction.removed\",\n \"typing.started\",\n ] as const;\n\n threadEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const baseName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channelName = this.buildChannelName(baseName, this.userChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents = [\"typing.started\", \"streaming.chunk\", \"dm.requested\"] as const;\n\n userEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n return this.pusher.connection?.state === \"connected\";\n }\n\n private dispatchToHandler(event: ChatEvent, handlers: EventHandlers): void {\n switch (event.type) {\n case \"message.posted\":\n handlers.onMessagePosted?.(event as any);\n break;\n case \"message.edited\":\n handlers.onMessageEdited?.(event as any);\n break;\n case \"message.deleted\":\n handlers.onMessageDeleted?.(event as any);\n break;\n case \"reaction.added\":\n handlers.onReactionAdded?.(event as any);\n break;\n case \"reaction.removed\":\n handlers.onReactionRemoved?.(event as any);\n break;\n case \"typing.started\":\n handlers.onTypingStarted?.(event as any);\n break;\n case \"streaming.chunk\":\n handlers.onStreamingChunk?.(event as any);\n break;\n case \"dm.requested\":\n handlers.onDMRequested?.(event as any);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Echo from \"laravel-echo\";\n\ninterface EchoChannel {\n listen(event: string, callback: (data: unknown) => void): this;\n unsubscribe(): void;\n stopListening(event?: string, callback?: (data: unknown) => void): this;\n}\n\nexport class LaravelEchoBroadcastClient implements BroadcastClient {\n private echo: Echo<any>;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, EchoChannel> = new Map();\n\n constructor(echo: Echo<any>, channelPrefix: string = \"chat\", channelTypes?: ChannelTypeConfig) {\n this.echo = echo;\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n }\n\n private subscribeToEcho(name: string, type: \"public\" | \"private\" | \"presence\"): EchoChannel {\n switch (type) {\n case \"private\":\n return this.echo.private(name) as unknown as EchoChannel;\n case \"presence\":\n return this.echo.join(name) as unknown as EchoChannel;\n default:\n return this.echo.channel(name) as unknown as EchoChannel;\n }\n }\n\n connect(): void | Promise<void> {\n return Promise.resolve();\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => {\n channel.unsubscribe?.();\n channel.stopListening?.();\n });\n this.subscriptions.clear();\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const channelName = await this.buildResolvedChannelName(threadId);\n const channel = this.subscribeToEcho(channelName, this.threadChannelType);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"message.posted\", handler: \"onMessagePosted\" },\n { type: \"message.edited\", handler: \"onMessageEdited\" },\n { type: \"message.deleted\", handler: \"onMessageDeleted\" },\n { type: \"reaction.added\", handler: \"onReactionAdded\" },\n { type: \"reaction.removed\", handler: \"onReactionRemoved\" },\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n ];\n\n threadEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const channelName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channel = this.subscribeToEcho(channelName, this.userChannelType);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n { type: \"streaming.chunk\", handler: \"onStreamingChunk\" },\n { type: \"dm.requested\", handler: \"onDMRequested\" },\n ];\n\n userEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n try {\n const connector = (this.echo as any).connector;\n if (!connector) return false;\n\n if (connector.pusher?.connection?.state === \"connected\") return true;\n if (connector.socket?.connected) return true;\n\n return false;\n } catch {\n return false;\n }\n }\n}\n","import type { PushConfig, PushSubscriptionStatus, PushEventData } from \"./types\";\n\nexport class PushManager {\n private config: PushConfig;\n private registration: ServiceWorkerRegistration | null = null;\n private status: PushSubscriptionStatus = \"unsupported\";\n private statusListeners: Set<(status: PushSubscriptionStatus) => void> = new Set();\n private messageListeners: Set<(data: PushEventData) => void> = new Set();\n\n constructor(config: PushConfig) {\n this.config = config;\n }\n\n static isSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"serviceWorker\" in navigator &&\n \"PushManager\" in window &&\n \"Notification\" in window\n );\n }\n\n getStatus(): PushSubscriptionStatus {\n return this.status;\n }\n\n onStatusChange(listener: (status: PushSubscriptionStatus) => void): () => void {\n this.statusListeners.add(listener);\n return () => {\n this.statusListeners.delete(listener);\n };\n }\n\n onMessage(listener: (data: PushEventData) => void): () => void {\n this.messageListeners.add(listener);\n return () => {\n this.messageListeners.delete(listener);\n };\n }\n\n async initialize(): Promise<void> {\n if (!PushManager.isSupported()) {\n this.setStatus(\"unsupported\");\n return;\n }\n if (Notification.permission === \"denied\") {\n this.setStatus(\"denied\");\n return;\n }\n\n try {\n this.registration = await navigator.serviceWorker.register(\n this.config.serviceWorkerUrl || \"/chat-service-worker.js\",\n {\n scope: this.config.serviceWorkerScope || \"/\",\n type: this.config.serviceWorkerType,\n },\n );\n await navigator.serviceWorker.ready;\n\n navigator.serviceWorker.addEventListener(\"message\", (event: MessageEvent) => {\n const msg = event.data as Record<string, unknown>;\n if (msg?.type === \"chat-widget:push-data\") {\n const pushData = msg.data as PushEventData;\n this.messageListeners.forEach((listener) => listener(pushData));\n }\n });\n\n const subscription = await this.registration.pushManager.getSubscription();\n this.setStatus(subscription ? \"subscribed\" : \"default\");\n } catch {\n this.setStatus(\"error\");\n }\n }\n\n async subscribe(): Promise<void> {\n if (!this.registration)\n throw new Error(\"PushManager not initialized. Call initialize() first.\");\n\n this.setStatus(\"subscribing\");\n\n try {\n let subscription = await this.registration.pushManager.getSubscription();\n\n if (!subscription) {\n const permission = await Notification.requestPermission();\n if (permission !== \"granted\") {\n this.setStatus(permission === \"denied\" ? \"denied\" : \"default\");\n return;\n }\n\n const vapidPublicKey = await this.config.getVapidPublicKey();\n const convertedKey = this.urlBase64ToUint8Array(vapidPublicKey);\n subscription = await this.registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: convertedKey.buffer as ArrayBuffer,\n });\n }\n\n await this.config.onSubscribe(subscription.toJSON());\n this.setStatus(\"subscribed\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push subscription failed\");\n }\n }\n\n async unsubscribe(): Promise<void> {\n if (!this.registration) return;\n\n try {\n const subscription = await this.registration.pushManager.getSubscription();\n if (subscription) {\n await this.config.onUnsubscribe(subscription.toJSON());\n await subscription.unsubscribe();\n }\n this.setStatus(\"default\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push unsubscription failed\");\n }\n }\n\n private urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));\n }\n\n private setStatus(status: PushSubscriptionStatus): void {\n this.status = status;\n this.statusListeners.forEach((listener) => listener(status));\n }\n}\n","import { HttpClient } from \"../client/HttpClient\";\nimport type { PushConfig } from \"./types\";\n\nexport function createPushSubscriptionHandlers(\n httpClient: HttpClient,\n userId: string,\n): Pick<PushConfig, \"onSubscribe\" | \"onUnsubscribe\"> {\n return {\n onSubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.post(\"/api/push/subscriptions\", {\n userId,\n subscription,\n userAgent: navigator.userAgent,\n });\n },\n onUnsubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.delete(\n `/api/push/subscriptions?userId=${encodeURIComponent(userId)}&endpoint=${encodeURIComponent(subscription.endpoint || \"\")}`,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED