Actors/Packages/WebSocket/API
@sigx/actors-ws · Preview

API#

Exports of @sigx/actors-ws v0.9.2.

Three entries. The root re-exports the client half, which is WinterCG-clean; ./node is the only one that touches Node built-ins.

EntryContents
@sigx/actors-wssocketTransport and its types — runtime-neutral re-exports of ./client
@sigx/actors-ws/clientthe same, at its source
@sigx/actors-ws/nodeattachActorSocket, toRequest, DEFAULT_SOCKET_PATH

./client#

TypeScript
function socketTransport(options?: SocketTransportOptions): ActorTransport;

interface SocketTransportOptions {
    connect?(handlers: SocketHandlers): SocketLink;
    url?: string;
    retryMs?: number;        // default 300
    maxRetryMs?: number;     // default 10_000
}

interface SocketLink {
    send(message: string): void;
    close(): void;
}

interface SocketHandlers {
    onOpen(): void;          // gates the first send
    onMessage(message: string): void;
    onClose(): void;
}

connect is called again after a drop — each call is one fresh attempt. Passing url on a runtime with no global WebSocket constructor throws with a message telling you to pass connect instead.

The returned value is an ordinary ActorTransport, so it also carries live() — the incremental subscription channel — and a close() that is idempotent by contract, since either the plugin or the live channel may release it first.

./node#

TypeScript
function attachActorSocket(server: Server, options: AttachActorSocketOptions): () => void;

interface AttachActorSocketOptions
    extends Omit<ActorSocketSessionOptions, 'request' | 'send' | 'close'> {
    path?: string;              // default '/_sigx/socket', matched exactly
    wss?: WebSocketServerLike;  // bring your own noServer WebSocketServer
}

function toRequest(request: IncomingMessage): Request;

const DEFAULT_SOCKET_PATH = '/_sigx/socket';

attachActorSocket returns a detach function. toRequest builds the WinterCG Request a Node upgrade does not come with — scheme http (the session folds ws:/http: when checking origin), headers including cookies and Origin carried over verbatim.

Everything AttachActorSocketOptions inherits — host, origin, maxMessageBytes, maxConcurrent, maxSubscriptions, pingMs, revalidateMs, maxConnectionMs, throttlePolicy, onError, stats — is documented under Socket sessions. bufferedBytes is supplied by the adapter from the socket's bufferedAmount.

Structural types#

WebSocketServerLike and MinimalWebSocket describe only the slices of ws the adapter actually drives, so a compatible implementation satisfies them without ws being installed:

TypeScript
interface WebSocketServerLike {
    handleUpgrade(
        request: IncomingMessage, socket: Duplex, head: Buffer,
        done: (client: MinimalWebSocket) => void,
    ): void;
}

interface MinimalWebSocket {
    send(message: string): void;
    close(code?: number, reason?: string): void;
    on(event: 'message', listener: (data: unknown, isBinary: boolean) => void): void;
    on(event: 'close', listener: () => void): void;
}

The wire#

Both halves speak @sigx/actors/socket-wire, which is a published subpath of @sigx/actors rather than something this package owns — so an adapter written outside this repo reaches the same protocol.

Next steps#