UNPKG

@cardos/service-bus-portal

Version:

A modular, composable cross-context communication system for Web Workers, iframes, Shared Workers, and Service Workers

1 lines 25.3 kB
{"version":3,"file":"index.mjs","names":["id: string","type: PortalType","config: PortalConfig","handler: (message: PortalMessage) => void","message: PortalMessage","direction: PortalType","target: Window | Worker","event: MessageEvent","eventTarget: EventTarget","channel: string","event: CustomEvent","portal: CommunicationPortal","serviceBus: {\n invoke: (key: string, ...args: unknown[]) => unknown;\n }","message: PortalMessage","responseMessage: PortalMessage","errorMessage: PortalMessage","key: string","_: unknown","prop: string","id: string","direction: PortalType","target: Window | Worker","config: Partial<PortalConfig>","fullConfig: PortalConfig","eventTarget: EventTarget","channel: string","worker: Worker","portalId?: string","iframe: HTMLIFrameElement","portal: CommunicationPortal","portalId: string","serviceBus: { invoke: (key: string, ...args: unknown[]) => unknown }"],"sources":["../src/core.ts","../src/service-bus.ts","../src/factory.ts"],"sourcesContent":["// service-bus-portal/src/core.ts\nimport type {\n CommunicationPortal,\n PortalMessage,\n PortalType,\n PortalConfig,\n PortalTargetInfo\n} from './types';\n\n// ==================== Base Portal Implementation ====================\n\n/**\n * Base portal implementation\n */\nexport abstract class BasePortal implements CommunicationPortal {\n protected messageHandlers: Array<(message: PortalMessage) => void> = [];\n protected connected = false;\n protected messageIdCounter = 0;\n\n constructor(\n public readonly id: string,\n public readonly type: PortalType,\n protected config: PortalConfig\n ) { }\n\n abstract send(message: PortalMessage): Promise<void>;\n abstract connect(): Promise<void>;\n abstract disconnect(): Promise<void>;\n abstract getTargetInfo(): PortalTargetInfo;\n\n onMessage(handler: (message: PortalMessage) => void): void {\n this.messageHandlers.push(handler);\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n generateMessageId(): string {\n return `${this.id}_${Date.now()}_${++this.messageIdCounter}`;\n }\n\n protected notifyHandlers(message: PortalMessage): void {\n\n this.messageHandlers.forEach(handler => {\n try {\n handler(message);\n } catch (error) {\n console.error('Portal message handler error:', error);\n }\n });\n }\n\n protected validateMessage(message: PortalMessage): boolean {\n return Boolean(message.id && message.type && message.timestamp > 0);\n }\n}\n\n// ==================== PostMessage Portal Implementation ====================\n\n/**\n * PostMessage portal implementation\n */\nexport class PostMessagePortal extends BasePortal {\n private target: Window | Worker;\n private messageListener: ((event: MessageEvent) => void) | undefined;\n\n constructor(\n id: string,\n direction: PortalType,\n target: Window | Worker,\n config: PortalConfig\n ) {\n super(id, direction, config);\n this.target = target;\n }\n\n async send(message: PortalMessage): Promise<void> {\n if (!this.connected) {\n throw new Error('Portal not connected');\n }\n\n const wrappedMessage = {\n __portal: true,\n portalId: this.id,\n data: message\n };\n\n\n\n if (typeof Window !== 'undefined' && this.target instanceof Window) {\n this.target.postMessage(wrappedMessage, this.getTargetOrigin());\n } else if (typeof self !== 'undefined' && this.target === self) {\n // In worker context, send to parent (main thread)\n self.postMessage(wrappedMessage);\n } else {\n this.target.postMessage(wrappedMessage);\n }\n }\n\n async connect(): Promise<void> {\n if (this.connected) return;\n\n\n this.messageListener = (event: MessageEvent) => {\n const data = event.data;\n if (data?.__portal && data.portalId === this.id) {\n const message = data.data as PortalMessage;\n if (this.validateMessage(message)) {\n this.notifyHandlers(message);\n }\n }\n };\n\n const eventTarget = this.getEventTarget();\n eventTarget.addEventListener('message', this.messageListener as EventListener);\n this.connected = true;\n }\n\n async disconnect(): Promise<void> {\n if (!this.connected) return;\n\n if (this.messageListener) {\n this.getEventTarget().removeEventListener('message', this.messageListener as EventListener);\n this.messageListener = undefined;\n }\n\n this.connected = false;\n }\n\n getTargetInfo(): PortalTargetInfo {\n return {\n type: this.type,\n origin: this.getTargetOrigin(),\n capabilities: ['postmessage'],\n metadata: { target: this.target }\n };\n }\n\n private getEventTarget(): EventTarget {\n return this.target as EventTarget;\n }\n\n private getTargetOrigin(): string {\n if (typeof Window !== 'undefined' && this.target instanceof Window) {\n return this.target.location.origin;\n }\n return '*';\n }\n}\n\n// ==================== EventTarget Portal Implementation ====================\n\n/**\n * EventTarget portal implementation\n */\nexport class EventTargetPortal extends BasePortal {\n private eventTarget: EventTarget;\n private channel: string;\n private listener: ((event: CustomEvent) => void) | undefined;\n\n constructor(\n id: string,\n direction: PortalType,\n eventTarget: EventTarget,\n channel: string,\n config: PortalConfig\n ) {\n super(id, direction, config);\n this.eventTarget = eventTarget;\n this.channel = channel;\n }\n\n async send(message: PortalMessage): Promise<void> {\n if (!this.connected) {\n throw new Error('Portal not connected');\n }\n\n const event = new CustomEvent(`${this.channel}:portal`, {\n detail: {\n portalId: this.id,\n data: message\n }\n });\n\n this.eventTarget.dispatchEvent(event);\n }\n\n async connect(): Promise<void> {\n if (this.connected) return;\n\n this.listener = (event: CustomEvent) => {\n const detail = event.detail;\n if (detail?.portalId === this.id) {\n const message = detail.data as PortalMessage;\n if (this.validateMessage(message)) {\n this.notifyHandlers(message);\n }\n }\n };\n\n this.eventTarget.addEventListener(`${this.channel}:portal`, this.listener as EventListener);\n this.connected = true;\n }\n\n async disconnect(): Promise<void> {\n if (!this.connected) return;\n\n if (this.listener) {\n this.eventTarget.removeEventListener(`${this.channel}:portal`, this.listener as EventListener);\n this.listener = undefined;\n }\n\n this.connected = false;\n }\n\n getTargetInfo(): PortalTargetInfo {\n return {\n type: this.type,\n capabilities: ['event-target'],\n metadata: { channel: this.channel, eventTarget: this.eventTarget }\n };\n }\n} ","// service-bus-portal/src/service-bus.ts\nimport type { CommunicationPortal, PortalMessage } from './types';\n\n// ==================== Service Bus Connector ====================\n\n/**\n * Service bus connector based on portal\n */\nexport class PortalServiceBusConnector {\n private portal: CommunicationPortal;\n private serviceBus: {\n invoke: (key: string, ...args: unknown[]) => unknown;\n };\n\n constructor(\n portal: CommunicationPortal,\n serviceBus: {\n invoke: (key: string, ...args: unknown[]) => unknown;\n }\n ) {\n this.portal = portal;\n this.serviceBus = serviceBus;\n this.setupMessageHandling();\n }\n\n async connect(): Promise<void> {\n await this.portal.connect();\n }\n\n async disconnect(): Promise<void> {\n await this.portal.disconnect();\n }\n\n private setupMessageHandling(): void {\n this.portal.onMessage(async (message) => {\n if (message.type === 'invoke') {\n await this.handleInvoke(message);\n }\n });\n }\n\n private async handleInvoke(message: PortalMessage): Promise<void> {\n try {\n const { key, args = [] } = message.data;\n if (!key) {\n throw new Error('Missing service key');\n }\n\n \n const result = await Promise.resolve(\n this.serviceBus.invoke(key, ...args)\n );\n\n \n const responseMessage: PortalMessage = {\n id: this.portal.generateMessageId(),\n type: 'result',\n timestamp: Date.now(),\n source: this.portal.id,\n target: message.source,\n data: { result },\n metadata: { originalMessageId: message.id }\n };\n\n await this.portal.send(responseMessage);\n\n } catch (error) {\n console.error(`[PortalServiceBusConnector] Error handling invoke:`, error);\n \n const errorMessage: PortalMessage = {\n id: this.portal.generateMessageId(),\n type: 'error',\n timestamp: Date.now(),\n source: this.portal.id,\n target: message.source,\n data: { \n error: error instanceof Error ? error.message : String(error) \n },\n metadata: { originalMessageId: message.id }\n };\n\n await this.portal.send(errorMessage);\n }\n }\n}\n\n// ==================== Service Bus Proxy ====================\n\n/**\n * Service bus proxy based on portal\n */\nexport class PortalServiceBusProxy<T = unknown> {\n private portal: CommunicationPortal;\n private pending = new Map<string, {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n }>();\n\n constructor(portal: CommunicationPortal) {\n this.portal = portal;\n this.setupMessageHandling();\n }\n\n async connect(): Promise<void> {\n await this.portal.connect();\n }\n\n async disconnect(): Promise<void> {\n // Clean up all pending requests\n for (const [id, pending] of this.pending) {\n clearTimeout(pending.timer);\n pending.reject(new Error('Portal disconnected'));\n }\n this.pending.clear();\n\n await this.portal.disconnect();\n }\n\n private setupMessageHandling(): void {\n this.portal.onMessage((message) => {\n \n const pending = this.pending.get(message.metadata?.originalMessageId as string);\n if (!pending) {\n console.warn(`[PortalServiceBusProxy] No pending request found for messageId: ${message.metadata?.originalMessageId}`);\n return;\n }\n\n clearTimeout(pending.timer);\n this.pending.delete(message.metadata?.originalMessageId as string);\n\n if (message.type === 'result') {\n pending.resolve(message.data.result);\n } else if (message.type === 'error') {\n console.error(`[PortalServiceBusProxy] Rejecting with error:`, message.data.error);\n pending.reject(new Error(message.data.error));\n }\n });\n }\n\n private async invoke(key: string, ...args: unknown[]): Promise<unknown> {\n if (!this.portal.isConnected()) {\n throw new Error('Portal not connected');\n }\n\n const messageId = this.portal.generateMessageId();\n \n \n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n console.error(`[PortalServiceBusProxy] Service invocation timeout for: ${key} (messageId: ${messageId})`);\n console.error(`[PortalServiceBusProxy] Pending requests:`, Array.from(this.pending.keys()));\n this.pending.delete(messageId);\n reject(new Error(`Service invocation timeout for: ${key}`));\n }, 10000);\n\n this.pending.set(messageId, { resolve, reject, timer });\n\n const message: PortalMessage = {\n id: messageId,\n type: 'invoke',\n timestamp: Date.now(),\n source: this.portal.id,\n target: '*',\n data: { key, args },\n metadata: { messageId }\n };\n\n \n this.portal.send(message).catch(error => {\n console.error(`[PortalServiceBusProxy] Failed to send message:`, error);\n this.pending.delete(messageId);\n clearTimeout(timer);\n reject(error);\n });\n });\n }\n\n createProxy(): T {\n return new Proxy(\n {},\n {\n get: (_: unknown, prop: string) => {\n return (...args: unknown[]) => this.invoke(prop, ...args);\n },\n }\n ) as T;\n }\n} ","// service-bus-portal/src/factory.ts\nimport type { PortalType, PortalConfig, CommunicationPortal } from './types';\nimport { PostMessagePortal, EventTargetPortal } from './core';\nimport { PortalServiceBusConnector, PortalServiceBusProxy } from './service-bus';\n\n// ==================== Portal Factory ====================\n\n/**\n * Portal factory for creating different types of portals\n */\nexport class PortalFactory {\n /**\n * Create a PostMessage-based portal\n */\n static createPostMessagePortal(\n id: string,\n direction: PortalType,\n target: Window | Worker,\n config: Partial<PortalConfig> = {}\n ): PostMessagePortal {\n const fullConfig: PortalConfig = {\n id,\n type: direction,\n timeoutMs: 10000,\n retryAttempts: 3,\n ...config\n };\n\n return new PostMessagePortal(id, direction, target, fullConfig);\n }\n\n /**\n * Create an EventTarget-based portal\n */\n static createEventTargetPortal(\n id: string,\n direction: PortalType,\n eventTarget: EventTarget,\n channel: string,\n config: Partial<PortalConfig> = {}\n ): EventTargetPortal {\n const fullConfig: PortalConfig = {\n id,\n type: direction,\n timeoutMs: 10000,\n retryAttempts: 3,\n ...config\n };\n\n return new EventTargetPortal(id, direction, eventTarget, channel, fullConfig);\n }\n\n /**\n * Create a portal for Web Worker communication\n * Automatically determines the correct configuration based on current context\n */\n static createWorkerPortal(\n worker: Worker,\n config: Partial<PortalConfig> = {},\n portalId?: string\n ): PostMessagePortal {\n const id = portalId || `worker-${Date.now()}`;\n \n // Check if we're in a worker context\n if (typeof window !== 'undefined' && window === self) {\n // Main thread context - create listener portal\n return this.createPostMessagePortal(\n id,\n 'worker-to-window',\n worker,\n config\n );\n } else {\n // Worker context - create sender portal\n return this.createPostMessagePortal(\n id,\n 'worker-to-window',\n worker,\n config\n );\n }\n }\n\n /**\n * Create a portal for window communication from worker context\n */\n static createWindowPortal(\n config: Partial<PortalConfig> = {},\n portalId?: string\n ): PostMessagePortal {\n const id = portalId || `window-${Date.now()}`;\n\n // Worker context - create sender portal\n return this.createPostMessagePortal(\n id,\n 'worker-to-window',\n self,\n config\n );\n }\n\n /**\n * Create a portal for iframe communication\n * Automatically determines the correct configuration based on current context\n */\n static createIframePortal(\n iframe: HTMLIFrameElement,\n config: Partial<PortalConfig> = {}\n ): PostMessagePortal {\n const id = `iframe-${Date.now()}`;\n\n // Check if we're in a main thread context\n if (typeof window !== 'undefined' && window !== self) {\n // Main thread context - create listener portal\n return this.createPostMessagePortal(\n id,\n 'iframe-to-window',\n window,\n config\n );\n } else {\n // Iframe context - create sender portal\n return this.createPostMessagePortal(\n id,\n 'iframe-to-window',\n self,\n config\n );\n }\n }\n}\n\n// ==================== Portal Composer ====================\n\n/**\n * Portal composer for managing multiple portals\n */\nexport class PortalComposer {\n private portals = new Map<string, CommunicationPortal>();\n private connectors = new Map<string, PortalServiceBusConnector>();\n private proxies = new Map<string, PortalServiceBusProxy>();\n\n /**\n * Add a portal to the composer\n */\n addPortal(portal: CommunicationPortal): void {\n this.portals.set(portal.id, portal);\n }\n\n /**\n * Remove a portal from the composer\n */\n removePortal(portalId: string): void {\n const portal = this.portals.get(portalId);\n if (portal) {\n portal.disconnect();\n this.portals.delete(portalId);\n this.connectors.delete(portalId);\n this.proxies.delete(portalId);\n }\n }\n\n /**\n * Create a service bus connector for a portal\n */\n createConnector(\n portalId: string,\n serviceBus: { invoke: (key: string, ...args: unknown[]) => unknown }\n ): PortalServiceBusConnector {\n const portal = this.portals.get(portalId);\n if (!portal) {\n throw new Error(`Portal not found: ${portalId}`);\n }\n\n const connector = new PortalServiceBusConnector(portal, serviceBus);\n this.connectors.set(portalId, connector);\n return connector;\n }\n\n /**\n * Create a service bus proxy for a portal\n */\n createProxy<T = unknown>(portalId: string): PortalServiceBusProxy<T> {\n const portal = this.portals.get(portalId);\n if (!portal) {\n throw new Error(`Portal not found: ${portalId}`);\n }\n\n const proxy = new PortalServiceBusProxy<T>(portal);\n this.proxies.set(portalId, proxy);\n return proxy;\n }\n\n /**\n * Connect all portals\n */\n async connectAll(): Promise<void> {\n const promises = Array.from(this.portals.values()).map(portal => portal.connect());\n await Promise.all(promises);\n }\n\n /**\n * Disconnect all portals\n */\n async disconnectAll(): Promise<void> {\n const promises = Array.from(this.portals.values()).map(portal => portal.disconnect());\n await Promise.all(promises);\n }\n\n /**\n * Get a portal by ID\n */\n getPortal(portalId: string): CommunicationPortal | undefined {\n return this.portals.get(portalId);\n }\n\n /**\n * List all portals\n */\n listPortals(): CommunicationPortal[] {\n return Array.from(this.portals.values());\n }\n} "],"mappings":"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"}