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

2.7 KiB

envelope — wire-frame Zod schema

(no submodules)

Purpose

@suaveplan/api-ws/envelope owns the canonical Zod schema for every WebSocket frame that flows between the host and a plugin. Engines parse incoming frames against this schema before the message reaches plugin code, so unknown top-level keys never leak past the host boundary and every frame is guaranteed to carry the correlation id and discriminator the subscription bus, ack pipeline, and reconnect-resume path require.

The shape is deliberately minimal — id, type, optional topic, optional payload, optional ts — so plugins can compose their own Zod schemas on top of payload without fighting the wire format.

Features

  • Strict object schema — extra keys are a parse failure, not a silent drop.
  • isWsEnvelope(value): value is WsEnvelope predicate for ergonomic narrowing inside engine adapters.
  • parseWsEnvelope(value) throws the underlying ZodError for callers that want to convert to a WsError at the boundary.
  • Always uses the default-import form import z from "zod" per the project Zod policy.

Usage: Basic

import { isWsEnvelope, parseWsEnvelope } from "@suaveplan/api-ws/envelope";

const frame = parseWsEnvelope(JSON.parse(rawText));
console.log(frame.id, frame.type);

Usage: Advanced

import { isWsEnvelope, type WsEnvelope } from "@suaveplan/api-ws/envelope";
import { WS_CODES, WsError } from "@suaveplan/api-ws/error-codes";
import z from "zod";

const orderPayload = z.object({ orderId: z.string() });

function handle(raw: unknown): void {
    if (!isWsEnvelope(raw)) {
        throw new WsError(WS_CODES.HANDSHAKE_FAILED, "invalid envelope");
    }
    const envelope: WsEnvelope = raw;
    if (envelope.type === "orders.ack") {
        const payload = orderPayload.parse(envelope.payload);
        // narrow + branch...
        void payload;
    }
}

API Reference

  • wsEnvelopeSchema: z.ZodSchema<WsEnvelope> — strict object schema.
  • type WsEnvelope = z.infer<typeof wsEnvelopeSchema>.
  • isWsEnvelope(value: unknown): value is WsEnvelope — type predicate.
  • parseWsEnvelope(value: unknown): WsEnvelope — throwing parser.

Implementation Notes

  • strict() mode is non-negotiable. Engines that need to allow custom extensions MUST do so by defining their own discriminated union of wsEnvelopeSchema.extend({ ... }) shapes per type, not by relaxing the base schema.
  • payload is z.unknown() rather than z.any() so downstream code is forced to narrow before use.
  • The Zod default-import form (import z from "zod") is the only Bun-safe form per the project policy and is enforced by a repo-wide grep test.