Skip to content

API reference > @kontsedal/olas-cross-tab

olas-cross-tab package ​

Functions ​

Function

Description

crossTabPlugin(options)

Cross-tab cache sync over BroadcastChannel. Mirrors writes and invalidations of opted-in queries across tabs of the same origin.

ts
const userQuery = defineQuery({ id: 'users/detail', …, meta: { crossTab: true } })

createRoot(app, {
  deps,
  queries: queryEngine(),
  plugins: [crossTabPlugin({ channelName: 'my-app/cache/v1' })],
})

Only queries with meta: { crossTab: true } sync, on both the send and the receive side. That covers infinite queries: their pages travel with theirpageParams, so the receiving tab keeps paging from them. Page arrays can be large, and maxPayloadBytes warns about them. Fetches and hydration are a per-tab concern — every tab runs its own fetcher — so they never cross.

**Server safety.** Without a channelFactory, the plugin opens a channel only in a browser tab or a web worker. On a Node, Bun or Deno server, and where BroadcastChannel is not defined, it installs no hooks and the root boots with cross-tab off. A server's BroadcastChannel reaches every root in the process, so per-request roots would otherwise read each other's writes. A channelFactory opens a channel wherever it returns one.

**Non-cloneable data.** BroadcastChannel uses structured clone. Cache data containing a function or a symbol throws aDataCloneError at postMessage. The plugin catches it, callsonWarn(...), and drops the message — the sender's cache is unaffected. A class instance does not throw: it arrives as a plain object, without its prototype.

defaultChannelFactory(name)

Default factory: wraps the platform BroadcastChannel in a browser tab or a web worker. Returns undefined anywhere else, such as on a Node, Bun or Deno server, and where BroadcastChannel is not defined. AchannelFactory passed to crossTabPlugin opens a channel wherever it returns one.

Variables ​

Variable

Description

CROSS_TAB_PLUGIN_NAME

The plugin's name — and the origin stamped on writes it applies from peers.

PROTOCOL_VERSION

Wire protocol for @kontsedal/olas-cross-tab messages. SPEC §13.2.

v (protocol version) and sourceId (unique per root) combine to make the three-layer echo prevention work:

  1. The sender mirrors only the app's own writes: a write the plugin applied from a peer carries the plugin's name as its origin, so it is never sent back. 2. Receiver filters its own sourceId (catches the case where the transport echoes the message back to the sender). 3. Receiver dedupes by (sourceId, msgId) — duplicate or out-of-order messages from the same peer are dropped.

Receivers also drop messages with a v they don't understand. The channel name itself is user-supplied; consumers who want clean cross-deploy isolation should embed a version in their channelName.

Type Aliases ​

Type Alias

Description

ChannelLike

Tiny BroadcastChannel-shaped abstraction. Lets tests inject a fake (a shared in-memory bus across multiple "tabs" in the same process) and keeps server safety in one place: outside a browser, and with nochannelFactory override, the plugin opens no channel and installs no hooks.

CrossTabOptions

Options accepted by crossTabPlugin(...). SPEC §13.2.

InvalidateMessage

What a tab posts when the app invalidates a synced query entry. A receiving tab invalidates the same entry.

Message

A message on the channel, told apart by type.

RelayedSource

The write sources a tab relays. A fetch and a hydration are per tab, and never cross.

SetDataMessage

What a tab posts when the app writes a synced query's data outside a fetch or hydration. A receiving tab applies data to the same entry, as whatsource says it is:

  • 'write' and 'replace' are canonical. The receiver writes the server truth, server.data when the sender's data held a guess and data otherwise, as a patch or as a replace that supersedes its own fetch. - 'optimistic' is a guess. The receiver shows data as a guess of its own, which leaves its stale clock alone and waits for the sender's rollback or commit. - 'rollback' removes that guess. server present means the sender still shows other guesses, and the receiver shows data as one. - 'commit' makes data the receiver's data as a commit does: the guess is committed, and the stale clock is left alone.

Released under the MIT License.