Skip to main content
Version: v0.0.3

Class: Connection

A single MLLP connection wrapping a Transport with a 6-state FSM, lifecycle events, per-connection warning streams, and getStats() observability.

Emits events: stateChange, connect, disconnect, reconnecting, close, message, warning, error.

Example

import { Connection, NetTransport } from '@cosyte/mllp';
import { createConnection } from 'node:net';

const socket = createConnection({ host: 'localhost', port: 2575 });
const conn = new Connection({ transport: new NetTransport(socket) });
conn.on('stateChange', ({ from, to }) => console.log(from, '->', to));
conn.on('message', ({ payload }) => console.log('received', payload.length, 'bytes'));
socket.on('connect', () =>
conn.notifyConnect(socket.remoteAddress ?? null, socket.remotePort ?? null)
);

Extends

  • EventEmitter

Constructors

Constructor

new Connection(opts): Connection

Construct a connection over the given transport. Starts in CONNECTING; call Connection.notifyConnect once the transport handshake completes.

Parameters

opts

ConnectionOptions

Connection options (the transport, message/warning handlers, drain timeout, framing).

Returns

Connection

Overrides

EventEmitter.constructor

Properties

beforeClose

beforeClose: (drainTimeoutMs) => Promise<void>

beforeClose hook, no-op default that resolves immediately.

An owner may replace this instance property to run work before the socket closes. Connection calls it during close(), racing against drainTimeoutMs.

Parameters

drainTimeoutMs

number

Returns

Promise<void>


connectionId

readonly connectionId: string

Stable UUIDv4 identifier for this connection.

Accessors

state

Get Signature

get state(): ConnectionState

Current FSM state. One of the 6 ConnectionState values.

Subscribe to 'stateChange' events for reactive state monitoring.

Returns

ConnectionState

Methods

close()

close(opts?): Promise<void>

Initiate graceful close of the connection.

  • If CONNECTING or RECONNECTING: cancels the pending attempt, transitions directly to CLOSED, and calls transport.destroy().
  • If CONNECTED: transitions to DRAINING, calls beforeClose(drainTimeoutMs), then DRAINING → DISCONNECTED once the hook resolves, or DRAINING → CLOSED if the drain timeout elapses first.
  • If DRAINING: waits for the existing drain to complete (idempotent).
  • If CLOSED or DISCONNECTED: no-op.

Parameters

opts?
drainTimeoutMs?

number

Override drain timeout (default: opts.drainTimeoutMs ?? 30_000).

Returns

Promise<void>

Example

await conn.close({ drainTimeoutMs: 5_000 });

destroy()

destroy(reason?): void

Abruptly destroy the connection, discarding any pending writes.

Transitions from any non-terminal state directly to CLOSED and calls transport.destroy(reason). Emits 'close' event. Idempotent, safe to call multiple times.

Parameters

reason?

Error

Optional error to propagate to the transport.

Returns

void

Example

conn.destroy(new Error('Timeout exceeded'));

getStats()

getStats(): ConnectionStats

Return a JSON-serializable observability snapshot.

All timestamp fields are Date | null (not epoch milliseconds). JSON.stringify() serialises them to ISO 8601 strings with no information loss.

warningsByCode reflects every warning ever received regardless of ring buffer truncation. warningsTruncated is true if the 100-entry ring buffer has overflowed.

Returns

ConnectionStats

Example

const stats = conn.getStats();
console.log(JSON.stringify(stats)); // log-pipeline friendly

notifyConnect()

notifyConnect(remoteAddress, remotePort): void

Notify the connection that the transport handshake has completed.

Transitions CONNECTING → CONNECTED and emits the 'connect' event. Called externally by Server/Client after the socket connects.

Parameters

remoteAddress

string | null

Remote peer IP address, or null if unavailable.

remotePort

number | null

Remote peer port, or null if unavailable.

Returns

void

Example

socket.on('connect', () =>
conn.notifyConnect(socket.remoteAddress ?? null, socket.remotePort ?? null)
);

onWarning()

onWarning(fn): void

Register or replace the per-connection warning subscriber.

Subsequent calls replace the previous handler (set-once semantics prevent leaks). The handler is called synchronously and any exception it throws is swallowed.

Parameters

fn

(w) => void

Returns

void

Example

conn.onWarning((w) => logger.warn({ code: w.code, connectionId: w.connectionId }));

send()

send(data): boolean

Write raw bytes to the transport (no framing applied).

The server and the client wrap this with encodeFrame() to add MLLP framing. Returns false if the connection is CLOSED or DISCONNECTED (no bytes written).

Parameters

data

Buffer

Returns

boolean

true if bytes flushed immediately; false if buffered (backpressure) or not writable.

Example

const flushed = conn.send(encodeFrame(payload));
if (!flushed) logger.warn('backpressure detected');