cevro-messenger-sdk 0.1.1 → 0.1.2
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/cjs/index.js +2 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +427 -80
- package/dist/esm/index.js.map +1 -1
- package/dist/types/core/ApiClient.d.ts +6 -1
- package/dist/types/core/ApiClient.d.ts.map +1 -1
- package/dist/types/core/CevroMessenger.d.ts +4 -0
- package/dist/types/core/CevroMessenger.d.ts.map +1 -1
- package/dist/types/core/WebSocketClient.d.ts.map +1 -1
- package/dist/types/i18n/strings.d.ts +25 -0
- package/dist/types/i18n/strings.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +7 -3
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/ui/ChatWindow.d.ts +59 -8
- package/dist/types/ui/ChatWindow.d.ts.map +1 -1
- package/dist/types/ui/MessageList.d.ts +8 -2
- package/dist/types/ui/MessageList.d.ts.map +1 -1
- package/dist/umd/cevro-messenger.min.js +2 -2
- package/dist/umd/cevro-messenger.min.js.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/core/EventEmitter.ts","../../src/utils/session.ts","../../src/utils/file-validation.ts","../../src/core/ApiClient.ts","../../node_modules/centrifuge/build/index.mjs","../../src/core/WebSocketClient.ts","../../src/utils/dom.ts","../../src/ui/Launcher.ts","../../src/ui/MessageList.ts","../../src/ui/ChatWindow.ts","../../src/core/CevroMessenger.ts","../../src/index.ts"],"sourcesContent":["import type { EventType, EventHandler } from '../types';\n\n/**\n * Simple event emitter for SDK events\n */\nexport class EventEmitter {\n private listeners: Map<EventType, Set<EventHandler>> = new Map();\n private onceHandlers: Map<EventHandler, EventHandler> = new Map(); // Maps wrapper -> original\n\n /**\n * Subscribe to an event\n */\n on<T = any>(event: EventType, handler: EventHandler<T>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(handler);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n /**\n * Subscribe to an event (fires only once)\n */\n once<T = any>(event: EventType, handler: EventHandler<T>): () => void {\n const onceHandler: EventHandler<T> = (data) => {\n this.onceHandlers.delete(onceHandler);\n this.off(event, onceHandler);\n handler(data);\n };\n this.onceHandlers.set(onceHandler, handler);\n return this.on(event, onceHandler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off(event: EventType, handler: EventHandler): void {\n const handlers = this.listeners.get(event);\n if (handlers) {\n handlers.delete(handler);\n // Also clean up from onceHandlers if it was a once handler\n this.onceHandlers.delete(handler);\n }\n }\n\n /**\n * Emit an event\n */\n emit<T = any>(event: EventType, data?: T): void {\n const handlers = this.listeners.get(event);\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(data);\n } catch (error) {\n console.error(`[CevroMessenger] Error in event handler for \"${event}\":`, error);\n }\n });\n }\n }\n\n /**\n * Remove all listeners for an event (or all events if no event specified)\n */\n removeAllListeners(event?: EventType): void {\n if (event) {\n // Clean up once handlers for this event\n const handlers = this.listeners.get(event);\n if (handlers) {\n handlers.forEach((handler) => {\n this.onceHandlers.delete(handler);\n });\n }\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n this.onceHandlers.clear();\n }\n }\n\n /**\n * Get listener count for an event\n */\n listenerCount(event: EventType): number {\n return this.listeners.get(event)?.size || 0;\n }\n}\n","import type { SessionData } from '../types';\n\n/**\n * Collect browser session data\n */\nexport function collectSessionData(): SessionData {\n const session: SessionData = {};\n\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return session;\n }\n\n try {\n // Browser info\n session.userAgent = navigator.userAgent;\n session.language = navigator.language;\n session.platform = navigator.platform;\n session.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n\n // Page context\n session.currentPage = window.location.href;\n session.pageTitle = document.title;\n session.referrer = document.referrer;\n\n // Screen dimensions\n session.screenWidth = window.screen.width;\n session.screenHeight = window.screen.height;\n session.viewportWidth = window.innerWidth;\n session.viewportHeight = window.innerHeight;\n session.devicePixelRatio = window.devicePixelRatio;\n\n // UTM parameters from URL\n const urlParams = new URLSearchParams(window.location.search);\n session.utmSource = urlParams.get('utm_source') || undefined;\n session.utmMedium = urlParams.get('utm_medium') || undefined;\n session.utmCampaign = urlParams.get('utm_campaign') || undefined;\n session.utmContent = urlParams.get('utm_content') || undefined;\n session.utmTerm = urlParams.get('utm_term') || undefined;\n\n // Capabilities\n session.cookiesEnabled = navigator.cookieEnabled;\n session.touchSupport = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n session.online = navigator.onLine;\n\n // Connection info (if available)\n const connection = (navigator as any).connection;\n if (connection) {\n session.connectionType = connection.effectiveType;\n }\n } catch (e) {\n // Silently ignore errors in session collection\n }\n\n return session;\n}\n\n/**\n * Get stored visitor token (signed by server)\n */\nexport function getStoredVisitorToken(): string | null {\n try {\n return localStorage.getItem('cevro_visitor_token');\n } catch {\n return null;\n }\n}\n\n/**\n * Store visitor token received from server\n */\nexport function storeVisitorToken(token: string): void {\n try {\n localStorage.setItem('cevro_visitor_token', token);\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Extract visitorId from visitorToken\n * Token format: visitorId.signature\n */\nexport function extractVisitorIdFromToken(token: string): string | null {\n if (!token) return null;\n const lastDotIndex = token.lastIndexOf('.');\n if (lastDotIndex <= 0) return null;\n return token.substring(0, lastDotIndex);\n}\n\n/**\n * Get visitorId from stored token (or null if not available)\n */\nexport function getStoredVisitorId(): string | null {\n const token = getStoredVisitorToken();\n return token ? extractVisitorIdFromToken(token) : null;\n}\n\n/**\n * Get visitor ID from stored token, or null if not yet available.\n * The visitor ID is assigned by the server and stored in the visitor token.\n */\nexport function generateVisitorId(): string | null {\n return getStoredVisitorId();\n}\n\n/**\n * Stored session data\n */\nexport interface StoredSessionData {\n sessionId?: string;\n contactId?: string;\n ticketId?: string;\n}\n\n/**\n * Get stored session data\n */\nexport function getStoredSession(): StoredSessionData | null {\n try {\n const stored = localStorage.getItem('cevro_session');\n return stored ? JSON.parse(stored) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Store session data\n */\nexport function storeSession(sessionId: string, contactId: string, ticketId: string): void {\n try {\n localStorage.setItem('cevro_session', JSON.stringify({ sessionId, contactId, ticketId }));\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Clear stored session data\n */\nexport function clearStoredSession(): void {\n try {\n localStorage.removeItem('cevro_session');\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Clear stored visitor token\n * Use this when you want to completely reset the visitor identity\n */\nexport function clearStoredVisitorToken(): void {\n try {\n localStorage.removeItem('cevro_visitor_token');\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Clear all stored data (session + visitor token)\n */\nexport function clearAllStoredData(): void {\n clearStoredSession();\n clearStoredVisitorToken();\n}\n","/**\n * File validation utilities for secure file uploads\n * Provides client-side validation as first line of defense\n */\n\n/**\n * Allowed MIME types for file uploads\n * This whitelist prevents potentially dangerous file types\n */\nexport const ALLOWED_MIME_TYPES: ReadonlySet<string> = new Set([\n // Images\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/svg+xml',\n // Documents\n 'application/pdf',\n 'text/plain',\n 'text/csv',\n // Microsoft Office\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'application/vnd.ms-powerpoint',\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n // Audio/Video\n 'audio/mpeg',\n 'audio/wav',\n 'audio/ogg',\n 'video/mp4',\n 'video/webm',\n // Archives (optional - can be disabled)\n 'application/zip',\n 'application/x-rar-compressed',\n]);\n\n/**\n * Dangerous file extensions that should always be blocked\n * Even if MIME type looks safe, these extensions are risky\n */\nexport const BLOCKED_EXTENSIONS: ReadonlySet<string> = new Set([\n '.exe', '.dll', '.bat', '.cmd', '.sh', '.bash',\n '.ps1', '.psm1', '.psd1', // PowerShell\n '.vbs', '.vbe', '.js', '.jse', '.ws', '.wsf', '.wsc', '.wsh', // Scripts\n '.msi', '.msp', '.mst', // Windows installers\n '.scr', '.pif', '.com', // Executables\n '.hta', '.cpl', '.msc', // Control panel/settings\n '.jar', '.class', // Java\n '.php', '.php3', '.php4', '.php5', '.phtml', // PHP\n '.asp', '.aspx', '.ashx', '.asmx', // ASP.NET\n '.jsp', '.jspx', // JSP\n '.py', '.pyc', '.pyw', // Python\n '.rb', '.rbw', // Ruby\n '.pl', '.pm', '.cgi', // Perl/CGI\n '.htaccess', '.htpasswd', // Apache config\n]);\n\n/**\n * Default file upload constraints\n */\nexport const DEFAULT_FILE_CONSTRAINTS = {\n maxSizeBytes: 25 * 1024 * 1024, // 25MB\n minSizeBytes: 1, // At least 1 byte\n maxFilenameLength: 255,\n} as const;\n\n/**\n * File validation configuration\n */\nexport interface FileValidationConfig {\n maxSizeBytes?: number;\n minSizeBytes?: number;\n allowedMimeTypes?: ReadonlySet<string> | Set<string>;\n blockedExtensions?: ReadonlySet<string> | Set<string>;\n maxFilenameLength?: number;\n}\n\n/**\n * File validation result\n */\nexport interface FileValidationResult {\n valid: boolean;\n error?: string;\n errorCode?: 'FILE_TOO_LARGE' | 'FILE_TOO_SMALL' | 'INVALID_TYPE' | 'BLOCKED_EXTENSION' | 'FILENAME_TOO_LONG' | 'EMPTY_FILE';\n}\n\n/**\n * Get file extension from filename (lowercase)\n */\nexport function getFileExtension(filename: string): string {\n const lastDot = filename.lastIndexOf('.');\n if (lastDot === -1 || lastDot === filename.length - 1) {\n return '';\n }\n return filename.substring(lastDot).toLowerCase();\n}\n\n/**\n * Sanitize filename for safe storage\n * Removes path traversal attempts and dangerous characters\n */\nexport function sanitizeFilename(filename: string): string {\n // Remove path components\n let sanitized = filename.replace(/^.*[\\\\/]/, '');\n\n // Remove null bytes and other control characters\n sanitized = sanitized.replace(/[\\x00-\\x1f\\x7f]/g, '');\n\n // Replace problematic characters\n sanitized = sanitized.replace(/[<>:\"/\\\\|?*]/g, '_');\n\n // Trim whitespace and dots from start/end\n sanitized = sanitized.replace(/^[\\s.]+|[\\s.]+$/g, '');\n\n // If empty after sanitization, use default name\n if (!sanitized) {\n sanitized = 'unnamed_file';\n }\n\n // Limit length\n if (sanitized.length > DEFAULT_FILE_CONSTRAINTS.maxFilenameLength) {\n const ext = getFileExtension(sanitized);\n const nameWithoutExt = sanitized.slice(0, -ext.length || undefined);\n const maxNameLength = DEFAULT_FILE_CONSTRAINTS.maxFilenameLength - ext.length;\n sanitized = nameWithoutExt.slice(0, maxNameLength) + ext;\n }\n\n return sanitized;\n}\n\n/**\n * Validate a file before upload\n * Returns validation result with error details if invalid\n */\nexport function validateFile(\n file: File,\n config: FileValidationConfig = {}\n): FileValidationResult {\n const {\n maxSizeBytes = DEFAULT_FILE_CONSTRAINTS.maxSizeBytes,\n minSizeBytes = DEFAULT_FILE_CONSTRAINTS.minSizeBytes,\n allowedMimeTypes = ALLOWED_MIME_TYPES,\n blockedExtensions = BLOCKED_EXTENSIONS,\n maxFilenameLength = DEFAULT_FILE_CONSTRAINTS.maxFilenameLength,\n } = config;\n\n // Check file size\n if (file.size === 0) {\n return {\n valid: false,\n error: 'File is empty',\n errorCode: 'EMPTY_FILE',\n };\n }\n\n if (file.size < minSizeBytes) {\n return {\n valid: false,\n error: `File is too small. Minimum size is ${formatFileSize(minSizeBytes)}`,\n errorCode: 'FILE_TOO_SMALL',\n };\n }\n\n if (file.size > maxSizeBytes) {\n return {\n valid: false,\n error: `File is too large. Maximum size is ${formatFileSize(maxSizeBytes)}`,\n errorCode: 'FILE_TOO_LARGE',\n };\n }\n\n // Check filename length\n if (file.name.length > maxFilenameLength) {\n return {\n valid: false,\n error: `Filename is too long. Maximum length is ${maxFilenameLength} characters`,\n errorCode: 'FILENAME_TOO_LONG',\n };\n }\n\n // Check for blocked extensions\n const extension = getFileExtension(file.name);\n if (extension && blockedExtensions.has(extension)) {\n return {\n valid: false,\n error: `File type \"${extension}\" is not allowed for security reasons`,\n errorCode: 'BLOCKED_EXTENSION',\n };\n }\n\n // Check MIME type\n const mimeType = file.type || 'application/octet-stream';\n if (!allowedMimeTypes.has(mimeType)) {\n // Allow files without explicit type if extension is safe\n if (mimeType === 'application/octet-stream' && extension && !blockedExtensions.has(extension)) {\n // Let it pass - backend will verify\n } else {\n return {\n valid: false,\n error: `File type \"${mimeType}\" is not allowed. Allowed types: images, documents, audio, video`,\n errorCode: 'INVALID_TYPE',\n };\n }\n }\n\n return { valid: true };\n}\n\n/**\n * Format file size to human-readable string\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];\n}\n\n/**\n * Generate accept attribute string from ALLOWED_MIME_TYPES\n * Used to sync file input accept with validation rules\n */\nexport function generateAcceptAttribute(allowedMimeTypes: ReadonlySet<string> = ALLOWED_MIME_TYPES): string {\n const accepts: string[] = [];\n\n allowedMimeTypes.forEach((mimeType) => {\n accepts.push(mimeType);\n });\n\n return accepts.join(',');\n}\n\n/**\n * Rate limiter for file uploads\n * Prevents rapid successive uploads\n */\nexport class UploadRateLimiter {\n private uploadTimestamps: number[] = [];\n private readonly maxUploads: number;\n private readonly windowMs: number;\n\n constructor(maxUploads = 5, windowMs = 60000) {\n this.maxUploads = maxUploads;\n this.windowMs = windowMs;\n }\n\n /**\n * Check if upload is allowed\n * Returns true if allowed, false if rate limited\n */\n canUpload(): boolean {\n const now = Date.now();\n // Remove timestamps outside the window\n this.uploadTimestamps = this.uploadTimestamps.filter(\n (timestamp) => now - timestamp < this.windowMs\n );\n return this.uploadTimestamps.length < this.maxUploads;\n }\n\n /**\n * Record an upload attempt\n */\n recordUpload(): void {\n this.uploadTimestamps.push(Date.now());\n }\n\n /**\n * Get remaining uploads in current window\n */\n getRemainingUploads(): number {\n const now = Date.now();\n this.uploadTimestamps = this.uploadTimestamps.filter(\n (timestamp) => now - timestamp < this.windowMs\n );\n return Math.max(0, this.maxUploads - this.uploadTimestamps.length);\n }\n\n /**\n * Get time until next upload is allowed (in ms)\n * Returns 0 if upload is allowed now\n */\n getTimeUntilNextUpload(): number {\n if (this.canUpload()) return 0;\n const oldestTimestamp = Math.min(...this.uploadTimestamps);\n return Math.max(0, this.windowMs - (Date.now() - oldestTimestamp));\n }\n\n /**\n * Reset the rate limiter\n */\n reset(): void {\n this.uploadTimestamps = [];\n }\n}\n","import type {\n CevroMessengerConfig,\n SendMessageRequest,\n Message,\n Conversation,\n Agent,\n} from '../types';\nimport { collectSessionData } from '../utils/session';\nimport {\n validateFile,\n sanitizeFilename,\n UploadRateLimiter,\n ALLOWED_MIME_TYPES,\n BLOCKED_EXTENSIONS,\n DEFAULT_FILE_CONSTRAINTS,\n} from '../utils/file-validation';\n\n/**\n * API client for communicating with Cevro backend\n */\nexport class ApiClient {\n private config: CevroMessengerConfig;\n private accessToken: string | null = null;\n private contactId: string | null = null;\n private currentTicketId: string | null = null;\n private visitorToken: string | null = null;\n private currentAgent: Agent | null = null;\n private uploadRateLimiter: UploadRateLimiter;\n\n constructor(config: CevroMessengerConfig) {\n this.config = config;\n\n // Initialize rate limiter with config or defaults\n const maxUploadsPerMinute = config.fileUpload?.maxUploadsPerMinute ?? 5;\n this.uploadRateLimiter = new UploadRateLimiter(maxUploadsPerMinute, 60000);\n }\n\n /**\n * Set visitor token for authenticated requests\n */\n setVisitorToken(token: string): void {\n this.visitorToken = token;\n }\n\n /**\n * Get visitor token\n */\n getVisitorToken(): string | null {\n return this.visitorToken;\n }\n\n /**\n * Set access token for authenticated requests\n */\n setAccessToken(token: string): void {\n this.accessToken = token;\n }\n\n /**\n * Get current contact ID\n */\n getContactId(): string | null {\n return this.contactId;\n }\n\n /**\n * Get current ticket ID\n */\n getCurrentTicketId(): string | null {\n return this.currentTicketId;\n }\n\n /**\n * Set current ticket ID\n */\n setCurrentTicketId(ticketId: string): void {\n this.currentTicketId = ticketId;\n }\n\n /**\n * Get current agent info\n */\n getCurrentAgent(): Agent | null {\n return this.currentAgent;\n }\n\n /**\n * Make API request\n */\n private async request<T>(\n endpoint: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.config.apiBase}${endpoint}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(options.headers as Record<string, string> || {}),\n };\n\n // Add workspace headers for gateway auth\n if (this.config.workspaceId) {\n headers['X-Workspace-Id'] = this.config.workspaceId;\n }\n if (this.config.brandId) {\n headers['X-Brand-Id'] = this.config.brandId;\n }\n if (this.visitorToken) {\n headers['X-Visitor-Token'] = this.visitorToken;\n }\n\n if (this.accessToken) {\n headers['Authorization'] = `Bearer ${this.accessToken}`;\n }\n\n const response = await fetch(url, {\n ...options,\n headers,\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ message: response.statusText }));\n throw new Error(error.message || `Request failed: ${response.status}`);\n }\n\n return response.json();\n }\n\n /**\n * Initialize a chat session\n * Called when chat opens to create/restore session\n */\n async initSession(\n visitorId: string | null,\n options?: { forceNewTicket?: boolean }\n ): Promise<{\n sessionId: string;\n contactId: string;\n ticketId: string;\n visitorId: string;\n isNewSession: boolean;\n isNewTicket: boolean;\n ticketClosed?: boolean;\n ticketClosedReason?: string;\n agent?: Agent;\n typingConfig?: {\n onDurationMs: number;\n offDurationMs: number;\n };\n messages?: Message[];\n }> {\n const session = collectSessionData();\n\n const payload: any = {\n visitorId,\n session,\n brandId: this.config.brandId,\n firstName: this.config.player?.firstName,\n lastName: this.config.player?.lastName,\n email: this.config.player?.email,\n phone: this.config.player?.phone,\n customAttributes: this.config.player?.customAttributes,\n locale: this.config.locale,\n forceNewTicket: options?.forceNewTicket,\n };\n\n // Add player data for authenticated users (for merge logic)\n if (this.config.player?.playerId) {\n payload.playerId = this.config.player.playerId;\n payload.playerHash = this.config.player.playerHash;\n }\n\n const result = await this.request<any>('/api/v1/sdk/session', {\n method: 'POST',\n body: JSON.stringify(payload),\n headers: visitorId ? { 'X-Visitor-Id': visitorId } : undefined,\n });\n\n // Store contact, ticket IDs and agent info\n this.contactId = result.contactId;\n this.currentTicketId = result.ticketId;\n if (result.agent) {\n this.currentAgent = result.agent;\n }\n\n return {\n sessionId: result.sessionId,\n contactId: result.contactId,\n ticketId: result.ticketId,\n visitorId: result.visitorId,\n isNewSession: result.isNewSession,\n isNewTicket: result.isNewTicket,\n ticketClosed: result.ticketClosed,\n ticketClosedReason: result.ticketClosedReason,\n agent: result.agent,\n typingConfig: result.typingConfig,\n messages: result.messages?.map((msg: any) => this.normalizeMessage(msg)),\n };\n }\n\n /**\n * Send a message to an existing conversation\n */\n async sendMessage(message: string, assetId?: string): Promise<Message> {\n if (!this.contactId || !this.currentTicketId) {\n throw new Error('No active session. Call initSession first.');\n }\n\n const payload: SendMessageRequest = {\n contactId: this.contactId,\n ticketId: this.currentTicketId,\n message,\n assetId,\n };\n\n const result = await this.request<any>('/api/v1/sdk/send', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n\n // Server returns {success: true, message: {...}}, extract the message\n return this.normalizeMessage(result.message || result);\n }\n\n /**\n * Get messages for the current ticket (for authenticated users)\n */\n async getMessages(ticketId?: string): Promise<Message[]> {\n const targetTicketId = ticketId || this.currentTicketId;\n if (!targetTicketId) {\n throw new Error('No ticket ID available');\n }\n\n const result = await this.request<any>(\n `/api/v1/messages/my-tickets?supportTicketId=${targetTicketId}`\n );\n\n const messages = result.results || result.messages || result || [];\n return messages.map((msg: any) => this.normalizeMessage(msg));\n }\n\n /**\n * Get user's support tickets (for authenticated users)\n */\n async getMyTickets(): Promise<Conversation[]> {\n const result = await this.request<any>('/api/v1/messages/my-tickets');\n\n const tickets = result.results || result.tickets || result || [];\n return tickets.map((ticket: any) => this.normalizeConversation(ticket));\n }\n\n /**\n * Upload a file using presigned S3 URL for better performance.\n * The file is uploaded directly to S3, bypassing the backend.\n *\n * Security features:\n * - File size validation (client-side)\n * - MIME type whitelist validation\n * - Blocked extension check\n * - Rate limiting (uploads per minute)\n * - Filename sanitization\n *\n * @param file - The file to upload\n * @param onProgress - Optional callback for upload progress (0-100)\n * @returns The asset ID to use when sending messages\n * @throws Error if validation fails or rate limited\n */\n async uploadFile(\n file: File,\n onProgress?: (progress: number) => void\n ): Promise<string> {\n // Step 0: Rate limiting check\n if (!this.uploadRateLimiter.canUpload()) {\n const waitTime = Math.ceil(this.uploadRateLimiter.getTimeUntilNextUpload() / 1000);\n throw new Error(`Too many uploads. Please wait ${waitTime} seconds before uploading again.`);\n }\n\n // Step 1: Validate file (size, type, extension)\n const validationConfig = {\n maxSizeBytes: this.config.fileUpload?.maxSizeBytes ?? DEFAULT_FILE_CONSTRAINTS.maxSizeBytes,\n allowedMimeTypes: this.config.fileUpload?.allowedMimeTypes\n ? new Set(this.config.fileUpload.allowedMimeTypes)\n : ALLOWED_MIME_TYPES,\n blockedExtensions: this.config.fileUpload?.additionalBlockedExtensions\n ? new Set([...BLOCKED_EXTENSIONS, ...this.config.fileUpload.additionalBlockedExtensions])\n : BLOCKED_EXTENSIONS,\n };\n\n const validation = validateFile(file, validationConfig);\n if (!validation.valid) {\n throw new Error(validation.error || 'File validation failed');\n }\n\n // Step 2: Sanitize filename\n const sanitizedFilename = sanitizeFilename(file.name);\n\n // Step 3: Record upload attempt for rate limiting\n this.uploadRateLimiter.recordUpload();\n\n // Step 4: Get presigned URL from backend\n const { uploadUrl, assetId } = await this.request<{\n uploadUrl: string;\n assetId: string;\n expiresIn: number;\n }>('/api/v1/sdk/upload-url', {\n method: 'POST',\n body: JSON.stringify({\n filename: sanitizedFilename,\n contentType: file.type || 'application/octet-stream',\n size: file.size,\n }),\n });\n\n // Step 5: Upload file directly to S3\n await this.uploadToS3(uploadUrl, file, onProgress);\n\n return assetId;\n }\n\n /**\n * Upload file directly to S3 using presigned URL\n */\n private async uploadToS3(\n uploadUrl: string,\n file: File,\n onProgress?: (progress: number) => void\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable && onProgress) {\n const progress = Math.round((event.loaded / event.total) * 100);\n onProgress(progress);\n }\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n resolve();\n } else {\n reject(new Error(`Upload failed with status ${xhr.status}`));\n }\n });\n\n xhr.addEventListener('error', () => {\n reject(new Error('Upload failed'));\n });\n\n xhr.open('PUT', uploadUrl);\n xhr.setRequestHeader('Content-Type', file.type || 'application/octet-stream');\n xhr.send(file);\n });\n }\n\n /**\n * Normalize message object from API response\n */\n private normalizeMessage(data: any): Message {\n return {\n id: data.objectId || data.id,\n body: data.body || '',\n inbound: data.inbound || false,\n outbound: data.outbound || !data.inbound,\n createdAt: data.createdAt || new Date().toISOString(),\n type: data.type || 'text',\n mediaUrl: data.mediaUrl,\n mediaType: data.mediaType,\n status: data.status || 'sent',\n richContent: data.richContent,\n };\n }\n\n /**\n * Normalize conversation object from API response\n */\n private normalizeConversation(data: any): Conversation {\n return {\n id: data.objectId || data.id,\n conversationId: data.conversationId || data.objectId || data.id,\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n status: data.resolved ? 'resolved' : data.escalated ? 'escalated' : 'open',\n unreadCount: data.unreadCount || 0,\n lastMessage: data.latestMessage ? this.normalizeMessage(data.latestMessage) : undefined,\n };\n }\n\n /**\n * Get Centrifugo connection token for real-time messaging\n *\n * For authenticated players: uses playerHash for identity verification\n * For visitors: uses server-signed visitorToken for security\n *\n * @param visitorToken - Server-signed visitor token (optional, server generates if not provided)\n */\n async getConnectionToken(visitorToken?: string | null): Promise<{\n token: string;\n visitorId: string;\n visitorToken: string;\n expiresAt: number;\n }> {\n const payload: any = {\n workspaceId: this.config.workspaceId,\n brandId: this.config.brandId,\n };\n\n if (visitorToken) {\n payload.visitorToken = visitorToken;\n }\n\n // Add player data for authenticated users\n if (this.config.player?.playerId) {\n payload.playerId = this.config.player.playerId;\n payload.playerHash = this.config.player.playerHash;\n payload.email = this.config.player.email;\n payload.firstName = this.config.player.firstName;\n }\n\n const result = await this.request<{\n token: string;\n visitorId: string;\n visitorToken: string;\n expiresAt: number;\n }>('/api/v1/sdk/token', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n\n return result;\n }\n\n /**\n * Refresh Centrifugo token before expiration\n */\n async refreshConnectionToken(visitorToken?: string | null): Promise<{\n token: string;\n visitorToken: string;\n expiresAt: number;\n }> {\n return this.getConnectionToken(visitorToken);\n }\n\n /**\n * Clear stored data (on shutdown)\n */\n clear(): void {\n this.accessToken = null;\n this.contactId = null;\n this.currentTicketId = null;\n }\n}\n","/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol */\r\n\r\n\r\nfunction __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\ntypeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\n\nfunction getDefaultExportFromCjs (x) {\n\treturn x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;\n}\n\nvar events = {exports: {}};\n\nvar R = typeof Reflect === 'object' ? Reflect : null;\nvar ReflectApply = R && typeof R.apply === 'function'\n ? R.apply\n : function ReflectApply(target, receiver, args) {\n return Function.prototype.apply.call(target, receiver, args);\n };\n\nvar ReflectOwnKeys;\nif (R && typeof R.ownKeys === 'function') {\n ReflectOwnKeys = R.ownKeys;\n} else if (Object.getOwnPropertySymbols) {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target)\n .concat(Object.getOwnPropertySymbols(target));\n };\n} else {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target);\n };\n}\n\nfunction ProcessEmitWarning(warning) {\n if (console && console.warn) console.warn(warning);\n}\n\nvar NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {\n return value !== value;\n};\n\nfunction EventEmitter() {\n EventEmitter.init.call(this);\n}\nevents.exports = EventEmitter;\nevents.exports.once = once;\n\n// Backwards-compat with node 0.10.x\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._eventsCount = 0;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nvar defaultMaxListeners = 10;\n\nfunction checkListener(listener) {\n if (typeof listener !== 'function') {\n throw new TypeError('The \"listener\" argument must be of type Function. Received type ' + typeof listener);\n }\n}\n\nObject.defineProperty(EventEmitter, 'defaultMaxListeners', {\n enumerable: true,\n get: function() {\n return defaultMaxListeners;\n },\n set: function(arg) {\n if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {\n throw new RangeError('The value of \"defaultMaxListeners\" is out of range. It must be a non-negative number. Received ' + arg + '.');\n }\n defaultMaxListeners = arg;\n }\n});\n\nEventEmitter.init = function() {\n\n if (this._events === undefined ||\n this._events === Object.getPrototypeOf(this)._events) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n }\n\n this._maxListeners = this._maxListeners || undefined;\n};\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {\n if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {\n throw new RangeError('The value of \"n\" is out of range. It must be a non-negative number. Received ' + n + '.');\n }\n this._maxListeners = n;\n return this;\n};\n\nfunction _getMaxListeners(that) {\n if (that._maxListeners === undefined)\n return EventEmitter.defaultMaxListeners;\n return that._maxListeners;\n}\n\nEventEmitter.prototype.getMaxListeners = function getMaxListeners() {\n return _getMaxListeners(this);\n};\n\nEventEmitter.prototype.emit = function emit(type) {\n var args = [];\n for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);\n var doError = (type === 'error');\n\n var events = this._events;\n if (events !== undefined)\n doError = (doError && events.error === undefined);\n else if (!doError)\n return false;\n\n // If there is no 'error' event listener then throw.\n if (doError) {\n var er;\n if (args.length > 0)\n er = args[0];\n if (er instanceof Error) {\n // Note: The comments on the `throw` lines are intentional, they show\n // up in Node's output if this results in an unhandled exception.\n throw er; // Unhandled 'error' event\n }\n // At least give some kind of context to the user\n var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));\n err.context = er;\n throw err; // Unhandled 'error' event\n }\n\n var handler = events[type];\n\n if (handler === undefined)\n return false;\n\n if (typeof handler === 'function') {\n ReflectApply(handler, this, args);\n } else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n ReflectApply(listeners[i], this, args);\n }\n\n return true;\n};\n\nfunction _addListener(target, type, listener, prepend) {\n var m;\n var events;\n var existing;\n\n checkListener(listener);\n\n events = target._events;\n if (events === undefined) {\n events = target._events = Object.create(null);\n target._eventsCount = 0;\n } else {\n // To avoid recursion in the case that type === \"newListener\"! Before\n // adding it to the listeners, first emit \"newListener\".\n if (events.newListener !== undefined) {\n target.emit('newListener', type,\n listener.listener ? listener.listener : listener);\n\n // Re-assign `events` because a newListener handler could have caused the\n // this._events to be assigned to a new object\n events = target._events;\n }\n existing = events[type];\n }\n\n if (existing === undefined) {\n // Optimize the case of one listener. Don't need the extra array object.\n existing = events[type] = listener;\n ++target._eventsCount;\n } else {\n if (typeof existing === 'function') {\n // Adding the second element, need to change to array.\n existing = events[type] =\n prepend ? [listener, existing] : [existing, listener];\n // If we've already got an array, just append.\n } else if (prepend) {\n existing.unshift(listener);\n } else {\n existing.push(listener);\n }\n\n // Check for listener leak\n m = _getMaxListeners(target);\n if (m > 0 && existing.length > m && !existing.warned) {\n existing.warned = true;\n // No error code for this since it is a Warning\n // eslint-disable-next-line no-restricted-syntax\n var w = new Error('Possible EventEmitter memory leak detected. ' +\n existing.length + ' ' + String(type) + ' listeners ' +\n 'added. Use emitter.setMaxListeners() to ' +\n 'increase limit');\n w.name = 'MaxListenersExceededWarning';\n w.emitter = target;\n w.type = type;\n w.count = existing.length;\n ProcessEmitWarning(w);\n }\n }\n\n return target;\n}\n\nEventEmitter.prototype.addListener = function addListener(type, listener) {\n return _addListener(this, type, listener, false);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.prependListener =\n function prependListener(type, listener) {\n return _addListener(this, type, listener, true);\n };\n\nfunction onceWrapper() {\n if (!this.fired) {\n this.target.removeListener(this.type, this.wrapFn);\n this.fired = true;\n if (arguments.length === 0)\n return this.listener.call(this.target);\n return this.listener.apply(this.target, arguments);\n }\n}\n\nfunction _onceWrap(target, type, listener) {\n var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };\n var wrapped = onceWrapper.bind(state);\n wrapped.listener = listener;\n state.wrapFn = wrapped;\n return wrapped;\n}\n\nEventEmitter.prototype.once = function once(type, listener) {\n checkListener(listener);\n this.on(type, _onceWrap(this, type, listener));\n return this;\n};\n\nEventEmitter.prototype.prependOnceListener =\n function prependOnceListener(type, listener) {\n checkListener(listener);\n this.prependListener(type, _onceWrap(this, type, listener));\n return this;\n };\n\n// Emits a 'removeListener' event if and only if the listener was removed.\nEventEmitter.prototype.removeListener =\n function removeListener(type, listener) {\n var list, events, position, i, originalListener;\n\n checkListener(listener);\n\n events = this._events;\n if (events === undefined)\n return this;\n\n list = events[type];\n if (list === undefined)\n return this;\n\n if (list === listener || list.listener === listener) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else {\n delete events[type];\n if (events.removeListener)\n this.emit('removeListener', type, list.listener || listener);\n }\n } else if (typeof list !== 'function') {\n position = -1;\n\n for (i = list.length - 1; i >= 0; i--) {\n if (list[i] === listener || list[i].listener === listener) {\n originalListener = list[i].listener;\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (position === 0)\n list.shift();\n else {\n spliceOne(list, position);\n }\n\n if (list.length === 1)\n events[type] = list[0];\n\n if (events.removeListener !== undefined)\n this.emit('removeListener', type, originalListener || listener);\n }\n\n return this;\n };\n\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n\nEventEmitter.prototype.removeAllListeners =\n function removeAllListeners(type) {\n var listeners, events, i;\n\n events = this._events;\n if (events === undefined)\n return this;\n\n // not listening for removeListener, no need to emit\n if (events.removeListener === undefined) {\n if (arguments.length === 0) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n } else if (events[type] !== undefined) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else\n delete events[type];\n }\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n var keys = Object.keys(events);\n var key;\n for (i = 0; i < keys.length; ++i) {\n key = keys[i];\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = Object.create(null);\n this._eventsCount = 0;\n return this;\n }\n\n listeners = events[type];\n\n if (typeof listeners === 'function') {\n this.removeListener(type, listeners);\n } else if (listeners !== undefined) {\n // LIFO order\n for (i = listeners.length - 1; i >= 0; i--) {\n this.removeListener(type, listeners[i]);\n }\n }\n\n return this;\n };\n\nfunction _listeners(target, type, unwrap) {\n var events = target._events;\n\n if (events === undefined)\n return [];\n\n var evlistener = events[type];\n if (evlistener === undefined)\n return [];\n\n if (typeof evlistener === 'function')\n return unwrap ? [evlistener.listener || evlistener] : [evlistener];\n\n return unwrap ?\n unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);\n}\n\nEventEmitter.prototype.listeners = function listeners(type) {\n return _listeners(this, type, true);\n};\n\nEventEmitter.prototype.rawListeners = function rawListeners(type) {\n return _listeners(this, type, false);\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n if (typeof emitter.listenerCount === 'function') {\n return emitter.listenerCount(type);\n } else {\n return listenerCount.call(emitter, type);\n }\n};\n\nEventEmitter.prototype.listenerCount = listenerCount;\nfunction listenerCount(type) {\n var events = this._events;\n\n if (events !== undefined) {\n var evlistener = events[type];\n\n if (typeof evlistener === 'function') {\n return 1;\n } else if (evlistener !== undefined) {\n return evlistener.length;\n }\n }\n\n return 0;\n}\n\nEventEmitter.prototype.eventNames = function eventNames() {\n return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];\n};\n\nfunction arrayClone(arr, n) {\n var copy = new Array(n);\n for (var i = 0; i < n; ++i)\n copy[i] = arr[i];\n return copy;\n}\n\nfunction spliceOne(list, index) {\n for (; index + 1 < list.length; index++)\n list[index] = list[index + 1];\n list.pop();\n}\n\nfunction unwrapListeners(arr) {\n var ret = new Array(arr.length);\n for (var i = 0; i < ret.length; ++i) {\n ret[i] = arr[i].listener || arr[i];\n }\n return ret;\n}\n\nfunction once(emitter, name) {\n return new Promise(function (resolve, reject) {\n function errorListener(err) {\n emitter.removeListener(name, resolver);\n reject(err);\n }\n\n function resolver() {\n if (typeof emitter.removeListener === 'function') {\n emitter.removeListener('error', errorListener);\n }\n resolve([].slice.call(arguments));\n }\n eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });\n if (name !== 'error') {\n addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });\n }\n });\n}\n\nfunction addErrorHandlerIfEventEmitter(emitter, handler, flags) {\n if (typeof emitter.on === 'function') {\n eventTargetAgnosticAddListener(emitter, 'error', handler, flags);\n }\n}\n\nfunction eventTargetAgnosticAddListener(emitter, name, listener, flags) {\n if (typeof emitter.on === 'function') {\n if (flags.once) {\n emitter.once(name, listener);\n } else {\n emitter.on(name, listener);\n }\n } else if (typeof emitter.addEventListener === 'function') {\n // EventTarget does not have `error` event semantics like Node\n // EventEmitters, we do not listen for `error` events here.\n emitter.addEventListener(name, function wrapListener(arg) {\n // IE does not have builtin `{ once: true }` support so we\n // have to do it manually.\n if (flags.once) {\n emitter.removeEventListener(name, wrapListener);\n }\n listener(arg);\n });\n } else {\n throw new TypeError('The \"emitter\" argument must be of type EventEmitter. Received type ' + typeof emitter);\n }\n}\n\nvar eventsExports = events.exports;\nvar EventEmitter$1 = /*@__PURE__*/getDefaultExportFromCjs(eventsExports);\n\nvar errorCodes;\n(function (errorCodes) {\n errorCodes[errorCodes[\"timeout\"] = 1] = \"timeout\";\n errorCodes[errorCodes[\"transportClosed\"] = 2] = \"transportClosed\";\n errorCodes[errorCodes[\"clientDisconnected\"] = 3] = \"clientDisconnected\";\n errorCodes[errorCodes[\"clientClosed\"] = 4] = \"clientClosed\";\n errorCodes[errorCodes[\"clientConnectToken\"] = 5] = \"clientConnectToken\";\n errorCodes[errorCodes[\"clientRefreshToken\"] = 6] = \"clientRefreshToken\";\n errorCodes[errorCodes[\"subscriptionUnsubscribed\"] = 7] = \"subscriptionUnsubscribed\";\n errorCodes[errorCodes[\"subscriptionSubscribeToken\"] = 8] = \"subscriptionSubscribeToken\";\n errorCodes[errorCodes[\"subscriptionRefreshToken\"] = 9] = \"subscriptionRefreshToken\";\n errorCodes[errorCodes[\"transportWriteError\"] = 10] = \"transportWriteError\";\n errorCodes[errorCodes[\"connectionClosed\"] = 11] = \"connectionClosed\";\n errorCodes[errorCodes[\"badConfiguration\"] = 12] = \"badConfiguration\";\n})(errorCodes || (errorCodes = {}));\nvar connectingCodes;\n(function (connectingCodes) {\n connectingCodes[connectingCodes[\"connectCalled\"] = 0] = \"connectCalled\";\n connectingCodes[connectingCodes[\"transportClosed\"] = 1] = \"transportClosed\";\n connectingCodes[connectingCodes[\"noPing\"] = 2] = \"noPing\";\n connectingCodes[connectingCodes[\"subscribeTimeout\"] = 3] = \"subscribeTimeout\";\n connectingCodes[connectingCodes[\"unsubscribeError\"] = 4] = \"unsubscribeError\";\n})(connectingCodes || (connectingCodes = {}));\nvar disconnectedCodes;\n(function (disconnectedCodes) {\n disconnectedCodes[disconnectedCodes[\"disconnectCalled\"] = 0] = \"disconnectCalled\";\n disconnectedCodes[disconnectedCodes[\"unauthorized\"] = 1] = \"unauthorized\";\n disconnectedCodes[disconnectedCodes[\"badProtocol\"] = 2] = \"badProtocol\";\n disconnectedCodes[disconnectedCodes[\"messageSizeLimit\"] = 3] = \"messageSizeLimit\";\n})(disconnectedCodes || (disconnectedCodes = {}));\nvar subscribingCodes;\n(function (subscribingCodes) {\n subscribingCodes[subscribingCodes[\"subscribeCalled\"] = 0] = \"subscribeCalled\";\n subscribingCodes[subscribingCodes[\"transportClosed\"] = 1] = \"transportClosed\";\n})(subscribingCodes || (subscribingCodes = {}));\nvar unsubscribedCodes;\n(function (unsubscribedCodes) {\n unsubscribedCodes[unsubscribedCodes[\"unsubscribeCalled\"] = 0] = \"unsubscribeCalled\";\n unsubscribedCodes[unsubscribedCodes[\"unauthorized\"] = 1] = \"unauthorized\";\n unsubscribedCodes[unsubscribedCodes[\"clientClosed\"] = 2] = \"clientClosed\";\n})(unsubscribedCodes || (unsubscribedCodes = {}));\nvar subscriptionFlags;\n(function (subscriptionFlags) {\n subscriptionFlags[subscriptionFlags[\"channelCompaction\"] = 1] = \"channelCompaction\";\n})(subscriptionFlags || (subscriptionFlags = {}));\n\n/** State of client. */\nvar State;\n(function (State) {\n State[\"Disconnected\"] = \"disconnected\";\n State[\"Connecting\"] = \"connecting\";\n State[\"Connected\"] = \"connected\";\n})(State || (State = {}));\n/** State of Subscription */\nvar SubscriptionState;\n(function (SubscriptionState) {\n SubscriptionState[\"Unsubscribed\"] = \"unsubscribed\";\n SubscriptionState[\"Subscribing\"] = \"subscribing\";\n SubscriptionState[\"Subscribed\"] = \"subscribed\";\n})(SubscriptionState || (SubscriptionState = {}));\n\n/** @internal */\nfunction startsWith(value, prefix) {\n return value.lastIndexOf(prefix, 0) === 0;\n}\n/** @internal */\nfunction isFunction(value) {\n if (value === undefined || value === null) {\n return false;\n }\n return typeof value === 'function';\n}\n/** @internal */\nfunction log(level, args) {\n if (globalThis.console) {\n const logger = globalThis.console[level];\n if (isFunction(logger)) {\n logger.apply(globalThis.console, args);\n }\n }\n}\nfunction randomInt(min, max) {\n return Math.floor(Math.random() * (max - min + 1) + min);\n}\n/** @internal */\nfunction backoff(step, min, max) {\n // Full jitter technique, see:\n // https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/\n if (step > 31) {\n step = 31;\n }\n const interval = randomInt(0, Math.min(max, min * Math.pow(2, step)));\n return Math.min(max, min + interval);\n}\n/** @internal */\nfunction errorExists(data) {\n return 'error' in data && data.error !== null;\n}\n/** @internal */\nfunction ttlMilliseconds(ttl) {\n // https://stackoverflow.com/questions/12633405/what-is-the-maximum-delay-for-setinterval\n return Math.min(ttl * 1000, 2147483647);\n}\n\n/** Subscription to a channel */\nclass Subscription extends EventEmitter$1 {\n /** Subscription constructor should not be used directly, create subscriptions using Client method. */\n constructor(centrifuge, channel, options) {\n super();\n this._resubscribeTimeout = null;\n this._refreshTimeout = null;\n this.channel = channel;\n this.state = SubscriptionState.Unsubscribed;\n this._centrifuge = centrifuge;\n this._token = '';\n this._getToken = null;\n this._data = null;\n this._getData = null;\n this._recover = false;\n this._offset = null;\n this._epoch = null;\n this._id = 0;\n this._recoverable = false;\n this._positioned = false;\n this._joinLeave = false;\n this._minResubscribeDelay = 500;\n this._maxResubscribeDelay = 20000;\n this._resubscribeTimeout = null;\n this._resubscribeAttempts = 0;\n this._promises = {};\n this._promiseId = 0;\n this._inflight = false;\n this._refreshTimeout = null;\n this._delta = '';\n this._delta_negotiated = false;\n this._tagsFilter = null;\n this._prevValue = null;\n this._unsubPromise = Promise.resolve();\n this._setOptions(options);\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n if (this._centrifuge._debugEnabled) {\n this.on('state', (ctx) => {\n this._debug('subscription state', channel, ctx.oldState, '->', ctx.newState);\n });\n this.on('error', (ctx) => {\n this._debug('subscription error', channel, ctx);\n });\n }\n else {\n // Avoid unhandled exception in EventEmitter for non-set error handler.\n this.on('error', function () { Function.prototype(); });\n }\n }\n /** ready returns a Promise which resolves upon subscription goes to Subscribed\n * state and rejects in case of subscription goes to Unsubscribed state.\n * Optional timeout can be passed.*/\n ready(timeout) {\n if (this.state === SubscriptionState.Unsubscribed) {\n return Promise.reject({ code: errorCodes.subscriptionUnsubscribed, message: this.state });\n }\n if (this.state === SubscriptionState.Subscribed) {\n return Promise.resolve();\n }\n return new Promise((res, rej) => {\n const ctx = {\n resolve: res,\n reject: rej\n };\n if (timeout) {\n ctx.timeout = setTimeout(function () {\n rej({ code: errorCodes.timeout, message: 'timeout' });\n }, timeout);\n }\n this._promises[this._nextPromiseId()] = ctx;\n });\n }\n /** subscribe to a channel.*/\n subscribe() {\n if (this._isSubscribed()) {\n return;\n }\n this._resubscribeAttempts = 0;\n this._setSubscribing(subscribingCodes.subscribeCalled, 'subscribe called');\n }\n /** unsubscribe from a channel, keeping position state.*/\n unsubscribe() {\n this._unsubPromise = this._setUnsubscribed(unsubscribedCodes.unsubscribeCalled, 'unsubscribe called', true);\n }\n /** publish data to a channel.*/\n publish(data) {\n return __awaiter(this, void 0, void 0, function* () {\n yield this._methodCall();\n return this._centrifuge.publish(this.channel, data);\n });\n }\n /** get online presence for a channel.*/\n presence() {\n return __awaiter(this, void 0, void 0, function* () {\n yield this._methodCall();\n return this._centrifuge.presence(this.channel);\n });\n }\n /** presence stats for a channel (num clients and unique users).*/\n presenceStats() {\n return __awaiter(this, void 0, void 0, function* () {\n yield this._methodCall();\n return this._centrifuge.presenceStats(this.channel);\n });\n }\n /** history for a channel. By default it does not return publications (only current\n * StreamPosition data) – provide an explicit limit > 0 to load publications.*/\n history(opts) {\n return __awaiter(this, void 0, void 0, function* () {\n yield this._methodCall();\n return this._centrifuge.history(this.channel, opts);\n });\n }\n /**\n * Sets server-side tags filter for the subscription.\n * This only applies on the next subscription attempt, not the current one.\n * Cannot be used together with delta option.\n *\n * @param tagsFilter - Filter configuration object or null to remove filter\n * @throws {Error} If both delta and tagsFilter are configured\n *\n * @example\n * ```typescript\n * // Simple equality filter\n * sub.setTagsFilter({\n * key: 'ticker',\n * cmp: 'eq',\n * val: 'BTC'\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Complex filter with logical operators\n * sub.setTagsFilter({\n * op: 'and',\n * nodes: [\n * { key: 'ticker', cmp: 'eq', val: 'BTC' },\n * { key: 'price', cmp: 'gt', val: '50000' }\n * ]\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Filter with IN operator\n * sub.setTagsFilter({\n * key: 'ticker',\n * cmp: 'in',\n * vals: ['BTC', 'ETH', 'SOL']\n * });\n * ```\n */\n setTagsFilter(tagsFilter) {\n if (tagsFilter && this._delta) {\n throw new Error('cannot use delta and tagsFilter together');\n }\n this._tagsFilter = tagsFilter;\n }\n /** setData allows setting subscription data. This only applied on the next subscription attempt,\n * Note that if getData callback is configured, it will override this value during resubscriptions. */\n setData(data) {\n this._data = data;\n }\n _methodCall() {\n if (this._isSubscribed()) {\n return Promise.resolve();\n }\n if (this._isUnsubscribed()) {\n return Promise.reject({\n code: errorCodes.subscriptionUnsubscribed,\n message: this.state\n });\n }\n return new Promise((resolve, reject) => {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n const timeoutDuration = this._centrifuge._config.timeout;\n const timeout = setTimeout(() => {\n reject({ code: errorCodes.timeout, message: 'timeout' });\n }, timeoutDuration);\n this._promises[this._nextPromiseId()] = {\n timeout,\n resolve,\n reject\n };\n });\n }\n _nextPromiseId() {\n return ++this._promiseId;\n }\n _needRecover() {\n return this._recover === true;\n }\n _isUnsubscribed() {\n return this.state === SubscriptionState.Unsubscribed;\n }\n _isSubscribing() {\n return this.state === SubscriptionState.Subscribing;\n }\n _isSubscribed() {\n return this.state === SubscriptionState.Subscribed;\n }\n _setState(newState) {\n if (this.state !== newState) {\n const oldState = this.state;\n this.state = newState;\n this.emit('state', { newState, oldState, channel: this.channel });\n return true;\n }\n return false;\n }\n _usesToken() {\n return this._token !== '' || this._getToken !== null;\n }\n _clearSubscribingState() {\n this._resubscribeAttempts = 0;\n this._clearResubscribeTimeout();\n }\n _clearSubscribedState() {\n this._clearRefreshTimeout();\n }\n _setSubscribed(result) {\n if (!this._isSubscribing()) {\n return;\n }\n this._clearSubscribingState();\n if (result.id) {\n this._id = result.id;\n }\n if (result.recoverable) {\n this._recover = true;\n this._offset = result.offset || 0;\n this._epoch = result.epoch || '';\n }\n if (result.delta) {\n this._delta_negotiated = true;\n }\n else {\n this._delta_negotiated = false;\n }\n this._setState(SubscriptionState.Subscribed);\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n const ctx = this._centrifuge._getSubscribeContext(this.channel, result);\n this.emit('subscribed', ctx);\n this._resolvePromises();\n const pubs = result.publications;\n if (pubs && pubs.length > 0) {\n for (const i in pubs) {\n if (!pubs.hasOwnProperty(i)) {\n continue;\n }\n this._handlePublication(pubs[i]);\n }\n }\n if (result.expires === true) {\n this._refreshTimeout = setTimeout(() => this._refresh(), ttlMilliseconds(result.ttl));\n }\n }\n _setSubscribing(code, reason) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this._isSubscribing()) {\n return;\n }\n if (this._isSubscribed()) {\n this._clearSubscribedState();\n }\n if (this._setState(SubscriptionState.Subscribing)) {\n this.emit('subscribing', { channel: this.channel, code: code, reason: reason });\n }\n // @ts-ignore – for performance reasons only await _unsubPromise for emulution case where it's required.\n if (this._centrifuge._transport && this._centrifuge._transport.emulation()) {\n yield this._unsubPromise;\n }\n if (!this._isSubscribing()) {\n return;\n }\n this._subscribe();\n });\n }\n _subscribe() {\n this._debug('subscribing on', this.channel);\n if (!this._isTransportOpen()) {\n this._debug('delay subscribe on', this.channel, 'till connected');\n return null;\n }\n if (this._inflight) {\n return null;\n }\n this._inflight = true;\n if (this._canSubscribeWithoutGettingToken()) {\n return this._subscribeWithoutToken();\n }\n this._getSubscriptionToken()\n .then(token => this._handleTokenResponse(token))\n .catch(e => this._handleTokenError(e));\n return null;\n }\n _isTransportOpen() {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n return this._centrifuge._transportIsOpen;\n }\n _canSubscribeWithoutGettingToken() {\n return !this._usesToken() || !!this._token;\n }\n _subscribeWithoutToken() {\n if (this._getData) {\n this._getDataAndSubscribe(this._token);\n return null;\n }\n else {\n return this._sendSubscribe(this._token);\n }\n }\n _getDataAndSubscribe(token) {\n if (!this._getData) {\n this._inflight = false;\n return;\n }\n this._getData({ channel: this.channel })\n .then(data => {\n if (!this._isSubscribing()) {\n this._inflight = false;\n return;\n }\n this._data = data;\n this._sendSubscribe(token);\n })\n .catch(e => this._handleGetDataError(e));\n }\n _handleGetDataError(error) {\n if (!this._isSubscribing()) {\n this._inflight = false;\n return;\n }\n if (error instanceof UnauthorizedError) {\n this._inflight = false;\n this._failUnauthorized();\n return;\n }\n this.emit('error', {\n type: 'subscribeData',\n channel: this.channel,\n error: {\n code: errorCodes.badConfiguration,\n message: (error === null || error === void 0 ? void 0 : error.toString()) || ''\n }\n });\n this._inflight = false;\n this._scheduleResubscribe();\n }\n _handleTokenResponse(token) {\n if (!this._isSubscribing()) {\n this._inflight = false;\n return;\n }\n if (!token) {\n this._inflight = false;\n this._failUnauthorized();\n return;\n }\n this._token = token;\n if (this._getData) {\n this._getDataAndSubscribe(token);\n }\n else {\n this._sendSubscribe(token);\n }\n }\n _handleTokenError(error) {\n if (!this._isSubscribing()) {\n this._inflight = false;\n return;\n }\n if (error instanceof UnauthorizedError) {\n this._inflight = false;\n this._failUnauthorized();\n return;\n }\n this.emit('error', {\n type: 'subscribeToken',\n channel: this.channel,\n error: {\n code: errorCodes.subscriptionSubscribeToken,\n message: (error === null || error === void 0 ? void 0 : error.toString()) || ''\n }\n });\n this._inflight = false;\n this._scheduleResubscribe();\n }\n _sendSubscribe(token) {\n if (!this._isTransportOpen()) {\n this._inflight = false;\n return null;\n }\n const cmd = this._buildSubscribeCommand(token);\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n this._centrifuge._call(cmd).then(resolveCtx => {\n this._inflight = false;\n const result = resolveCtx.reply.subscribe;\n this._handleSubscribeResponse(result);\n if (resolveCtx.next) {\n resolveCtx.next();\n }\n }, rejectCtx => {\n this._inflight = false;\n this._handleSubscribeError(rejectCtx.error);\n if (rejectCtx.next) {\n rejectCtx.next();\n }\n });\n return cmd;\n }\n _buildSubscribeCommand(token) {\n const req = { channel: this.channel };\n if (token)\n req.token = token;\n if (this._data)\n req.data = this._data;\n if (this._positioned)\n req.positioned = true;\n if (this._recoverable)\n req.recoverable = true;\n if (this._joinLeave)\n req.join_leave = true;\n req.flag = subscriptionFlags.channelCompaction;\n if (this._needRecover()) {\n req.recover = true;\n const offset = this._getOffset();\n if (offset)\n req.offset = offset;\n const epoch = this._getEpoch();\n if (epoch)\n req.epoch = epoch;\n }\n if (this._delta)\n req.delta = this._delta;\n if (this._tagsFilter)\n req.tf = this._tagsFilter;\n return { subscribe: req };\n }\n _debug(...args) {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n this._centrifuge._debug(...args);\n }\n _handleSubscribeError(error) {\n if (!this._isSubscribing()) {\n return;\n }\n if (error.code === errorCodes.timeout) {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n this._centrifuge._disconnect(connectingCodes.subscribeTimeout, 'subscribe timeout', true);\n return;\n }\n this._subscribeError(error);\n }\n _handleSubscribeResponse(result) {\n if (!this._isSubscribing()) {\n return;\n }\n this._setSubscribed(result);\n }\n _setUnsubscribed(code, reason, sendUnsubscribe) {\n if (this._isUnsubscribed()) {\n return Promise.resolve();\n }\n let promise = Promise.resolve();\n if (this._isSubscribed()) {\n if (sendUnsubscribe) {\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n promise = this._centrifuge._unsubscribe(this);\n }\n this._clearSubscribedState();\n }\n else if (this._isSubscribing()) {\n if (this._inflight && sendUnsubscribe) {\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n promise = this._centrifuge._unsubscribe(this);\n }\n this._clearSubscribingState();\n }\n this._inflight = false;\n if (this._setState(SubscriptionState.Unsubscribed)) {\n this.emit('unsubscribed', { channel: this.channel, code: code, reason: reason });\n }\n this._rejectPromises({ code: errorCodes.subscriptionUnsubscribed, message: this.state });\n return promise;\n }\n _handlePublication(pub) {\n if (this._delta && this._delta_negotiated) {\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n const { newData, newPrevValue } = this._centrifuge._codec.applyDeltaIfNeeded(pub, this._prevValue);\n pub.data = newData;\n this._prevValue = newPrevValue;\n }\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n const ctx = this._centrifuge._getPublicationContext(this.channel, pub);\n this.emit('publication', ctx);\n if (pub.offset) {\n this._offset = pub.offset;\n }\n }\n _handleJoin(join) {\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n const info = this._centrifuge._getJoinLeaveContext(join.info);\n this.emit('join', { channel: this.channel, info: info });\n }\n _handleLeave(leave) {\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n const info = this._centrifuge._getJoinLeaveContext(leave.info);\n this.emit('leave', { channel: this.channel, info: info });\n }\n _resolvePromises() {\n for (const id in this._promises) {\n if (!this._promises.hasOwnProperty(id)) {\n continue;\n }\n if (this._promises[id].timeout) {\n clearTimeout(this._promises[id].timeout);\n }\n this._promises[id].resolve();\n delete this._promises[id];\n }\n }\n _rejectPromises(err) {\n for (const id in this._promises) {\n if (!this._promises.hasOwnProperty(id)) {\n continue;\n }\n if (this._promises[id].timeout) {\n clearTimeout(this._promises[id].timeout);\n }\n this._promises[id].reject(err);\n delete this._promises[id];\n }\n }\n _scheduleResubscribe() {\n if (!this._isSubscribing()) {\n this._debug('not in subscribing state, skip resubscribe scheduling', this.channel);\n return;\n }\n const self = this;\n const delay = this._getResubscribeDelay();\n this._resubscribeTimeout = setTimeout(function () {\n if (self._isSubscribing()) {\n self._subscribe();\n }\n }, delay);\n this._debug('resubscribe scheduled after ' + delay, this.channel);\n }\n _subscribeError(err) {\n if (!this._isSubscribing()) {\n return;\n }\n if (err.code < 100 || err.code === 109 || err.temporary === true) {\n if (err.code === 109) { // Token expired error.\n this._token = '';\n }\n const errContext = {\n channel: this.channel,\n type: 'subscribe',\n error: err\n };\n if (this._centrifuge.state === State.Connected) {\n this.emit('error', errContext);\n }\n this._scheduleResubscribe();\n }\n else {\n this._setUnsubscribed(err.code, err.message, false);\n }\n }\n _getResubscribeDelay() {\n const delay = backoff(this._resubscribeAttempts, this._minResubscribeDelay, this._maxResubscribeDelay);\n this._resubscribeAttempts++;\n return delay;\n }\n _setOptions(options) {\n if (!options) {\n return;\n }\n if (options.since) {\n this._offset = options.since.offset || 0;\n this._epoch = options.since.epoch || '';\n this._recover = true;\n }\n if (options.data) {\n this._data = options.data;\n }\n if (options.getData) {\n this._getData = options.getData;\n }\n if (options.minResubscribeDelay !== undefined) {\n this._minResubscribeDelay = options.minResubscribeDelay;\n }\n if (options.maxResubscribeDelay !== undefined) {\n this._maxResubscribeDelay = options.maxResubscribeDelay;\n }\n if (options.token) {\n this._token = options.token;\n }\n if (options.getToken) {\n this._getToken = options.getToken;\n }\n if (options.positioned === true) {\n this._positioned = true;\n }\n if (options.recoverable === true) {\n this._recoverable = true;\n }\n if (options.joinLeave === true) {\n this._joinLeave = true;\n }\n if (options.delta) {\n if (options.delta !== 'fossil') {\n throw new Error('unsupported delta format');\n }\n this._delta = options.delta;\n }\n if (options.tagsFilter) {\n this._tagsFilter = options.tagsFilter;\n }\n if (this._tagsFilter && this._delta) {\n throw new Error('cannot use delta and tagsFilter together');\n }\n }\n _getOffset() {\n const offset = this._offset;\n if (offset !== null) {\n return offset;\n }\n return 0;\n }\n _getEpoch() {\n const epoch = this._epoch;\n if (epoch !== null) {\n return epoch;\n }\n return '';\n }\n _clearRefreshTimeout() {\n if (this._refreshTimeout !== null) {\n clearTimeout(this._refreshTimeout);\n this._refreshTimeout = null;\n }\n }\n _clearResubscribeTimeout() {\n if (this._resubscribeTimeout !== null) {\n clearTimeout(this._resubscribeTimeout);\n this._resubscribeTimeout = null;\n }\n }\n _getSubscriptionToken() {\n this._debug('get subscription token for channel', this.channel);\n const ctx = {\n channel: this.channel\n };\n const getToken = this._getToken;\n if (getToken === null) {\n this.emit('error', {\n type: 'configuration',\n channel: this.channel,\n error: {\n code: errorCodes.badConfiguration,\n message: 'provide a function to get channel subscription token'\n }\n });\n return Promise.reject(new UnauthorizedError(''));\n }\n return getToken(ctx);\n }\n _refresh() {\n this._clearRefreshTimeout();\n const self = this;\n this._getSubscriptionToken().then(function (token) {\n if (!self._isSubscribed()) {\n return;\n }\n if (!token) {\n self._failUnauthorized();\n return;\n }\n self._token = token;\n const req = {\n channel: self.channel,\n token: token\n };\n const msg = {\n 'sub_refresh': req\n };\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n self._centrifuge._call(msg).then(resolveCtx => {\n const result = resolveCtx.reply.sub_refresh;\n self._refreshResponse(result);\n if (resolveCtx.next) {\n resolveCtx.next();\n }\n }, rejectCtx => {\n self._refreshError(rejectCtx.error);\n if (rejectCtx.next) {\n rejectCtx.next();\n }\n });\n }).catch(function (e) {\n if (e instanceof UnauthorizedError) {\n self._failUnauthorized();\n return;\n }\n self.emit('error', {\n type: 'refreshToken',\n channel: self.channel,\n error: {\n code: errorCodes.subscriptionRefreshToken,\n message: e !== undefined ? e.toString() : ''\n }\n });\n self._refreshTimeout = setTimeout(() => self._refresh(), self._getRefreshRetryDelay());\n });\n }\n _refreshResponse(result) {\n if (!this._isSubscribed()) {\n return;\n }\n this._debug('subscription token refreshed, channel', this.channel);\n this._clearRefreshTimeout();\n if (result.expires === true) {\n this._refreshTimeout = setTimeout(() => this._refresh(), ttlMilliseconds(result.ttl));\n }\n }\n _refreshError(err) {\n if (!this._isSubscribed()) {\n return;\n }\n if (err.code < 100 || err.temporary === true) {\n this.emit('error', {\n type: 'refresh',\n channel: this.channel,\n error: err\n });\n this._refreshTimeout = setTimeout(() => this._refresh(), this._getRefreshRetryDelay());\n }\n else {\n this._setUnsubscribed(err.code, err.message, true);\n }\n }\n _getRefreshRetryDelay() {\n return backoff(0, 10000, 20000);\n }\n _failUnauthorized() {\n this._setUnsubscribed(unsubscribedCodes.unauthorized, 'unauthorized', true);\n }\n}\n\n/** @internal */\nclass SockjsTransport {\n constructor(endpoint, options) {\n this.endpoint = endpoint;\n this.options = options;\n this._transport = null;\n }\n name() {\n return 'sockjs';\n }\n subName() {\n return 'sockjs-' + this._transport.transport;\n }\n emulation() {\n return false;\n }\n supported() {\n return this.options.sockjs !== null;\n }\n initialize(_protocol, callbacks) {\n this._transport = new this.options.sockjs(this.endpoint, null, this.options.sockjsOptions);\n this._transport.onopen = () => {\n callbacks.onOpen();\n };\n this._transport.onerror = e => {\n callbacks.onError(e);\n };\n this._transport.onclose = closeEvent => {\n callbacks.onClose(closeEvent);\n };\n this._transport.onmessage = event => {\n callbacks.onMessage(event.data);\n };\n }\n close() {\n this._transport.close();\n }\n send(data) {\n this._transport.send(data);\n }\n}\n\n/** @internal */\nclass WebsocketTransport {\n constructor(endpoint, options) {\n this.endpoint = endpoint;\n this.options = options;\n this._transport = null;\n }\n name() {\n return 'websocket';\n }\n subName() {\n return 'websocket';\n }\n emulation() {\n return false;\n }\n supported() {\n return this.options.websocket !== undefined && this.options.websocket !== null;\n }\n initialize(protocol, callbacks) {\n let subProtocol = '';\n if (protocol === 'protobuf') {\n subProtocol = 'centrifuge-protobuf';\n }\n if (subProtocol !== '') {\n this._transport = new this.options.websocket(this.endpoint, subProtocol);\n }\n else {\n this._transport = new this.options.websocket(this.endpoint);\n }\n if (protocol === 'protobuf') {\n this._transport.binaryType = 'arraybuffer';\n }\n this._transport.onopen = () => {\n callbacks.onOpen();\n };\n this._transport.onerror = e => {\n callbacks.onError(e);\n };\n this._transport.onclose = closeEvent => {\n callbacks.onClose(closeEvent);\n };\n this._transport.onmessage = event => {\n callbacks.onMessage(event.data);\n };\n }\n close() {\n this._transport.close();\n }\n send(data) {\n this._transport.send(data);\n }\n}\n\n/** @internal */\nclass HttpStreamTransport {\n constructor(endpoint, options) {\n this.endpoint = endpoint;\n this.options = options;\n this._abortController = null;\n this._utf8decoder = new TextDecoder();\n this._protocol = 'json';\n }\n name() {\n return 'http_stream';\n }\n subName() {\n return 'http_stream';\n }\n emulation() {\n return true;\n }\n _handleErrors(response) {\n if (!response.ok)\n throw new Error(response.status);\n return response;\n }\n _fetchEventTarget(self, endpoint, options) {\n const eventTarget = new EventTarget();\n // fetch with connection timeout maybe? https://github.com/github/fetch/issues/175\n const fetchFunc = self.options.fetch;\n fetchFunc(endpoint, options)\n .then(self._handleErrors)\n .then(response => {\n eventTarget.dispatchEvent(new Event('open'));\n let jsonStreamBuf = '';\n let jsonStreamPos = 0;\n let protoStreamBuf = new Uint8Array();\n const reader = response.body.getReader();\n return new self.options.readableStream({\n start(controller) {\n function pump() {\n return reader.read().then(({ done, value }) => {\n // When no more data needs to be consumed, close the stream\n if (done) {\n eventTarget.dispatchEvent(new Event('close'));\n controller.close();\n return;\n }\n try {\n if (self._protocol === 'json') {\n jsonStreamBuf += self._utf8decoder.decode(value);\n while (jsonStreamPos < jsonStreamBuf.length) {\n if (jsonStreamBuf[jsonStreamPos] === '\\n') {\n const line = jsonStreamBuf.substring(0, jsonStreamPos);\n eventTarget.dispatchEvent(new MessageEvent('message', { data: line }));\n jsonStreamBuf = jsonStreamBuf.substring(jsonStreamPos + 1);\n jsonStreamPos = 0;\n }\n else {\n ++jsonStreamPos;\n }\n }\n }\n else {\n const mergedArray = new Uint8Array(protoStreamBuf.length + value.length);\n mergedArray.set(protoStreamBuf);\n mergedArray.set(value, protoStreamBuf.length);\n protoStreamBuf = mergedArray;\n while (true) {\n const result = self.options.decoder.decodeReply(protoStreamBuf);\n if (result.ok) {\n const data = protoStreamBuf.slice(0, result.pos);\n eventTarget.dispatchEvent(new MessageEvent('message', { data: data }));\n protoStreamBuf = protoStreamBuf.slice(result.pos);\n continue;\n }\n break;\n }\n }\n }\n catch (error) {\n // @ts-ignore - improve later.\n eventTarget.dispatchEvent(new Event('error', { detail: error }));\n eventTarget.dispatchEvent(new Event('close'));\n controller.close();\n return;\n }\n pump();\n }).catch(function (e) {\n // @ts-ignore - improve later.\n eventTarget.dispatchEvent(new Event('error', { detail: e }));\n eventTarget.dispatchEvent(new Event('close'));\n controller.close();\n return;\n });\n }\n return pump();\n }\n });\n })\n .catch(error => {\n // @ts-ignore - improve later.\n eventTarget.dispatchEvent(new Event('error', { detail: error }));\n eventTarget.dispatchEvent(new Event('close'));\n });\n return eventTarget;\n }\n supported() {\n return this.options.fetch !== null &&\n this.options.readableStream !== null &&\n typeof TextDecoder !== 'undefined' &&\n typeof AbortController !== 'undefined' &&\n typeof EventTarget !== 'undefined' &&\n typeof Event !== 'undefined' &&\n typeof MessageEvent !== 'undefined' &&\n typeof Error !== 'undefined';\n }\n initialize(protocol, callbacks, initialData) {\n this._protocol = protocol;\n this._abortController = new AbortController();\n let headers;\n let body;\n if (protocol === 'json') {\n headers = {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json'\n };\n body = initialData;\n }\n else {\n headers = {\n 'Accept': 'application/octet-stream',\n 'Content-Type': 'application/octet-stream'\n };\n body = initialData;\n }\n const fetchOptions = {\n method: 'POST',\n headers: headers,\n body: body,\n mode: 'cors',\n credentials: 'same-origin',\n signal: this._abortController.signal\n };\n const eventTarget = this._fetchEventTarget(this, this.endpoint, fetchOptions);\n eventTarget.addEventListener('open', () => {\n callbacks.onOpen();\n });\n eventTarget.addEventListener('error', (e) => {\n this._abortController.abort();\n callbacks.onError(e);\n });\n eventTarget.addEventListener('close', () => {\n this._abortController.abort();\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n });\n eventTarget.addEventListener('message', (e) => {\n callbacks.onMessage(e.data);\n });\n }\n close() {\n this._abortController.abort();\n }\n send(data, session, node) {\n let headers;\n let body;\n const req = {\n session: session,\n node: node,\n data: data\n };\n if (this._protocol === 'json') {\n headers = {\n 'Content-Type': 'application/json'\n };\n body = JSON.stringify(req);\n }\n else {\n headers = {\n 'Content-Type': 'application/octet-stream'\n };\n body = this.options.encoder.encodeEmulationRequest(req);\n }\n const fetchFunc = this.options.fetch;\n const fetchOptions = {\n method: 'POST',\n headers: headers,\n body: body,\n mode: 'cors',\n credentials: 'same-origin',\n };\n fetchFunc(this.options.emulationEndpoint, fetchOptions);\n }\n}\n\n/** @internal */\nclass SseTransport {\n constructor(endpoint, options) {\n this.endpoint = endpoint;\n this.options = options;\n this._protocol = 'json';\n this._transport = null;\n this._onClose = null;\n }\n name() {\n return 'sse';\n }\n subName() {\n return 'sse';\n }\n emulation() {\n return true;\n }\n supported() {\n return this.options.eventsource !== null && this.options.fetch !== null;\n }\n initialize(_protocol, callbacks, initialData) {\n let url;\n if (globalThis && globalThis.document && globalThis.document.baseURI) {\n // Handle case when endpoint is relative, like //example.com/connection/sse\n url = new URL(this.endpoint, globalThis.document.baseURI);\n }\n else {\n url = new URL(this.endpoint);\n }\n url.searchParams.append('cf_connect', initialData);\n const eventsourceOptions = {};\n const eventSource = new this.options.eventsource(url.toString(), eventsourceOptions);\n this._transport = eventSource;\n const self = this;\n eventSource.onopen = function () {\n callbacks.onOpen();\n };\n eventSource.onerror = function (e) {\n eventSource.close();\n callbacks.onError(e);\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n };\n eventSource.onmessage = function (e) {\n callbacks.onMessage(e.data);\n };\n self._onClose = function () {\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n };\n }\n close() {\n this._transport.close();\n if (this._onClose !== null) {\n this._onClose();\n }\n }\n send(data, session, node) {\n const req = {\n session: session,\n node: node,\n data: data\n };\n const headers = {\n 'Content-Type': 'application/json'\n };\n const body = JSON.stringify(req);\n const fetchFunc = this.options.fetch;\n const fetchOptions = {\n method: 'POST',\n headers: headers,\n body: body,\n mode: 'cors',\n credentials: 'same-origin',\n };\n fetchFunc(this.options.emulationEndpoint, fetchOptions);\n }\n}\n\n/** @internal */\nclass WebtransportTransport {\n constructor(endpoint, options) {\n this.endpoint = endpoint;\n this.options = options;\n this._transport = null;\n this._stream = null;\n this._writer = null;\n this._utf8decoder = new TextDecoder();\n this._protocol = 'json';\n }\n name() {\n return 'webtransport';\n }\n subName() {\n return 'webtransport';\n }\n emulation() {\n return false;\n }\n supported() {\n return this.options.webtransport !== undefined && this.options.webtransport !== null;\n }\n initialize(protocol, callbacks) {\n return __awaiter(this, void 0, void 0, function* () {\n let url;\n if (globalThis && globalThis.document && globalThis.document.baseURI) {\n // Handle case when endpoint is relative, like //example.com/connection/webtransport\n url = new URL(this.endpoint, globalThis.document.baseURI);\n }\n else {\n url = new URL(this.endpoint);\n }\n if (protocol === 'protobuf') {\n url.searchParams.append('cf_protocol', 'protobuf');\n }\n this._protocol = protocol;\n const eventTarget = new EventTarget();\n this._transport = new this.options.webtransport(url.toString());\n this._transport.closed.then(() => {\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n }).catch(() => {\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n });\n try {\n yield this._transport.ready;\n }\n catch (_a) {\n this.close();\n return;\n }\n let stream;\n try {\n stream = yield this._transport.createBidirectionalStream();\n }\n catch (_b) {\n this.close();\n return;\n }\n this._stream = stream;\n this._writer = this._stream.writable.getWriter();\n eventTarget.addEventListener('close', () => {\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n });\n eventTarget.addEventListener('message', (e) => {\n callbacks.onMessage(e.data);\n });\n this._startReading(eventTarget);\n callbacks.onOpen();\n });\n }\n _startReading(eventTarget) {\n return __awaiter(this, void 0, void 0, function* () {\n const reader = this._stream.readable.getReader();\n let jsonStreamBuf = '';\n let jsonStreamPos = 0;\n let protoStreamBuf = new Uint8Array();\n try {\n while (true) {\n const { done, value } = yield reader.read();\n if (value.length > 0) {\n if (this._protocol === 'json') {\n jsonStreamBuf += this._utf8decoder.decode(value);\n while (jsonStreamPos < jsonStreamBuf.length) {\n if (jsonStreamBuf[jsonStreamPos] === '\\n') {\n const line = jsonStreamBuf.substring(0, jsonStreamPos);\n eventTarget.dispatchEvent(new MessageEvent('message', { data: line }));\n jsonStreamBuf = jsonStreamBuf.substring(jsonStreamPos + 1);\n jsonStreamPos = 0;\n }\n else {\n ++jsonStreamPos;\n }\n }\n }\n else {\n const mergedArray = new Uint8Array(protoStreamBuf.length + value.length);\n mergedArray.set(protoStreamBuf);\n mergedArray.set(value, protoStreamBuf.length);\n protoStreamBuf = mergedArray;\n while (true) {\n const result = this.options.decoder.decodeReply(protoStreamBuf);\n if (result.ok) {\n const data = protoStreamBuf.slice(0, result.pos);\n eventTarget.dispatchEvent(new MessageEvent('message', { data: data }));\n protoStreamBuf = protoStreamBuf.slice(result.pos);\n continue;\n }\n break;\n }\n }\n }\n if (done) {\n break;\n }\n }\n }\n catch (_a) {\n eventTarget.dispatchEvent(new Event('close'));\n }\n });\n }\n close() {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n if (this._writer) {\n yield this._writer.close();\n }\n this._transport.close();\n }\n catch (e) {\n // already closed.\n }\n });\n }\n send(data) {\n return __awaiter(this, void 0, void 0, function* () {\n let binary;\n if (this._protocol === 'json') {\n // Need extra \\n since WT is non-frame protocol. \n binary = new TextEncoder().encode(data + '\\n');\n }\n else {\n binary = data;\n }\n try {\n yield this._writer.write(binary);\n }\n catch (e) {\n this.close();\n }\n });\n }\n}\n\n/*\nCopyright 2014-2024 Dmitry Chestnykh (JavaScript port)\nCopyright 2007 D. Richard Hipp (original C version)\n\nFossil SCM delta compression algorithm, this is only the applyDelta part extracted\nfrom https://github.com/dchest/fossil-delta-js. The code was slightly modified\nto strip unnecessary parts. The copyright on top of this file is from the original\nrepo on Github licensed under Simplified BSD License.\n*/\nconst zValue = [\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1,\n -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,\n 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36, -1, 37,\n 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,\n 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1,\n];\n// Reader reads bytes, chars, ints from array.\nclass Reader {\n constructor(array) {\n this.a = array; // source array\n this.pos = 0; // current position in array\n }\n haveBytes() {\n return this.pos < this.a.length;\n }\n getByte() {\n const b = this.a[this.pos];\n this.pos++;\n if (this.pos > this.a.length)\n throw new RangeError(\"out of bounds\");\n return b;\n }\n getChar() {\n return String.fromCharCode(this.getByte());\n }\n // Read base64-encoded unsigned integer.\n getInt() {\n let v = 0;\n let c;\n while (this.haveBytes() && (c = zValue[0x7f & this.getByte()]) >= 0) {\n v = (v << 6) + c;\n }\n this.pos--;\n return v >>> 0;\n }\n}\n// Write writes an array.\nclass Writer {\n constructor() {\n this.a = [];\n }\n toByteArray(sourceType) {\n if (Array.isArray(sourceType)) {\n return this.a;\n }\n return new Uint8Array(this.a);\n }\n // Copy from array at start to end.\n putArray(a, start, end) {\n // TODO: optimize.\n for (let i = start; i < end; i++)\n this.a.push(a[i]);\n }\n}\n// Return a 32-bit checksum of the array.\nfunction checksum(arr) {\n let sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, z = 0, N = arr.length;\n //TODO measure if this unrolling is helpful.\n while (N >= 16) {\n sum0 = (sum0 + arr[z + 0]) | 0;\n sum1 = (sum1 + arr[z + 1]) | 0;\n sum2 = (sum2 + arr[z + 2]) | 0;\n sum3 = (sum3 + arr[z + 3]) | 0;\n sum0 = (sum0 + arr[z + 4]) | 0;\n sum1 = (sum1 + arr[z + 5]) | 0;\n sum2 = (sum2 + arr[z + 6]) | 0;\n sum3 = (sum3 + arr[z + 7]) | 0;\n sum0 = (sum0 + arr[z + 8]) | 0;\n sum1 = (sum1 + arr[z + 9]) | 0;\n sum2 = (sum2 + arr[z + 10]) | 0;\n sum3 = (sum3 + arr[z + 11]) | 0;\n sum0 = (sum0 + arr[z + 12]) | 0;\n sum1 = (sum1 + arr[z + 13]) | 0;\n sum2 = (sum2 + arr[z + 14]) | 0;\n sum3 = (sum3 + arr[z + 15]) | 0;\n z += 16;\n N -= 16;\n }\n while (N >= 4) {\n sum0 = (sum0 + arr[z + 0]) | 0;\n sum1 = (sum1 + arr[z + 1]) | 0;\n sum2 = (sum2 + arr[z + 2]) | 0;\n sum3 = (sum3 + arr[z + 3]) | 0;\n z += 4;\n N -= 4;\n }\n sum3 = (((((sum3 + (sum2 << 8)) | 0) + (sum1 << 16)) | 0) + (sum0 << 24)) | 0;\n switch (N) {\n //@ts-ignore fallthrough is needed.\n case 3:\n sum3 = (sum3 + (arr[z + 2] << 8)) | 0; /* falls through */\n //@ts-ignore fallthrough is needed.\n case 2:\n sum3 = (sum3 + (arr[z + 1] << 16)) | 0; /* falls through */\n case 1:\n sum3 = (sum3 + (arr[z + 0] << 24)) | 0; /* falls through */\n }\n return sum3 >>> 0;\n}\n/**\n * Apply a delta byte array to a source byte array, returning the target byte array.\n */\nfunction applyDelta(source, delta) {\n let total = 0;\n const zDelta = new Reader(delta);\n const lenSrc = source.length;\n const lenDelta = delta.length;\n const limit = zDelta.getInt();\n if (zDelta.getChar() !== \"\\n\")\n throw new Error(\"size integer not terminated by '\\\\n'\");\n const zOut = new Writer();\n while (zDelta.haveBytes()) {\n const cnt = zDelta.getInt();\n let ofst;\n switch (zDelta.getChar()) {\n case \"@\":\n ofst = zDelta.getInt();\n if (zDelta.haveBytes() && zDelta.getChar() !== \",\")\n throw new Error(\"copy command not terminated by ','\");\n total += cnt;\n if (total > limit)\n throw new Error(\"copy exceeds output file size\");\n if (ofst + cnt > lenSrc)\n throw new Error(\"copy extends past end of input\");\n zOut.putArray(source, ofst, ofst + cnt);\n break;\n case \":\":\n total += cnt;\n if (total > limit)\n throw new Error(\"insert command gives an output larger than predicted\");\n if (cnt > lenDelta)\n throw new Error(\"insert count exceeds size of delta\");\n zOut.putArray(zDelta.a, zDelta.pos, zDelta.pos + cnt);\n zDelta.pos += cnt;\n break;\n case \";\":\n {\n const out = zOut.toByteArray(source);\n if (cnt !== checksum(out))\n throw new Error(\"bad checksum\");\n if (total !== limit)\n throw new Error(\"generated size does not match predicted size\");\n return out;\n }\n default:\n throw new Error(\"unknown delta operator\");\n }\n }\n throw new Error(\"unterminated delta\");\n}\n\n/** @internal */\nclass JsonCodec {\n name() {\n return 'json';\n }\n encodeCommands(commands) {\n return commands.map(c => JSON.stringify(c)).join('\\n');\n }\n decodeReplies(data) {\n return data.trim().split('\\n').map(r => JSON.parse(r));\n }\n applyDeltaIfNeeded(pub, prevValue) {\n let newData, newPrevValue;\n if (pub.delta) {\n // JSON string delta.\n const valueArray = applyDelta(prevValue, new TextEncoder().encode(pub.data));\n newData = JSON.parse(new TextDecoder().decode(valueArray));\n newPrevValue = valueArray;\n }\n else {\n // Full data as JSON string.\n newData = JSON.parse(pub.data);\n newPrevValue = new TextEncoder().encode(pub.data);\n }\n return { newData, newPrevValue };\n }\n}\n\nconst defaults = {\n headers: {},\n token: '',\n getToken: null,\n data: null,\n getData: null,\n debug: false,\n name: 'js',\n version: '',\n fetch: null,\n readableStream: null,\n websocket: null,\n eventsource: null,\n sockjs: null,\n sockjsOptions: {},\n emulationEndpoint: '/emulation',\n minReconnectDelay: 500,\n maxReconnectDelay: 20000,\n timeout: 5000,\n maxServerPingDelay: 10000,\n networkEventTarget: null,\n};\nclass UnauthorizedError extends Error {\n constructor(message) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n/** Centrifuge is a Centrifuge/Centrifugo bidirectional client. */\nclass Centrifuge extends EventEmitter$1 {\n /** Constructs Centrifuge client. Call connect() method to start connecting. */\n constructor(endpoint, options) {\n super();\n this._reconnectTimeout = null;\n this._refreshTimeout = null;\n this._serverPingTimeout = null;\n this.state = State.Disconnected;\n this._transportIsOpen = false;\n this._endpoint = endpoint;\n this._emulation = false;\n this._transports = [];\n this._currentTransportIndex = 0;\n this._triedAllTransports = false;\n this._transportWasOpen = false;\n this._transport = null;\n this._transportId = 0;\n this._deviceWentOffline = false;\n this._transportClosed = true;\n this._codec = new JsonCodec();\n this._reconnecting = false;\n this._reconnectTimeout = null;\n this._reconnectAttempts = 0;\n this._client = null;\n this._session = '';\n this._node = '';\n this._subs = {};\n this._serverSubs = {};\n this._commandId = 0;\n this._commands = [];\n this._batching = false;\n this._refreshRequired = false;\n this._refreshTimeout = null;\n this._callbacks = {};\n this._token = '';\n this._data = null;\n this._dispatchPromise = Promise.resolve();\n this._serverPing = 0;\n this._serverPingTimeout = null;\n this._sendPong = false;\n this._promises = {};\n this._promiseId = 0;\n this._debugEnabled = false;\n this._networkEventsSet = false;\n this._config = Object.assign(Object.assign({}, defaults), options);\n this._configure();\n if (this._debugEnabled) {\n this.on('state', (ctx) => {\n this._debug('client state', ctx.oldState, '->', ctx.newState);\n });\n this.on('error', (ctx) => {\n this._debug('client error', ctx);\n });\n }\n else {\n // Avoid unhandled exception in EventEmitter for non-set error handler.\n this.on('error', function () { Function.prototype(); });\n }\n }\n /** newSubscription allocates new Subscription to a channel. Since server only allows\n * one subscription per channel per client this method throws if client already has\n * channel subscription in internal registry.\n * */\n newSubscription(channel, options) {\n if (this.getSubscription(channel) !== null) {\n throw new Error('Subscription to the channel ' + channel + ' already exists');\n }\n const sub = new Subscription(this, channel, options);\n this._subs[channel] = sub;\n return sub;\n }\n /** getSubscription returns Subscription if it's registered in the internal\n * registry or null. */\n getSubscription(channel) {\n return this._getSub(channel);\n }\n /** removeSubscription allows removing Subcription from the internal registry. */\n removeSubscription(sub) {\n if (!sub) {\n return;\n }\n if (sub.state !== SubscriptionState.Unsubscribed) {\n sub.unsubscribe();\n }\n this._removeSubscription(sub);\n }\n /** Get a map with all current client-side subscriptions. */\n subscriptions() {\n return this._subs;\n }\n /** ready returns a Promise which resolves upon client goes to Connected\n * state and rejects in case of client goes to Disconnected or Failed state.\n * Users can provide optional timeout in milliseconds. */\n ready(timeout) {\n return __awaiter(this, void 0, void 0, function* () {\n switch (this.state) {\n case State.Disconnected:\n throw { code: errorCodes.clientDisconnected, message: 'client disconnected' };\n case State.Connected:\n return;\n default:\n return new Promise((resolve, reject) => {\n const ctx = { resolve, reject };\n if (timeout) {\n ctx.timeout = setTimeout(() => {\n reject({ code: errorCodes.timeout, message: 'timeout' });\n }, timeout);\n }\n this._promises[this._nextPromiseId()] = ctx;\n });\n }\n });\n }\n /** connect to a server. */\n connect() {\n if (this._isConnected()) {\n this._debug('connect called when already connected');\n return;\n }\n if (this._isConnecting()) {\n this._debug('connect called when already connecting');\n return;\n }\n this._debug('connect called');\n this._reconnectAttempts = 0;\n this._startConnecting();\n }\n /** disconnect from a server. */\n disconnect() {\n this._disconnect(disconnectedCodes.disconnectCalled, 'disconnect called', false);\n }\n /** setToken allows setting connection token. Or resetting used token to be empty. */\n setToken(token) {\n this._token = token;\n }\n /** setData allows setting connection data. This only affects the next connection attempt,\n * not the current one. Note that if getData callback is configured, it will override\n * this value during reconnects. */\n setData(data) {\n this._data = data;\n }\n /** setHeaders allows setting connection emulated headers. */\n setHeaders(headers) {\n this._config.headers = headers;\n }\n /** send asynchronous data to a server (without any response from a server\n * expected, see rpc method if you need response). */\n send(data) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n send: {\n data\n }\n };\n yield this._methodCall();\n const sent = this._transportSendCommands([cmd]); // can send message to server without id set\n if (!sent) {\n throw this._createErrorObject(errorCodes.transportWriteError, 'transport write error');\n }\n });\n }\n /** rpc to a server - i.e. a call which waits for a response with data. */\n rpc(method, data) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n rpc: {\n method,\n data\n }\n };\n yield this._methodCall();\n const result = yield this._callPromise(cmd, (reply) => reply.rpc);\n return {\n data: result.data\n };\n });\n }\n /** publish data to a channel. */\n publish(channel, data) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n publish: {\n channel,\n data\n }\n };\n yield this._methodCall();\n yield this._callPromise(cmd, () => ({}));\n return {};\n });\n }\n /** history for a channel. By default it does not return publications (only current\n * StreamPosition data) – provide an explicit limit > 0 to load publications.*/\n history(channel, options) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n history: this._getHistoryRequest(channel, options)\n };\n yield this._methodCall();\n const result = yield this._callPromise(cmd, (reply) => reply.history);\n const publications = [];\n if (result.publications) {\n for (let i = 0; i < result.publications.length; i++) {\n publications.push(this._getPublicationContext(channel, result.publications[i]));\n }\n }\n return {\n publications,\n epoch: result.epoch || '',\n offset: result.offset || 0\n };\n });\n }\n /** presence for a channel. */\n presence(channel) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n presence: {\n channel\n }\n };\n yield this._methodCall();\n const result = yield this._callPromise(cmd, (reply) => reply.presence);\n const clients = result.presence;\n for (const clientId in clients) {\n if (Object.prototype.hasOwnProperty.call(clients, clientId)) {\n const rawClient = clients[clientId];\n const connInfo = rawClient['conn_info'];\n const chanInfo = rawClient['chan_info'];\n if (connInfo) {\n rawClient.connInfo = connInfo;\n }\n if (chanInfo) {\n rawClient.chanInfo = chanInfo;\n }\n }\n }\n return { clients };\n });\n }\n presenceStats(channel) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n 'presence_stats': {\n channel\n }\n };\n yield this._methodCall();\n const result = yield this._callPromise(cmd, (reply) => {\n return reply.presence_stats;\n });\n return {\n numUsers: result.num_users,\n numClients: result.num_clients\n };\n });\n }\n /** start command batching (collect into temporary buffer without sending to a server)\n * until stopBatching called.*/\n startBatching() {\n // start collecting messages without sending them to Centrifuge until flush\n // method called\n this._batching = true;\n }\n /** stop batching commands and flush collected commands to the\n * network (all in one request/frame).*/\n stopBatching() {\n const self = this;\n // Why so nested? Two levels here requred to deal with promise resolving queue.\n // In Subscription case we wait 2 futures before sending data to connection.\n // Otherwise _batching becomes false before batching decision has a chance to be executed.\n Promise.resolve().then(function () {\n Promise.resolve().then(function () {\n self._batching = false;\n self._flush();\n });\n });\n }\n _debug(...args) {\n if (!this._debugEnabled) {\n return;\n }\n log('debug', args);\n }\n _codecName() {\n return this._codec.name();\n }\n /** @internal */\n _formatOverride() {\n return;\n }\n _configure() {\n if (!('Promise' in globalThis)) {\n throw new Error('Promise polyfill required');\n }\n if (!this._endpoint) {\n throw new Error('endpoint configuration required');\n }\n if (this._config.token !== null) {\n this._token = this._config.token;\n }\n if (this._config.data !== null) {\n this._data = this._config.data;\n }\n this._codec = new JsonCodec();\n this._formatOverride();\n if (this._config.debug === true ||\n (typeof localStorage !== 'undefined' && typeof localStorage.getItem === 'function' && localStorage.getItem('centrifuge.debug'))) {\n this._debugEnabled = true;\n }\n this._debug('config', this._config);\n if (typeof this._endpoint === 'string') ;\n else if (Array.isArray(this._endpoint)) {\n this._transports = this._endpoint;\n this._emulation = true;\n for (const i in this._transports) {\n if (this._transports.hasOwnProperty(i)) {\n const transportConfig = this._transports[i];\n if (!transportConfig.endpoint || !transportConfig.transport) {\n throw new Error('malformed transport configuration');\n }\n const transportName = transportConfig.transport;\n if (['websocket', 'http_stream', 'sse', 'sockjs', 'webtransport'].indexOf(transportName) < 0) {\n throw new Error('unsupported transport name: ' + transportName);\n }\n }\n }\n }\n else {\n throw new Error('unsupported url configuration type: only string or array of objects are supported');\n }\n }\n _setState(newState) {\n if (this.state !== newState) {\n this._reconnecting = false;\n const oldState = this.state;\n this.state = newState;\n this.emit('state', { newState, oldState });\n return true;\n }\n return false;\n }\n _isDisconnected() {\n return this.state === State.Disconnected;\n }\n _isConnecting() {\n return this.state === State.Connecting;\n }\n _isConnected() {\n return this.state === State.Connected;\n }\n _nextCommandId() {\n return ++this._commandId;\n }\n _setNetworkEvents() {\n if (this._networkEventsSet) {\n return;\n }\n let eventTarget = null;\n if (this._config.networkEventTarget !== null) {\n eventTarget = this._config.networkEventTarget;\n }\n else if (typeof globalThis.addEventListener !== 'undefined') {\n eventTarget = globalThis;\n }\n if (eventTarget) {\n eventTarget.addEventListener('offline', () => {\n this._debug('offline event triggered');\n if (this.state === State.Connected || this.state === State.Connecting) {\n this._disconnect(connectingCodes.transportClosed, 'transport closed', true);\n this._deviceWentOffline = true;\n }\n });\n eventTarget.addEventListener('online', () => {\n this._debug('online event triggered');\n if (this.state !== State.Connecting) {\n return;\n }\n if (this._deviceWentOffline && !this._transportClosed) {\n // This is a workaround for mobile Safari where close callback may be\n // not issued upon device going to the flight mode. We know for sure\n // that transport close was called, so we start reconnecting. In this\n // case if the close callback will be issued for some reason after some\n // time – it will be ignored due to transport ID mismatch.\n this._deviceWentOffline = false;\n this._transportClosed = true;\n }\n this._clearReconnectTimeout();\n this._startReconnecting();\n });\n this._networkEventsSet = true;\n }\n }\n _getReconnectDelay() {\n const delay = backoff(this._reconnectAttempts, this._config.minReconnectDelay, this._config.maxReconnectDelay);\n this._reconnectAttempts += 1;\n return delay;\n }\n _clearOutgoingRequests() {\n // fire errbacks of registered outgoing calls.\n for (const id in this._callbacks) {\n if (this._callbacks.hasOwnProperty(id)) {\n const callbacks = this._callbacks[id];\n clearTimeout(callbacks.timeout);\n const errback = callbacks.errback;\n if (!errback) {\n continue;\n }\n errback({ error: this._createErrorObject(errorCodes.connectionClosed, 'connection closed') });\n }\n }\n this._callbacks = {};\n }\n _clearConnectedState() {\n this._client = null;\n this._clearServerPingTimeout();\n this._clearRefreshTimeout();\n // fire events for client-side subscriptions.\n for (const channel in this._subs) {\n if (!this._subs.hasOwnProperty(channel)) {\n continue;\n }\n const sub = this._subs[channel];\n if (sub.state === SubscriptionState.Subscribed) {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._setSubscribing(subscribingCodes.transportClosed, 'transport closed');\n }\n }\n // fire events for server-side subscriptions.\n for (const channel in this._serverSubs) {\n if (this._serverSubs.hasOwnProperty(channel)) {\n this.emit('subscribing', { channel: channel });\n }\n }\n }\n _handleWriteError(commands) {\n for (const command of commands) {\n const id = command.id;\n if (!(id in this._callbacks)) {\n continue;\n }\n const callbacks = this._callbacks[id];\n clearTimeout(this._callbacks[id].timeout);\n delete this._callbacks[id];\n const errback = callbacks.errback;\n errback({ error: this._createErrorObject(errorCodes.transportWriteError, 'transport write error') });\n }\n }\n _transportSendCommands(commands) {\n if (!commands.length) {\n return true;\n }\n if (!this._transport) {\n return false;\n }\n try {\n this._transport.send(this._codec.encodeCommands(commands), this._session, this._node);\n }\n catch (e) {\n this._debug('error writing commands', e);\n this._handleWriteError(commands);\n return false;\n }\n return true;\n }\n _initializeTransport() {\n let websocket;\n if (this._config.websocket !== null) {\n websocket = this._config.websocket;\n }\n else {\n if (!(typeof globalThis.WebSocket !== 'function' && typeof globalThis.WebSocket !== 'object')) {\n websocket = globalThis.WebSocket;\n }\n }\n let sockjs = null;\n if (this._config.sockjs !== null) {\n sockjs = this._config.sockjs;\n }\n else {\n if (typeof globalThis.SockJS !== 'undefined') {\n sockjs = globalThis.SockJS;\n }\n }\n let eventsource = null;\n if (this._config.eventsource !== null) {\n eventsource = this._config.eventsource;\n }\n else {\n if (typeof globalThis.EventSource !== 'undefined') {\n eventsource = globalThis.EventSource;\n }\n }\n let fetchFunc = null;\n if (this._config.fetch !== null) {\n fetchFunc = this._config.fetch;\n }\n else {\n if (typeof globalThis.fetch !== 'undefined') {\n fetchFunc = globalThis.fetch;\n }\n }\n let readableStream = null;\n if (this._config.readableStream !== null) {\n readableStream = this._config.readableStream;\n }\n else {\n if (typeof globalThis.ReadableStream !== 'undefined') {\n readableStream = globalThis.ReadableStream;\n }\n }\n if (!this._emulation) {\n if (startsWith(this._endpoint, 'http')) {\n throw new Error('Provide explicit transport endpoints configuration in case of using HTTP (i.e. using array of TransportEndpoint instead of a single string), or use ws(s):// scheme in an endpoint if you aimed using WebSocket transport');\n }\n else {\n this._debug('client will use websocket');\n this._transport = new WebsocketTransport(this._endpoint, {\n websocket: websocket\n });\n if (!this._transport.supported()) {\n throw new Error('WebSocket constructor not found, make sure it is available globally or passed as a dependency in Centrifuge options');\n }\n }\n }\n else {\n if (this._currentTransportIndex >= this._transports.length) {\n this._triedAllTransports = true;\n this._currentTransportIndex = 0;\n }\n let count = 0;\n while (true) {\n if (count >= this._transports.length) {\n throw new Error('no supported transport found');\n }\n const transportConfig = this._transports[this._currentTransportIndex];\n const transportName = transportConfig.transport;\n const transportEndpoint = transportConfig.endpoint;\n if (transportName === 'websocket') {\n this._debug('trying websocket transport');\n this._transport = new WebsocketTransport(transportEndpoint, {\n websocket: websocket\n });\n if (!this._transport.supported()) {\n this._debug('websocket transport not available');\n this._currentTransportIndex++;\n count++;\n continue;\n }\n }\n else if (transportName === 'webtransport') {\n this._debug('trying webtransport transport');\n this._transport = new WebtransportTransport(transportEndpoint, {\n webtransport: globalThis.WebTransport,\n decoder: this._codec,\n encoder: this._codec\n });\n if (!this._transport.supported()) {\n this._debug('webtransport transport not available');\n this._currentTransportIndex++;\n count++;\n continue;\n }\n }\n else if (transportName === 'http_stream') {\n this._debug('trying http_stream transport');\n this._transport = new HttpStreamTransport(transportEndpoint, {\n fetch: fetchFunc,\n readableStream: readableStream,\n emulationEndpoint: this._config.emulationEndpoint,\n decoder: this._codec,\n encoder: this._codec\n });\n if (!this._transport.supported()) {\n this._debug('http_stream transport not available');\n this._currentTransportIndex++;\n count++;\n continue;\n }\n }\n else if (transportName === 'sse') {\n this._debug('trying sse transport');\n this._transport = new SseTransport(transportEndpoint, {\n eventsource: eventsource,\n fetch: fetchFunc,\n emulationEndpoint: this._config.emulationEndpoint,\n });\n if (!this._transport.supported()) {\n this._debug('sse transport not available');\n this._currentTransportIndex++;\n count++;\n continue;\n }\n }\n else if (transportName === 'sockjs') {\n this._debug('trying sockjs');\n this._transport = new SockjsTransport(transportEndpoint, {\n sockjs: sockjs,\n sockjsOptions: this._config.sockjsOptions\n });\n if (!this._transport.supported()) {\n this._debug('sockjs transport not available');\n this._currentTransportIndex++;\n count++;\n continue;\n }\n }\n else {\n throw new Error('unknown transport ' + transportName);\n }\n break;\n }\n }\n const self = this;\n const transport = this._transport;\n const transportId = this._nextTransportId();\n self._debug(\"id of transport\", transportId);\n let wasOpen = false;\n const initialCommands = [];\n if (this._transport.emulation()) {\n const connectCommand = self._sendConnect(true);\n initialCommands.push(connectCommand);\n }\n this._setNetworkEvents();\n const initialData = this._codec.encodeCommands(initialCommands);\n this._transportClosed = false;\n let connectTimeout;\n connectTimeout = setTimeout(function () {\n transport.close();\n }, this._config.timeout);\n this._transport.initialize(this._codecName(), {\n onOpen: function () {\n if (connectTimeout) {\n clearTimeout(connectTimeout);\n connectTimeout = null;\n }\n if (self._transportId != transportId) {\n self._debug('open callback from non-actual transport');\n transport.close();\n return;\n }\n wasOpen = true;\n self._debug(transport.subName(), 'transport open');\n if (transport.emulation()) {\n return;\n }\n self._transportIsOpen = true;\n self._transportWasOpen = true;\n self.startBatching();\n self._sendConnect(false);\n self._sendSubscribeCommands();\n self.stopBatching();\n //@ts-ignore must be used only for debug and test purposes. Exposed only for non-emulation transport.\n self.emit('__centrifuge_debug:connect_frame_sent', {});\n },\n onError: function (e) {\n if (self._transportId != transportId) {\n self._debug('error callback from non-actual transport');\n return;\n }\n self._debug('transport level error', e);\n },\n onClose: function (closeEvent) {\n if (connectTimeout) {\n clearTimeout(connectTimeout);\n connectTimeout = null;\n }\n if (self._transportId != transportId) {\n self._debug('close callback from non-actual transport');\n return;\n }\n self._debug(transport.subName(), 'transport closed');\n self._transportClosed = true;\n self._transportIsOpen = false;\n let reason = 'connection closed';\n let needReconnect = true;\n let code = 0;\n if (closeEvent && 'code' in closeEvent && closeEvent.code) {\n code = closeEvent.code;\n }\n if (closeEvent && closeEvent.reason) {\n try {\n const advice = JSON.parse(closeEvent.reason);\n reason = advice.reason;\n needReconnect = advice.reconnect;\n }\n catch (e) {\n reason = closeEvent.reason;\n if ((code >= 3500 && code < 4000) || (code >= 4500 && code < 5000)) {\n needReconnect = false;\n }\n }\n }\n if (code < 3000) {\n if (code === 1009) {\n code = disconnectedCodes.messageSizeLimit;\n reason = 'message size limit exceeded';\n needReconnect = false;\n }\n else {\n code = connectingCodes.transportClosed;\n reason = 'transport closed';\n }\n if (self._emulation && !self._transportWasOpen) {\n self._currentTransportIndex++;\n if (self._currentTransportIndex >= self._transports.length) {\n self._triedAllTransports = true;\n self._currentTransportIndex = 0;\n }\n }\n }\n else {\n // Codes >= 3000 are sent from a server application level.\n self._transportWasOpen = true;\n }\n if (self._isConnecting() && !wasOpen) {\n self.emit('error', {\n type: 'transport',\n error: {\n code: errorCodes.transportClosed,\n message: 'transport closed'\n },\n transport: transport.name()\n });\n }\n self._reconnecting = false;\n self._disconnect(code, reason, needReconnect);\n },\n onMessage: function (data) {\n self._dataReceived(data);\n }\n }, initialData);\n //@ts-ignore must be used only for debug and test purposes.\n self.emit('__centrifuge_debug:transport_initialized', {});\n }\n _sendConnect(skipSending) {\n const connectCommand = this._constructConnectCommand();\n const self = this;\n this._call(connectCommand, skipSending).then(resolveCtx => {\n const result = resolveCtx.reply.connect;\n self._connectResponse(result);\n if (resolveCtx.next) {\n resolveCtx.next();\n }\n }, rejectCtx => {\n self._connectError(rejectCtx.error);\n if (rejectCtx.next) {\n rejectCtx.next();\n }\n });\n return connectCommand;\n }\n _startReconnecting() {\n this._debug('start reconnecting');\n if (!this._isConnecting()) {\n this._debug('stop reconnecting: client not in connecting state');\n return;\n }\n if (this._reconnecting) {\n this._debug('reconnect already in progress, return from reconnect routine');\n return;\n }\n if (this._transportClosed === false) {\n this._debug('waiting for transport close');\n return;\n }\n this._reconnecting = true;\n const emptyToken = this._token === '';\n const needTokenRefresh = this._refreshRequired || (emptyToken && this._config.getToken !== null);\n if (!needTokenRefresh) {\n if (this._config.getData) {\n this._config.getData().then(data => {\n if (!this._isConnecting()) {\n return;\n }\n this._data = data;\n this._initializeTransport();\n })\n .catch(e => this._handleGetDataError(e));\n }\n else {\n this._initializeTransport();\n }\n return;\n }\n const self = this;\n this._getToken().then(function (token) {\n if (!self._isConnecting()) {\n return;\n }\n if (token == null || token == undefined) {\n self._failUnauthorized();\n return;\n }\n self._token = token;\n self._debug('connection token refreshed');\n if (self._config.getData) {\n self._config.getData().then(function (data) {\n if (!self._isConnecting()) {\n return;\n }\n self._data = data;\n self._initializeTransport();\n })\n .catch(e => self._handleGetDataError(e));\n }\n else {\n self._initializeTransport();\n }\n }).catch(function (e) {\n if (!self._isConnecting()) {\n return;\n }\n if (e instanceof UnauthorizedError) {\n self._failUnauthorized();\n return;\n }\n self.emit('error', {\n 'type': 'connectToken',\n 'error': {\n code: errorCodes.clientConnectToken,\n message: e !== undefined ? e.toString() : ''\n }\n });\n const delay = self._getReconnectDelay();\n self._debug('error on getting connection token, reconnect after ' + delay + ' milliseconds', e);\n self._reconnecting = false;\n self._reconnectTimeout = setTimeout(() => {\n self._startReconnecting();\n }, delay);\n });\n }\n _handleGetDataError(e) {\n if (e instanceof UnauthorizedError) {\n this._failUnauthorized();\n return;\n }\n this.emit('error', {\n type: 'connectData',\n error: {\n code: errorCodes.badConfiguration,\n message: (e === null || e === void 0 ? void 0 : e.toString()) || ''\n }\n });\n const delay = this._getReconnectDelay();\n this._debug('error on getting connect data, reconnect after ' + delay + ' milliseconds', e);\n this._reconnecting = false;\n this._reconnectTimeout = setTimeout(() => {\n this._startReconnecting();\n }, delay);\n }\n _connectError(err) {\n if (this.state !== State.Connecting) {\n return;\n }\n if (err.code === 109) { // token expired.\n // next connect attempt will try to refresh token.\n this._refreshRequired = true;\n }\n if (err.code < 100 || err.temporary === true || err.code === 109) {\n this.emit('error', {\n 'type': 'connect',\n 'error': err\n });\n this._debug('closing transport due to connect error');\n this._disconnect(err.code, err.message, true);\n }\n else {\n this._disconnect(err.code, err.message, false);\n }\n }\n _scheduleReconnect() {\n if (!this._isConnecting()) {\n return;\n }\n let isInitialHandshake = false;\n if (this._emulation && !this._transportWasOpen && !this._triedAllTransports) {\n isInitialHandshake = true;\n }\n let delay = this._getReconnectDelay();\n if (isInitialHandshake) {\n delay = 0;\n }\n this._debug('reconnect after ' + delay + ' milliseconds');\n this._clearReconnectTimeout();\n this._reconnectTimeout = setTimeout(() => {\n this._startReconnecting();\n }, delay);\n }\n _constructConnectCommand() {\n const req = {};\n if (this._token) {\n req.token = this._token;\n }\n if (this._data) {\n req.data = this._data;\n }\n if (this._config.name) {\n req.name = this._config.name;\n }\n if (this._config.version) {\n req.version = this._config.version;\n }\n if (Object.keys(this._config.headers).length > 0) {\n req.headers = this._config.headers;\n }\n const subs = {};\n let hasSubs = false;\n for (const channel in this._serverSubs) {\n if (this._serverSubs.hasOwnProperty(channel) && this._serverSubs[channel].recoverable) {\n hasSubs = true;\n const sub = {\n 'recover': true\n };\n if (this._serverSubs[channel].offset) {\n sub['offset'] = this._serverSubs[channel].offset;\n }\n if (this._serverSubs[channel].epoch) {\n sub['epoch'] = this._serverSubs[channel].epoch;\n }\n subs[channel] = sub;\n }\n }\n if (hasSubs) {\n req.subs = subs;\n }\n return {\n connect: req\n };\n }\n _getHistoryRequest(channel, options) {\n const req = {\n channel: channel\n };\n if (options !== undefined) {\n if (options.since) {\n req.since = {\n offset: options.since.offset\n };\n if (options.since.epoch) {\n req.since.epoch = options.since.epoch;\n }\n }\n if (options.limit !== undefined) {\n req.limit = options.limit;\n }\n if (options.reverse === true) {\n req.reverse = true;\n }\n }\n return req;\n }\n _methodCall() {\n if (this._isConnected()) {\n return Promise.resolve();\n }\n return new Promise((res, rej) => {\n const timeout = setTimeout(function () {\n rej({ code: errorCodes.timeout, message: 'timeout' });\n }, this._config.timeout);\n this._promises[this._nextPromiseId()] = {\n timeout: timeout,\n resolve: res,\n reject: rej\n };\n });\n }\n _callPromise(cmd, resultCB) {\n return new Promise((resolve, reject) => {\n this._call(cmd, false).then((resolveCtx) => {\n var _a;\n const result = resultCB(resolveCtx.reply);\n resolve(result);\n (_a = resolveCtx.next) === null || _a === void 0 ? void 0 : _a.call(resolveCtx);\n }, (rejectCtx) => {\n var _a;\n reject(rejectCtx.error);\n (_a = rejectCtx.next) === null || _a === void 0 ? void 0 : _a.call(rejectCtx);\n });\n });\n }\n _dataReceived(data) {\n if (this._serverPing > 0) {\n this._waitServerPing();\n }\n const replies = this._codec.decodeReplies(data);\n // We have to guarantee order of events in replies processing - i.e. start processing\n // next reply only when we finished processing of current one. Without syncing things in\n // this way we could get wrong publication events order as reply promises resolve\n // on next loop tick so for loop continues before we finished emitting all reply events.\n this._dispatchPromise = this._dispatchPromise.then(() => {\n let finishDispatch;\n this._dispatchPromise = new Promise(resolve => {\n finishDispatch = resolve;\n });\n this._dispatchSynchronized(replies, finishDispatch);\n });\n }\n _dispatchSynchronized(replies, finishDispatch) {\n let p = Promise.resolve();\n for (const i in replies) {\n if (replies.hasOwnProperty(i)) {\n p = p.then(() => {\n return this._dispatchReply(replies[i]);\n });\n }\n }\n p = p.then(() => {\n finishDispatch();\n });\n }\n _dispatchReply(reply) {\n let next;\n const p = new Promise(resolve => {\n next = resolve;\n });\n if (reply === undefined || reply === null) {\n this._debug('dispatch: got undefined or null reply');\n next();\n return p;\n }\n const id = reply.id;\n if (id && id > 0) {\n this._handleReply(reply, next);\n }\n else {\n if (!reply.push) {\n this._handleServerPing(next);\n }\n else {\n this._handlePush(reply.push, next);\n }\n }\n return p;\n }\n _call(cmd, skipSending) {\n return new Promise((resolve, reject) => {\n cmd.id = this._nextCommandId();\n this._registerCall(cmd.id, resolve, reject);\n if (!skipSending) {\n this._addCommand(cmd);\n }\n });\n }\n _startConnecting() {\n this._debug('start connecting');\n if (this._setState(State.Connecting)) {\n this.emit('connecting', { code: connectingCodes.connectCalled, reason: 'connect called' });\n }\n this._client = null;\n this._startReconnecting();\n }\n _disconnect(code, reason, reconnect) {\n if (this._isDisconnected()) {\n return;\n }\n // we mark transport is closed right away, because _clearConnectedState will move subscriptions to subscribing state\n // if transport will still be open at this time, subscribe frames will be sent to closing transport\n this._transportIsOpen = false;\n const previousState = this.state;\n this._reconnecting = false;\n const ctx = {\n code: code,\n reason: reason\n };\n let needEvent = false;\n if (reconnect) {\n needEvent = this._setState(State.Connecting);\n }\n else {\n needEvent = this._setState(State.Disconnected);\n this._rejectPromises({ code: errorCodes.clientDisconnected, message: 'disconnected' });\n }\n this._clearOutgoingRequests();\n if (previousState === State.Connecting) {\n this._clearReconnectTimeout();\n }\n if (previousState === State.Connected) {\n this._clearConnectedState();\n }\n if (needEvent) {\n if (this._isConnecting()) {\n this.emit('connecting', ctx);\n }\n else {\n this.emit('disconnected', ctx);\n }\n }\n if (this._transport) {\n this._debug(\"closing existing transport\");\n const transport = this._transport;\n this._transport = null;\n transport.close(); // Close only after setting this._transport to null to avoid recursion when calling transport close().\n // Need to mark as closed here, because connect call may be sync called after disconnect,\n // transport onClose callback will not be called yet\n this._transportClosed = true;\n this._nextTransportId();\n }\n else {\n this._debug(\"no transport to close\");\n }\n this._scheduleReconnect();\n }\n _failUnauthorized() {\n this._disconnect(disconnectedCodes.unauthorized, 'unauthorized', false);\n }\n _getToken() {\n this._debug('get connection token');\n if (!this._config.getToken) {\n this.emit('error', {\n type: 'configuration',\n error: {\n code: errorCodes.badConfiguration,\n message: 'token expired but no getToken function set in the configuration'\n }\n });\n return Promise.reject(new UnauthorizedError(''));\n }\n return this._config.getToken({});\n }\n _refresh() {\n const clientId = this._client;\n const self = this;\n this._getToken().then(function (token) {\n if (clientId !== self._client) {\n return;\n }\n if (!token) {\n self._failUnauthorized();\n return;\n }\n self._token = token;\n self._debug('connection token refreshed');\n if (!self._isConnected()) {\n return;\n }\n const cmd = {\n refresh: { token: self._token }\n };\n self._call(cmd, false).then(resolveCtx => {\n const result = resolveCtx.reply.refresh;\n self._refreshResponse(result);\n if (resolveCtx.next) {\n resolveCtx.next();\n }\n }, rejectCtx => {\n self._refreshError(rejectCtx.error);\n if (rejectCtx.next) {\n rejectCtx.next();\n }\n });\n }).catch(function (e) {\n if (!self._isConnected()) {\n return;\n }\n if (e instanceof UnauthorizedError) {\n self._failUnauthorized();\n return;\n }\n self.emit('error', {\n type: 'refreshToken',\n error: {\n code: errorCodes.clientRefreshToken,\n message: e !== undefined ? e.toString() : ''\n }\n });\n self._refreshTimeout = setTimeout(() => self._refresh(), self._getRefreshRetryDelay());\n });\n }\n _refreshError(err) {\n if (err.code < 100 || err.temporary === true) {\n this.emit('error', {\n type: 'refresh',\n error: err\n });\n this._refreshTimeout = setTimeout(() => this._refresh(), this._getRefreshRetryDelay());\n }\n else {\n this._disconnect(err.code, err.message, false);\n }\n }\n _getRefreshRetryDelay() {\n return backoff(0, 5000, 10000);\n }\n _refreshResponse(result) {\n if (this._refreshTimeout) {\n clearTimeout(this._refreshTimeout);\n this._refreshTimeout = null;\n }\n if (result.expires) {\n this._client = result.client;\n this._refreshTimeout = setTimeout(() => this._refresh(), ttlMilliseconds(result.ttl));\n }\n }\n _removeSubscription(sub) {\n if (sub === null) {\n return;\n }\n delete this._subs[sub.channel];\n }\n _unsubscribe(sub) {\n if (!this._transportIsOpen) {\n return Promise.resolve();\n }\n const req = {\n channel: sub.channel\n };\n const cmd = { unsubscribe: req };\n const self = this;\n const unsubscribePromise = new Promise((resolve, _) => {\n this._call(cmd, false).then(resolveCtx => {\n resolve();\n if (resolveCtx.next) {\n resolveCtx.next();\n }\n }, rejectCtx => {\n resolve();\n if (rejectCtx.next) {\n rejectCtx.next();\n }\n self._disconnect(connectingCodes.unsubscribeError, 'unsubscribe error', true);\n });\n });\n return unsubscribePromise;\n }\n _getSub(channel, id) {\n if (id && id > 0) {\n for (const ch in this._subs) {\n if (this._subs.hasOwnProperty(ch)) {\n const sub = this._subs[ch];\n // @ts-ignore – we are accessing private property for internal use\n if (sub._id === id) {\n return sub;\n }\n }\n }\n return null;\n }\n const sub = this._subs[channel];\n if (!sub) {\n return null;\n }\n return sub;\n }\n _isServerSub(channel) {\n return this._serverSubs[channel] !== undefined;\n }\n _sendSubscribeCommands() {\n const commands = [];\n for (const channel in this._subs) {\n if (!this._subs.hasOwnProperty(channel)) {\n continue;\n }\n const sub = this._subs[channel];\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n if (sub._inflight === true) {\n continue;\n }\n if (sub.state === SubscriptionState.Subscribing) {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n const cmd = sub._subscribe();\n if (cmd) {\n commands.push(cmd);\n }\n }\n }\n return commands;\n }\n _connectResponse(result) {\n this._transportIsOpen = true;\n this._transportWasOpen = true;\n this._reconnectAttempts = 0;\n this._refreshRequired = false;\n if (this._isConnected()) {\n return;\n }\n this._client = result.client;\n this._setState(State.Connected);\n if (this._refreshTimeout) {\n clearTimeout(this._refreshTimeout);\n }\n if (result.expires) {\n this._refreshTimeout = setTimeout(() => this._refresh(), ttlMilliseconds(result.ttl));\n }\n this._session = result.session;\n this._node = result.node;\n this.startBatching();\n this._sendSubscribeCommands();\n this.stopBatching();\n const ctx = {\n client: result.client,\n transport: this._transport.subName()\n };\n if (result.data) {\n ctx.data = result.data;\n }\n this.emit('connected', ctx);\n this._resolvePromises();\n this._processServerSubs(result.subs || {});\n if (result.ping && result.ping > 0) {\n this._serverPing = result.ping * 1000;\n this._sendPong = result.pong === true;\n this._waitServerPing();\n }\n else {\n this._serverPing = 0;\n }\n }\n _processServerSubs(subs) {\n for (const channel in subs) {\n if (!subs.hasOwnProperty(channel)) {\n continue;\n }\n const sub = subs[channel];\n this._serverSubs[channel] = {\n 'offset': sub.offset,\n 'epoch': sub.epoch,\n 'recoverable': sub.recoverable || false\n };\n const subCtx = this._getSubscribeContext(channel, sub);\n this.emit('subscribed', subCtx);\n }\n for (const channel in subs) {\n if (!subs.hasOwnProperty(channel)) {\n continue;\n }\n const sub = subs[channel];\n if (sub.recovered) {\n const pubs = sub.publications;\n if (pubs && pubs.length > 0) {\n for (const i in pubs) {\n if (pubs.hasOwnProperty(i)) {\n this._handlePublication(channel, pubs[i]);\n }\n }\n }\n }\n }\n for (const channel in this._serverSubs) {\n if (!this._serverSubs.hasOwnProperty(channel)) {\n continue;\n }\n if (!subs[channel]) {\n this.emit('unsubscribed', { channel: channel });\n delete this._serverSubs[channel];\n }\n }\n }\n _clearRefreshTimeout() {\n if (this._refreshTimeout !== null) {\n clearTimeout(this._refreshTimeout);\n this._refreshTimeout = null;\n }\n }\n _clearReconnectTimeout() {\n if (this._reconnectTimeout !== null) {\n clearTimeout(this._reconnectTimeout);\n this._reconnectTimeout = null;\n }\n }\n _clearServerPingTimeout() {\n if (this._serverPingTimeout !== null) {\n clearTimeout(this._serverPingTimeout);\n this._serverPingTimeout = null;\n }\n }\n _waitServerPing() {\n if (this._config.maxServerPingDelay === 0) {\n return;\n }\n if (!this._isConnected()) {\n return;\n }\n this._clearServerPingTimeout();\n this._serverPingTimeout = setTimeout(() => {\n if (!this._isConnected()) {\n return;\n }\n this._disconnect(connectingCodes.noPing, 'no ping', true);\n }, this._serverPing + this._config.maxServerPingDelay);\n }\n _getSubscribeContext(channel, result) {\n const ctx = {\n channel: channel,\n positioned: false,\n recoverable: false,\n wasRecovering: false,\n recovered: false,\n hasRecoveredPublications: false,\n };\n if (result.recovered) {\n ctx.recovered = true;\n }\n if (result.positioned) {\n ctx.positioned = true;\n }\n if (result.recoverable) {\n ctx.recoverable = true;\n }\n if (result.was_recovering) {\n ctx.wasRecovering = true;\n }\n let epoch = '';\n if ('epoch' in result) {\n epoch = result.epoch;\n }\n let offset = 0;\n if ('offset' in result) {\n offset = result.offset;\n }\n if (ctx.positioned || ctx.recoverable) {\n ctx.streamPosition = {\n 'offset': offset,\n 'epoch': epoch\n };\n }\n if (Array.isArray(result.publications) && result.publications.length > 0) {\n ctx.hasRecoveredPublications = true;\n }\n if (result.data) {\n ctx.data = result.data;\n }\n return ctx;\n }\n _handleReply(reply, next) {\n const id = reply.id;\n if (!(id in this._callbacks)) {\n next();\n return;\n }\n const callbacks = this._callbacks[id];\n clearTimeout(this._callbacks[id].timeout);\n delete this._callbacks[id];\n if (!errorExists(reply)) {\n const callback = callbacks.callback;\n if (!callback) {\n return;\n }\n callback({ reply, next });\n }\n else {\n const errback = callbacks.errback;\n if (!errback) {\n next();\n return;\n }\n const error = { code: reply.error.code, message: reply.error.message || '', temporary: reply.error.temporary || false };\n errback({ error, next });\n }\n }\n _handleJoin(channel, join, id) {\n const sub = this._getSub(channel, id);\n if (!sub && channel) {\n if (this._isServerSub(channel)) {\n const ctx = { channel: channel, info: this._getJoinLeaveContext(join.info) };\n this.emit('join', ctx);\n }\n return;\n }\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._handleJoin(join);\n }\n _handleLeave(channel, leave, id) {\n const sub = this._getSub(channel, id);\n if (!sub && channel) {\n if (this._isServerSub(channel)) {\n const ctx = { channel: channel, info: this._getJoinLeaveContext(leave.info) };\n this.emit('leave', ctx);\n }\n return;\n }\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._handleLeave(leave);\n }\n _handleUnsubscribe(channel, unsubscribe) {\n const sub = this._getSub(channel, 0);\n if (!sub && channel) {\n if (this._isServerSub(channel)) {\n delete this._serverSubs[channel];\n this.emit('unsubscribed', { channel: channel });\n }\n return;\n }\n if (unsubscribe.code < 2500) {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._setUnsubscribed(unsubscribe.code, unsubscribe.reason, false);\n }\n else {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._setSubscribing(unsubscribe.code, unsubscribe.reason);\n }\n }\n _handleSubscribe(channel, sub) {\n this._serverSubs[channel] = {\n 'offset': sub.offset,\n 'epoch': sub.epoch,\n 'recoverable': sub.recoverable || false\n };\n this.emit('subscribed', this._getSubscribeContext(channel, sub));\n }\n _handleDisconnect(disconnect) {\n const code = disconnect.code;\n let reconnect = true;\n if ((code >= 3500 && code < 4000) || (code >= 4500 && code < 5000)) {\n reconnect = false;\n }\n this._disconnect(code, disconnect.reason, reconnect);\n }\n _getPublicationContext(channel, pub) {\n const ctx = {\n channel: channel,\n data: pub.data\n };\n if (pub.offset) {\n ctx.offset = pub.offset;\n }\n if (pub.info) {\n ctx.info = this._getJoinLeaveContext(pub.info);\n }\n if (pub.tags) {\n ctx.tags = pub.tags;\n }\n return ctx;\n }\n _getJoinLeaveContext(clientInfo) {\n const info = {\n client: clientInfo.client,\n user: clientInfo.user\n };\n const connInfo = clientInfo['conn_info'];\n if (connInfo) {\n info.connInfo = connInfo;\n }\n const chanInfo = clientInfo['chan_info'];\n if (chanInfo) {\n info.chanInfo = chanInfo;\n }\n return info;\n }\n _handlePublication(channel, pub, id) {\n const sub = this._getSub(channel, id);\n if (!sub && channel) {\n if (this._isServerSub(channel)) {\n const ctx = this._getPublicationContext(channel, pub);\n this.emit('publication', ctx);\n if (pub.offset !== undefined) {\n this._serverSubs[channel].offset = pub.offset;\n }\n }\n return;\n }\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._handlePublication(pub);\n }\n _handleMessage(message) {\n this.emit('message', { data: message.data });\n }\n _handleServerPing(next) {\n if (this._sendPong) {\n const cmd = {};\n this._transportSendCommands([cmd]);\n }\n next();\n }\n _handlePush(data, next) {\n const channel = data.channel;\n const id = data.id;\n if (data.pub) {\n this._handlePublication(channel, data.pub, id);\n }\n else if (data.message) {\n this._handleMessage(data.message);\n }\n else if (data.join) {\n this._handleJoin(channel, data.join, id);\n }\n else if (data.leave) {\n this._handleLeave(channel, data.leave, id);\n }\n else if (data.unsubscribe) {\n this._handleUnsubscribe(channel, data.unsubscribe);\n }\n else if (data.subscribe) {\n this._handleSubscribe(channel, data.subscribe);\n }\n else if (data.disconnect) {\n this._handleDisconnect(data.disconnect);\n }\n next();\n }\n _flush() {\n const commands = this._commands.slice(0);\n this._commands = [];\n this._transportSendCommands(commands);\n }\n _createErrorObject(code, message, temporary) {\n const errObject = {\n code: code,\n message: message\n };\n if (temporary) {\n errObject.temporary = true;\n }\n return errObject;\n }\n _registerCall(id, callback, errback) {\n this._callbacks[id] = {\n callback: callback,\n errback: errback,\n timeout: null\n };\n this._callbacks[id].timeout = setTimeout(() => {\n delete this._callbacks[id];\n if (isFunction(errback)) {\n errback({ error: this._createErrorObject(errorCodes.timeout, 'timeout') });\n }\n }, this._config.timeout);\n }\n _addCommand(command) {\n if (this._batching) {\n this._commands.push(command);\n }\n else {\n this._transportSendCommands([command]);\n }\n }\n _nextPromiseId() {\n return ++this._promiseId;\n }\n _nextTransportId() {\n return ++this._transportId;\n }\n _resolvePromises() {\n for (const id in this._promises) {\n if (!this._promises.hasOwnProperty(id)) {\n continue;\n }\n if (this._promises[id].timeout) {\n clearTimeout(this._promises[id].timeout);\n }\n this._promises[id].resolve();\n delete this._promises[id];\n }\n }\n _rejectPromises(err) {\n for (const id in this._promises) {\n if (!this._promises.hasOwnProperty(id)) {\n continue;\n }\n if (this._promises[id].timeout) {\n clearTimeout(this._promises[id].timeout);\n }\n this._promises[id].reject(err);\n delete this._promises[id];\n }\n }\n}\nCentrifuge.SubscriptionState = SubscriptionState;\nCentrifuge.State = State;\nCentrifuge.UnauthorizedError = UnauthorizedError;\n\nexport { Centrifuge, State, Subscription, SubscriptionState, UnauthorizedError, connectingCodes, disconnectedCodes, errorCodes, subscribingCodes, subscriptionFlags, unsubscribedCodes };\n","import { Centrifuge, Subscription, PublicationContext } from 'centrifuge';\nimport type { CevroMessengerConfig, WSEventPayload } from '../types';\nimport { EventEmitter } from './EventEmitter';\n\n/**\n * Token refresh callback type\n */\nexport type TokenRefreshCallback = () => Promise<string>;\n\n/**\n * WebSocket client for real-time messaging via Centrifugo\n */\nexport class WebSocketClient {\n private config: CevroMessengerConfig;\n private events: EventEmitter;\n private client: Centrifuge | null = null;\n private personalSub: Subscription | null = null;\n private userId: string | null = null;\n private getTokenCallback: TokenRefreshCallback | null = null;\n\n constructor(config: CevroMessengerConfig, events: EventEmitter) {\n this.config = config;\n this.events = events;\n }\n\n /**\n * Set token refresh callback\n * Called when Centrifugo needs a new token (expiration, reconnect)\n */\n setTokenRefreshCallback(callback: TokenRefreshCallback): void {\n this.getTokenCallback = callback;\n }\n\n /**\n * Connect to Centrifugo server\n */\n connect(userId: string, connectionToken: string): void {\n if (this.client?.state === 'connected') {\n this.log('Already connected');\n return;\n }\n\n this.userId = userId;\n\n // Determine WebSocket URL from API base\n const wsUrl = this.getWebSocketUrl();\n\n // Build Centrifuge options\n const options: any = {\n token: connectionToken,\n debug: this.config.debug,\n };\n\n // Add token refresh callback if available\n // This is called when token expires or on reconnect\n if (this.getTokenCallback) {\n options.getToken = async () => {\n this.log('Token refresh requested by Centrifugo');\n try {\n const newToken = await this.getTokenCallback!();\n this.log('Token refreshed successfully');\n return newToken;\n } catch (error) {\n this.log('Token refresh failed:', error);\n throw error;\n }\n };\n }\n\n this.client = new Centrifuge(wsUrl, options);\n\n this.setupClientEventListeners();\n\n // Connect\n this.client.connect();\n }\n\n /**\n * Get WebSocket URL from config\n */\n private getWebSocketUrl(): string {\n // If centrifugoUrl is explicitly set, use it\n if (this.config.centrifugoUrl) {\n return this.config.centrifugoUrl;\n }\n\n // Otherwise derive from apiBase\n // e.g., https://api.example.com -> wss://ws.example.com/connection/websocket\n const apiUrl = new URL(this.config.apiBase);\n const wsProtocol = apiUrl.protocol === 'https:' ? 'wss:' : 'ws:';\n\n // Default to same host with /connection/websocket path\n return `${wsProtocol}//${apiUrl.host}/connection/websocket`;\n }\n\n /**\n * Setup Centrifuge client event listeners\n */\n private setupClientEventListeners(): void {\n if (!this.client) return;\n\n this.client.on('connected', (ctx) => {\n this.log('Connected to Centrifugo:', ctx);\n this.events.emit('connection:open', { clientId: ctx.client });\n\n // Subscribe to personal channel after connection\n this.subscribeToPersonalChannel();\n });\n\n this.client.on('disconnected', (ctx) => {\n this.log('Disconnected from Centrifugo:', ctx);\n this.events.emit('connection:close', { reason: ctx.reason, code: ctx.code });\n });\n\n this.client.on('error', (ctx) => {\n this.log('Connection error:', ctx);\n this.events.emit('connection:error', { error: ctx.error?.message || 'Unknown error' });\n });\n\n // Handle token refresh (for long-running connections)\n this.client.on('connecting', (ctx) => {\n this.log('Connecting...', ctx);\n });\n }\n\n /**\n * Subscribe to visitor channel for receiving messages\n * Uses visitorId which is always present (even for authenticated players)\n */\n private subscribeToPersonalChannel(): void {\n if (!this.client || !this.userId) return;\n\n // Always use visitor channel - visitorId is always present\n const channelName = `visitor:${this.userId}`;\n\n this.log('Subscribing to channel:', channelName);\n\n this.personalSub = this.client.newSubscription(channelName);\n\n this.personalSub.on('publication', (ctx: PublicationContext) => {\n this.handleMessage(ctx.data as WSEventPayload);\n });\n\n this.personalSub.on('subscribed', (ctx) => {\n this.log('Subscribed to channel:', channelName, ctx);\n });\n\n this.personalSub.on('error', (ctx) => {\n this.log('Subscription error:', ctx);\n this.events.emit('error', { type: 'subscription', error: ctx.error?.message });\n });\n\n this.personalSub.subscribe();\n }\n\n /**\n * Handle incoming message from Centrifugo\n * Payload structure: { type, data: {...}, timestamp }\n */\n private handleMessage(payload: any): void {\n this.log('Received message:', payload);\n\n const data = payload.data || payload;\n\n switch (payload.type) {\n case 'new_message':\n // Convert backend format to Message format\n const message = {\n id: data.id,\n body: data.body,\n inbound: data.inbound || false,\n outbound: data.outbound || false,\n createdAt: data.createdAt,\n type: data.type || 'text',\n mediaUrl: data.mediaUrl,\n };\n this.events.emit('message:received', {\n ticketId: data.ticketId,\n message,\n });\n break;\n\n case 'typing':\n if (data.isTyping) {\n this.events.emit('typing:start', {\n ticketId: data.ticketId,\n actor: data.senderType || 'agent',\n });\n } else {\n this.events.emit('typing:stop', {\n ticketId: data.ticketId,\n actor: data.senderType || 'agent',\n });\n }\n break;\n\n case 'ticket_created':\n this.events.emit('conversation:started', {\n ticketId: data.ticketId,\n contactId: data.contactId,\n createdAt: data.createdAt,\n });\n break;\n\n case 'ticket_status':\n this.events.emit('conversation:updated', {\n ticketId: data.ticketId,\n status: data.status,\n chatOpen: data.chatOpen, // Pass through chatOpen if backend sends it\n });\n break;\n\n default:\n this.log('Unknown message type:', payload.type);\n }\n }\n\n /**\n * Update connection token (for token refresh)\n */\n updateToken(newToken: string): void {\n if (this.client) {\n this.client.setToken(newToken);\n }\n }\n\n /**\n * Disconnect from Centrifugo\n */\n disconnect(): void {\n if (this.personalSub) {\n this.personalSub.unsubscribe();\n this.personalSub = null;\n }\n\n if (this.client) {\n this.client.disconnect();\n this.client = null;\n }\n\n this.userId = null;\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.client?.state === 'connected';\n }\n\n /**\n * Get current user ID\n */\n getUserId(): string | null {\n return this.userId;\n }\n\n /**\n * Log helper\n */\n private log(...args: any[]): void {\n if (this.config.debug) {\n console.log('[CevroMessenger WS]', ...args);\n }\n }\n}\n","/**\n * Create DOM element with attributes\n */\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attributes?: Record<string, string>,\n children?: (Node | string)[]\n): HTMLElementTagNameMap[K] {\n const element = document.createElement(tag);\n\n if (attributes) {\n Object.entries(attributes).forEach(([key, value]) => {\n if (key === 'className') {\n element.className = value;\n } else if (key.startsWith('data-') || key.startsWith('aria-')) {\n element.setAttribute(key, value);\n } else {\n (element as any)[key] = value;\n }\n });\n }\n\n if (children) {\n children.forEach((child) => {\n if (typeof child === 'string') {\n element.appendChild(document.createTextNode(child));\n } else {\n element.appendChild(child);\n }\n });\n }\n\n return element;\n}\n\n/**\n * Escape HTML to prevent XSS\n */\nexport function escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n}\n\n/**\n * Validate URL to prevent XSS via javascript: or data: protocols\n * Only allows http:, https:, and blob: protocols\n * blob: URLs are safe - they're generated by the browser for local files\n */\nexport function isValidUrl(url: string): boolean {\n if (!url || typeof url !== 'string') {\n return false;\n }\n\n try {\n const parsed = new URL(url, window.location.origin);\n return ['http:', 'https:', 'blob:'].includes(parsed.protocol);\n } catch {\n return false;\n }\n}\n\n/**\n * Sanitize URL - returns safe URL or empty string\n */\nexport function sanitizeUrl(url: string): string {\n return isValidUrl(url) ? url : '';\n}\n\n/**\n * Parse simple markdown (bold, italic, links, code)\n * URLs are validated to prevent XSS via javascript: protocol\n */\nexport function parseMarkdown(text: string): string {\n return escapeHtml(text)\n // Bold\n .replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>')\n // Italic\n .replace(/\\*(.+?)\\*/g, '<em>$1</em>')\n // Code\n .replace(/`(.+?)`/g, '<code>$1</code>')\n // Links - validate URL to prevent XSS\n .replace(/\\[(.+?)\\]\\((.+?)\\)/g, (_match, linkText, url) => {\n const safeUrl = sanitizeUrl(url);\n if (safeUrl) {\n return `<a href=\"${safeUrl}\" target=\"_blank\" rel=\"noopener\">${linkText}</a>`;\n }\n // If URL is invalid, just show the text without link\n return linkText;\n })\n // Line breaks\n .replace(/\\n/g, '<br>');\n}\n\n/**\n * Format timestamp\n */\nexport function formatTime(date: string | Date): string {\n const d = typeof date === 'string' ? new Date(date) : date;\n return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n}\n\n/**\n * Scroll element to bottom\n */\nexport function scrollToBottom(element: HTMLElement, smooth = true): void {\n element.scrollTo({\n top: element.scrollHeight,\n behavior: smooth ? 'smooth' : 'auto',\n });\n}\n\n/**\n * Check if element is scrolled to bottom\n */\nexport function isScrolledToBottom(element: HTMLElement, threshold = 50): boolean {\n return element.scrollHeight - element.scrollTop - element.clientHeight < threshold;\n}\n\n/**\n * Generate unique ID\n */\nexport function generateId(): string {\n return 'cevro_' + Math.random().toString(36).substring(2, 9);\n}\n","import type { CevroMessengerConfig } from '../types';\nimport { createElement, generateId } from '../utils/dom';\n\n/**\n * Launcher button component\n */\nexport class Launcher {\n private config: CevroMessengerConfig;\n private element: HTMLElement | null = null;\n private unreadBadge: HTMLElement | null = null;\n private onClick: () => void;\n\n constructor(config: CevroMessengerConfig, onClick: () => void) {\n this.config = config;\n this.onClick = onClick;\n }\n\n /**\n * Render the launcher button\n */\n render(): HTMLElement {\n if (this.element) {\n return this.element;\n }\n\n // Main container\n this.element = createElement('div', {\n className: 'cevro-launcher',\n id: generateId(),\n });\n\n // Apply positioning\n this.applyPositioning();\n\n // Create button\n const button = createElement('button', {\n className: 'cevro-launcher__button',\n 'aria-label': 'Open chat',\n 'data-testid': 'launcher-button',\n });\n\n // Chat icon (open state)\n const chatIcon = this.createChatIcon();\n chatIcon.classList.add('cevro-launcher__icon', 'cevro-launcher__icon--chat');\n button.appendChild(chatIcon);\n\n // Close icon (closed state)\n const closeIcon = this.createCloseIcon();\n closeIcon.classList.add('cevro-launcher__icon', 'cevro-launcher__icon--close');\n button.appendChild(closeIcon);\n\n // Unread badge\n this.unreadBadge = createElement('span', {\n className: 'cevro-launcher__badge',\n 'data-testid': 'unread-badge',\n });\n this.unreadBadge.style.display = 'none';\n button.appendChild(this.unreadBadge);\n\n // Click handler\n button.addEventListener('click', () => {\n this.onClick();\n });\n\n this.element.appendChild(button);\n\n return this.element;\n }\n\n /**\n * Apply positioning styles\n */\n private applyPositioning(): void {\n if (!this.element) return;\n\n const alignment = this.config.alignment || 'right';\n const vPadding = this.config.verticalPadding ?? 20;\n const hPadding = this.config.horizontalPadding ?? 20;\n\n this.element.style.bottom = `${vPadding}px`;\n\n if (alignment === 'left') {\n this.element.style.left = `${hPadding}px`;\n this.element.style.right = 'auto';\n } else {\n this.element.style.right = `${hPadding}px`;\n this.element.style.left = 'auto';\n }\n\n if (this.config.zIndex) {\n this.element.style.zIndex = String(this.config.zIndex);\n }\n }\n\n /**\n * Create chat bubble icon\n */\n private createChatIcon(): SVGElement {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('width', '24');\n svg.setAttribute('height', '24');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '2');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute(\n 'd',\n 'M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z'\n );\n svg.appendChild(path);\n\n return svg;\n }\n\n /**\n * Create chevron down icon (when chat is open)\n */\n private createCloseIcon(): SVGElement {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('width', '24');\n svg.setAttribute('height', '24');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '2.5');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n\n const polyline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');\n polyline.setAttribute('points', '6 9 12 15 18 9');\n svg.appendChild(polyline);\n\n return svg;\n }\n\n /**\n * Set open state\n */\n setOpen(isOpen: boolean): void {\n if (this.element) {\n this.element.classList.toggle('cevro-launcher--open', isOpen);\n }\n }\n\n /**\n * Update unread count\n */\n setUnreadCount(count: number): void {\n if (this.unreadBadge) {\n if (count > 0) {\n this.unreadBadge.textContent = count > 99 ? '99+' : String(count);\n this.unreadBadge.style.display = 'flex';\n } else {\n this.unreadBadge.style.display = 'none';\n }\n }\n }\n\n /**\n * Show the launcher\n */\n show(): void {\n if (this.element) {\n this.element.style.display = 'block';\n }\n }\n\n /**\n * Hide the launcher\n */\n hide(): void {\n if (this.element) {\n this.element.style.display = 'none';\n }\n }\n\n /**\n * Destroy the launcher\n */\n destroy(): void {\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n this.element = null;\n this.unreadBadge = null;\n }\n}\n","import type { Message, QuickAction } from '../types';\nimport { createElement, parseMarkdown, formatTime, scrollToBottom, isScrolledToBottom, generateId, isValidUrl } from '../utils/dom';\n\n/**\n * Message list component\n */\nexport class MessageList {\n private element: HTMLElement | null = null;\n private messagesContainer: HTMLElement | null = null;\n private messages: Map<string, HTMLElement> = new Map();\n private onQuickAction: ((action: QuickAction) => void) | null = null;\n private autoScroll = true;\n private closedMessageElement: HTMLElement | null = null;\n\n /**\n * Set quick action handler\n */\n setQuickActionHandler(handler: (action: QuickAction) => void): void {\n this.onQuickAction = handler;\n }\n\n /**\n * Render the message list\n */\n render(): HTMLElement {\n if (this.element) {\n return this.element;\n }\n\n this.element = createElement('div', {\n className: 'cevro-messages',\n id: generateId(),\n });\n\n this.messagesContainer = createElement('div', {\n className: 'cevro-messages__container',\n 'data-testid': 'messages-container',\n });\n\n // Track scroll position for auto-scroll\n this.messagesContainer.addEventListener('scroll', () => {\n this.autoScroll = isScrolledToBottom(this.messagesContainer!);\n });\n\n this.element.appendChild(this.messagesContainer);\n\n return this.element;\n }\n\n /**\n * Add a message to the list\n */\n addMessage(message: Message, animate = true): void {\n if (!this.messagesContainer) return;\n\n // Check if message already exists\n if (this.messages.has(message.id)) {\n this.updateMessage(message);\n return;\n }\n\n const messageEl = this.createMessageElement(message);\n if (animate) {\n messageEl.classList.add('cevro-message--animate');\n }\n\n this.messagesContainer.appendChild(messageEl);\n this.messages.set(message.id, messageEl);\n\n // Auto-scroll if at bottom\n if (this.autoScroll) {\n scrollToBottom(this.messagesContainer);\n }\n }\n\n /**\n * Update an existing message\n * @param message - Updated message data\n * @param oldId - Original message id (for optimistic updates where id changes)\n */\n updateMessage(message: Message, oldId?: string): void {\n const lookupId = oldId || message.id;\n const existingEl = this.messages.get(lookupId);\n if (!existingEl || !this.messagesContainer) return;\n\n const newEl = this.createMessageElement(message);\n this.messagesContainer.replaceChild(newEl, existingEl);\n\n // Remove old id entry and add new one\n if (oldId && oldId !== message.id) {\n this.messages.delete(oldId);\n }\n this.messages.set(message.id, newEl);\n }\n\n /**\n * Update upload progress for a message\n */\n updateMessageProgress(messageId: string, progress: number): void {\n const messageEl = this.messages.get(messageId);\n if (!messageEl) return;\n\n const progressFill = messageEl.querySelector('.cevro-file-progress__fill') as HTMLElement;\n const progressText = messageEl.querySelector('.cevro-file-progress__text');\n\n if (progressFill) {\n progressFill.style.width = `${progress}%`;\n }\n if (progressText) {\n progressText.textContent = `${progress}%`;\n }\n }\n\n /**\n * Remove a message from the list\n */\n removeMessage(messageId: string): void {\n const messageEl = this.messages.get(messageId);\n if (!messageEl) return;\n\n messageEl.remove();\n this.messages.delete(messageId);\n }\n\n /**\n * Create message element\n */\n private createMessageElement(message: Message): HTMLElement {\n // From SDK perspective:\n // - inbound: true = user's message (to backend) = show on RIGHT\n // - outbound: true = admin's message (from backend) = show on LEFT\n const isMyMessage = message.inbound === true;\n const wrapper = createElement('div', {\n className: `cevro-message ${isMyMessage ? 'cevro-message--outbound' : 'cevro-message--inbound'}`,\n 'data-message-id': message.id,\n 'data-testid': `message-${message.id}`,\n });\n\n // Avatar for admin messages (hidden via CSS, kept for potential future use)\n if (!isMyMessage) {\n const avatar = createElement('div', {\n className: 'cevro-message__avatar',\n });\n avatar.innerHTML = this.createBotAvatarSvg();\n wrapper.appendChild(avatar);\n }\n\n // Message content wrapper\n const contentWrapper = createElement('div', {\n className: 'cevro-message__content-wrapper',\n });\n\n // Message bubble\n const bubble = createElement('div', {\n className: 'cevro-message__bubble',\n });\n\n // Handle different message types\n const isImage = message.type === 'image' || message.attachment?.category === 'image';\n\n if (isImage && message.mediaUrl && isValidUrl(message.mediaUrl)) {\n // Image message - show actual image\n const imageContainer = createElement('div', {\n className: 'cevro-message__image-container',\n });\n\n const img = createElement('img', {\n className: 'cevro-message__image',\n }) as HTMLImageElement;\n img.src = message.mediaUrl;\n img.alt = message.attachment?.filename || 'Image';\n img.loading = 'lazy';\n imageContainer.appendChild(img);\n\n // Show progress overlay if uploading\n if (message.status === 'sending') {\n const progressOverlay = this.createProgressOverlay();\n imageContainer.appendChild(progressOverlay);\n }\n\n bubble.appendChild(imageContainer);\n } else if (message.type === 'file' || (message.attachment && !isImage)) {\n // File attachment (non-image) - show file card\n const fileCard = this.createFileCard(message);\n bubble.appendChild(fileCard);\n } else if (message.type === 'media' && message.mediaUrl && isValidUrl(message.mediaUrl)) {\n // Legacy media type\n const link = createElement('a', {\n className: 'cevro-message__attachment',\n }) as HTMLAnchorElement;\n link.href = message.mediaUrl;\n link.target = '_blank';\n link.rel = 'noopener';\n link.innerHTML = `\n ${this.getFileIcon('file')}\n <span>Attachment</span>\n `;\n bubble.appendChild(link);\n }\n\n // Text content\n if (message.body) {\n const textContent = createElement('div', {\n className: 'cevro-message__text',\n });\n textContent.innerHTML = parseMarkdown(message.body);\n bubble.appendChild(textContent);\n }\n\n contentWrapper.appendChild(bubble);\n\n // Quick actions\n if (message.richContent?.quickActions?.length) {\n const actionsContainer = createElement('div', {\n className: 'cevro-message__quick-actions',\n });\n\n message.richContent.quickActions.forEach((action) => {\n const button = createElement('button', {\n className: 'cevro-message__quick-action',\n });\n button.textContent = action.label;\n button.addEventListener('click', () => {\n if (this.onQuickAction) {\n this.onQuickAction(action);\n }\n });\n actionsContainer.appendChild(button);\n });\n\n contentWrapper.appendChild(actionsContainer);\n }\n\n // Timestamp and status\n const meta = createElement('div', {\n className: 'cevro-message__meta',\n });\n meta.textContent = formatTime(message.createdAt);\n\n // Status indicator for user's own messages\n if (isMyMessage && message.status) {\n const status = createElement('span', {\n className: `cevro-message__status cevro-message__status--${message.status}`,\n });\n status.innerHTML = this.getStatusIcon(message.status);\n meta.appendChild(status);\n }\n\n contentWrapper.appendChild(meta);\n wrapper.appendChild(contentWrapper);\n\n return wrapper;\n }\n\n /**\n * Create progress overlay for images\n */\n private createProgressOverlay(): HTMLElement {\n const overlay = createElement('div', {\n className: 'cevro-file-progress-overlay',\n });\n overlay.innerHTML = `\n <div class=\"cevro-file-progress\">\n <div class=\"cevro-file-progress__bar\">\n <div class=\"cevro-file-progress__fill\" style=\"width: 0%\"></div>\n </div>\n <span class=\"cevro-file-progress__text\">0%</span>\n </div>\n `;\n return overlay;\n }\n\n /**\n * Create file card for non-image attachments\n */\n private createFileCard(message: Message): HTMLElement {\n const attachment = message.attachment;\n const category = attachment?.category || 'file';\n const filename = attachment?.filename || 'File';\n const size = attachment?.size || 0;\n const isUploading = message.status === 'sending';\n\n const card = createElement('div', {\n className: `cevro-file-card cevro-file-card--${category}`,\n });\n\n // File icon\n const iconWrapper = createElement('div', {\n className: 'cevro-file-card__icon',\n });\n iconWrapper.innerHTML = this.getFileIcon(category);\n card.appendChild(iconWrapper);\n\n // File info\n const info = createElement('div', {\n className: 'cevro-file-card__info',\n });\n\n const name = createElement('div', {\n className: 'cevro-file-card__name',\n });\n name.textContent = this.truncateFilename(filename, 25);\n name.title = filename;\n info.appendChild(name);\n\n const details = createElement('div', {\n className: 'cevro-file-card__details',\n });\n details.textContent = this.formatFileSize(size);\n info.appendChild(details);\n\n card.appendChild(info);\n\n // Progress or download\n if (isUploading) {\n const progress = createElement('div', {\n className: 'cevro-file-card__progress',\n });\n progress.innerHTML = `\n <div class=\"cevro-file-progress\">\n <div class=\"cevro-file-progress__bar\">\n <div class=\"cevro-file-progress__fill\" style=\"width: 0%\"></div>\n </div>\n <span class=\"cevro-file-progress__text\">0%</span>\n </div>\n `;\n card.appendChild(progress);\n } else if (message.mediaUrl && isValidUrl(message.mediaUrl)) {\n // Make card clickable to download\n card.style.cursor = 'pointer';\n card.addEventListener('click', () => {\n window.open(message.mediaUrl, '_blank');\n });\n }\n\n return card;\n }\n\n /**\n * Get file icon SVG based on category\n */\n private getFileIcon(category: string): string {\n const icons: Record<string, string> = {\n pdf: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#E53935\"/>\n <path d=\"M14 2V8H20\" fill=\"#FFCDD2\"/>\n <path d=\"M9 13H10.5V14.5H9V16H7.5V11H10.5V12.5H9V13Z\" fill=\"white\"/>\n <path d=\"M11.5 11H13.5C14.05 11 14.5 11.45 14.5 12V14C14.5 14.55 14.05 15 13.5 15H12.5V16H11.5V11ZM13 14V12H12.5V14H13Z\" fill=\"white\"/>\n <path d=\"M15.5 11H17V12H16V13H17V14H16V16H15.5V11Z\" fill=\"white\"/>\n </svg>`,\n document: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#1976D2\"/>\n <path d=\"M14 2V8H20\" fill=\"#BBDEFB\"/>\n <path d=\"M8 12H16V13H8V12ZM8 15H14V16H8V15Z\" fill=\"white\"/>\n </svg>`,\n spreadsheet: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#388E3C\"/>\n <path d=\"M14 2V8H20\" fill=\"#C8E6C9\"/>\n <path d=\"M8 12H10V14H8V12ZM11 12H13V14H11V12ZM14 12H16V14H14V12ZM8 15H10V17H8V15ZM11 15H13V17H11V15Z\" fill=\"white\"/>\n </svg>`,\n presentation: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#F57C00\"/>\n <path d=\"M14 2V8H20\" fill=\"#FFE0B2\"/>\n <rect x=\"8\" y=\"12\" width=\"8\" height=\"5\" rx=\"1\" fill=\"white\"/>\n </svg>`,\n video: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#7B1FA2\"/>\n <path d=\"M14 2V8H20\" fill=\"#E1BEE7\"/>\n <path d=\"M10 11V17L15 14L10 11Z\" fill=\"white\"/>\n </svg>`,\n audio: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#00897B\"/>\n <path d=\"M14 2V8H20\" fill=\"#B2DFDB\"/>\n <path d=\"M12 11C10.9 11 10 11.9 10 13V15C10 16.1 10.9 17 12 17C13.1 17 14 16.1 14 15V13C14 11.9 13.1 11 12 11Z\" fill=\"white\"/>\n <path d=\"M15 14V15C15 16.66 13.66 18 12 18C10.34 18 9 16.66 9 15V14H8V15C8 17.03 9.53 18.71 11.5 18.96V20H10V21H14V20H12.5V18.96C14.47 18.71 16 17.03 16 15V14H15Z\" fill=\"white\"/>\n </svg>`,\n archive: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#795548\"/>\n <path d=\"M14 2V8H20\" fill=\"#D7CCC8\"/>\n <rect x=\"10\" y=\"11\" width=\"4\" height=\"2\" fill=\"white\"/>\n <rect x=\"10\" y=\"14\" width=\"4\" height=\"2\" fill=\"white\"/>\n <rect x=\"10\" y=\"17\" width=\"4\" height=\"2\" fill=\"white\"/>\n </svg>`,\n text: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#607D8B\"/>\n <path d=\"M14 2V8H20\" fill=\"#CFD8DC\"/>\n <path d=\"M8 12H16V13H8V12ZM8 15H14V16H8V15ZM8 18H16V19H8V18Z\" fill=\"white\"/>\n </svg>`,\n image: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#43A047\"/>\n <path d=\"M14 2V8H20\" fill=\"#C8E6C9\"/>\n <circle cx=\"10\" cy=\"13\" r=\"2\" fill=\"white\"/>\n <path d=\"M8 18L10 15L12 17L15 13L17 18H8Z\" fill=\"white\"/>\n </svg>`,\n file: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#90A4AE\"/>\n <path d=\"M14 2V8H20\" fill=\"#CFD8DC\"/>\n </svg>`,\n };\n\n return icons[category] || icons.file;\n }\n\n /**\n * Format file size to human readable\n */\n private formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];\n }\n\n /**\n * Truncate filename if too long\n */\n private truncateFilename(filename: string, maxLength: number): string {\n if (filename.length <= maxLength) return filename;\n\n const ext = filename.split('.').pop() || '';\n const name = filename.slice(0, filename.length - ext.length - 1);\n const truncatedName = name.slice(0, maxLength - ext.length - 4) + '...';\n return truncatedName + '.' + ext;\n }\n\n /**\n * Create bot avatar SVG\n */\n private createBotAvatarSvg(): string {\n return `\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\">\n <circle cx=\"16\" cy=\"16\" r=\"16\" fill=\"currentColor\"/>\n <path d=\"M16 8C11.582 8 8 11.582 8 16s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zm0 14.5c-3.59 0-6.5-2.91-6.5-6.5s2.91-6.5 6.5-6.5 6.5 2.91 6.5 6.5-2.91 6.5-6.5 6.5z\" fill=\"white\"/>\n <circle cx=\"13\" cy=\"14\" r=\"1.5\" fill=\"white\"/>\n <circle cx=\"19\" cy=\"14\" r=\"1.5\" fill=\"white\"/>\n <path d=\"M16 19c1.657 0 3-1.343 3-3h-6c0 1.657 1.343 3 3 3z\" fill=\"white\"/>\n </svg>\n `;\n }\n\n /**\n * Get status icon\n * - sending: single checkmark (message is being sent)\n * - sent: double checkmark (message delivered to server)\n * - delivered: double checkmark (same as sent)\n * - read: double checkmark filled (message was read)\n * - failed: X icon in red\n */\n private getStatusIcon(status: string): string {\n // Single checkmark\n const singleCheck = '<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>';\n // Double checkmark\n const doubleCheck = '<svg width=\"16\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"18 7 9.5 17 5 12\"/><polyline points=\"23 7 14.5 17 12 14\"/></svg>';\n // Double checkmark filled (for read)\n const doubleCheckRead = '<svg width=\"16\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#8B5CF6\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"18 7 9.5 17 5 12\"/><polyline points=\"23 7 14.5 17 12 14\"/></svg>';\n\n switch (status) {\n case 'sending':\n return singleCheck;\n case 'sent':\n case 'delivered':\n return doubleCheck;\n case 'read':\n return doubleCheckRead;\n case 'failed':\n return '<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#ef4444\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/></svg>';\n default:\n return '';\n }\n }\n\n /**\n * Show typing indicator\n */\n showTypingIndicator(): void {\n if (!this.messagesContainer) return;\n\n // Remove existing typing indicator\n this.hideTypingIndicator();\n\n const indicator = createElement('div', {\n className: 'cevro-typing-indicator',\n id: 'cevro-typing-indicator',\n 'data-testid': 'typing-indicator',\n });\n\n indicator.innerHTML = `\n <div class=\"cevro-typing-indicator__avatar\">\n ${this.createBotAvatarSvg()}\n </div>\n <div class=\"cevro-typing-indicator__dots\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n `;\n\n this.messagesContainer.appendChild(indicator);\n\n if (this.autoScroll) {\n scrollToBottom(this.messagesContainer);\n }\n }\n\n /**\n * Hide typing indicator\n */\n hideTypingIndicator(): void {\n const indicator = document.getElementById('cevro-typing-indicator');\n if (indicator) {\n indicator.remove();\n }\n }\n\n /**\n * Clear all messages\n */\n clear(): void {\n if (this.messagesContainer) {\n this.messagesContainer.innerHTML = '';\n }\n this.messages.clear();\n // Also remove closed message if present\n if (this.closedMessageElement) {\n this.closedMessageElement.remove();\n this.closedMessageElement = null;\n }\n }\n\n /**\n * Show closed chat message at the bottom of messages area\n * This displays when a ticket is closed (e.g., escalated and resolved)\n */\n showClosedMessage(): void {\n if (!this.messagesContainer) return;\n\n // Remove existing closed message\n this.hideClosedMessage();\n\n this.closedMessageElement = createElement('div', {\n className: 'cevro-messages__closed-notice',\n 'data-testid': 'closed-chat-message',\n });\n\n this.closedMessageElement.innerHTML = `\n <p class=\"cevro-messages__closed-text\">\n The agent closed the chat. If you need assistance please start a new chat.\n </p>\n `;\n\n this.messagesContainer.appendChild(this.closedMessageElement);\n\n // Scroll to show the closed message\n if (this.autoScroll) {\n scrollToBottom(this.messagesContainer);\n }\n }\n\n /**\n * Hide closed chat message\n */\n hideClosedMessage(): void {\n if (this.closedMessageElement) {\n this.closedMessageElement.remove();\n this.closedMessageElement = null;\n }\n }\n\n /**\n * Scroll to bottom\n */\n scrollToBottom(): void {\n if (this.messagesContainer) {\n scrollToBottom(this.messagesContainer, false);\n }\n }\n\n /**\n * Destroy the component\n */\n destroy(): void {\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n this.element = null;\n this.messagesContainer = null;\n this.messages.clear();\n }\n}\n","import type { CevroMessengerConfig, Message, QuickAction, Agent } from '../types';\nimport { createElement, generateId, isValidUrl } from '../utils/dom';\nimport { generateAcceptAttribute } from '../utils/file-validation';\nimport { MessageList } from './MessageList';\n\nexport interface ChatWindowCallbacks {\n onClose: () => void;\n onSendMessage: (message: string) => void;\n onQuickAction: (action: QuickAction) => void;\n onFileUpload?: (file: File) => void;\n}\n\n/**\n * Chat window component\n */\nexport class ChatWindow {\n private config: CevroMessengerConfig;\n private callbacks: ChatWindowCallbacks;\n private element: HTMLElement | null = null;\n private messageList: MessageList;\n private inputElement: HTMLTextAreaElement | null = null;\n private sendButton: HTMLButtonElement | null = null;\n private fileInput: HTMLInputElement | null = null;\n private fileButton: HTMLButtonElement | null = null;\n private isVisible = false;\n private agentAvatarElement: HTMLElement | null = null;\n private agentNameElement: HTMLElement | null = null;\n private inputWrapper: HTMLElement | null = null;\n private closedFooter: HTMLElement | null = null;\n private themeMediaQuery: MediaQueryList | null = null;\n private themeChangeHandler: ((e: MediaQueryListEvent) => void) | null = null;\n\n constructor(config: CevroMessengerConfig, callbacks: ChatWindowCallbacks) {\n this.config = config;\n this.callbacks = callbacks;\n this.messageList = new MessageList();\n this.messageList.setQuickActionHandler((action) => {\n this.callbacks.onQuickAction(action);\n });\n }\n\n /**\n * Render the chat window\n */\n render(): HTMLElement {\n if (this.element) {\n return this.element;\n }\n\n // Main container\n this.element = createElement('div', {\n className: 'cevro-chat-window',\n id: generateId(),\n });\n\n // Apply positioning\n this.applyPositioning();\n\n // Header\n const header = this.createHeader();\n this.element.appendChild(header);\n\n // Messages area\n const messagesArea = this.messageList.render();\n this.element.appendChild(messagesArea);\n\n // Input area\n this.inputWrapper = this.createInputArea();\n this.element.appendChild(this.inputWrapper);\n\n // Apply theme\n this.applyTheme();\n\n return this.element;\n }\n\n /**\n * Apply positioning styles\n */\n private applyPositioning(): void {\n if (!this.element) return;\n\n const alignment = this.config.alignment || 'right';\n const vPadding = this.config.verticalPadding ?? 20;\n const hPadding = this.config.horizontalPadding ?? 20;\n\n // Position above launcher\n this.element.style.bottom = `${vPadding + 70}px`;\n\n if (alignment === 'left') {\n this.element.style.left = `${hPadding}px`;\n this.element.style.right = 'auto';\n } else {\n this.element.style.right = `${hPadding}px`;\n this.element.style.left = 'auto';\n }\n\n if (this.config.zIndex) {\n this.element.style.zIndex = String(this.config.zIndex - 1);\n }\n }\n\n /**\n * Create header element\n */\n private createHeader(): HTMLElement {\n const header = createElement('div', {\n className: 'cevro-chat-window__header',\n });\n\n // Agent avatar\n this.agentAvatarElement = createElement('div', {\n className: 'cevro-chat-window__agent-avatar',\n 'data-testid': 'agent-avatar',\n });\n this.agentAvatarElement.innerHTML = this.createDefaultAvatarSvg();\n header.appendChild(this.agentAvatarElement);\n\n // Title section\n const titleSection = createElement('div', {\n className: 'cevro-chat-window__title-section',\n });\n\n this.agentNameElement = createElement('h2', {\n className: 'cevro-chat-window__title',\n 'data-testid': 'agent-name',\n }, ['Support']);\n\n const subtitle = createElement('p', {\n className: 'cevro-chat-window__subtitle',\n }, ['We typically reply within a few minutes']);\n\n titleSection.appendChild(this.agentNameElement);\n titleSection.appendChild(subtitle);\n header.appendChild(titleSection);\n\n // Close button\n const closeButton = createElement('button', {\n className: 'cevro-chat-window__close',\n 'aria-label': 'Close chat',\n 'data-testid': 'close-button',\n });\n closeButton.innerHTML = `\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n `;\n closeButton.addEventListener('click', () => {\n this.callbacks.onClose();\n });\n header.appendChild(closeButton);\n\n return header;\n }\n\n /**\n * Create default avatar SVG\n */\n private createDefaultAvatarSvg(): string {\n return `\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 40 40\" fill=\"none\">\n <circle cx=\"20\" cy=\"20\" r=\"20\" fill=\"rgba(255,255,255,0.2)\"/>\n <path d=\"M20 10C14.477 10 10 14.477 10 20s4.477 10 10 10 10-4.477 10-10-4.477-10-10-10zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z\" fill=\"white\"/>\n <circle cx=\"16\" cy=\"17\" r=\"2\" fill=\"white\"/>\n <circle cx=\"24\" cy=\"17\" r=\"2\" fill=\"white\"/>\n <path d=\"M20 24c2.071 0 3.75-1.679 3.75-3.75h-7.5c0 2.071 1.679 3.75 3.75 3.75z\" fill=\"white\"/>\n </svg>\n `;\n }\n\n /**\n * Set agent info in header\n */\n setAgent(agent: Agent): void {\n if (this.agentNameElement && agent.name) {\n this.agentNameElement.textContent = agent.name;\n }\n\n if (this.agentAvatarElement && agent.avatarUrl && isValidUrl(agent.avatarUrl)) {\n this.agentAvatarElement.innerHTML = '';\n const img = createElement('img', {\n className: 'cevro-chat-window__agent-avatar-img',\n });\n (img as HTMLImageElement).src = agent.avatarUrl;\n (img as HTMLImageElement).alt = agent.name || 'Agent';\n this.agentAvatarElement.appendChild(img);\n }\n }\n\n /**\n * Create input area element\n */\n private createInputArea(): HTMLElement {\n const wrapper = createElement('div', {\n className: 'cevro-chat-window__input-wrapper',\n });\n\n const inputArea = createElement('div', {\n className: 'cevro-chat-window__input-area',\n });\n\n // File upload button (paperclip icon)\n this.fileButton = createElement('button', {\n className: 'cevro-chat-window__file-button',\n 'aria-label': 'Attach file',\n 'data-testid': 'file-button',\n }) as HTMLButtonElement;\n this.fileButton.innerHTML = `\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M16.5 6V17.5C16.5 19.71 14.71 21.5 12.5 21.5C10.29 21.5 8.5 19.71 8.5 17.5V5C8.5 3.62 9.62 2.5 11 2.5C12.38 2.5 13.5 3.62 13.5 5V16.5C13.5 17.05 13.05 17.5 12.5 17.5C11.95 17.5 11.5 17.05 11.5 16.5V6H10V16.5C10 17.88 11.12 19 12.5 19C13.88 19 15 17.88 15 16.5V5C15 2.79 13.21 1 11 1C8.79 1 7 2.79 7 5V17.5C7 20.54 9.46 23 12.5 23C15.54 23 18 20.54 18 17.5V6H16.5Z\" fill=\"currentColor\"/>\n </svg>\n `;\n\n // Hidden file input\n this.fileInput = createElement('input', {\n className: 'cevro-chat-window__file-input',\n }) as HTMLInputElement;\n this.fileInput.type = 'file';\n // Generate accept attribute from allowed MIME types to stay in sync with validation\n this.fileInput.accept = this.config.fileUpload?.allowedMimeTypes\n ? this.config.fileUpload.allowedMimeTypes.join(',')\n : generateAcceptAttribute();\n this.fileInput.addEventListener('change', () => {\n if (this.fileInput?.files?.length && this.callbacks.onFileUpload) {\n this.callbacks.onFileUpload(this.fileInput.files[0]);\n this.fileInput.value = '';\n }\n });\n\n this.fileButton.addEventListener('click', () => {\n this.fileInput?.click();\n });\n\n inputArea.appendChild(this.fileButton);\n inputArea.appendChild(this.fileInput);\n\n // Text input (max 2000 characters)\n this.inputElement = createElement('textarea', {\n className: 'cevro-chat-window__input',\n 'data-testid': 'chat-input',\n }) as HTMLTextAreaElement;\n this.inputElement.placeholder = 'How can we help';\n this.inputElement.rows = 1;\n this.inputElement.setAttribute('maxlength', '2000');\n\n // Auto-resize textarea\n this.inputElement.addEventListener('input', () => {\n if (this.inputElement) {\n this.inputElement.style.height = 'auto';\n this.inputElement.style.height = Math.min(this.inputElement.scrollHeight, 100) + 'px';\n this.updateSendButtonState();\n }\n });\n\n // Handle enter key\n this.inputElement.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n this.handleSend();\n }\n });\n\n inputArea.appendChild(this.inputElement);\n\n // Send button - arrow icon\n this.sendButton = createElement('button', {\n className: 'cevro-chat-window__send-button',\n 'aria-label': 'Send message',\n 'data-testid': 'send-button',\n }) as HTMLButtonElement;\n this.sendButton.disabled = true;\n this.sendButton.innerHTML = `\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M12 19V5M5 12L12 5L19 12\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n `;\n\n this.sendButton.addEventListener('click', () => {\n this.handleSend();\n });\n\n inputArea.appendChild(this.sendButton);\n wrapper.appendChild(inputArea);\n\n // Powered by footer\n const footer = createElement('div', {\n className: 'cevro-chat-window__footer',\n });\n footer.innerHTML = 'Powered by <a href=\"https://cevro.ai\" target=\"_blank\" rel=\"noopener\">Cevro AI</a>';\n wrapper.appendChild(footer);\n\n return wrapper;\n }\n\n /**\n * Handle send message\n */\n private handleSend(): void {\n if (!this.inputElement) return;\n\n const message = this.inputElement.value.trim();\n if (!message) return;\n\n this.callbacks.onSendMessage(message);\n this.inputElement.value = '';\n this.inputElement.style.height = 'auto';\n this.updateSendButtonState();\n this.inputElement.focus();\n }\n\n /**\n * Update send button state\n */\n private updateSendButtonState(): void {\n if (this.sendButton && this.inputElement) {\n this.sendButton.disabled = !this.inputElement.value.trim();\n }\n }\n\n /**\n * Apply theme\n */\n private applyTheme(): void {\n if (!this.element) return;\n\n const theme = this.config.theme || 'light';\n\n // Clean up previous listener if exists\n this.cleanupThemeListener();\n\n if (theme === 'system') {\n this.themeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n const prefersDark = this.themeMediaQuery.matches;\n this.element.classList.toggle('cevro-chat-window--dark', prefersDark);\n\n // Add listener for theme changes\n this.themeChangeHandler = (e: MediaQueryListEvent) => {\n this.element?.classList.toggle('cevro-chat-window--dark', e.matches);\n };\n this.themeMediaQuery.addEventListener('change', this.themeChangeHandler);\n } else {\n this.element.classList.toggle('cevro-chat-window--dark', theme === 'dark');\n }\n }\n\n /**\n * Clean up theme change listener\n */\n private cleanupThemeListener(): void {\n if (this.themeMediaQuery && this.themeChangeHandler) {\n this.themeMediaQuery.removeEventListener('change', this.themeChangeHandler);\n this.themeMediaQuery = null;\n this.themeChangeHandler = null;\n }\n }\n\n /**\n * Add message to the chat\n */\n addMessage(message: Message, animate = true): void {\n this.messageList.addMessage(message, animate);\n }\n\n /**\n * Update message\n */\n updateMessage(message: Message, oldId?: string): void {\n this.messageList.updateMessage(message, oldId);\n }\n\n /**\n * Update upload progress for a message\n */\n updateMessageProgress(messageId: string, progress: number): void {\n this.messageList.updateMessageProgress(messageId, progress);\n }\n\n /**\n * Remove a message from the chat\n */\n removeMessage(messageId: string): void {\n this.messageList.removeMessage(messageId);\n }\n\n /**\n * Show typing indicator\n */\n showTypingIndicator(): void {\n this.messageList.showTypingIndicator();\n }\n\n /**\n * Hide typing indicator\n */\n hideTypingIndicator(): void {\n this.messageList.hideTypingIndicator();\n }\n\n /**\n * Clear messages\n */\n clearMessages(): void {\n this.messageList.clear();\n }\n\n /**\n * Show the chat window\n */\n show(): void {\n if (this.element) {\n this.element.classList.add('cevro-chat-window--visible');\n this.isVisible = true;\n this.inputElement?.focus();\n this.messageList.scrollToBottom();\n }\n }\n\n /**\n * Hide the chat window\n */\n hide(): void {\n if (this.element) {\n this.element.classList.remove('cevro-chat-window--visible');\n this.isVisible = false;\n }\n }\n\n /**\n * Check if visible\n */\n isWindowVisible(): boolean {\n return this.isVisible;\n }\n\n /**\n * Focus input\n */\n focusInput(): void {\n this.inputElement?.focus();\n }\n\n /**\n * Set ticket closed state\n * Shows the closed chat UI with \"New Conversation\" button\n *\n * @param closed - Whether the ticket is closed\n * @param onStartNewChat - Callback when user clicks \"New Conversation\"\n * @param options - Additional options\n * @param options.showHistory - Show message history (future paid feature)\n */\n setTicketClosed(\n closed: boolean,\n onStartNewChat?: () => void,\n options?: { showHistory?: boolean }\n ): void {\n const showHistory = options?.showHistory ?? false;\n\n if (closed) {\n // Clear messages if history is not enabled (future paid feature)\n if (!showHistory) {\n this.messageList.clear();\n }\n\n // Hide input area\n if (this.inputWrapper) {\n this.inputWrapper.style.display = 'none';\n }\n\n // Add closed message to messages area\n this.messageList.showClosedMessage();\n\n // Show closed footer with \"New Conversation\" button\n if (!this.closedFooter && this.element) {\n this.closedFooter = createElement('div', {\n className: 'cevro-chat-window__closed-footer',\n });\n\n const newChatButton = createElement('button', {\n className: 'cevro-chat-window__new-chat-button',\n }, ['New Conversation']);\n\n newChatButton.addEventListener('click', () => {\n if (onStartNewChat) {\n onStartNewChat();\n }\n });\n\n const poweredBy = createElement('div', {\n className: 'cevro-chat-window__powered-by',\n }, ['Powered by Cevro AI']);\n\n this.closedFooter.appendChild(newChatButton);\n this.closedFooter.appendChild(poweredBy);\n this.element.appendChild(this.closedFooter);\n }\n } else {\n // Show input area\n if (this.inputWrapper) {\n this.inputWrapper.style.display = '';\n }\n\n // Hide closed message\n this.messageList.hideClosedMessage();\n\n // Remove closed footer\n if (this.closedFooter && this.closedFooter.parentNode) {\n this.closedFooter.parentNode.removeChild(this.closedFooter);\n this.closedFooter = null;\n }\n }\n }\n\n /**\n * Destroy the component\n */\n destroy(): void {\n // Clean up theme listener\n this.cleanupThemeListener();\n\n this.messageList.destroy();\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n this.element = null;\n this.inputElement = null;\n this.sendButton = null;\n this.fileInput = null;\n this.fileButton = null;\n this.closedFooter = null;\n }\n}\n","import type {\n CevroMessengerConfig,\n PlayerData,\n Message,\n QuickAction,\n EventType,\n EventHandler,\n} from '../types';\nimport { EventEmitter } from './EventEmitter';\nimport { ApiClient } from './ApiClient';\nimport { WebSocketClient } from './WebSocketClient';\nimport { Launcher } from '../ui/Launcher';\nimport { ChatWindow } from '../ui/ChatWindow';\nimport {\n generateVisitorId,\n getStoredSession,\n storeSession,\n clearStoredSession,\n clearStoredVisitorToken,\n getStoredVisitorToken,\n storeVisitorToken,\n} from '../utils/session';\nimport { isValidUrl } from '../utils/dom';\n\n/**\n * Main Cevro Messenger SDK class\n */\nexport class CevroMessenger {\n private static instance: CevroMessenger | null = null;\n\n private config: CevroMessengerConfig;\n private events: EventEmitter;\n private api: ApiClient;\n private ws: WebSocketClient;\n private launcher: Launcher | null = null;\n private chatWindow: ChatWindow | null = null;\n private container: HTMLElement | null = null;\n private isBooted = false;\n private isVisible = false;\n private unreadCount = 0;\n private visitorId: string | null;\n\n private isSessionInitialized = false;\n private isInitializingSession: Promise<void> | null = null;\n private connectingPromise: Promise<void> | null = null;\n private typingCycleTimeout: ReturnType<typeof setTimeout> | null = null;\n private isTypingVisible = false;\n private typingConfig = { onDurationMs: 7000, offDurationMs: 4000 };\n\n constructor(config: CevroMessengerConfig) {\n this.config = this.normalizeConfig(config);\n this.events = new EventEmitter();\n this.api = new ApiClient(this.config);\n this.ws = new WebSocketClient(this.config, this.events);\n this.visitorId = generateVisitorId();\n\n // Setup token refresh callback for WebSocket\n this.ws.setTokenRefreshCallback(async () => {\n return this.refreshConnectionToken();\n });\n\n // Setup internal event handlers\n this.setupEventHandlers();\n\n // Singleton pattern\n CevroMessenger.instance = this;\n\n this.log('Initialized with config:', this.config);\n }\n\n /**\n * Get singleton instance\n */\n static getInstance(): CevroMessenger | null {\n return CevroMessenger.instance;\n }\n\n /**\n * Normalize and validate config\n */\n private normalizeConfig(config: CevroMessengerConfig): CevroMessengerConfig {\n return {\n ...config,\n apiBase: config.apiBase.replace(/\\/$/, ''), // Remove trailing slash\n alignment: config.alignment || 'right',\n verticalPadding: config.verticalPadding ?? 20,\n horizontalPadding: config.horizontalPadding ?? 20,\n theme: config.theme || 'light',\n zIndex: config.zIndex ?? 2147483647,\n debug: config.debug ?? false,\n };\n }\n\n /**\n * Setup internal event handlers\n */\n private setupEventHandlers(): void {\n // Handle incoming messages\n this.events.on('message:received', (data: { ticketId: string; message: Message }) => {\n this.log('Received message:', data);\n\n // Stop typing cycle and hide indicator when message arrives\n this.stopTypingCycle();\n\n if (this.chatWindow) {\n this.chatWindow.addMessage(data.message);\n }\n\n // Update unread count if window is not visible\n if (!this.isVisible) {\n this.setUnreadCount(this.unreadCount + 1);\n }\n });\n\n // Handle typing indicators from backend\n this.events.on('typing:start', (data: { ticketId: string; actor: string }) => {\n this.log('Typing started:', data);\n if (data.ticketId === this.api.getCurrentTicketId()) {\n this.startTypingCycle();\n }\n });\n\n this.events.on('typing:stop', (data: { ticketId: string; actor: string }) => {\n this.log('Typing stopped:', data);\n this.stopTypingCycle();\n });\n\n // Handle conversation started\n this.events.on('conversation:started', (data: { ticketId: string }) => {\n this.log('Conversation started:', data);\n });\n\n // Handle conversation/ticket status updates\n // Note: Currently using lazy detection (on send error) for closed tickets\n // This handler is kept for future real-time updates when backend supports it\n this.events.on('conversation:updated', (data: { ticketId: string; status: string }) => {\n this.log('Conversation updated:', data);\n });\n\n // Handle connection events\n this.events.on('connection:open', () => {\n this.log('WebSocket connected');\n });\n\n this.events.on('connection:close', () => {\n this.log('WebSocket disconnected');\n });\n\n this.events.on('connection:error', (data: { error: string }) => {\n this.log('WebSocket error:', data.error);\n });\n }\n\n /**\n * Boot the messenger\n */\n boot(): void {\n if (this.isBooted) {\n this.log('Already booted');\n return;\n }\n\n this.log('Booting...');\n\n // Create container\n this.container = document.createElement('div');\n this.container.id = 'cevro-messenger-container';\n document.body.appendChild(this.container);\n\n // Create launcher (if not hidden)\n if (!this.config.hideDefaultLauncher) {\n this.launcher = new Launcher(this.config, () => this.toggle());\n this.container.appendChild(this.launcher.render());\n }\n\n // Setup custom launcher if provided\n if (this.config.customLauncherSelector) {\n const customLauncher = document.querySelector(this.config.customLauncherSelector);\n if (customLauncher) {\n customLauncher.addEventListener('click', () => this.toggle());\n }\n }\n\n // Create chat window\n this.chatWindow = new ChatWindow(this.config, {\n onClose: () => this.hide(),\n onSendMessage: (message) => this.sendMessage(message),\n onQuickAction: (action) => this.handleQuickAction(action),\n onFileUpload: (file) => this.handleFileUpload(file),\n });\n this.container.appendChild(this.chatWindow.render());\n\n // Check for existing session (will be properly restored on show())\n const storedSession = getStoredSession();\n if (storedSession?.ticketId) {\n this.api.setCurrentTicketId(storedSession.ticketId);\n }\n\n this.isBooted = true;\n this.events.emit('boot');\n\n // WebSocket connection moved to show() - only connect when chat is opened\n\n this.log('Booted successfully');\n }\n\n /**\n * Connect to Centrifugo WebSocket server\n * Fetches connection token from API first\n *\n * Security: Uses signed visitorToken to prevent visitor spoofing\n */\n private async connectWebSocket(): Promise<void> {\n // If already connecting, wait for existing promise\n if (this.connectingPromise) {\n this.log('Already connecting to WebSocket, waiting...');\n return this.connectingPromise;\n }\n\n this.connectingPromise = this.doConnectWebSocket();\n return this.connectingPromise;\n }\n\n private async doConnectWebSocket(): Promise<void> {\n try {\n this.log('Fetching Centrifugo connection token...');\n\n // Get stored visitorToken (signed by server)\n const storedVisitorToken = getStoredVisitorToken();\n\n const result = await this.api.getConnectionToken(storedVisitorToken);\n\n // Always update visitorId from server response\n this.visitorId = result.visitorId;\n this.log('Visitor:', result.visitorId);\n\n // Store the visitorToken from server if provided\n if (result.visitorToken) {\n storeVisitorToken(result.visitorToken);\n this.api.setVisitorToken(result.visitorToken);\n }\n\n this.log('Got connection token, connecting to Centrifugo...');\n this.ws.connect(result.visitorId, result.token);\n\n this.events.emit('ready');\n } catch (error) {\n this.log('Failed to connect to WebSocket:', error);\n // Still emit ready - SDK works without real-time, just with polling\n this.events.emit('ready');\n this.events.emit('error', { type: 'websocket_connect', error });\n } finally {\n this.connectingPromise = null;\n }\n }\n\n /**\n * Refresh connection token for Centrifugo\n * Called automatically when token expires or on reconnect\n */\n private async refreshConnectionToken(): Promise<string> {\n this.log('Refreshing Centrifugo connection token...');\n\n const storedVisitorToken = getStoredVisitorToken();\n const result = await this.api.getConnectionToken(storedVisitorToken);\n\n // Update visitorToken if returned\n if (result.visitorToken) {\n storeVisitorToken(result.visitorToken);\n this.api.setVisitorToken(result.visitorToken);\n }\n\n this.log('Token refreshed for visitor:', result.visitorId);\n return result.token;\n }\n\n /**\n * Shutdown the messenger\n * @param options.clearVisitorData - If true, clears visitor token (visitor will get new identity on next init)\n */\n shutdown(options?: { clearVisitorData?: boolean }): void {\n if (!this.isBooted) {\n return;\n }\n\n this.log('Shutting down...');\n\n // Stop typing cycle\n this.stopTypingCycle();\n\n // Disconnect WebSocket\n this.ws.disconnect();\n\n // Destroy UI components\n this.launcher?.destroy();\n this.chatWindow?.destroy();\n\n // Remove container\n if (this.container && this.container.parentNode) {\n this.container.parentNode.removeChild(this.container);\n }\n\n // Clear stored data\n clearStoredSession();\n if (options?.clearVisitorData) {\n clearStoredVisitorToken();\n this.visitorId = null;\n }\n this.api.clear();\n\n // Reset state\n this.launcher = null;\n this.chatWindow = null;\n this.container = null;\n this.isBooted = false;\n this.isVisible = false;\n this.unreadCount = 0;\n this.isSessionInitialized = false;\n this.isInitializingSession = null;\n this.connectingPromise = null;\n\n this.events.emit('shutdown');\n this.log('Shutdown complete');\n }\n\n /**\n * Update player data\n * If playerId is provided and we have an existing visitor session,\n * this will merge the visitor with the authenticated player\n */\n async update(playerData: Partial<PlayerData>): Promise<void> {\n const hadPlayerId = !!this.config.player?.playerId;\n\n this.config.player = {\n ...this.config.player,\n ...playerData,\n } as PlayerData;\n\n this.log('Player data updated:', this.config.player);\n\n // If we're adding playerId for the first time (visitor → player),\n // re-initialize session to merge contacts\n if (!hadPlayerId && playerData.playerId && this.isSessionInitialized) {\n this.log('Player ID added, re-initializing session for merge...');\n this.isSessionInitialized = false;\n await this.initializeSession();\n }\n }\n\n /**\n * Show the messenger\n */\n async show(): Promise<void> {\n if (!this.isBooted) {\n this.boot();\n }\n\n if (this.chatWindow) {\n this.chatWindow.show();\n this.isVisible = true;\n this.launcher?.setOpen(true);\n this.setUnreadCount(0);\n this.events.emit('show');\n\n // Connect to WebSocket first (gets visitorId from server), then initialize session\n await this.connectWebSocket();\n await this.initializeSession();\n }\n }\n\n /**\n * Initialize session with backend\n * Creates/retrieves Contact and Ticket, loads existing messages\n * Uses promise pattern to ensure proper waiting when called concurrently\n */\n private async initializeSession(forceNew = false): Promise<void> {\n // If forcing new session, reset state\n if (forceNew) {\n this.isSessionInitialized = false;\n this.isInitializingSession = null;\n }\n\n // Already initialized - nothing to do\n if (this.isSessionInitialized) {\n return;\n }\n\n // If initialization is in progress, wait for it to complete\n if (this.isInitializingSession) {\n return this.isInitializingSession;\n }\n\n // Start new initialization - wrap with finally to ensure cleanup\n const initPromise = this.doInitializeSession().finally(() => {\n // Only clear if this is still the current initialization promise\n if (this.isInitializingSession === initPromise) {\n this.isInitializingSession = null;\n }\n });\n\n this.isInitializingSession = initPromise;\n return initPromise;\n }\n\n /**\n * Actual session initialization logic\n */\n private async doInitializeSession(options?: { forceNewTicket?: boolean }): Promise<void> {\n this.log('Initializing session...', options);\n\n try {\n const result = await this.api.initSession(this.visitorId, options);\n\n this.log('Session initialized:', result);\n\n // Store session data\n storeSession(result.sessionId, result.contactId, result.ticketId);\n this.isSessionInitialized = true;\n\n // Set agent info in header\n if (result.agent && this.chatWindow) {\n this.chatWindow.setAgent(result.agent);\n }\n\n // Store typing config from server\n if (result.typingConfig) {\n this.typingConfig = result.typingConfig;\n this.log('Typing config:', this.typingConfig);\n }\n\n // Load existing messages into chat window\n if (result.messages && result.messages.length > 0) {\n this.log(`Loading ${result.messages.length} existing messages`);\n for (const message of result.messages) {\n this.chatWindow?.addMessage(message);\n }\n }\n\n // Handle closed ticket state\n if (result.ticketClosed) {\n this.log('Ticket is closed:', result.ticketClosedReason);\n this.chatWindow?.setTicketClosed(true, () => this.startNewChat());\n }\n\n this.events.emit('session:initialized', {\n sessionId: result.sessionId,\n contactId: result.contactId,\n ticketId: result.ticketId,\n isNewSession: result.isNewSession,\n isNewTicket: result.isNewTicket,\n ticketClosed: result.ticketClosed,\n messageCount: result.messages?.length || 0,\n });\n\n } catch (error) {\n this.log('Failed to initialize session:', error);\n this.events.emit('error', { type: 'session_init', error });\n throw error; // Re-throw so callers know it failed\n }\n }\n\n /**\n * Start a new chat (creates a new ticket)\n * Used when the previous chat was closed\n */\n async startNewChat(): Promise<void> {\n this.log('Starting new chat...');\n\n // Clear current chat window messages\n this.chatWindow?.clearMessages();\n this.chatWindow?.setTicketClosed(false);\n\n // Re-initialize session with forceNewTicket\n this.isSessionInitialized = false;\n await this.doInitializeSession({ forceNewTicket: true });\n\n this.events.emit('chat:new_started');\n }\n\n /**\n * Hide the messenger\n */\n hide(): void {\n if (this.chatWindow) {\n this.chatWindow.hide();\n this.isVisible = false;\n this.launcher?.setOpen(false);\n this.events.emit('hide');\n }\n }\n\n /**\n * Toggle messenger visibility\n */\n toggle(): void {\n if (this.isVisible) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n /**\n * Maximum message length (2000 characters)\n */\n private static readonly MAX_MESSAGE_LENGTH = 2000;\n\n /**\n * Send a message\n */\n async sendMessage(message: string): Promise<void> {\n if (!message.trim()) return;\n\n // Validate message length\n if (message.length > CevroMessenger.MAX_MESSAGE_LENGTH) {\n this.log('Message too long:', message.length);\n this.events.emit('error', {\n type: 'validation',\n error: new Error(`Message is too long. Maximum ${CevroMessenger.MAX_MESSAGE_LENGTH} characters allowed.`),\n message: `Message is too long. Maximum ${CevroMessenger.MAX_MESSAGE_LENGTH} characters allowed.`,\n });\n return;\n }\n\n this.log('Sending message:', message);\n\n // Create optimistic message\n // inbound: true = user's message going TO backend (consistent with backend storage)\n const optimisticMessage: Message = {\n id: 'temp_' + Date.now(),\n body: message,\n inbound: true,\n outbound: false,\n createdAt: new Date().toISOString(),\n type: 'text',\n status: 'sending',\n };\n\n // Add to UI immediately\n this.chatWindow?.addMessage(optimisticMessage);\n\n try {\n // Ensure session is initialized before sending\n if (!this.isSessionInitialized) {\n await this.initializeSession();\n }\n\n // Store original temp id for lookup\n const tempId = optimisticMessage.id;\n\n // Send message to existing conversation\n const result = await this.api.sendMessage(message);\n\n // Update optimistic message with real data\n optimisticMessage.id = result.id;\n optimisticMessage.status = 'sent';\n this.chatWindow?.updateMessage(optimisticMessage, tempId);\n\n this.events.emit('message:sent', { message: result });\n\n // Typing indicator will be shown by backend via WebSocket event\n\n } catch (error: any) {\n this.log('Error sending message:', error);\n\n // Check if conversation is closed\n const isConversationClosed =\n error?.message?.includes('closed') ||\n error?.message?.includes('resolved') ||\n error?.message?.includes('escalated') ||\n error?.response?.data?.message?.includes('closed');\n\n if (isConversationClosed) {\n this.log('Conversation is closed, showing closed UI');\n\n // Remove the failed optimistic message\n this.chatWindow?.removeMessage(optimisticMessage.id);\n\n // Show closed UI with \"New Conversation\" button\n this.chatWindow?.setTicketClosed(true, () => this.startNewChat());\n return;\n }\n\n // Update optimistic message with error status\n optimisticMessage.status = 'failed';\n this.chatWindow?.updateMessage(optimisticMessage);\n\n this.events.emit('error', { error, type: 'send_message' });\n }\n }\n\n /**\n * Show new message composer with pre-filled text\n */\n showNewMessage(prefilledText?: string): void {\n this.show();\n\n if (prefilledText && this.chatWindow) {\n // Pre-fill the input (would need to expose this in ChatWindow)\n this.log('Pre-filling message:', prefilledText);\n }\n }\n\n /**\n * Handle quick action click\n */\n private async handleQuickAction(action: QuickAction): Promise<void> {\n this.log('Quick action clicked:', action);\n\n if (action.type === 'link' && action.url) {\n // Validate URL to prevent XSS via javascript: protocol\n if (isValidUrl(action.url)) {\n window.open(action.url, '_blank');\n } else {\n this.log('Invalid URL blocked:', action.url);\n }\n } else {\n // Send the action value as a message\n await this.sendMessage(action.value || action.label);\n }\n }\n\n /**\n * Handle file upload with progress tracking\n * Shows preview immediately, then uploads to S3, then sends to backend\n *\n * Security: File is validated before upload (size, type, extension)\n */\n private async handleFileUpload(file: File): Promise<void> {\n this.log('File upload:', file.name, file.type, file.size);\n\n // Variables for cleanup on error\n let localPreviewUrl: string | undefined;\n let tempId: string | undefined;\n\n try {\n // Ensure session is initialized before uploading\n if (!this.isSessionInitialized) {\n await this.initializeSession();\n }\n\n // Determine file type for display\n const isImage = file.type.startsWith('image/');\n const fileCategory = this.getFileCategory(file.type);\n\n // Create local preview URL for images\n localPreviewUrl = isImage ? URL.createObjectURL(file) : undefined;\n\n // Create optimistic message IMMEDIATELY (before upload starts)\n tempId = 'temp_' + Date.now();\n const optimisticMessage: Message = {\n id: tempId,\n body: '',\n inbound: true,\n outbound: false,\n createdAt: new Date().toISOString(),\n type: isImage ? 'image' : 'file',\n mediaUrl: localPreviewUrl,\n mediaType: file.type,\n status: 'sending',\n attachment: {\n filename: file.name,\n contentType: file.type || 'application/octet-stream',\n size: file.size,\n category: fileCategory,\n },\n };\n\n // Show preview in chat immediately\n this.chatWindow?.addMessage(optimisticMessage);\n\n // Now start the upload with progress (validation happens inside uploadFile)\n const assetId = await this.api.uploadFile(file, (progress) => {\n // Update progress in the message itself\n this.chatWindow?.updateMessageProgress(tempId!, progress);\n });\n\n // Send message to backend\n const result = await this.api.sendMessage('', assetId);\n\n // Update with real data from server, keeping blob URL if server didn't return mediaUrl\n const serverHasMediaUrl = result.mediaUrl && isValidUrl(result.mediaUrl);\n\n const updatedMessage: Message = {\n ...result,\n status: 'sent',\n type: isImage ? 'image' : 'file',\n mediaUrl: serverHasMediaUrl ? result.mediaUrl : localPreviewUrl,\n attachment: optimisticMessage.attachment,\n };\n this.chatWindow?.updateMessage(updatedMessage, tempId);\n\n // Only revoke blob URL if server returned a real URL\n if (localPreviewUrl && serverHasMediaUrl) {\n URL.revokeObjectURL(localPreviewUrl);\n }\n\n this.events.emit('message:sent', { type: fileCategory, fileName: file.name });\n\n } catch (error: any) {\n this.log('Error uploading file:', error);\n\n // Clean up blob URL on error\n if (localPreviewUrl) {\n URL.revokeObjectURL(localPreviewUrl);\n }\n\n // Remove failed optimistic message from UI\n if (tempId) {\n this.chatWindow?.removeMessage(tempId);\n }\n\n // Determine error type for better UX\n const errorMessage = error?.message || 'File upload failed';\n const isValidationError =\n errorMessage.includes('too large') ||\n errorMessage.includes('too small') ||\n errorMessage.includes('not allowed') ||\n errorMessage.includes('Too many uploads');\n\n // Emit specific error event with details\n this.events.emit('error', {\n error,\n type: isValidationError ? 'file_validation' : 'file_upload',\n message: errorMessage,\n fileName: file.name,\n });\n }\n }\n\n /**\n * Get file category for display purposes\n */\n private getFileCategory(mimeType: string): 'image' | 'pdf' | 'document' | 'spreadsheet' | 'presentation' | 'video' | 'audio' | 'archive' | 'text' | 'file' {\n if (mimeType.startsWith('image/')) return 'image';\n if (mimeType === 'application/pdf') return 'pdf';\n if (mimeType.includes('word') || mimeType.includes('document')) return 'document';\n if (mimeType.includes('sheet') || mimeType.includes('excel')) return 'spreadsheet';\n if (mimeType.includes('presentation') || mimeType.includes('powerpoint')) return 'presentation';\n if (mimeType.startsWith('video/')) return 'video';\n if (mimeType.startsWith('audio/')) return 'audio';\n if (mimeType.includes('zip') || mimeType.includes('archive') || mimeType.includes('compressed')) return 'archive';\n if (mimeType.startsWith('text/')) return 'text';\n return 'file';\n }\n\n /**\n * Set unread count\n */\n private setUnreadCount(count: number): void {\n this.unreadCount = count;\n this.launcher?.setUnreadCount(count);\n this.events.emit('unread_count_change', { count });\n }\n\n /**\n * Get current unread count\n */\n getUnreadCount(): number {\n return this.unreadCount;\n }\n\n /**\n * Get visitor ID (null if not yet assigned by server)\n */\n getVisitorId(): string | null {\n return this.visitorId;\n }\n\n /**\n * Subscribe to an event\n */\n on<T = any>(event: EventType, handler: EventHandler<T>): () => void {\n return this.events.on(event, handler);\n }\n\n /**\n * Subscribe to an event (once)\n */\n once<T = any>(event: EventType, handler: EventHandler<T>): () => void {\n return this.events.once(event, handler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off(event: EventType, handler: EventHandler): void {\n this.events.off(event, handler);\n }\n\n /**\n * Track custom event\n */\n trackEvent(eventName: string, metadata?: Record<string, any>): void {\n this.log('Track event:', eventName, metadata);\n // Could send to backend for analytics\n }\n\n /**\n * Start typing indicator cycle (5s on, 5s off, repeat)\n */\n private startTypingCycle(): void {\n // Clear any existing cycle\n this.stopTypingCycle();\n\n const { onDurationMs, offDurationMs } = this.typingConfig;\n\n const runCycle = () => {\n if (this.isTypingVisible) {\n // Currently showing - hide it\n this.chatWindow?.hideTypingIndicator();\n this.isTypingVisible = false;\n this.log('Typing cycle: hidden');\n // Schedule next show after pause\n this.typingCycleTimeout = setTimeout(runCycle, offDurationMs);\n } else {\n // Currently hidden - show it\n this.chatWindow?.showTypingIndicator();\n this.isTypingVisible = true;\n this.log('Typing cycle: visible');\n // Schedule next hide after typing duration\n this.typingCycleTimeout = setTimeout(runCycle, onDurationMs);\n }\n };\n\n // Start immediately with typing visible\n this.chatWindow?.showTypingIndicator();\n this.isTypingVisible = true;\n this.log('Typing cycle: started');\n\n // Schedule first toggle (hide after typing duration)\n this.typingCycleTimeout = setTimeout(runCycle, onDurationMs);\n }\n\n /**\n * Stop typing indicator cycle\n */\n private stopTypingCycle(): void {\n if (this.typingCycleTimeout) {\n clearTimeout(this.typingCycleTimeout);\n this.typingCycleTimeout = null;\n }\n\n if (this.isTypingVisible) {\n this.chatWindow?.hideTypingIndicator();\n this.isTypingVisible = false;\n }\n\n this.log('Typing cycle: stopped');\n }\n\n /**\n * Log helper\n */\n private log(...args: any[]): void {\n if (this.config.debug) {\n console.log('[CevroMessenger]', ...args);\n }\n }\n}\n","/**\n * Cevro Messenger SDK\n *\n * A customer support chat widget for web applications.\n *\n * @example\n * // ES Module\n * import CevroMessenger from '@cevro/messenger-sdk';\n *\n * const messenger = new CevroMessenger({\n * apiBase: 'https://api.yoursite.com',\n * workspaceId: 'your-workspace-id',\n * });\n *\n * messenger.boot();\n *\n * @example\n * // UMD (Script tag)\n * <script src=\"https://cdn.jsdelivr.net/npm/@cevro/messenger-sdk\"></script>\n * <script>\n * const messenger = new CevroMessenger({\n * apiBase: 'https://api.yoursite.com',\n * workspaceId: 'your-workspace-id',\n * });\n * messenger.boot();\n * </script>\n */\n\n// Import styles (will be injected by vite plugin)\nimport './styles/index.css';\n\n// Export main class\nexport { CevroMessenger } from './core/CevroMessenger';\n\n// Export types\nexport type {\n CevroMessengerConfig,\n PlayerData,\n SessionData,\n Message,\n Conversation,\n QuickAction,\n RichContent,\n EventType,\n EventHandler,\n} from './types';\n\n// Default export for convenience\nimport { CevroMessenger } from './core/CevroMessenger';\nexport default CevroMessenger;\n\n// Global instance management for UMD builds\ndeclare global {\n interface Window {\n CevroMessenger: typeof CevroMessenger;\n cevroMessenger?: CevroMessenger;\n }\n}\n\n// Auto-attach to window for UMD builds\nif (typeof window !== 'undefined') {\n window.CevroMessenger = CevroMessenger;\n}\n"],"names":["EventEmitter$2","constructor","__publicField","this","Map","on","event","handler","listeners","has","set","Set","get","add","off","once","onceHandler","data","onceHandlers","delete","handlers","emit","forEach","error","console","removeAllListeners","clear","listenerCount","_a","size","getStoredVisitorToken","localStorage","getItem","storeVisitorToken","token","setItem","generateVisitorId","lastDotIndex","lastIndexOf","substring","extractVisitorIdFromToken","getStoredVisitorId","ALLOWED_MIME_TYPES","BLOCKED_EXTENSIONS","DEFAULT_FILE_CONSTRAINTS","maxSizeBytes","minSizeBytes","maxFilenameLength","getFileExtension","filename","lastDot","length","toLowerCase","formatFileSize","bytes","i","Math","floor","log","parseFloat","pow","toFixed","UploadRateLimiter","maxUploads","windowMs","canUpload","now","Date","uploadTimestamps","filter","timestamp","recordUpload","push","getRemainingUploads","max","getTimeUntilNextUpload","oldestTimestamp","min","reset","ApiClient","config","maxUploadsPerMinute","fileUpload","uploadRateLimiter","setVisitorToken","visitorToken","getVisitorToken","setAccessToken","accessToken","getContactId","contactId","getCurrentTicketId","currentTicketId","setCurrentTicketId","ticketId","getCurrentAgent","currentAgent","request","endpoint","options","url","apiBase","headers","workspaceId","brandId","response","fetch","ok","json","catch","message","statusText","Error","status","initSession","visitorId","payload","session","window","navigator","userAgent","language","platform","timezone","Intl","DateTimeFormat","resolvedOptions","timeZone","currentPage","location","href","pageTitle","document","title","referrer","screenWidth","screen","width","screenHeight","height","viewportWidth","innerWidth","viewportHeight","innerHeight","devicePixelRatio","urlParams","URLSearchParams","search","utmSource","utmMedium","utmCampaign","utmContent","utmTerm","cookiesEnabled","cookieEnabled","touchSupport","maxTouchPoints","online","onLine","connection","connectionType","effectiveType","e","collectSessionData","firstName","player","lastName","_b","email","_c","phone","_d","customAttributes","_e","locale","forceNewTicket","_f","playerId","playerHash","result","method","body","JSON","stringify","agent","sessionId","isNewSession","isNewTicket","ticketClosed","ticketClosedReason","typingConfig","messages","_g","map","msg","normalizeMessage","sendMessage","assetId","getMessages","targetTicketId","results","getMyTickets","tickets","ticket","normalizeConversation","uploadFile","file","onProgress","waitTime","ceil","validation","allowedMimeTypes","blockedExtensions","valid","errorCode","name","extension","mimeType","type","validateFile","additionalBlockedExtensions","sanitizedFilename","sanitized","replace","ext","nameWithoutExt","slice","maxNameLength","sanitizeFilename","uploadUrl","contentType","uploadToS3","Promise","resolve","reject","xhr","XMLHttpRequest","upload","addEventListener","lengthComputable","progress","round","loaded","total","open","setRequestHeader","send","id","objectId","inbound","outbound","createdAt","toISOString","mediaUrl","mediaType","richContent","conversationId","updatedAt","resolved","escalated","unreadCount","lastMessage","latestMessage","getConnectionToken","refreshConnectionToken","__awaiter","thisArg","_arguments","P","generator","fulfilled","value","step","next","rejected","done","then","apply","getDefaultExportFromCjs","x","__esModule","Object","prototype","hasOwnProperty","call","SuppressedError","ReflectOwnKeys","events","exports","R","Reflect","ReflectApply","target","receiver","args","Function","ownKeys","getOwnPropertySymbols","getOwnPropertyNames","concat","NumberIsNaN","Number","isNaN","EventEmitter","init","emitter","errorListener","err","removeListener","resolver","arguments","eventTargetAgnosticAddListener","flags","addErrorHandlerIfEventEmitter","_events","_eventsCount","_maxListeners","defaultMaxListeners","checkListener","listener","TypeError","_getMaxListeners","that","_addListener","prepend","m","existing","warning","create","newListener","unshift","warned","w","String","count","warn","onceWrapper","fired","wrapFn","_onceWrap","state","wrapped","bind","_listeners","unwrap","evlistener","arr","ret","Array","unwrapListeners","arrayClone","n","copy","wrapListener","arg","removeEventListener","defineProperty","enumerable","RangeError","getPrototypeOf","setMaxListeners","getMaxListeners","doError","er","context","len","addListener","prependListener","prependOnceListener","list","position","originalListener","shift","index","pop","spliceOne","key","keys","rawListeners","eventNames","errorCodes","connectingCodes","disconnectedCodes","subscribingCodes","unsubscribedCodes","subscriptionFlags","State","SubscriptionState","EventEmitter$1","isFunction","backoff","interval","random","randomInt","ttlMilliseconds","ttl","Subscription","centrifuge","channel","super","_resubscribeTimeout","_refreshTimeout","Unsubscribed","_centrifuge","_token","_getToken","_data","_getData","_recover","_offset","_epoch","_id","_recoverable","_positioned","_joinLeave","_minResubscribeDelay","_maxResubscribeDelay","_resubscribeAttempts","_promises","_promiseId","_inflight","_delta","_delta_negotiated","_tagsFilter","_prevValue","_unsubPromise","_setOptions","_debugEnabled","ctx","_debug","oldState","newState","ready","timeout","code","subscriptionUnsubscribed","Subscribed","res","rej","setTimeout","_nextPromiseId","subscribe","_isSubscribed","_setSubscribing","subscribeCalled","unsubscribe","_setUnsubscribed","unsubscribeCalled","publish","_methodCall","presence","presenceStats","history","opts","setTagsFilter","tagsFilter","setData","_isUnsubscribed","timeoutDuration","_config","_needRecover","_isSubscribing","Subscribing","_setState","_usesToken","_clearSubscribingState","_clearResubscribeTimeout","_clearSubscribedState","_clearRefreshTimeout","_setSubscribed","recoverable","offset","epoch","delta","_getSubscribeContext","_resolvePromises","pubs","publications","_handlePublication","expires","_refresh","reason","_transport","emulation","_subscribe","_isTransportOpen","_canSubscribeWithoutGettingToken","_subscribeWithoutToken","_getSubscriptionToken","_handleTokenResponse","_handleTokenError","_transportIsOpen","_getDataAndSubscribe","_sendSubscribe","_handleGetDataError","UnauthorizedError","_failUnauthorized","badConfiguration","toString","_scheduleResubscribe","subscriptionSubscribeToken","cmd","_buildSubscribeCommand","_call","resolveCtx","reply","_handleSubscribeResponse","rejectCtx","_handleSubscribeError","req","positioned","join_leave","flag","channelCompaction","recover","_getOffset","_getEpoch","tf","_subscribeError","_disconnect","subscribeTimeout","sendUnsubscribe","promise","_unsubscribe","_rejectPromises","pub","newData","newPrevValue","_codec","applyDeltaIfNeeded","_getPublicationContext","_handleJoin","join","info","_getJoinLeaveContext","_handleLeave","leave","clearTimeout","self","delay","_getResubscribeDelay","temporary","errContext","Connected","since","getData","minResubscribeDelay","maxResubscribeDelay","getToken","joinLeave","sub_refresh","_refreshResponse","_refreshError","subscriptionRefreshToken","_getRefreshRetryDelay","unauthorized","SockjsTransport","subName","transport","supported","sockjs","initialize","_protocol","callbacks","sockjsOptions","onopen","onOpen","onerror","onError","onclose","closeEvent","onClose","onmessage","onMessage","close","WebsocketTransport","websocket","protocol","subProtocol","binaryType","HttpStreamTransport","_abortController","_utf8decoder","TextDecoder","_handleErrors","_fetchEventTarget","eventTarget","EventTarget","fetchFunc","dispatchEvent","Event","jsonStreamBuf","jsonStreamPos","protoStreamBuf","Uint8Array","reader","getReader","readableStream","start","controller","pump","read","decode","line","MessageEvent","mergedArray","decoder","decodeReply","pos","detail","AbortController","initialData","Accept","fetchOptions","mode","credentials","signal","abort","node","encoder","encodeEmulationRequest","emulationEndpoint","SseTransport","_onClose","eventsource","globalThis","baseURI","URL","searchParams","append","eventSource","WebtransportTransport","_stream","_writer","webtransport","closed","stream","createBidirectionalStream","writable","getWriter","_startReading","readable","binary","TextEncoder","encode","write","zValue","Reader","array","a","haveBytes","getByte","b","getChar","fromCharCode","getInt","c","v","Writer","toByteArray","sourceType","isArray","putArray","end","checksum","sum0","sum1","sum2","sum3","z","N","JsonCodec","encodeCommands","commands","decodeReplies","trim","split","r","parse","prevValue","valueArray","source","zDelta","lenSrc","lenDelta","limit","zOut","cnt","ofst","out","applyDelta","defaults","debug","version","minReconnectDelay","maxReconnectDelay","maxServerPingDelay","networkEventTarget","Centrifuge","_reconnectTimeout","_serverPingTimeout","Disconnected","_endpoint","_emulation","_transports","_currentTransportIndex","_triedAllTransports","_transportWasOpen","_transportId","_deviceWentOffline","_transportClosed","_reconnecting","_reconnectAttempts","_client","_session","_node","_subs","_serverSubs","_commandId","_commands","_batching","_refreshRequired","_callbacks","_dispatchPromise","_serverPing","_sendPong","_networkEventsSet","assign","_configure","newSubscription","getSubscription","sub","_getSub","removeSubscription","_removeSubscription","subscriptions","clientDisconnected","connect","_isConnected","_isConnecting","_startConnecting","disconnect","disconnectCalled","setToken","setHeaders","_transportSendCommands","_createErrorObject","transportWriteError","rpc","_callPromise","_getHistoryRequest","clients","clientId","rawClient","connInfo","chanInfo","presence_stats","numUsers","num_users","numClients","num_clients","startBatching","stopBatching","_flush","level","logger","_codecName","_formatOverride","transportConfig","transportName","indexOf","_isDisconnected","Connecting","_nextCommandId","_setNetworkEvents","transportClosed","_clearReconnectTimeout","_startReconnecting","_getReconnectDelay","_clearOutgoingRequests","errback","connectionClosed","_clearConnectedState","_clearServerPingTimeout","_handleWriteError","command","_initializeTransport","WebSocket","SockJS","EventSource","ReadableStream","transportEndpoint","WebTransport","prefix","transportId","_nextTransportId","wasOpen","initialCommands","connectCommand","_sendConnect","connectTimeout","_sendSubscribeCommands","needReconnect","advice","reconnect","messageSizeLimit","_dataReceived","skipSending","_constructConnectCommand","_connectResponse","_connectError","emptyToken","clientConnectToken","_scheduleReconnect","isInitialHandshake","subs","hasSubs","reverse","resultCB","_waitServerPing","replies","finishDispatch","_dispatchSynchronized","p","_dispatchReply","_handleReply","_handlePush","_handleServerPing","_registerCall","_addCommand","connectCalled","previousState","needEvent","refresh","clientRefreshToken","client","_","unsubscribeError","ch","_isServerSub","_processServerSubs","ping","pong","subCtx","recovered","noPing","wasRecovering","hasRecoveredPublications","was_recovering","streamPosition","callback","_handleUnsubscribe","_handleSubscribe","_handleDisconnect","tags","clientInfo","user","_handleMessage","errObject","WebSocketClient","setTokenRefreshCallback","getTokenCallback","userId","connectionToken","wsUrl","getWebSocketUrl","async","newToken","setupClientEventListeners","centrifugoUrl","apiUrl","host","subscribeToPersonalChannel","channelName","personalSub","handleMessage","isTyping","actor","senderType","chatOpen","updateToken","isConnected","getUserId","createElement","tag","attributes","children","element","entries","className","startsWith","setAttribute","child","appendChild","createTextNode","isValidUrl","parsed","origin","includes","parseMarkdown","text","div","textContent","innerHTML","escapeHtml","_match","linkText","safeUrl","sanitizeUrl","scrollToBottom","smooth","scrollTo","top","scrollHeight","behavior","generateId","Launcher","onClick","render","applyPositioning","button","chatIcon","createChatIcon","classList","closeIcon","createCloseIcon","unreadBadge","style","display","alignment","vPadding","verticalPadding","hPadding","horizontalPadding","bottom","left","right","zIndex","svg","createElementNS","path","polyline","setOpen","isOpen","toggle","setUnreadCount","show","hide","destroy","parentNode","removeChild","MessageList","setQuickActionHandler","onQuickAction","messagesContainer","autoScroll","threshold","scrollTop","clientHeight","isScrolledToBottom","addMessage","animate","updateMessage","messageEl","createMessageElement","oldId","lookupId","existingEl","newEl","replaceChild","updateMessageProgress","messageId","progressFill","querySelector","progressText","removeMessage","remove","isMyMessage","wrapper","avatar","createBotAvatarSvg","contentWrapper","bubble","isImage","attachment","category","imageContainer","img","src","alt","loading","progressOverlay","createProgressOverlay","fileCard","createFileCard","link","rel","getFileIcon","quickActions","actionsContainer","action","label","meta","date","toLocaleTimeString","hour","minute","getStatusIcon","overlay","isUploading","card","iconWrapper","truncateFilename","details","cursor","icons","pdf","spreadsheet","presentation","video","audio","archive","image","maxLength","showTypingIndicator","hideTypingIndicator","indicator","getElementById","closedMessageElement","showClosedMessage","hideClosedMessage","ChatWindow","messageList","header","createHeader","messagesArea","inputWrapper","createInputArea","applyTheme","agentAvatarElement","createDefaultAvatarSvg","titleSection","agentNameElement","subtitle","closeButton","setAgent","avatarUrl","inputArea","fileButton","fileInput","accept","accepts","generateAcceptAttribute","files","onFileUpload","click","inputElement","placeholder","rows","updateSendButtonState","shiftKey","preventDefault","handleSend","sendButton","disabled","footer","onSendMessage","focus","theme","cleanupThemeListener","themeMediaQuery","matchMedia","prefersDark","matches","themeChangeHandler","clearMessages","isVisible","isWindowVisible","focusInput","setTicketClosed","onStartNewChat","showHistory","closedFooter","newChatButton","poweredBy","_CevroMessenger","onDurationMs","offDurationMs","normalizeConfig","api","ws","setupEventHandlers","instance","getInstance","stopTypingCycle","chatWindow","startTypingCycle","boot","isBooted","container","hideDefaultLauncher","launcher","customLauncherSelector","customLauncher","handleQuickAction","handleFileUpload","storedSession","stored","getStoredSession","connectWebSocket","connectingPromise","doConnectWebSocket","storedVisitorToken","shutdown","removeItem","clearStoredSession","clearVisitorData","clearStoredVisitorToken","isSessionInitialized","isInitializingSession","update","playerData","hadPlayerId","initializeSession","forceNew","initPromise","doInitializeSession","finally","storeSession","startNewChat","messageCount","MAX_MESSAGE_LENGTH","optimisticMessage","tempId","_h","_i","_j","_k","showNewMessage","prefilledText","localPreviewUrl","fileCategory","getFileCategory","createObjectURL","serverHasMediaUrl","updatedMessage","revokeObjectURL","fileName","errorMessage","isValidationError","getUnreadCount","getVisitorId","trackEvent","eventName","metadata","runCycle","isTypingVisible","typingCycleTimeout","CevroMessenger"],"mappings":"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","x_google_ignoreList":[4]}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/core/EventEmitter.ts","../../src/utils/session.ts","../../src/utils/file-validation.ts","../../src/core/ApiClient.ts","../../node_modules/centrifuge/build/index.mjs","../../src/core/WebSocketClient.ts","../../src/utils/dom.ts","../../src/ui/Launcher.ts","../../src/i18n/strings.ts","../../src/ui/MessageList.ts","../../src/ui/ChatWindow.ts","../../src/core/CevroMessenger.ts","../../src/index.ts"],"sourcesContent":["import type { EventType, EventHandler } from '../types';\n\n/**\n * Simple event emitter for SDK events\n */\nexport class EventEmitter {\n private listeners: Map<EventType, Set<EventHandler>> = new Map();\n private onceHandlers: Map<EventHandler, EventHandler> = new Map(); // Maps wrapper -> original\n\n /**\n * Subscribe to an event\n */\n on<T = any>(event: EventType, handler: EventHandler<T>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(handler);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n /**\n * Subscribe to an event (fires only once)\n */\n once<T = any>(event: EventType, handler: EventHandler<T>): () => void {\n const onceHandler: EventHandler<T> = (data) => {\n this.onceHandlers.delete(onceHandler);\n this.off(event, onceHandler);\n handler(data);\n };\n this.onceHandlers.set(onceHandler, handler);\n return this.on(event, onceHandler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off(event: EventType, handler: EventHandler): void {\n const handlers = this.listeners.get(event);\n if (handlers) {\n handlers.delete(handler);\n // Also clean up from onceHandlers if it was a once handler\n this.onceHandlers.delete(handler);\n }\n }\n\n /**\n * Emit an event\n */\n emit<T = any>(event: EventType, data?: T): void {\n const handlers = this.listeners.get(event);\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(data);\n } catch (error) {\n console.error(`[CevroMessenger] Error in event handler for \"${event}\":`, error);\n }\n });\n }\n }\n\n /**\n * Remove all listeners for an event (or all events if no event specified)\n */\n removeAllListeners(event?: EventType): void {\n if (event) {\n // Clean up once handlers for this event\n const handlers = this.listeners.get(event);\n if (handlers) {\n handlers.forEach((handler) => {\n this.onceHandlers.delete(handler);\n });\n }\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n this.onceHandlers.clear();\n }\n }\n\n /**\n * Get listener count for an event\n */\n listenerCount(event: EventType): number {\n return this.listeners.get(event)?.size || 0;\n }\n}\n","import type { SessionData } from '../types';\n\n/**\n * Collect browser session data\n */\nexport function collectSessionData(): SessionData {\n const session: SessionData = {};\n\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return session;\n }\n\n try {\n // Browser info\n session.userAgent = navigator.userAgent;\n session.language = navigator.language;\n session.platform = navigator.platform;\n session.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n\n // Page context\n session.currentPage = window.location.href;\n session.pageTitle = document.title;\n session.referrer = document.referrer;\n\n // Screen dimensions\n session.screenWidth = window.screen.width;\n session.screenHeight = window.screen.height;\n session.viewportWidth = window.innerWidth;\n session.viewportHeight = window.innerHeight;\n session.devicePixelRatio = window.devicePixelRatio;\n\n // UTM parameters from URL\n const urlParams = new URLSearchParams(window.location.search);\n session.utmSource = urlParams.get('utm_source') || undefined;\n session.utmMedium = urlParams.get('utm_medium') || undefined;\n session.utmCampaign = urlParams.get('utm_campaign') || undefined;\n session.utmContent = urlParams.get('utm_content') || undefined;\n session.utmTerm = urlParams.get('utm_term') || undefined;\n\n // Capabilities\n session.cookiesEnabled = navigator.cookieEnabled;\n session.touchSupport = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n session.online = navigator.onLine;\n\n // Connection info (if available)\n const connection = (navigator as any).connection;\n if (connection) {\n session.connectionType = connection.effectiveType;\n }\n } catch (e) {\n // Silently ignore errors in session collection\n }\n\n return session;\n}\n\n/**\n * Get stored visitor token (signed by server)\n */\nexport function getStoredVisitorToken(): string | null {\n try {\n return localStorage.getItem('cevro_visitor_token');\n } catch {\n return null;\n }\n}\n\n/**\n * Store visitor token received from server\n */\nexport function storeVisitorToken(token: string): void {\n try {\n localStorage.setItem('cevro_visitor_token', token);\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Extract visitorId from visitorToken\n * Token format: visitorId.signature\n */\nexport function extractVisitorIdFromToken(token: string): string | null {\n if (!token) return null;\n const lastDotIndex = token.lastIndexOf('.');\n if (lastDotIndex <= 0) return null;\n return token.substring(0, lastDotIndex);\n}\n\n/**\n * Get visitorId from stored token (or null if not available)\n */\nexport function getStoredVisitorId(): string | null {\n const token = getStoredVisitorToken();\n return token ? extractVisitorIdFromToken(token) : null;\n}\n\n/**\n * Get visitor ID from stored token, or null if not yet available.\n * The visitor ID is assigned by the server and stored in the visitor token.\n */\nexport function generateVisitorId(): string | null {\n return getStoredVisitorId();\n}\n\n/**\n * Stored session data\n */\nexport interface StoredSessionData {\n sessionId?: string;\n contactId?: string;\n ticketId?: string;\n}\n\n/**\n * Get stored session data\n */\nexport function getStoredSession(): StoredSessionData | null {\n try {\n const stored = localStorage.getItem('cevro_session');\n return stored ? JSON.parse(stored) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Store session data\n */\nexport function storeSession(sessionId: string, contactId: string, ticketId: string): void {\n try {\n localStorage.setItem('cevro_session', JSON.stringify({ sessionId, contactId, ticketId }));\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Clear stored session data\n */\nexport function clearStoredSession(): void {\n try {\n localStorage.removeItem('cevro_session');\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Clear stored visitor token\n * Use this when you want to completely reset the visitor identity\n */\nexport function clearStoredVisitorToken(): void {\n try {\n localStorage.removeItem('cevro_visitor_token');\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Clear all stored data (session + visitor token)\n */\nexport function clearAllStoredData(): void {\n clearStoredSession();\n clearStoredVisitorToken();\n}\n","/**\n * File validation utilities for secure file uploads\n * Provides client-side validation as first line of defense\n */\n\n/**\n * Allowed MIME types for file uploads\n * This whitelist prevents potentially dangerous file types\n */\nexport const ALLOWED_MIME_TYPES: ReadonlySet<string> = new Set([\n // Images\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/svg+xml',\n // Documents\n 'application/pdf',\n 'text/plain',\n 'text/csv',\n // Microsoft Office\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'application/vnd.ms-powerpoint',\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n // Audio/Video\n 'audio/mpeg',\n 'audio/wav',\n 'audio/ogg',\n 'video/mp4',\n 'video/webm',\n // Archives (optional - can be disabled)\n 'application/zip',\n 'application/x-rar-compressed',\n]);\n\n/**\n * Dangerous file extensions that should always be blocked\n * Even if MIME type looks safe, these extensions are risky\n */\nexport const BLOCKED_EXTENSIONS: ReadonlySet<string> = new Set([\n '.exe', '.dll', '.bat', '.cmd', '.sh', '.bash',\n '.ps1', '.psm1', '.psd1', // PowerShell\n '.vbs', '.vbe', '.js', '.jse', '.ws', '.wsf', '.wsc', '.wsh', // Scripts\n '.msi', '.msp', '.mst', // Windows installers\n '.scr', '.pif', '.com', // Executables\n '.hta', '.cpl', '.msc', // Control panel/settings\n '.jar', '.class', // Java\n '.php', '.php3', '.php4', '.php5', '.phtml', // PHP\n '.asp', '.aspx', '.ashx', '.asmx', // ASP.NET\n '.jsp', '.jspx', // JSP\n '.py', '.pyc', '.pyw', // Python\n '.rb', '.rbw', // Ruby\n '.pl', '.pm', '.cgi', // Perl/CGI\n '.htaccess', '.htpasswd', // Apache config\n]);\n\n/**\n * Default file upload constraints\n */\nexport const DEFAULT_FILE_CONSTRAINTS = {\n maxSizeBytes: 25 * 1024 * 1024, // 25MB\n minSizeBytes: 1, // At least 1 byte\n maxFilenameLength: 255,\n} as const;\n\n/**\n * File validation configuration\n */\nexport interface FileValidationConfig {\n maxSizeBytes?: number;\n minSizeBytes?: number;\n allowedMimeTypes?: ReadonlySet<string> | Set<string>;\n blockedExtensions?: ReadonlySet<string> | Set<string>;\n maxFilenameLength?: number;\n}\n\n/**\n * File validation result\n */\nexport interface FileValidationResult {\n valid: boolean;\n error?: string;\n errorCode?: 'FILE_TOO_LARGE' | 'FILE_TOO_SMALL' | 'INVALID_TYPE' | 'BLOCKED_EXTENSION' | 'FILENAME_TOO_LONG' | 'EMPTY_FILE';\n}\n\n/**\n * Get file extension from filename (lowercase)\n */\nexport function getFileExtension(filename: string): string {\n const lastDot = filename.lastIndexOf('.');\n if (lastDot === -1 || lastDot === filename.length - 1) {\n return '';\n }\n return filename.substring(lastDot).toLowerCase();\n}\n\n/**\n * Sanitize filename for safe storage\n * Removes path traversal attempts and dangerous characters\n */\nexport function sanitizeFilename(filename: string): string {\n // Remove path components\n let sanitized = filename.replace(/^.*[\\\\/]/, '');\n\n // Remove null bytes and other control characters\n sanitized = sanitized.replace(/[\\x00-\\x1f\\x7f]/g, '');\n\n // Replace problematic characters\n sanitized = sanitized.replace(/[<>:\"/\\\\|?*]/g, '_');\n\n // Trim whitespace and dots from start/end\n sanitized = sanitized.replace(/^[\\s.]+|[\\s.]+$/g, '');\n\n // If empty after sanitization, use default name\n if (!sanitized) {\n sanitized = 'unnamed_file';\n }\n\n // Limit length\n if (sanitized.length > DEFAULT_FILE_CONSTRAINTS.maxFilenameLength) {\n const ext = getFileExtension(sanitized);\n const nameWithoutExt = sanitized.slice(0, -ext.length || undefined);\n const maxNameLength = DEFAULT_FILE_CONSTRAINTS.maxFilenameLength - ext.length;\n sanitized = nameWithoutExt.slice(0, maxNameLength) + ext;\n }\n\n return sanitized;\n}\n\n/**\n * Validate a file before upload\n * Returns validation result with error details if invalid\n */\nexport function validateFile(\n file: File,\n config: FileValidationConfig = {}\n): FileValidationResult {\n const {\n maxSizeBytes = DEFAULT_FILE_CONSTRAINTS.maxSizeBytes,\n minSizeBytes = DEFAULT_FILE_CONSTRAINTS.minSizeBytes,\n allowedMimeTypes = ALLOWED_MIME_TYPES,\n blockedExtensions = BLOCKED_EXTENSIONS,\n maxFilenameLength = DEFAULT_FILE_CONSTRAINTS.maxFilenameLength,\n } = config;\n\n // Check file size\n if (file.size === 0) {\n return {\n valid: false,\n error: 'File is empty',\n errorCode: 'EMPTY_FILE',\n };\n }\n\n if (file.size < minSizeBytes) {\n return {\n valid: false,\n error: `File is too small. Minimum size is ${formatFileSize(minSizeBytes)}`,\n errorCode: 'FILE_TOO_SMALL',\n };\n }\n\n if (file.size > maxSizeBytes) {\n return {\n valid: false,\n error: `File is too large. Maximum size is ${formatFileSize(maxSizeBytes)}`,\n errorCode: 'FILE_TOO_LARGE',\n };\n }\n\n // Check filename length\n if (file.name.length > maxFilenameLength) {\n return {\n valid: false,\n error: `Filename is too long. Maximum length is ${maxFilenameLength} characters`,\n errorCode: 'FILENAME_TOO_LONG',\n };\n }\n\n // Check for blocked extensions\n const extension = getFileExtension(file.name);\n if (extension && blockedExtensions.has(extension)) {\n return {\n valid: false,\n error: `File type \"${extension}\" is not allowed for security reasons`,\n errorCode: 'BLOCKED_EXTENSION',\n };\n }\n\n // Check MIME type\n const mimeType = file.type || 'application/octet-stream';\n if (!allowedMimeTypes.has(mimeType)) {\n // Allow files without explicit type if extension is safe\n if (mimeType === 'application/octet-stream' && extension && !blockedExtensions.has(extension)) {\n // Let it pass - backend will verify\n } else {\n return {\n valid: false,\n error: `File type \"${mimeType}\" is not allowed. Allowed types: images, documents, audio, video`,\n errorCode: 'INVALID_TYPE',\n };\n }\n }\n\n return { valid: true };\n}\n\n/**\n * Format file size to human-readable string\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];\n}\n\n/**\n * Generate accept attribute string from ALLOWED_MIME_TYPES\n * Used to sync file input accept with validation rules\n */\nexport function generateAcceptAttribute(allowedMimeTypes: ReadonlySet<string> = ALLOWED_MIME_TYPES): string {\n const accepts: string[] = [];\n\n allowedMimeTypes.forEach((mimeType) => {\n accepts.push(mimeType);\n });\n\n return accepts.join(',');\n}\n\n/**\n * Rate limiter for file uploads\n * Prevents rapid successive uploads\n */\nexport class UploadRateLimiter {\n private uploadTimestamps: number[] = [];\n private readonly maxUploads: number;\n private readonly windowMs: number;\n\n constructor(maxUploads = 5, windowMs = 60000) {\n this.maxUploads = maxUploads;\n this.windowMs = windowMs;\n }\n\n /**\n * Check if upload is allowed\n * Returns true if allowed, false if rate limited\n */\n canUpload(): boolean {\n const now = Date.now();\n // Remove timestamps outside the window\n this.uploadTimestamps = this.uploadTimestamps.filter(\n (timestamp) => now - timestamp < this.windowMs\n );\n return this.uploadTimestamps.length < this.maxUploads;\n }\n\n /**\n * Record an upload attempt\n */\n recordUpload(): void {\n this.uploadTimestamps.push(Date.now());\n }\n\n /**\n * Get remaining uploads in current window\n */\n getRemainingUploads(): number {\n const now = Date.now();\n this.uploadTimestamps = this.uploadTimestamps.filter(\n (timestamp) => now - timestamp < this.windowMs\n );\n return Math.max(0, this.maxUploads - this.uploadTimestamps.length);\n }\n\n /**\n * Get time until next upload is allowed (in ms)\n * Returns 0 if upload is allowed now\n */\n getTimeUntilNextUpload(): number {\n if (this.canUpload()) return 0;\n const oldestTimestamp = Math.min(...this.uploadTimestamps);\n return Math.max(0, this.windowMs - (Date.now() - oldestTimestamp));\n }\n\n /**\n * Reset the rate limiter\n */\n reset(): void {\n this.uploadTimestamps = [];\n }\n}\n","import type {\n CevroMessengerConfig,\n SendMessageRequest,\n Message,\n Conversation,\n Agent,\n LocaleStrings,\n} from '../types';\nimport { collectSessionData } from '../utils/session';\nimport {\n validateFile,\n sanitizeFilename,\n UploadRateLimiter,\n ALLOWED_MIME_TYPES,\n BLOCKED_EXTENSIONS,\n DEFAULT_FILE_CONSTRAINTS,\n} from '../utils/file-validation';\n\n/**\n * API client for communicating with Cevro backend\n */\nexport class ApiClient {\n private config: CevroMessengerConfig;\n private accessToken: string | null = null;\n private contactId: string | null = null;\n private currentTicketId: string | null = null;\n private visitorToken: string | null = null;\n private currentAgent: Agent | null = null;\n private uploadRateLimiter: UploadRateLimiter;\n\n constructor(config: CevroMessengerConfig) {\n this.config = config;\n\n // Initialize rate limiter with config or defaults\n const maxUploadsPerMinute = config.fileUpload?.maxUploadsPerMinute ?? 5;\n this.uploadRateLimiter = new UploadRateLimiter(maxUploadsPerMinute, 60000);\n }\n\n /**\n * Set visitor token for authenticated requests\n */\n setVisitorToken(token: string): void {\n this.visitorToken = token;\n }\n\n /**\n * Get visitor token\n */\n getVisitorToken(): string | null {\n return this.visitorToken;\n }\n\n /**\n * Set access token for authenticated requests\n */\n setAccessToken(token: string): void {\n this.accessToken = token;\n }\n\n /**\n * Get current contact ID\n */\n getContactId(): string | null {\n return this.contactId;\n }\n\n /**\n * Get current ticket ID\n */\n getCurrentTicketId(): string | null {\n return this.currentTicketId;\n }\n\n /**\n * Set current ticket ID\n */\n setCurrentTicketId(ticketId: string): void {\n this.currentTicketId = ticketId;\n }\n\n /**\n * Get current agent info\n */\n getCurrentAgent(): Agent | null {\n return this.currentAgent;\n }\n\n /**\n * Make API request\n */\n private async request<T>(\n endpoint: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.config.apiBase}${endpoint}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(options.headers as Record<string, string> || {}),\n };\n\n // Add workspace headers for gateway auth\n if (this.config.workspaceId) {\n headers['X-Workspace-Id'] = this.config.workspaceId;\n }\n if (this.config.brandId) {\n headers['X-Brand-Id'] = this.config.brandId;\n }\n if (this.visitorToken) {\n headers['X-Visitor-Token'] = this.visitorToken;\n }\n\n if (this.accessToken) {\n headers['Authorization'] = `Bearer ${this.accessToken}`;\n }\n\n const response = await fetch(url, {\n ...options,\n headers,\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ message: response.statusText }));\n throw new Error(error.message || `Request failed: ${response.status}`);\n }\n\n return response.json();\n }\n\n /**\n * Initialize a chat session\n * Called when chat opens to create/restore session\n */\n async initSession(\n visitorId: string | null,\n options?: { forceNewTicket?: boolean }\n ): Promise<{\n sessionId: string;\n contactId: string;\n ticketId: string;\n visitorId: string;\n isNewSession: boolean;\n isNewTicket: boolean;\n ticketClosed?: boolean;\n ticketClosedReason?: string;\n agent?: Agent;\n typingConfig?: {\n onDurationMs: number;\n offDurationMs: number;\n };\n messages?: Message[];\n locale?: Partial<LocaleStrings>;\n }> {\n const session = collectSessionData();\n\n const payload: any = {\n visitorId,\n session,\n brandId: this.config.brandId,\n firstName: this.config.player?.firstName,\n lastName: this.config.player?.lastName,\n email: this.config.player?.email,\n phone: this.config.player?.phone,\n customAttributes: this.config.player?.customAttributes,\n forceNewTicket: options?.forceNewTicket,\n };\n\n // Add player data for authenticated users (for merge logic)\n if (this.config.player?.playerId) {\n payload.playerId = this.config.player.playerId;\n payload.playerHash = this.config.player.playerHash;\n }\n\n const result = await this.request<any>('/api/v1/sdk/session', {\n method: 'POST',\n body: JSON.stringify(payload),\n headers: visitorId ? { 'X-Visitor-Id': visitorId } : undefined,\n });\n\n // Store contact, ticket IDs and agent info\n this.contactId = result.contactId;\n this.currentTicketId = result.ticketId;\n if (result.agent) {\n this.currentAgent = result.agent;\n }\n\n return {\n sessionId: result.sessionId,\n contactId: result.contactId,\n ticketId: result.ticketId,\n visitorId: result.visitorId,\n isNewSession: result.isNewSession,\n isNewTicket: result.isNewTicket,\n ticketClosed: result.ticketClosed,\n ticketClosedReason: result.ticketClosedReason,\n agent: result.agent,\n typingConfig: result.typingConfig,\n messages: result.messages?.map((msg: any) => this.normalizeMessage(msg)),\n locale: result.locale,\n };\n }\n\n /**\n * Send a message to an existing conversation\n */\n async sendMessage(message: string, assetId?: string): Promise<Message> {\n if (!this.contactId || !this.currentTicketId) {\n throw new Error('No active session. Call initSession first.');\n }\n\n const payload: SendMessageRequest = {\n contactId: this.contactId,\n ticketId: this.currentTicketId,\n message,\n assetId,\n };\n\n const result = await this.request<any>('/api/v1/sdk/send', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n\n // Server returns {success: true, message: {...}}, extract the message\n return this.normalizeMessage(result.message || result);\n }\n\n /**\n * Get messages for the current ticket (for authenticated users)\n */\n async getMessages(ticketId?: string): Promise<Message[]> {\n const targetTicketId = ticketId || this.currentTicketId;\n if (!targetTicketId) {\n throw new Error('No ticket ID available');\n }\n\n const result = await this.request<any>(\n `/api/v1/messages/my-tickets?supportTicketId=${targetTicketId}`\n );\n\n const messages = result.results || result.messages || result || [];\n return messages.map((msg: any) => this.normalizeMessage(msg));\n }\n\n /**\n * Get user's support tickets (for authenticated users)\n */\n async getMyTickets(): Promise<Conversation[]> {\n const result = await this.request<any>('/api/v1/messages/my-tickets');\n\n const tickets = result.results || result.tickets || result || [];\n return tickets.map((ticket: any) => this.normalizeConversation(ticket));\n }\n\n /**\n * Upload a file using presigned S3 URL for better performance.\n * The file is uploaded directly to S3, bypassing the backend.\n *\n * Security features:\n * - File size validation (client-side)\n * - MIME type whitelist validation\n * - Blocked extension check\n * - Rate limiting (uploads per minute)\n * - Filename sanitization\n *\n * @param file - The file to upload\n * @param onProgress - Optional callback for upload progress (0-100)\n * @returns The asset ID to use when sending messages\n * @throws Error if validation fails or rate limited\n */\n async uploadFile(\n file: File,\n onProgress?: (progress: number) => void\n ): Promise<string> {\n // Step 0: Rate limiting check\n if (!this.uploadRateLimiter.canUpload()) {\n const waitTime = Math.ceil(this.uploadRateLimiter.getTimeUntilNextUpload() / 1000);\n throw new Error(`Too many uploads. Please wait ${waitTime} seconds before uploading again.`);\n }\n\n // Step 1: Validate file (size, type, extension)\n const validationConfig = {\n maxSizeBytes: this.config.fileUpload?.maxSizeBytes ?? DEFAULT_FILE_CONSTRAINTS.maxSizeBytes,\n allowedMimeTypes: this.config.fileUpload?.allowedMimeTypes\n ? new Set(this.config.fileUpload.allowedMimeTypes)\n : ALLOWED_MIME_TYPES,\n blockedExtensions: this.config.fileUpload?.additionalBlockedExtensions\n ? new Set([...BLOCKED_EXTENSIONS, ...this.config.fileUpload.additionalBlockedExtensions])\n : BLOCKED_EXTENSIONS,\n };\n\n const validation = validateFile(file, validationConfig);\n if (!validation.valid) {\n throw new Error(validation.error || 'File validation failed');\n }\n\n // Step 2: Sanitize filename\n const sanitizedFilename = sanitizeFilename(file.name);\n\n // Step 3: Record upload attempt for rate limiting\n this.uploadRateLimiter.recordUpload();\n\n // Step 4: Get presigned URL from backend\n const { uploadUrl, assetId } = await this.request<{\n uploadUrl: string;\n assetId: string;\n expiresIn: number;\n }>('/api/v1/sdk/upload-url', {\n method: 'POST',\n body: JSON.stringify({\n filename: sanitizedFilename,\n contentType: file.type || 'application/octet-stream',\n size: file.size,\n }),\n });\n\n // Step 5: Upload file directly to S3\n await this.uploadToS3(uploadUrl, file, onProgress);\n\n return assetId;\n }\n\n /**\n * Upload file directly to S3 using presigned URL\n */\n private async uploadToS3(\n uploadUrl: string,\n file: File,\n onProgress?: (progress: number) => void\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable && onProgress) {\n const progress = Math.round((event.loaded / event.total) * 100);\n onProgress(progress);\n }\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n resolve();\n } else {\n reject(new Error(`Upload failed with status ${xhr.status}`));\n }\n });\n\n xhr.addEventListener('error', () => {\n reject(new Error('Upload failed'));\n });\n\n xhr.open('PUT', uploadUrl);\n xhr.setRequestHeader('Content-Type', file.type || 'application/octet-stream');\n xhr.send(file);\n });\n }\n\n /**\n * Normalize message object from API response\n */\n private normalizeMessage(data: any): Message {\n return {\n id: data.objectId || data.id,\n body: data.body || '',\n inbound: data.inbound || false,\n outbound: data.outbound || !data.inbound,\n createdAt: data.createdAt || new Date().toISOString(),\n type: data.type || 'text',\n mediaUrl: data.mediaUrl,\n mediaType: data.mediaType,\n status: data.status || 'sent',\n richContent: data.richContent,\n };\n }\n\n /**\n * Normalize conversation object from API response\n */\n private normalizeConversation(data: any): Conversation {\n return {\n id: data.objectId || data.id,\n conversationId: data.conversationId || data.objectId || data.id,\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n status: data.resolved ? 'resolved' : data.escalated ? 'escalated' : 'open',\n unreadCount: data.unreadCount || 0,\n lastMessage: data.latestMessage ? this.normalizeMessage(data.latestMessage) : undefined,\n };\n }\n\n /**\n * Get Centrifugo connection token for real-time messaging\n *\n * For authenticated players: uses playerHash for identity verification\n * For visitors: uses server-signed visitorToken for security\n *\n * @param visitorToken - Server-signed visitor token (optional, server generates if not provided)\n */\n async getConnectionToken(visitorToken?: string | null): Promise<{\n token: string;\n visitorId: string;\n visitorToken: string;\n expiresAt: number;\n }> {\n const payload: any = {\n workspaceId: this.config.workspaceId,\n brandId: this.config.brandId,\n };\n\n if (visitorToken) {\n payload.visitorToken = visitorToken;\n }\n\n // Add player data for authenticated users\n if (this.config.player?.playerId) {\n payload.playerId = this.config.player.playerId;\n payload.playerHash = this.config.player.playerHash;\n payload.email = this.config.player.email;\n payload.firstName = this.config.player.firstName;\n }\n\n const result = await this.request<{\n token: string;\n visitorId: string;\n visitorToken: string;\n expiresAt: number;\n }>('/api/v1/sdk/token', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n\n return result;\n }\n\n /**\n * Refresh Centrifugo token before expiration\n */\n async refreshConnectionToken(visitorToken?: string | null): Promise<{\n token: string;\n visitorToken: string;\n expiresAt: number;\n }> {\n return this.getConnectionToken(visitorToken);\n }\n\n /**\n * Submit CSAT rating for a closed conversation\n */\n async submitCSAT(\n ticketId: string,\n contactId: string,\n rating: number,\n feedback?: string\n ): Promise<void> {\n await this.request('/api/v1/sdk/csat', {\n method: 'POST',\n body: JSON.stringify({\n ticketId,\n contactId,\n rating,\n feedback,\n }),\n });\n }\n\n /**\n * Clear stored data (on shutdown)\n */\n clear(): void {\n this.accessToken = null;\n this.contactId = null;\n this.currentTicketId = null;\n }\n}\n","/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol */\r\n\r\n\r\nfunction __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\ntypeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\n\nfunction getDefaultExportFromCjs (x) {\n\treturn x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;\n}\n\nvar events = {exports: {}};\n\nvar R = typeof Reflect === 'object' ? Reflect : null;\nvar ReflectApply = R && typeof R.apply === 'function'\n ? R.apply\n : function ReflectApply(target, receiver, args) {\n return Function.prototype.apply.call(target, receiver, args);\n };\n\nvar ReflectOwnKeys;\nif (R && typeof R.ownKeys === 'function') {\n ReflectOwnKeys = R.ownKeys;\n} else if (Object.getOwnPropertySymbols) {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target)\n .concat(Object.getOwnPropertySymbols(target));\n };\n} else {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target);\n };\n}\n\nfunction ProcessEmitWarning(warning) {\n if (console && console.warn) console.warn(warning);\n}\n\nvar NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {\n return value !== value;\n};\n\nfunction EventEmitter() {\n EventEmitter.init.call(this);\n}\nevents.exports = EventEmitter;\nevents.exports.once = once;\n\n// Backwards-compat with node 0.10.x\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._eventsCount = 0;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nvar defaultMaxListeners = 10;\n\nfunction checkListener(listener) {\n if (typeof listener !== 'function') {\n throw new TypeError('The \"listener\" argument must be of type Function. Received type ' + typeof listener);\n }\n}\n\nObject.defineProperty(EventEmitter, 'defaultMaxListeners', {\n enumerable: true,\n get: function() {\n return defaultMaxListeners;\n },\n set: function(arg) {\n if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {\n throw new RangeError('The value of \"defaultMaxListeners\" is out of range. It must be a non-negative number. Received ' + arg + '.');\n }\n defaultMaxListeners = arg;\n }\n});\n\nEventEmitter.init = function() {\n\n if (this._events === undefined ||\n this._events === Object.getPrototypeOf(this)._events) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n }\n\n this._maxListeners = this._maxListeners || undefined;\n};\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {\n if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {\n throw new RangeError('The value of \"n\" is out of range. It must be a non-negative number. Received ' + n + '.');\n }\n this._maxListeners = n;\n return this;\n};\n\nfunction _getMaxListeners(that) {\n if (that._maxListeners === undefined)\n return EventEmitter.defaultMaxListeners;\n return that._maxListeners;\n}\n\nEventEmitter.prototype.getMaxListeners = function getMaxListeners() {\n return _getMaxListeners(this);\n};\n\nEventEmitter.prototype.emit = function emit(type) {\n var args = [];\n for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);\n var doError = (type === 'error');\n\n var events = this._events;\n if (events !== undefined)\n doError = (doError && events.error === undefined);\n else if (!doError)\n return false;\n\n // If there is no 'error' event listener then throw.\n if (doError) {\n var er;\n if (args.length > 0)\n er = args[0];\n if (er instanceof Error) {\n // Note: The comments on the `throw` lines are intentional, they show\n // up in Node's output if this results in an unhandled exception.\n throw er; // Unhandled 'error' event\n }\n // At least give some kind of context to the user\n var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));\n err.context = er;\n throw err; // Unhandled 'error' event\n }\n\n var handler = events[type];\n\n if (handler === undefined)\n return false;\n\n if (typeof handler === 'function') {\n ReflectApply(handler, this, args);\n } else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n ReflectApply(listeners[i], this, args);\n }\n\n return true;\n};\n\nfunction _addListener(target, type, listener, prepend) {\n var m;\n var events;\n var existing;\n\n checkListener(listener);\n\n events = target._events;\n if (events === undefined) {\n events = target._events = Object.create(null);\n target._eventsCount = 0;\n } else {\n // To avoid recursion in the case that type === \"newListener\"! Before\n // adding it to the listeners, first emit \"newListener\".\n if (events.newListener !== undefined) {\n target.emit('newListener', type,\n listener.listener ? listener.listener : listener);\n\n // Re-assign `events` because a newListener handler could have caused the\n // this._events to be assigned to a new object\n events = target._events;\n }\n existing = events[type];\n }\n\n if (existing === undefined) {\n // Optimize the case of one listener. Don't need the extra array object.\n existing = events[type] = listener;\n ++target._eventsCount;\n } else {\n if (typeof existing === 'function') {\n // Adding the second element, need to change to array.\n existing = events[type] =\n prepend ? [listener, existing] : [existing, listener];\n // If we've already got an array, just append.\n } else if (prepend) {\n existing.unshift(listener);\n } else {\n existing.push(listener);\n }\n\n // Check for listener leak\n m = _getMaxListeners(target);\n if (m > 0 && existing.length > m && !existing.warned) {\n existing.warned = true;\n // No error code for this since it is a Warning\n // eslint-disable-next-line no-restricted-syntax\n var w = new Error('Possible EventEmitter memory leak detected. ' +\n existing.length + ' ' + String(type) + ' listeners ' +\n 'added. Use emitter.setMaxListeners() to ' +\n 'increase limit');\n w.name = 'MaxListenersExceededWarning';\n w.emitter = target;\n w.type = type;\n w.count = existing.length;\n ProcessEmitWarning(w);\n }\n }\n\n return target;\n}\n\nEventEmitter.prototype.addListener = function addListener(type, listener) {\n return _addListener(this, type, listener, false);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.prependListener =\n function prependListener(type, listener) {\n return _addListener(this, type, listener, true);\n };\n\nfunction onceWrapper() {\n if (!this.fired) {\n this.target.removeListener(this.type, this.wrapFn);\n this.fired = true;\n if (arguments.length === 0)\n return this.listener.call(this.target);\n return this.listener.apply(this.target, arguments);\n }\n}\n\nfunction _onceWrap(target, type, listener) {\n var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };\n var wrapped = onceWrapper.bind(state);\n wrapped.listener = listener;\n state.wrapFn = wrapped;\n return wrapped;\n}\n\nEventEmitter.prototype.once = function once(type, listener) {\n checkListener(listener);\n this.on(type, _onceWrap(this, type, listener));\n return this;\n};\n\nEventEmitter.prototype.prependOnceListener =\n function prependOnceListener(type, listener) {\n checkListener(listener);\n this.prependListener(type, _onceWrap(this, type, listener));\n return this;\n };\n\n// Emits a 'removeListener' event if and only if the listener was removed.\nEventEmitter.prototype.removeListener =\n function removeListener(type, listener) {\n var list, events, position, i, originalListener;\n\n checkListener(listener);\n\n events = this._events;\n if (events === undefined)\n return this;\n\n list = events[type];\n if (list === undefined)\n return this;\n\n if (list === listener || list.listener === listener) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else {\n delete events[type];\n if (events.removeListener)\n this.emit('removeListener', type, list.listener || listener);\n }\n } else if (typeof list !== 'function') {\n position = -1;\n\n for (i = list.length - 1; i >= 0; i--) {\n if (list[i] === listener || list[i].listener === listener) {\n originalListener = list[i].listener;\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (position === 0)\n list.shift();\n else {\n spliceOne(list, position);\n }\n\n if (list.length === 1)\n events[type] = list[0];\n\n if (events.removeListener !== undefined)\n this.emit('removeListener', type, originalListener || listener);\n }\n\n return this;\n };\n\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n\nEventEmitter.prototype.removeAllListeners =\n function removeAllListeners(type) {\n var listeners, events, i;\n\n events = this._events;\n if (events === undefined)\n return this;\n\n // not listening for removeListener, no need to emit\n if (events.removeListener === undefined) {\n if (arguments.length === 0) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n } else if (events[type] !== undefined) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else\n delete events[type];\n }\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n var keys = Object.keys(events);\n var key;\n for (i = 0; i < keys.length; ++i) {\n key = keys[i];\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = Object.create(null);\n this._eventsCount = 0;\n return this;\n }\n\n listeners = events[type];\n\n if (typeof listeners === 'function') {\n this.removeListener(type, listeners);\n } else if (listeners !== undefined) {\n // LIFO order\n for (i = listeners.length - 1; i >= 0; i--) {\n this.removeListener(type, listeners[i]);\n }\n }\n\n return this;\n };\n\nfunction _listeners(target, type, unwrap) {\n var events = target._events;\n\n if (events === undefined)\n return [];\n\n var evlistener = events[type];\n if (evlistener === undefined)\n return [];\n\n if (typeof evlistener === 'function')\n return unwrap ? [evlistener.listener || evlistener] : [evlistener];\n\n return unwrap ?\n unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);\n}\n\nEventEmitter.prototype.listeners = function listeners(type) {\n return _listeners(this, type, true);\n};\n\nEventEmitter.prototype.rawListeners = function rawListeners(type) {\n return _listeners(this, type, false);\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n if (typeof emitter.listenerCount === 'function') {\n return emitter.listenerCount(type);\n } else {\n return listenerCount.call(emitter, type);\n }\n};\n\nEventEmitter.prototype.listenerCount = listenerCount;\nfunction listenerCount(type) {\n var events = this._events;\n\n if (events !== undefined) {\n var evlistener = events[type];\n\n if (typeof evlistener === 'function') {\n return 1;\n } else if (evlistener !== undefined) {\n return evlistener.length;\n }\n }\n\n return 0;\n}\n\nEventEmitter.prototype.eventNames = function eventNames() {\n return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];\n};\n\nfunction arrayClone(arr, n) {\n var copy = new Array(n);\n for (var i = 0; i < n; ++i)\n copy[i] = arr[i];\n return copy;\n}\n\nfunction spliceOne(list, index) {\n for (; index + 1 < list.length; index++)\n list[index] = list[index + 1];\n list.pop();\n}\n\nfunction unwrapListeners(arr) {\n var ret = new Array(arr.length);\n for (var i = 0; i < ret.length; ++i) {\n ret[i] = arr[i].listener || arr[i];\n }\n return ret;\n}\n\nfunction once(emitter, name) {\n return new Promise(function (resolve, reject) {\n function errorListener(err) {\n emitter.removeListener(name, resolver);\n reject(err);\n }\n\n function resolver() {\n if (typeof emitter.removeListener === 'function') {\n emitter.removeListener('error', errorListener);\n }\n resolve([].slice.call(arguments));\n }\n eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });\n if (name !== 'error') {\n addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });\n }\n });\n}\n\nfunction addErrorHandlerIfEventEmitter(emitter, handler, flags) {\n if (typeof emitter.on === 'function') {\n eventTargetAgnosticAddListener(emitter, 'error', handler, flags);\n }\n}\n\nfunction eventTargetAgnosticAddListener(emitter, name, listener, flags) {\n if (typeof emitter.on === 'function') {\n if (flags.once) {\n emitter.once(name, listener);\n } else {\n emitter.on(name, listener);\n }\n } else if (typeof emitter.addEventListener === 'function') {\n // EventTarget does not have `error` event semantics like Node\n // EventEmitters, we do not listen for `error` events here.\n emitter.addEventListener(name, function wrapListener(arg) {\n // IE does not have builtin `{ once: true }` support so we\n // have to do it manually.\n if (flags.once) {\n emitter.removeEventListener(name, wrapListener);\n }\n listener(arg);\n });\n } else {\n throw new TypeError('The \"emitter\" argument must be of type EventEmitter. Received type ' + typeof emitter);\n }\n}\n\nvar eventsExports = events.exports;\nvar EventEmitter$1 = /*@__PURE__*/getDefaultExportFromCjs(eventsExports);\n\nvar errorCodes;\n(function (errorCodes) {\n errorCodes[errorCodes[\"timeout\"] = 1] = \"timeout\";\n errorCodes[errorCodes[\"transportClosed\"] = 2] = \"transportClosed\";\n errorCodes[errorCodes[\"clientDisconnected\"] = 3] = \"clientDisconnected\";\n errorCodes[errorCodes[\"clientClosed\"] = 4] = \"clientClosed\";\n errorCodes[errorCodes[\"clientConnectToken\"] = 5] = \"clientConnectToken\";\n errorCodes[errorCodes[\"clientRefreshToken\"] = 6] = \"clientRefreshToken\";\n errorCodes[errorCodes[\"subscriptionUnsubscribed\"] = 7] = \"subscriptionUnsubscribed\";\n errorCodes[errorCodes[\"subscriptionSubscribeToken\"] = 8] = \"subscriptionSubscribeToken\";\n errorCodes[errorCodes[\"subscriptionRefreshToken\"] = 9] = \"subscriptionRefreshToken\";\n errorCodes[errorCodes[\"transportWriteError\"] = 10] = \"transportWriteError\";\n errorCodes[errorCodes[\"connectionClosed\"] = 11] = \"connectionClosed\";\n errorCodes[errorCodes[\"badConfiguration\"] = 12] = \"badConfiguration\";\n})(errorCodes || (errorCodes = {}));\nvar connectingCodes;\n(function (connectingCodes) {\n connectingCodes[connectingCodes[\"connectCalled\"] = 0] = \"connectCalled\";\n connectingCodes[connectingCodes[\"transportClosed\"] = 1] = \"transportClosed\";\n connectingCodes[connectingCodes[\"noPing\"] = 2] = \"noPing\";\n connectingCodes[connectingCodes[\"subscribeTimeout\"] = 3] = \"subscribeTimeout\";\n connectingCodes[connectingCodes[\"unsubscribeError\"] = 4] = \"unsubscribeError\";\n})(connectingCodes || (connectingCodes = {}));\nvar disconnectedCodes;\n(function (disconnectedCodes) {\n disconnectedCodes[disconnectedCodes[\"disconnectCalled\"] = 0] = \"disconnectCalled\";\n disconnectedCodes[disconnectedCodes[\"unauthorized\"] = 1] = \"unauthorized\";\n disconnectedCodes[disconnectedCodes[\"badProtocol\"] = 2] = \"badProtocol\";\n disconnectedCodes[disconnectedCodes[\"messageSizeLimit\"] = 3] = \"messageSizeLimit\";\n})(disconnectedCodes || (disconnectedCodes = {}));\nvar subscribingCodes;\n(function (subscribingCodes) {\n subscribingCodes[subscribingCodes[\"subscribeCalled\"] = 0] = \"subscribeCalled\";\n subscribingCodes[subscribingCodes[\"transportClosed\"] = 1] = \"transportClosed\";\n})(subscribingCodes || (subscribingCodes = {}));\nvar unsubscribedCodes;\n(function (unsubscribedCodes) {\n unsubscribedCodes[unsubscribedCodes[\"unsubscribeCalled\"] = 0] = \"unsubscribeCalled\";\n unsubscribedCodes[unsubscribedCodes[\"unauthorized\"] = 1] = \"unauthorized\";\n unsubscribedCodes[unsubscribedCodes[\"clientClosed\"] = 2] = \"clientClosed\";\n})(unsubscribedCodes || (unsubscribedCodes = {}));\nvar subscriptionFlags;\n(function (subscriptionFlags) {\n subscriptionFlags[subscriptionFlags[\"channelCompaction\"] = 1] = \"channelCompaction\";\n})(subscriptionFlags || (subscriptionFlags = {}));\n\n/** State of client. */\nvar State;\n(function (State) {\n State[\"Disconnected\"] = \"disconnected\";\n State[\"Connecting\"] = \"connecting\";\n State[\"Connected\"] = \"connected\";\n})(State || (State = {}));\n/** State of Subscription */\nvar SubscriptionState;\n(function (SubscriptionState) {\n SubscriptionState[\"Unsubscribed\"] = \"unsubscribed\";\n SubscriptionState[\"Subscribing\"] = \"subscribing\";\n SubscriptionState[\"Subscribed\"] = \"subscribed\";\n})(SubscriptionState || (SubscriptionState = {}));\n\n/** @internal */\nfunction startsWith(value, prefix) {\n return value.lastIndexOf(prefix, 0) === 0;\n}\n/** @internal */\nfunction isFunction(value) {\n if (value === undefined || value === null) {\n return false;\n }\n return typeof value === 'function';\n}\n/** @internal */\nfunction log(level, args) {\n if (globalThis.console) {\n const logger = globalThis.console[level];\n if (isFunction(logger)) {\n logger.apply(globalThis.console, args);\n }\n }\n}\nfunction randomInt(min, max) {\n return Math.floor(Math.random() * (max - min + 1) + min);\n}\n/** @internal */\nfunction backoff(step, min, max) {\n // Full jitter technique, see:\n // https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/\n if (step > 31) {\n step = 31;\n }\n const interval = randomInt(0, Math.min(max, min * Math.pow(2, step)));\n return Math.min(max, min + interval);\n}\n/** @internal */\nfunction errorExists(data) {\n return 'error' in data && data.error !== null;\n}\n/** @internal */\nfunction ttlMilliseconds(ttl) {\n // https://stackoverflow.com/questions/12633405/what-is-the-maximum-delay-for-setinterval\n return Math.min(ttl * 1000, 2147483647);\n}\n\n/** Subscription to a channel */\nclass Subscription extends EventEmitter$1 {\n /** Subscription constructor should not be used directly, create subscriptions using Client method. */\n constructor(centrifuge, channel, options) {\n super();\n this._resubscribeTimeout = null;\n this._refreshTimeout = null;\n this.channel = channel;\n this.state = SubscriptionState.Unsubscribed;\n this._centrifuge = centrifuge;\n this._token = '';\n this._getToken = null;\n this._data = null;\n this._getData = null;\n this._recover = false;\n this._offset = null;\n this._epoch = null;\n this._id = 0;\n this._recoverable = false;\n this._positioned = false;\n this._joinLeave = false;\n this._minResubscribeDelay = 500;\n this._maxResubscribeDelay = 20000;\n this._resubscribeTimeout = null;\n this._resubscribeAttempts = 0;\n this._promises = {};\n this._promiseId = 0;\n this._inflight = false;\n this._refreshTimeout = null;\n this._delta = '';\n this._delta_negotiated = false;\n this._tagsFilter = null;\n this._prevValue = null;\n this._unsubPromise = Promise.resolve();\n this._setOptions(options);\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n if (this._centrifuge._debugEnabled) {\n this.on('state', (ctx) => {\n this._debug('subscription state', channel, ctx.oldState, '->', ctx.newState);\n });\n this.on('error', (ctx) => {\n this._debug('subscription error', channel, ctx);\n });\n }\n else {\n // Avoid unhandled exception in EventEmitter for non-set error handler.\n this.on('error', function () { Function.prototype(); });\n }\n }\n /** ready returns a Promise which resolves upon subscription goes to Subscribed\n * state and rejects in case of subscription goes to Unsubscribed state.\n * Optional timeout can be passed.*/\n ready(timeout) {\n if (this.state === SubscriptionState.Unsubscribed) {\n return Promise.reject({ code: errorCodes.subscriptionUnsubscribed, message: this.state });\n }\n if (this.state === SubscriptionState.Subscribed) {\n return Promise.resolve();\n }\n return new Promise((res, rej) => {\n const ctx = {\n resolve: res,\n reject: rej\n };\n if (timeout) {\n ctx.timeout = setTimeout(function () {\n rej({ code: errorCodes.timeout, message: 'timeout' });\n }, timeout);\n }\n this._promises[this._nextPromiseId()] = ctx;\n });\n }\n /** subscribe to a channel.*/\n subscribe() {\n if (this._isSubscribed()) {\n return;\n }\n this._resubscribeAttempts = 0;\n this._setSubscribing(subscribingCodes.subscribeCalled, 'subscribe called');\n }\n /** unsubscribe from a channel, keeping position state.*/\n unsubscribe() {\n this._unsubPromise = this._setUnsubscribed(unsubscribedCodes.unsubscribeCalled, 'unsubscribe called', true);\n }\n /** publish data to a channel.*/\n publish(data) {\n return __awaiter(this, void 0, void 0, function* () {\n yield this._methodCall();\n return this._centrifuge.publish(this.channel, data);\n });\n }\n /** get online presence for a channel.*/\n presence() {\n return __awaiter(this, void 0, void 0, function* () {\n yield this._methodCall();\n return this._centrifuge.presence(this.channel);\n });\n }\n /** presence stats for a channel (num clients and unique users).*/\n presenceStats() {\n return __awaiter(this, void 0, void 0, function* () {\n yield this._methodCall();\n return this._centrifuge.presenceStats(this.channel);\n });\n }\n /** history for a channel. By default it does not return publications (only current\n * StreamPosition data) – provide an explicit limit > 0 to load publications.*/\n history(opts) {\n return __awaiter(this, void 0, void 0, function* () {\n yield this._methodCall();\n return this._centrifuge.history(this.channel, opts);\n });\n }\n /**\n * Sets server-side tags filter for the subscription.\n * This only applies on the next subscription attempt, not the current one.\n * Cannot be used together with delta option.\n *\n * @param tagsFilter - Filter configuration object or null to remove filter\n * @throws {Error} If both delta and tagsFilter are configured\n *\n * @example\n * ```typescript\n * // Simple equality filter\n * sub.setTagsFilter({\n * key: 'ticker',\n * cmp: 'eq',\n * val: 'BTC'\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Complex filter with logical operators\n * sub.setTagsFilter({\n * op: 'and',\n * nodes: [\n * { key: 'ticker', cmp: 'eq', val: 'BTC' },\n * { key: 'price', cmp: 'gt', val: '50000' }\n * ]\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Filter with IN operator\n * sub.setTagsFilter({\n * key: 'ticker',\n * cmp: 'in',\n * vals: ['BTC', 'ETH', 'SOL']\n * });\n * ```\n */\n setTagsFilter(tagsFilter) {\n if (tagsFilter && this._delta) {\n throw new Error('cannot use delta and tagsFilter together');\n }\n this._tagsFilter = tagsFilter;\n }\n /** setData allows setting subscription data. This only applied on the next subscription attempt,\n * Note that if getData callback is configured, it will override this value during resubscriptions. */\n setData(data) {\n this._data = data;\n }\n _methodCall() {\n if (this._isSubscribed()) {\n return Promise.resolve();\n }\n if (this._isUnsubscribed()) {\n return Promise.reject({\n code: errorCodes.subscriptionUnsubscribed,\n message: this.state\n });\n }\n return new Promise((resolve, reject) => {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n const timeoutDuration = this._centrifuge._config.timeout;\n const timeout = setTimeout(() => {\n reject({ code: errorCodes.timeout, message: 'timeout' });\n }, timeoutDuration);\n this._promises[this._nextPromiseId()] = {\n timeout,\n resolve,\n reject\n };\n });\n }\n _nextPromiseId() {\n return ++this._promiseId;\n }\n _needRecover() {\n return this._recover === true;\n }\n _isUnsubscribed() {\n return this.state === SubscriptionState.Unsubscribed;\n }\n _isSubscribing() {\n return this.state === SubscriptionState.Subscribing;\n }\n _isSubscribed() {\n return this.state === SubscriptionState.Subscribed;\n }\n _setState(newState) {\n if (this.state !== newState) {\n const oldState = this.state;\n this.state = newState;\n this.emit('state', { newState, oldState, channel: this.channel });\n return true;\n }\n return false;\n }\n _usesToken() {\n return this._token !== '' || this._getToken !== null;\n }\n _clearSubscribingState() {\n this._resubscribeAttempts = 0;\n this._clearResubscribeTimeout();\n }\n _clearSubscribedState() {\n this._clearRefreshTimeout();\n }\n _setSubscribed(result) {\n if (!this._isSubscribing()) {\n return;\n }\n this._clearSubscribingState();\n if (result.id) {\n this._id = result.id;\n }\n if (result.recoverable) {\n this._recover = true;\n this._offset = result.offset || 0;\n this._epoch = result.epoch || '';\n }\n if (result.delta) {\n this._delta_negotiated = true;\n }\n else {\n this._delta_negotiated = false;\n }\n this._setState(SubscriptionState.Subscribed);\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n const ctx = this._centrifuge._getSubscribeContext(this.channel, result);\n this.emit('subscribed', ctx);\n this._resolvePromises();\n const pubs = result.publications;\n if (pubs && pubs.length > 0) {\n for (const i in pubs) {\n if (!pubs.hasOwnProperty(i)) {\n continue;\n }\n this._handlePublication(pubs[i]);\n }\n }\n if (result.expires === true) {\n this._refreshTimeout = setTimeout(() => this._refresh(), ttlMilliseconds(result.ttl));\n }\n }\n _setSubscribing(code, reason) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this._isSubscribing()) {\n return;\n }\n if (this._isSubscribed()) {\n this._clearSubscribedState();\n }\n if (this._setState(SubscriptionState.Subscribing)) {\n this.emit('subscribing', { channel: this.channel, code: code, reason: reason });\n }\n // @ts-ignore – for performance reasons only await _unsubPromise for emulution case where it's required.\n if (this._centrifuge._transport && this._centrifuge._transport.emulation()) {\n yield this._unsubPromise;\n }\n if (!this._isSubscribing()) {\n return;\n }\n this._subscribe();\n });\n }\n _subscribe() {\n this._debug('subscribing on', this.channel);\n if (!this._isTransportOpen()) {\n this._debug('delay subscribe on', this.channel, 'till connected');\n return null;\n }\n if (this._inflight) {\n return null;\n }\n this._inflight = true;\n if (this._canSubscribeWithoutGettingToken()) {\n return this._subscribeWithoutToken();\n }\n this._getSubscriptionToken()\n .then(token => this._handleTokenResponse(token))\n .catch(e => this._handleTokenError(e));\n return null;\n }\n _isTransportOpen() {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n return this._centrifuge._transportIsOpen;\n }\n _canSubscribeWithoutGettingToken() {\n return !this._usesToken() || !!this._token;\n }\n _subscribeWithoutToken() {\n if (this._getData) {\n this._getDataAndSubscribe(this._token);\n return null;\n }\n else {\n return this._sendSubscribe(this._token);\n }\n }\n _getDataAndSubscribe(token) {\n if (!this._getData) {\n this._inflight = false;\n return;\n }\n this._getData({ channel: this.channel })\n .then(data => {\n if (!this._isSubscribing()) {\n this._inflight = false;\n return;\n }\n this._data = data;\n this._sendSubscribe(token);\n })\n .catch(e => this._handleGetDataError(e));\n }\n _handleGetDataError(error) {\n if (!this._isSubscribing()) {\n this._inflight = false;\n return;\n }\n if (error instanceof UnauthorizedError) {\n this._inflight = false;\n this._failUnauthorized();\n return;\n }\n this.emit('error', {\n type: 'subscribeData',\n channel: this.channel,\n error: {\n code: errorCodes.badConfiguration,\n message: (error === null || error === void 0 ? void 0 : error.toString()) || ''\n }\n });\n this._inflight = false;\n this._scheduleResubscribe();\n }\n _handleTokenResponse(token) {\n if (!this._isSubscribing()) {\n this._inflight = false;\n return;\n }\n if (!token) {\n this._inflight = false;\n this._failUnauthorized();\n return;\n }\n this._token = token;\n if (this._getData) {\n this._getDataAndSubscribe(token);\n }\n else {\n this._sendSubscribe(token);\n }\n }\n _handleTokenError(error) {\n if (!this._isSubscribing()) {\n this._inflight = false;\n return;\n }\n if (error instanceof UnauthorizedError) {\n this._inflight = false;\n this._failUnauthorized();\n return;\n }\n this.emit('error', {\n type: 'subscribeToken',\n channel: this.channel,\n error: {\n code: errorCodes.subscriptionSubscribeToken,\n message: (error === null || error === void 0 ? void 0 : error.toString()) || ''\n }\n });\n this._inflight = false;\n this._scheduleResubscribe();\n }\n _sendSubscribe(token) {\n if (!this._isTransportOpen()) {\n this._inflight = false;\n return null;\n }\n const cmd = this._buildSubscribeCommand(token);\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n this._centrifuge._call(cmd).then(resolveCtx => {\n this._inflight = false;\n const result = resolveCtx.reply.subscribe;\n this._handleSubscribeResponse(result);\n if (resolveCtx.next) {\n resolveCtx.next();\n }\n }, rejectCtx => {\n this._inflight = false;\n this._handleSubscribeError(rejectCtx.error);\n if (rejectCtx.next) {\n rejectCtx.next();\n }\n });\n return cmd;\n }\n _buildSubscribeCommand(token) {\n const req = { channel: this.channel };\n if (token)\n req.token = token;\n if (this._data)\n req.data = this._data;\n if (this._positioned)\n req.positioned = true;\n if (this._recoverable)\n req.recoverable = true;\n if (this._joinLeave)\n req.join_leave = true;\n req.flag = subscriptionFlags.channelCompaction;\n if (this._needRecover()) {\n req.recover = true;\n const offset = this._getOffset();\n if (offset)\n req.offset = offset;\n const epoch = this._getEpoch();\n if (epoch)\n req.epoch = epoch;\n }\n if (this._delta)\n req.delta = this._delta;\n if (this._tagsFilter)\n req.tf = this._tagsFilter;\n return { subscribe: req };\n }\n _debug(...args) {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n this._centrifuge._debug(...args);\n }\n _handleSubscribeError(error) {\n if (!this._isSubscribing()) {\n return;\n }\n if (error.code === errorCodes.timeout) {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n this._centrifuge._disconnect(connectingCodes.subscribeTimeout, 'subscribe timeout', true);\n return;\n }\n this._subscribeError(error);\n }\n _handleSubscribeResponse(result) {\n if (!this._isSubscribing()) {\n return;\n }\n this._setSubscribed(result);\n }\n _setUnsubscribed(code, reason, sendUnsubscribe) {\n if (this._isUnsubscribed()) {\n return Promise.resolve();\n }\n let promise = Promise.resolve();\n if (this._isSubscribed()) {\n if (sendUnsubscribe) {\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n promise = this._centrifuge._unsubscribe(this);\n }\n this._clearSubscribedState();\n }\n else if (this._isSubscribing()) {\n if (this._inflight && sendUnsubscribe) {\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n promise = this._centrifuge._unsubscribe(this);\n }\n this._clearSubscribingState();\n }\n this._inflight = false;\n if (this._setState(SubscriptionState.Unsubscribed)) {\n this.emit('unsubscribed', { channel: this.channel, code: code, reason: reason });\n }\n this._rejectPromises({ code: errorCodes.subscriptionUnsubscribed, message: this.state });\n return promise;\n }\n _handlePublication(pub) {\n if (this._delta && this._delta_negotiated) {\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n const { newData, newPrevValue } = this._centrifuge._codec.applyDeltaIfNeeded(pub, this._prevValue);\n pub.data = newData;\n this._prevValue = newPrevValue;\n }\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n const ctx = this._centrifuge._getPublicationContext(this.channel, pub);\n this.emit('publication', ctx);\n if (pub.offset) {\n this._offset = pub.offset;\n }\n }\n _handleJoin(join) {\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n const info = this._centrifuge._getJoinLeaveContext(join.info);\n this.emit('join', { channel: this.channel, info: info });\n }\n _handleLeave(leave) {\n // @ts-ignore – we are hiding some methods from public API autocompletion.\n const info = this._centrifuge._getJoinLeaveContext(leave.info);\n this.emit('leave', { channel: this.channel, info: info });\n }\n _resolvePromises() {\n for (const id in this._promises) {\n if (!this._promises.hasOwnProperty(id)) {\n continue;\n }\n if (this._promises[id].timeout) {\n clearTimeout(this._promises[id].timeout);\n }\n this._promises[id].resolve();\n delete this._promises[id];\n }\n }\n _rejectPromises(err) {\n for (const id in this._promises) {\n if (!this._promises.hasOwnProperty(id)) {\n continue;\n }\n if (this._promises[id].timeout) {\n clearTimeout(this._promises[id].timeout);\n }\n this._promises[id].reject(err);\n delete this._promises[id];\n }\n }\n _scheduleResubscribe() {\n if (!this._isSubscribing()) {\n this._debug('not in subscribing state, skip resubscribe scheduling', this.channel);\n return;\n }\n const self = this;\n const delay = this._getResubscribeDelay();\n this._resubscribeTimeout = setTimeout(function () {\n if (self._isSubscribing()) {\n self._subscribe();\n }\n }, delay);\n this._debug('resubscribe scheduled after ' + delay, this.channel);\n }\n _subscribeError(err) {\n if (!this._isSubscribing()) {\n return;\n }\n if (err.code < 100 || err.code === 109 || err.temporary === true) {\n if (err.code === 109) { // Token expired error.\n this._token = '';\n }\n const errContext = {\n channel: this.channel,\n type: 'subscribe',\n error: err\n };\n if (this._centrifuge.state === State.Connected) {\n this.emit('error', errContext);\n }\n this._scheduleResubscribe();\n }\n else {\n this._setUnsubscribed(err.code, err.message, false);\n }\n }\n _getResubscribeDelay() {\n const delay = backoff(this._resubscribeAttempts, this._minResubscribeDelay, this._maxResubscribeDelay);\n this._resubscribeAttempts++;\n return delay;\n }\n _setOptions(options) {\n if (!options) {\n return;\n }\n if (options.since) {\n this._offset = options.since.offset || 0;\n this._epoch = options.since.epoch || '';\n this._recover = true;\n }\n if (options.data) {\n this._data = options.data;\n }\n if (options.getData) {\n this._getData = options.getData;\n }\n if (options.minResubscribeDelay !== undefined) {\n this._minResubscribeDelay = options.minResubscribeDelay;\n }\n if (options.maxResubscribeDelay !== undefined) {\n this._maxResubscribeDelay = options.maxResubscribeDelay;\n }\n if (options.token) {\n this._token = options.token;\n }\n if (options.getToken) {\n this._getToken = options.getToken;\n }\n if (options.positioned === true) {\n this._positioned = true;\n }\n if (options.recoverable === true) {\n this._recoverable = true;\n }\n if (options.joinLeave === true) {\n this._joinLeave = true;\n }\n if (options.delta) {\n if (options.delta !== 'fossil') {\n throw new Error('unsupported delta format');\n }\n this._delta = options.delta;\n }\n if (options.tagsFilter) {\n this._tagsFilter = options.tagsFilter;\n }\n if (this._tagsFilter && this._delta) {\n throw new Error('cannot use delta and tagsFilter together');\n }\n }\n _getOffset() {\n const offset = this._offset;\n if (offset !== null) {\n return offset;\n }\n return 0;\n }\n _getEpoch() {\n const epoch = this._epoch;\n if (epoch !== null) {\n return epoch;\n }\n return '';\n }\n _clearRefreshTimeout() {\n if (this._refreshTimeout !== null) {\n clearTimeout(this._refreshTimeout);\n this._refreshTimeout = null;\n }\n }\n _clearResubscribeTimeout() {\n if (this._resubscribeTimeout !== null) {\n clearTimeout(this._resubscribeTimeout);\n this._resubscribeTimeout = null;\n }\n }\n _getSubscriptionToken() {\n this._debug('get subscription token for channel', this.channel);\n const ctx = {\n channel: this.channel\n };\n const getToken = this._getToken;\n if (getToken === null) {\n this.emit('error', {\n type: 'configuration',\n channel: this.channel,\n error: {\n code: errorCodes.badConfiguration,\n message: 'provide a function to get channel subscription token'\n }\n });\n return Promise.reject(new UnauthorizedError(''));\n }\n return getToken(ctx);\n }\n _refresh() {\n this._clearRefreshTimeout();\n const self = this;\n this._getSubscriptionToken().then(function (token) {\n if (!self._isSubscribed()) {\n return;\n }\n if (!token) {\n self._failUnauthorized();\n return;\n }\n self._token = token;\n const req = {\n channel: self.channel,\n token: token\n };\n const msg = {\n 'sub_refresh': req\n };\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n self._centrifuge._call(msg).then(resolveCtx => {\n const result = resolveCtx.reply.sub_refresh;\n self._refreshResponse(result);\n if (resolveCtx.next) {\n resolveCtx.next();\n }\n }, rejectCtx => {\n self._refreshError(rejectCtx.error);\n if (rejectCtx.next) {\n rejectCtx.next();\n }\n });\n }).catch(function (e) {\n if (e instanceof UnauthorizedError) {\n self._failUnauthorized();\n return;\n }\n self.emit('error', {\n type: 'refreshToken',\n channel: self.channel,\n error: {\n code: errorCodes.subscriptionRefreshToken,\n message: e !== undefined ? e.toString() : ''\n }\n });\n self._refreshTimeout = setTimeout(() => self._refresh(), self._getRefreshRetryDelay());\n });\n }\n _refreshResponse(result) {\n if (!this._isSubscribed()) {\n return;\n }\n this._debug('subscription token refreshed, channel', this.channel);\n this._clearRefreshTimeout();\n if (result.expires === true) {\n this._refreshTimeout = setTimeout(() => this._refresh(), ttlMilliseconds(result.ttl));\n }\n }\n _refreshError(err) {\n if (!this._isSubscribed()) {\n return;\n }\n if (err.code < 100 || err.temporary === true) {\n this.emit('error', {\n type: 'refresh',\n channel: this.channel,\n error: err\n });\n this._refreshTimeout = setTimeout(() => this._refresh(), this._getRefreshRetryDelay());\n }\n else {\n this._setUnsubscribed(err.code, err.message, true);\n }\n }\n _getRefreshRetryDelay() {\n return backoff(0, 10000, 20000);\n }\n _failUnauthorized() {\n this._setUnsubscribed(unsubscribedCodes.unauthorized, 'unauthorized', true);\n }\n}\n\n/** @internal */\nclass SockjsTransport {\n constructor(endpoint, options) {\n this.endpoint = endpoint;\n this.options = options;\n this._transport = null;\n }\n name() {\n return 'sockjs';\n }\n subName() {\n return 'sockjs-' + this._transport.transport;\n }\n emulation() {\n return false;\n }\n supported() {\n return this.options.sockjs !== null;\n }\n initialize(_protocol, callbacks) {\n this._transport = new this.options.sockjs(this.endpoint, null, this.options.sockjsOptions);\n this._transport.onopen = () => {\n callbacks.onOpen();\n };\n this._transport.onerror = e => {\n callbacks.onError(e);\n };\n this._transport.onclose = closeEvent => {\n callbacks.onClose(closeEvent);\n };\n this._transport.onmessage = event => {\n callbacks.onMessage(event.data);\n };\n }\n close() {\n this._transport.close();\n }\n send(data) {\n this._transport.send(data);\n }\n}\n\n/** @internal */\nclass WebsocketTransport {\n constructor(endpoint, options) {\n this.endpoint = endpoint;\n this.options = options;\n this._transport = null;\n }\n name() {\n return 'websocket';\n }\n subName() {\n return 'websocket';\n }\n emulation() {\n return false;\n }\n supported() {\n return this.options.websocket !== undefined && this.options.websocket !== null;\n }\n initialize(protocol, callbacks) {\n let subProtocol = '';\n if (protocol === 'protobuf') {\n subProtocol = 'centrifuge-protobuf';\n }\n if (subProtocol !== '') {\n this._transport = new this.options.websocket(this.endpoint, subProtocol);\n }\n else {\n this._transport = new this.options.websocket(this.endpoint);\n }\n if (protocol === 'protobuf') {\n this._transport.binaryType = 'arraybuffer';\n }\n this._transport.onopen = () => {\n callbacks.onOpen();\n };\n this._transport.onerror = e => {\n callbacks.onError(e);\n };\n this._transport.onclose = closeEvent => {\n callbacks.onClose(closeEvent);\n };\n this._transport.onmessage = event => {\n callbacks.onMessage(event.data);\n };\n }\n close() {\n this._transport.close();\n }\n send(data) {\n this._transport.send(data);\n }\n}\n\n/** @internal */\nclass HttpStreamTransport {\n constructor(endpoint, options) {\n this.endpoint = endpoint;\n this.options = options;\n this._abortController = null;\n this._utf8decoder = new TextDecoder();\n this._protocol = 'json';\n }\n name() {\n return 'http_stream';\n }\n subName() {\n return 'http_stream';\n }\n emulation() {\n return true;\n }\n _handleErrors(response) {\n if (!response.ok)\n throw new Error(response.status);\n return response;\n }\n _fetchEventTarget(self, endpoint, options) {\n const eventTarget = new EventTarget();\n // fetch with connection timeout maybe? https://github.com/github/fetch/issues/175\n const fetchFunc = self.options.fetch;\n fetchFunc(endpoint, options)\n .then(self._handleErrors)\n .then(response => {\n eventTarget.dispatchEvent(new Event('open'));\n let jsonStreamBuf = '';\n let jsonStreamPos = 0;\n let protoStreamBuf = new Uint8Array();\n const reader = response.body.getReader();\n return new self.options.readableStream({\n start(controller) {\n function pump() {\n return reader.read().then(({ done, value }) => {\n // When no more data needs to be consumed, close the stream\n if (done) {\n eventTarget.dispatchEvent(new Event('close'));\n controller.close();\n return;\n }\n try {\n if (self._protocol === 'json') {\n jsonStreamBuf += self._utf8decoder.decode(value);\n while (jsonStreamPos < jsonStreamBuf.length) {\n if (jsonStreamBuf[jsonStreamPos] === '\\n') {\n const line = jsonStreamBuf.substring(0, jsonStreamPos);\n eventTarget.dispatchEvent(new MessageEvent('message', { data: line }));\n jsonStreamBuf = jsonStreamBuf.substring(jsonStreamPos + 1);\n jsonStreamPos = 0;\n }\n else {\n ++jsonStreamPos;\n }\n }\n }\n else {\n const mergedArray = new Uint8Array(protoStreamBuf.length + value.length);\n mergedArray.set(protoStreamBuf);\n mergedArray.set(value, protoStreamBuf.length);\n protoStreamBuf = mergedArray;\n while (true) {\n const result = self.options.decoder.decodeReply(protoStreamBuf);\n if (result.ok) {\n const data = protoStreamBuf.slice(0, result.pos);\n eventTarget.dispatchEvent(new MessageEvent('message', { data: data }));\n protoStreamBuf = protoStreamBuf.slice(result.pos);\n continue;\n }\n break;\n }\n }\n }\n catch (error) {\n // @ts-ignore - improve later.\n eventTarget.dispatchEvent(new Event('error', { detail: error }));\n eventTarget.dispatchEvent(new Event('close'));\n controller.close();\n return;\n }\n pump();\n }).catch(function (e) {\n // @ts-ignore - improve later.\n eventTarget.dispatchEvent(new Event('error', { detail: e }));\n eventTarget.dispatchEvent(new Event('close'));\n controller.close();\n return;\n });\n }\n return pump();\n }\n });\n })\n .catch(error => {\n // @ts-ignore - improve later.\n eventTarget.dispatchEvent(new Event('error', { detail: error }));\n eventTarget.dispatchEvent(new Event('close'));\n });\n return eventTarget;\n }\n supported() {\n return this.options.fetch !== null &&\n this.options.readableStream !== null &&\n typeof TextDecoder !== 'undefined' &&\n typeof AbortController !== 'undefined' &&\n typeof EventTarget !== 'undefined' &&\n typeof Event !== 'undefined' &&\n typeof MessageEvent !== 'undefined' &&\n typeof Error !== 'undefined';\n }\n initialize(protocol, callbacks, initialData) {\n this._protocol = protocol;\n this._abortController = new AbortController();\n let headers;\n let body;\n if (protocol === 'json') {\n headers = {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json'\n };\n body = initialData;\n }\n else {\n headers = {\n 'Accept': 'application/octet-stream',\n 'Content-Type': 'application/octet-stream'\n };\n body = initialData;\n }\n const fetchOptions = {\n method: 'POST',\n headers: headers,\n body: body,\n mode: 'cors',\n credentials: 'same-origin',\n signal: this._abortController.signal\n };\n const eventTarget = this._fetchEventTarget(this, this.endpoint, fetchOptions);\n eventTarget.addEventListener('open', () => {\n callbacks.onOpen();\n });\n eventTarget.addEventListener('error', (e) => {\n this._abortController.abort();\n callbacks.onError(e);\n });\n eventTarget.addEventListener('close', () => {\n this._abortController.abort();\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n });\n eventTarget.addEventListener('message', (e) => {\n callbacks.onMessage(e.data);\n });\n }\n close() {\n this._abortController.abort();\n }\n send(data, session, node) {\n let headers;\n let body;\n const req = {\n session: session,\n node: node,\n data: data\n };\n if (this._protocol === 'json') {\n headers = {\n 'Content-Type': 'application/json'\n };\n body = JSON.stringify(req);\n }\n else {\n headers = {\n 'Content-Type': 'application/octet-stream'\n };\n body = this.options.encoder.encodeEmulationRequest(req);\n }\n const fetchFunc = this.options.fetch;\n const fetchOptions = {\n method: 'POST',\n headers: headers,\n body: body,\n mode: 'cors',\n credentials: 'same-origin',\n };\n fetchFunc(this.options.emulationEndpoint, fetchOptions);\n }\n}\n\n/** @internal */\nclass SseTransport {\n constructor(endpoint, options) {\n this.endpoint = endpoint;\n this.options = options;\n this._protocol = 'json';\n this._transport = null;\n this._onClose = null;\n }\n name() {\n return 'sse';\n }\n subName() {\n return 'sse';\n }\n emulation() {\n return true;\n }\n supported() {\n return this.options.eventsource !== null && this.options.fetch !== null;\n }\n initialize(_protocol, callbacks, initialData) {\n let url;\n if (globalThis && globalThis.document && globalThis.document.baseURI) {\n // Handle case when endpoint is relative, like //example.com/connection/sse\n url = new URL(this.endpoint, globalThis.document.baseURI);\n }\n else {\n url = new URL(this.endpoint);\n }\n url.searchParams.append('cf_connect', initialData);\n const eventsourceOptions = {};\n const eventSource = new this.options.eventsource(url.toString(), eventsourceOptions);\n this._transport = eventSource;\n const self = this;\n eventSource.onopen = function () {\n callbacks.onOpen();\n };\n eventSource.onerror = function (e) {\n eventSource.close();\n callbacks.onError(e);\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n };\n eventSource.onmessage = function (e) {\n callbacks.onMessage(e.data);\n };\n self._onClose = function () {\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n };\n }\n close() {\n this._transport.close();\n if (this._onClose !== null) {\n this._onClose();\n }\n }\n send(data, session, node) {\n const req = {\n session: session,\n node: node,\n data: data\n };\n const headers = {\n 'Content-Type': 'application/json'\n };\n const body = JSON.stringify(req);\n const fetchFunc = this.options.fetch;\n const fetchOptions = {\n method: 'POST',\n headers: headers,\n body: body,\n mode: 'cors',\n credentials: 'same-origin',\n };\n fetchFunc(this.options.emulationEndpoint, fetchOptions);\n }\n}\n\n/** @internal */\nclass WebtransportTransport {\n constructor(endpoint, options) {\n this.endpoint = endpoint;\n this.options = options;\n this._transport = null;\n this._stream = null;\n this._writer = null;\n this._utf8decoder = new TextDecoder();\n this._protocol = 'json';\n }\n name() {\n return 'webtransport';\n }\n subName() {\n return 'webtransport';\n }\n emulation() {\n return false;\n }\n supported() {\n return this.options.webtransport !== undefined && this.options.webtransport !== null;\n }\n initialize(protocol, callbacks) {\n return __awaiter(this, void 0, void 0, function* () {\n let url;\n if (globalThis && globalThis.document && globalThis.document.baseURI) {\n // Handle case when endpoint is relative, like //example.com/connection/webtransport\n url = new URL(this.endpoint, globalThis.document.baseURI);\n }\n else {\n url = new URL(this.endpoint);\n }\n if (protocol === 'protobuf') {\n url.searchParams.append('cf_protocol', 'protobuf');\n }\n this._protocol = protocol;\n const eventTarget = new EventTarget();\n this._transport = new this.options.webtransport(url.toString());\n this._transport.closed.then(() => {\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n }).catch(() => {\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n });\n try {\n yield this._transport.ready;\n }\n catch (_a) {\n this.close();\n return;\n }\n let stream;\n try {\n stream = yield this._transport.createBidirectionalStream();\n }\n catch (_b) {\n this.close();\n return;\n }\n this._stream = stream;\n this._writer = this._stream.writable.getWriter();\n eventTarget.addEventListener('close', () => {\n callbacks.onClose({\n code: 4,\n reason: 'connection closed'\n });\n });\n eventTarget.addEventListener('message', (e) => {\n callbacks.onMessage(e.data);\n });\n this._startReading(eventTarget);\n callbacks.onOpen();\n });\n }\n _startReading(eventTarget) {\n return __awaiter(this, void 0, void 0, function* () {\n const reader = this._stream.readable.getReader();\n let jsonStreamBuf = '';\n let jsonStreamPos = 0;\n let protoStreamBuf = new Uint8Array();\n try {\n while (true) {\n const { done, value } = yield reader.read();\n if (value.length > 0) {\n if (this._protocol === 'json') {\n jsonStreamBuf += this._utf8decoder.decode(value);\n while (jsonStreamPos < jsonStreamBuf.length) {\n if (jsonStreamBuf[jsonStreamPos] === '\\n') {\n const line = jsonStreamBuf.substring(0, jsonStreamPos);\n eventTarget.dispatchEvent(new MessageEvent('message', { data: line }));\n jsonStreamBuf = jsonStreamBuf.substring(jsonStreamPos + 1);\n jsonStreamPos = 0;\n }\n else {\n ++jsonStreamPos;\n }\n }\n }\n else {\n const mergedArray = new Uint8Array(protoStreamBuf.length + value.length);\n mergedArray.set(protoStreamBuf);\n mergedArray.set(value, protoStreamBuf.length);\n protoStreamBuf = mergedArray;\n while (true) {\n const result = this.options.decoder.decodeReply(protoStreamBuf);\n if (result.ok) {\n const data = protoStreamBuf.slice(0, result.pos);\n eventTarget.dispatchEvent(new MessageEvent('message', { data: data }));\n protoStreamBuf = protoStreamBuf.slice(result.pos);\n continue;\n }\n break;\n }\n }\n }\n if (done) {\n break;\n }\n }\n }\n catch (_a) {\n eventTarget.dispatchEvent(new Event('close'));\n }\n });\n }\n close() {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n if (this._writer) {\n yield this._writer.close();\n }\n this._transport.close();\n }\n catch (e) {\n // already closed.\n }\n });\n }\n send(data) {\n return __awaiter(this, void 0, void 0, function* () {\n let binary;\n if (this._protocol === 'json') {\n // Need extra \\n since WT is non-frame protocol. \n binary = new TextEncoder().encode(data + '\\n');\n }\n else {\n binary = data;\n }\n try {\n yield this._writer.write(binary);\n }\n catch (e) {\n this.close();\n }\n });\n }\n}\n\n/*\nCopyright 2014-2024 Dmitry Chestnykh (JavaScript port)\nCopyright 2007 D. Richard Hipp (original C version)\n\nFossil SCM delta compression algorithm, this is only the applyDelta part extracted\nfrom https://github.com/dchest/fossil-delta-js. The code was slightly modified\nto strip unnecessary parts. The copyright on top of this file is from the original\nrepo on Github licensed under Simplified BSD License.\n*/\nconst zValue = [\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1,\n -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,\n 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36, -1, 37,\n 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,\n 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1,\n];\n// Reader reads bytes, chars, ints from array.\nclass Reader {\n constructor(array) {\n this.a = array; // source array\n this.pos = 0; // current position in array\n }\n haveBytes() {\n return this.pos < this.a.length;\n }\n getByte() {\n const b = this.a[this.pos];\n this.pos++;\n if (this.pos > this.a.length)\n throw new RangeError(\"out of bounds\");\n return b;\n }\n getChar() {\n return String.fromCharCode(this.getByte());\n }\n // Read base64-encoded unsigned integer.\n getInt() {\n let v = 0;\n let c;\n while (this.haveBytes() && (c = zValue[0x7f & this.getByte()]) >= 0) {\n v = (v << 6) + c;\n }\n this.pos--;\n return v >>> 0;\n }\n}\n// Write writes an array.\nclass Writer {\n constructor() {\n this.a = [];\n }\n toByteArray(sourceType) {\n if (Array.isArray(sourceType)) {\n return this.a;\n }\n return new Uint8Array(this.a);\n }\n // Copy from array at start to end.\n putArray(a, start, end) {\n // TODO: optimize.\n for (let i = start; i < end; i++)\n this.a.push(a[i]);\n }\n}\n// Return a 32-bit checksum of the array.\nfunction checksum(arr) {\n let sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, z = 0, N = arr.length;\n //TODO measure if this unrolling is helpful.\n while (N >= 16) {\n sum0 = (sum0 + arr[z + 0]) | 0;\n sum1 = (sum1 + arr[z + 1]) | 0;\n sum2 = (sum2 + arr[z + 2]) | 0;\n sum3 = (sum3 + arr[z + 3]) | 0;\n sum0 = (sum0 + arr[z + 4]) | 0;\n sum1 = (sum1 + arr[z + 5]) | 0;\n sum2 = (sum2 + arr[z + 6]) | 0;\n sum3 = (sum3 + arr[z + 7]) | 0;\n sum0 = (sum0 + arr[z + 8]) | 0;\n sum1 = (sum1 + arr[z + 9]) | 0;\n sum2 = (sum2 + arr[z + 10]) | 0;\n sum3 = (sum3 + arr[z + 11]) | 0;\n sum0 = (sum0 + arr[z + 12]) | 0;\n sum1 = (sum1 + arr[z + 13]) | 0;\n sum2 = (sum2 + arr[z + 14]) | 0;\n sum3 = (sum3 + arr[z + 15]) | 0;\n z += 16;\n N -= 16;\n }\n while (N >= 4) {\n sum0 = (sum0 + arr[z + 0]) | 0;\n sum1 = (sum1 + arr[z + 1]) | 0;\n sum2 = (sum2 + arr[z + 2]) | 0;\n sum3 = (sum3 + arr[z + 3]) | 0;\n z += 4;\n N -= 4;\n }\n sum3 = (((((sum3 + (sum2 << 8)) | 0) + (sum1 << 16)) | 0) + (sum0 << 24)) | 0;\n switch (N) {\n //@ts-ignore fallthrough is needed.\n case 3:\n sum3 = (sum3 + (arr[z + 2] << 8)) | 0; /* falls through */\n //@ts-ignore fallthrough is needed.\n case 2:\n sum3 = (sum3 + (arr[z + 1] << 16)) | 0; /* falls through */\n case 1:\n sum3 = (sum3 + (arr[z + 0] << 24)) | 0; /* falls through */\n }\n return sum3 >>> 0;\n}\n/**\n * Apply a delta byte array to a source byte array, returning the target byte array.\n */\nfunction applyDelta(source, delta) {\n let total = 0;\n const zDelta = new Reader(delta);\n const lenSrc = source.length;\n const lenDelta = delta.length;\n const limit = zDelta.getInt();\n if (zDelta.getChar() !== \"\\n\")\n throw new Error(\"size integer not terminated by '\\\\n'\");\n const zOut = new Writer();\n while (zDelta.haveBytes()) {\n const cnt = zDelta.getInt();\n let ofst;\n switch (zDelta.getChar()) {\n case \"@\":\n ofst = zDelta.getInt();\n if (zDelta.haveBytes() && zDelta.getChar() !== \",\")\n throw new Error(\"copy command not terminated by ','\");\n total += cnt;\n if (total > limit)\n throw new Error(\"copy exceeds output file size\");\n if (ofst + cnt > lenSrc)\n throw new Error(\"copy extends past end of input\");\n zOut.putArray(source, ofst, ofst + cnt);\n break;\n case \":\":\n total += cnt;\n if (total > limit)\n throw new Error(\"insert command gives an output larger than predicted\");\n if (cnt > lenDelta)\n throw new Error(\"insert count exceeds size of delta\");\n zOut.putArray(zDelta.a, zDelta.pos, zDelta.pos + cnt);\n zDelta.pos += cnt;\n break;\n case \";\":\n {\n const out = zOut.toByteArray(source);\n if (cnt !== checksum(out))\n throw new Error(\"bad checksum\");\n if (total !== limit)\n throw new Error(\"generated size does not match predicted size\");\n return out;\n }\n default:\n throw new Error(\"unknown delta operator\");\n }\n }\n throw new Error(\"unterminated delta\");\n}\n\n/** @internal */\nclass JsonCodec {\n name() {\n return 'json';\n }\n encodeCommands(commands) {\n return commands.map(c => JSON.stringify(c)).join('\\n');\n }\n decodeReplies(data) {\n return data.trim().split('\\n').map(r => JSON.parse(r));\n }\n applyDeltaIfNeeded(pub, prevValue) {\n let newData, newPrevValue;\n if (pub.delta) {\n // JSON string delta.\n const valueArray = applyDelta(prevValue, new TextEncoder().encode(pub.data));\n newData = JSON.parse(new TextDecoder().decode(valueArray));\n newPrevValue = valueArray;\n }\n else {\n // Full data as JSON string.\n newData = JSON.parse(pub.data);\n newPrevValue = new TextEncoder().encode(pub.data);\n }\n return { newData, newPrevValue };\n }\n}\n\nconst defaults = {\n headers: {},\n token: '',\n getToken: null,\n data: null,\n getData: null,\n debug: false,\n name: 'js',\n version: '',\n fetch: null,\n readableStream: null,\n websocket: null,\n eventsource: null,\n sockjs: null,\n sockjsOptions: {},\n emulationEndpoint: '/emulation',\n minReconnectDelay: 500,\n maxReconnectDelay: 20000,\n timeout: 5000,\n maxServerPingDelay: 10000,\n networkEventTarget: null,\n};\nclass UnauthorizedError extends Error {\n constructor(message) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n/** Centrifuge is a Centrifuge/Centrifugo bidirectional client. */\nclass Centrifuge extends EventEmitter$1 {\n /** Constructs Centrifuge client. Call connect() method to start connecting. */\n constructor(endpoint, options) {\n super();\n this._reconnectTimeout = null;\n this._refreshTimeout = null;\n this._serverPingTimeout = null;\n this.state = State.Disconnected;\n this._transportIsOpen = false;\n this._endpoint = endpoint;\n this._emulation = false;\n this._transports = [];\n this._currentTransportIndex = 0;\n this._triedAllTransports = false;\n this._transportWasOpen = false;\n this._transport = null;\n this._transportId = 0;\n this._deviceWentOffline = false;\n this._transportClosed = true;\n this._codec = new JsonCodec();\n this._reconnecting = false;\n this._reconnectTimeout = null;\n this._reconnectAttempts = 0;\n this._client = null;\n this._session = '';\n this._node = '';\n this._subs = {};\n this._serverSubs = {};\n this._commandId = 0;\n this._commands = [];\n this._batching = false;\n this._refreshRequired = false;\n this._refreshTimeout = null;\n this._callbacks = {};\n this._token = '';\n this._data = null;\n this._dispatchPromise = Promise.resolve();\n this._serverPing = 0;\n this._serverPingTimeout = null;\n this._sendPong = false;\n this._promises = {};\n this._promiseId = 0;\n this._debugEnabled = false;\n this._networkEventsSet = false;\n this._config = Object.assign(Object.assign({}, defaults), options);\n this._configure();\n if (this._debugEnabled) {\n this.on('state', (ctx) => {\n this._debug('client state', ctx.oldState, '->', ctx.newState);\n });\n this.on('error', (ctx) => {\n this._debug('client error', ctx);\n });\n }\n else {\n // Avoid unhandled exception in EventEmitter for non-set error handler.\n this.on('error', function () { Function.prototype(); });\n }\n }\n /** newSubscription allocates new Subscription to a channel. Since server only allows\n * one subscription per channel per client this method throws if client already has\n * channel subscription in internal registry.\n * */\n newSubscription(channel, options) {\n if (this.getSubscription(channel) !== null) {\n throw new Error('Subscription to the channel ' + channel + ' already exists');\n }\n const sub = new Subscription(this, channel, options);\n this._subs[channel] = sub;\n return sub;\n }\n /** getSubscription returns Subscription if it's registered in the internal\n * registry or null. */\n getSubscription(channel) {\n return this._getSub(channel);\n }\n /** removeSubscription allows removing Subcription from the internal registry. */\n removeSubscription(sub) {\n if (!sub) {\n return;\n }\n if (sub.state !== SubscriptionState.Unsubscribed) {\n sub.unsubscribe();\n }\n this._removeSubscription(sub);\n }\n /** Get a map with all current client-side subscriptions. */\n subscriptions() {\n return this._subs;\n }\n /** ready returns a Promise which resolves upon client goes to Connected\n * state and rejects in case of client goes to Disconnected or Failed state.\n * Users can provide optional timeout in milliseconds. */\n ready(timeout) {\n return __awaiter(this, void 0, void 0, function* () {\n switch (this.state) {\n case State.Disconnected:\n throw { code: errorCodes.clientDisconnected, message: 'client disconnected' };\n case State.Connected:\n return;\n default:\n return new Promise((resolve, reject) => {\n const ctx = { resolve, reject };\n if (timeout) {\n ctx.timeout = setTimeout(() => {\n reject({ code: errorCodes.timeout, message: 'timeout' });\n }, timeout);\n }\n this._promises[this._nextPromiseId()] = ctx;\n });\n }\n });\n }\n /** connect to a server. */\n connect() {\n if (this._isConnected()) {\n this._debug('connect called when already connected');\n return;\n }\n if (this._isConnecting()) {\n this._debug('connect called when already connecting');\n return;\n }\n this._debug('connect called');\n this._reconnectAttempts = 0;\n this._startConnecting();\n }\n /** disconnect from a server. */\n disconnect() {\n this._disconnect(disconnectedCodes.disconnectCalled, 'disconnect called', false);\n }\n /** setToken allows setting connection token. Or resetting used token to be empty. */\n setToken(token) {\n this._token = token;\n }\n /** setData allows setting connection data. This only affects the next connection attempt,\n * not the current one. Note that if getData callback is configured, it will override\n * this value during reconnects. */\n setData(data) {\n this._data = data;\n }\n /** setHeaders allows setting connection emulated headers. */\n setHeaders(headers) {\n this._config.headers = headers;\n }\n /** send asynchronous data to a server (without any response from a server\n * expected, see rpc method if you need response). */\n send(data) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n send: {\n data\n }\n };\n yield this._methodCall();\n const sent = this._transportSendCommands([cmd]); // can send message to server without id set\n if (!sent) {\n throw this._createErrorObject(errorCodes.transportWriteError, 'transport write error');\n }\n });\n }\n /** rpc to a server - i.e. a call which waits for a response with data. */\n rpc(method, data) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n rpc: {\n method,\n data\n }\n };\n yield this._methodCall();\n const result = yield this._callPromise(cmd, (reply) => reply.rpc);\n return {\n data: result.data\n };\n });\n }\n /** publish data to a channel. */\n publish(channel, data) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n publish: {\n channel,\n data\n }\n };\n yield this._methodCall();\n yield this._callPromise(cmd, () => ({}));\n return {};\n });\n }\n /** history for a channel. By default it does not return publications (only current\n * StreamPosition data) – provide an explicit limit > 0 to load publications.*/\n history(channel, options) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n history: this._getHistoryRequest(channel, options)\n };\n yield this._methodCall();\n const result = yield this._callPromise(cmd, (reply) => reply.history);\n const publications = [];\n if (result.publications) {\n for (let i = 0; i < result.publications.length; i++) {\n publications.push(this._getPublicationContext(channel, result.publications[i]));\n }\n }\n return {\n publications,\n epoch: result.epoch || '',\n offset: result.offset || 0\n };\n });\n }\n /** presence for a channel. */\n presence(channel) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n presence: {\n channel\n }\n };\n yield this._methodCall();\n const result = yield this._callPromise(cmd, (reply) => reply.presence);\n const clients = result.presence;\n for (const clientId in clients) {\n if (Object.prototype.hasOwnProperty.call(clients, clientId)) {\n const rawClient = clients[clientId];\n const connInfo = rawClient['conn_info'];\n const chanInfo = rawClient['chan_info'];\n if (connInfo) {\n rawClient.connInfo = connInfo;\n }\n if (chanInfo) {\n rawClient.chanInfo = chanInfo;\n }\n }\n }\n return { clients };\n });\n }\n presenceStats(channel) {\n return __awaiter(this, void 0, void 0, function* () {\n const cmd = {\n 'presence_stats': {\n channel\n }\n };\n yield this._methodCall();\n const result = yield this._callPromise(cmd, (reply) => {\n return reply.presence_stats;\n });\n return {\n numUsers: result.num_users,\n numClients: result.num_clients\n };\n });\n }\n /** start command batching (collect into temporary buffer without sending to a server)\n * until stopBatching called.*/\n startBatching() {\n // start collecting messages without sending them to Centrifuge until flush\n // method called\n this._batching = true;\n }\n /** stop batching commands and flush collected commands to the\n * network (all in one request/frame).*/\n stopBatching() {\n const self = this;\n // Why so nested? Two levels here requred to deal with promise resolving queue.\n // In Subscription case we wait 2 futures before sending data to connection.\n // Otherwise _batching becomes false before batching decision has a chance to be executed.\n Promise.resolve().then(function () {\n Promise.resolve().then(function () {\n self._batching = false;\n self._flush();\n });\n });\n }\n _debug(...args) {\n if (!this._debugEnabled) {\n return;\n }\n log('debug', args);\n }\n _codecName() {\n return this._codec.name();\n }\n /** @internal */\n _formatOverride() {\n return;\n }\n _configure() {\n if (!('Promise' in globalThis)) {\n throw new Error('Promise polyfill required');\n }\n if (!this._endpoint) {\n throw new Error('endpoint configuration required');\n }\n if (this._config.token !== null) {\n this._token = this._config.token;\n }\n if (this._config.data !== null) {\n this._data = this._config.data;\n }\n this._codec = new JsonCodec();\n this._formatOverride();\n if (this._config.debug === true ||\n (typeof localStorage !== 'undefined' && typeof localStorage.getItem === 'function' && localStorage.getItem('centrifuge.debug'))) {\n this._debugEnabled = true;\n }\n this._debug('config', this._config);\n if (typeof this._endpoint === 'string') ;\n else if (Array.isArray(this._endpoint)) {\n this._transports = this._endpoint;\n this._emulation = true;\n for (const i in this._transports) {\n if (this._transports.hasOwnProperty(i)) {\n const transportConfig = this._transports[i];\n if (!transportConfig.endpoint || !transportConfig.transport) {\n throw new Error('malformed transport configuration');\n }\n const transportName = transportConfig.transport;\n if (['websocket', 'http_stream', 'sse', 'sockjs', 'webtransport'].indexOf(transportName) < 0) {\n throw new Error('unsupported transport name: ' + transportName);\n }\n }\n }\n }\n else {\n throw new Error('unsupported url configuration type: only string or array of objects are supported');\n }\n }\n _setState(newState) {\n if (this.state !== newState) {\n this._reconnecting = false;\n const oldState = this.state;\n this.state = newState;\n this.emit('state', { newState, oldState });\n return true;\n }\n return false;\n }\n _isDisconnected() {\n return this.state === State.Disconnected;\n }\n _isConnecting() {\n return this.state === State.Connecting;\n }\n _isConnected() {\n return this.state === State.Connected;\n }\n _nextCommandId() {\n return ++this._commandId;\n }\n _setNetworkEvents() {\n if (this._networkEventsSet) {\n return;\n }\n let eventTarget = null;\n if (this._config.networkEventTarget !== null) {\n eventTarget = this._config.networkEventTarget;\n }\n else if (typeof globalThis.addEventListener !== 'undefined') {\n eventTarget = globalThis;\n }\n if (eventTarget) {\n eventTarget.addEventListener('offline', () => {\n this._debug('offline event triggered');\n if (this.state === State.Connected || this.state === State.Connecting) {\n this._disconnect(connectingCodes.transportClosed, 'transport closed', true);\n this._deviceWentOffline = true;\n }\n });\n eventTarget.addEventListener('online', () => {\n this._debug('online event triggered');\n if (this.state !== State.Connecting) {\n return;\n }\n if (this._deviceWentOffline && !this._transportClosed) {\n // This is a workaround for mobile Safari where close callback may be\n // not issued upon device going to the flight mode. We know for sure\n // that transport close was called, so we start reconnecting. In this\n // case if the close callback will be issued for some reason after some\n // time – it will be ignored due to transport ID mismatch.\n this._deviceWentOffline = false;\n this._transportClosed = true;\n }\n this._clearReconnectTimeout();\n this._startReconnecting();\n });\n this._networkEventsSet = true;\n }\n }\n _getReconnectDelay() {\n const delay = backoff(this._reconnectAttempts, this._config.minReconnectDelay, this._config.maxReconnectDelay);\n this._reconnectAttempts += 1;\n return delay;\n }\n _clearOutgoingRequests() {\n // fire errbacks of registered outgoing calls.\n for (const id in this._callbacks) {\n if (this._callbacks.hasOwnProperty(id)) {\n const callbacks = this._callbacks[id];\n clearTimeout(callbacks.timeout);\n const errback = callbacks.errback;\n if (!errback) {\n continue;\n }\n errback({ error: this._createErrorObject(errorCodes.connectionClosed, 'connection closed') });\n }\n }\n this._callbacks = {};\n }\n _clearConnectedState() {\n this._client = null;\n this._clearServerPingTimeout();\n this._clearRefreshTimeout();\n // fire events for client-side subscriptions.\n for (const channel in this._subs) {\n if (!this._subs.hasOwnProperty(channel)) {\n continue;\n }\n const sub = this._subs[channel];\n if (sub.state === SubscriptionState.Subscribed) {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._setSubscribing(subscribingCodes.transportClosed, 'transport closed');\n }\n }\n // fire events for server-side subscriptions.\n for (const channel in this._serverSubs) {\n if (this._serverSubs.hasOwnProperty(channel)) {\n this.emit('subscribing', { channel: channel });\n }\n }\n }\n _handleWriteError(commands) {\n for (const command of commands) {\n const id = command.id;\n if (!(id in this._callbacks)) {\n continue;\n }\n const callbacks = this._callbacks[id];\n clearTimeout(this._callbacks[id].timeout);\n delete this._callbacks[id];\n const errback = callbacks.errback;\n errback({ error: this._createErrorObject(errorCodes.transportWriteError, 'transport write error') });\n }\n }\n _transportSendCommands(commands) {\n if (!commands.length) {\n return true;\n }\n if (!this._transport) {\n return false;\n }\n try {\n this._transport.send(this._codec.encodeCommands(commands), this._session, this._node);\n }\n catch (e) {\n this._debug('error writing commands', e);\n this._handleWriteError(commands);\n return false;\n }\n return true;\n }\n _initializeTransport() {\n let websocket;\n if (this._config.websocket !== null) {\n websocket = this._config.websocket;\n }\n else {\n if (!(typeof globalThis.WebSocket !== 'function' && typeof globalThis.WebSocket !== 'object')) {\n websocket = globalThis.WebSocket;\n }\n }\n let sockjs = null;\n if (this._config.sockjs !== null) {\n sockjs = this._config.sockjs;\n }\n else {\n if (typeof globalThis.SockJS !== 'undefined') {\n sockjs = globalThis.SockJS;\n }\n }\n let eventsource = null;\n if (this._config.eventsource !== null) {\n eventsource = this._config.eventsource;\n }\n else {\n if (typeof globalThis.EventSource !== 'undefined') {\n eventsource = globalThis.EventSource;\n }\n }\n let fetchFunc = null;\n if (this._config.fetch !== null) {\n fetchFunc = this._config.fetch;\n }\n else {\n if (typeof globalThis.fetch !== 'undefined') {\n fetchFunc = globalThis.fetch;\n }\n }\n let readableStream = null;\n if (this._config.readableStream !== null) {\n readableStream = this._config.readableStream;\n }\n else {\n if (typeof globalThis.ReadableStream !== 'undefined') {\n readableStream = globalThis.ReadableStream;\n }\n }\n if (!this._emulation) {\n if (startsWith(this._endpoint, 'http')) {\n throw new Error('Provide explicit transport endpoints configuration in case of using HTTP (i.e. using array of TransportEndpoint instead of a single string), or use ws(s):// scheme in an endpoint if you aimed using WebSocket transport');\n }\n else {\n this._debug('client will use websocket');\n this._transport = new WebsocketTransport(this._endpoint, {\n websocket: websocket\n });\n if (!this._transport.supported()) {\n throw new Error('WebSocket constructor not found, make sure it is available globally or passed as a dependency in Centrifuge options');\n }\n }\n }\n else {\n if (this._currentTransportIndex >= this._transports.length) {\n this._triedAllTransports = true;\n this._currentTransportIndex = 0;\n }\n let count = 0;\n while (true) {\n if (count >= this._transports.length) {\n throw new Error('no supported transport found');\n }\n const transportConfig = this._transports[this._currentTransportIndex];\n const transportName = transportConfig.transport;\n const transportEndpoint = transportConfig.endpoint;\n if (transportName === 'websocket') {\n this._debug('trying websocket transport');\n this._transport = new WebsocketTransport(transportEndpoint, {\n websocket: websocket\n });\n if (!this._transport.supported()) {\n this._debug('websocket transport not available');\n this._currentTransportIndex++;\n count++;\n continue;\n }\n }\n else if (transportName === 'webtransport') {\n this._debug('trying webtransport transport');\n this._transport = new WebtransportTransport(transportEndpoint, {\n webtransport: globalThis.WebTransport,\n decoder: this._codec,\n encoder: this._codec\n });\n if (!this._transport.supported()) {\n this._debug('webtransport transport not available');\n this._currentTransportIndex++;\n count++;\n continue;\n }\n }\n else if (transportName === 'http_stream') {\n this._debug('trying http_stream transport');\n this._transport = new HttpStreamTransport(transportEndpoint, {\n fetch: fetchFunc,\n readableStream: readableStream,\n emulationEndpoint: this._config.emulationEndpoint,\n decoder: this._codec,\n encoder: this._codec\n });\n if (!this._transport.supported()) {\n this._debug('http_stream transport not available');\n this._currentTransportIndex++;\n count++;\n continue;\n }\n }\n else if (transportName === 'sse') {\n this._debug('trying sse transport');\n this._transport = new SseTransport(transportEndpoint, {\n eventsource: eventsource,\n fetch: fetchFunc,\n emulationEndpoint: this._config.emulationEndpoint,\n });\n if (!this._transport.supported()) {\n this._debug('sse transport not available');\n this._currentTransportIndex++;\n count++;\n continue;\n }\n }\n else if (transportName === 'sockjs') {\n this._debug('trying sockjs');\n this._transport = new SockjsTransport(transportEndpoint, {\n sockjs: sockjs,\n sockjsOptions: this._config.sockjsOptions\n });\n if (!this._transport.supported()) {\n this._debug('sockjs transport not available');\n this._currentTransportIndex++;\n count++;\n continue;\n }\n }\n else {\n throw new Error('unknown transport ' + transportName);\n }\n break;\n }\n }\n const self = this;\n const transport = this._transport;\n const transportId = this._nextTransportId();\n self._debug(\"id of transport\", transportId);\n let wasOpen = false;\n const initialCommands = [];\n if (this._transport.emulation()) {\n const connectCommand = self._sendConnect(true);\n initialCommands.push(connectCommand);\n }\n this._setNetworkEvents();\n const initialData = this._codec.encodeCommands(initialCommands);\n this._transportClosed = false;\n let connectTimeout;\n connectTimeout = setTimeout(function () {\n transport.close();\n }, this._config.timeout);\n this._transport.initialize(this._codecName(), {\n onOpen: function () {\n if (connectTimeout) {\n clearTimeout(connectTimeout);\n connectTimeout = null;\n }\n if (self._transportId != transportId) {\n self._debug('open callback from non-actual transport');\n transport.close();\n return;\n }\n wasOpen = true;\n self._debug(transport.subName(), 'transport open');\n if (transport.emulation()) {\n return;\n }\n self._transportIsOpen = true;\n self._transportWasOpen = true;\n self.startBatching();\n self._sendConnect(false);\n self._sendSubscribeCommands();\n self.stopBatching();\n //@ts-ignore must be used only for debug and test purposes. Exposed only for non-emulation transport.\n self.emit('__centrifuge_debug:connect_frame_sent', {});\n },\n onError: function (e) {\n if (self._transportId != transportId) {\n self._debug('error callback from non-actual transport');\n return;\n }\n self._debug('transport level error', e);\n },\n onClose: function (closeEvent) {\n if (connectTimeout) {\n clearTimeout(connectTimeout);\n connectTimeout = null;\n }\n if (self._transportId != transportId) {\n self._debug('close callback from non-actual transport');\n return;\n }\n self._debug(transport.subName(), 'transport closed');\n self._transportClosed = true;\n self._transportIsOpen = false;\n let reason = 'connection closed';\n let needReconnect = true;\n let code = 0;\n if (closeEvent && 'code' in closeEvent && closeEvent.code) {\n code = closeEvent.code;\n }\n if (closeEvent && closeEvent.reason) {\n try {\n const advice = JSON.parse(closeEvent.reason);\n reason = advice.reason;\n needReconnect = advice.reconnect;\n }\n catch (e) {\n reason = closeEvent.reason;\n if ((code >= 3500 && code < 4000) || (code >= 4500 && code < 5000)) {\n needReconnect = false;\n }\n }\n }\n if (code < 3000) {\n if (code === 1009) {\n code = disconnectedCodes.messageSizeLimit;\n reason = 'message size limit exceeded';\n needReconnect = false;\n }\n else {\n code = connectingCodes.transportClosed;\n reason = 'transport closed';\n }\n if (self._emulation && !self._transportWasOpen) {\n self._currentTransportIndex++;\n if (self._currentTransportIndex >= self._transports.length) {\n self._triedAllTransports = true;\n self._currentTransportIndex = 0;\n }\n }\n }\n else {\n // Codes >= 3000 are sent from a server application level.\n self._transportWasOpen = true;\n }\n if (self._isConnecting() && !wasOpen) {\n self.emit('error', {\n type: 'transport',\n error: {\n code: errorCodes.transportClosed,\n message: 'transport closed'\n },\n transport: transport.name()\n });\n }\n self._reconnecting = false;\n self._disconnect(code, reason, needReconnect);\n },\n onMessage: function (data) {\n self._dataReceived(data);\n }\n }, initialData);\n //@ts-ignore must be used only for debug and test purposes.\n self.emit('__centrifuge_debug:transport_initialized', {});\n }\n _sendConnect(skipSending) {\n const connectCommand = this._constructConnectCommand();\n const self = this;\n this._call(connectCommand, skipSending).then(resolveCtx => {\n const result = resolveCtx.reply.connect;\n self._connectResponse(result);\n if (resolveCtx.next) {\n resolveCtx.next();\n }\n }, rejectCtx => {\n self._connectError(rejectCtx.error);\n if (rejectCtx.next) {\n rejectCtx.next();\n }\n });\n return connectCommand;\n }\n _startReconnecting() {\n this._debug('start reconnecting');\n if (!this._isConnecting()) {\n this._debug('stop reconnecting: client not in connecting state');\n return;\n }\n if (this._reconnecting) {\n this._debug('reconnect already in progress, return from reconnect routine');\n return;\n }\n if (this._transportClosed === false) {\n this._debug('waiting for transport close');\n return;\n }\n this._reconnecting = true;\n const emptyToken = this._token === '';\n const needTokenRefresh = this._refreshRequired || (emptyToken && this._config.getToken !== null);\n if (!needTokenRefresh) {\n if (this._config.getData) {\n this._config.getData().then(data => {\n if (!this._isConnecting()) {\n return;\n }\n this._data = data;\n this._initializeTransport();\n })\n .catch(e => this._handleGetDataError(e));\n }\n else {\n this._initializeTransport();\n }\n return;\n }\n const self = this;\n this._getToken().then(function (token) {\n if (!self._isConnecting()) {\n return;\n }\n if (token == null || token == undefined) {\n self._failUnauthorized();\n return;\n }\n self._token = token;\n self._debug('connection token refreshed');\n if (self._config.getData) {\n self._config.getData().then(function (data) {\n if (!self._isConnecting()) {\n return;\n }\n self._data = data;\n self._initializeTransport();\n })\n .catch(e => self._handleGetDataError(e));\n }\n else {\n self._initializeTransport();\n }\n }).catch(function (e) {\n if (!self._isConnecting()) {\n return;\n }\n if (e instanceof UnauthorizedError) {\n self._failUnauthorized();\n return;\n }\n self.emit('error', {\n 'type': 'connectToken',\n 'error': {\n code: errorCodes.clientConnectToken,\n message: e !== undefined ? e.toString() : ''\n }\n });\n const delay = self._getReconnectDelay();\n self._debug('error on getting connection token, reconnect after ' + delay + ' milliseconds', e);\n self._reconnecting = false;\n self._reconnectTimeout = setTimeout(() => {\n self._startReconnecting();\n }, delay);\n });\n }\n _handleGetDataError(e) {\n if (e instanceof UnauthorizedError) {\n this._failUnauthorized();\n return;\n }\n this.emit('error', {\n type: 'connectData',\n error: {\n code: errorCodes.badConfiguration,\n message: (e === null || e === void 0 ? void 0 : e.toString()) || ''\n }\n });\n const delay = this._getReconnectDelay();\n this._debug('error on getting connect data, reconnect after ' + delay + ' milliseconds', e);\n this._reconnecting = false;\n this._reconnectTimeout = setTimeout(() => {\n this._startReconnecting();\n }, delay);\n }\n _connectError(err) {\n if (this.state !== State.Connecting) {\n return;\n }\n if (err.code === 109) { // token expired.\n // next connect attempt will try to refresh token.\n this._refreshRequired = true;\n }\n if (err.code < 100 || err.temporary === true || err.code === 109) {\n this.emit('error', {\n 'type': 'connect',\n 'error': err\n });\n this._debug('closing transport due to connect error');\n this._disconnect(err.code, err.message, true);\n }\n else {\n this._disconnect(err.code, err.message, false);\n }\n }\n _scheduleReconnect() {\n if (!this._isConnecting()) {\n return;\n }\n let isInitialHandshake = false;\n if (this._emulation && !this._transportWasOpen && !this._triedAllTransports) {\n isInitialHandshake = true;\n }\n let delay = this._getReconnectDelay();\n if (isInitialHandshake) {\n delay = 0;\n }\n this._debug('reconnect after ' + delay + ' milliseconds');\n this._clearReconnectTimeout();\n this._reconnectTimeout = setTimeout(() => {\n this._startReconnecting();\n }, delay);\n }\n _constructConnectCommand() {\n const req = {};\n if (this._token) {\n req.token = this._token;\n }\n if (this._data) {\n req.data = this._data;\n }\n if (this._config.name) {\n req.name = this._config.name;\n }\n if (this._config.version) {\n req.version = this._config.version;\n }\n if (Object.keys(this._config.headers).length > 0) {\n req.headers = this._config.headers;\n }\n const subs = {};\n let hasSubs = false;\n for (const channel in this._serverSubs) {\n if (this._serverSubs.hasOwnProperty(channel) && this._serverSubs[channel].recoverable) {\n hasSubs = true;\n const sub = {\n 'recover': true\n };\n if (this._serverSubs[channel].offset) {\n sub['offset'] = this._serverSubs[channel].offset;\n }\n if (this._serverSubs[channel].epoch) {\n sub['epoch'] = this._serverSubs[channel].epoch;\n }\n subs[channel] = sub;\n }\n }\n if (hasSubs) {\n req.subs = subs;\n }\n return {\n connect: req\n };\n }\n _getHistoryRequest(channel, options) {\n const req = {\n channel: channel\n };\n if (options !== undefined) {\n if (options.since) {\n req.since = {\n offset: options.since.offset\n };\n if (options.since.epoch) {\n req.since.epoch = options.since.epoch;\n }\n }\n if (options.limit !== undefined) {\n req.limit = options.limit;\n }\n if (options.reverse === true) {\n req.reverse = true;\n }\n }\n return req;\n }\n _methodCall() {\n if (this._isConnected()) {\n return Promise.resolve();\n }\n return new Promise((res, rej) => {\n const timeout = setTimeout(function () {\n rej({ code: errorCodes.timeout, message: 'timeout' });\n }, this._config.timeout);\n this._promises[this._nextPromiseId()] = {\n timeout: timeout,\n resolve: res,\n reject: rej\n };\n });\n }\n _callPromise(cmd, resultCB) {\n return new Promise((resolve, reject) => {\n this._call(cmd, false).then((resolveCtx) => {\n var _a;\n const result = resultCB(resolveCtx.reply);\n resolve(result);\n (_a = resolveCtx.next) === null || _a === void 0 ? void 0 : _a.call(resolveCtx);\n }, (rejectCtx) => {\n var _a;\n reject(rejectCtx.error);\n (_a = rejectCtx.next) === null || _a === void 0 ? void 0 : _a.call(rejectCtx);\n });\n });\n }\n _dataReceived(data) {\n if (this._serverPing > 0) {\n this._waitServerPing();\n }\n const replies = this._codec.decodeReplies(data);\n // We have to guarantee order of events in replies processing - i.e. start processing\n // next reply only when we finished processing of current one. Without syncing things in\n // this way we could get wrong publication events order as reply promises resolve\n // on next loop tick so for loop continues before we finished emitting all reply events.\n this._dispatchPromise = this._dispatchPromise.then(() => {\n let finishDispatch;\n this._dispatchPromise = new Promise(resolve => {\n finishDispatch = resolve;\n });\n this._dispatchSynchronized(replies, finishDispatch);\n });\n }\n _dispatchSynchronized(replies, finishDispatch) {\n let p = Promise.resolve();\n for (const i in replies) {\n if (replies.hasOwnProperty(i)) {\n p = p.then(() => {\n return this._dispatchReply(replies[i]);\n });\n }\n }\n p = p.then(() => {\n finishDispatch();\n });\n }\n _dispatchReply(reply) {\n let next;\n const p = new Promise(resolve => {\n next = resolve;\n });\n if (reply === undefined || reply === null) {\n this._debug('dispatch: got undefined or null reply');\n next();\n return p;\n }\n const id = reply.id;\n if (id && id > 0) {\n this._handleReply(reply, next);\n }\n else {\n if (!reply.push) {\n this._handleServerPing(next);\n }\n else {\n this._handlePush(reply.push, next);\n }\n }\n return p;\n }\n _call(cmd, skipSending) {\n return new Promise((resolve, reject) => {\n cmd.id = this._nextCommandId();\n this._registerCall(cmd.id, resolve, reject);\n if (!skipSending) {\n this._addCommand(cmd);\n }\n });\n }\n _startConnecting() {\n this._debug('start connecting');\n if (this._setState(State.Connecting)) {\n this.emit('connecting', { code: connectingCodes.connectCalled, reason: 'connect called' });\n }\n this._client = null;\n this._startReconnecting();\n }\n _disconnect(code, reason, reconnect) {\n if (this._isDisconnected()) {\n return;\n }\n // we mark transport is closed right away, because _clearConnectedState will move subscriptions to subscribing state\n // if transport will still be open at this time, subscribe frames will be sent to closing transport\n this._transportIsOpen = false;\n const previousState = this.state;\n this._reconnecting = false;\n const ctx = {\n code: code,\n reason: reason\n };\n let needEvent = false;\n if (reconnect) {\n needEvent = this._setState(State.Connecting);\n }\n else {\n needEvent = this._setState(State.Disconnected);\n this._rejectPromises({ code: errorCodes.clientDisconnected, message: 'disconnected' });\n }\n this._clearOutgoingRequests();\n if (previousState === State.Connecting) {\n this._clearReconnectTimeout();\n }\n if (previousState === State.Connected) {\n this._clearConnectedState();\n }\n if (needEvent) {\n if (this._isConnecting()) {\n this.emit('connecting', ctx);\n }\n else {\n this.emit('disconnected', ctx);\n }\n }\n if (this._transport) {\n this._debug(\"closing existing transport\");\n const transport = this._transport;\n this._transport = null;\n transport.close(); // Close only after setting this._transport to null to avoid recursion when calling transport close().\n // Need to mark as closed here, because connect call may be sync called after disconnect,\n // transport onClose callback will not be called yet\n this._transportClosed = true;\n this._nextTransportId();\n }\n else {\n this._debug(\"no transport to close\");\n }\n this._scheduleReconnect();\n }\n _failUnauthorized() {\n this._disconnect(disconnectedCodes.unauthorized, 'unauthorized', false);\n }\n _getToken() {\n this._debug('get connection token');\n if (!this._config.getToken) {\n this.emit('error', {\n type: 'configuration',\n error: {\n code: errorCodes.badConfiguration,\n message: 'token expired but no getToken function set in the configuration'\n }\n });\n return Promise.reject(new UnauthorizedError(''));\n }\n return this._config.getToken({});\n }\n _refresh() {\n const clientId = this._client;\n const self = this;\n this._getToken().then(function (token) {\n if (clientId !== self._client) {\n return;\n }\n if (!token) {\n self._failUnauthorized();\n return;\n }\n self._token = token;\n self._debug('connection token refreshed');\n if (!self._isConnected()) {\n return;\n }\n const cmd = {\n refresh: { token: self._token }\n };\n self._call(cmd, false).then(resolveCtx => {\n const result = resolveCtx.reply.refresh;\n self._refreshResponse(result);\n if (resolveCtx.next) {\n resolveCtx.next();\n }\n }, rejectCtx => {\n self._refreshError(rejectCtx.error);\n if (rejectCtx.next) {\n rejectCtx.next();\n }\n });\n }).catch(function (e) {\n if (!self._isConnected()) {\n return;\n }\n if (e instanceof UnauthorizedError) {\n self._failUnauthorized();\n return;\n }\n self.emit('error', {\n type: 'refreshToken',\n error: {\n code: errorCodes.clientRefreshToken,\n message: e !== undefined ? e.toString() : ''\n }\n });\n self._refreshTimeout = setTimeout(() => self._refresh(), self._getRefreshRetryDelay());\n });\n }\n _refreshError(err) {\n if (err.code < 100 || err.temporary === true) {\n this.emit('error', {\n type: 'refresh',\n error: err\n });\n this._refreshTimeout = setTimeout(() => this._refresh(), this._getRefreshRetryDelay());\n }\n else {\n this._disconnect(err.code, err.message, false);\n }\n }\n _getRefreshRetryDelay() {\n return backoff(0, 5000, 10000);\n }\n _refreshResponse(result) {\n if (this._refreshTimeout) {\n clearTimeout(this._refreshTimeout);\n this._refreshTimeout = null;\n }\n if (result.expires) {\n this._client = result.client;\n this._refreshTimeout = setTimeout(() => this._refresh(), ttlMilliseconds(result.ttl));\n }\n }\n _removeSubscription(sub) {\n if (sub === null) {\n return;\n }\n delete this._subs[sub.channel];\n }\n _unsubscribe(sub) {\n if (!this._transportIsOpen) {\n return Promise.resolve();\n }\n const req = {\n channel: sub.channel\n };\n const cmd = { unsubscribe: req };\n const self = this;\n const unsubscribePromise = new Promise((resolve, _) => {\n this._call(cmd, false).then(resolveCtx => {\n resolve();\n if (resolveCtx.next) {\n resolveCtx.next();\n }\n }, rejectCtx => {\n resolve();\n if (rejectCtx.next) {\n rejectCtx.next();\n }\n self._disconnect(connectingCodes.unsubscribeError, 'unsubscribe error', true);\n });\n });\n return unsubscribePromise;\n }\n _getSub(channel, id) {\n if (id && id > 0) {\n for (const ch in this._subs) {\n if (this._subs.hasOwnProperty(ch)) {\n const sub = this._subs[ch];\n // @ts-ignore – we are accessing private property for internal use\n if (sub._id === id) {\n return sub;\n }\n }\n }\n return null;\n }\n const sub = this._subs[channel];\n if (!sub) {\n return null;\n }\n return sub;\n }\n _isServerSub(channel) {\n return this._serverSubs[channel] !== undefined;\n }\n _sendSubscribeCommands() {\n const commands = [];\n for (const channel in this._subs) {\n if (!this._subs.hasOwnProperty(channel)) {\n continue;\n }\n const sub = this._subs[channel];\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n if (sub._inflight === true) {\n continue;\n }\n if (sub.state === SubscriptionState.Subscribing) {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n const cmd = sub._subscribe();\n if (cmd) {\n commands.push(cmd);\n }\n }\n }\n return commands;\n }\n _connectResponse(result) {\n this._transportIsOpen = true;\n this._transportWasOpen = true;\n this._reconnectAttempts = 0;\n this._refreshRequired = false;\n if (this._isConnected()) {\n return;\n }\n this._client = result.client;\n this._setState(State.Connected);\n if (this._refreshTimeout) {\n clearTimeout(this._refreshTimeout);\n }\n if (result.expires) {\n this._refreshTimeout = setTimeout(() => this._refresh(), ttlMilliseconds(result.ttl));\n }\n this._session = result.session;\n this._node = result.node;\n this.startBatching();\n this._sendSubscribeCommands();\n this.stopBatching();\n const ctx = {\n client: result.client,\n transport: this._transport.subName()\n };\n if (result.data) {\n ctx.data = result.data;\n }\n this.emit('connected', ctx);\n this._resolvePromises();\n this._processServerSubs(result.subs || {});\n if (result.ping && result.ping > 0) {\n this._serverPing = result.ping * 1000;\n this._sendPong = result.pong === true;\n this._waitServerPing();\n }\n else {\n this._serverPing = 0;\n }\n }\n _processServerSubs(subs) {\n for (const channel in subs) {\n if (!subs.hasOwnProperty(channel)) {\n continue;\n }\n const sub = subs[channel];\n this._serverSubs[channel] = {\n 'offset': sub.offset,\n 'epoch': sub.epoch,\n 'recoverable': sub.recoverable || false\n };\n const subCtx = this._getSubscribeContext(channel, sub);\n this.emit('subscribed', subCtx);\n }\n for (const channel in subs) {\n if (!subs.hasOwnProperty(channel)) {\n continue;\n }\n const sub = subs[channel];\n if (sub.recovered) {\n const pubs = sub.publications;\n if (pubs && pubs.length > 0) {\n for (const i in pubs) {\n if (pubs.hasOwnProperty(i)) {\n this._handlePublication(channel, pubs[i]);\n }\n }\n }\n }\n }\n for (const channel in this._serverSubs) {\n if (!this._serverSubs.hasOwnProperty(channel)) {\n continue;\n }\n if (!subs[channel]) {\n this.emit('unsubscribed', { channel: channel });\n delete this._serverSubs[channel];\n }\n }\n }\n _clearRefreshTimeout() {\n if (this._refreshTimeout !== null) {\n clearTimeout(this._refreshTimeout);\n this._refreshTimeout = null;\n }\n }\n _clearReconnectTimeout() {\n if (this._reconnectTimeout !== null) {\n clearTimeout(this._reconnectTimeout);\n this._reconnectTimeout = null;\n }\n }\n _clearServerPingTimeout() {\n if (this._serverPingTimeout !== null) {\n clearTimeout(this._serverPingTimeout);\n this._serverPingTimeout = null;\n }\n }\n _waitServerPing() {\n if (this._config.maxServerPingDelay === 0) {\n return;\n }\n if (!this._isConnected()) {\n return;\n }\n this._clearServerPingTimeout();\n this._serverPingTimeout = setTimeout(() => {\n if (!this._isConnected()) {\n return;\n }\n this._disconnect(connectingCodes.noPing, 'no ping', true);\n }, this._serverPing + this._config.maxServerPingDelay);\n }\n _getSubscribeContext(channel, result) {\n const ctx = {\n channel: channel,\n positioned: false,\n recoverable: false,\n wasRecovering: false,\n recovered: false,\n hasRecoveredPublications: false,\n };\n if (result.recovered) {\n ctx.recovered = true;\n }\n if (result.positioned) {\n ctx.positioned = true;\n }\n if (result.recoverable) {\n ctx.recoverable = true;\n }\n if (result.was_recovering) {\n ctx.wasRecovering = true;\n }\n let epoch = '';\n if ('epoch' in result) {\n epoch = result.epoch;\n }\n let offset = 0;\n if ('offset' in result) {\n offset = result.offset;\n }\n if (ctx.positioned || ctx.recoverable) {\n ctx.streamPosition = {\n 'offset': offset,\n 'epoch': epoch\n };\n }\n if (Array.isArray(result.publications) && result.publications.length > 0) {\n ctx.hasRecoveredPublications = true;\n }\n if (result.data) {\n ctx.data = result.data;\n }\n return ctx;\n }\n _handleReply(reply, next) {\n const id = reply.id;\n if (!(id in this._callbacks)) {\n next();\n return;\n }\n const callbacks = this._callbacks[id];\n clearTimeout(this._callbacks[id].timeout);\n delete this._callbacks[id];\n if (!errorExists(reply)) {\n const callback = callbacks.callback;\n if (!callback) {\n return;\n }\n callback({ reply, next });\n }\n else {\n const errback = callbacks.errback;\n if (!errback) {\n next();\n return;\n }\n const error = { code: reply.error.code, message: reply.error.message || '', temporary: reply.error.temporary || false };\n errback({ error, next });\n }\n }\n _handleJoin(channel, join, id) {\n const sub = this._getSub(channel, id);\n if (!sub && channel) {\n if (this._isServerSub(channel)) {\n const ctx = { channel: channel, info: this._getJoinLeaveContext(join.info) };\n this.emit('join', ctx);\n }\n return;\n }\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._handleJoin(join);\n }\n _handleLeave(channel, leave, id) {\n const sub = this._getSub(channel, id);\n if (!sub && channel) {\n if (this._isServerSub(channel)) {\n const ctx = { channel: channel, info: this._getJoinLeaveContext(leave.info) };\n this.emit('leave', ctx);\n }\n return;\n }\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._handleLeave(leave);\n }\n _handleUnsubscribe(channel, unsubscribe) {\n const sub = this._getSub(channel, 0);\n if (!sub && channel) {\n if (this._isServerSub(channel)) {\n delete this._serverSubs[channel];\n this.emit('unsubscribed', { channel: channel });\n }\n return;\n }\n if (unsubscribe.code < 2500) {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._setUnsubscribed(unsubscribe.code, unsubscribe.reason, false);\n }\n else {\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._setSubscribing(unsubscribe.code, unsubscribe.reason);\n }\n }\n _handleSubscribe(channel, sub) {\n this._serverSubs[channel] = {\n 'offset': sub.offset,\n 'epoch': sub.epoch,\n 'recoverable': sub.recoverable || false\n };\n this.emit('subscribed', this._getSubscribeContext(channel, sub));\n }\n _handleDisconnect(disconnect) {\n const code = disconnect.code;\n let reconnect = true;\n if ((code >= 3500 && code < 4000) || (code >= 4500 && code < 5000)) {\n reconnect = false;\n }\n this._disconnect(code, disconnect.reason, reconnect);\n }\n _getPublicationContext(channel, pub) {\n const ctx = {\n channel: channel,\n data: pub.data\n };\n if (pub.offset) {\n ctx.offset = pub.offset;\n }\n if (pub.info) {\n ctx.info = this._getJoinLeaveContext(pub.info);\n }\n if (pub.tags) {\n ctx.tags = pub.tags;\n }\n return ctx;\n }\n _getJoinLeaveContext(clientInfo) {\n const info = {\n client: clientInfo.client,\n user: clientInfo.user\n };\n const connInfo = clientInfo['conn_info'];\n if (connInfo) {\n info.connInfo = connInfo;\n }\n const chanInfo = clientInfo['chan_info'];\n if (chanInfo) {\n info.chanInfo = chanInfo;\n }\n return info;\n }\n _handlePublication(channel, pub, id) {\n const sub = this._getSub(channel, id);\n if (!sub && channel) {\n if (this._isServerSub(channel)) {\n const ctx = this._getPublicationContext(channel, pub);\n this.emit('publication', ctx);\n if (pub.offset !== undefined) {\n this._serverSubs[channel].offset = pub.offset;\n }\n }\n return;\n }\n // @ts-ignore – we are hiding some symbols from public API autocompletion.\n sub._handlePublication(pub);\n }\n _handleMessage(message) {\n this.emit('message', { data: message.data });\n }\n _handleServerPing(next) {\n if (this._sendPong) {\n const cmd = {};\n this._transportSendCommands([cmd]);\n }\n next();\n }\n _handlePush(data, next) {\n const channel = data.channel;\n const id = data.id;\n if (data.pub) {\n this._handlePublication(channel, data.pub, id);\n }\n else if (data.message) {\n this._handleMessage(data.message);\n }\n else if (data.join) {\n this._handleJoin(channel, data.join, id);\n }\n else if (data.leave) {\n this._handleLeave(channel, data.leave, id);\n }\n else if (data.unsubscribe) {\n this._handleUnsubscribe(channel, data.unsubscribe);\n }\n else if (data.subscribe) {\n this._handleSubscribe(channel, data.subscribe);\n }\n else if (data.disconnect) {\n this._handleDisconnect(data.disconnect);\n }\n next();\n }\n _flush() {\n const commands = this._commands.slice(0);\n this._commands = [];\n this._transportSendCommands(commands);\n }\n _createErrorObject(code, message, temporary) {\n const errObject = {\n code: code,\n message: message\n };\n if (temporary) {\n errObject.temporary = true;\n }\n return errObject;\n }\n _registerCall(id, callback, errback) {\n this._callbacks[id] = {\n callback: callback,\n errback: errback,\n timeout: null\n };\n this._callbacks[id].timeout = setTimeout(() => {\n delete this._callbacks[id];\n if (isFunction(errback)) {\n errback({ error: this._createErrorObject(errorCodes.timeout, 'timeout') });\n }\n }, this._config.timeout);\n }\n _addCommand(command) {\n if (this._batching) {\n this._commands.push(command);\n }\n else {\n this._transportSendCommands([command]);\n }\n }\n _nextPromiseId() {\n return ++this._promiseId;\n }\n _nextTransportId() {\n return ++this._transportId;\n }\n _resolvePromises() {\n for (const id in this._promises) {\n if (!this._promises.hasOwnProperty(id)) {\n continue;\n }\n if (this._promises[id].timeout) {\n clearTimeout(this._promises[id].timeout);\n }\n this._promises[id].resolve();\n delete this._promises[id];\n }\n }\n _rejectPromises(err) {\n for (const id in this._promises) {\n if (!this._promises.hasOwnProperty(id)) {\n continue;\n }\n if (this._promises[id].timeout) {\n clearTimeout(this._promises[id].timeout);\n }\n this._promises[id].reject(err);\n delete this._promises[id];\n }\n }\n}\nCentrifuge.SubscriptionState = SubscriptionState;\nCentrifuge.State = State;\nCentrifuge.UnauthorizedError = UnauthorizedError;\n\nexport { Centrifuge, State, Subscription, SubscriptionState, UnauthorizedError, connectingCodes, disconnectedCodes, errorCodes, subscribingCodes, subscriptionFlags, unsubscribedCodes };\n","import { Centrifuge, Subscription, PublicationContext } from 'centrifuge';\nimport type { CevroMessengerConfig, WSEventPayload } from '../types';\nimport { EventEmitter } from './EventEmitter';\n\n/**\n * Token refresh callback type\n */\nexport type TokenRefreshCallback = () => Promise<string>;\n\n/**\n * WebSocket client for real-time messaging via Centrifugo\n */\nexport class WebSocketClient {\n private config: CevroMessengerConfig;\n private events: EventEmitter;\n private client: Centrifuge | null = null;\n private personalSub: Subscription | null = null;\n private userId: string | null = null;\n private getTokenCallback: TokenRefreshCallback | null = null;\n\n constructor(config: CevroMessengerConfig, events: EventEmitter) {\n this.config = config;\n this.events = events;\n }\n\n /**\n * Set token refresh callback\n * Called when Centrifugo needs a new token (expiration, reconnect)\n */\n setTokenRefreshCallback(callback: TokenRefreshCallback): void {\n this.getTokenCallback = callback;\n }\n\n /**\n * Connect to Centrifugo server\n */\n connect(userId: string, connectionToken: string): void {\n if (this.client?.state === 'connected') {\n this.log('Already connected');\n return;\n }\n\n this.userId = userId;\n\n // Determine WebSocket URL from API base\n const wsUrl = this.getWebSocketUrl();\n\n // Build Centrifuge options\n const options: any = {\n token: connectionToken,\n debug: this.config.debug,\n };\n\n // Add token refresh callback if available\n // This is called when token expires or on reconnect\n if (this.getTokenCallback) {\n options.getToken = async () => {\n this.log('Token refresh requested by Centrifugo');\n try {\n const newToken = await this.getTokenCallback!();\n this.log('Token refreshed successfully');\n return newToken;\n } catch (error) {\n this.log('Token refresh failed:', error);\n throw error;\n }\n };\n }\n\n this.client = new Centrifuge(wsUrl, options);\n\n this.setupClientEventListeners();\n\n // Connect\n this.client.connect();\n }\n\n /**\n * Get WebSocket URL from config\n */\n private getWebSocketUrl(): string {\n // If centrifugoUrl is explicitly set, use it\n if (this.config.centrifugoUrl) {\n return this.config.centrifugoUrl;\n }\n\n // Otherwise derive from apiBase\n // e.g., https://api.example.com -> wss://ws.example.com/connection/websocket\n const apiUrl = new URL(this.config.apiBase);\n const wsProtocol = apiUrl.protocol === 'https:' ? 'wss:' : 'ws:';\n\n // Default to same host with /connection/websocket path\n return `${wsProtocol}//${apiUrl.host}/connection/websocket`;\n }\n\n /**\n * Setup Centrifuge client event listeners\n */\n private setupClientEventListeners(): void {\n if (!this.client) return;\n\n this.client.on('connected', (ctx) => {\n this.log('Connected to Centrifugo:', ctx);\n this.events.emit('connection:open', { clientId: ctx.client });\n\n // Subscribe to personal channel after connection\n this.subscribeToPersonalChannel();\n });\n\n this.client.on('disconnected', (ctx) => {\n this.log('Disconnected from Centrifugo:', ctx);\n this.events.emit('connection:close', { reason: ctx.reason, code: ctx.code });\n });\n\n this.client.on('error', (ctx) => {\n this.log('Connection error:', ctx);\n this.events.emit('connection:error', { error: ctx.error?.message || 'Unknown error' });\n });\n\n // Handle token refresh (for long-running connections)\n this.client.on('connecting', (ctx) => {\n this.log('Connecting...', ctx);\n });\n }\n\n /**\n * Subscribe to visitor channel for receiving messages\n * Uses visitorId which is always present (even for authenticated players)\n */\n private subscribeToPersonalChannel(): void {\n if (!this.client || !this.userId) return;\n\n // Always use visitor channel - visitorId is always present\n const channelName = `visitor:${this.userId}`;\n\n // Check if already subscribed (handles reconnection case)\n const existingSub = this.client.getSubscription(channelName);\n if (existingSub) {\n this.log('Already have subscription for channel:', channelName);\n // Reuse existing subscription, just make sure it's subscribed\n this.personalSub = existingSub;\n if (existingSub.state !== 'subscribed') {\n existingSub.subscribe();\n }\n return;\n }\n\n this.log('Subscribing to channel:', channelName);\n\n this.personalSub = this.client.newSubscription(channelName);\n\n this.personalSub.on('publication', (ctx: PublicationContext) => {\n this.handleMessage(ctx.data as WSEventPayload);\n });\n\n this.personalSub.on('subscribed', (ctx) => {\n this.log('Subscribed to channel:', channelName, ctx);\n });\n\n this.personalSub.on('error', (ctx) => {\n this.log('Subscription error:', ctx);\n this.events.emit('error', { type: 'subscription', error: ctx.error?.message });\n });\n\n this.personalSub.subscribe();\n }\n\n /**\n * Handle incoming message from Centrifugo\n * Payload structure: { type, data: {...}, timestamp }\n */\n private handleMessage(payload: any): void {\n this.log('Received message:', payload);\n\n const data = payload.data || payload;\n\n switch (payload.type) {\n case 'new_message':\n // Convert backend format to Message format\n const message = {\n id: data.id,\n body: data.body,\n inbound: data.inbound || false,\n outbound: data.outbound || false,\n createdAt: data.createdAt,\n type: data.type || 'text',\n mediaUrl: data.mediaUrl,\n };\n this.events.emit('message:received', {\n ticketId: data.ticketId,\n message,\n });\n break;\n\n case 'typing':\n if (data.isTyping) {\n this.events.emit('typing:start', {\n ticketId: data.ticketId,\n actor: data.senderType || 'agent',\n });\n } else {\n this.events.emit('typing:stop', {\n ticketId: data.ticketId,\n actor: data.senderType || 'agent',\n });\n }\n break;\n\n case 'ticket_created':\n this.events.emit('conversation:started', {\n ticketId: data.ticketId,\n contactId: data.contactId,\n createdAt: data.createdAt,\n });\n break;\n\n case 'ticket_status':\n this.events.emit('conversation:updated', {\n ticketId: data.ticketId,\n status: data.status,\n message: data.message,\n closedAt: data.closedAt,\n });\n break;\n\n default:\n this.log('Unknown message type:', payload.type);\n }\n }\n\n /**\n * Update connection token (for token refresh)\n */\n updateToken(newToken: string): void {\n if (this.client) {\n this.client.setToken(newToken);\n }\n }\n\n /**\n * Disconnect from Centrifugo\n */\n disconnect(): void {\n if (this.personalSub) {\n this.personalSub.unsubscribe();\n this.personalSub = null;\n }\n\n if (this.client) {\n this.client.disconnect();\n this.client = null;\n }\n\n this.userId = null;\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.client?.state === 'connected';\n }\n\n /**\n * Get current user ID\n */\n getUserId(): string | null {\n return this.userId;\n }\n\n /**\n * Log helper\n */\n private log(...args: any[]): void {\n if (this.config.debug) {\n console.log('[CevroMessenger WS]', ...args);\n }\n }\n}\n","/**\n * Create DOM element with attributes\n */\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attributes?: Record<string, string>,\n children?: (Node | string)[]\n): HTMLElementTagNameMap[K] {\n const element = document.createElement(tag);\n\n if (attributes) {\n Object.entries(attributes).forEach(([key, value]) => {\n if (key === 'className') {\n element.className = value;\n } else if (key.startsWith('data-') || key.startsWith('aria-')) {\n element.setAttribute(key, value);\n } else {\n (element as any)[key] = value;\n }\n });\n }\n\n if (children) {\n children.forEach((child) => {\n if (typeof child === 'string') {\n element.appendChild(document.createTextNode(child));\n } else {\n element.appendChild(child);\n }\n });\n }\n\n return element;\n}\n\n/**\n * Escape HTML to prevent XSS\n */\nexport function escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n}\n\n/**\n * Validate URL to prevent XSS via javascript: or data: protocols\n * Only allows http:, https:, and blob: protocols\n * blob: URLs are safe - they're generated by the browser for local files\n */\nexport function isValidUrl(url: string): boolean {\n if (!url || typeof url !== 'string') {\n return false;\n }\n\n try {\n const parsed = new URL(url, window.location.origin);\n return ['http:', 'https:', 'blob:'].includes(parsed.protocol);\n } catch {\n return false;\n }\n}\n\n/**\n * Sanitize URL - returns safe URL or empty string\n */\nexport function sanitizeUrl(url: string): string {\n return isValidUrl(url) ? url : '';\n}\n\n/**\n * Parse simple markdown (bold, italic, links, code)\n * URLs are validated to prevent XSS via javascript: protocol\n */\nexport function parseMarkdown(text: string): string {\n return escapeHtml(text)\n // Bold\n .replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>')\n // Italic\n .replace(/\\*(.+?)\\*/g, '<em>$1</em>')\n // Code\n .replace(/`(.+?)`/g, '<code>$1</code>')\n // Links - validate URL to prevent XSS\n .replace(/\\[(.+?)\\]\\((.+?)\\)/g, (_match, linkText, url) => {\n const safeUrl = sanitizeUrl(url);\n if (safeUrl) {\n return `<a href=\"${safeUrl}\" target=\"_blank\" rel=\"noopener\">${linkText}</a>`;\n }\n // If URL is invalid, just show the text without link\n return linkText;\n })\n // Line breaks\n .replace(/\\n/g, '<br>');\n}\n\n/**\n * Format timestamp\n */\nexport function formatTime(date: string | Date): string {\n const d = typeof date === 'string' ? new Date(date) : date;\n return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n}\n\n/**\n * Scroll element to bottom\n */\nexport function scrollToBottom(element: HTMLElement, smooth = true): void {\n element.scrollTo({\n top: element.scrollHeight,\n behavior: smooth ? 'smooth' : 'auto',\n });\n}\n\n/**\n * Check if element is scrolled to bottom\n */\nexport function isScrolledToBottom(element: HTMLElement, threshold = 50): boolean {\n return element.scrollHeight - element.scrollTop - element.clientHeight < threshold;\n}\n\n/**\n * Generate unique ID\n */\nexport function generateId(): string {\n return 'cevro_' + Math.random().toString(36).substring(2, 9);\n}\n","import type { CevroMessengerConfig } from '../types';\nimport { createElement, generateId } from '../utils/dom';\n\n/**\n * Launcher button component\n */\nexport class Launcher {\n private config: CevroMessengerConfig;\n private element: HTMLElement | null = null;\n private unreadBadge: HTMLElement | null = null;\n private onClick: () => void;\n\n constructor(config: CevroMessengerConfig, onClick: () => void) {\n this.config = config;\n this.onClick = onClick;\n }\n\n /**\n * Render the launcher button\n */\n render(): HTMLElement {\n if (this.element) {\n return this.element;\n }\n\n // Main container\n this.element = createElement('div', {\n className: 'cevro-launcher',\n id: generateId(),\n });\n\n // Apply positioning\n this.applyPositioning();\n\n // Create button\n const button = createElement('button', {\n className: 'cevro-launcher__button',\n 'aria-label': 'Open chat',\n 'data-testid': 'launcher-button',\n });\n\n // Chat icon (open state)\n const chatIcon = this.createChatIcon();\n chatIcon.classList.add('cevro-launcher__icon', 'cevro-launcher__icon--chat');\n button.appendChild(chatIcon);\n\n // Close icon (closed state)\n const closeIcon = this.createCloseIcon();\n closeIcon.classList.add('cevro-launcher__icon', 'cevro-launcher__icon--close');\n button.appendChild(closeIcon);\n\n // Unread badge\n this.unreadBadge = createElement('span', {\n className: 'cevro-launcher__badge',\n 'data-testid': 'unread-badge',\n });\n this.unreadBadge.style.display = 'none';\n button.appendChild(this.unreadBadge);\n\n // Click handler\n button.addEventListener('click', () => {\n this.onClick();\n });\n\n this.element.appendChild(button);\n\n return this.element;\n }\n\n /**\n * Apply positioning styles\n */\n private applyPositioning(): void {\n if (!this.element) return;\n\n const alignment = this.config.alignment || 'right';\n const vPadding = this.config.verticalPadding ?? 20;\n const hPadding = this.config.horizontalPadding ?? 20;\n\n this.element.style.bottom = `${vPadding}px`;\n\n if (alignment === 'left') {\n this.element.style.left = `${hPadding}px`;\n this.element.style.right = 'auto';\n } else {\n this.element.style.right = `${hPadding}px`;\n this.element.style.left = 'auto';\n }\n\n if (this.config.zIndex) {\n this.element.style.zIndex = String(this.config.zIndex);\n }\n }\n\n /**\n * Create chat bubble icon\n */\n private createChatIcon(): SVGElement {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('width', '24');\n svg.setAttribute('height', '24');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '2');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute(\n 'd',\n 'M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z'\n );\n svg.appendChild(path);\n\n return svg;\n }\n\n /**\n * Create chevron down icon (when chat is open)\n */\n private createCloseIcon(): SVGElement {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('width', '24');\n svg.setAttribute('height', '24');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '2.5');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n\n const polyline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');\n polyline.setAttribute('points', '6 9 12 15 18 9');\n svg.appendChild(polyline);\n\n return svg;\n }\n\n /**\n * Set open state\n */\n setOpen(isOpen: boolean): void {\n if (this.element) {\n this.element.classList.toggle('cevro-launcher--open', isOpen);\n }\n }\n\n /**\n * Update unread count\n */\n setUnreadCount(count: number): void {\n if (this.unreadBadge) {\n if (count > 0) {\n this.unreadBadge.textContent = count > 99 ? '99+' : String(count);\n this.unreadBadge.style.display = 'flex';\n } else {\n this.unreadBadge.style.display = 'none';\n }\n }\n }\n\n /**\n * Show the launcher\n */\n show(): void {\n if (this.element) {\n this.element.style.display = 'block';\n }\n }\n\n /**\n * Hide the launcher\n */\n hide(): void {\n if (this.element) {\n this.element.style.display = 'none';\n }\n }\n\n /**\n * Destroy the launcher\n */\n destroy(): void {\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n this.element = null;\n this.unreadBadge = null;\n }\n}\n","/**\n * Localization strings for the Cevro Messenger widget\n */\n\nexport interface LocaleStrings {\n // Header\n headerTitle: string;\n headerSubtitle: string;\n\n // Input\n inputPlaceholder: string;\n\n // Closed chat\n closedMessage: string;\n newConversation: string;\n\n // CSAT\n csatTitle: string;\n csatSubtitle: string;\n csatPlaceholder: string;\n csatSubmit: string;\n csatThankYou: string;\n\n // Footer\n poweredBy: string;\n}\n\n/**\n * Default English strings\n */\nexport const defaultStrings: LocaleStrings = {\n // Header\n headerTitle: 'Cevro',\n headerSubtitle: 'We typically reply within a few minutes',\n\n // Input\n inputPlaceholder: 'How can we help?',\n\n // Closed chat\n closedMessage: 'The agent closed the chat.',\n newConversation: 'Start New Conversation',\n\n // CSAT\n csatTitle: 'How was your conversation?',\n csatSubtitle: 'Your feedback helps us get better.',\n csatPlaceholder: 'Thank you! What stood out?',\n csatSubmit: 'Submit Feedback',\n csatThankYou: 'Thank you for your feedback!',\n\n // Footer\n poweredBy: 'Powered by Cevro AI',\n};\n\n/**\n * Merge strings with priority: defaults < client config < backend (DB)\n */\nexport function getStrings(\n clientOverrides?: Partial<LocaleStrings>,\n backendOverrides?: Partial<LocaleStrings>\n): LocaleStrings {\n return {\n ...defaultStrings,\n ...clientOverrides,\n ...backendOverrides,\n };\n}\n","import type { Message, QuickAction, Agent } from '../types';\nimport { createElement, parseMarkdown, formatTime, scrollToBottom, isScrolledToBottom, generateId, isValidUrl } from '../utils/dom';\n\n/**\n * Message list component\n */\nexport class MessageList {\n private element: HTMLElement | null = null;\n private messagesContainer: HTMLElement | null = null;\n private messages: Map<string, HTMLElement> = new Map();\n private onQuickAction: ((action: QuickAction) => void) | null = null;\n private autoScroll = true;\n private closedMessageElement: HTMLElement | null = null;\n private currentAgent: Agent | null = null;\n\n /**\n * Set quick action handler\n */\n setQuickActionHandler(handler: (action: QuickAction) => void): void {\n this.onQuickAction = handler;\n }\n\n /**\n * Set agent info for message avatars\n */\n setAgent(agent: Agent): void {\n this.currentAgent = agent;\n }\n\n /**\n * Render the message list\n */\n render(): HTMLElement {\n if (this.element) {\n return this.element;\n }\n\n this.element = createElement('div', {\n className: 'cevro-messages',\n id: generateId(),\n });\n\n this.messagesContainer = createElement('div', {\n className: 'cevro-messages__container',\n 'data-testid': 'messages-container',\n });\n\n // Track scroll position for auto-scroll\n this.messagesContainer.addEventListener('scroll', () => {\n this.autoScroll = isScrolledToBottom(this.messagesContainer!);\n });\n\n this.element.appendChild(this.messagesContainer);\n\n return this.element;\n }\n\n /**\n * Add a message to the list\n */\n addMessage(message: Message, animate = true): void {\n if (!this.messagesContainer) return;\n\n // Check if message already exists\n if (this.messages.has(message.id)) {\n this.updateMessage(message);\n return;\n }\n\n const messageEl = this.createMessageElement(message);\n if (animate) {\n messageEl.classList.add('cevro-message--animate');\n }\n\n this.messagesContainer.appendChild(messageEl);\n this.messages.set(message.id, messageEl);\n\n // Auto-scroll if at bottom\n if (this.autoScroll) {\n scrollToBottom(this.messagesContainer);\n }\n }\n\n /**\n * Update an existing message\n * @param message - Updated message data\n * @param oldId - Original message id (for optimistic updates where id changes)\n */\n updateMessage(message: Message, oldId?: string): void {\n const lookupId = oldId || message.id;\n const existingEl = this.messages.get(lookupId);\n if (!existingEl || !this.messagesContainer) return;\n\n const newEl = this.createMessageElement(message);\n this.messagesContainer.replaceChild(newEl, existingEl);\n\n // Remove old id entry and add new one\n if (oldId && oldId !== message.id) {\n this.messages.delete(oldId);\n }\n this.messages.set(message.id, newEl);\n }\n\n /**\n * Update upload progress for a message\n */\n updateMessageProgress(messageId: string, progress: number): void {\n const messageEl = this.messages.get(messageId);\n if (!messageEl) return;\n\n const progressFill = messageEl.querySelector('.cevro-file-progress__fill') as HTMLElement;\n const progressText = messageEl.querySelector('.cevro-file-progress__text');\n\n if (progressFill) {\n progressFill.style.width = `${progress}%`;\n }\n if (progressText) {\n progressText.textContent = `${progress}%`;\n }\n }\n\n /**\n * Remove a message from the list\n */\n removeMessage(messageId: string): void {\n const messageEl = this.messages.get(messageId);\n if (!messageEl) return;\n\n messageEl.remove();\n this.messages.delete(messageId);\n }\n\n /**\n * Create message element\n */\n private createMessageElement(message: Message): HTMLElement {\n // From SDK perspective:\n // - inbound: true = user's message (to backend) = show on RIGHT\n // - outbound: true = admin's message (from backend) = show on LEFT\n const isMyMessage = message.inbound === true;\n const wrapper = createElement('div', {\n className: `cevro-message ${isMyMessage ? 'cevro-message--outbound' : 'cevro-message--inbound'}`,\n 'data-message-id': message.id,\n 'data-testid': `message-${message.id}`,\n });\n\n // Avatar for admin messages\n if (!isMyMessage) {\n const avatar = createElement('div', {\n className: 'cevro-message__avatar',\n });\n\n // Use agent avatar URL if available, otherwise use default bot SVG\n if (this.currentAgent?.avatarUrl && isValidUrl(this.currentAgent.avatarUrl)) {\n const img = createElement('img', {\n className: 'cevro-message__avatar-img',\n }) as HTMLImageElement;\n img.src = this.currentAgent.avatarUrl;\n img.alt = this.currentAgent.name || 'Agent';\n avatar.appendChild(img);\n } else {\n avatar.innerHTML = this.createBotAvatarSvg();\n }\n\n wrapper.appendChild(avatar);\n }\n\n // Message content wrapper\n const contentWrapper = createElement('div', {\n className: 'cevro-message__content-wrapper',\n });\n\n // Message bubble\n const bubble = createElement('div', {\n className: 'cevro-message__bubble',\n });\n\n // Handle different message types\n const isImage = message.type === 'image' || message.attachment?.category === 'image';\n\n if (isImage && message.mediaUrl && isValidUrl(message.mediaUrl)) {\n // Image message - show actual image\n const imageContainer = createElement('div', {\n className: 'cevro-message__image-container',\n });\n\n const img = createElement('img', {\n className: 'cevro-message__image',\n }) as HTMLImageElement;\n img.src = message.mediaUrl;\n img.alt = message.attachment?.filename || 'Image';\n img.loading = 'lazy';\n imageContainer.appendChild(img);\n\n // Show progress overlay if uploading\n if (message.status === 'sending') {\n const progressOverlay = this.createProgressOverlay();\n imageContainer.appendChild(progressOverlay);\n }\n\n bubble.appendChild(imageContainer);\n } else if (message.type === 'file' || (message.attachment && !isImage)) {\n // File attachment (non-image) - show file card\n const fileCard = this.createFileCard(message);\n bubble.appendChild(fileCard);\n } else if (message.type === 'media' && message.mediaUrl && isValidUrl(message.mediaUrl)) {\n // Legacy media type\n const link = createElement('a', {\n className: 'cevro-message__attachment',\n }) as HTMLAnchorElement;\n link.href = message.mediaUrl;\n link.target = '_blank';\n link.rel = 'noopener';\n link.innerHTML = `\n ${this.getFileIcon('file')}\n <span>Attachment</span>\n `;\n bubble.appendChild(link);\n }\n\n // Text content\n if (message.body) {\n const textContent = createElement('div', {\n className: 'cevro-message__text',\n });\n textContent.innerHTML = parseMarkdown(message.body);\n bubble.appendChild(textContent);\n }\n\n contentWrapper.appendChild(bubble);\n\n // Quick actions\n if (message.richContent?.quickActions?.length) {\n const actionsContainer = createElement('div', {\n className: 'cevro-message__quick-actions',\n });\n\n message.richContent.quickActions.forEach((action) => {\n const button = createElement('button', {\n className: 'cevro-message__quick-action',\n });\n button.textContent = action.label;\n button.addEventListener('click', () => {\n if (this.onQuickAction) {\n this.onQuickAction(action);\n }\n });\n actionsContainer.appendChild(button);\n });\n\n contentWrapper.appendChild(actionsContainer);\n }\n\n // Timestamp and status\n const meta = createElement('div', {\n className: 'cevro-message__meta',\n });\n meta.textContent = formatTime(message.createdAt);\n\n // Status indicator for user's own messages\n if (isMyMessage && message.status) {\n const status = createElement('span', {\n className: `cevro-message__status cevro-message__status--${message.status}`,\n });\n status.innerHTML = this.getStatusIcon(message.status);\n meta.appendChild(status);\n }\n\n contentWrapper.appendChild(meta);\n wrapper.appendChild(contentWrapper);\n\n return wrapper;\n }\n\n /**\n * Create progress overlay for images\n */\n private createProgressOverlay(): HTMLElement {\n const overlay = createElement('div', {\n className: 'cevro-file-progress-overlay',\n });\n overlay.innerHTML = `\n <div class=\"cevro-file-progress\">\n <div class=\"cevro-file-progress__bar\">\n <div class=\"cevro-file-progress__fill\" style=\"width: 0%\"></div>\n </div>\n <span class=\"cevro-file-progress__text\">0%</span>\n </div>\n `;\n return overlay;\n }\n\n /**\n * Create file card for non-image attachments\n */\n private createFileCard(message: Message): HTMLElement {\n const attachment = message.attachment;\n const category = attachment?.category || 'file';\n const filename = attachment?.filename || 'File';\n const size = attachment?.size || 0;\n const isUploading = message.status === 'sending';\n\n const card = createElement('div', {\n className: `cevro-file-card cevro-file-card--${category}`,\n });\n\n // File icon\n const iconWrapper = createElement('div', {\n className: 'cevro-file-card__icon',\n });\n iconWrapper.innerHTML = this.getFileIcon(category);\n card.appendChild(iconWrapper);\n\n // File info\n const info = createElement('div', {\n className: 'cevro-file-card__info',\n });\n\n const name = createElement('div', {\n className: 'cevro-file-card__name',\n });\n name.textContent = this.truncateFilename(filename, 25);\n name.title = filename;\n info.appendChild(name);\n\n const details = createElement('div', {\n className: 'cevro-file-card__details',\n });\n details.textContent = this.formatFileSize(size);\n info.appendChild(details);\n\n card.appendChild(info);\n\n // Progress or download\n if (isUploading) {\n const progress = createElement('div', {\n className: 'cevro-file-card__progress',\n });\n progress.innerHTML = `\n <div class=\"cevro-file-progress\">\n <div class=\"cevro-file-progress__bar\">\n <div class=\"cevro-file-progress__fill\" style=\"width: 0%\"></div>\n </div>\n <span class=\"cevro-file-progress__text\">0%</span>\n </div>\n `;\n card.appendChild(progress);\n } else if (message.mediaUrl && isValidUrl(message.mediaUrl)) {\n // Make card clickable to download\n card.style.cursor = 'pointer';\n card.addEventListener('click', () => {\n window.open(message.mediaUrl, '_blank');\n });\n }\n\n return card;\n }\n\n /**\n * Get file icon SVG based on category\n */\n private getFileIcon(category: string): string {\n const icons: Record<string, string> = {\n pdf: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#E53935\"/>\n <path d=\"M14 2V8H20\" fill=\"#FFCDD2\"/>\n <path d=\"M9 13H10.5V14.5H9V16H7.5V11H10.5V12.5H9V13Z\" fill=\"white\"/>\n <path d=\"M11.5 11H13.5C14.05 11 14.5 11.45 14.5 12V14C14.5 14.55 14.05 15 13.5 15H12.5V16H11.5V11ZM13 14V12H12.5V14H13Z\" fill=\"white\"/>\n <path d=\"M15.5 11H17V12H16V13H17V14H16V16H15.5V11Z\" fill=\"white\"/>\n </svg>`,\n document: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#1976D2\"/>\n <path d=\"M14 2V8H20\" fill=\"#BBDEFB\"/>\n <path d=\"M8 12H16V13H8V12ZM8 15H14V16H8V15Z\" fill=\"white\"/>\n </svg>`,\n spreadsheet: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#388E3C\"/>\n <path d=\"M14 2V8H20\" fill=\"#C8E6C9\"/>\n <path d=\"M8 12H10V14H8V12ZM11 12H13V14H11V12ZM14 12H16V14H14V12ZM8 15H10V17H8V15ZM11 15H13V17H11V15Z\" fill=\"white\"/>\n </svg>`,\n presentation: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#F57C00\"/>\n <path d=\"M14 2V8H20\" fill=\"#FFE0B2\"/>\n <rect x=\"8\" y=\"12\" width=\"8\" height=\"5\" rx=\"1\" fill=\"white\"/>\n </svg>`,\n video: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#7B1FA2\"/>\n <path d=\"M14 2V8H20\" fill=\"#E1BEE7\"/>\n <path d=\"M10 11V17L15 14L10 11Z\" fill=\"white\"/>\n </svg>`,\n audio: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#00897B\"/>\n <path d=\"M14 2V8H20\" fill=\"#B2DFDB\"/>\n <path d=\"M12 11C10.9 11 10 11.9 10 13V15C10 16.1 10.9 17 12 17C13.1 17 14 16.1 14 15V13C14 11.9 13.1 11 12 11Z\" fill=\"white\"/>\n <path d=\"M15 14V15C15 16.66 13.66 18 12 18C10.34 18 9 16.66 9 15V14H8V15C8 17.03 9.53 18.71 11.5 18.96V20H10V21H14V20H12.5V18.96C14.47 18.71 16 17.03 16 15V14H15Z\" fill=\"white\"/>\n </svg>`,\n archive: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#795548\"/>\n <path d=\"M14 2V8H20\" fill=\"#D7CCC8\"/>\n <rect x=\"10\" y=\"11\" width=\"4\" height=\"2\" fill=\"white\"/>\n <rect x=\"10\" y=\"14\" width=\"4\" height=\"2\" fill=\"white\"/>\n <rect x=\"10\" y=\"17\" width=\"4\" height=\"2\" fill=\"white\"/>\n </svg>`,\n text: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#607D8B\"/>\n <path d=\"M14 2V8H20\" fill=\"#CFD8DC\"/>\n <path d=\"M8 12H16V13H8V12ZM8 15H14V16H8V15ZM8 18H16V19H8V18Z\" fill=\"white\"/>\n </svg>`,\n image: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#43A047\"/>\n <path d=\"M14 2V8H20\" fill=\"#C8E6C9\"/>\n <circle cx=\"10\" cy=\"13\" r=\"2\" fill=\"white\"/>\n <path d=\"M8 18L10 15L12 17L15 13L17 18H8Z\" fill=\"white\"/>\n </svg>`,\n file: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z\" fill=\"#90A4AE\"/>\n <path d=\"M14 2V8H20\" fill=\"#CFD8DC\"/>\n </svg>`,\n };\n\n return icons[category] || icons.file;\n }\n\n /**\n * Format file size to human readable\n */\n private formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];\n }\n\n /**\n * Truncate filename if too long\n */\n private truncateFilename(filename: string, maxLength: number): string {\n if (filename.length <= maxLength) return filename;\n\n const ext = filename.split('.').pop() || '';\n const name = filename.slice(0, filename.length - ext.length - 1);\n const truncatedName = name.slice(0, maxLength - ext.length - 4) + '...';\n return truncatedName + '.' + ext;\n }\n\n /**\n * Create bot avatar SVG\n */\n private createBotAvatarSvg(): string {\n return `\n <svg width=\"28\" height=\"28\" viewBox=\"0 0 28 28\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"14\" cy=\"10\" r=\"4\" fill=\"white\"/>\n <path d=\"M7 22c0-3.866 3.134-7 7-7s7 3.134 7 7\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n `;\n }\n\n /**\n * Get status icon\n * - sending: single checkmark (message is being sent)\n * - sent: double checkmark (message delivered to server)\n * - delivered: double checkmark (same as sent)\n * - read: double checkmark filled (message was read)\n * - failed: X icon in red\n */\n private getStatusIcon(status: string): string {\n // Single checkmark\n const singleCheck = '<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>';\n // Double checkmark\n const doubleCheck = '<svg width=\"16\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"18 7 9.5 17 5 12\"/><polyline points=\"23 7 14.5 17 12 14\"/></svg>';\n // Double checkmark filled (for read)\n const doubleCheckRead = '<svg width=\"16\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#8B5CF6\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"18 7 9.5 17 5 12\"/><polyline points=\"23 7 14.5 17 12 14\"/></svg>';\n\n switch (status) {\n case 'sending':\n return singleCheck;\n case 'sent':\n case 'delivered':\n return doubleCheck;\n case 'read':\n return doubleCheckRead;\n case 'failed':\n return '<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#ef4444\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/></svg>';\n default:\n return '';\n }\n }\n\n /**\n * Show typing indicator\n */\n showTypingIndicator(): void {\n if (!this.messagesContainer) return;\n\n // Remove existing typing indicator\n this.hideTypingIndicator();\n\n const indicator = createElement('div', {\n className: 'cevro-typing-indicator',\n id: 'cevro-typing-indicator',\n 'data-testid': 'typing-indicator',\n });\n\n indicator.innerHTML = `\n <div class=\"cevro-typing-indicator__avatar\">\n ${this.createBotAvatarSvg()}\n </div>\n <div class=\"cevro-typing-indicator__dots\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n `;\n\n this.messagesContainer.appendChild(indicator);\n\n if (this.autoScroll) {\n scrollToBottom(this.messagesContainer);\n }\n }\n\n /**\n * Hide typing indicator\n */\n hideTypingIndicator(): void {\n const indicator = document.getElementById('cevro-typing-indicator');\n if (indicator) {\n indicator.remove();\n }\n }\n\n /**\n * Clear all messages\n */\n clear(): void {\n if (this.messagesContainer) {\n this.messagesContainer.innerHTML = '';\n }\n this.messages.clear();\n // Also remove closed message if present\n if (this.closedMessageElement) {\n this.closedMessageElement.remove();\n this.closedMessageElement = null;\n }\n }\n\n /**\n * Show closed chat message at the bottom of messages area\n * This displays when a ticket is closed (e.g., escalated and resolved)\n * @param message - Custom message text (optional)\n */\n showClosedMessage(message?: string): void {\n if (!this.messagesContainer) return;\n\n // Remove existing closed message\n this.hideClosedMessage();\n\n this.closedMessageElement = createElement('div', {\n className: 'cevro-messages__closed-notice',\n 'data-testid': 'closed-chat-message',\n });\n\n const displayMessage = message || 'The agent closed the chat. If you need assistance please start a new chat.';\n this.closedMessageElement.innerHTML = `\n <p class=\"cevro-messages__closed-text\">\n ${displayMessage}\n </p>\n `;\n\n this.messagesContainer.appendChild(this.closedMessageElement);\n\n // Scroll to show the closed message\n if (this.autoScroll) {\n scrollToBottom(this.messagesContainer);\n }\n }\n\n /**\n * Hide closed chat message\n */\n hideClosedMessage(): void {\n if (this.closedMessageElement) {\n this.closedMessageElement.remove();\n this.closedMessageElement = null;\n }\n }\n\n /**\n * Scroll to bottom\n */\n scrollToBottom(): void {\n if (this.messagesContainer) {\n scrollToBottom(this.messagesContainer, false);\n }\n }\n\n /**\n * Destroy the component\n */\n destroy(): void {\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n this.element = null;\n this.messagesContainer = null;\n this.messages.clear();\n }\n}\n","import type { CevroMessengerConfig, Message, QuickAction, Agent, LocaleStrings } from '../types';\nimport { createElement, generateId } from '../utils/dom';\nimport { generateAcceptAttribute } from '../utils/file-validation';\nimport { defaultStrings, getStrings } from '../i18n/strings';\nimport { MessageList } from './MessageList';\n\nexport interface ChatWindowCallbacks {\n onClose: () => void;\n onSendMessage: (message: string) => void;\n onQuickAction: (action: QuickAction) => void;\n onFileUpload?: (file: File) => void;\n onCSATSubmit?: (rating: number, feedback?: string) => Promise<void>;\n onStartNewChat?: () => void;\n}\n\n/**\n * Chat window component\n */\nexport class ChatWindow {\n private config: CevroMessengerConfig;\n private callbacks: ChatWindowCallbacks;\n private element: HTMLElement | null = null;\n private messageList: MessageList;\n private inputElement: HTMLTextAreaElement | null = null;\n private sendButton: HTMLButtonElement | null = null;\n private fileInput: HTMLInputElement | null = null;\n private fileButton: HTMLButtonElement | null = null;\n private isVisible = false;\n private logoElement: HTMLElement | null = null;\n private brandNameElement: HTMLElement | null = null;\n private headerSubtitleElement: HTMLElement | null = null;\n private inputWrapper: HTMLElement | null = null;\n private closedFooter: HTMLElement | null = null;\n private csatContainer: HTMLElement | null = null;\n private themeMediaQuery: MediaQueryList | null = null;\n private themeChangeHandler: ((e: MediaQueryListEvent) => void) | null = null;\n\n // Localization\n private strings: LocaleStrings = defaultStrings;\n\n // CSAT state\n private csatRating: number = 0;\n private csatSubmitting: boolean = false;\n\n constructor(\n config: CevroMessengerConfig,\n callbacks: ChatWindowCallbacks,\n strings?: LocaleStrings\n ) {\n this.config = config;\n this.callbacks = callbacks;\n this.strings = strings || getStrings(config.locale);\n this.messageList = new MessageList();\n this.messageList.setQuickActionHandler((action) => {\n this.callbacks.onQuickAction(action);\n });\n }\n\n /**\n * Update locale strings (e.g., after receiving from backend)\n */\n setStrings(backendStrings?: Partial<LocaleStrings>): void {\n this.strings = getStrings(this.config.locale, backendStrings);\n this.updateUIStrings();\n }\n\n /**\n * Update UI elements with current strings\n */\n private updateUIStrings(): void {\n if (this.headerSubtitleElement) {\n this.headerSubtitleElement.textContent = this.strings.headerSubtitle;\n }\n if (this.inputElement) {\n this.inputElement.placeholder = this.strings.inputPlaceholder;\n }\n }\n\n /**\n * Render the chat window\n */\n render(): HTMLElement {\n if (this.element) {\n return this.element;\n }\n\n // Main container\n this.element = createElement('div', {\n className: 'cevro-chat-window',\n id: generateId(),\n });\n\n // Apply positioning\n this.applyPositioning();\n\n // Header\n const header = this.createHeader();\n this.element.appendChild(header);\n\n // Messages area\n const messagesArea = this.messageList.render();\n this.element.appendChild(messagesArea);\n\n // Input area\n this.inputWrapper = this.createInputArea();\n this.element.appendChild(this.inputWrapper);\n\n // Apply theme\n this.applyTheme();\n\n return this.element;\n }\n\n /**\n * Apply positioning styles\n */\n private applyPositioning(): void {\n if (!this.element) return;\n\n const alignment = this.config.alignment || 'right';\n const vPadding = this.config.verticalPadding ?? 20;\n const hPadding = this.config.horizontalPadding ?? 20;\n\n // Position above launcher\n this.element.style.bottom = `${vPadding + 70}px`;\n\n if (alignment === 'left') {\n this.element.style.left = `${hPadding}px`;\n this.element.style.right = 'auto';\n } else {\n this.element.style.right = `${hPadding}px`;\n this.element.style.left = 'auto';\n }\n\n if (this.config.zIndex) {\n this.element.style.zIndex = String(this.config.zIndex - 1);\n }\n }\n\n /**\n * Create header element\n */\n private createHeader(): HTMLElement {\n const header = createElement('div', {\n className: 'cevro-chat-window__header',\n });\n\n // Company logo\n this.logoElement = createElement('div', {\n className: 'cevro-chat-window__logo',\n 'data-testid': 'company-logo',\n });\n this.logoElement.innerHTML = this.createCompanyLogoSvg();\n header.appendChild(this.logoElement);\n\n // Title section\n const titleSection = createElement('div', {\n className: 'cevro-chat-window__title-section',\n });\n\n this.brandNameElement = createElement('h2', {\n className: 'cevro-chat-window__title',\n 'data-testid': 'brand-name',\n }, [this.strings.headerTitle]);\n\n this.headerSubtitleElement = createElement('p', {\n className: 'cevro-chat-window__subtitle',\n }, [this.strings.headerSubtitle]);\n\n titleSection.appendChild(this.brandNameElement);\n titleSection.appendChild(this.headerSubtitleElement);\n header.appendChild(titleSection);\n\n // Close button\n const closeButton = createElement('button', {\n className: 'cevro-chat-window__close',\n 'aria-label': 'Close chat',\n 'data-testid': 'close-button',\n });\n closeButton.innerHTML = `\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n `;\n closeButton.addEventListener('click', () => {\n this.callbacks.onClose();\n });\n header.appendChild(closeButton);\n\n return header;\n }\n\n /**\n * Create company logo SVG\n */\n private createCompanyLogoSvg(): string {\n return `\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 40 40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"40\" height=\"40\" rx=\"8\" fill=\"url(#cevro-logo-gradient)\"/>\n <svg x=\"6\" y=\"6\" width=\"28\" height=\"28\" viewBox=\"0 0 512 498\">\n <g>\n <path fill=\"#FFFFFF\" d=\"M298.97,91.19l-32.23-32.23c-6.12-6.12-6.12-16.03,0-22.15l32.23-32.23c6.12-6.12,16.03-6.12,22.15,0\n l30.06,30.06c2.94,2.94,6.92,4.59,11.07,4.59h48.31v17.32h-48.31c-4.15,0-8.14,1.65-11.07,4.59l-30.05,30.06\n C315,97.3,305.09,97.31,298.97,91.19z\"/>\n <path fill=\"#FFFFFF\" d=\"M260.84,157h96.5c4.15,0,8.14,1.65,11.07,4.59l30.05,30.05c6.12,6.12,16.03,6.12,22.15,0l30.06-30.06\n c2.94-2.94,6.92-4.59,11.07-4.59h50.21v-17.32h-50.21c-4.15,0-8.14-1.65-11.07-4.59l-30.06-30.06\n c-6.12-6.12-16.03-6.12-22.15,0l-30.06,30.05c-2.94,2.94-6.92,4.59-11.07,4.59h-96.5c-4.15,0-8.14-1.65-11.07-4.59\n l-30.06-30.05c-6.12-6.12-16.03-6.12-22.15,0l-32.23,32.23c-6.12,6.12-6.12,16.03,0,22.15l32.23,32.23\n c6.12,6.12,16.03,6.12,22.15,0l30.06-30.05C252.7,158.65,256.69,157,260.84,157z\"/>\n <path fill=\"#FFFFFF\" d=\"M260.84,340.58h96.5c4.15,0,8.14-1.65,11.07-4.59l30.06-30.06c6.12-6.12,16.03-6.12,22.15,0L450.67,336\n c2.94,2.94,6.92,4.59,11.07,4.59h50.21v17.32h-50.21c-4.15,0-8.14,1.65-11.07,4.59l-30.05,30.06\n c-6.12,6.12-16.03,6.12-22.15,0l-30.06-30.06c-2.94-2.94-6.92-4.59-11.07-4.59h-96.5c-4.15,0-8.14,1.65-11.07,4.59\n l-30.05,30.06c-6.12,6.12-16.03,6.12-22.15,0l-32.23-32.23c-6.12-6.12-6.12-16.03,0-22.15l32.23-32.23\n c6.12,6.12,16.03-6.12,22.15,0L249.77,336C252.7,338.93,256.69,340.58,260.84,340.58z\"/>\n <path fill=\"#FFFFFF\" d=\"M343.17,259.89l-1.13,1.13l-31.09,31.09c-1.9,1.9-4.16,3.21-6.6,3.92c-3.92,1.19-8.2,0.83-11.83-1.13\n c-0.89-0.54-1.72-1.07-2.56-1.72c-0.42-0.3-0.83-0.65-1.25-1.07l-30.02-30.08h-0.06c-2.91-2.91-6.9-4.58-11.06-4.58h-86.71\n c-2.62,0-5.11,0.65-7.37,1.84c-0.89,0.53-1.72,1.07-2.5,1.72c-0.06-0.06-0.06-0.06-0.06,0c-0.36,0.36-0.71,0.65-1.07,1.01\n l-30.08,30.08h-0.06c-0.36,0.36-0.77,0.71-1.19,1.07c-0.77,0.71-1.66,1.25-2.56,1.72c-3.63,1.9-7.91,2.32-11.83,1.13\n c-0.95-0.3-1.84-0.71-2.73-1.13c-0.06,0-0.06,0-0.06,0c-1.31-0.77-2.56-1.66-3.69-2.79l-30.08-30.08h-0.06\n c-0.71-0.77-1.49-1.37-2.32-1.96c-0.06,0.06-0.06,0.06-0.06,0c-1.31-0.89-2.68-1.55-4.16-1.96\n c-1.49-0.42-3.03-0.65-4.58-0.65H6.3v-17.3h50.12c1.55,0,3.09-0.24,4.58-0.65c1.49-0.42,2.85-1.07,4.16-1.96\n c0-0.06,0-0.06,0.06,0c0.83-0.59,1.61-1.19,2.32-1.96h0.06l30.08-30.08c1.13-1.13,2.38-2.08,3.69-2.79c0,0,0-0.06,0.06,0\n c0.47-0.24,0.95-0.48,1.43-0.65c0.48-0.18,0.95-0.36,1.43-0.48c3.86-1.19,8.08-0.77,11.71,1.13\n c0.89,0.48,1.79,1.01,2.56,1.72c0.42,0.36,0.83,0.71,1.19,1.07h0.06l30.08,30.08c0.36,0.36,0.71,0.65,1.07,1.01\n c0,0.06,0,0.06,0.06,0c0.77,0.65,1.61,1.19,2.5,1.72c2.26,1.19,4.76,1.84,7.37,1.84h86.71c4.16,0,8.14-1.66,11.06-4.58h0.06\n l30.08-30.08c0.36-0.42,0.77-0.77,1.19-1.07c0.83-0.65,1.66-1.25,2.56-1.72c3.63-1.9,7.85-2.32,11.71-1.13\n c0.48,0.12,0.95,0.3,1.43,0.48c1.96,0.71,3.74,1.84,5.29,3.45l32.22,32.22C349.23,243.83,349.23,253.76,343.17,259.89z\"/>\n <path fill=\"#FFFFFF\" d=\"M298.02,406.39l-32.23,32.23c-6.12,6.12-6.12,16.03,0,22.15L298.02,493c6.12,6.12,16.03,6.12,22.15,0\n l30.06-30.06c2.94-2.94,6.92-4.59,11.07-4.59h50.21v-17.32h-50.21c-4.15,0-8.14-1.65-11.07-4.59l-30.06-30.06\n C314.05,400.28,304.13,400.28,298.02,406.39z\"/>\n </g>\n </svg>\n <defs>\n <linearGradient id=\"cevro-logo-gradient\" x1=\"0\" y1=\"0\" x2=\"40\" y2=\"40\" gradientUnits=\"userSpaceOnUse\">\n <stop offset=\"0%\" stop-color=\"#8B5CF6\"/>\n <stop offset=\"100%\" stop-color=\"#7C3AED\"/>\n </linearGradient>\n </defs>\n </svg>\n `;\n }\n\n /**\n * Set agent info (used for message avatars)\n */\n setAgent(agent: Agent): void {\n // Pass agent info to MessageList for message avatars\n this.messageList.setAgent(agent);\n }\n\n /**\n * Create input area element\n */\n private createInputArea(): HTMLElement {\n const wrapper = createElement('div', {\n className: 'cevro-chat-window__input-wrapper',\n });\n\n const inputArea = createElement('div', {\n className: 'cevro-chat-window__input-area',\n });\n\n // File upload button (paperclip icon)\n this.fileButton = createElement('button', {\n className: 'cevro-chat-window__file-button',\n 'aria-label': 'Attach file',\n 'data-testid': 'file-button',\n }) as HTMLButtonElement;\n this.fileButton.innerHTML = `\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M16.5 6V17.5C16.5 19.71 14.71 21.5 12.5 21.5C10.29 21.5 8.5 19.71 8.5 17.5V5C8.5 3.62 9.62 2.5 11 2.5C12.38 2.5 13.5 3.62 13.5 5V16.5C13.5 17.05 13.05 17.5 12.5 17.5C11.95 17.5 11.5 17.05 11.5 16.5V6H10V16.5C10 17.88 11.12 19 12.5 19C13.88 19 15 17.88 15 16.5V5C15 2.79 13.21 1 11 1C8.79 1 7 2.79 7 5V17.5C7 20.54 9.46 23 12.5 23C15.54 23 18 20.54 18 17.5V6H16.5Z\" fill=\"currentColor\"/>\n </svg>\n `;\n\n // Hidden file input\n this.fileInput = createElement('input', {\n className: 'cevro-chat-window__file-input',\n }) as HTMLInputElement;\n this.fileInput.type = 'file';\n // Generate accept attribute from allowed MIME types to stay in sync with validation\n this.fileInput.accept = this.config.fileUpload?.allowedMimeTypes\n ? this.config.fileUpload.allowedMimeTypes.join(',')\n : generateAcceptAttribute();\n this.fileInput.addEventListener('change', () => {\n if (this.fileInput?.files?.length && this.callbacks.onFileUpload) {\n this.callbacks.onFileUpload(this.fileInput.files[0]);\n this.fileInput.value = '';\n }\n });\n\n this.fileButton.addEventListener('click', () => {\n this.fileInput?.click();\n });\n\n inputArea.appendChild(this.fileButton);\n inputArea.appendChild(this.fileInput);\n\n // Text input (max 2000 characters)\n this.inputElement = createElement('textarea', {\n className: 'cevro-chat-window__input',\n 'data-testid': 'chat-input',\n }) as HTMLTextAreaElement;\n this.inputElement.placeholder = this.strings.inputPlaceholder;\n this.inputElement.rows = 1;\n this.inputElement.setAttribute('maxlength', '2000');\n\n // Auto-resize textarea\n this.inputElement.addEventListener('input', () => {\n if (this.inputElement) {\n this.inputElement.style.height = 'auto';\n this.inputElement.style.height = Math.min(this.inputElement.scrollHeight, 100) + 'px';\n this.updateSendButtonState();\n }\n });\n\n // Handle enter key\n this.inputElement.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n this.handleSend();\n }\n });\n\n inputArea.appendChild(this.inputElement);\n\n // Send button - arrow icon\n this.sendButton = createElement('button', {\n className: 'cevro-chat-window__send-button',\n 'aria-label': 'Send message',\n 'data-testid': 'send-button',\n }) as HTMLButtonElement;\n this.sendButton.disabled = true;\n this.sendButton.innerHTML = `\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M12 19V5M5 12L12 5L19 12\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n `;\n\n this.sendButton.addEventListener('click', () => {\n this.handleSend();\n });\n\n inputArea.appendChild(this.sendButton);\n wrapper.appendChild(inputArea);\n\n // Powered by footer\n const footer = createElement('div', {\n className: 'cevro-chat-window__footer',\n });\n footer.innerHTML = `${this.strings.poweredBy.replace('Cevro AI', '<a href=\"https://cevro.ai\" target=\"_blank\" rel=\"noopener\">Cevro AI</a>')}`;\n wrapper.appendChild(footer);\n\n return wrapper;\n }\n\n /**\n * Handle send message\n */\n private handleSend(): void {\n if (!this.inputElement) return;\n\n const message = this.inputElement.value.trim();\n if (!message) return;\n\n this.callbacks.onSendMessage(message);\n this.inputElement.value = '';\n this.inputElement.style.height = 'auto';\n this.updateSendButtonState();\n this.inputElement.focus();\n }\n\n /**\n * Update send button state\n */\n private updateSendButtonState(): void {\n if (this.sendButton && this.inputElement) {\n this.sendButton.disabled = !this.inputElement.value.trim();\n }\n }\n\n /**\n * Apply theme\n */\n private applyTheme(): void {\n if (!this.element) return;\n\n const theme = this.config.theme || 'light';\n\n // Clean up previous listener if exists\n this.cleanupThemeListener();\n\n if (theme === 'system') {\n this.themeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n const prefersDark = this.themeMediaQuery.matches;\n this.element.classList.toggle('cevro-chat-window--dark', prefersDark);\n\n // Add listener for theme changes\n this.themeChangeHandler = (e: MediaQueryListEvent) => {\n this.element?.classList.toggle('cevro-chat-window--dark', e.matches);\n };\n this.themeMediaQuery.addEventListener('change', this.themeChangeHandler);\n } else {\n this.element.classList.toggle('cevro-chat-window--dark', theme === 'dark');\n }\n }\n\n /**\n * Clean up theme change listener\n */\n private cleanupThemeListener(): void {\n if (this.themeMediaQuery && this.themeChangeHandler) {\n this.themeMediaQuery.removeEventListener('change', this.themeChangeHandler);\n this.themeMediaQuery = null;\n this.themeChangeHandler = null;\n }\n }\n\n /**\n * Add message to the chat\n */\n addMessage(message: Message, animate = true): void {\n this.messageList.addMessage(message, animate);\n }\n\n /**\n * Update message\n */\n updateMessage(message: Message, oldId?: string): void {\n this.messageList.updateMessage(message, oldId);\n }\n\n /**\n * Update upload progress for a message\n */\n updateMessageProgress(messageId: string, progress: number): void {\n this.messageList.updateMessageProgress(messageId, progress);\n }\n\n /**\n * Remove a message from the chat\n */\n removeMessage(messageId: string): void {\n this.messageList.removeMessage(messageId);\n }\n\n /**\n * Show typing indicator\n */\n showTypingIndicator(): void {\n this.messageList.showTypingIndicator();\n }\n\n /**\n * Hide typing indicator\n */\n hideTypingIndicator(): void {\n this.messageList.hideTypingIndicator();\n }\n\n /**\n * Clear messages\n */\n clearMessages(): void {\n this.messageList.clear();\n }\n\n /**\n * Show the chat window\n */\n show(): void {\n if (this.element) {\n this.element.classList.add('cevro-chat-window--visible');\n this.isVisible = true;\n this.inputElement?.focus();\n this.messageList.scrollToBottom();\n }\n }\n\n /**\n * Hide the chat window\n */\n hide(): void {\n if (this.element) {\n this.element.classList.remove('cevro-chat-window--visible');\n this.isVisible = false;\n }\n }\n\n /**\n * Check if visible\n */\n isWindowVisible(): boolean {\n return this.isVisible;\n }\n\n /**\n * Focus input\n */\n focusInput(): void {\n this.inputElement?.focus();\n }\n\n /**\n * Set ticket closed state\n * Shows CSAT form, then thank you, then \"New Conversation\" button\n *\n * @param closed - Whether the ticket is closed\n * @param onStartNewChat - Callback when user clicks \"New Conversation\"\n * @param options - Additional options\n * @param options.showHistory - Show message history (future paid feature)\n * @param options.skipCSAT - Skip CSAT and show new chat directly\n * @param options.ticketId - Ticket ID for CSAT localStorage tracking\n */\n setTicketClosed(\n closed: boolean,\n onStartNewChat?: () => void,\n options?: { showHistory?: boolean; skipCSAT?: boolean; ticketId?: string }\n ): void {\n const showHistory = options?.showHistory ?? false;\n const skipCSAT = options?.skipCSAT ?? false;\n const ticketId = options?.ticketId;\n\n if (closed) {\n // Clear messages if history is not enabled (future paid feature)\n if (!showHistory) {\n this.messageList.clear();\n }\n\n // Hide input area\n if (this.inputWrapper) {\n this.inputWrapper.style.display = 'none';\n }\n\n // Check if CSAT already submitted for this ticket\n const csatSubmitted = ticketId && localStorage.getItem(`cevro_csat_${ticketId}`);\n\n if (skipCSAT || csatSubmitted) {\n // Skip CSAT, show new chat directly\n this.showNewChatUI(onStartNewChat);\n } else {\n // Show CSAT form\n this.showCSATForm(onStartNewChat, ticketId);\n }\n } else {\n // Show input area\n if (this.inputWrapper) {\n this.inputWrapper.style.display = '';\n }\n\n // Hide closed message\n this.messageList.hideClosedMessage();\n\n // Remove CSAT container\n this.removeCSATContainer();\n\n // Remove closed footer\n if (this.closedFooter && this.closedFooter.parentNode) {\n this.closedFooter.parentNode.removeChild(this.closedFooter);\n this.closedFooter = null;\n }\n }\n }\n\n /**\n * Show CSAT rating form\n */\n private showCSATForm(onStartNewChat?: () => void, ticketId?: string): void {\n this.removeCSATContainer();\n this.csatRating = 0;\n\n if (!this.element) return;\n\n this.csatContainer = createElement('div', {\n className: 'cevro-csat',\n });\n\n // Title\n const title = createElement('h3', {\n className: 'cevro-csat__title',\n }, [this.strings.csatTitle]);\n\n // Subtitle\n const subtitle = createElement('p', {\n className: 'cevro-csat__subtitle',\n }, [this.strings.csatSubtitle]);\n\n // Stars container\n const starsContainer = createElement('div', {\n className: 'cevro-csat__stars',\n });\n\n for (let i = 1; i <= 5; i++) {\n const star = createElement('button', {\n className: 'cevro-csat__star',\n 'data-rating': String(i),\n 'aria-label': `Rate ${i} stars`,\n });\n star.innerHTML = this.createStarSvg(false);\n star.addEventListener('click', () => this.selectRating(i, starsContainer));\n star.addEventListener('mouseenter', () => this.previewRating(i, starsContainer));\n star.addEventListener('mouseleave', () => this.previewRating(this.csatRating, starsContainer));\n starsContainer.appendChild(star);\n }\n\n // Feedback textarea\n const feedbackInput = createElement('textarea', {\n className: 'cevro-csat__feedback',\n 'data-testid': 'csat-feedback',\n }) as HTMLTextAreaElement;\n feedbackInput.placeholder = this.strings.csatPlaceholder;\n feedbackInput.maxLength = 1000;\n\n // Submit button\n const submitButton = createElement('button', {\n className: 'cevro-csat__submit',\n 'data-testid': 'csat-submit',\n }, [this.strings.csatSubmit]) as HTMLButtonElement;\n submitButton.disabled = true;\n\n submitButton.addEventListener('click', async () => {\n if (this.csatRating === 0 || this.csatSubmitting) return;\n\n this.csatSubmitting = true;\n submitButton.disabled = true;\n submitButton.textContent = '...';\n\n try {\n if (this.callbacks.onCSATSubmit) {\n await this.callbacks.onCSATSubmit(this.csatRating, feedbackInput.value.trim() || undefined);\n }\n\n // Mark as submitted\n if (ticketId) {\n localStorage.setItem(`cevro_csat_${ticketId}`, '1');\n }\n\n // Show thank you\n this.showCSATThankYou(onStartNewChat);\n } catch (error) {\n console.error('[CevroMessenger] CSAT submit failed:', error);\n submitButton.disabled = false;\n submitButton.textContent = this.strings.csatSubmit;\n } finally {\n this.csatSubmitting = false;\n }\n });\n\n // Skip button (X in corner)\n const skipButton = createElement('button', {\n className: 'cevro-csat__skip',\n 'aria-label': 'Skip',\n });\n skipButton.innerHTML = `\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n `;\n skipButton.addEventListener('click', () => {\n this.showNewChatUI(onStartNewChat);\n });\n\n // Powered by footer\n const poweredBy = createElement('div', {\n className: 'cevro-csat__powered-by',\n });\n poweredBy.innerHTML = `${this.strings.poweredBy.replace('Cevro AI', '<a href=\"https://cevro.ai\" target=\"_blank\" rel=\"noopener\">Cevro AI</a>')}`;\n\n this.csatContainer.appendChild(skipButton);\n this.csatContainer.appendChild(title);\n this.csatContainer.appendChild(subtitle);\n this.csatContainer.appendChild(starsContainer);\n this.csatContainer.appendChild(feedbackInput);\n this.csatContainer.appendChild(submitButton);\n this.csatContainer.appendChild(poweredBy);\n\n this.element.appendChild(this.csatContainer);\n }\n\n /**\n * Show CSAT thank you state\n */\n private showCSATThankYou(onStartNewChat?: () => void): void {\n this.removeCSATContainer();\n\n if (!this.element) return;\n\n this.csatContainer = createElement('div', {\n className: 'cevro-csat cevro-csat--thank-you',\n });\n\n // Checkmark icon\n const icon = createElement('div', {\n className: 'cevro-csat__icon',\n });\n icon.innerHTML = `\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\" fill=\"none\">\n <circle cx=\"24\" cy=\"24\" r=\"24\" fill=\"#10B981\"/>\n <path d=\"M14 24L21 31L34 18\" stroke=\"white\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n `;\n\n // Thank you message\n const message = createElement('h3', {\n className: 'cevro-csat__title',\n }, [this.strings.csatThankYou]);\n\n // New chat button\n const newChatButton = createElement('button', {\n className: 'cevro-csat__submit',\n }, [this.strings.newConversation]);\n\n newChatButton.addEventListener('click', () => {\n if (onStartNewChat) {\n onStartNewChat();\n }\n });\n\n // Powered by footer\n const poweredBy = createElement('div', {\n className: 'cevro-csat__powered-by',\n });\n poweredBy.innerHTML = `${this.strings.poweredBy.replace('Cevro AI', '<a href=\"https://cevro.ai\" target=\"_blank\" rel=\"noopener\">Cevro AI</a>')}`;\n\n this.csatContainer.appendChild(icon);\n this.csatContainer.appendChild(message);\n this.csatContainer.appendChild(newChatButton);\n this.csatContainer.appendChild(poweredBy);\n\n this.element.appendChild(this.csatContainer);\n }\n\n /**\n * Show new chat UI (without CSAT)\n */\n private showNewChatUI(onStartNewChat?: () => void): void {\n this.removeCSATContainer();\n this.messageList.showClosedMessage(this.strings.closedMessage);\n\n if (!this.closedFooter && this.element) {\n this.closedFooter = createElement('div', {\n className: 'cevro-chat-window__closed-footer',\n });\n\n const newChatButton = createElement('button', {\n className: 'cevro-chat-window__new-chat-button',\n }, [this.strings.newConversation]);\n\n newChatButton.addEventListener('click', () => {\n if (onStartNewChat) {\n onStartNewChat();\n }\n });\n\n const poweredBy = createElement('div', {\n className: 'cevro-chat-window__powered-by',\n });\n poweredBy.innerHTML = `${this.strings.poweredBy.replace('Cevro AI', '<a href=\"https://cevro.ai\" target=\"_blank\" rel=\"noopener\">Cevro AI</a>')}`;\n\n this.closedFooter.appendChild(newChatButton);\n this.closedFooter.appendChild(poweredBy);\n this.element.appendChild(this.closedFooter);\n }\n }\n\n /**\n * Remove CSAT container\n */\n private removeCSATContainer(): void {\n if (this.csatContainer && this.csatContainer.parentNode) {\n this.csatContainer.parentNode.removeChild(this.csatContainer);\n this.csatContainer = null;\n }\n }\n\n /**\n * Select star rating\n */\n private selectRating(rating: number, container: HTMLElement): void {\n this.csatRating = rating;\n this.updateStars(rating, container);\n\n // Enable submit button\n const submitButton = this.csatContainer?.querySelector('.cevro-csat__submit') as HTMLButtonElement;\n if (submitButton) {\n submitButton.disabled = false;\n }\n }\n\n /**\n * Preview star rating on hover\n */\n private previewRating(rating: number, container: HTMLElement): void {\n this.updateStars(rating, container);\n }\n\n /**\n * Update stars display\n */\n private updateStars(rating: number, container: HTMLElement): void {\n const stars = container.querySelectorAll('.cevro-csat__star');\n stars.forEach((star, index) => {\n const filled = index < rating;\n star.innerHTML = this.createStarSvg(filled);\n star.classList.toggle('cevro-csat__star--filled', filled);\n });\n }\n\n /**\n * Create star SVG\n */\n private createStarSvg(filled: boolean): string {\n if (filled) {\n return `\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"#FBBF24\" stroke=\"#FBBF24\" stroke-width=\"1\">\n <polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\"/>\n </svg>\n `;\n }\n return `\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#D1D5DB\" stroke-width=\"1.5\">\n <polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\"/>\n </svg>\n `;\n }\n\n /**\n * Destroy the component\n */\n destroy(): void {\n // Clean up theme listener\n this.cleanupThemeListener();\n\n this.messageList.destroy();\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n this.element = null;\n this.inputElement = null;\n this.sendButton = null;\n this.fileInput = null;\n this.fileButton = null;\n this.closedFooter = null;\n this.csatContainer = null;\n }\n}\n","import type {\n CevroMessengerConfig,\n PlayerData,\n Message,\n QuickAction,\n EventType,\n EventHandler,\n} from '../types';\nimport { EventEmitter } from './EventEmitter';\nimport { ApiClient } from './ApiClient';\nimport { WebSocketClient } from './WebSocketClient';\nimport { Launcher } from '../ui/Launcher';\nimport { ChatWindow } from '../ui/ChatWindow';\nimport {\n generateVisitorId,\n getStoredSession,\n storeSession,\n clearStoredSession,\n clearStoredVisitorToken,\n getStoredVisitorToken,\n storeVisitorToken,\n} from '../utils/session';\nimport { isValidUrl } from '../utils/dom';\nimport { getStrings } from '../i18n/strings';\n\n/**\n * Main Cevro Messenger SDK class\n */\nexport class CevroMessenger {\n private static instance: CevroMessenger | null = null;\n\n private config: CevroMessengerConfig;\n private events: EventEmitter;\n private api: ApiClient;\n private ws: WebSocketClient;\n private launcher: Launcher | null = null;\n private chatWindow: ChatWindow | null = null;\n private container: HTMLElement | null = null;\n private isBooted = false;\n private isVisible = false;\n private unreadCount = 0;\n private visitorId: string | null;\n\n private isSessionInitialized = false;\n private isInitializingSession: Promise<void> | null = null;\n private connectingPromise: Promise<void> | null = null;\n private typingCycleTimeout: ReturnType<typeof setTimeout> | null = null;\n private isTypingVisible = false;\n private typingConfig = { onDurationMs: 7000, offDurationMs: 4000 };\n\n constructor(config: CevroMessengerConfig) {\n this.config = this.normalizeConfig(config);\n this.events = new EventEmitter();\n this.api = new ApiClient(this.config);\n this.ws = new WebSocketClient(this.config, this.events);\n this.visitorId = generateVisitorId();\n\n // Setup token refresh callback for WebSocket\n this.ws.setTokenRefreshCallback(async () => {\n return this.refreshConnectionToken();\n });\n\n // Setup internal event handlers\n this.setupEventHandlers();\n\n // Singleton pattern\n CevroMessenger.instance = this;\n\n this.log('Initialized with config:', this.config);\n }\n\n /**\n * Get singleton instance\n */\n static getInstance(): CevroMessenger | null {\n return CevroMessenger.instance;\n }\n\n /**\n * Normalize and validate config\n */\n private normalizeConfig(config: CevroMessengerConfig): CevroMessengerConfig {\n return {\n ...config,\n apiBase: config.apiBase.replace(/\\/$/, ''), // Remove trailing slash\n alignment: config.alignment || 'right',\n verticalPadding: config.verticalPadding ?? 20,\n horizontalPadding: config.horizontalPadding ?? 20,\n theme: config.theme || 'light',\n zIndex: config.zIndex ?? 2147483647,\n debug: config.debug ?? false,\n };\n }\n\n /**\n * Setup internal event handlers\n */\n private setupEventHandlers(): void {\n // Handle incoming messages\n this.events.on('message:received', (data: { ticketId: string; message: Message }) => {\n this.log('Received message:', data);\n\n // Stop typing cycle and hide indicator when message arrives\n this.stopTypingCycle();\n\n if (this.chatWindow) {\n this.chatWindow.addMessage(data.message);\n }\n\n // Update unread count if window is not visible\n if (!this.isVisible) {\n this.setUnreadCount(this.unreadCount + 1);\n }\n });\n\n // Handle typing indicators from backend\n this.events.on('typing:start', (data: { ticketId: string; actor: string }) => {\n this.log('Typing started:', data);\n if (data.ticketId === this.api.getCurrentTicketId()) {\n this.startTypingCycle();\n }\n });\n\n this.events.on('typing:stop', (data: { ticketId: string; actor: string }) => {\n this.log('Typing stopped:', data);\n this.stopTypingCycle();\n });\n\n // Handle conversation started\n this.events.on('conversation:started', (data: { ticketId: string }) => {\n this.log('Conversation started:', data);\n });\n\n // Handle conversation/ticket status updates (real-time close from admin)\n this.events.on('conversation:updated', (data: { ticketId: string; status: string; message?: string }) => {\n this.log('Conversation updated:', data);\n\n // Handle ticket closed by admin\n if (data.status === 'closed') {\n this.log('Ticket closed by admin, showing closed state');\n this.chatWindow?.setTicketClosed(true, () => this.startNewChat(), {\n ticketId: data.ticketId,\n });\n }\n });\n\n // Handle connection events\n this.events.on('connection:open', () => {\n this.log('WebSocket connected');\n });\n\n this.events.on('connection:close', () => {\n this.log('WebSocket disconnected');\n });\n\n this.events.on('connection:error', (data: { error: string }) => {\n this.log('WebSocket error:', data.error);\n });\n }\n\n /**\n * Boot the messenger\n */\n boot(): void {\n if (this.isBooted) {\n this.log('Already booted');\n return;\n }\n\n this.log('Booting...');\n\n // Create container\n this.container = document.createElement('div');\n this.container.id = 'cevro-messenger-container';\n document.body.appendChild(this.container);\n\n // Create launcher (if not hidden)\n if (!this.config.hideDefaultLauncher) {\n this.launcher = new Launcher(this.config, () => this.toggle());\n this.container.appendChild(this.launcher.render());\n }\n\n // Setup custom launcher if provided\n if (this.config.customLauncherSelector) {\n const customLauncher = document.querySelector(this.config.customLauncherSelector);\n if (customLauncher) {\n customLauncher.addEventListener('click', () => this.toggle());\n }\n }\n\n // Create chat window with merged locale strings\n const strings = getStrings(this.config.locale);\n this.chatWindow = new ChatWindow(this.config, {\n onClose: () => this.hide(),\n onSendMessage: (message) => this.sendMessage(message),\n onQuickAction: (action) => this.handleQuickAction(action),\n onFileUpload: (file) => this.handleFileUpload(file),\n onCSATSubmit: async (rating, feedback) => this.submitCSAT(rating, feedback),\n onStartNewChat: () => this.startNewChat(),\n }, strings);\n this.container.appendChild(this.chatWindow.render());\n\n // Check for existing session (will be properly restored on show())\n const storedSession = getStoredSession();\n if (storedSession?.ticketId) {\n this.api.setCurrentTicketId(storedSession.ticketId);\n }\n\n this.isBooted = true;\n this.events.emit('boot');\n\n // WebSocket connection moved to show() - only connect when chat is opened\n\n this.log('Booted successfully');\n }\n\n /**\n * Connect to Centrifugo WebSocket server\n * Fetches connection token from API first\n *\n * Security: Uses signed visitorToken to prevent visitor spoofing\n */\n private async connectWebSocket(): Promise<void> {\n // If already connecting, wait for existing promise\n if (this.connectingPromise) {\n this.log('Already connecting to WebSocket, waiting...');\n return this.connectingPromise;\n }\n\n this.connectingPromise = this.doConnectWebSocket();\n return this.connectingPromise;\n }\n\n private async doConnectWebSocket(): Promise<void> {\n try {\n this.log('Fetching Centrifugo connection token...');\n\n // Get stored visitorToken (signed by server)\n const storedVisitorToken = getStoredVisitorToken();\n\n const result = await this.api.getConnectionToken(storedVisitorToken);\n\n // Always update visitorId from server response\n this.visitorId = result.visitorId;\n this.log('Visitor:', result.visitorId);\n\n // Store the visitorToken from server if provided\n if (result.visitorToken) {\n storeVisitorToken(result.visitorToken);\n this.api.setVisitorToken(result.visitorToken);\n }\n\n this.log('Got connection token, connecting to Centrifugo...');\n this.ws.connect(result.visitorId, result.token);\n\n this.events.emit('ready');\n } catch (error) {\n this.log('Failed to connect to WebSocket:', error);\n // Still emit ready - SDK works without real-time, just with polling\n this.events.emit('ready');\n this.events.emit('error', { type: 'websocket_connect', error });\n } finally {\n this.connectingPromise = null;\n }\n }\n\n /**\n * Refresh connection token for Centrifugo\n * Called automatically when token expires or on reconnect\n */\n private async refreshConnectionToken(): Promise<string> {\n this.log('Refreshing Centrifugo connection token...');\n\n const storedVisitorToken = getStoredVisitorToken();\n const result = await this.api.getConnectionToken(storedVisitorToken);\n\n // Update visitorToken if returned\n if (result.visitorToken) {\n storeVisitorToken(result.visitorToken);\n this.api.setVisitorToken(result.visitorToken);\n }\n\n this.log('Token refreshed for visitor:', result.visitorId);\n return result.token;\n }\n\n /**\n * Shutdown the messenger\n * @param options.clearVisitorData - If true, clears visitor token (visitor will get new identity on next init)\n */\n shutdown(options?: { clearVisitorData?: boolean }): void {\n if (!this.isBooted) {\n return;\n }\n\n this.log('Shutting down...');\n\n // Stop typing cycle\n this.stopTypingCycle();\n\n // Disconnect WebSocket\n this.ws.disconnect();\n\n // Destroy UI components\n this.launcher?.destroy();\n this.chatWindow?.destroy();\n\n // Remove container\n if (this.container && this.container.parentNode) {\n this.container.parentNode.removeChild(this.container);\n }\n\n // Clear stored data\n clearStoredSession();\n if (options?.clearVisitorData) {\n clearStoredVisitorToken();\n this.visitorId = null;\n }\n this.api.clear();\n\n // Reset state\n this.launcher = null;\n this.chatWindow = null;\n this.container = null;\n this.isBooted = false;\n this.isVisible = false;\n this.unreadCount = 0;\n this.isSessionInitialized = false;\n this.isInitializingSession = null;\n this.connectingPromise = null;\n\n this.events.emit('shutdown');\n this.log('Shutdown complete');\n }\n\n /**\n * Update player data\n * If playerId is provided and we have an existing visitor session,\n * this will merge the visitor with the authenticated player\n */\n async update(playerData: Partial<PlayerData>): Promise<void> {\n const hadPlayerId = !!this.config.player?.playerId;\n\n this.config.player = {\n ...this.config.player,\n ...playerData,\n } as PlayerData;\n\n this.log('Player data updated:', this.config.player);\n\n // If we're adding playerId for the first time (visitor → player),\n // re-initialize session to merge contacts\n if (!hadPlayerId && playerData.playerId && this.isSessionInitialized) {\n this.log('Player ID added, re-initializing session for merge...');\n this.isSessionInitialized = false;\n await this.initializeSession();\n }\n }\n\n /**\n * Show the messenger\n */\n async show(): Promise<void> {\n if (!this.isBooted) {\n this.boot();\n }\n\n if (this.chatWindow) {\n this.chatWindow.show();\n this.isVisible = true;\n this.launcher?.setOpen(true);\n this.setUnreadCount(0);\n this.events.emit('show');\n\n // Connect to WebSocket first (gets visitorId from server), then initialize session\n await this.connectWebSocket();\n await this.initializeSession();\n }\n }\n\n /**\n * Initialize session with backend\n * Creates/retrieves Contact and Ticket, loads existing messages\n * Uses promise pattern to ensure proper waiting when called concurrently\n */\n private async initializeSession(forceNew = false): Promise<void> {\n // If forcing new session, reset state\n if (forceNew) {\n this.isSessionInitialized = false;\n this.isInitializingSession = null;\n }\n\n // Already initialized - nothing to do\n if (this.isSessionInitialized) {\n return;\n }\n\n // If initialization is in progress, wait for it to complete\n if (this.isInitializingSession) {\n return this.isInitializingSession;\n }\n\n // Start new initialization - wrap with finally to ensure cleanup\n const initPromise = this.doInitializeSession().finally(() => {\n // Only clear if this is still the current initialization promise\n if (this.isInitializingSession === initPromise) {\n this.isInitializingSession = null;\n }\n });\n\n this.isInitializingSession = initPromise;\n return initPromise;\n }\n\n /**\n * Actual session initialization logic\n */\n private async doInitializeSession(options?: { forceNewTicket?: boolean }): Promise<void> {\n this.log('Initializing session...', options);\n\n try {\n const result = await this.api.initSession(this.visitorId, options);\n\n this.log('Session initialized:', result);\n\n // Store session data\n storeSession(result.sessionId, result.contactId, result.ticketId);\n this.isSessionInitialized = true;\n\n // Set agent info in header\n if (result.agent && this.chatWindow) {\n this.chatWindow.setAgent(result.agent);\n }\n\n // Store typing config from server\n if (result.typingConfig) {\n this.typingConfig = result.typingConfig;\n this.log('Typing config:', this.typingConfig);\n }\n\n // Apply backend locale strings (highest priority: backend > client config > defaults)\n if (result.locale && this.chatWindow) {\n const mergedStrings = getStrings(this.config.locale, result.locale);\n this.chatWindow.setStrings(mergedStrings);\n this.log('Applied backend locale:', result.locale);\n }\n\n // Load existing messages into chat window\n if (result.messages && result.messages.length > 0) {\n this.log(`Loading ${result.messages.length} existing messages`);\n for (const message of result.messages) {\n this.chatWindow?.addMessage(message);\n }\n }\n\n // Handle closed ticket state\n if (result.ticketClosed) {\n this.log('Ticket is closed:', result.ticketClosedReason);\n this.chatWindow?.setTicketClosed(true, () => this.startNewChat(), {\n ticketId: result.ticketId,\n });\n }\n\n this.events.emit('session:initialized', {\n sessionId: result.sessionId,\n contactId: result.contactId,\n ticketId: result.ticketId,\n isNewSession: result.isNewSession,\n isNewTicket: result.isNewTicket,\n ticketClosed: result.ticketClosed,\n messageCount: result.messages?.length || 0,\n });\n\n } catch (error) {\n this.log('Failed to initialize session:', error);\n this.events.emit('error', { type: 'session_init', error });\n throw error; // Re-throw so callers know it failed\n }\n }\n\n /**\n * Submit CSAT rating for the current conversation\n */\n private async submitCSAT(rating: number, feedback?: string): Promise<void> {\n const ticketId = this.api.getCurrentTicketId();\n const contactId = this.api.getContactId();\n\n if (!ticketId || !contactId) {\n this.log('Cannot submit CSAT: no active session');\n throw new Error('No active session');\n }\n\n this.log('Submitting CSAT:', { ticketId, rating, feedback });\n\n await this.api.submitCSAT(ticketId, contactId, rating, feedback);\n\n this.log('CSAT submitted successfully');\n }\n\n /**\n * Start a new chat (creates a new ticket)\n * Used when the previous chat was closed\n */\n async startNewChat(): Promise<void> {\n this.log('Starting new chat...');\n\n // Clear current chat window messages\n this.chatWindow?.clearMessages();\n this.chatWindow?.setTicketClosed(false);\n\n // Re-initialize session with forceNewTicket\n this.isSessionInitialized = false;\n await this.doInitializeSession({ forceNewTicket: true });\n\n this.events.emit('chat:new_started');\n }\n\n /**\n * Hide the messenger\n */\n hide(): void {\n if (this.chatWindow) {\n this.chatWindow.hide();\n this.isVisible = false;\n this.launcher?.setOpen(false);\n this.events.emit('hide');\n }\n }\n\n /**\n * Toggle messenger visibility\n */\n toggle(): void {\n if (this.isVisible) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n /**\n * Maximum message length (2000 characters)\n */\n private static readonly MAX_MESSAGE_LENGTH = 2000;\n\n /**\n * Send a message\n */\n async sendMessage(message: string): Promise<void> {\n if (!message.trim()) return;\n\n // Validate message length\n if (message.length > CevroMessenger.MAX_MESSAGE_LENGTH) {\n this.log('Message too long:', message.length);\n this.events.emit('error', {\n type: 'validation',\n error: new Error(`Message is too long. Maximum ${CevroMessenger.MAX_MESSAGE_LENGTH} characters allowed.`),\n message: `Message is too long. Maximum ${CevroMessenger.MAX_MESSAGE_LENGTH} characters allowed.`,\n });\n return;\n }\n\n this.log('Sending message:', message);\n\n // Create optimistic message\n // inbound: true = user's message going TO backend (consistent with backend storage)\n const optimisticMessage: Message = {\n id: 'temp_' + Date.now(),\n body: message,\n inbound: true,\n outbound: false,\n createdAt: new Date().toISOString(),\n type: 'text',\n status: 'sending',\n };\n\n // Add to UI immediately\n this.chatWindow?.addMessage(optimisticMessage);\n\n try {\n // Ensure session is initialized before sending\n if (!this.isSessionInitialized) {\n await this.initializeSession();\n }\n\n // Store original temp id for lookup\n const tempId = optimisticMessage.id;\n\n // Send message to existing conversation\n const result = await this.api.sendMessage(message);\n\n // Update optimistic message with real data\n optimisticMessage.id = result.id;\n optimisticMessage.status = 'sent';\n this.chatWindow?.updateMessage(optimisticMessage, tempId);\n\n this.events.emit('message:sent', { message: result });\n\n // Typing indicator will be shown by backend via WebSocket event\n\n } catch (error: any) {\n this.log('Error sending message:', error);\n\n // Check if conversation is closed\n const isConversationClosed =\n error?.message?.includes('closed') ||\n error?.message?.includes('resolved') ||\n error?.message?.includes('escalated') ||\n error?.response?.data?.message?.includes('closed');\n\n if (isConversationClosed) {\n this.log('Conversation is closed, showing closed UI');\n\n // Remove the failed optimistic message\n this.chatWindow?.removeMessage(optimisticMessage.id);\n\n // Show closed UI with \"New Conversation\" button\n const ticketId = this.api.getCurrentTicketId() || undefined;\n this.chatWindow?.setTicketClosed(true, () => this.startNewChat(), { ticketId });\n return;\n }\n\n // Update optimistic message with error status\n optimisticMessage.status = 'failed';\n this.chatWindow?.updateMessage(optimisticMessage);\n\n this.events.emit('error', { error, type: 'send_message' });\n }\n }\n\n /**\n * Show new message composer with pre-filled text\n */\n showNewMessage(prefilledText?: string): void {\n this.show();\n\n if (prefilledText && this.chatWindow) {\n // Pre-fill the input (would need to expose this in ChatWindow)\n this.log('Pre-filling message:', prefilledText);\n }\n }\n\n /**\n * Handle quick action click\n */\n private async handleQuickAction(action: QuickAction): Promise<void> {\n this.log('Quick action clicked:', action);\n\n if (action.type === 'link' && action.url) {\n // Validate URL to prevent XSS via javascript: protocol\n if (isValidUrl(action.url)) {\n window.open(action.url, '_blank');\n } else {\n this.log('Invalid URL blocked:', action.url);\n }\n } else {\n // Send the action value as a message\n await this.sendMessage(action.value || action.label);\n }\n }\n\n /**\n * Handle file upload with progress tracking\n * Shows preview immediately, then uploads to S3, then sends to backend\n *\n * Security: File is validated before upload (size, type, extension)\n */\n private async handleFileUpload(file: File): Promise<void> {\n this.log('File upload:', file.name, file.type, file.size);\n\n // Variables for cleanup on error\n let localPreviewUrl: string | undefined;\n let tempId: string | undefined;\n\n try {\n // Ensure session is initialized before uploading\n if (!this.isSessionInitialized) {\n await this.initializeSession();\n }\n\n // Determine file type for display\n const isImage = file.type.startsWith('image/');\n const fileCategory = this.getFileCategory(file.type);\n\n // Create local preview URL for images\n localPreviewUrl = isImage ? URL.createObjectURL(file) : undefined;\n\n // Create optimistic message IMMEDIATELY (before upload starts)\n tempId = 'temp_' + Date.now();\n const optimisticMessage: Message = {\n id: tempId,\n body: '',\n inbound: true,\n outbound: false,\n createdAt: new Date().toISOString(),\n type: isImage ? 'image' : 'file',\n mediaUrl: localPreviewUrl,\n mediaType: file.type,\n status: 'sending',\n attachment: {\n filename: file.name,\n contentType: file.type || 'application/octet-stream',\n size: file.size,\n category: fileCategory,\n },\n };\n\n // Show preview in chat immediately\n this.chatWindow?.addMessage(optimisticMessage);\n\n // Now start the upload with progress (validation happens inside uploadFile)\n const assetId = await this.api.uploadFile(file, (progress) => {\n // Update progress in the message itself\n this.chatWindow?.updateMessageProgress(tempId!, progress);\n });\n\n // Send message to backend\n const result = await this.api.sendMessage('', assetId);\n\n // Update with real data from server, keeping blob URL if server didn't return mediaUrl\n const serverHasMediaUrl = result.mediaUrl && isValidUrl(result.mediaUrl);\n\n const updatedMessage: Message = {\n ...result,\n status: 'sent',\n type: isImage ? 'image' : 'file',\n mediaUrl: serverHasMediaUrl ? result.mediaUrl : localPreviewUrl,\n attachment: optimisticMessage.attachment,\n };\n this.chatWindow?.updateMessage(updatedMessage, tempId);\n\n // Only revoke blob URL if server returned a real URL\n if (localPreviewUrl && serverHasMediaUrl) {\n URL.revokeObjectURL(localPreviewUrl);\n }\n\n this.events.emit('message:sent', { type: fileCategory, fileName: file.name });\n\n } catch (error: any) {\n this.log('Error uploading file:', error);\n\n // Clean up blob URL on error\n if (localPreviewUrl) {\n URL.revokeObjectURL(localPreviewUrl);\n }\n\n // Remove failed optimistic message from UI\n if (tempId) {\n this.chatWindow?.removeMessage(tempId);\n }\n\n // Determine error type for better UX\n const errorMessage = error?.message || 'File upload failed';\n const isValidationError =\n errorMessage.includes('too large') ||\n errorMessage.includes('too small') ||\n errorMessage.includes('not allowed') ||\n errorMessage.includes('Too many uploads');\n\n // Emit specific error event with details\n this.events.emit('error', {\n error,\n type: isValidationError ? 'file_validation' : 'file_upload',\n message: errorMessage,\n fileName: file.name,\n });\n }\n }\n\n /**\n * Get file category for display purposes\n */\n private getFileCategory(mimeType: string): 'image' | 'pdf' | 'document' | 'spreadsheet' | 'presentation' | 'video' | 'audio' | 'archive' | 'text' | 'file' {\n if (mimeType.startsWith('image/')) return 'image';\n if (mimeType === 'application/pdf') return 'pdf';\n if (mimeType.includes('word') || mimeType.includes('document')) return 'document';\n if (mimeType.includes('sheet') || mimeType.includes('excel')) return 'spreadsheet';\n if (mimeType.includes('presentation') || mimeType.includes('powerpoint')) return 'presentation';\n if (mimeType.startsWith('video/')) return 'video';\n if (mimeType.startsWith('audio/')) return 'audio';\n if (mimeType.includes('zip') || mimeType.includes('archive') || mimeType.includes('compressed')) return 'archive';\n if (mimeType.startsWith('text/')) return 'text';\n return 'file';\n }\n\n /**\n * Set unread count\n */\n private setUnreadCount(count: number): void {\n this.unreadCount = count;\n this.launcher?.setUnreadCount(count);\n this.events.emit('unread_count_change', { count });\n }\n\n /**\n * Get current unread count\n */\n getUnreadCount(): number {\n return this.unreadCount;\n }\n\n /**\n * Get visitor ID (null if not yet assigned by server)\n */\n getVisitorId(): string | null {\n return this.visitorId;\n }\n\n /**\n * Subscribe to an event\n */\n on<T = any>(event: EventType, handler: EventHandler<T>): () => void {\n return this.events.on(event, handler);\n }\n\n /**\n * Subscribe to an event (once)\n */\n once<T = any>(event: EventType, handler: EventHandler<T>): () => void {\n return this.events.once(event, handler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off(event: EventType, handler: EventHandler): void {\n this.events.off(event, handler);\n }\n\n /**\n * Track custom event\n */\n trackEvent(eventName: string, metadata?: Record<string, any>): void {\n this.log('Track event:', eventName, metadata);\n // Could send to backend for analytics\n }\n\n /**\n * Start typing indicator cycle (5s on, 5s off, repeat)\n */\n private startTypingCycle(): void {\n // Clear any existing cycle\n this.stopTypingCycle();\n\n const { onDurationMs, offDurationMs } = this.typingConfig;\n\n const runCycle = () => {\n if (this.isTypingVisible) {\n // Currently showing - hide it\n this.chatWindow?.hideTypingIndicator();\n this.isTypingVisible = false;\n this.log('Typing cycle: hidden');\n // Schedule next show after pause\n this.typingCycleTimeout = setTimeout(runCycle, offDurationMs);\n } else {\n // Currently hidden - show it\n this.chatWindow?.showTypingIndicator();\n this.isTypingVisible = true;\n this.log('Typing cycle: visible');\n // Schedule next hide after typing duration\n this.typingCycleTimeout = setTimeout(runCycle, onDurationMs);\n }\n };\n\n // Start immediately with typing visible\n this.chatWindow?.showTypingIndicator();\n this.isTypingVisible = true;\n this.log('Typing cycle: started');\n\n // Schedule first toggle (hide after typing duration)\n this.typingCycleTimeout = setTimeout(runCycle, onDurationMs);\n }\n\n /**\n * Stop typing indicator cycle\n */\n private stopTypingCycle(): void {\n if (this.typingCycleTimeout) {\n clearTimeout(this.typingCycleTimeout);\n this.typingCycleTimeout = null;\n }\n\n if (this.isTypingVisible) {\n this.chatWindow?.hideTypingIndicator();\n this.isTypingVisible = false;\n }\n\n this.log('Typing cycle: stopped');\n }\n\n /**\n * Log helper\n */\n private log(...args: any[]): void {\n if (this.config.debug) {\n console.log('[CevroMessenger]', ...args);\n }\n }\n}\n","/**\n * Cevro Messenger SDK\n *\n * A customer support chat widget for web applications.\n *\n * @example\n * // ES Module\n * import CevroMessenger from '@cevro/messenger-sdk';\n *\n * const messenger = new CevroMessenger({\n * apiBase: 'https://api.yoursite.com',\n * workspaceId: 'your-workspace-id',\n * });\n *\n * messenger.boot();\n *\n * @example\n * // UMD (Script tag)\n * <script src=\"https://cdn.jsdelivr.net/npm/@cevro/messenger-sdk\"></script>\n * <script>\n * const messenger = new CevroMessenger({\n * apiBase: 'https://api.yoursite.com',\n * workspaceId: 'your-workspace-id',\n * });\n * messenger.boot();\n * </script>\n */\n\n// Import styles (will be injected by vite plugin)\nimport './styles/index.css';\n\n// Export main class\nexport { CevroMessenger } from './core/CevroMessenger';\n\n// Export types\nexport type {\n CevroMessengerConfig,\n PlayerData,\n SessionData,\n Message,\n Conversation,\n QuickAction,\n RichContent,\n EventType,\n EventHandler,\n} from './types';\n\n// Default export for convenience\nimport { CevroMessenger } from './core/CevroMessenger';\nexport default CevroMessenger;\n\n// Global instance management for UMD builds\ndeclare global {\n interface Window {\n CevroMessenger: typeof CevroMessenger;\n cevroMessenger?: CevroMessenger;\n }\n}\n\n// Auto-attach to window for UMD builds\nif (typeof window !== 'undefined') {\n window.CevroMessenger = CevroMessenger;\n}\n"],"names":["EventEmitter$2","constructor","__publicField","this","Map","on","event","handler","listeners","has","set","Set","get","add","off","once","onceHandler","data","onceHandlers","delete","handlers","emit","forEach","error","console","removeAllListeners","clear","listenerCount","_a","size","getStoredVisitorToken","localStorage","getItem","storeVisitorToken","token","setItem","generateVisitorId","lastDotIndex","lastIndexOf","substring","extractVisitorIdFromToken","getStoredVisitorId","ALLOWED_MIME_TYPES","BLOCKED_EXTENSIONS","DEFAULT_FILE_CONSTRAINTS","maxSizeBytes","minSizeBytes","maxFilenameLength","getFileExtension","filename","lastDot","length","toLowerCase","formatFileSize","bytes","i","Math","floor","log","parseFloat","pow","toFixed","UploadRateLimiter","maxUploads","windowMs","canUpload","now","Date","uploadTimestamps","filter","timestamp","recordUpload","push","getRemainingUploads","max","getTimeUntilNextUpload","oldestTimestamp","min","reset","ApiClient","config","maxUploadsPerMinute","fileUpload","uploadRateLimiter","setVisitorToken","visitorToken","getVisitorToken","setAccessToken","accessToken","getContactId","contactId","getCurrentTicketId","currentTicketId","setCurrentTicketId","ticketId","getCurrentAgent","currentAgent","request","endpoint","options","url","apiBase","headers","workspaceId","brandId","response","fetch","ok","json","catch","message","statusText","Error","status","initSession","visitorId","payload","session","window","navigator","userAgent","language","platform","timezone","Intl","DateTimeFormat","resolvedOptions","timeZone","currentPage","location","href","pageTitle","document","title","referrer","screenWidth","screen","width","screenHeight","height","viewportWidth","innerWidth","viewportHeight","innerHeight","devicePixelRatio","urlParams","URLSearchParams","search","utmSource","utmMedium","utmCampaign","utmContent","utmTerm","cookiesEnabled","cookieEnabled","touchSupport","maxTouchPoints","online","onLine","connection","connectionType","effectiveType","e","collectSessionData","firstName","player","lastName","_b","email","_c","phone","_d","customAttributes","_e","forceNewTicket","_f","playerId","playerHash","result","method","body","JSON","stringify","agent","sessionId","isNewSession","isNewTicket","ticketClosed","ticketClosedReason","typingConfig","messages","_g","map","msg","normalizeMessage","locale","sendMessage","assetId","getMessages","targetTicketId","results","getMyTickets","tickets","ticket","normalizeConversation","uploadFile","file","onProgress","waitTime","ceil","validation","allowedMimeTypes","blockedExtensions","valid","errorCode","name","extension","mimeType","type","validateFile","additionalBlockedExtensions","sanitizedFilename","sanitized","replace","ext","nameWithoutExt","slice","maxNameLength","sanitizeFilename","uploadUrl","contentType","uploadToS3","Promise","resolve","reject","xhr","XMLHttpRequest","upload","addEventListener","lengthComputable","progress","round","loaded","total","open","setRequestHeader","send","id","objectId","inbound","outbound","createdAt","toISOString","mediaUrl","mediaType","richContent","conversationId","updatedAt","resolved","escalated","unreadCount","lastMessage","latestMessage","getConnectionToken","refreshConnectionToken","submitCSAT","rating","feedback","__awaiter","thisArg","_arguments","P","generator","fulfilled","value","step","next","rejected","done","then","apply","getDefaultExportFromCjs","x","__esModule","Object","prototype","hasOwnProperty","call","SuppressedError","ReflectOwnKeys","events","exports","R","Reflect","ReflectApply","target","receiver","args","Function","ownKeys","getOwnPropertySymbols","getOwnPropertyNames","concat","NumberIsNaN","Number","isNaN","EventEmitter","init","emitter","errorListener","err","removeListener","resolver","arguments","eventTargetAgnosticAddListener","flags","addErrorHandlerIfEventEmitter","_events","_eventsCount","_maxListeners","defaultMaxListeners","checkListener","listener","TypeError","_getMaxListeners","that","_addListener","prepend","m","existing","warning","create","newListener","unshift","warned","w","String","count","warn","onceWrapper","fired","wrapFn","_onceWrap","state","wrapped","bind","_listeners","unwrap","evlistener","arr","ret","Array","unwrapListeners","arrayClone","n","copy","wrapListener","arg","removeEventListener","defineProperty","enumerable","RangeError","getPrototypeOf","setMaxListeners","getMaxListeners","doError","er","context","len","addListener","prependListener","prependOnceListener","list","position","originalListener","shift","index","pop","spliceOne","key","keys","rawListeners","eventNames","errorCodes","connectingCodes","disconnectedCodes","subscribingCodes","unsubscribedCodes","subscriptionFlags","State","SubscriptionState","EventEmitter$1","isFunction","backoff","interval","random","randomInt","ttlMilliseconds","ttl","Subscription","centrifuge","channel","super","_resubscribeTimeout","_refreshTimeout","Unsubscribed","_centrifuge","_token","_getToken","_data","_getData","_recover","_offset","_epoch","_id","_recoverable","_positioned","_joinLeave","_minResubscribeDelay","_maxResubscribeDelay","_resubscribeAttempts","_promises","_promiseId","_inflight","_delta","_delta_negotiated","_tagsFilter","_prevValue","_unsubPromise","_setOptions","_debugEnabled","ctx","_debug","oldState","newState","ready","timeout","code","subscriptionUnsubscribed","Subscribed","res","rej","setTimeout","_nextPromiseId","subscribe","_isSubscribed","_setSubscribing","subscribeCalled","unsubscribe","_setUnsubscribed","unsubscribeCalled","publish","_methodCall","presence","presenceStats","history","opts","setTagsFilter","tagsFilter","setData","_isUnsubscribed","timeoutDuration","_config","_needRecover","_isSubscribing","Subscribing","_setState","_usesToken","_clearSubscribingState","_clearResubscribeTimeout","_clearSubscribedState","_clearRefreshTimeout","_setSubscribed","recoverable","offset","epoch","delta","_getSubscribeContext","_resolvePromises","pubs","publications","_handlePublication","expires","_refresh","reason","_transport","emulation","_subscribe","_isTransportOpen","_canSubscribeWithoutGettingToken","_subscribeWithoutToken","_getSubscriptionToken","_handleTokenResponse","_handleTokenError","_transportIsOpen","_getDataAndSubscribe","_sendSubscribe","_handleGetDataError","UnauthorizedError","_failUnauthorized","badConfiguration","toString","_scheduleResubscribe","subscriptionSubscribeToken","cmd","_buildSubscribeCommand","_call","resolveCtx","reply","_handleSubscribeResponse","rejectCtx","_handleSubscribeError","req","positioned","join_leave","flag","channelCompaction","recover","_getOffset","_getEpoch","tf","_subscribeError","_disconnect","subscribeTimeout","sendUnsubscribe","promise","_unsubscribe","_rejectPromises","pub","newData","newPrevValue","_codec","applyDeltaIfNeeded","_getPublicationContext","_handleJoin","join","info","_getJoinLeaveContext","_handleLeave","leave","clearTimeout","self","delay","_getResubscribeDelay","temporary","errContext","Connected","since","getData","minResubscribeDelay","maxResubscribeDelay","getToken","joinLeave","sub_refresh","_refreshResponse","_refreshError","subscriptionRefreshToken","_getRefreshRetryDelay","unauthorized","SockjsTransport","subName","transport","supported","sockjs","initialize","_protocol","callbacks","sockjsOptions","onopen","onOpen","onerror","onError","onclose","closeEvent","onClose","onmessage","onMessage","close","WebsocketTransport","websocket","protocol","subProtocol","binaryType","HttpStreamTransport","_abortController","_utf8decoder","TextDecoder","_handleErrors","_fetchEventTarget","eventTarget","EventTarget","fetchFunc","dispatchEvent","Event","jsonStreamBuf","jsonStreamPos","protoStreamBuf","Uint8Array","reader","getReader","readableStream","start","controller","pump","read","decode","line","MessageEvent","mergedArray","decoder","decodeReply","pos","detail","AbortController","initialData","Accept","fetchOptions","mode","credentials","signal","abort","node","encoder","encodeEmulationRequest","emulationEndpoint","SseTransport","_onClose","eventsource","globalThis","baseURI","URL","searchParams","append","eventSource","WebtransportTransport","_stream","_writer","webtransport","closed","stream","createBidirectionalStream","writable","getWriter","_startReading","readable","binary","TextEncoder","encode","write","zValue","Reader","array","a","haveBytes","getByte","b","getChar","fromCharCode","getInt","c","v","Writer","toByteArray","sourceType","isArray","putArray","end","checksum","sum0","sum1","sum2","sum3","z","N","JsonCodec","encodeCommands","commands","decodeReplies","trim","split","r","parse","prevValue","valueArray","source","zDelta","lenSrc","lenDelta","limit","zOut","cnt","ofst","out","applyDelta","defaults","debug","version","minReconnectDelay","maxReconnectDelay","maxServerPingDelay","networkEventTarget","Centrifuge","_reconnectTimeout","_serverPingTimeout","Disconnected","_endpoint","_emulation","_transports","_currentTransportIndex","_triedAllTransports","_transportWasOpen","_transportId","_deviceWentOffline","_transportClosed","_reconnecting","_reconnectAttempts","_client","_session","_node","_subs","_serverSubs","_commandId","_commands","_batching","_refreshRequired","_callbacks","_dispatchPromise","_serverPing","_sendPong","_networkEventsSet","assign","_configure","newSubscription","getSubscription","sub","_getSub","removeSubscription","_removeSubscription","subscriptions","clientDisconnected","connect","_isConnected","_isConnecting","_startConnecting","disconnect","disconnectCalled","setToken","setHeaders","_transportSendCommands","_createErrorObject","transportWriteError","rpc","_callPromise","_getHistoryRequest","clients","clientId","rawClient","connInfo","chanInfo","presence_stats","numUsers","num_users","numClients","num_clients","startBatching","stopBatching","_flush","level","logger","_codecName","_formatOverride","transportConfig","transportName","indexOf","_isDisconnected","Connecting","_nextCommandId","_setNetworkEvents","transportClosed","_clearReconnectTimeout","_startReconnecting","_getReconnectDelay","_clearOutgoingRequests","errback","connectionClosed","_clearConnectedState","_clearServerPingTimeout","_handleWriteError","command","_initializeTransport","WebSocket","SockJS","EventSource","ReadableStream","transportEndpoint","WebTransport","prefix","transportId","_nextTransportId","wasOpen","initialCommands","connectCommand","_sendConnect","connectTimeout","_sendSubscribeCommands","needReconnect","advice","reconnect","messageSizeLimit","_dataReceived","skipSending","_constructConnectCommand","_connectResponse","_connectError","emptyToken","clientConnectToken","_scheduleReconnect","isInitialHandshake","subs","hasSubs","reverse","resultCB","_waitServerPing","replies","finishDispatch","_dispatchSynchronized","p","_dispatchReply","_handleReply","_handlePush","_handleServerPing","_registerCall","_addCommand","connectCalled","previousState","needEvent","refresh","clientRefreshToken","client","_","unsubscribeError","ch","_isServerSub","_processServerSubs","ping","pong","subCtx","recovered","noPing","wasRecovering","hasRecoveredPublications","was_recovering","streamPosition","callback","_handleUnsubscribe","_handleSubscribe","_handleDisconnect","tags","clientInfo","user","_handleMessage","errObject","WebSocketClient","setTokenRefreshCallback","getTokenCallback","userId","connectionToken","wsUrl","getWebSocketUrl","async","newToken","setupClientEventListeners","centrifugoUrl","apiUrl","host","subscribeToPersonalChannel","channelName","existingSub","personalSub","handleMessage","isTyping","actor","senderType","closedAt","updateToken","isConnected","getUserId","createElement","tag","attributes","children","element","entries","className","startsWith","setAttribute","child","appendChild","createTextNode","isValidUrl","parsed","origin","includes","parseMarkdown","text","div","textContent","innerHTML","escapeHtml","_match","linkText","safeUrl","sanitizeUrl","scrollToBottom","smooth","scrollTo","top","scrollHeight","behavior","generateId","Launcher","onClick","render","applyPositioning","button","chatIcon","createChatIcon","classList","closeIcon","createCloseIcon","unreadBadge","style","display","alignment","vPadding","verticalPadding","hPadding","horizontalPadding","bottom","left","right","zIndex","svg","createElementNS","path","polyline","setOpen","isOpen","toggle","setUnreadCount","show","hide","destroy","parentNode","removeChild","defaultStrings","headerTitle","headerSubtitle","inputPlaceholder","closedMessage","newConversation","csatTitle","csatSubtitle","csatPlaceholder","csatSubmit","csatThankYou","poweredBy","getStrings","clientOverrides","backendOverrides","MessageList","setQuickActionHandler","onQuickAction","setAgent","messagesContainer","autoScroll","threshold","scrollTop","clientHeight","isScrolledToBottom","addMessage","animate","updateMessage","messageEl","createMessageElement","oldId","lookupId","existingEl","newEl","replaceChild","updateMessageProgress","messageId","progressFill","querySelector","progressText","removeMessage","remove","isMyMessage","wrapper","avatar","avatarUrl","img","src","alt","createBotAvatarSvg","contentWrapper","bubble","isImage","attachment","category","imageContainer","loading","progressOverlay","createProgressOverlay","fileCard","createFileCard","link","rel","getFileIcon","quickActions","actionsContainer","action","label","meta","date","toLocaleTimeString","hour","minute","getStatusIcon","overlay","isUploading","card","iconWrapper","truncateFilename","details","cursor","icons","pdf","spreadsheet","presentation","video","audio","archive","image","maxLength","showTypingIndicator","hideTypingIndicator","indicator","getElementById","closedMessageElement","showClosedMessage","hideClosedMessage","displayMessage","ChatWindow","strings","messageList","setStrings","backendStrings","updateUIStrings","headerSubtitleElement","inputElement","placeholder","header","createHeader","messagesArea","inputWrapper","createInputArea","applyTheme","logoElement","createCompanyLogoSvg","titleSection","brandNameElement","closeButton","inputArea","fileButton","fileInput","accept","accepts","generateAcceptAttribute","files","onFileUpload","click","rows","updateSendButtonState","shiftKey","preventDefault","handleSend","sendButton","disabled","footer","onSendMessage","focus","theme","cleanupThemeListener","themeMediaQuery","matchMedia","prefersDark","matches","themeChangeHandler","clearMessages","isVisible","isWindowVisible","focusInput","setTicketClosed","onStartNewChat","showHistory","skipCSAT","csatSubmitted","showNewChatUI","showCSATForm","removeCSATContainer","closedFooter","csatRating","csatContainer","subtitle","starsContainer","star","createStarSvg","selectRating","previewRating","feedbackInput","submitButton","csatSubmitting","onCSATSubmit","showCSATThankYou","skipButton","icon","newChatButton","container","updateStars","querySelectorAll","filled","_CevroMessenger","onDurationMs","offDurationMs","normalizeConfig","api","ws","setupEventHandlers","instance","getInstance","stopTypingCycle","chatWindow","startTypingCycle","startNewChat","boot","isBooted","hideDefaultLauncher","launcher","customLauncherSelector","customLauncher","handleQuickAction","handleFileUpload","storedSession","stored","getStoredSession","connectWebSocket","connectingPromise","doConnectWebSocket","storedVisitorToken","shutdown","removeItem","clearStoredSession","clearVisitorData","clearStoredVisitorToken","isSessionInitialized","isInitializingSession","update","playerData","hadPlayerId","initializeSession","forceNew","initPromise","doInitializeSession","finally","storeSession","mergedStrings","messageCount","MAX_MESSAGE_LENGTH","optimisticMessage","tempId","_h","_i","_j","_k","showNewMessage","prefilledText","localPreviewUrl","fileCategory","getFileCategory","createObjectURL","serverHasMediaUrl","updatedMessage","revokeObjectURL","fileName","errorMessage","isValidationError","getUnreadCount","getVisitorId","trackEvent","eventName","metadata","runCycle","isTypingVisible","typingCycleTimeout","CevroMessenger"],"mappings":"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","x_google_ignoreList":[4]}
|