58 lines
2.4 KiB
TypeScript
58 lines
2.4 KiB
TypeScript
/**
|
|
* A JSON value carried from a module's server runtime to its browser UI.
|
|
*
|
|
* Realtime state is deliberately data, not transport vocabulary. A module does not open a socket,
|
|
* choose an origin, attach credentials, or know how its host keeps a subscription alive. The host
|
|
* owns all of that and gives the module only typed snapshots and updates.
|
|
*/
|
|
export type ModuleUiRealtimeJsonValue =
|
|
| boolean
|
|
| number
|
|
| string
|
|
| null
|
|
| readonly ModuleUiRealtimeJsonValue[]
|
|
| { readonly [key: string]: ModuleUiRealtimeJsonValue };
|
|
|
|
/** Connection state useful for rendering a small, honest status indicator. */
|
|
export type ModuleUiRealtimeStatus = "connecting" | "connected" | "reconnecting" | "closed";
|
|
|
|
/** Stable, browser-safe failures. A host never exposes a caught platform or network error. */
|
|
export type ModuleUiRealtimeErrorCode = "REALTIME_CONNECTION_FAILED" | "REALTIME_MESSAGE_INVALID";
|
|
|
|
export interface ModuleUiRealtimeError {
|
|
readonly code: ModuleUiRealtimeErrorCode;
|
|
readonly message: string;
|
|
}
|
|
|
|
/** Callbacks for one module-local channel. Snapshot and update are distinct on purpose: a UI can
|
|
* replace all derived state when it (re)connects, then apply later authoritative states normally. */
|
|
export interface ModuleUiRealtimeHandlers<State = ModuleUiRealtimeJsonValue> {
|
|
readonly onSnapshot?: (state: State, sequence: number) => void;
|
|
readonly onUpdate?: (state: State, sequence: number) => void;
|
|
readonly onStatus?: (status: ModuleUiRealtimeStatus) => void;
|
|
readonly onError?: (error: ModuleUiRealtimeError) => void;
|
|
}
|
|
|
|
/** One live subscription. Closing is synchronous and idempotent. */
|
|
export interface ModuleUiRealtimeSubscription {
|
|
close(): void;
|
|
}
|
|
|
|
/**
|
|
* A module UI's access to its own runtime-published state.
|
|
*
|
|
* `channel` is local to the module and uses lowercase kebab-case. The host supplies the module id,
|
|
* endpoint, origin, credentials, reconnection policy, and concrete transport. Modules can neither
|
|
* subscribe to another module nor supply a bearer token through this API.
|
|
*
|
|
* State must be JSON-compatible. The generic is intentionally unconstrained so a normal named
|
|
* interface can describe a payload without needing an index signature; the runtime wire boundary
|
|
* still validates that every delivered payload is JSON.
|
|
*/
|
|
export interface ModuleUiRealtimeClient {
|
|
subscribe<State = ModuleUiRealtimeJsonValue>(
|
|
channel: string,
|
|
handlers: ModuleUiRealtimeHandlers<State>,
|
|
): ModuleUiRealtimeSubscription;
|
|
}
|