Skip to content

danidoble/webserial-core

Repository files navigation

webserial-core

npm version npm downloads License: MIT TypeScript bundle size GitHub release Ask DeepWiki

A strongly-typed, event-driven, abstract TypeScript library for serial communication on the web. Supports Web Serial, WebUSB, Web Bluetooth, and WebSocket transports through a unified API.


⚠️ Breaking Changes — v2

Version 2 is a complete rewrite. Tthe public API is completally changed, please if you has an implementation of this library is better read docs as like a new integration See the Migration Guide before upgrading.


Features

  • Provider-agnostic — swap between Web Serial, WebUSB, Web Bluetooth, or WebSocket transport by injecting a single provider.
  • Strictly typed — full TypeScript generics, no implicit any, compatible with strict: true.
  • Typed eventsconnecting, connected, disconnected, data, sent, error, timeout, reconnecting, and more — all fully typed.
  • Built-in parsersdelimiter, fixedLength, raw. Implement SerialParser<T> for any custom binary or text protocol.
  • Command queue — FIFO write queue with optional per-command timeouts.
  • Auto-reconnect — configurable reconnect loop with back-off.
  • WebUSB polyfill — full WebUSB serial polyfill (CDC ACM, CP210x, CH340).
  • BLE NUS adapter — Nordic UART Service over Web Bluetooth GATT.
  • WebSocket bridge — relay serial I/O through a Node.js bridge server.

Installation

npm install webserial-core

Quick start

import { AbstractSerialDevice, delimiter } from "webserial-core";

class MyDevice extends AbstractSerialDevice<string> {
  constructor() {
    super({
      baudRate: 9600,
      parser: delimiter("\n"),
      autoReconnect: true,
    });
  }

  protected async handshake(): Promise<boolean> {
    return true; // return false to reject the port
  }
}

const device = new MyDevice();

device.on("serial:connected", () => console.log("Connected!"));
device.on("serial:data", (line) => console.log("←", line));
device.on("serial:disconnected", () => console.log("Disconnected."));
device.on("serial:error", (err) => console.error(err.message));

await device.connect(); // opens the browser port picker
await device.send("PING\n"); // enqueues a write
await device.disconnect();

Transport adapters

All four adapters expose the same SerialProvider interface. Inject your chosen adapter once before constructing any device:

import { AbstractSerialDevice, WebUsbProvider } from "webserial-core";
import { createBluetoothProvider } from "webserial-core";
import { createWebSocketProvider } from "webserial-core";

// WebUSB polyfill (Android Chrome, or desktop for testing)
AbstractSerialDevice.setProvider(new WebUsbProvider());

// Web Bluetooth (Nordic UART Service over BLE GATT)
AbstractSerialDevice.setProvider(createBluetoothProvider());

// WebSocket bridge (requires Node.js server — see demos/websocket/)
AbstractSerialDevice.setProvider(
  createWebSocketProvider("ws://localhost:8080"),
);

Parsers

import { delimiter, fixedLength, raw } from "webserial-core";

// Newline-delimited strings (Arduino Serial.println)
parser: delimiter("\n");

// 16-byte binary packets
parser: fixedLength(16);

// Raw Uint8Array chunks
parser: raw();

Events

Event Payload Description
serial:connecting connect() called, port picker about to open
serial:connected Port open, handshake passed
serial:disconnected Port closed
serial:data T Parser emitted a complete message
serial:sent Uint8Array Bytes written to the port
serial:error Error Unrecoverable error
serial:need-permission User denied access
serial:timeout Uint8Array Command timed out
serial:queue-empty Write queue is now idle
serial:reconnecting Auto-reconnect attempt starting

Project structure

src/
  core/           AbstractSerialDevice, SerialEventEmitter, SerialRegistry
  adapters/
    web-usb/      WebUsbProvider (WebUSB polyfill)
    web-bluetooth/ createBluetoothProvider (BLE NUS)
    websocket/    createWebSocketProvider (Node.js bridge)
  parsers/        delimiter, fixedLength, raw
  queue/          CommandQueue
  errors/         SerialPortConflictError, SerialPermissionError, …
  types/          SerialDeviceOptions, SerialProvider, SerialParser, …
demos/
  web-serial/     Native Web Serial demo
  web-usb/        WebUSB polyfill demo
  web-bluetooth/  Web Bluetooth BLE demo
  websocket/      WebSocket bridge demo + Node.js server
docs/             VitePress documentation site

Building

npm run build

Output in dist/:

File Format Use case
webserial-core.mjs ESM Bundlers, modern browsers
webserial-core.cjs CJS Node.js, legacy bundlers
webserial-core.umd.cjs UMD <script> tag, CDN
index.d.ts TypeScript Type declarations

Documentation

npm run docs:dev   # live VitePress server
npm run docs:build # static build → docs/.vitepress/dist

Browser compatibility

Feature Browser requirement
Web Serial Chrome 89+, Edge 89+
WebUSB Chrome 61+, Edge 79+
Web Bluetooth Chrome 56+, Edge 79+
WebSocket All modern browsers

All browser APIs require a secure context (HTTPS or localhost).

License

MIT © danidoble

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

 
 
 

Contributors