From 0f70a770ecb29c9edaf85afade84b87826a500fa Mon Sep 17 00:00:00 2001 From: david Date: Mon, 3 Feb 2025 19:03:23 +0100 Subject: [PATCH] . --- apps/server/debug-2025-02-03.log | 354 ++++++++++++++++++ apps/server/error-2025-02-03.log | 31 ++ apps/server/package.json | 4 +- apps/server/src/app.ts | 7 +- .../src/common/domain/aggregate-root.ts | 8 +- .../src/common/infrastructure/logger/index.ts | 9 +- .../sequelize/sequelize-repository.ts | 35 +- .../express/express-controller.ts | 8 +- .../express/middlewares/error-handler.ts | 31 -- .../middlewares/global-error-handler.ts | 34 ++ .../presentation/express/middlewares/index.ts | 2 +- apps/server/src/config/database.ts | 2 + apps/server/src/config/register-models.ts | 18 + .../application/auth-provider.interface.ts | 10 +- .../contexts/auth/application/auth.service.ts | 2 +- .../src/contexts/auth/application/index.ts | 6 +- .../domain/aggregates/authenticated-user.ts | 6 +- .../passport/passport-auth-provider.ts | 54 ++- .../sequelize/auth-user.model.ts | 26 +- .../authenticated-user.repository.ts | 17 +- .../contexts/auth/presentation/auth.routes.ts | 11 +- .../controllers/register.controller.ts | 20 +- .../controllers/register.presenter.ts | 21 ++ .../presentation/dto/auth.response.dto.ts | 8 +- apps/server/src/index.ts | 4 +- pnpm-lock.yaml | 25 +- 26 files changed, 644 insertions(+), 109 deletions(-) delete mode 100644 apps/server/src/common/presentation/express/middlewares/error-handler.ts create mode 100644 apps/server/src/common/presentation/express/middlewares/global-error-handler.ts create mode 100644 apps/server/src/config/register-models.ts create mode 100644 apps/server/src/contexts/auth/presentation/controllers/register.presenter.ts diff --git a/apps/server/debug-2025-02-03.log b/apps/server/debug-2025-02-03.log index ea6de809..5149fce1 100644 --- a/apps/server/debug-2025-02-03.log +++ b/apps/server/debug-2025-02-03.log @@ -501,3 +501,357 @@ {"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:12:00.008Z"} {"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:12:00.008Z"} {"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T13:12:30.183Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:33 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:33:47.073Z"} +{"label":"index.ts","level":"info","message":"Launched in: 64 ms","metadata":{},"timestamp":"2025-02-03T13:33:47.077Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:33:47.078Z"} +{"label":"index.ts","level":"info","message":"Process PID: 40114","metadata":{},"timestamp":"2025-02-03T13:33:47.078Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:33:47.079Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:33:47.080Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:33 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:33:52.391Z"} +{"label":"index.ts","level":"info","message":"Launched in: 64 ms","metadata":{},"timestamp":"2025-02-03T13:33:52.396Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:33:52.396Z"} +{"label":"index.ts","level":"info","message":"Process PID: 40152","metadata":{},"timestamp":"2025-02-03T13:33:52.397Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:33:52.397Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:33:52.398Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:37 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:37:57.969Z"} +{"label":"index.ts","level":"info","message":"Launched in: 72 ms","metadata":{},"timestamp":"2025-02-03T13:37:57.974Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:37:57.974Z"} +{"label":"index.ts","level":"info","message":"Process PID: 40249","metadata":{},"timestamp":"2025-02-03T13:37:57.975Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:37:57.975Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:37:57.976Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:42 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:42:38.093Z"} +{"label":"index.ts","level":"info","message":"Launched in: 66 ms","metadata":{},"timestamp":"2025-02-03T13:42:38.098Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:42:38.098Z"} +{"label":"index.ts","level":"info","message":"Process PID: 40436","metadata":{},"timestamp":"2025-02-03T13:42:38.098Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:42:38.099Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:42:38.100Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T13:43:15.112Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 14:43 CET","metadata":{},"timestamp":"2025-02-03T13:43:15.115Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T13:43:15.116Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T13:43:15.118Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 15:52 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T14:52:35.824Z"} +{"label":"index.ts","level":"info","message":"Launched in: 65 ms","metadata":{},"timestamp":"2025-02-03T14:52:35.828Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T14:52:35.829Z"} +{"label":"index.ts","level":"info","message":"Process PID: 41441","metadata":{},"timestamp":"2025-02-03T14:52:35.830Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T14:52:35.830Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T14:52:35.831Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:06 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:06:14.872Z"} +{"label":"index.ts","level":"info","message":"Launched in: 76 ms","metadata":{},"timestamp":"2025-02-03T15:06:14.877Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:06:14.878Z"} +{"label":"index.ts","level":"info","message":"Process PID: 41656","metadata":{},"timestamp":"2025-02-03T15:06:14.878Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:06:14.879Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:06:14.880Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:06 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:06:17.534Z"} +{"label":"index.ts","level":"info","message":"Launched in: 65 ms","metadata":{},"timestamp":"2025-02-03T15:06:17.538Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:06:17.538Z"} +{"label":"index.ts","level":"info","message":"Process PID: 41694","metadata":{},"timestamp":"2025-02-03T15:06:17.539Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:06:17.539Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:06:17.540Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:06 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:06:22.112Z"} +{"label":"index.ts","level":"info","message":"Launched in: 61 ms","metadata":{},"timestamp":"2025-02-03T15:06:22.117Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:06:22.117Z"} +{"label":"index.ts","level":"info","message":"Process PID: 41737","metadata":{},"timestamp":"2025-02-03T15:06:22.118Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:06:22.118Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:06:22.119Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:11 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:11:06.405Z"} +{"label":"index.ts","level":"info","message":"Launched in: 75 ms","metadata":{},"timestamp":"2025-02-03T15:11:06.410Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:11:06.411Z"} +{"label":"index.ts","level":"info","message":"Process PID: 41809","metadata":{},"timestamp":"2025-02-03T15:11:06.411Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:11:06.412Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:11:06.413Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:38 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:38:01.470Z"} +{"label":"index.ts","level":"info","message":"Launched in: 97 ms","metadata":{},"timestamp":"2025-02-03T15:38:01.477Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:38:01.477Z"} +{"label":"index.ts","level":"info","message":"Process PID: 42348","metadata":{},"timestamp":"2025-02-03T15:38:01.478Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:38:01.478Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:38:01.479Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:38 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:38:31.195Z"} +{"label":"index.ts","level":"info","message":"Launched in: 127 ms","metadata":{},"timestamp":"2025-02-03T15:38:31.200Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:38:31.200Z"} +{"label":"index.ts","level":"info","message":"Process PID: 42493","metadata":{},"timestamp":"2025-02-03T15:38:31.201Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:38:31.201Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:38:31.202Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T15:39:10.809Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:39 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:39:51.236Z"} +{"label":"index.ts","level":"info","message":"Launched in: 116 ms","metadata":{},"timestamp":"2025-02-03T15:39:51.240Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:39:51.240Z"} +{"label":"index.ts","level":"info","message":"Process PID: 42651","metadata":{},"timestamp":"2025-02-03T15:39:51.241Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:39:51.241Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:39:51.242Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:41 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:41:02.744Z"} +{"label":"index.ts","level":"info","message":"Launched in: 112 ms","metadata":{},"timestamp":"2025-02-03T15:41:02.748Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:41:02.749Z"} +{"label":"index.ts","level":"info","message":"Process PID: 42751","metadata":{},"timestamp":"2025-02-03T15:41:02.749Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:41:02.750Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:41:02.750Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:41 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:41:35.476Z"} +{"label":"index.ts","level":"info","message":"Launched in: 111 ms","metadata":{},"timestamp":"2025-02-03T15:41:35.480Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:41:35.481Z"} +{"label":"index.ts","level":"info","message":"Process PID: 42820","metadata":{},"timestamp":"2025-02-03T15:41:35.481Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:41:35.482Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:41:35.482Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:42 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:42:07.872Z"} +{"label":"index.ts","level":"info","message":"Launched in: 111 ms","metadata":{},"timestamp":"2025-02-03T15:42:07.878Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:42:07.879Z"} +{"label":"index.ts","level":"info","message":"Process PID: 42999","metadata":{},"timestamp":"2025-02-03T15:42:07.879Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:42:07.880Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:42:07.880Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:43 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:43:36.295Z"} +{"label":"index.ts","level":"info","message":"Launched in: 112 ms","metadata":{},"timestamp":"2025-02-03T15:43:36.299Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:43:36.300Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43061","metadata":{},"timestamp":"2025-02-03T15:43:36.300Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:43:36.301Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:43:36.301Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:43 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:43:57.574Z"} +{"label":"index.ts","level":"info","message":"Launched in: 111 ms","metadata":{},"timestamp":"2025-02-03T15:43:57.579Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:43:57.579Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43125","metadata":{},"timestamp":"2025-02-03T15:43:57.580Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:43:57.580Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:43:57.581Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:44 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:44:21.746Z"} +{"label":"index.ts","level":"info","message":"Launched in: 132 ms","metadata":{},"timestamp":"2025-02-03T15:44:21.751Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:44:21.752Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43193","metadata":{},"timestamp":"2025-02-03T15:44:21.752Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:44:21.753Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:44:21.753Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:45 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:45:08.119Z"} +{"label":"index.ts","level":"info","message":"Launched in: 106 ms","metadata":{},"timestamp":"2025-02-03T15:45:08.126Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:45:08.126Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43274","metadata":{},"timestamp":"2025-02-03T15:45:08.127Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:45:08.127Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:45:08.127Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:45 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:45:18.635Z"} +{"label":"index.ts","level":"info","message":"Launched in: 120 ms","metadata":{},"timestamp":"2025-02-03T15:45:18.640Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:45:18.641Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43338","metadata":{},"timestamp":"2025-02-03T15:45:18.641Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:45:18.642Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:45:18.642Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T15:45:20.949Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T15:45:21.063Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T15:45:39.770Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T15:45:39.878Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:54 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:54:26.279Z"} +{"label":"index.ts","level":"info","message":"Launched in: 105 ms","metadata":{},"timestamp":"2025-02-03T15:54:26.284Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:54:26.285Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43507","metadata":{},"timestamp":"2025-02-03T15:54:26.285Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:54:26.286Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:54:26.286Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:55 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:55:57.541Z"} +{"label":"index.ts","level":"info","message":"Launched in: 110 ms","metadata":{},"timestamp":"2025-02-03T15:55:57.546Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:55:57.546Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43616","metadata":{},"timestamp":"2025-02-03T15:55:57.547Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:55:57.547Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:55:57.548Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:56 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:56:23.772Z"} +{"label":"index.ts","level":"info","message":"Launched in: 93 ms","metadata":{},"timestamp":"2025-02-03T15:56:23.776Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:56:23.777Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43680","metadata":{},"timestamp":"2025-02-03T15:56:23.777Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:56:23.778Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:56:23.778Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:56 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:56:43.510Z"} +{"label":"index.ts","level":"info","message":"Launched in: 103 ms","metadata":{},"timestamp":"2025-02-03T15:56:43.515Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:56:43.515Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43744","metadata":{},"timestamp":"2025-02-03T15:56:43.516Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:56:43.516Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:56:43.516Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:57 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:57:15.506Z"} +{"label":"index.ts","level":"info","message":"Launched in: 116 ms","metadata":{},"timestamp":"2025-02-03T15:57:15.512Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:57:15.513Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43818","metadata":{},"timestamp":"2025-02-03T15:57:15.513Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:57:15.514Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:57:15.514Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 16:59 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T15:59:00.572Z"} +{"label":"index.ts","level":"info","message":"Launched in: 114 ms","metadata":{},"timestamp":"2025-02-03T15:59:00.577Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T15:59:00.578Z"} +{"label":"index.ts","level":"info","message":"Process PID: 43985","metadata":{},"timestamp":"2025-02-03T15:59:00.578Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T15:59:00.579Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T15:59:00.579Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T15:59:05.144Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T15:59:05.260Z"} +{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T15:59:05.262Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T15:59:05.277Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T15:59:35.359Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T15:59:35.469Z"} +{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T15:59:35.470Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T15:59:35.473Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T15:59:48.697Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T15:59:48.809Z"} +{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T15:59:48.809Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T15:59:48.811Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T16:00:10.397Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 17:00 CET","metadata":{},"timestamp":"2025-02-03T16:00:10.400Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T16:00:10.400Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T16:00:10.401Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:00 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:00:14.508Z"} +{"label":"index.ts","level":"info","message":"Launched in: 115 ms","metadata":{},"timestamp":"2025-02-03T16:00:14.513Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:00:14.513Z"} +{"label":"index.ts","level":"info","message":"Process PID: 44240","metadata":{},"timestamp":"2025-02-03T16:00:14.514Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:00:14.514Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:00:14.515Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T16:00:42.123Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 17:00 CET","metadata":{},"timestamp":"2025-02-03T16:00:42.126Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T16:00:42.127Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T16:00:42.129Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:00 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:00:55.118Z"} +{"label":"index.ts","level":"info","message":"Launched in: 109 ms","metadata":{},"timestamp":"2025-02-03T16:00:55.123Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:00:55.124Z"} +{"label":"index.ts","level":"info","message":"Process PID: 44412","metadata":{},"timestamp":"2025-02-03T16:00:55.125Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:00:55.125Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:00:55.126Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:01:00.696Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:01:00.874Z"} +{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T16:01:28.918Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T16:01:28.932Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:01:31.304Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:01:31.455Z"} +{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T16:02:07.671Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T16:02:07.678Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:04 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:04:06.753Z"} +{"label":"index.ts","level":"info","message":"Launched in: 110 ms","metadata":{},"timestamp":"2025-02-03T16:04:06.757Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:04:06.758Z"} +{"label":"index.ts","level":"info","message":"Process PID: 44695","metadata":{},"timestamp":"2025-02-03T16:04:06.758Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:04:06.759Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:04:06.759Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:04:12.145Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:04:12.325Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:05:54.782Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:05 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:05:55.740Z"} +{"label":"index.ts","level":"info","message":"Launched in: 114 ms","metadata":{},"timestamp":"2025-02-03T16:05:55.744Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:05:55.745Z"} +{"label":"index.ts","level":"info","message":"Process PID: 44859","metadata":{},"timestamp":"2025-02-03T16:05:55.745Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:05:55.746Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:05:55.746Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:05:58.253Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:05:58.413Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:06:09.336Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:06:09.345Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:07:12.444Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:07:12.558Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:29:22.183Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:29:22.193Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:29 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:29:23.260Z"} +{"label":"index.ts","level":"info","message":"Launched in: 121 ms","metadata":{},"timestamp":"2025-02-03T16:29:23.264Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:29:23.265Z"} +{"label":"index.ts","level":"info","message":"Process PID: 45299","metadata":{},"timestamp":"2025-02-03T16:29:23.266Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:29:23.266Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:29:23.266Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:29:25.686Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:29:25.795Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:29:25.843Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T16:29:25.848Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:29 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:29:55.708Z"} +{"label":"index.ts","level":"info","message":"Launched in: 118 ms","metadata":{},"timestamp":"2025-02-03T16:29:55.713Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:29:55.714Z"} +{"label":"index.ts","level":"info","message":"Process PID: 45379","metadata":{},"timestamp":"2025-02-03T16:29:55.714Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:29:55.715Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:29:55.715Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:29:58.289Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:29:58.411Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:29:58.465Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:29:58.471Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:30:27.301Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:30:27.397Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:30:58.651Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:30:58.659Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:31:11.179Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:31:11.291Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:31:11.297Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:31:39.339Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:31:39.439Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:31:39.443Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:31:39.446Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:31:45.960Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:31:46.051Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:42:21.737Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:43 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:43:14.603Z"} +{"label":"index.ts","level":"info","message":"Launched in: 113 ms","metadata":{},"timestamp":"2025-02-03T16:43:14.608Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:43:14.609Z"} +{"label":"index.ts","level":"info","message":"Process PID: 45957","metadata":{},"timestamp":"2025-02-03T16:43:14.609Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:43:14.610Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:43:14.610Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:44 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:44:04.262Z"} +{"label":"index.ts","level":"info","message":"Launched in: 100 ms","metadata":{},"timestamp":"2025-02-03T16:44:04.267Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:44:04.267Z"} +{"label":"index.ts","level":"info","message":"Process PID: 46028","metadata":{},"timestamp":"2025-02-03T16:44:04.268Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:44:04.268Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:44:04.269Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:51 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:51:39.471Z"} +{"label":"index.ts","level":"info","message":"Launched in: 119 ms","metadata":{},"timestamp":"2025-02-03T16:51:39.477Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:51:39.477Z"} +{"label":"index.ts","level":"info","message":"Process PID: 46375","metadata":{},"timestamp":"2025-02-03T16:51:39.478Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:51:39.478Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:51:39.479Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:52 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:52:12.077Z"} +{"label":"index.ts","level":"info","message":"Launched in: 109 ms","metadata":{},"timestamp":"2025-02-03T16:52:12.082Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:52:12.082Z"} +{"label":"index.ts","level":"info","message":"Process PID: 46428","metadata":{},"timestamp":"2025-02-03T16:52:12.083Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:52:12.083Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:52:12.084Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:52 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:52:30.663Z"} +{"label":"index.ts","level":"info","message":"Launched in: 116 ms","metadata":{},"timestamp":"2025-02-03T16:52:30.668Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:52:30.669Z"} +{"label":"index.ts","level":"info","message":"Process PID: 46495","metadata":{},"timestamp":"2025-02-03T16:52:30.670Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:52:30.670Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:52:30.670Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:52 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:52:36.498Z"} +{"label":"index.ts","level":"info","message":"Launched in: 116 ms","metadata":{},"timestamp":"2025-02-03T16:52:36.502Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:52:36.503Z"} +{"label":"index.ts","level":"info","message":"Process PID: 46535","metadata":{},"timestamp":"2025-02-03T16:52:36.503Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:52:36.504Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:52:36.505Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:52 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:52:47.875Z"} +{"label":"index.ts","level":"info","message":"Launched in: 119 ms","metadata":{},"timestamp":"2025-02-03T16:52:47.879Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:52:47.880Z"} +{"label":"index.ts","level":"info","message":"Process PID: 46603","metadata":{},"timestamp":"2025-02-03T16:52:47.880Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:52:47.881Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:52:47.881Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:53:04.464Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:53:04.591Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:53:04.645Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:53:04.652Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:53:13.248Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:53:13.353Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:53:24.919Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 17:53 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T16:53:52.655Z"} +{"label":"index.ts","level":"info","message":"Launched in: 112 ms","metadata":{},"timestamp":"2025-02-03T16:53:52.660Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T16:53:52.660Z"} +{"label":"index.ts","level":"info","message":"Process PID: 46783","metadata":{},"timestamp":"2025-02-03T16:53:52.661Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T16:53:52.661Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T16:53:52.662Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:53:59.649Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:53:59.770Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:53:59.783Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T16:54:31.568Z"} +{"label":"index.ts","level":"info","message":"[Domain Event Created]: AuthenticatedUser ==> UserAuthenticatedEvent","metadata":{},"timestamp":"2025-02-03T16:54:31.742Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T17:53:46.420Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T17:53:46.434Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 18:54 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T17:54:23.734Z"} +{"label":"index.ts","level":"info","message":"Launched in: 125 ms","metadata":{},"timestamp":"2025-02-03T17:54:23.740Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T17:54:23.741Z"} +{"label":"index.ts","level":"info","message":"Process PID: 48097","metadata":{},"timestamp":"2025-02-03T17:54:23.741Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T17:54:23.742Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T17:54:23.743Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 18:54 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T17:54:26.837Z"} +{"label":"index.ts","level":"info","message":"Launched in: 111 ms","metadata":{},"timestamp":"2025-02-03T17:54:26.841Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T17:54:26.842Z"} +{"label":"index.ts","level":"info","message":"Process PID: 48139","metadata":{},"timestamp":"2025-02-03T17:54:26.842Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T17:54:26.843Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T17:54:26.843Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T17:55:55.467Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 18:55 CET","metadata":{},"timestamp":"2025-02-03T17:55:55.473Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T17:55:55.474Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T17:55:55.475Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 19:02 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T18:02:48.032Z"} +{"label":"index.ts","level":"info","message":"Launched in: 138 ms","metadata":{},"timestamp":"2025-02-03T18:02:48.038Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T18:02:48.038Z"} +{"label":"index.ts","level":"info","message":"Process PID: 48517","metadata":{},"timestamp":"2025-02-03T18:02:48.039Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T18:02:48.040Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T18:02:48.040Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/login","metadata":{},"timestamp":"2025-02-03T18:02:59.655Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 19:03 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T18:03:04.157Z"} +{"label":"index.ts","level":"info","message":"Launched in: 111 ms","metadata":{},"timestamp":"2025-02-03T18:03:04.161Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T18:03:04.162Z"} +{"label":"index.ts","level":"info","message":"Process PID: 48674","metadata":{},"timestamp":"2025-02-03T18:03:04.162Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T18:03:04.163Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T18:03:04.163Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/login","metadata":{},"timestamp":"2025-02-03T18:03:09.003Z"} diff --git a/apps/server/error-2025-02-03.log b/apps/server/error-2025-02-03.log index 9a80f9ea..9a339e68 100644 --- a/apps/server/error-2025-02-03.log +++ b/apps/server/error-2025-02-03.log @@ -20,3 +20,34 @@ {"label":"index.ts","level":"error","message":"Could not close connections in time, forcefully shutting down","metadata":{},"timestamp":"2025-02-03T11:30:14.987Z"} {"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","name":"SequelizeDatabaseError","original":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"parameters":{},"parent":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');"},"timestamp":"2025-02-03T11:39:04.414Z"} {"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T13:05:42.332Z"} +{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T15:59:05.262Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T15:59:05.277Z"} +{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T15:59:35.470Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T15:59:35.473Z"} +{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T15:59:48.809Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T15:59:48.811Z"} +{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T16:01:28.918Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T16:01:28.932Z"} +{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T16:02:07.671Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T16:02:07.678Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:05:54.782Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:06:09.336Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:06:09.345Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:29:22.183Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:29:22.193Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:29:25.843Z"} +{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T16:29:25.848Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:29:58.465Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:29:58.471Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:30:58.651Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:30:58.659Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:31:11.297Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:31:39.443Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:31:39.446Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:42:21.737Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:53:04.645Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:53:04.652Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:53:24.919Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:53:59.783Z"} +{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T17:53:46.420Z"} +{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T17:53:46.434Z"} diff --git a/apps/server/package.json b/apps/server/package.json index 30caa5c6..1a230ab3 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -25,8 +25,9 @@ "@types/jsonwebtoken": "^9.0.8", "@types/luxon": "^3.4.2", "@types/node": "^22.10.7", - "@types/passport": "^1.0.17", + "@types/passport": "^1.0.16", "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", "@types/response-time": "^2.3.8", "@typescript-eslint/eslint-plugin": "^8.22.0", "@typescript-eslint/parser": "^8.22.0", @@ -62,6 +63,7 @@ "mysql2": "^3.12.0", "passport": "^0.7.0", "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", "reflect-metadata": "^0.2.2", "response-time": "^2.3.3", "sequelize": "^6.37.5", diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 67afcd46..574adb7f 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -1,5 +1,5 @@ -import { initLogger } from "@common/infrastructure/logger"; -import { errorHandler } from "@common/presentation"; +import { logger } from "@common/infrastructure/logger"; +import { globalErrorHandler } from "@common/presentation"; import dotenv from "dotenv"; import express, { Application } from "express"; import helmet from "helmet"; @@ -8,7 +8,6 @@ import responseTime from "response-time"; import { v1Routes } from "./routes"; dotenv.config(); -const logger = initLogger(); export function createApp(): Application { const app = express(); @@ -37,7 +36,7 @@ export function createApp(): Application { app.use("/api/v1", v1Routes()); // Gestión global de errores - app.use(errorHandler); + app.use(globalErrorHandler); return app; } diff --git a/apps/server/src/common/domain/aggregate-root.ts b/apps/server/src/common/domain/aggregate-root.ts index 1f52f282..f2bdf94a 100644 --- a/apps/server/src/common/domain/aggregate-root.ts +++ b/apps/server/src/common/domain/aggregate-root.ts @@ -1,3 +1,4 @@ +import { logger } from "@common/infrastructure/logger"; import { DomainEntity } from "./domain-entity"; import { IDomainEvent } from "./events"; @@ -7,11 +8,8 @@ export abstract class AggregateRoot extends DomainEntity { private logDomainEventAdded(event: IDomainEvent): void { const thisClass = Reflect.getPrototypeOf(this); const domainEventClass = Reflect.getPrototypeOf(event); - console.info( - `[Domain Event Created]:`, - thisClass?.constructor.name, - "==>", - domainEventClass?.constructor.name + logger.info( + `[Domain Event Created]: ${thisClass?.constructor.name} ==> ${domainEventClass?.constructor.name}` ); } diff --git a/apps/server/src/common/infrastructure/logger/index.ts b/apps/server/src/common/infrastructure/logger/index.ts index 5a06f78e..bc3f8af5 100644 --- a/apps/server/src/common/infrastructure/logger/index.ts +++ b/apps/server/src/common/infrastructure/logger/index.ts @@ -6,7 +6,7 @@ import DailyRotateFile from "winston-daily-rotate-file"; dotenv.config(); -export const initLogger = () => { +const initLogger = () => { const isProduction = process.env.NODE_ENV === "production"; const consoleFormat = format.combine( @@ -44,7 +44,7 @@ export const initLogger = () => { ); const logger = createLogger({ - level: isProduction ? "debug" : "debug", + level: isProduction ? "error" : "debug", format: fileFormat, @@ -86,6 +86,5 @@ export const initLogger = () => { return logger; }; -export const logger = () => { - return initLogger(); -}; +const logger = initLogger(); +export { logger }; diff --git a/apps/server/src/common/infrastructure/sequelize/sequelize-repository.ts b/apps/server/src/common/infrastructure/sequelize/sequelize-repository.ts index 02cba251..8f87b1a0 100644 --- a/apps/server/src/common/infrastructure/sequelize/sequelize-repository.ts +++ b/apps/server/src/common/infrastructure/sequelize/sequelize-repository.ts @@ -1,5 +1,6 @@ import { IAggregateRootRepository, Result, UniqueID } from "@common/domain"; import { ModelDefined, Transaction } from "sequelize"; +import { logger } from "../logger"; export abstract class SequelizeRepository implements IAggregateRootRepository { protected _findById( @@ -81,22 +82,32 @@ export abstract class SequelizeRepository implements IAggregateRootRepository } /** - * 🔹 Manejo de errores de la base de datos + * 🔹 Manejo de errores de la base de datos con personalización + * @param error Error lanzado por Sequelize + * @param errorMapper Función opcional para personalizar errores específicos */ - protected _handleDatabaseError(error: unknown): Result { + protected _handleDatabaseError( + error: unknown, + errorMapper?: (error: Error) => string | null + ): Result { const _error = error as Error; - if (_error.name === "SequelizeUniqueConstraintError") { - return Result.fail(new Error("User with this email already exists")); + + logger.error(`Database error: ${_error.message}`); + + // Si la clase hija proporciona un mapeo personalizado, lo usa + if (errorMapper) { + const mappedMessage = errorMapper(_error); + if (mappedMessage) { + return Result.fail(new Error(mappedMessage)); + } } - if (_error.name === "SequelizeConnectionError") { - return Result.fail(new Error("Database connection lost")); - } + // Mapa de errores genéricos para la base de datos + const ERROR_MAP = new Map([ + ["SequelizeConnectionError", "Database connection lost"], + ["SequelizeTimeoutError", "Database request timed out"], + ]); - if (_error.name === "SequelizeTimeoutError") { - return Result.fail(new Error("Database request timed out")); - } - - return Result.fail(new Error("Unexpected database error")); + return Result.fail(new Error(ERROR_MAP.get(_error.name) || "Unexpected database error")); } } diff --git a/apps/server/src/common/presentation/express/express-controller.ts b/apps/server/src/common/presentation/express/express-controller.ts index a4bf9dc4..79345180 100644 --- a/apps/server/src/common/presentation/express/express-controller.ts +++ b/apps/server/src/common/presentation/express/express-controller.ts @@ -1,3 +1,4 @@ +import { logger } from "@common/infrastructure/logger"; import { NextFunction, Request, Response } from "express"; import httpStatus from "http-status"; import { ApiError } from "./api-error"; @@ -24,6 +25,7 @@ export abstract class ExpressController { } protected errorResponse(apiError: ApiError) { + logger.error(`[${apiError.status}] ${apiError.title}: ${apiError.detail}`); return this.res.status(apiError.status).json(apiError); } @@ -143,8 +145,10 @@ export abstract class ExpressController { try { this.executeImpl(); - } catch (error) { - this.internalServerError((error as Error).message); + } catch (error: unknown) { + const _error = error as Error; + logger.error(`Unhandled error in controller: ${_error.message}`); + this.internalServerError(_error.message); } } } diff --git a/apps/server/src/common/presentation/express/middlewares/error-handler.ts b/apps/server/src/common/presentation/express/middlewares/error-handler.ts deleted file mode 100644 index f71b4091..00000000 --- a/apps/server/src/common/presentation/express/middlewares/error-handler.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { NextFunction, Request, Response } from "express"; -import { ApiError } from "../api-error"; - -export const errorHandler = (err: any, req: Request, res: Response, next: NextFunction) => { - // Si ya se envió una respuesta, delegamos al siguiente error handler - if (res.headersSent) { - return next(err); - } - - // Verifica si el error es una instancia de ApiError - if (err instanceof ApiError) { - // Respuesta con formato RFC 7807 - return res.status(err.status).json({ - type: err.type, - title: err.title, - status: err.status, - detail: err.detail, - instance: err.instance ?? req.originalUrl, - errors: err.errors ?? [], // Aquí puedes almacenar validaciones, etc. - }); - } - - // Si no es un ApiError, lo tratamos como un error interno (500) - return res.status(500).json({ - type: "https://example.com/probs/internal-server-error", - title: "Internal Server Error", - status: 500, - detail: err.message || "Ha ocurrido un error inesperado.", - instance: req.originalUrl, - }); -}; diff --git a/apps/server/src/common/presentation/express/middlewares/global-error-handler.ts b/apps/server/src/common/presentation/express/middlewares/global-error-handler.ts new file mode 100644 index 00000000..0003575a --- /dev/null +++ b/apps/server/src/common/presentation/express/middlewares/global-error-handler.ts @@ -0,0 +1,34 @@ +import { logger } from "@common/infrastructure/logger"; +import { NextFunction, Request, Response } from "express"; +import { ApiError } from "../api-error"; + +export const globalErrorHandler = (error: any, req: Request, res: Response, next: NextFunction) => { + // Si ya se envió una respuesta, delegamos al siguiente error handler + if (res.headersSent) { + return next(error); + } + + logger.error(`Unhandled API error: ${error.message}`); + + // Verifica si el error es una instancia de ApiError + if (error instanceof ApiError) { + // Respuesta con formato RFC 7807 + return res.status(error.status).json({ + type: error.type, + title: error.title, + status: error.status, + detail: error.detail, + instance: error.instance ?? req.originalUrl, + errors: error.errors ?? [], // Aquí puedes almacenar validaciones, etc. + }); + } + + // Si no es un ApiError, lo tratamos como un error interno (500) + return res.status(500).json({ + type: "https://example.com/probs/internal-server-error", + title: "Internal Server Error", + status: 500, + detail: error.message || "Ha ocurrido un error inesperado.", + instance: req.originalUrl, + }); +}; diff --git a/apps/server/src/common/presentation/express/middlewares/index.ts b/apps/server/src/common/presentation/express/middlewares/index.ts index 6394c391..de655522 100644 --- a/apps/server/src/common/presentation/express/middlewares/index.ts +++ b/apps/server/src/common/presentation/express/middlewares/index.ts @@ -1 +1 @@ -export * from "./error-handler"; +export * from "./global-error-handler"; diff --git a/apps/server/src/config/database.ts b/apps/server/src/config/database.ts index 6a652c1f..c5884032 100644 --- a/apps/server/src/config/database.ts +++ b/apps/server/src/config/database.ts @@ -1,5 +1,6 @@ import dotenv from "dotenv"; import { Sequelize } from "sequelize"; +import { registerModels } from "./register-models"; dotenv.config(); @@ -23,6 +24,7 @@ export const sequelize = new Sequelize( export async function connectToDatabase(): Promise { try { + await registerModels(); await sequelize.authenticate(); console.log("✅ Database connection established successfully."); } catch (error) { diff --git a/apps/server/src/config/register-models.ts b/apps/server/src/config/register-models.ts new file mode 100644 index 00000000..3a1eaf03 --- /dev/null +++ b/apps/server/src/config/register-models.ts @@ -0,0 +1,18 @@ +import { sequelize } from "./database"; + +/** + * 🔹 Registra todos los modelos en Sequelize + */ +export const registerModels = async () => { + try { + if (process.env.NODE_ENV !== "production") { + await sequelize.sync({ alter: true }); + console.log("✅ Database synchronized successfully."); + } else { + console.log("⚠️ Running in production mode - Skipping database sync."); + } + } catch (error) { + console.error("❌ Error synchronizing database:", error); + process.exit(1); + } +}; diff --git a/apps/server/src/contexts/auth/application/auth-provider.interface.ts b/apps/server/src/contexts/auth/application/auth-provider.interface.ts index 0eed9174..18d4bad9 100644 --- a/apps/server/src/contexts/auth/application/auth-provider.interface.ts +++ b/apps/server/src/contexts/auth/application/auth-provider.interface.ts @@ -1,9 +1,11 @@ +import { AuthenticatedUser } from "../domain"; + export interface IAuthProvider { + /* JWT Strategy */ generateAccessToken(payload: any): string; generateRefreshToken(payload: any): string; - - /** - * 🔹 Verifica la validez de un token JWT y devuelve su payload - */ verifyToken(token: string): any; + + /* LocalStrategy */ + verifyUser(email: string, password: string): Promise; } diff --git a/apps/server/src/contexts/auth/application/auth.service.ts b/apps/server/src/contexts/auth/application/auth.service.ts index d5d81dad..cdba29a4 100644 --- a/apps/server/src/contexts/auth/application/auth.service.ts +++ b/apps/server/src/contexts/auth/application/auth.service.ts @@ -11,7 +11,7 @@ import { IAuthProvider } from "./auth-provider.interface"; import { IAuthService } from "./auth-service.interface"; export class AuthService implements IAuthService { - private _respository!: IAuthenticatedUserRepository; + private readonly _respository!: IAuthenticatedUserRepository; private readonly _transactionManager!: ITransactionManager; private readonly _authProvider: IAuthProvider; diff --git a/apps/server/src/contexts/auth/application/index.ts b/apps/server/src/contexts/auth/application/index.ts index f281f971..ae075f28 100644 --- a/apps/server/src/contexts/auth/application/index.ts +++ b/apps/server/src/contexts/auth/application/index.ts @@ -12,6 +12,10 @@ export * from "./auth-service.interface"; export const createAuthService = (): IAuthService => { const transactionManager = createSequelizeTransactionManager(); const authenticatedUserRepository = createAuthenticatedUserRepository(); - const authProvider: IAuthProvider = createPassportAuthProvider(); + + const authProvider: IAuthProvider = createPassportAuthProvider( + authenticatedUserRepository, + transactionManager + ); return new AuthService(authenticatedUserRepository, transactionManager, authProvider); }; diff --git a/apps/server/src/contexts/auth/domain/aggregates/authenticated-user.ts b/apps/server/src/contexts/auth/domain/aggregates/authenticated-user.ts index a52b8daa..cb173118 100644 --- a/apps/server/src/contexts/auth/domain/aggregates/authenticated-user.ts +++ b/apps/server/src/contexts/auth/domain/aggregates/authenticated-user.ts @@ -21,6 +21,10 @@ export class AuthenticatedUser extends AggregateRoot { return Result.ok(user); } + comparePassword(plainPassword: string): Promise { + return this._props.passwordHash.compare(plainPassword); + } + /** * 🔹 Devuelve una representación lista para persistencia */ @@ -30,7 +34,7 @@ export class AuthenticatedUser extends AggregateRoot { username: this._props.username.toString(), email: this._props.email.toString(), password: this._props.passwordHash.toString(), - roles: JSON.stringify(this._props.roles), + roles: this._props.roles.map((role) => role.toString()), token: this._props.token, }; } diff --git a/apps/server/src/contexts/auth/infraestructure/passport/passport-auth-provider.ts b/apps/server/src/contexts/auth/infraestructure/passport/passport-auth-provider.ts index 6aa11e87..510fee68 100644 --- a/apps/server/src/contexts/auth/infraestructure/passport/passport-auth-provider.ts +++ b/apps/server/src/contexts/auth/infraestructure/passport/passport-auth-provider.ts @@ -1,14 +1,28 @@ +import { createSequelizeTransactionManager } from "@common/infrastructure"; +import { ITransactionManager } from "@common/infrastructure/database"; import { IAuthProvider } from "@contexts/auth/application"; +import { + AuthenticatedUser, + EmailAddress, + IAuthenticatedUserRepository, +} from "@contexts/auth/domain"; import jwt from "jsonwebtoken"; import passport from "passport"; import { ExtractJwt, Strategy as JwtStrategy } from "passport-jwt"; +import { Strategy as LocalStrategy } from "passport-local"; +import { createAuthenticatedUserRepository } from "../sequelize"; const SECRET_KEY = process.env.JWT_SECRET || "supersecretkey"; const ACCESS_EXPIRATION = process.env.JWT_ACCESS_EXPIRATION || "1h"; const REFRESH_EXPIRATION = process.env.JWT_REFRESH_EXPIRATION || "7d"; export class PassportAuthProvider implements IAuthProvider { - constructor() { + private readonly _repository: IAuthenticatedUserRepository; + private readonly _transactionManager!: ITransactionManager; + + constructor(repository: IAuthenticatedUserRepository, transactionManager: ITransactionManager) { + this._repository = repository; + this._transactionManager = transactionManager; this.initializePassport(); } @@ -24,6 +38,19 @@ export class PassportAuthProvider implements IAuthProvider { return jwt.verify(token, SECRET_KEY); } + async verifyUser(email: string, password: string): Promise { + const emailVO = EmailAddress.create(email); + if (emailVO.isFailure) return Promise.resolve(null); + + const userResult = await this._repository.findUserByEmail(emailVO.data); + if (userResult.isFailure || !userResult.data) return Promise.resolve(null); + + const user = userResult.data; + const isValidPassword = await user.comparePassword(password); + + return !isValidPassword ? Promise.resolve(null) : Promise.resolve(user); + } + /** * 🔹 Configura PassportJS con la estrategia JWT */ @@ -42,7 +69,30 @@ export class PassportAuthProvider implements IAuthProvider { } }) ); + + passport.use( + new LocalStrategy( + { usernameField: "email", passwordField: "password" }, + async (email, password, done) => { + try { + const user = await this.verifyUser(email, password); + return user + ? done(null, user) + : done(null, false, { message: "Invalid email or password" }); + } catch (error) { + return done(error, false); + } + } + ) + ); } } -export const createPassportAuthProvider = () => new PassportAuthProvider(); +export const createPassportAuthProvider = ( + repository?: IAuthenticatedUserRepository, + transactionManager?: ITransactionManager +) => { + const _transactionManager = transactionManager || createSequelizeTransactionManager(); + const _repository = repository || createAuthenticatedUserRepository(); + return new PassportAuthProvider(_repository, _transactionManager); +}; diff --git a/apps/server/src/contexts/auth/infraestructure/sequelize/auth-user.model.ts b/apps/server/src/contexts/auth/infraestructure/sequelize/auth-user.model.ts index 3f6fb567..60263202 100644 --- a/apps/server/src/contexts/auth/infraestructure/sequelize/auth-user.model.ts +++ b/apps/server/src/contexts/auth/infraestructure/sequelize/auth-user.model.ts @@ -1,5 +1,5 @@ +import { sequelize } from "@config/database"; import { DataTypes, InferAttributes, InferCreationAttributes, Model } from "sequelize"; -import { sequelize } from "../../../../config/database"; export type AuthUserCreationAttributes = InferCreationAttributes; @@ -7,12 +7,12 @@ class AuthUserModel extends Model< InferAttributes, InferCreationAttributes > { - public id!: string; - public username!: string; - public email!: string; - public password!: string; - public roles!: string[]; - public isActive!: boolean; + declare id: string; + declare username: string; + declare email: string; + declare password: string; + declare roles: string[]; + declare isActive: boolean; } AuthUserModel.init( @@ -36,9 +36,17 @@ AuthUserModel.init( allowNull: false, }, roles: { - type: DataTypes.ARRAY(DataTypes.STRING), + type: DataTypes.STRING, allowNull: false, - defaultValue: [], + defaultValue: "USER", + get(this: AuthUserModel): string[] { + const rawValue = this.getDataValue("roles") as any; + return String(rawValue).split(";"); + }, + set(this: AuthUserModel, value: string[]) { + const rawValue = value.join(";") as any; + this.setDataValue("roles", rawValue); + }, }, isActive: { type: DataTypes.BOOLEAN, diff --git a/apps/server/src/contexts/auth/infraestructure/sequelize/authenticated-user.repository.ts b/apps/server/src/contexts/auth/infraestructure/sequelize/authenticated-user.repository.ts index e5f36d5c..d5396e50 100644 --- a/apps/server/src/contexts/auth/infraestructure/sequelize/authenticated-user.repository.ts +++ b/apps/server/src/contexts/auth/infraestructure/sequelize/authenticated-user.repository.ts @@ -15,6 +15,17 @@ export class AuthenticatedUserRepository { private readonly _mapper!: IAuthenticatedUserMapper; + /** + * 🔹 Función personalizada para mapear errores de unicidad en autenticación + */ + private _customErrorMapper(error: Error): string | null { + if (error.name === "SequelizeUniqueConstraintError") { + return "User with this email already exists"; + } + + return null; + } + constructor(mapper: IAuthenticatedUserMapper) { super(); this._mapper = mapper; @@ -34,7 +45,7 @@ export class AuthenticatedUserRepository return Result.ok(Boolean(rawUser)); } catch (error: any) { - return this._handleDatabaseError(error); + return this._handleDatabaseError(error, this._customErrorMapper); } } @@ -56,7 +67,7 @@ export class AuthenticatedUserRepository return this._mapper.toDomain(rawUser); } catch (error: any) { - return this._handleDatabaseError(error); + return this._handleDatabaseError(error, this._customErrorMapper); } } @@ -69,7 +80,7 @@ export class AuthenticatedUserRepository await AuthUserModel.create(persistenceData, { transaction }); return Result.ok(); } catch (error: any) { - return this._handleDatabaseError(error); + return this._handleDatabaseError(error, this._customErrorMapper); } } } diff --git a/apps/server/src/contexts/auth/presentation/auth.routes.ts b/apps/server/src/contexts/auth/presentation/auth.routes.ts index 5708332b..872abbfa 100644 --- a/apps/server/src/contexts/auth/presentation/auth.routes.ts +++ b/apps/server/src/contexts/auth/presentation/auth.routes.ts @@ -1,12 +1,7 @@ import { validateRequest } from "@common/presentation"; -import { NextFunction, Request, Response, Router } from "express"; +import { Router } from "express"; import { createRegisterController } from "./controllers"; -import { RegisterUserSchema } from "./dto"; - -const loggerMiddleware = () => (req: Request, res: Response, next: NextFunction) => { - console.log(`${req.method} ${req.path}`); - next(); -}; +import { LoginUserSchema, RegisterUserSchema } from "./dto"; export const authRouter = (appRouter: Router) => { const authRoutes: Router = Router({ mergeParams: true }); @@ -43,7 +38,7 @@ export const authRouter = (appRouter: Router) => { * * @apiError (401) {String} message Invalid email or password. */ - //authRoutes.post("/login", authController.login); + authRoutes.post("/login", validateRequest(LoginUserSchema)); /** * @api {post} /api/auth/select-company Select an active company diff --git a/apps/server/src/contexts/auth/presentation/controllers/register.controller.ts b/apps/server/src/contexts/auth/presentation/controllers/register.controller.ts index cc0022fd..7ce91616 100644 --- a/apps/server/src/contexts/auth/presentation/controllers/register.controller.ts +++ b/apps/server/src/contexts/auth/presentation/controllers/register.controller.ts @@ -1,13 +1,16 @@ import { ExpressController } from "@common/presentation"; import { createAuthService, IAuthService } from "@contexts/auth/application"; import { EmailAddress, PasswordHash, Username } from "@contexts/auth/domain"; +import { IRegisterPresenter, RegisterPresenter } from "./register.presenter"; class RegisterController extends ExpressController { private readonly _authService!: IAuthService; + private readonly _presenter!: IRegisterPresenter; - public constructor(authService: IAuthService) { + public constructor(authService: IAuthService, presenter: IRegisterPresenter) { super(); this._authService = authService; + this._presenter = presenter; } async executeImpl() { @@ -19,15 +22,14 @@ class RegisterController extends ExpressController { return this.clientError("Invalid input data"); } - const result = await this._authService.registerUser({ + const userOrError = await this._authService.registerUser({ username: usernameVO.data, email: emailVO.data, passwordHash: passwordHashVO.data, }); - if (result.isFailure) { - console.log(result.error); - const message = result.error.message; + if (userOrError.isFailure) { + const message = userOrError.error.message; if (message.includes("User with this email already exists")) { return this.conflictError(message); @@ -45,15 +47,11 @@ class RegisterController extends ExpressController { return this.internalServerError(message); } - return this.created({ - accessToken: result.data.accessToken, - refreshToken: result.data.refreshToken, - userId: result.data.user.getID(), - }); + return this.created(this._presenter.map(userOrError.data)); } } export const createRegisterController = () => { const authService = createAuthService(); - return new RegisterController(authService); + return new RegisterController(authService, RegisterPresenter); }; diff --git a/apps/server/src/contexts/auth/presentation/controllers/register.presenter.ts b/apps/server/src/contexts/auth/presentation/controllers/register.presenter.ts new file mode 100644 index 00000000..2e3d05bc --- /dev/null +++ b/apps/server/src/contexts/auth/presentation/controllers/register.presenter.ts @@ -0,0 +1,21 @@ +import { AuthenticatedUser } from "@contexts/auth/domain"; +import { IRegisterUserResponseDTO } from "../dto"; + +export interface IRegisterPresenter { + map: (user: AuthenticatedUser) => IRegisterUserResponseDTO; +} + +export const RegisterPresenter: IRegisterPresenter = { + map: (user: AuthenticatedUser): IRegisterUserResponseDTO => { + //const { user, token, refreshToken } = loginUser; + //const roles = user.getRoles()?.map((rol) => rol.toString()) || []; + + const userData = user.toPersistenceData(); + + return { + userId: userData, + email: userData.email, + username: userData.username, + }; + }, +}; diff --git a/apps/server/src/contexts/auth/presentation/dto/auth.response.dto.ts b/apps/server/src/contexts/auth/presentation/dto/auth.response.dto.ts index db8398a0..72e57692 100644 --- a/apps/server/src/contexts/auth/presentation/dto/auth.response.dto.ts +++ b/apps/server/src/contexts/auth/presentation/dto/auth.response.dto.ts @@ -1,15 +1,15 @@ -export interface IRegisterUserDTO { +export interface IRegisterUserResponseDTO { + userId: string; username: string; email: string; - password: string; } -export interface ILoginUserDTO { +export interface ILoginUserResponseDTO { email: string; password: string; } -export interface ISelectCompanyDTO { +export interface ISelectCompanyResponseDTO { companyId: string; } diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index c8fb084d..bca1174d 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -1,12 +1,10 @@ -import { initLogger } from "@common/infrastructure/logger"; +import { logger } from "@common/infrastructure/logger"; import { connectToDatabase } from "@config/database"; import { createApp } from "app"; import http from "http"; import { DateTime } from "luxon"; import { ENV } from "./config"; -const logger = initLogger(); - // Guardamos información del estado del servidor export const currentState = { launchedAt: DateTime.now(), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 184c5fd6..9f42ec40 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -68,6 +68,9 @@ importers: passport-jwt: specifier: ^4.0.1 version: 4.0.1 + passport-local: + specifier: ^1.0.0 + version: 1.0.0 reflect-metadata: specifier: ^0.2.2 version: 0.2.2 @@ -124,11 +127,14 @@ importers: specifier: ^22.10.7 version: 22.12.0 '@types/passport': - specifier: ^1.0.17 + specifier: ^1.0.16 version: 1.0.17 '@types/passport-jwt': specifier: ^4.0.1 version: 4.0.1 + '@types/passport-local': + specifier: ^1.0.38 + version: 1.0.38 '@types/response-time': specifier: ^2.3.8 version: 2.3.8 @@ -1193,6 +1199,9 @@ packages: '@types/passport-jwt@4.0.1': resolution: {integrity: sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==} + '@types/passport-local@1.0.38': + resolution: {integrity: sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==} + '@types/passport-strategy@0.2.38': resolution: {integrity: sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==} @@ -3143,6 +3152,10 @@ packages: passport-jwt@4.0.1: resolution: {integrity: sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==} + passport-local@1.0.0: + resolution: {integrity: sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==} + engines: {node: '>= 0.4.0'} + passport-strategy@1.0.0: resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==} engines: {node: '>= 0.4.0'} @@ -4951,6 +4964,12 @@ snapshots: '@types/jsonwebtoken': 9.0.8 '@types/passport-strategy': 0.2.38 + '@types/passport-local@1.0.38': + dependencies: + '@types/express': 4.17.21 + '@types/passport': 1.0.17 + '@types/passport-strategy': 0.2.38 + '@types/passport-strategy@0.2.38': dependencies: '@types/express': 4.17.21 @@ -7424,6 +7443,10 @@ snapshots: jsonwebtoken: 9.0.2 passport-strategy: 1.0.0 + passport-local@1.0.0: + dependencies: + passport-strategy: 1.0.0 + passport-strategy@1.0.0: {} passport@0.7.0: