# Skill: new-endpoint

Add a new API endpoint to an existing module.

TRIGGER: When the user asks to add a new endpoint, route, or API action to an existing module (e.g., "add a deactivate user endpoint", "create an endpoint to bulk import suppliers").

## Instructions

### 1. Read Before Writing

Always read the existing controller, use-cases, drivers, and contract files before making changes. Understand the current patterns and avoid duplicating existing functionality.

### 2. Layer-by-Layer (Bottom Up)

Add code in this order:

**a) Contract** (if new operation is needed)
- Add the method signature to the driver interface in `contracts/<domain>-driver.contract.ts`.
- Type it with the Zod-derived DTO classes from `dto/` — request DTOs (`Create*RequestDto`, `Update*RequestDto`) for input, `*ResponseDto` for the return. Do **not** introduce hand-written `*Data` interfaces; the DTO is the single source of truth.

**b) Driver** (if new DB query is needed)
- Add the method implementation in `drivers/prisma-<domain>.driver.ts`.
- Use Prisma query methods and map the row to the response DTO via the driver's `to<Entity>Response` mapper (timestamps → `.toISOString()`, omit `deletedAt`).

**c) Use-Case** (for business logic)
- Create a new use-case file: `use-cases/<verb>-<entity>.use-case.ts`.
- One class per action with an `execute()` method.
- Inject drivers via DI tokens: `@Inject(<DOMAIN>_DRIVER)`.
- Throw appropriate NestJS exceptions: `NotFoundException`, `ConflictException`, `BadRequestException`, `ForbiddenException`.

**d) DTO** (if endpoint accepts a body or custom query params)
- Create a new DTO file in `dto/` using Zod schema + `createZodDto()`.
- Reuse `PaginationDto` from `src/common/dto/pagination.dto.ts` for paginated list endpoints.
- Follow naming: `<verb>-<entity>.dto.ts` (e.g., `deactivate-user.dto.ts`).
- See `/new-dto` skill for full DTO conventions and Zod reference.

**e) Controller**
- Add the route handler method.
- Inject the new use-case in the constructor.
- Apply decorators in this order: `@Public()` or `@Roles()` or `@Permissions()`, then HTTP method (`@Get`, `@Post`, `@Patch`, `@Delete`), then `@HttpCode` (if not default), then Swagger decorators.
- Always include `@ApiOperation`, `@ApiResponse` for success and error cases.
- Use `@ApiParam` for path parameters.
- Use `ParseUUIDPipe` on all `:id` path parameters: `@Param('id', ParseUUIDPipe) id: string`.

**f) Module**
- Register the new use-case in the module's `providers` array.

### 3. HTTP Method Conventions

| Action | Method | Route | Status |
|--------|--------|-------|--------|
| List | GET | `/` | 200 |
| Get one | GET | `/:id` | 200 |
| Create | POST | `/` | 201 |
| Update | PATCH | `/:id` | 200 |
| Delete | DELETE | `/:id` | 200 |
| Custom action | POST | `/:id/<action>` | 200 |

### 4. Response Handling

All responses are automatically wrapped by `TransformInterceptor` into `{ statusCode, data, timestamp }`. Do NOT manually wrap responses. Just return the data.

### 5. Auth Decorators

- `@Public()` — skip JWT auth entirely (login, register, public endpoints).
- `@Roles(DomainRole.ADMIN)` — require specific role.
- `@Permissions('domain.action')` — require specific permission.
- No decorator = authenticated user (JWT required, any role).

### 6. Verify

```bash
yarn lint         # Fix any linting issues
yarn test         # Ensure nothing is broken
```
