@pingpong-js/plugin-zod
v1.0.1
Published
Zod schema validation plugin for @pingpong-js/fetch with type-safe API responses
Maintainers
Readme
@pingpong-js/plugin-zod
Zod schema validation plugin for @pingpong-js/fetch with type-safe API responses.
Installation
npm install @pingpong-js/plugin-zod
# peer dependencies
npm install @pingpong-js/fetch zodFeatures
- ✅ Response Validation: Validate API responses against Zod schemas
- 🔄 Data Transformation: Parse and transform response data
- 📝 Request Validation: Validate request bodies before sending
- 🎯 URL Pattern Matching: Different schemas for different endpoints
- 🏭 Typed Client Factory: Create fully typed API clients
- ⚠️ Custom Error Handling: Flexible error handling options
Usage
Basic Validation
import pingpong from '@pingpong-js/fetch';
import { withZod } from '@pingpong-js/plugin-zod';
import { z } from 'zod';
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
});
pingpong.onResponse(withZod(UserSchema));
const user = await pingpong.get('/api/users/1');
// Throws ZodValidationError if response doesn't match schema!Data Transformation
import pingpong from '@pingpong-js/fetch';
import { withZodParse } from '@pingpong-js/plugin-zod';
import { z } from 'zod';
const UserSchema = z.object({
id: z.number(),
created_at: z.string().transform(s => new Date(s)), // Transform to Date
name: z.string().transform(s => s.toUpperCase()), // Transform to uppercase
});
pingpong.onResponse(withZodParse(UserSchema));
const user = await pingpong.get('/api/users/1');
console.log(user.data.created_at instanceof Date); // true!
console.log(user.data.name); // "JOHN DOE"Schema Registry
Different schemas for different endpoints:
import pingpong from '@pingpong-js/fetch';
import { withZodRegistry } from '@pingpong-js/plugin-zod';
import { z } from 'zod';
let lastUrl = '';
pingpong.onRequest(req => { lastUrl = req.url; return req; });
const UserSchema = z.object({ id: z.number(), name: z.string() });
const PostSchema = z.object({ id: z.number(), title: z.string() });
pingpong.onResponse(withZodRegistry(
[
[/\/users\/\d+$/, UserSchema],
[/\/posts\/\d+$/, PostSchema],
],
() => lastUrl
));Typed Client Factory
Create fully typed API clients:
import pingpong from '@pingpong-js/fetch';
import { createTypedClient } from '@pingpong-js/plugin-zod';
import { z } from 'zod';
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
});
const userApi = createTypedClient(pingpong, UserSchema);
// Returns validated, typed data directly!
const user = await userApi.get('/api/users/1');
console.log(user.name); // TypeScript knows this is string!Request Body Validation
import pingpong from '@pingpong-js/fetch';
import { withZodRequest } from '@pingpong-js/plugin-zod';
import { z } from 'zod';
const CreateUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
});
pingpong.onRequest(withZodRequest(CreateUserSchema, {
methods: ['POST', 'PUT'],
urlPattern: /\/users/,
}));
// Throws ZodValidationError if body is invalid!
await pingpong.post('/api/users', {
name: '', // Error: name must be at least 1 character
email: 'invalid', // Error: invalid email
});Error Response Validation
import pingpong from '@pingpong-js/fetch';
import { withZodError } from '@pingpong-js/plugin-zod';
import { z } from 'zod';
const ErrorSchema = z.object({
error: z.object({
code: z.string(),
message: z.string(),
}),
});
pingpong.onResponse(withZodError(ErrorSchema));API Reference
withZod(schema, options?)
Validate response data against a Zod schema.
Options:
strict: Throw on validation failure (default:true)onError: Custom error handlerformatError: Custom error message formatterstatusCodes: Only validate specific status codes
withZodParse(schema, options?)
Parse and transform response data. Replaces response.data with parsed value.
withZodError(schema, options?)
Validate error responses (non-2xx status codes).
withZodRegistry(schemas, urlExtractor, options?)
Validate responses based on URL patterns.
createTypedClient(client, schema, options?)
Create a typed API client that returns validated data directly.
withZodRequest(schema, options?)
Validate request bodies before sending.
ZodValidationError
Custom error class with access to the underlying Zod error.
import { ZodValidationError } from '@pingpong-js/plugin-zod';
try {
await pingpong.get('/api/users/1');
} catch (error) {
if (error instanceof ZodValidationError) {
console.log(error.zodError.issues);
}
}License
MIT
