feat: add native module realtime transport
CI / verify (pull_request) Successful in 37s
CI / infrastructure-smoke (pull_request) Successful in 13s
CI / migration-smoke (pull_request) Successful in 1m7s

This commit is contained in:
ekklesia
2026-08-23 18:47:18 -05:00
parent fcc531a39c
commit fc6c8045c4
53 changed files with 3959 additions and 108 deletions
+57
View File
@@ -0,0 +1,57 @@
/**
* 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;
}