feat: API Gateway (Express 5 + Prisma + Monday) y conexion de apps al API
- api-gateway: servicio Monday (retry 429/complejidad, paginacion cursor, column IDs por titulo), endpoints unidades/cotizaciones/clientes/planes, webhook con handshake challenge, Prisma SQLite dev, 55 tests - cotizador: inventario desde /api/unidades con fallback a seed - alta-clientes: POST /api/clientes + upload multipart de documentos - cobranza: persistencia via API con respaldo offline en localStorage - .env.example con board IDs del workspace Frasa-CAS
This commit is contained in:
23
api-gateway/src/middleware/errorHandler.ts
Normal file
23
api-gateway/src/middleware/errorHandler.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import type { NextFunction, Request, Response } from 'express'
|
||||
import { ZodError } from 'zod'
|
||||
import { MulterError } from 'multer'
|
||||
import { AppError } from '../utils/errors.js'
|
||||
|
||||
/** Error handler central: zod → 400 con issues, AppError → su status, resto → 500 */
|
||||
export function errorHandler(err: unknown, req: Request, res: Response, _next: NextFunction): void {
|
||||
if (err instanceof ZodError) {
|
||||
res.status(400).json({ error: 'Validación fallida', issues: err.issues })
|
||||
return
|
||||
}
|
||||
if (err instanceof MulterError) {
|
||||
res.status(400).json({ error: `Error de carga de archivos: ${err.message}` })
|
||||
return
|
||||
}
|
||||
if (err instanceof AppError) {
|
||||
res.status(err.status).json({ error: err.message })
|
||||
return
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`[500] ${req.method} ${req.originalUrl}:`, err)
|
||||
res.status(500).json({ error: 'Error interno del servidor' })
|
||||
}
|
||||
11
api-gateway/src/middleware/requestLogger.ts
Normal file
11
api-gateway/src/middleware/requestLogger.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { NextFunction, Request, Response } from 'express'
|
||||
|
||||
/** Logger de requests simple: método, ruta, status y duración */
|
||||
export function requestLogger(req: Request, res: Response, next: NextFunction): void {
|
||||
const inicio = Date.now()
|
||||
res.on('finish', () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`${req.method} ${req.originalUrl} ${res.statusCode} ${Date.now() - inicio}ms`)
|
||||
})
|
||||
next()
|
||||
}
|
||||
Reference in New Issue
Block a user