From 67ce4abf78ecaeffb4ecebc09a614cd1d3eeaa24 Mon Sep 17 00:00:00 2001 From: sergeyyarkov Date: Tue, 24 Oct 2023 23:29:57 +0300 Subject: [PATCH] progress --- app/index.js | 21 +++- config/modbus-client.config.js | 4 +- data.db | Bin 12288 -> 12288 bytes middlewares/error-handler.middleware.js | 20 ++++ middlewares/index.js | 1 + package-lock.json | 147 ++++++++++++++++++++++++ package.json | 1 + public/js/api.js | 2 +- public/js/app.js | 2 +- routes/api.router.js | 2 +- 10 files changed, 193 insertions(+), 7 deletions(-) create mode 100644 middlewares/error-handler.middleware.js diff --git a/app/index.js b/app/index.js index 79ed823..b118fb4 100644 --- a/app/index.js +++ b/app/index.js @@ -4,13 +4,30 @@ import pino from "pino-http"; /** * Routers */ -import { apiRouter } from "../routes/api.router.js"; +import { apiRouter } from "#root/routes/api.router.js"; + +/** + * Middlewares + */ +import { errorHandlerMiddleware } from "#root/middlewares/index.js"; const app = express(); -app.use(pino()); +app.use( + pino( + process.env.NODE_ENV === "development" && { + transport: { + target: "pino-pretty", + options: { + colorize: true, + }, + }, + }, + ), +); app.use(express.urlencoded({ extended: true })); app.use(express.static("public")); app.use("/api", apiRouter); +app.use(errorHandlerMiddleware()); export default app; diff --git a/config/modbus-client.config.js b/config/modbus-client.config.js index daacd91..b92ee82 100644 --- a/config/modbus-client.config.js +++ b/config/modbus-client.config.js @@ -1,7 +1,7 @@ -import Modbus from 'modbus-serial'; +import Modbus from "modbus-serial"; const modbusClient = new Modbus(); -modbusClient.on('close', () => console.log('Modbus connection closed.')); +modbusClient.on("close", () => console.log("Modbus connection closed.")); export default modbusClient; diff --git a/data.db b/data.db index 194889d9ad052131cd8c5a42e334c70392ecec74..ea1148a1a32d51c3bc5c2392f76a8e953495c469 100644 GIT binary patch delta 66 zcmZojXh@hK#l)yJQN{^KZcJFl&vJu-|HfuPg>(G!Y7E>A!s<-COrngOOd-wzhL%Qp VhGrIe26~1D28`b}f0ySJ001oJ5C8xG delta 52 zcmZojXh@hK#l-M$qKp%e+?cS8pXCYz|CP;x3a9uvv>3PfuCqIxEXGzY_HQfAN Ho>Kq-$IlQY diff --git a/middlewares/error-handler.middleware.js b/middlewares/error-handler.middleware.js new file mode 100644 index 0000000..ba7e75d --- /dev/null +++ b/middlewares/error-handler.middleware.js @@ -0,0 +1,20 @@ +export function errorHandlerMiddleware() { + /** + * @param {any} error + * @param {import('express').Request} req + * @param {import('express').Response} res + * @param {import('express').NextFunction} next + */ + return (error, req, res, next) => { + req.log.error(error, "Something went wrong"); + const status = error.statusCode || 500; + const message = error.message || "Internal Server Error"; + res.status(500).json({ + error: { + status, + message, + stack: process.env.NODE_ENV === "development" ? error.stack : {}, + }, + }); + }; +} diff --git a/middlewares/index.js b/middlewares/index.js index c1257d8..88a1752 100644 --- a/middlewares/index.js +++ b/middlewares/index.js @@ -1 +1,2 @@ export * from "./validate-body.middleware.js"; +export * from "./error-handler.middleware.js"; diff --git a/package-lock.json b/package-lock.json index b06b456..d90c88a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -547,6 +547,12 @@ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, "commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -592,6 +598,12 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, + "dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -682,6 +694,15 @@ } } }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, "env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -752,6 +773,12 @@ "vary": "~1.1.2" } }, + "fast-copy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", + "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==", + "dev": true + }, "fast-glob": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", @@ -781,6 +808,12 @@ "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==" }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, "fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -963,6 +996,49 @@ "function-bind": "^1.1.2" } }, + "help-me": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", + "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", + "dev": true, + "requires": { + "glob": "^8.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", @@ -1166,6 +1242,12 @@ "integrity": "sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==", "dev": true }, + "joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true + }, "lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -1293,6 +1375,12 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, "minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -1749,6 +1837,43 @@ "process-warning": "^2.0.0" } }, + "pino-pretty": { + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.2.3.tgz", + "integrity": "sha512-4jfIUc8TC1GPUfDyMSlW1STeORqkoxec71yhxIpLDQapUu8WOuoz2TTCoidrIssyz78LZC69whBMPIKCMbi3cw==", + "dev": true, + "requires": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.0", + "fast-safe-stringify": "^2.1.1", + "help-me": "^4.0.1", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "dev": true, + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + } + } + }, "pino-std-serializers": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", @@ -1872,6 +1997,16 @@ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -1995,6 +2130,12 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "dev": true + }, "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -2259,6 +2400,12 @@ "ansi-regex": "^5.0.1" } }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "sucrase": { "version": "3.34.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", diff --git a/package.json b/package.json index 89b9cbb..4f49d03 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ }, "devDependencies": { "nodemon": "^3.0.1", + "pino-pretty": "^10.2.3", "tailwindcss": "^3.3.3" }, "imports": { diff --git a/public/js/api.js b/public/js/api.js index ea1ef7a..47b5148 100644 --- a/public/js/api.js +++ b/public/js/api.js @@ -6,7 +6,7 @@ const urlPrefix = "/api"; */ async function handle(response) { const data = await response.json(); - if (!response.ok) return Promise.reject((data && data.message) || response.statusText); + if (!response.ok) return Promise.reject(data.error || response.statusText); return data; } diff --git a/public/js/app.js b/public/js/app.js index 6523735..153a535 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -88,7 +88,7 @@ document.addEventListener("alpine:init", async () => { await api.post("/modbus/connect"); this.$store.app.currentPage = "monitoring"; } catch (error) { - this.errorMessage = "Modbus connection error."; + this.errorMessage = `Modbus connection error: ${error.message}`; } } diff --git a/routes/api.router.js b/routes/api.router.js index 4eb4bf4..56d7fa5 100644 --- a/routes/api.router.js +++ b/routes/api.router.js @@ -88,7 +88,7 @@ apiRouter.get("/app/is_configured", async (req, res, next) => { const config = await appService.getConfig(db); let is_configured = false; - if (!config) return res.status(200).json({ is_configured }); + if (!config) return res.status(200).json({ is_configured: false }); const isValuesExists = (colPrefix) => { const keys = Object.keys(config).filter((k) => k.includes(colPrefix));