diff --git a/.gitea/workflows/lint.yaml b/.gitea/workflows/lint.yaml index 7e90096..7b48e42 100644 --- a/.gitea/workflows/lint.yaml +++ b/.gitea/workflows/lint.yaml @@ -22,3 +22,4 @@ jobs: - name: Run lint run: bun run lint + diff --git a/.gitea/workflows/publish.yml b/.gitea/workflows/publish.yml index 87d4db4..b29269e 100644 --- a/.gitea/workflows/publish.yml +++ b/.gitea/workflows/publish.yml @@ -1,4 +1,4 @@ -name: Publish npm package +name: Publish on: push: @@ -43,6 +43,9 @@ jobs: - name: Build run: bun run build + - name: Build binaries + run: bun run binaries + - name: Configure Gitea registry auth run: | echo "//git.blassanto.me/api/packages/blas/npm/:_authToken=${NODE_AUTH_TOKEN}" >> ~/.bunfig.toml @@ -52,7 +55,37 @@ jobs: env: NODE_AUTH_TOKEN: ${{ secrets.PUBLISH_TOKEN }} - - name: Publish to Gitea + - name: Publish to Gitea registry run: bun publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.PUBLISH_TOKEN }} + + - name: Create Gitea release and upload binaries + run: | + VERSION=${GITHUB_REF_NAME#v} + + RELEASE_ID=$(curl -s -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + "https://git.blassanto.me/api/v1/repos/blas/openapi-clean-arch-gen/releases" \ + -d "{ + \"tag_name\": \"${GITHUB_REF_NAME}\", + \"name\": \"v${VERSION}\", + \"body\": \"## Installation\n\nDownload the binary for your platform or install via the npm registry:\n\n\`\`\`bash\nbun add -g @blas/openapi-clean-arch-generator --registry https://git.blassanto.me/api/packages/blas/npm/\n\`\`\`\", + \"draft\": false, + \"prerelease\": false + }" | bun -e "let d='';process.stdin.on('data',c=>d+=c).on('end',()=>console.log(JSON.parse(d).id))") + + echo "Created release ID: $RELEASE_ID" + + for BINARY in dist/bin/*; do + FILENAME=$(basename "$BINARY") + echo "Uploading $FILENAME..." + curl -s -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -F "attachment=@${BINARY};filename=${FILENAME}" \ + "https://git.blassanto.me/api/v1/repos/blas/openapi-clean-arch-gen/releases/${RELEASE_ID}/assets" + done + env: + GITEA_TOKEN: ${{ secrets.TOKEN }} + diff --git a/.gitignore b/.gitignore index 2aacdee..fc2813a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ package-lock.json .temp-generated/ temp-generated/ dist/ +dist/bin/ generation-report.json diff --git a/README.md b/README.md index 5946b7d..d396be7 100644 --- a/README.md +++ b/README.md @@ -1,90 +1,112 @@ # OpenAPI Clean Architecture Generator -Generador de código Angular con Clean Architecture desde archivos OpenAPI/Swagger. Automatiza la creación de DTOs, repositorios, mappers, casos de uso y providers de inyección de dependencias. +Angular code generator that creates clean architecture boilerplate from OpenAPI/Swagger specifications. Automates the creation of DTOs, repositories, mappers, use cases and dependency injection providers. -## 📦 Requisitos +## 📦 Requirements - [Bun](https://bun.sh) >= 1.0.0 -- [Java](https://www.java.com) (requerido por `openapi-generator-cli`) +- [Java](https://www.java.com) (required by `openapi-generator-cli`) -## 🚀 Instalación +## 🚀 Installation -### Opción 1: Instalar como CLI global desde el registry +### Option 0: Prebuilt binary (no dependencies) + +Download the binary for your platform from the releases page and run it directly — no Node, Bun or Java required: + +```bash +# macOS (Apple Silicon) +curl -L /generate-clean-arch-macos-arm64 -o generate-clean-arch +chmod +x generate-clean-arch && ./generate-clean-arch -i swagger.yaml + +# macOS (Intel) +curl -L /generate-clean-arch-macos-x64 -o generate-clean-arch +chmod +x generate-clean-arch && ./generate-clean-arch -i swagger.yaml + +# Linux x64 +curl -L /generate-clean-arch-linux-x64 -o generate-clean-arch +chmod +x generate-clean-arch && ./generate-clean-arch -i swagger.yaml + +# Windows (PowerShell) +curl -L /generate-clean-arch-windows-x64.exe -o generate-clean-arch.exe +.\generate-clean-arch.exe -i swagger.yaml +``` + +### Option 1: Install as a global CLI from the registry ```bash bun add -g @blas/openapi-clean-arch-generator --registry https://git.blassanto.me/api/packages/blas/npm/ ``` -O configurando el registry en tu `.npmrc` / `bunfig.toml`: +Or configure the registry in your `.npmrc` / `bunfig.toml` and then run: ```bash generate-clean-arch -i swagger.yaml ``` -### Opción 2: Clonar y usar en local +### Option 2: Clone and use locally ```bash git clone cd openapi-clean-arch-generator bun install -bun run setup # instala openapi-generator-cli globalmente +bun run setup # installs openapi-generator-cli globally ``` -## 📖 Uso +## 📖 Usage -### Comando básico +### Basic command ```bash -# Instalado globalmente +# Installed globally generate-clean-arch -i swagger.yaml -# Desde el repositorio (compilado) +# From the repository (compiled) bun run generate -- -i swagger.yaml -# Desde el repositorio (desarrollo, sin compilar) +# From the repository (development, no compilation needed) bun run generate:dev -- -i swagger.yaml ``` -### Opciones disponibles +### Available options ``` -Opciones: - -V, --version Mostrar versión - -i, --input Archivo OpenAPI/Swagger (yaml o json) [default: swagger.yaml] - -o, --output Directorio de salida [default: ./src/app] - -t, --templates Directorio de templates personalizados [default: ./templates] - -s, --select-endpoints Seleccionar interactivamente tags y endpoints a generar - --skip-install No instalar dependencias - --dry-run Simular sin generar archivos - -h, --help Mostrar ayuda +Options: + -V, --version Show version + -i, --input OpenAPI/Swagger file (yaml or json) [default: swagger.yaml] + -o, --output Output directory [default: ./src/app] + -t, --templates Custom templates directory [default: ./templates] + -s, --select-endpoints Interactively select tags and endpoints to generate + --skip-install Skip dependency installation + --dry-run Simulate without writing files + -h, --help Show help ``` -### Ejemplos +### Examples ```bash -# Generar desde swagger.yaml en src/app +# Generate from swagger.yaml into src/app generate-clean-arch -i swagger.yaml -o ./src/app -# Seleccionar tags/endpoints de forma interactiva +# Interactively select tags/endpoints generate-clean-arch -i api.yaml -s -# Usar templates personalizados -generate-clean-arch -i api.yaml -t ./mis-templates +# Use custom templates +generate-clean-arch -i api.yaml -t ./my-templates -# Modo de prueba (no genera archivos) +# Dry run (no files written) generate-clean-arch -i swagger.yaml --dry-run -# Especificar todos los parámetros +# Full example with all options generate-clean-arch -i ./docs/api.yaml -o ./frontend/src/app -t ./custom-templates ``` -## 📁 Estructura Generada +## 📁 Generated Structure -El generador crea la siguiente estructura siguiendo Clean Architecture: +The generator creates the following structure following Clean Architecture: ``` src/app/ -├── data/ # Capa de datos +├── data/ # Data layer │ ├── dtos/ # Data Transfer Objects │ │ ├── node/ │ │ │ └── node.dto.ts @@ -92,20 +114,20 @@ src/app/ │ │ │ └── order-type.dto.ts │ │ └── supply-mode/ │ │ └── supply-mode.dto.ts -│ ├── repositories/ # Implementaciones de repositorios +│ ├── repositories/ # Repository implementations │ │ ├── node.repository.impl.ts │ │ ├── order-type.repository.impl.ts │ │ └── supply-mode.repository.impl.ts -│ └── mappers/ # Transformadores DTO → Entidad +│ └── mappers/ # DTO → Entity transformers │ ├── node.mapper.ts │ ├── order-type.mapper.ts │ └── supply-mode.mapper.ts -├── domain/ # Capa de dominio -│ ├── repositories/ # Contratos de repositorios +├── domain/ # Domain layer +│ ├── repositories/ # Repository contracts │ │ ├── node.repository.contract.ts │ │ ├── order-type.repository.contract.ts │ │ └── supply-mode.repository.contract.ts -│ └── use-cases/ # Casos de uso +│ └── use-cases/ # Use cases │ ├── node/ │ │ ├── node.use-cases.contract.ts │ │ └── node.use-cases.impl.ts @@ -115,57 +137,57 @@ src/app/ │ └── supply-mode/ │ ├── supply-mode.use-cases.contract.ts │ └── supply-mode.use-cases.impl.ts -├── di/ # Inyección de dependencias -│ ├── repositories/ # Providers de repositorios +├── di/ # Dependency injection +│ ├── repositories/ # Repository providers │ │ ├── node.repository.provider.ts │ │ ├── order-type.repository.provider.ts │ │ └── supply-mode.repository.provider.ts -│ └── use-cases/ # Providers de use cases +│ └── use-cases/ # Use case providers │ ├── node.use-cases.provider.ts │ ├── order-type.use-cases.provider.ts │ └── supply-mode.use-cases.provider.ts -└── entities/ # Entidades de dominio +└── entities/ # Domain entities └── models/ ├── node.model.ts ├── order-type.model.ts └── supply-mode.model.ts ``` -## 🔧 Personalización de Templates +## 🔧 Template Customization -Los templates están en `templates/` y usan sintaxis [Mustache](https://mustache.github.io/). Puedes sobreescribirlos pasando tu propio directorio con `-t`. +Templates live in `templates/` and use [Mustache](https://mustache.github.io/) syntax. Override them by passing your own directory with `-t`. -| Template | Genera | +| Template | Generates | |---|---| | `model.mustache` | DTOs | -| `model-entity.mustache` | Entidades de dominio | -| `mapper.mustache` | Mappers DTO → Entidad | -| `api.repository.contract.mustache` | Contratos de repositorio | -| `api.repository.impl.mustache` | Implementaciones de repositorio | -| `api.use-cases.contract.mustache` | Contratos de use cases | -| `api.use-cases.impl.mustache` | Implementaciones de use cases | -| `repository.provider.mustache` | Providers de repositorio | -| `use-cases.provider.mustache` | Providers de use cases | +| `model-entity.mustache` | Domain entity models | +| `mapper.mustache` | DTO → Entity mappers | +| `api.repository.contract.mustache` | Repository contracts | +| `api.repository.impl.mustache` | Repository implementations | +| `api.use-cases.contract.mustache` | Use case contracts | +| `api.use-cases.impl.mustache` | Use case implementations | +| `repository.provider.mustache` | Repository DI providers | +| `use-cases.provider.mustache` | Use case DI providers | -### Variables Mustache disponibles +### Available Mustache variables ```mustache -{{classname}} - Nombre de la clase (ej: "OrderType") -{{classVarName}} - Nombre en camelCase (ej: "orderType") -{{classFilename}} - Nombre del archivo (ej: "order-type") -{{constantName}} - Constante en UPPER_SNAKE_CASE (ej: "ORDER_TYPE") -{{description}} - Descripción del schema -{{httpMethod}} - Método HTTP (get, post, put, delete…) -{{path}} - Path del endpoint -{{nickname}} - Nombre del método -{{allParams}} - Todos los parámetros del endpoint -{{returnType}} - Tipo de retorno -{{vars}} - Variables del modelo +{{classname}} - Class name (e.g. "OrderType") +{{classVarName}} - camelCase name (e.g. "orderType") +{{classFilename}} - File name (e.g. "order-type") +{{constantName}} - UPPER_SNAKE_CASE constant (e.g. "ORDER_TYPE") +{{description}} - Schema description +{{httpMethod}} - HTTP method (get, post, put, delete…) +{{path}} - Endpoint path +{{nickname}} - Method name +{{allParams}} - All endpoint parameters +{{returnType}} - Return type +{{vars}} - Model variables ``` -## 📊 Reporte de Generación +## 📊 Generation Report -Tras cada ejecución se crea `generation-report.json`: +After each run a `generation-report.json` file is created: ```json { @@ -182,17 +204,17 @@ Tras cada ejecución se crea `generation-report.json`: } ``` -## 🎯 Ejemplo de integración en Angular +## 🎯 Angular Integration Example -### 1. Generar código +### 1. Generate code ```bash generate-clean-arch -i ./docs/api.yaml -o ./src/app ``` -### 2. Registrar providers +### 2. Register providers -En tu `app.config.ts` (Angular 17+ standalone): +In your `app.config.ts` (Angular 17+ standalone): ```typescript import { ApplicationConfig } from '@angular/core'; @@ -203,12 +225,12 @@ export const appConfig: ApplicationConfig = { providers: [ NodeRepositoryProvider, NodeUseCasesProvider, - // ... resto de providers generados + // ... rest of generated providers ] }; ``` -### 3. Usar en componentes +### 3. Use in components ```typescript import { Component, inject } from '@angular/core'; @@ -231,25 +253,25 @@ export class NodesComponent { ## 🐛 Troubleshooting -### `openapi-generator-cli` no encontrado +### `openapi-generator-cli` not found ```bash bun run setup -# o manualmente: +# or manually: bun add -g @openapitools/openapi-generator-cli ``` -### Archivo swagger.yaml no encontrado +### swagger.yaml file not found -Especifica la ruta correcta con `-i`: +Specify the correct path with `-i`: ```bash -generate-clean-arch -i ./ruta/a/tu/api.yaml +generate-clean-arch -i ./path/to/your/api.yaml ``` -### Los path aliases `@/` no se resuelven +### Path aliases `@/` not resolving -Configura los aliases en el `tsconfig.json` de tu proyecto Angular: +Configure the aliases in your Angular project's `tsconfig.json`: ```json { @@ -261,24 +283,24 @@ Configura los aliases en el `tsconfig.json` de tu proyecto Angular: } ``` -### Los templates no generan el código esperado +### Templates not generating expected code -1. Verifica que tus templates están en `./templates/` o pasa la ruta con `-t` -2. Revisa la sintaxis Mustache -3. Usa `--dry-run` para simular sin escribir archivos +1. Make sure your templates are in `./templates/` or pass the path with `-t` +2. Check the Mustache syntax +3. Use `--dry-run` to simulate without writing files -## 📝 Notas +## 📝 Notes -- El generador produce archivos `.ts` listos para usar, no los compila -- Los providers deben registrarse manualmente en tu módulo o config de Angular -- Requiere Angular 17+ (usa la función `inject()`) -- Compatible con proyectos standalone y basados en módulos +- The generator produces ready-to-use `.ts` files, it does not compile them +- Providers must be registered manually in your Angular module or config +- Requires Angular 17+ (uses the `inject()` function) +- Compatible with both standalone and module-based projects -## 🤝 Contribuir +## 🤝 Contributing -Si encuentras bugs o mejoras, abre un issue o PR en el repositorio. +Found a bug or have an improvement? Open an issue or PR in the repository. -## 📄 Licencia +## 📄 License MIT diff --git a/package.json b/package.json index 7887433..51924e0 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,12 @@ "prepublishOnly": "bun run build", "generate": "bun dist/main.js", "generate:dev": "bun main.ts", + "binaries": "bun run binary:mac-arm64 && bun run binary:mac-x64 && bun run binary:linux-x64 && bun run binary:linux-arm64 && bun run binary:windows", + "binary:mac-arm64": "bun build --compile --target=bun-darwin-arm64 --outfile dist/bin/generate-clean-arch-macos-arm64 main.ts", + "binary:mac-x64": "bun build --compile --target=bun-darwin-x64 --outfile dist/bin/generate-clean-arch-macos-x64 main.ts", + "binary:linux-x64": "bun build --compile --target=bun-linux-x64 --outfile dist/bin/generate-clean-arch-linux-x64 main.ts", + "binary:linux-arm64": "bun build --compile --target=bun-linux-arm64 --outfile dist/bin/generate-clean-arch-linux-arm64 main.ts", + "binary:windows": "bun build --compile --target=bun-windows-x64 --outfile dist/bin/generate-clean-arch-windows-x64.exe main.ts", "lint": "eslint 'main.ts' 'src/**/*.ts' -f unix", "lint:fix": "eslint 'main.ts' 'src/**/*.ts' --fix -f unix", "format": "prettier --write .",