Files
terminal-lab/terminal/packages/terminal-core/src/session/sessionMachine.ts
douboer@gmail.com 3b7c1d558a first commit
2026-03-03 13:23:14 +08:00

62 lines
1.7 KiB
TypeScript

import type { SessionState } from "../types";
/** 合法状态迁移表 */
const TRANSITIONS: Record<SessionState, SessionState[]> = {
idle: ["connecting", "disconnected"],
connecting: ["auth_pending", "error", "disconnected"],
auth_pending: ["connected", "error", "disconnected"],
connected: ["reconnecting", "disconnected", "error"],
reconnecting: ["connected", "error", "disconnected"],
disconnected: ["connecting", "idle"],
error: ["connecting", "disconnected"],
};
export function canTransition(from: SessionState, to: SessionState): boolean {
return (TRANSITIONS[from] ?? []).includes(to);
}
export function assertTransition(from: SessionState, to: SessionState): void {
if (!canTransition(from, to)) {
throw new Error(`非法状态跳转: ${from}${to}`);
}
}
/**
* SessionMachine — 会话生命周期状态机。
* 纯状态逻辑,无任何副作用,零 DOM 依赖。
*/
export class SessionMachine {
private _state: SessionState = "idle";
private listeners = new Set<(state: SessionState) => void>();
get state(): SessionState {
return this._state;
}
transition(to: SessionState): void {
assertTransition(this._state, to);
this._state = to;
for (const fn of this.listeners) {
fn(this._state);
}
}
tryTransition(to: SessionState): boolean {
if (!canTransition(this._state, to)) return false;
this.transition(to);
return true;
}
onChange(fn: (state: SessionState) => void): () => void {
this.listeners.add(fn);
return () => this.listeners.delete(fn);
}
reset(): void {
this._state = "idle";
for (const fn of this.listeners) {
fn(this._state);
}
}
}