From 7d8ca534957919836d519c55170d93df94a02a7d Mon Sep 17 00:00:00 2001 From: david Date: Mon, 3 Feb 2025 14:12:36 +0100 Subject: [PATCH] . --- .vscode/launch.json | 48 ++ .vscode/settings.json | 37 +- ...3dcc376d1f0ca8880ce87cfefd2f30d-audit.json | 15 + ...3d5e50d48b909cd34375b545b447bc6-audit.json | 15 + apps/server/.env.development | 5 +- apps/server/debug-2025-02-03.log | 503 ++++++++++++ apps/server/error-2025-02-03.log | 22 + apps/server/package.json | 31 +- apps/server/src/app.ts | 8 + .../aggregate-root-repository.interface.ts | 9 +- apps/server/src/common/domain/result.spec.ts | 8 +- apps/server/src/common/domain/result.ts | 23 +- .../domain/value-objects/unique-id.spec.ts | 8 +- .../database/transaction-manager.interface.ts | 2 +- .../database/transaction-manager.ts | 2 +- .../src/common/infrastructure/logger/index.ts | 91 +++ .../infrastructure/passport/passport.ts | 2 +- .../common/infrastructure/sequelize/index.ts | 1 + .../sequelize/sequelize-repository.ts | 140 ++-- .../sequelize-transaction-manager.ts | 4 + .../express/express-controller.ts | 137 +++- apps/server/src/config/index.ts | 11 + .../application/auth-provider.interface.ts | 9 + .../application/auth-service.interface.ts | 10 +- .../contexts/auth/application/auth.service.ts | 102 ++- .../src/contexts/auth/application/index.ts | 22 +- .../domain/aggregates/authenticated-user.ts | 17 +- apps/server/src/contexts/auth/domain/index.ts | 1 - ...authenticated-user-repository.interface.ts | 13 +- .../value-objects/email-address.spec.ts | 20 +- .../value-objects/password-hash.spec.ts | 10 +- .../domain/value-objects/password-hash.ts | 10 +- .../contexts/auth/infraestructure/index.ts | 3 +- .../mappers/authenticated-user.mapper.ts | 27 +- .../auth/infraestructure/passport/index.ts | 1 + .../passport/passport-auth-provider.ts | 48 ++ .../authenticated-user.repository.ts | 96 +-- .../auth/presentation/auth.controller.ts | 57 -- .../contexts/auth/presentation/auth.routes.ts | 14 +- .../controllers/register.controller.ts | 46 +- .../presentation/dto/auth.validation.dto.ts | 4 +- .../src/contexts/auth/presentation/index.ts | 5 +- .../auth/presentation/middleware/index.ts | 1 + .../presentation/middleware/passport-auth.ts | 12 + apps/server/src/index.ts | 132 +++- apps/server/src/routes/v1.routes.ts | 7 - pnpm-lock.yaml | 733 +++++++++++++++++- tsconfig.base.json | 5 +- 48 files changed, 2145 insertions(+), 382 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 apps/server/.571b27c4f3dcc376d1f0ca8880ce87cfefd2f30d-audit.json create mode 100644 apps/server/.e6616b1c93d5e50d48b909cd34375b545b447bc6-audit.json create mode 100644 apps/server/debug-2025-02-03.log create mode 100644 apps/server/error-2025-02-03.log create mode 100644 apps/server/src/common/infrastructure/logger/index.ts create mode 100644 apps/server/src/contexts/auth/application/auth-provider.interface.ts create mode 100644 apps/server/src/contexts/auth/infraestructure/passport/index.ts create mode 100644 apps/server/src/contexts/auth/infraestructure/passport/passport-auth-provider.ts delete mode 100644 apps/server/src/contexts/auth/presentation/auth.controller.ts create mode 100644 apps/server/src/contexts/auth/presentation/middleware/index.ts create mode 100644 apps/server/src/contexts/auth/presentation/middleware/passport-auth.ts diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..95034f85 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,48 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch firefox localhost", + "type": "firefox", + "request": "launch", + "reAttach": true, + "url": "http://localhost:5173", + "webRoot": "${workspaceFolder}/client" + }, + + { + "name": "Launch Chrome localhost", + "type": "chrome", + "request": "launch", + "reAttach": true, + "url": "http://localhost:5173", + "webRoot": "${workspaceFolder}/client" + }, + + { + "type": "msedge", + "request": "launch", + "name": "CLIENT: Launch Edge against localhost", + "url": "http://localhost:5173", + "webRoot": "${workspaceFolder}/client" + }, + + { + "type": "node", + "request": "attach", + "name": "SERVER: Attach to dev:debug", + "port": 4321, + "restart": true, + "cwd": "${workspaceRoot}" + }, + + { + "name": "Launch via YARN", + "request": "launch", + "runtimeArgs": ["run", "server"], + "runtimeExecutable": "yarn", + "skipFiles": ["/**", "client/**", "dist/**", "doc/**"], + "type": "node" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index c66eac75..4d9466c3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,20 +1,19 @@ { - "editor.codeActionsOnSave": { - "source.organizeImports": "explicit", - "source.fixAll.eslint": "explicit" - }, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true, - "editor.formatOnPaste": false, - "prettier.useEditorConfig": false, - "prettier.useTabs": false, - "prettier.configPath": ".prettierrc", - "asciidoc.antora.enableAntoraSupport": true, - - // other vscode settings - "tailwindCSS.rootFontSize": 16, - "[handlebars]": { - "editor.defaultFormatter": "vscode.html-language-features" - } // <- your root font size here - } - \ No newline at end of file + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.fixAll.eslint": "explicit" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.formatOnPaste": false, + "prettier.useEditorConfig": false, + "prettier.useTabs": false, + "prettier.configPath": ".prettierrc", + "asciidoc.antora.enableAntoraSupport": true, + + // other vscode settings + "tailwindCSS.rootFontSize": 16, + "[handlebars]": { + "editor.defaultFormatter": "vscode.html-language-features" + } // <- your root font size here +} diff --git a/apps/server/.571b27c4f3dcc376d1f0ca8880ce87cfefd2f30d-audit.json b/apps/server/.571b27c4f3dcc376d1f0ca8880ce87cfefd2f30d-audit.json new file mode 100644 index 00000000..9857aebf --- /dev/null +++ b/apps/server/.571b27c4f3dcc376d1f0ca8880ce87cfefd2f30d-audit.json @@ -0,0 +1,15 @@ +{ + "keep": { + "days": true, + "amount": 1 + }, + "auditLog": ".571b27c4f3dcc376d1f0ca8880ce87cfefd2f30d-audit.json", + "files": [ + { + "date": 1738578708264, + "name": "debug-2025-02-03.log", + "hash": "48ca17f819e391cb5ae1909a6ee0fa4d9c8cdb6667ef893547acb004f4a79737" + } + ], + "hashType": "sha256" +} \ No newline at end of file diff --git a/apps/server/.e6616b1c93d5e50d48b909cd34375b545b447bc6-audit.json b/apps/server/.e6616b1c93d5e50d48b909cd34375b545b447bc6-audit.json new file mode 100644 index 00000000..bf5e8ba3 --- /dev/null +++ b/apps/server/.e6616b1c93d5e50d48b909cd34375b545b447bc6-audit.json @@ -0,0 +1,15 @@ +{ + "keep": { + "days": true, + "amount": 1 + }, + "auditLog": ".e6616b1c93d5e50d48b909cd34375b545b447bc6-audit.json", + "files": [ + { + "date": 1738578708262, + "name": "error-2025-02-03.log", + "hash": "a21f154f5c386a75eee98a35c2b100da7df1b8002cf99851b90bd12810f1fe8a" + } + ], + "hashType": "sha256" +} \ No newline at end of file diff --git a/apps/server/.env.development b/apps/server/.env.development index 822543e1..0d869dfa 100644 --- a/apps/server/.env.development +++ b/apps/server/.env.development @@ -6,4 +6,7 @@ DB_DIALECT=mariadb DB_PORT=3306 PORT=3002 -JWT_SECRET=clave_secreta_para_tokens + +JWT_SECRET=supersecretkey +JWT_ACCESS_EXPIRATION=1h +JWT_REFRESH_EXPIRATION=7d diff --git a/apps/server/debug-2025-02-03.log b/apps/server/debug-2025-02-03.log new file mode 100644 index 00000000..ea6de809 --- /dev/null +++ b/apps/server/debug-2025-02-03.log @@ -0,0 +1,503 @@ +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:31 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:31:48.326Z"} +{"label":"index.ts","level":"info","message":"Launched in: 58 ms","metadata":{},"timestamp":"2025-02-03T10:31:48.330Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:31:48.331Z"} +{"label":"index.ts","level":"info","message":"Process PID: 27291","metadata":{},"timestamp":"2025-02-03T10:31:48.331Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:31:48.332Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:31:48.332Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:31:54.022Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:31 CET","metadata":{},"timestamp":"2025-02-03T10:31:54.025Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T10:31:54.026Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T10:31:54.027Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:31:54.029Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:31 CET","metadata":{},"timestamp":"2025-02-03T10:31:54.030Z"} +{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:31:54 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:31:54.031Z"} +{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:31:54.034Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:33 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:33:04.048Z"} +{"label":"index.ts","level":"info","message":"Launched in: 72 ms","metadata":{},"timestamp":"2025-02-03T10:33:04.052Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:33:04.053Z"} +{"label":"index.ts","level":"info","message":"Process PID: 27486","metadata":{},"timestamp":"2025-02-03T10:33:04.053Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:33:04.054Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:33:04.054Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:33:04.888Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:33 CET","metadata":{},"timestamp":"2025-02-03T10:33:04.890Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T10:33:04.891Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T10:33:04.891Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:33:04.892Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:33 CET","metadata":{},"timestamp":"2025-02-03T10:33:04.893Z"} +{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:33:04 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:33:04.894Z"} +{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:33:04.896Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:33 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:33:46.916Z"} +{"label":"index.ts","level":"info","message":"Launched in: 57 ms","metadata":{},"timestamp":"2025-02-03T10:33:46.920Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:33:46.921Z"} +{"label":"index.ts","level":"info","message":"Process PID: 27632","metadata":{},"timestamp":"2025-02-03T10:33:46.922Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:33:46.922Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:33:46.922Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:33:49.225Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:33 CET","metadata":{},"timestamp":"2025-02-03T10:33:49.228Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T10:33:49.228Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T10:33:49.229Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:33:49.230Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:33 CET","metadata":{},"timestamp":"2025-02-03T10:33:49.231Z"} +{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:33:49 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:33:49.232Z"} +{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:33:49.233Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:35 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:35:48.079Z"} +{"label":"index.ts","level":"info","message":"Launched in: 59 ms","metadata":{},"timestamp":"2025-02-03T10:35:48.083Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:35:48.083Z"} +{"label":"index.ts","level":"info","message":"Process PID: 27747","metadata":{},"timestamp":"2025-02-03T10:35:48.084Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:35:48.084Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:35:48.084Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:37 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:37:13.858Z"} +{"label":"index.ts","level":"info","message":"Launched in: 79 ms","metadata":{},"timestamp":"2025-02-03T10:37:13.862Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:37:13.863Z"} +{"label":"index.ts","level":"info","message":"Process PID: 27943","metadata":{},"timestamp":"2025-02-03T10:37:13.863Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:37:13.864Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:37:13.864Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:37:14.746Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:37 CET","metadata":{},"timestamp":"2025-02-03T10:37:14.750Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T10:37:14.751Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T10:37:14.752Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:37:14.753Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:37 CET","metadata":{},"timestamp":"2025-02-03T10:37:14.754Z"} +{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:37:14 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:37:14.756Z"} +{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:37:14.758Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:47 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:47:16.343Z"} +{"label":"index.ts","level":"info","message":"Launched in: 63 ms","metadata":{},"timestamp":"2025-02-03T10:47:16.347Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:47:16.347Z"} +{"label":"index.ts","level":"info","message":"Process PID: 28264","metadata":{},"timestamp":"2025-02-03T10:47:16.348Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:47:16.348Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:47:16.349Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:47 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:47:24.661Z"} +{"label":"index.ts","level":"info","message":"Launched in: 60 ms","metadata":{},"timestamp":"2025-02-03T10:47:24.665Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:47:24.666Z"} +{"label":"index.ts","level":"info","message":"Process PID: 28355","metadata":{},"timestamp":"2025-02-03T10:47:24.667Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:47:24.667Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:47:24.667Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:47:26.385Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:47 CET","metadata":{},"timestamp":"2025-02-03T10:47:26.388Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T10:47:26.389Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T10:47:26.390Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:47:26.391Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:47 CET","metadata":{},"timestamp":"2025-02-03T10:47:26.392Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T10:47:26.394Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:47 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:47:35.396Z"} +{"label":"index.ts","level":"info","message":"Launched in: 58 ms","metadata":{},"timestamp":"2025-02-03T10:47:35.400Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:47:35.400Z"} +{"label":"index.ts","level":"info","message":"Process PID: 28502","metadata":{},"timestamp":"2025-02-03T10:47:35.401Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:47:35.401Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:47:35.401Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:47:46.762Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:47 CET","metadata":{},"timestamp":"2025-02-03T10:47:46.765Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T10:47:46.766Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T10:47:46.767Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:47:46.767Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:47 CET","metadata":{},"timestamp":"2025-02-03T10:47:46.768Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T10:47:46.769Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:51 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:51:55.876Z"} +{"label":"index.ts","level":"info","message":"Launched in: 57 ms","metadata":{},"timestamp":"2025-02-03T10:51:55.880Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:51:55.881Z"} +{"label":"index.ts","level":"info","message":"Process PID: 28711","metadata":{},"timestamp":"2025-02-03T10:51:55.881Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:51:55.882Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:51:55.882Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:53 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:53:58.189Z"} +{"label":"index.ts","level":"info","message":"Launched in: 62 ms","metadata":{},"timestamp":"2025-02-03T10:53:58.193Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:53:58.193Z"} +{"label":"index.ts","level":"info","message":"Process PID: 28911","metadata":{},"timestamp":"2025-02-03T10:53:58.194Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:53:58.194Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:53:58.195Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:54 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:54:05.950Z"} +{"label":"index.ts","level":"info","message":"Launched in: 71 ms","metadata":{},"timestamp":"2025-02-03T10:54:05.954Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:54:05.955Z"} +{"label":"index.ts","level":"info","message":"Process PID: 28989","metadata":{},"timestamp":"2025-02-03T10:54:05.955Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:54:05.956Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:54:05.957Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:55 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:55:06.572Z"} +{"label":"index.ts","level":"info","message":"Launched in: 62 ms","metadata":{},"timestamp":"2025-02-03T10:55:06.577Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:55:06.577Z"} +{"label":"index.ts","level":"info","message":"Process PID: 29110","metadata":{},"timestamp":"2025-02-03T10:55:06.577Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:55:06.578Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:55:06.578Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:55 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:55:12.694Z"} +{"label":"index.ts","level":"info","message":"Launched in: 71 ms","metadata":{},"timestamp":"2025-02-03T10:55:12.699Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:55:12.700Z"} +{"label":"index.ts","level":"info","message":"Process PID: 29161","metadata":{},"timestamp":"2025-02-03T10:55:12.700Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:55:12.701Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:55:12.702Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T10:55:17.083Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T10:55:28.369Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:56:00.604Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:56 CET","metadata":{},"timestamp":"2025-02-03T10:56:00.607Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T10:56:00.608Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T10:56:00.609Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T10:56:00.610Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 11:56 CET","metadata":{},"timestamp":"2025-02-03T10:56:00.611Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T10:56:00.612Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:56 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:56:05.436Z"} +{"label":"index.ts","level":"info","message":"Launched in: 60 ms","metadata":{},"timestamp":"2025-02-03T10:56:05.440Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:56:05.440Z"} +{"label":"index.ts","level":"info","message":"Process PID: 29346","metadata":{},"timestamp":"2025-02-03T10:56:05.441Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:56:05.441Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:56:05.442Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T10:56:54.617Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:57 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:57:08.751Z"} +{"label":"index.ts","level":"info","message":"Launched in: 69 ms","metadata":{},"timestamp":"2025-02-03T10:57:08.756Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:57:08.756Z"} +{"label":"index.ts","level":"info","message":"Process PID: 29445","metadata":{},"timestamp":"2025-02-03T10:57:08.757Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:57:08.757Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:57:08.758Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:57 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:57:26.753Z"} +{"label":"index.ts","level":"info","message":"Launched in: 80 ms","metadata":{},"timestamp":"2025-02-03T10:57:26.758Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:57:26.758Z"} +{"label":"index.ts","level":"info","message":"Process PID: 29570","metadata":{},"timestamp":"2025-02-03T10:57:26.759Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:57:26.759Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:57:26.760Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T10:57:29.177Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:58 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:58:08.314Z"} +{"label":"index.ts","level":"info","message":"Launched in: 58 ms","metadata":{},"timestamp":"2025-02-03T10:58:08.318Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:58:08.318Z"} +{"label":"index.ts","level":"info","message":"Process PID: 29658","metadata":{},"timestamp":"2025-02-03T10:58:08.319Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:58:08.319Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:58:08.320Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 11:58 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T10:58:27.678Z"} +{"label":"index.ts","level":"info","message":"Launched in: 62 ms","metadata":{},"timestamp":"2025-02-03T10:58:27.682Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T10:58:27.682Z"} +{"label":"index.ts","level":"info","message":"Process PID: 29728","metadata":{},"timestamp":"2025-02-03T10:58:27.683Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T10:58:27.683Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T10:58:27.684Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:07 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:07:32.542Z"} +{"label":"index.ts","level":"info","message":"Launched in: 70 ms","metadata":{},"timestamp":"2025-02-03T11:07:32.546Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:07:32.547Z"} +{"label":"index.ts","level":"info","message":"Process PID: 30300","metadata":{},"timestamp":"2025-02-03T11:07:32.547Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:07:32.548Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:07:32.548Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:07 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:07:55.056Z"} +{"label":"index.ts","level":"info","message":"Launched in: 72 ms","metadata":{},"timestamp":"2025-02-03T11:07:55.060Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:07:55.061Z"} +{"label":"index.ts","level":"info","message":"Process PID: 30384","metadata":{},"timestamp":"2025-02-03T11:07:55.062Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:07:55.062Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:07:55.063Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:08:06.420Z"} +{"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:08:06.568Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:08:30.465Z"} +{"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:08:30.574Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:08:49.579Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:08:49.582Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:08 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:08:54.964Z"} +{"label":"index.ts","level":"info","message":"Launched in: 62 ms","metadata":{},"timestamp":"2025-02-03T11:08:54.968Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:08:54.968Z"} +{"label":"index.ts","level":"info","message":"Process PID: 30628","metadata":{},"timestamp":"2025-02-03T11:08:54.969Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:08:54.969Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:08:54.970Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:09:05.303Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 12:09 CET","metadata":{},"timestamp":"2025-02-03T11:09:05.306Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T11:09:05.307Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T11:09:05.308Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:09:05.309Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 12:09 CET","metadata":{},"timestamp":"2025-02-03T11:09:05.309Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T11:09:05.310Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:13 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:13:50.071Z"} +{"label":"index.ts","level":"info","message":"Launched in: 63 ms","metadata":{},"timestamp":"2025-02-03T11:13:50.075Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:13:50.076Z"} +{"label":"index.ts","level":"info","message":"Process PID: 31564","metadata":{},"timestamp":"2025-02-03T11:13:50.077Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:13:50.077Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:13:50.078Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:14:03.058Z"} +{"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:14:03.193Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:14:19.007Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:14:19.010Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:14:19.132Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:20 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:20:36.249Z"} +{"label":"index.ts","level":"info","message":"Launched in: 64 ms","metadata":{},"timestamp":"2025-02-03T11:20:36.253Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:20:36.253Z"} +{"label":"index.ts","level":"info","message":"Process PID: 33993","metadata":{},"timestamp":"2025-02-03T11:20:36.254Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:20:36.254Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:20:36.255Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:20:39.531Z"} +{"label":"index.ts","level":"info","message":"Shut down at: 3 de febrero de 2025, 12:20 CET","metadata":{},"timestamp":"2025-02-03T11:20:39.534Z"} +{"label":"index.ts","level":"info","message":"Closed out remaining connections.","metadata":{},"timestamp":"2025-02-03T11:20:39.534Z"} +{"label":"index.ts","level":"info","message":"Bye!","metadata":{},"timestamp":"2025-02-03T11:20:39.536Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:20 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:20:43.979Z"} +{"label":"index.ts","level":"info","message":"Launched in: 61 ms","metadata":{},"timestamp":"2025-02-03T11:20:43.984Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:20:43.984Z"} +{"label":"index.ts","level":"info","message":"Process PID: 34099","metadata":{},"timestamp":"2025-02-03T11:20:43.985Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:20:43.985Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:20:43.986Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:20:46.872Z"} +{"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:20:47.049Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:20:50.520Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:20 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:20:53.818Z"} +{"label":"index.ts","level":"info","message":"Launched in: 60 ms","metadata":{},"timestamp":"2025-02-03T11:20:53.823Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:20:53.823Z"} +{"label":"index.ts","level":"info","message":"Process PID: 34196","metadata":{},"timestamp":"2025-02-03T11:20:53.824Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:20:53.824Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:20:53.825Z"} +{"label":"index.ts","level":"error","message":"Could not close connections in time, forcefully shutting down","metadata":{},"timestamp":"2025-02-03T11:21:20.528Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:21:42.752Z"} +{"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:22:22.098Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:22 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:22:42.651Z"} +{"label":"index.ts","level":"info","message":"Launched in: 63 ms","metadata":{},"timestamp":"2025-02-03T11:22:42.656Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:22:42.656Z"} +{"label":"index.ts","level":"info","message":"Process PID: 34476","metadata":{},"timestamp":"2025-02-03T11:22:42.657Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:22:42.657Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:22:42.658Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:22 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:22:48.049Z"} +{"label":"index.ts","level":"info","message":"Launched in: 62 ms","metadata":{},"timestamp":"2025-02-03T11:22:48.053Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:22:48.054Z"} +{"label":"index.ts","level":"info","message":"Process PID: 34516","metadata":{},"timestamp":"2025-02-03T11:22:48.054Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:22:48.055Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:22:48.055Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:22:51.754Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:24 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:24:57.165Z"} +{"label":"index.ts","level":"info","message":"Launched in: 69 ms","metadata":{},"timestamp":"2025-02-03T11:24:57.170Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:24:57.171Z"} +{"label":"index.ts","level":"info","message":"Process PID: 34710","metadata":{},"timestamp":"2025-02-03T11:24:57.171Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:24:57.172Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:24:57.172Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:25:01.961Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:28 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:28:08.745Z"} +{"label":"index.ts","level":"info","message":"Launched in: 61 ms","metadata":{},"timestamp":"2025-02-03T11:28:08.749Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:28:08.750Z"} +{"label":"index.ts","level":"info","message":"Process PID: 34895","metadata":{},"timestamp":"2025-02-03T11:28:08.750Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:28:08.751Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:28:08.752Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:28:15.111Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:28 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:28:33.351Z"} +{"label":"index.ts","level":"info","message":"Launched in: 61 ms","metadata":{},"timestamp":"2025-02-03T11:28:33.355Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:28:33.356Z"} +{"label":"index.ts","level":"info","message":"Process PID: 35002","metadata":{},"timestamp":"2025-02-03T11:28:33.356Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:28:33.357Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:28:33.357Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:28:39.509Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:28:52.885Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:28 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:28:56.892Z"} +{"label":"index.ts","level":"info","message":"Launched in: 63 ms","metadata":{},"timestamp":"2025-02-03T11:28:56.896Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:28:56.896Z"} +{"label":"index.ts","level":"info","message":"Process PID: 35142","metadata":{},"timestamp":"2025-02-03T11:28:56.897Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:28:56.897Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:28:56.898Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:29:12.361Z"} +{"label":"index.ts","level":"error","message":"Could not close connections in time, forcefully shutting down","metadata":{},"timestamp":"2025-02-03T11:29:22.891Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:29:34.887Z"} +{"label":"index.ts","level":"warn","message":"⚡️ Shutting down server","metadata":{},"timestamp":"2025-02-03T11:29:44.966Z"} +{"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":"info","message":"Time: 3 de febrero de 2025, 12:30 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:30:43.689Z"} +{"label":"index.ts","level":"info","message":"Launched in: 66 ms","metadata":{},"timestamp":"2025-02-03T11:30:43.693Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:30:43.694Z"} +{"label":"index.ts","level":"info","message":"Process PID: 35655","metadata":{},"timestamp":"2025-02-03T11:30:43.694Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:30:43.695Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:30:43.696Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:30:46.889Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:31:08.346Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:32 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:32:05.660Z"} +{"label":"index.ts","level":"info","message":"Launched in: 61 ms","metadata":{},"timestamp":"2025-02-03T11:32:05.664Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:32:05.665Z"} +{"label":"index.ts","level":"info","message":"Process PID: 35906","metadata":{},"timestamp":"2025-02-03T11:32:05.665Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:32:05.666Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:32:05.667Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:32:19.844Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 12:32 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:32:59.925Z"} +{"label":"index.ts","level":"info","message":"Launched in: 60 ms","metadata":{},"timestamp":"2025-02-03T11:32:59.929Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:32:59.930Z"} +{"label":"index.ts","level":"info","message":"Process PID: 36039","metadata":{},"timestamp":"2025-02-03T11:32:59.931Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:32:59.931Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:32:59.932Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:33:08.197Z"} +{"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":"info","message":"Time: 3 de febrero de 2025, 12:39 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T11:39:05.433Z"} +{"label":"index.ts","level":"info","message":"Launched in: 79 ms","metadata":{},"timestamp":"2025-02-03T11:39:05.437Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T11:39:05.438Z"} +{"label":"index.ts","level":"info","message":"Process PID: 36303","metadata":{},"timestamp":"2025-02-03T11:39:05.438Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T11:39:05.439Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T11:39:05.439Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T11:42:04.893Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:09 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:09:10.945Z"} +{"label":"index.ts","level":"info","message":"Launched in: 75 ms","metadata":{},"timestamp":"2025-02-03T12:09:10.950Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:09:10.950Z"} +{"label":"index.ts","level":"info","message":"Process PID: 36704","metadata":{},"timestamp":"2025-02-03T12:09:10.951Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:09:10.951Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:09:10.952Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:09 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:09:48.476Z"} +{"label":"index.ts","level":"info","message":"Launched in: 60 ms","metadata":{},"timestamp":"2025-02-03T12:09:48.480Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:09:48.480Z"} +{"label":"index.ts","level":"info","message":"Process PID: 36772","metadata":{},"timestamp":"2025-02-03T12:09:48.481Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:09:48.481Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:09:48.482Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:38 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:38:49.952Z"} +{"label":"index.ts","level":"info","message":"Launched in: 65 ms","metadata":{},"timestamp":"2025-02-03T12:38:49.956Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:38:49.957Z"} +{"label":"index.ts","level":"info","message":"Process PID: 36990","metadata":{},"timestamp":"2025-02-03T12:38:49.957Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:38:49.958Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:38:49.958Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:39 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:39:00.284Z"} +{"label":"index.ts","level":"info","message":"Launched in: 63 ms","metadata":{},"timestamp":"2025-02-03T12:39:00.288Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:39:00.288Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37060","metadata":{},"timestamp":"2025-02-03T12:39:00.289Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:39:00.289Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:39:00.290Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:39 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:39:19.498Z"} +{"label":"index.ts","level":"info","message":"Launched in: 62 ms","metadata":{},"timestamp":"2025-02-03T12:39:19.502Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:39:19.502Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37125","metadata":{},"timestamp":"2025-02-03T12:39:19.503Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:39:19.504Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:39:19.504Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:42 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:42:15.390Z"} +{"label":"index.ts","level":"info","message":"Launched in: 70 ms","metadata":{},"timestamp":"2025-02-03T12:42:15.395Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:42:15.395Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37257","metadata":{},"timestamp":"2025-02-03T12:42:15.396Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:42:15.397Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:42:15.397Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:43 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:43:12.245Z"} +{"label":"index.ts","level":"info","message":"Launched in: 74 ms","metadata":{},"timestamp":"2025-02-03T12:43:12.250Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:43:12.251Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37338","metadata":{},"timestamp":"2025-02-03T12:43:12.251Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:43:12.252Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:43:12.253Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:46 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:46:31.979Z"} +{"label":"index.ts","level":"info","message":"Launched in: 74 ms","metadata":{},"timestamp":"2025-02-03T12:46:31.984Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:46:31.985Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37459","metadata":{},"timestamp":"2025-02-03T12:46:31.985Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:46:31.986Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:46:31.986Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:46 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:46:40.345Z"} +{"label":"index.ts","level":"info","message":"Launched in: 63 ms","metadata":{},"timestamp":"2025-02-03T12:46:40.349Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:46:40.349Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37524","metadata":{},"timestamp":"2025-02-03T12:46:40.350Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:46:40.350Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:46:40.351Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:47 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:47:37.569Z"} +{"label":"index.ts","level":"info","message":"Launched in: 64 ms","metadata":{},"timestamp":"2025-02-03T12:47:37.574Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:47:37.574Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37567","metadata":{},"timestamp":"2025-02-03T12:47:37.574Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:47:37.575Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:47:37.576Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:48 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:48:43.576Z"} +{"label":"index.ts","level":"info","message":"Launched in: 73 ms","metadata":{},"timestamp":"2025-02-03T12:48:43.581Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:48:43.581Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37638","metadata":{},"timestamp":"2025-02-03T12:48:43.582Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:48:43.582Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:48:43.583Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:48 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:48:58.255Z"} +{"label":"index.ts","level":"info","message":"Launched in: 63 ms","metadata":{},"timestamp":"2025-02-03T12:48:58.259Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:48:58.260Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37703","metadata":{},"timestamp":"2025-02-03T12:48:58.260Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:48:58.261Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:48:58.262Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:49 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:49:54.186Z"} +{"label":"index.ts","level":"info","message":"Launched in: 64 ms","metadata":{},"timestamp":"2025-02-03T12:49:54.191Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:49:54.191Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37785","metadata":{},"timestamp":"2025-02-03T12:49:54.192Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:49:54.192Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:49:54.193Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:50 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:50:00.507Z"} +{"label":"index.ts","level":"info","message":"Launched in: 66 ms","metadata":{},"timestamp":"2025-02-03T12:50:00.512Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:50:00.512Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37839","metadata":{},"timestamp":"2025-02-03T12:50:00.513Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:50:00.513Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:50:00.514Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:50 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:50:13.018Z"} +{"label":"index.ts","level":"info","message":"Launched in: 67 ms","metadata":{},"timestamp":"2025-02-03T12:50:13.023Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:50:13.023Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37896","metadata":{},"timestamp":"2025-02-03T12:50:13.024Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:50:13.024Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:50:13.025Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:50 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:50:24.758Z"} +{"label":"index.ts","level":"info","message":"Launched in: 63 ms","metadata":{},"timestamp":"2025-02-03T12:50:24.762Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:50:24.762Z"} +{"label":"index.ts","level":"info","message":"Process PID: 37960","metadata":{},"timestamp":"2025-02-03T12:50:24.763Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:50:24.763Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:50:24.764Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T12:50:32.682Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T12:50:51.584Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:52 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:52:06.054Z"} +{"label":"index.ts","level":"info","message":"Launched in: 65 ms","metadata":{},"timestamp":"2025-02-03T12:52:06.059Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:52:06.059Z"} +{"label":"index.ts","level":"info","message":"Process PID: 38086","metadata":{},"timestamp":"2025-02-03T12:52:06.060Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:52:06.060Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:52:06.061Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:52 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:52:19.286Z"} +{"label":"index.ts","level":"info","message":"Launched in: 62 ms","metadata":{},"timestamp":"2025-02-03T12:52:19.290Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:52:19.290Z"} +{"label":"index.ts","level":"info","message":"Process PID: 38151","metadata":{},"timestamp":"2025-02-03T12:52:19.291Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:52:19.291Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:52:19.292Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 13:52 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T12:52:35.505Z"} +{"label":"index.ts","level":"info","message":"Launched in: 75 ms","metadata":{},"timestamp":"2025-02-03T12:52:35.510Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T12:52:35.511Z"} +{"label":"index.ts","level":"info","message":"Process PID: 38232","metadata":{},"timestamp":"2025-02-03T12:52:35.511Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T12:52:35.512Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T12:52:35.513Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T12:52:37.674Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T12:53:01.900Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T12:53:36.527Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:04 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:04:06.250Z"} +{"label":"index.ts","level":"info","message":"Launched in: 68 ms","metadata":{},"timestamp":"2025-02-03T13:04:06.255Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:04:06.255Z"} +{"label":"index.ts","level":"info","message":"Process PID: 38689","metadata":{},"timestamp":"2025-02-03T13:04:06.256Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:04:06.256Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:04:06.257Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T13:04:08.938Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T13:04:27.021Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T13:04:32.711Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T13:04:59.520Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:05 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:05:24.056Z"} +{"label":"index.ts","level":"info","message":"Launched in: 63 ms","metadata":{},"timestamp":"2025-02-03T13:05:24.060Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:05:24.060Z"} +{"label":"index.ts","level":"info","message":"Process PID: 38914","metadata":{},"timestamp":"2025-02-03T13:05:24.061Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:05:24.061Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:05:24.062Z"} +{"label":"index.ts","level":"info","message":"Incoming request POST to /api/v1/auth/register","metadata":{},"timestamp":"2025-02-03T13:05:27.776Z"} +{"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":"info","message":"Time: 3 de febrero de 2025, 14:05 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:05:49.085Z"} +{"label":"index.ts","level":"info","message":"Launched in: 64 ms","metadata":{},"timestamp":"2025-02-03T13:05:49.089Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:05:49.090Z"} +{"label":"index.ts","level":"info","message":"Process PID: 39028","metadata":{},"timestamp":"2025-02-03T13:05:49.090Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:05:49.091Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:05:49.091Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:07 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:07:23.173Z"} +{"label":"index.ts","level":"info","message":"Launched in: 76 ms","metadata":{},"timestamp":"2025-02-03T13:07:23.178Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:07:23.178Z"} +{"label":"index.ts","level":"info","message":"Process PID: 39177","metadata":{},"timestamp":"2025-02-03T13:07:23.179Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:07:23.179Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:07:23.180Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:07 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:07:30.372Z"} +{"label":"index.ts","level":"info","message":"Launched in: 60 ms","metadata":{},"timestamp":"2025-02-03T13:07:30.377Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:07:30.377Z"} +{"label":"index.ts","level":"info","message":"Process PID: 39263","metadata":{},"timestamp":"2025-02-03T13:07:30.378Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:07:30.378Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:07:30.379Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:08 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:08:09.521Z"} +{"label":"index.ts","level":"info","message":"Launched in: 64 ms","metadata":{},"timestamp":"2025-02-03T13:08:09.525Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:08:09.526Z"} +{"label":"index.ts","level":"info","message":"Process PID: 39320","metadata":{},"timestamp":"2025-02-03T13:08:09.526Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:08:09.527Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:08:09.528Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:08 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:08:55.178Z"} +{"label":"index.ts","level":"info","message":"Launched in: 60 ms","metadata":{},"timestamp":"2025-02-03T13:08:55.182Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:08:55.182Z"} +{"label":"index.ts","level":"info","message":"Process PID: 39385","metadata":{},"timestamp":"2025-02-03T13:08:55.183Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:08:55.183Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:08:55.184Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:09 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:09:04.247Z"} +{"label":"index.ts","level":"info","message":"Launched in: 78 ms","metadata":{},"timestamp":"2025-02-03T13:09:04.252Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:09:04.253Z"} +{"label":"index.ts","level":"info","message":"Process PID: 39451","metadata":{},"timestamp":"2025-02-03T13:09:04.253Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:09:04.254Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:09:04.255Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:11 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:11:17.725Z"} +{"label":"index.ts","level":"info","message":"Launched in: 63 ms","metadata":{},"timestamp":"2025-02-03T13:11:17.729Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:11:17.730Z"} +{"label":"index.ts","level":"info","message":"Process PID: 39642","metadata":{},"timestamp":"2025-02-03T13:11:17.730Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:11:17.731Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:11:17.731Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:11 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:11:54.946Z"} +{"label":"index.ts","level":"info","message":"Launched in: 75 ms","metadata":{},"timestamp":"2025-02-03T13:11:54.951Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:11:54.951Z"} +{"label":"index.ts","level":"info","message":"Process PID: 39706","metadata":{},"timestamp":"2025-02-03T13:11:54.952Z"} +{"label":"index.ts","level":"info","message":"To shut down your server, press + C at any time","metadata":{},"timestamp":"2025-02-03T13:11:54.953Z"} +{"label":"index.ts","level":"info","message":"⚡️ Server: http://localhost:3002","metadata":{},"timestamp":"2025-02-03T13:11:54.953Z"} +{"label":"index.ts","level":"info","message":"Time: 3 de febrero de 2025, 14:12 CET Europe/Madrid","metadata":{},"timestamp":"2025-02-03T13:12:00.002Z"} +{"label":"index.ts","level":"info","message":"Launched in: 60 ms","metadata":{},"timestamp":"2025-02-03T13:12:00.006Z"} +{"label":"index.ts","level":"info","message":"Environment: development","metadata":{},"timestamp":"2025-02-03T13:12:00.007Z"} +{"label":"index.ts","level":"info","message":"Process PID: 39743","metadata":{},"timestamp":"2025-02-03T13:12:00.007Z"} +{"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"} diff --git a/apps/server/error-2025-02-03.log b/apps/server/error-2025-02-03.log new file mode 100644 index 00000000..9a80f9ea --- /dev/null +++ b/apps/server/error-2025-02-03.log @@ -0,0 +1,22 @@ +{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:31:54 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:31:54.031Z"} +{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:31:54.034Z"} +{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:33:04 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:33:04.894Z"} +{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:33:04.896Z"} +{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:33:49 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:33:49.232Z"} +{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:33:49.233Z"} +{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:37:14 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:37:14.756Z"} +{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:37:14.758Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T10:47:26.394Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T10:47:46.769Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T10:56:00.612Z"} +{"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:08:06.568Z"} +{"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:08:30.574Z"} +{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T11:09:05.310Z"} +{"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:14:03.193Z"} +{"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:20:47.049Z"} +{"label":"index.ts","level":"error","message":"Could not close connections in time, forcefully shutting down","metadata":{},"timestamp":"2025-02-03T11:21:20.528Z"} +{"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:22:22.098Z"} +{"label":"index.ts","level":"error","message":"Could not close connections in time, forcefully shutting down","metadata":{},"timestamp":"2025-02-03T11:29:22.891Z"} +{"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"} diff --git a/apps/server/package.json b/apps/server/package.json index db9d7095..30caa5c6 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -4,7 +4,8 @@ "description": "", "main": "index.js", "scripts": { - "dev": "tsx watch src/index.ts", + "dev": "ts-node-dev -r tsconfig-paths/register ./src/index.ts", + "dev:debug": "ts-node-dev --transpile-only --respawn --inspect=4321 -r tsconfig-paths/register ./src/index.ts", "clean": "rm -rf dist", "typecheck": "tsc --noEmit", "build": "npm run clean && npm run typecheck && esbuild src/index.ts --platform=node --format=cjs --bundle --sourcemap --minify --outdir=dist", @@ -19,9 +20,10 @@ "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", "@types/bcrypt": "^5.0.2", - "@types/express": "^5.0.0", + "@types/express": "^4.17.21", "@types/jest": "^29.5.14", "@types/jsonwebtoken": "^9.0.8", + "@types/luxon": "^3.4.2", "@types/node": "^22.10.7", "@types/passport": "^1.0.17", "@types/passport-jwt": "^4.0.1", @@ -29,22 +31,32 @@ "@typescript-eslint/eslint-plugin": "^8.22.0", "@typescript-eslint/parser": "^8.22.0", "eslint": "^9.19.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-hexagonal-architecture": "^1.0.3", + "eslint-plugin-import": "^2.28.0", + "eslint-plugin-jest": "^27.4.2", + "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "eslint-plugin-sort-class-members": "^1.19.0", + "eslint-plugin-unused-imports": "^3.0.0", "jest": "^29.7.0", "nodemon": "^3.1.9", "ts-jest": "^29.2.5", "ts-node-dev": "^2.0.0", - "tsx": "^4.19.2", "typescript": "^5.7.3" }, "dependencies": { "bcrypt": "^5.1.1", + "cls-rtracer": "^2.6.3", "cors": "^2.8.5", "dotenv": "^16.4.7", "esbuild": "^0.24.0", - "express": "^4.21.2", + "express": "^4.18.2", "helmet": "^8.0.0", + "http": "0.0.1-security", "http-status": "^2.1.0", "jsonwebtoken": "^9.0.2", + "luxon": "^3.5.0", "mariadb": "^3.4.0", "module-alias": "^2.2.3", "mysql2": "^3.12.0", @@ -54,13 +66,18 @@ "response-time": "^2.3.3", "sequelize": "^6.37.5", "shallow-equal-object": "^1.1.1", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", "uuid": "^11.0.5", + "winston": "^3.17.0", + "winston-daily-rotate-file": "^5.0.0", "zod": "^3.24.1" }, + "engines": { + "node": ">=22" + }, "_moduleAliases": { "@common": "./dist/common", - "@auth": "./dist/auth", - "@config": "./dist/config", - "@companies": "./dist/companies" + "@config": "./dist/config" } } diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 0e9838cc..67afcd46 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -1,11 +1,14 @@ +import { initLogger } from "@common/infrastructure/logger"; import { errorHandler } from "@common/presentation"; import dotenv from "dotenv"; import express, { Application } from "express"; import helmet from "helmet"; +import passport from "passport"; import responseTime from "response-time"; import { v1Routes } from "./routes"; dotenv.config(); +const logger = initLogger(); export function createApp(): Application { const app = express(); @@ -25,6 +28,11 @@ export function createApp(): Application { // Inicializar Passport app.use(passport.initialize()); + app.use((req, _, next) => { + logger.info(`Incoming request ${req.method} to ${req.path}`); + next(); + }); + // Registrar rutas de la API app.use("/api/v1", v1Routes()); diff --git a/apps/server/src/common/domain/aggregate-root-repository.interface.ts b/apps/server/src/common/domain/aggregate-root-repository.interface.ts index 272bec7f..845c7ae7 100644 --- a/apps/server/src/common/domain/aggregate-root-repository.interface.ts +++ b/apps/server/src/common/domain/aggregate-root-repository.interface.ts @@ -1,8 +1 @@ -import { Result } from "./result"; - -export interface IAggregateRootRepository { - findById(id: string): Promise>; - create(entity: T): Promise>; - update(entity: T): Promise>; - delete(id: string): Promise>; -} +export interface IAggregateRootRepository {} diff --git a/apps/server/src/common/domain/result.spec.ts b/apps/server/src/common/domain/result.spec.ts index 2a26f8e1..75299bae 100644 --- a/apps/server/src/common/domain/result.spec.ts +++ b/apps/server/src/common/domain/result.spec.ts @@ -4,8 +4,8 @@ describe("Result", () => { it("should create a successful result", () => { const result = Result.ok("Success Data"); - expect(result.isOk()).toBe(true); - expect(result.isError()).toBe(false); + expect(result.isSuccess).toBe(true); + expect(result.isSuccess).toBe(false); expect(result.data).toBe("Success Data"); }); @@ -13,8 +13,8 @@ describe("Result", () => { const error = new Error("Test error"); const result = Result.fail(error); - expect(result.isOk()).toBe(false); - expect(result.isError()).toBe(true); + expect(result.isSuccess).toBe(false); + expect(result.isSuccess).toBe(true); expect(result.error).toBe(error); }); diff --git a/apps/server/src/common/domain/result.ts b/apps/server/src/common/domain/result.ts index d48f1288..6edcdc69 100644 --- a/apps/server/src/common/domain/result.ts +++ b/apps/server/src/common/domain/result.ts @@ -1,6 +1,5 @@ export class Result { - private readonly isSuccess: boolean; - + private readonly _isSuccess: boolean; private readonly _data?: T; private readonly _error?: E; @@ -13,7 +12,7 @@ export class Result { throw new Error(`InvalidOperation: A failing result needs to contain an error message`); } - this.isSuccess = isSuccess; + this._isSuccess = isSuccess; this._error = error; this._data = data; @@ -30,7 +29,7 @@ export class Result { static combine(results: Result[]): Result { for (const result of results) { - if (result.isError()) { + if (result.isFailure) { return result; } } @@ -38,23 +37,23 @@ export class Result { return Result.ok(); } - isOk(): boolean { - return this.isSuccess; + get isSuccess(): boolean { + return this._isSuccess; } - isError(): boolean { - return !this.isSuccess; + get isFailure(): boolean { + return !this._isSuccess; } get data(): T { - if (!this.isSuccess) { + if (!this._isSuccess) { throw new Error("Cannot get value data from a failed result."); } return this._data as T; } get error(): E { - if (this.isSuccess) { + if (this._isSuccess) { throw new Error("Cannot get error from a successful result."); } return this._error as E; @@ -65,7 +64,7 @@ export class Result { * Si el `Result` es un `ok`, devuelve `data`, de lo contrario, devuelve `defaultValue`. */ getOrElse(defaultValue: any): T | any { - return this.isSuccess ? this.data : defaultValue; + return this._isSuccess ? this.data : defaultValue; } /** @@ -73,6 +72,6 @@ export class Result { * Evalúa el `Result`: ejecuta `onOk()` si es `ok` o `onError()` si es `fail`. */ match(onOk: (data: T) => R, onError: (error: E) => R): R { - return this.isSuccess ? onOk(this.data) : onError(this.error); + return this._isSuccess ? onOk(this.data) : onError(this.error); } } diff --git a/apps/server/src/common/domain/value-objects/unique-id.spec.ts b/apps/server/src/common/domain/value-objects/unique-id.spec.ts index 8e702b80..9e472d66 100644 --- a/apps/server/src/common/domain/value-objects/unique-id.spec.ts +++ b/apps/server/src/common/domain/value-objects/unique-id.spec.ts @@ -4,7 +4,7 @@ describe("UniqueID Value Object", () => { it("should generate a new UUID using generateNewID()", () => { const result = UniqueID.generateNewID(); - expect(result.isOk()).toBe(true); + expect(result.isSuccess).toBe(true); expect(result.data.getValue()).toMatch( /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i ); @@ -13,7 +13,7 @@ describe("UniqueID Value Object", () => { it("should return an error for an invalid UUID", () => { const result = UniqueID.create("invalid-uuid"); - expect(result.isError()).toBe(true); + expect(result.isSuccess).toBe(true); expect(result.error.message).toBe("Invalid UUID format"); }); @@ -21,7 +21,7 @@ describe("UniqueID Value Object", () => { const validUUID = "550e8400-e29b-41d4-a716-446655440000"; const result = UniqueID.create(validUUID); - expect(result.isOk()).toBe(true); + expect(result.isSuccess).toBe(true); expect(result.data.getValue()).toBe(validUUID); }); @@ -29,7 +29,7 @@ describe("UniqueID Value Object", () => { const validUUID = "550e8400-e29b-41d4-a716-446655440000"; const result = UniqueID.create(validUUID); - expect(result.isOk()).toBe(true); + expect(result.isSuccess).toBe(true); expect(result.data.toString()).toBe(validUUID); }); }); diff --git a/apps/server/src/common/infrastructure/database/transaction-manager.interface.ts b/apps/server/src/common/infrastructure/database/transaction-manager.interface.ts index dea3e5a5..12c39705 100644 --- a/apps/server/src/common/infrastructure/database/transaction-manager.interface.ts +++ b/apps/server/src/common/infrastructure/database/transaction-manager.interface.ts @@ -13,7 +13,7 @@ export interface ITransactionManager { * 🔹 Ejecuta un bloque de código dentro de una transacción * Si algo falla, se hace rollback automáticamente. */ - execute(work: (transaction: any) => Promise): Promise; + complete(work: (transaction: any) => Promise): Promise; /** * 🔹 Confirma la transacción diff --git a/apps/server/src/common/infrastructure/database/transaction-manager.ts b/apps/server/src/common/infrastructure/database/transaction-manager.ts index affcd677..c22cd847 100644 --- a/apps/server/src/common/infrastructure/database/transaction-manager.ts +++ b/apps/server/src/common/infrastructure/database/transaction-manager.ts @@ -25,7 +25,7 @@ export abstract class TransactionManager implements ITransactionManager { /** * 🔹 Ejecuta una función dentro de una transacción */ - async execute(work: (transaction: any) => Promise): Promise { + async complete(work: (transaction: any) => Promise): Promise { await this.start(); try { const result = await work(this.getTransaction()); diff --git a/apps/server/src/common/infrastructure/logger/index.ts b/apps/server/src/common/infrastructure/logger/index.ts new file mode 100644 index 00000000..5a06f78e --- /dev/null +++ b/apps/server/src/common/infrastructure/logger/index.ts @@ -0,0 +1,91 @@ +import rTracer from "cls-rtracer"; +import dotenv from "dotenv"; +import path from "path"; +import { createLogger, format, transports } from "winston"; +import DailyRotateFile from "winston-daily-rotate-file"; + +dotenv.config(); + +export const initLogger = () => { + const isProduction = process.env.NODE_ENV === "production"; + + const consoleFormat = format.combine( + format.colorize(), + format.timestamp(), + format.align(), + format.splat(), + format.printf((info) => { + const rid = rTracer.id(); + + let out = + isProduction && rid + ? `${info.timestamp} [request-id:${rid}] - ${info.level}: [${info.label}]: ${info.message}` + : `${info.timestamp} - ${info.level}: [${info.label}]: ${info.message}`; + + if (info.metadata?.error) { + out = `${out} ${info.metadata.error}`; + if (info.metadata?.error?.stack) { + out = `${out} ${info.metadata.error.stack}`; + } + } + + return out; + }) + ); + + const fileFormat = format.combine( + format.timestamp(), + format.splat(), + format.label({ label: path.basename(String(require.main?.filename)) }), + //format.metadata(), + format.metadata({ fillExcept: ["message", "level", "timestamp", "label"] }), + format.simple(), + format.json() + ); + + const logger = createLogger({ + level: isProduction ? "debug" : "debug", + + format: fileFormat, + + transports: [ + new DailyRotateFile({ + dirname: isProduction ? "/logs" : ".", + filename: "error-%DATE%.log", + datePattern: "YYYY-MM-DD", + utc: true, + level: "error", + maxSize: "5m", + maxFiles: "1d", + }), + new DailyRotateFile({ + dirname: isProduction ? "/logs" : ".", + filename: "debug-%DATE%.log", + datePattern: "YYYY-MM-DD", + utc: true, + level: "debug", + maxSize: "5m", + maxFiles: "1d", + }), + ], + }); + + // + // If we're not in production then log to the `console` with the format: + // `${info.level}: ${info.message} JSON.stringify({ ...rest }) ` + // + //if (!config.isProduction) { + logger.add( + new transports.Console({ + format: consoleFormat, + level: "debug", + }) + ); + //} + + return logger; +}; + +export const logger = () => { + return initLogger(); +}; diff --git a/apps/server/src/common/infrastructure/passport/passport.ts b/apps/server/src/common/infrastructure/passport/passport.ts index cd2aad5a..d3c0455e 100644 --- a/apps/server/src/common/infrastructure/passport/passport.ts +++ b/apps/server/src/common/infrastructure/passport/passport.ts @@ -14,7 +14,7 @@ passport.use( new JwtStrategy(jwtOptions, async (payload, done) => { try { const userResult = await authUserRepository.findById(payload.userId); - if (userResult.isError()) { + if (userResult.isFailure) { return done(null, false); } return done(null, userResult.data); diff --git a/apps/server/src/common/infrastructure/sequelize/index.ts b/apps/server/src/common/infrastructure/sequelize/index.ts index 74dfc4bc..cbe4ce74 100644 --- a/apps/server/src/common/infrastructure/sequelize/index.ts +++ b/apps/server/src/common/infrastructure/sequelize/index.ts @@ -1 +1,2 @@ export * from "./sequelize-repository"; +export * from "./sequelize-transaction-manager"; diff --git a/apps/server/src/common/infrastructure/sequelize/sequelize-repository.ts b/apps/server/src/common/infrastructure/sequelize/sequelize-repository.ts index f4cb5a8c..02cba251 100644 --- a/apps/server/src/common/infrastructure/sequelize/sequelize-repository.ts +++ b/apps/server/src/common/infrastructure/sequelize/sequelize-repository.ts @@ -1,66 +1,102 @@ -import { IAggregateRootRepository, Result } from "@common/domain"; -import { Transaction } from "sequelize"; +import { IAggregateRootRepository, Result, UniqueID } from "@common/domain"; +import { ModelDefined, Transaction } from "sequelize"; export abstract class SequelizeRepository implements IAggregateRootRepository { - /** - * 🔹 Convertir un modelo de Sequelize en un agregado del dominio - * Cada repositorio concreto debe implementar este método. - */ - protected abstract toDomain(entity: any): Result; + protected _findById( + model: ModelDefined, + id: string, + params: any = {}, + transaction?: Transaction + ): Promise { + return model.findByPk(id.toString(), { + transaction, + ...params, + }); + } - /** - * 🔹 Convertir un agregado del dominio en datos listos para persistir - */ - protected abstract toPersistence(aggregate: T): any; + protected async _exists( + model: ModelDefined, + field: string, + value: any, + transaction?: Transaction + ): Promise { + const where: { [key: string]: any } = {}; + where[field] = value; - /** - * 🔹 Buscar por ID y devolver el agregado - */ - async findById(id: string, transaction?: Transaction): Promise> { - const entity = await this._findById(id, transaction); - if (!entity) { - return Result.fail(new Error("Entity not found")); + const count: number = await model.count({ + where, + transaction, + }); + + return Promise.resolve(Boolean(count !== 0)); + } + + protected async _save( + model: ModelDefined, + id: UniqueID, + data: any, + params: any = {}, + transaction?: Transaction + ): Promise { + if (await this._exists(model, "id", id.toString())) { + await model.update( + { + ...data, + id: undefined, + }, + { + where: { id: id.toString() }, + transaction: transaction, + ...params, + } + ); + } else { + await model.create( + { + ...data, + id: id.toString(), + }, + { + include: [{ all: true }], + transaction: transaction, + ...params, + } + ); } - return this.toDomain(entity); + } + + protected async _deleteById( + model: ModelDefined, + id: UniqueID, + force: boolean = false, + transaction?: Transaction + ) { + await model.destroy({ + where: { + id: id.toString(), + }, + transaction, + force, + }); } /** - * 🔹 Crear un nuevo agregado en la BD + * 🔹 Manejo de errores de la base de datos */ - async create(aggregate: T, transaction?: Transaction): Promise> { - const data = this.toPersistence(aggregate); - await this._create(data, transaction); - return Result.ok(); - } - - /** - * 🔹 Actualizar un agregado en la BD - */ - async update(aggregate: T, transaction?: Transaction): Promise> { - const data = this.toPersistence(aggregate); - const updated = await this._update(data.id, data, transaction); - if (!updated) { - return Result.fail(new Error("Failed to update entity")); + protected _handleDatabaseError(error: unknown): Result { + const _error = error as Error; + if (_error.name === "SequelizeUniqueConstraintError") { + return Result.fail(new Error("User with this email already exists")); } - return Result.ok(); - } - /** - * 🔹 Eliminar un agregado de la BD - */ - async delete(id: string, transaction?: Transaction): Promise> { - const deleted = await this._delete(id, transaction); - if (!deleted) { - return Result.fail(new Error("Failed to delete entity")); + if (_error.name === "SequelizeConnectionError") { + return Result.fail(new Error("Database connection lost")); } - return Result.ok(); - } - /** - * 🔹 Métodos privados que deben ser implementados en la infraestructura - */ - protected abstract _findById(id: string, transaction?: Transaction): Promise; - protected abstract _create(data: any, transaction?: Transaction): Promise; - protected abstract _update(id: string, data: any, transaction?: Transaction): Promise; - protected abstract _delete(id: string, transaction?: Transaction): Promise; + if (_error.name === "SequelizeTimeoutError") { + return Result.fail(new Error("Database request timed out")); + } + + return Result.fail(new Error("Unexpected database error")); + } } diff --git a/apps/server/src/common/infrastructure/sequelize/sequelize-transaction-manager.ts b/apps/server/src/common/infrastructure/sequelize/sequelize-transaction-manager.ts index afd4b3d3..6f69058d 100644 --- a/apps/server/src/common/infrastructure/sequelize/sequelize-transaction-manager.ts +++ b/apps/server/src/common/infrastructure/sequelize/sequelize-transaction-manager.ts @@ -19,3 +19,7 @@ export class SequelizeTransactionManager extends TransactionManager { } } } + +export const createSequelizeTransactionManager = () => { + return new SequelizeTransactionManager(); +}; diff --git a/apps/server/src/common/presentation/express/express-controller.ts b/apps/server/src/common/presentation/express/express-controller.ts index aa70837c..a4bf9dc4 100644 --- a/apps/server/src/common/presentation/express/express-controller.ts +++ b/apps/server/src/common/presentation/express/express-controller.ts @@ -1,5 +1,6 @@ import { NextFunction, Request, Response } from "express"; import httpStatus from "http-status"; +import { ApiError } from "./api-error"; export abstract class ExpressController { protected req!: Request; @@ -8,25 +9,10 @@ export abstract class ExpressController { protected abstract executeImpl(): Promise; - public execute(req: Request, res: Response, next: NextFunction): void { - this.req = req; - this.res = res; - this.next = next; - - this.executeImpl(); - } - protected ok(dto?: T) { return dto ? this.res.status(httpStatus.OK).json(dto) : this.res.status(httpStatus.OK).send(); } - protected fail(error: string | Error) { - console.error("ExpressController FAIL:", error); - return this.res - .status(httpStatus.INTERNAL_SERVER_ERROR) - .json({ message: error instanceof Error ? error.message : error }); - } - protected created(dto?: T) { return dto ? this.res.status(httpStatus.CREATED).json(dto) @@ -37,27 +23,128 @@ export abstract class ExpressController { return this.res.status(httpStatus.NO_CONTENT).send(); } - protected clientError(message?: string) { - return this.res.status(httpStatus.BAD_REQUEST).json({ message }); + protected errorResponse(apiError: ApiError) { + return this.res.status(apiError.status).json(apiError); } + /** + * 🔹 Respuesta para errores de cliente (400 Bad Request) + */ + protected clientError(message: string, errors?: any[]) { + return this.errorResponse( + new ApiError({ + status: 400, + title: "Bad Request", + detail: message, + errors, + }) + ); + } + + /** + * 🔹 Respuesta para errores de autenticación (401 Unauthorized) + */ protected unauthorizedError(message?: string) { - return this.res.status(httpStatus.UNAUTHORIZED).json({ message }); + return this.errorResponse( + new ApiError({ + status: 401, + title: "Unauthorized", + detail: message ?? "You are not authorized to access this resource.", + }) + ); } + /** + * 🔹 Respuesta para errores de autorización (403 Forbidden) + */ protected forbiddenError(message?: string) { - return this.res.status(httpStatus.FORBIDDEN).json({ message }); + return this.errorResponse( + new ApiError({ + status: 403, + title: "Forbidden", + detail: message ?? "You do not have permission to perform this action.", + }) + ); } - protected notFoundError(message?: string) { - return this.res.status(httpStatus.NOT_FOUND).json({ message }); + /** + * 🔹 Respuesta para recursos no encontrados (404 Not Found) + */ + protected notFoundError(message: string) { + return this.errorResponse( + new ApiError({ + status: 404, + title: "Not Found", + detail: message, + }) + ); } - protected conflictError(message?: string) { - return this.res.status(httpStatus.CONFLICT).json({ message }); + /** + * 🔹 Respuesta para conflictos (409 Conflict) + */ + protected conflictError(message: string, errors?: any[]) { + return this.errorResponse( + new ApiError({ + status: 409, + title: "Conflict", + detail: message, + errors, + }) + ); } - protected invalidInputError(message?: string) { - return this.res.status(httpStatus.UNPROCESSABLE_ENTITY).json({ message }); + /** + * 🔹 Respuesta para errores de validación de entrada (422 Unprocessable Entity) + */ + protected invalidInputError(message: string, errors?: any[]) { + return this.errorResponse( + new ApiError({ + status: 422, + title: "Invalid Input", + detail: message, + errors, + }) + ); + } + + /** + * Respuesta para errores de servidor no disponible (503 Service Unavailable) + * @param message + * @returns + */ + protected unavailableError(message?: string) { + return this.errorResponse( + new ApiError({ + status: 503, + title: "Service Unavailable", + detail: message ?? "The service is currently unavailable. Please try again later.", + }) + ); + } + + /** + * 🔹 Respuesta para errores internos del servidor (500 Internal Server Error) + */ + protected internalServerError(message?: string) { + return this.errorResponse( + new ApiError({ + status: 500, + title: "Internal Server Error", + detail: message ?? "An unexpected error occurred. Please try again later.", + }) + ); + } + + public execute(req: Request, res: Response, next: NextFunction): void { + this.req = req; + this.res = res; + this.next = next; + + try { + this.executeImpl(); + } catch (error) { + this.internalServerError((error as Error).message); + } } } diff --git a/apps/server/src/config/index.ts b/apps/server/src/config/index.ts index c30cd664..a3a59312 100644 --- a/apps/server/src/config/index.ts +++ b/apps/server/src/config/index.ts @@ -1 +1,12 @@ +import dotenv from "dotenv"; export * from "./database"; + +// Carga variables de entorno desde el archivo .env +dotenv.config(); + +// Exporta una configuración centralizada, aplicando valores por defecto donde sea necesario +export const ENV = { + HOST: process.env.HOST || process.env.HOSTNAME || "localhost", + PORT: process.env.PORT || "18888", + NODE_ENV: process.env.NODE_ENV || "development", +}; diff --git a/apps/server/src/contexts/auth/application/auth-provider.interface.ts b/apps/server/src/contexts/auth/application/auth-provider.interface.ts new file mode 100644 index 00000000..0eed9174 --- /dev/null +++ b/apps/server/src/contexts/auth/application/auth-provider.interface.ts @@ -0,0 +1,9 @@ +export interface IAuthProvider { + generateAccessToken(payload: any): string; + generateRefreshToken(payload: any): string; + + /** + * 🔹 Verifica la validez de un token JWT y devuelve su payload + */ + verifyToken(token: string): any; +} diff --git a/apps/server/src/contexts/auth/application/auth-service.interface.ts b/apps/server/src/contexts/auth/application/auth-service.interface.ts index 15cbab22..f464379e 100644 --- a/apps/server/src/contexts/auth/application/auth-service.interface.ts +++ b/apps/server/src/contexts/auth/application/auth-service.interface.ts @@ -6,9 +6,9 @@ export interface IAuthService { * 🔹 Registra un nuevo usuario en el sistema. * Si el email ya existe, devuelve un error. */ - registerUser( - username: Username, - email: EmailAddress, - password: PasswordHash - ): Promise>; + registerUser(params: { + username: Username; + email: EmailAddress; + passwordHash: PasswordHash; + }): Promise>; } diff --git a/apps/server/src/contexts/auth/application/auth.service.ts b/apps/server/src/contexts/auth/application/auth.service.ts index 60923ce8..d5d81dad 100644 --- a/apps/server/src/contexts/auth/application/auth.service.ts +++ b/apps/server/src/contexts/auth/application/auth.service.ts @@ -1,20 +1,28 @@ import { Result, UniqueID } from "@common/domain"; import { ITransactionManager } from "@common/infrastructure/database"; import { + AuthenticatedUser, EmailAddress, IAuthenticatedUserRepository, PasswordHash, Username, } from "@contexts/auth/domain"; +import { IAuthProvider } from "./auth-provider.interface"; import { IAuthService } from "./auth-service.interface"; export class AuthService implements IAuthService { private _respository!: IAuthenticatedUserRepository; private readonly _transactionManager!: ITransactionManager; + private readonly _authProvider: IAuthProvider; - constructor(repository: IAuthenticatedUserRepository, transactionManager: ITransactionManager) { + constructor( + repository: IAuthenticatedUserRepository, + transactionManager: ITransactionManager, + authProvider: IAuthProvider + ) { this._respository = repository; this._transactionManager = transactionManager; + this._authProvider = authProvider; } /** @@ -24,49 +32,79 @@ export class AuthService implements IAuthService { async registerUser(params: { username: Username; email: EmailAddress; - password: PasswordHash; - }): Promise> { - return await this._transactionManager.execute(async (transaction) => { - const { username, email, password } = params; - const userIdResult = UniqueID.generateNewID(); + passwordHash: PasswordHash; + }): Promise> { + try { + return await this._transactionManager.complete(async (transaction) => { + const { username, email, passwordHash } = params; - // Verificar si el usuario ya existe - const userExists = await this._respository.userExists(email.toString(), transaction); - if (userExists) { - return Result.fail(new Error("Email is already registered")); - } + // Verificar si el usuario ya existe + const userExists = await this._respository.findUserByEmail(email, transaction); + if (userExists.isSuccess && userExists.data) { + return Result.fail(new Error("Email is already registered")); + } - const user = await this._respository.createUser( - { - id: userIdResult, - username: username, - email: email, - password: password, - isActive: true, - }, - transaction - ); + if (userExists.isFailure) { + return Result.fail(userExists.error); + } - return Result.ok({ userId: user.id }); - }); + const newUserId = UniqueID.generateNewID().data; + + // 🔹 Generar Access Token y Refresh Token + const accessToken = this._authProvider.generateAccessToken({ + userId: newUserId.toString(), + email: email.toString(), + roles: ["USER"], + }); + + const refreshToken = this._authProvider.generateRefreshToken({ + userId: newUserId.toString(), + }); + + const userOrError = AuthenticatedUser.create( + { + username, + email, + passwordHash, + roles: ["USER"], + token: accessToken, + }, + newUserId + ); + + if (userOrError.isFailure) { + return Result.fail(userOrError.error); + } + + const createdResult = await this._respository.createUser(userOrError.data, transaction); + + if (createdResult.isFailure) { + return Result.fail(createdResult.error); + } + + return Result.ok(userOrError.data); + }); + } catch (error: unknown) { + return Result.fail(error as Error); + } } /** * 🔹 `login` * Autentica un usuario y genera un token JWT bajo transacción. */ - static async login( + /*static async login( email: string, password: string ): Promise> { return await authUserRepository.executeTransaction(async (transaction) => { const emailResult = EmailAddress.create(email); - if (emailResult.isError()) { + if (emailResult.isFailure) { return Result.fail(emailResult.error); } const user = await authUserRepository.findByEmail(emailResult.data.getValue(), transaction); - if (user.isError()) { + if (user.isFailure) { return Result.fail(new Error("Invalid email or password")); } @@ -79,19 +117,19 @@ export class AuthService implements IAuthService { return Result.ok({ token, userId: user.data.getUserID() }); }); - } + }*/ /** * 🔹 `selectCompany` * Permite a un usuario seleccionar una empresa activa en la sesión bajo transacción. */ - static async selectCompany( + /*static async selectCompany( userId: string, companyId: string ): Promise> { return await authUserRepository.executeTransaction(async (transaction) => { const user = await authUserRepository.findById(userId, transaction); - if (user.isError()) { + if (user.isFailure) { return Result.fail(new Error("User not found")); } @@ -106,13 +144,13 @@ export class AuthService implements IAuthService { return Result.ok({ message: "Company selected successfully" }); }); - } + }*/ /** * 🔹 `logout` * Simula el cierre de sesión de un usuario. No requiere transacción. */ - static logout(): Result<{ message: string }, never> { + /*static logout(): Result<{ message: string }, never> { return Result.ok({ message: "Logged out successfully" }); - } + }*/ } diff --git a/apps/server/src/contexts/auth/application/index.ts b/apps/server/src/contexts/auth/application/index.ts index e2719d0c..f281f971 100644 --- a/apps/server/src/contexts/auth/application/index.ts +++ b/apps/server/src/contexts/auth/application/index.ts @@ -1,11 +1,17 @@ -export * from "./auth-service.interface"; -import { ITransactionManager } from "@common/infrastructure/database"; -import { SequelizeTransactionManager } from "@common/infrastructure/sequelize/sequelize-transaction-manager"; -import { AuthenticatedUserRepository } from "../infraestructure"; +import { createSequelizeTransactionManager } from "@common/infrastructure"; + +import { createAuthenticatedUserRepository } from "../infraestructure"; +import { createPassportAuthProvider } from "../infraestructure/passport/passport-auth-provider"; +import { IAuthProvider } from "./auth-provider.interface"; +import { IAuthService } from "./auth-service.interface"; import { AuthService } from "./auth.service"; -const transactionManager: ITransactionManager = new SequelizeTransactionManager(); -const authenticatedUserRepository = new AuthenticatedUserRepository(); -const authService = new AuthService(authenticatedUserRepository, transactionManager); +export * from "./auth-provider.interface"; +export * from "./auth-service.interface"; -export { authService }; +export const createAuthService = (): IAuthService => { + const transactionManager = createSequelizeTransactionManager(); + const authenticatedUserRepository = createAuthenticatedUserRepository(); + const authProvider: IAuthProvider = createPassportAuthProvider(); + 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 fbed7f78..a52b8daa 100644 --- a/apps/server/src/contexts/auth/domain/aggregates/authenticated-user.ts +++ b/apps/server/src/contexts/auth/domain/aggregates/authenticated-user.ts @@ -1,25 +1,21 @@ import { AggregateRoot, Result, UniqueID } from "@common/domain"; import { UserAuthenticatedEvent } from "../events"; -import { EmailAddress, Username } from "../value-objects"; +import { EmailAddress, PasswordHash, Username } from "../value-objects"; export interface IAuthenticatedUserProps { username: Username; email: EmailAddress; + passwordHash: PasswordHash; roles: string[]; token: string; } export class AuthenticatedUser extends AggregateRoot { - static create(props: IAuthenticatedUserProps, id?: UniqueID): Result { - const { username, email, roles, token } = props; - - if (!id || !username || !email || !token) { - return Result.fail(new Error("Invalid authenticated user data")); - } - - const user = new AuthenticatedUser({ username, email, roles, token }, id); + static create(props: IAuthenticatedUserProps, id: UniqueID): Result { + const user = new AuthenticatedUser(props, id); // 🔹 Disparar evento de dominio "UserAuthenticatedEvent" + const { email } = props; user.addDomainEvent(new UserAuthenticatedEvent(id, email.toString())); return Result.ok(user); @@ -28,11 +24,12 @@ export class AuthenticatedUser extends AggregateRoot { /** * 🔹 Devuelve una representación lista para persistencia */ - public toPersistenceData(): any { + toPersistenceData(): any { return { id: this._id.toString(), username: this._props.username.toString(), email: this._props.email.toString(), + password: this._props.passwordHash.toString(), roles: JSON.stringify(this._props.roles), token: this._props.token, }; diff --git a/apps/server/src/contexts/auth/domain/index.ts b/apps/server/src/contexts/auth/domain/index.ts index 2cca2244..84f4dfe9 100644 --- a/apps/server/src/contexts/auth/domain/index.ts +++ b/apps/server/src/contexts/auth/domain/index.ts @@ -1,5 +1,4 @@ export * from "./aggregates/authenticated-user"; -export * from "./auth-user.entity"; export * from "./events/user-authenticated.event"; export * from "./repositories"; export * from "./value-objects"; diff --git a/apps/server/src/contexts/auth/domain/repositories/authenticated-user-repository.interface.ts b/apps/server/src/contexts/auth/domain/repositories/authenticated-user-repository.interface.ts index e86d62c1..af2eb1cb 100644 --- a/apps/server/src/contexts/auth/domain/repositories/authenticated-user-repository.interface.ts +++ b/apps/server/src/contexts/auth/domain/repositories/authenticated-user-repository.interface.ts @@ -1 +1,12 @@ -export interface IAuthenticatedUserRepository {} +import { Result } from "@common/domain"; +import { AuthenticatedUser } from "../aggregates"; +import { EmailAddress } from "../value-objects"; + +export interface IAuthenticatedUserRepository { + findUserByEmail( + email: EmailAddress, + transaction?: any + ): Promise>; + + createUser(user: AuthenticatedUser, transaction?: any): Promise>; +} diff --git a/apps/server/src/contexts/auth/domain/value-objects/email-address.spec.ts b/apps/server/src/contexts/auth/domain/value-objects/email-address.spec.ts index 090b8721..06f8f50e 100644 --- a/apps/server/src/contexts/auth/domain/value-objects/email-address.spec.ts +++ b/apps/server/src/contexts/auth/domain/value-objects/email-address.spec.ts @@ -4,28 +4,28 @@ describe("EmailAddress Value Object", () => { it("should create a valid email", () => { const result = EmailAddress.create("user@example.com"); - expect(result.isOk()).toBe(true); + expect(result.isSuccess).toBe(true); expect(result.data.getValue()).toBe("user@example.com"); }); it("should return an error for invalid email format", () => { const result = EmailAddress.create("invalid-email"); - expect(result.isError()).toBe(true); + expect(result.isSuccess).toBe(true); expect(result.error.message).toBe("Invalid email format"); }); it("should allow null email", () => { const result = EmailAddress.create(null); - expect(result.isOk()).toBe(true); + expect(result.isSuccess).toBe(true); expect(result.data.getValue()).toBe(null); }); it("should convert empty string to null", () => { const result = EmailAddress.create(""); - expect(result.isOk()).toBe(true); + expect(result.isSuccess).toBe(true); expect(result.data.getValue()).toBe(null); }); @@ -33,8 +33,8 @@ describe("EmailAddress Value Object", () => { const email1 = EmailAddress.create("test@example.com"); const email2 = EmailAddress.create("test@example.com"); - expect(email1.isOk()).toBe(true); - expect(email2.isOk()).toBe(true); + expect(email1.isSuccess).toBe(true); + expect(email2.isSuccess).toBe(true); expect(email1.data.equals(email2.data)).toBe(true); }); @@ -42,22 +42,22 @@ describe("EmailAddress Value Object", () => { const email1 = EmailAddress.create("test@example.com"); const email2 = EmailAddress.create("other@example.com"); - expect(email1.isOk()).toBe(true); - expect(email2.isOk()).toBe(true); + expect(email1.isSuccess).toBe(true); + expect(email2.isSuccess).toBe(true); expect(email1.data.equals(email2.data)).toBe(false); }); it("should detect empty email correctly", () => { const email = EmailAddress.create(null); - expect(email.isOk()).toBe(true); + expect(email.isSuccess).toBe(true); expect(email.data.isEmpty()).toBe(true); }); it("should detect non-empty email correctly", () => { const email = EmailAddress.create("test@example.com"); - expect(email.isOk()).toBe(true); + expect(email.isSuccess).toBe(true); expect(email.data.isEmpty()).toBe(false); }); }); diff --git a/apps/server/src/contexts/auth/domain/value-objects/password-hash.spec.ts b/apps/server/src/contexts/auth/domain/value-objects/password-hash.spec.ts index 3ba7e745..dd4f2baa 100644 --- a/apps/server/src/contexts/auth/domain/value-objects/password-hash.spec.ts +++ b/apps/server/src/contexts/auth/domain/value-objects/password-hash.spec.ts @@ -4,20 +4,20 @@ describe("PasswordHash Value Object", () => { it("should hash a valid password", async () => { const result = await PasswordHash.create("StrongPass123"); - expect(result.isOk()).toBe(true); + expect(result.isSuccess).toBe(true); expect(result.data.getValue()).not.toBe("StrongPass123"); // Should be hashed }); it("should return an error for short password", async () => { const result = await PasswordHash.create("12345"); - expect(result.isError()).toBe(true); - expect(result.error.message).toBe("Password must be at least 8 characters long"); + expect(result.isSuccess).toBe(true); + expect(result.error.message).toBe("Password must be at least 6 characters long"); }); it("should validate password comparison correctly", async () => { const result = await PasswordHash.create("SecurePass123"); - expect(result.isOk()).toBe(true); + expect(result.isSuccess).toBe(true); const isValid = await result.data.compare("SecurePass123"); expect(isValid).toBe(true); @@ -25,7 +25,7 @@ describe("PasswordHash Value Object", () => { it("should fail password comparison for incorrect passwords", async () => { const result = await PasswordHash.create("SecurePass123"); - expect(result.isOk()).toBe(true); + expect(result.isSuccess).toBe(true); const isValid = await result.data.compare("WrongPassword"); expect(isValid).toBe(false); diff --git a/apps/server/src/contexts/auth/domain/value-objects/password-hash.ts b/apps/server/src/contexts/auth/domain/value-objects/password-hash.ts index 9e9402d5..83617af6 100644 --- a/apps/server/src/contexts/auth/domain/value-objects/password-hash.ts +++ b/apps/server/src/contexts/auth/domain/value-objects/password-hash.ts @@ -2,26 +2,22 @@ import { Result, ValueObject } from "@common/domain"; import bcrypt from "bcrypt"; import { z } from "zod"; -const PasswordSchema = z - .string() - .min(8, { message: "Password must be at least 8 characters long" }); - export class PasswordHash extends ValueObject { private static readonly SALT_ROUNDS = 10; - static async create(plainPassword: string): Promise> { + static create(plainPassword: string): Result { const result = PasswordHash.validate(plainPassword); if (!result.success) { return Result.fail(new Error(result.error.errors[0].message)); } - const hashed = await bcrypt.hash(result.data, this.SALT_ROUNDS); + const hashed = bcrypt.hashSync(result.data, this.SALT_ROUNDS); return Result.ok(new PasswordHash(hashed)); } private static validate(password: string) { - const schema = z.string().min(8, { message: "Password must be at least 8 characters long" }); + const schema = z.string().min(6, { message: "Password must be at least 6 characters long" }); return schema.safeParse(password); } diff --git a/apps/server/src/contexts/auth/infraestructure/index.ts b/apps/server/src/contexts/auth/infraestructure/index.ts index 91f6b2d5..bcfc98bc 100644 --- a/apps/server/src/contexts/auth/infraestructure/index.ts +++ b/apps/server/src/contexts/auth/infraestructure/index.ts @@ -1,3 +1,4 @@ export * from "./jwt.helper"; +export * from "./mappers"; +export * from "./passport"; export * from "./sequelize"; -12; diff --git a/apps/server/src/contexts/auth/infraestructure/mappers/authenticated-user.mapper.ts b/apps/server/src/contexts/auth/infraestructure/mappers/authenticated-user.mapper.ts index 81dbbb8e..53d29d21 100644 --- a/apps/server/src/contexts/auth/infraestructure/mappers/authenticated-user.mapper.ts +++ b/apps/server/src/contexts/auth/infraestructure/mappers/authenticated-user.mapper.ts @@ -1,11 +1,12 @@ import { Result, UniqueID } from "@common/domain"; -import { AuthenticatedUser, EmailAddress, Username } from "@contexts/auth/domain"; +import { AuthenticatedUser, EmailAddress, PasswordHash, Username } from "@contexts/auth/domain"; +import { IAuthenticatedUserMapper } from "./authenticated-user-mapper.interface"; -export class AuthenticatedUserMapper { +export class AuthenticatedUserMapper implements IAuthenticatedUserMapper { /** * 🔹 Convierte una entidad de la base de datos en un agregado de dominio `AuthenticatedUser` */ - static toDomain(entity: any): Result { + toDomain(entity: any): Result { if (!entity) { return Result.fail(new Error("Entity not found")); } @@ -13,12 +14,18 @@ export class AuthenticatedUserMapper { // Crear Value Objects asegurando que sean válidos const uniqueIdResult = UniqueID.create(entity.id); const usernameResult = Username.create(entity.username); + const passwordHashResult = PasswordHash.create(entity.passwordHash); const emailResult = EmailAddress.create(entity.email); - + 1; // Validar que no haya errores en la creación de los Value Objects - const okOrError = Result.combine([uniqueIdResult, usernameResult, emailResult]); - if (okOrError.isError()) { - return okOrError; + const okOrError = Result.combine([ + uniqueIdResult, + usernameResult, + passwordHashResult, + emailResult, + ]); + if (okOrError.isFailure) { + return Result.fail(okOrError.error.message); } // Crear el agregado de dominio @@ -26,6 +33,7 @@ export class AuthenticatedUserMapper { { username: usernameResult.data!, email: emailResult.data!, + passwordHash: passwordHashResult.data!, roles: entity.roles || [], token: entity.token, }, @@ -36,7 +44,10 @@ export class AuthenticatedUserMapper { /** * 🔹 Convierte un agregado `AuthenticatedUser` en un objeto listo para persistencia */ - static toPersistence(authenticatedUser: AuthenticatedUser): any { + toPersistence(authenticatedUser: AuthenticatedUser): any { return authenticatedUser.toPersistenceData(); } } + +export const createAuthenticatedUserMapper = (): IAuthenticatedUserMapper => + new AuthenticatedUserMapper(); diff --git a/apps/server/src/contexts/auth/infraestructure/passport/index.ts b/apps/server/src/contexts/auth/infraestructure/passport/index.ts new file mode 100644 index 00000000..c4e280b7 --- /dev/null +++ b/apps/server/src/contexts/auth/infraestructure/passport/index.ts @@ -0,0 +1 @@ +export * from "./passport-auth-provider"; 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 new file mode 100644 index 00000000..6aa11e87 --- /dev/null +++ b/apps/server/src/contexts/auth/infraestructure/passport/passport-auth-provider.ts @@ -0,0 +1,48 @@ +import { IAuthProvider } from "@contexts/auth/application"; +import jwt from "jsonwebtoken"; +import passport from "passport"; +import { ExtractJwt, Strategy as JwtStrategy } from "passport-jwt"; + +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() { + this.initializePassport(); + } + + generateAccessToken(payload: any): string { + return jwt.sign(payload, SECRET_KEY, { expiresIn: ACCESS_EXPIRATION }); + } + + generateRefreshToken(payload: any): string { + return jwt.sign(payload, SECRET_KEY, { expiresIn: REFRESH_EXPIRATION }); + } + + verifyToken(token: string): any { + return jwt.verify(token, SECRET_KEY); + } + + /** + * 🔹 Configura PassportJS con la estrategia JWT + */ + private initializePassport(): void { + const jwtOptions = { + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + secretOrKey: SECRET_KEY, + }; + + passport.use( + new JwtStrategy(jwtOptions, (payload, done) => { + try { + return done(null, payload); + } catch (error) { + return done(error, false); + } + }) + ); + } +} + +export const createPassportAuthProvider = () => new PassportAuthProvider(); 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 d6834dbe..e5f36d5c 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 @@ -1,13 +1,12 @@ -import { Result, UniqueID } from "@common/domain"; +import { Result } from "@common/domain"; import { SequelizeRepository } from "@common/infrastructure"; import { AuthenticatedUser, EmailAddress, IAuthenticatedUserRepository, - Username, } from "@contexts/auth/domain"; import { Transaction } from "sequelize"; -import { IAuthenticatedUserMapper } from "../mappers"; +import { createAuthenticatedUserMapper, IAuthenticatedUserMapper } from "../mappers"; import { AuthUserModel } from "./auth-user.model"; export class AuthenticatedUserRepository @@ -21,56 +20,61 @@ export class AuthenticatedUserRepository this._mapper = mapper; } - protected async _findById(id: string, transaction?: Transaction): Promise { - return await AuthUserModel.findByPk(id, { transaction }); - } + async userExists( + email: EmailAddress, + transaction?: Transaction + ): Promise> { + try { + const rawUser: any = await this._findById( + AuthUserModel, + "email", + email.toString(), + transaction + ); - async create(user: AuthenticatedUser, transaction?: Transaction): Promise> { - const persistenceData = this._mapper.toPersistence(user); - await AuthUserModel.create(persistenceData, { transaction }); - return Result.ok(); - } - protected async _update(id: string, data: any, transaction?: Transaction): Promise { - const [updated] = await AuthUserModel.update(data, { where: { id }, transaction }); - return updated > 0; - } - - protected async _delete(id: string, transaction?: Transaction): Promise { - const deleted = await AuthUserModel.destroy({ where: { id }, transaction }); - return deleted > 0; - } - - protected toDomain(entity: any): Result { - if (!entity) { - return Result.fail(new Error("Entity not found")); + return Result.ok(Boolean(rawUser)); + } catch (error: any) { + return this._handleDatabaseError(error); } + } - // 🔹 Crear los Value Objects manejando errores correctamente - const idOrError = UniqueID.create(entity.id); - const usernameOrError = Username.create(entity.username); - const emailOrError = EmailAddress.create(entity.email); + async findUserByEmail( + email: EmailAddress, + transaction?: Transaction + ): Promise> { + try { + const rawUser: any = await this._findById( + AuthUserModel, + "email", + email.toString(), + transaction + ); - // 🔹 Si algún Value Object es inválido, devolver el error inmediatamente - const combinedResults = [idOrError, usernameOrError, emailOrError]; - for (const result of combinedResults) { - if (result.isError()) { - return Result.fail(result.error); + if (!rawUser === true) { + return Result.ok(null); } + + return this._mapper.toDomain(rawUser); + } catch (error: any) { + return this._handleDatabaseError(error); } - - // 🔹 Crear las propiedades validadas del agregado - const props = { - username: usernameOrError.data!, - email: emailOrError.data!, - roles: entity.roles || [], - token: entity.token, - }; - - // 🔹 Crear el agregado manejando errores - return AuthenticatedUser.create(props, idOrError.data!); } - protected toPersistence(authenticatedUser: AuthenticatedUser): any { - this._mapper.toPersistence(authenticatedUser); + async createUser( + user: AuthenticatedUser, + transaction?: Transaction + ): Promise> { + try { + const persistenceData = this._mapper.toPersistence(user); + await AuthUserModel.create(persistenceData, { transaction }); + return Result.ok(); + } catch (error: any) { + return this._handleDatabaseError(error); + } } } + +export const createAuthenticatedUserRepository = (): IAuthenticatedUserRepository => { + const authenticatedUserMapper = createAuthenticatedUserMapper(); + return new AuthenticatedUserRepository(authenticatedUserMapper); +}; diff --git a/apps/server/src/contexts/auth/presentation/auth.controller.ts b/apps/server/src/contexts/auth/presentation/auth.controller.ts deleted file mode 100644 index f795fea2..00000000 --- a/apps/server/src/contexts/auth/presentation/auth.controller.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { ExpressController } from "@common/presentation/express/express-controller"; -import { Request, Response } from "express"; -import { AuthService } from "../application"; -import { EmailAddress, PasswordHash, Username } from "../domain"; -import { IRegisterUserRequestDTO } from "./dto"; - -class AuthController extends ExpressController { - protected async executeImpl(): Promise { - this.clientError("Method not implemented"); - } - - async register(req: Request, res: Response) { - const { username, email, password }: IRegisterUserRequestDTO = req.body; - - const emailVO = EmailAddress.create(email); - const usernameVO = Username.create(username); - const passwordVO = await PasswordHash.create(password); - - const combined = [emailVO, usernameVO, passwordVO].every((r) => r.isOk()); - - if (!combined) { - return this.clientError("Invalid input data"); - } - - const result = await AuthService.registerUser({ - username: usernameVO.data, - email: emailVO.data, - password: passwordVO.data, - }); - - return result.isError() - ? this.clientError(result.error.message) - : this.created({ userId: result.data.userId }); - } - - async login(req: Request, res: Response) { - const { email, password } = req.body; - const result = await AuthService.login(email, password); - - return result.isError() ? this.unauthorizedError(result.error.message) : this.ok(result.data); - } - - async selectCompany(req: Request, res: Response) { - const userId = (req as any).user.userId; - const { companyId } = req.body; - - const result = await AuthService.selectCompany(userId, companyId); - - return result.isError() ? this.forbiddenError(result.error.message) : this.ok(result.data); - } - - async logout(req: Request, res: Response) { - return this.ok(AuthService.logout()); - } -} - -export const authController = new AuthController(); diff --git a/apps/server/src/contexts/auth/presentation/auth.routes.ts b/apps/server/src/contexts/auth/presentation/auth.routes.ts index a4051334..5708332b 100644 --- a/apps/server/src/contexts/auth/presentation/auth.routes.ts +++ b/apps/server/src/contexts/auth/presentation/auth.routes.ts @@ -1,8 +1,6 @@ -import { authController } from "./auth.controller"; - import { validateRequest } from "@common/presentation"; import { NextFunction, Request, Response, Router } from "express"; -import { registerController } from "./controllers"; +import { createRegisterController } from "./controllers"; import { RegisterUserSchema } from "./dto"; const loggerMiddleware = () => (req: Request, res: Response, next: NextFunction) => { @@ -27,7 +25,9 @@ export const authRouter = (appRouter: Router) => { * * @apiError (400) {String} message Error message. */ - authRoutes.post("/register", validateRequest(RegisterUserSchema), registerController.execute); + authRoutes.post("/register", validateRequest(RegisterUserSchema), (req, res, next) => { + createRegisterController().execute(req, res, next); + }); /** * @api {post} /api/auth/login Authenticate a user @@ -43,7 +43,7 @@ export const authRouter = (appRouter: Router) => { * * @apiError (401) {String} message Invalid email or password. */ - authRoutes.post("/login", authController.login); + //authRoutes.post("/login", authController.login); /** * @api {post} /api/auth/select-company Select an active company @@ -59,7 +59,7 @@ export const authRouter = (appRouter: Router) => { * * @apiError (403) {String} message Unauthorized or invalid company selection. */ - authRoutes.post("/select-company", authMiddleware, authController.selectCompany); + //authRoutes.post("/select-company", authMiddleware, authController.selectCompany); /** * @api {post} /api/auth/logout Logout user @@ -71,7 +71,7 @@ export const authRouter = (appRouter: Router) => { * * @apiSuccess (200) {String} message Success message. */ - authRoutes.post("/logout", authMiddleware, authController.logout); + //authRoutes.post("/logout", authMiddleware, authController.logout); appRouter.use("/auth", authRoutes); }; 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 a7448736..cc0022fd 100644 --- a/apps/server/src/contexts/auth/presentation/controllers/register.controller.ts +++ b/apps/server/src/contexts/auth/presentation/controllers/register.controller.ts @@ -1,12 +1,11 @@ import { ExpressController } from "@common/presentation"; -import { authService } from "@contexts/auth/application"; -import { AuthService } from "@contexts/auth/application/auth.service"; +import { createAuthService, IAuthService } from "@contexts/auth/application"; import { EmailAddress, PasswordHash, Username } from "@contexts/auth/domain"; class RegisterController extends ExpressController { - private readonly _authService!: AuthService; + private readonly _authService!: IAuthService; - constructor(authService: AuthService) { + public constructor(authService: IAuthService) { super(); this._authService = authService; } @@ -14,22 +13,47 @@ class RegisterController extends ExpressController { async executeImpl() { const emailVO = EmailAddress.create(this.req.body.email); const usernameVO = Username.create(this.req.body.username); - const passwordVO = await PasswordHash.create(this.req.body.password); + const passwordHashVO = await PasswordHash.create(this.req.body.password); - if ([emailVO, usernameVO, passwordVO].some((r) => r.isError())) { + if ([emailVO, usernameVO, passwordHashVO].some((r) => r.isFailure)) { return this.clientError("Invalid input data"); } const result = await this._authService.registerUser({ username: usernameVO.data, email: emailVO.data, - password: passwordVO.data, + passwordHash: passwordHashVO.data, }); - return result.isError() - ? this.clientError(result.error.message) - : this.created({ userId: result.data.userId }); + if (result.isFailure) { + console.log(result.error); + const message = result.error.message; + + if (message.includes("User with this email already exists")) { + return this.conflictError(message); + } + + if ( + message.includes("Database connection lost") || + message.includes("Database request timed out") + ) { + return this.unavailableError( + "Database service is currently unavailable. Please try again later." + ); + } + + return this.internalServerError(message); + } + + return this.created({ + accessToken: result.data.accessToken, + refreshToken: result.data.refreshToken, + userId: result.data.user.getID(), + }); } } -export const registerController = new RegisterController(authService); +export const createRegisterController = () => { + const authService = createAuthService(); + return new RegisterController(authService); +}; diff --git a/apps/server/src/contexts/auth/presentation/dto/auth.validation.dto.ts b/apps/server/src/contexts/auth/presentation/dto/auth.validation.dto.ts index 2bf71243..4265af47 100644 --- a/apps/server/src/contexts/auth/presentation/dto/auth.validation.dto.ts +++ b/apps/server/src/contexts/auth/presentation/dto/auth.validation.dto.ts @@ -3,12 +3,12 @@ import { z } from "zod"; export const RegisterUserSchema = z.object({ username: z.string().min(3, "Username must be at least 3 characters long"), email: z.string().email("Invalid email format"), - password: z.string().min(8, "Password must be at least 8 characters long"), + password: z.string().min(6, "Password must be at least 6 characters long"), }); export const LoginUserSchema = z.object({ email: z.string().email("Invalid email format"), - password: z.string().min(8, "Password must be at least 8 characters long"), + password: z.string().min(6, "Password must be at least 6 characters long"), }); export const SelectCompanySchema = z.object({ diff --git a/apps/server/src/contexts/auth/presentation/index.ts b/apps/server/src/contexts/auth/presentation/index.ts index fd010ada..0229de14 100644 --- a/apps/server/src/contexts/auth/presentation/index.ts +++ b/apps/server/src/contexts/auth/presentation/index.ts @@ -1 +1,4 @@ -export * from "./auth.controller"; +export * from "./auth.routes"; +export * from "./controllers"; +export * from "./dto"; +export * from "./middleware"; diff --git a/apps/server/src/contexts/auth/presentation/middleware/index.ts b/apps/server/src/contexts/auth/presentation/middleware/index.ts new file mode 100644 index 00000000..db9a0811 --- /dev/null +++ b/apps/server/src/contexts/auth/presentation/middleware/index.ts @@ -0,0 +1 @@ +export * from "./passport-auth"; diff --git a/apps/server/src/contexts/auth/presentation/middleware/passport-auth.ts b/apps/server/src/contexts/auth/presentation/middleware/passport-auth.ts new file mode 100644 index 00000000..538ef256 --- /dev/null +++ b/apps/server/src/contexts/auth/presentation/middleware/passport-auth.ts @@ -0,0 +1,12 @@ +import { NextFunction, Request, Response } from "express"; +import passport from "passport"; + +export function authenticateJWT(req: Request, res: Response, next: NextFunction) { + passport.authenticate("jwt", { session: false }, (err, user) => { + if (err || !user) { + return res.status(401).json({ message: "Unauthorized: Invalid token" }); + } + (req as any).user = user; + next(); + })(req, res, next); +} diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index 79053f50..c8fb084d 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -1,16 +1,128 @@ -import { createApp } from "./app"; -import { connectToDatabase } from "./config/database"; +import { initLogger } 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 PORT = process.env.PORT || 3000; +const logger = initLogger(); -(async () => { - // Conexión a la base de datos - await connectToDatabase(); +// Guardamos información del estado del servidor +export const currentState = { + launchedAt: DateTime.now(), + appPath: process.cwd(), + host: ENV.HOST, + port: ENV.PORT, + environment: ENV.NODE_ENV, + connections: {} as Record, +}; - // Inicializar la aplicación - const app = createApp(); +// Manejo de cierre forzado del servidor (graceful shutdown) +const serverStop = (server: http.Server) => { + const forceTimeout = 30000; - app.listen(PORT, () => { - console.log(`Servidor escuchando en http://localhost:${PORT}`); + return new Promise((resolve, reject) => { + logger.warn("⚡️ Shutting down server"); + + setTimeout(() => { + logger.error("Could not close connections in time, forcefully shutting down"); + resolve(); + }, forceTimeout).unref(); + + server.close((err) => { + if (err) { + return reject(err); + } + logger.info("Closed out remaining connections."); + logger.info("Bye!"); + resolve(); + }); }); +}; + +// Manejo de errores al iniciar el servidor +const serverError = (error: NodeJS.ErrnoException) => { + logger.debug(`⛔️ Server wasn't able to start properly.`); + + if (error.code === "EADDRINUSE") { + logger.error(`The port ${error.port} is already used by another application.`); + } else { + logger.error(error); + } + + // Dependiendo de la criticidad, podrías forzar el proceso a salir + // process.exit(1); +}; + +// Almacena en "connections" cada nueva conexión (descomentar si se quiere seguimiento) +const serverConnection = (conn: any) => { + const key = `${conn.remoteAddress}:${conn.remotePort}`; + currentState.connections[key] = conn; + + conn.on("close", () => { + delete currentState.connections[key]; + }); +}; + +//const sequelizeConn = createSequelizeAdapter(); +//const firebirdConn = createFirebirdAdapter(); + +// Crea el servidor HTTP +const server = http + .createServer(createApp()) + .once("listening", () => + process.on("SIGINT", async () => { + // Por ejemplo, podrías desconectar la base de datos aquí: + // firebirdConn.disconnect(); + // O forzar desconexión en adapters + // sequelizeConn.close(); + + await serverStop(server); + }) + ) + .on("close", () => + logger.info(`Shut down at: ${DateTime.now().toLocaleString(DateTime.DATETIME_FULL)}`) + ) + .on("connection", serverConnection) + .on("error", serverError); + +// Ejemplo de adapters de base de datos (descoméntalos si los necesitas) +// const sequelizeConn = createSequelizeAdapter(); +// const firebirdConn = createFirebirdAdapter(); + +// Manejo de promesas no capturadas +process.on("unhandledRejection", (reason: any, promise: Promise) => { + logger.error("Unhandled Rejection at:", promise, "reason:", reason); + // Dependiendo de la aplicación, podrías desear una salida total o un cierre controlado + // process.exit(1); +}); + +// Manejo de excepciones no controladas +process.on("uncaughtException", (error: Error) => { + // firebirdConn.disconnect(); + logger.error(`${new Date().toUTCString()} uncaughtException:`, error.message); + logger.error(error.stack); + // process.exit(1); +}); + +// Arranca el servidor si la conexión a la base de datos va bien +(async () => { + try { + await connectToDatabase(); + // Lógica de inicialización de DB, si procede: + // initStructure(sequelizeConn.connection); + // insertUsers(); + + server.listen(currentState.port, () => { + const now = DateTime.now(); + logger.info(`Time: ${now.toLocaleString(DateTime.DATETIME_FULL)} ${now.zoneName}`); + logger.info(`Launched in: ${now.diff(currentState.launchedAt).toMillis()} ms`); + logger.info(`Environment: ${currentState.environment}`); + logger.info(`Process PID: ${process.pid}`); + logger.info("To shut down your server, press + C at any time"); + logger.info(`⚡️ Server: http://${currentState.host}:${currentState.port}`); + }); + } catch (error) { + serverError(error as NodeJS.ErrnoException); + } })(); diff --git a/apps/server/src/routes/v1.routes.ts b/apps/server/src/routes/v1.routes.ts index ad826ade..6a586fd0 100644 --- a/apps/server/src/routes/v1.routes.ts +++ b/apps/server/src/routes/v1.routes.ts @@ -8,13 +8,6 @@ export const v1Routes = () => { res.send("Hello world!"); }); - routes.use((req, res, next) => { - console.log( - `[${new Date().toLocaleTimeString()}] Incoming request ${req.method} to ${req.path}` - ); - next(); - }); - authRouter(routes); return routes; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 44c5e029..184c5fd6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: bcrypt: specifier: ^5.1.1 version: 5.1.1 + cls-rtracer: + specifier: ^2.6.3 + version: 2.6.3 cors: specifier: ^2.8.5 version: 2.8.5 @@ -33,17 +36,23 @@ importers: specifier: ^0.24.0 version: 0.24.2 express: - specifier: ^4.21.2 + specifier: ^4.18.2 version: 4.21.2 helmet: specifier: ^8.0.0 version: 8.0.0 + http: + specifier: 0.0.1-security + version: 0.0.1-security http-status: specifier: ^2.1.0 version: 2.1.0 jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 + luxon: + specifier: ^3.5.0 + version: 3.5.0 mariadb: specifier: ^3.4.0 version: 3.4.0 @@ -71,9 +80,21 @@ importers: shallow-equal-object: specifier: ^1.1.1 version: 1.1.1 + ts-node: + specifier: ^10.9.1 + version: 10.9.2(@types/node@22.12.0)(typescript@5.7.3) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 uuid: specifier: ^11.0.5 version: 11.0.5 + winston: + specifier: ^3.17.0 + version: 3.17.0 + winston-daily-rotate-file: + specifier: ^5.0.0 + version: 5.0.0(winston@3.17.0) zod: specifier: ^3.24.1 version: 3.24.1 @@ -88,14 +109,17 @@ importers: specifier: ^5.0.2 version: 5.0.2 '@types/express': - specifier: ^5.0.0 - version: 5.0.0 + specifier: ^4.17.21 + version: 4.17.21 '@types/jest': specifier: ^29.5.14 version: 29.5.14 '@types/jsonwebtoken': specifier: ^9.0.8 version: 9.0.8 + '@types/luxon': + specifier: ^3.4.2 + version: 3.4.2 '@types/node': specifier: ^22.10.7 version: 22.12.0 @@ -117,6 +141,30 @@ importers: eslint: specifier: ^9.19.0 version: 9.19.0(jiti@1.21.7) + eslint-config-prettier: + specifier: ^9.0.0 + version: 9.1.0(eslint@9.19.0(jiti@1.21.7)) + eslint-plugin-hexagonal-architecture: + specifier: ^1.0.3 + version: 1.0.3(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3) + eslint-plugin-import: + specifier: ^2.28.0 + version: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7)) + eslint-plugin-jest: + specifier: ^27.4.2 + version: 27.9.0(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7))(jest@29.7.0(@types/node@22.12.0)(ts-node@10.9.2(@types/node@22.12.0)(typescript@5.7.3)))(typescript@5.7.3) + eslint-plugin-prettier: + specifier: ^5.0.0 + version: 5.2.3(eslint-config-prettier@9.1.0(eslint@9.19.0(jiti@1.21.7)))(eslint@9.19.0(jiti@1.21.7))(prettier@3.4.2) + eslint-plugin-simple-import-sort: + specifier: ^10.0.0 + version: 10.0.0(eslint@9.19.0(jiti@1.21.7)) + eslint-plugin-sort-class-members: + specifier: ^1.19.0 + version: 1.21.0(eslint@9.19.0(jiti@1.21.7)) + eslint-plugin-unused-imports: + specifier: ^3.0.0 + version: 3.2.0(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7)) jest: specifier: ^29.7.0 version: 29.7.0(@types/node@22.12.0)(ts-node@10.9.2(@types/node@22.12.0)(typescript@5.7.3)) @@ -129,9 +177,6 @@ importers: ts-node-dev: specifier: ^2.0.0 version: 2.0.0(@types/node@22.12.0)(typescript@5.7.3) - tsx: - specifier: ^4.19.2 - version: 4.19.2 typescript: specifier: ^5.7.3 version: 5.7.3 @@ -448,10 +493,17 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} + '@dabh/diagnostics@2.0.3': + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + '@esbuild/aix-ppc64@0.23.1': resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} engines: {node: '>=18'} @@ -922,6 +974,10 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@pkgr/core@0.1.1': + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@radix-ui/react-compose-refs@1.1.1': resolution: {integrity: sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==} peerDependencies: @@ -1035,6 +1091,9 @@ packages: cpu: [x64] os: [win32] + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -1083,11 +1142,11 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/express-serve-static-core@5.0.6': - resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==} + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} - '@types/express@5.0.0': - resolution: {integrity: sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==} + '@types/express@4.17.21': + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} '@types/geojson@7946.0.16': resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} @@ -1113,9 +1172,15 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/jsonwebtoken@9.0.8': resolution: {integrity: sha512-7fx54m60nLFUVYlxAB1xpe9CBWX2vSrk50Y6ogRJ1v5xxtba7qXTg5BgYDN5dq+yuQQ9HaVlHJyAAt1/mxryFg==} + '@types/luxon@3.4.2': + resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==} + '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} @@ -1157,6 +1222,9 @@ packages: '@types/response-time@2.3.8': resolution: {integrity: sha512-7qGaNYvdxc0zRab8oHpYx7AW17qj+G0xuag1eCrw3M2VWPJQ/HyKaaghWygiaOUl0y9x7QGQwppDpqLJ5V9pzw==} + '@types/semver@7.5.8': + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} @@ -1172,6 +1240,9 @@ packages: '@types/strip-json-comments@0.0.30': resolution: {integrity: sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==} + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + '@types/validator@13.12.2': resolution: {integrity: sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==} @@ -1196,6 +1267,10 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/scope-manager@5.62.0': + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/scope-manager@8.22.0': resolution: {integrity: sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1207,16 +1282,35 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/types@5.62.0': + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/types@8.22.0': resolution: {integrity: sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@5.62.0': + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/typescript-estree@8.22.0': resolution: {integrity: sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/utils@5.62.0': + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@typescript-eslint/utils@8.22.0': resolution: {integrity: sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1224,6 +1318,10 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/visitor-keys@5.62.0': + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/visitor-keys@8.22.0': resolution: {integrity: sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1324,10 +1422,18 @@ packages: resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} engines: {node: '>= 0.4'} + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + array.prototype.findlast@1.2.5: resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} engines: {node: '>= 0.4'} + array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + engines: {node: '>= 0.4'} + array.prototype.flat@1.3.3: resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} engines: {node: '>= 0.4'} @@ -1499,6 +1605,10 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} + cls-rtracer@2.6.3: + resolution: {integrity: sha512-O7M/m2M/KfT9v+q7ka9nmsadS67ce9P8+1Zgm6VFamK56oFd1iCoJ9m8hYKUQpK4+RofyaexxHJlOBkxqCDs3Q==} + engines: {node: '>=12.17.0 <13.0.0 || >=13.14.0 <14.0.0 || >=14.0.0'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -1510,17 +1620,32 @@ packages: collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + color-support@1.1.3: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true + color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + + colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -1593,6 +1718,14 @@ packages: supports-color: optional: true + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.4.0: resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} @@ -1659,6 +1792,10 @@ packages: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} @@ -1711,6 +1848,9 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} @@ -1784,10 +1924,82 @@ packages: peerDependencies: eslint: '>=7.0.0' + eslint-config-prettier@9.1.0: + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-module-utils@2.12.0: + resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-hexagonal-architecture@1.0.3: + resolution: {integrity: sha512-Im3JkmK0MAw92puUZVhvXmR14SoS04NjgF5R6+rzM7eKGUPoePWoTaxZ0hILGGaJVfccllF7Z2APlaoErznz5A==} + peerDependencies: + eslint: '*' + + eslint-plugin-import@2.31.0: + resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-jest@27.9.0: + resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 || ^7.0.0 + eslint: ^7.0.0 || ^8.0.0 + jest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + jest: + optional: true + eslint-plugin-only-warn@1.1.0: resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} engines: {node: '>=6'} + eslint-plugin-prettier@5.2.3: + resolution: {integrity: sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + eslint-plugin-react-hooks@5.1.0: resolution: {integrity: sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==} engines: {node: '>=10'} @@ -1805,12 +2017,41 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + eslint-plugin-simple-import-sort@10.0.0: + resolution: {integrity: sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==} + peerDependencies: + eslint: '>=5.0.0' + + eslint-plugin-sort-class-members@1.21.0: + resolution: {integrity: sha512-QKV4jvGMu/ge1l4s1TUBC6rqqV/fbABWY7q2EeNpV3FRikoX6KuLhiNvS8UuMi+EERe0hKGrNU9e6ukFDxNnZQ==} + engines: {node: '>=4.0.0'} + peerDependencies: + eslint: '>=0.8.0' + eslint-plugin-turbo@2.3.4: resolution: {integrity: sha512-9ncoUJkQGkC28NmlQiS17oB9mrE8XaSulRZiB5pv9vmRbYjOfUwyGhY3EIcoBRdww81igxOzXmAmvNNd6GFBPg==} peerDependencies: eslint: '>6.6.0' turbo: '>2.0.0' + eslint-plugin-unused-imports@3.2.0: + resolution: {integrity: sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': 6 - 7 + eslint: '8' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + + eslint-rule-composer@0.3.0: + resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} + engines: {node: '>=4.0.0'} + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + eslint-scope@8.2.0: resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1850,6 +2091,10 @@ packages: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} @@ -1881,6 +2126,9 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + fast-glob@3.3.1: resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} engines: {node: '>=8.6.0'} @@ -1901,10 +2149,16 @@ packages: fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + file-stream-rotator@0.6.1: + resolution: {integrity: sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==} + filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} @@ -1931,6 +2185,9 @@ packages: flatted@3.3.2: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + for-each@0.3.4: resolution: {integrity: sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==} engines: {node: '>= 0.4'} @@ -2043,6 +2300,10 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -2102,6 +2363,9 @@ packages: resolution: {integrity: sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==} engines: {node: '>= 0.4.0'} + http@0.0.1-security: + resolution: {integrity: sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g==} + https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -2164,6 +2428,9 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-async-function@2.1.1: resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} engines: {node: '>= 0.4'} @@ -2478,6 +2745,10 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -2504,6 +2775,9 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -2557,6 +2831,10 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + logform@2.7.0: + resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} + engines: {node: '>= 12.0.0'} + long@5.2.4: resolution: {integrity: sha512-qtzLbJE8hq7VabR3mISmVGtoXP8KGc2Z/AT8OuqlYD7JTR3oqrgwdjnk07wpj1twXxYmgDXgoKVWUG/fReSzHg==} @@ -2583,6 +2861,10 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + engines: {node: '>=12'} + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -2789,6 +3071,10 @@ packages: resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} engines: {node: '>= 0.4'} + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + object.values@1.2.1: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} @@ -2804,6 +3090,9 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} @@ -2884,6 +3173,10 @@ packages: path-to-regexp@0.1.12: resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + pause@0.0.1: resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==} @@ -2958,6 +3251,10 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + prettier@3.4.2: resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} engines: {node: '>=14'} @@ -3120,6 +3417,10 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -3235,6 +3536,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + simple-update-notifier@2.0.0: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} @@ -3267,6 +3571,9 @@ packages: resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} engines: {node: '>= 0.6'} + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -3358,6 +3665,10 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + synckit@0.9.2: + resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} + engines: {node: ^14.18.0 || >=16.0.0} + tailwind-merge@2.6.0: resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==} @@ -3379,6 +3690,9 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -3411,6 +3725,10 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + ts-api-utils@2.0.0: resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} engines: {node: '>=18.12'} @@ -3469,9 +3787,28 @@ packages: '@swc/wasm': optional: true + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + tsconfig@7.0.0: resolution: {integrity: sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==} + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsutils@3.21.0: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + tsx@4.19.2: resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==} engines: {node: '>=18.0.0'} @@ -3598,6 +3935,10 @@ packages: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -3686,6 +4027,20 @@ packages: wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + winston-daily-rotate-file@5.0.0: + resolution: {integrity: sha512-JDjiXXkM5qvwY06733vf09I2wnMXpZEhxEVOSPenZMii+g7pcDcTBt2MRugnoi8BwVSuCT2jfRXBUy+n1Zz/Yw==} + engines: {node: '>=8'} + peerDependencies: + winston: ^3 + + winston-transport@4.9.0: + resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} + engines: {node: '>= 12.0.0'} + + winston@3.17.0: + resolution: {integrity: sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==} + engines: {node: '>= 12.0.0'} + wkx@0.5.0: resolution: {integrity: sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==} @@ -3952,10 +4307,18 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} + '@colors/colors@1.6.0': {} + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 + '@dabh/diagnostics@2.0.3': + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + '@esbuild/aix-ppc64@0.23.1': optional: true @@ -4395,6 +4758,8 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true + '@pkgr/core@0.1.1': {} + '@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.8)(react@18.3.1)': dependencies: react: 18.3.1 @@ -4465,6 +4830,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.32.1': optional: true + '@rtsao/scc@1.1.0': {} + '@sinclair/typebox@0.27.8': {} '@sinonjs/commons@3.0.1': @@ -4523,17 +4890,17 @@ snapshots: '@types/estree@1.0.6': {} - '@types/express-serve-static-core@5.0.6': + '@types/express-serve-static-core@4.19.6': dependencies: '@types/node': 22.12.0 '@types/qs': 6.9.18 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 - '@types/express@5.0.0': + '@types/express@4.17.21': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 5.0.6 + '@types/express-serve-static-core': 4.19.6 '@types/qs': 6.9.18 '@types/serve-static': 1.15.7 @@ -4562,11 +4929,15 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/json5@0.0.29': {} + '@types/jsonwebtoken@9.0.8': dependencies: '@types/ms': 2.1.0 '@types/node': 22.12.0 + '@types/luxon@3.4.2': {} + '@types/mime@1.3.5': {} '@types/ms@2.1.0': {} @@ -4582,12 +4953,12 @@ snapshots: '@types/passport-strategy@0.2.38': dependencies: - '@types/express': 5.0.0 + '@types/express': 4.17.21 '@types/passport': 1.0.17 '@types/passport@1.0.17': dependencies: - '@types/express': 5.0.0 + '@types/express': 4.17.21 '@types/prop-types@15.7.14': {} @@ -4610,9 +4981,11 @@ snapshots: '@types/response-time@2.3.8': dependencies: - '@types/express': 5.0.0 + '@types/express': 4.17.21 '@types/node': 22.12.0 + '@types/semver@7.5.8': {} + '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 @@ -4630,6 +5003,8 @@ snapshots: '@types/strip-json-comments@0.0.30': {} + '@types/triple-beam@1.3.5': {} + '@types/validator@13.12.2': {} '@types/yargs-parser@21.0.3': {} @@ -4696,6 +5071,11 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/scope-manager@5.62.0': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + '@typescript-eslint/scope-manager@8.22.0': dependencies: '@typescript-eslint/types': 8.22.0 @@ -4723,8 +5103,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/types@5.62.0': {} + '@typescript-eslint/types@8.22.0': {} + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.7.3)': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.4.0(supports-color@5.5.0) + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.6.3 + tsutils: 3.21.0(typescript@5.7.3) + optionalDependencies: + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/typescript-estree@8.22.0(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 8.22.0 @@ -4753,6 +5149,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@5.62.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0(jiti@1.21.7)) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.7.3) + eslint: 9.19.0(jiti@1.21.7) + eslint-scope: 5.1.1 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/utils@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.6.3)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0(jiti@1.21.7)) @@ -4775,6 +5186,11 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/visitor-keys@5.62.0': + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.22.0': dependencies: '@typescript-eslint/types': 8.22.0 @@ -4877,6 +5293,8 @@ snapshots: get-intrinsic: 1.2.7 is-string: 1.1.1 + array-union@2.1.0: {} + array.prototype.findlast@1.2.5: dependencies: call-bind: 1.0.8 @@ -4886,6 +5304,15 @@ snapshots: es-object-atoms: 1.1.1 es-shim-unscopables: 1.0.2 + array.prototype.findlastindex@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.0.2 + array.prototype.flat@1.3.3: dependencies: call-bind: 1.0.8 @@ -5118,20 +5545,45 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + cls-rtracer@2.6.3: + dependencies: + uuid: 9.0.1 + clsx@2.1.1: {} co@4.6.0: {} collect-v8-coverage@1.0.2: {} + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + color-convert@2.0.1: dependencies: color-name: 1.1.4 + color-name@1.1.3: {} + color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + color-support@1.1.3: {} + color@3.2.1: + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + + colorspace@1.1.4: + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + commander@4.1.1: {} concat-map@0.0.1: {} @@ -5204,6 +5656,10 @@ snapshots: dependencies: ms: 2.0.0 + debug@3.2.7: + dependencies: + ms: 2.1.3 + debug@4.4.0(supports-color@5.5.0): dependencies: ms: 2.1.3 @@ -5246,6 +5702,10 @@ snapshots: diff@4.0.2: {} + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + dlv@1.1.3: {} doctrine@2.1.0: @@ -5288,6 +5748,8 @@ snapshots: emoji-regex@9.2.2: {} + enabled@2.0.0: {} + encodeurl@1.0.2: {} encodeurl@2.0.0: {} @@ -5420,6 +5882,7 @@ snapshots: '@esbuild/win32-arm64': 0.23.1 '@esbuild/win32-ia32': 0.23.1 '@esbuild/win32-x64': 0.23.1 + optional: true esbuild@0.24.2: optionalDependencies: @@ -5461,8 +5924,92 @@ snapshots: dependencies: eslint: 9.19.0(jiti@1.21.7) + eslint-config-prettier@9.1.0(eslint@9.19.0(jiti@1.21.7)): + dependencies: + eslint: 9.19.0(jiti@1.21.7) + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.19.0(jiti@1.21.7)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3) + eslint: 9.19.0(jiti@1.21.7) + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + + eslint-plugin-hexagonal-architecture@1.0.3(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3): + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3) + eslint: 9.19.0(jiti@1.21.7) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.19.0(jiti@1.21.7)) + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + - typescript + + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.19.0(jiti@1.21.7) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.19.0(jiti@1.21.7)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7))(jest@29.7.0(@types/node@22.12.0)(ts-node@10.9.2(@types/node@22.12.0)(typescript@5.7.3)))(typescript@5.7.3): + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3) + eslint: 9.19.0(jiti@1.21.7) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3) + jest: 29.7.0(@types/node@22.12.0)(ts-node@10.9.2(@types/node@22.12.0)(typescript@5.7.3)) + transitivePeerDependencies: + - supports-color + - typescript + eslint-plugin-only-warn@1.1.0: {} + eslint-plugin-prettier@5.2.3(eslint-config-prettier@9.1.0(eslint@9.19.0(jiti@1.21.7)))(eslint@9.19.0(jiti@1.21.7))(prettier@3.4.2): + dependencies: + eslint: 9.19.0(jiti@1.21.7) + prettier: 3.4.2 + prettier-linter-helpers: 1.0.0 + synckit: 0.9.2 + optionalDependencies: + eslint-config-prettier: 9.1.0(eslint@9.19.0(jiti@1.21.7)) + eslint-plugin-react-hooks@5.1.0(eslint@9.19.0(jiti@1.21.7)): dependencies: eslint: 9.19.0(jiti@1.21.7) @@ -5493,12 +6040,34 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-simple-import-sort@10.0.0(eslint@9.19.0(jiti@1.21.7)): + dependencies: + eslint: 9.19.0(jiti@1.21.7) + + eslint-plugin-sort-class-members@1.21.0(eslint@9.19.0(jiti@1.21.7)): + dependencies: + eslint: 9.19.0(jiti@1.21.7) + eslint-plugin-turbo@2.3.4(eslint@9.19.0(jiti@1.21.7))(turbo@2.3.4): dependencies: dotenv: 16.0.3 eslint: 9.19.0(jiti@1.21.7) turbo: 2.3.4 + eslint-plugin-unused-imports@3.2.0(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7)): + dependencies: + eslint: 9.19.0(jiti@1.21.7) + eslint-rule-composer: 0.3.0 + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3) + + eslint-rule-composer@0.3.0: {} + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + eslint-scope@8.2.0: dependencies: esrecurse: 4.3.0 @@ -5565,6 +6134,8 @@ snapshots: dependencies: estraverse: 5.3.0 + estraverse@4.3.0: {} + estraverse@5.3.0: {} esutils@2.0.3: {} @@ -5631,6 +6202,8 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-diff@1.3.0: {} + fast-glob@3.3.1: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -5659,10 +6232,16 @@ snapshots: dependencies: bser: 2.1.1 + fecha@4.2.3: {} + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 + file-stream-rotator@0.6.1: + dependencies: + moment: 2.30.1 + filelist@1.0.4: dependencies: minimatch: 5.1.6 @@ -5700,6 +6279,8 @@ snapshots: flatted@3.3.2: {} + fn.name@1.1.0: {} + for-each@0.3.4: dependencies: is-callable: 1.2.7 @@ -5788,6 +6369,7 @@ snapshots: get-tsconfig@4.10.0: dependencies: resolve-pkg-maps: 1.0.0 + optional: true glob-parent@5.1.2: dependencies: @@ -5826,6 +6408,15 @@ snapshots: define-properties: 1.2.1 gopd: 1.2.0 + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -5872,6 +6463,8 @@ snapshots: http-status@2.1.0: {} + http@0.0.1-security: {} + https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 @@ -5930,6 +6523,8 @@ snapshots: is-arrayish@0.2.1: {} + is-arrayish@0.3.2: {} + is-async-function@2.1.1: dependencies: async-function: 1.0.0 @@ -6440,6 +7035,10 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json5@1.0.2: + dependencies: + minimist: 1.2.8 + json5@2.2.3: {} jsonwebtoken@9.0.2: @@ -6479,6 +7078,8 @@ snapshots: kleur@3.0.3: {} + kuler@2.0.0: {} + leven@3.1.0: {} levn@0.4.1: @@ -6518,6 +7119,15 @@ snapshots: lodash@4.17.21: {} + logform@2.7.0: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.5.0 + triple-beam: 1.4.1 + long@5.2.4: {} loose-envify@1.4.0: @@ -6538,6 +7148,8 @@ snapshots: dependencies: react: 18.3.1 + luxon@3.5.0: {} + make-dir@3.1.0: dependencies: semver: 6.3.1 @@ -6728,6 +7340,12 @@ snapshots: es-abstract: 1.23.9 es-object-atoms: 1.1.1 + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + object.values@1.2.1: dependencies: call-bind: 1.0.8 @@ -6745,6 +7363,10 @@ snapshots: dependencies: wrappy: 1.0.2 + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 @@ -6825,6 +7447,8 @@ snapshots: path-to-regexp@0.1.12: {} + path-type@4.0.0: {} + pause@0.0.1: {} pg-connection-string@2.7.0: {} @@ -6883,6 +7507,10 @@ snapshots: prelude-ls@1.2.1: {} + prettier-linter-helpers@1.0.0: + dependencies: + fast-diff: 1.3.0 + prettier@3.4.2: {} pretty-format@29.7.0: @@ -6990,7 +7618,8 @@ snapshots: resolve-from@5.0.0: {} - resolve-pkg-maps@1.0.0: {} + resolve-pkg-maps@1.0.0: + optional: true resolve.exports@2.0.3: {} @@ -7073,6 +7702,8 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 + safe-stable-stringify@2.5.0: {} + safer-buffer@2.1.2: {} scheduler@0.23.2: @@ -7204,6 +7835,10 @@ snapshots: signal-exit@4.1.0: {} + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + simple-update-notifier@2.0.0: dependencies: semver: 7.6.3 @@ -7230,6 +7865,8 @@ snapshots: sqlstring@2.3.3: {} + stack-trace@0.0.10: {} + stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 @@ -7343,6 +7980,11 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + synckit@0.9.2: + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.8.1 + tailwind-merge@2.6.0: {} tailwindcss-animate@1.0.7(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.12.0)(typescript@5.7.3))): @@ -7391,6 +8033,8 @@ snapshots: glob: 7.2.3 minimatch: 3.1.2 + text-hex@1.0.0: {} + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -7415,6 +8059,8 @@ snapshots: tree-kill@1.2.2: {} + triple-beam@1.4.1: {} + ts-api-utils@2.0.0(typescript@5.6.3): dependencies: typescript: 5.6.3 @@ -7481,6 +8127,19 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + tsconfig@7.0.0: dependencies: '@types/strip-bom': 3.0.0 @@ -7488,12 +8147,22 @@ snapshots: strip-bom: 3.0.0 strip-json-comments: 2.0.1 + tslib@1.14.1: {} + + tslib@2.8.1: {} + + tsutils@3.21.0(typescript@5.7.3): + dependencies: + tslib: 1.14.1 + typescript: 5.7.3 + tsx@4.19.2: dependencies: esbuild: 0.23.1 get-tsconfig: 4.10.0 optionalDependencies: fsevents: 2.3.3 + optional: true turbo-darwin-64@2.3.4: optional: true @@ -7623,6 +8292,8 @@ snapshots: uuid@8.3.2: {} + uuid@9.0.1: {} + v8-compile-cache-lib@3.0.1: {} v8-to-istanbul@9.3.0: @@ -7706,6 +8377,34 @@ snapshots: dependencies: string-width: 4.2.3 + winston-daily-rotate-file@5.0.0(winston@3.17.0): + dependencies: + file-stream-rotator: 0.6.1 + object-hash: 3.0.0 + triple-beam: 1.4.1 + winston: 3.17.0 + winston-transport: 4.9.0 + + winston-transport@4.9.0: + dependencies: + logform: 2.7.0 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + + winston@3.17.0: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.6 + is-stream: 2.0.1 + logform: 2.7.0 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.5.0 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.9.0 + wkx@0.5.0: dependencies: '@types/node': 22.12.0 diff --git a/tsconfig.base.json b/tsconfig.base.json index b974ef2e..aea48d7f 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,9 +1,12 @@ { "compilerOptions": { - "target": "ES6", + "target": "ES2022", "module": "CommonJS", "outDir": "./dist", + "sourceMap": true, "strict": true, + "pretty": true, + "removeComments": true /* Do not emit comments to output. */, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true,