This document provides a high-level reference for the core MoonBit APIs in the crdt project.
The SyncEditor is the primary facade for the editor application, integrating the CRDT document, incremental parser, and undo manager.
SyncEditor::new_lambda(agent_id : String, capture_timeout_ms? : Int = 500) -> SyncEditor[@ast.Term]Creates the lambda-calculus editor facade used by the current apps and tests.
insert(text : String) -> Unit raiseInserts text at the current cursor position.delete() -> BoolDeletes the character at the current cursor position (forward delete).backspace() -> BoolDeletes the character before the current cursor position.move_cursor(position : Int) -> UnitMoves the cursor to the specified absolute position.get_text() -> StringReturns the full document text.get_cursor() -> IntReturns the current cursor position.set_text(new_text : String) -> UnitReplaces the entire document text (useful for initialization).
insert_and_record(text : String, timestamp_ms : Int) -> Unit raisedelete_and_record(timestamp_ms : Int) -> Boolbackspace_and_record(timestamp_ms : Int) -> Boolundo() -> Boolredo() -> Boolcan_undo() -> Boolcan_redo() -> Bool
export_all() -> @text.SyncMessageExports all operations for initial synchronization.export_since(peer_version : @text.Version) -> @text.SyncMessageExports operations created since the specified peer version.apply_sync(msg : @text.SyncMessage) -> UnitApplies a synchronization message received from a peer.get_version() -> @text.VersionReturns the current document version.
get_ast() -> @ast.TermReturns the current parsed AST.get_ast_pretty() -> StringReturns a pretty-printed string of the AST.get_errors() -> Array[String]Returns a list of parse errors.is_parse_valid() -> BoolReturns true if the current text parses without errors.
apply_tree_edit(op : @proj.TreeEditOp, timestamp_ms : Int) -> Result[Unit, TreeEditError]Applies a structural tree edit by round-tripping through the text CRDT.delete_node(node_id : @proj.NodeId, timestamp_ms : Int) -> Result[Unit, TreeEditError]commit_edit(node_id : @proj.NodeId, new_text : String, timestamp_ms : Int) -> Result[Unit, TreeEditError]move_node(source_id : @proj.NodeId, target_id : @proj.NodeId, position : @proj.DropPosition, timestamp_ms : Int) -> Result[Unit, TreeEditError]
decode_message(data : Bytes) -> SyncMessage?Compatibility decoder that drops malformed frames by returningNone.decode_message_result(data : Bytes) -> Result[SyncMessage, ProtocolError]Typed decoder for callers that need explicit protocol failure reasons.ws_on_message(data : Bytes) -> UnitApplies incoming wire data. Malformed protocol/input frames are intentionally dropped as resilience policy; typed decode helpers exist when diagnostics are needed outside the hot path.
Manages transient state like peer cursors and presence information.
set(key : String, value : EphemeralValue) -> Unit raise EphemeralErrorSets a value for a specific key (usually a peer ID).get(key : String) -> EphemeralValue?Retrieves a value for a key.delete(key : String) -> Unit raise EphemeralErrorRemoves a key from the store.encode_all() -> BytesEncodes all non-expired state for broadcasting.apply(data : Bytes) -> Unit raise EphemeralErrorApplies an encoded update from a peer.remove_outdated() -> UnitPrunes expired entries based ontimeout_ms.
The editor package now uses typed boundary errors rather than raw strings for
its main internal error surfaces:
EphemeralErrorTreeEditErrorProtocolError
Each exposes .message() for conversion at UI/FFI edges.
Low-level sync/document failures still come from @text.TextError and should
remain owned by the text layer.
The root JS FFI remains a string/JSON boundary. Internal typed errors are flattened there rather than earlier in the call stack.
Examples:
apply_tree_edit_json(handle, op_json, timestamp_ms) -> "ok" | "error: ..."apply_sync_json(handle, sync_json) -> Stringexport_all_json(handle) -> String
See JS Integration for the browser-facing surface.