webserial-core 1.2.1 → 2.0.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/{LICENSE → LICENSE.md} +1 -1
  2. package/README.md +142 -287
  3. package/dist/adapters/web-bluetooth/WebBluetoothProvider.d.ts +19 -0
  4. package/dist/adapters/web-bluetooth/index.d.ts +6 -0
  5. package/dist/adapters/web-usb/WebUsbProvider.d.ts +127 -0
  6. package/dist/adapters/web-usb/index.d.ts +6 -0
  7. package/dist/adapters/websocket/WebSocketProvider.d.ts +20 -0
  8. package/dist/adapters/websocket/index.d.ts +6 -0
  9. package/dist/core/AbstractSerialDevice.d.ts +108 -0
  10. package/dist/core/SerialEventEmitter.d.ts +37 -0
  11. package/dist/core/SerialRegistry.d.ts +53 -0
  12. package/dist/errors/index.d.ts +40 -0
  13. package/dist/index.d.ts +10 -0
  14. package/dist/parsers/DelimiterParser.d.ts +22 -0
  15. package/dist/parsers/FixedLengthParser.d.ts +23 -0
  16. package/dist/parsers/RawParser.d.ts +22 -0
  17. package/dist/parsers/index.d.ts +7 -0
  18. package/dist/queue/CommandQueue.d.ts +98 -0
  19. package/dist/types/index.d.ts +124 -0
  20. package/dist/webserial-core.cjs +1 -0
  21. package/dist/webserial-core.mjs +853 -0
  22. package/dist/webserial-core.umd.js +1 -0
  23. package/package.json +62 -68
  24. package/dist/types/Core.d.ts +0 -268
  25. package/dist/types/Core.d.ts.map +0 -1
  26. package/dist/types/Devices.d.ts +0 -62
  27. package/dist/types/Devices.d.ts.map +0 -1
  28. package/dist/types/Dispatcher.d.ts +0 -98
  29. package/dist/types/Dispatcher.d.ts.map +0 -1
  30. package/dist/types/SerialError.d.ts +0 -61
  31. package/dist/types/SerialError.d.ts.map +0 -1
  32. package/dist/types/SerialEvent.d.ts +0 -4
  33. package/dist/types/SerialEvent.d.ts.map +0 -1
  34. package/dist/types/Socket.d.ts +0 -29
  35. package/dist/types/Socket.d.ts.map +0 -1
  36. package/dist/types/main.d.ts +0 -15
  37. package/dist/types/main.d.ts.map +0 -1
  38. package/dist/types/utils.d.ts +0 -3
  39. package/dist/types/utils.d.ts.map +0 -1
  40. package/dist/webserial-core.js +0 -1241
  41. package/dist/webserial-core.js.map +0 -1
  42. package/dist/webserial-core.umd.cjs +0 -5
  43. package/dist/webserial-core.umd.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 danidoble
3
+ Copyright (c) 2026 danidoble
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,30 +1,43 @@
1
- # WebSerial Core
1
+ # webserial-core
2
2
 
3
- An easy way to connect to a serial port from a web page.
4
-
5
- [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/danidoble/webserial-core)
6
3
  [![npm version](https://badge.fury.io/js/webserial-core.svg)](https://www.npmjs.com/package/webserial-core)
4
+ [![npm downloads](https://img.shields.io/npm/dm/webserial-core)](https://www.npmjs.com/package/webserial-core)
7
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ ![TypeScript](https://img.shields.io/badge/TypeScript-ready-blue)
7
+ ![bundle size](https://img.shields.io/bundlephobia/minzip/webserial-core)
8
+ ![GitHub release](https://img.shields.io/github/v/release/danidoble/webserial-core)
9
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/danidoble/webserial-core)
10
+
11
+
12
+ A strongly-typed, event-driven, abstract TypeScript library for serial
13
+ communication on the web. Supports **Web Serial**, **WebUSB**, **Web
14
+ Bluetooth**, and **WebSocket** transports through a unified API.
8
15
 
9
- > [!NOTE]
10
- > Since version 1.0.7 default response is an instance of Uint8Array.
11
- > To change the response put this code inside your constructor to change the default response.
12
- > `this.getResponseAsArrayBuffer()`
13
- > `this.getResponseAsArrayHex()`
14
- > `this.getResponseAsUint8Array()`
15
- > `this.getResponseAsString()`
16
- > Only choose one of them.
16
+ ---
17
+
18
+ > **⚠️ Breaking Changes v2**
19
+ >
20
+ > Version 2 is a complete rewrite. Tthe public API is completally changed,
21
+ > please if you has an implementation of this library is better read docs as like a
22
+ > new integration See the [Migration Guide](docs/guide/migration-v1-v2.md) before upgrading.
23
+
24
+ ---
17
25
 
18
26
  ## Features
19
27
 
20
- - 🔌 Easy serial port connection from web browsers
21
- - 🎯 TypeScript support with full type definitions
22
- - 🧪 Comprehensive test suite with Vitest
23
- - 📦 Multiple module formats (ESM, UMD)
24
- - 🔍 Source maps for debugging
25
- - 🌐 Socket.io integration for remote connections
26
- - ⚡ Event-driven architecture
27
- - 🛡️ Custom error handling with `SerialError`
28
+ - **Provider-agnostic** swap between Web Serial, WebUSB, Web Bluetooth, or
29
+ WebSocket transport by injecting a single provider.
30
+ - **Strictly typed** full TypeScript generics, no implicit `any`, compatible
31
+ with `strict: true`.
32
+ - **Typed events** `connecting`, `connected`, `disconnected`, `data`,
33
+ `sent`, `error`, `timeout`, `reconnecting`, and more — all fully typed.
34
+ - **Built-in parsers** — `delimiter`, `fixedLength`, `raw`. Implement
35
+ `SerialParser<T>` for any custom binary or text protocol.
36
+ - **Command queue** — FIFO write queue with optional per-command timeouts.
37
+ - **Auto-reconnect** — configurable reconnect loop with back-off.
38
+ - **WebUSB polyfill** — full WebUSB serial polyfill (CDC ACM, CP210x, CH340).
39
+ - **BLE NUS adapter** — Nordic UART Service over Web Bluetooth GATT.
40
+ - **WebSocket bridge** — relay serial I/O through a Node.js bridge server.
28
41
 
29
42
  ## Installation
30
43
 
@@ -32,301 +45,143 @@ An easy way to connect to a serial port from a web page.
32
45
  npm install webserial-core
33
46
  ```
34
47
 
35
- ## Usage
48
+ ## Quick start
36
49
 
37
- > [!NOTE]
38
- > If you are using Linux, you need to add your user to the `dialout` group to access the serial port.
39
- > ```bash
40
- > sudo usermod -a -G dialout $USER
41
- > ```
42
- > After that, you need to log out and log in again to apply the changes.
50
+ ```ts
51
+ import { AbstractSerialDevice, delimiter } from "webserial-core";
43
52
 
44
- You need to create a new class to configure your device functions. In this example, we are going to create a class to
45
- connect to an Arduino device.
53
+ class MyDevice extends AbstractSerialDevice<string> {
54
+ constructor() {
55
+ super({
56
+ baudRate: 9600,
57
+ parser: delimiter("\n"),
58
+ autoReconnect: true,
59
+ });
60
+ }
46
61
 
47
- The first step is having the Arduino code ready. In this case, we are going to use the following code.
62
+ protected async handshake(): Promise<boolean> {
63
+ return true; // return false to reject the port
64
+ }
65
+ }
48
66
 
49
- ```cpp
50
- // serial.ino
67
+ const device = new MyDevice();
51
68
 
52
- void setup() {
53
- Serial.begin(9600);
54
- }
69
+ device.on("serial:connected", () => console.log("Connected!"));
70
+ device.on("serial:data", (line) => console.log("←", line));
71
+ device.on("serial:disconnected", () => console.log("Disconnected."));
72
+ device.on("serial:error", (err) => console.error(err.message));
55
73
 
56
- void loop() {
57
- if (Serial.available() > 0) { // Check if data to read is available
58
- String comando = Serial.readStringUntil('\n'); // read the data until a new line is found
59
-
60
- if(comando.startsWith("CONNECT")){
61
- Serial.println("connected");
62
- } else if (comando.startsWith("CREDITS")) {
63
- Serial.println("created by danidoble");
64
- } else if (comando.startsWith("HI")) {
65
- Serial.println("hello there");
66
- } else {
67
- Serial.println("ara ara, what are you doing?");
68
- }
69
- }
70
- }
74
+ await device.connect(); // opens the browser port picker
75
+ await device.send("PING\n"); // enqueues a write
76
+ await device.disconnect();
71
77
  ```
72
78
 
73
- Create a new class to connect to the device.
74
-
75
- ```javascript
76
- // arduino.js
77
- import { Core } from 'webserial-core';
78
-
79
- export class Arduino extends Core {
80
- constructor(
81
- {
82
- filters = null,
83
- config_port = {
84
- baudRate: 9600,
85
- dataBits: 8,
86
- stopBits: 1,
87
- parity: "none",
88
- bufferSize: 32768,
89
- flowControl: "none",
90
- },
91
- no_device = 1,
92
- } = {
93
- filters: null,
94
- config_port: {
95
- baudRate: 9600,
96
- dataBits: 8,
97
- stopBits: 1,
98
- parity: "none",
99
- bufferSize: 32768,
100
- flowControl: "none",
101
- },
102
- no_device: 1,
103
- }
104
- ) {
105
- super({ filters, config_port, no_device });
106
- this.__internal__.device.type = "arduino";
107
- Devices.registerType(this.__internal__.device.type);
108
- if (Devices.getByNumber(this.typeDevice, no_device)) {
109
- throw new Error(`Device ${this.typeDevice} ${no_device} already exists`);
110
- }
111
- this.__internal__.time.response_connection = 2e3;
112
- this.__internal__.time.response_general = 2e3;
113
- this.__internal__.serial.delay_first_connection = 1_000;
114
- this.#registerAvailableListenersArduino();
115
- Devices.add(this);
116
- this.getResponseAsString();
117
- }
79
+ ## Transport adapters
118
80
 
119
- #registerAvailableListenersArduino() {
120
- /*const _ = [
121
- 'my_own_event_dispatched',
122
- 'my_other_own_event_dispatched',
123
- ];
124
- for (const event of _) {
125
- this.serialRegisterAvailableListener(event)
126
- }
127
- */
128
- }
81
+ All four adapters expose the same `SerialProvider` interface. Inject your
82
+ chosen adapter once before constructing any device:
129
83
 
130
- serialMessage(codex) {
131
- const message = {
132
- code: [],
133
- name: "",
134
- description: "",
135
- request: "",
136
- no_code: 0,
137
- };
138
-
139
- message.code = codex;
140
-
141
- switch (codex) {
142
- case "connected":
143
- message.name = "connected";
144
- message.description = "Connection established";
145
- message.request = "connect";
146
- message.no_code = 100;
147
- break;
148
- case "created by danidoble":
149
- message.name = "thanks";
150
- message.description = "thanks for using this software";
151
- message.request = "credits";
152
- message.no_code = 101;
153
- break;
154
- case "hello there":
155
- message.name = "hello there";
156
- message.description = "hi human";
157
- message.request = "hi";
158
- message.no_code = 102;
159
- break;
160
- case "ara ara":
161
- message.name = "ara ara";
162
- message.description = "troll";
163
- message.request = "ara ara";
164
- message.no_code = 404;
165
- break;
166
- default:
167
- message.name = "unknown";
168
- message.description = "Unknown command";
169
- message.request = "unknown";
170
- message.no_code = 400;
171
- break;
172
- }
173
-
174
- this.dispatch("serial:message", message);
175
- }
84
+ ```ts
85
+ import { AbstractSerialDevice, WebUsbProvider } from "webserial-core";
86
+ import { createBluetoothProvider } from "webserial-core";
87
+ import { createWebSocketProvider } from "webserial-core";
176
88
 
177
- serialSetConnectionConstant() {
178
- return this.add0x(this.parseStringToBytes("CONNECT"));
179
- }
89
+ // WebUSB polyfill (Android Chrome, or desktop for testing)
90
+ AbstractSerialDevice.setProvider(new WebUsbProvider());
180
91
 
181
- async sayCredits() {
182
- const arr = this.parseStringToBytes("CREDITS");
183
- await this.appendToQueue(arr, "credits");
184
- }
92
+ // Web Bluetooth (Nordic UART Service over BLE GATT)
93
+ AbstractSerialDevice.setProvider(createBluetoothProvider());
185
94
 
186
- async sayHi() {
187
- const arr = this.parseStringToBytes("HI");
188
- await this.appendToQueue(arr, "hi");
189
- }
95
+ // WebSocket bridge (requires Node.js server — see demos/websocket/)
96
+ AbstractSerialDevice.setProvider(
97
+ createWebSocketProvider("ws://localhost:8080"),
98
+ );
99
+ ```
190
100
 
191
- async sayAra() {
192
- const arr = this.parseStringToBytes("OTHER");
193
- await this.appendToQueue(arr, "ara");
194
- }
101
+ ## Parsers
195
102
 
196
- async sendCustomCode({ code = "" } = { code: "" }) {
197
- if (typeof code !== "string") throw new Error("Invalid string");
198
- const arr = this.parseStringToBytes(code);
199
- await this.appendToQueue(arr, "custom");
200
- }
201
- }
103
+ ```ts
104
+ import { delimiter, fixedLength, raw } from "webserial-core";
105
+
106
+ // Newline-delimited strings (Arduino Serial.println)
107
+ parser: delimiter("\n");
108
+
109
+ // 16-byte binary packets
110
+ parser: fixedLength(16);
111
+
112
+ // Raw Uint8Array chunks
113
+ parser: raw();
202
114
  ```
203
115
 
204
- Then you can use the class to connect to your device.
205
-
206
- ```javascript
207
- // serialConnection.js
208
-
209
- import { Arduino } from './arduino.js';
210
-
211
- const arduino = new Arduino();
212
-
213
- arduino.on('serial:message', (message) => {
214
- console.log(message);
215
- });
216
-
217
- arduino.on('serial:timeout', (data) => {
218
- console.log('serial:timeout', data.detail);
219
- });
220
-
221
- // if you need to debug the data sent
222
- // arduino.on('serial:sent', data => {
223
- // console.log('serial:sent',data.detail);
224
- // });
225
-
226
- arduino.on('serial:error', (event) => {
227
- document.getElementById('log').innerText += event.detail.message + '\n\n';
228
- });
229
-
230
- // eslint-disable-next-line no-unused-vars
231
- arduino.on('serial:disconnected', (event) => {
232
- document.getElementById('log').innerText += 'Disconnected\n\n';
233
-
234
- document.getElementById('disconnected').classList.remove('hidden');
235
- document.getElementById('connect').classList.remove('hidden');
236
- document.getElementById("disconnect")?.classList.add("hidden");
237
- });
238
-
239
- // eslint-disable-next-line no-unused-vars
240
- arduino.on('serial:connecting', (event) => {
241
- document.getElementById('log').innerText += 'Connecting\n\n';
242
- });
243
-
244
- // eslint-disable-next-line no-unused-vars
245
- arduino.on('serial:connected', (event) => {
246
- document.getElementById('log').innerText += 'Connected\n\n';
247
-
248
- document.getElementById('disconnected').classList.add('hidden');
249
- document.getElementById('need-permission').classList.add('hidden');
250
- document.getElementById('connect').classList.add('hidden');
251
- document.getElementById("disconnect")?.classList.remove("hidden");
252
- });
253
-
254
- // eslint-disable-next-line no-unused-vars
255
- arduino.on('serial:need-permission', (event) => {
256
- document.getElementById('disconnected').classList.remove('hidden');
257
- document.getElementById('need-permission').classList.remove('hidden');
258
- document.getElementById('connect').classList.remove('hidden');
259
- document.getElementById("disconnect")?.classList.add("hidden");
260
- });
261
-
262
- // eslint-disable-next-line no-unused-vars
263
- arduino.on('serial:soft-reload', (event) => {
264
- // reset your variables
265
- });
266
-
267
- // eslint-disable-next-line no-unused-vars
268
- arduino.on('serial:unsupported', (event) => {
269
- document.getElementById('unsupported').classList.remove('hidden');
270
- });
271
-
272
- function tryConnect() {
273
- arduino
274
- .connect()
275
- .then(() => {})
276
- .catch(console.error);
277
- }
116
+ ## Events
278
117
 
279
- document.addEventListener('DOMContentLoaded', () => {
280
- tryConnect();
281
- document.getElementById('connect')?.addEventListener('click', tryConnect);
282
- document.getElementById("disconnect")?.addEventListener("click", async () => {
283
- await board.disconnect().catch(console.error);
284
- document.getElementById('log')?.innerText += 'Disconnected by user\n\n';
285
- });
286
- });
118
+ | Event | Payload | Description |
119
+ | ------------------------ | ------------ | --------------------------------------------- |
120
+ | `serial:connecting` | — | `connect()` called, port picker about to open |
121
+ | `serial:connected` | — | Port open, handshake passed |
122
+ | `serial:disconnected` | — | Port closed |
123
+ | `serial:data` | `T` | Parser emitted a complete message |
124
+ | `serial:sent` | `Uint8Array` | Bytes written to the port |
125
+ | `serial:error` | `Error` | Unrecoverable error |
126
+ | `serial:need-permission` | — | User denied access |
127
+ | `serial:timeout` | `Uint8Array` | Command timed out |
128
+ | `serial:queue-empty` | — | Write queue is now idle |
129
+ | `serial:reconnecting` | — | Auto-reconnect attempt starting |
287
130
 
131
+ ## Project structure
132
+
133
+ ```
134
+ src/
135
+ core/ AbstractSerialDevice, SerialEventEmitter, SerialRegistry
136
+ adapters/
137
+ web-usb/ WebUsbProvider (WebUSB polyfill)
138
+ web-bluetooth/ createBluetoothProvider (BLE NUS)
139
+ websocket/ createWebSocketProvider (Node.js bridge)
140
+ parsers/ delimiter, fixedLength, raw
141
+ queue/ CommandQueue
142
+ errors/ SerialPortConflictError, SerialPermissionError, …
143
+ types/ SerialDeviceOptions, SerialProvider, SerialParser, …
144
+ demos/
145
+ web-serial/ Native Web Serial demo
146
+ web-usb/ WebUSB polyfill demo
147
+ web-bluetooth/ Web Bluetooth BLE demo
148
+ websocket/ WebSocket bridge demo + Node.js server
149
+ docs/ VitePress documentation site
288
150
  ```
289
151
 
290
- But wait still need to create the HTML file.
152
+ ## Building
291
153
 
292
- ```html
293
- <!doctype html>
294
- <html lang="en">
154
+ ```bash
155
+ npm run build
156
+ ```
295
157
 
296
- <head>
297
- <meta charset="UTF-8">
298
- <meta name="viewport" content="width=device-width, initial-scale=1">
299
- <title>Webserial</title>
300
- <script src="./serialConnection.js" type="module"></script>
301
- </head>
158
+ Output in `dist/`:
302
159
 
303
- <body class="bg-neutral-950 text-white p-4 w-full">
160
+ | File | Format | Use case |
161
+ | ------------------------ | ---------- | ------------------------- |
162
+ | `webserial-core.mjs` | ESM | Bundlers, modern browsers |
163
+ | `webserial-core.cjs` | CJS | Node.js, legacy bundlers |
164
+ | `webserial-core.umd.cjs` | UMD | `<script>` tag, CDN |
165
+ | `index.d.ts` | TypeScript | Type declarations |
304
166
 
305
- <div class="webserial w-full max-w-xl mx-auto grid grid-cols-1 gap-y-4">
306
- <div class="my-6"></div>
307
- <button id="connect" class="hidden px-4 py-3 bg-gray-800 rounded-lg">Connect to serial</button>
308
- <button id="disconnect" class="hidden px-4 py-3 bg-rose-800 rounded-lg">Disconnect device</button>
167
+ ## Documentation
309
168
 
310
- <div id="need-permission" class="hidden p-4 bg-rose-900 rounded-lg">
311
- Woooah! It seems that you need to give permission to access the serial port.
312
- Please, click the button 'Connect to serial' to try again.
313
- </div>
169
+ ```bash
170
+ npm run docs:dev # live VitePress server
171
+ npm run docs:build # static build docs/.vitepress/dist
172
+ ```
314
173
 
315
- <div id="disconnected" class="hidden p-4 bg-neutral-900 w-full">
316
- The arduino is disconnected. Please, check the connection.
317
- </div>
174
+ ## Browser compatibility
318
175
 
319
- <div id="unsupported" class="hidden p-4 bg-orange-700 w-full absolute bottom-0 left-0">
320
- This browser does not support the WebSerial API. Please, use a compatible browser.
321
- </div>
176
+ | Feature | Browser requirement |
177
+ | ------------- | -------------------- |
178
+ | Web Serial | Chrome 89+, Edge 89+ |
179
+ | WebUSB | Chrome 61+, Edge 79+ |
180
+ | Web Bluetooth | Chrome 56+, Edge 79+ |
181
+ | WebSocket | All modern browsers |
322
182
 
323
- <div id="log" class="bg-neutral-800 p-4 rounded-lg">
324
- Log: <br>
325
- </div>
326
- </div>
183
+ All browser APIs require a **secure context** (HTTPS or `localhost`).
327
184
 
328
- <script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio,container-queries"></script>
329
- </body>
185
+ ## License
330
186
 
331
- </html>
332
- ```
187
+ MIT © [danidoble](https://github.com/danidoble/webserial-core)
@@ -0,0 +1,19 @@
1
+ import { SerialProvider } from '../../types/index.js';
2
+ /**
3
+ * Creates a {@link SerialProvider} that uses the Web Bluetooth API
4
+ * to communicate with Nordic UART Service (NUS) devices.
5
+ *
6
+ * Pass the returned provider to `AbstractSerialDevice.setProvider()` before
7
+ * calling `connect()`.
8
+ *
9
+ * @returns A `SerialProvider` backed by the Web Bluetooth API.
10
+ * @throws {Error} If `navigator.bluetooth` is not available in the current environment.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { createBluetoothProvider, AbstractSerialDevice } from 'webserial-core';
15
+ *
16
+ * AbstractSerialDevice.setProvider(createBluetoothProvider());
17
+ * ```
18
+ */
19
+ export declare function createBluetoothProvider(): SerialProvider;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @file index.ts
3
+ * Web Bluetooth adapter — re-exports `createBluetoothProvider` as the public API
4
+ * for using the Web Bluetooth (Nordic UART Service) transport.
5
+ */
6
+ export { createBluetoothProvider } from './WebBluetoothProvider.js';
@@ -0,0 +1,127 @@
1
+ import { SerialPolyfillOptions, SerialPortFilter, SerialProvider } from '../../types/index.js';
2
+ interface USBDeviceFilter {
3
+ vendorId?: number;
4
+ productId?: number;
5
+ classCode?: number;
6
+ subclassCode?: number;
7
+ protocolCode?: number;
8
+ serialNumber?: string;
9
+ }
10
+ interface USBEndpoint {
11
+ readonly endpointNumber: number;
12
+ readonly direction: "in" | "out";
13
+ readonly type: "bulk" | "interrupt" | "isochronous";
14
+ readonly packetSize: number;
15
+ }
16
+ interface USBAlternateInterface {
17
+ readonly alternateSetting: number;
18
+ readonly interfaceClass: number;
19
+ readonly interfaceSubclass: number;
20
+ readonly interfaceProtocol: number;
21
+ readonly interfaceName: string | undefined;
22
+ readonly endpoints: readonly USBEndpoint[];
23
+ }
24
+ interface USBInterface {
25
+ readonly interfaceNumber: number;
26
+ readonly alternate: USBAlternateInterface;
27
+ readonly alternates: readonly USBAlternateInterface[];
28
+ readonly claimed: boolean;
29
+ }
30
+ interface USBConfiguration {
31
+ readonly configurationValue: number;
32
+ readonly configurationName: string | undefined;
33
+ readonly interfaces: readonly USBInterface[];
34
+ }
35
+ interface USBInTransferResult {
36
+ readonly data: DataView | undefined;
37
+ readonly status: "ok" | "stall" | "babble";
38
+ }
39
+ interface USBOutTransferResult {
40
+ readonly bytesWritten: number;
41
+ readonly status: "ok" | "stall";
42
+ }
43
+ interface USBControlTransferParameters {
44
+ requestType: "standard" | "class" | "vendor";
45
+ recipient: "device" | "interface" | "endpoint" | "other";
46
+ request: number;
47
+ value: number;
48
+ index: number;
49
+ }
50
+ interface USBDevice {
51
+ readonly vendorId: number;
52
+ readonly productId: number;
53
+ readonly configuration: USBConfiguration | null;
54
+ readonly configurations: readonly USBConfiguration[];
55
+ readonly opened: boolean;
56
+ open(): Promise<void>;
57
+ close(): Promise<void>;
58
+ forget(): Promise<void>;
59
+ selectConfiguration(configurationValue: number): Promise<void>;
60
+ claimInterface(interfaceNumber: number): Promise<void>;
61
+ releaseInterface(interfaceNumber: number): Promise<void>;
62
+ controlTransferOut(setup: USBControlTransferParameters, data?: BufferSource): Promise<USBOutTransferResult>;
63
+ transferIn(endpointNumber: number, length: number): Promise<USBInTransferResult>;
64
+ transferOut(endpointNumber: number, data: ArrayBuffer): Promise<USBOutTransferResult>;
65
+ }
66
+ interface USB {
67
+ requestDevice(options: {
68
+ filters: USBDeviceFilter[];
69
+ }): Promise<USBDevice>;
70
+ getDevices(): Promise<USBDevice[]>;
71
+ }
72
+ declare global {
73
+ interface Navigator {
74
+ readonly usb: USB;
75
+ }
76
+ }
77
+ /**
78
+ * A {@link SerialProvider} implementation that uses the WebUSB API.
79
+ *
80
+ * Supported protocols (auto-detected unless overridden via `protocol`):
81
+ * - `cdc_acm` — Standard CDC ACM (auto-detected for interface class 2).
82
+ * - `cp210x` — Silicon Labs CP2102/CP2104 (auto-detected for vendorId `0x10c4`).
83
+ * - `none` — Raw bulk transfer, no initialization commands sent.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * import { WebUsbProvider, AbstractSerialDevice } from 'webserial-core';
88
+ *
89
+ * // Standard CDC ACM device (class 2, auto-detected)
90
+ * AbstractSerialDevice.setProvider(new WebUsbProvider());
91
+ *
92
+ * // Vendor-specific device with CP210x (e.g. ESP32 with CP2102)
93
+ * AbstractSerialDevice.setProvider(new WebUsbProvider({
94
+ * usbControlInterfaceClass: 255,
95
+ * usbTransferInterfaceClass: 255,
96
+ * }));
97
+ * ```
98
+ */
99
+ export declare class WebUsbProvider implements SerialProvider {
100
+ private readonly options_;
101
+ /**
102
+ * @param options - Optional USB interface class and protocol settings.
103
+ * Defaults to CDC ACM (interface class 2).
104
+ */
105
+ constructor(options?: SerialPolyfillOptions);
106
+ /**
107
+ * Prompts the user to select a USB device and returns a `SerialPort`-
108
+ * compatible wrapper for it.
109
+ *
110
+ * @param options - Optional filter list to narrow the USB device picker.
111
+ * @param polyfillOptions - Per-request override of polyfill settings.
112
+ * @returns A `SerialPort`-compatible object backed by the selected USB device.
113
+ * @throws {DOMException} If the user cancels the device picker.
114
+ */
115
+ requestPort(options?: {
116
+ filters?: SerialPortFilter[];
117
+ }, polyfillOptions?: SerialPolyfillOptions): Promise<SerialPort>;
118
+ /**
119
+ * Returns `SerialPort`-compatible wrappers for all previously granted
120
+ * USB devices.
121
+ *
122
+ * @param polyfillOptions - Per-request override of polyfill settings.
123
+ * @returns An array of `SerialPort`-compatible objects.
124
+ */
125
+ getPorts(polyfillOptions?: SerialPolyfillOptions): Promise<SerialPort[]>;
126
+ }
127
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @file index.ts
3
+ * Web USB adapter — re-exports `WebUsbProvider` as the public API
4
+ * for using the WebUSB API as a serial transport.
5
+ */
6
+ export { WebUsbProvider } from './WebUsbProvider.js';
@@ -0,0 +1,20 @@
1
+ import { SerialProvider } from '../../types/index.js';
2
+ /**
3
+ * Creates a {@link SerialProvider} that communicates with a Node.js serial
4
+ * bridge server over WebSockets.
5
+ *
6
+ * The bridge server must implement the JSON wire protocol described in this
7
+ * file's module documentation. A reference implementation is provided in
8
+ * `demos/websocket/server.js`.
9
+ *
10
+ * @param serverUrl - The WebSocket URL of the bridge server (e.g. `"ws://localhost:8080"`).
11
+ * @returns A `SerialProvider` that relays serial I/O over WebSocket.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { createWebSocketProvider, AbstractSerialDevice } from 'webserial-core';
16
+ *
17
+ * AbstractSerialDevice.setProvider(createWebSocketProvider('ws://localhost:8080'));
18
+ * ```
19
+ */
20
+ export declare function createWebSocketProvider(serverUrl: string): SerialProvider;