{"version":3,"sources":["/Users/gwakko/Projects/shared-websocket/dist/chunk-RJKAFACH.cjs","../src/TabSync.ts"],"names":[],"mappings":"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","file":"/Users/gwakko/Projects/shared-websocket/dist/chunk-RJKAFACH.cjs","sourcesContent":[null,"import './utils/disposable';\nimport type { Unsubscribe, Logger } from './types';\n\ninterface SyncMessage {\n  key: string;\n  value: unknown;\n  deleted?: boolean;\n}\n\ninterface TabSyncOptions {\n  /** Enable debug logging (default: false). */\n  debug?: boolean;\n  /** Custom logger (default: console). */\n  logger?: Logger;\n}\n\nconst NOOP_LOGGER: Logger = { debug() {}, info() {}, warn() {}, error() {} };\n\n/**\n * Cross-tab state synchronization via BroadcastChannel.\n * No WebSocket needed — works standalone for sharing state between browser tabs.\n *\n * @example\n * const sync = new TabSync('my-app');\n * sync.set('theme', 'dark');\n * sync.on('theme', (theme) => applyTheme(theme));\n *\n * @example\n * // With debug logging\n * const sync = new TabSync('my-app', { debug: true });\n */\nexport class TabSync implements Disposable {\n  private store = new Map<string, unknown>();\n  private listeners = new Map<string, Set<(value: unknown) => void>>();\n  private bc: BroadcastChannel;\n  private disposed = false;\n  private readonly log: Logger;\n\n  constructor(channel = 'tab-sync', options?: TabSyncOptions) {\n    this.log = options?.debug ? (options.logger ?? console) : NOOP_LOGGER;\n    this.log.debug('[TabSync] init', { channel });\n    this.bc = new BroadcastChannel(channel);\n    this.bc.onmessage = (ev: MessageEvent<SyncMessage>) => {\n      const { key, value, deleted } = ev.data;\n      if (deleted) {\n        this.store.delete(key);\n        this.log.debug('[TabSync] ← remote delete', key);\n      } else {\n        this.store.set(key, value);\n        this.log.debug('[TabSync] ← remote set', key, value);\n      }\n      this.emit(key, value);\n    };\n  }\n\n  /** Set a value and broadcast to all tabs. Local listeners also fire. */\n  set<T>(key: string, value: T): void {\n    this.store.set(key, value);\n    this.bc.postMessage({ key, value } satisfies SyncMessage);\n    this.log.debug('[TabSync] → set', key, value);\n    this.emit(key, value);\n  }\n\n  /** Get current value from local store. */\n  get<T>(key: string): T | undefined {\n    return this.store.get(key) as T | undefined;\n  }\n\n  /** Delete a key and broadcast deletion to all tabs. */\n  delete(key: string): void {\n    this.store.delete(key);\n    this.bc.postMessage({ key, value: undefined, deleted: true } satisfies SyncMessage);\n    this.log.debug('[TabSync] → delete', key);\n    this.emit(key, undefined);\n  }\n\n  /** Check if a key exists in the local store. */\n  has(key: string): boolean {\n    return this.store.has(key);\n  }\n\n  /** Get all keys in the local store. */\n  keys(): string[] {\n    return [...this.store.keys()];\n  }\n\n  /** Get number of entries. */\n  get size(): number {\n    return this.store.size;\n  }\n\n  /**\n   * Listen for changes to a key. Fires when any tab (including this one) calls set().\n   *\n   * @example\n   * sync.on('cart', (cart) => updateBadge(cart.items.length));\n   */\n  on<T>(key: string, fn: (value: T) => void): Unsubscribe {\n    let set = this.listeners.get(key);\n    if (!set) {\n      set = new Set();\n      this.listeners.set(key, set);\n    }\n    const wrapper = fn as (value: unknown) => void;\n    set.add(wrapper);\n    return () => set!.delete(wrapper);\n  }\n\n  /** Listen for a key change once, then auto-unsubscribe. */\n  once<T>(key: string, fn: (value: T) => void): Unsubscribe {\n    const unsub = this.on<T>(key, (value) => {\n      unsub();\n      fn(value);\n    });\n    return unsub;\n  }\n\n  /** Clear all keys and notify listeners. */\n  clear(): void {\n    const keys = [...this.store.keys()];\n    this.log.debug('[TabSync] → clear', keys);\n    this.store.clear();\n    for (const key of keys) {\n      this.bc.postMessage({ key, value: undefined, deleted: true } satisfies SyncMessage);\n      this.emit(key, undefined);\n    }\n  }\n\n  /** Dispose — close BroadcastChannel and clear all state. */\n  dispose(): void {\n    this[Symbol.dispose]();\n  }\n\n  private emit(key: string, value: unknown): void {\n    const set = this.listeners.get(key);\n    if (set) {\n      for (const fn of set) fn(value);\n    }\n  }\n\n  [Symbol.dispose](): void {\n    if (this.disposed) return;\n    this.disposed = true;\n    this.bc.close();\n    this.store.clear();\n    this.listeners.clear();\n  }\n}\n"]}