From 25f0ab2a2905e1895162c33bfb54732e526027b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Sun, 28 Jan 2024 14:52:59 +0000 Subject: [PATCH] refactor!: Major rewrite, switching to ECMAScript instead of CJS. Implements #942 --- .eslintrc.yml | 17 +- package-lock.json | 823 ++++++------------ package.json | 17 +- src/api/api.js | 4 +- src/api/base_conversion.js | 9 +- src/api/butler_ping.js | 4 +- src/api/disk_utils.js | 18 +- src/api/key_value_store.js | 24 +- src/api/mqtt_publish_message.js | 4 +- src/api/newrelic_event.js | 4 +- src/api/newrelic_metric.js | 4 +- src/api/scheduler.js | 27 +- src/api/sense_app.js | 4 +- src/api/sense_app_dump.js | 9 +- src/api/sense_list_apps.js | 9 +- src/api/sense_start_task.js | 4 +- src/api/slack_post_message.js | 4 +- src/app.js | 85 +- src/butler.js | 29 +- src/docker-healthcheck.js | 2 +- src/globals.js | 51 +- src/jest.config.js | 2 +- src/lib/assert/assert_config_file.js | 21 +- src/lib/config_util.js | 11 +- src/lib/disk_utils.js | 10 +- src/lib/heartbeat.js | 8 +- src/lib/incident_mgmt/new_relic.js | 30 +- .../new_relic_service_monitor.js | 9 +- src/lib/incident_mgmt/signl4.js | 24 +- src/lib/key_value_store.js | 25 +- src/lib/log_rest_call.js | 6 +- src/lib/mqtt_handlers.js | 29 +- src/lib/msteams_notification.js | 22 +- src/lib/post_to_influxdb.js | 25 +- src/lib/post_to_new_relic.js | 16 +- src/lib/scheduler.js | 57 +- src/lib/scriptlog.js | 59 +- src/lib/service_monitor.js | 56 +- src/lib/service_uptime.js | 21 +- src/lib/slack_api.js | 6 +- src/lib/slack_notification.js | 28 +- src/lib/smtp.js | 52 +- src/lib/telemetry.js | 10 +- src/lib/testemail.js | 8 +- src/lib/winsvc.js | 21 +- src/plugins/sensible.js | 6 +- src/plugins/support.js | 4 +- src/qrs_util/app_tag_util.js | 11 +- src/qrs_util/does_task_exist.js | 8 +- src/qrs_util/get_app_owner.js | 8 +- src/qrs_util/get_tasks.js | 8 +- src/qrs_util/index.js | 8 - src/qrs_util/sense_start_task.js | 9 +- src/qrs_util/task_cp_util.js | 19 +- src/qrs_util/task_tag_util.js | 11 +- src/routes/api.js | 11 +- src/routes/base_conversion.js | 13 +- src/routes/butler_ping.js | 11 +- src/routes/disk_utils.js | 21 +- src/routes/key_value_store.js | 23 +- src/routes/mqtt_publish_message.js | 11 +- src/routes/newrelic_event.js | 13 +- src/routes/newrelic_metric.js | 13 +- src/routes/scheduler.js | 67 +- src/routes/sense_app.js | 30 +- src/routes/sense_app_dump.js | 23 +- src/routes/sense_list_apps.js | 22 +- src/routes/sense_start_task.js | 35 +- src/routes/slack_post_message.js | 15 +- src/test/env.js | 12 + src/test/routes/api.test.js | 8 +- src/test/routes/baseconversion.test.js | 9 +- src/test/routes/butlerping.test.js | 11 +- src/test/routes/disk_utils.test.js | 14 +- src/test/routes/keyvaluestore.test.js | 8 +- src/test/routes/mqttpublishmessage.test.js | 8 +- src/test/routes/scheduler.test.js | 55 +- src/test/routes/senseapp.test.js | 13 +- ...nsestarttask_start-task-filter_off.test.js | 12 +- ...ensestarttask_start-task-filter_on.test.js | 17 +- src/test/routes/slackpostmessage.test.js | 8 +- src/udp/index.js | 4 - src/udp/udp_handlers.js | 80 +- src/udp_client/udp_client.js | 4 +- 84 files changed, 971 insertions(+), 1400 deletions(-) delete mode 100644 src/qrs_util/index.js create mode 100644 src/test/env.js delete mode 100644 src/udp/index.js diff --git a/.eslintrc.yml b/.eslintrc.yml index 0f3f5768..e5f9d889 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,17 +1,28 @@ env: - es6: true - es2021: true + # es6: true + es2023: true node: true + # commonjs: false extends: - airbnb-base + # - eslint:recommended - prettier parserOptions: - ecmaVersion: 12 + ecmaVersion: 2023 sourceType: module + requireConfigFile: false + babelOptions: + plugins: + - '@babel/plugin-syntax-import-assertions' +parser: '@babel/eslint-parser' rules: prettier/prettier: error + import/no-unresolved: 2 + import/no-commonjs: 2 + import/extensions: [2, "ignorePackages"] plugins: - prettier + - import globals: beforeAll: readonly afterAll: readonly diff --git a/package-lock.json b/package-lock.json index c66e6ccc..01490347 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,6 @@ "eslint": "^8.55.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.29.0", "eslint-plugin-prettier": "^5.0.1", "express-handlebars": "^7.0.7", "fastify": "^4.24.3", @@ -68,6 +67,9 @@ "xstate": "^4.38.3" }, "devDependencies": { + "@babel/eslint-parser": "^7.23.9", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "eslint-plugin-import": "^2.29.1", "jest": "^29.7.0", "prettier": "^3.1.1", "snyk": "^1.1260.0" @@ -95,12 +97,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -179,31 +181,31 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", - "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.20.tgz", - "integrity": "sha512-Y6jd1ahLubuYweD/zJH+vvOY141v4f9igNQAQ+MBgq9JlHS2iTsZKn1aMsb3vGccZsXI16VzTBw52Xx0DWmtnA==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.22.15", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.22.20", - "@babel/helpers": "^7.22.15", - "@babel/parser": "^7.22.16", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.20", - "@babel/types": "^7.22.19", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", @@ -217,19 +219,40 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "node_modules/@babel/eslint-parser": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.23.9.tgz", + "integrity": "sha512-xPndlO7qxiJbn0ATvfXQBjCS7qApc9xmKHArgI/FTEFxXas5dnjC/VqM37lfZun9dclRYcn+YQAr6uDFy0bB2g==", + "dev": true, + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -239,14 +262,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -301,9 +324,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.20.tgz", - "integrity": "sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -353,9 +376,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -371,32 +394,32 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz", - "integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", "dev": true, "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -479,9 +502,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -526,6 +549,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -551,9 +589,9 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -653,9 +691,9 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -679,34 +717,34 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -723,12 +761,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -768,231 +806,6 @@ "kuler": "^2.0.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.9.tgz", - "integrity": "sha512-jkYjjq7SdsWuNI6b5quymW0oC83NN5FdRPuCbs9HZ02mfVdAP8B8eeqLSYU3gb6OJEaY5CQabtTFbqBf26H3GA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.9.tgz", - "integrity": "sha512-q4cR+6ZD0938R19MyEW3jEsMzbb/1rulLXiNAJQADD/XYp7pT+rOS5JGxvpRW8dFDEfjW4wLgC/3FXIw4zYglQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.9.tgz", - "integrity": "sha512-KOqoPntWAH6ZxDwx1D6mRntIgZh9KodzgNOy5Ebt9ghzffOk9X2c1sPwtM9P+0eXbefnDhqYfkh5PLP5ULtWFA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.9.tgz", - "integrity": "sha512-KBJ9S0AFyLVx2E5D8W0vExqRW01WqRtczUZ8NRu+Pi+87opZn5tL4Y0xT0mA4FtHctd0ZgwNoN639fUUGlNIWw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.9.tgz", - "integrity": "sha512-vE0VotmNTQaTdX0Q9dOHmMTao6ObjyPm58CHZr1UK7qpNleQyxlFlNCaHsHx6Uqv86VgPmR4o2wdNq3dP1qyDQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.9.tgz", - "integrity": "sha512-uFQyd/o1IjiEk3rUHSwUKkqZwqdvuD8GevWF065eqgYfexcVkxh+IJgwTaGZVu59XczZGcN/YMh9uF1fWD8j1g==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.9.tgz", - "integrity": "sha512-WMLgWAtkdTbTu1AWacY7uoj/YtHthgqrqhf1OaEWnZb7PQgpt8eaA/F3LkV0E6K/Lc0cUr/uaVP/49iE4M4asA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.9.tgz", - "integrity": "sha512-C/ChPohUYoyUaqn1h17m/6yt6OB14hbXvT8EgM1ZWaiiTYz7nWZR0SYmMnB5BzQA4GXl3BgBO1l8MYqL/He3qw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.9.tgz", - "integrity": "sha512-PiPblfe1BjK7WDAKR1Cr9O7VVPqVNpwFcPWgfn4xu0eMemzRp442hXyzF/fSwgrufI66FpHOEJk0yYdPInsmyQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.9.tgz", - "integrity": "sha512-f37i/0zE0MjDxijkPSQw1CO/7C27Eojqb+r3BbHVxMLkj8GCa78TrBZzvPyA/FNLUMzP3eyHCVkAopkKVja+6Q==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.9.tgz", - "integrity": "sha512-t6mN147pUIf3t6wUt3FeumoOTPfmv9Cc6DQlsVBpB7eCpLOqQDyWBP1ymXn1lDw4fNUSb/gBcKAmvTP49oIkaA==", - "cpu": [ - "loong64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.9.tgz", - "integrity": "sha512-jg9fujJTNTQBuDXdmAg1eeJUL4Jds7BklOTkkH80ZgQIoCTdQrDaHYgbFZyeTq8zbY+axgptncko3v9p5hLZtw==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.9.tgz", - "integrity": "sha512-tkV0xUX0pUUgY4ha7z5BbDS85uI7ABw3V1d0RNTii7E9lbmV8Z37Pup2tsLV46SQWzjOeyDi1Q7Wx2+QM8WaCQ==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.9.tgz", - "integrity": "sha512-DfLp8dj91cufgPZDXr9p3FoR++m3ZJ6uIXsXrIvJdOjXVREtXuQCjfMfvmc3LScAVmLjcfloyVtpn43D56JFHg==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.9.tgz", - "integrity": "sha512-zHbglfEdC88KMgCWpOl/zc6dDYJvWGLiUtmPRsr1OgCViu3z5GncvNVdf+6/56O2Ca8jUU+t1BW261V6kp8qdw==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/linux-x64": { "version": "0.19.9", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.9.tgz", @@ -1008,96 +821,6 @@ "node": ">=12" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.9.tgz", - "integrity": "sha512-GThgZPAwOBOsheA2RUlW5UeroRfESwMq/guy8uEe3wJlAOjpOXuSevLRd70NZ37ZrpO6RHGHgEHvPg1h3S1Jug==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.9.tgz", - "integrity": "sha512-Ki6PlzppaFVbLnD8PtlVQfsYw4S9n3eQl87cqgeIw+O3sRr9IghpfSKY62mggdt1yCSZ8QWvTZ9jo9fjDSg9uw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.9.tgz", - "integrity": "sha512-MLHj7k9hWh4y1ddkBpvRj2b9NCBhfgBt3VpWbHQnXRedVun/hC7sIyTGDGTfsGuXo4ebik2+3ShjcPbhtFwWDw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.9.tgz", - "integrity": "sha512-GQoa6OrQ8G08guMFgeXPH7yE/8Dt0IfOGWJSfSH4uafwdC7rWwrfE6P9N8AtPGIjUzdo2+7bN8Xo3qC578olhg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.9.tgz", - "integrity": "sha512-UOozV7Ntykvr5tSOlGCrqU3NBr3d8JqPes0QWN2WOXfvkWVGRajC+Ym0/Wj88fUgecUCLDdJPDF0Nna2UK3Qtg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.9.tgz", - "integrity": "sha512-oxoQgglOP7RH6iasDrhY+R/3cHrfwIDvRlT4CGChflq6twk8iENeVvMJjmvBb94Ik1Z+93iGO27err7w6l54GQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -1885,9 +1608,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1913,6 +1636,37 @@ "node": ">=8" } }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1974,79 +1728,63 @@ } }, "node_modules/@sentry-internal/tracing": { - "version": "7.64.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.64.0.tgz", - "integrity": "sha512-1XE8W6ki7hHyBvX9hfirnGkKDBKNq3bDJyXS86E0bYVDl94nvbRM9BD9DHsCFetqYkVm1yDGEK+6aUVs4CztoQ==", + "version": "7.98.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.98.0.tgz", + "integrity": "sha512-FnhD2uMLIAJvv4XsYPv3qsTTtxrImyLxiZacudJyaWFhxoeVQ8bKKbWJ/Ar68FAwqTtjXMeY5evnEBbRMcQlaA==", "dev": true, "dependencies": { - "@sentry/core": "7.64.0", - "@sentry/types": "7.64.0", - "@sentry/utils": "7.64.0", - "tslib": "^2.4.1 || ^1.9.3" + "@sentry/core": "7.98.0", + "@sentry/types": "7.98.0", + "@sentry/utils": "7.98.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/core": { - "version": "7.64.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.64.0.tgz", - "integrity": "sha512-IzmEyl5sNG7NyEFiyFHEHC+sizsZp9MEw1+RJRLX6U5RITvcsEgcajSkHQFafaBPzRrcxZMdm47Cwhl212LXcw==", + "version": "7.98.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.98.0.tgz", + "integrity": "sha512-baRUcpCNGyk7cApQHMfqEZJkXdvAKK+z/dVWiMqWc5T5uhzMnPE8/gjP1JZsMtJSQ8g5nHimBdI5TwOyZtxPaA==", "dev": true, "dependencies": { - "@sentry/types": "7.64.0", - "@sentry/utils": "7.64.0", - "tslib": "^2.4.1 || ^1.9.3" + "@sentry/types": "7.98.0", + "@sentry/utils": "7.98.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/node": { - "version": "7.64.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.64.0.tgz", - "integrity": "sha512-wRi0uTnp1WSa83X2yLD49tV9QPzGh5e42IKdIDBiQ7lV9JhLILlyb34BZY1pq6p4dp35yDasDrP3C7ubn7wo6A==", + "version": "7.98.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.98.0.tgz", + "integrity": "sha512-9cHW217DnU9wC4iR+QxmY3q59N1Touh23hPMDtpMRmbRHSgrmLMoHTVPhK9zHsXRs0mUeidmMqY1ubAWauQByw==", "dev": true, "dependencies": { - "@sentry-internal/tracing": "7.64.0", - "@sentry/core": "7.64.0", - "@sentry/types": "7.64.0", - "@sentry/utils": "7.64.0", - "cookie": "^0.4.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^2.4.1 || ^1.9.3" + "@sentry-internal/tracing": "7.98.0", + "@sentry/core": "7.98.0", + "@sentry/types": "7.98.0", + "@sentry/utils": "7.98.0" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry/node/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/@sentry/types": { - "version": "7.64.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.64.0.tgz", - "integrity": "sha512-LqjQprWXjUFRmzIlUjyA+KL+38elgIYmAeoDrdyNVh8MK5IC1W2Lh1Q87b4yOiZeMiIhIVNBd7Ecoh2rodGrGA==", + "version": "7.98.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.98.0.tgz", + "integrity": "sha512-pc034ziM0VTETue4bfBcBqTWGy4w0okidtoZJjGVrYAfE95ObZnUGVj/XYIQ3FeCYWIa7NFN2MvdsCS0buwivQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.64.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.64.0.tgz", - "integrity": "sha512-HRlM1INzK66Gt+F4vCItiwGKAng4gqzCR4C5marsL3qv6SrKH98dQnCGYgXluSWaaa56h97FRQu7TxCk6jkSvQ==", + "version": "7.98.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.98.0.tgz", + "integrity": "sha512-0/LY+kpHxItVRY0xPDXPXVsKRb95cXsGSQf8sVMtfSjz++0bLL1U4k7PFz1c5s2/Vk0B8hS6duRrgMv6dMIZDw==", "dev": true, "dependencies": { - "@sentry/types": "7.64.0", - "tslib": "^2.4.1 || ^1.9.3" + "@sentry/types": "7.98.0" }, "engines": { "node": ">=8" @@ -2059,9 +1797,9 @@ "dev": true }, "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" @@ -2077,9 +1815,9 @@ } }, "node_modules/@types/babel__core": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", - "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -2090,18 +1828,18 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.5", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", - "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", - "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -2109,42 +1847,42 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", - "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" } }, "node_modules/@types/graceful-fs": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", - "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" @@ -2175,9 +1913,9 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, "node_modules/@types/triple-beam": { @@ -2194,18 +1932,18 @@ } }, "node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, "node_modules/@ungap/structured-clone": { @@ -2253,18 +1991,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2740,9 +2466,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", "dev": true, "funding": [ { @@ -2759,10 +2485,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -2852,9 +2578,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001538", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz", - "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==", + "version": "1.0.30001581", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", + "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", "dev": true, "funding": [ { @@ -2896,9 +2622,9 @@ } }, "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { @@ -3514,9 +3240,9 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.4.526", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.526.tgz", - "integrity": "sha512-tjjTMjmZAx1g6COrintLTa2/jcafYKxKoiEkdQOrVdbLaHh2wCt2nsAF8ZHweezkrP+dl/VG9T5nabcYoo0U5Q==", + "version": "1.4.648", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz", + "integrity": "sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==", "dev": true }, "node_modules/email-validator": { @@ -3858,9 +3584,9 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", - "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dependencies": { "array-includes": "^3.1.7", "array.prototype.findlastindex": "^1.2.3", @@ -3878,7 +3604,7 @@ "object.groupby": "^1.0.1", "object.values": "^1.1.7", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -4977,19 +4703,6 @@ "node": ">= 0.8" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -5441,18 +5154,18 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", - "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", "dev": true, "dependencies": { "@babel/core": "^7.12.3", @@ -6414,12 +6127,6 @@ "triple-beam": "^1.3.0" } }, - "node_modules/lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "dev": true - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -6733,9 +6440,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/nodemailer": { @@ -7352,9 +7059,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", - "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", "dev": true, "funding": [ { @@ -7836,9 +7543,9 @@ } }, "node_modules/snyk": { - "version": "1.1260.0", - "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.1260.0.tgz", - "integrity": "sha512-LnUsIPkDprwo4Y9w9or1Y0zvBOIxVJbqSYmKm6+ehdmpmo9I/NuTyVj+iF+A4n+r6ljOCcD3WOPP/JA4uvo7gw==", + "version": "1.1275.0", + "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.1275.0.tgz", + "integrity": "sha512-BtlgoHSTqr0M3x5QpOuxxX3d9S6TY/PcL6gd56VSLmfyVtAVueWWce1+w+HdyGpleE/tkBD7neb9klxsUgGi0Q==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -7887,9 +7594,9 @@ } }, "node_modules/sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, "node_modules/stack-trace": { @@ -8254,9 +7961,9 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -8468,9 +8175,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.12.tgz", - "integrity": "sha512-tE1smlR58jxbFMtrMpFNRmsrOXlpNXss965T1CrpwuZUzUAg/TBQc94SpyhDLSzrqrJS9xTRBthnZAGcE1oaxg==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -8523,25 +8230,19 @@ } }, "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" + "convert-source-map": "^2.0.0" }, "engines": { "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 76f0e2e0..a7c2e628 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,19 @@ "version": "9.4.0", "description": "Superpowers for Qlik Sense. Task scheduling, key-value store, advanced alerting and more.", "scripts": { - "test": "jest", + "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js", "test2": "node_modules/jshint/bin/jshint butler.js", "format1": "npm run format", "format": "npm run format:prettier", "format:prettier": "npx prettier --config .prettierrc \"./**/*.{ts,css,less,js}\" --write", "butler": "node src/butler.js", - "lint": "npx eslint src/**/*.js" + "lint": "npx eslint ./src/**/*.js" + }, + "jest": { + "transform": {}, + "setupFiles": [ + "./src/test/env.js" + ] }, "repository": { "type": "git", @@ -36,7 +42,8 @@ "files": [ "butler.js" ], - "main": "butler.js", + "type": "module", + "exports": "./butler.js", "directories": { "lib": "lib", "test": "test" @@ -63,7 +70,6 @@ "eslint": "^8.55.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.29.0", "eslint-plugin-prettier": "^5.0.1", "express-handlebars": "^7.0.7", "fastify": "^4.24.3", @@ -101,6 +107,9 @@ "xstate": "^4.38.3" }, "devDependencies": { + "@babel/eslint-parser": "^7.23.9", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "eslint-plugin-import": "^2.29.1", "jest": "^29.7.0", "prettier": "^3.1.1", "snyk": "^1.1260.0" diff --git a/src/api/api.js b/src/api/api.js index 186c1246..75ec3257 100644 --- a/src/api/api.js +++ b/src/api/api.js @@ -16,6 +16,4 @@ const apiGetAPIEndpointsEnabled = { }, }; -module.exports = { - apiGetAPIEndpointsEnabled, -}; +export default apiGetAPIEndpointsEnabled; diff --git a/src/api/base_conversion.js b/src/api/base_conversion.js index 4e5f3e93..9ebcdb52 100644 --- a/src/api/base_conversion.js +++ b/src/api/base_conversion.js @@ -1,4 +1,4 @@ -const apiGetBase62ToBase16 = { +export const apiGetBase62ToBase16 = { schema: { description: 'Converts strings from base62 to base16.', summary: 'Converts strings from base62 to base16.', @@ -55,7 +55,7 @@ const apiGetBase62ToBase16 = { }, }; -const apiGetBase16ToBase62 = { +export const apiGetBase16ToBase62 = { schema: { description: 'Converts strings from base16 to base62.', summary: 'Converts strings from base16 to base62.', @@ -116,8 +116,3 @@ const apiGetBase16ToBase62 = { }, }, }; - -module.exports = { - apiGetBase62ToBase16, - apiGetBase16ToBase62, -}; diff --git a/src/api/butler_ping.js b/src/api/butler_ping.js index 69561168..4e98bbc4 100644 --- a/src/api/butler_ping.js +++ b/src/api/butler_ping.js @@ -26,6 +26,4 @@ const apiGetButlerPing = { }, }; -module.exports = { - apiGetButlerPing, -}; +export default apiGetButlerPing; diff --git a/src/api/disk_utils.js b/src/api/disk_utils.js index 60b1f584..a9b46eea 100644 --- a/src/api/disk_utils.js +++ b/src/api/disk_utils.js @@ -1,4 +1,4 @@ -const apiFileCopy = { +export const apiFileCopy = { schema: { description: "Copying of files is only posttible between pre-approved directories.\nDefining approved source and destination directories is done in Butler's config file.\n\nIf the source directory contains subdirectories, these will be copied too.", @@ -97,7 +97,7 @@ const apiFileCopy = { }, }; -const apiFileMove = { +export const apiFileMove = { schema: { description: "Moving of files is only posttible between pre-approved directories.\nDefining approved source and destination directories is done in Butler's config file.\n\nIf the source directory contains subdirectories, these will be moved too.", @@ -181,7 +181,7 @@ const apiFileMove = { }, }; -const apiFileDelete = { +export const apiFileDelete = { schema: { description: "It is only possible to delete files in pre-approved directories, or subdirectories thereof.\nDefining approved directories is done in Butler's config file.", @@ -239,7 +239,7 @@ const apiFileDelete = { }, }; -const apiCreateDir = { +export const apiCreateDir = { schema: { description: "If the directory already exists nothing will happen.\nIf permissions don't allow a directory to be created, or if the path is invalid, an error will be returned.", @@ -292,7 +292,7 @@ const apiCreateDir = { }, }; -const apiCreateDirQvd = { +export const apiCreateDirQvd = { schema: { description: "Creates a directory in QVD directory (which is defined in Butler's config file).", summary: 'Creates a directory in designated QVD directory.', @@ -343,11 +343,3 @@ const apiCreateDirQvd = { }, }, }; - -module.exports = { - apiFileCopy, - apiFileMove, - apiFileDelete, - apiCreateDir, - apiCreateDirQvd, -}; diff --git a/src/api/key_value_store.js b/src/api/key_value_store.js index 87852e17..d8e9c2a3 100644 --- a/src/api/key_value_store.js +++ b/src/api/key_value_store.js @@ -1,4 +1,4 @@ -const apiGetAllNamespaces = { +export const apiGetAllNamespaces = { schema: { description: '', summary: 'List all currently defined namespaces.', @@ -26,7 +26,7 @@ const apiGetAllNamespaces = { }, }; -const apiGetKVPair = { +export const apiGetKVPair = { schema: { description: '', summary: 'Get the value associated with a key, in a specific namespace.', @@ -99,7 +99,7 @@ const apiGetKVPair = { }, }; -const apiGetKVExists = { +export const apiGetKVExists = { schema: { description: 'Returns true if the specified key exists, otherwise false.', summary: 'Checks if a key exists in a namespace.', @@ -181,7 +181,7 @@ const apiGetKVExists = { }, }; -const apiPostKVPair = { +export const apiPostKVPair = { schema: { description: 'If the specified key already exists it will be overwritten.\n\nIf the posted data has a TTL, it will start counting when the post occur.\nI.e. if a previouly posted key also had a TTL, it will be replace with the most recent TTL.', @@ -270,7 +270,7 @@ const apiPostKVPair = { }, }; -const apiDeleteKVPair = { +export const apiDeleteKVPair = { schema: { description: '', summary: 'Delete a key-value pair in a specific namespace.', @@ -322,7 +322,7 @@ const apiDeleteKVPair = { }, }; -const apiDeleteNamespace = { +export const apiDeleteNamespace = { schema: { description: '', summary: 'Delete a namespace and all key-value pairs in it.', @@ -368,7 +368,7 @@ const apiDeleteNamespace = { }, }; -const apiGetKeysInNamespace = { +export const apiGetKeysInNamespace = { schema: { description: '', summary: 'Retrieve a list of all keys present in the specified namespace.', @@ -438,13 +438,3 @@ const apiGetKeysInNamespace = { }, }, }; - -module.exports = { - apiGetAllNamespaces, - apiGetKVPair, - apiGetKVExists, - apiPostKVPair, - apiDeleteKVPair, - apiDeleteNamespace, - apiGetKeysInNamespace, -}; diff --git a/src/api/mqtt_publish_message.js b/src/api/mqtt_publish_message.js index b95c67aa..8d4efcf5 100644 --- a/src/api/mqtt_publish_message.js +++ b/src/api/mqtt_publish_message.js @@ -54,6 +54,4 @@ const apiPutMqttMessage = { }, }; -module.exports = { - apiPutMqttMessage, -}; +export default apiPutMqttMessage; diff --git a/src/api/newrelic_event.js b/src/api/newrelic_event.js index 6ce5eabd..55ac0669 100644 --- a/src/api/newrelic_event.js +++ b/src/api/newrelic_event.js @@ -74,6 +74,4 @@ const apiPostNewRelicEvent = { }, }; -module.exports = { - apiPostNewRelicEvent, -}; +export default apiPostNewRelicEvent; diff --git a/src/api/newrelic_metric.js b/src/api/newrelic_metric.js index 1331dd81..9de37744 100644 --- a/src/api/newrelic_metric.js +++ b/src/api/newrelic_metric.js @@ -88,6 +88,4 @@ const apiPostNewRelicMetric = { }, }; -module.exports = { - apiPostNewRelicMetric, -}; +export default apiPostNewRelicMetric; diff --git a/src/api/scheduler.js b/src/api/scheduler.js index 7440a870..f5336e83 100644 --- a/src/api/scheduler.js +++ b/src/api/scheduler.js @@ -1,4 +1,4 @@ -const apiGETSchedules = { +export const apiGETSchedules = { schema: { summary: 'Get all information available for existing schedule(s).', description: @@ -101,7 +101,7 @@ const apiGETSchedules = { }, }; -const apiPOSTSchedules = { +export const apiPOSTSchedules = { schema: { summary: 'Create a new schedule.', description: '', @@ -224,7 +224,7 @@ const apiPOSTSchedules = { }, }; -const apiDELETESchedules = { +export const apiDELETESchedules = { schema: { summary: 'Delete a schedule.', description: '', @@ -270,7 +270,7 @@ const apiDELETESchedules = { }, }; -const apiPUTSchedulesStart = { +export const apiPUTSchedulesStart = { schema: { summary: 'Start a schedule.', description: "Start a schedule, i.e. have the scheduler run the associated reload task according to the schedule's cron settings.", @@ -369,7 +369,7 @@ const apiPUTSchedulesStart = { }, }; -const apiPUTSchedulesStop = { +export const apiPUTSchedulesStop = { schema: { summary: 'Stop a schedule.', description: 'Stop a schedule, i.e. tell the scheduler to no longer execute the schedule according to its cron settings.', @@ -468,7 +468,7 @@ const apiPUTSchedulesStop = { }, }; -const apiPUTSchedulesStartAll = { +export const apiPUTSchedulesStartAll = { schema: { summary: 'Start all schedules.', description: @@ -544,7 +544,7 @@ const apiPUTSchedulesStartAll = { }, }; -const apiPUTSchedulesStopAll = { +export const apiPUTSchedulesStopAll = { schema: { summary: 'Stop all schedules.', description: 'Stop all schedules, i.e. tell the scheduler to no longer execute any schedule according to its cron settings.', @@ -619,7 +619,7 @@ const apiPUTSchedulesStopAll = { }, }; -const apiGETSchedulerStatus = { +export const apiGETSchedulerStatus = { schema: { summary: 'Get scheduler status.', description: @@ -647,14 +647,3 @@ const apiGETSchedulerStatus = { }, }, }; - -module.exports = { - apiGETSchedules, - apiPOSTSchedules, - apiDELETESchedules, - apiPUTSchedulesStart, - apiPUTSchedulesStartAll, - apiPUTSchedulesStop, - apiPUTSchedulesStopAll, - apiGETSchedulerStatus, -}; diff --git a/src/api/sense_app.js b/src/api/sense_app.js index 45948284..5e4ee3cc 100644 --- a/src/api/sense_app.js +++ b/src/api/sense_app.js @@ -80,6 +80,4 @@ const apiPutAppReload = { }, }; -module.exports = { - apiPutAppReload, -}; +export default apiPutAppReload; diff --git a/src/api/sense_app_dump.js b/src/api/sense_app_dump.js index df916162..481793a7 100644 --- a/src/api/sense_app_dump.js +++ b/src/api/sense_app_dump.js @@ -1,4 +1,4 @@ -const apiGetSenseAppDump = { +export const apiGetSenseAppDump = { schema: { summary: 'Dump a Sense app to JSON.', description: 'Does the same thing as `/v4/app/:appId/dump`', @@ -72,7 +72,7 @@ const apiGetSenseAppDump = { }, }; -const apiGetAppDump = { +export const apiGetAppDump = { schema: { summary: 'Dump a Sense app to JSON.', description: 'Does the same thing as `/v4/senseappdump/:appId`', @@ -145,8 +145,3 @@ const apiGetAppDump = { }, }, }; - -module.exports = { - apiGetSenseAppDump, - apiGetAppDump, -}; diff --git a/src/api/sense_list_apps.js b/src/api/sense_list_apps.js index 80148ada..3478eb08 100644 --- a/src/api/sense_list_apps.js +++ b/src/api/sense_list_apps.js @@ -1,4 +1,4 @@ -const apiGetSenseListApps = { +export const apiGetSenseListApps = { schema: { summary: 'Get a list of all apps in Sense environment.', description: 'Does the same thing as `/v4/apps/list`', @@ -37,7 +37,7 @@ const apiGetSenseListApps = { }, }; -const apiGetAppsList = { +export const apiGetAppsList = { schema: { summary: 'Get a list of all apps in Sense environment.', description: 'Does the same thing as `/v4/senselistapps`', @@ -75,8 +75,3 @@ const apiGetAppsList = { }, }, }; - -module.exports = { - apiGetSenseListApps, - apiGetAppsList, -}; diff --git a/src/api/sense_start_task.js b/src/api/sense_start_task.js index f4aeeb61..ea577978 100644 --- a/src/api/sense_start_task.js +++ b/src/api/sense_start_task.js @@ -145,6 +145,4 @@ const apiPutStartTask = { }, }; -module.exports = { - apiPutStartTask, -}; +export default apiPutStartTask; diff --git a/src/api/slack_post_message.js b/src/api/slack_post_message.js index 58b3590b..2d538bf4 100644 --- a/src/api/slack_post_message.js +++ b/src/api/slack_post_message.js @@ -82,6 +82,4 @@ const apiPutSlackPostMessage = { }, }; -module.exports = { - apiPutSlackPostMessage, -}; +export default apiPutSlackPostMessage; diff --git a/src/app.js b/src/app.js index 4e9948e0..bc4c7851 100644 --- a/src/app.js +++ b/src/app.js @@ -2,22 +2,23 @@ /* eslint-disable global-require */ // const Fastify = require('fastify'); -const path = require('path'); -const Fastify = require('fastify'); -const AutoLoad = require('@fastify/autoload'); -const FastifySwagger = require('@fastify/swagger'); -const FastifySwaggerUi = require('@fastify/swagger-ui'); -const FastifyReplyFrom = require('@fastify/reply-from'); -const FastifyHealthcheck = require('fastify-healthcheck'); -const FastifyRateLimit = require('@fastify/rate-limit'); - -const globals = require('./globals'); -const heartbeat = require('./lib/heartbeat'); -const scheduler = require('./lib/scheduler'); -const serviceUptime = require('./lib/service_uptime'); -const telemetry = require('./lib/telemetry'); -const configUtil = require('./lib/config_util'); -const { sendTestEmail } = require('./lib/testemail'); +import path from 'path'; +import { fileURLToPath } from 'url'; +import Fastify from 'fastify'; +// import AutoLoad from '@fastify/autoload'; +import FastifySwagger from '@fastify/swagger'; +import FastifySwaggerUi from '@fastify/swagger-ui'; +import FastifyReplyFrom from '@fastify/reply-from'; +import FastifyHealthcheck from 'fastify-healthcheck'; +import FastifyRateLimit from '@fastify/rate-limit'; + +import globals from './globals.js'; +import setupHeartbeatTimer from './lib/heartbeat.js'; +import { loadSchedulesFromDisk } from './lib/scheduler.js'; +import serviceUptimeStart from './lib/service_uptime.js'; +import setupAnonUsageReportTimer from './lib/telemetry.js'; +import { configVerifyAllTaskId } from './lib/config_util.js'; +import sendTestEmail from './lib/testemail.js'; async function build(opts = {}) { // Create two Fastify servers. One server is a REST server and the other is a reverse proxy server. @@ -36,20 +37,22 @@ async function build(opts = {}) { (globals.config.has('Butler.uptimeMonitor.enabled') && globals.config.get('Butler.uptimeMonitor.enabled') === true) || (globals.config.has('Butler.uptimeMonitor.enable') && globals.config.get('Butler.uptimeMonitor.enable') === true) ) { - serviceUptime.serviceUptimeStart(); + serviceUptimeStart(); } // Load certificates to use when connecting to healthcheck API - const certFile = path.resolve(__dirname, globals.config.get('Butler.cert.clientCert')); - const keyFile = path.resolve(__dirname, globals.config.get('Butler.cert.clientCertKey')); - const caFile = path.resolve(__dirname, globals.config.get('Butler.cert.clientCertCA')); + const filename = fileURLToPath(import.meta.url); + const dirname = path.dirname(filename); + const certFile = path.resolve(dirname, globals.config.get('Butler.cert.clientCert')); + const keyFile = path.resolve(dirname, globals.config.get('Butler.cert.clientCertKey')); + const caFile = path.resolve(dirname, globals.config.get('Butler.cert.clientCertCA')); // Set up heartbeats, if enabled in the config file if ( (globals.config.has('Butler.heartbeat.enabled') && globals.config.get('Butler.heartbeat.enabled') === true) || (globals.config.has('Butler.heartbeat.enable') && globals.config.get('Butler.heartbeat.enable') === true) ) { - heartbeat.setupHeartbeatTimer(globals.config, globals.logger); + setupHeartbeatTimer(globals.config, globals.logger); } try { @@ -115,12 +118,12 @@ async function build(opts = {}) { (globals.config.has('Butler.anonTelemetry') === true && globals.config.get('Butler.anonTelemetry') === true) ) { // Set up the timer to send anonymous telemetry - telemetry.setupAnonUsageReportTimer(); + setupAnonUsageReportTimer(); globals.logger.verbose('MAIN: Anonymous telemetry reporting has been set up.'); } // Verify that select parts of config file are valid - configUtil.configVerifyAllTaskId(); + configVerifyAllTaskId(); // Show link to Swagger API docs page, if the API is enabled if (globals.config.has('Butler.restServerConfig.enable') && globals.config.get('Butler.restServerConfig.enable') === true) { @@ -166,8 +169,8 @@ async function build(opts = {}) { // This loads all plugins defined in plugins. // Those should be support plugins that are reused through your application - await restServer.register(require('./plugins/sensible'), { options: Object.assign({}, opts) }); - await restServer.register(require('./plugins/support'), { options: Object.assign({}, opts) }); + await restServer.register(import('./plugins/sensible.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./plugins/support.js'), { options: Object.assign({}, opts) }); await restServer.register(FastifySwagger, { mode: 'dynamic', @@ -204,20 +207,20 @@ async function build(opts = {}) { }); // Loads all plugins defined in routes - await restServer.register(require('./routes/api'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/base_conversion'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/butler_ping'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/disk_utils'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/key_value_store'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/mqtt_publish_message'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/newrelic_event'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/newrelic_metric'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/scheduler'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/sense_app'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/sense_app_dump'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/sense_list_apps'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/sense_start_task'), { options: Object.assign({}, opts) }); - await restServer.register(require('./routes/slack_post_message'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/api.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/base_conversion.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/butler_ping.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/disk_utils.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/key_value_store.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/mqtt_publish_message.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/newrelic_event.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/newrelic_metric.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/scheduler.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/sense_app.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/sense_app_dump.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/sense_list_apps.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/sense_start_task.js'), { options: Object.assign({}, opts) }); + await restServer.register(import('./routes/slack_post_message.js'), { options: Object.assign({}, opts) }); // --------------------------------------------------- // Configure X-HTTP-Method-Override handling @@ -284,7 +287,7 @@ async function build(opts = {}) { // Load already defined schedules if (globals.config.has('Butler.scheduler')) { if (globals.config.get('Butler.scheduler.enable') === true) { - scheduler.loadSchedulesFromDisk(); + loadSchedulesFromDisk(); // scheduler.launchAllSchedules(); } else { // eslint-disable-next-line quotes @@ -297,4 +300,4 @@ async function build(opts = {}) { return { restServer, proxyRestServer, dockerHealthCheckServer }; } -module.exports = build; +export default build; diff --git a/src/butler.js b/src/butler.js index 4aa6ca4d..c996a7d3 100644 --- a/src/butler.js +++ b/src/butler.js @@ -1,22 +1,29 @@ // Add dependencies -const mqtt = require('mqtt'); -const dgram = require('dgram'); +import mqtt from 'mqtt'; + +import dgram from 'dgram'; // Load code from sub modules -const globals = require('./globals'); -const serviceMonitor = require('./lib/service_monitor'); +import globals from './globals.js'; +import setupServiceMonitorTimer from './lib/service_monitor.js'; // The build function creates a new instance of the App class and returns it. -const build = require('./app'); -const udp = require('./udp'); -const { mqttInitHandlers } = require('./lib/mqtt_handlers'); +import build from './app.js'; + +import udpInitTaskErrorServer from './udp/udp_handlers.js'; +import mqttInitHandlers from './lib/mqtt_handlers.js'; + +// import configFileStructureAssert from './lib/assert/assert_config_file.js'; +// import configFileYamlAssert from './lib/assert/assert_config_file.js'; +// import configFileNewRelicAssert from './lib/assert/assert_config_file.js'; +// import configFileInfluxDbAssert from './lib/assert/assert_config_file.js'; -const { +import { configFileStructureAssert, configFileYamlAssert, configFileNewRelicAssert, configFileInfluxDbAssert, -} = require('./lib/assert/assert_config_file'); +} from './lib/assert/assert_config_file.js'; const start = async () => { // Verify correct structure of config file @@ -136,7 +143,7 @@ const start = async () => { // Set up service monitoring, if enabled in the config file if (globals.config.has('Butler.serviceMonitor.enable') && globals.config.get('Butler.serviceMonitor.enable') === true) { - serviceMonitor.setupServiceMonitorTimer(globals.config, globals.logger); + setupServiceMonitorTimer(globals.config, globals.logger); } // Prepare to listen on port Y for incoming UDP connections regarding failed tasks @@ -148,7 +155,7 @@ const start = async () => { // --------------------------------------------------- // Set up UDP handlers if (globals.config.get('Butler.udpServerConfig.enable')) { - udp.udp.udpInitTaskErrorServer(); + udpInitTaskErrorServer(); // Start UDP server for failed task events globals.udpServerReloadTaskSocket.bind(globals.udpPortTaskFailure, globals.udpHost); diff --git a/src/docker-healthcheck.js b/src/docker-healthcheck.js index b6d890d0..f2ff0eff 100644 --- a/src/docker-healthcheck.js +++ b/src/docker-healthcheck.js @@ -1,6 +1,6 @@ /* eslint-disable no-console */ // Set up REST endpoint for Docker healthchecks -const httpHealth = require('http'); +import httpHealth from 'http'; const optionsHealth = { host: 'localhost', diff --git a/src/globals.js b/src/globals.js index 36acce46..4d83bf58 100644 --- a/src/globals.js +++ b/src/globals.js @@ -1,17 +1,25 @@ -const os = require('os'); -const crypto = require('crypto'); -const fs = require('fs-extra'); -const upath = require('upath'); -const Influx = require('influx'); -const { IncomingWebhook } = require('ms-teams-webhook'); -const si = require('systeminformation'); -const isUncPath = require('is-unc-path'); -const winston = require('winston'); +import os from 'os'; +import crypto from 'crypto'; +import fs from 'fs-extra'; +import upath from 'upath'; +import Influx from 'influx'; +import { IncomingWebhook } from 'ms-teams-webhook'; +import si from 'systeminformation'; +import isUncPath from 'is-unc-path'; +import winston from 'winston'; +import { fileURLToPath } from 'url'; // Add dependencies -const { Command, Option } = require('commander'); +import { Command, Option } from 'commander'; -require('winston-daily-rotate-file'); +import 'winston-daily-rotate-file'; + +// Get app version from package.json file +// import { version as appVersion } from '../package.json'; +// import { version as appVersion } from '../package.json' assert { type: 'json' }; +const loadJSON = (path) => JSON.parse(fs.readFileSync(new URL(path, import.meta.url))); +const { version } = loadJSON('../package.json'); +const appVersion = version; // Variable holding info about all defined schedules const configSchedule = []; @@ -29,9 +37,6 @@ function checkFileExistsSync(filepath) { return flag; } -// Get app version from package.json file -const appVersion = require('../package.json').version; - // Command line parameters const program = new Command(); program @@ -92,7 +97,9 @@ if (options.configfile && options.configfile.length > 0) { const env = process.env.NODE_ENV; // Get path to config file - configFileExpanded = upath.resolve(__dirname, `./config/${env}.yaml`); + const filename = fileURLToPath(import.meta.url); + const dirname = upath.dirname(filename); + configFileExpanded = upath.resolve(dirname, `./config/${env}.yaml`); } // Are we running as standalone app or not? @@ -103,7 +110,7 @@ if (isPkg && configFileOption === undefined) { } // eslint-disable-next-line import/order -const config = require('config'); +import config from 'config'; // Are there New Relic account name(s), API key(s) and account ID(s) specified on the command line? // There must be the same number of each specified! @@ -216,9 +223,11 @@ logger.verbose( // Helper function to read the contents of the certificate files: const readCert = (filename) => fs.readFileSync(filename); -const certPath = upath.resolve(__dirname, config.get('Butler.cert.clientCert')); -const keyPath = upath.resolve(__dirname, config.get('Butler.cert.clientCertKey')); -const caPath = upath.resolve(__dirname, config.get('Butler.cert.clientCertCA')); +const filename = fileURLToPath(import.meta.url); +const dirname = upath.dirname(filename); +const certPath = upath.resolve(dirname, config.get('Butler.cert.clientCert')); +const keyPath = upath.resolve(dirname, config.get('Butler.cert.clientCertKey')); +const caPath = upath.resolve(dirname, config.get('Butler.cert.clientCertCA')); let configEngine; let configQRS; @@ -313,7 +322,7 @@ if ( // UDP server connection parameters const udpHost = config.get('Butler.udpServerConfig.serverHost'); -let udpServerReloadTaskSocket = null; +const udpServerReloadTaskSocket = null; // Prepare to listen on port Y for incoming UDP connections regarding failed tasks // const udpServerReloadTaskSocket = dgram.createSocket({ // type: 'udp4', @@ -627,7 +636,7 @@ function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } -module.exports = { +export default { config, configEngine, configFileExpanded, diff --git a/src/jest.config.js b/src/jest.config.js index 3e755aaf..116a1ad6 100644 --- a/src/jest.config.js +++ b/src/jest.config.js @@ -3,7 +3,7 @@ * https://jestjs.io/docs/configuration */ -module.exports = { +export default { // All imported modules in your tests should be mocked automatically // automock: false, diff --git a/src/lib/assert/assert_config_file.js b/src/lib/assert/assert_config_file.js index b724111a..db8ac16d 100644 --- a/src/lib/assert/assert_config_file.js +++ b/src/lib/assert/assert_config_file.js @@ -1,9 +1,9 @@ -const QrsInteract = require('qrs-interact'); -const yaml = require('js-yaml'); -const { getReloadTasksCustomProperties } = require('../../qrs_util/task_cp_util'); +import QrsInteract from 'qrs-interact'; +import yaml from 'js-yaml'; +import { getReloadTasksCustomProperties } from '../../qrs_util/task_cp_util.js'; // Veriify InfluxDb related settings in the config file -const configFileInfluxDbAssert = async (config, configQRS, logger) => { +export const configFileInfluxDbAssert = async (config, configQRS, logger) => { // Set up shared Sense repository service configuration const cfg = { hostname: config.get('Butler.configQRS.host'), @@ -83,7 +83,7 @@ const configFileInfluxDbAssert = async (config, configQRS, logger) => { /** * Verify New Relic settings in the config file */ -const configFileNewRelicAssert = async (config, configQRS, logger) => { +export const configFileNewRelicAssert = async (config, configQRS, logger) => { // Set up shared Sense repository service configuration const cfg = { hostname: config.get('Butler.configQRS.host'), @@ -486,7 +486,7 @@ const configFileNewRelicAssert = async (config, configQRS, logger) => { }; // Function to verify that config file is valid YAML -const configFileYamlAssert = async (configFile) => { +export const configFileYamlAssert = async (configFile) => { try { const data = await yaml.load(configFile); return true; @@ -497,7 +497,7 @@ const configFileYamlAssert = async (configFile) => { }; // Function to verify that config variable have same structure as production.yaml file -const configFileStructureAssert = async (config, logger) => { +export const configFileStructureAssert = async (config, logger) => { let configFileCorrect = true; if (!config.has('Butler.logLevel')) { logger.error('ASSERT CONFIG: Missing config file entry "Butler.logLevel"'); @@ -2387,10 +2387,3 @@ const configFileStructureAssert = async (config, logger) => { process.exit(1); } }; - -module.exports = { - configFileNewRelicAssert, - configFileStructureAssert, - configFileYamlAssert, - configFileInfluxDbAssert, -}; diff --git a/src/lib/config_util.js b/src/lib/config_util.js index 312752d9..f9759136 100644 --- a/src/lib/config_util.js +++ b/src/lib/config_util.js @@ -1,9 +1,9 @@ -const globals = require('../globals'); +import globals from '../globals.js'; // Construct a new RegExp object matching guids const guidRegExp = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/; -const configVerifyAllTaskId = () => { +export const configVerifyAllTaskId = () => { try { // Only verify allowed task IDs if that feature is turned on if (globals.config.has('Butler.startTaskFilter.enable') && globals.config.get('Butler.startTaskFilter.enable') === true) { @@ -27,7 +27,7 @@ const configVerifyAllTaskId = () => { } }; -const verifyTaskId = (taskId) => { +export const verifyTaskId = (taskId) => { try { if (guidRegExp.test(taskId) === true) { globals.logger.verbose(`TASK ID VERIFY: Task ID is valid: ${taskId}`); @@ -39,8 +39,3 @@ const verifyTaskId = (taskId) => { } return false; }; - -module.exports = { - configVerifyAllTaskId, - verifyTaskId, -}; diff --git a/src/lib/disk_utils.js b/src/lib/disk_utils.js index 4c35206f..bf7447af 100644 --- a/src/lib/disk_utils.js +++ b/src/lib/disk_utils.js @@ -1,8 +1,8 @@ -// Function to check if a given directory (child) is a subdirectory of +// Function to check if a given directory (child) is a subdirectory of // another directory (parent). // -// This function assumes that both child and parent are normalized paths -// (i.e., they don't contain . or .. segments), and that they use +// This function assumes that both child and parent are normalized paths +// (i.e., they don't contain . or .. segments), and that they use // forward slashes (/) as path separators. const isDirectoryChildOf = (child, parent) => { if (child === parent) return true; @@ -12,6 +12,4 @@ const isDirectoryChildOf = (child, parent) => { return parentTokens.every((t, i) => child.split('/').filter((j) => j.length)[i] === t); }; -module.exports = { - isDirectoryChildOf, -}; +export default isDirectoryChildOf; diff --git a/src/lib/heartbeat.js b/src/lib/heartbeat.js index 9928a7f7..60de3f8e 100644 --- a/src/lib/heartbeat.js +++ b/src/lib/heartbeat.js @@ -1,5 +1,5 @@ -const later = require('@breejs/later'); -const axios = require('axios'); +import later from '@breejs/later'; +import axios from 'axios'; const callRemoteURL = (remoteURL, logger) => { axios @@ -31,6 +31,4 @@ function setupHeartbeatTimer(config, logger) { } } -module.exports = { - setupHeartbeatTimer, -}; +export default setupHeartbeatTimer; diff --git a/src/lib/incident_mgmt/new_relic.js b/src/lib/incident_mgmt/new_relic.js index a5b0e567..5190905a 100644 --- a/src/lib/incident_mgmt/new_relic.js +++ b/src/lib/incident_mgmt/new_relic.js @@ -1,8 +1,7 @@ -const axios = require('axios'); -const QrsInteract = require('qrs-interact'); -const { RateLimiterMemory } = require('rate-limiter-flexible'); - -const globals = require('../../globals'); +import axios from 'axios'; +import QrsInteract from 'qrs-interact'; +import { RateLimiterMemory } from 'rate-limiter-flexible'; +import globals from '../../globals.js'; function getQRSConfig() { const cfg = { @@ -380,7 +379,7 @@ function getReloadAbortedLogConfig() { } } -async function sendNewRelicEvent(incidentConfig, reloadParams, destNewRelicAccounts) { +export async function sendNewRelicEvent(incidentConfig, reloadParams, destNewRelicAccounts) { try { // Build final payload const payload = []; @@ -463,7 +462,7 @@ async function sendNewRelicEvent(incidentConfig, reloadParams, destNewRelicAccou } } -async function sendNewRelicLog(incidentConfig, reloadParams, destNewRelicAccounts) { +export async function sendNewRelicLog(incidentConfig, reloadParams, destNewRelicAccounts) { try { // Build final URL const logApiUrl = incidentConfig.url; @@ -598,7 +597,7 @@ async function sendNewRelicLog(incidentConfig, reloadParams, destNewRelicAccount } } -async function sendReloadTaskFailureEvent(reloadParams) { +export async function sendReloadTaskFailureEvent(reloadParams) { const params = reloadParams; rateLimiterFailedReloadsEvent @@ -740,7 +739,7 @@ async function sendReloadTaskFailureEvent(reloadParams) { }); } -async function sendReloadTaskFailureLog(reloadParams) { +export async function sendReloadTaskFailureLog(reloadParams) { const params = reloadParams; rateLimiterFailedReloadsLog @@ -880,7 +879,7 @@ async function sendReloadTaskFailureLog(reloadParams) { }); } -function sendReloadTaskAbortedEvent(reloadParams) { +export function sendReloadTaskAbortedEvent(reloadParams) { const params = reloadParams; rateLimiterAbortedReloadsEvent @@ -1022,7 +1021,7 @@ function sendReloadTaskAbortedEvent(reloadParams) { }); } -function sendReloadTaskAbortedLog(reloadParams) { +export function sendReloadTaskAbortedLog(reloadParams) { const params = reloadParams; rateLimiterAbortedReloadsLog @@ -1163,12 +1162,3 @@ function sendReloadTaskAbortedLog(reloadParams) { globals.logger.verbose(`TASK ABORT NEWRELIC: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); }); } - -module.exports = { - sendReloadTaskFailureEvent, - sendReloadTaskFailureLog, - sendReloadTaskAbortedEvent, - sendReloadTaskAbortedLog, - sendNewRelicEvent, - sendNewRelicLog, -}; diff --git a/src/lib/incident_mgmt/new_relic_service_monitor.js b/src/lib/incident_mgmt/new_relic_service_monitor.js index 3e6ba9e6..8d532578 100644 --- a/src/lib/incident_mgmt/new_relic_service_monitor.js +++ b/src/lib/incident_mgmt/new_relic_service_monitor.js @@ -1,7 +1,6 @@ -const { RateLimiterMemory } = require('rate-limiter-flexible'); - -const globals = require('../../globals'); -const { sendNewRelicEvent, sendNewRelicLog } = require('./new_relic'); +import { RateLimiterMemory } from 'rate-limiter-flexible'; +import globals from '../../globals.js'; +import { sendNewRelicEvent, sendNewRelicLog } from './new_relic.js'; let rateLimiterServiceStatusEvent; let rateLimiterServiceStatusLog; @@ -352,7 +351,7 @@ async function sendServiceMonitorLog(serviceStatusParams) { }); } -module.exports = { +export default { sendServiceMonitorEvent, sendServiceMonitorLog, }; diff --git a/src/lib/incident_mgmt/signl4.js b/src/lib/incident_mgmt/signl4.js index 6412652b..0db6304c 100644 --- a/src/lib/incident_mgmt/signl4.js +++ b/src/lib/incident_mgmt/signl4.js @@ -1,7 +1,6 @@ -const axios = require('axios'); -const { RateLimiterMemory } = require('rate-limiter-flexible'); - -const globals = require('../../globals'); +import axios from 'axios'; +import { RateLimiterMemory } from 'rate-limiter-flexible'; +import globals from '../../globals.js'; let rateLimiterFailedReloads; let rateLimiterAbortedReloads; @@ -125,7 +124,7 @@ async function sendSignl4(incidentConfig, reloadParams) { } } -function sendReloadTaskFailureNotification(reloadParams) { +export function sendReloadTaskFailureNotification(reloadParams) { rateLimiterFailedReloads .consume(reloadParams.taskId, 1) .then(async (rateLimiterRes) => { @@ -133,7 +132,9 @@ function sendReloadTaskFailureNotification(reloadParams) { globals.logger.info( `SIGNL4 RELOAD TASK FAILED ALERT: Rate limiting check passed for failed task notification. Task name: "${reloadParams.taskName}"` ); - globals.logger.verbose(`SIGNL4 RELOAD TASK FAILED ALERT: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); + globals.logger.verbose( + `SIGNL4 RELOAD TASK FAILED ALERT: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"` + ); // Make sure Slack sending is enabled in the config file and that we have all required settings const incidentConfig = getReloadFailedEventConfig(); @@ -156,7 +157,7 @@ function sendReloadTaskFailureNotification(reloadParams) { }); } -function sendReloadTaskAbortedNotification(reloadParams) { +export function sendReloadTaskAbortedNotification(reloadParams) { rateLimiterAbortedReloads .consume(reloadParams.taskId, 1) .then(async (rateLimiterRes) => { @@ -164,7 +165,9 @@ function sendReloadTaskAbortedNotification(reloadParams) { globals.logger.info( `SIGNL4 RELOAD TASK ABORTED ALERT: Rate limiting check passed for aborted task notification. Task name: "${reloadParams.taskName}"` ); - globals.logger.verbose(`SIGNL4 RELOAD TASK ABORTED ALERT: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); + globals.logger.verbose( + `SIGNL4 RELOAD TASK ABORTED ALERT: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"` + ); // Make sure outgoing webhooks are enabled in the config file and that we have all required settings const incidentConfig = getReloadAbortedEventConfig(); @@ -186,8 +189,3 @@ function sendReloadTaskAbortedNotification(reloadParams) { globals.logger.verbose(`SIGNL4 RELOAD TASK ABORTED ALERT: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); }); } - -module.exports = { - sendReloadTaskFailureNotification, - sendReloadTaskAbortedNotification, -}; diff --git a/src/lib/key_value_store.js b/src/lib/key_value_store.js index ec49e143..dfe92ca9 100644 --- a/src/lib/key_value_store.js +++ b/src/lib/key_value_store.js @@ -1,24 +1,24 @@ -const Keyv = require('@keyvhq/core'); +import Keyv from '@keyvhq/core'; // Load global variables and functions -const globals = require('../globals'); +import globals from '../globals.js'; // Main key-value store // eslint-disable-next-line prefer-const let kvStore = []; -function getNamespaceList() { +export function getNamespaceList() { const ns = []; kvStore.forEach((item) => ns.push(item.namespace)); return ns; } -function getNamespace(namespaceName) { +export function getNamespace(namespaceName) { const ns = kvStore.find((item) => item.namespace === namespaceName); return ns; } -async function deleteNamespace(namespaceName) { +export async function deleteNamespace(namespaceName) { try { // Remove all KV pairs from namespace const ns = kvStore.find((item) => item.namespace === namespaceName); @@ -32,7 +32,7 @@ async function deleteNamespace(namespaceName) { } } -async function getValue(namespace, key) { +export async function getValue(namespace, key) { try { const ns = getNamespace(namespace); if (ns !== undefined) { @@ -46,7 +46,7 @@ async function getValue(namespace, key) { } } -async function deleteKeyValuePair(namespace, key) { +export async function deleteKeyValuePair(namespace, key) { try { const ns = getNamespace(namespace); if (ns !== undefined) { @@ -60,7 +60,7 @@ async function deleteKeyValuePair(namespace, key) { } } -async function addKeyValuePair(newNamespace, newKey, newValue, newTtl) { +export async function addKeyValuePair(newNamespace, newKey, newValue, newTtl) { try { // Does namespace already exist? const kv = kvStore.find((item) => item.namespace === newNamespace); @@ -105,12 +105,3 @@ async function addKeyValuePair(newNamespace, newKey, newValue, newTtl) { globals.logger.error(`Error while adding new KV pair: ${err}`); } } - -module.exports = { - deleteNamespace, - deleteKeyValuePair, - getNamespace, - getNamespaceList, - addKeyValuePair, - getValue, -}; diff --git a/src/lib/log_rest_call.js b/src/lib/log_rest_call.js index 359e20ad..7d3bb6a7 100644 --- a/src/lib/log_rest_call.js +++ b/src/lib/log_rest_call.js @@ -1,11 +1,13 @@ // Load global variables and functions -const globals = require('../globals'); +import globals from '../globals.js'; // Function for logging info about REST call -module.exports.logRESTCall = (req) => { +export const logRESTCall = (req) => { globals.logger.info(`${req.url} called from ${req.headers.remoteip}`); globals.logger.debug(`Query: ${JSON.stringify(req.query, null, 2)}`); globals.logger.debug(`Body: ${JSON.stringify(req.body, null, 2)}`); globals.logger.debug(`Params: ${JSON.stringify(req.params, null, 2)}`); globals.logger.debug(`Headers: ${JSON.stringify(req.headers, null, 2)}`); }; + +export default logRESTCall; diff --git a/src/lib/mqtt_handlers.js b/src/lib/mqtt_handlers.js index b3e14450..abdc28dc 100644 --- a/src/lib/mqtt_handlers.js +++ b/src/lib/mqtt_handlers.js @@ -1,12 +1,15 @@ -const mqtt = require('mqtt'); -const { validate } = require('uuid'); -const fs = require('fs'); -const upath = require('upath'); +import mqtt from 'mqtt'; +import { validate } from 'uuid'; +import fs from 'fs'; +import upath from 'upath'; +import { fileURLToPath } from 'url'; // Load global variables and functions -const { config, logger, execPath } = require('../globals'); -const globals = require('../globals'); -const qrsUtil = require('../qrs_util'); +// import { globals, config, logger } from '../globals.js'; +import globals from '../globals.js'; +import senseStartTask from '../qrs_util/sense_start_task.js'; + +const { config, logger } = globals; function mqttInitHandlers() { try { @@ -44,8 +47,10 @@ function mqttInitHandlers() { // Helper function to read the contents of the certificate files: const readCert = (filename) => fs.readFileSync(filename); - const certFile = upath.resolve(__dirname, config.get('Butler.mqttConfig.azureEventGrid.clientCertFile')); - const keyFile = upath.resolve(__dirname, config.get('Butler.mqttConfig.azureEventGrid.clientKeyFile')); + const filename = fileURLToPath(import.meta.url); + const dirname = upath.dirname(filename); + const certFile = upath.resolve(dirname, config.get('Butler.mqttConfig.azureEventGrid.clientCertFile')); + const keyFile = upath.resolve(dirname, config.get('Butler.mqttConfig.azureEventGrid.clientKeyFile')); // const certFile = path.join(execPath, config.get('Butler.mqttConfig.azureEventGrid.clientCertFile')); // const keyFile = path.join(execPath, config.get('Butler.mqttConfig.azureEventGrid.clientKeyFile')); @@ -139,7 +144,7 @@ function mqttInitHandlers() { } logger.verbose(`MQTT IN: Valid task ID ${message.toString()}.`); - const res = await qrsUtil.senseStartTask.senseStartTask(message.toString()); + const res = await senseStartTask(message.toString()); if (res) { logger.info(`MQTT IN: Started task ID ${message.toString()}.`); @@ -167,6 +172,4 @@ function mqttInitHandlers() { } } -module.exports = { - mqttInitHandlers, -}; +export default mqttInitHandlers; diff --git a/src/lib/msteams_notification.js b/src/lib/msteams_notification.js index 94841530..1d465aca 100644 --- a/src/lib/msteams_notification.js +++ b/src/lib/msteams_notification.js @@ -1,10 +1,10 @@ /* eslint-disable no-param-reassign */ -const fs = require('fs'); -const handlebars = require('handlebars'); -const { RateLimiterMemory } = require('rate-limiter-flexible'); +import fs from 'fs'; -const globals = require('../globals'); -const { getAppOwner } = require('../qrs_util/get_app_owner'); +import handlebars from 'handlebars'; +import { RateLimiterMemory } from 'rate-limiter-flexible'; +import globals from '../globals.js'; +import getAppOwner from '../qrs_util/get_app_owner.js'; let rateLimiterMemoryFailedReloads; let rateLimiterMemoryAbortedReloads; @@ -418,7 +418,7 @@ async function sendTeams(teamsWebhookObj, teamsConfig, templateContext, msgType) } } -function sendReloadTaskFailureNotificationTeams(reloadParams) { +export function sendReloadTaskFailureNotificationTeams(reloadParams) { rateLimiterMemoryFailedReloads .consume(reloadParams.taskId, 1) .then(async (rateLimiterRes) => { @@ -564,7 +564,7 @@ function sendReloadTaskFailureNotificationTeams(reloadParams) { }); } -function sendReloadTaskAbortedNotificationTeams(reloadParams) { +export function sendReloadTaskAbortedNotificationTeams(reloadParams) { rateLimiterMemoryAbortedReloads .consume(reloadParams.taskId, 1) .then(async (rateLimiterRes) => { @@ -709,7 +709,7 @@ function sendReloadTaskAbortedNotificationTeams(reloadParams) { }); } -function sendServiceMonitorNotificationTeams(serviceParams) { +export function sendServiceMonitorNotificationTeams(serviceParams) { rateLimiterMemoryServiceMonitor .consume(`${serviceParams.host}|${serviceParams.serviceName}`, 1) .then(async (rateLimiterRes) => { @@ -754,9 +754,3 @@ function sendServiceMonitorNotificationTeams(serviceParams) { globals.logger.verbose(`TEAMS SERVICE MONITOR: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); }); } - -module.exports = { - sendReloadTaskFailureNotificationTeams, - sendReloadTaskAbortedNotificationTeams, - sendServiceMonitorNotificationTeams, -}; diff --git a/src/lib/post_to_influxdb.js b/src/lib/post_to_influxdb.js index 82e459cf..4dc285bd 100755 --- a/src/lib/post_to_influxdb.js +++ b/src/lib/post_to_influxdb.js @@ -1,8 +1,7 @@ -const _ = require('lodash'); +import _ from 'lodash'; +import globals from '../globals.js'; -const globals = require('../globals'); - -function postButlerMemoryUsageToInfluxdb(memory) { +export function postButlerMemoryUsageToInfluxdb(memory) { // Get Butler version const butlerVersion = globals.appVersion; @@ -40,7 +39,7 @@ function postButlerMemoryUsageToInfluxdb(memory) { } // Add function to store windows service status to InfluxDB -function postWindowsServiceStatusToInfluxDB(serviceStatus) { +export function postWindowsServiceStatusToInfluxDB(serviceStatus) { globals.logger.verbose( `INFLUXDB WINDOWS SERVICE STATUS: Sending service status to InfluxDB: service="${serviceStatus.serviceFriendlyName}", status="${serviceStatus.serviceStatus}"` ); @@ -93,7 +92,11 @@ function postWindowsServiceStatusToInfluxDB(serviceStatus) { .then(() => { globals.logger.silly( - `INFLUXDB WINDOWS SERVICE STATUS: Influxdb datapoint for INFLUXDB WINDOWS SERVICE STATUS: ${JSON.stringify(datapoint, null, 2)}` + `INFLUXDB WINDOWS SERVICE STATUS: Influxdb datapoint for INFLUXDB WINDOWS SERVICE STATUS: ${JSON.stringify( + datapoint, + null, + 2 + )}` ); datapoint = null; @@ -105,7 +108,7 @@ function postWindowsServiceStatusToInfluxDB(serviceStatus) { } // Store information about successful reload tasks to InfluxDB -function postReloadTaskSuccessNotificationInfluxDb(reloadParams) { +export function postReloadTaskSuccessNotificationInfluxDb(reloadParams) { try { globals.logger.verbose('INFLUXDB RELOAD TASK SUCCESS: Sending reload task notification to InfluxDB'); @@ -207,7 +210,7 @@ function postReloadTaskSuccessNotificationInfluxDb(reloadParams) { } // Store information about failed reload tasks to InfluxDB -function postReloadTaskFailureNotificationInfluxDb(reloadParams) { +export function postReloadTaskFailureNotificationInfluxDb(reloadParams) { try { globals.logger.info('INFLUXDB RELOAD TASK FAILED: Sending reload task notification to InfluxDB'); // Build InfluxDB datapoint @@ -330,9 +333,3 @@ function postReloadTaskFailureNotificationInfluxDb(reloadParams) { globals.logger.error(`INFLUXDB RELOAD TASK FAILED: ${err}`); } } -module.exports = { - postButlerMemoryUsageToInfluxdb, - postWindowsServiceStatusToInfluxDB, - postReloadTaskFailureNotificationInfluxDb, - postReloadTaskSuccessNotificationInfluxDb, -}; diff --git a/src/lib/post_to_new_relic.js b/src/lib/post_to_new_relic.js index 50109f3b..e000eb9e 100755 --- a/src/lib/post_to_new_relic.js +++ b/src/lib/post_to_new_relic.js @@ -1,9 +1,9 @@ /* eslint-disable guard-for-in */ -const axios = require('axios'); +import axios from 'axios'; -const globals = require('../globals'); +import globals from '../globals.js'; -async function postButlerUptimeToNewRelic(fields) { +export async function postButlerUptimeToNewRelic(fields) { try { const payload = []; const metrics = []; @@ -153,7 +153,7 @@ async function postButlerUptimeToNewRelic(fields) { } } -async function postFailedReloadEventToNewRelic() { +export async function postFailedReloadEventToNewRelic() { try { // } catch (error) { @@ -162,7 +162,7 @@ async function postFailedReloadEventToNewRelic() { } } -async function postAbortedReloadEventToNewRelic() { +export async function postAbortedReloadEventToNewRelic() { try { // } catch (error) { @@ -170,9 +170,3 @@ async function postAbortedReloadEventToNewRelic() { globals.logger.error(`NEW RELIC UPTIME: Error posting reload aborted event: ${error}`); } } - -module.exports = { - postButlerUptimeToNewRelic, - postFailedReloadEventToNewRelic, - postAbortedReloadEventToNewRelic, -}; diff --git a/src/lib/scheduler.js b/src/lib/scheduler.js index ee2307fc..954a7128 100644 --- a/src/lib/scheduler.js +++ b/src/lib/scheduler.js @@ -1,9 +1,8 @@ -const fs = require('fs'); -const yaml = require('js-yaml'); -const CronJobManager = require('cron-job-manager'); - -const globals = require('../globals'); -const qrsUtil = require('../qrs_util'); +import fs from 'fs'; +import yaml from 'js-yaml'; +import CronJobManager from 'cron-job-manager'; +import globals from '../globals.js'; +import senseStartTask from '../qrs_util/sense_start_task.js'; const cronManager = new CronJobManager(); @@ -20,7 +19,7 @@ function addCronEntry(newSchedule) { newSchedule.cronSchedule, () => { globals.logger.info(`SCHEDULER: Cron event for schedule ID ${newSchedule.id.toString()}: ${newSchedule.name}`); - qrsUtil.senseStartTask.senseStartTask(newSchedule.qlikSenseTaskId); + senseStartTask(newSchedule.qlikSenseTaskId); }, { start: @@ -32,7 +31,7 @@ function addCronEntry(newSchedule) { } // Add new schedule -function addSchedule(newSchedule) { +export function addSchedule(newSchedule) { try { globals.logger.debug(`SCHEDULER: Adding new schedule: ${JSON.stringify(newSchedule, null, 2)}`); @@ -56,7 +55,7 @@ function addSchedule(newSchedule) { } } -function loadSchedulesFromDisk() { +export function loadSchedulesFromDisk() { // Load scheduler config, if available try { if (globals.config.has('Butler.scheduler')) { @@ -79,7 +78,7 @@ function loadSchedulesFromDisk() { } // Start all currently defined schedules -function startAllSchedules() { +export function startAllSchedules() { return new Promise((resolve, reject) => { globals.logger.debug('SCHEDULER: Starting all schedules'); @@ -101,7 +100,7 @@ function startAllSchedules() { } // Stop all currently defined schedules -function stopAllSchedules() { +export function stopAllSchedules() { return new Promise((resolve, reject) => { globals.logger.debug('SCHEDULER: Stopping all schedules'); @@ -122,22 +121,32 @@ function stopAllSchedules() { }); } +// Get schedule statuses +export function getSchedulesStatus() { + globals.logger.debug('SCHEDULER: Getting all crons'); + + const cronList = cronManager.listCrons(); + globals.logger.debug(`SCHEDULER: Cron list: ${JSON.stringify(cronList, null, 2)}`); + + return cronList; +} + // Get array with all schedules -function getAllSchedules() { +export function getAllSchedules() { globals.logger.debug('SCHEDULER: Getting all schedules'); return globals.configSchedule; } // Get object with a single schedule -function getSchedule(scheduleId) { +export function getSchedule(scheduleId) { globals.logger.debug('SCHEDULER: Getting schedule'); return globals.configSchedule.find((item) => item.id === scheduleId); } // Does a particular schedule exist? -function existsSchedule(scheduleId) { +export function existsSchedule(scheduleId) { // Does the schedule ID exist? const idExists = globals.configSchedule.find((item) => item.id === scheduleId) !== undefined; globals.logger.debug(`SCHEDULER: Does schedule id ${scheduleId} exist: ${JSON.stringify(idExists, null, 2)}`); @@ -150,7 +159,7 @@ function existsSchedule(scheduleId) { } // Delete a schedule -function deleteSchedule(deleteScheduleId) { +export function deleteSchedule(deleteScheduleId) { try { globals.logger.debug(`SCHEDULER: Deleting schedule with ID: ${deleteScheduleId}`); @@ -178,7 +187,7 @@ function deleteSchedule(deleteScheduleId) { } } -function startSchedule(scheduleId) { +export function startSchedule(scheduleId) { try { cronManager.start(scheduleId.toString()); @@ -195,7 +204,7 @@ function startSchedule(scheduleId) { } } -function stopSchedule(scheduleId) { +export function stopSchedule(scheduleId) { try { cronManager.stop(scheduleId.toString()); @@ -211,17 +220,3 @@ function stopSchedule(scheduleId) { return false; } } - -module.exports = { - loadSchedulesFromDisk, - startAllSchedules, - stopAllSchedules, - startSchedule, - stopSchedule, - getAllSchedules, - addSchedule, - getSchedule, - deleteSchedule, - existsSchedule, - cronManager, -}; diff --git a/src/lib/scriptlog.js b/src/lib/scriptlog.js index 93bcbc27..e6aee7bb 100644 --- a/src/lib/scriptlog.js +++ b/src/lib/scriptlog.js @@ -1,11 +1,10 @@ -const QrsInteract = require('qrs-interact'); -const axios = require('axios'); -const https = require('https'); -const luxon = require('luxon'); -const path = require('path'); -const fs = require('fs'); - -const globals = require('../globals'); +import QrsInteract from 'qrs-interact'; +import axios from 'axios'; +import https from 'https'; +import { Duration, DateTime } from 'luxon'; +import path from 'path'; +import fs from 'fs'; +import globals from '../globals.js'; const taskStatusLookup = { 0: 'NeverStarted', @@ -41,7 +40,7 @@ function delay(milliseconds) { } // Function to get reload task execution results -async function getReloadTaskExecutionResults(reloadTaskId) { +export async function getReloadTaskExecutionResults(reloadTaskId) { try { // Set up Sense repository service configuration const configQRS = { @@ -86,7 +85,7 @@ async function getReloadTaskExecutionResults(reloadTaskId) { } // Add duration as JSON - const taskDuration = luxon.Duration.fromMillis(result1.body.operational.lastExecutionResult.duration); + const taskDuration = Duration.fromMillis(result1.body.operational.lastExecutionResult.duration); taskInfo.executionDuration = taskDuration.shiftTo('hours', 'minutes', 'seconds').toObject(); taskInfo.executionDuration.seconds = Math.floor(taskInfo.executionDuration.seconds); @@ -101,14 +100,14 @@ async function getReloadTaskExecutionResults(reloadTaskId) { startTimeLocal5: '-', }; } else { - const luxonDT = luxon.DateTime.fromISO(result1.body.operational.lastExecutionResult.startTime); + const luxonDT = DateTime.fromISO(result1.body.operational.lastExecutionResult.startTime); taskInfo.executionStartTime = { startTimeUTC: result1.body.operational.lastExecutionResult.startTime, startTimeLocal1: luxonDT.toFormat('yyyy-LL-dd HH:mm:ss'), - startTimeLocal2: luxonDT.toLocaleString(luxon.DateTime.DATETIME_SHORT_WITH_SECONDS), - startTimeLocal3: luxonDT.toLocaleString(luxon.DateTime.DATETIME_MED_WITH_SECONDS), - startTimeLocal4: luxonDT.toLocaleString(luxon.DateTime.DATETIME_FULL_WITH_SECONDS), - startTimeLocal5: luxonDT.toLocaleString(luxon.DateTime.DATETIME_FULL_WITH_SECONDS), + startTimeLocal2: luxonDT.toLocaleString(DateTime.DATETIME_SHORT_WITH_SECONDS), + startTimeLocal3: luxonDT.toLocaleString(DateTime.DATETIME_MED_WITH_SECONDS), + startTimeLocal4: luxonDT.toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS), + startTimeLocal5: luxonDT.toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS), }; } @@ -123,14 +122,14 @@ async function getReloadTaskExecutionResults(reloadTaskId) { stopTimeLocal5: '-', }; } else { - const luxonDT = luxon.DateTime.fromISO(result1.body.operational.lastExecutionResult.stopTime); + const luxonDT = DateTime.fromISO(result1.body.operational.lastExecutionResult.stopTime); taskInfo.executionStopTime = { stopTimeUTC: result1.body.operational.lastExecutionResult.stopTime, stopTimeLocal1: luxonDT.toFormat('yyyy-LL-dd HH:mm:ss'), - stopTimeLocal2: luxonDT.toLocaleString(luxon.DateTime.DATETIME_SHORT_WITH_SECONDS), - stopTimeLocal3: luxonDT.toLocaleString(luxon.DateTime.DATETIME_MED_WITH_SECONDS), - stopTimeLocal4: luxonDT.toLocaleString(luxon.DateTime.DATETIME_FULL_WITH_SECONDS), - stopTimeLocal5: luxonDT.toLocaleString(luxon.DateTime.DATETIME_FULL_WITH_SECONDS), + stopTimeLocal2: luxonDT.toLocaleString(DateTime.DATETIME_SHORT_WITH_SECONDS), + stopTimeLocal3: luxonDT.toLocaleString(DateTime.DATETIME_MED_WITH_SECONDS), + stopTimeLocal4: luxonDT.toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS), + stopTimeLocal5: luxonDT.toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS), }; } @@ -149,14 +148,14 @@ async function getReloadTaskExecutionResults(reloadTaskId) { }; } - const luxonDT = luxon.DateTime.fromISO(item.detailCreatedDate); + const luxonDT = DateTime.fromISO(item.detailCreatedDate); return { timestampUTC: item.detailCreatedDate, timestampLocal1: luxonDT.toFormat('yyyy-LL-dd HH:mm:ss'), - timestampLocal2: luxonDT.toLocaleString(luxon.DateTime.DATETIME_SHORT_WITH_SECONDS), - timestampLocal3: luxonDT.toLocaleString(luxon.DateTime.DATETIME_MED_WITH_SECONDS), - timestampLocal4: luxonDT.toLocaleString(luxon.DateTime.DATETIME_FULL_WITH_SECONDS), - timestampLocal5: luxonDT.toLocaleString(luxon.DateTime.DATETIME_FULL_WITH_SECONDS), + timestampLocal2: luxonDT.toLocaleString(DateTime.DATETIME_SHORT_WITH_SECONDS), + timestampLocal3: luxonDT.toLocaleString(DateTime.DATETIME_MED_WITH_SECONDS), + timestampLocal4: luxonDT.toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS), + timestampLocal5: luxonDT.toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS), message: item.message, detailsType: item.detailsType, }; @@ -172,7 +171,7 @@ async function getReloadTaskExecutionResults(reloadTaskId) { // Function to get: // - reload task execution results // - reload task script log -async function getScriptLog(reloadTaskId, headLineCount, tailLineCount) { +export async function getScriptLog(reloadTaskId, headLineCount, tailLineCount) { try { // Step 1 const taskInfo = await getReloadTaskExecutionResults(reloadTaskId); @@ -283,7 +282,7 @@ async function getScriptLog(reloadTaskId, headLineCount, tailLineCount) { } } -async function failedTaskStoreLogOnDisk(reloadParams) { +export async function failedTaskStoreLogOnDisk(reloadParams) { try { // Get top level directory where logs should be stored const reloadLogDirRoot = globals.config.get('Butler.scriptLog.storeOnDisk.reloadTaskFailure.logDirectory'); @@ -313,9 +312,3 @@ async function failedTaskStoreLogOnDisk(reloadParams) { return false; } } - -module.exports = { - getScriptLog, - failedTaskStoreLogOnDisk, - getReloadTaskExecutionResults, -}; diff --git a/src/lib/service_monitor.js b/src/lib/service_monitor.js index 076c5b9c..42fa35a7 100644 --- a/src/lib/service_monitor.js +++ b/src/lib/service_monitor.js @@ -1,14 +1,14 @@ -const later = require('@breejs/later'); -const { createMachine, interpret } = require('xstate'); - -const svcTools = require('./winsvc'); -const globals = require('../globals'); -const newRelic = require('./incident_mgmt/new_relic_service_monitor'); -const webhookOut = require('./webhook_notification'); -const slack = require('./slack_notification'); -const teams = require('./msteams_notification'); -const smtp = require('./smtp'); -const influxDb = require('./post_to_influxdb'); +import later from '@breejs/later'; +import { createMachine, interpret } from 'xstate'; + +import { statusAll, status, details } from './winsvc.js'; +import globals from '../globals.js'; +import newRelic from './incident_mgmt/new_relic_service_monitor.js'; +import { sendServiceMonitorWebhook } from './webhook_notification.js'; +import { sendServiceMonitorNotificationSlack } from './slack_notification.js'; +import { sendServiceMonitorNotificationTeams } from './msteams_notification.js'; +import { sendServiceMonitorNotificationEmail } from './smtp.js'; +import { postWindowsServiceStatusToInfluxDB } from './post_to_influxdb.js'; // One state machines for each service const serviceStateMachine = []; @@ -135,7 +135,7 @@ const verifyServicesExist = async (config, logger) => { // Get status of all services on host logger.verbose(`VERIFY WIN SERVICES EXIST: Getting status of all Windows services on host ${host.host}`); // eslint-disable-next-line no-await-in-loop - const serviceStatusAll = await svcTools.statusAll(logger, host.host); + const serviceStatusAll = await statusAll(logger, host.host); const servicesToCheck = host.services; // eslint-disable-next-line no-restricted-syntax @@ -185,7 +185,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { // Get status of all services on host logger.verbose(`Getting status of all Windows services on host ${host.host}`); - const serviceStatusAll = await svcTools.statusAll(logger, host.host); + const serviceStatusAll = await statusAll(logger, host.host); servicesToCheck.forEach(async (service) => { logger.verbose(`Checking status of Windows service ${service.name} (="${service.friendlyName}") on host ${host.host}`); @@ -201,11 +201,11 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { } // Get status of this service - const serviceStatus = await svcTools.status(logger, service.name, host.host); + const serviceStatus = await status(logger, service.name, host.host); logger.verbose(`Got reply: Service ${service.name} (="${service.friendlyName}") on host ${host.host} status: ${serviceStatus}`); // Get details about this service - const serviceDetails = await svcTools.details(logger, service.name, host.host); + const serviceDetails = await details(logger, service.name, host.host); if ( serviceStatus === 'STOPPED' && config.has('Butler.incidentTool.newRelic.serviceMonitor.monitorServiceState.stopped.enable') && @@ -267,7 +267,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { globals.config.has('Butler.serviceMonitor.alertDestination.webhook.enable') && globals.config.get('Butler.serviceMonitor.alertDestination.webhook.enable') === true ) { - webhookOut.sendServiceMonitorWebhook({ + sendServiceMonitorWebhook({ serviceName: service.name, serviceFriendlyName: service.friendlyName, serviceStatus, @@ -286,7 +286,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { globals.config.get('Butler.slackNotification.enable') === true && globals.config.get('Butler.serviceMonitor.alertDestination.slack.enable') === true ) { - slack.sendServiceMonitorNotificationSlack({ + sendServiceMonitorNotificationSlack({ serviceName: service.name, serviceFriendlyName: service.friendlyName, serviceStatus, @@ -305,7 +305,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { globals.config.get('Butler.teamsNotification.enable') === true && globals.config.get('Butler.serviceMonitor.alertDestination.teams.enable') === true ) { - teams.sendServiceMonitorNotificationTeams({ + sendServiceMonitorNotificationTeams({ serviceName: service.name, serviceFriendlyName: service.friendlyName, serviceStatus, @@ -324,7 +324,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { globals.config.get('Butler.emailNotification.enable') === true && globals.config.get('Butler.serviceMonitor.alertDestination.email.enable') === true ) { - smtp.sendServiceMonitorNotificationEmail({ + sendServiceMonitorNotificationEmail({ serviceName: service.name, serviceFriendlyName: service.friendlyName, serviceStatus, @@ -349,7 +349,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { // First check? if (isFirstCheck) { // Set state to running as this is the first/startup check and we don't want to alert in this case - const res = smService.stateSvc.send('START'); + smService.stateSvc.send('START'); } const prevState = smService.stateSvc.state.value; @@ -405,7 +405,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { globals.config.has('Butler.serviceMonitor.alertDestination.webhook.enable') && globals.config.get('Butler.serviceMonitor.alertDestination.webhook.enable') === true ) { - webhookOut.sendServiceMonitorWebhook({ + sendServiceMonitorWebhook({ serviceName: service.name, serviceFriendlyName: service.friendlyName, serviceStatus, @@ -424,7 +424,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { globals.config.get('Butler.slackNotification.enable') === true && globals.config.get('Butler.serviceMonitor.alertDestination.slack.enable') === true ) { - slack.sendServiceMonitorNotificationSlack({ + sendServiceMonitorNotificationSlack({ serviceName: service.name, serviceFriendlyName: service.friendlyName, serviceStatus, @@ -443,7 +443,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { globals.config.get('Butler.teamsNotification.enable') === true && globals.config.get('Butler.serviceMonitor.alertDestination.teams.enable') === true ) { - teams.sendServiceMonitorNotificationTeams({ + sendServiceMonitorNotificationTeams({ serviceName: service.name, serviceFriendlyName: service.friendlyName, serviceStatus, @@ -462,7 +462,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { globals.config.get('Butler.emailNotification.enable') === true && globals.config.get('Butler.serviceMonitor.alertDestination.email.enable') === true ) { - smtp.sendServiceMonitorNotificationEmail({ + sendServiceMonitorNotificationEmail({ serviceName: service.name, serviceFriendlyName: service.friendlyName, serviceStatus, @@ -504,7 +504,7 @@ const checkServiceStatus = async (config, logger, isFirstCheck = false) => { ? globals.config.get('Butler.influxDb.instanceTag') : ''; - influxDb.postWindowsServiceStatusToInfluxDB({ + postWindowsServiceStatusToInfluxDB({ instanceTag, serviceName: service.name, serviceFriendlyName: service.friendlyName, @@ -582,7 +582,7 @@ async function setupServiceMonitorTimer(config, logger) { }); } } - + const sched = later.parse.text(config.get('Butler.serviceMonitor.frequency')); later.setInterval(() => { checkServiceStatus(config, logger, false); @@ -611,6 +611,4 @@ async function setupServiceMonitorTimer(config, logger) { } } -module.exports = { - setupServiceMonitorTimer, -}; +export default setupServiceMonitorTimer; diff --git a/src/lib/service_uptime.js b/src/lib/service_uptime.js index 99d25ad6..f65adbb3 100644 --- a/src/lib/service_uptime.js +++ b/src/lib/service_uptime.js @@ -1,10 +1,9 @@ -const later = require('@breejs/later'); -const moment = require('moment'); -require('moment-precise-range-plugin'); - -const globals = require('../globals'); -const postToInfluxdb = require('./post_to_influxdb'); -const postToHttp = require('./post_to_new_relic'); +import later from '@breejs/later'; +import moment from 'moment'; +import 'moment-precise-range-plugin'; +import globals from '../globals.js'; +import { postButlerMemoryUsageToInfluxdb } from './post_to_influxdb.js'; +import { postButlerUptimeToNewRelic } from './post_to_new_relic.js'; function serviceUptimeStart() { const uptimeLogLevel = globals.config.get('Butler.uptimeMonitor.logLevel'); @@ -77,7 +76,7 @@ function serviceUptimeStart() { globals.config.has('Butler.uptimeMonitor.storeInInfluxdb.enable') && globals.config.get('Butler.uptimeMonitor.storeInInfluxdb.enable') === true ) { - postToInfluxdb.postButlerMemoryUsageToInfluxdb({ + postButlerMemoryUsageToInfluxdb({ instanceTag: butlerMemoryInfluxTag, heapUsedMByte, heapTotalMByte, @@ -91,7 +90,7 @@ function serviceUptimeStart() { globals.config.has('Butler.uptimeMonitor.storeNewRelic.enable') && globals.config.get('Butler.uptimeMonitor.storeNewRelic.enable') === true ) { - postToHttp.postButlerUptimeToNewRelic({ + postButlerUptimeToNewRelic({ intervalMillisec, heapUsed, heapTotal, @@ -105,6 +104,4 @@ function serviceUptimeStart() { }, later.parse.text(uptimeInterval)); } -module.exports = { - serviceUptimeStart, -}; +export default serviceUptimeStart; diff --git a/src/lib/slack_api.js b/src/lib/slack_api.js index 2b28d0cf..3f58c115 100644 --- a/src/lib/slack_api.js +++ b/src/lib/slack_api.js @@ -1,4 +1,4 @@ -const axios = require('axios'); +import axios from 'axios'; async function slackSend(slackConfig, logger) { // TODO Sanity check Slack config @@ -31,6 +31,4 @@ async function slackSend(slackConfig, logger) { } } -module.exports = { - slackSend, -}; +export default slackSend; diff --git a/src/lib/slack_notification.js b/src/lib/slack_notification.js index 470e6ef6..2a3d577c 100644 --- a/src/lib/slack_notification.js +++ b/src/lib/slack_notification.js @@ -1,12 +1,12 @@ /* eslint-disable no-param-reassign */ -const fs = require('fs'); -const handlebars = require('handlebars'); -const { RateLimiterMemory } = require('rate-limiter-flexible'); +import fs from 'fs'; -const globals = require('../globals'); -const slackApi = require('./slack_api'); -const { getAppOwner } = require('../qrs_util/get_app_owner'); +import handlebars from 'handlebars'; +import { RateLimiterMemory } from 'rate-limiter-flexible'; +import globals from '../globals.js'; +import slackSend from './slack_api.js'; +import getAppOwner from '../qrs_util/get_app_owner.js'; let rateLimiterMemoryFailedReloads; let rateLimiterMemoryAbortedReloads; @@ -450,9 +450,9 @@ async function sendSlack(slackConfig, templateContext, msgType) { if (slackMsg !== null) { msg.text = slackMsg; - const res = await slackApi.slackSend(msg, globals.logger); + const res = await slackSend(msg, globals.logger); if (res !== undefined) { - globals.logger.debug(`SLACK SEND: Result from calling slackApi.slackSend: ${res.statusText} (${res.status}): ${res.data}`); + globals.logger.debug(`SLACK SEND: Result from calling slackSend: ${res.statusText} (${res.status}): ${res.data}`); } } } catch (err) { @@ -460,7 +460,7 @@ async function sendSlack(slackConfig, templateContext, msgType) { } } -function sendReloadTaskFailureNotificationSlack(reloadParams) { +export function sendReloadTaskFailureNotificationSlack(reloadParams) { rateLimiterMemoryFailedReloads .consume(reloadParams.taskId, 1) .then(async (rateLimiterRes) => { @@ -622,7 +622,7 @@ function sendReloadTaskFailureNotificationSlack(reloadParams) { }); } -function sendReloadTaskAbortedNotificationSlack(reloadParams) { +export function sendReloadTaskAbortedNotificationSlack(reloadParams) { rateLimiterMemoryAbortedReloads .consume(reloadParams.taskId, 1) .then(async (rateLimiterRes) => { @@ -769,7 +769,7 @@ function sendReloadTaskAbortedNotificationSlack(reloadParams) { }); } -function sendServiceMonitorNotificationSlack(serviceParams) { +export function sendServiceMonitorNotificationSlack(serviceParams) { rateLimiterMemoryServiceMonitor .consume(`${serviceParams.host}|${serviceParams.serviceName}`, 1) .then(async (rateLimiterRes) => { @@ -814,9 +814,3 @@ function sendServiceMonitorNotificationSlack(serviceParams) { globals.logger.debug(`SLACK SERVICE MONITOR: Rate limiting details "${JSON.stringify(err, null, 2)}"`); }); } - -module.exports = { - sendReloadTaskFailureNotificationSlack, - sendReloadTaskAbortedNotificationSlack, - sendServiceMonitorNotificationSlack, -}; diff --git a/src/lib/smtp.js b/src/lib/smtp.js index 46b40eda..b33cc4e7 100644 --- a/src/lib/smtp.js +++ b/src/lib/smtp.js @@ -1,13 +1,14 @@ /* eslint-disable consistent-return */ -const nodemailer = require('nodemailer'); -const hbs = require('nodemailer-express-handlebars'); -const expressHandlebars = require('express-handlebars'); -const handlebars = require('handlebars'); -const { RateLimiterMemory } = require('rate-limiter-flexible'); -const emailValidator = require('email-validator'); +import nodemailer from 'nodemailer'; -const globals = require('../globals'); -const qrsUtil = require('../qrs_util'); +import hbs from 'nodemailer-express-handlebars'; +import expressHandlebars from 'express-handlebars'; +import handlebars from 'handlebars'; +import { RateLimiterMemory } from 'rate-limiter-flexible'; +import emailValidator from 'email-validator'; +import globals from '../globals.js'; +import { getTaskCustomPropertyValues, isCustomPropertyValueSet } from '../qrs_util/task_cp_util.js'; +import getAppOwner from '../qrs_util/get_app_owner.js'; let rateLimiterMemoryFailedReloads; let rateLimiterMemoryAbortedReloads; @@ -288,7 +289,7 @@ async function sendEmail(from, recipientsEmail, emailPriority, subjectHandlebars } } -async function sendEmailBasic(from, recipientsEmail, emailPriority, subject, body) { +export async function sendEmailBasic(from, recipientsEmail, emailPriority, subject, body) { try { // First make sure email sending is enabled in the config file and that we have all required SMTP settings if (isSmtpConfigOk() === false) { @@ -335,7 +336,7 @@ async function sendEmailBasic(from, recipientsEmail, emailPriority, subject, bod } } -async function sendReloadTaskFailureNotificationEmail(reloadParams) { +export async function sendReloadTaskFailureNotificationEmail(reloadParams) { // Determine if an alert should be sent or not // 1. If config setting Butler.emailNotification.reloadTaskFailure.alertEnableByCustomProperty.enable is true // ... only send alerts for the tasks that have "enabledValue" set @@ -372,7 +373,7 @@ async function sendReloadTaskFailureNotificationEmail(reloadParams) { let mainSendList = []; // 1. Add task-specific notfication email adressess (set via custom property on reload tasks) to send list. - const taskSpecificAlertEmailAddresses = await qrsUtil.customPropertyUtil.getTaskCustomPropertyValues( + const taskSpecificAlertEmailAddresses = await getTaskCustomPropertyValues( reloadParams.taskId, emailAlertCpTaskSpecificEmailAddressName ); @@ -403,11 +404,7 @@ async function sendReloadTaskFailureNotificationEmail(reloadParams) { `EMAIL RELOAD TASK FAILED ALERT: Only send alert emails for tasks with email-alert-CP "${emailAlertCpName}" set` ); - const sendAlert = await qrsUtil.customPropertyUtil.isCustomPropertyValueSet( - reloadParams.taskId, - emailAlertCpName, - emailAlertCpEnabledValue - ); + const sendAlert = await isCustomPropertyValueSet(reloadParams.taskId, emailAlertCpName, emailAlertCpEnabledValue); if (sendAlert === true) { globals.logger.debug( @@ -423,7 +420,7 @@ async function sendReloadTaskFailureNotificationEmail(reloadParams) { } // Get app owner - const appOwner = await qrsUtil.getAppOwner.getAppOwner(reloadParams.appId); + const appOwner = await getAppOwner(reloadParams.appId); // If enabled in config file: Add app owners (excluding those that don't have an email address!) to list of recipients // 3 Should app owners get alerts? @@ -600,7 +597,7 @@ async function sendReloadTaskFailureNotificationEmail(reloadParams) { } } -async function sendReloadTaskAbortedNotificationEmail(reloadParams) { +export async function sendReloadTaskAbortedNotificationEmail(reloadParams) { // Determine if an alert should be sent or not // 1. If config setting Butler.emailNotification.reloadTaskAborted.alertEnableByCustomProperty.enable is true // ... only send alerts for the tasks that have "enabledValue" set @@ -637,7 +634,7 @@ async function sendReloadTaskAbortedNotificationEmail(reloadParams) { let mainSendList = []; // 1. Add task-specific notfication email adressess (set via custom property on reload tasks) to send list. - const taskSpecificAlertEmailAddresses = await qrsUtil.customPropertyUtil.getTaskCustomPropertyValues( + const taskSpecificAlertEmailAddresses = await getTaskCustomPropertyValues( reloadParams.taskId, emailAlertCpTaskSpecificEmailAddressName ); @@ -661,11 +658,7 @@ async function sendReloadTaskAbortedNotificationEmail(reloadParams) { `EMAIL RELOAD TASK ABORTED ALERT: Only send alert emails for tasks with email-alert-CP "${emailAlertCpName}" set` ); - const sendAlert = await qrsUtil.customPropertyUtil.isCustomPropertyValueSet( - reloadParams.taskId, - emailAlertCpName, - emailAlertCpEnabledValue - ); + const sendAlert = await isCustomPropertyValueSet(reloadParams.taskId, emailAlertCpName, emailAlertCpEnabledValue); if (sendAlert === true) { // 2.2.1 Yes: Add system-wide list of recipients to send list @@ -678,7 +671,7 @@ async function sendReloadTaskAbortedNotificationEmail(reloadParams) { } // Get app owner - const appOwner = await qrsUtil.getAppOwner.getAppOwner(reloadParams.appId); + const appOwner = await getAppOwner(reloadParams.appId); // If enabled in config file: Add app owners (excluding those that don't have an email address!) to list of recipients // 3 Should app owners get alerts? @@ -850,7 +843,7 @@ async function sendReloadTaskAbortedNotificationEmail(reloadParams) { } } -async function sendServiceMonitorNotificationEmail(serviceParams) { +export async function sendServiceMonitorNotificationEmail(serviceParams) { if (isSmtpConfigOk() === false) { return 1; } @@ -941,10 +934,3 @@ async function sendServiceMonitorNotificationEmail(serviceParams) { }); } } - -module.exports = { - sendReloadTaskFailureNotificationEmail, - sendReloadTaskAbortedNotificationEmail, - sendServiceMonitorNotificationEmail, - sendEmailBasic, -}; diff --git a/src/lib/telemetry.js b/src/lib/telemetry.js index 40481cbf..792624f1 100644 --- a/src/lib/telemetry.js +++ b/src/lib/telemetry.js @@ -1,7 +1,7 @@ /* eslint-disable camelcase */ -const { PostHog } = require('posthog-node'); +import { PostHog } from 'posthog-node'; -const globals = require('../globals'); +import globals from '../globals.js'; // Define variable to hold the PostHog client let posthogClient; @@ -462,7 +462,7 @@ const callRemoteURL = async () => { } }; -function setupAnonUsageReportTimer(logger, hostInfo) { +export default function setupAnonUsageReportTimer(logger, hostInfo) { try { // Setup PostHog client posthogClient = new PostHog('phc_5cmKiX9OubQjsSfOZuaolWaxo2z7WXqd295eB0uOtTb', { @@ -486,7 +486,3 @@ function setupAnonUsageReportTimer(logger, hostInfo) { logger.error(`TELEMETRY: ${err}`); } } - -module.exports = { - setupAnonUsageReportTimer, -}; diff --git a/src/lib/testemail.js b/src/lib/testemail.js index 16d23c91..685bc1e1 100644 --- a/src/lib/testemail.js +++ b/src/lib/testemail.js @@ -1,5 +1,5 @@ -const globals = require('../globals'); -const { sendEmailBasic } = require('./smtp'); +import globals from '../globals.js'; +import { sendEmailBasic } from './smtp.js'; function sendTestEmail(emailAddress, fromAddress) { try { @@ -25,6 +25,4 @@ function sendTestEmail(emailAddress, fromAddress) { } } -module.exports = { - sendTestEmail, -}; +export default sendTestEmail; diff --git a/src/lib/winsvc.js b/src/lib/winsvc.js index 0a93ae40..1ab58721 100644 --- a/src/lib/winsvc.js +++ b/src/lib/winsvc.js @@ -1,11 +1,11 @@ -const { exec } = require('child_process'); +import { exec } from 'child_process'; /** * Get all names of services installed * @param {object} logger Logger object * @param {string} host Host from which to get services */ -function all(logger, host = null) { +export function all(logger, host = null) { // If host is not specified, use services on localhost // Create promise @@ -63,7 +63,7 @@ function all(logger, host = null) { * @param {string} serviceName Name of service * @param {string} host Host on which service is running */ -function exists(logger, serviceName, host = null) { +export function exists(logger, serviceName, host = null) { // If host is not specified, use services on localhost // Create promise @@ -122,7 +122,7 @@ function exists(logger, serviceName, host = null) { * @param {object} logger Logger object * @param {string} host Host on which service is running */ -function statusAll(logger, host = null) { +export function statusAll(logger, host = null) { // Create promise return new Promise((resolve, reject) => { // If host is not specified, get services on localhost @@ -210,7 +210,7 @@ function statusAll(logger, host = null) { * @param {string} serviceName Name of service * @param {string} host Host on which service is running */ -function status(logger, serviceName, host = null) { +export function status(logger, serviceName, host = null) { // Create promise return new Promise((resolve, reject) => { // With invalid service name, reject @@ -297,7 +297,7 @@ function status(logger, serviceName, host = null) { * @param {string} serviceName Name of service * @param {string} host Host on which service is running */ -function details(logger, serviceName, host = null) { +export function details(logger, serviceName, host = null) { // Create promise return new Promise((resolve, reject) => { // With invalid service name, reject @@ -426,12 +426,3 @@ function details(logger, serviceName, host = null) { // ); }); } - -// Module schema -module.exports = { - all, - details, - exists, - status, - statusAll, -}; diff --git a/src/plugins/sensible.js b/src/plugins/sensible.js index 995eb3ba..a9535b2f 100644 --- a/src/plugins/sensible.js +++ b/src/plugins/sensible.js @@ -1,4 +1,4 @@ -const fp = require('fastify-plugin'); +import fp from 'fastify-plugin'; /** * This plugins adds some utilities to handle http errors @@ -6,9 +6,9 @@ const fp = require('fastify-plugin'); * @see https://github.com/fastify/fastify-sensible */ // eslint-disable-next-line no-unused-vars -module.exports = fp(async (fastify, _opts) => { +export default fp(async (fastify, _opts) => { // eslint-disable-next-line global-require - await fastify.register(require('@fastify/sensible'), { + await fastify.register(import('@fastify/sensible'), { errorHandler: false, }); }); diff --git a/src/plugins/support.js b/src/plugins/support.js index c1f93cb2..373fca62 100644 --- a/src/plugins/support.js +++ b/src/plugins/support.js @@ -1,10 +1,10 @@ -const fp = require('fastify-plugin'); +import fp from 'fastify-plugin'; // the use of fastify-plugin is required to be able // to export the decorators to the outer scope // eslint-disable-next-line no-unused-vars -module.exports = fp(async (fastify, _opts) => { +export default fp(async (fastify, _opts) => { // eslint-disable-next-line arrow-body-style fastify.decorate('someSupport', () => { return 'hugs'; diff --git a/src/qrs_util/app_tag_util.js b/src/qrs_util/app_tag_util.js index ee935ef8..22f0c6bf 100644 --- a/src/qrs_util/app_tag_util.js +++ b/src/qrs_util/app_tag_util.js @@ -1,7 +1,6 @@ -const path = require('path'); -const QrsInteract = require('qrs-interact'); - -const globals = require('../globals'); +import path from 'path'; +import QrsInteract from 'qrs-interact'; +import globals from '../globals.js'; /** * @@ -55,6 +54,4 @@ async function getAppTags(appId) { } } -module.exports = { - getAppTags, -}; +export default getAppTags; diff --git a/src/qrs_util/does_task_exist.js b/src/qrs_util/does_task_exist.js index ff7ee289..d2fe2581 100644 --- a/src/qrs_util/does_task_exist.js +++ b/src/qrs_util/does_task_exist.js @@ -1,8 +1,8 @@ -const QrsInteract = require('qrs-interact'); -const globals = require('../globals'); +import QrsInteract from 'qrs-interact'; +import globals from '../globals.js'; // Function for getting info about owner of Qlik Sense apps -module.exports.doesTaskExist = async (taskId) => { +const doesTaskExist = async (taskId) => { // eslint-disable-next-line no-unused-vars try { const qrsInstance = new QrsInteract({ @@ -48,3 +48,5 @@ module.exports.doesTaskExist = async (taskId) => { return false; } }; + +export default doesTaskExist; diff --git a/src/qrs_util/get_app_owner.js b/src/qrs_util/get_app_owner.js index d1eac610..1b7e17fe 100644 --- a/src/qrs_util/get_app_owner.js +++ b/src/qrs_util/get_app_owner.js @@ -1,8 +1,8 @@ -const QrsInteract = require('qrs-interact'); -const globals = require('../globals'); +import QrsInteract from 'qrs-interact'; +import globals from '../globals.js'; // Function for getting info about owner of Qlik Sense apps -module.exports.getAppOwner = async (appId) => { +const getAppOwner = async (appId) => { try { const qrsInstance = new QrsInteract({ hostname: globals.configQRS.host, @@ -57,3 +57,5 @@ module.exports.getAppOwner = async (appId) => { return false; } }; + +export default getAppOwner; diff --git a/src/qrs_util/get_tasks.js b/src/qrs_util/get_tasks.js index f5335c9d..ae20d1d1 100644 --- a/src/qrs_util/get_tasks.js +++ b/src/qrs_util/get_tasks.js @@ -1,9 +1,9 @@ -const QrsInteract = require('qrs-interact'); -const globals = require('../globals'); +import QrsInteract from 'qrs-interact'; +import globals from '../globals.js'; // Function for getting info about owner of Qlik Sense apps // filter: { tag: 'abc', customProperty: { name: 'def', value: 'ghi' } } -module.exports.getTasks = async (filter) => { +const getTasks = async (filter) => { try { const qrsInstance = new QrsInteract({ hostname: globals.configQRS.host, @@ -70,3 +70,5 @@ module.exports.getTasks = async (filter) => { return false; } }; + +export default getTasks; diff --git a/src/qrs_util/index.js b/src/qrs_util/index.js deleted file mode 100644 index 9c4652ec..00000000 --- a/src/qrs_util/index.js +++ /dev/null @@ -1,8 +0,0 @@ -/* eslint-disable global-require */ -module.exports = { - senseStartTask: require('./sense_start_task'), - doesTaskExist: require('./does_task_exist'), - getTasks: require('./get_tasks'), - getAppOwner: require('./get_app_owner'), - customPropertyUtil: require('./task_cp_util'), -}; diff --git a/src/qrs_util/sense_start_task.js b/src/qrs_util/sense_start_task.js index 82a23c8e..ee7d853b 100644 --- a/src/qrs_util/sense_start_task.js +++ b/src/qrs_util/sense_start_task.js @@ -1,6 +1,5 @@ -const QrsInteract = require('qrs-interact'); - -const globals = require('../globals'); +import QrsInteract from 'qrs-interact'; +import globals from '../globals.js'; // Function for starting Sense task, given its task ID (as it appears in the QMC task list) async function senseStartTask(taskId) { @@ -40,6 +39,4 @@ async function senseStartTask(taskId) { } } -module.exports = { - senseStartTask, -}; +export default senseStartTask; diff --git a/src/qrs_util/task_cp_util.js b/src/qrs_util/task_cp_util.js index 10a78a0f..d3c9a2aa 100644 --- a/src/qrs_util/task_cp_util.js +++ b/src/qrs_util/task_cp_util.js @@ -1,7 +1,6 @@ -const path = require('path'); -const QrsInteract = require('qrs-interact'); - -const globals = require('../globals'); +import path from 'path'; +import QrsInteract from 'qrs-interact'; +import globals from '../globals.js'; /** * @@ -10,7 +9,7 @@ const globals = require('../globals'); * @param {*} cpValue * @returns */ -async function isCustomPropertyValueSet(taskId, cpName, cpValue, logger) { +export async function isCustomPropertyValueSet(taskId, cpName, cpValue, logger) { const localLogger = logger !== undefined ? logger : globals.logger; localLogger.debug(`Checking if value "${cpValue}" is set for custom property "${cpName}"`); @@ -62,7 +61,7 @@ async function isCustomPropertyValueSet(taskId, cpName, cpValue, logger) { * @param {*} cpName * @returns */ -async function getTaskCustomPropertyValues(taskId, cpName) { +export async function getTaskCustomPropertyValues(taskId, cpName) { globals.logger.debug(`GETTASKCPVALUE: Retrieving all values for custom property "${cpName}" of reload task ${taskId}`); try { @@ -110,7 +109,7 @@ async function getTaskCustomPropertyValues(taskId, cpName) { } // Function to get all custom properties that are available for reload tasks -async function getReloadTasksCustomProperties(config, configQRS, logger) { +export async function getReloadTasksCustomProperties(config, configQRS, logger) { logger.debug('GETRELOADTASKSCP: Retrieving all custom properties that are available for reload tasks'); try { @@ -152,9 +151,3 @@ async function getReloadTasksCustomProperties(config, configQRS, logger) { return false; } } - -module.exports = { - isCustomPropertyValueSet, - getTaskCustomPropertyValues, - getReloadTasksCustomProperties, -}; diff --git a/src/qrs_util/task_tag_util.js b/src/qrs_util/task_tag_util.js index 8c5ce296..98b6f42d 100644 --- a/src/qrs_util/task_tag_util.js +++ b/src/qrs_util/task_tag_util.js @@ -1,7 +1,6 @@ -const path = require('path'); -const QrsInteract = require('qrs-interact'); - -const globals = require('../globals'); +import path from 'path'; +import QrsInteract from 'qrs-interact'; +import globals from '../globals.js'; /** * @@ -54,6 +53,4 @@ async function getTaskTags(taskId) { } } -module.exports = { - getTaskTags, -}; +export default getTaskTags; diff --git a/src/routes/api.js b/src/routes/api.js index 309bade1..548bd7a5 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -1,9 +1,10 @@ -const httpErrors = require('http-errors'); +import httpErrors from 'http-errors'; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { apiGetAPIEndpointsEnabled } = require('../api/api'); +import globals from '../globals.js'; + +import { logRESTCall } from '../lib/log_rest_call.js'; +import apiGetAPIEndpointsEnabled from '../api/api.js'; async function handlerGetAPIEndpointsEnabled(request, reply) { try { @@ -18,7 +19,7 @@ async function handlerGetAPIEndpointsEnabled(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.apiListEnbledEndpoints') && globals.config.get('Butler.restServerEndpointsEnable.apiListEnbledEndpoints') diff --git a/src/routes/base_conversion.js b/src/routes/base_conversion.js index 4178064a..eb888025 100644 --- a/src/routes/base_conversion.js +++ b/src/routes/base_conversion.js @@ -1,11 +1,12 @@ /* eslint-disable camelcase */ -const httpErrors = require('http-errors'); -const anyBase = require('any-base'); +import httpErrors from 'http-errors'; + +import anyBase from 'any-base'; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { apiGetBase16ToBase62, apiGetBase62ToBase16 } = require('../api/base_conversion'); +import globals from '../globals.js'; +import { logRESTCall } from '../lib/log_rest_call.js'; +import { apiGetBase16ToBase62, apiGetBase62ToBase16 } from '../api/base_conversion.js'; const base62_to_Hex = anyBase('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', '0123456789abcdef'); const hex_to_base62 = anyBase('0123456789abcdef', '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'); @@ -55,7 +56,7 @@ async function handlerGetBase16ToBase62(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.base62ToBase16') && globals.config.get('Butler.restServerEndpointsEnable.base62ToBase16') diff --git a/src/routes/butler_ping.js b/src/routes/butler_ping.js index 51431f3d..780cbf28 100644 --- a/src/routes/butler_ping.js +++ b/src/routes/butler_ping.js @@ -1,9 +1,10 @@ -const httpErrors = require('http-errors'); +import httpErrors from 'http-errors'; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { apiGetButlerPing } = require('../api/butler_ping'); +import globals from '../globals.js'; + +import { logRESTCall } from '../lib/log_rest_call.js'; +import apiGetButlerPing from '../api/butler_ping.js'; async function handlerGetButlerPing(request, reply) { try { @@ -21,7 +22,7 @@ async function handlerGetButlerPing(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.butlerping') && globals.config.get('Butler.restServerEndpointsEnable.butlerping') diff --git a/src/routes/disk_utils.js b/src/routes/disk_utils.js index 2f28d072..61ddb8a0 100644 --- a/src/routes/disk_utils.js +++ b/src/routes/disk_utils.js @@ -1,14 +1,15 @@ -const httpErrors = require('http-errors'); -const fs = require('fs-extra'); -const upath = require('upath'); -const { mkdirp } = require('mkdirp'); -const isUncPath = require('is-unc-path'); +import httpErrors from 'http-errors'; +import fs from 'fs-extra'; +import upath from 'upath'; +import { mkdirp } from 'mkdirp'; +import isUncPath from 'is-unc-path'; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { isDirectoryChildOf } = require('../lib/disk_utils'); -const { apiFileCopy, apiFileMove, apiFileDelete, apiCreateDir, apiCreateDirQvd } = require('../api/disk_utils'); +import globals from '../globals.js'; + +import { logRESTCall } from '../lib/log_rest_call.js'; +import isDirectoryChildOf from '../lib/disk_utils.js'; +import { apiFileCopy, apiFileMove, apiFileDelete, apiCreateDir, apiCreateDirQvd } from '../api/disk_utils.js'; async function handlerFileCopy(request, reply) { try { @@ -341,7 +342,7 @@ async function handlerCreateDir(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.fileCopy') && globals.config.get('Butler.restServerEndpointsEnable.fileCopy') diff --git a/src/routes/key_value_store.js b/src/routes/key_value_store.js index e60d40c0..6dc5e451 100644 --- a/src/routes/key_value_store.js +++ b/src/routes/key_value_store.js @@ -1,19 +1,12 @@ /* eslint-disable no-lonely-if */ -const httpErrors = require('http-errors'); +import httpErrors from 'http-errors'; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); - -const { - getNamespaceList, - getNamespace, - deleteNamespace, - addKeyValuePair, - deleteKeyValuePair, - getValue, -} = require('../lib/key_value_store'); -const { +import globals from '../globals.js'; + +import { logRESTCall } from '../lib/log_rest_call.js'; +import { getNamespaceList, getNamespace, deleteNamespace, addKeyValuePair, deleteKeyValuePair, getValue } from '../lib/key_value_store.js'; +import { apiGetAllNamespaces, apiGetKVPair, apiGetKVExists, @@ -21,7 +14,7 @@ const { apiDeleteKVPair, apiDeleteNamespace, apiGetKeysInNamespace, -} = require('../api/key_value_store'); +} from '../api/key_value_store.js'; async function handlerGetNamespaceList(request, reply) { try { @@ -317,7 +310,7 @@ async function handlerGetKeyList(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.keyValueStore') && globals.config.get('Butler.restServerEndpointsEnable.keyValueStore') diff --git a/src/routes/mqtt_publish_message.js b/src/routes/mqtt_publish_message.js index 85f5660d..f146311c 100644 --- a/src/routes/mqtt_publish_message.js +++ b/src/routes/mqtt_publish_message.js @@ -1,9 +1,10 @@ -const httpErrors = require('http-errors'); +import httpErrors from 'http-errors'; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { apiPutMqttMessage } = require('../api/mqtt_publish_message'); +import globals from '../globals.js'; + +import { logRESTCall } from '../lib/log_rest_call.js'; +import apiPutMqttMessage from '../api/mqtt_publish_message.js'; // eslint-disable-next-line consistent-return function handlerPutMqttMessage(request, reply) { @@ -46,7 +47,7 @@ function handlerPutMqttMessage(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.mqttPublishMessage') && globals.config.get('Butler.restServerEndpointsEnable.mqttPublishMessage') diff --git a/src/routes/newrelic_event.js b/src/routes/newrelic_event.js index cce6092a..2873e852 100644 --- a/src/routes/newrelic_event.js +++ b/src/routes/newrelic_event.js @@ -1,10 +1,11 @@ -const httpErrors = require('http-errors'); -const axios = require('axios'); +import httpErrors from 'http-errors'; +import axios from 'axios'; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { apiPostNewRelicEvent } = require('../api/newrelic_event'); +import globals from '../globals.js'; + +import { logRESTCall } from '../lib/log_rest_call.js'; +import apiPostNewRelicEvent from '../api/newrelic_event.js'; // eslint-disable-next-line consistent-return async function handlerPostNewRelicEvent(request, reply) { @@ -134,7 +135,7 @@ async function handlerPostNewRelicEvent(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.newRelic.postNewRelicEvent') && globals.config.get('Butler.restServerEndpointsEnable.newRelic.postNewRelicEvent') === true diff --git a/src/routes/newrelic_metric.js b/src/routes/newrelic_metric.js index ef16de24..48f6cc82 100644 --- a/src/routes/newrelic_metric.js +++ b/src/routes/newrelic_metric.js @@ -1,10 +1,11 @@ -const httpErrors = require('http-errors'); -const axios = require('axios'); +import httpErrors from 'http-errors'; +import axios from 'axios'; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { apiPostNewRelicMetric } = require('../api/newrelic_metric'); +import globals from '../globals.js'; + +import { logRESTCall } from '../lib/log_rest_call.js'; +import apiPostNewRelicMetric from '../api/newrelic_metric.js'; // eslint-disable-next-line consistent-return async function handlerPostNewRelicMetric(request, reply) { @@ -129,7 +130,7 @@ async function handlerPostNewRelicMetric(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.newRelic.postNewRelicMetric') && globals.config.get('Butler.restServerEndpointsEnable.newRelic.postNewRelicMetric') === true diff --git a/src/routes/scheduler.js b/src/routes/scheduler.js index 99816bb8..ef3693c6 100644 --- a/src/routes/scheduler.js +++ b/src/routes/scheduler.js @@ -1,11 +1,24 @@ -const httpErrors = require('http-errors'); -const uuid = require('uuid'); +import httpErrors from 'http-errors'; +import { v4 as uuidv4 } from 'uuid'; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const scheduler = require('../lib/scheduler'); -const { +import globals from '../globals.js'; + +import { logRESTCall } from '../lib/log_rest_call.js'; +import { + getSchedulesStatus, + existsSchedule, + getAllSchedules, + addSchedule, + deleteSchedule, + startSchedule, + stopSchedule, + getSchedule, + startAllSchedules, + stopAllSchedules, +} from '../lib/scheduler.js'; + +import { apiGETSchedules, apiPOSTSchedules, apiDELETESchedules, @@ -14,7 +27,7 @@ const { apiPUTSchedulesStop, apiPUTSchedulesStopAll, apiGETSchedulerStatus, -} = require('../api/scheduler'); +} from '../api/scheduler.js'; async function handlerGETSchedules(request, reply) { try { @@ -23,16 +36,17 @@ async function handlerGETSchedules(request, reply) { // Is there a schedule ID passed along? if (request.query.id !== undefined) { // Return specific schedule, if it exists - if (scheduler.existsSchedule(request.query.id)) { - const sched = scheduler.getAllSchedules().find((item) => item.id === request.query.id); + // Schedule should be returned in array, even though only one schedule is returned + if (existsSchedule(request.query.id)) { + const sched = getAllSchedules().find((item) => item.id === request.query.id); - reply.code(200).send(JSON.stringify(sched)); + reply.code(200).send(JSON.stringify([sched])); } else { reply.send(httpErrors(400, `REST SCHEDULER: Schedule ID ${request.query.id} not found.`)); } } else { // Return all schedules - reply.code(200).send(scheduler.getAllSchedules()); + reply.code(200).send(getAllSchedules()); } } catch (err) { globals.logger.error( @@ -48,10 +62,10 @@ async function handlerPOSTSchedules(request, reply) { const newSchedule = request.body; - newSchedule.id = uuid.v4(); + newSchedule.id = uuidv4(); newSchedule.created = new Date().toISOString(); - scheduler.addSchedule(newSchedule); + addSchedule(newSchedule); reply.code(201).send(JSON.stringify(newSchedule)); } catch (err) { @@ -67,7 +81,7 @@ async function handlerDELETESchedules(request, reply) { logRESTCall(request); globals.logger.debug(`REST SCHEDULER: Deleting schdule with ID: ${request.params.scheduleId}`); - if (scheduler.deleteSchedule(request.params.scheduleId) === true) { + if (deleteSchedule(request.params.scheduleId) === true) { // Delete succeeded reply.code(204).send(); } else { @@ -90,10 +104,13 @@ async function handlerPUTSchedulesStart(request, reply) { if (request.params.scheduleId !== undefined && request.params.scheduleId !== '') { globals.logger.debug(`REST SCHEDULER: Starting schedule ID: ${request.params.scheduleId}`); - if (scheduler.startSchedule(request.params.scheduleId) === true) { + if (startSchedule(request.params.scheduleId) === true) { // Start succeeded + + const schedule = getSchedule(request.params.scheduleId); globals.logger.info(`REST SCHEDULER: Started schedule ID: ${request.params.scheduleId}`); - reply.code(200).send(JSON.stringify([scheduler.getSchedule(request.params.scheduleId)])); + // reply.code(200).send(JSON.stringify([request.params.scheduleId])); + reply.code(200).send(JSON.stringify([schedule])); } else { // Start failed. Return error globals.logger.info(`REST SCHEDULER: Failed starting schedule ID: ${request.params.scheduleId}`); @@ -101,10 +118,10 @@ async function handlerPUTSchedulesStart(request, reply) { } } else { // Start all schedules - await scheduler.startAllSchedules(); + await startAllSchedules(); globals.logger.info('REST SCHEDULER: Started all schedules.'); - reply.code(200).send(JSON.stringify(scheduler.getAllSchedules())); + reply.code(200).send(JSON.stringify(getAllSchedules())); } } catch (err) { globals.logger.error( @@ -122,10 +139,10 @@ async function handlerPUTSchedulesStop(request, reply) { if (request.params.scheduleId !== undefined && request.params.scheduleId !== '') { globals.logger.debug(`REST SCHEDULER: Stopping schedule ID: ${request.params.scheduleId}`); - if (scheduler.stopSchedule(request.params.scheduleId) === true) { + if (stopSchedule(request.params.scheduleId) === true) { // Stop succeeded globals.logger.info(`REST SCHEDULER: Stopped schedule ID: ${request.params.scheduleId}`); - reply.code(200).send(JSON.stringify([scheduler.getSchedule(request.params.scheduleId)])); + reply.code(200).send(JSON.stringify([getSchedule(request.params.scheduleId)])); } else { // Stop failed. Return error globals.logger.error(`REST SCHEDULER: Failed stopping schedule ID: ${request.params.scheduleId}`); @@ -133,10 +150,10 @@ async function handlerPUTSchedulesStop(request, reply) { } } else { // Stop all schedules - await scheduler.stopAllSchedules(); + await stopAllSchedules(); globals.logger.info('REST SCHEDULER: Stopped all schedules.'); - reply.code(200).send(JSON.stringify(scheduler.getAllSchedules())); + reply.code(200).send(JSON.stringify(getAllSchedules())); } } catch (err) { globals.logger.error( @@ -150,8 +167,8 @@ async function handlerGETSchedulesStatus(request, reply) { try { logRESTCall(request); - // let status = `${scheduler.cronManager}`; - const status = scheduler.cronManager.listCrons(); + // const status = scheduler.cronManager.listCrons(); + const status = getSchedulesStatus(); reply.code(200).send(status); } catch (err) { globals.logger.error(`REST SCHEDULER: Failed retrieving scheduler status, error is: ${JSON.stringify(err, null, 2)}`); @@ -160,7 +177,7 @@ async function handlerGETSchedulesStatus(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if (globals.config.has('Butler.scheduler.enable') && globals.config.get('Butler.scheduler.enable')) { if ( globals.config.has('Butler.restServerEndpointsEnable.scheduler.getSchedule') && diff --git a/src/routes/sense_app.js b/src/routes/sense_app.js index b2dafdbd..7a13ef79 100644 --- a/src/routes/sense_app.js +++ b/src/routes/sense_app.js @@ -1,20 +1,24 @@ -const httpErrors = require('http-errors'); -const enigma = require('enigma.js'); -const SenseUtilities = require('enigma.js/sense-utilities'); -const WebSocket = require('ws'); +import httpErrors from 'http-errors'; +import enigma from 'enigma.js'; +import SenseUtilities from 'enigma.js/sense-utilities.js'; +import WebSocket from 'ws'; +import { createRequire } from "module"; // Load global variables and functions -const globals = require('../globals'); -const qrsUtil = require('../qrs_util'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { apiPutAppReload } = require('../api/sense_app'); +import globals from '../globals.js'; + +import senseStartTask from '../qrs_util/sense_start_task.js'; +import { logRESTCall } from '../lib/log_rest_call.js'; +import apiPutAppReload from '../api/sense_app.js'; // Set up enigma.js configuration async function handlerPutAppReload(request, reply) { try { - // eslint-disable-next-line import/no-dynamic-require, global-require - const qixSchema = require(`enigma.js/schemas/${globals.configEngine.engineVersion}`); + const schemaFile = `../../node_modules/enigma.js/schemas/${globals.configEngine.engineVersion}.json`; + const require = createRequire(import.meta.url); + // eslint-disable-next-line import/no-dynamic-require + const qixSchema = require(schemaFile); logRESTCall(request); @@ -101,7 +105,7 @@ async function handlerPutAppReload(request, reply) { `APPRELOAD: Starting task ${taskId} after reloading success of ${request.params.appId} on host ${globals.configEngine.host}, engine version is ${engineVersion.qComponentVersion}.` ); - qrsUtil.senseStartTask.senseStartTask(taskId); + senseStartTask(taskId); } } else { globals.logger.warn( @@ -115,7 +119,7 @@ async function handlerPutAppReload(request, reply) { `APPRELOAD: Starting task ${taskId} after reloading failure of ${request.params.appId} on host ${globals.configEngine.host}, engine version is ${engineVersion.qComponentVersion}.` ); - qrsUtil.senseStartTask.senseStartTask(taskId); + senseStartTask(taskId); } } @@ -147,7 +151,7 @@ async function handlerPutAppReload(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.senseAppReload') && globals.config.get('Butler.restServerEndpointsEnable.senseAppReload') diff --git a/src/routes/sense_app_dump.js b/src/routes/sense_app_dump.js index 59827aff..427ef8c4 100644 --- a/src/routes/sense_app_dump.js +++ b/src/routes/sense_app_dump.js @@ -1,18 +1,21 @@ -const serializeApp = require('serializeapp'); -const httpErrors = require('http-errors'); -const enigma = require('enigma.js'); -const WebSocket = require('ws'); +import serializeApp from 'serializeapp'; +import httpErrors from 'http-errors'; +import enigma from 'enigma.js'; +import WebSocket from 'ws'; +import { createRequire } from "module"; -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { apiGetSenseAppDump, apiGetAppDump } = require('../api/sense_app_dump'); +import globals from '../globals.js'; +import { logRESTCall } from '../lib/log_rest_call.js'; +import { apiGetSenseAppDump, apiGetAppDump } from '../api/sense_app_dump.js'; // Set up enigma.js configuration function handlerGetSenseAppDump(request, reply) { try { - // eslint-disable-next-line import/no-dynamic-require, global-require - const qixSchema = require(`enigma.js/schemas/${globals.configEngine.engineVersion}`); + const schemaFile = `../../node_modules/enigma.js/schemas/${globals.configEngine.engineVersion}.json`; + const require = createRequire(import.meta.url); + // eslint-disable-next-line import/no-dynamic-require + const qixSchema = require(schemaFile); logRESTCall(request); @@ -94,7 +97,7 @@ function handlerGetSenseAppDump(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.senseAppDump') && globals.config.get('Butler.restServerEndpointsEnable.senseAppDump') diff --git a/src/routes/sense_list_apps.js b/src/routes/sense_list_apps.js index 8aeb0842..6efbcea8 100644 --- a/src/routes/sense_list_apps.js +++ b/src/routes/sense_list_apps.js @@ -1,18 +1,22 @@ -const httpErrors = require('http-errors'); -const enigma = require('enigma.js'); -const WebSocket = require('ws'); +import httpErrors from 'http-errors'; +import enigma from 'enigma.js'; +import WebSocket from 'ws'; +import { createRequire } from "module"; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { apiGetSenseListApps, apiGetAppsList } = require('../api/sense_list_apps'); +import globals from '../globals.js'; + +import { logRESTCall } from '../lib/log_rest_call.js'; +import { apiGetSenseListApps, apiGetAppsList } from '../api/sense_list_apps.js'; // Set up enigma.js configuration function handlerGetSenseListApps(request, reply) { try { - // eslint-disable-next-line import/no-dynamic-require, global-require - const qixSchema = require(`enigma.js/schemas/${globals.configEngine.engineVersion}`); + const schemaFile = `../../node_modules/enigma.js/schemas/${globals.configEngine.engineVersion}.json`; + const require = createRequire(import.meta.url); + // eslint-disable-next-line import/no-dynamic-require + const qixSchema = require(schemaFile); logRESTCall(request); @@ -92,7 +96,7 @@ function handlerGetSenseListApps(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.senseListApps') && globals.config.get('Butler.restServerEndpointsEnable.senseListApps') diff --git a/src/routes/sense_start_task.js b/src/routes/sense_start_task.js index 532d6aad..76cd33e6 100644 --- a/src/routes/sense_start_task.js +++ b/src/routes/sense_start_task.js @@ -1,12 +1,15 @@ -const httpErrors = require('http-errors'); +import httpErrors from 'http-errors'; // Load global variables and functions -const globals = require('../globals'); -const qrsUtil = require('../qrs_util'); -const { logRESTCall } = require('../lib/log_rest_call'); -const { addKeyValuePair } = require('../lib/key_value_store'); -const { apiPutStartTask } = require('../api/sense_start_task'); -const { verifyTaskId } = require('../lib/config_util'); +import globals from '../globals.js'; + +import doesTaskExist from '../qrs_util/does_task_exist.js'; +import senseStartTask from '../qrs_util/sense_start_task.js'; +import getTasks from '../qrs_util/get_tasks.js'; +import { logRESTCall } from '../lib/log_rest_call.js'; +import { addKeyValuePair } from '../lib/key_value_store.js'; +import apiPutStartTask from '../api/sense_start_task.js'; +import { verifyTaskId } from '../lib/config_util.js'; // Get array of allowed task IDs function getTaskIdAllowed() { @@ -119,7 +122,7 @@ async function handlerPutStartTask(request, reply) { ) { // Task ID is allowed // Verify task exists - taskExists = await qrsUtil.doesTaskExist.doesTaskExist(request.params.taskId); + taskExists = await doesTaskExist(request.params.taskId); if (taskExists.exists) { tasksToStartTaskId.push(taskExists.task); globals.logger.silly( @@ -175,7 +178,7 @@ async function handlerPutStartTask(request, reply) { // Verify task exists // payload: { taskId: 'abc' } // eslint-disable-next-line no-await-in-loop - taskExists = await qrsUtil.doesTaskExist.doesTaskExist(item.payload.taskId); + taskExists = await doesTaskExist(item.payload.taskId); if (taskExists.exists) { tasksToStartTaskId.push(taskExists.task); globals.logger.silly( @@ -205,7 +208,7 @@ async function handlerPutStartTask(request, reply) { // payload: { tag: 'abc' } // eslint-disable-next-line no-await-in-loop - const tagTasks = await qrsUtil.getTasks.getTasks({ tag: item.payload.tag }); + const tagTasks = await getTasks({ tag: item.payload.tag }); // eslint-disable-next-line no-restricted-syntax for (const task of tagTasks) { tasksToStartTags.push(task); @@ -229,7 +232,7 @@ async function handlerPutStartTask(request, reply) { // payload: { customPropertyName: 'abc', customPropertyValue: 'def } // eslint-disable-next-line no-await-in-loop - const cpTasks = await qrsUtil.getTasks.getTasks({ + const cpTasks = await getTasks({ customProperty: { name: item.payload.customPropertyName, value: item.payload.customPropertyValue, @@ -271,7 +274,7 @@ async function handlerPutStartTask(request, reply) { // eslint-disable-next-line no-restricted-syntax for (const item of tasksToStartTaskId) { globals.logger.verbose(`STARTTASK: Starting task: ${item.taskId}`); - qrsUtil.senseStartTask.senseStartTask(item.taskId); + senseStartTask(item.taskId); res.tasksId.started.push({ taskId: item.taskId, taskName: item.taskName }); } } else { @@ -287,7 +290,7 @@ async function handlerPutStartTask(request, reply) { // eslint-disable-next-line no-restricted-syntax for (const item of tasksToStartTaskId) { globals.logger.verbose(`STARTTASK: Starting task: ${item.taskId}`); - qrsUtil.senseStartTask.senseStartTask(item.taskId); + senseStartTask(item.taskId); res.tasksId.started.push({ taskId: item.taskId, taskName: item.taskName }); } res.tasksId.invalid = tasksInvalid; @@ -298,7 +301,7 @@ async function handlerPutStartTask(request, reply) { // eslint-disable-next-line no-restricted-syntax for (const item of tasksToStartTags) { globals.logger.verbose(`STARTTASK: Starting task: ${item.taskId}`); - qrsUtil.senseStartTask.senseStartTask(item.taskId); + senseStartTask(item.taskId); } res.tasksTag = tasksToStartTags; } @@ -308,7 +311,7 @@ async function handlerPutStartTask(request, reply) { // eslint-disable-next-line no-restricted-syntax for (const item of tasksToStartCPs) { globals.logger.verbose(`STARTTASK: Starting task: ${item.taskId}`); - qrsUtil.senseStartTask.senseStartTask(item.taskId); + senseStartTask(item.taskId); } res.tasksCP = tasksToStartCPs; } @@ -321,7 +324,7 @@ async function handlerPutStartTask(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.senseStartTask') && globals.config.get('Butler.restServerEndpointsEnable.senseStartTask') diff --git a/src/routes/slack_post_message.js b/src/routes/slack_post_message.js index d839c97b..368abbfd 100644 --- a/src/routes/slack_post_message.js +++ b/src/routes/slack_post_message.js @@ -1,10 +1,11 @@ -const httpErrors = require('http-errors'); +import httpErrors from 'http-errors'; // Load global variables and functions -const globals = require('../globals'); -const { logRESTCall } = require('../lib/log_rest_call'); -const slackApi = require('../lib/slack_api'); -const { apiPutSlackPostMessage } = require('../api/slack_post_message'); +import globals from '../globals.js'; + +import { logRESTCall } from '../lib/log_rest_call.js'; +import slackSend from '../lib/slack_api.js'; +import apiPutSlackPostMessage from '../api/slack_post_message.js'; async function handlerPutSlackPostMessage(request, reply) { try { @@ -33,7 +34,7 @@ async function handlerPutSlackPostMessage(request, reply) { webhookUrl: globals.config.get('Butler.slackNotification.restMessage.webhookURL'), }; - slackApi.slackSend(slackConfig, globals.logger); + await slackSend(slackConfig, globals.logger); reply.code(201).send(request.body); } @@ -46,7 +47,7 @@ async function handlerPutSlackPostMessage(request, reply) { } // eslint-disable-next-line no-unused-vars -module.exports = async (fastify, options) => { +export default async (fastify, options) => { if ( globals.config.has('Butler.restServerEndpointsEnable.slackPostMessage') && globals.config.get('Butler.restServerEndpointsEnable.slackPostMessage') diff --git a/src/test/env.js b/src/test/env.js new file mode 100644 index 00000000..b46845ed --- /dev/null +++ b/src/test/env.js @@ -0,0 +1,12 @@ +import path from 'path'; + +const configDir = path.resolve('./src/config/'); + +process.env.NODE_CONFIG_DIR = configDir; +process.env.NODE_ENV = 'production'; +process.env.SUPPRESS_NO_CONFIG_WARNING = 'false'; + +export const { NODE_CONFIG_DIR } = process.env; +export const { SUPPRESS_NO_CONFIG_WARNING } = process.env; +export const { NODE_ENV } = process.env; + diff --git a/src/test/routes/api.test.js b/src/test/routes/api.test.js index 7b3c54f6..f230a9fa 100644 --- a/src/test/routes/api.test.js +++ b/src/test/routes/api.test.js @@ -1,9 +1,5 @@ -const path = require('path'); -const axios = require('axios'); - -process.env.NODE_CONFIG_DIR = path.resolve('./src/config/'); -process.env.NODE_ENV = 'production'; -const config = require('config'); +import config from 'config'; +import axios from 'axios'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, diff --git a/src/test/routes/baseconversion.test.js b/src/test/routes/baseconversion.test.js index eb3686ff..03df29d2 100644 --- a/src/test/routes/baseconversion.test.js +++ b/src/test/routes/baseconversion.test.js @@ -1,11 +1,6 @@ /* eslint-disable camelcase */ -const path = require('path'); -const axios = require('axios'); - -process.env.NODE_CONFIG_DIR = path.resolve('./src/config/'); -process.env.NODE_ENV = 'production'; -// console.log(process.env["NODE_CONFIG_DIR"]) -const config = require('config'); +import config from 'config'; +import axios from 'axios'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, diff --git a/src/test/routes/butlerping.test.js b/src/test/routes/butlerping.test.js index b2af4aa2..151075f8 100644 --- a/src/test/routes/butlerping.test.js +++ b/src/test/routes/butlerping.test.js @@ -1,9 +1,8 @@ -const path = require('path'); -const axios = require('axios'); +import axios from 'axios'; +import config from 'config'; -process.env.NODE_CONFIG_DIR = path.resolve('./src/config/'); -process.env.NODE_ENV = 'production'; -const config = require('config'); +// Load global variables and functions +import globals from '../../globals.js'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, @@ -13,7 +12,7 @@ const instance = axios.create({ let result; // Get app version from package.json -const appVersion = require('../../../package.json').version; +const { appVersion } = globals; /** * D1 diff --git a/src/test/routes/disk_utils.test.js b/src/test/routes/disk_utils.test.js index 09b70f2c..c2131e3e 100644 --- a/src/test/routes/disk_utils.test.js +++ b/src/test/routes/disk_utils.test.js @@ -1,14 +1,10 @@ /* eslint-disable no-console */ /* eslint-disable camelcase */ -const fs = require('fs/promises'); -const upath = require('upath'); -const axios = require('axios'); - -process.env.NODE_CONFIG_DIR = upath.resolve('./src/config/'); -process.env.NODE_ENV = 'production'; -const config = require('config'); - -const { isDirectoryChildOf } = require('../../lib/disk_utils'); +import config from 'config'; +import fs from 'fs/promises'; +import upath from 'upath'; +import axios from 'axios'; +import isDirectoryChildOf from '../../lib/disk_utils.js'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, diff --git a/src/test/routes/keyvaluestore.test.js b/src/test/routes/keyvaluestore.test.js index 8583d8a3..e474e658 100644 --- a/src/test/routes/keyvaluestore.test.js +++ b/src/test/routes/keyvaluestore.test.js @@ -1,9 +1,5 @@ -const path = require('path'); -const axios = require('axios'); - -process.env.NODE_CONFIG_DIR = path.resolve('./src/config/'); -process.env.NODE_ENV = 'production'; -const config = require('config'); +import config from 'config'; +import axios from 'axios'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, diff --git a/src/test/routes/mqttpublishmessage.test.js b/src/test/routes/mqttpublishmessage.test.js index c0157f80..f0725731 100644 --- a/src/test/routes/mqttpublishmessage.test.js +++ b/src/test/routes/mqttpublishmessage.test.js @@ -1,9 +1,5 @@ -const path = require('path'); -const axios = require('axios'); - -process.env.NODE_CONFIG_DIR = path.resolve('./src/config/'); -process.env.NODE_ENV = 'production'; -const config = require('config'); +import config from 'config'; +import axios from 'axios'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, diff --git a/src/test/routes/scheduler.test.js b/src/test/routes/scheduler.test.js index 4d4bf000..c8e91442 100644 --- a/src/test/routes/scheduler.test.js +++ b/src/test/routes/scheduler.test.js @@ -1,9 +1,5 @@ -const path = require('path'); -const axios = require('axios'); - -process.env.NODE_CONFIG_DIR = path.resolve('./src/config/'); -process.env.NODE_ENV = 'production'; -const config = require('config'); +import config from 'config'; +import axios from 'axios'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, @@ -126,15 +122,15 @@ describe('H2: GET /v4/schedules', () => { }); test('Response should contain correct fields', () => { - expect(result.data.name).toEqual(scheduleName1); - expect(result.data.cronSchedule).toEqual(scheduleCron1); - expect(result.data.timezone).toEqual(scheduleTimezone1); - expect(result.data.qlikSenseTaskId).toEqual(scheduleTaskId1); - expect(result.data.startupState).toEqual(scheduleStartupState1); - expect(result.data.tags).toEqual([scheduleTag1, scheduleTag2]); - expect(result.data.id).toBeTruthy(); - expect(result.data.created).toBeTruthy(); - expect(result.data.lastKnownState).toEqual('started'); + expect(result.data[0].name).toEqual(scheduleName1); + expect(result.data[0].cronSchedule).toEqual(scheduleCron1); + expect(result.data[0].timezone).toEqual(scheduleTimezone1); + expect(result.data[0].qlikSenseTaskId).toEqual(scheduleTaskId1); + expect(result.data[0].startupState).toEqual(scheduleStartupState1); + expect(result.data[0].tags).toEqual([scheduleTag1, scheduleTag2]); + expect(result.data[0].id).toBeTruthy(); + expect(result.data[0].created).toBeTruthy(); + expect(result.data[0].lastKnownState).toEqual('started'); }); test('It should respond with 204 when deleting an existing schedule', async () => { @@ -196,10 +192,13 @@ describe('H4: PUT /v4/schedules/:scheduleId/start', () => { expect(result.status).toBe(200); }); - test('Response should be an object and last known state stopped', () => { + test('Response data should be an array', () => { expect(result.data).toBeTruthy(); - expect(typeof result.data).toBe('object'); - expect(result.data.lastKnownState).toBe('stopped'); + expect(Array.isArray(result.data)).toBe(true); + }); + + test('Response should have last known state stopped', () => { + expect(result.data[0].lastKnownState).toBe('stopped'); }); test('It should respond with 200 when starting an existing schedule', async () => { @@ -213,7 +212,7 @@ describe('H4: PUT /v4/schedules/:scheduleId/start', () => { expect(typeof result.data).toBe('object'); }); - test('Response should contain correct fields', () => { + test('Response should contain correct fields', () => { expect(result.data[0].name).toEqual(scheduleName1); expect(result.data[0].cronSchedule).toEqual(scheduleCron1); expect(result.data[0].timezone).toEqual(scheduleTimezone1); @@ -235,10 +234,10 @@ describe('H4: PUT /v4/schedules/:scheduleId/start', () => { expect(result.status).toBe(200); }); - test('Response should be an object and last known state started', () => { + test('Response should be an array and last known state started', () => { expect(result.data).toBeTruthy(); - expect(typeof result.data).toBe('object'); - expect(result.data.lastKnownState).toBe('started'); + expect(Array.isArray(result.data)).toBe(true); + expect(result.data[0].lastKnownState).toBe('started'); }); test('It should respond with 204 when deleting an existing schedule', async () => { @@ -310,10 +309,10 @@ describe('H6: PUT /v4/schedules/:scheduleId/stop', () => { expect(result.status).toBe(200); }); - test('Response should be an object and last known state started', () => { + test('Response should be an array and last known state started', () => { expect(result.data).toBeTruthy(); - expect(typeof result.data).toBe('object'); - expect(result.data.lastKnownState).toBe('started'); + expect(Array.isArray(result.data)).toBe(true); + expect(result.data[0].lastKnownState).toBe('started'); }); test('It should respond with 200 when stopping an existing schedule', async () => { @@ -349,10 +348,10 @@ describe('H6: PUT /v4/schedules/:scheduleId/stop', () => { expect(result.status).toBe(200); }); - test('Response should be an object and last known state started', () => { + test('Response should be an array and last known state started', () => { expect(result.data).toBeTruthy(); - expect(typeof result.data).toBe('object'); - expect(result.data.lastKnownState).toBe('stopped'); + expect(Array.isArray(result.data)).toBe(true); + expect(result.data[0].lastKnownState).toBe('stopped'); }); test('It should respond with 204 when deleting an existing schedule', async () => { diff --git a/src/test/routes/senseapp.test.js b/src/test/routes/senseapp.test.js index aa31698c..43fd6351 100644 --- a/src/test/routes/senseapp.test.js +++ b/src/test/routes/senseapp.test.js @@ -1,9 +1,5 @@ -const path = require('path'); -const axios = require('axios'); - -process.env.NODE_CONFIG_DIR = path.resolve('./src/config/'); -process.env.NODE_ENV = 'production'; -const config = require('config'); +import config from 'config'; +import axios from 'axios'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, @@ -22,8 +18,9 @@ beforeAll(async () => { appId1 = 'c1e27bf7-56ae-45b9-87a6-cdfab255b269'; appPartialReload1 = true; appReloadMode1 = 0; - appStartTaskSuccess = ['e3b27f50-b1c0-4879-88fc-c7cdd9c1cf3e', '7552d9fc-d1bb-4975-9a38-18357de531ea']; - appStartTaskFailure = ['fb0f317d-da91-4b86-aafa-0174ae1e8c8f', 'fa93345c-f7a3-4f43-ab24-4da4245e16e8']; + // Task IDs to be started after successful reload + appStartTaskSuccess = ['25732e8f-a96f-44c0-ba81-7407a2ef4c8a', '62a91752-0340-4db4-ab1f-4df4e671ea60']; + appStartTaskFailure = ['4788dc51-2bf6-45f0-a4ad-8bd8d40e1d3f', 'd2902674-6bde-4d64-86c0-2e5d3a0c08f2']; }); afterAll(async () => { diff --git a/src/test/routes/sensestarttask_start-task-filter_off.test.js b/src/test/routes/sensestarttask_start-task-filter_off.test.js index a9fd029a..a111f6a2 100644 --- a/src/test/routes/sensestarttask_start-task-filter_off.test.js +++ b/src/test/routes/sensestarttask_start-task-filter_off.test.js @@ -1,11 +1,6 @@ /* eslint-disable camelcase */ -const path = require('path'); -const axios = require('axios'); - -process.env.NODE_CONFIG_DIR = path.resolve('./src/config/'); -// Use config file where start task filtering is turned ON -process.env.NODE_ENV = 'production'; -const config = require('config'); +import config from 'config'; +import axios from 'axios'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, @@ -22,10 +17,13 @@ let taskId_notallowed1; let taskTag1; let taskTag2; let taskTag_invalid1; +let taskTag_notallowed1; let taskCPName1; let taskCPName_invalid1; +let taskCPName_notallowed1; let taskCPValue1; let taskCPValue2; +let taskCPValue_notallowed1; let taskCPValue_invalid1; let taskKVNamespace1; let taskKVKey1; diff --git a/src/test/routes/sensestarttask_start-task-filter_on.test.js b/src/test/routes/sensestarttask_start-task-filter_on.test.js index c8eb68fd..596f2bad 100644 --- a/src/test/routes/sensestarttask_start-task-filter_on.test.js +++ b/src/test/routes/sensestarttask_start-task-filter_on.test.js @@ -1,11 +1,6 @@ /* eslint-disable camelcase */ -const path = require('path'); -const axios = require('axios'); - -process.env.NODE_CONFIG_DIR = path.resolve('./src/config/'); -// Use config file where start task filtering is turned ON -process.env.NODE_ENV = 'production'; -const config = require('config'); +import config from 'config'; +import axios from 'axios'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, @@ -447,7 +442,7 @@ if (config.get('Butler.startTaskFilter.enable') === true) { expect(result.data.tasksId.started.length).toBe(0); expect(result.data.tasksId.invalid.length).toBe(1); expect(result.data.tasksId.denied.length).toBe(0); - expect(result.data.tasksTag.length).toBe(4); + expect(result.data.tasksTag.length).toBe(5); expect(result.data.tasksTagDenied.length).toBe(0); expect(result.data.tasksCP.length).toBe(0); expect(result.data.tasksCPDenied.length).toBe(0); @@ -495,7 +490,7 @@ if (config.get('Butler.startTaskFilter.enable') === true) { expect(result.data.tasksId.started.length).toBe(0); expect(result.data.tasksId.invalid.length).toBe(1); expect(result.data.tasksId.denied.length).toBe(0); - expect(result.data.tasksTag.length).toBe(4); + expect(result.data.tasksTag.length).toBe(5); expect(result.data.tasksTagDenied.length).toBe(1); expect(result.data.tasksCP.length).toBe(0); expect(result.data.tasksCPDenied.length).toBe(0); @@ -682,7 +677,7 @@ if (config.get('Butler.startTaskFilter.enable') === true) { expect(result.data.tasksId.started.length).toBe(3); expect(result.data.tasksId.invalid.length).toBe(1); expect(result.data.tasksId.denied.length).toBe(1); - expect(result.data.tasksTag.length).toBe(4); + expect(result.data.tasksTag.length).toBe(5); expect(result.data.tasksTagDenied.length).toBe(1); expect(result.data.tasksCP.length).toBe(4); expect(result.data.tasksCPDenied.length).toBe(2); @@ -1101,7 +1096,7 @@ if (config.get('Butler.startTaskFilter.enable') === true) { expect(result.data.tasksId.started.length).toBe(3); expect(result.data.tasksId.invalid.length).toBe(1); expect(result.data.tasksId.denied.length).toBe(1); - expect(result.data.tasksTag.length).toBe(4); + expect(result.data.tasksTag.length).toBe(5); expect(result.data.tasksTagDenied.length).toBe(1); expect(result.data.tasksCP.length).toBe(4); expect(result.data.tasksCPDenied.length).toBe(2); diff --git a/src/test/routes/slackpostmessage.test.js b/src/test/routes/slackpostmessage.test.js index cc7939d6..b139b7fa 100644 --- a/src/test/routes/slackpostmessage.test.js +++ b/src/test/routes/slackpostmessage.test.js @@ -1,10 +1,6 @@ /* eslint-disable camelcase */ -const path = require('path'); -const axios = require('axios'); - -process.env.NODE_CONFIG_DIR = path.resolve('./src/config/'); -process.env.NODE_ENV = 'production'; -const config = require('config'); +import config from 'config'; +import axios from 'axios'; const instance = axios.create({ baseURL: `http://localhost:${config.get('Butler.restServerConfig.serverPort')}`, diff --git a/src/udp/index.js b/src/udp/index.js deleted file mode 100644 index 269c908b..00000000 --- a/src/udp/index.js +++ /dev/null @@ -1,4 +0,0 @@ -/* eslint-disable global-require */ -module.exports = { - udp: require('./udp_handlers'), -}; diff --git a/src/udp/udp_handlers.js b/src/udp/udp_handlers.js index fe0d658a..57e47f7e 100644 --- a/src/udp/udp_handlers.js +++ b/src/udp/udp_handlers.js @@ -1,17 +1,23 @@ // Load global variables and functions -const globals = require('../globals'); -const smtp = require('../lib/smtp'); -const slack = require('../lib/slack_notification'); -const webhookOut = require('../lib/webhook_notification'); -const msteams = require('../lib/msteams_notification'); -const signl4 = require('../lib/incident_mgmt/signl4'); -const newRelic = require('../lib/incident_mgmt/new_relic'); -const { failedTaskStoreLogOnDisk, getScriptLog, getReloadTaskExecutionResults } = require('../lib/scriptlog'); -const { getTaskTags } = require('../qrs_util/task_tag_util'); -const { getAppTags } = require('../qrs_util/app_tag_util'); -const { doesTaskExist } = require('../qrs_util/does_task_exist'); -const qrsUtil = require('../qrs_util'); -const { postReloadTaskFailureNotificationInfluxDb, postReloadTaskSuccessNotificationInfluxDb } = require('../lib/post_to_influxdb'); +import globals from '../globals.js'; +import { sendReloadTaskAbortedNotificationEmail, sendReloadTaskFailureNotificationEmail } from '../lib/smtp.js'; +import { sendReloadTaskFailureNotificationSlack, sendReloadTaskAbortedNotificationSlack } from '../lib/slack_notification.js'; +import { sendReloadTaskAbortedNotificationWebhook, sendReloadTaskFailureNotificationWebhook } from '../lib/webhook_notification.js'; +import { sendReloadTaskFailureNotificationTeams, sendReloadTaskAbortedNotificationTeams } from '../lib/msteams_notification.js'; +import { sendReloadTaskFailureNotification, sendReloadTaskAbortedNotification } from '../lib/incident_mgmt/signl4.js'; +import { + sendReloadTaskFailureLog, + sendReloadTaskFailureEvent, + sendReloadTaskAbortedLog, + sendReloadTaskAbortedEvent, +} from '../lib/incident_mgmt/new_relic.js'; +import { failedTaskStoreLogOnDisk, getScriptLog, getReloadTaskExecutionResults } from '../lib/scriptlog.js'; +import getTaskTags from '../qrs_util/task_tag_util.js'; +import getAppTags from '../qrs_util/app_tag_util.js'; +import doesTaskExist from '../qrs_util/does_task_exist.js'; +import { isCustomPropertyValueSet } from '../qrs_util/task_cp_util.js'; + +import { postReloadTaskFailureNotificationInfluxDb, postReloadTaskSuccessNotificationInfluxDb } from '../lib/post_to_influxdb.js'; // Handler for failed scheduler initiated reloads const schedulerAborted = async (msg) => { @@ -55,7 +61,7 @@ const schedulerAborted = async (msg) => { globals.config.get('Butler.incidentTool.signl4.enable') === true && globals.config.get('Butler.incidentTool.signl4.reloadTaskAborted.enable') === true ) { - signl4.sendReloadTaskAbortedNotification({ + sendReloadTaskAbortedNotification({ hostName: msg[1], user: msg[4].replace(/\\/g, '/'), taskName: msg[2], @@ -78,7 +84,7 @@ const schedulerAborted = async (msg) => { globals.config.get('Butler.incidentTool.newRelic.enable') === true && globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.enable') === true ) { - newRelic.sendReloadTaskAbortedEvent({ + sendReloadTaskAbortedEvent({ qs_hostName: msg[1], qs_user: msg[4].replace(/\\/g, '/'), qs_taskName: msg[2], @@ -101,7 +107,7 @@ const schedulerAborted = async (msg) => { globals.config.get('Butler.incidentTool.newRelic.enable') === true && globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.log.enable') === true ) { - newRelic.sendReloadTaskAbortedLog({ + sendReloadTaskAbortedLog({ qs_hostName: msg[1], qs_user: msg[4].replace(/\\/g, '/'), qs_taskName: msg[2], @@ -125,7 +131,7 @@ const schedulerAborted = async (msg) => { globals.config.get('Butler.slackNotification.enable') === true && globals.config.get('Butler.slackNotification.reloadTaskAborted.enable') === true ) { - slack.sendReloadTaskAbortedNotificationSlack({ + sendReloadTaskAbortedNotificationSlack({ hostName: msg[1], user: msg[4].replace(/\\/g, '/'), taskName: msg[2], @@ -149,7 +155,7 @@ const schedulerAborted = async (msg) => { globals.config.get('Butler.teamsNotification.enable') === true && globals.config.get('Butler.teamsNotification.reloadTaskAborted.enable') === true ) { - msteams.sendReloadTaskAbortedNotificationTeams({ + sendReloadTaskAbortedNotificationTeams({ hostName: msg[1], user: msg[4].replace(/\\/g, '/'), taskName: msg[2], @@ -173,7 +179,7 @@ const schedulerAborted = async (msg) => { globals.config.get('Butler.emailNotification.enable') === true && globals.config.get('Butler.emailNotification.reloadTaskAborted.enable') === true ) { - smtp.sendReloadTaskAbortedNotificationEmail({ + sendReloadTaskAbortedNotificationEmail({ hostName: msg[1], user: msg[4], taskName: msg[2], @@ -194,7 +200,7 @@ const schedulerAborted = async (msg) => { // Note that there is no enable/disable flag for failed reloads. // Whether alerts are sent or not is controlled by whether there are any webhook URLs or not if (globals.config.has('Butler.webhookNotification.enable') && globals.config.get('Butler.webhookNotification.enable') === true) { - webhookOut.sendReloadTaskAbortedNotificationWebhook({ + sendReloadTaskAbortedNotificationWebhook({ hostName: msg[1], user: msg[4], taskName: msg[2], @@ -306,7 +312,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.incidentTool.signl4.enable') === true && globals.config.get('Butler.incidentTool.signl4.reloadTaskFailure.enable') === true ) { - signl4.sendReloadTaskFailureNotification({ + sendReloadTaskFailureNotification({ hostName: msg[0], user: msg[3].replace(/\\/g, '/'), taskName: msg[1], @@ -327,7 +333,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.incidentTool.newRelic.enable') === true && globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.enable') === true ) { - newRelic.sendReloadTaskFailureEvent({ + sendReloadTaskFailureEvent({ qs_hostName: msg[0], qs_user: msg[3].replace(/\\/g, '/'), qs_taskName: msg[1], @@ -348,7 +354,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.incidentTool.newRelic.enable') === true && globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.log.enable') === true ) { - newRelic.sendReloadTaskFailureLog({ + sendReloadTaskFailureLog({ qs_hostName: msg[0], qs_user: msg[3].replace(/\\/g, '/'), qs_taskName: msg[1], @@ -370,7 +376,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.slackNotification.enable') === true && globals.config.get('Butler.slackNotification.reloadTaskFailure.enable') === true ) { - slack.sendReloadTaskFailureNotificationSlack({ + sendReloadTaskFailureNotificationSlack({ hostName: msg[0], user: msg[3].replace(/\\/g, '/'), taskName: msg[1], @@ -392,7 +398,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.teamsNotification.enable') === true && globals.config.get('Butler.teamsNotification.reloadTaskFailure.enable') === true ) { - msteams.sendReloadTaskFailureNotificationTeams({ + sendReloadTaskFailureNotificationTeams({ hostName: msg[0], user: msg[3].replace(/\\/g, '/'), taskName: msg[1], @@ -414,7 +420,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.emailNotification.enable') === true && globals.config.get('Butler.emailNotification.reloadTaskFailure.enable') === true ) { - smtp.sendReloadTaskFailureNotificationEmail({ + sendReloadTaskFailureNotificationEmail({ hostName: msg[0], user: msg[3].replace(/\\\\/g, '\\'), taskName: msg[1], @@ -436,7 +442,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.has('Butler.webhookNotification.reloadTaskFailure.enable') && globals.config.get('Butler.webhookNotification.reloadTaskFailure.enable') === true ) { - webhookOut.sendReloadTaskFailureNotificationWebhook({ + sendReloadTaskFailureNotificationWebhook({ hostName: msg[0], user: msg[3].replace(/\\\\/g, '\\'), taskName: msg[1], @@ -540,7 +546,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.incidentTool.signl4.enable') === true && globals.config.get('Butler.incidentTool.signl4.reloadTaskFailure.enable') === true ) { - signl4.sendReloadTaskFailureNotification({ + sendReloadTaskFailureNotification({ hostName: msg[1], user: msg[4].replace(/\\/g, '/'), taskName: msg[2], @@ -563,7 +569,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.incidentTool.newRelic.enable') === true && globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.enable') === true ) { - newRelic.sendReloadTaskFailureEvent({ + sendReloadTaskFailureEvent({ qs_hostName: msg[1], qs_user: msg[4].replace(/\\/g, '/'), qs_taskName: msg[2], @@ -586,7 +592,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.incidentTool.newRelic.enable') === true && globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.log.enable') === true ) { - newRelic.sendReloadTaskFailureLog({ + sendReloadTaskFailureLog({ qs_hostName: msg[1], qs_user: msg[4].replace(/\\/g, '/'), qs_taskName: msg[2], @@ -634,7 +640,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.slackNotification.enable') === true && globals.config.get('Butler.slackNotification.reloadTaskFailure.enable') === true ) { - slack.sendReloadTaskFailureNotificationSlack({ + sendReloadTaskFailureNotificationSlack({ hostName: msg[1], user: msg[4].replace(/\\/g, '/'), taskName: msg[2], @@ -658,7 +664,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.teamsNotification.enable') === true && globals.config.get('Butler.teamsNotification.reloadTaskFailure.enable') === true ) { - msteams.sendReloadTaskFailureNotificationTeams({ + sendReloadTaskFailureNotificationTeams({ hostName: msg[1], user: msg[4].replace(/\\/g, '/'), taskName: msg[2], @@ -682,7 +688,7 @@ const schedulerFailed = async (msg, legacyFlag) => { globals.config.get('Butler.emailNotification.enable') === true && globals.config.get('Butler.emailNotification.reloadTaskFailure.enable') === true ) { - smtp.sendReloadTaskFailureNotificationEmail({ + sendReloadTaskFailureNotificationEmail({ hostName: msg[1], user: msg[4].replace(/\\\\/g, '\\'), taskName: msg[2], @@ -703,7 +709,7 @@ const schedulerFailed = async (msg, legacyFlag) => { // Note that there is no enable/disable flag for failed reloads. // Whether alerts are sent or not is controlled by whether there are any webhook URLs or not if (globals.config.has('Butler.webhookNotification.enable') && globals.config.get('Butler.webhookNotification.enable') === true) { - webhookOut.sendReloadTaskFailureNotificationWebhook({ + sendReloadTaskFailureNotificationWebhook({ hostName: msg[1], user: msg[4].replace(/\\\\/g, '\\'), taskName: msg[2], @@ -802,7 +808,7 @@ const schedulerReloadTaskSuccess = async (msg) => { const customPropertyValue = globals.config.get('Butler.influxDb.reloadTaskSuccess.byCustomProperty.enabledValue'); // Get custom property value for this task - const customPropertyValueForTask = await qrsUtil.customPropertyUtil.isCustomPropertyValueSet( + const customPropertyValueForTask = await isCustomPropertyValueSet( reloadTaskId, customPropertyName, customPropertyValue, @@ -917,7 +923,7 @@ const schedulerReloadTaskSuccess = async (msg) => { // -------------------------------------------------------- // Set up UDP server handlers for acting on Sense failed task events // -------------------------------------------------------- -module.exports.udpInitTaskErrorServer = () => { +const udpInitTaskErrorServer = () => { // Handler for UDP server startup event // eslint-disable-next-line no-unused-vars globals.udpServerReloadTaskSocket.on('listening', (message, remote) => { @@ -1065,3 +1071,5 @@ module.exports.udpInitTaskErrorServer = () => { } }); }; + +export default udpInitTaskErrorServer; diff --git a/src/udp_client/udp_client.js b/src/udp_client/udp_client.js index 7d3d0f7e..07fef948 100644 --- a/src/udp_client/udp_client.js +++ b/src/udp_client/udp_client.js @@ -1,5 +1,5 @@ -const dgram = require('dgram'); -const yargs = require('yargs'); +import dgram from 'dgram'; +import yargs from 'yargs'; // Parse command line parameters const { argv } = yargs