insieme
v2.1.1
Published
An offline-first collaborative library with authoritative server for real-time data synchronization
Downloads
560
Maintainers
Readme
Insieme
Insieme is an offline-first sync library built around an authoritative server. Clients create local drafts, submit them when transport is available, and converge on a server-ordered committed event stream.
TypeScript declaration files are bundled with the package, and the published entry points are split by environment so browser-safe imports stay distinct from Node-only adapters.
Install
bun add insiemeEntry Points
Use the package entry point that matches your runtime.
| Import path | Use for | Includes |
| --- | --- | --- |
| insieme | Portable client surface. Alias of insieme/client. | createSyncClient, client transports, client stores, createReducer |
| insieme/client | Explicit client-only imports. | Same surface as insieme |
| insieme/browser | Browser-explicit imports. | Same surface as insieme/client |
| insieme/node | Node-only client + server work. | Everything in insieme/client, plus createSyncServer, WS server helpers, and Node persistence adapters |
| insieme/server | Backward-compatible server alias. | Same surface as insieme/node |
Quick rule:
- Browser app: import from
insiemeorinsieme/client. - Node client using SQLite: import from
insieme/node. - Sync server: import from
insieme/nodeorinsieme/server.
Client Quick Start
import {
createOfflineTransport,
createInMemoryClientStore,
createSyncClient,
} from "insieme/client";
const clientStore = createInMemoryClientStore();
const transport = createOfflineTransport();
const client = createSyncClient({
transport,
store: clientStore,
token: "jwt",
clientId: "C1",
projectId: "workspace-1",
});
await client.start();
await client.submitEvent({
partition: "workspace-1",
type: "counter.increment",
schemaVersion: 1,
payload: { amount: 1 },
});Attach a real transport later without replacing the client instance:
await transport.setOnlineTransport(realWebSocketTransport);Server Quick Start
import { createInMemorySyncStore, createSyncServer } from "insieme/node";
const serverStore = createInMemorySyncStore();
const server = createSyncServer({
auth: {
verifyToken: async () => ({ clientId: "C1", claims: {} }),
},
authz: {
authorizeProject: async () => true,
},
validation: {
validate: async () => {},
},
store: serverStore,
clock: { now: () => Date.now() },
});Persistence Adapters
Client-side stores:
createInMemoryClientStore()frominsieme/clientfor tests and dev.createIndexedDbClientStore()frominsieme/clientfor browser persistence.createLibsqlClientStore(client)frominsieme/clientfor@libsql/client.createAsyncSqliteClientStore({ driver })frominsieme/clientfor injected async SQLite runtimes such as Tauri-backed adapters.createSqliteClientStore(db)frominsieme/nodeforbetter-sqlite3style SQLite APIs.
Server-side sync stores:
createInMemorySyncStore()frominsieme/node.createLibsqlSyncStore(client)frominsieme/node.createSqliteSyncStore(db)frominsieme/node.
LibSQL example:
import { createClient } from "@libsql/client";
import { createLibsqlClientStore } from "insieme/client";
import { createLibsqlSyncStore } from "insieme/node";
const clientDb = createClient({ url: "file:./insieme-client.db" });
const serverDb = createClient({ url: "file:./insieme-server.db" });
const clientStore = createLibsqlClientStore(clientDb);
const syncStore = createLibsqlSyncStore(serverDb);Materialized Views
Built-in client stores support optional partition-scoped materialized views.
import { createLibsqlClientStore, createReducer } from "insieme/client";
const reducer = createReducer({
schemaHandlers: {
"counter.increment": ({ state, payload }) => {
state.count = (state.count ?? 0) + payload.amount;
},
},
});
const store = createLibsqlClientStore(db, {
materializedViews: [
{
name: "event-count",
version: "1",
initialState: () => ({ count: 0 }),
reduce: reducer,
},
],
});
const view = await store.loadMaterializedView({
viewName: "event-count",
partition: "workspace-1",
});Materialized views update only when a committed event is newly inserted. Duplicate committed deliveries are ignored by the built-in stores.
Subscribe to a hot materialized view partition:
const unsubscribe = await store.subscribeMaterializedView({
viewName: "event-count",
partition: "workspace-1",
onChange: ({ value, lastCommittedId }) => {
console.log(value, lastCommittedId);
},
});Public API Highlights
createSyncClient: project-scoped client runtime (start,submitEvent,syncNow,flushDrafts,stop,close).createSyncServer: authoritative server runtime (attachConnection,shutdown).createOfflineTransport: local-first transport that buffers submits until an online transport is attached.createBrowserWebSocketTransport: browserWebSockettransport adapter.- Built-in client stores: stable inspection (
listDraftsOrdered,listCommitted,listCommittedAfter,getCursor), view subscriptions (subscribeMaterializedView), and explicitclose(). attachWsConnection/createWsServerRuntime: Node WebSocket bridge helpers for the server runtime.createReducer: event-type dispatcher for replay and materialized-view reducers.
Docs
- Docs index
- Package entry points
- JavaScript interface reference
- Client storage model
- Materialized views
- Protocol messages
- Production checklist
Examples
Production-style examples live in examples/real-client-usage.
Ops Helper
Run SQLite integrity checks:
bun run ops:sqlite:integrity -- /path/to/client.db /path/to/server.db