2.8 KiB
2.8 KiB
event
Purpose
Zod schema validating the SseEvent shape accepted by SseService.broadcast. Ensures application payloads cannot bypass the boundary with malformed ids, negative retry values, or empty event names. Validation failure raises SseError(SSE_INVALID_INPUT) with the ZodError chained as cause so consumers can surface field-level diagnostics to upstream handlers.
Features
idis optional at the boundary — the service generates one via the configuredidGeneratorwhen absent. When supplied it must be a non-empty string.event(the SSEevent:field) optional but non-empty when supplied.dataaccepts any JSON-serialisable value (z.unknown()); the handler is responsible for JSON serialisation on the wire.retryconstrained to positive integers so aretry: 0orretry: -1cannot be sent (both are confusing in browsers).
Usage: Basic
import { SseEventSchema } from "@suaveplan/api-plugin-sse/schemas/event";
const parsed = SseEventSchema.parse({ data: { kind: "ping" } });
// parsed.id is undefined; the service fills it from idGenerator
Usage: Advanced
import { SseEventSchema } from "@suaveplan/api-plugin-sse/schemas/event";
import { SSE_CODES, SseError } from "@suaveplan/api-plugin-sse/error-codes/error-codes";
function safeBroadcast(service: { broadcast: (c: string, e: unknown) => void }, channel: string, raw: unknown) {
const parsed = SseEventSchema.safeParse(raw);
if (!parsed.success) {
throw new SseError(SSE_CODES.INVALID_INPUT, "invalid SSE event", {
cause: parsed.error,
context: { channel, raw },
});
}
service.broadcast(channel, parsed.data);
}
safeBroadcast(service, "notifications", { event: "ping", data: { ts: Date.now() } });
API Reference
SseEventSchema— Zod object schema. Fields:id— optional non-empty string.event— optional non-empty string.data—z.unknown()(any JSON-serialisable value).retry— optional positive integer (milliseconds).
type SseEventInputParsed—z.input<typeof SseEventSchema>(caller-facing).type SseEventResolved—z.output<typeof SseEventSchema>(post-validation).
Implementation Notes
- The schema is intentionally NOT
.strict()because applications may pass through additional metadata as part of the broadcast call (tags,severity, etc.). The service does not propagate unknown fields to the wire — onlyid,event,retry,dataare framed. data: undefinedis rejected —undefinedcannot be JSON-stringified and would silently drop the payload at framing time.- A stricter
dataschema (e.g.z.object({ kind: z.string() })) belongs in application code that composes its own broadcast wrappers. The plugin level is intentionally permissive to support arbitrary payloads.