-
Notifications
You must be signed in to change notification settings - Fork 0
Arquitectura
palta es deliberadamente aburrida: un directorio por país, un archivo por módulo, contratos compartidos y nada más. Esa simpleza es lo que permite tener 23 países sin que el mantenimiento explote.
.
├── src/
│ ├── [pais]/ # un directorio por país
│ │ ├── index.ts # re-exporta los submódulos
│ │ ├── [documento].ts
│ │ ├── currency.ts
│ │ ├── phone.ts
│ │ └── zipcode.ts
│ ├── measurements/
│ │ ├── index.ts
│ │ ├── length.ts
│ │ ├── weight.ts
│ │ └── volume.ts
│ ├── detect.ts
│ ├── index.ts # exporta los 23 namespaces, detect y measurements
│ ├── types.ts # contratos compartidos
│ └── utils.ts
├── tests/ # espejo de src/, un archivo por módulo
├── demo/index.html
├── tsup.config.ts
├── vitest.config.ts
└── package.json
tests/ es un espejo exacto de src/. Si agregás src/xx/ruc.ts, el test va en
tests/xx/ruc.test.ts.
Todo vive en src/types.ts. Son seis interfaces y tres uniones de tipos, y no se agregan
más:
| interfaz | implementada por |
|---|---|
DocumentModule |
todos los documentos de todos los países |
CurrencyModule |
currency de cada país |
PhoneModule |
phone de cada país |
ZipcodeModule |
zipcode de cada país |
MeasurementModule<U> |
length, weight, volume
|
La sexta es DetectResult, que nadie implementa: es lo que devuelve detect().
Un módulo nuevo implementa uno de estos. No se inventan contratos: si algo no encaja, la conversación es sobre el contrato, no sobre una excepción local.
Los contratos completos están en Referencia de API.
src/utils.ts tiene cuatro funciones y ninguna es casual:
| función | por qué existe |
|---|---|
onlyDigits(v) |
normalizar entradas antes de validar |
onlyDigitsAndK(v) |
el RUT chileno admite K como verificador |
padLeft(v, len, char) |
documentos que se guardan sin ceros a la izquierda |
safeStr(v) |
convertir null, undefined y no-strings a ''
|
safeStr es la pieza que hace cumplir la regla defensiva sin repetir guardas en 60 archivos.
Todo módulo empieza pasando su entrada por ahí.
src/index.ts re-exporta los 23 países como namespaces, más detect y measurements:
export * as br from './br/index.js'
export * as cl from './cl/index.js'
// ...
export * as do_ from './do/index.js'
export { detect } from './detect.js'
export * as measurements from './measurements/index.js'do_ lleva guion bajo porque do es palabra reservada de JavaScript. El subpath de
package.json no lo lleva: sigue siendo "./do".
Los imports internos usan extensión .js aunque los archivos sean .ts. Es lo que exige el
resolver de ESM de Node.
tsup genera ESM, CJS y declaraciones de tipos, con un entry por país más la raíz y
measurements.
npm run buildCada entry de tsup.config.ts tiene su contraparte en exports de package.json. Si agregás
uno y olvidás el otro, el subpath no resuelve. Ese es el error más común al sumar un país, y
por eso Agregar un país lista los cinco pasos en orden.
Los tests importan directo de src/, no del paquete construido. Corren sin haber hecho
build, lo que hace el ciclo de desarrollo mucho más corto.
npm test
npm run test:coverage # umbrales por métrica, definidos en vitest.config.tsLos umbrales están configurados en vitest.config.ts y los aplica la CI: 94% en líneas y
statements, 98% en funciones y 90% en ramas.
| comando | qué verifica |
|---|---|
npm run lint |
tsc --noEmit — es la única puerta estática, no hay ESLint |
npm run test:coverage |
tests más los umbrales de cobertura |
npm run build |
que tsup genere ESM, CJS y tipos sin errores |
La CI (.github/workflows/ci.yml) corre los tres en cada push y cada PR contra main, en
Node 22, y sube el reporte de cobertura como artefacto.
Ver también: Algoritmos, Contribuir.
Empezar
Referencia
Colaborar
Enlaces