Connection and configuration
SerialConfig
The constructor accepts the exact SerialConfig contract from serial-core.
| Option | Type | Required | Behavior |
|---|---|---|---|
| baudRate | number | yes | Serial speed; match the device |
| autoConnect | boolean | no | Default false; when true, connect in a microtask after construction |
| reconnectInterval | number | no | Initial retry delay; default 2000 ms |
| autoReconnect | boolean | no | Default true; enable automatic recovery |
| reconnectBackoffFactor | number | no | Delay multiplier, at least 1; default 1 |
| maxReconnectInterval | number | no | Delay ceiling; default max(30000, reconnectInterval) |
| maxReconnectAttempts | number | no | Retry budget excluding initial attempt; default Infinity |
| writeTimeout | number | no | Physical write/drain deadline; default 5000 ms |
| responseTimeout | number | no | serial-core response wait deadline; default 5000 ms; distinct from JSD ACK timeout |
| maxQueueSize | number | no | Active plus pending command capacity; default 1000; also bounds JSD's backlog |
| path | string | no | Explicit port path |
| vendorId | string | no | USB vendor filter when scanning |
| productId | string | no | USB product filter when scanning |
| serialNumber | string | no | Exact serial number for discovery |
| parser | NodeJS.ReadWriteStream | no | Shared custom parser, mutually exclusive with parserFactory |
| parserFactory | () => NodeJS.ReadWriteStream | no | Fresh parser each session; JSD supplies a delimiter factory by default |
| handshake | JSDHandshake | no | Custom handshake; JSD supplies a protocol handshake otherwise |
Use autoConnect: false to attach all listeners before initiating a connection. The constructor preserves the caller's configuration and supplies defaults in a separate object. A fresh parser per session prevents partial frames surviving a reconnect.
Port paths and discovery
Typical paths are /dev/ttyUSB0 or /dev/ttyACM0 on Linux, /dev/cu.usbserial-* on macOS, and COM3 on Windows. Use your actual path.
const ports = await JSD.listPorts({ availableOnly: true });
console.table(ports);JSD exposes static and instance listPorts() / findPorts() methods. Filters combine with AND and do not open ports. availableOnly checks module-local reservations, not OS-wide availability. To connect through discovery, omit path and provide vendorId, productId, or serialNumber:
const jsd = new JSD({
vendorId: '0403',
productId: '6001',
baudRate: 9600,
autoConnect: false,
reconnectInterval: 1_000
});Scanning belongs to serial-core. Its installed version selects the first matching unreserved port using normalized exact VID/PID matching and an exact serial number. An explicit path takes precedence. Enumeration errors reject; no match returns an empty list.
Readiness and reconnection
start(): void asks serial-core to connect. Observe DISCONNECTED, SCANNING, CONNECTING, CONNECTED, and RECONNECTING through serial:status. Failures are reported through serial:error and serial-core applies the configured retry budget and capped backoff. Observe serial:reconnecting with { attempt, delay } and serial:reconnectFailed with { attempts }. Counts exclude the initial connection attempt.
import { once } from 'node:events';
const ready = once(jsd, 'serial:connected', {
signal: AbortSignal.timeout(10_000)
});
jsd.start();
await ready;The example bounds the readiness wait; it does not turn serial:error into a rejection. Keep an error listener and call stop() if your application abandons connection attempts.
Default handshake and parser
JSD sends its licensing connection frame and accepts a valid ACK or DATA frame. The default handshake timeout is 500 ms. Its delimiter parser splits at 0xC0 and excludes that delimiter. Invalid frames fail CRC or frame validation.
A supplied handshake replaces the default entirely:
import type { JSDHandshake } from '@danidoble/serial-node-jsd';
const handshake: JSDHandshake = {
command: Buffer.from([/* your device handshake bytes */]),
pattern: /READY/,
timeout: 1_000
};command accepts string or Buffer, pattern string or RegExp, timeout milliseconds, hexPattern an optional boolean, and callback an optional (data: Buffer | string) => boolean. A callback, when supplied, determines success instead of the pattern. maxBufferSize bounds accumulated pattern input (default 65536 bytes). Callback mode receives individual chunks/frames. Both successful handshake transmission and validation are required. Use settings appropriate to the device.
Shutdown and retries
stop(): Promise<void> delegates to serial-core disconnect and cancels its reconnection scheduling. It also clears JSD commands, ACK timers, and delayed initial status queries. Lost session commands are never automatically replayed after reconnection. Late write callbacks from the old session cannot change a new session. Pending log reads, channel assignment, carts, and dispenses reject with JSD session ended; operation outcome may be unknown. Their polling timers are released and cached machine readiness is invalidated. This does not undo a physical operation. No per-operation cancellation handle is exposed; application deadlines are still needed if a device remains connected but never completes its response.
The JSD command queue waits for a matching ACK after physical write/drain. Its default interval is 500 ms, with the initial send plus up to three resends. NACK is exposed as an event and does not immediately remove the queued command.