bun-ws-router
Version:
A simple and efficient WebSocket router for Bun with Zod/Valibot message validation.
84 lines • 2.48 kB
JavaScript
/* SPDX-FileCopyrightText: 2025-present Kriasoft */
/* SPDX-License-Identifier: MIT */
import { z } from "zod";
/**
* Base schema for message metadata.
* Provides common fields that are available on all messages.
* Can be extended for specific message types.
*/
export const MessageMetadataSchema = z.object({
clientId: z.string().optional(), // UUID v7 generated by router automatically
timestamp: z.number().int().positive().optional(),
correlationId: z.string().optional(), // Can be any string for flexibility
});
/**
* Base message schema that all specific message types extend.
* Defines the minimum structure required for routing.
*/
export const MessageSchema = z.object({
type: z.string(),
meta: MessageMetadataSchema,
});
/**
* Standard error codes for WebSocket communication.
* Used in ErrorMessage payloads for consistent error handling.
*/
export const ErrorCode = z.enum([
"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
? MessageMetadataSchema.extend(meta.shape)
: MessageMetadataSchema;
const baseSchema = {
type: z.literal(messageType),
meta: metaSchema,
};
if (payload === undefined) {
return z.object(baseSchema);
}
const payloadSchema = payload instanceof z.ZodType
? payload
: z.object(payload);
return z.object({
...baseSchema,
payload: payloadSchema,
});
}
/**
* Standard error message schema for consistent error responses.
*/
export const ErrorMessage = messageSchema("ERROR", {
code: ErrorCode,
message: z.string().optional(),
context: z.record(z.string(), z.any()).optional(),
});
/**
* Creates a validated WebSocket message from a schema.
*
* @example
* ```typescript
* const EchoSchema = messageSchema("ECHO", { text: z.string() });
* const message = createMessage(EchoSchema, { text: "Hello" });
*
* if (message.success) {
* ws.send(JSON.stringify(message.data));
* }
* ```
*/
export function createMessage(schema, payload, meta) {
const messageData = {
type: schema.shape.type.value,
payload,
meta: meta || {},
};
return schema.safeParse(messageData);
}
//# sourceMappingURL=schema.js.map