v4 consolidates public API cleanup from Phase 1 (#472) and Phase 2 (#485) into one major upgrade. This guide covers both phases so you can migrate once.
TypeScript-facing changes introduced in v3 (SerialErrorCode const object, discriminated-union state$) remain as documented in Migrating to v3.
import {
createSerialSession,
isWebSerialSupported,
SerialSessionStatus,
} from '@gurezo/web-serial-rxjs';
import { shareReplay } from 'rxjs';
if (!isWebSerialSupported()) {
// fallback UI before creating a session
}
const session = createSerialSession({ baudRate: 9600 });
session.state$.subscribe((state) => {
if (state.status === SerialSessionStatus.Unsupported) {
// unsupported UI after session creation
}
});
// Prefer the stream that matches your use case:
session.receive$.subscribe(/* decoded chunks */);
session.lines$.subscribe(/* complete lines */);
session.terminalText$.subscribe(/* terminal display text */);
// If you previously used receiveReplay$, compose operators yourself.
// This is NOT a drop-in replacement for the removed API.
const replayedReceive$ = session.receive$.pipe(
shareReplay({
bufferSize: 1,
refCount: true,
}),
);
Phase 1 of #472 removed duplicate / escape-hatch APIs so state$ and dispose$() are the only public sources for lifecycle and teardown. Documentation pass: #478.
| Removed API | Replacement |
|---|---|
destroy$() |
dispose$() |
isConnected$ |
state$ with state.status (or derive a boolean from state$) |
portInfo$ |
state.portInfo when state.status === SerialSessionStatus.Connected |
getPortInfo() |
state.portInfo when connected (same as above) |
getCurrentPort() |
No direct replacement. Use state.portInfo for identification; raw SerialPort is not exposed |
Longer examples and checklists: Migrating to v3 – Phase 1 API removals.
Phase 2 of #485 removes session-attached derived APIs and options that did not match their names or session responsibilities. Implementation: #486, #487, #488. Docs: #490.
| Before (v3 and earlier) | After (v4) |
|---|---|
session.receiveReplay$ |
session.receive$ composed with the RxJS operators you need |
options.receiveReplay |
Removed |
session.isBrowserSupported() |
Top-level isWebSerialSupported(), or state$ with Unsupported |
| Mixed / opaque session options | SerialConnectionOptions + SerialSessionFeatureOptions composition |
receiveReplay$ and receiveReplay optionreceiveReplay$ only replayed past chunks when receiveReplay.enabled was set at session creation. When disabled it behaved like receive$, so the name and behavior did not match. Replay applied to decoded receive chunks only—not to lines$ or terminalText$—and required separate bufferSize / maxChars limits.
v4 removes both the stream and the option. If your app needs replay-like caching, compose operators on receive$ yourself.
import { shareReplay } from 'rxjs';
const replayedReceive$ = session.receive$.pipe(
shareReplay({
bufferSize: 1,
refCount: true,
}),
);
This pattern is not guaranteed to be fully compatible with the removed receiveReplay$ API:
shareReplay bufferSize counts events, not characters. The old option also supported maxChars.maxChars / character-budget limit in this recipe.shareReplay reset / refCount behavior differs from the old session-owned buffer).Do not treat shareReplay as a complete substitute for the deleted feature.
Web Serial availability is not per-session state. Calling createSerialSession() only to check support was confusing.
Before creating a session (sync feature detection):
import { isWebSerialSupported } from '@gurezo/web-serial-rxjs';
if (!isWebSerialSupported()) {
// fallback UI
}
After the session exists, prefer state$ for UI that follows lifecycle:
import { SerialSessionStatus } from '@gurezo/web-serial-rxjs';
session.state$.subscribe((state) => {
if (state.status === SerialSessionStatus.Unsupported) {
// unsupported UI
}
});
session.isBrowserSupported() is removed. See also API concepts – SerialSession / isWebSerialSupported.
SerialSessionOptions remains a single factory argument, but responsibilities are clearer:
SerialConnectionOptions = W3C connection parameters for port.open
SerialSessionFeatureOptions = library-specific session features
SerialSessionOptions = Partial<SerialConnectionOptions> & SerialSessionFeatureOptions
baudRate, dataBits, stopBits, parity, bufferSize, flowControlfilters, terminalBuffer, lineBuffer (receiveReplay is gone)Boundary semantics (0 = unlimited for buffer limits only; connection fields require > 0) are documented in API concepts – SerialSessionOptions.
These are not duplicates. Each abstracts a different use case:
| API | Use it for |
|---|---|
receive$ |
Decoded UTF-8 chunks from the read pump |
lines$ |
Newline-framed complete lines (logs / protocols) |
terminalText$ |
Cumulative text for terminal display (including \r redraw behavior) |
They stay on SerialSession so apps do not reimplement framing, incomplete tails, or terminal buffer limits. Details: API concepts – SerialSession.
The following stay as in v3 / Phase 1 completion:
connect$, send$, disconnect$, dispose$) run when subscribed (cold)errors$ and operation-Observable error notification semantics are unchangedlines$ / terminalText$ are not moved to user-land operatorsTarget public shape:
export interface SerialSession {
readonly state$: Observable<SerialSessionState>;
readonly errors$: Observable<SerialError>;
readonly receive$: Observable<string>;
readonly lines$: Observable<string>;
readonly terminalText$: Observable<string>;
connect$(): Observable<void>;
disconnect$(): Observable<void>;
send$(data: SerialPayload): Observable<void>;
dispose$(): Observable<void>;
}
Plus the top-level helper:
export function isWebSerialSupported(): boolean;
destroy$() with dispose$(); drive lifecycle UI from state$isConnected$ / portInfo$ / getPortInfo() / getCurrentPort() with state$ / state.portInforeceiveReplay$ subscriptions and receiveReplay optionsreceive$ and accept the differences abovesession.isBrowserSupported() with isWebSerialSupported() or state$ UnsupportedINVALID_RECEIVE_REPLAY_OPTIONS, RECEIVE_REPLAY_BUFFER_OVERFLOW)receive$ / lines$ / terminalText$ by use case, not as interchangeable aliasesSerialSession.receiveReplay$ and SerialSessionOptions.receiveReplaySerialSession.isBrowserSupported(); use top-level isWebSerialSupported()SerialSessionOptions as connection fields + feature options (filters, terminalBuffer, lineBuffer)SerialErrorCode, discriminated-union state$, Phase 1 detail sectionsSerialClient → SerialSession (note: v4 browser check is top-level again)