{"version":3,"sources":["/Users/gwakko/Projects/shared-websocket/dist/react.cjs","../src/adapters/react/context.ts","../src/adapters/react/auth.ts","../src/adapters/react/events.ts","../src/adapters/react/state.ts","../src/adapters/react/status.ts","../src/adapters/react/subscriptions.ts"],"names":["useState","useEffectEvent","useEffect"],"mappings":"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","file":"/Users/gwakko/Projects/shared-websocket/dist/react.cjs","sourcesContent":[null,"import {\n  createContext,\n  useContext,\n  useRef,\n  useSyncExternalStore,\n  type ReactNode,\n  createElement,\n} from 'react';\nimport { SharedWebSocket } from '../../SharedWebSocket';\nimport type { SharedWebSocketOptions } from '../../types';\n\n// ─── Context ─────────────────────────────────────────────\n\nconst SharedWSContext = createContext<SharedWebSocket | null>(null);\n\n/**\n * Per-provider store that owns a single SharedWebSocket. The instance is born\n * on the first subscriber (commit-time, never during a render) and torn down\n * when the last subscriber leaves — so there is exactly one instance per\n * provider, and a render that React throws away never constructs anything.\n */\ninterface SocketStore {\n  subscribe: (onChange: () => void) => () => void;\n  getSnapshot: () => SharedWebSocket | null;\n  getServerSnapshot: () => null;\n}\n\nfunction createSocketStore(url: string, options?: SharedWebSocketOptions): SocketStore {\n  let socket: SharedWebSocket | null = null;\n  const listeners = new Set<() => void>();\n\n  return {\n    subscribe(onChange) {\n      listeners.add(onChange);\n      if (!socket) {\n        socket = new SharedWebSocket(url, options);\n        void socket.connect();\n        listeners.forEach((l) => l());\n      }\n      return () => {\n        listeners.delete(onChange);\n        if (listeners.size === 0) {\n          socket?.[Symbol.dispose]();\n          socket = null;\n        }\n      };\n    },\n    getSnapshot: () => socket,\n    getServerSnapshot: () => null,\n  };\n}\n\n/**\n * Provider props — pass URL and options as props for flexibility.\n *\n * @example\n * <SharedWebSocketProvider url=\"wss://api.example.com/ws\" options={{ auth: getToken }}>\n *   <App />\n * </SharedWebSocketProvider>\n */\nexport interface SharedWebSocketProviderProps {\n  url: string;\n  options?: SharedWebSocketOptions;\n  children: ReactNode;\n}\n\n/**\n * Provider component — owns one SharedWebSocket for its lifetime via an external\n * store. The instance is created on mount (connect runs once) and disposed on\n * unmount. `useSharedWebSocket()` is `null` until the instance exists.\n */\nexport function SharedWebSocketProvider({ url, options, children }: SharedWebSocketProviderProps) {\n  // One store per provider. Locked to the first url/options — remount the\n  // provider (e.g. via a `key`) to target a different endpoint.\n  const storeRef = useRef<SocketStore | null>(null);\n  storeRef.current ??= createSocketStore(url, options);\n\n  const socket = useSyncExternalStore(\n    storeRef.current.subscribe,\n    storeRef.current.getSnapshot,\n    storeRef.current.getServerSnapshot,\n  );\n\n  return createElement(SharedWSContext.Provider, { value: socket }, children);\n}\n\n/**\n * Access the SharedWebSocket instance from context. Returns `null` until the\n * provider's instance is connected (first render and SSR). Feature hooks\n * (`useSocketEvent`, `useChannel`, …) handle the null internally; for imperative\n * call sites that need the instance, use {@link useSharedWebSocketOrThrow}.\n *\n * @example\n * const ws = useSharedWebSocket();\n * if (ws) ws.send('chat.message', { text: 'Hello' });\n */\nexport function useSharedWebSocket(): SharedWebSocket | null {\n  return useContext(SharedWSContext);\n}\n\n/**\n * Like {@link useSharedWebSocket} but asserts the instance exists. Use only at\n * imperative call sites that run after the provider has mounted (event handlers,\n * effects) — calling it during the first render will throw, since the socket is\n * not created until commit.\n *\n * @example\n * function SendButton() {\n *   const ws = useSharedWebSocketOrThrow();\n *   return <button onClick={() => ws.send('ping', {})}>Ping</button>;\n * }\n */\nexport function useSharedWebSocketOrThrow(): SharedWebSocket {\n  const socket = useContext(SharedWSContext);\n  if (!socket) {\n    throw new Error(\n      'useSharedWebSocketOrThrow: no connected SharedWebSocket. It is null until the provider mounts — ' +\n        'use it in event handlers/effects, or call useSharedWebSocket() and handle null.',\n    );\n  }\n  return socket;\n}\n","import { useEffect, useState, useEffectEvent } from 'react';\nimport { useSharedWebSocket } from './context';\n\n/**\n * Reactive auth state with authenticate/deauthenticate actions.\n * Syncs across all tabs via BroadcastChannel. No-ops while the socket is null.\n *\n * @example\n * function Header() {\n *   const { isAuthenticated, deauthenticate } = useSocketAuth();\n *   return isAuthenticated\n *     ? <button onClick={deauthenticate}>Logout</button>\n *     : <Link to=\"/login\">Login</Link>;\n * }\n */\nexport function useSocketAuth(): {\n  isAuthenticated: boolean;\n  authenticate: (token: string) => void;\n  deauthenticate: () => void;\n} {\n  const socket = useSharedWebSocket();\n  const [isAuthenticated, setIsAuthenticated] = useState(() => socket?.isAuthenticated ?? false);\n\n  const onAuthChange = useEffectEvent((authenticated: boolean) => {\n    setIsAuthenticated(authenticated);\n  });\n\n  useEffect(() => {\n    if (!socket) return;\n    setIsAuthenticated(socket.isAuthenticated); // sync current state when the socket attaches\n    return socket.onAuthChange(onAuthChange);\n  }, [socket]);\n\n  const authenticate = useEffectEvent((token: string) => {\n    socket?.authenticate(token);\n  });\n\n  const deauthenticate = useEffectEvent(() => {\n    socket?.deauthenticate();\n  });\n\n  return { isAuthenticated, authenticate, deauthenticate };\n}\n","import { useEffect, useState, useEffectEvent } from 'react';\nimport { useSharedWebSocket } from './context';\nimport type { EventHandler } from '../../types';\n\n/**\n * Subscribe to a WebSocket event.\n * - Without callback: returns the latest received value (reactive state).\n * - With callback: calls your handler on each event (stable ref via useEffectEvent).\n *\n * Subscription attaches automatically once the socket is ready (no-op while null).\n *\n * @example\n * const order = useSocketEvent<Order>('order.created');\n *\n * @example\n * useSocketEvent<Order>('order.created', (order) => playSound('new-order'));\n */\nexport function useSocketEvent<T>(event: string, callback?: (data: T, raw?: unknown) => void): T | undefined {\n  const socket = useSharedWebSocket();\n  const [value, setValue] = useState<T | undefined>(undefined);\n\n  const onEvent = useEffectEvent((data: T, raw?: unknown) => {\n    if (callback) {\n      callback(data, raw);\n    } else {\n      setValue(data);\n    }\n  });\n\n  useEffect(() => {\n    if (!socket) return;\n    return socket.on(event, onEvent as EventHandler);\n  }, [socket, event]);\n\n  return callback ? undefined : value;\n}\n\n/**\n * Accumulate WebSocket events into an array.\n * - Without callback: returns accumulated array (reactive state).\n * - With callback: calls your handler on each event, you manage your own state.\n *\n * @example\n * const messages = useSocketStream<ChatMessage>('chat.message');\n *\n * @example\n * useSocketStream<ChatMessage>('chat.message', (msg) =>\n *   setMessages((prev) => [msg, ...prev].slice(0, 50)),\n * );\n */\nexport function useSocketStream<T>(event: string, callback?: (data: T, raw?: unknown) => void): T[] {\n  const socket = useSharedWebSocket();\n  const [items, setItems] = useState<T[]>([]);\n\n  const onEvent = useEffectEvent((data: T, raw?: unknown) => {\n    if (callback) {\n      callback(data, raw);\n    } else {\n      setItems((prev) => [...prev, data]);\n    }\n  });\n\n  useEffect(() => {\n    if (!socket) return;\n    if (!callback) setItems([]);\n    return socket.on(event, onEvent as EventHandler);\n  }, [socket, event]);\n\n  return callback ? [] : items;\n}\n\n/**\n * Subscribe to a WebSocket event with just a callback — no state, no return value.\n * Fire-and-forget: side effects, logging, analytics, sounds, browser notifications.\n *\n * @example\n * useSocketCallback<Order>('order.created', (order) => playSound('new-order'));\n */\nexport function useSocketCallback<T>(event: string, callback: (data: T, raw?: unknown) => void): void {\n  const socket = useSharedWebSocket();\n\n  const handler = useEffectEvent((data: T, raw?: unknown) => {\n    callback(data, raw);\n  });\n\n  useEffect(() => {\n    if (!socket) return;\n    return socket.on(event, handler as EventHandler);\n  }, [socket, event]);\n}\n","import { useEffect, useState, useEffectEvent } from 'react';\nimport { useSharedWebSocket } from './context';\n\n/**\n * Two-way state sync across browser tabs.\n * - Without callback: returns [value, setter] (like useState but synced).\n * - With callback: calls your handler when any tab updates this key.\n *\n * While the socket is null the setter updates local state only; it broadcasts\n * once the socket is ready.\n *\n * @example\n * const [cart, setCart] = useSocketSync<Cart>('cart', { items: [] });\n */\nexport function useSocketSync<T>(\n  key: string,\n  initialValue: T,\n  callback?: (value: T) => void,\n): [T, (value: T) => void] {\n  const socket = useSharedWebSocket();\n  const [value, setValue] = useState<T>(() => socket?.getSync<T>(key) ?? initialValue);\n\n  const onSync = useEffectEvent((synced: T) => {\n    setValue(synced);\n    callback?.(synced);\n  });\n\n  useEffect(() => {\n    if (!socket) return;\n    return socket.onSync<T>(key, onSync);\n  }, [socket, key]);\n\n  const setAndSync = useEffectEvent((newValue: T) => {\n    setValue(newValue);\n    socket?.sync(key, newValue);\n  });\n\n  return [value, setAndSync];\n}\n","import { useEffect, useState, useEffectEvent } from 'react';\nimport { useSharedWebSocket } from './context';\nimport type { TabRole, SocketLifecycleHandlers } from '../../types';\n\n/**\n * Reactive connection status. Reports `false`/`'follower'` while the socket is\n * null, then tracks the live instance once it is ready.\n *\n * @example\n * const { connected, tabRole } = useSocketStatus();\n */\nexport function useSocketStatus(): {\n  connected: boolean;\n  tabRole: TabRole;\n  isAuthenticated: boolean;\n} {\n  const socket = useSharedWebSocket();\n  const [connected, setConnected] = useState(() => socket?.connected ?? false);\n  const [tabRole, setTabRole] = useState<TabRole>(() => socket?.tabRole ?? 'follower');\n  const [isAuthenticated, setIsAuthenticated] = useState(() => socket?.isAuthenticated ?? false);\n\n  const tick = useEffectEvent(() => {\n    setConnected(socket?.connected ?? false);\n    setTabRole(socket?.tabRole ?? 'follower');\n    setIsAuthenticated(socket?.isAuthenticated ?? false);\n  });\n\n  useEffect(() => {\n    if (!socket) return;\n    tick();\n    const interval = setInterval(tick, 1000);\n    return () => clearInterval(interval);\n  }, [socket]);\n\n  return { connected, tabRole, isAuthenticated };\n}\n\n/**\n * Lifecycle hooks — react to connection state changes. Wires up once the socket\n * is ready (no-op while null).\n *\n * @example\n * useSocketLifecycle({\n *   onConnect: () => console.log('Connected!'),\n *   onError: (err) => reportError(err),\n * });\n */\nexport function useSocketLifecycle(handlers: SocketLifecycleHandlers): void {\n  const socket = useSharedWebSocket();\n\n  const onConnect = useEffectEvent(() => handlers.onConnect?.());\n  const onDisconnect = useEffectEvent(() => handlers.onDisconnect?.());\n  const onReconnecting = useEffectEvent(() => handlers.onReconnecting?.());\n  const onReconnectFailed = useEffectEvent(() => handlers.onReconnectFailed?.());\n  const onLeaderChange = useEffectEvent((isLeader: boolean) => handlers.onLeaderChange?.(isLeader));\n  const onError = useEffectEvent((error: unknown) => handlers.onError?.(error));\n  const onActive = useEffectEvent(() => handlers.onActive?.());\n  const onInactive = useEffectEvent(() => handlers.onInactive?.());\n  const onVisibilityChange = useEffectEvent((isActive: boolean) => handlers.onVisibilityChange?.(isActive));\n  const onAuthChange = useEffectEvent((authenticated: boolean) => handlers.onAuthChange?.(authenticated));\n\n  useEffect(() => {\n    if (!socket) return;\n    const unsubs = [\n      socket.onConnect(onConnect),\n      socket.onDisconnect(onDisconnect),\n      socket.onReconnecting(onReconnecting),\n      socket.onReconnectFailed(onReconnectFailed),\n      socket.onLeaderChange(onLeaderChange),\n      socket.onError(onError),\n      socket.onActive(onActive),\n      socket.onInactive(onInactive),\n      socket.onVisibilityChange(onVisibilityChange),\n      socket.onAuthChange(onAuthChange),\n    ];\n    return () => unsubs.forEach((u) => u());\n  }, [socket]);\n}\n\n/**\n * Reactive reconnect state with a manual `reconnect` action. Use this to\n * power a \"Reconnect\" snackbar/banner after auto-reconnect gives up.\n *\n * @example\n * const { hasFailed, reconnect } = useSocketReconnect();\n */\nexport function useSocketReconnect(): {\n  hasFailed: boolean;\n  reconnect: () => void;\n} {\n  const socket = useSharedWebSocket();\n  const [hasFailed, setHasFailed] = useState(false);\n\n  const onFailed = useEffectEvent(() => setHasFailed(true));\n  const onConnected = useEffectEvent(() => setHasFailed(false));\n\n  useEffect(() => {\n    if (!socket) return;\n    const unsubs = [\n      socket.onReconnectFailed(onFailed),\n      socket.onConnect(onConnected),\n    ];\n    return () => unsubs.forEach((u) => u());\n  }, [socket]);\n\n  const reconnect = useEffectEvent(() => {\n    setHasFailed(false);\n    socket?.reconnect();\n  });\n\n  return { hasFailed, reconnect };\n}\n","import { useEffect, useState } from 'react';\nimport { useSharedWebSocket } from './context';\nimport type { Channel } from '../../types';\n\n/**\n * Subscribe to a private channel. Joins once the socket is ready, leaves on\n * unmount. Returns `null` until the channel is joined.\n *\n * @example\n * const chat = useChannel('chat:room_123');\n * const message = useSocketEvent('chat:room_123:message');\n * chat?.send('message', { text: 'Hello' });\n */\nexport function useChannel(name: string, options?: { auth?: boolean }): Channel | null {\n  const socket = useSharedWebSocket();\n  const [channel, setChannel] = useState<Channel | null>(null);\n\n  useEffect(() => {\n    if (!socket) return;\n    const ch = socket.channel(name, options);\n    setChannel(ch);\n    return () => {\n      ch.leave();\n      setChannel(null);\n    };\n  }, [socket, name]);\n\n  return channel;\n}\n\n/**\n * Subscribe to server-side topics. Subscribes once the socket is ready,\n * unsubscribes on unmount.\n *\n * @example\n * useTopics(['notifications:orders', 'notifications:payments']);\n */\nexport function useTopics(topics: string[], options?: { auth?: boolean }): void {\n  const socket = useSharedWebSocket();\n\n  useEffect(() => {\n    if (!socket) return;\n    topics.forEach((t) => socket.subscribe(t, options));\n    return () => topics.forEach((t) => socket.unsubscribe(t));\n  }, [socket, topics.join(',')]);\n}\n\n/**\n * Enable browser push notifications for an event. Activates once the socket is\n * ready, cleans up on unmount.\n *\n * @example\n * usePush('order.created', {\n *   title: (order) => `New Order #${order.id}`,\n *   body: (order) => `$${order.total}`,\n * });\n */\nexport function usePush<T = unknown>(\n  event: string,\n  config: {\n    title: string | ((data: T) => string);\n    body?: string | ((data: T) => string);\n    icon?: string;\n    tag?: string | ((data: T) => string);\n    leaderOnly?: boolean;\n    onlyWhenHidden?: boolean;\n    onClick?: (data: T) => void;\n  },\n): void {\n  const socket = useSharedWebSocket();\n\n  useEffect(() => {\n    if (!socket) return;\n    return socket.push<T>(event, config);\n  }, [socket, event]);\n}\n"]}