Import it from @grafloria/engine.
One peer.
Local edits to diagram are captured, appended to log, and handed to onLocalOp. Remote ops arrive at receive(), are de-duplicated, applied, and NOT echoed back.
tsclass Replica
Properties
| Name | Type | Default | Description |
|---|---|---|---|
log |
Methods
constructor( readonly diagram: DiagramModel, private readonly options: ReplicaOptions )get actor(): ActorIdget clock(): number— The clock to resume from, and the watermark a peer asks us to catch up past.get quarantinedLinks(): string[]— Links held out of the document because an endpoint node is missing. See integrity.ts.get canUndo(): booleanget canRedo(): booleanreceive(ops: readonly Op[]): Op[]— Take ops from a peer.
Returns the ops that were actually NEW to us — which is what you forward to other peers in a mesh, and which is exactly nothing when the same batch arrives twice.
undo(): Op[]— UNDO MY LAST EDIT — not the last edit.
The per-actor property is structural: capture only ever sees LOCAL mutations (remote ops are applied with capture suppressed), so nothing another peer did can be on this stack to begin with. See undo.ts for what happens when my edit has already been superseded by someone else's — the short version is that it does nothing, on purpose.
redo(): Op[]transact<T>(fn: () => T): T— Group everythingfndoes into ONE undo step.
Deleting a node with three links is four ops and, without this, four presses of Ctrl-Z. Grouping is a LOCAL concern — it changes what one keypress takes back, never what goes on the wire — so two peers may group differently and still converge.
history(): readonly Op[]— Everything we know, in total order — the catch-up payload for a joining peer.adopt(ops: readonly Op[]): void— Adopt a persisted op-log tail whose EFFECTS ARE ALREADY IN THE MODEL.
This is receive()'s quiet twin, and the difference is the whole point. receive() is
for ops the model has not seen: it applies them. adopt() is for reopening a saved
document, where the snapshot ALREADY CONTAINS everything the ops did — so it seeds the
log (so a duplicate re-delivery is recognised), the LWW stamps (so a straggling older
write is still refused after a reload) and the repair index, and applies NOTHING.
Re-applying them would be harmless for content — the reducer's redundant-write guard would drop every one — but it would bump every version counter and fire a full repaint for a document that has not changed. Worse, it would make opening a file look like an edit to anyone watching the model's change events.
dispose(): void
Was this page helpful?