2.8 KiB
subscription
(no submodules)
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-wsmessage types. parseSubscriptionMessagereturns a structured{ ok, message }or{ ok: false, issues }rather than throwing — engines decide whether to close the connection.assertSubscriptionTransportraisesGRAPHQL.SUBSCRIPTION_TRANSPORT_UNAVAILABLEwhen the marker reports the transport is offline.
Usage: Basic
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:
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 thegraphql-wsmessage 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.