Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
# `subprotocol`
## Purpose
Implements RFC 6455 §4.1 subprotocol negotiation as a tiny pure function. The server is supplied the client's requested protocols and the server-supported list; the function returns the first server-supported protocol the client requested, or `null` when the client requested nothing.
This is exposed as a public utility because callers occasionally need to short-circuit the full handshake — for example, an OpenAPI documentation route advertising the engine's supported subprotocols before any actual upgrade.
## Features
- Strict RFC 6455 ordering — server-supported list determines priority, NOT the client's preference list.
- Throws `WS_BUN.SUBPROTOCOL_UNSUPPORTED` when the client requested any subprotocol but none match.
- Returns `null` for the common "client requested nothing" case.
## Usage: Basic
```ts
import { resolveSubprotocol } from "@suaveplan/api-ws-bun";
const chosen = resolveSubprotocol(
["graphql-transport-ws"],
["suaveplan.v1", "graphql-transport-ws"]
);
// chosen === "graphql-transport-ws"
```
## Usage: Advanced
```ts
import { WS_BUN_CODES, resolveSubprotocol } from "@suaveplan/api-ws-bun";
try {
resolveSubprotocol(["unknown"], ["suaveplan.v1"]);
} catch (err) {
if ((err as { code?: string }).code === WS_BUN_CODES.SUBPROTOCOL_UNSUPPORTED) {
// respond 400 with `Sec-WebSocket-Protocol: <server's list>`
}
}
```
## API Reference
- `resolveSubprotocol(requested, supported): string | null` — pure negotiation function.
## Implementation Notes
Server-priority ordering matters: a client might list `["graphql-ws", "graphql-transport-ws"]` expecting the older protocol, but if the server prefers the newer one and lists it first, the function returns `"graphql-transport-ws"`. That matches the RFC and matches the behaviour Bun's native `Server.upgrade` would apply if the negotiation were delegated to Bun itself.
The empty-`requested` short-circuit returns `null` rather than throwing because RFC 6455 explicitly permits handshakes with no `Sec-WebSocket-Protocol` header — the connection is valid, it just has no negotiated subprotocol. This is the default state for a Bun client written against the foundation's plain-JSON envelope wire format.