/** * The transport contract: one logical connection of ordered, opaque messages, * and the strategy that opens one. * * A {@link Transport} opens a {@link Connection} for an api key. A * {@link Connection} is a single reliable, exactly-once, in-order stream in * both directions, with a terminal end — a transient drop is invisible (the * connection reconnects and replays beneath this contract), so only a * deliberate {@link Connection.close} or a terminal failure ends it. Both are * payload-blind: a message is opaque `unknown`, so what it *means* (a command, * a result) belongs to the session layer, and the one contract serves every * carriage. * * `connection.ts` implements {@link Connection}; `websocket.ts` and `http1.ts` * are the {@link Transport}s. */ export interface Transport { open(apiKey: string): PromiseLike; } /** * How a connection ended: the close-registry `code` where the end was a * protocol close, and the human `reason` to surface. Either may be absent — a * caller {@link Connection.close} carries no code and an optional reason, and a * failure the carriage detects out of band (a socket that would not construct) * carries a reason but no code — so a plain close is the empty close. * * The code is what can be branched on: `closeReason` folds a server-supplied * detail into `reason`, so two ends with the same meaning can read differently. * `connection.ts` holds the registry — `1` unauthorized, `2` invalid token, `3` * protocol violation. */ export type Close = { readonly code?: number; readonly reason?: string; }; export interface Connection { /** * Enqueue one opaque message into the ordered outbound stream. Returns `false` * when the message is rejected for exceeding `MAX_MESSAGE_BYTES` — it is not * queued, so the caller must settle its command as a failure rather than await * a result that will never come; `true` when accepted (or dropped because the * connection is already ending, in which case the imminent teardown settles * the command). */ send(message: unknown): boolean; /** * Subscribe to inbound message batches. `listener` is called once per batch * with its messages; a terminal end is reported separately through * {@link Connection.closed}, never here. Returns an unsubscribe function. */ onMessages(listener: (messages: ReadonlyArray) => void): () => void; /** * The stream's terminal end, as a {@link PromiseLike}: it resolves with the * {@link Close} that ended it — the failure where it ended on its own (a * refused resume, say), or what was passed to {@link Connection.close}. */ readonly closed: PromiseLike; /** * End the stream deliberately, resolving {@link Connection.closed} with the * optional `reason`. Idempotent. */ close(reason?: string): void; }