UNPKG

vyndra-js

Version:

Micro Node.js framework with routing, ORM, decorators, and automatic DI

431 lines (325 loc) 9.66 kB
# VyndraJS **VyndraJS** es un **micro-framework para Node.js y TypeScript** que combina **routing**, **ORM**, **inyección automática de dependencias (DI)** y **decoradores modernos**. Está diseñado para crear **APIs, microservicios y arquitecturas modulares** de manera rápida, limpia y escalable. VyndraJS busca ofrecer una **estructura de código coherente, predecible y moderna**, con soporte nativo para **autoimportación de componentes**, **publicación de eventos con RabbitMQ** y un **CLI oficial** para automatizar tareas comunes. --- ## Instalación ```bash npm install vyndra-js npm install -g vyndra-js ``` --- ## Estructura recomendada ``` src/ ├─ controllers/ └─ user.controller.ts ├─ services/ └─ user.service.ts ├─ repositories/ └─ user.repository.ts ├─ models/ └─ user.model.ts ├─ listeners/ └─ auth.listener.ts └─ main.ts ``` > VyndraJS **autoimporta** automáticamente todos los archivos con sufijos `.controller.js` y `.service.ts` al iniciar la aplicación. --- ## Requisitos y consideraciones ### Requisitos básicos Antes de usar VyndraJS, asegúrate de tener: - **Node.js 18 o superior** - **TypeScript** instalado global o localmente ```bash npm install -D typescript ts-node ``` - Archivo `tsconfig.json` configurado con decoradores habilitados: ```json { "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "NodeNext", "experimentalDecorators": true, "emitDecoratorMetadata": true } } ``` --- ### Requisitos opcionales: RabbitMQ VyndraJS ofrece integración nativa con **RabbitMQ** para manejar **eventos asíncronos** mediante decoradores como `@Publish()` y `@QueueListenerMethod()`. Puedes habilitar RabbitMQ de dos maneras: #### 1. Usando variables de entorno: ```bash MESSAGE_BROKER_PORT=5672 MESSAGE_BROKER_HOST=amqps://user:pass@bunny.cloudamqp.com/vhost MESSAGE_BROKER_TIMEOUT=15000 MESSAGE_BROKER_AMQP=5672 MESSAGE_BROKER_MANAGEMENT=15672 MESSAGE_BROKER_IMAGE=rabbitmq:3-management ``` #### 2. Dejando que VyndraJS cree un contenedor automáticamente: ```ts const app = new App({ docker: { os: "windows" } // "linux" | "mac" }); ``` #### 3. Creandolo por comandos CLI: ```ts vyndra create:broker <os> // "windows" | "linux" | "mac" ``` > Esto descargará la imagen oficial de **RabbitMQ** y creará un contenedor configurado para ejecutarse junto a la aplicación. > Ideal para entornos de desarrollo sin necesidad de instalar Rabbit manualmente. --- ### Nota sobre el ORM > **Los modelos del ORM (entidades y repositorios) se encuentran actualmente en desarrollo.** > > Las clases `@Entity`, `@Id`, `@Column` y `CrudRepository` están disponibles en una versión inicial funcional, pero pueden sufrir cambios en futuras versiones para mejorar rendimiento y compatibilidad con PostgreSQL, MySQL y SQLite. --- ## CLI oficial de VyndraJS VyndraJS incluye una **CLI potente y minimalista** que automatiza la creación de proyectos y componentes. ### Comandos disponibles ```bash # Crear un nuevo proyecto base con configuración TypeScript y .env vyndra create:app <nombre> # Crear e inicilizar un nuevo contenedor RabbitMQ vyndra create:broker <os> # Crear un módulo completo con subcarpetas vyndra make:module <nombre> # Crear un controller (crea el módulo si no existe) vyndra make:controller <nombre> # Crear un servicio vyndra make:service <nombre> # Crear un modelo (ORM) vyndra make:model <nombre> # Crear un repositorio vyndra make:repository <nombre> # Crear un listener para RabbitMQ vyndra make:listener <nombre> ``` --- ### Comando `create:app` El comando `vyndra create:app <nombre>` genera automáticamente una aplicación base con: - Estructura inicial `src/` - Configuración de **TypeScript** - Archivo `.env` listo para usar RabbitMQ - Configuración inicial de `App` con soporte Docker opcional Ejemplo: ```bash vyndra create:app my-project ``` Estructura generada: ``` my-project/ ├─ src/ ├─ controllers/ ├─ services/ ├─ repositories/ ├─ models/ ├─ listeners/ └─ index.ts ├─ .env ├─ tsconfig.json ├─ package.json └─ README.md ``` --- ## Ejemplos de uso ### Definir una entidad ```ts import { Id, Column, Entity } from "vyndra-js"; @Entity("users") export class User { @Id() id!: number; @Column({ length: 255, notNull: true }) name!: string; @Column({ default: true }) isValid!: boolean; @Column({ withTimezone: true }) createdAt!: Date; } ``` --- ### Crear un repositorio CRUD ```ts import { CrudRepository, Injectable, Repository } from "vyndra-js"; import { User } from "../models/user.model.js"; @Injectable() @Repository(User) export class UserRepository extends CrudRepository<User> {} ``` --- ### Crear un servicio con AutoWired y Publish ```ts import { AutoWired, Injectable, Publish } from "vyndra-js"; import { UserRepository } from "../repositories/user.repository.js"; import { User } from "../models/user.model.js"; @Injectable() export class UserService { @AutoWired private userRepository!: UserRepository; async getAll() { const data = await this.userRepository.findAll(); return data; } async getById(id: number) { const data = await this.userRepository.findById(id); return data; } async getByField(field: keyof User, value: any) { const data = await this.userRepository.findByField(field, value); return data; } async post(body: User) { const data = await this.userRepository.save(body); return data; } async update(id: number, body: User) { const data = await this.userRepository.update(id, body); return data; } async delete(id: number) { const data = await this.userRepository.delete(id); return data; } @Publish("event") async event(message: string) { return { date: Date.now(), message }; } } ``` --- ### Crear un controller ```ts import { Controller, Get, Post, Response, Request, AutoWired, Patch, Delete, } from "vyndra-js"; import { UserService } from "../services/user.service.js"; @Controller("/user") export class UserController { @AutoWired private userService!: UserService; @Get("/") async get(req: Request, res: Response) { try { const result = await this.userService.getById(Number(req.query?.id)); res.status(200).json(result); } catch (error) { res.status(500).json(error); } } @Get("/all") async getAll(req: Request, res: Response) { try { res.status(200).json(await this.userService.getAll()); } catch (error) { res.status(500).json(error); } } @Post("/") async post(req: Request, res: Response) { try { res.status(200).json(await this.userService.post(req.body)); } catch (error) { res.status(500).json(error); } } @Post("/field") async getByField(req: Request, res: Response) { try { const { field, value } = req.body; res.status(200).json(await this.userService.getByField(field, value)); } catch (error) { res.status(500).json(error); } } @Patch("/") async patch(req: Request, res: Response) { try { res .status(200) .json(await this.userService.update(Number(req.query?.id), req.body)); } catch (error) { res.status(500).json(error); } } @Delete("/") async delete(req: Request, res: Response) { try { res .status(200) .json(await this.userService.delete(Number(req.query?.id))); } catch (error) { res.status(500).json(error); } } @Post("/all") async event(req: Request, res: Response) { try { res .status(200) .json(await this.userService.event(String(req.query?.message))); } catch (error) { res.status(500).json(error); } } } ``` --- ### Crear un listener RabbitMQ ```ts import { QueueListener, QueueListenerMethod } from "vyndra-js"; @QueueListener() export class UserListener { @QueueListenerMethod("event") handleEvent(message: any) { console.log(message); } } ``` --- ## Flujo de eventos con RabbitMQ ``` [Servicio con @Publish] ---> [Cola RabbitMQ] ---> [Listener con @QueueListenerMethod] ``` - Los **servicios** publican eventos con `@Publish("nombreEvento")`. - RabbitMQ los enruta a la cola correspondiente. - Los **listeners** los consumen y procesan automáticamente. --- ## Características principales - Decoradores modernos (`@Controller`, `@Injectable`, `@Entity`, `@Repository`, `@Get`, `@Post`, etc.) - nyección automática de dependencias (DI) - ORM con CRUD básico (en desarrollo activo) - Autoimportación de módulos y servicios - Routing automático basado en decoradores - Integración nativa con RabbitMQ - CLI oficial para scaffolding rápido - Diseño preparado para microservicios y gRPC (en próximas versiones) --- ## Roadmap | Fase | Estado | Descripción | | ----- | ------ | ------------------------------------------- | | 1️⃣ | | Routing y ORM básico | | 2️⃣ | 🚧 | Microservicios y gRPC | | 3️⃣ | | Validaciones, autenticación, CLI extendida | | 4️⃣ | 🔮 | ORM completo con migraciones y relaciones | --- ## Licencia **MIT License** Dependencias: - drizzle-orm MIT - pg / @types/pg MIT - reflect-metadata MIT - dotenv MIT - amqplib / @types/amqplib MIT - commander MIT compatible ---