@validex/fastify
v1.0.3
Published
Fastify plugin for validex — request validation via decorators and hooks
Downloads
458
Maintainers
Readme
@validex/fastify
Fastify 5 plugin for validex — request validation via decorators and hooks.
- Prerequisites
- Install
- Plugin Registration — app.register with options
- Request Validation — route-level and handler-level
- Decorators — app.validate, request.validate
- Error Handling — default response, custom handler
Prerequisites
@validex/core, zod, fastify, and fastify-plugin must be installed.
Install
pnpm add @validex/core @validex/fastify zod fastify fastify-pluginPlugin Registration
import Fastify from 'fastify'
import { validexPlugin } from '@validex/fastify'
const app = Fastify()
await app.register(validexPlugin, {
rules: {
email: { blockDisposable: true },
password: { length: { min: 10 } },
},
preload: {
disposable: true,
passwords: 'basic',
},
})Plugin Options
interface ValidexFastifyOptions {
rules?: GlobalConfig['rules'] // Per-rule defaults (same as setup({ rules }))
preload?: PreloadOptions // Data files to preload at registration
errorHandler?: ( // Custom validation error handler
result: ValidationResult<unknown>,
request: FastifyRequest,
reply: FastifyReply,
) => void | Promise<void>
}Request Validation
In-handler validation
Validate request body, query, or params inside route handlers:
import { z } from 'zod'
import { Email } from '@validex/core'
const schema = z.object({ email: Email() })
app.post('/users', async (request) => {
const result = await request.validate(schema)
if (!result.success) {
return { errors: result.firstErrors }
}
return { user: result.data }
})
// Validate query params
app.get('/search', async (request) => {
const result = await request.validate(querySchema, { source: 'query' })
// ...
})
// Validate route params
app.get('/users/:id', async (request) => {
const result = await request.validate(paramsSchema, { source: 'params' })
// ...
})Route-level preValidation
Automatically validate request body before the handler runs:
app.post('/users', {
// Fastify preValidation hook — validates body before handler runs
config: { validex: { body: userSchema } },
handler: async (request) => {
return { created: true }
},
})Failed validation returns a 400 response with structured errors by default:
{
"statusCode": 400,
"error": "Validation Error",
"errors": { "email": "Email is not a valid email address" },
"allErrors": { "email": ["Email is not a valid email address"] }
}errors contains the first error message per field (for simple display). allErrors contains all messages per field (for detailed feedback).
Decorators
The plugin adds the following to the Fastify instance:
| Decorator | Scope | Signature |
|-----------|-------|-----------|
| app.validate | Instance | (schema, data) => Promise<ValidationResult> |
| request.validate | Request | (schema, opts?) => Promise<ValidationResult> |
app.validate validates arbitrary data. request.validate validates from request body (default), query, or params.
Standalone Functions
The decorator implementations are also exported for use outside the request lifecycle (e.g., in tests, workers, or middleware):
import { validateData, validateRequest } from '@validex/fastify'
const result = await validateData(schema, data)| Function | Signature |
|----------|-----------|
| validateData | (schema, data) => Promise<ValidationResult> |
| validateRequest | (schema, sources, source?) => Promise<ValidationResult> |
Error Handling
Override the default 400 response with a custom error handler:
await app.register(validexPlugin, {
errorHandler: (result, request, reply) => {
reply.status(422).send({
message: 'Validation failed',
errors: result.errors,
})
},
})