json-crdt-server
Version:
JSON CRDT server and syncing local-first browser client
168 lines (167 loc) • 5.34 kB
TypeScript
export interface StoreBlock {
/** Block ID. */
id: string;
/** Timestamp in (milliseconds) when the block was created. */
ts: number;
/** Timestamp in (milliseconds) when the block was last updated. */
uts: number;
/** The latest snapshot of the block. */
snapshot: StoreSnapshot;
/**
* The latest changes that have been stored, but not yet applied to the the
* latest snapshot.
*/
tip: StoreBatch[];
}
/**
* Represents a state snapshot of a block at a certain point in time.
*/
export interface StoreSnapshot {
/** Block ID. */
id: string;
/** Sequence number. The seq number of the last applied {@link StoreBatch}. */
seq: number;
/** Timestamp in (milliseconds) when the snapshot was created. */
ts: number;
/** The state of the snapshot encoded in algorithm-specific format. */
blob: Uint8Array;
}
/**
* Represents a list of changes to apply to a block.
*/
export interface StoreBatch {
/**
* Server enforced sequence number. The client must provide a sequence number
* that is greater than the current sequence number of the block.
*/
seq: number;
/** Timestamp (in milliseconds) when the batch was processed by the server. */
ts: number;
/** Timestamp (in milliseconds) when the batch was created by the client. */
cts?: number;
/**
* A list of atomic changes to apply to the block.
*/
patches: StorePatch[];
}
/**
* Represents an atomic change unit in algorithm-specific format.
*/
export interface StorePatch {
/** Time (in milliseconds) when the patch was created by the client. */
cts?: number;
/** Client set, optional, user ID, who created the patch. */
uid?: string;
/** The patch contents in algorithm-specific format. */
blob: Uint8Array;
}
export type StoreIncomingSnapshot = Omit<StoreSnapshot, 'ts' | 'uts'>;
export type StoreIncomingBatch = Omit<StoreBatch, 'seq' | 'ts'>;
export interface Store {
/**
* Create a new block.
*
* @param id Block ID.
* @param batch Initial patches to apply to a new block.
* @returns Newly created block data.
*/
create(start: StoreSnapshot, end: StoreSnapshot, batch?: StoreIncomingBatch): Promise<StoreCreateResult>;
/**
* Push changes to an existing block.
*
* @param id Block ID.
* @param batch Patches to apply to the block.
* @returns Updated block data.
*/
push(snapshot: StoreIncomingSnapshot, batch: StoreIncomingBatch): Promise<StorePushResult>;
/**
* Compacts block's history by merging batches until the given sequence number.
*
* @param id Block ID.
* @param to Sequence number until which the start of the block history
* has to be compacted.
* @param advance Callback which performs batch merging.
*/
compact?(id: string, to: number, advance: Advance): Promise<void>;
/**
* Retrieve an existing block.
*
* @param id Block ID.
* @returns Block data, or `undefined` if the block does not exist.
*/
get(id: string): Promise<StoreGetResult | undefined>;
/**
* Retrieve a snapshot at a given sequence number.
*
* @param id Block ID.
* @returns Snapshot and a list of batches to apply to the snapshot to get
* to the state at the given sequence number.
*/
getSnapshot(id: string, seq: number): Promise<{
snapshot: StoreSnapshot;
batches: StoreBatch[];
}>;
/**
* Retrieve the existence of a block.
*
* @param id Block ID.
*/
exists(id: string): Promise<boolean>;
/**
* Retrieve the sequence number of a block.
*
* @param id Block ID.
* @returns Block sequence number, or `undefined` if the block does not exist.
*/
seq(id: string): Promise<number | undefined>;
/**
* Retrieve the history of batches for a block.
*
* @param id Block ID.
* @param min Minimum sequence number.
* @param max Maximum sequence number.
* @returns List of batches.
*/
scan(id: string, min: number, max: number): Promise<StoreBatch[]>;
/**
* Remove a block.
*
* @param id Block ID.
* @returns `true` if the block was removed, `false` if the block did not exist.
*/
remove(id: string): Promise<boolean>;
/**
* Remove all blocks that have not been accessed since the given timestamp.
*
* @param ts Timestamp in milliseconds.
*/
removeAccessedBefore(ts: number, limit: number): Promise<void>;
/**
* Remove a number of oldest blocks, measured by last update time.
*
* @param x Number of oldest blocks to remove.
*/
removeOldest(x: number): Promise<void>;
/**
* Retrieve statistics about the store.
*
* @returns Number of blocks and batches.
*/
stats(): {
blocks: number;
batches: number;
};
stop?(): Promise<void>;
}
export interface StoreCreateResult {
block: StoreBlock;
batch?: StoreBatch;
}
export interface StorePushResult {
snapshot: StoreSnapshot;
batch: StoreBatch;
}
export interface StoreGetResult {
block: StoreBlock;
}
export type Advance = (start: StoreSnapshot['blob'], batches: AsyncIterable<StoreBatch>) => Promise<StoreSnapshot['blob']>;