Contribuir
Las contribuciones son bienvenidas. dte-sdk arma documentos tributarios con valor legal y maneja llaves de firma, así que la corrección, las pruebas y la disciplina con los datos importan más que la velocidad. Esta página te lleva desde un clon hasta un pull request.
El repositorio#
- Código e issues: github.com/arrowsw/dte-sdk.
- Rama: el trabajo ocurre en
canary. Abre los pull requests contra ella. Fusionar encanarynunca publica nada. - Estado: la versión más reciente en npm es la
0.8.0, ycanarytiene lo que viene; la1.0.0será la primera versión recomendada para producción. Hasta entonces la API puede cambiar en cualquier versión. - Licencia: MIT, © Arrow Software. Al contribuir aceptas que tu aporte se publique bajo ella.
Reportar issues#
¿Encontraste un error o tienes una solicitud?
- Busca primero entre los issues existentes.
- Abre uno nuevo con una descripción clara, los pasos para reproducirlo, el comportamiento esperado y el real, y un ejemplo mínimo de código.
Cuando adjuntes XML, entradas o capturas, tacha los datos: reemplaza RUT, nombres y montos reales por los valores ficticios que usa esta documentación, y nunca adjuntes un CAF, certificado, contraseña, token o sesión del portal reales. Ver Sin datos reales.
Para vulnerabilidades de seguridad, no abras un issue público. Repórtalas en privado como se describe en Seguridad.
Preparar el entorno de desarrollo#
Necesitas Node 22.12 o superior, npm y git. Bajo la 22.12, require() no puede cargar un módulo ES, algo que el paquete soporta para proyectos CommonJS.
git clone https://github.com/arrowsw/dte-sdk.git
cd dte-sdk
git checkout canary
npm install # también compila, mediante el script `prepare`
npm testComandos#
| Comando | Qué hace |
|---|---|
npm test | Ejecuta la suite de Jest: pruebas unitarias, basadas en propiedades, de tipos y de humo del paquete compilado. |
npm test -- --coverage | Lo mismo, haciendo cumplir los umbrales de cobertura. Es lo que ejecuta CI. |
npm run build | Compila con esbuild (módulos ES, un archivo por entrada más trozos compartidos) y emite las declaraciones con tsc. |
npm run lint | ESLint (configuración flat) con Prettier. |
npm run prettier | Formatea src y tests. |
npm run size | La guarda de tamaño del bundle (.size-limit.json): cada entrada tiene un límite en kB, minificada y comprimida. |
npm run scan | Falla si un archivo versionado contiene un RUT real, una ruta local o un secreto. Ver Sin datos reales. |
npm run mutation | Pruebas de mutación con Stryker. Ver más abajo. |
npm run fixtures, npm run fixtures:tls | Regeneran los fixtures sintéticos. Esto cambia todas las llaves, así que regenera tests/__snapshots__/ en el mismo commit. |
La prueba de humo del paquete compilado carga los archivos construidos, así que ejecuta npm run build de nuevo después de cambiar las fuentes.
Estilo: Prettier con comillas simples, sin punto y coma, comas finales y 120 columnas; TypeScript en modo estricto; ESLint con las reglas recomendadas (un prefijo de guion bajo marca un argumento o variable que no se usa a propósito). npm run prettier y npm run lint forman parte de la guarda previa a publicar.
La estructura#
src/
index.ts entrada `dte-sdk` (documentos, totales, timbres, firmas, sobres, libros, cliente del SII)
node/index.ts entrada `dte-sdk/node`
portal/index.ts entrada `dte-sdk/portal`
pdf/index.ts entrada `dte-sdk/pdf`
errors.ts DteError y los códigos estables
... una carpeta por área: document, totals, ted, signature, envelope, books, sii, portal…
tests/
<área>/ las pruebas junto al área que cubren
fixtures/ certificados, CAF, respuestas del SII, XML golden y esquemas oficiales sintéticos
support/ SII falso, constructores y utilidades (no se recogen como pruebas)
live/ pruebas de humo opt-in contra el SII realDos reglas mantienen honestas las entradas: la entrada raíz no debe evaluar ningún módulo node: al importarse (los adaptadores de Node los cargan en el primer uso), y una función que necesita Node pertenece a dte-sdk/node o a dte-sdk/portal, no a la raíz.
Pruebas#
Todo cambio viene con pruebas. La suite usa Jest con ts-jest y cuatro tipos de prueba:
- Pruebas unitarias de cada función: el camino feliz, cada código
DteErrorque puede lanzar y los casos límite (redondeos, descuentos, líneas exentas, una respuesta cortada). - Pruebas basadas en propiedades (fast-check) para invariantes como totales y codificaciones.
- Pruebas de tipos (expect-type) para que los tipos públicos no se desvíen.
- Pruebas golden y de esquemas: el XML de los libros y sobres se compara byte a byte con archivos golden y se valida contra los esquemas oficiales del SII.
El cliente de servicios web del SII se prueba contra un SII falso (tests/support/fake-sii.ts) que sirve respuestas sintéticas desde tests/fixtures/sii/, y el portal contra páginas sintéticas. Es deliberado y honesto: esas pruebas no pueden mostrar cómo responde el SII real. Estado dice qué ha tocado lo real.
El umbral de cobertura del 100 %#
jest.config.cjs fija un umbral global de 100 % en sentencias, ramas, funciones y líneas, medido contra src/**/*.ts (nunca contra el dist compilado). CI falla ante cualquier caída. Si código real introduce una rama realmente inalcanzable, baja el umbral de forma deliberada y documenta el porqué en el mismo pull request; no dejes una rama sin probar ni agregues un comentario para esconderla.
Pruebas de mutación#
npm run mutation ejecuta Stryker sobre src/**/*.ts con el runner de Jest. Es lento, así que es un chequeo de profundidad periódico y no una guarda por commit. Sus umbrales son 90 (alto), 80 (bajo) y 70 (corte).
Pruebas de humo en vivo#
Las pruebas de tests/live hablan con el ambiente de certificación del SII con un certificado real. Nunca corren en CI y se omiten salvo que las actives:
SII_LIVE=1 SII_CERT_PFX=/path/to/firma.pfx SII_CERT_PASSWORD="$PFX_PASSWORD" \
[SII_COMPANY_RUT=… SII_LIVE_TRACK_ID=…] npx jest tests/liveNada de una ejecución en vivo se sube al repositorio: ni salidas, ni directorios de captura, ni RUT. Si las ejecutas, usas tu propio certificado contra el SII; lee antes Seguridad.
La convención de JSDoc bilingüe#
La documentación de la API vive en el código, en inglés y en español. Toda función, tipo y campo exportado tiene un bloque JSDoc con una línea EN: y una línea ES:, y lo mismo las etiquetas @param, @returns y @throws {DteError} (una línea @throws lista los códigos de error que puede lanzar la función, en ambos idiomas):
/**
* EN: Type guard for `DteError`.
* ES: Guarda de tipo para `DteError`.
* @param value EN: anything. ES: cualquier valor.
* @returns EN: true when `value` is a `DteError`. ES: true cuando `value` es un `DteError`.
*/En los campos del modelo de dominio, la línea ES: nombra la etiqueta del SII que produce el campo, para que quien conoce el formato del SII encuentre el camino de vuelta:
/** EN: Folio. ES: `NroDoc` — Folio del documento. */
readonly folio: numberEl modelo se nombra en inglés; las etiquetas y el vocabulario propios del SII aparecen en la línea ES: y en el XML. Un pull request que agrega un export sin ambos idiomas está incompleto.
Sin datos reales#
El repositorio es público y nunca debe contener a un contribuyente real. Esto cubre código, pruebas, fixtures, documentación, mensajes de commit, issues y pull requests.
- Usa datos ficticios. Los RUT de los ejemplos y las pruebas son valores de documentación, como
76543210-3,12345678-5y66666666-6(el RUT genérico del propio SII). Los certificados, CAF y llaves TLS detests/fixturesse generan localmente y son sintéticos. Las contraseñas de los ejemplos vienen deprocess.env. npm run scanlo hace cumplir. Falla cuando un archivo versionado bajosrc/,tests/,scripts/,docs/,README.md,llms.txtoCHANGELOG.mdcontiene un RUT fuera de una lista corta permitida, una ruta local de una máquina o un archivo que parece un secreto (.pfx,.p12,.pem,.key,.env; los fixtures son la única excepción). Corre en CI y antes de cada publicación. Agregar un RUT a la lista es una decisión deliberada: pregunta primero de quién es.- Nunca subas un CAF, certificado, token o sesión del portal reales, ni una captura de un intercambio real. Una captura tacha los secretos pero conserva los RUT y el XML.
Commits y pull requests#
Crea una rama desde canary
git checkout canary && git pull
git checkout -b fix/short-descriptionImplementa con pruebas
Agrega pruebas para el nuevo comportamiento, teniendo presente el umbral de cobertura, y escribe el JSDoc en ambos idiomas.
Verifica en local
npm test -- --coverage
npm run lint
npm run scan
npm run build && npm run sizeActualiza el changelog
Agrega una línea bajo [Unreleased] en CHANGELOG.md, que sigue Keep a Changelog. Si cambias la API pública, actualiza también el README.
Abre el pull request
Contra canary, con un título en el estilo convencional que usa el historial: feat: …, fix: …, docs: …, feat!: … para un cambio incompatible. Di qué cambió y por qué, y qué probaste. Los pull requests se fusionan con squash.
Los pull requests de funcionalidades nunca suben la versión. Ningún pull request que cambie el comportamiento toca version en package.json ni en package-lock.json.
Publicaciones#
Las versiones las publican los mantenedores, siguiendo RELEASING.md:
- Una versión es su propio pull request (rama
release/X.Y.Z, commitchore(release): X.Y.Z) que contiene solo el cambio de versión y la sección finalizada delCHANGELOG. - Publicar solo se dispara con un tag. Subir un tag
vX.Y.Zejecuta en CI el workflow de publicación:npm ci, la guarda previa a publicar (scan, pruebas, Prettier y lint), una verificación de que el tag coincide con la versión depackage.json, ynpm publish --provenance. - Sin token y con procedencia. El workflow se autentica con npm Trusted Publishing (GitHub OIDC), así que no existe un
NPM_TOKENque filtrar, y cada tarball lleva una atestación de procedencia que lo enlaza con su commit y su build de origen.
Licencia#
dte-sdk se publica bajo la licencia MIT.