Herramientas CLI
Fox Framework incluye un potente sistema de línea de comandos (CLI) que facilita la creación, desarrollo y mantenimiento de aplicaciones. Esta herramienta está diseñada para incrementar la productividad del desarrollador, automatizar tareas repetitivas y mantener la consistencia del código.
Características Principales
- Scaffolding de proyectos y componentes
- Generación automática de código (controladores, servicios, etc.)
- Migración y gestión de bases de datos
- Testing y diagnóstico de aplicaciones
- Despliegue y gestión de entornos
- Extensible mediante plugins personalizados
- Interactivo con prompts y asistentes
- Documentación integrada y contextual
Instalación
La CLI de Fox Framework se puede instalar globalmente para usarla en cualquier proyecto:
# Instalación global
npm install -g fox-framework-cli
# O ejecutarla directamente con npx
npx fox-framework-cli [comando]También puedes instalarla como dependencia de desarrollo en tu proyecto:
# Instalación local como dependencia de desarrollo
npm install --save-dev fox-framework-cliDespués de la instalación, la CLI estará disponible a través del comando fox:
fox --helpComandos Básicos
Crear un Nuevo Proyecto
# Crear un nuevo proyecto usando el asistente interactivo
fox new my-project
# Crear con opciones específicas
fox new my-project --template api --typescript --dockerOpciones disponibles:
--template: Tipo de proyecto (api,web,monorepo,microservices)--typescript: Configurar proyecto con TypeScript--docker: Incluir configuración Docker--git: Inicializar repositorio Git--install: Instalar dependencias automáticamente--skip-prompts: Usar configuración por defecto sin preguntar
Generar Componentes
# Generar un nuevo controlador
fox generate controller UserController
# Forma abreviada
fox g controller UserController
# Con opciones adicionales
fox g controller UserController --resource --model=UserTipos de componentes que se pueden generar:
controller: Controladores para gestionar peticiones HTTPservice: Servicios para lógica de negociomiddleware: Middleware para procesamiento de peticionesmodel: Modelos de datosrepository: Repositorios para acceso a datosvalidator: Validadores de datosinterface: Interfaces TypeScripttest: Tests unitarios o de integraciónview: Plantillas de vistas
Opciones comunes:
--dry-run: Mostrar qué archivos se crearían sin generarlos realmente--force: Sobrescribir archivos existentes--path: Ubicación específica donde generar los archivos--spec: Generar también archivos de test
Ejecutar la Aplicación
# Iniciar la aplicación en modo desarrollo
fox start
# Iniciar con opciones específicas
fox start --port=3000 --env=dev --watchOpciones:
--port: Puerto en el que iniciar la aplicación--env: Entorno (dev,test,prod)--watch: Reiniciar automáticamente al detectar cambios--debug: Activar modo debug--inspect: Activar inspector de Node.js
Administrar el Proyecto
# Ver información sobre el proyecto
fox info
# Verificar consistencia y buenas prácticas
fox lint
# Actualizar framework y dependencias
fox update
# Limpiar archivos temporales y cachés
fox cleanGeneración de Código
Controladores
# Generar controlador básico
fox g controller UserController
# Controlador CRUD completo
fox g controller UserController --resource --model=User
# Controlador con opciones personalizadas
fox g controller PaymentController --methods=process,verify,refundEsto generará archivos como:
src/controllers/user.controller.ts
src/controllers/__tests__/user.controller.test.tsEjemplo de controlador generado:
import { Controller, Get, Post, Put, Delete, HttpContext } from '@foxframework/core';
import { UserService } from '../services/user.service';
@Controller('/users')
export class UserController {
constructor(private userService: UserService) {}
@Get('/')
async getAll(ctx: HttpContext) {
const users = await this.userService.findAll(ctx.query);
return users;
}
@Get('/:id')
async getOne(ctx: HttpContext) {
const user = await this.userService.findById(ctx.params.id);
if (!user) {
ctx.status = 404;
return { error: 'User not found' };
}
return user;
}
@Post('/')
async create(ctx: HttpContext) {
const user = await this.userService.create(ctx.body);
ctx.status = 201;
return user;
}
@Put('/:id')
async update(ctx: HttpContext) {
const updated = await this.userService.update(ctx.params.id, ctx.body);
return updated;
}
@Delete('/:id')
async delete(ctx: HttpContext) {
await this.userService.delete(ctx.params.id);
ctx.status = 204;
return null;
}
}Servicios
# Generar servicio básico
fox g service UserService
# Servicio con modelo e inyección
fox g service PaymentService --model=Payment --inject=PaymentGateway,NotificationServiceEjemplo de servicio generado:
import { Injectable } from '@foxframework/core';
import { User } from '../models/user.model';
import { UserRepository } from '../repositories/user.repository';
@Injectable()
export class UserService {
constructor(private userRepository: UserRepository) {}
async findAll(filters = {}) {
return this.userRepository.findAll(filters);
}
async findById(id: string) {
return this.userRepository.findById(id);
}
async create(userData: Partial<User>) {
// Validación y lógica de negocio aquí
return this.userRepository.create(userData);
}
async update(id: string, userData: Partial<User>) {
return this.userRepository.update(id, userData);
}
async delete(id: string) {
return this.userRepository.delete(id);
}
}Middleware
# Generar middleware básico
fox g middleware AuthMiddleware
# Middleware con opciones
fox g middleware RateLimiterMiddleware --config=rate-limiterEjemplo de middleware generado:
import { Middleware, HttpContext, NextFunction } from '@foxframework/core';
@Middleware()
export class AuthMiddleware {
async handle(ctx: HttpContext, next: NextFunction) {
// Obtener y verificar token
const token = ctx.headers.authorization?.split('Bearer ')[1];
if (!token) {
ctx.status = 401;
return { error: 'Authorization token required' };
}
try {
// Verificar token y extraer información del usuario
const user = await this.verifyToken(token);
// Añadir usuario al contexto
ctx.auth = { user };
// Continuar con la cadena de middleware
return next();
} catch (error) {
ctx.status = 401;
return { error: 'Invalid token' };
}
}
private async verifyToken(token: string) {
// Implementar verificación de token
// ...
return { id: '123', role: 'user' };
}
}Modelos
# Generar modelo básico
fox g model User
# Modelo con atributos
fox g model Product --attrs="name:string,price:number,description:string"
# Modelo con relaciones
fox g model Order --attrs="total:number,status:string" --relations="user:belongsTo,items:hasMany"Ejemplo de modelo generado:
import { Model, Field, Required, Min, Max, HasMany } from '@foxframework/database';
@Model('users')
export class User {
@Field({ primary: true })
id: string;
@Field()
@Required()
name: string;
@Field()
@Required()
email: string;
@Field({ secure: true })
@Required()
password: string;
@Field()
role: string = 'user';
@Field()
createdAt: Date = new Date();
@Field()
updatedAt: Date = new Date();
@HasMany(() => Order)
orders: Order[];
}Proyectos Completos
# Crear una API REST completa
fox new my-api --template api
# Crear una aplicación web con frontend
fox new my-web-app --template web
# Crear una arquitectura de microservicios
fox new my-system --template microservicesGestión de Base de Datos
Migraciones
# Crear una nueva migración
fox g migration CreateUsersTable
# Ejecutar migraciones pendientes
fox db:migrate
# Revertir última migración
fox db:rollback
# Ver estado de migraciones
fox db:statusEjemplo de una migración generada:
import { Migration } from '@foxframework/database';
export default class CreateUsersTable implements Migration {
async up(db) {
await db.schema.createTable('users', table => {
table.uuid('id').primary();
table.string('name').notNullable();
table.string('email').notNullable().unique();
table.string('password').notNullable();
table.string('role').defaultTo('user');
table.timestamps(true, true);
});
}
async down(db) {
await db.schema.dropTable('users');
}
}Seeders
# Crear un seeder
fox g seeder UsersSeeder
# Ejecutar todos los seeders
fox db:seed
# Ejecutar un seeder específico
fox db:seed UsersSeederEjemplo de seeder generado:
import { Seeder } from '@foxframework/database';
import { User } from '../models/user.model';
export default class UsersSeeder implements Seeder {
async run(db) {
// Crear usuarios de ejemplo
await db.table('users').insert([
{
id: '550e8400-e29b-41d4-a716-446655440000',
name: 'Admin User',
email: 'admin@example.com',
password: await this.hashPassword('admin123'),
role: 'admin'
},
{
id: '550e8400-e29b-41d4-a716-446655440001',
name: 'Test User',
email: 'user@example.com',
password: await this.hashPassword('user123'),
role: 'user'
}
]);
}
private async hashPassword(password: string): Promise<string> {
// Implementar hash de contraseña
return password; // En un caso real, hacer hash
}
}Testing
Ejecutar Tests
# Ejecutar todos los tests
fox test
# Ejecutar tests con cobertura
fox test --coverage
# Ejecutar tests específicos
fox test --pattern="user.*"
# Ejecutar en modo watch
fox test --watchGenerar Tests
# Generar test unitario
fox g test unit UserService
# Generar test de integración
fox g test integration UserController
# Generar test end-to-end
fox g test e2e UserFlowEjemplo de test unitario generado:
import { describe, it, expect, beforeEach, mock } from '@foxframework/testing';
import { UserService } from '../../services/user.service';
import { UserRepository } from '../../repositories/user.repository';
describe('UserService', () => {
let userService: UserService;
let userRepository: jest.Mocked<UserRepository>;
beforeEach(() => {
// Crear mock del repositorio
userRepository = {
findAll: jest.fn(),
findById: jest.fn(),
create: jest.fn(),
update: jest.fn(),
delete: jest.fn()
} as any;
// Crear instancia de servicio con dependencia mockeada
userService = new UserService(userRepository);
});
describe('findAll', () => {
it('should return all users', async () => {
// Arrange
const mockUsers = [
{ id: '1', name: 'User 1' },
{ id: '2', name: 'User 2' }
];
userRepository.findAll.mockResolvedValue(mockUsers);
// Act
const result = await userService.findAll();
// Assert
expect(userRepository.findAll).toHaveBeenCalled();
expect(result).toEqual(mockUsers);
});
});
describe('create', () => {
it('should create a user', async () => {
// Arrange
const userData = { name: 'New User', email: 'new@example.com' };
const createdUser = { id: '3', ...userData };
userRepository.create.mockResolvedValue(createdUser);
// Act
const result = await userService.create(userData);
// Assert
expect(userRepository.create).toHaveBeenCalledWith(userData);
expect(result).toEqual(createdUser);
});
});
// Más tests...
});Despliegue y Entornos
Configuración de Entornos
# Configurar un nuevo entorno
fox env:setup production
# Generar archivos .env para distintos entornos
fox env:create --template
# Verificar configuración de entorno
fox env:check production
# Listar variables de entorno
fox env:listDespliegue
# Preparar para despliegue
fox deploy:build --env=production
# Desplegar a entorno específico
fox deploy --target=server1 --env=production
# Configurar opciones de despliegue
fox deploy:configExtensiones y Personalización
Crear Plugin
# Generar estructura básica de plugin
fox plugin:create fox-plugin-stripe
# Instalar plugin existente
fox plugin:install fox-plugin-stripeEstructura típica de un plugin:
fox-plugin-stripe/
├── README.md
├── package.json
├── src/
│ ├── index.ts
│ ├── types.ts
│ ├── services/
│ │ └── stripe.service.ts
│ └── controllers/
│ └── payment.controller.ts
└── templates/
└── config.template.tsCrear Comandos Personalizados
Puedes extender la CLI con tus propios comandos creando un archivo .foxrc.js en la raíz de tu proyecto:
// .foxrc.js
module.exports = {
commands: {
// Comando personalizado
'clean:logs': {
description: 'Eliminar archivos de log antiguos',
action: async (args) => {
const { exec } = require('child_process');
const days = args.days || 7;
console.log(`Eliminando logs de más de ${days} días...`);
exec(`find ./logs -type f -name "*.log" -mtime +${days} -delete`,
(error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error.message}`);
return;
}
console.log('Logs antiguos eliminados correctamente');
}
);
},
options: [
{ name: 'days', type: 'number', description: 'Días para considerar un log como antiguo' }
]
}
},
// Hooks para eventos del ciclo de vida
hooks: {
'pre-build': () => console.log('Ejecutando tareas antes del build...'),
'post-build': () => console.log('Build completado, ejecutando tareas finales...')
},
// Plantillas personalizadas
templates: {
'custom-controller': {
description: 'Controlador con estructura personalizada',
files: {
'src/controllers/{name}.controller.ts': require.resolve('./templates/custom-controller.template.ts')
}
}
}
};Para usar este comando personalizado:
fox clean:logs --days=30Configurar Defaults
También puedes configurar opciones por defecto en .foxrc.js:
module.exports = {
// Configuración global
config: {
// Estructura de directorios personalizada
paths: {
controllers: 'src/api/controllers',
services: 'src/services',
models: 'src/domain/models',
repositories: 'src/infrastructure/repositories'
},
// Opciones por defecto para generadores
generators: {
controller: {
template: 'custom-controller',
includeSpec: true
},
model: {
baseClass: 'BaseModel',
timestamps: true
}
}
}
};Interacción y UX
Modo Interactivo
# Iniciar CLI en modo interactivo
fox interactive
# O la versión corta
fox iEsto iniciará una interfaz interactiva con:
- Historial de comandos
- Autocompletado
- Sugerencias contextuales
- Navegación de opciones
Asistentes y Prompts
La CLI utiliza prompts interactivos para guiarte en la creación de componentes:
fox createMostrará un asistente paso a paso:
- Selección del tipo de componente
- Configuración de opciones
- Confirmación y previsualización
- Generación de archivos
Diagnóstico y Solución de Problemas
Información del Sistema
# Ver información detallada del proyecto y entorno
fox info --detailed
# Verificar si hay problemas conocidos
fox doctorEsto mostrará:
- Versiones de dependencias
- Configuración del entorno
- Problemas potenciales
- Sugerencias de optimización
Logs y Depuración
# Ver logs de la CLI
fox logs
# Ejecutar en modo verbose
fox [comando] --verbose
# Depurar problemas
fox debug [problema]Comandos Adicionales
Gestión de Módulos
# Generar un nuevo módulo (agrupación lógica)
fox g module UserManagement
# Listar módulos
fox module:list
# Describir estructura de un módulo
fox module:describe UserManagementDocumentación
# Generar documentación automática
fox docs:generate
# Visualizar documentación localmente
fox docs:serve
# Verificar cobertura de documentación
fox docs:coverageAnálisis de Código
# Ejecutar linter
fox lint
# Arreglar problemas automáticamente
fox lint --fix
# Analizar estructura y dependencias
fox analyze
# Verificar cumplimiento de mejores prácticas
fox qualityIntegración con IDEs
Fox CLI proporciona integración con los principales IDEs:
Visual Studio Code
Instala la extensión "Fox Framework Tools" para:
- Snippets y autocompletado
- Comandos integrados en la paleta
- Diagnóstico en tiempo real
- Vista de estructura del proyecto
WebStorm/IntelliJ
Configura los scripts externos en tu IDE:
- Settings → Tools → External Tools
- Añadir comandos fox como herramientas externas
- Asignar atajos de teclado
Buenas Prácticas
Estructura del Proyecto
La CLI promueve una estructura consistente:
src/
├── controllers/ # Controladores HTTP
├── services/ # Lógica de negocio
├── models/ # Modelos de datos
├── repositories/ # Acceso a datos
├── middleware/ # Middleware HTTP
├── validators/ # Validación de datos
├── config/ # Configuración
├── utils/ # Utilidades generales
└── types/ # Definiciones TypeScriptGeneración vs Modificación
- Usa
--dry-runpara previsualizar cambios - Preferiblemente genera código nuevo en vez de modificar existente
- Para modificaciones estructurales, usa
refactoren lugar degenerate
Trabajo en Equipo
- Commitea los archivos
.foxrc.jspara compartir configuración - Documenta comandos personalizados
- Usa
--templatepara mantener consistencia en el equipo
Conclusión
La herramienta CLI de Fox Framework es un componente fundamental del ecosistema, diseñada para acelerar el desarrollo y mantener la consistencia del código. Con funcionalidades para scaffolding, generación de código, testing, despliegue y más, la CLI te permite centrarte en construir tu aplicación en lugar de en tareas repetitivas.
Las características de personalización y extensión permiten adaptar la herramienta a las necesidades específicas de cada equipo y proyecto, mientras que la integración con IDEs y otras herramientas la hacen parte natural del flujo de trabajo del desarrollador.
Para obtener ayuda detallada sobre cualquier comando, utiliza:
fox help [comando]Para mantenerte al día con las últimas actualizaciones y características:
fox update
fox changelog