@schafevormfenster/ts-rest-zod-handler
v0.1.6
Published
Framework-neutral TsRest Zod validation handler with reusable helper utilities
Readme
@schafevormfenster/ts-rest-zod-handler
Framework-neutral TsRest Zod validation handler with reusable helper utilities
Purpose
@schafevormfenster/ts-rest-zod-handler is a framework-neutral validation error handler for ts-rest applications. It handles all types of validation errors (JSON parsing, Zod validation, ts-rest request/response validation) and returns consistent error responses while leaving logging responsibilities to client applications.
This package leverages zod-validation-error for user-friendly Zod error message formatting.
Key Features
- ✅ Centralized Error Handler: Single
handleZodErrorfunction handles all validation scenarios - ✅ User-Friendly Messages: Uses
zod-validation-errorfor readable error messages - ✅ Helper Utilities: Reusable functions for custom error workflows (
getSafePayloadExcerpt, etc.) - ✅ Framework-Neutral: No built-in logging - integrate with any logging framework
- ✅ Type-Safe: Returns properly formatted
TsRestResponsewithApiErrorbody
Installation
pnpm add @schafevormfenster/ts-rest-zod-handlerBasic Usage
As Error Handler in createNextHandler
The recommended way to use this package:
import { createNextHandler } from "@ts-rest/next";
import { handleZodError } from "@schafevormfenster/ts-rest-zod-handler";
import { MyContract } from "./my.contract";
const handler = createNextHandler(
MyContract,
{
myEndpoint: async ({ body }) => {
// Your route implementation
const result = await processData(body);
return {
status: 200,
body: {
status: 200,
timestamp: new Date().toISOString(),
data: result,
},
};
},
},
{
jsonQuery: true,
responseValidation: true,
handlerType: "app-router",
errorHandler: handleZodError, // Handles all validation errors
}
);
export { handler as POST };Logging Validation Errors
Intercept the response to log validation errors:
export async function POST(request: Request) {
const response = await handler(request);
// Log validation errors
if (response.status === 400) {
const body = await response.clone().json();
log.error({ error: body.error, method: request.method }, "Validation error");
}
return response;
}Using Helper Functions
import {
getSafePayloadExcerpt,
isResponseValidationError,
} from "@schafevormfenster/ts-rest-zod-handler";
// For advanced Zod error formatting, use zod-validation-error directly:
import { fromZodError } from "zod-validation-error";
import { ZodError } from "zod";
try {
schema.parse(data);
} catch (error) {
if (error instanceof ZodError) {
const validationError = fromZodError(error as never, {
maxIssuesInMessage: 3,
prefix: "Validation error",
});
console.log(validationError.message);
// "Validation error: Expected string, received number at "field.name""
}
}
// Safely truncate payloads for logging
const excerpt = getSafePayloadExcerpt(largePayload); // Truncated to 500 chars
// Check if error is response validation
if (isResponseValidationError(error)) {
log.error({ error }, "Response validation failed");
}Documentation
For detailed usage, integration patterns, and best practices, see:
- INSTRUCTIONS.md - Complete integration guide with DOs/DON'Ts, logging patterns, and examples
- CONTRIBUTING.md - Development guide for contributors
Exported Functions
Main Handler
handleZodError(error: unknown): Promise<TsRestResponse>- Handles all validation errors
Helper Functions
getSafePayloadExcerpt(payload: unknown): string | undefined- Safely truncate payloads (500 chars)isResponseValidationError(error: unknown): boolean- Check if error is response validation
For advanced error message formatting, use zod-validation-error directly.
Error Response Format
All errors return a consistent ApiError format:
{
status: 400 | 500,
error: "Human-readable error message",
trace?: unknown // Error details for debugging
}Status Codes
- 400: Client errors (validation, malformed JSON, bad requests)
- 500: Server errors (response validation, internal errors)
License
See the root LICENSE file for license information.
Built with ❤️ by the Schafe vorm Fenster team
