import { PeerChannel } from '@noy-db/by-peer'; export { PeerChannel } from '@noy-db/by-peer'; import { NoydbMesh } from '@noy-db/hub/by'; /** * **@noy-db/by-tabs** real-time {@link NoydbMesh} — a drain-barrier * transport over a {@link PeerChannel} (BroadcastChannel between tabs). * * The kernel defines the {@link NoydbMesh} port (#469); the store * default polls `_meta/schema-fence`, but a multi-tab app can inject this * push-based provider so a schema cutover fences **instantly** instead of via * store polling. The migration cutover and `@klum-db/lobby` both drive the same * port through `mesh`, so neither names `by-tabs`. * * ## Shared core * * The protocol (JSON `co-fence`/`co-presence` envelopes, per-vault fence + * presence maps, local-update-before-broadcast, prune-on-read) is transport * agnostic — it is **identical** for a BroadcastChannel tab and a WebRTC peer. * To stay DRY, that core lives once in `@noy-db/by-peer` as * `channelMesh`; `byTabs` is a thin, named delegation. See * that module for the wire protocol and local-echo notes. * * @module */ /** * Build a real-time {@link NoydbMesh} backed by a {@link PeerChannel} * (a BroadcastChannel between tabs of the same origin). * * Delegates to the shared `channelMesh` core in `@noy-db/by-peer` — the * by-tabs and by-peer transports run the identical drain-barrier protocol, so * the logic is not duplicated. Pass it as * `createNoydb({ mesh: byTabs(ch) })`, or drive it * directly via `runDrainBarrier`. */ declare function byTabs(channel: PeerChannel): NoydbMesh; /** * **@noy-db/by-tabs** — BroadcastChannel multi-tab transport for noy-db. * * Wraps the browser `BroadcastChannel` API as a `PeerChannel`, the * primitive every `by-*` transport implements. Sub-millisecond fan-out * across tabs of the same origin; same code shape as `@noy-db/by-peer`, * just a different wire. * * Compose with `peerStore()` / `servePeerStore()` from `@noy-db/by-peer` * for an asymmetric tab-as-remote-store topology, or use the channel * directly to publish change events to every other tab. * * ## Threat model * * - `BroadcastChannel` is same-origin by browser policy — only documents * served from the same scheme + host + port can subscribe. * - noy-db already encrypts at rest — every tab on the channel sees * only AES-256-GCM ciphertext envelopes. The transport never decrypts. * - Untrusted tabs (e.g. third-party iframes that share an origin via * `document.domain` legacy) can still see the channel. Treat * BroadcastChannel as origin-scoped, not session-scoped. * * @packageDocumentation */ /** * Options for `tabsChannel()`. */ interface TabsChannelOptions { /** * BroadcastChannel name. Two tabs subscribed to the same name see * each other's messages. Use a stable, vault-scoped string like * `'noy-db:vault-acme'` to keep different vaults isolated. */ readonly name: string; } /** * Wrap a `BroadcastChannel` as a `PeerChannel`. * * Returns a no-op channel (always `isOpen: false`, no-op `send`) when * `BroadcastChannel` is undefined — so server-side rendering, Node * scripts, and older browsers can import the package without crashing * before they feature-detect. */ declare function tabsChannel(options: TabsChannelOptions): PeerChannel; /** * Whether `BroadcastChannel` is available in the current runtime. Use * this as a pre-flight before rendering UI that relies on tab-to-tab * sync — Node, SSR, and a handful of older browsers don't ship it. */ declare function isTabsChannelAvailable(): boolean; export { type TabsChannelOptions, byTabs, isTabsChannelAvailable, tabsChannel };