# OpenAPI Clean Architecture Generator 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. ## πŸ“¦ Requirements - [Bun](https://bun.sh) >= 1.0.0 - [Java](https://www.java.com) (required by `openapi-generator-cli`) ## πŸš€ Installation ### 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 https://git.blassanto.me/blas/openapi-clean-arch-gen/releases/latest/download/generate-clean-arch-macos-arm64 -o generate-clean-arch chmod +x generate-clean-arch && ./generate-clean-arch -i swagger.yaml # macOS (Intel) curl -L https://git.blassanto.me/blas/openapi-clean-arch-gen/releases/latest/download/generate-clean-arch-macos-x64 -o generate-clean-arch chmod +x generate-clean-arch && ./generate-clean-arch -i swagger.yaml # Linux x64 curl -L https://git.blassanto.me/blas/openapi-clean-arch-gen/releases/latest/download/generate-clean-arch-linux-x64 -o generate-clean-arch chmod +x generate-clean-arch && ./generate-clean-arch -i swagger.yaml # Windows (PowerShell) curl -L https://git.blassanto.me/blas/openapi-clean-arch-gen/releases/latest/download/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 npm ```bash bun add -g @0kmpo/openapi-clean-arch-generator ``` Then run: ```bash generate-clean-arch -i swagger.yaml ``` ### Option 2: Clone and use locally ```bash git clone cd openapi-clean-arch-generator bun install bun run setup # installs openapi-generator-cli globally ``` ## πŸ“– Usage ### Basic command ```bash # Installed globally generate-clean-arch -i swagger.yaml # From the repository (compiled) bun run generate -- -i swagger.yaml # From the repository (development, no compilation needed) bun run generate:dev -- -i swagger.yaml ``` ### Available options ``` 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 ``` ### Examples ```bash # Generate from swagger.yaml into src/app generate-clean-arch -i swagger.yaml -o ./src/app # Interactively select tags/endpoints generate-clean-arch -i api.yaml -s # Use custom templates generate-clean-arch -i api.yaml -t ./my-templates # Dry run (no files written) generate-clean-arch -i swagger.yaml --dry-run # Full example with all options generate-clean-arch -i ./docs/api.yaml -o ./frontend/src/app -t ./custom-templates ``` ## πŸ“ Generated Structure The generator creates the following structure following Clean Architecture: ``` src/app/ β”œβ”€β”€ data/ # Data layer β”‚ β”œβ”€β”€ dtos/ # Data Transfer Objects β”‚ β”‚ β”œβ”€β”€ node/ β”‚ β”‚ β”‚ β”œβ”€β”€ node.dto.ts β”‚ β”‚ β”‚ └── node.dto.mock.ts β”‚ β”‚ β”œβ”€β”€ order-type/ β”‚ β”‚ β”‚ β”œβ”€β”€ order-type.dto.ts β”‚ β”‚ β”‚ └── order-type.dto.mock.ts β”‚ β”‚ └── supply-mode/ β”‚ β”‚ β”œβ”€β”€ supply-mode.dto.ts β”‚ β”‚ └── supply-mode.dto.mock.ts β”‚ β”œβ”€β”€ repositories/ # Repository implementations β”‚ β”‚ β”œβ”€β”€ node.repository.impl.ts β”‚ β”‚ β”œβ”€β”€ node.repository.impl.mock.ts β”‚ β”‚ β”œβ”€β”€ node.repository.impl.spec.ts β”‚ β”‚ β”œβ”€β”€ order-type.repository.impl.ts β”‚ β”‚ β”œβ”€β”€ order-type.repository.impl.mock.ts β”‚ β”‚ β”œβ”€β”€ order-type.repository.impl.spec.ts β”‚ β”‚ └── ... β”‚ └── mappers/ # DTO β†’ Entity transformers β”‚ β”œβ”€β”€ node.mapper.ts β”‚ β”œβ”€β”€ node.mapper.spec.ts β”‚ β”œβ”€β”€ order-type.mapper.ts β”‚ β”œβ”€β”€ order-type.mapper.spec.ts β”‚ └── ... β”œβ”€β”€ domain/ # Domain layer β”‚ β”œβ”€β”€ repositories/ # Repository contracts β”‚ β”‚ β”œβ”€β”€ node.repository.contract.ts β”‚ β”‚ └── ... β”‚ └── use-cases/ # Use cases β”‚ β”œβ”€β”€ node/ β”‚ β”‚ β”œβ”€β”€ node.use-cases.contract.ts β”‚ β”‚ β”œβ”€β”€ node.use-cases.impl.ts β”‚ β”‚ β”œβ”€β”€ node.use-cases.mock.ts β”‚ β”‚ └── node.use-cases.impl.spec.ts β”‚ └── ... β”œβ”€β”€ di/ # Dependency injection β”‚ β”œβ”€β”€ repositories/ # Repository providers β”‚ β”‚ β”œβ”€β”€ node.repository.provider.ts β”‚ β”‚ β”œβ”€β”€ node.repository.provider.mock.ts β”‚ β”‚ └── ... β”‚ └── use-cases/ # Use case providers β”‚ β”œβ”€β”€ node.use-cases.provider.ts β”‚ β”œβ”€β”€ node.use-cases.provider.mock.ts β”‚ └── ... └── entities/ # Domain entities └── models/ β”œβ”€β”€ node.model.ts β”œβ”€β”€ node.model.mock.ts β”œβ”€β”€ node.model.spec.ts └── ... ``` ## πŸ”§ Template Customization Templates live in `templates/` and use [Mustache](https://mustache.github.io/) syntax. Override them by passing your own directory with `-t`. | Template | Generates | |---|---| | `model.mustache` | DTOs | | `model.mock.mustache` | DTO mocks | | `dto.mock.mustache` | DTO mocks (alternative) | | `model-entity.mustache` | Domain entity models | | `model-entity.spec.mustache` | Entity model specs | | `mapper.mustache` | DTO β†’ Entity mappers | | `mapper.spec.mustache` | Mapper specs | | `api.repository.contract.mustache` | Repository contracts | | `api.repository.impl.mustache` | Repository implementations | | `api.repository.impl.mock.mustache` | Repository mocks | | `api.repository.impl.spec.mustache` | Repository specs | | `api.use-cases.contract.mustache` | Use case contracts | | `api.use-cases.impl.mustache` | Use case implementations | | `api.use-cases.mock.mustache` | Use case mocks | | `api.use-cases.impl.spec.mustache` | Use case specs | | `repository.provider.mustache` | Repository DI providers | | `repository.provider.mock.mustache` | Repository provider mocks | | `use-cases.provider.mustache` | Use case DI providers | | `use-cases.provider.mock.mustache` | Use case provider mocks | ### Available Mustache variables ```mustache {{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 ``` ## πŸ“Š Generation Report After each run a `generation-report.json` file is created: ```json { "timestamp": "2025-01-15T10:30:00.000Z", "tags": 3, "endpoints": 8, "tagDetails": [ { "name": "User", "description": "User operations", "endpoints": 3 }, { "name": "Product", "description": "Product operations", "endpoints": 2 } ], "outputDirectory": "./src/app", "linting": { "prettier": { "ran": true, "filesFormatted": 42 }, "eslint": { "ran": true, "filesFixed": 42 } }, "structure": { "dtos": 15, "repositories": 9, "mappers": 5, "useCases": 6, "providers": 12, "mocks": 18, "specs": 14 } } ``` ## 🎯 Angular Integration Example ### 1. Generate code ```bash generate-clean-arch -i ./docs/api.yaml -o ./src/app ``` ### 2. Register providers In your `app.config.ts` (Angular 17+ standalone): ```typescript import { ApplicationConfig } from '@angular/core'; import { NodeRepositoryProvider } from './di/repositories/node.repository.provider'; import { NodeUseCasesProvider } from './di/use-cases/node.use-cases.provider'; export const appConfig: ApplicationConfig = { providers: [ NodeRepositoryProvider, NodeUseCasesProvider, // ... rest of generated providers ] }; ``` ### 3. Use in components ```typescript import { Component, inject } from '@angular/core'; import { NODE_USE_CASES } from './domain/use-cases/node/node.use-cases.contract'; @Component({ selector: 'app-nodes', template: `...` }) export class NodesComponent { readonly #nodeUseCases = inject(NODE_USE_CASES); loadNodes(): void { this.#nodeUseCases.getNodes().subscribe((nodes) => { console.log(nodes); }); } } ``` ## πŸ› Troubleshooting ### `openapi-generator-cli` not found ```bash bun run setup # or manually: bun add -g @openapitools/openapi-generator-cli ``` ### swagger.yaml file not found Specify the correct path with `-i`: ```bash generate-clean-arch -i ./path/to/your/api.yaml ``` ### Path aliases `@/` not resolving Configure the aliases in your Angular project's `tsconfig.json`: ```json { "compilerOptions": { "paths": { "@/*": ["src/app/*"] } } } ``` ### Templates not generating expected code 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 ## πŸ“ Notes - 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 ## 🀝 Contributing Found a bug or have an improvement? Open an issue or PR in the repository. ## πŸ“„ License MIT