- Introduced Zod DTOs for request validation across multiple controllers, replacing inline validation with structured classes for improved maintainability and clarity. - Updated ESLint configuration to enforce a rule against importing Zod directly in BFF controllers, promoting the use of shared domain schemas for request validation. - Removed the SecureErrorMapperService to streamline the security module, as its functionality was deemed unnecessary. - Enhanced various controllers to utilize the new DTOs, ensuring consistent validation and response handling across the application.
62 lines
1.8 KiB
Markdown
62 lines
1.8 KiB
Markdown
# BFF Validation Standard (2025): DTOs + Global Pipe (Zod)
|
||
|
||
This repository follows the “big org standard” for NestJS request validation:
|
||
|
||
- **Schemas live in the shared domain layer** (`@customer-portal/domain`)
|
||
- **Controllers use DTOs** built from those schemas
|
||
- **Validation runs globally** via a single app-wide pipe
|
||
|
||
---
|
||
|
||
## Standard Pattern
|
||
|
||
### 1) Define the schema in `@customer-portal/domain`
|
||
|
||
Put request/param/query schemas in the relevant domain module’s `schema.ts`.
|
||
|
||
Example (conceptual):
|
||
|
||
```ts
|
||
// packages/domain/<domain>/schema.ts
|
||
import { z } from "zod";
|
||
|
||
export const exampleRequestSchema = z.object({
|
||
name: z.string().min(1),
|
||
});
|
||
```
|
||
|
||
### 2) Create a DTO in the controller using `createZodDto(schema)`
|
||
|
||
```ts
|
||
import { createZodDto } from "nestjs-zod";
|
||
import { exampleRequestSchema } from "@customer-portal/domain/<domain>";
|
||
|
||
class ExampleRequestDto extends createZodDto(exampleRequestSchema) {}
|
||
```
|
||
|
||
Then use `ExampleRequestDto` in `@Body()`, `@Param()`, or `@Query()`.
|
||
|
||
### 3) Rely on the global `ZodValidationPipe`
|
||
|
||
The BFF registers `ZodValidationPipe` globally via `APP_PIPE` in `apps/bff/src/app.module.ts`.
|
||
|
||
That means controllers should **not** import `zod` or define ad-hoc Zod schemas inline for request validation.
|
||
|
||
---
|
||
|
||
## Boundary Validation (Integrations / Mapping)
|
||
|
||
In addition to request DTO validation, we validate at integration boundaries:
|
||
|
||
- **Provider raw → domain**: validate raw payloads and the mapped domain model using domain schemas.
|
||
- **BFF → Portal**: use the same domain contracts for stable payload shapes where possible.
|
||
|
||
---
|
||
|
||
## Governance / Linting
|
||
|
||
We enforce this pattern via ESLint:
|
||
|
||
- Controllers are expected to import schemas from `@customer-portal/domain`
|
||
- Controllers should not import `zod` directly (to prevent drifting schema definitions into the controller layer)
|