Stores are schema-driven key-value stores that sync across all connected clients in real time. Define a schema, and the SDK gives you fully typed CRUD operations with automatic validation and real-time change events.
Access stores via client.stores.<storeName>.
Schema Definition
Define your store schemas using defineStores() from @collab-kit/utils and pass to the client constructor:
import { defineStores } from '@collab-kit/utils';
const stores = defineStores({
tasks: {
title: { type: 'string', required: true },
completed: { type: 'boolean', default: false },
assignee: { type: 'string' },
},
settings: {
theme: { type: 'string', required: true, default: 'light' },
fontSize: { type: 'number', required: true, default: 14 },
notifications: { type: 'boolean', default: true },
},
});
const client = new CollabKitClient({
serverUrl: 'https://api.collab-kit.com',
authToken: '<jwt>',
stores,
});
| Option | Type | Description |
|---|
type | 'string' | 'number' | 'boolean' | The primitive type of the field |
required | boolean | If true, the field must be present on set. Defaults to false |
default | string | number | boolean | Default value applied when the field is missing on set |
Methods
Add Entry
set({ key, value })
Create or overwrite an entry. Required fields (without defaults) must be provided:
await client.stores.tasks.set({
key: 'task-1',
value: { title: 'Build stores feature', assignee: 'user-001' },
});
// 'completed' defaults to false (from schema)
Get Entry
get({ key })
Fetch a single entry by key. Returns null if the key doesn’t exist:
const task = await client.stores.tasks.get({ key: 'task-1' });
// { title: 'Build stores feature', completed: false, assignee: 'user-001' } | null
Get All Entries
getAll()
Fetch all entries in the store:
const all = await client.stores.tasks.getAll();
// [{ key: 'task-1', value: { title: '...', completed: false, assignee: '...' } }]
Update Entry
update({ key, value })
Partially update an existing entry. Only the provided fields are validated and merged:
await client.stores.tasks.update({
key: 'task-1',
value: { completed: true },
});
// Only 'completed' is updated; 'title' and 'assignee' remain unchanged
Delete Entry
delete({ key })
Delete an entry by key:
await client.stores.tasks.delete({ key: 'task-1' });
Sync Store
sync()
Force a full sync of the store from the server:
await client.stores.tasks.sync();
Events
You can listen to changes made to a store like so:
client.stores.tasks.on('changed', (event) => {
console.log(event.key); // 'task-1'
console.log(event.action); // 'set' | 'update' | 'delete'
console.log(event.value); // the new value (or null on delete)
});
// Alternatively, subscribe to a specific key
client.stores.tasks.on('task-1', (value) => {
console.log('task-1 changed:', value);
});
| Event | Payload | Description |
|---|
changes | { key: string, action: 'set' | 'update' | 'delete', value: T | null } | Store changes along with the action |
<store-key> | T | Value as defined in the store schema |
Store events fire for changes made by other clients. Your own set/update/delete calls resolve with the new value directly.
Validation
The client validates values against the schema before sending them to the server:
set: All required fields (without default) must be provided. Default values are applied for missing fields that have defaults.
update: Only provided fields are validated against their schema types.
- Type checking: Values must match the declared
type (string, number, or boolean).
If validation fails, the operation throws an error before making a network request.
Examples
Task Store
import CollabKitClient from '@collab-kit/client';
import { defineStores } from '@collab-kit/utils';
const stores = defineStores({
tasks: {
title: { type: 'string', required: true },
completed: { type: 'boolean', default: false },
assignee: { type: 'string' },
},
});
// Listen for changes from other clients
client.stores.tasks.on('changed', ({ key, action, value }) => {
console.log(`[${action}] ${key}:`, value);
renderTaskList();
});
// Create a task
await client.stores.tasks.set({
key: 'task-1',
value: { title: 'Ship v1' },
});
// Mark complete
await client.stores.tasks.update({
key: 'task-1',
value: { completed: true },
});