2025-11-06 16:14:49 +00:00
|
|
|
import { globalErrorHandler } from "@erp/core/api";
|
2025-08-12 15:09:04 +00:00
|
|
|
import cors, { CorsOptions } from "cors";
|
2025-01-29 16:01:17 +00:00
|
|
|
import express, { Application } from "express";
|
|
|
|
|
import helmet from "helmet";
|
2025-01-30 10:45:31 +00:00
|
|
|
import responseTime from "response-time";
|
2025-08-12 15:09:04 +00:00
|
|
|
// ❗️ No cargamos dotenv aquí. Debe hacerse en el entrypoint o en ./config.
|
|
|
|
|
// dotenv.config();
|
|
|
|
|
import { ENV } from "./config";
|
2025-10-30 18:26:57 +00:00
|
|
|
import { logger } from "./lib/logger";
|
2025-01-29 16:01:17 +00:00
|
|
|
|
|
|
|
|
export function createApp(): Application {
|
|
|
|
|
const app = express();
|
2025-11-04 09:12:05 +00:00
|
|
|
app.set("port", process.env.SERVER_PORT ?? 3002);
|
2025-01-29 16:01:17 +00:00
|
|
|
|
2025-08-12 15:09:04 +00:00
|
|
|
// Oculta la cabecera x-powered-by
|
2025-01-29 16:01:17 +00:00
|
|
|
app.disable("x-powered-by");
|
|
|
|
|
|
2025-08-12 15:09:04 +00:00
|
|
|
// Desactiva ETag correctamente a nivel de Express
|
|
|
|
|
app.set("etag", false);
|
|
|
|
|
|
|
|
|
|
// ───────────────────────────────────────────────────────────────────────────
|
|
|
|
|
// Parsers
|
2025-01-29 16:01:17 +00:00
|
|
|
app.use(express.json());
|
|
|
|
|
app.use(express.text());
|
|
|
|
|
app.use(express.urlencoded({ extended: true }));
|
|
|
|
|
|
2025-08-12 15:09:04 +00:00
|
|
|
// Métrica de tiempo de respuesta
|
|
|
|
|
app.use(responseTime());
|
2025-01-29 16:01:17 +00:00
|
|
|
|
2025-08-12 15:09:04 +00:00
|
|
|
// ───────────────────────────────────────────────────────────────────────────
|
|
|
|
|
// CORS
|
|
|
|
|
const devCors: CorsOptions = {
|
|
|
|
|
// En desarrollo reflejamos el Origin entrante (permite credenciales)
|
|
|
|
|
origin: true,
|
|
|
|
|
credentials: true,
|
|
|
|
|
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
|
|
|
exposedHeaders: [
|
|
|
|
|
"Content-Disposition",
|
|
|
|
|
"Content-Type",
|
|
|
|
|
"Content-Length",
|
|
|
|
|
"X-Total-Count",
|
|
|
|
|
"Pagination-Count",
|
|
|
|
|
"Pagination-Page",
|
|
|
|
|
"Pagination-Limit",
|
|
|
|
|
],
|
|
|
|
|
};
|
2025-06-17 16:18:25 +00:00
|
|
|
|
2025-08-12 15:09:04 +00:00
|
|
|
const prodCors: CorsOptions = {
|
|
|
|
|
origin: ENV.FRONTEND_URL,
|
|
|
|
|
credentials: true,
|
|
|
|
|
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
|
|
|
exposedHeaders: [
|
|
|
|
|
"Content-Disposition",
|
|
|
|
|
"Content-Type",
|
|
|
|
|
"Content-Length",
|
|
|
|
|
"X-Total-Count",
|
|
|
|
|
"Pagination-Count",
|
|
|
|
|
"Pagination-Page",
|
|
|
|
|
"Pagination-Limit",
|
|
|
|
|
],
|
|
|
|
|
};
|
2025-06-17 16:18:25 +00:00
|
|
|
|
2025-08-12 15:09:04 +00:00
|
|
|
app.use(cors(ENV.NODE_ENV === "development" ? devCors : prodCors));
|
|
|
|
|
|
|
|
|
|
// ───────────────────────────────────────────────────────────────────────────
|
|
|
|
|
// Seguridad HTTP
|
2025-04-01 15:32:53 +00:00
|
|
|
app.use(helmet());
|
|
|
|
|
|
2025-08-12 15:09:04 +00:00
|
|
|
// ───────────────────────────────────────────────────────────────────────────
|
|
|
|
|
// Política de caché por defecto (no almacenamiento)
|
|
|
|
|
app.use((_, res, next) => {
|
2025-04-01 15:32:53 +00:00
|
|
|
res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
|
|
|
|
|
res.setHeader("Pragma", "no-cache");
|
|
|
|
|
res.setHeader("Expires", "0");
|
2025-08-12 15:09:04 +00:00
|
|
|
next();
|
2025-04-01 15:32:53 +00:00
|
|
|
});
|
|
|
|
|
|
2025-08-12 15:09:04 +00:00
|
|
|
// Inicializar Auth Provider (placeholder)
|
|
|
|
|
app.use((_, __, next) => {
|
|
|
|
|
// authProvider.initialize();
|
2025-02-05 20:40:59 +00:00
|
|
|
next();
|
|
|
|
|
});
|
2025-02-01 21:48:13 +00:00
|
|
|
|
2025-08-12 15:09:04 +00:00
|
|
|
// Logging de cada request
|
2025-02-03 13:12:36 +00:00
|
|
|
app.use((req, _, next) => {
|
2025-08-12 15:09:04 +00:00
|
|
|
logger.info(`▶️ Incoming request ${req.method} to ${req.path}`);
|
2025-02-03 13:12:36 +00:00
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
|
2025-11-06 16:14:49 +00:00
|
|
|
// Gestión global de errores.
|
|
|
|
|
// Siempre al final de la cadena de middlewares
|
|
|
|
|
// y después de las rutas.
|
|
|
|
|
app.use(globalErrorHandler);
|
|
|
|
|
|
2025-01-29 16:01:17 +00:00
|
|
|
return app;
|
|
|
|
|
}
|