← Volver al blog
5 min de lecturaArquitectura

Cómo escribir una librería organizacional/de código abierto (opinión) | Parte 2 — Versionado, changelog y pruebas

SemVer, changelogs, disciplina de releases y una estrategia de tests que protege el contrato de tu librería—continuación del ejemplo Slothy de la Parte 1.

Esta es la Parte 2 de la serie. Si aún no la has leído, empieza por la Parte 1 — Especificación: flujo README primero, contratos MVP y paquetes por capas (@slothy/core, @slothy/angular).

Aquí nos centramos en lo que mantiene ese contrato honesto en el tiempo: versionado, disciplina de changelog y pruebas.


Versionado — SemVer con intención

El versionado semántico (MAJOR.MINOR.PATCH) es una herramienta de comunicación. Un número nuevo cuenta una historia:

Salto Significado habitual
MAJOR Cambio incompatible en la API pública soportada (o en el comportamiento del que la gente dependía).
MINOR Novedades compatibles hacia atrás (nueva opción de config, nuevo export).
PATCH Correcciones de bugs que respetan el contrato documentado.

¿Qué cuenta como “romper”?

Sé más estricto que “el build sigue pasando”. Rompe, entre otras cosas:

  • Renombrar o quitar símbolos exportados.
  • Endurecer tipos de forma que rechace entradas antes válidas.
  • Cambiar el comportamiento por defecto cuando el anterior era observable aunque no estuviera bien documentado—porque la gente igual dependerá de él.

Si debes cambiar un comportamiento del que dependen los usuarios, o documentas el antiguo como no soportado en un MINOR con deprecación, o sacas un MAJOR con guía de migración.

La era 0.x

Mientras la API aún cambia, 0.y.z indica inestabilidad: un MINOR puede incluir rupturas hasta que te comprometas con 1.0.0. Después de 1.0.0, trata los MAJOR como un acontecimiento: guía de migración, codemods si aplica, y relato claro en el changelog.

Alinear varios paquetes (@slothy/*)

Si tienes un monorepo con @slothy/core y @slothy/angular:

  • Opción A — versiones independientes: cada paquete tiene su propio semver. Documenta qué versiones del adaptador van con qué rango de core (peer dependency + notas de release).
  • Opción B — lockstep: un mismo número para todos los paquetes (más simple para quien consume, más pesado para quien mantiene).

Elige una estrategia y documéntala en el README raíz. Evita el “desfase silencioso” de peers.


Changelog — una sola fuente de verdad

Los logs automáticos de git son ruidosos. Un changelog redactado (véase Keep a Changelog) ayuda a responder: ¿me conviene actualizar hoy?

Secciones recomendadas:

  • Added — APIs o funcionalidades nuevas.
  • Changed — Cambios de comportamiento que no rompen contrato.
  • Deprecated — Qué se eliminará y cuándo.
  • Removed — Lo que realmente desaparece en este release.
  • Fixed — Corrección de bugs.
  • Security — Avisos de seguridad.

Conectar cambios con la API pública

En lugar de “refactor interno,” prefiero:

Fixed: createSlothyClient ya no lanza cuando storage es indexed_db y el almacén está vacío (issue #42).

Así la nota habla de lo que hace el usuario, no de cómo reorganizaste carpetas.

Guías de migración en MAJOR

Para cada MAJOR, añade MIGRATION.md (o una sección en el changelog) con:

  1. Fragmentos antes / después.
  2. Por qué el cambio (un párrafo).
  3. Pasos mecánicos (búsqueda y reemplazo, exports renombrados).

Releases — ritmo predecible

Tanto si publicas en npm (público o privado) como en un registro interno:

  1. Etiqueta en git (v2.0.0) alineada con la versión publicada.
  2. CI en el tag: tests, build, opcionalmente tamaño de bundle.
  3. Publicación desde un árbol limpio (muchos equipos solo publican desde CI).

En organizaciones, define quién puede publicar y desde qué rama (p. ej. solo main).

Deprecaciones

Usa JSDoc @deprecated en TypeScript, console.warn en runtime (con mesura) y entradas en el changelog con fecha o versión de retirada (“se elimina en v3”).


Pruebas — protege el contrato, no las carpetas

1. La API pública primero

Los tests deben importar @slothy/core igual que quien consume (desde el entry compilado, no desde rutas profundas de src/lib/domain/... salvo que esas rutas estén soportadas oficialmente).

// slothy-core.public-api.spec.ts
import { createSlothyClient } from '@slothy/core';

it('crea un cliente con almacenamiento in_memory', async () => {
  const client = await createSlothyClient({ storage: 'in_memory', debug: false });
  expect(client).toBeDefined();
});

Si un refactor interno rompe solo tests internos, te has alejado demasiado de la superficie soportada.

2. Tests de contrato para adaptadores

En @slothy/angular, comprueba que forRoot expone un cliente coherente con core:

  • Las mismas operaciones sobre tareas tienen el mismo éxito o error con la misma config.
  • Los tokens resuelven sin instancias duplicadas de SlothyClient en escenarios típicos.

3. Evita testear detalles de implementación

No asserts sobre nombres de métodos privados o grafos de módulos internos salvo que formen parte de tu promesa de estabilidad.

4. Matriz solo donde importa

Mínimo razonable:

  • Unitarias para lógica de dominio pura.
  • Integración para backends de almacenamiento (in_memory vs indexed_db en entorno headless cuando sea viable).

Para adaptadores Angular, smoke tests con TestBed que compilen los imports y registren forRoot.


CI como barrera

Una base práctica:

Comprobación Para qué
Lint + formato Coherencia de exports y documentación.
tsc --noEmit / build Tipos rotos antes de publicar.
Tests Lo anterior.
Empaquetado en seco Que files / exports del package.json incluyan lo que crees.

Opcional pero útil: límites de tamaño de bundle en @slothy/core para detectar dependencias pesadas accidentales.


Cómo encaja la Parte 2 con la Parte 1

Parte 1 Parte 2
README como contrato El changelog explica cómo evoluciona ese contrato
Límites MVP SemVer codifica qué es una “subida segura”
Paquetes por capas Alineación de versiones + tests de adaptadores

¿Siguiente paso?

Sigue con la Parte 3 — Contribuidores y documentación: CONTRIBUTING.md, plantillas de issues, RFCs y documentación de API (TSDoc / referencia generada).


Etiquetas: código abierto, librería, TypeScript, Angular, semver, testing