# Guía de estilo — DTOs y organización de carpetas > **Objetivo:** asegurar que **todos** los equipos usen un vocabulario y una estructura de ficheros idéntica al modelar, versionar y serializar los *Data Transfer Objects* (DTO). > Esta guía aplica a cualquier API HTTP/JSON implementada en Express + TypeScript que siga DDD, SOLID y CQRS. --- ## 1. Estructura de carpetas obligatoria ```text src/ └─ / (ej. billing/) └─ api/ └─ dto/ ├─ common/ ← Tipos reutilizables (MoneyDTO, AddressDTO…) ├─ request/ ← Sólo comandos y queries │ ├─ *.command.dto.ts │ └─ *.query.dto.ts │ └─ response/ ← Sólo resultados/vistas ├─ *.result.dto.ts └─ *.view.dto.ts ``` *Alias TS recomendado*: `@/dto/*` → `src//api/dto/*`. --- ## 2. Convención de nombres | Categoría | Sufijo **obligatorio** | Descripción & ejemplos | |-----------|------------------------|------------------------| | **Comandos** (mutaciones) | `…CommandDTO` | `CreateInvoiceCommandDTO`, `UpdateInvoiceCommandDTO`, `DeleteInvoiceCommandDTO`, `ChangeInvoiceStatusCommandDTO` | | **Queries** (lecturas con filtros) | `…QueryDTO` | `ListInvoicesQueryDTO`, `GetInvoiceByIdQueryDTO` | | **Resultados** (respuesta de comandos) | `…ResultDTO` | `InvoiceCreationResultDTO`, `InvoiceDeletionResultDTO` | | **Vistas** (respuesta de queries) | `…ViewDTO` | `InvoiceViewDTO`, `InvoiceSummaryViewDTO` | | **Tipos comunes** | `…DTO` | `MoneyDTO`, `PaginationMetaDTO`, `AddressDTO` | *Regla de oro:* **No existe ningún DTO sin sufijo, salvo los tipos comunes dentro de `common/`.** --- ## 3. Reglas de contenido 1. **Solo datos planos**: números, cadenas, literales, arrays; nada de lógica. 2. **Fechas** en ISO-8601 UTC (`yyyy-MM-dd'T'HH:mm:ss.SSS'Z'`). 3. **Enums** expuestos como _string literal_ en `snake_case` o `UPPER_SNAKE_CASE`; evita números mágicos. 4. **Moneda** - **Siempre** con la estructura común: ```ts export interface MoneyDTO { amount: number | null; // unidades mínimas (ej. céntimos) scale: number; // nº de decimales (2 = céntimos) currency_code: string; // ISO-4217 (“EUR”) } ``` - Se importa desde `dto/common/money.dto.ts`. --- ## 4. Guía de mapeo | Dirección | Componente responsable | Ubicación | |-----------|------------------------|-----------| | **DTO → Dominio** | `…CommandMapper` / `…QueryMapper` | `src//application/mappers/` | | **Dominio → DTO** | `…ResultMapper` / `…ViewMapper` | mismo directorio | Cada mapper implementa **una** función pública: ```ts interface InvoiceCreationResultMapper { toResult(entity: Invoice): InvoiceCreationResultDTO; } ``` --- ## 5. Validación y versiones 1. **Validación de entrada** - Usa `class-validator` o Zod en el *controller*; nunca en el dominio. - Convierte a Value Objects una vez que el DTO pasó la validación. 2. **Versionado** - Añade sufijos de versión en el **archivo**, no en el nombre de la interfaz: `invoice.view.v2.dto.ts` → `export interface InvoiceViewV2DTO { … }` - Mantén las versiones anteriores durante **≥1 release** o hasta que los consumidores migren. --- ## 6. Ejemplo completo (creación de factura) ```text billing/ ├─ api/ │ └─ dto/ │ ├─ input/create-invoice.command.dto.ts │ ├─ output/invoice-creation.result.dto.ts │ └─ common/money.dto.ts └─ application/ └─ mappers/ └─ invoice-creation.result.mapper.ts ``` ```ts // create-invoice.command.dto.ts export interface CreateInvoiceCommandDTO { customerId: string; issueDate: string; lines: ReadonlyArray<{ description: string; quantity: number; unitPrice: MoneyDTO; }>; } // invoice-creation.result.dto.ts export interface InvoiceCreationResultDTO { invoiceId: string; number: string; totalAmount: MoneyDTO; createdAt: string; } ``` --- ## 7. Checklist antes de hacer *merge* - [ ] Archivo ubicado en la carpeta correcta. - [ ] Sufijo conforme (**CommandDTO**, **QueryDTO**, **ResultDTO**, **ViewDTO**). - [ ] Todos los importes usan `MoneyDTO`. - [ ] Tipos opcionales marcados con `?` y comentados. - [ ] **Sin** lógica, constructores ni métodos. - [ ] PR incluye al menos un test de mapper (input ⇄ dominio ⇄ output). --- ## 8. Tabla resumen | Carpeta | Sufijo | Ejemplo clásico | |---------|--------|-----------------| | `dto/input/` | `CommandDTO` | `DeleteInvoiceCommandDTO` | | `dto/input/` | `QueryDTO` | `ListInvoicesQueryDTO` | | `dto/output/` | `ResultDTO` | `InvoiceDeletionResultDTO` | | `dto/output/` | `ViewDTO` | `InvoiceSummaryViewDTO` | | `dto/common/` | `DTO` | `MoneyDTO` |