Interface: StarterServerOptions
Options for createStarterServer(), the "three lines of code" factory.
Extends ServerOptions with port, host, and handleSignals. Defaults:
autoAck: 'AA', drainTimeoutMs: 30_000, Symbol.asyncDispose wired.
Example
import { createStarterServer } from '@cosyte/mllp';
const server = await createStarterServer({
port: 2575,
onMessage: (buf) => buildAckBuffer(buf),
});
// server is listening, auto-ACK enabled, Symbol.asyncDispose wired
await using _ = server; // closes on scope exit
Extends
Properties
allowWildcardBind?
optionalallowWildcardBind?:boolean
Opt-in required to bind a wildcard host, a bind-safety guardrail.
Without this flag, listen() rejects a wildcard host in
two tiers: literal spellings ('0.0.0.0', '::', '', '::0',
'0:0:0:0:0:0:0:0', '::ffff:0.0.0.0', …) reject pre-bind (fast
path, nothing is ever bound); resolver-only shorthands ('0',
'0.0', '0x0.0.0.0', hostnames resolving to the unspecified
address, …) are caught post-bind against the OS-normalized bound
address, the just-bound server closes before any connection can be
accepted and listen() rejects, with no listening state and no
'listening' event either way. When true, binding a wildcard host
emits a one-time 'securityWarning' (MLLP_BIND_ALL_INTERFACES) at
listen time.
Default
false
Inherited from
ServerOptions.allowWildcardBind
autoAck?
optionalautoAck?:"AA"| ((payload,meta,conn) =>Buffer<ArrayBufferLike> |Promise<Buffer<ArrayBufferLike>>)
Auto-ACK mode. When set, the server builds and sends the ACK for each message.
'AA', auto-acknowledge with the fail-safe commit contract:- With an
onMessagehandler ⇒ commit-gated (recommended). The server awaitsonMessage(the durable-commit step), then sendsAAon success or a negative ACK on failure (AEby default;ARvia MllpAckError). The positive ACK cannot precede a successful commit, a handler throw can never yieldAA. - Without an
onMessagehandler ⇒ transport-accept.AAis sent on frame receipt. ThisAAmeans only "bytes received and framed", not "application-processed". ⚠️ For clinical messages this is unsafe on its own: pair'AA'with anonMessagehandler that durably commits, so the ACK reflects real processing.
- With an
fn,fn(payload, meta, conn)builds the ACK bytes the server sends; the caller fully owns MSA-1 (e.g. to emit enhanced-modeCA/CE/CR).
The 'message' event always fires BEFORE the ACK is sent. Do NOT call
conn.send() in onMessage when autoAck is set, this results in two ACKs.
Inherited from
deadPeerTimeoutMs?
optionaldeadPeerTimeoutMs?:number
Application-level idle close timeout in ms.
If no HL7 messages are received on a connection for this interval, the connection
is destroyed via conn.destroy(new Error('idle timeout')).
Resets on every 'message' event. Distinct from keepaliveIntervalMs (OS TCP probe).
Inherited from
ServerOptions.deadPeerTimeoutMs
drainTimeoutMs?
optionaldrainTimeoutMs?:number
Graceful drain timeout passed to conn.close() during server.close().
Default: 30 000 ms.
Inherited from
framing?
optionalframing?:Omit<FrameReaderOptions,"onFrame"|"onWarning">
FrameReader tolerance options applied to every accepted connection.
Merged with SERVER_DEFAULT_FRAMING, caller-supplied values override defaults.
onFrame and onWarning are managed internally and must not be supplied here.
Inherited from
handleSignals?
optionalhandleSignals?:boolean
Register process.once('SIGTERM') and process.once('SIGINT') handlers that
call server.close() then process.exit(0). Default: false.
Handlers are automatically removed when server.close() is called, so
process.listenerCount('SIGTERM') === 0 after close() completes, preventing
handler accumulation across test instances or multiple server restarts.
host?
optionalhost?:string
Host to bind to. Default '127.0.0.1' (bind-safety hardening,
was '0.0.0.0'; binding all interfaces now requires
ServerOptions.allowWildcardBind: true).
keepaliveIntervalMs?
optionalkeepaliveIntervalMs?:number
TCP keepalive probe interval in ms.
Calls socket.setKeepAlive(true, ms) on each accepted socket.
Uses OS TCP stack to detect dead peers (half-open, network partitions).
Distinct from deadPeerTimeoutMs (application-level idle close).
Inherited from
ServerOptions.keepaliveIntervalMs
onMessage?
optionalonMessage?: (payload,meta,conn) =>void|Promise<void>
Called for each decoded MLLP message.
Its role depends on autoAck, this is the commit contract (HL7 v2.5.1 §2.9.2):
autoAck: 'AA'+ this handler ⇒ commit-gated (the safe default). The handler is the durable-commit step. The server awaits it and only then sends the ACK: resolve ⇒AA; throw/reject ⇒AE(orARvia MllpAckError), a positive ACK can never precede a successful commit. Do not callconn.send()here in this mode.autoAckunset ⇒ manual mode. The handler owns the response; build and send the ACK yourself viaconn.send(encodeFrame(ackPayload)). Its return value is ignored.autoAck: fn⇒ observation only.fnbuilds the ACK; this handler runs first as a side effect and its return value is ignored. Do not callconn.send()here.
May be sync or async; an async handler is awaited in commit-gated mode.
Parameters
payload
Buffer
meta
conn
Returns
void | Promise<void>
Inherited from
onWarning?
optionalonWarning?: (w) =>void
Per-connection warning subscriber. Called for every framing warning on every connection.
Parameters
w
Returns
void
Inherited from
port
port:
number
Port to listen on.
tls?
optionaltls?:ServerTlsOptions
Enable TLS (MLLPS) for this server. When set, the server binds a
tls.Server instead of a plain net.Server, consumes 'secureConnection'
(post-handshake sockets) instead of 'connection', and surfaces failed
handshakes via the 'tlsClientError' event rather than crashing.
Spec anchor: IHE ATNA ITI-19 (https://profiles.ihe.net/ITI/TF/Volume2/ITI-19.html).
Default
undefined (plaintext TCP)