Réplica funcional del monorepo cfdi-node en Elixir. Contiene 34 paquetes organizados por dominio, cada uno como un proyecto Mix independiente.
Este proyecto no usa umbrella de Elixir. En su lugar usa el patrón poncho: un proyecto raíz que depende de cada paquete vía path: dependencies. Esto permite agrupar los paquetes en carpetas por dominio (como Node.js) sin las restricciones del umbrella.
cfdi-elixir/
├── mix.exs ← proyecto raíz (poncho), lista los 34 paquetes
├── packages/
│ ├── cfdi/ ← @cfdi/* de Node.js
│ │ ├── cancelacion/
│ │ ├── cfdi/
│ │ ├── cleaner/
│ │ ├── complementos/
│ │ ├── csf/
│ │ ├── descarga/
│ │ ├── designs/
│ │ ├── elements/
│ │ ├── estado/
│ │ ├── expresiones/
│ │ ├── pdf/
│ │ ├── retenciones/
│ │ ├── rfc/
│ │ ├── schema/
│ │ ├── transform/
│ │ ├── types/
│ │ ├── utils/
│ │ ├── validador/
│ │ └── xml/
│ ├── sat/ ← @sat/* de Node.js
│ │ ├── auth/
│ │ ├── banxico/
│ │ ├── captcha/
│ │ ├── catalogos/
│ │ ├── catalogos_codegen/
│ │ ├── certificados/
│ │ ├── contabilidad/
│ │ ├── diot/
│ │ ├── opinion/
│ │ ├── pacs/
│ │ ├── recursos/
│ │ ├── scraper/
│ │ └── xsd/
│ ├── clir/ ← @clir/* y @saxon-he/* de Node.js
│ │ ├── openssl/
│ │ └── saxon_he/
│ └── renapo/ ← @renapo/* de Node.js
│ └── curp/
└── lib/mix/tasks/
├── bump.ex ← versionado con pre-release tags y cascada
└── hex_publish_all.ex ← publicación a Hex en orden topológico
# Instalar dependencias
mix deps.get
# Compilar todo
mix compile
# Tests de un paquete específico
cd packages/sat/catalogos && mix test
# Tests de todos los paquetes
find packages -mindepth 3 -maxdepth 3 -name "mix.exs" -execdir mix test \;Regenera los 15 módulos de sat_catalogos a partir de los archivos oficiales del SAT (catCFDI.xsd + catCFDI.xlsx). Ejecutar desde el paquete catalogos_codegen:
cd packages/sat/catalogos_codegen
# Regenerar con el XLSX ya presente en packages/files/4.0/
mix sat.catalogos.generate
# Descargar el XLSX más reciente del SAT y regenerar
mix sat.catalogos.generate --force-downloadVer más opciones en packages/sat/catalogos_codegen/README.md.
Cada directorio dentro de packages/<grupo>/<nombre>/ es un proyecto Mix completo con su propio mix.exs, lib/, y test/. Puedes compilar y testear cada uno por separado:
cd packages/cfdi/rfc
mix deps.get
mix testLos paquetes usan path: para depender de otros paquetes del monorepo:
# packages/cfdi/xml/mix.exs
defp deps do
[
{:cfdi_csd, path: "../csd"}, # mismo grupo
{:saxon_he, path: "../../clir/saxon_he"}, # otro grupo
{:xml_builder, "~> 2.1"} # Hex (externo)
]
end- Mismo grupo:
path: "../<paquete>" - Otro grupo:
path: "../../<grupo>/<paquete>" - Externo: se declara como dependencia normal de Hex
Herramienta integrada similar a Rush para manejar versiones semver con pre-release tags y bumps en cascada.
mix bump --listcfdi/
cancelacion 0.0.1
catalogos 4.0.16
xml 4.0.18
...
sat/
auth 1.0.1
banxico 0.0.1
...
mix bump sat_catalogos patch # 4.0.16 → 4.0.17
mix bump sat_auth minor # 1.0.1 → 1.1.0
mix bump sat_certificados major # 4.0.16 → 5.0.0Los tags permiten publicar versiones de prueba antes del release estable.
Hex y semver 2.0 soportan pre-release: las versiones con tag siempre son menores
que la versión estable del mismo número (4.0.18-dev.1 < 4.0.18).
┌─────────────────────────────────────────────────────────────────┐
│ Ciclo de vida de versión │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 4.0.17 (estable actual) │
│ │ │
│ ├── mix bump <app> patch --tag dev │
│ │ → 4.0.18-dev.1 bump base + agrega tag │
│ │ │
│ ├── mix bump <app> patch --tag dev │
│ │ → 4.0.18-dev.2 mismo tag = solo incrementa │
│ │ │
│ ├── mix bump <app> patch --tag dev │
│ │ → 4.0.18-dev.3 otro fix en dev │
│ │ │
│ ├── mix bump <app> patch --tag beta │
│ │ → 4.0.18-beta.1 cambio de tag = mantiene base │
│ │ │
│ ├── mix bump <app> patch --tag beta │
│ │ → 4.0.18-beta.2 fix en beta │
│ │ │
│ ├── mix bump <app> release │
│ │ → 4.0.18 quita tag = release estable │
│ │ │
│ 4.0.18 (nueva versión estable) │
│ │
└─────────────────────────────────────────────────────────────────┘
# Iniciar desarrollo: versión estable → dev
mix bump cfdi_complementos patch --tag dev # 4.0.17 → 4.0.18-dev.1
# Iterar en dev (mismo tag solo incrementa el número)
mix bump cfdi_complementos patch --tag dev # 4.0.18-dev.1 → 4.0.18-dev.2
mix bump cfdi_complementos patch --tag dev # 4.0.18-dev.2 → 4.0.18-dev.3
# Promover a beta (cambio de tag mantiene el base)
mix bump cfdi_complementos patch --tag beta # 4.0.18-dev.3 → 4.0.18-beta.1
# Iterar en beta
mix bump cfdi_complementos patch --tag beta # 4.0.18-beta.1 → 4.0.18-beta.2
# Release final (quita el tag)
mix bump cfdi_complementos release # 4.0.18-beta.2 → 4.0.18| Situación | Comando | Resultado |
|---|---|---|
Versión limpia 4.0.17 |
patch --tag dev |
4.0.18-dev.1 (bump base + tag) |
Mismo tag -dev.2 |
patch --tag dev |
4.0.18-dev.3 (solo incrementa) |
Otro tag -dev.3 |
patch --tag beta |
4.0.18-beta.1 (mantiene base, cambia tag) |
Cualquier tag -beta.2 |
release |
4.0.18 (quita tag) |
| Tag | Uso |
|---|---|
dev |
Desarrollo activo, puede romper cosas |
alpha |
Primera versión de prueba interna |
beta |
Feature-complete pero puede tener bugs |
rc |
Release candidate, listo para producción salvo bugs |
Nota: Hex ordena pre-release tags alfabéticamente (
alpha < beta < dev < rc). La versión estable (4.0.18) siempre es mayor que cualquier pre-release del mismo número.
Cuando haces bump de un paquete, automáticamente hace patch bump a todos los que dependen de él (como Rush):
mix bump clir_openssl minor --dry-runVersion changes:
clir_openssl 0.0.17 → 0.1.0 (minor)
cfdi_csd 4.0.16 → 4.0.17 (patch) ← depende de clir_openssl
sat_auth 1.0.1 → 1.0.2 (patch) ← depende de cfdi_csd
cfdi_xml 4.0.18 → 4.0.19 (patch) ← depende de cfdi_csd
cfdi_descarga 0.0.1 → 0.0.2 (patch) ← depende de sat_auth
cfdi_cancelacion 0.0.1 → 0.0.2 (patch) ← depende de sat_auth
| Flag | Efecto |
|---|---|
--dry-run |
Muestra qué cambiaría sin modificar archivos |
--no-cascade |
Solo hace bump del paquete indicado |
--tag TAG |
Agrega pre-release tag (dev, beta, rc, alpha) |
mix bump --graph cfdi_csdDependents of cfdi_csd:
└─ sat_auth
└─ cfdi_descarga
└─ cfdi_cancelacion
└─ cfdi_xml
Herramienta que publica todos los paquetes a Hex respetando el orden de dependencias.
Equivalente a rush publish en Node.js.
mix hex.publish_all --graph╔══════════════════════════════════════════════════╗
║ CFDI Umbrella — Dependency Graph ║
╚══════════════════════════════════════════════════╝
┌── Level 0 (sin dependencias internas) ──┐
│ sat_catalogos v4.0.16
│ cfdi_complementos v4.0.17
│ clir_openssl v0.0.17
│ saxon_he v12.5.2
│ ... (28 apps)
│ ▼
┌── Level 1 ──┐
│ sat_certificados v4.0.16
│ └─ depends on: clir_openssl
│ cfdi_designs v1.0.0
│ └─ depends on: cfdi_xml, cfdi_utils, cfdi_types, cfdi_complementos
│ ▼
┌── Level 2 ──┐
│ cfdi_xml v4.0.18
│ └─ depends on: cfdi_csd, cfdi_transform, cfdi_complementos, ...
│ sat_auth v1.0.1
│ └─ depends on: cfdi_csd
│ ▼
┌── Level 3 ──┐
│ cfdi_cancelacion v0.0.1
│ └─ depends on: sat_auth
│ cfdi_descarga v0.0.1
│ └─ depends on: sat_auth
└── end ──┘
mix hex.publish_all --dry-runMuestra el orden de publicación y los cambios que haría en cada mix.exs:
cfdi_csd mix.exs changes:
{:clir_openssl, path: "..."} → {:clir_openssl, "~> 0.0"}
cfdi_xml mix.exs changes:
{:cfdi_csd, path: "..."} → {:cfdi_csd, "~> 4.0"}
{:cfdi_transform, path: "..."} → {:cfdi_transform, "~> 4.0"}
...
# Publicar todo
mix hex.publish_all
# Publicar con bump de versión
mix hex.publish_all --bump patch
# Publicar solo un paquete (incluye sus deps automáticamente)
mix hex.publish_all --only cfdi_xml
# Publicar a una organización
mix hex.publish_all --org miorgPara cada paquete (en orden topológico):
- Backup del
mix.exsoriginal - Bump de versión si se pasó
--bump - Reemplazo de deps
path:→~> X.Y(versión publicada) - Inyección de
package/0con licencia y links mix hex.publish --yes- Restauración del
mix.exsoriginal (siempre, incluso si falla)
# 1. Desarrollo: bump a dev
mix bump cfdi_xml patch --tag dev
# 2. Iterar y probar
mix bump cfdi_xml patch --tag dev # incrementa dev.N
# 3. Beta
mix bump cfdi_xml patch --tag beta
# 4. Release
mix bump cfdi_xml release
# 5. Publicar todo a Hex
mix hex.publish_allNode.js (@scope/name) |
Elixir (app name) | Ruta |
|---|---|---|
@cfdi/cancelacion |
:cfdi_cancelacion |
packages/cfdi/cancelacion/ |
@cfdi/cleaner |
:cfdi_cleaner |
packages/cfdi/cleaner/ |
@cfdi/complementos |
:cfdi_complementos |
packages/cfdi/complementos/ |
@cfdi/csf |
:cfdi_csf |
packages/cfdi/csf/ |
@cfdi/descarga |
:cfdi_descarga |
packages/cfdi/descarga/ |
@cfdi/designs |
:cfdi_designs |
packages/cfdi/designs/ |
@cfdi/elements |
:cfdi_elements |
packages/cfdi/elements/ |
@cfdi/estado |
:cfdi_estado |
packages/cfdi/estado/ |
@cfdi/expresiones |
:cfdi_expresiones |
packages/cfdi/expresiones/ |
@cfdi/pdf |
:cfdi_pdf |
packages/cfdi/pdf/ |
@cfdi/retenciones |
:cfdi_retenciones |
packages/cfdi/retenciones/ |
@cfdi/rfc |
:cfdi_rfc |
packages/cfdi/rfc/ |
@cfdi/schema |
:cfdi_schema |
packages/cfdi/schema/ |
@cfdi/transform |
:cfdi_transform |
packages/cfdi/transform/ |
@cfdi/types |
:cfdi_types |
packages/cfdi/types/ |
@cfdi/utils |
:cfdi_utils |
packages/cfdi/utils/ |
@cfdi/validador |
:cfdi_validador |
packages/cfdi/validador/ |
@cfdi/xml |
:cfdi_xml |
packages/cfdi/xml/ |
@sat/auth |
:sat_auth |
packages/sat/auth/ |
@sat/banxico |
:sat_banxico |
packages/sat/banxico/ |
@sat/captcha |
:sat_captcha |
packages/sat/captcha/ |
@sat/catalogos |
:sat_catalogos |
packages/sat/catalogos/ |
@sat/catalogos-codegen |
:sat_catalogos_codegen |
packages/sat/catalogos_codegen/ |
@sat/certificados |
:sat_certificados |
packages/sat/certificados/ |
@sat/contabilidad |
:sat_contabilidad |
packages/sat/contabilidad/ |
@sat/diot |
:sat_diot |
packages/sat/diot/ |
@sat/opinion |
:sat_opinion |
packages/sat/opinion/ |
@sat/pacs |
:sat_pacs |
packages/sat/pacs/ |
@sat/recursos |
:sat_recursos |
packages/sat/recursos/ |
@sat/scraper |
:sat_scraper |
packages/sat/scraper/ |
@sat/xsd |
:sat_xsd |
packages/sat/xsd/ |
@clir/openssl |
:clir_openssl |
packages/clir/openssl/ |
@saxon-he/cli |
:saxon_he |
packages/clir/saxon_he/ |
@renapo/curp |
:renapo_curp |
packages/renapo/curp/ |
| Umbrella | Poncho (este proyecto) | |
|---|---|---|
| Estructura | packages/sat_catalogos/ (plano) |
packages/sat/catalogos/ (agrupado) |
| Descubrimiento | Automático por Mix | Explícito en deps del root |
| Deps entre apps | in_umbrella: true |
path: "../catalogos" |
mix test (root) |
Corre todos los tests | Corre solo root tests |
mix compile |
Compila todo | Compila todo (via path deps) |
| Build compartido | Sí (por defecto) | Sí (via build_path compartido) |