react-native-web-serial-api 0.0.3 → 0.1.0

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 (119) hide show
  1. package/README.md +23 -0
  2. package/TESTING.md +301 -0
  3. package/android/build.gradle +2 -2
  4. package/lib/commonjs/UsbSerial.js +58 -26
  5. package/lib/commonjs/UsbSerial.js.map +1 -1
  6. package/lib/commonjs/WebSerial.js +169 -57
  7. package/lib/commonjs/WebSerial.js.map +1 -1
  8. package/lib/commonjs/index.js +13 -1
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/lib/dom-exception.js +176 -0
  11. package/lib/commonjs/lib/dom-exception.js.map +1 -0
  12. package/lib/commonjs/lib/event-target.js +138 -0
  13. package/lib/commonjs/lib/event-target.js.map +1 -0
  14. package/lib/commonjs/lib/promise.js +23 -0
  15. package/lib/commonjs/lib/promise.js.map +1 -0
  16. package/lib/commonjs/testing/index.js +70 -0
  17. package/lib/commonjs/testing/index.js.map +1 -0
  18. package/lib/commonjs/testing/install.js +54 -0
  19. package/lib/commonjs/testing/install.js.map +1 -0
  20. package/lib/commonjs/testing/serial-device.js +164 -0
  21. package/lib/commonjs/testing/serial-device.js.map +1 -0
  22. package/lib/commonjs/testing/virtual-serial.js +615 -0
  23. package/lib/commonjs/testing/virtual-serial.js.map +1 -0
  24. package/lib/commonjs/transport.js +61 -0
  25. package/lib/commonjs/transport.js.map +1 -0
  26. package/lib/typescript/src/UsbSerial.d.ts +24 -67
  27. package/lib/typescript/src/UsbSerial.d.ts.map +1 -1
  28. package/lib/typescript/src/WebSerial.d.ts +11 -2
  29. package/lib/typescript/src/WebSerial.d.ts.map +1 -1
  30. package/lib/typescript/src/index.d.ts +2 -0
  31. package/lib/typescript/src/index.d.ts.map +1 -1
  32. package/lib/typescript/src/lib/dom-exception.d.ts +100 -0
  33. package/lib/typescript/src/lib/dom-exception.d.ts.map +1 -0
  34. package/lib/typescript/src/lib/event-target.d.ts +53 -0
  35. package/lib/typescript/src/lib/event-target.d.ts.map +1 -0
  36. package/lib/typescript/src/lib/promise.d.ts +11 -0
  37. package/lib/typescript/src/lib/promise.d.ts.map +1 -0
  38. package/lib/typescript/src/testing/index.d.ts +23 -0
  39. package/lib/typescript/src/testing/index.d.ts.map +1 -0
  40. package/lib/typescript/src/testing/install.d.ts +25 -0
  41. package/lib/typescript/src/testing/install.d.ts.map +1 -0
  42. package/lib/typescript/src/testing/serial-device.d.ts +127 -0
  43. package/lib/typescript/src/testing/serial-device.d.ts.map +1 -0
  44. package/lib/typescript/src/testing/virtual-serial.d.ts +205 -0
  45. package/lib/typescript/src/testing/virtual-serial.d.ts.map +1 -0
  46. package/lib/typescript/src/transport.d.ts +131 -0
  47. package/lib/typescript/src/transport.d.ts.map +1 -0
  48. package/package.json +38 -2
  49. package/src/UsbSerial.ts +65 -90
  50. package/src/WebSerial.ts +227 -88
  51. package/src/index.ts +2 -7
  52. package/src/lib/dom-exception.ts +129 -60
  53. package/src/lib/event-target.ts +46 -21
  54. package/src/lib/promise.ts +7 -7
  55. package/src/testing/index.ts +42 -0
  56. package/src/testing/install.ts +65 -0
  57. package/src/testing/serial-device.ts +193 -0
  58. package/src/testing/virtual-serial.ts +801 -0
  59. package/src/transport.ts +200 -0
  60. package/babel.config.js +0 -3
  61. package/biome.json +0 -35
  62. package/example/.watchmanconfig +0 -1
  63. package/example/App.tsx +0 -71
  64. package/example/__tests__/App.test.tsx +0 -16
  65. package/example/__tests__/connectEvents.test.tsx +0 -81
  66. package/example/__tests__/getPorts.test.tsx +0 -140
  67. package/example/android/app/build.gradle +0 -120
  68. package/example/android/app/debug.keystore +0 -0
  69. package/example/android/app/proguard-rules.pro +0 -10
  70. package/example/android/app/src/debug/AndroidManifest.xml +0 -9
  71. package/example/android/app/src/main/AndroidManifest.xml +0 -38
  72. package/example/android/app/src/main/java/dev/uzlopak/MainActivity.kt +0 -22
  73. package/example/android/app/src/main/java/dev/uzlopak/MainApplication.kt +0 -41
  74. package/example/android/app/src/main/res/drawable/rn_edit_text_material.xml +0 -37
  75. package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  76. package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  77. package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  78. package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  79. package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  80. package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  81. package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  82. package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  83. package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  84. package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  85. package/example/android/app/src/main/res/values/strings.xml +0 -3
  86. package/example/android/app/src/main/res/values/styles.xml +0 -9
  87. package/example/android/build.gradle +0 -22
  88. package/example/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  89. package/example/android/gradle/wrapper/gradle-wrapper.properties +0 -7
  90. package/example/android/gradle.properties +0 -47
  91. package/example/android/gradlew +0 -252
  92. package/example/android/gradlew.bat +0 -94
  93. package/example/android/settings.gradle +0 -6
  94. package/example/app.json +0 -4
  95. package/example/babel.config.js +0 -21
  96. package/example/biome.json +0 -47
  97. package/example/deploy.sh +0 -11
  98. package/example/index.html +0 -26
  99. package/example/index.js +0 -9
  100. package/example/index.web.js +0 -8
  101. package/example/jest.config.js +0 -12
  102. package/example/metro.config.js +0 -58
  103. package/example/package-lock.json +0 -14510
  104. package/example/package.json +0 -48
  105. package/example/react-native.config.js +0 -17
  106. package/example/src/components/AppBar.tsx +0 -73
  107. package/example/src/components/Menu.tsx +0 -90
  108. package/example/src/components/SingleChoiceDialog.tsx +0 -120
  109. package/example/src/screens/ConnectScreen.tsx +0 -195
  110. package/example/src/screens/DevicesScreen.tsx +0 -252
  111. package/example/src/screens/TerminalScreen.tsx +0 -572
  112. package/example/src/settings.ts +0 -43
  113. package/example/src/theme.ts +0 -19
  114. package/example/src/util/TextUtil.ts +0 -129
  115. package/example/tsconfig.json +0 -10
  116. package/example/vite.config.mjs +0 -55
  117. package/scripts/deploy-release.sh +0 -127
  118. package/tsconfig.build.json +0 -7
  119. package/tsconfig.json +0 -20
@@ -0,0 +1,205 @@
1
+ /**
2
+ * VirtualSerialTransport — an in-memory {@link SerialTransport} for tests and
3
+ * on-device demos.
4
+ *
5
+ * It implements the exact same interface the production `UsbSerialModule` does,
6
+ * but talks to simulated devices instead of real USB hardware. Because it has
7
+ * **no `react-native` dependency**, the same instance drives:
8
+ *
9
+ * - Jest/Node unit tests and the conformance suite,
10
+ * - the example app's "virtual device" mode on a real Android device, and
11
+ * - the example app running in a browser (react-native-web).
12
+ *
13
+ * Inject it via `new Serial(transport)` or globally with `setUsbSerial(transport)`.
14
+ *
15
+ * @example
16
+ * const transport = new VirtualSerialTransport();
17
+ * transport.addDevice(new EchoDevice(), {hasPermission: true});
18
+ * const serial = new Serial(transport);
19
+ * const [port] = await serial.getPorts();
20
+ * await port.open({baudRate: 115200});
21
+ * // writes to port.writable now come back on port.readable (echo)
22
+ */
23
+ import type { ConnectEvent, ControlLine, DataEvent, ErrorEvent, FlowControl, OpenOptions, PortFilter, PortId, PortPickerLabels, SerialTransport, Subscription } from '../transport';
24
+ import type { SerialDevice } from './serial-device';
25
+ /** Transport-side knobs when registering a {@link SerialDevice}. */
26
+ export type VirtualDeviceOptions = {
27
+ /** Whether the app already holds USB permission. Defaults to false. */
28
+ hasPermission?: boolean;
29
+ /** Defaults to 0. A USB device may expose several ports. */
30
+ portNumber?: number;
31
+ /** Override the device's serialNumber for enumeration. */
32
+ serialNumber?: string;
33
+ /**
34
+ * Cross-wire output signals onto inputs the way a null-modem/loopback plug
35
+ * would (DTR→DSR+DCD, RTS→CTS) so getSignals() reflects setSignals().
36
+ * Defaults to true.
37
+ */
38
+ loopbackSignals?: boolean;
39
+ /**
40
+ * When the port is opened with hardware (RTS/CTS) flow control, the device
41
+ * de-asserts CTS once this many bytes have been written without the receiver
42
+ * draining — modelling a full receive buffer. Defaults to 256.
43
+ */
44
+ flowControlThreshold?: number;
45
+ };
46
+ export type VirtualSerialOptions = {
47
+ /** Devices to register on construction (same as calling addDevice). */
48
+ devices?: SerialDevice[];
49
+ /**
50
+ * Delay (ms) applied to async operations and to inbound data delivery.
51
+ * 0 (default) resolves on a microtask — deterministic for Jest. A small
52
+ * positive value makes streaming feel realistic on a device.
53
+ */
54
+ latencyMs?: number;
55
+ /**
56
+ * Whether showPortPicker() grants USB permission to the chosen device,
57
+ * mirroring the real Android picker. Defaults to true.
58
+ */
59
+ autoGrantPermission?: boolean;
60
+ /**
61
+ * If set, inbound data larger than this is delivered as several `onData`
62
+ * events of at most this many bytes — modelling how a real serial port hands
63
+ * data up in chunks. 0/undefined delivers each write's reply in one event.
64
+ */
65
+ chunkSize?: number;
66
+ };
67
+ /** Operations whose next invocation can be made to fail (error injection). */
68
+ export type FailableOp = 'open' | 'close' | 'write' | 'startReading' | 'stopReading' | 'setSignals' | 'getSignals';
69
+ type OutputSignals = {
70
+ dtr: boolean;
71
+ rts: boolean;
72
+ brk: boolean;
73
+ };
74
+ type InputSignals = {
75
+ dcd: boolean;
76
+ cts: boolean;
77
+ ri: boolean;
78
+ dsr: boolean;
79
+ };
80
+ /**
81
+ * A simulated USB-serial device. Returned by {@link VirtualSerialTransport.addDevice}.
82
+ * The mutable fields and the helper methods let a test or demo drive the device
83
+ * the way physical hardware (and a human plugging cables) otherwise would.
84
+ */
85
+ export declare class VirtualDevice {
86
+ #private;
87
+ readonly usbVendorId: number;
88
+ readonly usbProductId: number;
89
+ readonly portNumber: number;
90
+ serialNumber: string;
91
+ /** Reassigned on every (re)attach, mirroring Android's behaviour. */
92
+ deviceId: number;
93
+ attached: boolean;
94
+ hasPermission: boolean;
95
+ isOpen: boolean;
96
+ reading: boolean;
97
+ /** The hosted behaviour. */
98
+ readonly serialDevice: SerialDevice;
99
+ loopbackSignals: boolean;
100
+ flowControl: FlowControl;
101
+ flowControlThreshold: number;
102
+ openOptions: Required<OpenOptions> | null;
103
+ /**
104
+ * When non-null, the device delivers at most this many bytes before raising a
105
+ * `BufferOverrunError` — models a fixed-size receive buffer overflowing.
106
+ */
107
+ overrunLimit: number | null;
108
+ _rxDelivered: number;
109
+ _overran: boolean;
110
+ _hwWritten: number;
111
+ readonly output: OutputSignals;
112
+ readonly input: InputSignals;
113
+ /** Every byte frame the host has written to this device, in order. */
114
+ readonly written: number[][];
115
+ constructor(transport: VirtualSerialTransport, deviceId: number, device: SerialDevice, options: VirtualDeviceOptions);
116
+ /** Push inbound bytes to the host as if the device sent them unprompted. */
117
+ push(bytes: number[] | Uint8Array): void;
118
+ /**
119
+ * Raise a read error on the host's readable stream. `name` is the W3C error
120
+ * type (e.g. "BreakError", "BufferOverrunError"); the current polyfill ignores
121
+ * it and surfaces "NetworkError" regardless (a documented spec gap).
122
+ */
123
+ emitError(message: string, name?: string): void;
124
+ /**
125
+ * Make the device deliver at most `bytes` bytes and then raise a
126
+ * `BufferOverrunError`, modelling a receive buffer of that size overflowing.
127
+ */
128
+ overrunAfter(bytes: number): this;
129
+ /** Make the next call to `op` reject once (error injection). */
130
+ failNext(op: FailableOp): this;
131
+ /** @internal consume a queued failure for `op`. */
132
+ _consumeFail(op: FailableOp): boolean;
133
+ /** Directly set device-asserted input signals (DCD/CTS/RI/DSR). */
134
+ setInputSignals(signals: Partial<InputSignals>): void;
135
+ /** Physically attach (or re-attach) this device — fires "connect". */
136
+ attach(): void;
137
+ /** Physically detach this device — fires "disconnect". */
138
+ detach(): void;
139
+ /** Simulate an unplug while open: errors the open stream, then disconnects. */
140
+ loseDevice(): void;
141
+ }
142
+ type Listener<E> = (event: E) => void;
143
+ /**
144
+ * In-memory transport backing one or more {@link VirtualDevice}s.
145
+ */
146
+ export declare class VirtualSerialTransport implements SerialTransport {
147
+ #private;
148
+ constructor(options?: VirtualSerialOptions);
149
+ /** All devices known to the transport (attached or not). */
150
+ get devices(): readonly VirtualDevice[];
151
+ /**
152
+ * Register a {@link SerialDevice}. It starts attached but does not fire
153
+ * "connect"; its identity (usbVendorId/usbProductId/serialNumber) is read from
154
+ * the device, and `options` carries the transport-side knobs.
155
+ */
156
+ addDevice(serialDevice: SerialDevice, options?: VirtualDeviceOptions): VirtualDevice;
157
+ /** Remove a device entirely; detaches it first if attached. */
158
+ removeDevice(device: VirtualDevice): void;
159
+ /** (Re)attach a device, assigning it a fresh deviceId, and fire "connect". */
160
+ attach(device: VirtualDevice): void;
161
+ /** Detach a device and fire "disconnect"; any open port becomes closed. */
162
+ detach(device: VirtualDevice): void;
163
+ /** Simulate an unplug while open: error the stream first, then disconnect. */
164
+ loseDevice(device: VirtualDevice): void;
165
+ /** Script the next showPortPicker() resolution (a device or a predicate). */
166
+ selectNextPort(target: VirtualDevice | ((d: VirtualDevice) => boolean)): void;
167
+ /** Make the next showPortPicker() reject (user cancelled / no port). */
168
+ rejectNextPortPicker(): void;
169
+ /** @internal deliver inbound bytes to the host's readable stream. */
170
+ _deliver(device: VirtualDevice, data: number[]): void;
171
+ /** @internal raise a read error for a device's open port. */
172
+ _error(device: VirtualDevice, message: string, name?: string): void;
173
+ findAllDrivers(): Promise<ReadonlyArray<PortId>>;
174
+ showPortPicker(filter: ReadonlyArray<PortFilter>, _labels?: PortPickerLabels): Promise<PortId>;
175
+ requestPermission(deviceId: number): Promise<boolean>;
176
+ open(deviceId: number, portNumber: number, options: OpenOptions): Promise<void>;
177
+ close(deviceId: number, portNumber: number): Promise<void>;
178
+ isOpen(deviceId: number, portNumber: number): boolean;
179
+ write(deviceId: number, portNumber: number, data: number[], _timeout?: number): Promise<void>;
180
+ startReading(deviceId: number, portNumber: number): Promise<void>;
181
+ stopReading(deviceId: number, portNumber: number): Promise<void>;
182
+ setParameters(deviceId: number, portNumber: number, options: OpenOptions): Promise<void>;
183
+ setDTR(deviceId: number, portNumber: number, value: boolean): Promise<void>;
184
+ setRTS(deviceId: number, portNumber: number, value: boolean): Promise<void>;
185
+ setBreak(deviceId: number, portNumber: number, value: boolean): Promise<void>;
186
+ getDTR(deviceId: number, portNumber: number): Promise<boolean>;
187
+ getRTS(deviceId: number, portNumber: number): Promise<boolean>;
188
+ getCD(deviceId: number, portNumber: number): Promise<boolean>;
189
+ getCTS(deviceId: number, portNumber: number): Promise<boolean>;
190
+ getRI(deviceId: number, portNumber: number): Promise<boolean>;
191
+ getDSR(deviceId: number, portNumber: number): Promise<boolean>;
192
+ getControlLines(deviceId: number, portNumber: number): Promise<ControlLine[]>;
193
+ getSupportedControlLines(_deviceId: number, _portNumber: number): Promise<ControlLine[]>;
194
+ setFlowControl(deviceId: number, portNumber: number, flowControl: FlowControl): Promise<void>;
195
+ getFlowControl(deviceId: number, portNumber: number): Promise<FlowControl>;
196
+ getSupportedFlowControl(_deviceId: number, _portNumber: number): Promise<FlowControl[]>;
197
+ purgeHwBuffers(_deviceId: number, _portNumber: number, _purgeWriteBuffers: boolean, _purgeReadBuffers: boolean): Promise<void>;
198
+ getSerial(deviceId: number, portNumber: number): Promise<string>;
199
+ onData(listener: Listener<DataEvent>): Subscription;
200
+ onError(listener: Listener<ErrorEvent>): Subscription;
201
+ onConnect(listener: Listener<ConnectEvent>): Subscription;
202
+ onDisconnect(listener: Listener<ConnectEvent>): Subscription;
203
+ }
204
+ export {};
205
+ //# sourceMappingURL=virtual-serial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual-serial.d.ts","sourceRoot":"","sources":["../../../../src/testing/virtual-serial.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Hardware-transport seam for the Web Serial polyfill.
3
+ *
4
+ * `SerialTransport` is the single interface that the `Serial`/`SerialPort`
5
+ * classes depend on to talk to "the device". The production implementation
6
+ * (`UsbSerialModule`, backed by the `NativeUsbSerial` TurboModule — see
7
+ * {@link ./UsbSerial}) and the in-memory test/dev double
8
+ * (`VirtualSerialTransport` — see {@link ./testing/virtual-serial}) both
9
+ * implement it.
10
+ *
11
+ * This module is intentionally free of any `react-native` import. That is what
12
+ * lets the virtual transport — and therefore the conformance suite built on top
13
+ * of it — run unchanged under Node/Jest, in a browser, and on a device.
14
+ */
15
+ export type ControlLine = 'RTS' | 'CTS' | 'DTR' | 'DSR' | 'CD' | 'RI';
16
+ export type FlowControl = 'NONE' | 'RTS_CTS' | 'DTR_DSR' | 'XON_XOFF' | 'XON_XOFF_INLINE';
17
+ export type PortFilter = {
18
+ usbVendorId?: number;
19
+ usbProductId?: number;
20
+ };
21
+ export type PortPickerLabels = {
22
+ titleSelectPort?: string;
23
+ titleNoPortsAvailable?: string;
24
+ messageNoPortsAvailable?: string;
25
+ };
26
+ export type PortId = {
27
+ deviceId: number;
28
+ portNumber: number;
29
+ usbVendorId: number;
30
+ usbProductId: number;
31
+ /**
32
+ * Whether the app currently holds Android USB permission to access this
33
+ * device (via the system attach dialog or a prior permission request).
34
+ */
35
+ hasPermission: boolean;
36
+ };
37
+ export type DataEvent = {
38
+ deviceId: number;
39
+ portNumber: number;
40
+ data: number[];
41
+ };
42
+ export type ErrorEvent = {
43
+ deviceId: number;
44
+ portNumber: number;
45
+ error: string;
46
+ /**
47
+ * Optional spec error name (e.g. "BreakError", "BufferOverrunError",
48
+ * "FramingError", "ParityError") for a typed read error. When present the
49
+ * polyfill surfaces a DOMException of that name on the readable stream
50
+ * (otherwise it defaults to "NetworkError"); the WPT-derived spec tests in
51
+ * src/__tests__/conformance-suite.ts exercise this (BreakError,
52
+ * BufferOverrunError).
53
+ */
54
+ errorName?: string;
55
+ };
56
+ export type ConnectEvent = {
57
+ deviceId: number;
58
+ usbVendorId: number;
59
+ usbProductId: number;
60
+ };
61
+ export declare const Parity: {
62
+ readonly NONE: 0;
63
+ readonly ODD: 1;
64
+ readonly EVEN: 2;
65
+ readonly MARK: 3;
66
+ readonly SPACE: 4;
67
+ };
68
+ export declare const DataBits: {
69
+ readonly FIVE: 5;
70
+ readonly SIX: 6;
71
+ readonly SEVEN: 7;
72
+ readonly EIGHT: 8;
73
+ };
74
+ export declare const StopBits: {
75
+ readonly ONE: 1;
76
+ readonly ONE_FIVE: 3;
77
+ readonly TWO: 2;
78
+ };
79
+ export type OpenOptions = {
80
+ baudRate: number;
81
+ dataBits?: number;
82
+ stopBits?: number;
83
+ parity?: number;
84
+ };
85
+ export declare const DEFAULT_OPEN_OPTIONS: Required<Omit<OpenOptions, 'baudRate'>>;
86
+ /** Handle returned by the `on*` subscription methods. */
87
+ export type Subscription = {
88
+ remove: () => void;
89
+ };
90
+ /**
91
+ * The contract every serial transport must satisfy. It mirrors the JS-friendly
92
+ * surface of `UsbSerialModule` exactly, so `UsbSerialModule implements
93
+ * SerialTransport` is a faithful 1:1 and any conforming double (e.g.
94
+ * `VirtualSerialTransport`) is a drop-in replacement.
95
+ *
96
+ * Ports are addressed by the pair `(deviceId, portNumber)`. Inbound bytes,
97
+ * read errors and device attach/detach arrive through the `on*` subscriptions.
98
+ */
99
+ export interface SerialTransport {
100
+ findAllDrivers(): Promise<ReadonlyArray<PortId>>;
101
+ showPortPicker(filter: ReadonlyArray<PortFilter>, labels?: PortPickerLabels): Promise<PortId>;
102
+ requestPermission(deviceId: number): Promise<boolean>;
103
+ open(deviceId: number, portNumber: number, options: OpenOptions): Promise<void>;
104
+ close(deviceId: number, portNumber: number): Promise<void>;
105
+ isOpen(deviceId: number, portNumber: number): boolean;
106
+ write(deviceId: number, portNumber: number, data: number[], timeout?: number): Promise<void>;
107
+ startReading(deviceId: number, portNumber: number): Promise<void>;
108
+ stopReading(deviceId: number, portNumber: number): Promise<void>;
109
+ setParameters(deviceId: number, portNumber: number, options: OpenOptions): Promise<void>;
110
+ setDTR(deviceId: number, portNumber: number, value: boolean): Promise<void>;
111
+ setRTS(deviceId: number, portNumber: number, value: boolean): Promise<void>;
112
+ getDTR(deviceId: number, portNumber: number): Promise<boolean>;
113
+ getRTS(deviceId: number, portNumber: number): Promise<boolean>;
114
+ getCD(deviceId: number, portNumber: number): Promise<boolean>;
115
+ getCTS(deviceId: number, portNumber: number): Promise<boolean>;
116
+ getDSR(deviceId: number, portNumber: number): Promise<boolean>;
117
+ getRI(deviceId: number, portNumber: number): Promise<boolean>;
118
+ getControlLines(deviceId: number, portNumber: number): Promise<ControlLine[]>;
119
+ getSupportedControlLines(deviceId: number, portNumber: number): Promise<ControlLine[]>;
120
+ setFlowControl(deviceId: number, portNumber: number, flowControl: FlowControl): Promise<void>;
121
+ getFlowControl(deviceId: number, portNumber: number): Promise<FlowControl>;
122
+ getSupportedFlowControl(deviceId: number, portNumber: number): Promise<FlowControl[]>;
123
+ setBreak(deviceId: number, portNumber: number, value: boolean): Promise<void>;
124
+ purgeHwBuffers(deviceId: number, portNumber: number, purgeWriteBuffers: boolean, purgeReadBuffers: boolean): Promise<void>;
125
+ getSerial(deviceId: number, portNumber: number): Promise<string>;
126
+ onData(listener: (event: DataEvent) => void): Subscription;
127
+ onError(listener: (event: ErrorEvent) => void): Subscription;
128
+ onConnect(listener: (event: ConnectEvent) => void): Subscription;
129
+ onDisconnect(listener: (event: ConnectEvent) => void): Subscription;
130
+ }
131
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;AAGtE,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,SAAS,GACT,SAAS,GACT,UAAU,GACV,iBAAiB,CAAC;AAEtB,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,MAAM;;;;;;CAMT,CAAC;AAEX,eAAO,MAAM,QAAQ;;;;;CAKX,CAAC;AAEX,eAAO,MAAM,QAAQ;;;;CAIX,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAIxE,CAAC;AAEF,yDAAyD;AACzD,MAAM,MAAM,YAAY,GAAG;IAAC,MAAM,EAAE,MAAM,IAAI,CAAA;CAAC,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAE9B,cAAc,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,cAAc,CACZ,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,EACjC,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAGtD,IAAI,CACF,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IAGtD,KAAK,CACH,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAGjE,aAAa,CACX,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IAGjB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9E,wBAAwB,CACtB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAG1B,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3E,uBAAuB,CACrB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAG1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,OAAO,EAC1B,gBAAgB,EAAE,OAAO,GACxB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAGjE,MAAM,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,YAAY,CAAC;IAC3D,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,YAAY,CAAC;IAC7D,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,YAAY,CAAC;IACjE,YAAY,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,YAAY,CAAC;CACrE"}
package/package.json CHANGED
@@ -1,17 +1,49 @@
1
1
  {
2
2
  "name": "react-native-web-serial-api",
3
- "version": "0.0.3",
3
+ "version": "0.1.0",
4
4
  "description": "W3C Web Serial API (navigator.serial) for React Native on Android, backed by a USB-serial TurboModule (built on mik3y/usb-serial-for-android).",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "react-native": "lib/commonjs/index.js",
7
7
  "source": "src/index.ts",
8
8
  "types": "lib/typescript/src/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "source": "./src/index.ts",
12
+ "types": "./lib/typescript/src/index.d.ts",
13
+ "react-native": "./lib/commonjs/index.js",
14
+ "default": "./lib/commonjs/index.js"
15
+ },
16
+ "./testing": {
17
+ "source": "./src/testing/index.ts",
18
+ "types": "./lib/typescript/src/testing/index.d.ts",
19
+ "react-native": "./lib/commonjs/testing/index.js",
20
+ "default": "./lib/commonjs/testing/index.js"
21
+ },
22
+ "./package.json": "./package.json"
23
+ },
24
+ "files": [
25
+ "src",
26
+ "lib",
27
+ "android",
28
+ "react-native.config.js",
29
+ "TESTING.md",
30
+ "!android/build",
31
+ "!**/__tests__",
32
+ "!**/__fixtures__",
33
+ "!**/__mocks__",
34
+ "!**/.*"
35
+ ],
9
36
  "scripts": {
10
37
  "prepare": "bob build",
11
38
  "clean": "node -e \"require('fs').rm(\\\"./lib\\\", { recursive: true }, () => {console.log(\\\"'lib' folder deleted\\\")})\"",
12
39
  "typecheck": "tsc --noEmit",
13
40
  "lint": "biome check src",
14
- "format": "biome check --write src"
41
+ "format": "biome check --write src",
42
+ "test": "jest",
43
+ "test:watch": "jest --watch",
44
+ "test:coverage": "jest --coverage",
45
+ "test:emulator:e2e": "npm --prefix example run e2e",
46
+ "test:host+emulator": "node ./node_modules/jest/bin/jest.js && npm --prefix example run e2e"
15
47
  },
16
48
  "keywords": [
17
49
  "react-native",
@@ -53,7 +85,11 @@
53
85
  "devDependencies": {
54
86
  "@biomejs/biome": "2.4.16",
55
87
  "@react-native/babel-preset": "0.85.3",
88
+ "@react-native/jest-preset": "0.85.3",
89
+ "@types/jest": "^29.5.14",
56
90
  "@types/react": "^19.2.6",
91
+ "babel-jest": "29.6.3",
92
+ "jest": "29.6.3",
57
93
  "react": "19.2.3",
58
94
  "react-native": "0.85.3",
59
95
  "react-native-builder-bob": "^0.41.0",
package/src/UsbSerial.ts CHANGED
@@ -1,92 +1,39 @@
1
1
  import {NativeEventEmitter, NativeModules} from 'react-native';
2
2
  import NativeUsbSerial from './NativeUsbSerial';
3
-
4
- export type ControlLine = 'RTS' | 'CTS' | 'DTR' | 'DSR' | 'CD' | 'RI';
5
- export type FlowControl =
6
- | 'NONE'
7
- | 'RTS_CTS'
8
- | 'DTR_DSR'
9
- | 'XON_XOFF'
10
- | 'XON_XOFF_INLINE';
11
-
12
- export type PortFilter = {
13
- usbVendorId?: number;
14
- usbProductId?: number;
15
- };
16
-
17
- export type PortPickerLabels = {
18
- titleSelectPort?: string;
19
- titleNoPortsAvailable?: string;
20
- messageNoPortsAvailable?: string;
21
- };
22
-
23
- export type PortId = {
24
- deviceId: number;
25
- portNumber: number;
26
- usbVendorId: number;
27
- usbProductId: number;
28
- /**
29
- * Whether the app currently holds Android USB permission to access this
30
- * device (via the system attach dialog or a prior permission request).
31
- */
32
- hasPermission: boolean;
33
- };
34
-
35
- export type DataEvent = {
36
- deviceId: number;
37
- portNumber: number;
38
- data: number[];
39
- };
40
-
41
- export type ErrorEvent = {
42
- deviceId: number;
43
- portNumber: number;
44
- error: string;
45
- };
46
-
47
- export type ConnectEvent = {
48
- deviceId: number;
49
- usbVendorId: number;
50
- usbProductId: number;
51
- };
52
-
53
- export const Parity = {
54
- NONE: 0,
55
- ODD: 1,
56
- EVEN: 2,
57
- MARK: 3,
58
- SPACE: 4,
59
- } as const;
60
-
61
- export const DataBits = {
62
- FIVE: 5,
63
- SIX: 6,
64
- SEVEN: 7,
65
- EIGHT: 8,
66
- } as const;
67
-
68
- export const StopBits = {
69
- ONE: 1,
70
- ONE_FIVE: 3,
71
- TWO: 2,
72
- } as const;
73
-
74
- export type OpenOptions = {
75
- baudRate: number;
76
- dataBits?: number;
77
- stopBits?: number;
78
- parity?: number;
79
- };
80
-
81
- const DEFAULT_OPEN_OPTIONS: Required<Omit<OpenOptions, 'baudRate'>> = {
82
- dataBits: DataBits.EIGHT,
83
- stopBits: StopBits.ONE,
84
- parity: Parity.NONE,
85
- };
86
-
87
- type Subscription = {remove: () => void};
88
-
89
- export class UsbSerialModule {
3
+ import type {
4
+ ConnectEvent,
5
+ ControlLine,
6
+ DataEvent,
7
+ ErrorEvent,
8
+ FlowControl,
9
+ OpenOptions,
10
+ PortFilter,
11
+ PortId,
12
+ PortPickerLabels,
13
+ SerialTransport,
14
+ Subscription,
15
+ } from './transport';
16
+ import {DEFAULT_OPEN_OPTIONS} from './transport';
17
+
18
+ // These types and enums were originally declared in this module and form part
19
+ // of the public `UsbSerial` namespace. They now live in ./transport (a
20
+ // react-native-free module the virtual transport also builds on) and are
21
+ // re-exported here unchanged for backwards compatibility.
22
+ export type {
23
+ ConnectEvent,
24
+ ControlLine,
25
+ DataEvent,
26
+ ErrorEvent,
27
+ FlowControl,
28
+ OpenOptions,
29
+ PortFilter,
30
+ PortId,
31
+ PortPickerLabels,
32
+ SerialTransport,
33
+ } from './transport';
34
+ export {DataBits, Parity, StopBits} from './transport';
35
+
36
+ export class UsbSerialModule implements SerialTransport {
90
37
  private readonly native: NonNullable<typeof NativeUsbSerial>;
91
38
  private readonly emitter: NativeEventEmitter;
92
39
 
@@ -300,11 +247,39 @@ export class UsbSerialModule {
300
247
  }
301
248
  }
302
249
 
303
- let instance: UsbSerialModule | null = null;
304
-
305
- export function getUsbSerial(): UsbSerialModule {
250
+ let instance: SerialTransport | null = null;
251
+ let override: SerialTransport | null = null;
252
+
253
+ /**
254
+ * Resolve the active serial transport. Returns the override set via
255
+ * {@link setUsbSerial} if present (used by tests and by the example's on-device
256
+ * "virtual device" mode); otherwise lazily constructs the real native-backed
257
+ * {@link UsbSerialModule}.
258
+ */
259
+ export function getUsbSerial(): SerialTransport {
260
+ if (override) return override;
306
261
  if (!instance) {
307
262
  instance = new UsbSerialModule();
308
263
  }
309
264
  return instance;
310
265
  }
266
+
267
+ /**
268
+ * Override the transport returned by {@link getUsbSerial}. Pass a
269
+ * {@link SerialTransport} (e.g. a `VirtualSerialTransport`) to make the
270
+ * singleton `serial` instance — and any `new Serial()` created without an
271
+ * explicit transport — talk to it instead of real hardware. Pass `null` to
272
+ * clear the override.
273
+ *
274
+ * Inject before the first `getPorts()` / `requestPort()` / `addEventListener()`
275
+ * call so the lazy initialisation in `Serial` picks it up.
276
+ */
277
+ export function setUsbSerial(transport: SerialTransport | null): void {
278
+ override = transport;
279
+ }
280
+
281
+ /** Clear any override and drop the cached native instance (test teardown). */
282
+ export function resetUsbSerial(): void {
283
+ override = null;
284
+ instance = null;
285
+ }