@sygnl/talon 1.0.1 → 1.0.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/TalonClient.ts"],"names":[],"mappings":";;;AAoCO,IAAM,cAAN,MAAkB;AAAA,EAQvB,YAAY,OAAA,EAA6B;AACvC,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AACzB,IAAA,IAAA,CAAK,aAAA,uBAAoB,GAAA,EAAI;AAC7B,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAQ,KAAA,IAAS,KAAA;AAG9B,IAAA,IAAA,CAAK,kBAAA,GAAqB,KAAK,SAAA,CAAU,SAAA,CAAU,KAAK,aAAA,CAAc,IAAA,CAAK,IAAI,CAAC,CAAA;AAChF,IAAA,IAAA,CAAK,gBAAA,GAAmB,KAAK,SAAA,CAAU,aAAA,CAAc,KAAK,iBAAA,CAAkB,IAAA,CAAK,IAAI,CAAC,CAAA;AACtF,IAAA,IAAA,CAAK,gBAAA,GAAmB,KAAK,SAAA,CAAU,OAAA,CAAQ,KAAK,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA;AAG1E,IAAA,IAAI,OAAA,CAAQ,gBAAgB,KAAA,EAAO;AACjC,MAAA,IAAA,CAAK,OAAA,EAAQ,CAAE,KAAA,CAAM,CAAC,KAAA,KAAU;AAC9B,QAAA,IAAA,CAAK,GAAA,CAAI,wBAAwB,KAAK,CAAA;AAAA,MACxC,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAA,GAAyB;AACpC,IAAA,OAAO,IAAA,CAAK,UAAU,OAAA,EAAQ;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKO,UAAA,GAAmB;AACxB,IAAA,IAAA,CAAK,UAAU,UAAA,EAAW;AAC1B,IAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAa,KAAK,KAAA,EAA+C;AAC/D,IAAA,MAAM,OAAA,GAA2B;AAAA,MAC/B,IAAA,EAAM,OAAA;AAAA,MACN,IAAA,EAAM,KAAA;AAAA,MACN,EAAA,EAAI,KAAK,UAAA,EAAW;AAAA,MACpB,SAAA,EAAW,KAAK,GAAA;AAAI,KACtB;AAEA,IAAA,IAAA,CAAK,GAAA,CAAI,oBAAoB,OAAO,CAAA;AACpC,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBO,EAAA,CAAY,WAAmB,OAAA,EAAsC;AAC1E,IAAA,IAAI,CAAC,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,SAAS,CAAA,EAAG;AACtC,MAAA,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,SAAA,kBAAW,IAAI,KAAK,CAAA;AAAA,IAC7C;AAEA,IAAA,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,SAAS,CAAA,CAAG,IAAI,OAAO,CAAA;AAC9C,IAAA,IAAA,CAAK,GAAA,CAAI,CAAA,qBAAA,EAAwB,SAAS,CAAA,CAAE,CAAA;AAG5C,IAAA,OAAO,MAAM;AACX,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,SAAS,CAAA;AACjD,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,QAAA,CAAS,OAAO,OAAO,CAAA;AACvB,QAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACvB,UAAA,IAAA,CAAK,aAAA,CAAc,OAAO,SAAS,CAAA;AAAA,QACrC;AAAA,MACF;AACA,MAAA,IAAA,CAAK,GAAA,CAAI,CAAA,yBAAA,EAA4B,SAAS,CAAA,CAAE,CAAA;AAAA,IAClD,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,IAAA,CAAc,WAAmB,OAAA,EAAsC;AAC5E,IAAA,MAAM,cAAA,GAAiB,CAAC,IAAA,KAAY;AAClC,MAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,MAAA,WAAA,EAAY;AAAA,IACd,CAAA;AAEA,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,EAAA,CAAG,SAAA,EAAW,cAAc,CAAA;AACrD,IAAA,OAAO,WAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,IAAI,SAAA,EAAyB;AAClC,IAAA,IAAA,CAAK,aAAA,CAAc,OAAO,SAAS,CAAA;AACnC,IAAA,IAAA,CAAK,GAAA,CAAI,CAAA,0BAAA,EAA6B,SAAS,CAAA,CAAE,CAAA;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,KAAA,GAAwB;AACjC,IAAA,OAAO,KAAK,SAAA,CAAU,KAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,SAAA,GAAqB;AAC9B,IAAA,OAAO,IAAA,CAAK,UAAU,KAAA,KAAU,WAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,OAAA,EAA+B;AACnD,IAAA,IAAA,CAAK,GAAA,CAAI,qBAAqB,OAAO,CAAA;AAErC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,QAAQ,IAAI,CAAA;AACpD,IAAA,IAAI,QAAA,IAAY,QAAA,CAAS,IAAA,GAAO,CAAA,EAAG;AACjC,MAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC5B,QAAA,IAAI;AACF,UAAA,OAAA,CAAQ,QAAQ,IAAI,CAAA;AAAA,QACtB,SAAS,KAAA,EAAO;AACd,UAAA,IAAA,CAAK,GAAA,CAAI,CAAA,qBAAA,EAAwB,OAAA,CAAQ,IAAI,KAAK,KAAK,CAAA;AAAA,QACzD;AAAA,MACF,CAAC,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,GAAA,CAAI,CAAA,8BAAA,EAAiC,OAAA,CAAQ,IAAI,CAAA,CAAE,CAAA;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,KAAA,EAA6B;AACrD,IAAA,IAAA,CAAK,GAAA,CAAI,CAAA,eAAA,EAAkB,KAAK,CAAA,CAAE,CAAA;AAGlC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,eAAe,CAAA;AACvD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,QAAA,CAAS,QAAQ,CAAC,OAAA,KAAY,QAAQ,EAAE,KAAA,EAAO,CAAC,CAAA;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,KAAA,EAAoB;AACtC,IAAA,IAAA,CAAK,GAAA,CAAI,oBAAoB,KAAK,CAAA;AAGlC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,QAAQ,CAAA;AAChD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,QAAA,CAAS,QAAQ,CAAC,OAAA,KAAY,QAAQ,EAAE,KAAA,EAAO,CAAC,CAAA;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,OAAA,GAAgB;AACtB,IAAA,IAAA,CAAK,kBAAA,IAAqB;AAC1B,IAAA,IAAA,CAAK,gBAAA,IAAmB;AACxB,IAAA,IAAA,CAAK,gBAAA,IAAmB;AACxB,IAAA,IAAA,CAAK,cAAc,KAAA,EAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAA,GAAqB;AAC3B,IAAA,OAAO,CAAA,IAAA,EAAO,IAAA,CAAK,GAAA,EAAK,IAAI,IAAA,CAAK,MAAA,EAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,MAAA,CAAO,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKQ,GAAA,CAAI,SAAiB,IAAA,EAAsB;AACjD,IAAA,IAAI,IAAA,CAAK,KAAA,IAAS,OAAO,OAAA,KAAY,WAAA,EAAa;AAChD,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,cAAA,EAAiB,OAAO,CAAA,CAAA,EAAI,QAAQ,EAAE,CAAA;AAAA,IACpD;AAAA,EACF;AACF","file":"index.cjs","sourcesContent":["import type {\n TalonTransport,\n TalonClientOptions,\n OutboundMessage,\n InboundMessage,\n EventHandler,\n TransportState,\n} from './types';\n\n/**\n * TalonClient - Bidirectional event delivery client\n * \n * Features:\n * - Send events TO the edge\n * - Receive updates FROM the edge\n * - Transport-agnostic (WebSocket, Webhook, etc.)\n * - Event emitter pattern for edge responses\n * \n * @example\n * ```typescript\n * import { TalonClient } from '@sygnl/talon';\n * import { WebSocketTransport } from '@sygnl/talon/transports';\n * \n * const talon = new TalonClient({\n * transport: new WebSocketTransport('wss://edge.sygnl.io')\n * });\n * \n * // Send event TO edge\n * await talon.send({ event: 'add_to_cart', product_id: 'abc' });\n * \n * // Receive updates FROM edge\n * talon.on('attribution_updated', (data) => {\n * console.log('Attribution:', data);\n * });\n * ```\n */\nexport class TalonClient {\n private transport: TalonTransport;\n private eventHandlers: Map<string, Set<EventHandler>>;\n private messageUnsubscribe?: () => void;\n private stateUnsubscribe?: () => void;\n private errorUnsubscribe?: () => void;\n private debug: boolean;\n\n constructor(options: TalonClientOptions) {\n this.transport = options.transport;\n this.eventHandlers = new Map();\n this.debug = options.debug ?? false;\n\n // Subscribe to transport messages\n this.messageUnsubscribe = this.transport.onMessage(this.handleMessage.bind(this));\n this.stateUnsubscribe = this.transport.onStateChange(this.handleStateChange.bind(this));\n this.errorUnsubscribe = this.transport.onError(this.handleError.bind(this));\n\n // Auto-connect if requested\n if (options.autoConnect !== false) {\n this.connect().catch((error) => {\n this.log('Auto-connect failed:', error);\n });\n }\n }\n\n /**\n * Connect to the edge\n */\n public async connect(): Promise<void> {\n return this.transport.connect();\n }\n\n /**\n * Disconnect from the edge\n */\n public disconnect(): void {\n this.transport.disconnect();\n this.cleanup();\n }\n\n /**\n * Send event TO the edge\n * \n * @param event - Event data to send\n * @returns Promise that resolves when sent\n * \n * @example\n * ```typescript\n * await talon.send({\n * event: 'add_to_cart',\n * product_id: 'prod_123',\n * price: 99.99\n * });\n * ```\n */\n public async send(event: Record<string, unknown>): Promise<void> {\n const message: OutboundMessage = {\n type: 'event',\n data: event,\n id: this.generateId(),\n timestamp: Date.now(),\n };\n\n this.log('Sending message:', message);\n return this.transport.send(message);\n }\n\n /**\n * Subscribe to events FROM the edge\n * \n * @param eventType - Event type to listen for\n * @param handler - Function to call when event received\n * @returns Unsubscribe function\n * \n * @example\n * ```typescript\n * const unsubscribe = talon.on('attribution_updated', (data) => {\n * console.log('Attribution:', data);\n * });\n * \n * // Later: unsubscribe()\n * ```\n */\n public on<T = any>(eventType: string, handler: EventHandler<T>): () => void {\n if (!this.eventHandlers.has(eventType)) {\n this.eventHandlers.set(eventType, new Set());\n }\n\n this.eventHandlers.get(eventType)!.add(handler);\n this.log(`Subscribed to event: ${eventType}`);\n\n // Return unsubscribe function\n return () => {\n const handlers = this.eventHandlers.get(eventType);\n if (handlers) {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this.eventHandlers.delete(eventType);\n }\n }\n this.log(`Unsubscribed from event: ${eventType}`);\n };\n }\n\n /**\n * Subscribe to event once (auto-unsubscribe after first call)\n */\n public once<T = any>(eventType: string, handler: EventHandler<T>): () => void {\n const wrappedHandler = (data: T) => {\n handler(data);\n unsubscribe();\n };\n\n const unsubscribe = this.on(eventType, wrappedHandler);\n return unsubscribe;\n }\n\n /**\n * Remove all handlers for an event type\n */\n public off(eventType: string): void {\n this.eventHandlers.delete(eventType);\n this.log(`Removed all handlers for: ${eventType}`);\n }\n\n /**\n * Get current connection state\n */\n public get state(): TransportState {\n return this.transport.state;\n }\n\n /**\n * Check if connected\n */\n public get connected(): boolean {\n return this.transport.state === 'connected';\n }\n\n /**\n * Handle incoming message from transport\n */\n private handleMessage(message: InboundMessage): void {\n this.log('Received message:', message);\n\n const handlers = this.eventHandlers.get(message.type);\n if (handlers && handlers.size > 0) {\n handlers.forEach((handler) => {\n try {\n handler(message.data);\n } catch (error) {\n this.log(`Error in handler for ${message.type}:`, error);\n }\n });\n } else {\n this.log(`No handlers for message type: ${message.type}`);\n }\n }\n\n /**\n * Handle transport state change\n */\n private handleStateChange(state: TransportState): void {\n this.log(`State changed: ${state}`);\n \n // Emit state change event\n const handlers = this.eventHandlers.get('_state_change');\n if (handlers) {\n handlers.forEach((handler) => handler({ state }));\n }\n }\n\n /**\n * Handle transport error\n */\n private handleError(error: Error): void {\n this.log('Transport error:', error);\n \n // Emit error event\n const handlers = this.eventHandlers.get('_error');\n if (handlers) {\n handlers.forEach((handler) => handler({ error }));\n }\n }\n\n /**\n * Cleanup subscriptions\n */\n private cleanup(): void {\n this.messageUnsubscribe?.();\n this.stateUnsubscribe?.();\n this.errorUnsubscribe?.();\n this.eventHandlers.clear();\n }\n\n /**\n * Generate unique message ID\n */\n private generateId(): string {\n return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n /**\n * Debug logging\n */\n private log(message: string, data?: unknown): void {\n if (this.debug && typeof console !== 'undefined') {\n console.log(`[TalonClient] ${message}`, data || '');\n }\n }\n}\n"]} \n /** Auto-reconnect on disconnect */\n autoReconnect?: boolean;\n \n /** Reconnect delay in ms */\n reconnectDelay?: number;\n \n /** Max reconnect attempts (0 = infinite) */\n maxReconnectAttempts?: number;\n \n /** Connection timeout in ms */\n connectionTimeout?: number;\n \n /** Debug mode */\n debug?: boolean;\n}\n\n/**\n * WebSocket transport for bidirectional communication\n * \n * Features:\n * - Real-time bidirectional communication\n * - Auto-reconnect with exponential backoff\n * - Connection state management\n * - Message queuing during disconnection\n * \n * @example\n * ```typescript\n * const transport = new WebSocketTransport({\n * url: 'wss://edge.sygnl.io',\n * autoReconnect: true\n * });\n * ```\n */\nexport class WebSocketTransport implements TalonTransport {\n private url: string;\n private ws: WebSocket | null = null;\n private _state: TransportState = 'disconnected';\n private autoReconnect: boolean;\n private reconnectDelay: number;\n private maxReconnectAttempts: number;\n private reconnectAttempts = 0;\n private reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\n private connectionTimeout: number;\n private debug: boolean;\n \n private messageHandlers = new Set<(message: InboundMessage) => void>();\n private stateHandlers = new Set<(state: TransportState) => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n private messageQueue: OutboundMessage[] = [];\n\n constructor(options: WebSocketTransportOptions) {\n this.url = options.url;\n this.autoReconnect = options.autoReconnect ?? true;\n this.reconnectDelay = options.reconnectDelay ?? 1000;\n this.maxReconnectAttempts = options.maxReconnectAttempts ?? 0; // 0 = infinite\n this.connectionTimeout = options.connectionTimeout ?? 10000;\n this.debug = options.debug ?? false;\n }\n\n public get state(): TransportState {\n return this._state;\n }\n\n public async connect(): Promise<void> {\n if (this._state === 'connected' || this._state === 'connecting') {\n this.log('Already connected or connecting');\n return;\n }\n\n this.setState('connecting');\n this.log(`Connecting to ${this.url}`);\n\n return new Promise((resolve, reject) => {\n try {\n this.ws = new WebSocket(this.url);\n\n const timeout = setTimeout(() => {\n reject(new Error('Connection timeout'));\n this.ws?.close();\n }, this.connectionTimeout);\n\n this.ws.onopen = () => {\n clearTimeout(timeout);\n this.setState('connected');\n this.reconnectAttempts = 0;\n this.log('Connected');\n \n // Flush queued messages\n this.flushMessageQueue();\n \n resolve();\n };\n\n this.ws.onerror = () => {\n clearTimeout(timeout);\n const error = new Error('WebSocket connection error');\n this.log('Connection error:', error);\n this.emitError(error);\n reject(error);\n };\n\n this.ws.onclose = () => {\n clearTimeout(timeout);\n this.handleDisconnect();\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n } catch (error) {\n this.setState('error');\n const err = error instanceof Error ? error : new Error('Unknown error');\n this.emitError(err);\n reject(err);\n }\n });\n }\n\n public disconnect(): void {\n this.log('Disconnecting');\n this.autoReconnect = false; // Disable auto-reconnect on manual disconnect\n \n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n\n this.setState('disconnected');\n }\n\n public async send(message: OutboundMessage): Promise<void> {\n if (this._state !== 'connected' || !this.ws) {\n // Queue message if not connected\n this.log('Not connected, queueing message');\n this.messageQueue.push(message);\n return;\n }\n\n try {\n const payload = JSON.stringify(message);\n this.ws.send(payload);\n this.log('Sent message:', message);\n } catch (error) {\n const err = error instanceof Error ? error : new Error('Send failed');\n this.log('Send error:', err);\n this.emitError(err);\n throw err;\n }\n }\n\n public onMessage(handler: (message: InboundMessage) => void): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n public onStateChange(handler: (state: TransportState) => void): () => void {\n this.stateHandlers.add(handler);\n return () => this.stateHandlers.delete(handler);\n }\n\n public onError(handler: (error: Error) => void): () => void {\n this.errorHandlers.add(handler);\n return () => this.errorHandlers.delete(handler);\n }\n\n /**\n * Handle incoming WebSocket message\n */\n private handleMessage(data: string): void {\n try {\n const message: InboundMessage = JSON.parse(data);\n this.log('Received message:', message);\n \n this.messageHandlers.forEach((handler) => {\n try {\n handler(message);\n } catch (error) {\n this.log('Handler error:', error);\n }\n });\n } catch (error) {\n this.log('Failed to parse message:', error);\n this.emitError(new Error('Invalid message format'));\n }\n }\n\n /**\n * Handle WebSocket disconnect\n */\n private handleDisconnect(): void {\n this.log('Disconnected');\n this.ws = null;\n\n if (this.autoReconnect && \n (this.maxReconnectAttempts === 0 || this.reconnectAttempts < this.maxReconnectAttempts)) {\n this.setState('reconnecting');\n this.scheduleReconnect();\n } else {\n this.setState('disconnected');\n }\n }\n\n /**\n * Schedule reconnection attempt with exponential backoff\n */\n private scheduleReconnect(): void {\n const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);\n this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts + 1})`);\n\n this.reconnectTimeout = setTimeout(() => {\n this.reconnectAttempts++;\n this.connect().catch((error) => {\n this.log('Reconnect failed:', error);\n this.handleDisconnect();\n });\n }, delay);\n }\n\n /**\n * Flush queued messages\n */\n private flushMessageQueue(): void {\n if (this.messageQueue.length === 0) {\n return;\n }\n\n this.log(`Flushing ${this.messageQueue.length} queued messages`);\n const queue = [...this.messageQueue];\n this.messageQueue = [];\n\n queue.forEach((message) => {\n this.send(message).catch((error) => {\n this.log('Failed to flush message:', error);\n });\n });\n }\n\n /**\n * Set connection state\n */\n private setState(state: TransportState): void {\n if (this._state === state) {\n return;\n }\n\n this._state = state;\n this.stateHandlers.forEach((handler) => {\n try {\n handler(state);\n } catch (error) {\n this.log('State handler error:', error);\n }\n });\n }\n\n /**\n * Emit error to handlers\n */\n private emitError(error: Error): void {\n this.errorHandlers.forEach((handler) => {\n try {\n handler(error);\n } catch (err) {\n this.log('Error handler error:', err);\n }\n });\n }\n\n /**\n * Debug logging\n */\n private log(message: string, data?: unknown): void {\n if (this.debug && typeof console !== 'undefined') {\n console.log(`[WebSocketTransport] ${message}`, data || '');\n }\n }\n}\n","import type {\n TalonTransport,\n OutboundMessage,\n InboundMessage,\n TransportState,\n} from '../types';\n\n/**\n * Webhook transport options\n */\nexport interface WebhookTransportOptions {\n /** Webhook URL */\n url: string;\n \n /** HTTP method */\n method?: 'POST' | 'PUT';\n \n /** Custom headers */\n headers?: Record<string, string>;\n \n /** Request timeout in ms */\n timeout?: number;\n \n /** Retry failed requests */\n retry?: boolean;\n \n /** Max retry attempts */\n maxRetries?: number;\n \n /** Retry delay in ms */\n retryDelay?: number;\n \n /** Debug mode */\n debug?: boolean;\n}\n\n/**\n * Webhook transport for fire-and-forget HTTP requests\n * \n * Features:\n * - One-way communication (no responses)\n * - HTTP POST/PUT requests\n * - Optional retry logic\n * - Custom headers support\n * \n * Use this for:\n * - Server-side event delivery\n * - Fire-and-forget scenarios\n * - When WebSocket not available/needed\n * \n * @example\n * ```typescript\n * const transport = new WebhookTransport({\n * url: 'https://edge.sygnl.io/webhook',\n * method: 'POST',\n * retry: true\n * });\n * ```\n */\nexport class WebhookTransport implements TalonTransport {\n private url: string;\n private method: 'POST' | 'PUT';\n private headers: Record<string, string>;\n private timeout: number;\n private retry: boolean;\n private maxRetries: number;\n private retryDelay: number;\n private debug: boolean;\n private _state: TransportState = 'disconnected';\n \n private messageHandlers = new Set<(message: InboundMessage) => void>();\n private stateHandlers = new Set<(state: TransportState) => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n\n constructor(options: WebhookTransportOptions) {\n this.url = options.url;\n this.method = options.method ?? 'POST';\n this.headers = {\n 'Content-Type': 'application/json',\n ...options.headers,\n };\n this.timeout = options.timeout ?? 10000;\n this.retry = options.retry ?? false;\n this.maxRetries = options.maxRetries ?? 3;\n this.retryDelay = options.retryDelay ?? 1000;\n this.debug = options.debug ?? false;\n }\n\n public get state(): TransportState {\n return this._state;\n }\n\n public async connect(): Promise<void> {\n // Webhook is \"connected\" immediately (stateless)\n this.log('Webhook transport ready');\n this.setState('connected');\n }\n\n public disconnect(): void {\n this.log('Disconnecting webhook transport');\n this.setState('disconnected');\n }\n\n public async send(message: OutboundMessage): Promise<void> {\n if (this._state !== 'connected') {\n throw new Error('Transport not connected');\n }\n\n let lastError: Error | null = null;\n const attempts = this.retry ? this.maxRetries + 1 : 1;\n\n for (let attempt = 0; attempt < attempts; attempt++) {\n try {\n await this.sendRequest(message);\n this.log(`Sent message (attempt ${attempt + 1})`);\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error('Send failed');\n this.log(`Send failed (attempt ${attempt + 1}):`, lastError);\n\n if (attempt < attempts - 1) {\n // Wait before retry (exponential backoff)\n const delay = this.retryDelay * Math.pow(2, attempt);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n\n // All attempts failed\n if (lastError) {\n this.emitError(lastError);\n throw lastError;\n }\n }\n\n public onMessage(handler: (message: InboundMessage) => void): () => void {\n // Webhook is one-way, but keep interface consistent\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n public onStateChange(handler: (state: TransportState) => void): () => void {\n this.stateHandlers.add(handler);\n return () => this.stateHandlers.delete(handler);\n }\n\n public onError(handler: (error: Error) => void): () => void {\n this.errorHandlers.add(handler);\n return () => this.errorHandlers.delete(handler);\n }\n\n /**\n * Send HTTP request\n */\n private async sendRequest(message: OutboundMessage): Promise<void> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(this.url, {\n method: this.method,\n headers: this.headers,\n body: JSON.stringify(message),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n this.log(`Request successful: ${response.status}`);\n } catch (error) {\n clearTimeout(timeoutId);\n \n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new Error('Request timeout');\n }\n throw error;\n }\n \n throw new Error('Request failed');\n }\n }\n\n /**\n * Set connection state\n */\n private setState(state: TransportState): void {\n if (this._state === state) {\n return;\n }\n\n this._state = state;\n this.stateHandlers.forEach((handler) => {\n try {\n handler(state);\n } catch (error) {\n this.log('State handler error:', error);\n }\n });\n }\n\n /**\n * Emit error to handlers\n */\n private emitError(error: Error): void {\n this.errorHandlers.forEach((handler) => {\n try {\n handler(error);\n } catch (err) {\n this.log('Error handler error:', err);\n }\n });\n }\n\n /**\n * Debug logging\n */\n private log(message: string, data?: unknown): void {\n if (this.debug && typeof console !== 'undefined') {\n console.log(`[WebhookTransport] ${message}`, data || '');\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/transports/WebSocketTransport.ts","../src/transports/WebhookTransport.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n TalonTransport,\n OutboundMessage,\n InboundMessage,\n TransportState,\n} from '../types';\n\n/**\n * WebSocket transport options\n */\nexport interface WebSocketTransportOptions {\n /** WebSocket URL */\n url: string;\n \n /** Auto-reconnect on disconnect */\n autoReconnect?: boolean;\n \n /** Reconnect delay in ms */\n reconnectDelay?: number;\n \n /** Max reconnect attempts (0 = infinite) */\n maxReconnectAttempts?: number;\n \n /** Connection timeout in ms */\n connectionTimeout?: number;\n \n /** Debug mode */\n debug?: boolean;\n}\n\n/**\n * WebSocket transport for bidirectional communication\n * \n * Features:\n * - Real-time bidirectional communication\n * - Auto-reconnect with exponential backoff\n * - Connection state management\n * - Message queuing during disconnection\n * \n * @example\n * ```typescript\n * const transport = new WebSocketTransport({\n * url: 'wss://edge.sygnl.io',\n * autoReconnect: true\n * });\n * ```\n */\nexport class WebSocketTransport implements TalonTransport {\n private url: string;\n private ws: WebSocket | null = null;\n private _state: TransportState = 'disconnected';\n private autoReconnect: boolean;\n private reconnectDelay: number;\n private maxReconnectAttempts: number;\n private reconnectAttempts = 0;\n private reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\n private connectionTimeout: number;\n private debug: boolean;\n \n private messageHandlers = new Set<(message: InboundMessage) => void>();\n private stateHandlers = new Set<(state: TransportState) => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n private messageQueue: OutboundMessage[] = [];\n\n constructor(options: WebSocketTransportOptions) {\n this.url = options.url;\n this.autoReconnect = options.autoReconnect ?? true;\n this.reconnectDelay = options.reconnectDelay ?? 1000;\n this.maxReconnectAttempts = options.maxReconnectAttempts ?? 0; // 0 = infinite\n this.connectionTimeout = options.connectionTimeout ?? 10000;\n this.debug = options.debug ?? false;\n }\n\n public get state(): TransportState {\n return this._state;\n }\n\n public async connect(): Promise<void> {\n if (this._state === 'connected' || this._state === 'connecting') {\n this.log('Already connected or connecting');\n return;\n }\n\n this.setState('connecting');\n this.log(`Connecting to ${this.url}`);\n\n return new Promise((resolve, reject) => {\n try {\n this.ws = new WebSocket(this.url);\n\n const timeout = setTimeout(() => {\n reject(new Error('Connection timeout'));\n this.ws?.close();\n }, this.connectionTimeout);\n\n this.ws.onopen = () => {\n clearTimeout(timeout);\n this.setState('connected');\n this.reconnectAttempts = 0;\n this.log('Connected');\n \n // Flush queued messages\n this.flushMessageQueue();\n \n resolve();\n };\n\n this.ws.onerror = () => {\n clearTimeout(timeout);\n const error = new Error('WebSocket connection error');\n this.log('Connection error:', error);\n this.emitError(error);\n reject(error);\n };\n\n this.ws.onclose = () => {\n clearTimeout(timeout);\n this.handleDisconnect();\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n } catch (error) {\n this.setState('error');\n const err = error instanceof Error ? error : new Error('Unknown error');\n this.emitError(err);\n reject(err);\n }\n });\n }\n\n public disconnect(): void {\n this.log('Disconnecting');\n this.autoReconnect = false; // Disable auto-reconnect on manual disconnect\n \n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n\n this.setState('disconnected');\n }\n\n public async send(message: OutboundMessage): Promise<void> {\n if (this._state !== 'connected' || !this.ws) {\n // Queue message if not connected\n this.log('Not connected, queueing message');\n this.messageQueue.push(message);\n return;\n }\n\n try {\n const payload = JSON.stringify(message);\n this.ws.send(payload);\n this.log('Sent message:', message);\n } catch (error) {\n const err = error instanceof Error ? error : new Error('Send failed');\n this.log('Send error:', err);\n this.emitError(err);\n throw err;\n }\n }\n\n public onMessage(handler: (message: InboundMessage) => void): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n public onStateChange(handler: (state: TransportState) => void): () => void {\n this.stateHandlers.add(handler);\n return () => this.stateHandlers.delete(handler);\n }\n\n public onError(handler: (error: Error) => void): () => void {\n this.errorHandlers.add(handler);\n return () => this.errorHandlers.delete(handler);\n }\n\n /**\n * Handle incoming WebSocket message\n */\n private handleMessage(data: string): void {\n try {\n const message: InboundMessage = JSON.parse(data);\n this.log('Received message:', message);\n \n this.messageHandlers.forEach((handler) => {\n try {\n handler(message);\n } catch (error) {\n this.log('Handler error:', error);\n }\n });\n } catch (error) {\n this.log('Failed to parse message:', error);\n this.emitError(new Error('Invalid message format'));\n }\n }\n\n /**\n * Handle WebSocket disconnect\n */\n private handleDisconnect(): void {\n this.log('Disconnected');\n this.ws = null;\n\n if (this.autoReconnect && \n (this.maxReconnectAttempts === 0 || this.reconnectAttempts < this.maxReconnectAttempts)) {\n this.setState('reconnecting');\n this.scheduleReconnect();\n } else {\n this.setState('disconnected');\n }\n }\n\n /**\n * Schedule reconnection attempt with exponential backoff\n */\n private scheduleReconnect(): void {\n const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);\n this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts + 1})`);\n\n this.reconnectTimeout = setTimeout(() => {\n this.reconnectAttempts++;\n this.connect().catch((error) => {\n this.log('Reconnect failed:', error);\n this.handleDisconnect();\n });\n }, delay);\n }\n\n /**\n * Flush queued messages\n */\n private flushMessageQueue(): void {\n if (this.messageQueue.length === 0) {\n return;\n }\n\n this.log(`Flushing ${this.messageQueue.length} queued messages`);\n const queue = [...this.messageQueue];\n this.messageQueue = [];\n\n queue.forEach((message) => {\n this.send(message).catch((error) => {\n this.log('Failed to flush message:', error);\n });\n });\n }\n\n /**\n * Set connection state\n */\n private setState(state: TransportState): void {\n if (this._state === state) {\n return;\n }\n\n this._state = state;\n this.stateHandlers.forEach((handler) => {\n try {\n handler(state);\n } catch (error) {\n this.log('State handler error:', error);\n }\n });\n }\n\n /**\n * Emit error to handlers\n */\n private emitError(error: Error): void {\n this.errorHandlers.forEach((handler) => {\n try {\n handler(error);\n } catch (err) {\n this.log('Error handler error:', err);\n }\n });\n }\n\n /**\n * Debug logging\n */\n private log(message: string, data?: unknown): void {\n if (this.debug && typeof console !== 'undefined') {\n console.log(`[WebSocketTransport] ${message}`, data || '');\n }\n }\n}\n","import type {\n TalonTransport,\n OutboundMessage,\n InboundMessage,\n TransportState,\n} from '../types';\n\n/**\n * Webhook transport options\n */\nexport interface WebhookTransportOptions {\n /** Webhook URL */\n url: string;\n \n /** HTTP method */\n method?: 'POST' | 'PUT';\n \n /** Custom headers */\n headers?: Record<string, string>;\n \n /** Request timeout in ms */\n timeout?: number;\n \n /** Retry failed requests */\n retry?: boolean;\n \n /** Max retry attempts */\n maxRetries?: number;\n \n /** Retry delay in ms */\n retryDelay?: number;\n \n /** Debug mode */\n debug?: boolean;\n}\n\n/**\n * Webhook transport for fire-and-forget HTTP requests\n * \n * Features:\n * - One-way communication (no responses)\n * - HTTP POST/PUT requests\n * - Optional retry logic\n * - Custom headers support\n * \n * Use this for:\n * - Server-side event delivery\n * - Fire-and-forget scenarios\n * - When WebSocket not available/needed\n * \n * @example\n * ```typescript\n * const transport = new WebhookTransport({\n * url: 'https://edge.sygnl.io/webhook',\n * method: 'POST',\n * retry: true\n * });\n * ```\n */\nexport class WebhookTransport implements TalonTransport {\n private url: string;\n private method: 'POST' | 'PUT';\n private headers: Record<string, string>;\n private timeout: number;\n private retry: boolean;\n private maxRetries: number;\n private retryDelay: number;\n private debug: boolean;\n private _state: TransportState = 'disconnected';\n \n private messageHandlers = new Set<(message: InboundMessage) => void>();\n private stateHandlers = new Set<(state: TransportState) => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n\n constructor(options: WebhookTransportOptions) {\n this.url = options.url;\n this.method = options.method ?? 'POST';\n this.headers = {\n 'Content-Type': 'application/json',\n ...options.headers,\n };\n this.timeout = options.timeout ?? 10000;\n this.retry = options.retry ?? false;\n this.maxRetries = options.maxRetries ?? 3;\n this.retryDelay = options.retryDelay ?? 1000;\n this.debug = options.debug ?? false;\n }\n\n public get state(): TransportState {\n return this._state;\n }\n\n public async connect(): Promise<void> {\n // Webhook is \"connected\" immediately (stateless)\n this.log('Webhook transport ready');\n this.setState('connected');\n }\n\n public disconnect(): void {\n this.log('Disconnecting webhook transport');\n this.setState('disconnected');\n }\n\n public async send(message: OutboundMessage): Promise<void> {\n if (this._state !== 'connected') {\n throw new Error('Transport not connected');\n }\n\n let lastError: Error | null = null;\n const attempts = this.retry ? this.maxRetries + 1 : 1;\n\n for (let attempt = 0; attempt < attempts; attempt++) {\n try {\n await this.sendRequest(message);\n this.log(`Sent message (attempt ${attempt + 1})`);\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error('Send failed');\n this.log(`Send failed (attempt ${attempt + 1}):`, lastError);\n\n if (attempt < attempts - 1) {\n // Wait before retry (exponential backoff)\n const delay = this.retryDelay * Math.pow(2, attempt);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n\n // All attempts failed\n if (lastError) {\n this.emitError(lastError);\n throw lastError;\n }\n }\n\n public onMessage(handler: (message: InboundMessage) => void): () => void {\n // Webhook is one-way, but keep interface consistent\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n public onStateChange(handler: (state: TransportState) => void): () => void {\n this.stateHandlers.add(handler);\n return () => this.stateHandlers.delete(handler);\n }\n\n public onError(handler: (error: Error) => void): () => void {\n this.errorHandlers.add(handler);\n return () => this.errorHandlers.delete(handler);\n }\n\n /**\n * Send HTTP request\n */\n private async sendRequest(message: OutboundMessage): Promise<void> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(this.url, {\n method: this.method,\n headers: this.headers,\n body: JSON.stringify(message),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n this.log(`Request successful: ${response.status}`);\n } catch (error) {\n clearTimeout(timeoutId);\n \n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new Error('Request timeout');\n }\n throw error;\n }\n \n throw new Error('Request failed');\n }\n }\n\n /**\n * Set connection state\n */\n private setState(state: TransportState): void {\n if (this._state === state) {\n return;\n }\n\n this._state = state;\n this.stateHandlers.forEach((handler) => {\n try {\n handler(state);\n } catch (error) {\n this.log('State handler error:', error);\n }\n });\n }\n\n /**\n * Emit error to handlers\n */\n private emitError(error: Error): void {\n this.errorHandlers.forEach((handler) => {\n try {\n handler(error);\n } catch (err) {\n this.log('Error handler error:', err);\n }\n });\n }\n\n /**\n * Debug logging\n */\n private log(message: string, data?: unknown): void {\n if (this.debug && typeof console !== 'undefined') {\n console.log(`[WebhookTransport] ${message}`, data || '');\n }\n }\n}\n"]}
package/dist/index.js CHANGED
@@ -1,152 +1,185 @@
1
- // src/transports/WebSocketTransport.ts
2
- var WebSocketTransport = class {
1
+ // src/TalonClient.ts
2
+ var TalonClient = class {
3
3
  constructor(options) {
4
- this.ws = null;
5
- this._state = "disconnected";
6
- this.reconnectAttempts = 0;
7
- this.reconnectTimeout = null;
8
- this.messageHandlers = /* @__PURE__ */ new Set();
9
- this.stateHandlers = /* @__PURE__ */ new Set();
10
- this.errorHandlers = /* @__PURE__ */ new Set();
11
- this.messageQueue = [];
12
- this.url = options.url;
13
- this.autoReconnect = options.autoReconnect ?? true;
14
- this.reconnectDelay = options.reconnectDelay ?? 1e3;
15
- this.maxReconnectAttempts = options.maxReconnectAttempts ?? 0;
16
- this.connectionTimeout = options.connectionTimeout ?? 1e4;
4
+ this.transport = options.transport;
5
+ this.eventHandlers = /* @__PURE__ */ new Map();
17
6
  this.debug = options.debug ?? false;
7
+ this.messageUnsubscribe = this.transport.onMessage(this.handleMessage.bind(this));
8
+ this.stateUnsubscribe = this.transport.onStateChange(this.handleStateChange.bind(this));
9
+ this.errorUnsubscribe = this.transport.onError(this.handleError.bind(this));
10
+ if (options.autoConnect !== false) {
11
+ this.connect().catch((error) => {
12
+ this.log("Auto-connect failed:", error);
13
+ });
14
+ }
18
15
  }
19
- get state() {
20
- return this._state;
21
- }
16
+ /**
17
+ * Connect to the edge
18
+ */
22
19
  async connect() {
23
- if (this._state === "connected" || this._state === "connecting") {
24
- this.log("Already connected or connecting");
25
- return;
26
- }
27
- this.setState("connecting");
28
- this.log(`Connecting to ${this.url}`);
29
- return new Promise((resolve, reject) => {
30
- try {
31
- this.ws = new WebSocket(this.url);
32
- const timeout = setTimeout(() => {
33
- reject(new Error("Connection timeout"));
34
- this.ws?.close();
35
- }, this.connectionTimeout);
36
- this.ws.onopen = () => {
37
- clearTimeout(timeout);
38
- this.setState("connected");
39
- this.reconnectAttempts = 0;
40
- this.log("Connected");
41
- this.flushMessageQueue();
42
- resolve();
43
- };
44
- this.ws.onerror = () => {
45
- clearTimeout(timeout);
46
- const error = new Error("WebSocket connection error");
47
- this.log("Connection error:", error);
48
- this.emitError(error);
49
- reject(error);
50
- };
51
- this.ws.onclose = () => {
52
- clearTimeout(timeout);
53
- this.handleDisconnect();
54
- };
55
- this.ws.onmessage = (event) => {
56
- this.handleMessage(event.data);
57
- };
58
- } catch (error) {
59
- this.setState("error");
60
- const err = error instanceof Error ? error : new Error("Unknown error");
61
- this.emitError(err);
62
- reject(err);
63
- }
64
- });
20
+ return this.transport.connect();
65
21
  }
22
+ /**
23
+ * Disconnect from the edge
24
+ */
66
25
  disconnect() {
67
- this.log("Disconnecting");
68
- this.autoReconnect = false;
69
- if (this.reconnectTimeout) {
70
- clearTimeout(this.reconnectTimeout);
71
- this.reconnectTimeout = null;
72
- }
73
- if (this.ws) {
74
- this.ws.close();
75
- this.ws = null;
76
- }
77
- this.setState("disconnected");
26
+ this.transport.disconnect();
27
+ this.cleanup();
78
28
  }
79
- async send(message) {
80
- if (this._state !== "connected" || !this.ws) {
81
- this.log("Not connected, queueing message");
82
- this.messageQueue.push(message);
83
- return;
84
- }
85
- try {
86
- const payload = JSON.stringify(message);
87
- this.ws.send(payload);
88
- this.log("Sent message:", message);
89
- } catch (error) {
90
- const err = error instanceof Error ? error : new Error("Send failed");
91
- this.log("Send error:", err);
92
- this.emitError(err);
93
- throw err;
29
+ /**
30
+ * Send event TO the edge
31
+ *
32
+ * @param event - Event data to send
33
+ * @returns Promise that resolves when sent
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * await talon.send({
38
+ * event: 'add_to_cart',
39
+ * product_id: 'prod_123',
40
+ * price: 99.99
41
+ * });
42
+ * ```
43
+ */
44
+ async send(event) {
45
+ const message = {
46
+ type: "event",
47
+ data: event,
48
+ id: this.generateId(),
49
+ timestamp: Date.now()
50
+ };
51
+ this.log("Sending message:", message);
52
+ return this.transport.send(message);
53
+ }
54
+ /**
55
+ * Subscribe to events FROM the edge
56
+ *
57
+ * @param eventType - Event type to listen for
58
+ * @param handler - Function to call when event received
59
+ * @returns Unsubscribe function
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * const unsubscribe = talon.on('attribution_updated', (data) => {
64
+ * console.log('Attribution:', data);
65
+ * });
66
+ *
67
+ * // Later: unsubscribe()
68
+ * ```
69
+ */
70
+ on(eventType, handler) {
71
+ if (!this.eventHandlers.has(eventType)) {
72
+ this.eventHandlers.set(eventType, /* @__PURE__ */ new Set());
94
73
  }
74
+ this.eventHandlers.get(eventType).add(handler);
75
+ this.log(`Subscribed to event: ${eventType}`);
76
+ return () => {
77
+ const handlers = this.eventHandlers.get(eventType);
78
+ if (handlers) {
79
+ handlers.delete(handler);
80
+ if (handlers.size === 0) {
81
+ this.eventHandlers.delete(eventType);
82
+ }
83
+ }
84
+ this.log(`Unsubscribed from event: ${eventType}`);
85
+ };
95
86
  }
96
- onMessage(handler) {
97
- this.messageHandlers.add(handler);
98
- return () => this.messageHandlers.delete(handler);
87
+ /**
88
+ * Subscribe to event once (auto-unsubscribe after first call)
89
+ */
90
+ once(eventType, handler) {
91
+ const wrappedHandler = (data) => {
92
+ handler(data);
93
+ unsubscribe();
94
+ };
95
+ const unsubscribe = this.on(eventType, wrappedHandler);
96
+ return unsubscribe;
99
97
  }
100
- onStateChange(handler) {
101
- this.stateHandlers.add(handler);
102
- return () => this.stateHandlers.delete(handler);
98
+ /**
99
+ * Remove all handlers for an event type
100
+ */
101
+ off(eventType) {
102
+ this.eventHandlers.delete(eventType);
103
+ this.log(`Removed all handlers for: ${eventType}`);
103
104
  }
104
- onError(handler) {
105
- this.errorHandlers.add(handler);
106
- return () => this.errorHandlers.delete(handler);
105
+ /**
106
+ * Get current connection state
107
+ */
108
+ get state() {
109
+ return this.transport.state;
107
110
  }
108
111
  /**
109
- * Handle incoming WebSocket message
112
+ * Check if connected
110
113
  */
111
- handleMessage(data) {
112
- try {
113
- const message = JSON.parse(data);
114
- this.log("Received message:", message);
115
- this.messageHandlers.forEach((handler) => {
114
+ get connected() {
115
+ return this.transport.state === "connected";
116
+ }
117
+ /**
118
+ * Handle incoming message from transport
119
+ */
120
+ handleMessage(message) {
121
+ this.log("Received message:", message);
122
+ const handlers = this.eventHandlers.get(message.type);
123
+ if (handlers && handlers.size > 0) {
124
+ handlers.forEach((handler) => {
116
125
  try {
117
- handler(message);
126
+ handler(message.data);
118
127
  } catch (error) {
119
- this.log("Handler error:", error);
128
+ this.log(`Error in handler for ${message.type}:`, error);
120
129
  }
121
130
  });
122
- } catch (error) {
123
- this.log("Failed to parse message:", error);
124
- this.emitError(new Error("Invalid message format"));
131
+ } else {
132
+ this.log(`No handlers for message type: ${message.type}`);
125
133
  }
126
134
  }
127
135
  /**
128
- * Handle WebSocket disconnect
136
+ * Handle transport state change
129
137
  */
130
- handleDisconnect() {
131
- this.log("Disconnected");
132
- this.ws = null;
133
- if (this.autoReconnect && (this.maxReconnectAttempts === 0 || this.reconnectAttempts < this.maxReconnectAttempts)) {
134
- this.setState("reconnecting");
135
- this.scheduleReconnect();
136
- } else {
137
- this.setState("disconnected");
138
+ handleStateChange(state) {
139
+ this.log(`State changed: ${state}`);
140
+ const handlers = this.eventHandlers.get("_state_change");
141
+ if (handlers) {
142
+ handlers.forEach((handler) => handler({ state }));
138
143
  }
139
144
  }
140
145
  /**
141
- * Schedule reconnection attempt with exponential backoff
146
+ * Handle transport error
142
147
  */
143
- scheduleReconnect() {
144
- const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);
145
- this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts + 1})`);
146
- this.reconnectTimeout = setTimeout(() => {
147
- this.reconnectAttempts++;
148
- this.connect().catch((error) => {
149
- this.log("Reconnect failed:", error);
148
+ handleError(error) {
149
+ this.log("Transport error:", error);
150
+ const handlers = this.eventHandlers.get("_error");
151
+ if (handlers) {
152
+ handlers.forEach((handler) => handler({ error }));
153
+ }
154
+ }
155
+ /**
156
+ * Cleanup subscriptions
157
+ */
158
+ cleanup() {
159
+ this.messageUnsubscribe?.();
160
+ this.stateUnsubscribe?.();
161
+ this.errorUnsubscribe?.();
162
+ this.eventHandlers.clear();
163
+ }
164
+ /**
165
+ * Generate unique message ID
166
+ */
167
+ generateId() {
168
+ return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
169
+ }
170
+ /**
171
+ * Debug logging
172
+ */
173
+ log(message, data) {
174
+ if (this.debug && typeof console !== "undefined") {
175
+ console.log(`[TalonClient] ${message}`, data || "");
176
+ }
177
+ }
178
+ };
179
+
180
+ export { TalonClient };
181
+ //# sourceMappingURL=index.js.map
182
+ //# sourceMappingURL=index.js.mapled:", error);
150
183
  this.handleDisconnect();
151
184
  });
152
185
  }, delay);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transports/WebSocketTransport.ts","../src/transports/WebhookTransport.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n TalonTransport,\n OutboundMessage,\n InboundMessage,\n TransportState,\n} from '../types';\n\n/**\n * WebSocket transport options\n */\nexport interface WebSocketTransportOptions {\n /** WebSocket URL */\n url: string;\n \n /** Auto-reconnect on disconnect */\n autoReconnect?: boolean;\n \n /** Reconnect delay in ms */\n reconnectDelay?: number;\n \n /** Max reconnect attempts (0 = infinite) */\n maxReconnectAttempts?: number;\n \n /** Connection timeout in ms */\n connectionTimeout?: number;\n \n /** Debug mode */\n debug?: boolean;\n}\n\n/**\n * WebSocket transport for bidirectional communication\n * \n * Features:\n * - Real-time bidirectional communication\n * - Auto-reconnect with exponential backoff\n * - Connection state management\n * - Message queuing during disconnection\n * \n * @example\n * ```typescript\n * const transport = new WebSocketTransport({\n * url: 'wss://edge.sygnl.io',\n * autoReconnect: true\n * });\n * ```\n */\nexport class WebSocketTransport implements TalonTransport {\n private url: string;\n private ws: WebSocket | null = null;\n private _state: TransportState = 'disconnected';\n private autoReconnect: boolean;\n private reconnectDelay: number;\n private maxReconnectAttempts: number;\n private reconnectAttempts = 0;\n private reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\n private connectionTimeout: number;\n private debug: boolean;\n \n private messageHandlers = new Set<(message: InboundMessage) => void>();\n private stateHandlers = new Set<(state: TransportState) => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n private messageQueue: OutboundMessage[] = [];\n\n constructor(options: WebSocketTransportOptions) {\n this.url = options.url;\n this.autoReconnect = options.autoReconnect ?? true;\n this.reconnectDelay = options.reconnectDelay ?? 1000;\n this.maxReconnectAttempts = options.maxReconnectAttempts ?? 0; // 0 = infinite\n this.connectionTimeout = options.connectionTimeout ?? 10000;\n this.debug = options.debug ?? false;\n }\n\n public get state(): TransportState {\n return this._state;\n }\n\n public async connect(): Promise<void> {\n if (this._state === 'connected' || this._state === 'connecting') {\n this.log('Already connected or connecting');\n return;\n }\n\n this.setState('connecting');\n this.log(`Connecting to ${this.url}`);\n\n return new Promise((resolve, reject) => {\n try {\n this.ws = new WebSocket(this.url);\n\n const timeout = setTimeout(() => {\n reject(new Error('Connection timeout'));\n this.ws?.close();\n }, this.connectionTimeout);\n\n this.ws.onopen = () => {\n clearTimeout(timeout);\n this.setState('connected');\n this.reconnectAttempts = 0;\n this.log('Connected');\n \n // Flush queued messages\n this.flushMessageQueue();\n \n resolve();\n };\n\n this.ws.onerror = () => {\n clearTimeout(timeout);\n const error = new Error('WebSocket connection error');\n this.log('Connection error:', error);\n this.emitError(error);\n reject(error);\n };\n\n this.ws.onclose = () => {\n clearTimeout(timeout);\n this.handleDisconnect();\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n } catch (error) {\n this.setState('error');\n const err = error instanceof Error ? error : new Error('Unknown error');\n this.emitError(err);\n reject(err);\n }\n });\n }\n\n public disconnect(): void {\n this.log('Disconnecting');\n this.autoReconnect = false; // Disable auto-reconnect on manual disconnect\n \n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n\n this.setState('disconnected');\n }\n\n public async send(message: OutboundMessage): Promise<void> {\n if (this._state !== 'connected' || !this.ws) {\n // Queue message if not connected\n this.log('Not connected, queueing message');\n this.messageQueue.push(message);\n return;\n }\n\n try {\n const payload = JSON.stringify(message);\n this.ws.send(payload);\n this.log('Sent message:', message);\n } catch (error) {\n const err = error instanceof Error ? error : new Error('Send failed');\n this.log('Send error:', err);\n this.emitError(err);\n throw err;\n }\n }\n\n public onMessage(handler: (message: InboundMessage) => void): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n public onStateChange(handler: (state: TransportState) => void): () => void {\n this.stateHandlers.add(handler);\n return () => this.stateHandlers.delete(handler);\n }\n\n public onError(handler: (error: Error) => void): () => void {\n this.errorHandlers.add(handler);\n return () => this.errorHandlers.delete(handler);\n }\n\n /**\n * Handle incoming WebSocket message\n */\n private handleMessage(data: string): void {\n try {\n const message: InboundMessage = JSON.parse(data);\n this.log('Received message:', message);\n \n this.messageHandlers.forEach((handler) => {\n try {\n handler(message);\n } catch (error) {\n this.log('Handler error:', error);\n }\n });\n } catch (error) {\n this.log('Failed to parse message:', error);\n this.emitError(new Error('Invalid message format'));\n }\n }\n\n /**\n * Handle WebSocket disconnect\n */\n private handleDisconnect(): void {\n this.log('Disconnected');\n this.ws = null;\n\n if (this.autoReconnect && \n (this.maxReconnectAttempts === 0 || this.reconnectAttempts < this.maxReconnectAttempts)) {\n this.setState('reconnecting');\n this.scheduleReconnect();\n } else {\n this.setState('disconnected');\n }\n }\n\n /**\n * Schedule reconnection attempt with exponential backoff\n */\n private scheduleReconnect(): void {\n const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);\n this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts + 1})`);\n\n this.reconnectTimeout = setTimeout(() => {\n this.reconnectAttempts++;\n this.connect().catch((error) => {\n this.log('Reconnect failed:', error);\n this.handleDisconnect();\n });\n }, delay);\n }\n\n /**\n * Flush queued messages\n */\n private flushMessageQueue(): void {\n if (this.messageQueue.length === 0) {\n return;\n }\n\n this.log(`Flushing ${this.messageQueue.length} queued messages`);\n const queue = [...this.messageQueue];\n this.messageQueue = [];\n\n queue.forEach((message) => {\n this.send(message).catch((error) => {\n this.log('Failed to flush message:', error);\n });\n });\n }\n\n /**\n * Set connection state\n */\n private setState(state: TransportState): void {\n if (this._state === state) {\n return;\n }\n\n this._state = state;\n this.stateHandlers.forEach((handler) => {\n try {\n handler(state);\n } catch (error) {\n this.log('State handler error:', error);\n }\n });\n }\n\n /**\n * Emit error to handlers\n */\n private emitError(error: Error): void {\n this.errorHandlers.forEach((handler) => {\n try {\n handler(error);\n } catch (err) {\n this.log('Error handler error:', err);\n }\n });\n }\n\n /**\n * Debug logging\n */\n private log(message: string, data?: unknown): void {\n if (this.debug && typeof console !== 'undefined') {\n console.log(`[WebSocketTransport] ${message}`, data || '');\n }\n }\n}\n","import type {\n TalonTransport,\n OutboundMessage,\n InboundMessage,\n TransportState,\n} from '../types';\n\n/**\n * Webhook transport options\n */\nexport interface WebhookTransportOptions {\n /** Webhook URL */\n url: string;\n \n /** HTTP method */\n method?: 'POST' | 'PUT';\n \n /** Custom headers */\n headers?: Record<string, string>;\n \n /** Request timeout in ms */\n timeout?: number;\n \n /** Retry failed requests */\n retry?: boolean;\n \n /** Max retry attempts */\n maxRetries?: number;\n \n /** Retry delay in ms */\n retryDelay?: number;\n \n /** Debug mode */\n debug?: boolean;\n}\n\n/**\n * Webhook transport for fire-and-forget HTTP requests\n * \n * Features:\n * - One-way communication (no responses)\n * - HTTP POST/PUT requests\n * - Optional retry logic\n * - Custom headers support\n * \n * Use this for:\n * - Server-side event delivery\n * - Fire-and-forget scenarios\n * - When WebSocket not available/needed\n * \n * @example\n * ```typescript\n * const transport = new WebhookTransport({\n * url: 'https://edge.sygnl.io/webhook',\n * method: 'POST',\n * retry: true\n * });\n * ```\n */\nexport class WebhookTransport implements TalonTransport {\n private url: string;\n private method: 'POST' | 'PUT';\n private headers: Record<string, string>;\n private timeout: number;\n private retry: boolean;\n private maxRetries: number;\n private retryDelay: number;\n private debug: boolean;\n private _state: TransportState = 'disconnected';\n \n private messageHandlers = new Set<(message: InboundMessage) => void>();\n private stateHandlers = new Set<(state: TransportState) => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n\n constructor(options: WebhookTransportOptions) {\n this.url = options.url;\n this.method = options.method ?? 'POST';\n this.headers = {\n 'Content-Type': 'application/json',\n ...options.headers,\n };\n this.timeout = options.timeout ?? 10000;\n this.retry = options.retry ?? false;\n this.maxRetries = options.maxRetries ?? 3;\n this.retryDelay = options.retryDelay ?? 1000;\n this.debug = options.debug ?? false;\n }\n\n public get state(): TransportState {\n return this._state;\n }\n\n public async connect(): Promise<void> {\n // Webhook is \"connected\" immediately (stateless)\n this.log('Webhook transport ready');\n this.setState('connected');\n }\n\n public disconnect(): void {\n this.log('Disconnecting webhook transport');\n this.setState('disconnected');\n }\n\n public async send(message: OutboundMessage): Promise<void> {\n if (this._state !== 'connected') {\n throw new Error('Transport not connected');\n }\n\n let lastError: Error | null = null;\n const attempts = this.retry ? this.maxRetries + 1 : 1;\n\n for (let attempt = 0; attempt < attempts; attempt++) {\n try {\n await this.sendRequest(message);\n this.log(`Sent message (attempt ${attempt + 1})`);\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error('Send failed');\n this.log(`Send failed (attempt ${attempt + 1}):`, lastError);\n\n if (attempt < attempts - 1) {\n // Wait before retry (exponential backoff)\n const delay = this.retryDelay * Math.pow(2, attempt);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n\n // All attempts failed\n if (lastError) {\n this.emitError(lastError);\n throw lastError;\n }\n }\n\n public onMessage(handler: (message: InboundMessage) => void): () => void {\n // Webhook is one-way, but keep interface consistent\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n public onStateChange(handler: (state: TransportState) => void): () => void {\n this.stateHandlers.add(handler);\n return () => this.stateHandlers.delete(handler);\n }\n\n public onError(handler: (error: Error) => void): () => void {\n this.errorHandlers.add(handler);\n return () => this.errorHandlers.delete(handler);\n }\n\n /**\n * Send HTTP request\n */\n private async sendRequest(message: OutboundMessage): Promise<void> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(this.url, {\n method: this.method,\n headers: this.headers,\n body: JSON.stringify(message),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n this.log(`Request successful: ${response.status}`);\n } catch (error) {\n clearTimeout(timeoutId);\n \n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new Error('Request timeout');\n }\n throw error;\n }\n \n throw new Error('Request failed');\n }\n }\n\n /**\n * Set connection state\n */\n private setState(state: TransportState): void {\n if (this._state === state) {\n return;\n }\n\n this._state = state;\n this.stateHandlers.forEach((handler) => {\n try {\n handler(state);\n } catch (error) {\n this.log('State handler error:', error);\n }\n });\n }\n\n /**\n * Emit error to handlers\n */\n private emitError(error: Error): void {\n this.errorHandlers.forEach((handler) => {\n try {\n handler(error);\n } catch (err) {\n this.log('Error handler error:', err);\n }\n });\n }\n\n /**\n * Debug logging\n */\n private log(message: string, data?: unknown): void {\n if (this.debug && typeof console !== 'undefined') {\n console.log(`[WebhookTransport] ${message}`, data || '');\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/TalonClient.ts"],"names":[],"mappings":";AAoCO,IAAM,cAAN,MAAkB;AAAA,EAQvB,YAAY,OAAA,EAA6B;AACvC,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AACzB,IAAA,IAAA,CAAK,aAAA,uBAAoB,GAAA,EAAI;AAC7B,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAQ,KAAA,IAAS,KAAA;AAG9B,IAAA,IAAA,CAAK,kBAAA,GAAqB,KAAK,SAAA,CAAU,SAAA,CAAU,KAAK,aAAA,CAAc,IAAA,CAAK,IAAI,CAAC,CAAA;AAChF,IAAA,IAAA,CAAK,gBAAA,GAAmB,KAAK,SAAA,CAAU,aAAA,CAAc,KAAK,iBAAA,CAAkB,IAAA,CAAK,IAAI,CAAC,CAAA;AACtF,IAAA,IAAA,CAAK,gBAAA,GAAmB,KAAK,SAAA,CAAU,OAAA,CAAQ,KAAK,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA;AAG1E,IAAA,IAAI,OAAA,CAAQ,gBAAgB,KAAA,EAAO;AACjC,MAAA,IAAA,CAAK,OAAA,EAAQ,CAAE,KAAA,CAAM,CAAC,KAAA,KAAU;AAC9B,QAAA,IAAA,CAAK,GAAA,CAAI,wBAAwB,KAAK,CAAA;AAAA,MACxC,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAA,GAAyB;AACpC,IAAA,OAAO,IAAA,CAAK,UAAU,OAAA,EAAQ;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKO,UAAA,GAAmB;AACxB,IAAA,IAAA,CAAK,UAAU,UAAA,EAAW;AAC1B,IAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAa,KAAK,KAAA,EAA+C;AAC/D,IAAA,MAAM,OAAA,GAA2B;AAAA,MAC/B,IAAA,EAAM,OAAA;AAAA,MACN,IAAA,EAAM,KAAA;AAAA,MACN,EAAA,EAAI,KAAK,UAAA,EAAW;AAAA,MACpB,SAAA,EAAW,KAAK,GAAA;AAAI,KACtB;AAEA,IAAA,IAAA,CAAK,GAAA,CAAI,oBAAoB,OAAO,CAAA;AACpC,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBO,EAAA,CAAY,WAAmB,OAAA,EAAsC;AAC1E,IAAA,IAAI,CAAC,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,SAAS,CAAA,EAAG;AACtC,MAAA,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,SAAA,kBAAW,IAAI,KAAK,CAAA;AAAA,IAC7C;AAEA,IAAA,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,SAAS,CAAA,CAAG,IAAI,OAAO,CAAA;AAC9C,IAAA,IAAA,CAAK,GAAA,CAAI,CAAA,qBAAA,EAAwB,SAAS,CAAA,CAAE,CAAA;AAG5C,IAAA,OAAO,MAAM;AACX,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,SAAS,CAAA;AACjD,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,QAAA,CAAS,OAAO,OAAO,CAAA;AACvB,QAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACvB,UAAA,IAAA,CAAK,aAAA,CAAc,OAAO,SAAS,CAAA;AAAA,QACrC;AAAA,MACF;AACA,MAAA,IAAA,CAAK,GAAA,CAAI,CAAA,yBAAA,EAA4B,SAAS,CAAA,CAAE,CAAA;AAAA,IAClD,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,IAAA,CAAc,WAAmB,OAAA,EAAsC;AAC5E,IAAA,MAAM,cAAA,GAAiB,CAAC,IAAA,KAAY;AAClC,MAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,MAAA,WAAA,EAAY;AAAA,IACd,CAAA;AAEA,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,EAAA,CAAG,SAAA,EAAW,cAAc,CAAA;AACrD,IAAA,OAAO,WAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,IAAI,SAAA,EAAyB;AAClC,IAAA,IAAA,CAAK,aAAA,CAAc,OAAO,SAAS,CAAA;AACnC,IAAA,IAAA,CAAK,GAAA,CAAI,CAAA,0BAAA,EAA6B,SAAS,CAAA,CAAE,CAAA;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,KAAA,GAAwB;AACjC,IAAA,OAAO,KAAK,SAAA,CAAU,KAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,SAAA,GAAqB;AAC9B,IAAA,OAAO,IAAA,CAAK,UAAU,KAAA,KAAU,WAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,OAAA,EAA+B;AACnD,IAAA,IAAA,CAAK,GAAA,CAAI,qBAAqB,OAAO,CAAA;AAErC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,QAAQ,IAAI,CAAA;AACpD,IAAA,IAAI,QAAA,IAAY,QAAA,CAAS,IAAA,GAAO,CAAA,EAAG;AACjC,MAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC5B,QAAA,IAAI;AACF,UAAA,OAAA,CAAQ,QAAQ,IAAI,CAAA;AAAA,QACtB,SAAS,KAAA,EAAO;AACd,UAAA,IAAA,CAAK,GAAA,CAAI,CAAA,qBAAA,EAAwB,OAAA,CAAQ,IAAI,KAAK,KAAK,CAAA;AAAA,QACzD;AAAA,MACF,CAAC,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,GAAA,CAAI,CAAA,8BAAA,EAAiC,OAAA,CAAQ,IAAI,CAAA,CAAE,CAAA;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,KAAA,EAA6B;AACrD,IAAA,IAAA,CAAK,GAAA,CAAI,CAAA,eAAA,EAAkB,KAAK,CAAA,CAAE,CAAA;AAGlC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,eAAe,CAAA;AACvD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,QAAA,CAAS,QAAQ,CAAC,OAAA,KAAY,QAAQ,EAAE,KAAA,EAAO,CAAC,CAAA;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,KAAA,EAAoB;AACtC,IAAA,IAAA,CAAK,GAAA,CAAI,oBAAoB,KAAK,CAAA;AAGlC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,QAAQ,CAAA;AAChD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,QAAA,CAAS,QAAQ,CAAC,OAAA,KAAY,QAAQ,EAAE,KAAA,EAAO,CAAC,CAAA;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,OAAA,GAAgB;AACtB,IAAA,IAAA,CAAK,kBAAA,IAAqB;AAC1B,IAAA,IAAA,CAAK,gBAAA,IAAmB;AACxB,IAAA,IAAA,CAAK,gBAAA,IAAmB;AACxB,IAAA,IAAA,CAAK,cAAc,KAAA,EAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAA,GAAqB;AAC3B,IAAA,OAAO,CAAA,IAAA,EAAO,IAAA,CAAK,GAAA,EAAK,IAAI,IAAA,CAAK,MAAA,EAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,MAAA,CAAO,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKQ,GAAA,CAAI,SAAiB,IAAA,EAAsB;AACjD,IAAA,IAAI,IAAA,CAAK,KAAA,IAAS,OAAO,OAAA,KAAY,WAAA,EAAa;AAChD,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,cAAA,EAAiB,OAAO,CAAA,CAAA,EAAI,QAAQ,EAAE,CAAA;AAAA,IACpD;AAAA,EACF;AACF","file":"index.js","sourcesContent":["import type {\n TalonTransport,\n TalonClientOptions,\n OutboundMessage,\n InboundMessage,\n EventHandler,\n TransportState,\n} from './types';\n\n/**\n * TalonClient - Bidirectional event delivery client\n * \n * Features:\n * - Send events TO the edge\n * - Receive updates FROM the edge\n * - Transport-agnostic (WebSocket, Webhook, etc.)\n * - Event emitter pattern for edge responses\n * \n * @example\n * ```typescript\n * import { TalonClient } from '@sygnl/talon';\n * import { WebSocketTransport } from '@sygnl/talon/transports';\n * \n * const talon = new TalonClient({\n * transport: new WebSocketTransport('wss://edge.sygnl.io')\n * });\n * \n * // Send event TO edge\n * await talon.send({ event: 'add_to_cart', product_id: 'abc' });\n * \n * // Receive updates FROM edge\n * talon.on('attribution_updated', (data) => {\n * console.log('Attribution:', data);\n * });\n * ```\n */\nexport class TalonClient {\n private transport: TalonTransport;\n private eventHandlers: Map<string, Set<EventHandler>>;\n private messageUnsubscribe?: () => void;\n private stateUnsubscribe?: () => void;\n private errorUnsubscribe?: () => void;\n private debug: boolean;\n\n constructor(options: TalonClientOptions) {\n this.transport = options.transport;\n this.eventHandlers = new Map();\n this.debug = options.debug ?? false;\n\n // Subscribe to transport messages\n this.messageUnsubscribe = this.transport.onMessage(this.handleMessage.bind(this));\n this.stateUnsubscribe = this.transport.onStateChange(this.handleStateChange.bind(this));\n this.errorUnsubscribe = this.transport.onError(this.handleError.bind(this));\n\n // Auto-connect if requested\n if (options.autoConnect !== false) {\n this.connect().catch((error) => {\n this.log('Auto-connect failed:', error);\n });\n }\n }\n\n /**\n * Connect to the edge\n */\n public async connect(): Promise<void> {\n return this.transport.connect();\n }\n\n /**\n * Disconnect from the edge\n */\n public disconnect(): void {\n this.transport.disconnect();\n this.cleanup();\n }\n\n /**\n * Send event TO the edge\n * \n * @param event - Event data to send\n * @returns Promise that resolves when sent\n * \n * @example\n * ```typescript\n * await talon.send({\n * event: 'add_to_cart',\n * product_id: 'prod_123',\n * price: 99.99\n * });\n * ```\n */\n public async send(event: Record<string, unknown>): Promise<void> {\n const message: OutboundMessage = {\n type: 'event',\n data: event,\n id: this.generateId(),\n timestamp: Date.now(),\n };\n\n this.log('Sending message:', message);\n return this.transport.send(message);\n }\n\n /**\n * Subscribe to events FROM the edge\n * \n * @param eventType - Event type to listen for\n * @param handler - Function to call when event received\n * @returns Unsubscribe function\n * \n * @example\n * ```typescript\n * const unsubscribe = talon.on('attribution_updated', (data) => {\n * console.log('Attribution:', data);\n * });\n * \n * // Later: unsubscribe()\n * ```\n */\n public on<T = any>(eventType: string, handler: EventHandler<T>): () => void {\n if (!this.eventHandlers.has(eventType)) {\n this.eventHandlers.set(eventType, new Set());\n }\n\n this.eventHandlers.get(eventType)!.add(handler);\n this.log(`Subscribed to event: ${eventType}`);\n\n // Return unsubscribe function\n return () => {\n const handlers = this.eventHandlers.get(eventType);\n if (handlers) {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this.eventHandlers.delete(eventType);\n }\n }\n this.log(`Unsubscribed from event: ${eventType}`);\n };\n }\n\n /**\n * Subscribe to event once (auto-unsubscribe after first call)\n */\n public once<T = any>(eventType: string, handler: EventHandler<T>): () => void {\n const wrappedHandler = (data: T) => {\n handler(data);\n unsubscribe();\n };\n\n const unsubscribe = this.on(eventType, wrappedHandler);\n return unsubscribe;\n }\n\n /**\n * Remove all handlers for an event type\n */\n public off(eventType: string): void {\n this.eventHandlers.delete(eventType);\n this.log(`Removed all handlers for: ${eventType}`);\n }\n\n /**\n * Get current connection state\n */\n public get state(): TransportState {\n return this.transport.state;\n }\n\n /**\n * Check if connected\n */\n public get connected(): boolean {\n return this.transport.state === 'connected';\n }\n\n /**\n * Handle incoming message from transport\n */\n private handleMessage(message: InboundMessage): void {\n this.log('Received message:', message);\n\n const handlers = this.eventHandlers.get(message.type);\n if (handlers && handlers.size > 0) {\n handlers.forEach((handler) => {\n try {\n handler(message.data);\n } catch (error) {\n this.log(`Error in handler for ${message.type}:`, error);\n }\n });\n } else {\n this.log(`No handlers for message type: ${message.type}`);\n }\n }\n\n /**\n * Handle transport state change\n */\n private handleStateChange(state: TransportState): void {\n this.log(`State changed: ${state}`);\n \n // Emit state change event\n const handlers = this.eventHandlers.get('_state_change');\n if (handlers) {\n handlers.forEach((handler) => handler({ state }));\n }\n }\n\n /**\n * Handle transport error\n */\n private handleError(error: Error): void {\n this.log('Transport error:', error);\n \n // Emit error event\n const handlers = this.eventHandlers.get('_error');\n if (handlers) {\n handlers.forEach((handler) => handler({ error }));\n }\n }\n\n /**\n * Cleanup subscriptions\n */\n private cleanup(): void {\n this.messageUnsubscribe?.();\n this.stateUnsubscribe?.();\n this.errorUnsubscribe?.();\n this.eventHandlers.clear();\n }\n\n /**\n * Generate unique message ID\n */\n private generateId(): string {\n return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n /**\n * Debug logging\n */\n private log(message: string, data?: unknown): void {\n if (this.debug && typeof console !== 'undefined') {\n console.log(`[TalonClient] ${message}`, data || '');\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sygnl/talon",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Bidirectional event delivery client with WebSocket and Webhook transports",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -58,6 +58,7 @@
58
58
  "license": "Apache-2.0",
59
59
  "repository": {
60
60
  "type": "git",
61
- "url": "https://github.com/sygnl/talon"
62
- }
61
+ "url": "https://github.com/edgefoundryinc/talon"
62
+ },
63
+ "homepage": "https://sygnl.app/"
63
64
  }