API overview
Core surface of worker-sync-db. Types are inferred from your schema via defineSchema.
createDatabase(options)
function createDatabase<S extends CollectionSchema>(
options: CreateDatabaseOptions<S>,
): Promise<DatabaseClient<S>>;CreateDatabaseOptions
| Option | Type | Required | Description |
|---|---|---|---|
schema | S extends CollectionSchema | yes | Collection definitions |
dbName | string | yes | SharedWorker name + IndexedDB name |
sharedWorker | string | URL | recommended | URL to shared-worker bundle |
dedicatedWorker | string | URL | recommended | URL to dedicated-worker bundle |
mode | 'auto' | 'shared' | 'dedicated' | no | Default 'auto' |
remote | RemoteSyncAdapter | FetchSyncConfig | no | Enables sync |
onConflict | (conflict) => void | no | Push conflicts (delegate adapter) |
Throws if window is undefined (SSR).
Worker URL exports
import { sharedWorkerUrl, dedicatedWorkerUrl } from 'worker-sync-db';URL objects pointing at dist/shared-worker/entry.js and dist/dedicated-worker/entry.js. Used as defaults when sharedWorker / dedicatedWorker are omitted.
DatabaseClient<S>
get(collection, id)
get<C extends keyof S & string>(
collection: C,
id: string,
): Promise<InferDoc<S, C> | null>;Returns the document or null if missing or soft-deleted.
put(collection, doc)
put<C extends keyof S & string>(
collection: C,
doc: Record<string, unknown> & { id: string },
): Promise<InferDoc<S, C>>;Upserts a document. Adds _version, _updatedAt. Enqueues a sync op when remote is set. Notifies all subscribed tabs.
delete(collection, id)
delete<C extends keyof S & string>(
collection: C,
id: string,
): Promise<InferDoc<S, C>>;Soft-deletes (_deleted: true). Returns the updated document or throws NotFound.
query(collection, opts?)
query<C extends keyof S & string>(
collection: C,
opts?: QueryOptions,
): Promise<InferDoc<S, C>[]>;QueryOptions | Description |
|---|---|
index | Index name from schema |
range | IDBKeyRangeInit: both bounds → only/bound; only lower → lowerBound; only upper → upperBound |
limit | Maximum number of results |
includeDeleted | Include soft-deleted documents |
subscribe(collection, listener, filter?)
subscribe<C extends keyof S & string>(
collection: C,
listener: (event: ChangeEvent<InferDoc<S, C>>) => void,
filter?: { field: string; value: unknown },
): () => void;ChangeEvent:
{
type: 'put' | 'delete';
collection: string;
doc: T | null; // null on delete
id: string;
}Returns an unsubscribe function. Register in every tab that should receive live updates.
Optional filter limits worker fan-out to puts where doc[field] === value (deletes are not delivered when a filter is set). The filter is taken from the first subscriber for that collection in the tab.
Also receives changes applied from remote pull (not only local multi-tab writes).
syncNow()
syncNow(): Promise<SyncStatus>;Pushes pending operations, then pulls remote changes. No-op queue flush if remote is not configured.
getSyncStatus() / onSyncStatusChange(listener)
interface SyncStatus {
pending: number;
lastSyncAt: number | null;
lastError: string | null;
online: boolean;
}close()
Sends disconnect, closes the port, rejects in-flight RPCs.
Types
defineSchema / CollectionSchema
type CollectionSchema = Record<
string,
{ keyPath: string; indexes?: Record<string, string> }
>;
function defineSchema<S extends CollectionSchema>(schema: S): S;DocumentMeta
interface DocumentMeta {
id: string;
_version: number;
_updatedAt: number;
_deleted?: boolean;
}Sync adapters
interface RemoteSyncAdapter {
pull(cursor: string | null): Promise<{
changes: RemoteChange[];
nextCursor: string | null;
}>;
push(ops: PendingOp[]): Promise<{
applied: string[];
conflicts?: Conflict[];
}>;
}
interface FetchSyncConfig {
pullUrl: string;
pushUrl: string;
headers?: Record<string, string>;
}Errors
DatabaseError with code:
| Code | Meaning |
|---|---|
NotFound | Document missing on delete |
WorkerDead | SharedWorker / Worker failed to load |
SchemaMismatch | Different schema for same dbName |
NotConnected | Port closed |
Timeout | RPC exceeded timeout (default 30s) |
InvalidRequest | Unknown request or aborted |
StorageError | IndexedDB / sync failure |
Low-level API
For advanced integration without createDatabase:
connectSharedWorker(options)→PortBridgeconnectDedicatedWorker(options)→PortBridgePortBridge.call(request)— typed RPCPortBridge.onEvent(listener)— worker events
See src/client/PortBridge.ts and src/shared/protocol.ts in the repository.