This commit is contained in:
David Arranz 2025-02-03 14:12:36 +01:00
parent 350b8a8422
commit 7d8ca53495
48 changed files with 2145 additions and 382 deletions

48
.vscode/launch.json vendored Normal file
View File

@ -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": ["<node_internals>/**", "client/**", "dist/**", "doc/**"],
"type": "node"
}
]
}

37
.vscode/settings.json vendored
View File

@ -1,20 +1,19 @@
{ {
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.organizeImports": "explicit", "source.organizeImports": "explicit",
"source.fixAll.eslint": "explicit" "source.fixAll.eslint": "explicit"
}, },
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.formatOnPaste": false, "editor.formatOnPaste": false,
"prettier.useEditorConfig": false, "prettier.useEditorConfig": false,
"prettier.useTabs": false, "prettier.useTabs": false,
"prettier.configPath": ".prettierrc", "prettier.configPath": ".prettierrc",
"asciidoc.antora.enableAntoraSupport": true, "asciidoc.antora.enableAntoraSupport": true,
// other vscode settings // other vscode settings
"tailwindCSS.rootFontSize": 16, "tailwindCSS.rootFontSize": 16,
"[handlebars]": { "[handlebars]": {
"editor.defaultFormatter": "vscode.html-language-features" "editor.defaultFormatter": "vscode.html-language-features"
} // <- your root font size here } // <- your root font size here
} }

View File

@ -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"
}

View File

@ -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"
}

View File

@ -6,4 +6,7 @@ DB_DIALECT=mariadb
DB_PORT=3306 DB_PORT=3306
PORT=3002 PORT=3002
JWT_SECRET=clave_secreta_para_tokens
JWT_SECRET=supersecretkey
JWT_ACCESS_EXPIRATION=1h
JWT_REFRESH_EXPIRATION=7d

View File

@ -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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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 <CTRL> + 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"}

View File

@ -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"}

View File

@ -4,7 +4,8 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "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", "clean": "rm -rf dist",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "npm run clean && npm run typecheck && esbuild src/index.ts --platform=node --format=cjs --bundle --sourcemap --minify --outdir=dist", "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/eslint-config": "workspace:*",
"@repo/typescript-config": "workspace:*", "@repo/typescript-config": "workspace:*",
"@types/bcrypt": "^5.0.2", "@types/bcrypt": "^5.0.2",
"@types/express": "^5.0.0", "@types/express": "^4.17.21",
"@types/jest": "^29.5.14", "@types/jest": "^29.5.14",
"@types/jsonwebtoken": "^9.0.8", "@types/jsonwebtoken": "^9.0.8",
"@types/luxon": "^3.4.2",
"@types/node": "^22.10.7", "@types/node": "^22.10.7",
"@types/passport": "^1.0.17", "@types/passport": "^1.0.17",
"@types/passport-jwt": "^4.0.1", "@types/passport-jwt": "^4.0.1",
@ -29,22 +31,32 @@
"@typescript-eslint/eslint-plugin": "^8.22.0", "@typescript-eslint/eslint-plugin": "^8.22.0",
"@typescript-eslint/parser": "^8.22.0", "@typescript-eslint/parser": "^8.22.0",
"eslint": "^9.19.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", "jest": "^29.7.0",
"nodemon": "^3.1.9", "nodemon": "^3.1.9",
"ts-jest": "^29.2.5", "ts-jest": "^29.2.5",
"ts-node-dev": "^2.0.0", "ts-node-dev": "^2.0.0",
"tsx": "^4.19.2",
"typescript": "^5.7.3" "typescript": "^5.7.3"
}, },
"dependencies": { "dependencies": {
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"cls-rtracer": "^2.6.3",
"cors": "^2.8.5", "cors": "^2.8.5",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"esbuild": "^0.24.0", "esbuild": "^0.24.0",
"express": "^4.21.2", "express": "^4.18.2",
"helmet": "^8.0.0", "helmet": "^8.0.0",
"http": "0.0.1-security",
"http-status": "^2.1.0", "http-status": "^2.1.0",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"luxon": "^3.5.0",
"mariadb": "^3.4.0", "mariadb": "^3.4.0",
"module-alias": "^2.2.3", "module-alias": "^2.2.3",
"mysql2": "^3.12.0", "mysql2": "^3.12.0",
@ -54,13 +66,18 @@
"response-time": "^2.3.3", "response-time": "^2.3.3",
"sequelize": "^6.37.5", "sequelize": "^6.37.5",
"shallow-equal-object": "^1.1.1", "shallow-equal-object": "^1.1.1",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"uuid": "^11.0.5", "uuid": "^11.0.5",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",
"zod": "^3.24.1" "zod": "^3.24.1"
}, },
"engines": {
"node": ">=22"
},
"_moduleAliases": { "_moduleAliases": {
"@common": "./dist/common", "@common": "./dist/common",
"@auth": "./dist/auth", "@config": "./dist/config"
"@config": "./dist/config",
"@companies": "./dist/companies"
} }
} }

View File

@ -1,11 +1,14 @@
import { initLogger } from "@common/infrastructure/logger";
import { errorHandler } from "@common/presentation"; import { errorHandler } from "@common/presentation";
import dotenv from "dotenv"; import dotenv from "dotenv";
import express, { Application } from "express"; import express, { Application } from "express";
import helmet from "helmet"; import helmet from "helmet";
import passport from "passport";
import responseTime from "response-time"; import responseTime from "response-time";
import { v1Routes } from "./routes"; import { v1Routes } from "./routes";
dotenv.config(); dotenv.config();
const logger = initLogger();
export function createApp(): Application { export function createApp(): Application {
const app = express(); const app = express();
@ -25,6 +28,11 @@ export function createApp(): Application {
// Inicializar Passport // Inicializar Passport
app.use(passport.initialize()); app.use(passport.initialize());
app.use((req, _, next) => {
logger.info(`Incoming request ${req.method} to ${req.path}`);
next();
});
// Registrar rutas de la API // Registrar rutas de la API
app.use("/api/v1", v1Routes()); app.use("/api/v1", v1Routes());

View File

@ -1,8 +1 @@
import { Result } from "./result"; export interface IAggregateRootRepository<T> {}
export interface IAggregateRootRepository<T> {
findById(id: string): Promise<Result<T, Error>>;
create(entity: T): Promise<Result<void, Error>>;
update(entity: T): Promise<Result<void, Error>>;
delete(id: string): Promise<Result<void, Error>>;
}

View File

@ -4,8 +4,8 @@ describe("Result", () => {
it("should create a successful result", () => { it("should create a successful result", () => {
const result = Result.ok("Success Data"); const result = Result.ok("Success Data");
expect(result.isOk()).toBe(true); expect(result.isSuccess).toBe(true);
expect(result.isError()).toBe(false); expect(result.isSuccess).toBe(false);
expect(result.data).toBe("Success Data"); expect(result.data).toBe("Success Data");
}); });
@ -13,8 +13,8 @@ describe("Result", () => {
const error = new Error("Test error"); const error = new Error("Test error");
const result = Result.fail(error); const result = Result.fail(error);
expect(result.isOk()).toBe(false); expect(result.isSuccess).toBe(false);
expect(result.isError()).toBe(true); expect(result.isSuccess).toBe(true);
expect(result.error).toBe(error); expect(result.error).toBe(error);
}); });

View File

@ -1,6 +1,5 @@
export class Result<T, E extends Error = Error> { export class Result<T, E extends Error = Error> {
private readonly isSuccess: boolean; private readonly _isSuccess: boolean;
private readonly _data?: T; private readonly _data?: T;
private readonly _error?: E; private readonly _error?: E;
@ -13,7 +12,7 @@ export class Result<T, E extends Error = Error> {
throw new Error(`InvalidOperation: A failing result needs to contain an error message`); throw new Error(`InvalidOperation: A failing result needs to contain an error message`);
} }
this.isSuccess = isSuccess; this._isSuccess = isSuccess;
this._error = error; this._error = error;
this._data = data; this._data = data;
@ -30,7 +29,7 @@ export class Result<T, E extends Error = Error> {
static combine(results: Result<any, any>[]): Result<any, any> { static combine(results: Result<any, any>[]): Result<any, any> {
for (const result of results) { for (const result of results) {
if (result.isError()) { if (result.isFailure) {
return result; return result;
} }
} }
@ -38,23 +37,23 @@ export class Result<T, E extends Error = Error> {
return Result.ok<any>(); return Result.ok<any>();
} }
isOk(): boolean { get isSuccess(): boolean {
return this.isSuccess; return this._isSuccess;
} }
isError(): boolean { get isFailure(): boolean {
return !this.isSuccess; return !this._isSuccess;
} }
get data(): T { get data(): T {
if (!this.isSuccess) { if (!this._isSuccess) {
throw new Error("Cannot get value data from a failed result."); throw new Error("Cannot get value data from a failed result.");
} }
return this._data as T; return this._data as T;
} }
get error(): E { get error(): E {
if (this.isSuccess) { if (this._isSuccess) {
throw new Error("Cannot get error from a successful result."); throw new Error("Cannot get error from a successful result.");
} }
return this._error as E; return this._error as E;
@ -65,7 +64,7 @@ export class Result<T, E extends Error = Error> {
* Si el `Result` es un `ok`, devuelve `data`, de lo contrario, devuelve `defaultValue`. * Si el `Result` es un `ok`, devuelve `data`, de lo contrario, devuelve `defaultValue`.
*/ */
getOrElse(defaultValue: any): T | any { getOrElse(defaultValue: any): T | any {
return this.isSuccess ? this.data : defaultValue; return this._isSuccess ? this.data : defaultValue;
} }
/** /**
@ -73,6 +72,6 @@ export class Result<T, E extends Error = Error> {
* Evalúa el `Result`: ejecuta `onOk()` si es `ok` o `onError()` si es `fail`. * Evalúa el `Result`: ejecuta `onOk()` si es `ok` o `onError()` si es `fail`.
*/ */
match<R>(onOk: (data: T) => R, onError: (error: E) => R): R { match<R>(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);
} }
} }

View File

@ -4,7 +4,7 @@ describe("UniqueID Value Object", () => {
it("should generate a new UUID using generateNewID()", () => { it("should generate a new UUID using generateNewID()", () => {
const result = UniqueID.generateNewID(); const result = UniqueID.generateNewID();
expect(result.isOk()).toBe(true); expect(result.isSuccess).toBe(true);
expect(result.data.getValue()).toMatch( 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 /^[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", () => { it("should return an error for an invalid UUID", () => {
const result = UniqueID.create("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"); expect(result.error.message).toBe("Invalid UUID format");
}); });
@ -21,7 +21,7 @@ describe("UniqueID Value Object", () => {
const validUUID = "550e8400-e29b-41d4-a716-446655440000"; const validUUID = "550e8400-e29b-41d4-a716-446655440000";
const result = UniqueID.create(validUUID); const result = UniqueID.create(validUUID);
expect(result.isOk()).toBe(true); expect(result.isSuccess).toBe(true);
expect(result.data.getValue()).toBe(validUUID); expect(result.data.getValue()).toBe(validUUID);
}); });
@ -29,7 +29,7 @@ describe("UniqueID Value Object", () => {
const validUUID = "550e8400-e29b-41d4-a716-446655440000"; const validUUID = "550e8400-e29b-41d4-a716-446655440000";
const result = UniqueID.create(validUUID); const result = UniqueID.create(validUUID);
expect(result.isOk()).toBe(true); expect(result.isSuccess).toBe(true);
expect(result.data.toString()).toBe(validUUID); expect(result.data.toString()).toBe(validUUID);
}); });
}); });

View File

@ -13,7 +13,7 @@ export interface ITransactionManager {
* 🔹 Ejecuta un bloque de código dentro de una transacción * 🔹 Ejecuta un bloque de código dentro de una transacción
* Si algo falla, se hace rollback automáticamente. * Si algo falla, se hace rollback automáticamente.
*/ */
execute<T>(work: (transaction: any) => Promise<T>): Promise<T>; complete<T>(work: (transaction: any) => Promise<T>): Promise<T>;
/** /**
* 🔹 Confirma la transacción * 🔹 Confirma la transacción

View File

@ -25,7 +25,7 @@ export abstract class TransactionManager implements ITransactionManager {
/** /**
* 🔹 Ejecuta una función dentro de una transacción * 🔹 Ejecuta una función dentro de una transacción
*/ */
async execute<T>(work: (transaction: any) => Promise<T>): Promise<T> { async complete<T>(work: (transaction: any) => Promise<T>): Promise<T> {
await this.start(); await this.start();
try { try {
const result = await work(this.getTransaction()); const result = await work(this.getTransaction());

View File

@ -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();
};

View File

@ -14,7 +14,7 @@ passport.use(
new JwtStrategy(jwtOptions, async (payload, done) => { new JwtStrategy(jwtOptions, async (payload, done) => {
try { try {
const userResult = await authUserRepository.findById(payload.userId); const userResult = await authUserRepository.findById(payload.userId);
if (userResult.isError()) { if (userResult.isFailure) {
return done(null, false); return done(null, false);
} }
return done(null, userResult.data); return done(null, userResult.data);

View File

@ -1 +1,2 @@
export * from "./sequelize-repository"; export * from "./sequelize-repository";
export * from "./sequelize-transaction-manager";

View File

@ -1,66 +1,102 @@
import { IAggregateRootRepository, Result } from "@common/domain"; import { IAggregateRootRepository, Result, UniqueID } from "@common/domain";
import { Transaction } from "sequelize"; import { ModelDefined, Transaction } from "sequelize";
export abstract class SequelizeRepository<T> implements IAggregateRootRepository<T> { export abstract class SequelizeRepository<T> implements IAggregateRootRepository<T> {
/** protected _findById(
* 🔹 Convertir un modelo de Sequelize en un agregado del dominio model: ModelDefined<any, any>,
* Cada repositorio concreto debe implementar este método. id: string,
*/ params: any = {},
protected abstract toDomain(entity: any): Result<T, Error>; transaction?: Transaction
): Promise<any> {
return model.findByPk(id.toString(), {
transaction,
...params,
});
}
/** protected async _exists(
* 🔹 Convertir un agregado del dominio en datos listos para persistir model: ModelDefined<any, any>,
*/ field: string,
protected abstract toPersistence(aggregate: T): any; value: any,
transaction?: Transaction
): Promise<boolean> {
const where: { [key: string]: any } = {};
where[field] = value;
/** const count: number = await model.count({
* 🔹 Buscar por ID y devolver el agregado where,
*/ transaction,
async findById(id: string, transaction?: Transaction): Promise<Result<T, Error>> { });
const entity = await this._findById(id, transaction);
if (!entity) { return Promise.resolve(Boolean(count !== 0));
return Result.fail(new Error("Entity not found")); }
protected async _save(
model: ModelDefined<any, any>,
id: UniqueID,
data: any,
params: any = {},
transaction?: Transaction
): Promise<void> {
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<any, any>,
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<Result<void, Error>> { protected _handleDatabaseError(error: unknown): Result<never, Error> {
const data = this.toPersistence(aggregate); const _error = error as Error;
await this._create(data, transaction); if (_error.name === "SequelizeUniqueConstraintError") {
return Result.ok(); return Result.fail(new Error("User with this email already exists"));
}
/**
* 🔹 Actualizar un agregado en la BD
*/
async update(aggregate: T, transaction?: Transaction): Promise<Result<void, Error>> {
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"));
} }
return Result.ok();
}
/** if (_error.name === "SequelizeConnectionError") {
* 🔹 Eliminar un agregado de la BD return Result.fail(new Error("Database connection lost"));
*/
async delete(id: string, transaction?: Transaction): Promise<Result<void, Error>> {
const deleted = await this._delete(id, transaction);
if (!deleted) {
return Result.fail(new Error("Failed to delete entity"));
} }
return Result.ok();
}
/** if (_error.name === "SequelizeTimeoutError") {
* 🔹 Métodos privados que deben ser implementados en la infraestructura return Result.fail(new Error("Database request timed out"));
*/ }
protected abstract _findById(id: string, transaction?: Transaction): Promise<any>;
protected abstract _create(data: any, transaction?: Transaction): Promise<void>; return Result.fail(new Error("Unexpected database error"));
protected abstract _update(id: string, data: any, transaction?: Transaction): Promise<boolean>; }
protected abstract _delete(id: string, transaction?: Transaction): Promise<boolean>;
} }

View File

@ -19,3 +19,7 @@ export class SequelizeTransactionManager extends TransactionManager {
} }
} }
} }
export const createSequelizeTransactionManager = () => {
return new SequelizeTransactionManager();
};

View File

@ -1,5 +1,6 @@
import { NextFunction, Request, Response } from "express"; import { NextFunction, Request, Response } from "express";
import httpStatus from "http-status"; import httpStatus from "http-status";
import { ApiError } from "./api-error";
export abstract class ExpressController { export abstract class ExpressController {
protected req!: Request; protected req!: Request;
@ -8,25 +9,10 @@ export abstract class ExpressController {
protected abstract executeImpl(): Promise<void | any>; protected abstract executeImpl(): Promise<void | any>;
public execute(req: Request, res: Response, next: NextFunction): void {
this.req = req;
this.res = res;
this.next = next;
this.executeImpl();
}
protected ok<T>(dto?: T) { protected ok<T>(dto?: T) {
return dto ? this.res.status(httpStatus.OK).json(dto) : this.res.status(httpStatus.OK).send(); 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<T>(dto?: T) { protected created<T>(dto?: T) {
return dto return dto
? this.res.status(httpStatus.CREATED).json(dto) ? this.res.status(httpStatus.CREATED).json(dto)
@ -37,27 +23,128 @@ export abstract class ExpressController {
return this.res.status(httpStatus.NO_CONTENT).send(); return this.res.status(httpStatus.NO_CONTENT).send();
} }
protected clientError(message?: string) { protected errorResponse(apiError: ApiError) {
return this.res.status(httpStatus.BAD_REQUEST).json({ message }); 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) { 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) { 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);
}
} }
} }

View File

@ -1 +1,12 @@
import dotenv from "dotenv";
export * from "./database"; 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",
};

View File

@ -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;
}

View File

@ -6,9 +6,9 @@ export interface IAuthService {
* 🔹 Registra un nuevo usuario en el sistema. * 🔹 Registra un nuevo usuario en el sistema.
* Si el email ya existe, devuelve un error. * Si el email ya existe, devuelve un error.
*/ */
registerUser( registerUser(params: {
username: Username, username: Username;
email: EmailAddress, email: EmailAddress;
password: PasswordHash passwordHash: PasswordHash;
): Promise<Result<AuthenticatedUser, Error>>; }): Promise<Result<AuthenticatedUser, Error>>;
} }

View File

@ -1,20 +1,28 @@
import { Result, UniqueID } from "@common/domain"; import { Result, UniqueID } from "@common/domain";
import { ITransactionManager } from "@common/infrastructure/database"; import { ITransactionManager } from "@common/infrastructure/database";
import { import {
AuthenticatedUser,
EmailAddress, EmailAddress,
IAuthenticatedUserRepository, IAuthenticatedUserRepository,
PasswordHash, PasswordHash,
Username, Username,
} from "@contexts/auth/domain"; } from "@contexts/auth/domain";
import { IAuthProvider } from "./auth-provider.interface";
import { IAuthService } from "./auth-service.interface"; import { IAuthService } from "./auth-service.interface";
export class AuthService implements IAuthService { export class AuthService implements IAuthService {
private _respository!: IAuthenticatedUserRepository; private _respository!: IAuthenticatedUserRepository;
private readonly _transactionManager!: ITransactionManager; private readonly _transactionManager!: ITransactionManager;
private readonly _authProvider: IAuthProvider;
constructor(repository: IAuthenticatedUserRepository, transactionManager: ITransactionManager) { constructor(
repository: IAuthenticatedUserRepository,
transactionManager: ITransactionManager,
authProvider: IAuthProvider
) {
this._respository = repository; this._respository = repository;
this._transactionManager = transactionManager; this._transactionManager = transactionManager;
this._authProvider = authProvider;
} }
/** /**
@ -24,49 +32,79 @@ export class AuthService implements IAuthService {
async registerUser(params: { async registerUser(params: {
username: Username; username: Username;
email: EmailAddress; email: EmailAddress;
password: PasswordHash; passwordHash: PasswordHash;
}): Promise<Result<{ userId: string }, Error>> { }): Promise<Result<AuthenticatedUser, Error>> {
return await this._transactionManager.execute(async (transaction) => { try {
const { username, email, password } = params; return await this._transactionManager.complete(async (transaction) => {
const userIdResult = UniqueID.generateNewID(); const { username, email, passwordHash } = params;
// Verificar si el usuario ya existe // Verificar si el usuario ya existe
const userExists = await this._respository.userExists(email.toString(), transaction); const userExists = await this._respository.findUserByEmail(email, transaction);
if (userExists) { if (userExists.isSuccess && userExists.data) {
return Result.fail(new Error("Email is already registered")); return Result.fail(new Error("Email is already registered"));
} }
const user = await this._respository.createUser( if (userExists.isFailure) {
{ return Result.fail(userExists.error);
id: userIdResult, }
username: username,
email: email,
password: password,
isActive: true,
},
transaction
);
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` * 🔹 `login`
* Autentica un usuario y genera un token JWT bajo transacción. * Autentica un usuario y genera un token JWT bajo transacción.
*/ */
static async login( /*static async login(
email: string, email: string,
password: string password: string
): Promise<Result<{ token: string; userId: string }, Error>> { ): Promise<Result<{ token: string; userId: string }, Error>> {
return await authUserRepository.executeTransaction(async (transaction) => { return await authUserRepository.executeTransaction(async (transaction) => {
const emailResult = EmailAddress.create(email); const emailResult = EmailAddress.create(email);
if (emailResult.isError()) { if (emailResult.isFailure) {
return Result.fail(emailResult.error); return Result.fail(emailResult.error);
} }
const user = await authUserRepository.findByEmail(emailResult.data.getValue(), transaction); const user = await authUserRepository.findByEmail(emailResult.data.getValue(), transaction);
if (user.isError()) { if (user.isFailure) {
return Result.fail(new Error("Invalid email or password")); 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() }); return Result.ok({ token, userId: user.data.getUserID() });
}); });
} }*/
/** /**
* 🔹 `selectCompany` * 🔹 `selectCompany`
* Permite a un usuario seleccionar una empresa activa en la sesión bajo transacción. * Permite a un usuario seleccionar una empresa activa en la sesión bajo transacción.
*/ */
static async selectCompany( /*static async selectCompany(
userId: string, userId: string,
companyId: string companyId: string
): Promise<Result<{ message: string }, Error>> { ): Promise<Result<{ message: string }, Error>> {
return await authUserRepository.executeTransaction(async (transaction) => { return await authUserRepository.executeTransaction(async (transaction) => {
const user = await authUserRepository.findById(userId, transaction); const user = await authUserRepository.findById(userId, transaction);
if (user.isError()) { if (user.isFailure) {
return Result.fail(new Error("User not found")); return Result.fail(new Error("User not found"));
} }
@ -106,13 +144,13 @@ export class AuthService implements IAuthService {
return Result.ok({ message: "Company selected successfully" }); return Result.ok({ message: "Company selected successfully" });
}); });
} }*/
/** /**
* 🔹 `logout` * 🔹 `logout`
* Simula el cierre de sesión de un usuario. No requiere transacción. * 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" }); return Result.ok({ message: "Logged out successfully" });
} }*/
} }

View File

@ -1,11 +1,17 @@
export * from "./auth-service.interface"; import { createSequelizeTransactionManager } from "@common/infrastructure";
import { ITransactionManager } from "@common/infrastructure/database";
import { SequelizeTransactionManager } from "@common/infrastructure/sequelize/sequelize-transaction-manager"; import { createAuthenticatedUserRepository } from "../infraestructure";
import { AuthenticatedUserRepository } 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"; import { AuthService } from "./auth.service";
const transactionManager: ITransactionManager = new SequelizeTransactionManager(); export * from "./auth-provider.interface";
const authenticatedUserRepository = new AuthenticatedUserRepository(); export * from "./auth-service.interface";
const authService = new AuthService(authenticatedUserRepository, transactionManager);
export { authService }; export const createAuthService = (): IAuthService => {
const transactionManager = createSequelizeTransactionManager();
const authenticatedUserRepository = createAuthenticatedUserRepository();
const authProvider: IAuthProvider = createPassportAuthProvider();
return new AuthService(authenticatedUserRepository, transactionManager, authProvider);
};

View File

@ -1,25 +1,21 @@
import { AggregateRoot, Result, UniqueID } from "@common/domain"; import { AggregateRoot, Result, UniqueID } from "@common/domain";
import { UserAuthenticatedEvent } from "../events"; import { UserAuthenticatedEvent } from "../events";
import { EmailAddress, Username } from "../value-objects"; import { EmailAddress, PasswordHash, Username } from "../value-objects";
export interface IAuthenticatedUserProps { export interface IAuthenticatedUserProps {
username: Username; username: Username;
email: EmailAddress; email: EmailAddress;
passwordHash: PasswordHash;
roles: string[]; roles: string[];
token: string; token: string;
} }
export class AuthenticatedUser extends AggregateRoot<IAuthenticatedUserProps> { export class AuthenticatedUser extends AggregateRoot<IAuthenticatedUserProps> {
static create(props: IAuthenticatedUserProps, id?: UniqueID): Result<AuthenticatedUser, Error> { static create(props: IAuthenticatedUserProps, id: UniqueID): Result<AuthenticatedUser, Error> {
const { username, email, roles, token } = props; const user = new AuthenticatedUser(props, id);
if (!id || !username || !email || !token) {
return Result.fail(new Error("Invalid authenticated user data"));
}
const user = new AuthenticatedUser({ username, email, roles, token }, id);
// 🔹 Disparar evento de dominio "UserAuthenticatedEvent" // 🔹 Disparar evento de dominio "UserAuthenticatedEvent"
const { email } = props;
user.addDomainEvent(new UserAuthenticatedEvent(id, email.toString())); user.addDomainEvent(new UserAuthenticatedEvent(id, email.toString()));
return Result.ok(user); return Result.ok(user);
@ -28,11 +24,12 @@ export class AuthenticatedUser extends AggregateRoot<IAuthenticatedUserProps> {
/** /**
* 🔹 Devuelve una representación lista para persistencia * 🔹 Devuelve una representación lista para persistencia
*/ */
public toPersistenceData(): any { toPersistenceData(): any {
return { return {
id: this._id.toString(), id: this._id.toString(),
username: this._props.username.toString(), username: this._props.username.toString(),
email: this._props.email.toString(), email: this._props.email.toString(),
password: this._props.passwordHash.toString(),
roles: JSON.stringify(this._props.roles), roles: JSON.stringify(this._props.roles),
token: this._props.token, token: this._props.token,
}; };

View File

@ -1,5 +1,4 @@
export * from "./aggregates/authenticated-user"; export * from "./aggregates/authenticated-user";
export * from "./auth-user.entity";
export * from "./events/user-authenticated.event"; export * from "./events/user-authenticated.event";
export * from "./repositories"; export * from "./repositories";
export * from "./value-objects"; export * from "./value-objects";

View File

@ -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<Result<AuthenticatedUser | null, Error>>;
createUser(user: AuthenticatedUser, transaction?: any): Promise<Result<void, Error>>;
}

View File

@ -4,28 +4,28 @@ describe("EmailAddress Value Object", () => {
it("should create a valid email", () => { it("should create a valid email", () => {
const result = EmailAddress.create("user@example.com"); 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"); expect(result.data.getValue()).toBe("user@example.com");
}); });
it("should return an error for invalid email format", () => { it("should return an error for invalid email format", () => {
const result = EmailAddress.create("invalid-email"); const result = EmailAddress.create("invalid-email");
expect(result.isError()).toBe(true); expect(result.isSuccess).toBe(true);
expect(result.error.message).toBe("Invalid email format"); expect(result.error.message).toBe("Invalid email format");
}); });
it("should allow null email", () => { it("should allow null email", () => {
const result = EmailAddress.create(null); const result = EmailAddress.create(null);
expect(result.isOk()).toBe(true); expect(result.isSuccess).toBe(true);
expect(result.data.getValue()).toBe(null); expect(result.data.getValue()).toBe(null);
}); });
it("should convert empty string to null", () => { it("should convert empty string to null", () => {
const result = EmailAddress.create(""); const result = EmailAddress.create("");
expect(result.isOk()).toBe(true); expect(result.isSuccess).toBe(true);
expect(result.data.getValue()).toBe(null); expect(result.data.getValue()).toBe(null);
}); });
@ -33,8 +33,8 @@ describe("EmailAddress Value Object", () => {
const email1 = EmailAddress.create("test@example.com"); const email1 = EmailAddress.create("test@example.com");
const email2 = EmailAddress.create("test@example.com"); const email2 = EmailAddress.create("test@example.com");
expect(email1.isOk()).toBe(true); expect(email1.isSuccess).toBe(true);
expect(email2.isOk()).toBe(true); expect(email2.isSuccess).toBe(true);
expect(email1.data.equals(email2.data)).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 email1 = EmailAddress.create("test@example.com");
const email2 = EmailAddress.create("other@example.com"); const email2 = EmailAddress.create("other@example.com");
expect(email1.isOk()).toBe(true); expect(email1.isSuccess).toBe(true);
expect(email2.isOk()).toBe(true); expect(email2.isSuccess).toBe(true);
expect(email1.data.equals(email2.data)).toBe(false); expect(email1.data.equals(email2.data)).toBe(false);
}); });
it("should detect empty email correctly", () => { it("should detect empty email correctly", () => {
const email = EmailAddress.create(null); const email = EmailAddress.create(null);
expect(email.isOk()).toBe(true); expect(email.isSuccess).toBe(true);
expect(email.data.isEmpty()).toBe(true); expect(email.data.isEmpty()).toBe(true);
}); });
it("should detect non-empty email correctly", () => { it("should detect non-empty email correctly", () => {
const email = EmailAddress.create("test@example.com"); const email = EmailAddress.create("test@example.com");
expect(email.isOk()).toBe(true); expect(email.isSuccess).toBe(true);
expect(email.data.isEmpty()).toBe(false); expect(email.data.isEmpty()).toBe(false);
}); });
}); });

View File

@ -4,20 +4,20 @@ describe("PasswordHash Value Object", () => {
it("should hash a valid password", async () => { it("should hash a valid password", async () => {
const result = await PasswordHash.create("StrongPass123"); 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 expect(result.data.getValue()).not.toBe("StrongPass123"); // Should be hashed
}); });
it("should return an error for short password", async () => { it("should return an error for short password", async () => {
const result = await PasswordHash.create("12345"); const result = await PasswordHash.create("12345");
expect(result.isError()).toBe(true); expect(result.isSuccess).toBe(true);
expect(result.error.message).toBe("Password must be at least 8 characters long"); expect(result.error.message).toBe("Password must be at least 6 characters long");
}); });
it("should validate password comparison correctly", async () => { it("should validate password comparison correctly", async () => {
const result = await PasswordHash.create("SecurePass123"); const result = await PasswordHash.create("SecurePass123");
expect(result.isOk()).toBe(true); expect(result.isSuccess).toBe(true);
const isValid = await result.data.compare("SecurePass123"); const isValid = await result.data.compare("SecurePass123");
expect(isValid).toBe(true); expect(isValid).toBe(true);
@ -25,7 +25,7 @@ describe("PasswordHash Value Object", () => {
it("should fail password comparison for incorrect passwords", async () => { it("should fail password comparison for incorrect passwords", async () => {
const result = await PasswordHash.create("SecurePass123"); const result = await PasswordHash.create("SecurePass123");
expect(result.isOk()).toBe(true); expect(result.isSuccess).toBe(true);
const isValid = await result.data.compare("WrongPassword"); const isValid = await result.data.compare("WrongPassword");
expect(isValid).toBe(false); expect(isValid).toBe(false);

View File

@ -2,26 +2,22 @@ import { Result, ValueObject } from "@common/domain";
import bcrypt from "bcrypt"; import bcrypt from "bcrypt";
import { z } from "zod"; import { z } from "zod";
const PasswordSchema = z
.string()
.min(8, { message: "Password must be at least 8 characters long" });
export class PasswordHash extends ValueObject<string> { export class PasswordHash extends ValueObject<string> {
private static readonly SALT_ROUNDS = 10; private static readonly SALT_ROUNDS = 10;
static async create(plainPassword: string): Promise<Result<PasswordHash, Error>> { static create(plainPassword: string): Result<PasswordHash, Error> {
const result = PasswordHash.validate(plainPassword); const result = PasswordHash.validate(plainPassword);
if (!result.success) { if (!result.success) {
return Result.fail(new Error(result.error.errors[0].message)); 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)); return Result.ok(new PasswordHash(hashed));
} }
private static validate(password: string) { 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); return schema.safeParse(password);
} }

View File

@ -1,3 +1,4 @@
export * from "./jwt.helper"; export * from "./jwt.helper";
export * from "./mappers";
export * from "./passport";
export * from "./sequelize"; export * from "./sequelize";
12;

View File

@ -1,11 +1,12 @@
import { Result, UniqueID } from "@common/domain"; 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` * 🔹 Convierte una entidad de la base de datos en un agregado de dominio `AuthenticatedUser`
*/ */
static toDomain(entity: any): Result<AuthenticatedUser, Error> { toDomain(entity: any): Result<AuthenticatedUser, Error> {
if (!entity) { if (!entity) {
return Result.fail(new Error("Entity not found")); return Result.fail(new Error("Entity not found"));
} }
@ -13,12 +14,18 @@ export class AuthenticatedUserMapper {
// Crear Value Objects asegurando que sean válidos // Crear Value Objects asegurando que sean válidos
const uniqueIdResult = UniqueID.create(entity.id); const uniqueIdResult = UniqueID.create(entity.id);
const usernameResult = Username.create(entity.username); const usernameResult = Username.create(entity.username);
const passwordHashResult = PasswordHash.create(entity.passwordHash);
const emailResult = EmailAddress.create(entity.email); const emailResult = EmailAddress.create(entity.email);
1;
// Validar que no haya errores en la creación de los Value Objects // Validar que no haya errores en la creación de los Value Objects
const okOrError = Result.combine([uniqueIdResult, usernameResult, emailResult]); const okOrError = Result.combine([
if (okOrError.isError()) { uniqueIdResult,
return okOrError; usernameResult,
passwordHashResult,
emailResult,
]);
if (okOrError.isFailure) {
return Result.fail(okOrError.error.message);
} }
// Crear el agregado de dominio // Crear el agregado de dominio
@ -26,6 +33,7 @@ export class AuthenticatedUserMapper {
{ {
username: usernameResult.data!, username: usernameResult.data!,
email: emailResult.data!, email: emailResult.data!,
passwordHash: passwordHashResult.data!,
roles: entity.roles || [], roles: entity.roles || [],
token: entity.token, token: entity.token,
}, },
@ -36,7 +44,10 @@ export class AuthenticatedUserMapper {
/** /**
* 🔹 Convierte un agregado `AuthenticatedUser` en un objeto listo para persistencia * 🔹 Convierte un agregado `AuthenticatedUser` en un objeto listo para persistencia
*/ */
static toPersistence(authenticatedUser: AuthenticatedUser): any { toPersistence(authenticatedUser: AuthenticatedUser): any {
return authenticatedUser.toPersistenceData(); return authenticatedUser.toPersistenceData();
} }
} }
export const createAuthenticatedUserMapper = (): IAuthenticatedUserMapper =>
new AuthenticatedUserMapper();

View File

@ -0,0 +1 @@
export * from "./passport-auth-provider";

View File

@ -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();

View File

@ -1,13 +1,12 @@
import { Result, UniqueID } from "@common/domain"; import { Result } from "@common/domain";
import { SequelizeRepository } from "@common/infrastructure"; import { SequelizeRepository } from "@common/infrastructure";
import { import {
AuthenticatedUser, AuthenticatedUser,
EmailAddress, EmailAddress,
IAuthenticatedUserRepository, IAuthenticatedUserRepository,
Username,
} from "@contexts/auth/domain"; } from "@contexts/auth/domain";
import { Transaction } from "sequelize"; import { Transaction } from "sequelize";
import { IAuthenticatedUserMapper } from "../mappers"; import { createAuthenticatedUserMapper, IAuthenticatedUserMapper } from "../mappers";
import { AuthUserModel } from "./auth-user.model"; import { AuthUserModel } from "./auth-user.model";
export class AuthenticatedUserRepository export class AuthenticatedUserRepository
@ -21,56 +20,61 @@ export class AuthenticatedUserRepository
this._mapper = mapper; this._mapper = mapper;
} }
protected async _findById(id: string, transaction?: Transaction): Promise<any> { async userExists(
return await AuthUserModel.findByPk(id, { transaction }); email: EmailAddress,
} transaction?: Transaction
): Promise<Result<boolean, Error>> {
try {
const rawUser: any = await this._findById(
AuthUserModel,
"email",
email.toString(),
transaction
);
async create(user: AuthenticatedUser, transaction?: Transaction): Promise<Result<void, Error>> { return Result.ok(Boolean(rawUser));
const persistenceData = this._mapper.toPersistence(user); } catch (error: any) {
await AuthUserModel.create(persistenceData, { transaction }); return this._handleDatabaseError(error);
return Result.ok();
}
protected async _update(id: string, data: any, transaction?: Transaction): Promise<boolean> {
const [updated] = await AuthUserModel.update(data, { where: { id }, transaction });
return updated > 0;
}
protected async _delete(id: string, transaction?: Transaction): Promise<boolean> {
const deleted = await AuthUserModel.destroy({ where: { id }, transaction });
return deleted > 0;
}
protected toDomain(entity: any): Result<AuthenticatedUser, Error> {
if (!entity) {
return Result.fail(new Error("Entity not found"));
} }
}
// 🔹 Crear los Value Objects manejando errores correctamente async findUserByEmail(
const idOrError = UniqueID.create(entity.id); email: EmailAddress,
const usernameOrError = Username.create(entity.username); transaction?: Transaction
const emailOrError = EmailAddress.create(entity.email); ): Promise<Result<AuthenticatedUser | null, Error>> {
try {
const rawUser: any = await this._findById(
AuthUserModel,
"email",
email.toString(),
transaction
);
// 🔹 Si algún Value Object es inválido, devolver el error inmediatamente if (!rawUser === true) {
const combinedResults = [idOrError, usernameOrError, emailOrError]; return Result.ok(null);
for (const result of combinedResults) {
if (result.isError()) {
return Result.fail(result.error);
} }
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 { async createUser(
this._mapper.toPersistence(authenticatedUser); user: AuthenticatedUser,
transaction?: Transaction
): Promise<Result<void, Error>> {
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);
};

View File

@ -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<void> {
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();

View File

@ -1,8 +1,6 @@
import { authController } from "./auth.controller";
import { validateRequest } from "@common/presentation"; import { validateRequest } from "@common/presentation";
import { NextFunction, Request, Response, Router } from "express"; import { NextFunction, Request, Response, Router } from "express";
import { registerController } from "./controllers"; import { createRegisterController } from "./controllers";
import { RegisterUserSchema } from "./dto"; import { RegisterUserSchema } from "./dto";
const loggerMiddleware = () => (req: Request, res: Response, next: NextFunction) => { const loggerMiddleware = () => (req: Request, res: Response, next: NextFunction) => {
@ -27,7 +25,9 @@ export const authRouter = (appRouter: Router) => {
* *
* @apiError (400) {String} message Error message. * @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 * @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. * @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 * @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. * @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 * @api {post} /api/auth/logout Logout user
@ -71,7 +71,7 @@ export const authRouter = (appRouter: Router) => {
* *
* @apiSuccess (200) {String} message Success message. * @apiSuccess (200) {String} message Success message.
*/ */
authRoutes.post("/logout", authMiddleware, authController.logout); //authRoutes.post("/logout", authMiddleware, authController.logout);
appRouter.use("/auth", authRoutes); appRouter.use("/auth", authRoutes);
}; };

View File

@ -1,12 +1,11 @@
import { ExpressController } from "@common/presentation"; import { ExpressController } from "@common/presentation";
import { authService } from "@contexts/auth/application"; import { createAuthService, IAuthService } from "@contexts/auth/application";
import { AuthService } from "@contexts/auth/application/auth.service";
import { EmailAddress, PasswordHash, Username } from "@contexts/auth/domain"; import { EmailAddress, PasswordHash, Username } from "@contexts/auth/domain";
class RegisterController extends ExpressController { class RegisterController extends ExpressController {
private readonly _authService!: AuthService; private readonly _authService!: IAuthService;
constructor(authService: AuthService) { public constructor(authService: IAuthService) {
super(); super();
this._authService = authService; this._authService = authService;
} }
@ -14,22 +13,47 @@ class RegisterController extends ExpressController {
async executeImpl() { async executeImpl() {
const emailVO = EmailAddress.create(this.req.body.email); const emailVO = EmailAddress.create(this.req.body.email);
const usernameVO = Username.create(this.req.body.username); 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"); return this.clientError("Invalid input data");
} }
const result = await this._authService.registerUser({ const result = await this._authService.registerUser({
username: usernameVO.data, username: usernameVO.data,
email: emailVO.data, email: emailVO.data,
password: passwordVO.data, passwordHash: passwordHashVO.data,
}); });
return result.isError() if (result.isFailure) {
? this.clientError(result.error.message) console.log(result.error);
: this.created({ userId: result.data.userId }); 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);
};

View File

@ -3,12 +3,12 @@ import { z } from "zod";
export const RegisterUserSchema = z.object({ export const RegisterUserSchema = z.object({
username: z.string().min(3, "Username must be at least 3 characters long"), username: z.string().min(3, "Username must be at least 3 characters long"),
email: z.string().email("Invalid email format"), 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({ export const LoginUserSchema = z.object({
email: z.string().email("Invalid email format"), 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({ export const SelectCompanySchema = z.object({

View File

@ -1 +1,4 @@
export * from "./auth.controller"; export * from "./auth.routes";
export * from "./controllers";
export * from "./dto";
export * from "./middleware";

View File

@ -0,0 +1 @@
export * from "./passport-auth";

View File

@ -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);
}

View File

@ -1,16 +1,128 @@
import { createApp } from "./app"; import { initLogger } from "@common/infrastructure/logger";
import { connectToDatabase } from "./config/database"; 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 () => { // Guardamos información del estado del servidor
// Conexión a la base de datos export const currentState = {
await connectToDatabase(); launchedAt: DateTime.now(),
appPath: process.cwd(),
host: ENV.HOST,
port: ENV.PORT,
environment: ENV.NODE_ENV,
connections: {} as Record<string, any>,
};
// Inicializar la aplicación // Manejo de cierre forzado del servidor (graceful shutdown)
const app = createApp(); const serverStop = (server: http.Server) => {
const forceTimeout = 30000;
app.listen(PORT, () => { return new Promise<void>((resolve, reject) => {
console.log(`Servidor escuchando en http://localhost:${PORT}`); 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<any>) => {
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 <CTRL> + C at any time");
logger.info(`⚡️ Server: http://${currentState.host}:${currentState.port}`);
});
} catch (error) {
serverError(error as NodeJS.ErrnoException);
}
})(); })();

View File

@ -8,13 +8,6 @@ export const v1Routes = () => {
res.send("Hello world!"); res.send("Hello world!");
}); });
routes.use((req, res, next) => {
console.log(
`[${new Date().toLocaleTimeString()}] Incoming request ${req.method} to ${req.path}`
);
next();
});
authRouter(routes); authRouter(routes);
return routes; return routes;

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,12 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES6", "target": "ES2022",
"module": "CommonJS", "module": "CommonJS",
"outDir": "./dist", "outDir": "./dist",
"sourceMap": true,
"strict": true, "strict": true,
"pretty": true,
"removeComments": true /* Do not emit comments to output. */,
"esModuleInterop": true, "esModuleInterop": true,
"skipLibCheck": true, "skipLibCheck": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,