UNPKG

bun-ws-router

Version:

A simple and efficient WebSocket router for Bun with Zod/Valibot message validation.

82 lines 2.44 kB
/* SPDX-FileCopyrightText: 2025-present Kriasoft */ /* SPDX-License-Identifier: MIT */ import * as v from "valibot"; /** * Base schema for message metadata. * Provides common fields that are available on all messages. * Can be extended for specific message types. */ export const MessageMetadataSchema = v.object({ clientId: v.optional(v.string()), timestamp: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1))), correlationId: v.optional(v.string()), }); /** * Base message schema that all specific message types extend. * Defines the minimum structure required for routing. */ export const MessageSchema = v.object({ type: v.string(), meta: MessageMetadataSchema, }); /** * Standard error codes for WebSocket communication. * Used in ErrorMessage payloads for consistent error handling. */ export const ErrorCode = v.picklist([ "INVALID_MESSAGE_FORMAT", "VALIDATION_FAILED", "UNSUPPORTED_MESSAGE_TYPE", "AUTHENTICATION_FAILED", "AUTHORIZATION_FAILED", "RESOURCE_NOT_FOUND", "RATE_LIMIT_EXCEEDED", "INTERNAL_SERVER_ERROR", ]); export function messageSchema(messageType, payload, meta) { const metaSchema = meta ? v.object({ ...MessageMetadataSchema.entries, ...meta.entries }) : MessageMetadataSchema; const baseSchema = { type: v.literal(messageType), meta: metaSchema, }; if (payload === undefined) { return v.object(baseSchema); } return v.object({ ...baseSchema, payload, }); } /** * Standard error message schema for consistent error responses. */ export const ErrorMessage = messageSchema("ERROR", v.object({ code: ErrorCode, message: v.optional(v.string()), context: v.optional(v.record(v.string(), v.any())), })); /** * Creates a validated WebSocket message from a schema. * * @example * ```typescript * const EchoSchema = messageSchema("ECHO", v.object({ text: v.string() })); * const message = createMessage(EchoSchema, { text: "Hello" }); * * if (message.success) { * ws.send(JSON.stringify(message.output)); * } * ``` */ export function createMessage(schema, payload, meta) { const messageData = { type: schema.entries.type.literal, payload, meta: meta || {}, }; // eslint-disable-next-line @typescript-eslint/no-explicit-any return v.safeParse(schema, messageData); } //# sourceMappingURL=schema.js.map