Query and Path Parameters
Query Parameters
Section titled “Query Parameters”Validate URL query parameters using the 'query' source:
import { YelixHono } from '@yelix/hono';import { zValidatorYelix, type ZInfer } from '@yelix/zod-validator';import { z } from 'zod';
const app = new YelixHono();
const querySchema = z.object({ page: z.string().transform(Number).pipe(z.number().int().positive()), limit: z.string().transform(Number).pipe(z.number().int().positive().max(100)), search: z.string().optional(),});
app.get( '/users', zValidatorYelix('query', querySchema), (c) => { // ZInfer provides full type safety const { page, limit, search }: ZInfer<typeof querySchema> = c.req.valid('query' as never); return c.json({ page, limit, search }); });Example request: GET /users?page=1&limit=10&search=john
Path Parameters
Section titled “Path Parameters”Validate URL path parameters using the 'param' source:
import { zValidatorYelix, type ZInfer } from '@yelix/zod-validator';
const paramSchema = z.object({ id: z.string().uuid(),});
app.get( '/users/:id', zValidatorYelix('param', paramSchema), (c) => { // ZInfer provides full type safety const { id }: ZInfer<typeof paramSchema> = c.req.valid('param' as never); return c.json({ userId: id }); });Example request: GET /users/123e4567-e89b-12d3-a456-426614174000
Type Transformations
Section titled “Type Transformations”Query parameters are always strings, so you may need to transform them:
// Transform string to numberz.string().transform(Number).pipe(z.number().int().positive())
// Transform string to booleanz.string().transform((val) => val === 'true')
// Transform string to datez.string().datetime()
// Multiple transformationsz.string() .transform(Number) .pipe(z.number().int().positive().max(100))Combining Query and Path Parameters
Section titled “Combining Query and Path Parameters”You can validate both in the same route:
app.get( '/users/:id/posts', zValidatorYelix('param', z.object({ id: z.string().uuid(), })), zValidatorYelix('query', z.object({ page: z.string().transform(Number).pipe(z.number().int().positive()), limit: z.string().transform(Number).pipe(z.number().int().positive().max(50)), })), (c) => { const { id } = c.req.valid('param' as never); const { page, limit } = c.req.valid('query' as never); return c.json({ userId: id, page, limit }); });Common Patterns
Section titled “Common Patterns”Pagination
Section titled “Pagination”const paginationSchema = z.object({ page: z.string() .default('1') .transform(Number) .pipe(z.number().int().positive()), limit: z.string() .default('10') .transform(Number) .pipe(z.number().int().positive().max(100)),});
app.get('/items', zValidatorYelix('query', paginationSchema), handler);Filtering
Section titled “Filtering”const filterSchema = z.object({ status: z.enum(['active', 'inactive', 'pending']).optional(), category: z.string().optional(), minPrice: z.string() .optional() .transform((val) => val ? Number(val) : undefined) .pipe(z.number().positive().optional()), maxPrice: z.string() .optional() .transform((val) => val ? Number(val) : undefined) .pipe(z.number().positive().optional()),});
app.get('/products', zValidatorYelix('query', filterSchema), handler);Sorting
Section titled “Sorting”const sortSchema = z.object({ sortBy: z.enum(['name', 'price', 'createdAt']).default('createdAt'), order: z.enum(['asc', 'desc']).default('desc'),});
app.get('/products', zValidatorYelix('query', sortSchema), handler);OpenAPI Documentation
Section titled “OpenAPI Documentation”Query and path parameters are automatically documented in your OpenAPI spec:
import { YelixHono, openapi } from '@yelix/hono';import { zValidatorYelix } from '@yelix/zod-validator';import { z } from 'zod';
app.get( '/users/:id', openapi({ summary: 'Get User by ID', }), zValidatorYelix('param', z.object({ id: z.string().uuid(), })), zValidatorYelix('query', z.object({ include: z.enum(['posts', 'comments']).optional(), })), handler);The parameters will automatically appear in your OpenAPI documentation with their types and constraints!