Skip to content

API reference / @jsprismarine/console-protocol

@jsprismarine/console-protocol ​

Join the Discord Servernpm

Message types and links between the JSPrismarine server and its console.

When the server runs under the terminal UI it is a child process, and the two sides talk over Node's IPC channel. This package defines what they say to each other and how a message gets from one side to the other. It depends only on @jsprismarine/logger (for LogLevel), so neither the server nor the host pulls in a renderer by importing it.

There are three message families. ServerMessage is everything the server sends: hello on connect, log records with a sequence number and log.dropped when the server had to shed records, status with TPS, player count, memory, and uptime, lifecycle state changes, and command.result and complete.result replies. ConsoleMessage is what the console sends back: command, complete, subscribe to set the log level, and shutdown. SupervisorEvent never crosses the channel; the host raises it for the UI to describe its own state (watching, a changed path, regenerating data, a restart, raw child output).

A MessageLink<In, Out> is the channel itself: send, onMessage, onClose, close. send returns false when the channel asks the sender to slow down. Three adapters implement it: childProcessLink() on the server side over process.send, subprocessLink(child) on the host side over the spawned child, and memoryLinkPair() for tests. isServerMessage and isConsoleMessage check that incoming JSON has one of the known shapes before you trust it.

Exports ​

NameKind
PROTOCOL_VERSIONconstant, currently 1; every message carries it as v
ServerMessage, ServerMessageType, LogEntry, LifecycleStatetypes for the server side
ConsoleMessage, ConsoleMessageTypetypes for the console side
SupervisorEvent, SupervisorStatetypes for host-local events
isServerMessage, isConsoleMessagetype guards
MessageLink, LinkOptionsthe channel interface and adapter options
childProcessLink, subprocessLink, memoryLinkPairadapters
ChildProcessLink, ChildProcessLinkOptions, IpcProcesstypes for the server-side adapter

Interfaces ​

Defined in: childProcessLink.ts:29

A MessageLink over the IPC channel of the current process, with a flush for the shutdown path: Node discards IPC writes still queued when process.exit runs, so the server awaits flush() before exiting to get its last messages out.

Extends ​

Type Parameters ​

In ​

In

Out ​

Out

Methods ​

close() ​

close(): void

Defined in: link.ts:38

Closes the channel. Calling it more than once has no further effect.

Returns ​

void

Inherited from ​

MessageLink.close

flush() ​

flush(): Promise<void>

Defined in: childProcessLink.ts:31

Resolves once Node has written every message queued so far to the channel, or once the channel has closed.

Returns ​

Promise<void>

onClose() ​

onClose(listener): () => void

Defined in: link.ts:35

Registers a listener that runs once when the channel closes, whether this end called close or the other end went away. Listeners run in registration order.

Parameters ​
listener ​

() => void

Returns ​

A function that removes the listener.

() => void

Inherited from ​

MessageLink.onClose

onMessage() ​

onMessage(listener): () => void

Defined in: link.ts:27

Registers a listener for incoming messages. Listeners run in registration order, one after another, for each message.

Parameters ​
listener ​

(message) => void

Returns ​

A function that removes the listener.

() => void

Inherited from ​

MessageLink.onMessage

send() ​

send(message): boolean

Defined in: link.ts:19

Queues a message for the other end.

Parameters ​
message ​

Out

Returns ​

boolean

true when the channel accepted the message. false means the channel asked for a pause, either because its unsent backlog passed the adapter's threshold or because it has closed. Nothing is dropped by the adapter on false; the sender may keep sending, but it should cap its own queue because every queued message stays in memory until the receiver reads it.

Inherited from ​

MessageLink.send


ChildProcessLinkOptions ​

Defined in: childProcessLink.ts:19

Options for childProcessLink.

Extends ​

Type Parameters ​

In ​

In

Properties ​

proc? ​

optional proc?: IpcProcess

Defined in: childProcessLink.ts:21

The process whose IPC channel carries the messages. Defaults to the current process.

validate ​

validate: (value) => value is In

Defined in: link.ts:48

Type guard applied to every incoming message, typically isServerMessage or isConsoleMessage.

Parameters ​
value ​

unknown

Returns ​

value is In

Inherited from ​

LinkOptions.validate


IpcProcess ​

Defined in: childProcessLink.ts:8

The parts of process the server-side link uses. process satisfies it when Node started the process with an 'ipc' stdio entry; tests can pass a double.

Properties ​

connected ​

connected: boolean

Defined in: childProcessLink.ts:9

Methods ​

disconnect()? ​

optional disconnect(): void

Defined in: childProcessLink.ts:11

Returns ​

void

off() ​
Call Signature ​

off(event, listener): unknown

Defined in: childProcessLink.ts:14

Parameters ​
event ​

"message"

listener ​

(message) => void

Returns ​

unknown

Call Signature ​

off(event, listener): unknown

Defined in: childProcessLink.ts:15

Parameters ​
event ​

"disconnect"

listener ​

() => void

Returns ​

unknown

on() ​
Call Signature ​

on(event, listener): unknown

Defined in: childProcessLink.ts:12

Parameters ​
event ​

"message"

listener ​

(message) => void

Returns ​

unknown

Call Signature ​

on(event, listener): unknown

Defined in: childProcessLink.ts:13

Parameters ​
event ​

"disconnect"

listener ​

() => void

Returns ​

unknown

send()? ​

optional send(message, sendHandle?, options?, callback?): boolean

Defined in: childProcessLink.ts:10

Parameters ​
message ​

unknown

sendHandle? ​

unknown

options? ​

unknown

callback? ​

(error) => void

Returns ​

boolean


LinkOptions ​

Defined in: link.ts:46

Options shared by the adapters that read from another process. Incoming data is JSON the other side wrote, so the adapter cannot know its type; validate decides, and anything it rejects is dropped without a throw.

Extended by ​

Type Parameters ​

In ​

In

Properties ​

validate ​

validate: (value) => value is In

Defined in: link.ts:48

Type guard applied to every incoming message, typically isServerMessage or isConsoleMessage.

Parameters ​
value ​

unknown

Returns ​

value is In


LogEntry ​

Defined in: messages.ts:25

One log record as the server forwards it to the console.

seq increases by one per record so the console can detect a gap even when a log.dropped message is itself lost. at is epoch milliseconds so the console formats the time for its own zone. formatted is the ANSI line the logger would have printed itself.

Properties ​

at ​

at: number

Defined in: messages.ts:29

formatted ​

formatted: string

Defined in: messages.ts:31

level ​

level: "error" | "warn" | "info" | "verbose" | "debug" | "silly"

Defined in: messages.ts:27

message ​

message: string

Defined in: messages.ts:30

namespace ​

namespace: string

Defined in: messages.ts:28

seq ​

seq: number

Defined in: messages.ts:26


Defined in: link.ts:9

One end of a two-way message channel between the server and the console.

In is what this end receives and Out what it sends, so the server holds a MessageLink<ConsoleMessage, ServerMessage> and the console the mirror image. Adapters carry the messages over an IPC channel or, in tests, over memory; callers see only this interface.

Extended by ​

Type Parameters ​

In ​

In

Out ​

Out

Methods ​

close() ​

close(): void

Defined in: link.ts:38

Closes the channel. Calling it more than once has no further effect.

Returns ​

void

onClose() ​

onClose(listener): () => void

Defined in: link.ts:35

Registers a listener that runs once when the channel closes, whether this end called close or the other end went away. Listeners run in registration order.

Parameters ​
listener ​

() => void

Returns ​

A function that removes the listener.

() => void

onMessage() ​

onMessage(listener): () => void

Defined in: link.ts:27

Registers a listener for incoming messages. Listeners run in registration order, one after another, for each message.

Parameters ​
listener ​

(message) => void

Returns ​

A function that removes the listener.

() => void

send() ​

send(message): boolean

Defined in: link.ts:19

Queues a message for the other end.

Parameters ​
message ​

Out

Returns ​

boolean

true when the channel accepted the message. false means the channel asked for a pause, either because its unsent backlog passed the adapter's threshold or because it has closed. Nothing is dropped by the adapter on false; the sender may keep sending, but it should cap its own queue because every queued message stays in memory until the receiver reads it.

Type Aliases ​

ConsoleMessage ​

ConsoleMessage = Envelope<"command"> & object | Envelope<"complete"> & object | Envelope<"shutdown"> | Envelope<"subscribe"> & object

Defined in: messages.ts:67

Messages the console sends to the server.


ConsoleMessageType ​

ConsoleMessageType = ConsoleMessage["type"]

Defined in: messages.ts:77

The type of a ConsoleMessage.


IpcChild ​

IpcChild = Pick<ChildProcess, "connected" | "send" | "disconnect" | "on" | "off">

Defined in: subprocessLink.ts:9

The part of a ChildProcess the link reads: the IPC channel and its lifecycle events. A real child satisfies it; tests pass an emitter with the same members.


LifecycleState ​

LifecycleState = typeof LIFECYCLE_STATES[number]

Defined in: messages.ts:38

One of LIFECYCLE_STATES.


ServerMessage ​

ServerMessage = Envelope<"hello"> & object | Envelope<"log"> & LogEntry | Envelope<"log.dropped"> & object | Envelope<"status"> & object | Envelope<"lifecycle"> & object | Envelope<"command.result"> & object | Envelope<"complete.result"> & object

Defined in: messages.ts:46

Messages the server sends to the console.


ServerMessageType ​

ServerMessageType = ServerMessage["type"]

Defined in: messages.ts:74

The type of a ServerMessage.


SupervisorEvent ​

SupervisorEvent = { code?: number | null; generation: number; signal?: string | null; state: SupervisorState; type: "supervisor.state"; } | { canRestart?: boolean; root: string; type: "supervisor.watching"; } | { path: string; type: "supervisor.changed"; } | { ok?: boolean; type: "supervisor.generating"; } | { stream: "stdout" | "stderr"; text: string; type: "supervisor.output"; }

Defined in: messages.ts:87

Events the host raises about the server child. They never cross the IPC channel; the host produces them from the child's exit status, the file watcher, and the child's stdio pipes, and the console renders them as status and toasts rather than log lines.

Union Members ​

Type Literal ​

{ code?: number | null; generation: number; signal?: string | null; state: SupervisorState; type: "supervisor.state"; }


Type Literal ​

{ canRestart?: boolean; root: string; type: "supervisor.watching"; }

canRestart? ​

optional canRestart?: boolean

Whether the host will act on a restart request. Set by the supervisor on the way out; a frontend treats a missing value as false.

root ​

root: string

type ​

type: "supervisor.watching"


Type Literal ​

{ path: string; type: "supervisor.changed"; }


Type Literal ​

{ ok?: boolean; type: "supervisor.generating"; }


Type Literal ​

{ stream: "stdout" | "stderr"; text: string; type: "supervisor.output"; }


SupervisorState ​

SupervisorState = "starting" | "running" | "stopping" | "stopped" | "crashed" | "restarting" | "waiting"

Defined in: messages.ts:80

States of the host's supervisor, which owns the server child process.

Variables ​

LIFECYCLE_STATES ​

const LIFECYCLE_STATES: readonly ["starting", "running", "stopping"]

Defined in: messages.ts:35

Server lifecycle states reported over the link. stopped and crashed come from the child's exit, not a message.


PROTOCOL_VERSION ​

const PROTOCOL_VERSION: 1 = 1

Defined in: messages.ts:11

Version of the message schema. Both sides stamp it on every message as v, and the type guards reject messages from another version so a mismatched host and server fail loudly instead of misreading each other.

Functions ​

childProcessLink<In, Out>(options): ChildProcessLink<In, Out>

Defined in: childProcessLink.ts:50

Builds the server-side link over the IPC channel Node opens when the host forks the server with an 'ipc' stdio entry. Messages travel through process.send in Node's JSON mode, so they must be plain JSON values. Registering a message listener makes the channel keep the process alive until it disconnects.

send returns what process.send returns: false once the unsent backlog passes Node's threshold or after the channel closed. The close listeners run when the channel disconnects, whether through MessageLink.close or because the host went away. A channel that is already disconnected when the link is built, because the host went away during startup, is reported the same way: the close listeners run on the next microtask, which leaves the caller its synchronous turn to register them, so the server still learns to shut down.

Type Parameters ​

In ​

In

Out ​

Out

Parameters ​

options ​

ChildProcessLinkOptions<In>

Returns ​

ChildProcessLink<In, Out>

Throws ​

When the process has no IPC channel, which means it was not started by child_process.fork or with an 'ipc' stdio entry.


isConsoleMessage() ​

isConsoleMessage(value): value is ConsoleMessage

Defined in: messages.ts:210

Whether a decoded JSON value is a ConsoleMessage of this protocol version with its required fields present and of the right kind. The subscribe level must be a log level.

Parameters ​

value ​

unknown

Returns ​

value is ConsoleMessage


isLifecycleState() ​

isLifecycleState(value): value is "starting" | "running" | "stopping"

Defined in: messages.ts:41

Whether a decoded value names one of LIFECYCLE_STATES.

Parameters ​

value ​

unknown

Returns ​

value is "starting" | "running" | "stopping"


isServerMessage() ​

isServerMessage(value): value is ServerMessage

Defined in: messages.ts:199

Whether a decoded JSON value is a ServerMessage of this protocol version with its required fields present and of the right kind. Literal fields such as level and state must hold one of their declared values.

Parameters ​

value ​

unknown

Returns ​

value is ServerMessage


memoryLinkPair() ​

memoryLinkPair<A, B>(): [MessageLink<A, B>, MessageLink<B, A>]

Defined in: memoryLink.ts:15

Two in-memory MessageLinks wired to each other, for tests that need a server and a console in one process. Messages are delivered on a microtask, so send returns before any listener runs, as with a real channel. close() on either end runs the close listeners of both ends synchronously; messages still queued at that moment are dropped.

Type Parameters ​

A ​

A

B ​

B

Returns ​

[MessageLink<A, B>, MessageLink<B, A>]

A tuple of the end that receives A and sends B, and the end that receives B and sends A.


subprocessLink<In, Out>(child, options): MessageLink<In, Out>

Defined in: subprocessLink.ts:22

Builds the host-side link to a server child spawned with an 'ipc' stdio entry. Messages travel through child.send, and incoming ones pass options.validate before any listener sees them, so a stray JSON value from the child is dropped rather than thrown.

The link closes when the child's 'close' or 'exit' event fires or its channel disconnects. 'close' is needed on its own: a spawn that fails (ENOENT, EAGAIN, EMFILE) emits 'error' and 'close' but never 'exit'. stopped versus crashed is for the caller to derive from the child's exit code. MessageLink.close disconnects the channel but leaves the child running; stopping it is the supervisor's job.

Type Parameters ​

In ​

In

Out ​

Out extends Serializable

Parameters ​

child ​

IpcChild

options ​

LinkOptions<In>

Returns ​

MessageLink<In, Out>