Files
skills/docs/api-stack/api/api-graphql/src/subscription/subscription.md
2026-05-29 08:20:56 +01:00

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-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

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 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.