# Gestión de dependencias

Este documento define las prácticas recomendadas para gestionar dependencias en proyectos JavaScript/TypeScript en todo el ecosistema de Decentraland. Se aplica a front-end, back-end, SDKs, bibliotecas compartidas y a cualquier paquete basado en npm/yarn/pnpm.

> **Resumen**:
>
> * **Estrategia de versiones** → Usar **versiones exactas/fijas** para `dependencies` (seguridad) y `devDependencies` (entorno de desarrollo consistente). Usar **rangos de versión** solo para `peerDependencies` (flexibilidad).
> * **Excepción** → Los paquetes de Decentraland (`@dcl/*`, `decentraland-*`) pueden usar rangos de versión (`^`) ya que son paquetes internos de confianza.
> * **Bibliotecas/paquetes compartidos** → Usar `peerDependencies` con rangos de versión (^) para bibliotecas compartidas (React, @dcl/schemas, etc.). Usar `dependencies` con versiones exactas solo para utilidades seguras de duplicar.
> * **Apps/servicios finales** → Usar `dependencies` con versiones exactas para paquetes en tiempo de ejecución (React, ethers, etc.).

## 1. Justificación

Muchas bibliotecas dependen de singletons globales, React Context, identidad de clase, cachés compartidos, enums de esquemas o pools de BD compartidos. Instalar múltiples versiones de la misma biblioteca puede provocar:

* Contexto no compartido entre copias
* Cachés o pools duplicados
* Comprobaciones instanceof que fallan
* Desajustes de enums/símbolos
* Aumento del tamaño del bundle
* Errores en tiempo de ejecución difíciles de diagnosticar

La gestión correcta de dependencias previene estos problemas.

### No-objetivos

Este estándar **no** intenta:

* Imponer un único gestor de paquetes (npm, yarn, pnpm están todos soportados)
* Garantizar una sola copia física en `node_modules` (el foco está en la deduplicación en tiempo de ejecución/bundle)

## 2. Definiciones

| Campo                  | Propósito                                                                        | Responsabilidad del consumidor                                 | Aplica a             |
| ---------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------- | -------------------- |
| `dependencies`         | Paquetes usados internamente por el módulo                                       | Ninguna - no se espera que el consumidor los proporcione       | Apps y bibliotecas   |
| `peerDependencies`     | Paquetes que deben resolverse a una sola versión efectiva en tiempo de ejecución | Debe instalarlos (o usar peerDependenciesMeta para opcionales) | **Solo bibliotecas** |
| `peerDependenciesMeta` | Metadatos para peerDependencies, usado para marcar peers como opcionales         | Ninguna - solo afecta el comportamiento del gestor de paquetes | **Solo bibliotecas** |
| `devDependencies`      | Herramientas usadas únicamente durante el desarrollo                             | Ninguna                                                        | Apps y bibliotecas   |

### Acerca de peerDependenciesMeta

`peerDependenciesMeta` es un campo que proporciona metadatos sobre tus `peerDependencies`. El caso de uso más común es marcar peers como **opcionales**:

* **Peers requeridos** (por defecto): El gestor de paquetes advertirá si no están instalados
* **Peers opcionales**: El gestor de paquetes no advertirá si faltan; tu paquete debería manejar su ausencia con gracia

Esto es útil para paquetes que pueden funcionar con o sin ciertas dependencias (por ejemplo, una utilidad que funciona con o sin React, o una biblioteca que soporta múltiples proveedores Web3).

### Apps vs Bibliotecas

**Bibliotecas / Paquetes Compartidos:**

* Usar `peerDependencies` para paquetes que deben resolverse a una sola versión efectiva en tiempo de ejecución (React, ethers, @dcl/schemas)
* El consumidor (app) proporciona estas dependencias
* Previene instalaciones duplicadas y conflictos de singletons

**Apps / Servicios Finales:**

* A menudo usan `dependencies` para paquetes en tiempo de ejecución (React, ethers, etc.)
* Son el consumidor final, por lo que la duplicación no es una preocupación
* `peerDependencies` sigue siendo válido si la app podría ser consumida como dependencia

## 3. Cuándo usar cada campo

> **Referencia rápida**: Ver [Sección 4](#4-examples) para paquetes comunes y su colocación recomendada.

### Usar peerDependencies para (Solo bibliotecas):

**En bibliotecas/paquetes compartidos**, usar `peerDependencies` para paquetes que deben resolverse a una sola versión efectiva en tiempo de ejecución:

* React, Redux, wagmi, ethers, viem
* @dcl/schemas y bibliotecas similares de cruce de ecosistemas
* decentraland/connect
* Drivers de BD cuando se comparten pools
* Cualquier biblioteca que dependa de singletons o context

✅ Correcto (Biblioteca):

```json
{
  "peerDependencies": {
    "react": "^18.0.0",
    "@dcl/schemas": "^20.0.0"
  }
}
```

❌ Incorrecto (Biblioteca usando dependencies para libs compartidas):

```json
{
  "dependencies": {
    "react": "^18.0.0"
  }
}
```

### Usar dependencies para:

* Utilidades seguras de duplicar (lodash-es, date-fns)
* **En apps**: Paquetes en tiempo de ejecución como React, ethers (cuando la app es el consumidor final)

> **Importante**: Siempre usar **versiones exactas/fijas** en `dependencies` para seguridad.

✅ Correcto (Biblioteca):

```json
{
  "dependencies": {
    "lodash-es": "4.17.21",
    "date-fns": "3.6.0"
  }
}
```

✅ Correcto (App):

```json
{
  "dependencies": {
    "react": "18.3.1",
    "ethers": "6.13.0",
    "lodash-es": "4.17.21"
  }
}
```

### peerDependencies opcionales (peerDependenciesMeta)

Para paquetes reusables que funcionan con o sin ciertas dependencias, usar `peerDependenciesMeta` para marcar peers como opcionales:

✅ Correcto:

```json
{
  "peerDependencies": {
    "react": "^18.0.0",
    "ethers": "^6.0.0"
  },
  "peerDependenciesMeta": {
    "ethers": {
      "optional": true
    }
  }
}
```

**Lo que esto significa:**

* `react` es **requerido**: El consumidor debe instalarlo o el gestor de paquetes advertirá
* `ethers` es **opcionales**: El consumidor no necesita instalarlo; tu paquete debería comprobar su presencia antes de usarlo

**Casos de uso:**

* Paquetes que funcionan tanto en entornos con React como sin React
* Bibliotecas que soportan múltiples proveedores Web3 (ethers, viem, etc.)
* Utilidades que mejoran otras bibliotecas pero no son obligatorias

### Usar devDependencies para:

* Herramientas (TypeScript, ESLint, testers, bundlers)

> **Importante**: Siempre usar **versiones exactas/fijas** en `devDependencies` para asegurar un entorno de desarrollo consistente en el equipo.

✅ Correcto:

```json
{
  "devDependencies": {
    "typescript": "5.4.5",
    "eslint": "8.57.0",
    "vitest": "1.6.0"
  }
}
```

## 4. Ejemplos

### Paquetes que DEBEN ser peerDependencies (contexto compartido / singletons)

* `react`, `react-dom`, `react-redux`, `react-router-dom`
* `redux`, `@reduxjs/toolkit`
* `ethers`, `viem`, `wagmi`
* `@dcl/schemas`, `@dcl/ui-env`, `@dcl/crypto`
* `decentraland-dapps`, `decentraland-ui`, `decentraland-ui2`, `decentraland-connect`
* `pg`, `pg-pool`

### Paquetes que DEBERÍAN ser dependencies (seguros de duplicar)

* `lodash-es`, `date-fns`
* `uuid`, `nanoid`
* `zod`, `ajv`
* `ms`, `mitt`, `fp-future`

## 5. Estándares relacionados

* [Estándares de testing](https://docs.decentraland.org/contributor/contributor-es/guias-para-colaboradores/testing-standards)
* [Estándares de UI](https://github.com/decentraland/docs/blob/main/contributor/contributor-guides/ui-standards/README.md)
* [Estándares de Web UI](https://github.com/decentraland/docs/blob/main/contributor/contributor-guides/web-ui-standards/README.md)
* [Arquitectura WKC](https://github.com/decentraland/docs/blob/main/contributor/contributor-guides/well-known-components/README.md)
* [Guías de documentación de API](https://docs.decentraland.org/contributor/contributor-es/guias-para-colaboradores/api-documentation)
