fix: resolve TypeScript compilation errors in API

- Add explicit IRouter type to all route files
- Add explicit Express type to app.ts
- Fix env.ts by moving getCorsOrigins after parsing
- Fix token.ts SignOptions type for expiresIn
- Cast req.params.id to String() in controllers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Consultoria AS
2026-01-31 06:48:26 +00:00
parent 3098a40356
commit 3466ec740e
19 changed files with 50 additions and 48 deletions

View File

@@ -1,4 +1,4 @@
import express from 'express'; import express, { type Express } from 'express';
import cors from 'cors'; import cors from 'cors';
import helmet from 'helmet'; import helmet from 'helmet';
import { env, getCorsOrigins } from './config/env.js'; import { env, getCorsOrigins } from './config/env.js';
@@ -16,7 +16,7 @@ import { tenantsRoutes } from './routes/tenants.routes.js';
import fielRoutes from './routes/fiel.routes.js'; import fielRoutes from './routes/fiel.routes.js';
import satRoutes from './routes/sat.routes.js'; import satRoutes from './routes/sat.routes.js';
const app = express(); const app: Express = express();
// Security // Security
app.use(helmet()); app.use(helmet());

View File

@@ -15,11 +15,6 @@ const envSchema = z.object({
CORS_ORIGIN: z.string().default('http://localhost:3000'), CORS_ORIGIN: z.string().default('http://localhost:3000'),
}); });
// Parse CORS origins (comma-separated) into array
export function getCorsOrigins(): string[] {
return parsed.data.CORS_ORIGIN.split(',').map(origin => origin.trim());
}
const parsed = envSchema.safeParse(process.env); const parsed = envSchema.safeParse(process.env);
if (!parsed.success) { if (!parsed.success) {
@@ -28,3 +23,8 @@ if (!parsed.success) {
} }
export const env = parsed.data; export const env = parsed.data;
// Parse CORS origins (comma-separated) into array
export function getCorsOrigins(): string[] {
return env.CORS_ORIGIN.split(',').map(origin => origin.trim());
}

View File

@@ -17,7 +17,7 @@ export async function getAlertas(req: Request, res: Response, next: NextFunction
export async function getAlerta(req: Request, res: Response, next: NextFunction) { export async function getAlerta(req: Request, res: Response, next: NextFunction) {
try { try {
const alerta = await alertasService.getAlertaById(req.tenantSchema!, parseInt(req.params.id)); const alerta = await alertasService.getAlertaById(req.tenantSchema!, parseInt(String(req.params.id)));
if (!alerta) { if (!alerta) {
return res.status(404).json({ message: 'Alerta no encontrada' }); return res.status(404).json({ message: 'Alerta no encontrada' });
} }
@@ -38,7 +38,7 @@ export async function createAlerta(req: Request, res: Response, next: NextFuncti
export async function updateAlerta(req: Request, res: Response, next: NextFunction) { export async function updateAlerta(req: Request, res: Response, next: NextFunction) {
try { try {
const alerta = await alertasService.updateAlerta(req.tenantSchema!, parseInt(req.params.id), req.body); const alerta = await alertasService.updateAlerta(req.tenantSchema!, parseInt(String(req.params.id)), req.body);
res.json(alerta); res.json(alerta);
} catch (error) { } catch (error) {
next(error); next(error);
@@ -47,7 +47,7 @@ export async function updateAlerta(req: Request, res: Response, next: NextFuncti
export async function deleteAlerta(req: Request, res: Response, next: NextFunction) { export async function deleteAlerta(req: Request, res: Response, next: NextFunction) {
try { try {
await alertasService.deleteAlerta(req.tenantSchema!, parseInt(req.params.id)); await alertasService.deleteAlerta(req.tenantSchema!, parseInt(String(req.params.id)));
res.status(204).send(); res.status(204).send();
} catch (error) { } catch (error) {
next(error); next(error);

View File

@@ -35,7 +35,7 @@ export async function createEvento(req: Request, res: Response, next: NextFuncti
export async function updateEvento(req: Request, res: Response, next: NextFunction) { export async function updateEvento(req: Request, res: Response, next: NextFunction) {
try { try {
const evento = await calendarioService.updateEvento(req.tenantSchema!, parseInt(req.params.id), req.body); const evento = await calendarioService.updateEvento(req.tenantSchema!, parseInt(String(req.params.id)), req.body);
res.json(evento); res.json(evento);
} catch (error) { } catch (error) {
next(error); next(error);
@@ -44,7 +44,7 @@ export async function updateEvento(req: Request, res: Response, next: NextFuncti
export async function deleteEvento(req: Request, res: Response, next: NextFunction) { export async function deleteEvento(req: Request, res: Response, next: NextFunction) {
try { try {
await calendarioService.deleteEvento(req.tenantSchema!, parseInt(req.params.id)); await calendarioService.deleteEvento(req.tenantSchema!, parseInt(String(req.params.id)));
res.status(204).send(); res.status(204).send();
} catch (error) { } catch (error) {
next(error); next(error);

View File

@@ -33,7 +33,7 @@ export async function getCfdiById(req: Request, res: Response, next: NextFunctio
return next(new AppError(400, 'Schema no configurado')); return next(new AppError(400, 'Schema no configurado'));
} }
const cfdi = await cfdiService.getCfdiById(req.tenantSchema, req.params.id); const cfdi = await cfdiService.getCfdiById(req.tenantSchema, String(req.params.id));
if (!cfdi) { if (!cfdi) {
return next(new AppError(404, 'CFDI no encontrado')); return next(new AppError(404, 'CFDI no encontrado'));
@@ -131,7 +131,7 @@ export async function deleteCfdi(req: Request, res: Response, next: NextFunction
return next(new AppError(403, 'No tienes permisos para eliminar CFDIs')); return next(new AppError(403, 'No tienes permisos para eliminar CFDIs'));
} }
await cfdiService.deleteCfdi(req.tenantSchema, req.params.id); await cfdiService.deleteCfdi(req.tenantSchema, String(req.params.id));
res.status(204).send(); res.status(204).send();
} catch (error) { } catch (error) {
next(error); next(error);

View File

@@ -22,7 +22,7 @@ export async function getTenant(req: Request, res: Response, next: NextFunction)
throw new AppError(403, 'Solo administradores pueden ver detalles de clientes'); throw new AppError(403, 'Solo administradores pueden ver detalles de clientes');
} }
const tenant = await tenantsService.getTenantById(req.params.id); const tenant = await tenantsService.getTenantById(String(req.params.id));
if (!tenant) { if (!tenant) {
throw new AppError(404, 'Cliente no encontrado'); throw new AppError(404, 'Cliente no encontrado');
} }
@@ -65,7 +65,7 @@ export async function updateTenant(req: Request, res: Response, next: NextFuncti
throw new AppError(403, 'Solo administradores pueden editar clientes'); throw new AppError(403, 'Solo administradores pueden editar clientes');
} }
const { id } = req.params; const id = String(req.params.id);
const { nombre, rfc, plan, cfdiLimit, usersLimit, active } = req.body; const { nombre, rfc, plan, cfdiLimit, usersLimit, active } = req.body;
const tenant = await tenantsService.updateTenant(id, { const tenant = await tenantsService.updateTenant(id, {
@@ -89,7 +89,7 @@ export async function deleteTenant(req: Request, res: Response, next: NextFuncti
throw new AppError(403, 'Solo administradores pueden eliminar clientes'); throw new AppError(403, 'Solo administradores pueden eliminar clientes');
} }
await tenantsService.deleteTenant(req.params.id); await tenantsService.deleteTenant(String(req.params.id));
res.status(204).send(); res.status(204).send();
} catch (error) { } catch (error) {
next(error); next(error);

View File

@@ -1,9 +1,9 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
import { tenantMiddleware } from '../middlewares/tenant.middleware.js'; import { tenantMiddleware } from '../middlewares/tenant.middleware.js';
import * as alertasController from '../controllers/alertas.controller.js'; import * as alertasController from '../controllers/alertas.controller.js';
const router = Router(); const router: IRouter = Router();
router.use(authenticate); router.use(authenticate);
router.use(tenantMiddleware); router.use(tenantMiddleware);

View File

@@ -1,8 +1,8 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import * as authController from '../controllers/auth.controller.js'; import * as authController from '../controllers/auth.controller.js';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
const router = Router(); const router: IRouter = Router();
router.post('/register', authController.register); router.post('/register', authController.register);
router.post('/login', authController.login); router.post('/login', authController.login);

View File

@@ -1,9 +1,9 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
import { tenantMiddleware } from '../middlewares/tenant.middleware.js'; import { tenantMiddleware } from '../middlewares/tenant.middleware.js';
import * as calendarioController from '../controllers/calendario.controller.js'; import * as calendarioController from '../controllers/calendario.controller.js';
const router = Router(); const router: IRouter = Router();
router.use(authenticate); router.use(authenticate);
router.use(tenantMiddleware); router.use(tenantMiddleware);

View File

@@ -1,9 +1,9 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
import { tenantMiddleware } from '../middlewares/tenant.middleware.js'; import { tenantMiddleware } from '../middlewares/tenant.middleware.js';
import * as cfdiController from '../controllers/cfdi.controller.js'; import * as cfdiController from '../controllers/cfdi.controller.js';
const router = Router(); const router: IRouter = Router();
router.use(authenticate); router.use(authenticate);
router.use(tenantMiddleware); router.use(tenantMiddleware);

View File

@@ -1,9 +1,9 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
import { tenantMiddleware } from '../middlewares/tenant.middleware.js'; import { tenantMiddleware } from '../middlewares/tenant.middleware.js';
import * as dashboardController from '../controllers/dashboard.controller.js'; import * as dashboardController from '../controllers/dashboard.controller.js';
const router = Router(); const router: IRouter = Router();
router.use(authenticate); router.use(authenticate);
router.use(tenantMiddleware); router.use(tenantMiddleware);

View File

@@ -1,9 +1,9 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
import { tenantMiddleware } from '../middlewares/tenant.middleware.js'; import { tenantMiddleware } from '../middlewares/tenant.middleware.js';
import * as exportController from '../controllers/export.controller.js'; import * as exportController from '../controllers/export.controller.js';
const router = Router(); const router: IRouter = Router();
router.use(authenticate); router.use(authenticate);
router.use(tenantMiddleware); router.use(tenantMiddleware);

View File

@@ -1,8 +1,8 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import * as fielController from '../controllers/fiel.controller.js'; import * as fielController from '../controllers/fiel.controller.js';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
const router = Router(); const router: IRouter = Router();
// Todas las rutas requieren autenticación // Todas las rutas requieren autenticación
router.use(authenticate); router.use(authenticate);

View File

@@ -1,9 +1,9 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
import { tenantMiddleware } from '../middlewares/tenant.middleware.js'; import { tenantMiddleware } from '../middlewares/tenant.middleware.js';
import * as impuestosController from '../controllers/impuestos.controller.js'; import * as impuestosController from '../controllers/impuestos.controller.js';
const router = Router(); const router: IRouter = Router();
router.use(authenticate); router.use(authenticate);
router.use(tenantMiddleware); router.use(tenantMiddleware);

View File

@@ -1,9 +1,9 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
import { tenantMiddleware } from '../middlewares/tenant.middleware.js'; import { tenantMiddleware } from '../middlewares/tenant.middleware.js';
import * as reportesController from '../controllers/reportes.controller.js'; import * as reportesController from '../controllers/reportes.controller.js';
const router = Router(); const router: IRouter = Router();
router.use(authenticate); router.use(authenticate);
router.use(tenantMiddleware); router.use(tenantMiddleware);

View File

@@ -1,8 +1,8 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import * as satController from '../controllers/sat.controller.js'; import * as satController from '../controllers/sat.controller.js';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
const router = Router(); const router: IRouter = Router();
// Todas las rutas requieren autenticación // Todas las rutas requieren autenticación
router.use(authenticate); router.use(authenticate);

View File

@@ -1,8 +1,8 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
import * as tenantsController from '../controllers/tenants.controller.js'; import * as tenantsController from '../controllers/tenants.controller.js';
const router = Router(); const router: IRouter = Router();
router.use(authenticate); router.use(authenticate);

View File

@@ -1,8 +1,8 @@
import { Router } from 'express'; import { Router, type IRouter } from 'express';
import { authenticate } from '../middlewares/auth.middleware.js'; import { authenticate } from '../middlewares/auth.middleware.js';
import * as usuariosController from '../controllers/usuarios.controller.js'; import * as usuariosController from '../controllers/usuarios.controller.js';
const router = Router(); const router: IRouter = Router();
router.use(authenticate); router.use(authenticate);

View File

@@ -1,17 +1,19 @@
import jwt from 'jsonwebtoken'; import jwt, { type SignOptions } from 'jsonwebtoken';
import type { JWTPayload } from '@horux/shared'; import type { JWTPayload } from '@horux/shared';
import { env } from '../config/env.js'; import { env } from '../config/env.js';
export function generateAccessToken(payload: Omit<JWTPayload, 'iat' | 'exp'>): string { export function generateAccessToken(payload: Omit<JWTPayload, 'iat' | 'exp'>): string {
return jwt.sign(payload, env.JWT_SECRET, { const options: SignOptions = {
expiresIn: env.JWT_EXPIRES_IN, expiresIn: env.JWT_EXPIRES_IN as SignOptions['expiresIn'],
}); };
return jwt.sign(payload, env.JWT_SECRET, options);
} }
export function generateRefreshToken(payload: Omit<JWTPayload, 'iat' | 'exp'>): string { export function generateRefreshToken(payload: Omit<JWTPayload, 'iat' | 'exp'>): string {
return jwt.sign(payload, env.JWT_SECRET, { const options: SignOptions = {
expiresIn: env.JWT_REFRESH_EXPIRES_IN, expiresIn: env.JWT_REFRESH_EXPIRES_IN as SignOptions['expiresIn'],
}); };
return jwt.sign(payload, env.JWT_SECRET, options);
} }
export function verifyToken(token: string): JWTPayload { export function verifyToken(token: string): JWTPayload {