@gurezo/web-serial-rxjs 0.2.0 → 2.0.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.
- package/README.ja.md +21 -107
- package/README.md +23 -127
- package/dist/errors/serial-error-code.d.ts +7 -0
- package/dist/errors/serial-error-code.d.ts.map +1 -1
- package/dist/index.d.ts +31 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +459 -673
- package/dist/index.mjs +459 -673
- package/dist/index.mjs.map +4 -4
- package/dist/session/create-serial-session.d.ts +49 -0
- package/dist/session/create-serial-session.d.ts.map +1 -0
- package/dist/session/index.d.ts +5 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/internal/build-request-options.d.ts +18 -0
- package/dist/session/internal/build-request-options.d.ts.map +1 -0
- package/dist/session/internal/has-web-serial-support.d.ts +12 -0
- package/dist/session/internal/has-web-serial-support.d.ts.map +1 -0
- package/dist/session/internal/line-buffer.d.ts +14 -0
- package/dist/session/internal/line-buffer.d.ts.map +1 -0
- package/dist/session/normalize-serial-error.d.ts +55 -0
- package/dist/session/normalize-serial-error.d.ts.map +1 -0
- package/dist/session/read-pump.d.ts +74 -0
- package/dist/session/read-pump.d.ts.map +1 -0
- package/dist/session/send-queue.d.ts +58 -0
- package/dist/session/send-queue.d.ts.map +1 -0
- package/dist/session/serial-session-options.d.ts +80 -0
- package/dist/session/serial-session-options.d.ts.map +1 -0
- package/dist/session/serial-session-state.d.ts +35 -0
- package/dist/session/serial-session-state.d.ts.map +1 -0
- package/dist/session/serial-session.d.ts +143 -0
- package/dist/session/serial-session.d.ts.map +1 -0
- package/dist/session/session-state-machine.d.ts +39 -0
- package/dist/session/session-state-machine.d.ts.map +1 -0
- package/package.json +1 -5
- package/web-serial-rxjs-icon.png +0 -0
- package/dist/browser/browser-detection.d.ts +0 -104
- package/dist/browser/browser-detection.d.ts.map +0 -1
- package/dist/browser/browser-support.d.ts +0 -57
- package/dist/browser/browser-support.d.ts.map +0 -1
- package/dist/client/index.d.ts +0 -283
- package/dist/client/index.d.ts.map +0 -1
- package/dist/client/serial-client.d.ts +0 -137
- package/dist/client/serial-client.d.ts.map +0 -1
- package/dist/filters/build-request-options.d.ts +0 -42
- package/dist/filters/build-request-options.d.ts.map +0 -1
- package/dist/io/observable-to-writable.d.ts +0 -65
- package/dist/io/observable-to-writable.d.ts.map +0 -1
- package/dist/io/readable-to-observable.d.ts +0 -44
- package/dist/io/readable-to-observable.d.ts.map +0 -1
- package/dist/lib/web-serial-rxjs.d.ts +0 -7
- package/dist/lib/web-serial-rxjs.d.ts.map +0 -1
- package/dist/shell/create-shell-client.d.ts +0 -17
- package/dist/shell/create-shell-client.d.ts.map +0 -1
- package/dist/shell/index.d.ts +0 -2
- package/dist/shell/index.d.ts.map +0 -1
- package/dist/types/options.d.ts +0 -107
- package/dist/types/options.d.ts.map +0 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
/**
|
|
3
|
+
* A single enqueued unit of work. Operations are awaited sequentially so
|
|
4
|
+
* that `send$` guarantees call order even when the caller fires multiple
|
|
5
|
+
* observables concurrently.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export type SendQueueOperation<T> = () => Promise<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Internal helper returned by {@link createSendQueue}.
|
|
12
|
+
*
|
|
13
|
+
* The queue is intentionally not an RxJS operator because Issue #199 calls
|
|
14
|
+
* out explicitly that `send$` must not be re-implemented with `mergeMap`
|
|
15
|
+
* (or any other concurrency-altering operator). A chained `Promise<void>`
|
|
16
|
+
* is the simplest way to guarantee strict FIFO ordering while still
|
|
17
|
+
* surfacing per-operation completion back to the caller.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export interface SendQueue {
|
|
22
|
+
/**
|
|
23
|
+
* Schedule an operation to run after all previously enqueued operations
|
|
24
|
+
* have settled (resolved or rejected). The returned Observable completes
|
|
25
|
+
* with the operation's resolved value, or errors with its rejection.
|
|
26
|
+
*
|
|
27
|
+
* Subscribing is what actually schedules the work - the queue is driven
|
|
28
|
+
* by `defer`, so late/never-subscribed Observables never enqueue.
|
|
29
|
+
*/
|
|
30
|
+
enqueue<T>(operation: SendQueueOperation<T>): Observable<T>;
|
|
31
|
+
/**
|
|
32
|
+
* Reset the internal promise chain. Existing in-flight operations keep
|
|
33
|
+
* running because we do not cancel native promises, but no newly
|
|
34
|
+
* enqueued work will wait for them. Use this when the session is torn
|
|
35
|
+
* down so a fresh `connect$` starts with a clean chain.
|
|
36
|
+
*/
|
|
37
|
+
clear(): void;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create an internal send queue that serialises `send$` writes.
|
|
41
|
+
*
|
|
42
|
+
* Ordering model:
|
|
43
|
+
*
|
|
44
|
+
* - Each `enqueue` call appends its operation to a single `Promise<void>`
|
|
45
|
+
* chain.
|
|
46
|
+
* - A failure in one operation does not poison the chain - the next
|
|
47
|
+
* operation still runs (the chain is advanced with a `.then(() => {},
|
|
48
|
+
* () => {})` safety tail).
|
|
49
|
+
* - Unsubscribing before the operation resolves suppresses `next` /
|
|
50
|
+
* `complete` / `error` for that subscriber; the underlying promise is
|
|
51
|
+
* still awaited so later operations continue to respect call order.
|
|
52
|
+
*
|
|
53
|
+
* @internal
|
|
54
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/199 | Issue #199}
|
|
55
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/203 | Issue #203}
|
|
56
|
+
*/
|
|
57
|
+
export declare function createSendQueue(): SendQueue;
|
|
58
|
+
//# sourceMappingURL=send-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-queue.d.ts","sourceRoot":"","sources":["../../src/session/send-queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAS,MAAM,MAAM,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;AAErD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;;OAOG;IACH,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IAC5D;;;;;OAKG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAwC3C"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for creating a {@link SerialSession} via {@link createSerialSession}.
|
|
3
|
+
*
|
|
4
|
+
* These options configure the serial port connection parameters used when
|
|
5
|
+
* calling `port.open` and `navigator.serial.requestPort`. All properties
|
|
6
|
+
* are optional; omitted fields fall back to {@link DEFAULT_SERIAL_SESSION_OPTIONS}.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const session = createSerialSession({
|
|
11
|
+
* baudRate: 115200,
|
|
12
|
+
* dataBits: 8,
|
|
13
|
+
* stopBits: 1,
|
|
14
|
+
* parity: 'none',
|
|
15
|
+
* flowControl: 'none',
|
|
16
|
+
* filters: [{ usbVendorId: 0x1234, usbProductId: 0x5678 }],
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/199 | Issue #199}
|
|
21
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/200 | Issue #200}
|
|
22
|
+
*/
|
|
23
|
+
export interface SerialSessionOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Baud rate for the serial port connection (bits per second).
|
|
26
|
+
*
|
|
27
|
+
* Common values include 9600, 19200, 38400, 57600, 115200, etc.
|
|
28
|
+
* Must match the baud rate configured on the connected device.
|
|
29
|
+
*
|
|
30
|
+
* @default 9600
|
|
31
|
+
*/
|
|
32
|
+
baudRate?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Number of data bits per character (7 or 8).
|
|
35
|
+
*
|
|
36
|
+
* @default 8
|
|
37
|
+
*/
|
|
38
|
+
dataBits?: 7 | 8;
|
|
39
|
+
/**
|
|
40
|
+
* Number of stop bits (1 or 2).
|
|
41
|
+
*
|
|
42
|
+
* @default 1
|
|
43
|
+
*/
|
|
44
|
+
stopBits?: 1 | 2;
|
|
45
|
+
/**
|
|
46
|
+
* Parity checking mode.
|
|
47
|
+
*
|
|
48
|
+
* @default 'none'
|
|
49
|
+
*/
|
|
50
|
+
parity?: 'none' | 'even' | 'odd';
|
|
51
|
+
/**
|
|
52
|
+
* Buffer size for the underlying read stream, in bytes.
|
|
53
|
+
*
|
|
54
|
+
* @default 255
|
|
55
|
+
*/
|
|
56
|
+
bufferSize?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Flow control mode.
|
|
59
|
+
*
|
|
60
|
+
* @default 'none'
|
|
61
|
+
*/
|
|
62
|
+
flowControl?: 'none' | 'hardware';
|
|
63
|
+
/**
|
|
64
|
+
* Filters for port selection when requesting a port.
|
|
65
|
+
*
|
|
66
|
+
* When specified, the port selection dialog will only show devices
|
|
67
|
+
* matching these filters. Each filter can specify `usbVendorId` and/or
|
|
68
|
+
* `usbProductId`.
|
|
69
|
+
*/
|
|
70
|
+
filters?: SerialPortFilter[];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Default values applied to omitted {@link SerialSessionOptions} fields.
|
|
74
|
+
*
|
|
75
|
+
* @internal
|
|
76
|
+
*/
|
|
77
|
+
export declare const DEFAULT_SERIAL_SESSION_OPTIONS: Required<Omit<SerialSessionOptions, 'filters'>> & {
|
|
78
|
+
filters?: SerialPortFilter[];
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=serial-session-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serial-session-options.d.ts","sourceRoot":"","sources":["../../src/session/serial-session-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAEjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAEjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IAEjC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAElC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,EAAE,QAAQ,CACnD,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CACtC,GAAG;IAAE,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;CAQjC,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactive lifecycle state for a {@link SerialSession}.
|
|
3
|
+
*
|
|
4
|
+
* This is the v2 API counterpart of the legacy `SerialState` used by
|
|
5
|
+
* `SerialClient`. The runtime values are the same flat strings v1
|
|
6
|
+
* consumers used for UI switches; the {@link SerialSessionState} const
|
|
7
|
+
* object is the canonical source of those literals so call sites can
|
|
8
|
+
* avoid string typos and get IDE completion.
|
|
9
|
+
*
|
|
10
|
+
* Lifecycle transitions:
|
|
11
|
+
*
|
|
12
|
+
* ```
|
|
13
|
+
* idle -> connecting -> connected -> disconnecting -> idle
|
|
14
|
+
* \-> error
|
|
15
|
+
* (any) -> unsupported (when Web Serial API is unavailable)
|
|
16
|
+
* (any) -> error (when an unrecoverable failure occurs)
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/199 | Issue #199}
|
|
20
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/200 | Issue #200}
|
|
21
|
+
*/
|
|
22
|
+
export declare const SerialSessionState: {
|
|
23
|
+
readonly Idle: "idle";
|
|
24
|
+
readonly Connecting: "connecting";
|
|
25
|
+
readonly Connected: "connected";
|
|
26
|
+
readonly Disconnecting: "disconnecting";
|
|
27
|
+
readonly Unsupported: "unsupported";
|
|
28
|
+
readonly Error: "error";
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* String union of allowed {@link SerialSessionState} runtime values
|
|
32
|
+
* (same set as the values on the {@link SerialSessionState} object).
|
|
33
|
+
*/
|
|
34
|
+
export type SerialSessionState = (typeof SerialSessionState)[keyof typeof SerialSessionState];
|
|
35
|
+
//# sourceMappingURL=serial-session-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serial-session-state.d.ts","sourceRoot":"","sources":["../../src/session/serial-session-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,kBAAkB;;;;;;;CAOrB,CAAC;AAEX;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAC5B,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { Observable } from 'rxjs';
|
|
2
|
+
import type { SerialError } from '../errors/serial-error';
|
|
3
|
+
import type { SerialSessionState } from './serial-session-state';
|
|
4
|
+
/**
|
|
5
|
+
* v2 public API for interacting with the Web Serial API through a
|
|
6
|
+
* minimal, session-oriented surface.
|
|
7
|
+
*
|
|
8
|
+
* The session is intentionally slim so that apps (Angular, Vue, React, etc.)
|
|
9
|
+
* can drive their UI purely from `state$` + `isConnected$` + `receive$` + `lines$` + `errors$` and never
|
|
10
|
+
* have to rebuild BehaviorSubjects, manage a read loop, or serialize writes
|
|
11
|
+
* themselves.
|
|
12
|
+
*
|
|
13
|
+
* All imperative Web Serial work (open / read loop / write / close) is
|
|
14
|
+
* encapsulated by the implementation. Only Observables are exposed.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const session = createSerialSession({ baudRate: 115200 });
|
|
19
|
+
*
|
|
20
|
+
* session.state$.subscribe((state) => console.log('state:', state));
|
|
21
|
+
* session.receive$.subscribe((chunk) => console.log('rx:', chunk));
|
|
22
|
+
* session.errors$.subscribe((error) => console.error('err:', error));
|
|
23
|
+
*
|
|
24
|
+
* session.connect$().subscribe();
|
|
25
|
+
* session.send$('hello\r\n').subscribe();
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/199 | Issue #199}
|
|
29
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/200 | Issue #200}
|
|
30
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/203 | Issue #203}
|
|
31
|
+
*/
|
|
32
|
+
export interface SerialSession {
|
|
33
|
+
/**
|
|
34
|
+
* Synchronous feature detection for the Web Serial API.
|
|
35
|
+
*
|
|
36
|
+
* Never throws; intended for UI branching before calling `connect$`.
|
|
37
|
+
*
|
|
38
|
+
* @returns `true` when `navigator.serial` is available.
|
|
39
|
+
*/
|
|
40
|
+
isBrowserSupported(): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Open a serial port and start the internal read pump.
|
|
43
|
+
*
|
|
44
|
+
* Returns an Observable that completes when the port is fully opened and
|
|
45
|
+
* the read pump is running. Subscribing to `receive$` before calling
|
|
46
|
+
* `connect$` is safe: emissions simply start after the pump is active.
|
|
47
|
+
*
|
|
48
|
+
* @returns An Observable that completes on successful connection.
|
|
49
|
+
*/
|
|
50
|
+
connect$(): Observable<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Close the active serial port and stop the internal read pump.
|
|
53
|
+
*
|
|
54
|
+
* Safe to call when already disconnected.
|
|
55
|
+
*
|
|
56
|
+
* @returns An Observable that completes when the port is fully closed.
|
|
57
|
+
*/
|
|
58
|
+
disconnect$(): Observable<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Reactive session lifecycle state.
|
|
61
|
+
*
|
|
62
|
+
* Replays the current state on subscribe. UIs should drive entirely from
|
|
63
|
+
* this stream instead of reconstructing their own BehaviorSubject.
|
|
64
|
+
*/
|
|
65
|
+
readonly state$: Observable<SerialSessionState>;
|
|
66
|
+
/**
|
|
67
|
+
* `true` when {@link state$} is `'connected'`, `false` for all other states.
|
|
68
|
+
*
|
|
69
|
+
* Derived from `state$` with `distinctUntilChanged` so UIs can bind
|
|
70
|
+
* connect/disabled flags without reimplementing the comparison.
|
|
71
|
+
*/
|
|
72
|
+
readonly isConnected$: Observable<boolean>;
|
|
73
|
+
/**
|
|
74
|
+
* Primary error channel.
|
|
75
|
+
*
|
|
76
|
+
* All {@link SerialError} instances produced by the session (connect /
|
|
77
|
+
* read / write / close) are multiplexed here. This is the main channel,
|
|
78
|
+
* not a supplementary one.
|
|
79
|
+
*
|
|
80
|
+
* Every emission is the exact same instance that is also surfaced to
|
|
81
|
+
* the relevant call-site subscriber (for example `connect$().subscribe`
|
|
82
|
+
* receives the same `SerialError` that `errors$` emits for that
|
|
83
|
+
* failure), so a single subscription is enough to observe the full
|
|
84
|
+
* error history without double-normalisation.
|
|
85
|
+
*
|
|
86
|
+
* Fatal failures (connect / read / close) additionally drive `state$`
|
|
87
|
+
* to `'error'` and tear down the live pump + port; non-fatal failures
|
|
88
|
+
* (currently only `send$` write failures) are multiplexed here without
|
|
89
|
+
* mutating `state$`, on the assumption that a real connection loss is
|
|
90
|
+
* detected by the read pump on the next tick.
|
|
91
|
+
*
|
|
92
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/204 | Issue #204}
|
|
93
|
+
*/
|
|
94
|
+
readonly errors$: Observable<SerialError>;
|
|
95
|
+
/**
|
|
96
|
+
* Incoming data from the serial port as UTF-8 decoded text.
|
|
97
|
+
*
|
|
98
|
+
* The stream is driven by the read pump started by `connect$` and is
|
|
99
|
+
* decoded internally with a streaming `TextDecoder`, so multi-byte
|
|
100
|
+
* characters split across chunks are joined correctly. It is **not**
|
|
101
|
+
* subscription-lazy: emissions happen regardless of whether a consumer
|
|
102
|
+
* is currently subscribed, so late subscribers see only new data.
|
|
103
|
+
*
|
|
104
|
+
* Emits **raw decoder chunks** (not line-aligned). For newline-framed
|
|
105
|
+
* protocols, use {@link lines$} or derive your own framing from
|
|
106
|
+
* `receive$`.
|
|
107
|
+
*/
|
|
108
|
+
readonly receive$: Observable<string>;
|
|
109
|
+
/**
|
|
110
|
+
* Decoded text split into **complete lines** using `\n`, `\r\n`, and
|
|
111
|
+
* lone interior `\r` (see implementation). A trailing fragment without
|
|
112
|
+
* a line terminator is buffered until a later chunk completes a line, or
|
|
113
|
+
* discarded on disconnect. It is **not** subscription-lazy: the same
|
|
114
|
+
* framing runs whenever the read pump is active, independent of
|
|
115
|
+
* subscribers.
|
|
116
|
+
*/
|
|
117
|
+
readonly lines$: Observable<string>;
|
|
118
|
+
/**
|
|
119
|
+
* Enqueue data for ordered transmission.
|
|
120
|
+
*
|
|
121
|
+
* Writes are serialized internally through a FIFO send queue so that
|
|
122
|
+
* concurrent `send$` calls are delivered to the port in **call order**,
|
|
123
|
+
* regardless of how quickly each subscriber runs. String payloads are
|
|
124
|
+
* UTF-8 encoded via a shared `TextEncoder`; `Uint8Array` payloads are
|
|
125
|
+
* passed through unchanged. Write failures are normalized into
|
|
126
|
+
* {@link SerialError} with {@link SerialErrorCode.WRITE_FAILED} and
|
|
127
|
+
* multiplexed on {@link SerialSession.errors$} in addition to being
|
|
128
|
+
* surfaced to the subscriber, so a single subscription is enough to
|
|
129
|
+
* observe every I/O error. Calling `send$` while the session is not in
|
|
130
|
+
* `'connected'` state fails fast with
|
|
131
|
+
* {@link SerialErrorCode.PORT_NOT_OPEN}.
|
|
132
|
+
*
|
|
133
|
+
* The returned Observable completes once the enqueued payload has been
|
|
134
|
+
* flushed to the underlying writer.
|
|
135
|
+
*
|
|
136
|
+
* @param data - Text (UTF-8 encoded) or raw bytes to send.
|
|
137
|
+
* @returns An Observable that completes when the payload is written.
|
|
138
|
+
*
|
|
139
|
+
* @see {@link https://github.com/gurezo/web-serial-rxjs/issues/203 | Issue #203}
|
|
140
|
+
*/
|
|
141
|
+
send$(data: string | Uint8Array): Observable<void>;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=serial-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serial-session.d.ts","sourceRoot":"","sources":["../../src/session/serial-session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,kBAAkB,IAAI,OAAO,CAAC;IAE9B;;;;;;;;OAQG;IACH,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;IAE7B;;;;;;OAMG;IACH,WAAW,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;IAEhC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAEhD;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IAE1C;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAEtC;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAEpC;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;CACpD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { SerialSessionState } from './serial-session-state';
|
|
3
|
+
/**
|
|
4
|
+
* Internal state machine that backs {@link SerialSession.state$}.
|
|
5
|
+
*
|
|
6
|
+
* The machine is deliberately kept as an internal module (not exported
|
|
7
|
+
* from the package) because the public surface is only the Observable.
|
|
8
|
+
* Sub-issues of #199 (read pump / send queue / errors) drive transitions
|
|
9
|
+
* through the dedicated `to*` methods below instead of mutating a shared
|
|
10
|
+
* `BehaviorSubject` directly.
|
|
11
|
+
*
|
|
12
|
+
* Design notes:
|
|
13
|
+
*
|
|
14
|
+
* - Invalid transitions are silently rejected so that the `state$` stream
|
|
15
|
+
* never emits a state that violates the lifecycle contract. A
|
|
16
|
+
* `console.warn` is emitted in development builds to aid debugging.
|
|
17
|
+
* - `unsupported` is terminal: once entered (during construction when
|
|
18
|
+
* `navigator.serial` is missing), the machine refuses every further
|
|
19
|
+
* transition.
|
|
20
|
+
* - `state$` is derived from a {@link BehaviorSubject} so late subscribers
|
|
21
|
+
* still receive the current state on subscription.
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export declare class SessionStateMachine {
|
|
26
|
+
private readonly subject;
|
|
27
|
+
constructor(initial?: SerialSessionState);
|
|
28
|
+
get current(): SerialSessionState;
|
|
29
|
+
get state$(): Observable<SerialSessionState>;
|
|
30
|
+
toConnecting(): boolean;
|
|
31
|
+
toConnected(): boolean;
|
|
32
|
+
toDisconnecting(): boolean;
|
|
33
|
+
toIdle(): boolean;
|
|
34
|
+
toError(): boolean;
|
|
35
|
+
toUnsupported(): boolean;
|
|
36
|
+
complete(): void;
|
|
37
|
+
private transition;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=session-state-machine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-state-machine.d.ts","sourceRoot":"","sources":["../../src/session/session-state-machine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,UAAU,EAAE,MAAM,MAAM,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAoC5D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;gBAElD,OAAO,GAAE,kBAA4C;IAIjE,IAAI,OAAO,IAAI,kBAAkB,CAEhC;IAED,IAAI,MAAM,IAAI,UAAU,CAAC,kBAAkB,CAAC,CAE3C;IAED,YAAY,IAAI,OAAO;IAIvB,WAAW,IAAI,OAAO;IAItB,eAAe,IAAI,OAAO;IAI1B,MAAM,IAAI,OAAO;IAIjB,OAAO,IAAI,OAAO;IAIlB,aAAa,IAAI,OAAO;IAIxB,QAAQ,IAAI,IAAI;IAIhB,OAAO,CAAC,UAAU;CAoBnB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gurezo/web-serial-rxjs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "RxJS-based utilities for the Web Serial API, usable from Angular, React, Svelte, and Vanilla JavaScript/TypeScript.",
|
|
5
5
|
"author": "Akihiko Kigure <akihiko.kigure@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,10 +11,6 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"import": "./dist/index.mjs"
|
|
13
13
|
},
|
|
14
|
-
"./shell": {
|
|
15
|
-
"types": "./dist/shell/index.d.ts",
|
|
16
|
-
"import": "./dist/shell/index.mjs"
|
|
17
|
-
},
|
|
18
14
|
"./package.json": "./package.json"
|
|
19
15
|
},
|
|
20
16
|
"files": [
|
package/web-serial-rxjs-icon.png
CHANGED
|
Binary file
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser type enumeration for identifying the browser environment.
|
|
3
|
-
*
|
|
4
|
-
* This enum is used to identify the specific browser type, which is useful for
|
|
5
|
-
* browser-specific behavior or error messages.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* const browserType = detectBrowserType();
|
|
10
|
-
* if (browserType === BrowserType.CHROME) {
|
|
11
|
-
* console.log('Running in Chrome');
|
|
12
|
-
* }
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
export declare enum BrowserType {
|
|
16
|
-
/** Google Chrome browser */
|
|
17
|
-
CHROME = "chrome",
|
|
18
|
-
/** Microsoft Edge browser */
|
|
19
|
-
EDGE = "edge",
|
|
20
|
-
/** Opera browser */
|
|
21
|
-
OPERA = "opera",
|
|
22
|
-
/** Unknown or unsupported browser */
|
|
23
|
-
UNKNOWN = "unknown"
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Feature detection for Web Serial API.
|
|
27
|
-
*
|
|
28
|
-
* Checks if the browser supports the Web Serial API by verifying the presence
|
|
29
|
-
* of `navigator.serial`. This is a non-throwing check that returns `false` if
|
|
30
|
-
* the API is not available.
|
|
31
|
-
*
|
|
32
|
-
* Note: This function only checks for API availability, not whether the browser
|
|
33
|
-
* type is supported. For a throwing check that provides better error messages,
|
|
34
|
-
* use {@link checkBrowserSupport}.
|
|
35
|
-
*
|
|
36
|
-
* @returns `true` if the Web Serial API is available, `false` otherwise
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```typescript
|
|
40
|
-
* if (hasWebSerialSupport()) {
|
|
41
|
-
* // Safe to use serial port functionality
|
|
42
|
-
* const client = createSerialClient();
|
|
43
|
-
* } else {
|
|
44
|
-
* console.error('Web Serial API is not supported');
|
|
45
|
-
* }
|
|
46
|
-
* ```
|
|
47
|
-
*
|
|
48
|
-
* @see {@link checkBrowserSupport} for a throwing version with better error messages
|
|
49
|
-
* @see {@link isBrowserSupported} for an alias to this function
|
|
50
|
-
*/
|
|
51
|
-
export declare function hasWebSerialSupport(): boolean;
|
|
52
|
-
/**
|
|
53
|
-
* Detect browser type from the user agent string.
|
|
54
|
-
*
|
|
55
|
-
* Analyzes the browser's user agent string to identify the browser type.
|
|
56
|
-
* This function is useful for providing browser-specific functionality or
|
|
57
|
-
* error messages.
|
|
58
|
-
*
|
|
59
|
-
* @returns The detected {@link BrowserType}, or {@link BrowserType.UNKNOWN} if the browser cannot be identified
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* ```typescript
|
|
63
|
-
* const browserType = detectBrowserType();
|
|
64
|
-
* switch (browserType) {
|
|
65
|
-
* case BrowserType.CHROME:
|
|
66
|
-
* console.log('Running in Chrome');
|
|
67
|
-
* break;
|
|
68
|
-
* case BrowserType.EDGE:
|
|
69
|
-
* console.log('Running in Edge');
|
|
70
|
-
* break;
|
|
71
|
-
* case BrowserType.OPERA:
|
|
72
|
-
* console.log('Running in Opera');
|
|
73
|
-
* break;
|
|
74
|
-
* default:
|
|
75
|
-
* console.log('Unknown browser');
|
|
76
|
-
* }
|
|
77
|
-
* ```
|
|
78
|
-
*
|
|
79
|
-
* @see {@link isChromiumBased} for checking if the browser is Chromium-based
|
|
80
|
-
*/
|
|
81
|
-
export declare function detectBrowserType(): BrowserType;
|
|
82
|
-
/**
|
|
83
|
-
* Check if the browser is Chromium-based.
|
|
84
|
-
*
|
|
85
|
-
* Determines if the current browser is based on Chromium, which includes
|
|
86
|
-
* Chrome, Edge, and Opera. These browsers support the Web Serial API.
|
|
87
|
-
*
|
|
88
|
-
* @returns `true` if the browser is Chromium-based (Chrome, Edge, or Opera), `false` otherwise
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```typescript
|
|
92
|
-
* if (isChromiumBased()) {
|
|
93
|
-
* // Browser supports Web Serial API
|
|
94
|
-
* const client = createSerialClient();
|
|
95
|
-
* } else {
|
|
96
|
-
* console.error('Please use a Chromium-based browser (Chrome, Edge, or Opera)');
|
|
97
|
-
* }
|
|
98
|
-
* ```
|
|
99
|
-
*
|
|
100
|
-
* @see {@link detectBrowserType} for identifying the specific browser type
|
|
101
|
-
* @see {@link hasWebSerialSupport} for checking Web Serial API availability
|
|
102
|
-
*/
|
|
103
|
-
export declare function isChromiumBased(): boolean;
|
|
104
|
-
//# sourceMappingURL=browser-detection.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"browser-detection.d.ts","sourceRoot":"","sources":["../../src/browser/browser-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,oBAAY,WAAW;IACrB,4BAA4B;IAC5B,MAAM,WAAW;IACjB,6BAA6B;IAC7B,IAAI,SAAS;IACb,oBAAoB;IACpB,KAAK,UAAU;IACf,qCAAqC;IACrC,OAAO,YAAY;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAO7C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,IAAI,WAAW,CAoB/C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAOzC"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Check if the browser supports the Web Serial API, throwing an error if not supported.
|
|
3
|
-
*
|
|
4
|
-
* This function performs a feature detection check and throws a {@link SerialError}
|
|
5
|
-
* with code {@link SerialErrorCode.BROWSER_NOT_SUPPORTED} if the Web Serial API
|
|
6
|
-
* is not available. The error message includes the detected browser type for better
|
|
7
|
-
* user feedback.
|
|
8
|
-
*
|
|
9
|
-
* This is the recommended way to check browser support before using serial port
|
|
10
|
-
* functionality, as it provides clear error messages.
|
|
11
|
-
*
|
|
12
|
-
* @throws {@link SerialError} with code {@link SerialErrorCode.BROWSER_NOT_SUPPORTED}
|
|
13
|
-
* if the browser doesn't support the Web Serial API
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* try {
|
|
18
|
-
* checkBrowserSupport();
|
|
19
|
-
* // Safe to use serial port functionality
|
|
20
|
-
* const client = createSerialClient();
|
|
21
|
-
* } catch (error) {
|
|
22
|
-
* if (error instanceof SerialError && error.code === SerialErrorCode.BROWSER_NOT_SUPPORTED) {
|
|
23
|
-
* console.error(error.message);
|
|
24
|
-
* // Show user-friendly message: "Please use a Chromium-based browser..."
|
|
25
|
-
* }
|
|
26
|
-
* }
|
|
27
|
-
* ```
|
|
28
|
-
*
|
|
29
|
-
* @see {@link isBrowserSupported} for a non-throwing version that returns a boolean
|
|
30
|
-
* @see {@link hasWebSerialSupport} for the underlying feature detection function
|
|
31
|
-
*/
|
|
32
|
-
export declare function checkBrowserSupport(): void;
|
|
33
|
-
/**
|
|
34
|
-
* Check if the browser supports the Web Serial API (non-throwing version).
|
|
35
|
-
*
|
|
36
|
-
* This is a convenience function that returns a boolean indicating whether
|
|
37
|
-
* the Web Serial API is available. Unlike {@link checkBrowserSupport}, this
|
|
38
|
-
* function does not throw an error if the API is not available.
|
|
39
|
-
*
|
|
40
|
-
* @returns `true` if the Web Serial API is supported, `false` otherwise
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```typescript
|
|
44
|
-
* if (isBrowserSupported()) {
|
|
45
|
-
* const client = createSerialClient();
|
|
46
|
-
* // Use serial port functionality
|
|
47
|
-
* } else {
|
|
48
|
-
* console.error('Web Serial API is not supported in this browser');
|
|
49
|
-
* // Show fallback UI or message
|
|
50
|
-
* }
|
|
51
|
-
* ```
|
|
52
|
-
*
|
|
53
|
-
* @see {@link checkBrowserSupport} for a throwing version with better error messages
|
|
54
|
-
* @see {@link hasWebSerialSupport} which this function calls internally
|
|
55
|
-
*/
|
|
56
|
-
export declare function isBrowserSupported(): boolean;
|
|
57
|
-
//# sourceMappingURL=browser-support.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"browser-support.d.ts","sourceRoot":"","sources":["../../src/browser/browser-support.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAa1C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C"}
|