first commit
This commit is contained in:
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# Dependencias
|
||||
node_modules/
|
||||
package-lock.json
|
||||
|
||||
# Archivos temporales de generación
|
||||
.temp-generated/
|
||||
temp-generated/
|
||||
|
||||
# Reportes
|
||||
generation-report.json
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Sistema operativo
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Output de prueba
|
||||
test-output/
|
||||
33
.openapi-generator-ignore
Normal file
33
.openapi-generator-ignore
Normal file
@@ -0,0 +1,33 @@
|
||||
# OpenAPI Generator Ignore File
|
||||
# Archivos que no queremos generar
|
||||
|
||||
# Documentación
|
||||
README.md
|
||||
.gitignore
|
||||
git_push.sh
|
||||
|
||||
# NPM
|
||||
.npmignore
|
||||
package.json
|
||||
package-lock.json
|
||||
|
||||
# TypeScript config
|
||||
tsconfig.json
|
||||
tsconfig.spec.json
|
||||
|
||||
# Angular specific
|
||||
angular.json
|
||||
karma.conf.js
|
||||
|
||||
# Tests que no usamos
|
||||
*.spec.ts
|
||||
|
||||
# Variables de entorno
|
||||
variables.ts
|
||||
configuration.ts
|
||||
|
||||
# Encoder
|
||||
encoder.ts
|
||||
|
||||
# API base que usamos nuestra propia implementación
|
||||
api.ts
|
||||
157
QUICKSTART.md
Normal file
157
QUICKSTART.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# 🚀 Guía de Inicio Rápido
|
||||
|
||||
## Instalación en 3 pasos
|
||||
|
||||
### 1. Instalar dependencias
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. Instalar OpenAPI Generator CLI
|
||||
|
||||
```bash
|
||||
npm run setup
|
||||
# O manualmente:
|
||||
npm install -g @openapitools/openapi-generator-cli
|
||||
```
|
||||
|
||||
### 3. Probar con el ejemplo incluido
|
||||
|
||||
```bash
|
||||
node generate.js -i example-swagger.yaml -o ./test-output --dry-run
|
||||
```
|
||||
|
||||
## Uso con tu API
|
||||
|
||||
### Paso 1: Copia tu archivo Swagger/OpenAPI
|
||||
|
||||
```bash
|
||||
cp /ruta/a/tu/api.yaml ./swagger.yaml
|
||||
```
|
||||
|
||||
### Paso 2: Genera el código
|
||||
|
||||
```bash
|
||||
node generate.js -i swagger.yaml -o ./src/app
|
||||
```
|
||||
|
||||
### Paso 3: Revisa los archivos generados
|
||||
|
||||
```bash
|
||||
ls -la ./src/app/data/
|
||||
ls -la ./src/app/domain/
|
||||
ls -la ./src/app/di/
|
||||
```
|
||||
|
||||
## Opciones Comunes
|
||||
|
||||
### Generar en otra carpeta
|
||||
|
||||
```bash
|
||||
node generate.js -i swagger.yaml -o ./frontend/src/app
|
||||
```
|
||||
|
||||
### Usar templates personalizados
|
||||
|
||||
```bash
|
||||
# Edita los archivos en ./templates/
|
||||
# Luego ejecuta:
|
||||
node generate.js -i swagger.yaml -t ./templates
|
||||
```
|
||||
|
||||
### Modo de prueba (sin generar archivos)
|
||||
|
||||
```bash
|
||||
node generate.js -i swagger.yaml --dry-run
|
||||
```
|
||||
|
||||
## Integración con tu proyecto Angular
|
||||
|
||||
### 1. Registra los providers
|
||||
|
||||
En `app.config.ts` o `app.module.ts`:
|
||||
|
||||
```typescript
|
||||
import { UserRepositoryProvider } from '@/di/repositories/user.repository.provider';
|
||||
import { UserUseCasesProvider } from '@/di/use-cases/user.use-cases.provider';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
// ... otros providers
|
||||
UserRepositoryProvider,
|
||||
UserUseCasesProvider
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
### 2. Configura los path aliases
|
||||
|
||||
En `tsconfig.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["src/app/*"],
|
||||
"@environment": ["src/environments/environment"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Usa en tus componentes
|
||||
|
||||
```typescript
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { USER_USE_CASES } from '@/domain/use-cases/user/user.use-cases.contract';
|
||||
|
||||
@Component({
|
||||
selector: 'app-users',
|
||||
template: `...`
|
||||
})
|
||||
export class UsersComponent {
|
||||
#userUseCases = inject(USER_USE_CASES);
|
||||
|
||||
ngOnInit() {
|
||||
this.#userUseCases.getUsers().subscribe(users => {
|
||||
console.log(users);
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### ❌ Error: openapi-generator-cli: command not found
|
||||
|
||||
**Solución:**
|
||||
```bash
|
||||
npm install -g @openapitools/openapi-generator-cli
|
||||
```
|
||||
|
||||
### ❌ Error: Cannot find module 'commander'
|
||||
|
||||
**Solución:**
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### ❌ Los archivos no se generan
|
||||
|
||||
**Solución:** Verifica que el directorio de salida existe o usa `--dry-run` para ver qué pasaría:
|
||||
```bash
|
||||
node generate.js --dry-run
|
||||
```
|
||||
|
||||
## Próximos pasos
|
||||
|
||||
1. ✅ Genera el código desde tu Swagger
|
||||
2. 📝 Ajusta los templates según tus necesidades
|
||||
3. 🔧 Configura los path aliases en tu tsconfig.json
|
||||
4. 📦 Registra los providers en tu módulo Angular
|
||||
5. 🚀 ¡Usa el código generado en tus componentes!
|
||||
|
||||
## ¿Necesitas ayuda?
|
||||
|
||||
Consulta el README.md completo para documentación detallada.
|
||||
286
README.md
Normal file
286
README.md
Normal file
@@ -0,0 +1,286 @@
|
||||
# OpenAPI Clean Architecture Generator
|
||||
|
||||
Generador de código Angular con Clean Architecture desde archivos OpenAPI/Swagger.
|
||||
|
||||
## 🚀 Instalación
|
||||
|
||||
### Opción 1: Instalación Global
|
||||
|
||||
```bash
|
||||
npm install -g @openapitools/openapi-generator-cli
|
||||
npm install
|
||||
```
|
||||
|
||||
### Opción 2: Usar directamente
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run setup
|
||||
```
|
||||
|
||||
## 📖 Uso
|
||||
|
||||
### Comando básico
|
||||
|
||||
```bash
|
||||
node generate.js -i swagger.yaml
|
||||
```
|
||||
|
||||
### Opciones disponibles
|
||||
|
||||
```bash
|
||||
node generate.js [opciones]
|
||||
|
||||
Opciones:
|
||||
-V, --version Mostrar versión
|
||||
-i, --input <file> Archivo OpenAPI/Swagger (yaml o json) [default: swagger.yaml]
|
||||
-o, --output <dir> Directorio de salida [default: ./src/app]
|
||||
-t, --templates <dir> Directorio de templates personalizados [default: ./templates]
|
||||
--skip-install No instalar dependencias
|
||||
--dry-run Simular sin generar archivos
|
||||
-h, --help Mostrar ayuda
|
||||
```
|
||||
|
||||
### Ejemplos
|
||||
|
||||
```bash
|
||||
# Generar desde swagger.yaml en src/app
|
||||
node generate.js -i swagger.yaml -o ./src/app
|
||||
|
||||
# Usar templates personalizados
|
||||
node generate.js -i api.yaml -t ./mis-templates
|
||||
|
||||
# Modo de prueba (no genera archivos)
|
||||
node generate.js -i swagger.yaml --dry-run
|
||||
|
||||
# Especificar todos los parámetros
|
||||
node generate.js -i ./docs/api.yaml -o ./frontend/src/app -t ./custom-templates
|
||||
```
|
||||
|
||||
## 📁 Estructura Generada
|
||||
|
||||
El generador crea la siguiente estructura siguiendo Clean Architecture:
|
||||
|
||||
```
|
||||
src/app/
|
||||
├── data/ # Capa de datos
|
||||
│ ├── dtos/ # Data Transfer Objects
|
||||
│ │ ├── node/
|
||||
│ │ │ └── node.dto.ts
|
||||
│ │ ├── order-type/
|
||||
│ │ │ └── order-type.dto.ts
|
||||
│ │ └── supply-mode/
|
||||
│ │ └── supply-mode.dto.ts
|
||||
│ ├── repositories/ # Implementaciones de repositorios
|
||||
│ │ ├── node.repository.impl.ts
|
||||
│ │ ├── order-type.repository.impl.ts
|
||||
│ │ └── supply-mode.repository.impl.ts
|
||||
│ └── mappers/ # Transformadores DTO → Entidad
|
||||
│ ├── node.mapper.ts
|
||||
│ ├── order-type.mapper.ts
|
||||
│ └── supply-mode.mapper.ts
|
||||
├── domain/ # Capa de dominio
|
||||
│ ├── repositories/ # Contratos de repositorios
|
||||
│ │ ├── node.repository.contract.ts
|
||||
│ │ ├── order-type.repository.contract.ts
|
||||
│ │ └── supply-mode.repository.contract.ts
|
||||
│ └── use-cases/ # Casos de uso
|
||||
│ ├── node/
|
||||
│ │ ├── node.use-cases.contract.ts
|
||||
│ │ └── node.use-cases.impl.ts
|
||||
│ ├── order-type/
|
||||
│ │ ├── order-type.use-cases.contract.ts
|
||||
│ │ └── order-type.use-cases.impl.ts
|
||||
│ └── supply-mode/
|
||||
│ ├── supply-mode.use-cases.contract.ts
|
||||
│ └── supply-mode.use-cases.impl.ts
|
||||
├── di/ # Inyección de dependencias
|
||||
│ ├── repositories/ # Providers de repositorios
|
||||
│ │ ├── node.repository.provider.ts
|
||||
│ │ ├── order-type.repository.provider.ts
|
||||
│ │ └── supply-mode.repository.provider.ts
|
||||
│ └── use-cases/ # Providers de use cases
|
||||
│ ├── node.use-cases.provider.ts
|
||||
│ ├── order-type.use-cases.provider.ts
|
||||
│ └── supply-mode.use-cases.provider.ts
|
||||
└── entities/ # Entidades de dominio
|
||||
└── models/
|
||||
├── node.model.ts
|
||||
├── order-type.model.ts
|
||||
└── supply-mode.model.ts
|
||||
```
|
||||
|
||||
## 🔧 Personalización
|
||||
|
||||
### Modificar Templates
|
||||
|
||||
Los templates están en la carpeta `templates/`. Cada archivo `.mustache` define cómo se genera un tipo de archivo.
|
||||
|
||||
Templates disponibles:
|
||||
- `model.mustache` - DTOs
|
||||
- `model-entity.mustache` - Entidades del modelo
|
||||
- `mapper.mustache` - Mappers
|
||||
- `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
|
||||
|
||||
### Variables Mustache Disponibles
|
||||
|
||||
```mustache
|
||||
{{classname}} - Nombre de la clase (ej: "OrderType")
|
||||
{{classVarName}} - Nombre en camelCase (ej: "orderType")
|
||||
{{classFilename}} - Nombre del archivo (ej: "order-type")
|
||||
{{constantName}} - Constante (ej: "ORDER_TYPE")
|
||||
{{description}} - Descripción del schema
|
||||
{{httpMethod}} - Método HTTP (get, post, etc)
|
||||
{{path}} - Path del endpoint
|
||||
{{nickname}} - Nombre del método
|
||||
{{allParams}} - Todos los parámetros
|
||||
{{returnType}} - Tipo de retorno
|
||||
{{vars}} - Variables del modelo
|
||||
```
|
||||
|
||||
## 📊 Reporte de Generación
|
||||
|
||||
Después de cada generación, se crea un archivo `generation-report.json` con estadísticas:
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2025-01-15T10:30:00.000Z",
|
||||
"tags": 3,
|
||||
"endpoints": 8,
|
||||
"outputDirectory": "./src/app",
|
||||
"structure": {
|
||||
"dtos": 15,
|
||||
"repositories": 9,
|
||||
"mappers": 3,
|
||||
"useCases": 6
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 Ejemplo Completo
|
||||
|
||||
### 1. Preparar tu proyecto
|
||||
|
||||
```bash
|
||||
# Clonar o copiar el generador
|
||||
cd mi-proyecto-angular
|
||||
mkdir generator
|
||||
cd generator
|
||||
# Copiar archivos del generador aquí
|
||||
```
|
||||
|
||||
### 2. Copiar tu Swagger
|
||||
|
||||
```bash
|
||||
cp ../docs/api.yaml ./swagger.yaml
|
||||
```
|
||||
|
||||
### 3. Generar código
|
||||
|
||||
```bash
|
||||
node generate.js
|
||||
```
|
||||
|
||||
### 4. Registrar providers en Angular
|
||||
|
||||
En tu `app.module.ts` o `app.config.ts`:
|
||||
|
||||
```typescript
|
||||
import { NodeRepositoryProvider } from '@/di/repositories/node.repository.provider';
|
||||
import { NodeUseCasesProvider } from '@/di/use-cases/node.use-cases.provider';
|
||||
// ... importar otros providers
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
// Repositories
|
||||
NodeRepositoryProvider,
|
||||
OrderTypeRepositoryProvider,
|
||||
SupplyModeRepositoryProvider,
|
||||
|
||||
// Use Cases
|
||||
NodeUseCasesProvider,
|
||||
OrderTypeUseCasesProvider,
|
||||
SupplyModeUseCasesProvider
|
||||
]
|
||||
})
|
||||
export class AppModule {}
|
||||
```
|
||||
|
||||
### 5. Usar en componentes
|
||||
|
||||
```typescript
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { NODE_USE_CASES, NodeUseCases } from '@/domain/use-cases/node/node.use-cases.contract';
|
||||
|
||||
@Component({
|
||||
selector: 'app-nodes',
|
||||
template: `...`
|
||||
})
|
||||
export class NodesComponent {
|
||||
#nodeUseCases = inject(NODE_USE_CASES);
|
||||
|
||||
loadNodes() {
|
||||
this.#nodeUseCases.getNodes('TI').subscribe(nodes => {
|
||||
console.log(nodes);
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Error: openapi-generator-cli no encontrado
|
||||
|
||||
```bash
|
||||
npm install -g @openapitools/openapi-generator-cli
|
||||
# o
|
||||
npm run setup
|
||||
```
|
||||
|
||||
### Error: Archivo swagger.yaml no encontrado
|
||||
|
||||
Asegúrate de especificar la ruta correcta:
|
||||
```bash
|
||||
node generate.js -i ./ruta/a/tu/swagger.yaml
|
||||
```
|
||||
|
||||
### Los imports no se resuelven (@/ no funciona)
|
||||
|
||||
Configura los path aliases en tu `tsconfig.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["src/app/*"],
|
||||
"@environment": ["src/environments/environment"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Los templates no generan el código esperado
|
||||
|
||||
1. Verifica que tus templates están en `./templates/`
|
||||
2. Revisa la sintaxis Mustache
|
||||
3. Usa `--dry-run` para verificar sin generar archivos
|
||||
|
||||
## 📝 Notas
|
||||
|
||||
- El generador crea archivos `.ts`, no los compila
|
||||
- Los providers deben registrarse manualmente en tu módulo Angular
|
||||
- Asegúrate de tener configurado `@mercadona/common` o ajusta los imports en los templates
|
||||
- El generador asume Angular 17+ con inject() function
|
||||
|
||||
## 🤝 Contribuir
|
||||
|
||||
Si encuentras bugs o mejoras, siéntete libre de modificar los templates y el script según tus necesidades.
|
||||
|
||||
## 📄 Licencia
|
||||
|
||||
MIT
|
||||
150
example-swagger.yaml
Normal file
150
example-swagger.yaml
Normal file
@@ -0,0 +1,150 @@
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: Example API
|
||||
description: API de ejemplo para probar el generador
|
||||
version: 1.0.0
|
||||
tags:
|
||||
- name: User
|
||||
description: Operaciones de usuario
|
||||
- name: Product
|
||||
description: Operaciones de productos
|
||||
paths:
|
||||
/v1/users:
|
||||
get:
|
||||
tags:
|
||||
- User
|
||||
summary: Obtener lista de usuarios
|
||||
operationId: getUsers
|
||||
parameters:
|
||||
- name: search
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserResponse'
|
||||
post:
|
||||
tags:
|
||||
- User
|
||||
summary: Crear usuario
|
||||
operationId: createUser
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CreateUserRequest'
|
||||
responses:
|
||||
'201':
|
||||
description: Created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserSchema'
|
||||
/v1/users/{id}:
|
||||
get:
|
||||
tags:
|
||||
- User
|
||||
summary: Obtener usuario por ID
|
||||
operationId: getUserById
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserSchema'
|
||||
delete:
|
||||
tags:
|
||||
- User
|
||||
summary: Eliminar usuario
|
||||
operationId: deleteUser
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'204':
|
||||
description: No Content
|
||||
/v1/products:
|
||||
get:
|
||||
tags:
|
||||
- Product
|
||||
summary: Obtener lista de productos
|
||||
operationId: getProducts
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ProductResponse'
|
||||
components:
|
||||
schemas:
|
||||
UserSchema:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
example: 1
|
||||
name:
|
||||
type: string
|
||||
example: Juan Pérez
|
||||
email:
|
||||
type: string
|
||||
example: juan@example.com
|
||||
active:
|
||||
type: boolean
|
||||
example: true
|
||||
CreateUserRequest:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
- email
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: Juan Pérez
|
||||
email:
|
||||
type: string
|
||||
example: juan@example.com
|
||||
UserResponse:
|
||||
type: object
|
||||
properties:
|
||||
users:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UserSchema'
|
||||
ProductSchema:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
example: 100
|
||||
name:
|
||||
type: string
|
||||
example: Laptop HP
|
||||
price:
|
||||
type: number
|
||||
format: float
|
||||
example: 599.99
|
||||
ProductResponse:
|
||||
type: object
|
||||
properties:
|
||||
products:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ProductSchema'
|
||||
311
generate.js
Executable file
311
generate.js
Executable file
@@ -0,0 +1,311 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const yaml = require('js-yaml');
|
||||
const { program } = require('commander');
|
||||
|
||||
// Colores para console (sin dependencias externas)
|
||||
const colors = {
|
||||
reset: '\x1b[0m',
|
||||
bright: '\x1b[1m',
|
||||
green: '\x1b[32m',
|
||||
blue: '\x1b[34m',
|
||||
yellow: '\x1b[33m',
|
||||
red: '\x1b[31m',
|
||||
cyan: '\x1b[36m'
|
||||
};
|
||||
|
||||
function log(message, color = 'reset') {
|
||||
console.log(`${colors[color]}${message}${colors.reset}`);
|
||||
}
|
||||
|
||||
function logSuccess(message) {
|
||||
log(`✅ ${message}`, 'green');
|
||||
}
|
||||
|
||||
function logInfo(message) {
|
||||
log(`ℹ️ ${message}`, 'blue');
|
||||
}
|
||||
|
||||
function logWarning(message) {
|
||||
log(`⚠️ ${message}`, 'yellow');
|
||||
}
|
||||
|
||||
function logError(message) {
|
||||
log(`❌ ${message}`, 'red');
|
||||
}
|
||||
|
||||
function logStep(message) {
|
||||
log(`\n🚀 ${message}`, 'cyan');
|
||||
}
|
||||
|
||||
// Configuración del CLI
|
||||
program
|
||||
.name('generate-clean-arch')
|
||||
.description('Generador de código Angular con Clean Architecture desde OpenAPI/Swagger')
|
||||
.version('1.0.0')
|
||||
.option('-i, --input <file>', 'Archivo OpenAPI/Swagger (yaml o json)', 'swagger.yaml')
|
||||
.option('-o, --output <dir>', 'Directorio de salida', './src/app')
|
||||
.option('-t, --templates <dir>', 'Directorio de templates personalizados', './templates')
|
||||
.option('--skip-install', 'No instalar dependencias')
|
||||
.option('--dry-run', 'Simular sin generar archivos')
|
||||
.parse(process.argv);
|
||||
|
||||
const options = program.opts();
|
||||
|
||||
// Validar que existe openapi-generator-cli
|
||||
function checkOpenApiGenerator() {
|
||||
try {
|
||||
execSync('openapi-generator-cli version', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Instalar openapi-generator-cli
|
||||
function installOpenApiGenerator() {
|
||||
logStep('Instalando @openapitools/openapi-generator-cli...');
|
||||
try {
|
||||
execSync('npm install -g @openapitools/openapi-generator-cli', { stdio: 'inherit' });
|
||||
logSuccess('OpenAPI Generator CLI instalado correctamente');
|
||||
} catch (error) {
|
||||
logError('Error al instalar OpenAPI Generator CLI');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Crear estructura de directorios
|
||||
function createDirectoryStructure(baseDir) {
|
||||
const dirs = [
|
||||
path.join(baseDir, 'data/dtos'),
|
||||
path.join(baseDir, 'data/repositories'),
|
||||
path.join(baseDir, 'data/mappers'),
|
||||
path.join(baseDir, 'domain/repositories'),
|
||||
path.join(baseDir, 'domain/use-cases'),
|
||||
path.join(baseDir, 'di/repositories'),
|
||||
path.join(baseDir, 'di/use-cases'),
|
||||
path.join(baseDir, 'entities/models')
|
||||
];
|
||||
|
||||
dirs.forEach(dir => {
|
||||
fs.ensureDirSync(dir);
|
||||
});
|
||||
|
||||
logSuccess('Estructura de directorios creada');
|
||||
}
|
||||
|
||||
// Analizar el swagger para extraer tags y dominios
|
||||
function analyzeSwagger(swaggerFile) {
|
||||
logStep('Analizando archivo OpenAPI...');
|
||||
|
||||
try {
|
||||
const fileContent = fs.readFileSync(swaggerFile, 'utf8');
|
||||
const swagger = yaml.load(fileContent);
|
||||
|
||||
const tags = swagger.tags || [];
|
||||
const paths = swagger.paths || {};
|
||||
|
||||
logInfo(`Encontrados ${tags.length} tags en el API`);
|
||||
logInfo(`Encontrados ${Object.keys(paths).length} endpoints`);
|
||||
|
||||
tags.forEach(tag => {
|
||||
logInfo(` - ${tag.name}: ${tag.description || 'Sin descripción'}`);
|
||||
});
|
||||
|
||||
return { tags, paths, swagger };
|
||||
} catch (error) {
|
||||
logError(`Error al leer el archivo Swagger: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Generar código con OpenAPI Generator
|
||||
function generateCode(swaggerFile, templatesDir) {
|
||||
logStep('Generando código desde OpenAPI...');
|
||||
|
||||
const tempDir = path.join(process.cwd(), '.temp-generated');
|
||||
|
||||
// Limpiar directorio temporal
|
||||
if (fs.existsSync(tempDir)) {
|
||||
fs.removeSync(tempDir);
|
||||
}
|
||||
|
||||
try {
|
||||
const command = `openapi-generator-cli generate \
|
||||
-i "${swaggerFile}" \
|
||||
-g typescript-angular \
|
||||
-t "${templatesDir}" \
|
||||
-o "${tempDir}" \
|
||||
--additional-properties=ngVersion=17.0.0,withInterfaces=true,providedInRoot=false,supportsES6=true,modelPropertyNaming=camelCase`;
|
||||
|
||||
execSync(command, { stdio: 'inherit' });
|
||||
logSuccess('Código generado correctamente');
|
||||
|
||||
return tempDir;
|
||||
} catch (error) {
|
||||
logError('Error al generar código');
|
||||
if (fs.existsSync(tempDir)) {
|
||||
fs.removeSync(tempDir);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Organizar archivos según Clean Architecture
|
||||
function organizeFiles(tempDir, outputDir) {
|
||||
logStep('Organizando archivos en estructura Clean Architecture...');
|
||||
|
||||
const moves = [
|
||||
{ from: 'model', to: path.join(outputDir, 'data/dtos'), pattern: '*.dto.ts' },
|
||||
{ from: 'model', to: path.join(outputDir, 'entities/models'), pattern: '*.model.ts' },
|
||||
{ from: 'api', to: path.join(outputDir, 'domain/repositories'), pattern: '*.repository.contract.ts' },
|
||||
{ from: 'api', to: path.join(outputDir, 'data/repositories'), pattern: '*.repository.impl.ts' },
|
||||
{ from: 'api', to: path.join(outputDir, 'data/repositories'), pattern: '*.repository.mock.ts' },
|
||||
{ from: 'api', to: path.join(outputDir, 'data/mappers'), pattern: '*.mapper.ts' },
|
||||
{ from: 'api', to: path.join(outputDir, 'domain/use-cases'), pattern: '*.use-cases.contract.ts' },
|
||||
{ from: 'api', to: path.join(outputDir, 'domain/use-cases'), pattern: '*.use-cases.impl.ts' },
|
||||
{ from: 'providers', to: path.join(outputDir, 'di/repositories'), pattern: '*.repository.provider.ts' },
|
||||
{ from: 'providers', to: path.join(outputDir, 'di/use-cases'), pattern: '*.use-cases.provider.ts' }
|
||||
];
|
||||
|
||||
let filesMoved = 0;
|
||||
|
||||
moves.forEach(({ from, to, pattern }) => {
|
||||
const sourceDir = path.join(tempDir, from);
|
||||
|
||||
if (fs.existsSync(sourceDir)) {
|
||||
fs.ensureDirSync(to);
|
||||
|
||||
const files = fs.readdirSync(sourceDir).filter(file => {
|
||||
if (pattern.includes('*')) {
|
||||
const regex = new RegExp(pattern.replace('*', '.*'));
|
||||
return regex.test(file);
|
||||
}
|
||||
return file.endsWith(pattern);
|
||||
});
|
||||
|
||||
files.forEach(file => {
|
||||
const sourcePath = path.join(sourceDir, file);
|
||||
const destPath = path.join(to, file);
|
||||
|
||||
fs.copySync(sourcePath, destPath);
|
||||
filesMoved++;
|
||||
logInfo(` ${file} → ${path.relative(process.cwd(), destPath)}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
logSuccess(`${filesMoved} archivos organizados correctamente`);
|
||||
}
|
||||
|
||||
// Limpiar directorio temporal
|
||||
function cleanup(tempDir) {
|
||||
if (fs.existsSync(tempDir)) {
|
||||
fs.removeSync(tempDir);
|
||||
logInfo('Archivos temporales eliminados');
|
||||
}
|
||||
}
|
||||
|
||||
// Generar reporte
|
||||
function generateReport(outputDir, analysis) {
|
||||
logStep('Generando reporte de generación...');
|
||||
|
||||
const report = {
|
||||
timestamp: new Date().toISOString(),
|
||||
tags: analysis.tags.length,
|
||||
endpoints: Object.keys(analysis.paths).length,
|
||||
outputDirectory: outputDir,
|
||||
structure: {
|
||||
dtos: fs.readdirSync(path.join(outputDir, 'data/dtos')).length,
|
||||
repositories: fs.readdirSync(path.join(outputDir, 'data/repositories')).length,
|
||||
mappers: fs.readdirSync(path.join(outputDir, 'data/mappers')).length,
|
||||
useCases: fs.readdirSync(path.join(outputDir, 'domain/use-cases')).length
|
||||
}
|
||||
};
|
||||
|
||||
const reportPath = path.join(process.cwd(), 'generation-report.json');
|
||||
fs.writeJsonSync(reportPath, report, { spaces: 2 });
|
||||
|
||||
logSuccess(`Reporte guardado en: ${reportPath}`);
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
// Función principal
|
||||
async function main() {
|
||||
console.log('\n' + '='.repeat(60));
|
||||
log(' OpenAPI Clean Architecture Generator', 'bright');
|
||||
log(' Angular + Clean Architecture Code Generator', 'cyan');
|
||||
console.log('='.repeat(60) + '\n');
|
||||
|
||||
// Validar archivo de entrada
|
||||
if (!fs.existsSync(options.input)) {
|
||||
logError(`Archivo no encontrado: ${options.input}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
logInfo(`Archivo de entrada: ${options.input}`);
|
||||
logInfo(`Directorio de salida: ${options.output}`);
|
||||
logInfo(`Templates: ${options.templates}`);
|
||||
|
||||
if (options.dryRun) {
|
||||
logWarning('Modo DRY RUN - No se generarán archivos');
|
||||
}
|
||||
|
||||
// Verificar/Instalar OpenAPI Generator
|
||||
if (!checkOpenApiGenerator()) {
|
||||
logWarning('OpenAPI Generator CLI no encontrado');
|
||||
if (!options.skipInstall) {
|
||||
installOpenApiGenerator();
|
||||
} else {
|
||||
logError('Instala openapi-generator-cli con: npm install -g @openapitools/openapi-generator-cli');
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
logSuccess('OpenAPI Generator CLI encontrado');
|
||||
}
|
||||
|
||||
// Analizar Swagger
|
||||
const analysis = analyzeSwagger(options.input);
|
||||
|
||||
if (options.dryRun) {
|
||||
logInfo('Finalizando en modo DRY RUN');
|
||||
return;
|
||||
}
|
||||
|
||||
// Crear estructura de directorios
|
||||
createDirectoryStructure(options.output);
|
||||
|
||||
// Generar código
|
||||
const tempDir = generateCode(options.input, options.templates);
|
||||
|
||||
// Organizar archivos
|
||||
organizeFiles(tempDir, options.output);
|
||||
|
||||
// Limpiar
|
||||
cleanup(tempDir);
|
||||
|
||||
// Generar reporte
|
||||
const report = generateReport(options.output, analysis);
|
||||
|
||||
// Resumen final
|
||||
console.log('\n' + '='.repeat(60));
|
||||
log(' ✨ Generación completada con éxito', 'green');
|
||||
console.log('='.repeat(60));
|
||||
console.log(`\n📊 Resumen:`);
|
||||
console.log(` - DTOs generados: ${report.structure.dtos}`);
|
||||
console.log(` - Repositories: ${report.structure.repositories}`);
|
||||
console.log(` - Mappers: ${report.structure.mappers}`);
|
||||
console.log(` - Use Cases: ${report.structure.useCases}`);
|
||||
console.log(`\n📁 Archivos generados en: ${colors.cyan}${options.output}${colors.reset}\n`);
|
||||
}
|
||||
|
||||
// Ejecutar
|
||||
main().catch(error => {
|
||||
logError(`Error fatal: ${error.message}`);
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
23
openapitools.json
Normal file
23
openapitools.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json",
|
||||
"spaces": 2,
|
||||
"generator-cli": {
|
||||
"version": "7.2.0",
|
||||
"generators": {
|
||||
"typescript-angular-clean": {
|
||||
"generatorName": "typescript-angular",
|
||||
"output": "./.temp-generated",
|
||||
"glob": "**/*",
|
||||
"additionalProperties": {
|
||||
"ngVersion": "17.0.0",
|
||||
"modelPropertyNaming": "camelCase",
|
||||
"supportsES6": true,
|
||||
"withInterfaces": true,
|
||||
"providedInRoot": false,
|
||||
"npmName": "api-client",
|
||||
"npmVersion": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
package.json
Normal file
31
package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "openapi-clean-arch-generator",
|
||||
"version": "1.0.0",
|
||||
"description": "Generador de código Angular con Clean Architecture desde OpenAPI/Swagger",
|
||||
"main": "generate.js",
|
||||
"bin": {
|
||||
"generate-clean-arch": "./generate.js"
|
||||
},
|
||||
"scripts": {
|
||||
"generate": "node generate.js",
|
||||
"setup": "npm install -g @openapitools/openapi-generator-cli"
|
||||
},
|
||||
"keywords": [
|
||||
"openapi",
|
||||
"swagger",
|
||||
"angular",
|
||||
"clean-architecture",
|
||||
"code-generator"
|
||||
],
|
||||
"author": "Blas",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"commander": "^11.1.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
}
|
||||
34
templates/api.repository.contract.mustache
Normal file
34
templates/api.repository.contract.mustache
Normal file
@@ -0,0 +1,34 @@
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
import { InjectionToken } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
{{#imports}}
|
||||
import { {{classname}} } from '@/entities/models/{{classFilename}}.model';
|
||||
{{/imports}}
|
||||
|
||||
/**
|
||||
* {{classname}} Repository Contract
|
||||
* Generated from OpenAPI tag: {{classname}}
|
||||
*/
|
||||
export interface {{classname}}Repository {
|
||||
{{#operation}}
|
||||
/**
|
||||
* {{summary}}
|
||||
{{#notes}}
|
||||
* {{notes}}
|
||||
{{/notes}}
|
||||
{{#allParams}}
|
||||
* @param {{paramName}} {{description}}
|
||||
{{/allParams}}
|
||||
*/
|
||||
{{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{dataType}}{{^-last}}, {{/-last}}{{/allParams}}): Observable<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}void{{/returnType}}>;
|
||||
|
||||
{{/operation}}
|
||||
}
|
||||
|
||||
export const {{constantName}}_REPOSITORY = new InjectionToken<{{classname}}Repository>('{{constantName}}_REPOSITORY');
|
||||
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
61
templates/api.repository.impl.mustache
Normal file
61
templates/api.repository.impl.mustache
Normal file
@@ -0,0 +1,61 @@
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { environment } from '@environment';
|
||||
|
||||
import { MRepository } from '@mercadona/core/utils/repository';
|
||||
|
||||
import { {{classname}}Repository } from '../../../domain/repositories/{{classFilename}}.repository.contract';
|
||||
{{#imports}}
|
||||
import { {{classname}}Dto } from '@/dtos/{{classFilename}}/{{classFilename}}.dto';
|
||||
import { {{classname}} } from '@/entities/models/{{classFilename}}.model';
|
||||
import { {{classVarName}}Mapper } from '@/mappers/{{classFilename}}/{{classFilename}}.mapper';
|
||||
{{/imports}}
|
||||
|
||||
/**
|
||||
* {{classname}} Repository Implementation
|
||||
* Generated from OpenAPI tag: {{classname}}
|
||||
*/
|
||||
@Injectable()
|
||||
export class {{classname}}RepositoryImpl extends MRepository implements {{classname}}Repository {
|
||||
constructor() {
|
||||
super(`${environment.modapApi.url}`);
|
||||
}
|
||||
|
||||
{{#operation}}
|
||||
{{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{dataType}}{{^-last}}, {{/-last}}{{/allParams}}): Observable<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}void{{/returnType}}> {
|
||||
{{#isListContainer}}
|
||||
return this.{{httpMethod}}<{{returnBaseType}}Dto>('{{path}}'{{#hasQueryParams}}, {
|
||||
params: { {{#queryParams}}{{paramName}}{{^-last}}, {{/-last}}{{/queryParams}} }
|
||||
}{{/hasQueryParams}}{{#hasBodyParam}}, {{bodyParam}}{{/hasBodyParam}})
|
||||
.pipe(
|
||||
map((response) => response.{{#vendorExtensions}}{{x-response-property}}{{/vendorExtensions}}{{^vendorExtensions}}items{{/vendorExtensions}}.map({{returnBaseType}}Mapper))
|
||||
);
|
||||
{{/isListContainer}}
|
||||
{{^isListContainer}}
|
||||
{{#returnType}}
|
||||
return this.{{httpMethod}}<{{returnType}}Dto>('{{path}}'{{#hasQueryParams}}, {
|
||||
params: { {{#queryParams}}{{paramName}}{{^-last}}, {{/-last}}{{/queryParams}} }
|
||||
}{{/hasQueryParams}}{{#hasBodyParam}}, {{bodyParam}}{{/hasBodyParam}})
|
||||
.pipe(
|
||||
map({{returnType}}Mapper)
|
||||
);
|
||||
{{/returnType}}
|
||||
{{^returnType}}
|
||||
return this.{{httpMethod}}<void>('{{path}}'{{#hasQueryParams}}, {
|
||||
params: { {{#queryParams}}{{paramName}}{{^-last}}, {{/-last}}{{/queryParams}} }
|
||||
}{{/hasQueryParams}}{{#hasBodyParam}}, {{bodyParam}}{{/hasBodyParam}});
|
||||
{{/returnType}}
|
||||
{{/isListContainer}}
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
}
|
||||
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
34
templates/api.use-cases.contract.mustache
Normal file
34
templates/api.use-cases.contract.mustache
Normal file
@@ -0,0 +1,34 @@
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
import { InjectionToken } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
{{#imports}}
|
||||
import { {{classname}} } from '@/entities/models/{{classFilename}}.model';
|
||||
{{/imports}}
|
||||
|
||||
/**
|
||||
* {{classname}} Use Cases Contract
|
||||
* Generated from OpenAPI tag: {{classname}}
|
||||
*/
|
||||
export interface {{classname}}UseCases {
|
||||
{{#operation}}
|
||||
/**
|
||||
* {{summary}}
|
||||
{{#notes}}
|
||||
* {{notes}}
|
||||
{{/notes}}
|
||||
{{#allParams}}
|
||||
* @param {{paramName}} {{description}}
|
||||
{{/allParams}}
|
||||
*/
|
||||
{{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{dataType}}{{^-last}}, {{/-last}}{{/allParams}}): Observable<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}void{{/returnType}}>;
|
||||
|
||||
{{/operation}}
|
||||
}
|
||||
|
||||
export const {{constantName}}_USE_CASES = new InjectionToken<{{classname}}UseCases>('{{constantName}}_USE_CASES');
|
||||
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
32
templates/api.use-cases.impl.mustache
Normal file
32
templates/api.use-cases.impl.mustache
Normal file
@@ -0,0 +1,32 @@
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { {{classname}}UseCases } from './{{classFilename}}.use-cases.contract';
|
||||
|
||||
import { {{constantName}}_REPOSITORY, {{classname}}Repository } from '@/domain/repositories/{{classFilename}}.repository.contract';
|
||||
{{#imports}}
|
||||
import { {{classname}} } from '@/entities/models/{{classFilename}}.model';
|
||||
{{/imports}}
|
||||
|
||||
/**
|
||||
* {{classname}} Use Cases Implementation
|
||||
* Generated from OpenAPI tag: {{classname}}
|
||||
*/
|
||||
@Injectable()
|
||||
export class {{classname}}UseCasesImpl implements {{classname}}UseCases {
|
||||
#{{classVarName}}Repository: {{classname}}Repository = inject({{constantName}}_REPOSITORY);
|
||||
|
||||
{{#operation}}
|
||||
{{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{dataType}}{{^-last}}, {{/-last}}{{/allParams}}): Observable<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}void{{/returnType}}> {
|
||||
return this.#{{classVarName}}Repository.{{nickname}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
}
|
||||
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
28
templates/mapper.mustache
Normal file
28
templates/mapper.mustache
Normal file
@@ -0,0 +1,28 @@
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
import { MapFromFn } from '@mercadona/common/public';
|
||||
import { Builder } from '@mercadona/common/utils';
|
||||
|
||||
import { {{classname}}Dto } from '@/dtos/{{classFilename}}/{{classFilename}}.dto';
|
||||
import { {{classname}} } from '@/entities/models/{{classFilename}}.model';
|
||||
|
||||
/**
|
||||
* {{classname}} Mapper
|
||||
* Converts DTO to Domain Entity
|
||||
* Generated from OpenAPI schema: {{classname}}
|
||||
*/
|
||||
export const {{classVarName}}Mapper: MapFromFn<{{classname}}Dto, {{classname}}> = (dto: {{classname}}Dto): {{classname}} =>
|
||||
Builder.forModel({{classname}})
|
||||
{{#allModels}}
|
||||
{{#model}}
|
||||
{{#vars}}
|
||||
.{{name}}(dto.{{name}})
|
||||
{{/vars}}
|
||||
{{/model}}
|
||||
{{/allModels}}
|
||||
.build();
|
||||
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
24
templates/model-entity.mustache
Normal file
24
templates/model-entity.mustache
Normal file
@@ -0,0 +1,24 @@
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
{{#imports}}
|
||||
import { {{classname}} } from './{{classFilename}}.model';
|
||||
{{/imports}}
|
||||
|
||||
/**
|
||||
* {{classname}} Entity
|
||||
* {{#description}}{{description}}{{/description}}
|
||||
* Generated from OpenAPI schema
|
||||
*/
|
||||
export class {{classname}} {
|
||||
{{#vars}}
|
||||
{{#description}}
|
||||
/**
|
||||
* {{description}}
|
||||
*/
|
||||
{{/description}}
|
||||
{{name}}{{^required}}?{{/required}}: {{dataType}};
|
||||
{{/vars}}
|
||||
}
|
||||
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
20
templates/model.mustache
Normal file
20
templates/model.mustache
Normal file
@@ -0,0 +1,20 @@
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
/**
|
||||
* {{classname}} DTO
|
||||
* {{#description}}{{description}}{{/description}}
|
||||
* Generated from OpenAPI specification
|
||||
*/
|
||||
export interface {{classname}}Dto {
|
||||
{{#vars}}
|
||||
{{#description}}
|
||||
/**
|
||||
* {{description}}
|
||||
*/
|
||||
{{/description}}
|
||||
{{name}}{{^required}}?{{/required}}: {{dataType}};
|
||||
{{/vars}}
|
||||
}
|
||||
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
20
templates/repository.provider.mustache
Normal file
20
templates/repository.provider.mustache
Normal file
@@ -0,0 +1,20 @@
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
import { Provider } from '@angular/core';
|
||||
|
||||
import { {{constantName}}_REPOSITORY } from '@/domain/repositories/{{classFilename}}.repository.contract';
|
||||
import { {{classname}}RepositoryImpl } from '@/data/repositories/{{classFilename}}.repository.impl';
|
||||
|
||||
/**
|
||||
* {{classname}} Repository Provider
|
||||
* Binds the repository contract with its implementation
|
||||
*/
|
||||
export const {{classname}}RepositoryProvider: Provider = {
|
||||
provide: {{constantName}}_REPOSITORY,
|
||||
useClass: {{classname}}RepositoryImpl
|
||||
};
|
||||
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
20
templates/use-cases.provider.mustache
Normal file
20
templates/use-cases.provider.mustache
Normal file
@@ -0,0 +1,20 @@
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
import { Provider } from '@angular/core';
|
||||
|
||||
import { {{constantName}}_USE_CASES } from '@/domain/use-cases/{{classFilename}}/{{classFilename}}.use-cases.contract';
|
||||
import { {{classname}}UseCasesImpl } from '@/domain/use-cases/{{classFilename}}/{{classFilename}}.use-cases.impl';
|
||||
|
||||
/**
|
||||
* {{classname}} Use Cases Provider
|
||||
* Binds the use cases contract with its implementation
|
||||
*/
|
||||
export const {{classname}}UseCasesProvider: Provider = {
|
||||
provide: {{constantName}}_USE_CASES,
|
||||
useClass: {{classname}}UseCasesImpl
|
||||
};
|
||||
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
Reference in New Issue
Block a user