Reliable state synchronization between multiple windows/processes (e.g. Tauri multi-window).
You provide:
- a subscriber (an invalidation signal: “something changed, refresh!”)
- a provider (fetches a snapshot:
{ revision, data }) - an applier (applies the snapshot to your local state)
state-sync provides:
- a small engine that handles common hard parts: coalescing, retry hooks, lifecycle, and avoiding many race conditions around refresh/apply.
- What is this?
- How it works (concepts)
- Packages
- Install
- Quickstart (core)
- Quickstart (Tauri)
- Quickstart (Pinia)
- Docs & examples
- Development
- Rust crate
- License
state-sync is a framework-agnostic, transport-agnostic way to keep one logical piece of state consistent across multiple runtimes.
Typical use cases:
- Tauri: sync settings/auth/cache between windows
- Web: sync state between tabs/iframes (planned via BroadcastChannel/adapters)
- Any IPC where you can emit an invalidation + fetch a snapshot
Non-goals:
- Realtime CRDT merging or fine-grained patches. The model here is “invalidate → fetch canonical snapshot → apply”.
- Topic: string identifier for a resource (
'settings','profile','cache:user:123') - Revision: monotonic-ish version identifier for ordering (string)
- Invalidation event: “your snapshot may be stale” (subscriber emits these)
- Snapshot provider: returns an envelope
{ revision, data } - Applier: takes the snapshot and mutates your local state
If invalidations come in fast (or the transport drops/duplicates), the engine aims to behave well:
- it coalesces refresh requests
- it keeps a consistent lifecycle (
start(),stop(),refresh()) - it exposes structured error hooks to help observe retry/refresh failures
| Package | What it is |
|---|---|
@statesync/core |
Engine + revision protocol + types |
@statesync/pinia |
Pinia snapshot applier adapter |
@statesync/tauri |
Tauri transport adapters (subscriber + provider) |
npm install @statesync/core
# optional adapters:
npm install @statesync/pinia
npm install @statesync/tauriimport { createConsoleLogger, createRevisionSync } from '@statesync/core';
const handle = createRevisionSync({
topic: 'settings',
subscriber: myInvalidationSubscriber, // emits “changed” events
provider: mySnapshotProvider, // returns { revision, data }
applier: {
apply(snapshot) {
// snapshot.data is your payload
console.log('Apply:', snapshot.revision, snapshot.data);
},
},
logger: createConsoleLogger({ debug: true }),
onError(ctx) {
// ctx.phase: 'subscribe' | 'getSnapshot' | 'apply' | ...
console.error(`[${ctx.phase}]`, ctx.error);
},
});
await handle.start();Use Tauri events for invalidation and invoke for snapshots.
import { createRevisionSync } from '@statesync/core';
import {
createTauriInvalidationSubscriber,
createTauriSnapshotProvider,
} from '@statesync/tauri';
import { listen } from '@tauri-apps/api/event';
import { invoke } from '@tauri-apps/api/core';
const handle = createRevisionSync({
topic: 'settings',
subscriber: createTauriInvalidationSubscriber({
listen,
eventName: 'state-sync:invalidation',
}),
provider: createTauriSnapshotProvider({
invoke,
commandName: 'get_snapshot',
args: { topic: 'settings' },
}),
applier: myApplier,
});
await handle.start();Apply snapshots directly into a Pinia store.
import { createRevisionSync } from '@statesync/core';
import { createPiniaSnapshotApplier } from '@statesync/pinia';
const handle = createRevisionSync({
topic: 'settings',
subscriber: mySubscriber,
provider: myProvider,
applier: createPiniaSnapshotApplier({
store: myPiniaStore,
// mode: 'replace' | 'merge' (see docs)
}),
});
await handle.start();- Getting started:
docs/guide/quickstart.md - Protocol:
docs/guide/protocol.md - Multi-window guide:
docs/guide/multi-window.md - Lifecycle contract:
docs/lifecycle.md - Compatibility:
docs/compatibility.md - Troubleshooting:
docs/troubleshooting.md - Examples:
docs/examples/ - Release checklist:
docs/release-checklist.md
Also see package-specific READMEs:
packages/core/README.mdpackages/pinia/README.mdpackages/tauri/README.md
pnpm install
pnpm lint
pnpm typecheck
pnpm test
pnpm buildThe crates/state-sync directory contains an experimental Rust crate.
It is not part of the npm release and is versioned independently.
cd crates/state-sync
cargo fmt
cargo clippy --all-targets -- -D warnings
cargo testMIT (see LICENSE).