{"version":3,"file":"index.mjs","names":["createBaseContext","wsConnectedEvent","wsDisconnectedEvent","wsErrorEvent","createBaseContext"],"sources":["../../../../src/adapters/websocket/h3/global.ts","../../../../src/adapters/websocket/h3/peer.ts"],"sourcesContent":["import type { Hooks, Message, Peer, WSError } from 'crossws'\n\nimport type { EventContext } from '../../../context'\nimport type { DirectionalEventa, Eventa } from '../../../eventa'\n\nimport { createContext as createBaseContext } from '../../../context'\nimport { and, defineEventa, defineInboundEventa, defineOutboundEventa, EventaFlowDirection, matchBy } from '../../../eventa'\nimport { generateWebsocketPayload, parseWebsocketPayload } from '../internal'\n\nexport const wsConnectedEvent = defineEventa<{ id: string }>('eventa:adapters:websocket-global:connected')\nexport const wsDisconnectedEvent = defineEventa<{ id: string }>('eventa:adapters:websocket-global:disconnected')\nexport const wsErrorEvent = defineEventa<{ error: unknown }>('eventa:adapters:websocket-global:error')\n\nexport function createGlobalContext(): {\n  websocketHandlers: Omit<Hooks, 'upgrade'>\n  context: EventContext<any, { raw: { error?: WSError, message?: Message } }>\n} {\n  const ctx = createBaseContext<any, { raw: { error?: WSError, message?: Message } }>()\n  const peers = new Set<Peer>()\n\n  ctx.on(and(\n    matchBy((e: DirectionalEventa<any>) => e._flowDirection === EventaFlowDirection.Outbound || !e._flowDirection),\n    matchBy('*'),\n  ), (event) => {\n    const data = JSON.stringify(generateWebsocketPayload(event.id, { ...defineOutboundEventa(event.type), ...event }))\n    for (const peer of peers) {\n      peer.send(data)\n    }\n  })\n\n  return {\n    websocketHandlers: {\n      open(peer) {\n        peers.add(peer)\n        ctx.emit(wsConnectedEvent, { id: peer.id }, { raw: { } })\n      },\n\n      close(peer) {\n        peers.delete(peer)\n        ctx.emit(wsDisconnectedEvent, { id: peer.id }, { raw: { } })\n      },\n\n      error(_, error) {\n        console.error('WebSocket error:', error)\n        ctx.emit(wsErrorEvent, { error }, { raw: { error } })\n      },\n\n      async message(_, message) {\n        try {\n          const { type, payload } = parseWebsocketPayload<Eventa<any>>(message.text())\n          ctx.emit(defineInboundEventa(type), payload.body, { raw: { message } })\n        }\n        catch (error) {\n          console.error('Failed to parse WebSocket message:', error)\n          ctx.emit(wsErrorEvent, { error }, { raw: { message } })\n        }\n      },\n    },\n    context: ctx,\n  }\n}\n","import type { Hooks, Message, Peer } from 'crossws'\n\nimport type { EventContext } from '../../../context'\nimport type { DirectionalEventa, Eventa } from '../../../eventa'\n\nimport { createContext as createBaseContext } from '../../../context'\nimport { and, defineEventa, defineInboundEventa, defineOutboundEventa, EventaFlowDirection, matchBy } from '../../../eventa'\nimport { generateWebsocketPayload, parseWebsocketPayload } from '../internal'\n\nexport const wsConnectedEvent = defineEventa<{ id: string }>('eventa:adapters:websocket-peer:connected')\nexport const wsDisconnectedEvent = defineEventa<{ id: string }>('eventa:adapters:websocket-peer:disconnected')\nexport const wsErrorEvent = defineEventa<{ error: unknown }>('eventa:adapters:websocket-peer:error')\n\nexport function createPeerContext(peer: Peer): {\n  hooks: Pick<Hooks, 'message' | 'close' | 'error'>\n  context: EventContext<any, { raw: { message: Message } }>\n} {\n  const peerId = peer.id\n  const ctx = createBaseContext<any, { raw: { message: Message } }>()\n\n  ctx.on(and(\n    matchBy((e: DirectionalEventa<any>) => e._flowDirection === EventaFlowDirection.Outbound || !e._flowDirection),\n    matchBy('*'),\n  ), (event) => {\n    const data = JSON.stringify(generateWebsocketPayload(event.id, { ...defineOutboundEventa(event.type), ...event }))\n    peer.send(data)\n  })\n\n  return {\n    hooks: {\n      message(peer, message) {\n        if (peer.id === peerId) {\n          try {\n            const { type, payload } = parseWebsocketPayload<Eventa<any>>(message.text())\n            ctx.emit(defineInboundEventa(type), payload.body, { raw: { message } })\n          }\n          catch (error) {\n            // Per-message parse failure — recoverable, do NOT abort lifetime.\n            console.error('Failed to parse WebSocket message:', error)\n            ctx.emit(wsErrorEvent, { error }, { raw: { message } })\n          }\n        }\n      },\n      close(peer, details) {\n        // crossws fires close for ANY peer; filter to our own.\n        if (peer.id !== peerId) {\n          return\n        }\n        const reasonText = details.reason ? ` (${details.reason})` : ''\n        // Cascade-cancel any in-flight `defineInvoke(...)` so server-side code\n        // that issued an invoke back to this peer doesn't hang on close.\n        ctx.abort(new Error(`eventa: invoke cancelled, peer disconnected${reasonText}`))\n        ctx.emit(wsDisconnectedEvent, { id: peerId })\n      },\n      error(peer, error) {\n        if (peer.id !== peerId) {\n          return\n        }\n        ctx.abort(error instanceof Error ? error : new Error('eventa: invoke cancelled, peer error'))\n        ctx.emit(wsErrorEvent, { error })\n      },\n    },\n    context: ctx,\n  }\n}\n\nexport interface PeerContext { peer: Peer, context: EventContext<any, { raw: { message: Message } }> }\n\nexport function createPeerHooks(): { hooks: Partial<Hooks>, untilLeastOneConnected: Promise<PeerContext> } {\n  let resolve: (value: PeerContext) => void\n  const untilLeastOneConnected = new Promise<PeerContext>((r) => {\n    resolve = r\n  })\n\n  // NOTICE: single-peer model — these closure-scoped hook refs get overwritten\n  // when a second peer connects, so `createPeerHooks` only correctly serves the\n  // most-recently-opened peer. Multi-peer support requires a peerId-keyed Map\n  // and a different \"untilLeastOneConnected\" semantic; out of scope here.\n  let message: Hooks['message'] | undefined\n  let close: Hooks['close'] | undefined\n  let error: Hooks['error'] | undefined\n\n  const hooks: Pick<Hooks, 'open' | 'message' | 'close' | 'error'> = {\n    open: (peer) => {\n      const { context, hooks } = createPeerContext(peer)\n      message = hooks.message\n      close = hooks.close\n      error = hooks.error\n      resolve({ peer, context })\n    },\n    message: (peer, msg) => {\n      message?.(peer, msg)\n    },\n    close: (peer, details) => {\n      close?.(peer, details)\n    },\n    error: (peer, err) => {\n      error?.(peer, err)\n    },\n  }\n\n  return { hooks, untilLeastOneConnected }\n}\n"],"mappings":"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"}