On this page
Deterministic, transport-neutral optimistic sync. Local rendering is never
blocked: changes queue immediately, while hosts explicitly call sendNext
or retry to perform network work.
Examples
return sync ; // Call sync.destroy() before removing the Grid.
See also
constructor
applyVersionedOperation
destroy
flush
handleResponse
on
pendingCommits
pendingCount
ready
recoverConflict
resumeAfterReload
retry
retryPersistence
send
sendNext
serverVersion
setOnline
state
subscribe
Members 19
constructor
applyVersionedOperation
destroy
flush
handleResponse Public for transports that deliver responses independently of send promises.
on
on : ( listener : SyncListener ) => () => void ;
pendingCommits
pendingCount
ready Resolves after durable work is restored and every startup commit is visible locally.
ready : () => Promise <void> ;
recoverConflict Recover from the outstanding base-version conflict without reloading the document.
Recover from the outstanding base-version conflict without reloading the
document. This succeeds when the pending work and every server version it
did not see change different cells, and neither inserts, deletes, or moves
rows or columns: the local Grid then already shows the server result plus
the pending work, so recovery applies the missed server versions and moves
the pending queue onto the new server version. Call flush afterwards to
send it. In every other case nothing changes and the result names the
reason; the host then reloads and calls resumeAfterReload.
Examples
if ( result . status === "recovered" ) await sync . flush (); // A reload-required result leaves the document unchanged for host recovery.
See also
resumeAfterReload Resume only after the host remounted/reloaded document state and reapplied retained local operations.
Resume only after the host remounted/reloaded document state and reapplied
retained local operations. No lossy structural merge is attempted here.
retry Explicit retry; the original mutation ID and durable record are retained.
retryPersistence
retryPersistence : ( clientMutationId : string ) => Promise < boolean > ;
send
sendNext
serverVersion
setOnline Update connectivity. Reconnection drains durable work in order; going offline aborts in-flight requests so retries retain their mutation IDs.
setOnline : ( online : boolean ) => void ;
state
subscribe
Declaration
View full TypeScript declaration
requestedMutationId ?: string ,
on : ( listener : SyncListener ) => () => void ;
ready : () => Promise < void >;
clientMutationId : string ,
retryPersistence : ( clientMutationId : string ) => Promise < boolean >;
clientMutationId : string ,
setOnline : ( online : boolean ) => void ;
Referenced by
Workspace packages depending on @sheetwrite/core
@sheetwrite/benchdependency
@sheetwrite/docs-startdependency
@sheetwrite/reactdependency
@sheetwrite/sveltedependency
@sheetwrite/vuedependency
@sheetwrite/xlsxdependency
Public exports naming SyncCoordinator
class SyncCoordinator class SyncCoordinator class SyncCoordinator Deterministic, transport-neutral optimistic sync. Local rendering is never blocked: changes queue immediately, while hosts explicitly call sendNext or retry to perform network work. @example import { SyncCoordinator, type Grid, type PersistenceAdapter } from "@sheetwrite/core"; async function connect(grid: Grid, adapter: PersistenceAdapter, documentId: string, serverVersion: number) { const sync = new SyncCoordinator(grid, adapter, { documentId, serverVersion }); await sync.ready(); await sync.flush(); return sync; // Call sync.destroy() before removing the Grid. }@see PersistenceAdapter *@see SyncCoordinator.recoverConflictAPI reference → interface Grid interface Grid interface Grid Imperative grid handle for document commands, events, rendering, and teardown. @example import type { Grid } from "@sheetwrite/core"; function updateTotal(grid: Grid) { const sheet = grid.getActiveSheet(); const result = grid.applyTransaction({ patches: [{ op: "set", addr: { sheet, row: 0, col: 0 }, value: { kind: "literal", value: 42 } }], }); if (result.status === "applied") grid.scrollToCell({ sheet, row: 0, col: 0 }); return grid.aggregate(0, "sum"); }@see createGrid *@see Grid.applyTransactionAPI reference → interface PersistenceAdapter interface PersistenceAdapter interface PersistenceAdapter Host load and commit contract for versioned workbook persistence. @example import { MemoryPersistenceAdapter, type PersistenceAdapter, type WorkbookSnapshot } from "@sheetwrite/core"; async function loadLocal(snapshot: WorkbookSnapshot) { if (!snapshot.documentId) throw new Error("A document ID is required"); const adapter: PersistenceAdapter = new MemoryPersistenceAdapter(snapshot); return adapter.load(snapshot.documentId); }@see MemoryPersistenceAdapter *@see SyncCoordinatorAPI reference → function connect(grid: Grid, adapter: PersistenceAdapter, documentId: string, serverVersion: number): Promise<SyncCoordinator> function connect (
grid : Grid ,
adapter : PersistenceAdapter ,
documentId : string ,
serverVersion : number ,
) : Promise < SyncCoordinator > function connect (
grid : Grid ,
adapter : PersistenceAdapter ,
documentId : string ,
serverVersion : number ,
) : Promise < SyncCoordinator > grid: Grid let grid : Grid let grid : Grid The imperative core grid this controller owns. API reference → serverVersion: number let serverVersion : number let serverVersion : number Last accepted contiguous remote server version. API reference → const sync: SyncCoordinator const sync : SyncCoordinator const sync : SyncCoordinator API reference → new SyncCoordinator(grid: Grid, adapter: PersistenceAdapter, options: SyncCoordinatorOptions): SyncCoordinator new SyncCoordinator (grid: Grid, adapter: PersistenceAdapter, options: SyncCoordinatorOptions): SyncCoordinator new SyncCoordinator (grid: Grid, adapter: PersistenceAdapter, options: SyncCoordinatorOptions): SyncCoordinator Deterministic, transport-neutral optimistic sync. Local rendering is never blocked: changes queue immediately, while hosts explicitly call sendNext or retry to perform network work. @example import { SyncCoordinator, type Grid, type PersistenceAdapter } from "@sheetwrite/core"; async function connect(grid: Grid, adapter: PersistenceAdapter, documentId: string, serverVersion: number) { const sync = new SyncCoordinator(grid, adapter, { documentId, serverVersion }); await sync.ready(); await sync.flush(); return sync; // Call sync.destroy() before removing the Grid. }@see PersistenceAdapter *@see SyncCoordinator.recoverConflictAPI reference → adapter: PersistenceAdapter let adapter : PersistenceAdapter let adapter : PersistenceAdapter API reference → SyncCoordinatorOptions.documentId: string interface SyncCoordinatorOptions {
documentId : string ;
} interface SyncCoordinatorOptions {
documentId : string ;
} API reference → SyncCoordinatorOptions.serverVersion: number interface SyncCoordinatorOptions {
serverVersion : number ;
} interface SyncCoordinatorOptions {
serverVersion : number ;
} Last accepted contiguous remote server version. API reference → SyncCoordinator.ready(): Promise<void> SyncCoordinator. ready (): Promise <void> SyncCoordinator. ready (): Promise <void> Resolves after durable work is restored and every startup commit is visible locally. API reference → SyncCoordinator.flush(): Promise<readonly PersistenceCommitResponse[]> SyncCoordinator. flush (): Promise < readonly PersistenceCommitResponse[] > SyncCoordinator. flush (): Promise < readonly PersistenceCommitResponse[] > interface Grid {
readonly store: Store;
readonly actions: GridActions;
getRuntimeResourceSnapshot(
operation: RuntimeResourceOperation,
phase: RuntimeResourcePhase,
runtime?: RuntimeMemoryObservation,
): RuntimeResourceSnapshot;
getCommandState(command: GridCommandName): GridCommandState;
setActiveSheet(id: SheetId): void;
scrollToCell(addr: CellAddress): void;
getCellAtPoint(
clientX: number,
clientY: number,
): CellAddress | null;
// … 122 more lines — see the API reference
} interface Grid {
readonly store : Store ;
readonly actions : GridActions ;
getRuntimeResourceSnapshot (
operation : RuntimeResourceOperation ,
phase : RuntimeResourcePhase ,
runtime ?: RuntimeMemoryObservation ,
) : RuntimeResourceSnapshot ;
getCommandState ( command : GridCommandName ) : GridCommandState ;
setActiveSheet ( id : SheetId ) : void ;
scrollToCell ( addr : CellAddress ) : void ;
getCellAtPoint (
clientX : number ,
clientY : number ,
) : CellAddress | null ;
// … 122 more lines — see the API reference
} interface Grid {
readonly store : Store ;
readonly actions : GridActions ;
getRuntimeResourceSnapshot (
operation : RuntimeResourceOperation ,
phase : RuntimeResourcePhase ,
runtime ?: RuntimeMemoryObservation ,
) : RuntimeResourceSnapshot ;
getCommandState (
command : GridCommandName ,
) : GridCommandState ;
setActiveSheet (
id : SheetId ,
) : void ;
scrollToCell (
addr : CellAddress ,
) : void ;
getCellAtPoint (
clientX : number ,
// … 259 more lines — see the API reference
} Imperative grid handle for document commands, events, rendering, and teardown. @example import type { Grid } from "@sheetwrite/core"; function updateTotal(grid: Grid) { const sheet = grid.getActiveSheet(); const result = grid.applyTransaction({ patches: [{ op: "set", addr: { sheet, row: 0, col: 0 }, value: { kind: "literal", value: 42 } }], }); if (result.status === "applied") grid.scrollToCell({ sheet, row: 0, col: 0 }); return grid.aggregate(0, "sum"); } @see createGrid @see Grid.applyTransaction API reference → interface PersistenceAdapter {
load(
documentId: string,
signal?: AbortSignal,
): Promise<WorkbookSnapshot>;
commit(
request: PersistenceCommitRequest,
): Promise<PersistenceCommitResponse>;
commitBatch?(
request: PersistenceBatchCommitRequest,
): Promise<PersistenceCommitResponse>;
} interface PersistenceAdapter {
load (
documentId : string ,
signal ?: AbortSignal ,
) : Promise < WorkbookSnapshot >;
commit (
request : PersistenceCommitRequest ,
) : Promise < PersistenceCommitResponse >;
commitBatch ? (
request : PersistenceBatchCommitRequest ,
) : Promise < PersistenceCommitResponse >;
} interface PersistenceAdapter {
load (
documentId : string ,
signal ?: AbortSignal ,
) : Promise < WorkbookSnapshot >;
commit (
request : PersistenceCommitRequest ,
) : Promise < PersistenceCommitResponse >;
commitBatch ? (
request : PersistenceBatchCommitRequest ,
) : Promise < PersistenceCommitResponse >;
} Host load and commit contract for versioned workbook persistence. @example import { MemoryPersistenceAdapter, type PersistenceAdapter, type WorkbookSnapshot } from "@sheetwrite/core"; async function loadLocal(snapshot: WorkbookSnapshot) { if (!snapshot.documentId) throw new Error("A document ID is required"); const adapter: PersistenceAdapter = new MemoryPersistenceAdapter(snapshot); return adapter.load(snapshot.documentId); } @see MemoryPersistenceAdapter @see SyncCoordinator API reference → interface SyncCoordinatorOptions {
documentId: string;
serverVersion: number;
createMutationId?: () => string;
pendingStorage?: PendingCommitStorage;
initialConnection?: "offline" | "online";
recoverVersionGap?: (
request: SyncVersionGapRequest,
) => Promise<readonly VersionedOperation[] | WorkbookSnapshot>;
limits?: Partial<SyncCoordinatorLimits>;
} interface SyncCoordinatorOptions {
documentId : string ;
serverVersion : number ;
createMutationId ?: () => string ;
pendingStorage ?: PendingCommitStorage ;
initialConnection ?: "offline" | "online" ;
recoverVersionGap ?: (
request : SyncVersionGapRequest ,
) => Promise < readonly VersionedOperation [] | WorkbookSnapshot >;
limits ?: Partial < SyncCoordinatorLimits >;
} interface SyncCoordinatorOptions {
documentId : string ;
serverVersion : number ;
createMutationId ?: () => string ;
pendingStorage ?: PendingCommitStorage ;
initialConnection ?:
"offline" | "online" ;
recoverVersionGap ?: (
request : SyncVersionGapRequest ,
) => Promise <
| readonly VersionedOperation []
| WorkbookSnapshot
>;
limits ?: Partial < SyncCoordinatorLimits >;
} Document, version, durability, and online options for synchronization. API reference → interface VersionedOperation {
version: number;
readonly operations: readonly DocumentOp[];
clientMutationId?: string;
batch?: VersionBatchMember;
} interface VersionedOperation {
version : number ;
readonly operations : readonly DocumentOp [];
clientMutationId ?: string ;
batch ?: VersionBatchMember ;
} interface VersionedOperation {
version : number ;
readonly operations : readonly DocumentOp [];
clientMutationId ?: string ;
batch ?: VersionBatchMember ;
} Remote document operations paired with a contiguous server version. API reference → type PersistenceCommitResponse =
| { status: "applied"; version: number; clientMutationId: string }
| {
status: "duplicate";
version: number;
clientMutationId: string;
}
| {
status: "conflict";
currentVersion: number;
operationsSinceBase?: readonly VersionedOperation[];
snapshot?: WorkbookSnapshot;
}; type PersistenceCommitResponse =
| { status : "applied" ; version : number ; clientMutationId : string }
| {
status : "duplicate" ;
version : number ;
clientMutationId : string ;
}
| {
status : "conflict" ;
currentVersion : number ;
operationsSinceBase ?: readonly VersionedOperation [];
snapshot ?: WorkbookSnapshot ;
}; type PersistenceCommitResponse =
| {
status : "applied" ;
version : number ;
clientMutationId : string ;
}
| {
status : "duplicate" ;
version : number ;
clientMutationId : string ;
}
| {
status : "conflict" ;
currentVersion : number ;
operationsSinceBase ?: readonly VersionedOperation [];
snapshot ?: WorkbookSnapshot ;
}; Applied, duplicate, or conflict acknowledgement from persistence. applied confirms the submitted operations unchanged; normalization must conflict. API reference → interface SyncMutationRecord {
status: SyncMutationStatus;
documentId: string;
baseVersion: number;
clientMutationId: string;
readonly operations: readonly DocumentOp[];
readonly versionOperationCounts?: readonly number[];
} interface SyncMutationRecord {
status : SyncMutationStatus ;
documentId : string ;
baseVersion : number ;
clientMutationId : string ;
readonly operations : readonly DocumentOp [];
readonly versionOperationCounts ?: readonly number [];
} interface SyncMutationRecord {
status : SyncMutationStatus ;
documentId : string ;
baseVersion : number ;
clientMutationId : string ;
readonly operations : readonly DocumentOp [];
readonly versionOperationCounts ?: readonly number [];
} Pending commit paired with its current synchronization status. API reference → type SyncConflictRecovery =
| { status: "recovered"; serverVersion: number }
| {
status: "reload-required";
reason: SyncConflictReloadReason;
conflict?: RebaseConflict;
}
| { status: "no-conflict" }; type SyncConflictRecovery =
| { status : "recovered" ; serverVersion : number }
| {
status : "reload-required" ;
reason : SyncConflictReloadReason ;
conflict ?: RebaseConflict ;
}
| { status : "no-conflict" }; type SyncConflictRecovery =
| {
status : "recovered" ;
serverVersion : number ;
}
| {
status : "reload-required" ;
reason : SyncConflictReloadReason ;
conflict ?: RebaseConflict ;
}
| { status : "no-conflict" }; Outcome of SyncCoordinator.recoverConflict. API reference → function recover(sync: SyncCoordinator): Promise<SyncConflictRecovery> function recover (
sync : SyncCoordinator ,
) : Promise < SyncConflictRecovery > function recover (
sync : SyncCoordinator ,
) : Promise < SyncConflictRecovery > const result: SyncConflictRecovery const result : SyncConflictRecovery const result : SyncConflictRecovery Search state after the replacement (matches re-scanned against the new data). API reference → sync: SyncCoordinator let sync : SyncCoordinator let sync : SyncCoordinator API reference → SyncCoordinator.recoverConflict(): Promise<SyncConflictRecovery> SyncCoordinator. recoverConflict (): Promise < SyncConflictRecovery > SyncCoordinator. recoverConflict (): Promise < SyncConflictRecovery > Recover from the outstanding base-version conflict without reloading the document. This succeeds when the pending work and every server version it did not see change different cells, and neither inserts, deletes, or moves rows or columns: the local Grid then already shows the server result plus the pending work, so recovery applies the missed server versions and moves the pending queue onto the new server version. Call flush afterwards to send it. In every other case nothing changes and the result names the reason; the host then reloads and calls resumeAfterReload. @example import type { SyncCoordinator } from "@sheetwrite/core"; async function recover(sync: SyncCoordinator) { const result = await sync.recoverConflict(); if (result.status === "recovered") await sync.flush(); // A reload-required result leaves the document unchanged for host recovery. return result; }@see SyncCoordinator.resumeAfterReloadAPI reference → status: "recovered" | "reload-required" | "no-conflict" let status : "recovered" | "reload-required" | "no-conflict" let status :
| "recovered"
| "reload-required"
| "no-conflict" interface WorkbookSnapshot {
schemaVersion: 1;
documentId?: string;
version?: number;
workbook: {
activeSheet: SheetId;
namedRanges?: NamedRangeSnapshot[];
};
sheets: SheetSnapshot[];
} interface WorkbookSnapshot {
schemaVersion : 1 ;
documentId ?: string ;
version ?: number ;
workbook : {
activeSheet : SheetId ;
namedRanges ?: NamedRangeSnapshot [];
};
sheets : SheetSnapshot [];
} interface WorkbookSnapshot {
schemaVersion : 1 ;
documentId ?: string ;
version ?: number ;
workbook : {
activeSheet : SheetId ;
namedRanges ?: NamedRangeSnapshot [];
};
sheets : SheetSnapshot [];
} Schema-versioned serializable workbook document. API reference → interface SyncStateSnapshot {
connection: SyncConnectionState;
activity: SyncActivityState;
pendingCount: number;
pendingOperations: number;
pendingEncodedBytes: number;
pendingCapacity: SyncPendingCapacityState;
serverVersion: number;
} interface SyncStateSnapshot {
connection : SyncConnectionState ;
activity : SyncActivityState ;
pendingCount : number ;
pendingOperations : number ;
pendingEncodedBytes : number ;
pendingCapacity : SyncPendingCapacityState ;
serverVersion : number ;
} interface SyncStateSnapshot {
connection : SyncConnectionState ;
activity : SyncActivityState ;
pendingCount : number ;
pendingOperations : number ;
pendingEncodedBytes : number ;
pendingCapacity : SyncPendingCapacityState ;
serverVersion : number ;
} Immutable observable synchronization state. API reference → interface RemoteOperationSource {
subscribe(
listener: (
operation: VersionedOperation,
) => void | Promise<void>,
signal?: AbortSignal,
): undefined | (() => void);
} interface RemoteOperationSource {
subscribe (
listener : (
operation : VersionedOperation ,
) => void | Promise < void >,
signal ?: AbortSignal ,
) : undefined | (() => void );
} interface RemoteOperationSource {
subscribe (
listener : (
operation : VersionedOperation ,
) => void | Promise < void >,
signal ?: AbortSignal ,
) : undefined | (() => void );
} Host subscription contract for ordered versioned operations. Sources that can pause intake should await the listener promise to preserve backpressure. API reference →