first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
# `subscription`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Validate incoming `graphql-ws` subscription envelopes and surface a typed
"transport unavailable" failure when `api-ws` isn't wired into the host.
Subscriptions ride the WebSocket engine published in `api-ws` (design
§10.4); this file is the contract-side handshake validator + transport
gating, not the dispatch loop itself.
The Zod-validated envelope shape covers the subset of the `graphql-ws`
protocol the host care about (`connection_init`, `subscribe`, `next`,
`error`, `complete`, plus the ping/pong heartbeat). Engines validate inbound
frames with `parseSubscriptionMessage` before dispatching to a
`SubscriptionResolver`.
## Features
- Zod schema covering all eight `graphql-ws` message types.
- `parseSubscriptionMessage` returns a structured `{ ok, message }` or
`{ ok: false, issues }` rather than throwing — engines decide whether
to close the connection.
- `assertSubscriptionTransport` raises
`GRAPHQL.SUBSCRIPTION_TRANSPORT_UNAVAILABLE` when the marker reports
the transport is offline.
## Usage: Basic
```ts
import { parseSubscriptionMessage } from "@suaveplan/api-graphql/subscription";
const result = parseSubscriptionMessage(JSON.parse(frame));
if (result.ok) {
dispatch(result.message);
} else {
closeWithCode(4400, result.issues.join("; "));
}
```
## Usage: Advanced
Gate `executeSubscription` on transport availability so engine adapters
return a typed error rather than a generic transport failure:
```ts
import {
assertSubscriptionTransport,
GraphqlError,
} from "@suaveplan/api-graphql";
try {
assertSubscriptionTransport({ available: false, protocol: "graphql-ws" });
} catch (e) {
if (e instanceof GraphqlError) {
// "GRAPHQL.SUBSCRIPTION_TRANSPORT_UNAVAILABLE"
console.error(e.graphqlCode);
}
}
```
## API Reference
- `subscriptionMessageSchema` — Zod discriminated union over the
`graphql-ws` message types.
- `SubscriptionMessage` — inferred TypeScript type.
- `SubscriptionTransportMarker` — `{ available, protocol: "graphql-ws" }`.
- `parseSubscriptionMessage(raw) → { ok: true; message } | { ok: false; issues }`.
- `assertSubscriptionTransport(marker) → void` — throws when unavailable.
## Implementation Notes
The schema is intentionally permissive on payload shape — the inner
`payload.query` is validated; the `variables` and `extensions` carriers
accept any record because plugin authors define their own variable shapes.
The host re-validates `variables` against the operation's declared shape
at execute time.
The `SUBSCRIPTION_TRANSPORT_UNAVAILABLE` failure mode exists because the
host MAY ship without `api-ws` (a query-only deployment). Plugins that
register subscription resolvers but find no transport wired need a clear
boot-time signal; this is it.