Skip to content
Homeostate

Core

@homeostate/core

State-manager and CRDT-backend agnostic sync engine between a store adapter and a CrdtBackend

@homeostate/core@0.1.1npmSource
Warning

Draft / placeholder release. 0.0.0 reserves the name while the API is still being designed. Nothing here is stable — do not depend on it yet.

State-manager and CRDT-backend agnostic sync engine. It keeps a store, reached through a StoreAdapter, in sync with a CrdtBackend such as @homeostate/crdt-yjs, @homeostate/crdt-loro, or @homeostate/crdt-automerge.

Install

npm install @homeostate/core @homeostate/crdt-yjs yjs

@homeostate/core has no runtime dependencies; pick a backend package for the CRDT library you use.

Usage

import { createSyncEngine } from "@homeostate/core";
import { createYjsBackend } from "@homeostate/crdt-yjs";

const engine = createSyncEngine(createYjsBackend(doc, "shared"), adapter, {
  seed: "if-empty",
});
engine.connect();

createMemoryBackend() is a plain-JSON backend without replication, meant for tests. getChanges is exported so a backend can turn a write(next) into fine-grained operations.

Connecting

connect() reconciles the store and the backend per key, over the view the filter allows:

  • A key the backend holds wins over the store's value, so a peer joining a populated room adopts it rather than overwriting it.
  • A synced key the backend does not hold stays in the store. With the default seed: 'if-empty' those keys are written into the backend in one write; with seed: 'never' they are left to the next local change.
  • Keys the filter excludes are never read into the store and never written out.

Afterwards the backend owns the synced document: each local change replaces it with the store's filtered state, and a key removed from the backend is removed from the store. A reconnect adopts the backend again, so edits made while disconnected are dropped unless they are still in the store's local-only keys.

See the repository for the full workspace, store adapters, and a runnable playground.