ProsemirrorEx.Authority (prosemirror_ex v0.3.0)

Copy Markdown View Source

Functional core for a collaborative editing authority server.

Holds the canonical document, receives steps from clients, validates versions, applies steps, and provides step history for client catch-up.

Implements the three responsibilities from the ProseMirror collaborative editing guide:

  1. Track a current document version
  2. Accept changes from editors when they apply, adding them to the change list
  3. Provide a way for editors to receive changes since a given version

Optionally bounds retained step history (as in the official collab demo's MAX_STEP_HISTORY) so memory does not grow without bound. When a requested version has been trimmed away, steps_since/2 returns {:error, :history_unavailable} and the client should fetch a full document snapshot via doc/1 instead.

This is a pure data structure with no process — use ProsemirrorEx.Authority.Server for a GenServer wrapper.

Summary

Functions

Return the current document.

Return the oldest version still available in step history.

Create a new Authority with the given schema and optional initial document.

Return steps and their client IDs from since to the current version.

Return the current version.

Types

t()

@type t() :: %ProsemirrorEx.Authority{
  doc: term(),
  max_history: pos_integer() | nil,
  schema: term(),
  step_client_ids: [term()],
  steps: [term()],
  version: non_neg_integer()
}

Functions

doc(authority)

Return the current document.

first_version(authority)

Return the oldest version still available in step history.

Equals version - length(steps). When history is empty this equals the current version (a fresh authority or one whose history was fully trimmed after catch-up is still at a consistent version with a current doc snapshot).

new(schema, doc \\ nil, opts \\ [])

Create a new Authority with the given schema and optional initial document.

If doc is nil, creates a minimal valid document using the schema's top node type.

Options

  • :max_history — maximum number of steps to retain (default nil, unlimited). Matches the official ProseMirror collab demo's history window. When exceeded, older steps are discarded; clients that are too far behind must reload the full document. A single receive_steps batch may not exceed this limit ({:error, :batch_too_large}); accepted batches are always retained in full so steps_since/2 from the pre-batch version remains valid.

receive_steps(auth, client_id, client_version, steps)

Receive steps from a client.

Steps must be pre-deserialized Step structs. The client's version must match the authority's current version, otherwise {:error, :version_mismatch} is returned.

Returns:

  • {:ok, updated_authority} on success
  • {:error, :version_mismatch} if client_version != authority.version
  • {:error, :batch_too_large} if max_history is set and the batch is larger (a batch must fit in the history window so steps_since(client_version) still works after accept — needed for broadcast/catch-up)
  • {:error, :step_failed, message} if a step fails to apply

steps_since(auth, since)

Return steps and their client IDs from since to the current version.

Uses the same indexing as the official ProseMirror collab demo: retained steps may not start at version 0 when max_history has trimmed older entries.

Returns:

  • {:ok, steps, client_ids} on success
  • {:error, :invalid_version} if since is negative or beyond current version
  • {:error, :history_unavailable} if since is older than the retained window

version(authority)

Return the current version.