2.6 KiB
2.6 KiB
connection — canonical WsConnection contract
(no submodules)
Purpose
@suaveplan/api-ws/connection declares the abstract WsConnection
interface every concrete engine (api-ws-bun, future browser shims)
implements. Plugins author against this contract; the host wires whichever
engine the deployment requires. This is The type-only foundation —
no runtime, no state, just the interface and its supporting helper types.
The handshake principal is frozen for the connection's lifetime; the
contract intentionally exposes principal as a readonly Principal so a
plugin cannot mutate it mid-session, and the host emits
connection.principal_expired (an api-host concern) when the underlying
session lapses.
Features
WsConnectioninterface — id, principal, tenantId, lastEventId, state, plussubscribe / unsubscribe / send / close / ack.WsConnectionState—"open" | "closing" | "closed".SubscribeOptions— tenant override and optionalfilterpredicate.SubscriptionFilter<Payload>—(payload: Payload) => boolean.
Usage: Basic
import type { WsConnection } from "@suaveplan/api-ws/connection";
async function onConnect(conn: WsConnection): Promise<void> {
await conn.subscribe("orders.created", { tenant: conn.tenantId });
}
Usage: Advanced
import type {
SubscribeOptions,
WsConnection,
} from "@suaveplan/api-ws/connection";
interface OrderEvent { priority: number }
const opts: SubscribeOptions<OrderEvent> = {
tenant: tenantId,
filter: (payload): boolean => payload.priority >= 5,
};
await conn.subscribe("orders.created", opts);
await conn.send({ id: "1", type: "ack", topic: "orders.created" });
conn.ack("e-42");
if (conn.state !== "open") {
return;
}
API Reference
interface WsConnection { id, principal, tenantId, lastEventId, state, subscribe, unsubscribe, send, close, ack }.type WsConnectionState = "open" | "closing" | "closed".type SubscriptionFilter<Payload> = (payload: Payload) => boolean.interface SubscribeOptions<Payload> { tenant?: TenantId; filter?: SubscriptionFilter<Payload> }.
Implementation Notes
sendaccepts aWsEnvelope(the wire schema) so engines can apply the same boundary validation on outbound frames they apply on inbound.subscribe/unsubscribe/send/closeare typed asvoid | Promise<void>so engines that need to coordinate with a broker can be async, while in-memory engines can stay synchronous.ackis synchronous because it only updates the connection'slastEventIdcursor; it never blocks on I/O.