diff --git a/src/common/controllers/example-zod.controller.ts b/src/common/controllers/example-zod.controller.ts new file mode 100644 index 00000000..c8496f7c --- /dev/null +++ b/src/common/controllers/example-zod.controller.ts @@ -0,0 +1,14 @@ +import { Controller, Post, Body } from '@nestjs/common'; +import { ZodValidationPipe } from '../pipes/zod-validation.pipe'; +import { ExampleZodSchema, ExampleZodDto } from '../dto/example-zod.dto'; + +@Controller('example-zod') +export class ExampleZodController { + @Post() + create(@Body(new ZodValidationPipe(ExampleZodSchema)) dto: ExampleZodDto) { + return { + success: true, + data: dto, + }; + } +} diff --git a/src/common/decorators/zod-body.decorator.ts b/src/common/decorators/zod-body.decorator.ts new file mode 100644 index 00000000..50d69d36 --- /dev/null +++ b/src/common/decorators/zod-body.decorator.ts @@ -0,0 +1,11 @@ +import { createParamDecorator, ExecutionContext } from '@nestjs/common'; +import { ZodTypeAny } from 'zod'; +import { ZodValidationPipe } from '../pipes/zod-validation.pipe'; + +export function ZodBody(schema: ZodTypeAny) { + return createParamDecorator((_data: unknown, ctx: ExecutionContext) => { + const request = ctx.switchToHttp().getRequest(); + const pipe = new ZodValidationPipe(schema); + return pipe.transform(request.body, { type: 'body' }); + })(); +} diff --git a/src/common/dto/example-zod.dto.ts b/src/common/dto/example-zod.dto.ts new file mode 100644 index 00000000..cf5f9f60 --- /dev/null +++ b/src/common/dto/example-zod.dto.ts @@ -0,0 +1,9 @@ +import { z } from 'zod'; + +export const ExampleZodSchema = z.object({ + title: z.string().min(1, 'Title is required'), + description: z.string().optional(), + tags: z.array(z.string()).default([]), +}); + +export type ExampleZodDto = z.infer; diff --git a/src/common/pipes/zod-validation.pipe.spec.ts b/src/common/pipes/zod-validation.pipe.spec.ts index 687b588c..2494fdad 100644 --- a/src/common/pipes/zod-validation.pipe.spec.ts +++ b/src/common/pipes/zod-validation.pipe.spec.ts @@ -177,4 +177,4 @@ describe('ZodValidationPipe', () => { expect(details[0].message).toContain('Localized:'); } }); -}); +}); \ No newline at end of file diff --git a/src/common/pipes/zod-validation.pipe.ts b/src/common/pipes/zod-validation.pipe.ts index 2eac8084..20f8e1e1 100644 --- a/src/common/pipes/zod-validation.pipe.ts +++ b/src/common/pipes/zod-validation.pipe.ts @@ -11,7 +11,7 @@ export interface ZodValidationPipeOptions { /** * A pipe that validates and parses an incoming payload against a Zod schema. - * Instantiated per-schema, e.g. `@Body(new ZodValidationPipe(createAgentSchema))`. + * Instantiated per-schema, e.g. `@Body(new ZodValidationPipe(createAgentSchema)) کیا۔ * Rejects unknown/invalid data with a structured VALIDATION_ERROR whose * `details` use the canonical {@link formatZodError} shape, supporting localized error message overrides. */