Initial Commit
This commit is contained in:
41
packages/api-stack/api/api-ws/src/envelope/envelope.ts
Normal file
41
packages/api-stack/api/api-ws/src/envelope/envelope.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import z from "zod";
|
||||
|
||||
/**
|
||||
* Wire envelope for every WebSocket frame that flows between the host and a
|
||||
* plugin. Unknown top-level keys are rejected so clients cannot smuggle
|
||||
* fields past the host's validation gate.
|
||||
*
|
||||
* The shape is intentionally minimal:
|
||||
* - `id` correlates request/response/ack frames.
|
||||
* - `type` is the message discriminator (plugin-defined namespace).
|
||||
* - `topic` names the subscription (optional for non-subscription frames).
|
||||
* - `payload` is the opaque body — plugins narrow with their own Zod schema.
|
||||
* - `ts` is an optional ISO-8601 producer timestamp.
|
||||
*/
|
||||
export const wsEnvelopeSchema = z
|
||||
.object({
|
||||
id: z.string().min(1),
|
||||
type: z.string().min(1),
|
||||
topic: z.string().min(1).optional(),
|
||||
payload: z.unknown().optional(),
|
||||
ts: z.string().min(1).optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export type WsEnvelope = z.infer<typeof wsEnvelopeSchema>;
|
||||
|
||||
/**
|
||||
* Type-narrowing helper: returns `true` (and narrows `value` to
|
||||
* `WsEnvelope`) when the candidate parses successfully.
|
||||
*/
|
||||
export function isWsEnvelope(value: unknown): value is WsEnvelope {
|
||||
return wsEnvelopeSchema.safeParse(value).success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strict parser that throws the underlying `ZodError` on failure. Callers
|
||||
* that prefer a typed thrown error should wrap with `WsError`.
|
||||
*/
|
||||
export function parseWsEnvelope(value: unknown): WsEnvelope {
|
||||
return wsEnvelopeSchema.parse(value);
|
||||
}
|
||||
Reference in New Issue
Block a user