tabs
@noy-db/by-tabs·pnpm add @noy-db/by-tabs @noy-db/by-peer @noy-db/hubSub-millisecond fan-out between tabs of the same browser origin over the nativeBroadcastChannelAPI.
What it does
@noy-db/by-tabs wraps the browser's BroadcastChannel as a PeerChannel — the same channel shape every other by-* transport implements — so it composes with peerStore() / servePeerStore() from @noy-db/by-peer. One tab serves its store over the channel; the others operate on it live instead of each maintaining their own round-trip to IndexedDB. isTabsChannelAvailable() is a pre-flight check: it returns false under SSR or Node, or in older browsers, where tabsChannel() falls back to a no-op channel (isOpen stays false, send() throws) so importing code doesn't crash before feature-detecting.
BroadcastChannel is same-origin by browser policy — only documents on the same scheme + host + port can subscribe. noy-db already encrypts at rest, so every tab on the channel sees AES-256-GCM ciphertext envelopes only; treat the channel as origin-scoped, not session-scoped, since untrusted same-origin iframes can still subscribe.
Usage
import { tabsChannel, isTabsChannelAvailable } from '@noy-db/by-tabs'
import { peerStore, servePeerStore } from '@noy-db/by-peer'
if (!isTabsChannelAvailable()) {
// Node, SSR, or an older browser — fall back to direct store access.
}
// Tab A — proxy operations to Tab B's store.
const channel = tabsChannel({ name: 'noy-db:vault-acme' })
const remote = peerStore({ channel })
// Tab B — answer the RPC calls against its local store.
servePeerStore({ channel: tabsChannel({ name: 'noy-db:vault-acme' }), store: localStore })