.
This commit is contained in:
parent
0fdf18baf3
commit
484f0119a7
12
.vscode/launch.json
vendored
12
.vscode/launch.json
vendored
@ -1,12 +1,20 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "WEB: Run in Development Mode",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "pnpm",
|
||||
"runtimeArgs": ["run", "dev", "--filter", "web"],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "SERVER: Run in Development Mode",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "npm",
|
||||
"runtimeArgs": ["run", "dev"],
|
||||
"runtimeExecutable": "pnpm",
|
||||
"runtimeArgs": ["run", "dev", "--filter", "server"],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
|
||||
@ -42,6 +42,7 @@
|
||||
"dependencies": {
|
||||
"@erp/core": "workspace:*",
|
||||
"@erp/auth": "workspace:*",
|
||||
"@erp/invoices": "workspace:*",
|
||||
"bcrypt": "^5.1.1",
|
||||
"cls-rtracer": "^2.6.3",
|
||||
"cors": "^2.8.5",
|
||||
|
||||
@ -5,9 +5,12 @@ import os from "node:os";
|
||||
import { createApp } from "./app";
|
||||
import { ENV } from "./config";
|
||||
import { tryConnectToDatabase } from "./config/database";
|
||||
import { listRoutes } from "./lib";
|
||||
import { initModules } from "./lib/modules";
|
||||
import { registerModules } from "./register-modules";
|
||||
|
||||
const API_BASE_PATH = "/api/v1";
|
||||
|
||||
// Guardamos información del estado del servidor
|
||||
export const currentState = {
|
||||
launchedAt: DateTime.now(),
|
||||
@ -129,7 +132,10 @@ process.on("uncaughtException", (error: Error) => {
|
||||
// initStructure(sequelizeConn.connection);
|
||||
// insertUsers();
|
||||
|
||||
await initModules({ app, database, baseRoutePath: "/api/v1", logger });
|
||||
await initModules({ app, database, baseRoutePath: API_BASE_PATH, logger });
|
||||
|
||||
logger.info("holaaaaaaaaaaaaaaaaa");
|
||||
console.log(listRoutes(app._router, API_BASE_PATH));
|
||||
|
||||
server.listen(currentState.port, () => {
|
||||
server.emit("listening");
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from "./list-routes";
|
||||
export * from "./logger";
|
||||
export * from "./modules";
|
||||
|
||||
30
apps/server/src/lib/list-routes.ts
Normal file
30
apps/server/src/lib/list-routes.ts
Normal file
@ -0,0 +1,30 @@
|
||||
// Función para listar rutas
|
||||
export function listRoutes(appOrRouter, basePath = "") {
|
||||
const routes = [];
|
||||
|
||||
appOrRouter.stack.forEach((middleware) => {
|
||||
if (middleware.route) {
|
||||
// Es una ruta directa
|
||||
const methods = Object.keys(middleware.route.methods).map((m) => m.toUpperCase());
|
||||
routes.push({
|
||||
path: basePath + middleware.route.path,
|
||||
methods,
|
||||
});
|
||||
} else if (middleware.name === "router" && middleware.handle.stack) {
|
||||
// Es un router anidado
|
||||
const newBasePath =
|
||||
basePath +
|
||||
(middleware.regexp?.source !== "^\\/?$"
|
||||
? middleware.regexp
|
||||
?.toString()
|
||||
.replace(/^\/\^\\/, "")
|
||||
.replace(/\\\/\?\(\?=\\\/\|\$\)\/i$/, "")
|
||||
.replace(/\\\//g, "/")
|
||||
: "");
|
||||
const childRoutes = listRoutes(middleware.handle, basePath + (middleware?.path || ""));
|
||||
routes.push(...childRoutes);
|
||||
}
|
||||
});
|
||||
|
||||
return routes;
|
||||
}
|
||||
@ -7,10 +7,10 @@ const registeredModules: Map<string, IModuleServer> = new Map();
|
||||
const initializedModules = new Set<string>();
|
||||
|
||||
export function registerModule(pkg: IModuleServer) {
|
||||
if (registeredModules.has(pkg.metadata.name)) {
|
||||
throw new Error(`❌ Paquete "${pkg.metadata.name}" ya registrado.`);
|
||||
if (registeredModules.has(pkg.name)) {
|
||||
throw new Error(`❌ Paquete "${pkg.name}" ya registrado.`);
|
||||
}
|
||||
registeredModules.set(pkg.metadata.name, pkg);
|
||||
registeredModules.set(pkg.name, pkg);
|
||||
}
|
||||
|
||||
export async function initModules(params: ModuleParams) {
|
||||
@ -27,7 +27,7 @@ const loadModule = (name: string, params: ModuleParams) => {
|
||||
if (!pkg) throw new Error(`❌ Paquete "${name}" no encontrado.`);
|
||||
|
||||
// Resolver dependencias primero
|
||||
const deps = pkg.metadata.dependencies || [];
|
||||
const deps = pkg.dependencies || [];
|
||||
deps.forEach((dep) => loadModule(dep, params));
|
||||
|
||||
// Inicializar el module
|
||||
@ -44,7 +44,7 @@ const loadModule = (name: string, params: ModuleParams) => {
|
||||
if (pkgApi?.services) {
|
||||
const services = pkgApi.services;
|
||||
if (services && typeof services === "object") {
|
||||
registerService(pkg.metadata.name, services);
|
||||
registerService(pkg.name, services);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { authAPIModule } from "@erp/auth/api";
|
||||
import { invoicesAPIModule } from "@erp/invoices/api";
|
||||
import { registerModule } from "./lib";
|
||||
//import { invoicesAPIModule } from "@erp/invoices/api";
|
||||
|
||||
export const registerModules = () => {
|
||||
registerModule(authAPIModule);
|
||||
//registerModule(invoicesAPIModule);
|
||||
registerModule(invoicesAPIModule);
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { AuthModuleManifiest } from "@erp/auth/client";
|
||||
import { IModuleClient } from "@erp/core/client";
|
||||
//import InvoicesModule from "@erp/invoices/client";
|
||||
import { InvoicesModuleManifiest } from "@erp/invoices/client";
|
||||
|
||||
export const modules: IModuleClient[] = [AuthModuleManifiest];
|
||||
export const modules: IModuleClient[] = [AuthModuleManifiest, InvoicesModuleManifiest];
|
||||
|
||||
@ -32,6 +32,8 @@ export const AppRoutes = (): JSX.Element => {
|
||||
|
||||
const grouped = groupModulesByLayout(modules);
|
||||
|
||||
console.log(grouped);
|
||||
|
||||
return (
|
||||
<Router>
|
||||
<ScrollToTop />
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
import { IModuleServer, ModuleParams } from "@erp/core";
|
||||
import { IModuleServer, ModuleParams } from "@erp/core/api";
|
||||
|
||||
export const authAPIModule: IModuleServer = {
|
||||
metadata: {
|
||||
name: "auth",
|
||||
version: "1.0.0",
|
||||
dependencies: [],
|
||||
},
|
||||
name: "auth",
|
||||
version: "1.0.0",
|
||||
dependencies: [],
|
||||
init(params: ModuleParams) {
|
||||
// const contacts = getService<ContactsService>("contacts");
|
||||
const { logger } = params;
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { PropsWithChildren, createContext, useEffect, useState } from "react";
|
||||
import { IAuthService } from "../services";
|
||||
|
||||
export interface AuthContextType {
|
||||
export type AuthContextType = {
|
||||
token: string | null;
|
||||
isAuthenticated: boolean;
|
||||
login: (email: string, password: string) => Promise<void>;
|
||||
logout: () => void;
|
||||
}
|
||||
};
|
||||
|
||||
export interface AuthContextParams {
|
||||
authService: IAuthService;
|
||||
@ -20,7 +20,10 @@ export const AuthContext = createContext<AuthContextType | undefined>(undefined)
|
||||
/**
|
||||
* Proveedor de autenticación para toda la app.
|
||||
*/
|
||||
export const AuthProvider = ({ params, children }: PropsWithChildren<{ params: any }>) => {
|
||||
export const AuthProvider = ({
|
||||
params,
|
||||
children,
|
||||
}: PropsWithChildren<{ params: AuthContextParams }>) => {
|
||||
const { getAccessToken, setAccessToken, clearAccessToken, authService } = params;
|
||||
|
||||
const [token, setToken] = useState<string | null>(getAccessToken());
|
||||
@ -30,9 +33,9 @@ export const AuthProvider = ({ params, children }: PropsWithChildren<{ params: a
|
||||
}, []);
|
||||
|
||||
const login = async (email: string, password: string) => {
|
||||
const { access_token } = await authService.login({ email, password });
|
||||
setAccessToken(access_token);
|
||||
setToken(access_token);
|
||||
const { token } = await authService.login({ email, password });
|
||||
setAccessToken(token);
|
||||
setToken(token);
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
|
||||
@ -7,7 +7,7 @@ import { AuthContext, AuthContextType } from "../context";
|
||||
export const useAuth = (): AuthContextType => {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error("useAuth debe usarse dentro de <AuthProvider>");
|
||||
throw new Error("useAuth must be used within a AuthProvider");
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ITransactionManager } from "@erp/core";
|
||||
import { ITransactionManager } from "@erp/core/api";
|
||||
import { Criteria } from "@repo/rdx-criteria/server";
|
||||
import { Collection, Result } from "@repo/rdx-utils";
|
||||
import { Transaction } from "sequelize";
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import { IModuleServer, ModuleParams } from "@erp/core";
|
||||
import { IModuleServer, ModuleParams } from "@erp/core/api";
|
||||
import { invoicesRouter, models } from "./infrastructure";
|
||||
|
||||
export const invoicesAPIModule: IModuleServer = {
|
||||
metadata: {
|
||||
name: "invoices",
|
||||
version: "1.0.0",
|
||||
dependencies: [],
|
||||
},
|
||||
name: "invoices",
|
||||
version: "1.0.0",
|
||||
dependencies: [],
|
||||
|
||||
init(params: ModuleParams) {
|
||||
// const contacts = getService<ContactsService>("contacts");
|
||||
const { logger } = params;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ModuleParams } from "@erp/core";
|
||||
import { ModuleParams } from "@erp/core/api";
|
||||
import { Application, NextFunction, Request, Response, Router } from "express";
|
||||
import { Sequelize } from "sequelize";
|
||||
import { buildListInvoicesController } from "../../presentation";
|
||||
@ -21,6 +21,8 @@ export const invoicesRouter = (params: ModuleParams) => {
|
||||
}
|
||||
);
|
||||
|
||||
app.use(`${baseRoutePath}/invoices`, routes);
|
||||
|
||||
/*routes.get(
|
||||
"/:invoiceId",
|
||||
//checkTabContext,
|
||||
@ -59,6 +61,4 @@ export const invoicesRouter = (params: ModuleParams) => {
|
||||
buildDeleteInvoiceController().execute(req, res, next);
|
||||
}
|
||||
);*/
|
||||
|
||||
app.use(`${baseRoutePath}/invoices`, routes);
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ISequelizeMapper, MapperParamsType, SequelizeMapper } from "@erp/core";
|
||||
import { ISequelizeMapper, MapperParamsType, SequelizeMapper } from "@erp/core/api";
|
||||
import { UniqueID } from "@repo/rdx-ddd";
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import { InferCreationAttributes } from "sequelize";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ISequelizeMapper, MapperParamsType, SequelizeMapper } from "@erp/core";
|
||||
import { ISequelizeMapper, MapperParamsType, SequelizeMapper } from "@erp/core/api";
|
||||
import { UniqueID, UtcDate } from "@repo/rdx-ddd";
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import { Invoice, InvoiceNumber, InvoiceSerie, InvoiceStatus } from "../../domain";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { SequelizeRepository } from "@erp/core";
|
||||
import { SequelizeRepository } from "@erp/core/api";
|
||||
import { Criteria } from "@repo/rdx-criteria/server";
|
||||
import { UniqueID } from "@repo/rdx-ddd";
|
||||
import { Collection, Result } from "@repo/rdx-utils";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ExpressController } from "@erp/core";
|
||||
import { ExpressController } from "@erp/core/api";
|
||||
import { UniqueID } from "@repo/rdx-ddd";
|
||||
import { GetInvoiceUseCase } from "../../application";
|
||||
import { IGetInvoicePresenter } from "./presenter";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { SequelizeTransactionManager } from "@erp/core";
|
||||
import { SequelizeTransactionManager } from "@erp/core/api";
|
||||
import { Sequelize } from "sequelize";
|
||||
import { InvoiceService } from "../../domain";
|
||||
import { InvoiceRepository, invoiceMapper } from "../../infrastructure";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { SequelizeTransactionManager } from "@erp/core";
|
||||
import { SequelizeTransactionManager } from "@erp/core/api";
|
||||
import { Sequelize } from "sequelize";
|
||||
import { ListInvoicesUseCase } from "../../application";
|
||||
import { InvoiceService } from "../../domain";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ExpressController } from "@erp/core";
|
||||
import { ExpressController } from "@erp/core/api";
|
||||
import { ListInvoicesUseCase } from "../../application";
|
||||
import { IListInvoicesPresenter } from "./presenter";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { IListResponseDTO } from "@erp/core";
|
||||
import { IListResponseDTO } from "@erp/core/api";
|
||||
import { Criteria } from "@repo/rdx-criteria/server";
|
||||
import { Collection } from "@repo/rdx-utils";
|
||||
import { IListInvoicesResponseDTO } from "../../../../common/dto";
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Outlet } from "react-router-dom";
|
||||
import { InvoicesProvider } from "../hooks";
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
export const InvoicesLayout = () => {
|
||||
export const InvoicesLayout = ({ children }: PropsWithChildren) => {
|
||||
return (
|
||||
<InvoicesProvider>
|
||||
<Outlet />
|
||||
</InvoicesProvider>
|
||||
<>
|
||||
<h1>hola</h1>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
1
modules/invoices/src/web/context/index.ts
Normal file
1
modules/invoices/src/web/context/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./invoices-context";
|
||||
21
modules/invoices/src/web/context/invoices-context.tsx
Normal file
21
modules/invoices/src/web/context/invoices-context.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import { usePagination } from "@erp/core/client";
|
||||
import { PropsWithChildren, createContext } from "react";
|
||||
|
||||
export type InvoicesContextType = {};
|
||||
|
||||
export const InvoicesContext = createContext<InvoicesContextType | null>(null);
|
||||
|
||||
export const InvoicesProvider = ({ children }: PropsWithChildren) => {
|
||||
const [pagination, setPagination] = usePagination();
|
||||
|
||||
return (
|
||||
<InvoicesContext.Provider
|
||||
value={{
|
||||
pagination,
|
||||
setPagination,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</InvoicesContext.Provider>
|
||||
);
|
||||
};
|
||||
@ -1,27 +1,11 @@
|
||||
import { usePagination } from "@erp/core/hooks";
|
||||
import { PropsWithChildren, createContext, useContext } from "react";
|
||||
import { useContext } from "react";
|
||||
import { InvoicesContext, InvoicesContextType } from "../context";
|
||||
|
||||
export type IInvoicesContextState = {};
|
||||
|
||||
export const InvoicesContext = createContext<IInvoicesContextState | null>(null);
|
||||
|
||||
export const InvoicesProvider = ({ children }: PropsWithChildren) => {
|
||||
const [pagination, setPagination] = usePagination();
|
||||
|
||||
return (
|
||||
<InvoicesContext.Provider
|
||||
value={{
|
||||
pagination,
|
||||
setPagination,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</InvoicesContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useInvoicesContext = () => {
|
||||
export const useInvoices = (): InvoicesContextType => {
|
||||
const context = useContext(InvoicesContext);
|
||||
if (context === null) throw new Error("useInvoices must be used within a InvoicesProvider");
|
||||
if (!context) {
|
||||
throw new Error("useInvoices must be used within a InvoicesProvider");
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
|
||||
@ -1,11 +1,4 @@
|
||||
import { IListResponseDTO } from "@erp/core";
|
||||
import {
|
||||
IGetListDataProviderParams,
|
||||
UseListQueryResult,
|
||||
useDataSource,
|
||||
useList,
|
||||
useQueryKey,
|
||||
} from "@erp/core/client";
|
||||
import { useDataSource, useQueryKey } from "@erp/core/client";
|
||||
import { IListInvoicesResponseDTO } from "@erp/invoices/common/dto";
|
||||
|
||||
export type UseInvoicesListParams = Omit<IGetListDataProviderParams, "filters" | "resource"> & {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//import { ProtectedRoute } from "@erp/auth/components";
|
||||
import { JSX, lazy } from "react";
|
||||
import { Route } from "react-router-dom";
|
||||
import { ModuleClientParams } from "@erp/core/client";
|
||||
import { lazy } from "react";
|
||||
import { Outlet, RouteObject } from "react-router-dom";
|
||||
|
||||
// Lazy load components
|
||||
const InvoicesLayout = lazy(() =>
|
||||
@ -27,24 +27,32 @@ const DashboardPage = lazy(() => import("./app").then((m) => ({ default: m.Dashb
|
||||
const InvoicesLayout = lazy(() => import("./app").then((m) => ({ default: m.InvoicesLayout })));
|
||||
const InvoicesList = lazy(() => import("./app").then((m) => ({ default: m.InvoicesList })));*/
|
||||
|
||||
export const InvoiceRoutes = (): JSX.Element => {
|
||||
return (
|
||||
<Route path='/invoices' element={<InvoicesLayout />}>
|
||||
<Route index element={<InvoicesList />} />
|
||||
<Route path='list' element={<InvoicesList />} />
|
||||
export const InvoiceRoutes = (params: ModuleClientParams): RouteObject[] => {
|
||||
return [
|
||||
{
|
||||
path: "*",
|
||||
element: (
|
||||
<InvoicesLayout>
|
||||
<Outlet context={params} />
|
||||
</InvoicesLayout>
|
||||
),
|
||||
children: [
|
||||
{ path: "", element: <InvoicesList /> }, // index
|
||||
{ path: "list", element: <InvoicesList /> },
|
||||
{ path: "*", element: <InvoicesList /> },
|
||||
|
||||
{/*<Route path='create' element={<InvoiceCreate />} />
|
||||
<Route path=':id' element={<InvoicesList />} />
|
||||
<Route path=':id/edit' element={<InvoicesList />} />
|
||||
<Route path=':id/delete' element={<InvoicesList />} />
|
||||
<Route path=':id/view' element={<InvoicesList />} />
|
||||
<Route path=':id/print' element={<InvoicesList />} />
|
||||
<Route path=':id/email' element={<InvoicesList />} />
|
||||
<Route path=':id/download' element={<InvoicesList />} />
|
||||
<Route path=':id/duplicate' element={<InvoicesList />} />
|
||||
<Route path=':id/preview' element={<InvoicesList />} />*/}
|
||||
|
||||
<Route path='*' element={<InvoicesList />} />
|
||||
</Route>
|
||||
);
|
||||
//
|
||||
/*{ path: "create", element: <InvoicesList /> },
|
||||
{ path: ":id", element: <InvoicesList /> },
|
||||
{ path: ":id/edit", element: <InvoicesList /> },
|
||||
{ path: ":id/delete", element: <InvoicesList /> },
|
||||
{ path: ":id/view", element: <InvoicesList /> },
|
||||
{ path: ":id/print", element: <InvoicesList /> },
|
||||
{ path: ":id/email", element: <InvoicesList /> },
|
||||
{ path: ":id/download", element: <InvoicesList /> },
|
||||
{ path: ":id/duplicate", element: <InvoicesList /> },
|
||||
{ path: ":id/preview", element: <InvoicesList /> },*/
|
||||
],
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { IModuleClient } from "@erp/core/client";
|
||||
import { IModuleClient, ModuleClientParams } from "@erp/core/client";
|
||||
import i18next from "i18next";
|
||||
import enResources from "../common/locales/en.json";
|
||||
import esResources from "../common/locales/es.json";
|
||||
@ -7,18 +7,18 @@ import { InvoiceRoutes } from "./invoice-routes";
|
||||
const MODULE_NAME = "invoices";
|
||||
const MODULE_VERSION = "1.0.0";
|
||||
|
||||
export const InvoicesModuleManifest: IModuleClient = {
|
||||
export const InvoicesModuleManifiest: IModuleClient = {
|
||||
name: MODULE_NAME,
|
||||
version: MODULE_VERSION,
|
||||
dependencies: ["auth"],
|
||||
protected: true,
|
||||
layout: "app",
|
||||
|
||||
routes: () => {
|
||||
routes: (params: ModuleClientParams) => {
|
||||
i18next.addResourceBundle("en", MODULE_NAME, enResources, true, true);
|
||||
i18next.addResourceBundle("es", MODULE_NAME, esResources, true, true);
|
||||
return InvoiceRoutes();
|
||||
return InvoiceRoutes(params);
|
||||
},
|
||||
};
|
||||
|
||||
export default InvoicesModuleManifest;
|
||||
export default InvoicesModuleManifiest;
|
||||
|
||||
@ -41,6 +41,9 @@ importers:
|
||||
'@erp/core':
|
||||
specifier: workspace:*
|
||||
version: link:../../modules/core
|
||||
'@erp/invoices':
|
||||
specifier: workspace:*
|
||||
version: link:../../modules/invoices
|
||||
bcrypt:
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user