TypeScript icon, indicating that this package has built-in type declarations

1.1.6 • Public • Published


An extensible framework for working with Serial-Ports that required explicitly defined protocols. Also exposes minimal well-known protocols such as Modbus.

Note: This package is recommended to be used with TypeScript however all definitions are defaulted to counter this if need be. However full-functionality will be more accessible through TypeScript (such as dynamic protocol typing).


npm install ext-port

Port Framework

As a wrapper utility, ext-port allows defining explicit protocols for a chosen serial-port. This can be done by defining a protocol and an optional parser. This package exposes varying avenues to do this (such as be regular inheritance or interface agreements). The definitions of these for ext-port are as follows:

Protocol > Type of incoming and outgoing data. These will be defined as <IN>:<OUT>.

Parser > Native stream transform implementation that uses a definable codec for encoding and decoding protocol data.

Default Port

By default, any ext.Port will use the underlying protocol of <Buffer>:<Buffer> with no parser transformation.

/// Importing (all exports also exposed as non-default)
import ext from 'ext-port';

/// Port Construction
const port = new ext.Port({ path: '/dev/ROBOT', baudRate: 38400 });

Both the path and baudRate options are required and the port does not open by default when constructed.

Protocol Declaration

A protocol can be defined in one of two ways, through the Duplex generic, or from extending the Any protocol. These typings are initially transient until a coinciding parser is also defined.

import type { Protocol } from 'ext-port';
import ext from 'ext-port';

/// Generic
type MyProtocol = Protocol.Duplex<string, [string]>;

/// Interface Extension
interface IMyProtocol extends Protocol.Any {
    incoming: string;
    outgoing: [string];

/// Usage on `ext.Port`
const port = new ext.Port<MyProtocol>({ /** ... */ });

Note: The outgoing definition is required to be in an array format. The reason for this is to allow for multiple arguments to the exposed write command for port instances.

Parser Declaration

Since protocols are inherently transient due to be type-casts only, a parser (and codec if extending from the ext-port library) is required to convert incoming and outgoing data.

Some examples for parsers can be seen in the lib/parser/impl directory, alongside additional codec examples in the lib/codec/impl directory.

Note: SerialPort.io parsers can be used interchangeable with this library. To do this, the ext.Parser.Abstract parent, directly inherits from a Transform in the same manner that the other parsers do, however adds improved functionality with Monadic style result handling.

Port Properties

path – The current serial-port path.
baudRate – The current serial-port baud-rate.
isOpen – Flag to denote the current serial-port state.
parser – Exposed access to set the current parser.

Port Methods

Most methods return a monadic result instead of required a designated callback handler. This allows for a simpler process (removing callback hell) of handling outcomes that may occur when changing state on a port instance. The library to coordinate this is ts-monadable.

open – Opens a port instance. Returns a promisified monadic result.

import ext from 'ext-port';
const port = new ext.Port({ path: '/dev/ROBOT', baudRate: 115200 });
const result = await port.open();

if (result.is('some')) /** Handle Error ... */
else /** Proceed as normal */

close – Closes a port instance. Returns a promisified monadic result.

const result = await port.close();
if (result.is('some')) console.log(result.unwrap());

write – Writes to a port instance as defined by the protocol definition.

const result = await port.write( /** Protocol Arguments... */ );

flush – Flushes a port instance.

await port.flush(); // nothing special

update – Allows updating various port properties.

port.update({ baudRate: /** ... */, parser: /** ... */ });

on – Typed event handler for exposed port events.
once – Typed event registration for once-only events.

port.on('open', () => /** Open event handler. */);
port.once('close', (disconnected: boolean) => /** Close event handler. */);

port.on('incoming', (incoming: any) => /** Decoded incoming event handler. */);
port.on('outgoing', (buffer: Buffer) => /** Encoded outgoing event handler. */);

port.on('_error', (error: ext.IPortError) => /** Error event handler. */);
port.on('_warning', (warning: ext.IPortWarning) => /** Warning event handler. */);

Note: Both items return bigint keys that can be used to later remove the associated events.

ignore – Ignores all event-listeners unless given specific keys of events to ignore.

port.ignore('incoming', /** Optional keys. */);

sleep – Sleeps for a given duration of time. Also returns input data to allow for throttling or delaying execution asynchronously.

// Regular usage
await port.sleep(1000); // wait for 1 second

// Result delay usage
const result = await port.close().then((res) => port.sleep(1000, res));


Alongside the expected serial-port functionality, some utilities are also exposed. This includes a fixed-typing stdint implementation for TypeScript, all monadic typings and some checksum algorithms.


The primary purpose of this library is to help in defining and implementing complex serial-port protocols with improved usability. To coincide with this, some protocols are implemented for use. These include:




npm i ext-port

DownloadsWeekly Downloads






Unpacked Size

195 kB

Total Files


Last publish


  • rroesslerio