reestructurar en paquetes
This commit is contained in:
parent
6a674a60ec
commit
180a708956
@ -1,3 +1,5 @@
|
|||||||
|
import { sequelize } from "config/database";
|
||||||
|
import { initPackages } from "core/package-loader";
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
import express, { Application } from "express";
|
import express, { Application } from "express";
|
||||||
import helmet from "helmet";
|
import helmet from "helmet";
|
||||||
@ -5,7 +7,6 @@ import responseTime from "response-time";
|
|||||||
import { authProvider } from "./contexts/auth/infraestructure";
|
import { authProvider } from "./contexts/auth/infraestructure";
|
||||||
import { logger } from "./core/common/infrastructure/logger";
|
import { logger } from "./core/common/infrastructure/logger";
|
||||||
import { globalErrorHandler } from "./core/common/presentation";
|
import { globalErrorHandler } from "./core/common/presentation";
|
||||||
import { v1Routes } from "./routes";
|
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
@ -47,7 +48,8 @@ export function createApp(): Application {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Registrar rutas de la API
|
// Registrar rutas de la API
|
||||||
app.use("/api/v1", v1Routes());
|
// app.use("/api/v1", v1Routes());
|
||||||
|
initPackages(app, sequelize);
|
||||||
|
|
||||||
// Gestión global de errores.
|
// Gestión global de errores.
|
||||||
// Siempre al final de la cadena de middlewares
|
// Siempre al final de la cadena de middlewares
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { logger } from "core/common/infrastructure/logger";
|
import { logger } from "core/common/infrastructure/logger";
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
import { Sequelize } from "sequelize";
|
import { Sequelize } from "sequelize";
|
||||||
import { registerModels } from "./register-models";
|
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
@ -40,7 +39,7 @@ export const sequelize = new Sequelize(
|
|||||||
export async function connectToDatabase(): Promise<void> {
|
export async function connectToDatabase(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await sequelize.authenticate();
|
await sequelize.authenticate();
|
||||||
await registerModels();
|
//await registerModels();
|
||||||
logger.info(`✔️${" "}Database connection established successfully.`);
|
logger.info(`✔️${" "}Database connection established successfully.`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("❌ Unable to connect to the database:", error);
|
logger.error("❌ Unable to connect to the database:", error);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { sequelize } from "@config/database";
|
|
||||||
import { Transaction } from "sequelize";
|
import { Transaction } from "sequelize";
|
||||||
|
import { sequelize } from "../../../../config/database";
|
||||||
import { TransactionManager } from "../database";
|
import { TransactionManager } from "../database";
|
||||||
|
|
||||||
export class SequelizeTransactionManager extends TransactionManager {
|
export class SequelizeTransactionManager extends TransactionManager {
|
||||||
|
|||||||
55
apps/server/src/core/package-loader.ts
Normal file
55
apps/server/src/core/package-loader.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { IPackageServer } from "@libs/package";
|
||||||
|
import { Express } from "express";
|
||||||
|
import { Sequelize } from "sequelize";
|
||||||
|
import { registerService } from "./service-registry";
|
||||||
|
|
||||||
|
const registeredPackages: Map<string, IPackageServer> = new Map();
|
||||||
|
const initializedPackages = new Set<string>();
|
||||||
|
|
||||||
|
export function registerPackage(pkg: IPackageServer) {
|
||||||
|
if (registeredPackages.has(pkg.metadata.name)) {
|
||||||
|
throw new Error(`❌ Paquete "${pkg.metadata.name}" ya registrado.`);
|
||||||
|
}
|
||||||
|
registeredPackages.set(pkg.metadata.name, pkg);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initPackages(app: Express, sequelize: Sequelize) {
|
||||||
|
for (const [name] of registeredPackages) {
|
||||||
|
loadPackage(name, app, sequelize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadPackage(name: string, app: Express, sequelize: Sequelize) {
|
||||||
|
if (initializedPackages.has(name)) return;
|
||||||
|
|
||||||
|
const pkg = registeredPackages.get(name);
|
||||||
|
if (!pkg) throw new Error(`❌ Paquete "${name}" no encontrado.`);
|
||||||
|
|
||||||
|
// Resolver dependencias primero
|
||||||
|
const deps = pkg.metadata.dependencies || [];
|
||||||
|
deps.forEach((dep) => loadPackage(dep, app, sequelize));
|
||||||
|
|
||||||
|
// Inicializar el package
|
||||||
|
pkg.init(app);
|
||||||
|
|
||||||
|
const pkgApi = pkg.registerDependencies?.();
|
||||||
|
|
||||||
|
// Registrar modelos de Sequelize, si los expone
|
||||||
|
|
||||||
|
if (pkgApi?.models) {
|
||||||
|
for (const initModelFn of pkgApi.models) {
|
||||||
|
initModelFn(sequelize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registrar sus servicios, si los expone
|
||||||
|
if (pkgApi?.services) {
|
||||||
|
const services = pkgApi.services;
|
||||||
|
if (services && typeof services === "object") {
|
||||||
|
registerService(pkg.metadata.name, services);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initializedPackages.add(name);
|
||||||
|
console.log(`✅ Paquete "${name}" inicializado.`);
|
||||||
|
}
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import { Application } from "express";
|
|
||||||
import { IPlugin } from "./plugin.interface";
|
|
||||||
|
|
||||||
const plugins: IPlugin[] = [];
|
|
||||||
|
|
||||||
export function registerPlugin(plugin: IPlugin) {
|
|
||||||
plugins.push(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function initPlugins(app: Application) {
|
|
||||||
plugins.forEach((plugin) => plugin.init(app));
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
import { Application } from "express";
|
|
||||||
|
|
||||||
export interface PluginMetadata {
|
|
||||||
name: string;
|
|
||||||
version: string;
|
|
||||||
description?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lista de nombres de plugins requeridos por este plugin.
|
|
||||||
*/
|
|
||||||
dependencies?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IPlugin {
|
|
||||||
metadata: PluginMetadata;
|
|
||||||
init(app: Application): void;
|
|
||||||
registerDependencies?(): void;
|
|
||||||
}
|
|
||||||
36
apps/server/src/core/service-registry.ts
Normal file
36
apps/server/src/core/service-registry.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
const services: Record<string, any> = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registra un objeto de servicio (API) bajo un nombre.
|
||||||
|
*/
|
||||||
|
export function registerService(name: string, api: any) {
|
||||||
|
if (services[name]) {
|
||||||
|
throw new Error(`❌ Servicio "${name}" ya fue registrado.`);
|
||||||
|
}
|
||||||
|
services[name] = api;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recupera un servicio registrado, con tipado opcional.
|
||||||
|
*/
|
||||||
|
export function getService<T = any>(name: string): T {
|
||||||
|
const service = services[name];
|
||||||
|
if (!service) {
|
||||||
|
throw new Error(`❌ Servicio "${name}" no encontrado.`);
|
||||||
|
}
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permite saber si un servicio fue registrado.
|
||||||
|
*/
|
||||||
|
export function hasService(name: string): boolean {
|
||||||
|
return !!services[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Devuelve todos los servicios (para depuración o tests).
|
||||||
|
*/
|
||||||
|
export function listServices(): string[] {
|
||||||
|
return Object.keys(services);
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import http from "http";
|
import http from "http";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
|
import { registerPackages } from "packages";
|
||||||
import { createApp } from "./app";
|
import { createApp } from "./app";
|
||||||
import { ENV } from "./config";
|
import { ENV } from "./config";
|
||||||
import { connectToDatabase } from "./config/database";
|
import { connectToDatabase } from "./config/database";
|
||||||
@ -66,6 +67,9 @@ const serverConnection = (conn: any) => {
|
|||||||
//const sequelizeConn = createSequelizeAdapter();
|
//const sequelizeConn = createSequelizeAdapter();
|
||||||
//const firebirdConn = createFirebirdAdapter();
|
//const firebirdConn = createFirebirdAdapter();
|
||||||
|
|
||||||
|
// Cargar paquetes de la aplicación
|
||||||
|
registerPackages();
|
||||||
|
|
||||||
// Crea el servidor HTTP
|
// Crea el servidor HTTP
|
||||||
const server = http
|
const server = http
|
||||||
.createServer(createApp())
|
.createServer(createApp())
|
||||||
|
|||||||
8
apps/server/src/packages.ts
Normal file
8
apps/server/src/packages.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// apps/server/src/plugins.ts
|
||||||
|
//import { ContactsPackage } from '@packages/contacts/server';
|
||||||
|
//import { InvoicesPackage } from '@packages/invoices/server';
|
||||||
|
|
||||||
|
export const registerPackages = () => {
|
||||||
|
//registerPackage(ContactsPackage);
|
||||||
|
//registerPackage(InvoicesPackage);
|
||||||
|
};
|
||||||
@ -8,10 +8,11 @@
|
|||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@shared/*": ["../../packages/shared/*"],
|
|
||||||
"@common/*": ["common/*"],
|
|
||||||
"@contexts/*": ["contexts/*"],
|
"@contexts/*": ["contexts/*"],
|
||||||
"@config/*": ["config/*"]
|
"@libs/*": ["../../../libs/*"],
|
||||||
|
"@packages/*": ["../../../packages/*"]
|
||||||
|
/*"@common/*": ["common/*"],*/
|
||||||
|
/*"@config/*": ["config/*"]*/
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
//Contrato para los packages backend (Node.js)
|
//Contrato para los packages backend (Node.js)
|
||||||
|
|
||||||
import { Express } from "express";
|
import { Express } from "express";
|
||||||
import { PackageMetadata } from "./types";
|
import { PackageDependencies, PackageMetadata } from "./types";
|
||||||
|
|
||||||
export interface IPackageServer {
|
export interface IPackageServer {
|
||||||
metadata: PackageMetadata;
|
metadata: PackageMetadata;
|
||||||
init(app: Express): void;
|
init(app: Express): void;
|
||||||
registerDependencies?(): void;
|
registerDependencies?(): PackageDependencies;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
"@types/react": "^19.1.2",
|
"@types/react": "^19.1.2",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
"sequelize": "^6.37.5",
|
||||||
"typescript": "*"
|
"typescript": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,17 @@
|
|||||||
// Contiene tipos comunes entre cliente y servidor
|
// Contiene tipos comunes entre cliente y servidor
|
||||||
|
|
||||||
|
import { Model, Sequelize } from "sequelize";
|
||||||
|
|
||||||
|
type ModelInitializer = (sequelize: Sequelize) => typeof Model;
|
||||||
|
|
||||||
export interface PackageMetadata {
|
export interface PackageMetadata {
|
||||||
name: string;
|
name: string;
|
||||||
version: string;
|
version: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
dependencies?: string[];
|
dependencies?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PackageDependencies {
|
||||||
|
models?: ModelInitializer[];
|
||||||
|
services?: { [key: string]: any };
|
||||||
|
}
|
||||||
|
|||||||
30
packages/invoices/server/index.ts
Normal file
30
packages/invoices/server/index.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/* import { getService } from "@apps/server/src/core/service-registry"; */
|
||||||
|
import { IPackageServer } from "@libs/package";
|
||||||
|
//import initInvoiceModel from './models/contact.model';
|
||||||
|
|
||||||
|
export const InvoicesPackage: IPackageServer = {
|
||||||
|
metadata: {
|
||||||
|
name: "invoices",
|
||||||
|
version: "1.0.0",
|
||||||
|
dependencies: ["contacts"],
|
||||||
|
},
|
||||||
|
init(app) {
|
||||||
|
// const contacts = getService<ContactsService>("contacts");
|
||||||
|
|
||||||
|
app.get("/invoices", (req, res) => {
|
||||||
|
// const customer = await contacts.getContactById('123');
|
||||||
|
res.send("Aquí van las facturas");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
registerDependencies() {
|
||||||
|
return {
|
||||||
|
models: [
|
||||||
|
/*initInvoiceModel*/
|
||||||
|
],
|
||||||
|
services: {
|
||||||
|
getInvoice: () => {},
|
||||||
|
/*...*/
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -283,6 +283,9 @@ importers:
|
|||||||
react:
|
react:
|
||||||
specifier: ^18.3.1
|
specifier: ^18.3.1
|
||||||
version: 18.3.1
|
version: 18.3.1
|
||||||
|
sequelize:
|
||||||
|
specifier: ^6.37.5
|
||||||
|
version: 6.37.7(mysql2@3.14.0)
|
||||||
typescript:
|
typescript:
|
||||||
specifier: '*'
|
specifier: '*'
|
||||||
version: 5.7.3
|
version: 5.7.3
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user