ouija board1
jeeboard docs protocol index.md
3.7 kB
Markdown
at main


title: Message transport with @jeeboard/protocol description: Explains the endpoint abstraction and the in-process endpoint pair from the @jeeboard/protocol package. #

Message transport with @jeeboard/protocol #

The @jeeboard/protocol package defines a small message-transport abstraction. A message transport is a channel that moves messages between two parts of an application. The replication layer in @jeeboard/automerge uses this abstraction. It sends document changes and presence data through an endpoint.

The package does not contain a network implementation. You supply the transport, or you use the in-process pair that the package provides.

Key concepts #

  • A message is a value that an endpoint delivers to listeners. You select the message type with a generic type parameter.
  • A message listener is a function that receives a message. The type is MessageListener<Message>.
  • An endpoint is one side of a message transport. It has a send method and a subscribe method. The type is Endpoint<Message>.
  • An endpoint pair is a set of two connected endpoints, a and b. The type is EndpointPair<Message>.

An endpoint has two operations:

  • send(message) delivers a message to the listeners of the opposite endpoint.
  • subscribe(listener) registers a message listener. It returns a function that removes the listener.

NOTE: An endpoint does not receive its own messages. A call to a.send notifies only the listeners of b.

Entry points #

The package exports three types and one function:

  • MessageListener<Message> — the message listener type.
  • Endpoint<Message> — the endpoint interface.
  • EndpointPair<Message> — the endpoint pair interface with fields a and b.
  • createInProcessEndpointPair<Message>() — creates a connected endpoint pair in the current process.

Typical usage #

This example creates an endpoint pair and sends messages in both directions. It matches the tests in packages/protocol/test/protocol.test.mjs.

import { createInProcessEndpointPair } from "@jeeboard/protocol";

const { a, b } = createInProcessEndpointPair<{ type: string; revision: number }>();

a.subscribe((message) => {
  console.log("a received", message);
});
b.subscribe((message) => {
  console.log("b received", message);
});

a.send({ type: "patch", revision: 1 }); // delivered to b
b.send({ type: "ack", revision: 1 }); // delivered to a

Remove a listener #

To remove a listener, call the function that subscribe returns.

  1. Call subscribe and keep the returned function.
  2. Call the returned function to remove the listener.
  3. Send again to confirm that the listener does not run.
const { a, b } = createInProcessEndpointPair<{ type: string }>();

const unsubscribe = a.subscribe((message) => {
  console.log(message);
});

b.send({ type: "first" }); // the listener runs
unsubscribe();
b.send({ type: "second" }); // the listener does not run

Custom transports #

The in-process pair delivers messages synchronously in the same process. For network communication, you implement the Endpoint<Message> interface yourself. For example, you can wrap a WebSocket or a MessagePort in an endpoint.

The createBoardRealtimeSession function in @jeeboard/automerge accepts any Endpoint<BoardRealtimeMessage>. This design keeps the replication logic independent from the transport.

WARNING: The in-process pair does not copy messages. The listener receives the same object reference. Do not mutate a message after you send it.

API reference #

See the generated API documentation at API reference.