Skip to content
Homeostate

Core

Testing API

In-memory backend and persistence adapter factories for testing sync behavior and document storage without external services.

@homeostate/core@0.3.0npmSource

Import these factories and types from @homeostate/core/testing. They implement the same contracts as production backends and persistence adapters without network or browser storage.

createMemoryBackend

declare const createMemoryBackend: (initial?: unknown) => MemoryBackend;

interface MemoryBackend extends CrdtBackend {
  receive: (next: unknown) => void;
}

Returns a CrdtBackend with an extra receive method. The initial state defaults to {}. Values are copied through JSON, so use plain JSON.

MemberReturnsBehavior
read()unknownA fresh copy of the held state.
write(next)voidReplaces the held state with a copy, without notifying subscribers, and ignores previous. Models the engine's own write.
receive(next)voidReplaces the held state with a copy, then synchronously notifies every subscriber. Models a full snapshot arriving from a peer.
subscribe(callback)UnsubscribeRegisters a callback; the returned function removes it.

Separate memory backends do not exchange state. See the sync engine example for testing local and remote changes together.

memory-backend-example.ts
import { createMemoryBackend } from "@homeostate/core/testing";

const backend = createMemoryBackend({ count: 0 });
let notifications = 0;
const unsubscribe = backend.subscribe(() => {
  notifications++;
});

backend.write({ count: 1 });
console.log(notifications); // 0

backend.receive({ count: 2 });
console.log(backend.read(), notifications); // { count: 2 }, 1

unsubscribe();

createMemoryPersistenceAdapter

declare const createMemoryPersistenceAdapter: () => MemoryPersistenceAdapter;

interface MemoryPersistenceAdapter extends PersistenceAdapter {
  size: (key: string) => number;
}

Returns a PersistenceAdapter with an extra size(key) method. Each call creates independent storage: reuse one adapter to test a document being destroyed and restored, or several documents sharing storage.

MemberReturnsBehavior
load(key)Promise<StoredUpdates>Copies the stored byte arrays and returns their current log version.
append(key, update)Promise<void>Stores a copy of the update.
compact(key, snapshot, version)Promise<void>Replaces entries through version with a copied snapshot, retaining later entries.
clear(key)Promise<void>Removes that key's log.
size(key)numberCounts update entries, not bytes or application records.
memory-persistence-example.ts
import { createMemoryPersistenceAdapter } from "@homeostate/core/testing";

const storage = createMemoryPersistenceAdapter();
await storage.append("room", new Uint8Array([1]));
const loaded = await storage.load("room");

// Another writer appends after the load used for compaction.
await storage.append("room", new Uint8Array([2]));
await storage.compact("room", new Uint8Array([9]), loaded.version);
console.log(storage.size("room")); // 2: the later update and the snapshot

await storage.clear("room");
console.log(await storage.load("room")); // { updates: [], version: 0 }

Source: memory-backend.ts and memory-persistence.ts.