import { randomId } from '../../utils/random.ts' export const startChannel = () => { const caller = window.name ?? randomId() let isDesk = false const waitingMessages: Record, 'reject' | 'resolve'>> = {} const messageHandler = ({ data, origin }: MessageEvent) => { if (origin.endsWith('.desk.blip.ai')) { isDesk = true } const deferred = waitingMessages[data?.trackingProperties?.id] if (deferred) { if (data.message?.caller === caller) { // This is a echo message, ignore it return } delete waitingMessages[data.trackingProperties.id] if (data.error) { deferred.reject(JSON.parse(data.error)) } else { deferred.resolve(data.response) } } } window.addEventListener('message', messageHandler) let isDestroyed = false return { get isDesk() { return isDesk }, post: (action: string, content: unknown, options?: { fireAndForget: T extends void ? never : true }) => { if (isDestroyed) { throw new Error('Channel is destroyed') } const id = randomId() let promise: Promise if (options?.fireAndForget) { promise = Promise.resolve() } else { const deferred = Promise.withResolvers() waitingMessages[id] = { reject: deferred.reject, resolve: deferred.resolve } promise = deferred.promise } window.parent.postMessage( { message: { action: `blipEvent:${action}`, content, caller, }, trackingProperties: { id, }, }, '*', ) return promise as Promise }, destroy: () => { window.removeEventListener('message', messageHandler) isDestroyed = true }, } }