.
This commit is contained in:
parent
4bf8467efb
commit
416f1367aa
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@ -22,6 +22,7 @@
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/apps/server/src/index.ts",
|
||||
"runtimeArgs": ["-r", "ts-node/register"],
|
||||
"envFile": "${workspaceFolder}/apps/server/.env",
|
||||
"env": {
|
||||
"NODE_ENV": "development",
|
||||
"NODE_OPTIONS": "--inspect=0"
|
||||
@ -40,12 +41,11 @@
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/apps/server/src/index.ts",
|
||||
"runtimeArgs": ["--nolazy", "-r", "ts-node/register", "-r", "tsconfig-paths/register"],
|
||||
"runtimeArgs": ["--require", "tsconfig-paths/register", "--inspect"],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"outFiles": ["${workspaceFolder}/**/*.js"],
|
||||
"sourceMaps": true,
|
||||
"envFile": "${workspaceFolder}/apps/server/.env",
|
||||
"preLaunchTask": "build",
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
},
|
||||
{
|
||||
|
||||
6
apps/server/nodemon.json
Normal file
6
apps/server/nodemon.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"watch": ["../../packages", "../../modules", "src"],
|
||||
"ext": "ts,js,json",
|
||||
"ignore": ["dist", "node_modules"],
|
||||
"exec": "ts-node -r tsconfig-paths/register src/index.ts"
|
||||
}
|
||||
@ -6,8 +6,8 @@
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "rm -rf dist && rm -rf node_modules",
|
||||
"dev": "ts-node-dev --respawn --inspect --transpile-only --require tsconfig-paths/register src/index.ts",
|
||||
"dev:nodemon": "nodemon --exec \"node -r esbuild-register ./src/index.ts\" -e .ts",
|
||||
"dev:2": "ts-node-dev --respawn --inspect --transpile-only --require tsconfig-paths/register src/index.ts",
|
||||
"dev": "nodemon --watch ../../packages --watch ../../modules --watch ./src --ext ts,js,json --exec ts-node-dev -r tsconfig-paths/register src/index.ts",
|
||||
"lint": "tsc --noEmit && eslint \"src/**/*.ts*\" --max-warnings 0",
|
||||
"start": "node -r esbuild-register ./src/index.ts",
|
||||
"test": "jest --detectOpenHandles"
|
||||
@ -17,10 +17,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@rdx/core": "workspace:*",
|
||||
"@rdx/ddd-domain": "workspace:*",
|
||||
"@rdx/logger": "workspace:*",
|
||||
"@rdx/modules": "workspace:*",
|
||||
"@rdx/utils": "workspace:*",
|
||||
"@modules/invoices": "workspace:*",
|
||||
"bcrypt": "^5.1.1",
|
||||
"body-parser": "^2.2.0",
|
||||
@ -41,7 +37,7 @@
|
||||
"path": "^0.12.7",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"response-time": "^2.3.3",
|
||||
"sequelize": "^6.37.7",
|
||||
"sequelize": "^6.37.5",
|
||||
"zod": "^3.24.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { globalErrorHandler } from "@rdx/core";
|
||||
import { logger } from "@rdx/logger";
|
||||
import { globalErrorHandler, logger } from "@rdx/core";
|
||||
import dotenv from "dotenv";
|
||||
import express, { Application } from "express";
|
||||
import helmet from "helmet";
|
||||
|
||||
@ -1,48 +1,82 @@
|
||||
import { logger } from "@rdx/logger";
|
||||
import { logger } from "@rdx/core";
|
||||
import dotenv from "dotenv";
|
||||
import { Sequelize } from "sequelize";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
export const sequelize = new Sequelize(
|
||||
process.env.DB_NAME as string, // database
|
||||
process.env.DB_USER as string, // username
|
||||
process.env.DB_PASSWORD as string, // password
|
||||
{
|
||||
host: process.env.DB_HOST as string,
|
||||
dialect: "mysql",
|
||||
port: parseInt(process.env.DB_PORT || "3306", 10),
|
||||
dialectOptions: {
|
||||
multipleStatements: true,
|
||||
dateStrings: true,
|
||||
typeCast: true,
|
||||
//timezone: "Z",
|
||||
},
|
||||
pool: {
|
||||
max: 10,
|
||||
min: 0,
|
||||
acquire: 30000,
|
||||
idle: 10000,
|
||||
},
|
||||
logQueryParameters: true,
|
||||
logging: process.env.DB_LOGGING === "true" ? logger.debug : false,
|
||||
define: {
|
||||
charset: "utf8mb4",
|
||||
collate: "utf8mb4_unicode_ci",
|
||||
//freezeTableName: true,
|
||||
underscored: true,
|
||||
timestamps: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
let sequelizeInstance: Sequelize | null = null;
|
||||
|
||||
function getDatabase(): Sequelize {
|
||||
if (sequelizeInstance) {
|
||||
return sequelizeInstance;
|
||||
}
|
||||
|
||||
sequelizeInstance = new Sequelize(
|
||||
process.env.DB_NAME as string,
|
||||
process.env.DB_USER as string,
|
||||
process.env.DB_PASSWORD as string,
|
||||
{
|
||||
host: process.env.DB_HOST as string,
|
||||
dialect: "mysql",
|
||||
port: parseInt(process.env.DB_PORT || "3306", 10),
|
||||
dialectOptions: {
|
||||
multipleStatements: true,
|
||||
dateStrings: true,
|
||||
typeCast: true,
|
||||
},
|
||||
pool: {
|
||||
max: 10,
|
||||
min: 0,
|
||||
acquire: 30000,
|
||||
idle: 10000,
|
||||
},
|
||||
logQueryParameters: true,
|
||||
logging: process.env.DB_LOGGING === "true" ? logger.debug : false,
|
||||
define: {
|
||||
charset: "utf8mb4",
|
||||
collate: "utf8mb4_unicode_ci",
|
||||
underscored: true,
|
||||
timestamps: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return sequelizeInstance;
|
||||
}
|
||||
|
||||
export async function tryConnectToDatabase() {
|
||||
const database = getDatabase();
|
||||
|
||||
if (!database) {
|
||||
const error = new Error("❌ Database not found.");
|
||||
logger.error({
|
||||
message: error.message,
|
||||
label: "tryConnectToDatabase",
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
logger.info({ message: `🔸 Connecting to database...`, label: "tryConnectToDatabase" });
|
||||
|
||||
export async function connectToDatabase(): Promise<void> {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
await database.authenticate();
|
||||
//await registerModels();
|
||||
logger.info(`✔️${" "}Database connection established successfully.`);
|
||||
logger.info({
|
||||
message: `✔️${" "}Database connection established successfully.`,
|
||||
label: "tryConnectToDatabase",
|
||||
meta: {
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT,
|
||||
database: process.env.DB_NAME,
|
||||
user: process.env.DB_USER,
|
||||
},
|
||||
});
|
||||
return database;
|
||||
} catch (error) {
|
||||
logger.error("❌ Unable to connect to the database:", error);
|
||||
process.exit(1);
|
||||
logger.error({
|
||||
message: `❌ Unable to connect to the database: ${(error as Error).message}`,
|
||||
error,
|
||||
label: "tryConnectToDatabase",
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,56 +1,59 @@
|
||||
import { logger } from "@rdx/logger";
|
||||
import { ModelInitializer, ModuleParams } from "@rdx/modules";
|
||||
import { logger, ModuleParams } from "@rdx/core";
|
||||
|
||||
const registeredModels: Map<string, any> = new Map();
|
||||
const initializedModels = new Set<string>();
|
||||
const allModelInitializers: any[] = [];
|
||||
const registeredModels: { [key: string]: any } = {};
|
||||
|
||||
/**
|
||||
* 🔹 Registra todos los modelos en Sequelize
|
||||
*/
|
||||
export const registerModel = (models: ModelInitializer[], params: ModuleParams) => {
|
||||
for (const initModelFn of models) {
|
||||
const model = initModelFn();
|
||||
if (model) {
|
||||
registeredModels.set(model.name, model);
|
||||
}
|
||||
}
|
||||
export const registerModels = (models: any[], params?: ModuleParams) => {
|
||||
allModelInitializers.push(...models);
|
||||
};
|
||||
|
||||
export const initModels = async (params: ModuleParams) => {
|
||||
registeredModels.forEach((_, name) => loadModel(name, params));
|
||||
logger.info({ message: `Init models...`, label: "initModels" });
|
||||
|
||||
const { database } = params;
|
||||
if (!database) {
|
||||
const error = new Error("❌ Database not found.");
|
||||
logger.error({
|
||||
message: error.message,
|
||||
label: "initModels",
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Inicializar modelos
|
||||
allModelInitializers.forEach((initializer) => {
|
||||
const model = initializer(database);
|
||||
registeredModels[model.name] = model;
|
||||
logger.info({
|
||||
message: `🔸 Model "${model.name}" registered (sequelize)`,
|
||||
label: "registerModel",
|
||||
});
|
||||
});
|
||||
|
||||
// Configurar asociaciones
|
||||
Object.values(registeredModels).forEach((model) => {
|
||||
if (typeof model.associate === "function") {
|
||||
model.associate(database);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// Sincronizamos DB en modo desarrollo
|
||||
const { database } = params;
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
await database.sync({ force: false, alter: true });
|
||||
logger.info(`✔️${" "}Database synchronized successfully.`);
|
||||
logger.info({ message: `✔️${" "}Database synchronized successfully.`, label: "initModels" });
|
||||
} else {
|
||||
logger.warning("⚠️ Running in production mode - Skipping database sync.");
|
||||
logger.warning({
|
||||
message: "⚠️ Running in production mode - Skipping database sync.",
|
||||
label: "initModels",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("❌ Error synchronizing database:", error);
|
||||
process.exit(1);
|
||||
} catch (err) {
|
||||
const error = err as Error;
|
||||
logger.error({ message: "❌ Error synchronizing database:", error, label: "initModels" });
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const loadModel = (name: string, params: ModuleParams) => {
|
||||
if (initializedModels.has(name)) return;
|
||||
|
||||
const model = registeredModels.get(name);
|
||||
if (!model) throw new Error(`❌ Model "${name}" not found.`);
|
||||
|
||||
const { database } = params;
|
||||
|
||||
// Asociaciones y hooks de los modelos, si existen
|
||||
if (model.associate) {
|
||||
model.associate(database);
|
||||
}
|
||||
|
||||
if (model.hooks) {
|
||||
model.hooks(database);
|
||||
}
|
||||
|
||||
initializedModels.add(name);
|
||||
logger.info(`🔸 Model "${model.name}" registered (sequelize)`);
|
||||
};
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { logger } from "@rdx/logger";
|
||||
import { IModuleServer, ModuleParams } from "@rdx/modules";
|
||||
import { initModels, registerModel } from "./model-loader";
|
||||
import { IModuleServer, logger, ModuleParams } from "@rdx/core";
|
||||
import { initModels, registerModels } from "./model-loader";
|
||||
import { registerService } from "./service-registry";
|
||||
|
||||
const registeredModules: Map<string, IModuleServer> = new Map();
|
||||
@ -13,11 +12,11 @@ export function registerModule(pkg: IModuleServer) {
|
||||
registeredModules.set(pkg.metadata.name, pkg);
|
||||
}
|
||||
|
||||
export function initModules(params: ModuleParams) {
|
||||
export async function initModules(params: ModuleParams) {
|
||||
registeredModules.forEach((_, name) => {
|
||||
loadModule(name, params);
|
||||
});
|
||||
initModels(params);
|
||||
await initModels(params);
|
||||
}
|
||||
|
||||
const loadModule = (name: string, params: ModuleParams) => {
|
||||
@ -37,7 +36,7 @@ const loadModule = (name: string, params: ModuleParams) => {
|
||||
|
||||
// Registrar modelos de Sequelize, si los expone
|
||||
if (pkgApi?.models) {
|
||||
registerModel(pkgApi.models, params);
|
||||
registerModels(pkgApi.models, params);
|
||||
}
|
||||
|
||||
// Registrar sus servicios, si los expone
|
||||
@ -49,5 +48,5 @@ const loadModule = (name: string, params: ModuleParams) => {
|
||||
}
|
||||
|
||||
initializedModules.add(name);
|
||||
logger.info(`✅ Paquete "${name}" registrado.`);
|
||||
logger.info({ message: `✅ Module "${name}" registered`, label: "loadModule" });
|
||||
};
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { logger } from "@rdx/logger";
|
||||
import { logger } from "@rdx/core";
|
||||
import http from "http";
|
||||
import { DateTime } from "luxon";
|
||||
import os from "os";
|
||||
import { createApp } from "./app";
|
||||
import { ENV } from "./config";
|
||||
import { connectToDatabase, sequelize as database } from "./config/database";
|
||||
import { tryConnectToDatabase } from "./config/database";
|
||||
import { initModules } from "./core/helpers";
|
||||
import { registerModules } from "./modules";
|
||||
|
||||
@ -42,13 +43,17 @@ const serverStop = (server: http.Server) => {
|
||||
|
||||
// Manejo de errores al iniciar el servidor
|
||||
const serverError = (error: NodeJS.ErrnoException) => {
|
||||
logger.info(`⛔️ Server wasn't able to start properly.`);
|
||||
logger.error({
|
||||
message: `⛔️ Server wasn't able to start properly.`,
|
||||
label: "serverError0",
|
||||
error,
|
||||
});
|
||||
|
||||
if (error.code === "EADDRINUSE") {
|
||||
logger.error(error.message);
|
||||
logger.error({ message: error.message, error, label: "serverError1" });
|
||||
//logger.error(`The port ${error.port} is already used by another application.`);
|
||||
} else {
|
||||
logger.error(error);
|
||||
logger.error({ message: error.message, error, label: "serverError2" });
|
||||
}
|
||||
|
||||
// Dependiendo de la criticidad, podrías forzar el proceso a salir
|
||||
@ -113,7 +118,7 @@ process.on("uncaughtException", (error: Error) => {
|
||||
});
|
||||
|
||||
// Arranca el servidor si la conexión a la base de datos va bien
|
||||
(async (app) => {
|
||||
(async () => {
|
||||
try {
|
||||
const now = DateTime.now();
|
||||
logger.info(`Time: ${now.toLocaleString(DateTime.DATETIME_FULL)} ${now.zoneName}`);
|
||||
@ -121,18 +126,45 @@ process.on("uncaughtException", (error: Error) => {
|
||||
logger.info(`Environment: ${currentState.environment}`);
|
||||
logger.info(`Process PID: ${process.pid}`);
|
||||
|
||||
await connectToDatabase();
|
||||
// Lógica de inicialización de DB, si procede:
|
||||
// initStructure(sequelizeConn.connection);
|
||||
// insertUsers();
|
||||
|
||||
initModules({ app, database: database, baseRoutePath: "/api/v1" });
|
||||
const database = await tryConnectToDatabase();
|
||||
|
||||
await initModules({ app, database, baseRoutePath: "/api/v1" });
|
||||
|
||||
server.listen(currentState.port, () => {
|
||||
server.emit("listening");
|
||||
|
||||
const networkInterfaces = os.networkInterfaces();
|
||||
const addresses: string[] = [];
|
||||
|
||||
// Obtiene todas las direcciones IPv4
|
||||
for (const interfaceName in networkInterfaces) {
|
||||
const networkInterface = networkInterfaces[interfaceName];
|
||||
if (networkInterface) {
|
||||
for (const iface of networkInterface) {
|
||||
if (iface.family === "IPv4" && !iface.internal) {
|
||||
addresses.push(iface.address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addresses.forEach((address) => {
|
||||
logger.info(`⚡️ Server accessible at: http://${address}:${currentState.port}`);
|
||||
});
|
||||
logger.info(`Server started at: ${DateTime.now().toLocaleString(DateTime.DATETIME_FULL)}`);
|
||||
logger.info(`Server PID: ${process.pid}`);
|
||||
logger.info(
|
||||
`Server launched in: ${DateTime.now().diff(currentState.launchedAt).toMillis()} ms`
|
||||
);
|
||||
logger.info(`Server path: ${currentState.appPath}`);
|
||||
logger.info(`Server environment: ${currentState.environment}`);
|
||||
logger.info("To shut down your server, press <CTRL> + C at any time");
|
||||
logger.info(`⚡️ Server: http://${currentState.host}:${currentState.port}`);
|
||||
});
|
||||
} catch (error) {
|
||||
serverError(error as NodeJS.ErrnoException);
|
||||
}
|
||||
})(app);
|
||||
})();
|
||||
|
||||
@ -1,10 +1,50 @@
|
||||
{
|
||||
"extends": "@repo/typescript-config/base.json",
|
||||
"compilerOptions": {
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
/* Basic Options */
|
||||
"target": "ES2022" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
|
||||
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||
"lib": ["ES2022", "dom"] /* Specify library files to be included in the compilation. */,
|
||||
|
||||
"allowJs": false /* Allow javascript files to be compiled. */,
|
||||
"pretty": true,
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
"jsx": "preserve" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */,
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
"sourceMap": true /* Generates corresponding '.map' file. */,
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./dist/" /* Redirect output structure to the directory. */,
|
||||
//"rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
|
||||
// "composite": true, /* Enable project compilation */
|
||||
"removeComments": true /* Do not emit comments to output. */,
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"skipLibCheck": false /* Skip type checking of declaration files. */,
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
"noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */,
|
||||
"strictNullChecks": true /* Enable strict null checks. */,
|
||||
"strictFunctionTypes": true /* Enable strict checking of function types. */,
|
||||
"strictPropertyInitialization": false /* Enable strict checking of property initialization in classes. */,
|
||||
"noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
"noUnusedLocals": false /* Report errors on unused locals. */,
|
||||
"noUnusedParameters": false /* Report errors on unused parameters. */,
|
||||
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
|
||||
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
|
||||
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
||||
//"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
|
||||
|
||||
"rootDir": "./src",
|
||||
"types": ["node", "jest"],
|
||||
//"types": ["node", "jest"],
|
||||
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
|
||||
@ -52,10 +52,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@rdx/core": "workspace:*",
|
||||
"@rdx/ddd-domain": "workspace:*",
|
||||
"@rdx/logger": "workspace:*",
|
||||
"@rdx/modules": "workspace:*",
|
||||
"@rdx/utils": "workspace:*",
|
||||
"bcrypt": "^5.1.1",
|
||||
"body-parser": "^2.2.0",
|
||||
"cors": "^2.8.5",
|
||||
@ -75,7 +71,7 @@
|
||||
"path": "^0.12.7",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"response-time": "^2.3.3",
|
||||
"sequelize": "^6.37.7",
|
||||
"sequelize": "^6.37.5",
|
||||
"zod": "^3.24.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
import { ITransactionManager } from "@rdx/core";
|
||||
import { UniqueID, UtcDate } from "@rdx/ddd-domain";
|
||||
import { logger } from "@rdx/logger";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { ITransactionManager, logger, Result, UniqueID, UtcDate } from "@rdx/core";
|
||||
import { IInvoiceService, Invoice } from "../domain";
|
||||
|
||||
import { IInvoiceProps, InvoiceNumber, InvoiceSerie, InvoiceStatus } from "../domain";
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
import { ITransactionManager } from "@rdx/core";
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { logger } from "@rdx/logger";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { ITransactionManager, logger, Result, UniqueID } from "@rdx/core";
|
||||
import { IInvoiceService } from "../domain";
|
||||
|
||||
export class DeleteInvoiceUseCase {
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
import { ITransactionManager } from "@rdx/core";
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { logger } from "@rdx/logger";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { ITransactionManager, logger, Result, UniqueID } from "@rdx/core";
|
||||
import { IInvoiceService, Invoice } from "../domain";
|
||||
|
||||
export class GetInvoiceUseCase {
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { ITransactionManager } from "@rdx/core";
|
||||
import { logger } from "@rdx/logger";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Collection, ITransactionManager, logger, Result } from "@rdx/core";
|
||||
import { IInvoiceService, Invoice } from "../domain";
|
||||
|
||||
export class ListInvoicesUseCase {
|
||||
@ -14,7 +12,29 @@ export class ListInvoicesUseCase {
|
||||
try {
|
||||
return await this.invoiceService.findInvoices(transaction);
|
||||
} catch (error: unknown) {
|
||||
logger.error(error as Error);
|
||||
logger.error({
|
||||
//message: error as Error,
|
||||
message: "hola",
|
||||
label: "ListInvoicesUseCase",
|
||||
});
|
||||
// Aquí puedes manejar el error de manera más específica si es necesario
|
||||
// Por ejemplo, puedes lanzar un error personalizado o registrar el error
|
||||
|
||||
// logger.error({ message: error, label: "ListInvoicesUseCase" });
|
||||
// return Result.fail(new Error("Error al listar las facturas"));
|
||||
|
||||
// O simplemente devolver el error original
|
||||
// return Result.fail(error as Error);
|
||||
|
||||
// Si el error es un Error de Sequelize, puedes manejarlo de manera diferente
|
||||
// if (error instanceof SequelizeError) {
|
||||
// return Result.fail(new Error("Error de base de datos"));
|
||||
// }
|
||||
// Si el error es un Error de Sequelize, puedes manejarlo de manera diferente
|
||||
// if (error instanceof SequelizeError) {
|
||||
// return Result.fail(new Error("Error de base de datos"));
|
||||
// }
|
||||
|
||||
return Result.fail(error as Error);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { ITransactionManager } from "@rdx/core";
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { UniqueID } from "@rdx/core";
|
||||
import { logger } from "@rdx/logger";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Collection, Result } from "@rdx/core";
|
||||
import { IInvoiceService, Invoice, InvoiceItem } from "../domain";
|
||||
|
||||
import { IInvoiceProps, InvoiceNumber, InvoiceStatus } from "../domain";
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { AggregateRoot, MoneyValue, UniqueID, UtcDate } from "@rdx/ddd-domain";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { AggregateRoot, Collection, MoneyValue, Result, UniqueID, UtcDate } from "@rdx/core";
|
||||
import { InvoiceCustomer, InvoiceItem, InvoiceItems } from "../entities";
|
||||
import { InvoiceNumber, InvoiceSerie, InvoiceStatus } from "../value-objects";
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { EmailAddress, Name, PostalAddress, ValueObject } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { EmailAddress, Name, PostalAddress, Result, ValueObject } from "@rdx/core";
|
||||
import { PhoneNumber } from "libphonenumber-js";
|
||||
import { InvoiceAddressType } from "../../value-objects";
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DomainEntity, Name, TINNumber, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { DomainEntity, Name, Result, TINNumber, UniqueID } from "@rdx/core";
|
||||
import { InvoiceAddress } from "./invoice-address";
|
||||
|
||||
export interface IInvoiceCustomerProps {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { MoneyValue, Quantity } from "@rdx/ddd-domain";
|
||||
import { MoneyValue, Quantity } from "@rdx/core";
|
||||
|
||||
import { InvoiceItemDescription } from "../../../value-objects";
|
||||
import { InvoiceItem } from "../invoice-item";
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DomainEntity, MoneyValue, Percentage, Quantity, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { DomainEntity, MoneyValue, Percentage, Quantity, Result, UniqueID } from "@rdx/core";
|
||||
import { InvoiceItemDescription } from "../../value-objects";
|
||||
|
||||
export interface IInvoiceItemProps {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Collection } from "@rdx/utils";
|
||||
import { Collection } from "@rdx/core";
|
||||
import { InvoiceItem } from "./invoice-item";
|
||||
|
||||
export class InvoiceItems extends Collection<InvoiceItem> {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Collection, Result, UniqueID } from "@rdx/core";
|
||||
import { Invoice } from "../aggregates";
|
||||
|
||||
export interface IInvoiceRepository {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Collection, Result, UniqueID } from "@rdx/core";
|
||||
import { IInvoiceProps, Invoice } from "../aggregates";
|
||||
|
||||
export interface IInvoiceService {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Collection, Result, UniqueID } from "@rdx/core";
|
||||
import { Transaction } from "sequelize";
|
||||
import { IInvoiceProps, Invoice } from "../aggregates";
|
||||
import { IInvoiceRepository } from "../repositories";
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ValueObject } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, ValueObject } from "@rdx/core";
|
||||
|
||||
interface IInvoiceAddressTypeProps {
|
||||
value: string;
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ValueObject } from "@rdx/ddd-domain";
|
||||
import { Maybe, Result } from "@rdx/utils";
|
||||
import { Maybe, Result, ValueObject } from "@rdx/core";
|
||||
import { z } from "zod";
|
||||
|
||||
interface IInvoiceItemDescriptionProps {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ValueObject } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, ValueObject } from "@rdx/core";
|
||||
import { z } from "zod";
|
||||
|
||||
interface IInvoiceNumberProps {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ValueObject } from "@rdx/ddd-domain";
|
||||
import { Maybe, Result } from "@rdx/utils";
|
||||
import { Maybe, Result, ValueObject } from "@rdx/core";
|
||||
import { z } from "zod";
|
||||
|
||||
interface IInvoiceSerieProps {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ValueObject } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, ValueObject } from "@rdx/core";
|
||||
|
||||
interface IInvoiceStatusProps {
|
||||
value: string;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
/* import { getService } from "@apps/server/src/core/service-registry"; */
|
||||
import { logger } from "@rdx/logger";
|
||||
import { IModuleServer, ModuleParams } from "@rdx/modules";
|
||||
import { initInvoiceModel, invoicesRouter } from "./intrastructure";
|
||||
import { IModuleServer, ModuleParams, logger } from "@rdx/core";
|
||||
import { invoicesRouter, models } from "./intrastructure";
|
||||
|
||||
export const invoicesModule: IModuleServer = {
|
||||
metadata: {
|
||||
@ -18,7 +17,7 @@ export const invoicesModule: IModuleServer = {
|
||||
const { database } = params;
|
||||
logger.info({ message: "🚀 Invoices module dependencies registered", label: "invoices" });
|
||||
return {
|
||||
models: [() => initInvoiceModel(database)],
|
||||
models,
|
||||
services: {
|
||||
getInvoice: () => {},
|
||||
/*...*/
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { buildGetInvoiceController, buildListInvoicesController } from "../../presentation";
|
||||
|
||||
import { ModuleParams } from "@rdx/modules";
|
||||
import { ModuleParams } from "@rdx/core";
|
||||
import { Application, NextFunction, Request, Response, Router } from "express";
|
||||
import { Sequelize } from "sequelize";
|
||||
import { buildGetInvoiceController, buildListInvoicesController } from "../../presentation";
|
||||
|
||||
export const invoicesRouter = (params: ModuleParams) => {
|
||||
const { app, database, baseRoutePath } = params as {
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
import { Invoice, InvoiceItem, InvoiceItemDescription } from "#/server/domain";
|
||||
import { ISequelizeMapper, MapperParamsType, SequelizeMapper } from "@rdx/core";
|
||||
import { MoneyValue, Percentage, Quantity, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import {
|
||||
ISequelizeMapper,
|
||||
MapperParamsType,
|
||||
MoneyValue,
|
||||
Percentage,
|
||||
Quantity,
|
||||
Result,
|
||||
SequelizeMapper,
|
||||
UniqueID,
|
||||
} from "@rdx/core";
|
||||
import { InferCreationAttributes } from "sequelize";
|
||||
import { InvoiceItemCreationAttributes, InvoiceItemModel, InvoiceModel } from "../sequelize";
|
||||
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
import { Invoice, InvoiceNumber, InvoiceSerie, InvoiceStatus } from "#/server/domain";
|
||||
import { ISequelizeMapper, MapperParamsType, SequelizeMapper } from "@rdx/core";
|
||||
import { UniqueID, UtcDate } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import {
|
||||
ISequelizeMapper,
|
||||
MapperParamsType,
|
||||
Result,
|
||||
SequelizeMapper,
|
||||
UniqueID,
|
||||
UtcDate,
|
||||
} from "@rdx/core";
|
||||
import { InvoiceCreationAttributes, InvoiceModel } from "../sequelize";
|
||||
import { InvoiceItemMapper } from "./invoice-item.mapper";
|
||||
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
import { IInvoiceRepository } from "../../domain";
|
||||
import { invoiceRepository } from "./invoice.repository";
|
||||
import invoiceItemModelInit from "./invoice-item.model";
|
||||
import invoiceModelInit from "./invoice.model";
|
||||
|
||||
export * from "./invoice-item.model";
|
||||
export * from "./invoice-item.model"; // exporta las clases, tipos
|
||||
export * from "./invoice.model";
|
||||
|
||||
export * from "./invoice.repository";
|
||||
|
||||
export const createInvoiceRepository = (): IInvoiceRepository => {
|
||||
return invoiceRepository;
|
||||
};
|
||||
// Array de inicializadores para que registerModels() lo use
|
||||
export const models = [invoiceItemModelInit, invoiceModelInit];
|
||||
|
||||
@ -4,25 +4,20 @@ import {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
Model,
|
||||
NonAttribute,
|
||||
Sequelize,
|
||||
} from "sequelize";
|
||||
import { InvoiceModel } from "./invoice.model";
|
||||
|
||||
export type InvoiceItemCreationAttributes = InferCreationAttributes<InvoiceItemModel, {}> & {};
|
||||
export type InvoiceItemCreationAttributes = InferCreationAttributes<
|
||||
InvoiceItemModel,
|
||||
{ omit: "invoice" }
|
||||
>;
|
||||
|
||||
export class InvoiceItemModel extends Model<
|
||||
InferAttributes<InvoiceItemModel>,
|
||||
InvoiceItemCreationAttributes
|
||||
InferCreationAttributes<InvoiceItemModel, { omit: "invoice" }>
|
||||
> {
|
||||
static associate(connection: Sequelize) {
|
||||
/*const { Invoice_Model, InvoiceItem_Model } = connection.models;
|
||||
|
||||
InvoiceItem_Model.belongsTo(Invoice_Model, {
|
||||
as: "invoice",
|
||||
foreignKey: "invoice_id",
|
||||
onDelete: "CASCADE",
|
||||
});*/
|
||||
}
|
||||
|
||||
declare item_id: string;
|
||||
declare invoice_id: string;
|
||||
|
||||
@ -47,10 +42,20 @@ export class InvoiceItemModel extends Model<
|
||||
declare total_amount: CreationOptional<number>;
|
||||
declare total_scale: CreationOptional<number>;
|
||||
|
||||
//declare invoice?: NonAttribute<InvoiceModel>;
|
||||
declare invoice: NonAttribute<InvoiceModel>;
|
||||
|
||||
static associate(database: Sequelize) {
|
||||
/*const { Invoice_Model, InvoiceItem_Model } = connection.models;
|
||||
|
||||
InvoiceItem_Model.belongsTo(Invoice_Model, {
|
||||
as: "invoice",
|
||||
foreignKey: "invoice_id",
|
||||
onDelete: "CASCADE",
|
||||
});*/
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize: Sequelize) => {
|
||||
export default (database: Sequelize) => {
|
||||
InvoiceItemModel.init(
|
||||
{
|
||||
item_id: {
|
||||
@ -153,7 +158,7 @@ export default (sequelize: Sequelize) => {
|
||||
},
|
||||
},
|
||||
{
|
||||
sequelize,
|
||||
sequelize: database,
|
||||
tableName: "invoice_items",
|
||||
|
||||
defaultScope: {},
|
||||
|
||||
@ -13,17 +13,10 @@ export type InvoiceCreationAttributes = InferCreationAttributes<InvoiceModel, {
|
||||
items?: InvoiceItemCreationAttributes[];
|
||||
};
|
||||
|
||||
export class InvoiceModel extends Model<InferAttributes<InvoiceModel>, InvoiceCreationAttributes> {
|
||||
static associate(connection: Sequelize) {
|
||||
const { InvoiceModel, InvoiceItemModel } = connection.models;
|
||||
|
||||
InvoiceModel.hasMany(InvoiceItemModel, {
|
||||
as: "items",
|
||||
foreignKey: "invoice_id",
|
||||
onDelete: "CASCADE",
|
||||
});
|
||||
}
|
||||
|
||||
export class InvoiceModel extends Model<
|
||||
InferAttributes<InvoiceModel>,
|
||||
InferCreationAttributes<InvoiceModel, { omit: "items" }>
|
||||
> {
|
||||
declare id: string;
|
||||
|
||||
declare invoice_status: string;
|
||||
@ -42,14 +35,23 @@ export class InvoiceModel extends Model<InferAttributes<InvoiceModel>, InvoiceCr
|
||||
declare total_amount: CreationOptional<number>;
|
||||
declare total_scale: CreationOptional<number>;
|
||||
|
||||
// Relationships
|
||||
// Relaciones
|
||||
declare items: NonAttribute<InvoiceItemModel[]>;
|
||||
//declare customer: NonAttribute<InvoiceParticipant_Model[]>;
|
||||
|
||||
static associate(database: Sequelize) {
|
||||
const { InvoiceModel, InvoiceItemModel } = database.models;
|
||||
|
||||
InvoiceModel.hasMany(InvoiceItemModel, {
|
||||
as: "items",
|
||||
foreignKey: "invoice_id",
|
||||
onDelete: "CASCADE",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const initInvoiceModel = (sequelize: Sequelize) => {
|
||||
return sequelize.define(
|
||||
"InvoiceModel",
|
||||
export default (database: Sequelize) => {
|
||||
InvoiceModel.init(
|
||||
{
|
||||
id: {
|
||||
type: new DataTypes.UUID(),
|
||||
@ -118,6 +120,7 @@ const initInvoiceModel = (sequelize: Sequelize) => {
|
||||
},
|
||||
},
|
||||
{
|
||||
sequelize: database,
|
||||
tableName: "invoices",
|
||||
|
||||
paranoid: true, // softs deletes
|
||||
@ -136,6 +139,6 @@ const initInvoiceModel = (sequelize: Sequelize) => {
|
||||
scopes: {},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export { initInvoiceModel };
|
||||
return InvoiceModel;
|
||||
};
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
import { SequelizeRepository } from "@rdx/core";
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Transaction } from "sequelize";
|
||||
import { Collection, logger, Result, SequelizeRepository, UniqueID } from "@rdx/core";
|
||||
import { Sequelize, Transaction } from "sequelize";
|
||||
import { IInvoiceRepository, Invoice } from "../../domain";
|
||||
import { IInvoiceMapper, invoiceMapper } from "../mappers/invoice.mapper";
|
||||
import { IInvoiceMapper } from "../mappers/invoice.mapper";
|
||||
import { InvoiceItemModel } from "./invoice-item.model";
|
||||
import { InvoiceModel } from "./invoice.model";
|
||||
|
||||
class InvoiceRepository extends SequelizeRepository<Invoice> implements IInvoiceRepository {
|
||||
export class InvoiceRepository extends SequelizeRepository<Invoice> implements IInvoiceRepository {
|
||||
private readonly _mapper!: IInvoiceMapper;
|
||||
|
||||
/**
|
||||
@ -21,8 +19,8 @@ class InvoiceRepository extends SequelizeRepository<Invoice> implements IInvoice
|
||||
return null;
|
||||
}
|
||||
|
||||
constructor(mapper: IInvoiceMapper) {
|
||||
super();
|
||||
constructor(database: Sequelize, mapper: IInvoiceMapper) {
|
||||
super(database);
|
||||
this._mapper = mapper;
|
||||
}
|
||||
|
||||
@ -38,25 +36,28 @@ class InvoiceRepository extends SequelizeRepository<Invoice> implements IInvoice
|
||||
|
||||
async findAll(transaction?: Transaction): Promise<Result<Collection<Invoice>, Error>> {
|
||||
try {
|
||||
const rawInvoices: any = await this._findAll(
|
||||
InvoiceModel,
|
||||
{
|
||||
include: [
|
||||
{
|
||||
model: InvoiceItemModel,
|
||||
as: "items",
|
||||
},
|
||||
],
|
||||
},
|
||||
transaction
|
||||
);
|
||||
const rawInvoices = await InvoiceModel.findAll({
|
||||
include: [
|
||||
{
|
||||
model: InvoiceItemModel,
|
||||
as: "items",
|
||||
},
|
||||
],
|
||||
transaction,
|
||||
});
|
||||
|
||||
if (!rawInvoices === true) {
|
||||
return Result.fail(new Error("Invoice with email not exists"));
|
||||
}
|
||||
/*if (!rawInvoices === true) {
|
||||
return Result.fail(new Error("Invoice not exists"));
|
||||
}*/
|
||||
|
||||
logger.debug({
|
||||
message: "rawInvoices",
|
||||
label: "InvoiceRepository",
|
||||
meta: { data: rawInvoices },
|
||||
});
|
||||
|
||||
return this._mapper.mapArrayToDomain(rawInvoices);
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
return this._handleDatabaseError(error, this._customErrorMapper);
|
||||
}
|
||||
}
|
||||
@ -106,6 +107,3 @@ class InvoiceRepository extends SequelizeRepository<Invoice> implements IInvoice
|
||||
await this._save(InvoiceModel, invoice.id, invoiceData, {}, transaction);
|
||||
}
|
||||
}
|
||||
|
||||
const invoiceRepository = new InvoiceRepository(invoiceMapper);
|
||||
export { invoiceRepository };
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ExpressController } from "@rdx/core";
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { ExpressController, UniqueID } from "@rdx/core";
|
||||
import { CreateInvoiceUseCase } from "../../../application";
|
||||
import { ICreateInvoiceRequestDTO } from "../../dto";
|
||||
import { ICreateInvoicePresenter } from "./presenter";
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import { CreateInvoiceUseCase } from "#/server/application";
|
||||
import { InvoiceService } from "#/server/domain";
|
||||
import { invoiceRepository } from "#/server/intrastructure";
|
||||
import { invoiceMapper, InvoiceRepository } from "#/server/intrastructure";
|
||||
import { SequelizeTransactionManager } from "@rdx/core";
|
||||
import { Sequelize } from "sequelize";
|
||||
import { CreateInvoiceUseCase } from "../../../application";
|
||||
import { CreateInvoiceController } from "./create-invoice.controller";
|
||||
import { createInvoicePresenter } from "./presenter";
|
||||
|
||||
export const buildCreateInvoiceController = (database: Sequelize) => {
|
||||
const transactionManager = new SequelizeTransactionManager(database);
|
||||
const invoiceRepository = new InvoiceRepository(database, invoiceMapper);
|
||||
const invoiceService = new InvoiceService(invoiceRepository);
|
||||
|
||||
const useCase = new CreateInvoiceUseCase(invoiceService, transactionManager);
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { GetInvoiceUseCase } from "#/server/application";
|
||||
import { ExpressController } from "@rdx/core";
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { ExpressController, UniqueID } from "@rdx/core";
|
||||
import { IGetInvoicePresenter } from "./presenter";
|
||||
|
||||
export class GetInvoiceController extends ExpressController {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { GetInvoiceUseCase } from "#/server/application";
|
||||
import { InvoiceService } from "#/server/domain";
|
||||
import { invoiceRepository } from "#/server/intrastructure";
|
||||
import { invoiceMapper, InvoiceRepository } from "#/server/intrastructure";
|
||||
import { SequelizeTransactionManager } from "@rdx/core";
|
||||
import { Sequelize } from "sequelize";
|
||||
import { GetInvoiceController } from "./get-invoice.controller";
|
||||
@ -8,6 +8,7 @@ import { getInvoicePresenter } from "./presenter";
|
||||
|
||||
export const buildGetInvoiceController = (database: Sequelize) => {
|
||||
const transactionManager = new SequelizeTransactionManager(database);
|
||||
const invoiceRepository = new InvoiceRepository(database, invoiceMapper);
|
||||
const invoiceService = new InvoiceService(invoiceRepository);
|
||||
|
||||
const useCase = new GetInvoiceUseCase(invoiceService, transactionManager);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { InvoiceItem } from "#/server/domain";
|
||||
import { IInvoicingContext } from "#/server/intrastructure";
|
||||
import { Collection } from "@rdx/utils";
|
||||
import { Collection } from "@rdx/core";
|
||||
|
||||
export const invoiceItemPresenter = (items: Collection<InvoiceItem>, context: IInvoicingContext) =>
|
||||
items.totalCount > 0
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ListInvoicesUseCase } from "#/server/application";
|
||||
import { InvoiceService } from "#/server/domain";
|
||||
import { invoiceRepository } from "#/server/intrastructure";
|
||||
import { invoiceMapper, InvoiceRepository } from "#/server/intrastructure";
|
||||
import { SequelizeTransactionManager } from "@rdx/core";
|
||||
import { Sequelize } from "sequelize";
|
||||
import { ListInvoicesController } from "./list-invoices.controller";
|
||||
@ -8,6 +8,7 @@ import { listInvoicesPresenter } from "./presenter";
|
||||
|
||||
export const buildListInvoicesController = (database: Sequelize) => {
|
||||
const transactionManager = new SequelizeTransactionManager(database);
|
||||
const invoiceRepository = new InvoiceRepository(database, invoiceMapper);
|
||||
const invoiceService = new InvoiceService(invoiceRepository);
|
||||
|
||||
const useCase = new ListInvoicesUseCase(invoiceService, transactionManager);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Invoice } from "#/server/domain";
|
||||
import { IListInvoicesResponseDTO } from "#/server/presentation/dto";
|
||||
import { Collection } from "@rdx/utils";
|
||||
import { Collection } from "@rdx/core";
|
||||
|
||||
export interface IListInvoicesPresenter {
|
||||
toDTO: (invoices: Collection<Invoice>) => IListInvoicesResponseDTO[];
|
||||
|
||||
@ -1,10 +1,50 @@
|
||||
{
|
||||
"extends": "@repo/typescript-config/base.json",
|
||||
"compilerOptions": {
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
/* Basic Options */
|
||||
"target": "ES2022" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
|
||||
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||
"lib": ["ES2022", "dom"] /* Specify library files to be included in the compilation. */,
|
||||
|
||||
"allowJs": false /* Allow javascript files to be compiled. */,
|
||||
"pretty": true,
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
"jsx": "preserve" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */,
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
"sourceMap": true /* Generates corresponding '.map' file. */,
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./dist/" /* Redirect output structure to the directory. */,
|
||||
//"rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
|
||||
// "composite": true, /* Enable project compilation */
|
||||
"removeComments": true /* Do not emit comments to output. */,
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"skipLibCheck": false /* Skip type checking of declaration files. */,
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
"noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */,
|
||||
"strictNullChecks": true /* Enable strict null checks. */,
|
||||
"strictFunctionTypes": true /* Enable strict checking of function types. */,
|
||||
"strictPropertyInitialization": false /* Enable strict checking of property initialization in classes. */,
|
||||
"noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
"noUnusedLocals": false /* Report errors on unused locals. */,
|
||||
"noUnusedParameters": false /* Report errors on unused parameters. */,
|
||||
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
|
||||
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
|
||||
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
||||
//"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
|
||||
|
||||
"rootDir": "./src",
|
||||
"types": ["node", "jest"],
|
||||
//"types": ["node", "jest"],
|
||||
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
|
||||
@ -3,15 +3,18 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev:server": "pnpm run dev --filter './apps/server'",
|
||||
"dev:server:watch": "nodemon --watch ./apps/server --ext ts --exec ts-node-dev -r tsconfig-paths/register ./apps/server/src/index.ts",
|
||||
"dev": "turbo run dev",
|
||||
"build": "turbo run build",
|
||||
"clean": "turbo run clean && rm -rf node_modules",
|
||||
"dev": "turbo run dev",
|
||||
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
||||
"lint": "turbo run lint",
|
||||
"test": "turbo run test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^9.25.1",
|
||||
"nodemon": "^3.1.10",
|
||||
"prettier": "^3.5.3",
|
||||
"ts-node": "^10.9.2",
|
||||
"ts-node-dev": "^2.0.0",
|
||||
@ -20,5 +23,5 @@
|
||||
"engines": {
|
||||
"node": ">=22.13.1"
|
||||
},
|
||||
"packageManager": "pnpm@10.9.0"
|
||||
"packageManager": "pnpm@10.10.0"
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "rm -rf dist && rm -rf node_modules",
|
||||
"clean": "rm -rf dist && rm -rf node_modules",
|
||||
"lint": "eslint src/",
|
||||
"lint:fix": "eslint src/ --fix",
|
||||
"typecheck": "tsc --noEmit",
|
||||
@ -52,10 +52,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@rdx/core": "workspace:*",
|
||||
"@rdx/ddd-domain": "workspace:*",
|
||||
"@rdx/logger": "workspace:*",
|
||||
"@rdx/modules": "workspace:*",
|
||||
"@rdx/utils": "workspace:*",
|
||||
"bcrypt": "^5.1.1",
|
||||
"body-parser": "^2.2.0",
|
||||
"cors": "^2.8.5",
|
||||
@ -75,7 +71,7 @@
|
||||
"path": "^0.12.7",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"response-time": "^2.3.3",
|
||||
"sequelize": "^6.37.7",
|
||||
"sequelize": "^6.37.5",
|
||||
"zod": "^3.24.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { IUserService, User } from "@/domain";
|
||||
import { ITransactionManager } from "@rdx/core";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Collection, ITransactionManager, Result } from "@rdx/core";
|
||||
|
||||
export class ListUsersUseCase {
|
||||
constructor(
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { IAuthService, RegisterData } from "@/domain";
|
||||
import { ITransactionManager } from "@rdx/core";
|
||||
import { ITransactionManager, Result } from "@rdx/core";
|
||||
import { logger } from "@rdx/logger";
|
||||
import { Result } from "@rdx/utils";
|
||||
|
||||
export class RegisterUseCase {
|
||||
constructor(
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { AggregateRoot, EmailAddress, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { AggregateRoot, EmailAddress, Result, UniqueID } from "@rdx/core";
|
||||
import { UserAuthenticatedEvent } from "../events";
|
||||
import { HashPassword, PlainPassword, Username } from "../value-objects";
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { AggregateRoot, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { AggregateRoot, Result, UniqueID } from "@rdx/core";
|
||||
|
||||
export interface IRoleProps {}
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { AggregateRoot, EmailAddress, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { AggregateRoot, EmailAddress, Result, UniqueID } from "@rdx/core";
|
||||
import { UserAuthenticatedEvent } from "../events";
|
||||
import { Username } from "../value-objects";
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DomainEntity, EmailAddress, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { DomainEntity, EmailAddress, Result, UniqueID } from "@rdx/core";
|
||||
|
||||
export interface IJWTPayloadProps {
|
||||
tabId: UniqueID;
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DomainEntity, EmailAddress, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { DomainEntity, EmailAddress, Result, UniqueID } from "@rdx/core";
|
||||
import { PlainPassword } from "../value-objects";
|
||||
|
||||
export interface ILoginDataProps {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DomainEntity, EmailAddress, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { DomainEntity, EmailAddress, Result, UniqueID } from "@rdx/core";
|
||||
|
||||
export interface ILogoutDataProps {
|
||||
email: EmailAddress;
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DomainEntity, EmailAddress } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { DomainEntity, EmailAddress, Result } from "@rdx/core";
|
||||
import { HashPassword, Username } from "../value-objects";
|
||||
|
||||
export interface IRegisterDataProps {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DomainEntity, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { DomainEntity, Result, UniqueID } from "@rdx/core";
|
||||
|
||||
export interface ITabContextProps {
|
||||
tabId: UniqueID;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { IDomainEvent, UniqueID } from "@rdx/ddd-domain";
|
||||
import { IDomainEvent, UniqueID } from "@rdx/core";
|
||||
|
||||
export class UserAuthenticatedEvent implements IDomainEvent {
|
||||
public readonly eventName = "UserAuthenticated";
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { EmailAddress } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { EmailAddress, Result } from "@rdx/core";
|
||||
import { AuthenticatedUser } from "../aggregates";
|
||||
import { Username } from "../value-objects";
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, UniqueID } from "@rdx/core";
|
||||
import { Transaction } from "sequelize";
|
||||
import { TabContext } from "../entities";
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { EmailAddress, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Collection, EmailAddress, Result, UniqueID } from "@rdx/core";
|
||||
import { User } from "../aggregates";
|
||||
|
||||
export interface IUserRepository {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { EmailAddress } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { EmailAddress, Result } from "@rdx/core";
|
||||
import {
|
||||
AuthenticatedUser,
|
||||
IJWTPayload,
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { EmailAddress, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { EmailAddress, Result, UniqueID } from "@rdx/core";
|
||||
import {
|
||||
AuthenticatedUser,
|
||||
IAuthenticatedUserRepository,
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, UniqueID } from "@rdx/core";
|
||||
import { TabContext } from "../entities";
|
||||
|
||||
export interface ITabContextService {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, UniqueID } from "@rdx/core";
|
||||
import { TabContext } from "../entities";
|
||||
import { ITabContextRepository } from "../repositories";
|
||||
import { ITabContextService } from "./tab-context-service.interface";
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Collection, Result, UniqueID } from "@rdx/core";
|
||||
import { User } from "../aggregates";
|
||||
|
||||
export interface IUserService {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Collection, Result, UniqueID } from "@rdx/core";
|
||||
import { IUserRepository, User } from "..";
|
||||
import { IUserService } from "./user-service.interface";
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ValueObject } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, ValueObject } from "@rdx/core";
|
||||
import { z } from "zod";
|
||||
|
||||
const RoleSchema = z.enum(["Admin", "User", "Manager", "Editor"]);
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ValueObject } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, ValueObject } from "@rdx/core";
|
||||
import bcrypt from "bcrypt";
|
||||
import { z } from "zod";
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ValueObject } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, ValueObject } from "@rdx/core";
|
||||
import { z } from "zod";
|
||||
|
||||
interface PlainPasswordProps {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ValueObject } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, ValueObject } from "@rdx/core";
|
||||
import { z } from "zod";
|
||||
|
||||
interface TokenProps {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ValueObject } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, ValueObject } from "@rdx/core";
|
||||
import { z } from "zod";
|
||||
|
||||
interface UsernameProps {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { Result, UniqueID } from "@rdx/core";
|
||||
import { ISequelizeMapper, MapperParamsType, SequelizeMapper } from "../../../common";
|
||||
import { TabContext } from "../../domain";
|
||||
import { TabContextCreationAttributes, TabContextModel } from "../sequelize";
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { EmailAddress, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { EmailAddress, Result, UniqueID } from "@rdx/core";
|
||||
import { ISequelizeMapper, MapperParamsType, SequelizeMapper } from "../../../common";
|
||||
import { User, Username } from "../../domain";
|
||||
import { UserCreationAttributes, UserModel } from "../sequelize";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//import { authProvider } from "@contexts/auth/infraestructure";
|
||||
import { UniqueID } from "@rdx/ddd-domain";
|
||||
import { UniqueID } from "@rdx/core";
|
||||
import { NextFunction, Response } from "express";
|
||||
import { ApiError, ExpressController } from "../../../common";
|
||||
import { AuthenticatedRequest } from "../../../common/presentation/express/types";
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { SequelizeRepository } from "@rdx/core";
|
||||
import { EmailAddress } from "@rdx/ddd-domain";
|
||||
import { Result } from "@rdx/utils";
|
||||
import { EmailAddress, Result, SequelizeRepository } from "@rdx/core";
|
||||
import { Transaction } from "sequelize";
|
||||
import { AuthenticatedUser, IAuthenticatedUserRepository, Username } from "../../domain";
|
||||
import { authenticatedUserMapper, IAuthenticatedUserMapper } from "../mappers";
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { IUserRepository, User } from "@/domain";
|
||||
import { SequelizeRepository } from "@rdx/core";
|
||||
import { EmailAddress, UniqueID } from "@rdx/ddd-domain";
|
||||
import { Collection, Result } from "@rdx/utils";
|
||||
import { Collection, EmailAddress, Result, SequelizeRepository, UniqueID } from "@rdx/core";
|
||||
import { Transaction } from "sequelize";
|
||||
import { IUserMapper, userMapper } from "../mappers";
|
||||
import { UserModel } from "./user.model";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Collection, ensureString } from "@rdx/utils";
|
||||
import { Collection, ensureString } from "@rdx/core";
|
||||
import { User } from "../../../domain";
|
||||
import { IListUsersResponseDTO } from "../../dto";
|
||||
|
||||
|
||||
@ -42,6 +42,8 @@
|
||||
"@types/supertest": "^6.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^8.31.0",
|
||||
"@typescript-eslint/parser": "^8.31.0",
|
||||
"@types/winston": "^2.4.4",
|
||||
"@types/react": "^19.1.2",
|
||||
"esbuild": "^0.25.3",
|
||||
"esbuild-register": "^3.6.0",
|
||||
"eslint": "^9.25.1",
|
||||
@ -51,10 +53,6 @@
|
||||
"typescript": "5.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@rdx/ddd-domain": "workspace:*",
|
||||
"@rdx/logger": "workspace:*",
|
||||
"@rdx/modules": "workspace:*",
|
||||
"@rdx/utils": "workspace:*",
|
||||
"bcrypt": "^5.1.1",
|
||||
"body-parser": "^2.2.0",
|
||||
"cors": "^2.8.5",
|
||||
@ -74,7 +72,14 @@
|
||||
"path": "^0.12.7",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"response-time": "^2.3.3",
|
||||
"sequelize": "^6.37.7",
|
||||
"zod": "^3.24.3"
|
||||
"zod": "^3.24.3",
|
||||
"cls-rtracer": "^2.6.3",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"sequelize": "^6.37.5",
|
||||
"shallow-equal-object": "^1.1.1",
|
||||
"uuid": "^11.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { logger } from "@rdx/logger";
|
||||
import { logger } from "../infrastructure";
|
||||
import { DomainEntity } from "./domain-entity";
|
||||
import { IDomainEvent } from "./events";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Result, Maybe } from "@rdx/utils";
|
||||
import { z } from "zod";
|
||||
import { Maybe, Result } from "../../helpers";
|
||||
import { ValueObject } from "./value-object";
|
||||
|
||||
interface EmailAddressProps {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user