# IMPACTO DE CAMBIOS EN API

**Version:** 1.0.0
**Fecha:** 2025-12-08
**Prioridad:** OBLIGATORIA - Consultar antes de modificar endpoints
**Sistema:** SIMCO + CAPVED

---

## PROPOSITO

Documentar el impacto de modificar endpoints REST (Controllers), rutas, metodos HTTP, y contratos de API en el sistema.

---

## 1. CLASIFICACION DE CAMBIOS API

```
╔══════════════════════════════════════════════════════════════════════╗
║  TIPOS DE CAMBIOS EN API                                             ║
╠══════════════════════════════════════════════════════════════════════╣
║                                                                       ║
║  BREAKING CHANGES (⚠️ ROMPEN CLIENTES):                              ║
║  • Eliminar endpoint                                                  ║
║  • Cambiar ruta de endpoint                                          ║
║  • Cambiar metodo HTTP                                               ║
║  • Eliminar campo de response                                        ║
║  • Cambiar tipo de campo en response                                 ║
║  • Agregar campo requerido a request                                 ║
║  • Cambiar formato de error                                          ║
║                                                                       ║
║  NON-BREAKING CHANGES (✅ COMPATIBLES):                              ║
║  • Agregar endpoint nuevo                                            ║
║  • Agregar campo opcional a request                                  ║
║  • Agregar campo a response                                          ║
║  • Agregar nuevo codigo de error                                     ║
║  • Mejorar mensaje de error                                          ║
║                                                                       ║
╚══════════════════════════════════════════════════════════════════════╝
```

---

## 2. CAMBIOS EN RUTAS (BREAKING)

### 2.1 Cambiar Ruta de Endpoint

```typescript
// ANTES
@Get('users/by-email/:email')

// DESPUES
@Get('users/search/email/:email')
```

**Impacto:**

| Componente | Impacto | Accion Requerida |
|------------|---------|------------------|
| Frontend Service | ROMPE | Actualizar URL |
| Frontend Hooks | ROMPE | Actualizar llamadas |
| Documentacion | Desactualizada | Actualizar |
| Clientes externos | ROMPE | Notificar + migrar |
| Tests e2e | ROMPE | Actualizar URLs |

**Proceso de Migracion:**

```
OPCION A: Migracion Inmediata (proyectos internos)
═══════════════════════════════════════════════════════════════
1. Actualizar Frontend primero (cambiar URL)
2. Actualizar Backend (cambiar ruta)
3. Deploy coordinado

OPCION B: Deprecacion Gradual (APIs publicas)
═══════════════════════════════════════════════════════════════
1. Agregar nueva ruta (mantener vieja)
2. Marcar vieja como @Deprecated
3. Notificar clientes
4. Periodo de gracia (30-90 dias)
5. Eliminar ruta vieja
```

**Implementacion Deprecacion:**

```typescript
// Mantener ambas rutas temporalmente
@Get('users/by-email/:email')
@ApiOperation({
    summary: 'Buscar por email (DEPRECATED)',
    deprecated: true,
    description: 'Use GET /users/search/email/:email instead'
})
async findByEmailDeprecated(@Param('email') email: string) {
    return this.findByEmail(email);
}

@Get('users/search/email/:email')
@ApiOperation({ summary: 'Buscar usuario por email' })
async findByEmail(@Param('email') email: string) {
    return this.userService.findByEmail(email);
}
```

### 2.2 Cambiar Prefijo de Controller

```typescript
// ANTES
@Controller('products')

// DESPUES
@Controller('catalog/products')
```

**Impacto:** TODOS los endpoints del controller cambian de ruta.

```
ANTES:
GET  /api/products
POST /api/products
GET  /api/products/:id

DESPUES:
GET  /api/catalog/products
POST /api/catalog/products
GET  /api/catalog/products/:id
```

**Checklist:**

```
[ ] 1. Buscar en frontend: grep -rn "/products" apps/
[ ] 2. Actualizar TODOS los services que usan estos endpoints
[ ] 3. Actualizar tests e2e
[ ] 4. Actualizar documentacion
[ ] 5. Verificar Swagger refleja cambios
```

---

## 3. CAMBIOS EN METODO HTTP (BREAKING)

### Cambiar Metodo

```typescript
// ANTES: Actualizar con POST
@Post(':id/update')
async update() {}

// DESPUES: Actualizar con PUT (RESTful correcto)
@Put(':id')
async update() {}
```

**Impacto Frontend:**

```typescript
// ANTES
const response = await api.post(`/users/${id}/update`, data);

// DESPUES
const response = await api.put(`/users/${id}`, data);
```

**Checklist:**

```
[ ] 1. Identificar todos los lugares que llaman al endpoint
[ ] 2. Actualizar metodo HTTP en frontend service
[ ] 3. Actualizar tests
[ ] 4. Si API publica: periodo de deprecacion
```

---

## 4. CAMBIOS EN REQUEST DTO

### 4.1 Agregar Campo Requerido (BREAKING)

```typescript
// ANTES
export class CreateOrderDto {
    productId: string;
    quantity: number;
}

// DESPUES - Nuevo campo requerido
export class CreateOrderDto {
    productId: string;
    quantity: number;
    @IsNotEmpty()
    deliveryAddress: string;  // ← BREAKING: requerido
}
```

**Impacto:**

| Componente | Impacto | Accion |
|------------|---------|--------|
| Frontend Form | ROMPE | Agregar campo |
| Frontend Zod | ROMPE | Agregar validacion |
| Clientes existentes | ROMPE | Falla validacion |
| Tests | ROMPE | Actualizar fixtures |

**Mitigacion:**

```typescript
// OPCION 1: Hacer opcional con default
@IsOptional()
@IsString()
deliveryAddress?: string = 'Por definir';

// OPCION 2: Migrar en fases
// Fase 1: Agregar como opcional
// Fase 2: Poblar datos existentes
// Fase 3: Hacer requerido
```

### 4.2 Agregar Campo Opcional (NON-BREAKING)

```typescript
// Agregar campo opcional - NO rompe
export class CreateOrderDto {
    productId: string;
    quantity: number;

    @IsOptional()
    @IsString()
    notes?: string;  // ← NON-BREAKING: opcional
}
```

**Impacto:**

| Componente | Impacto | Accion |
|------------|---------|--------|
| Frontend | Ninguno inmediato | Agregar si se quiere usar |
| Clientes existentes | Ninguno | Siguen funcionando |
| Tests | Ninguno | Siguen pasando |

### 4.3 Eliminar Campo de Request (BREAKING si requerido)

```typescript
// ANTES
export class CreateUserDto {
    email: string;
    password: string;
    legacyCode: string;  // ← Se va a eliminar
}

// DESPUES
export class CreateUserDto {
    email: string;
    password: string;
    // legacyCode eliminado
}
```

**Proceso:**

```
1. Hacer campo opcional primero (si era requerido)
2. Marcar como @Deprecated en Swagger
3. Ignorar en backend (no procesar)
4. Notificar clientes
5. Eliminar despues de periodo de gracia
```

### 4.4 Cambiar Validacion (Puede ser BREAKING)

```typescript
// ANTES: email cualquier formato
@IsString()
email: string;

// DESPUES: email debe ser valido
@IsEmail()
email: string;
```

**Impacto:** Requests que antes pasaban ahora fallan.

**Mitigacion:**

```typescript
// Agregar transformacion para casos edge
@IsEmail()
@Transform(({ value }) => value?.toLowerCase().trim())
email: string;
```

---

## 5. CAMBIOS EN RESPONSE DTO

### 5.1 Eliminar Campo de Response (BREAKING)

```typescript
// ANTES
export class UserResponseDto {
    id: string;
    email: string;
    legacyCode: string;  // ← Se elimina
}

// DESPUES
export class UserResponseDto {
    id: string;
    email: string;
    // legacyCode eliminado
}
```

**Impacto Frontend:**

```typescript
// Si frontend usa el campo, ROMPE
const UserCard = ({ user }) => {
    return <div>{user.legacyCode}</div>;  // ← TypeError: undefined
};
```

**Proceso Seguro:**

```
1. Buscar uso en frontend: grep -rn "legacyCode" apps/
2. Eliminar uso en frontend primero
3. Luego eliminar de ResponseDto
4. Deploy coordinado
```

### 5.2 Agregar Campo a Response (NON-BREAKING)

```typescript
// Agregar campo - NO rompe
export class UserResponseDto {
    id: string;
    email: string;
    createdAt: Date;  // ← Nuevo campo
}
```

**Impacto:**

- Frontend puede ignorar campos nuevos
- TypeScript mostrara warning si interface no coincide
- Actualizar interface en frontend eventualmente

### 5.3 Cambiar Tipo de Campo (BREAKING)

```typescript
// ANTES
export class ProductResponseDto {
    price: number;  // 99
}

// DESPUES
export class ProductResponseDto {
    price: string;  // "99.00"
}
```

**Impacto Frontend:**

```typescript
// ANTES funcionaba
const total = product.price * quantity;

// DESPUES rompe (string * number = NaN)
const total = product.price * quantity;  // NaN!

// Debe cambiar a
const total = parseFloat(product.price) * quantity;
```

### 5.4 Cambiar Estructura de Response (BREAKING)

```typescript
// ANTES: Array directo
@Get()
async findAll(): Promise<UserResponseDto[]> {
    return this.users;
}
// Response: [{ id: 1 }, { id: 2 }]

// DESPUES: Objeto paginado
@Get()
async findAll(): Promise<PaginatedResponse<UserResponseDto>> {
    return { data: this.users, total: 100, page: 1 };
}
// Response: { data: [...], total: 100, page: 1 }
```

**Impacto Frontend:**

```typescript
// ANTES
const users = await api.get('/users');
users.map(u => ...);

// DESPUES
const response = await api.get('/users');
response.data.map(u => ...);  // Acceder a .data
```

---

## 6. CAMBIOS EN CODIGOS DE ERROR

### 6.1 Agregar Nuevo Codigo (NON-BREAKING)

```typescript
// Agregar nueva excepcion - generalmente no rompe
throw new ConflictException('Email already registered');
// HTTP 409 - nuevo codigo
```

**Impacto:** Frontend deberia manejar, pero no rompe si no lo hace.

### 6.2 Cambiar Codigo Existente (BREAKING)

```typescript
// ANTES: 400 para duplicado
throw new BadRequestException('Email exists');

// DESPUES: 409 para duplicado (correcto)
throw new ConflictException('Email exists');
```

**Impacto:** Frontend que verifica status code especifico rompe.

```typescript
// Frontend que rompe
if (error.status === 400 && error.message.includes('Email')) {
    // Ya no entra aqui
}

// Frontend robusto
if (error.status === 409 || error.message.includes('Email')) {
    // Maneja ambos casos
}
```

### 6.3 Cambiar Formato de Error (BREAKING)

```typescript
// ANTES
{
    "statusCode": 400,
    "message": "Validation failed"
}

// DESPUES
{
    "error": {
        "code": "VALIDATION_ERROR",
        "message": "Validation failed",
        "details": [...]
    }
}
```

**Impacto:** TODO el manejo de errores en frontend debe cambiar.

---

## 7. VERSIONADO DE API

### Cuando Usar Versionado

```
USA VERSIONADO CUANDO:
• API es consumida por clientes externos
• Cambios breaking frecuentes
• Necesitas mantener compatibilidad largo plazo

NO NECESITAS VERSIONADO CUANDO:
• Solo frontend interno consume la API
• Puedes coordinar deploys
• Equipo pequeno con comunicacion directa
```

### Implementacion de Versiones

```typescript
// Opcion 1: En URL
@Controller('v1/users')
export class UsersV1Controller {}

@Controller('v2/users')
export class UsersV2Controller {}

// Opcion 2: En Header
@Controller('users')
@ApiHeader({ name: 'Api-Version', enum: ['1', '2'] })
export class UsersController {
    @Get()
    findAll(@Headers('Api-Version') version: string) {
        if (version === '2') {
            return this.findAllV2();
        }
        return this.findAllV1();
    }
}
```

---

## 8. CHECKLIST POR TIPO DE CAMBIO

### Agregar Endpoint Nuevo

```
[ ] 1. Crear metodo en Controller
[ ] 2. Agregar decoradores Swagger (@ApiOperation, @ApiResponse)
[ ] 3. Crear/actualizar DTOs si necesario
[ ] 4. Implementar en Service
[ ] 5. Agregar tests
[ ] 6. Actualizar Frontend service
[ ] 7. Crear Frontend hook si necesario
[ ] 8. Verificar Swagger
```

### Modificar Endpoint Existente (NON-BREAKING)

```
[ ] 1. Verificar que cambio es non-breaking
[ ] 2. Actualizar Controller
[ ] 3. Actualizar DTOs si necesario
[ ] 4. Actualizar Swagger decoradores
[ ] 5. Actualizar tests
[ ] 6. Actualizar Frontend si aprovecha nuevas features
```

### Modificar Endpoint Existente (BREAKING)

```
[ ] 1. Evaluar: ¿se puede hacer non-breaking?
[ ] 2. Buscar todos los consumidores: grep -rn "endpoint" apps/
[ ] 3. Planear estrategia de migracion
[ ] 4. Si API publica: crear version nueva, deprecar vieja
[ ] 5. Si API interna: coordinar con frontend
[ ] 6. Actualizar Frontend PRIMERO (apuntar a nuevo)
[ ] 7. Actualizar Backend
[ ] 8. Actualizar tests
[ ] 9. Deploy coordinado
[ ] 10. Eliminar codigo deprecated despues de periodo
```

### Eliminar Endpoint

```
[ ] 1. Buscar todos los usos: grep -rn "endpoint" apps/ tests/
[ ] 2. Eliminar uso en Frontend
[ ] 3. Eliminar tests del endpoint
[ ] 4. Marcar como @Deprecated (si API publica)
[ ] 5. Periodo de gracia
[ ] 6. Eliminar de Controller
[ ] 7. Limpiar Service si metodos quedan sin usar
```

---

## 9. FRONTEND: ADAPTARSE A CAMBIOS API

### Service Layer Pattern

```typescript
// Encapsular llamadas API en service
// Facilita cambiar cuando API cambia

// user.service.ts
export const userService = {
    // Si cambia la ruta, solo cambiar aqui
    getAll: () => api.get<User[]>('/users'),

    // Si cambia estructura response
    getAllPaginated: async (page: number) => {
        const response = await api.get<PaginatedResponse<User>>('/users', { params: { page } });
        return response.data;  // Extraer data aqui
    },

    // Si cambia metodo HTTP
    update: (id: string, data: UpdateUserDto) =>
        api.put<User>(`/users/${id}`, data),  // Cambiar post→put aqui
};
```

### Type Guards para Cambios de Estructura

```typescript
// Manejar diferentes versiones de response
interface UserV1 {
    name: string;
}

interface UserV2 {
    firstName: string;
    lastName: string;
}

function isUserV2(user: UserV1 | UserV2): user is UserV2 {
    return 'firstName' in user;
}

function getDisplayName(user: UserV1 | UserV2): string {
    if (isUserV2(user)) {
        return `${user.firstName} ${user.lastName}`;
    }
    return user.name;
}
```

---

## 10. MATRIZ DE DECISION

```
¿Es BREAKING CHANGE?
        │
        ▼
   ┌────────────┐
   │ ¿Cambio de │───NO───▶ Implementar directamente
   │   ruta?    │          Actualizar Swagger
   └────────────┘          Actualizar Frontend (opcional)
        │
       YES
        │
        ▼
   ┌────────────┐
   │ ¿API       │───NO───▶ Actualizar Frontend PRIMERO
   │ publica?   │          Luego actualizar Backend
   └────────────┘          Deploy coordinado
        │
       YES
        │
        ▼
   ┌────────────────────────────────────────┐
   │ 1. Crear endpoint nuevo               │
   │ 2. Deprecar endpoint viejo            │
   │ 3. Notificar clientes                 │
   │ 4. Periodo de gracia (30-90 dias)     │
   │ 5. Eliminar endpoint viejo            │
   └────────────────────────────────────────┘
```

---

## 11. COMANDOS UTILES

```bash
# Ver todos los endpoints actuales
curl http://localhost:3000/api-json | jq '.paths | keys'

# Ver detalle de un endpoint
curl http://localhost:3000/api-json | jq '.paths["/users/{id}"]'

# Buscar uso de endpoint en frontend
grep -rn "users" apps/*/services/
grep -rn "/api/users" apps/

# Comparar Swagger entre versiones
diff <(curl -s http://localhost:3000/api-json | jq -S) \
     <(curl -s http://production/api-json | jq -S)
```

---

**Version:** 1.0.0 | **Sistema:** SIMCO | **Tipo:** Guia de Impacto
