resolve conflicts

This commit is contained in:
Alex Holliday committed 2026-03-03 22:04:59 +00:00
commit 298018035d
12 files changed
+820 -176

No files matched your search

+14
View File
@@ -1,6 +1,7 @@
import globals from "globals";
import pluginJs from "@eslint/js";
import mochaPlugin from "eslint-plugin-mocha";
import tseslint from "typescript-eslint";
/*
Please do not forget to look at the latest eslint configurations and rules.
@@ -10,6 +11,9 @@ ESlint v9 configuration is different than v8.
/** @type {import('eslint').Linter.Config[]} */
export default [
{
ignores: ["dist/**", "node_modules/**", "coverage/**", "test/**"],
},
{
languageOptions: {
globals: {
@@ -21,9 +25,19 @@ export default [
},
},
pluginJs.configs.recommended, // Core JS rules
...tseslint.configs.recommended, // TypeScript recommended rules
mochaPlugin.configs.flat.recommended, // Mocha rules
{
files: ["**/*.ts", "**/*.tsx"],
languageOptions: {
parser: tseslint.parser,
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
"@typescript-eslint/no-explicit-any": "warn", // Warn on 'any' types
"mocha/max-top-level-suites": "warn", // Warn if there are too many top-level suites instead of failing
},
},
+448 -4
View File
@@ -65,6 +65,8 @@
"@types/ping": "0.4.4",
"@types/swagger-ui-express": "4.1.8",
"@types/ws": "^8.18.1",
"@typescript-eslint/eslint-plugin": "^8.56.1",
"@typescript-eslint/parser": "^8.56.1",
"c8": "10.1.3",
"eslint": "^9.17.0",
"eslint-plugin-mocha": "^10.5.0",
@@ -78,7 +80,8 @@
"ts-node": "^10.9.2",
"tsc-alias": "1.8.16",
"tsx": "4.20.5",
"typescript": "5.9.2"
"typescript": "5.9.2",
"typescript-eslint": "^8.56.1"
},
"engines": {
"node": ">=20"
@@ -2045,9 +2048,9 @@
}
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
"integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
"integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4699,6 +4702,361 @@
"dev": true,
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz",
"integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/type-utils": "8.56.1",
"@typescript-eslint/utils": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.56.1",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz",
"integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1",
"debug": "^4.4.3"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/parser/node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz",
"integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.56.1",
"@typescript-eslint/types": "^8.56.1",
"debug": "^4.4.3"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/project-service/node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz",
"integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz",
"integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz",
"integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/utils": "8.56.1",
"debug": "^4.4.3",
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz",
"integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz",
"integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.56.1",
"@typescript-eslint/tsconfig-utils": "8.56.1",
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
"tinyglobby": "^0.2.15",
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
"dev": true,
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
"integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "10.2.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"brace-expansion": "^5.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz",
"integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz",
"integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.56.1",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@ungap/structured-clone": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
@@ -14263,6 +14621,55 @@
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==",
"license": "MIT"
},
"node_modules/tinyglobby": {
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
"picomatch": "^4.0.3"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tinyglobby/node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/tinyglobby/node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/tldts": {
"version": "6.1.86",
"resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz",
@@ -14352,6 +14759,19 @@
"node": ">= 14.0.0"
}
},
"node_modules/ts-api-utils": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
"integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18.12"
},
"peerDependencies": {
"typescript": ">=4.8.4"
}
},
"node_modules/ts-jest": {
"version": "29.4.6",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz",
@@ -14583,6 +15003,30 @@
"node": ">=14.17"
}
},
"node_modules/typescript-eslint": {
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.1.tgz",
"integrity": "sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.56.1",
"@typescript-eslint/parser": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/utils": "8.56.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/uglify-js": {
"version": "3.19.3",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
+4 -1
View File
@@ -80,6 +80,8 @@
"@types/ping": "0.4.4",
"@types/swagger-ui-express": "4.1.8",
"@types/ws": "^8.18.1",
"@typescript-eslint/eslint-plugin": "^8.56.1",
"@typescript-eslint/parser": "^8.56.1",
"c8": "10.1.3",
"eslint": "^9.17.0",
"eslint-plugin-mocha": "^10.5.0",
@@ -93,6 +95,7 @@
"ts-node": "^10.9.2",
"tsc-alias": "1.8.16",
"tsx": "4.20.5",
"typescript": "5.9.2"
"typescript": "5.9.2",
"typescript-eslint": "^8.56.1"
}
}
+3 -2
View File
@@ -29,7 +29,6 @@ import { NotificationMessageBuilder, INotificationMessageBuilder } from "../serv
import axios from "axios";
import got from "got";
import ping from "ping";
import http from "http";
import https from "https";
import Docker from "dockerode";
import net from "net";
@@ -151,7 +150,9 @@ export const initializeServices = async ({
got,
https,
jmespath,
GameDig,
GameDig as unknown as {
query: (options: { type: string; host: string; port?: number }) => Promise<{ ping?: number } & { [key: string]: unknown }>;
},
ping,
logger,
Docker,
@@ -282,7 +282,11 @@ class SuperSimpleQueue implements ISuperSimpleQueue {
};
obliterate = async () => {
console.log("obliterate not implemented");
this.logger.warn({
message: "obliterate method not implemented",
service: SERVICE_NAME,
method: "obliterate",
});
};
}
@@ -1,6 +1,17 @@
import { HTTPError, RequestError } from "got";
import type { Got, Response } from "got";
import type { Monitor, MonitorStatusResponse, GrpcStatusPayload } from "@/types/index.js";
import type {
Monitor,
MonitorStatusResponse,
GrpcStatusPayload,
PageSpeedStatusPayload,
HttpStatusPayload,
HardwareStatusPayload,
PingStatusPayload,
DockerStatusPayload,
PortStatusPayload,
GameStatusPayload,
} from "@/types/index.js";
import type { AxiosStatic } from "axios";
import { AppError } from "@/utils/AppError.js";
import path from "path";
@@ -27,8 +38,25 @@ interface BuildStatusResponseArgs<T> {
export interface INetworkService {
readonly serviceName: string;
requestStatus(monitor: Monitor): Promise<MonitorStatusResponse>;
requestWebhook(type: string, url: string, body: any): Promise<{ type: string; status: boolean; code: number; message: string; payload?: unknown }>;
requestStatus(
monitor: Monitor
): Promise<
MonitorStatusResponse<
| PingStatusPayload
| HttpStatusPayload
| PageSpeedStatusPayload
| HardwareStatusPayload
| DockerStatusPayload
| PortStatusPayload
| GameStatusPayload
| GrpcStatusPayload
>
>;
requestWebhook(
type: string,
url: string,
body: unknown
): Promise<{ type: string; status: boolean; code: number; message: string; payload?: unknown }>;
requestPagerDuty(args: { message: string; routingKey: string; monitorUrl: string }): Promise<boolean>;
requestMatrix(args: { homeserverUrl: string; accessToken: string; roomId: string; message: string }): Promise<{
status: boolean;
@@ -41,24 +69,31 @@ export interface INetworkService {
class NetworkService implements INetworkService {
static SERVICE_NAME = SERVICE_NAME;
private typeHandlers!: Record<string, (monitor: Monitor) => Promise<MonitorStatusResponse>>;
private TYPE_PING: string;
private TYPE_HTTP: string;
private TYPE_PAGESPEED: string;
private TYPE_HARDWARE: string;
private TYPE_DOCKER: string;
private TYPE_PORT: string;
private TYPE_GAME: string;
private TYPE_GRPC: string;
private SERVICE_NAME: string;
private NETWORK_ERROR: number;
private PING_ERROR: number;
private axios: AxiosStatic;
private got: Got;
private https: any;
private jmespath: any;
private GameDig: any;
private ping: any;
private https: typeof import("https");
private jmespath: { search: (data: unknown, expression: string) => unknown };
private GameDig: { query: (options: { type: string; host: string; port?: number }) => Promise<{ ping?: number } & { [key: string]: unknown }> };
private ping: typeof import("ping");
private logger: ILogger;
private Docker: any;
private net: any;
private Docker: typeof import("dockerode");
private net: typeof import("net");
private settingsService: ISettingsService;
private grpc: any;
private protoLoader: any;
private WebSocket: any;
private grpc: typeof import("@grpc/grpc-js");
private protoLoader: typeof import("@grpc/proto-loader");
private buildStatusResponse = <T>({
monitor,
@@ -93,7 +128,7 @@ class NetworkService implements INetworkService {
statusResponse.responseTime = error.timings?.phases?.total ?? 0;
statusResponse.timings = error.timings;
}
return { ...statusResponse, ...(overrides ?? {}) };
return { ...statusResponse, ...(overrides ?? {}) } as MonitorStatusResponse<T>;
}
return {
@@ -111,35 +146,32 @@ class NetworkService implements INetworkService {
expectedValue,
extracted,
...(overrides ?? {}),
};
} as MonitorStatusResponse<T>;
};
constructor(
axios: AxiosStatic,
got: Got,
https: any,
jmespath: any,
GameDig: any,
ping: any,
https: typeof import("https"),
jmespath: { search: (data: unknown, expression: string) => unknown },
GameDig: { query: (options: { type: string; host: string; port?: number }) => Promise<{ ping?: number } & { [key: string]: unknown }> },
ping: typeof import("ping"),
logger: ILogger,
Docker: any,
net: any,
Docker: typeof import("dockerode"),
net: typeof import("net"),
settingsService: ISettingsService,
grpc: any,
protoLoader: any,
WebSocket: any
WebSocket: any,
grpc: typeof import("@grpc/grpc-js"),
protoLoader: typeof import("@grpc/proto-loader")
) {
this.typeHandlers = {
ping: (m) => this.requestPing(m),
http: (m) => this.requestHttp(m),
pagespeed: (m) => this.requestPageSpeed(m),
hardware: (m) => this.requestHardware(m),
docker: (m) => this.requestDocker(m),
port: (m) => this.requestPort(m),
game: (m) => this.requestGame(m),
grpc: (m) => this.requestGrpc(m),
websocket: (m) => this.requestWebSocket(m),
};
this.TYPE_PING = "ping";
this.TYPE_HTTP = "http";
this.TYPE_PAGESPEED = "pagespeed";
this.TYPE_HARDWARE = "hardware";
this.TYPE_DOCKER = "docker";
this.TYPE_PORT = "port";
this.TYPE_GAME = "game";
this.TYPE_GRPC = "grpc";
this.SERVICE_NAME = SERVICE_NAME;
this.NETWORK_ERROR = 5000;
this.PING_ERROR = 5001;
@@ -185,13 +217,45 @@ class NetworkService implements INetworkService {
}
// Main entry point
async requestStatus(monitor: Monitor): Promise<MonitorStatusResponse> {
async requestStatus(
monitor: Monitor
): Promise<
MonitorStatusResponse<
| PingStatusPayload
| HttpStatusPayload
| PageSpeedStatusPayload
| HardwareStatusPayload
| DockerStatusPayload
| PortStatusPayload
| GameStatusPayload
| GrpcStatusPayload
>
> {
const type = monitor?.type || "unknown";
const handler = this.typeHandlers[type];
return handler ? handler(monitor) : this.handleUnsupportedType(type);
switch (type) {
case this.TYPE_PING:
return await this.requestPing(monitor);
case this.TYPE_HTTP:
return await this.requestHttp<HttpStatusPayload>(monitor);
case this.TYPE_PAGESPEED:
return await this.requestPageSpeed(monitor);
case this.TYPE_HARDWARE:
return await this.requestHardware(monitor);
case this.TYPE_DOCKER:
return await this.requestDocker(monitor);
case this.TYPE_PORT:
return await this.requestPort(monitor);
case this.TYPE_GAME:
return await this.requestGame(monitor);
case this.TYPE_GRPC:
return await this.requestGrpc(monitor);
default:
return this.handleUnsupportedType(type);
}
}
private async requestPing(monitor: Monitor): Promise<MonitorStatusResponse> {
private async requestPing(monitor: Monitor): Promise<MonitorStatusResponse<PingStatusPayload>> {
try {
if (!monitor?.url) {
throw new Error("Monitor URL is required");
@@ -211,36 +275,33 @@ class NetworkService implements INetworkService {
throw new Error("Ping failed - no result returned");
}
const pingResponse = this.buildStatusResponse({
const pingResponse = this.buildStatusResponse<PingStatusPayload>({
monitor,
payload: response,
payload: response as PingStatusPayload,
overrides: {
status: (response as { alive?: boolean })?.alive ?? false,
code: 200,
message: "Success",
responseTime: (response as { time?: number })?.time ?? 0,
payload: response,
},
payload: response as PingStatusPayload,
} as MonitorStatusResponseOverrides<PingStatusPayload>,
});
if (error) {
pingResponse.status = false;
pingResponse.code = this.PING_ERROR;
pingResponse.message = "Ping failed";
return pingResponse;
}
return pingResponse;
} catch (err: any) {
err.service = this.SERVICE_NAME;
err.method = "requestPing";
throw err;
} catch (err: unknown) {
const originalMessage = err instanceof Error ? err.message : String(err);
throw new AppError({
message: originalMessage || "Error performing ping",
service: this.SERVICE_NAME,
method: "requestPing",
details: { url: monitor.url },
});
}
}
private async requestHttp(monitor: Monitor): Promise<MonitorStatusResponse> {
const { url, secret, id, teamId, type, ignoreTlsErrors, useAdvancedMatching, jsonPath, matchMethod, expectedValue } = monitor;
const httpResponse = this.buildStatusResponse({
private async requestHttp<T = unknown>(monitor: Monitor): Promise<MonitorStatusResponse<T>> {
const { url, secret, ignoreTlsErrors, useAdvancedMatching, jsonPath, matchMethod, expectedValue } = monitor;
const httpResponse = this.buildStatusResponse<T>({
monitor,
overrides: {
status: false,
@@ -253,7 +314,7 @@ class NetworkService implements INetworkService {
if (!url) {
throw new Error("Monitor URL is required");
}
const config: Record<string, any> = {
const config: Record<string, unknown> = {
headers: secret ? { Authorization: `Bearer ${secret}` } : undefined,
};
@@ -267,7 +328,7 @@ class NetworkService implements INetworkService {
const response = await this.got(url, config);
let payload: any;
let payload: T | string | undefined;
const contentType = response.headers["content-type"];
if (contentType && contentType.includes("application/json")) {
@@ -355,23 +416,27 @@ class NetworkService implements INetworkService {
}
}
return httpResponse;
} catch (err: any) {
if (err.name === "HTTPError" || err.name === "RequestError") {
httpResponse.code = err?.response?.statusCode || this.NETWORK_ERROR;
} catch (err: unknown) {
if (err instanceof HTTPError || err instanceof RequestError) {
httpResponse.code = err.response?.statusCode || this.NETWORK_ERROR;
httpResponse.status = false;
httpResponse.message = err?.response?.statusCode || err.message;
httpResponse.responseTime = err?.timings?.phases?.total || 0;
httpResponse.message = String(err.response?.statusCode) || err.message;
httpResponse.responseTime = err.timings?.phases?.total || 0;
httpResponse.payload = null;
httpResponse.timings = err?.timings || {};
httpResponse.timings = err.timings || undefined;
return httpResponse;
}
err.service = this.SERVICE_NAME;
err.method = "requestHttp";
throw err;
const originalMessage = err instanceof Error ? err.message : String(err);
throw new AppError({
message: originalMessage || "Error performing HTTP request",
service: this.SERVICE_NAME,
method: "requestHttp",
details: { url: monitor.url },
});
}
}
private async requestPageSpeed(monitor: Monitor): Promise<MonitorStatusResponse> {
private async requestPageSpeed(monitor: Monitor): Promise<MonitorStatusResponse<PageSpeedStatusPayload>> {
try {
const url = monitor.url;
if (!url) {
@@ -389,28 +454,36 @@ class NetworkService implements INetworkService {
details: { url },
});
}
return await this.requestHttp({
return await this.requestHttp<PageSpeedStatusPayload>({
...monitor,
url: pageSpeedUrl,
});
} catch (err: any) {
err.service = this.SERVICE_NAME;
err.method = "requestPageSpeed";
throw err;
} catch (err: unknown) {
const originalMessage = err instanceof Error ? err.message : String(err);
throw new AppError({
message: originalMessage || "Error performing PageSpeed request",
service: this.SERVICE_NAME,
method: "requestPageSpeed",
details: { url: monitor.url },
});
}
}
private async requestHardware(monitor: Monitor): Promise<MonitorStatusResponse> {
private async requestHardware(monitor: Monitor): Promise<MonitorStatusResponse<HardwareStatusPayload>> {
try {
return await this.requestHttp(monitor);
} catch (err: any) {
err.service = this.SERVICE_NAME;
err.method = "requestHardware";
throw err;
return await this.requestHttp<HardwareStatusPayload>(monitor);
} catch (err: unknown) {
const originalMessage = err instanceof Error ? err.message : String(err);
throw new AppError({
message: originalMessage || "Error performing hardware request",
service: this.SERVICE_NAME,
method: "requestHardware",
details: { url: monitor.url },
});
}
}
private async requestDocker(monitor: Monitor): Promise<MonitorStatusResponse> {
private async requestDocker(monitor: Monitor): Promise<MonitorStatusResponse<DockerStatusPayload>> {
try {
if (!monitor.url) {
throw new Error("Monitor URL is required");
@@ -420,7 +493,7 @@ class NetworkService implements INetworkService {
socketPath: "/var/run/docker.sock",
});
const dockerResponse = this.buildStatusResponse({
const dockerResponse = this.buildStatusResponse<DockerStatusPayload>({
monitor,
overrides: {
status: false,
@@ -436,10 +509,10 @@ class NetworkService implements INetworkService {
// Priority-based matching to avoid ambiguity:
// 1. Exact full ID match (64-char)
let exactIdMatch = containers.find((c: any) => c.Id.toLowerCase() === normalizedInput);
const exactIdMatch = containers.find((c) => c.Id.toLowerCase() === normalizedInput);
// 2. Exact container name match (case-insensitive)
let exactNameMatch = containers.find((c: any) =>
const exactNameMatch = containers.find((c) =>
c.Names.some((name: string) => {
const cleanName = name.replace(/^\/+/, "").toLowerCase();
return cleanName === normalizedInput;
@@ -447,10 +520,10 @@ class NetworkService implements INetworkService {
);
// 3. Partial ID match (fallback for backwards compatibility)
let partialIdMatch = containers.find((c: any) => c.Id.toLowerCase().startsWith(normalizedInput));
const partialIdMatch = containers.find((c) => c.Id.toLowerCase().startsWith(normalizedInput));
// Select container based on priority
let targetContainer = exactIdMatch || exactNameMatch || partialIdMatch;
const targetContainer = exactIdMatch || exactNameMatch || partialIdMatch;
// Return negative response if no container
if (!targetContainer) {
@@ -486,9 +559,8 @@ class NetworkService implements INetworkService {
}
const container = docker.getContainer(targetContainer.Id);
const { response, responseTime, error }: { response?: any; responseTime?: number; error?: any } = await this.timeRequest(() =>
container.inspect()
);
const { response, responseTime, error }: { response?: { State: { Status: string } } | null; responseTime: number; error: unknown } =
await this.timeRequest(() => container.inspect());
dockerResponse.responseTime = responseTime;
dockerResponse.status = response?.State?.Status === "running" ? true : false;
@@ -497,20 +569,28 @@ class NetworkService implements INetworkService {
if (error) {
dockerResponse.status = false;
dockerResponse.code = error.statusCode || this.NETWORK_ERROR;
dockerResponse.message = error.reason || "Failed to fetch Docker container information";
dockerResponse.code =
(error && typeof error === "object" && "statusCode" in error ? (error as { statusCode?: number }).statusCode : undefined) ||
this.NETWORK_ERROR;
dockerResponse.message =
(error && typeof error === "object" && "reason" in error ? (error as { reason?: string }).reason : undefined) ||
"Failed to fetch Docker container information";
return dockerResponse;
}
return dockerResponse;
} catch (err: any) {
err.service = this.SERVICE_NAME;
err.method = "requestDocker";
throw err;
} catch (err: unknown) {
const originalMessage = err instanceof Error ? err.message : String(err);
throw new AppError({
message: originalMessage || "Error performing Docker request",
service: this.SERVICE_NAME,
method: "requestDocker",
details: { url: monitor.url },
});
}
}
private async requestPort(monitor: Monitor): Promise<MonitorStatusResponse> {
private async requestPort(monitor: Monitor): Promise<MonitorStatusResponse<PortStatusPayload>> {
try {
const { url, port } = monitor;
if (!port) {
@@ -537,14 +617,14 @@ class NetworkService implements INetworkService {
reject(new Error("Connection timeout"));
});
socket.on("error", (err: any) => {
socket.on("error", (err: unknown) => {
socket.destroy();
reject(err);
});
});
});
const portResponse = this.buildStatusResponse({
const portResponse = this.buildStatusResponse<PortStatusPayload>({
monitor,
overrides: {
code: 200,
@@ -562,18 +642,22 @@ class NetworkService implements INetworkService {
}
return portResponse;
} catch (error: any) {
error.service = this.SERVICE_NAME;
error.method = "requestTCP";
throw error;
} catch (err: unknown) {
const originalMessage = err instanceof Error ? err.message : String(err);
throw new AppError({
message: originalMessage || "Error performing port check",
service: this.SERVICE_NAME,
method: "requestPort",
details: { url: monitor.url, port: monitor.port },
});
}
}
private async requestGame(monitor: Monitor): Promise<MonitorStatusResponse> {
private async requestGame(monitor: Monitor): Promise<MonitorStatusResponse<GameStatusPayload>> {
try {
const { url, port, gameId } = monitor;
const gameResponse = this.buildStatusResponse({
const gameResponse = this.buildStatusResponse<GameStatusPayload>({
monitor,
overrides: {
code: 200,
@@ -586,13 +670,14 @@ class NetworkService implements INetworkService {
type: gameId ?? "unknown",
host: url,
port: port ?? 0,
}).catch((error: any) => {
}).catch((error: unknown): undefined => {
this.logger.warn({
message: error.message,
message: error instanceof Error ? error.message : String(error),
service: this.SERVICE_NAME,
method: "requestGame",
details: { url, port, gameId },
});
return undefined;
});
if (!state) {
@@ -602,16 +687,20 @@ class NetworkService implements INetworkService {
return gameResponse;
}
gameResponse.responseTime = state.ping;
gameResponse.payload = state;
gameResponse.responseTime = state.ping ?? 0;
gameResponse.payload = state as GameStatusPayload;
return gameResponse;
} catch (error: any) {
error.service = this.SERVICE_NAME;
error.method = "requestPing";
throw error;
} catch (err: unknown) {
const originalMessage = err instanceof Error ? err.message : String(err);
throw new AppError({
message: originalMessage || "Error performing game server check",
service: this.SERVICE_NAME,
method: "requestGame",
details: { url: monitor.url, port: monitor.port, gameId: monitor.gameId },
});
}
}
private async requestGrpc(monitor: Monitor): Promise<MonitorStatusResponse> {
private async requestGrpc(monitor: Monitor): Promise<MonitorStatusResponse<GrpcStatusPayload>> {
try {
const { url, port, ignoreTlsErrors } = monitor;
const grpcServiceName = monitor.grpcServiceName || "";
@@ -635,7 +724,21 @@ class NetworkService implements INetworkService {
defaults: true,
oneofs: true,
});
const grpcObject = this.grpc.loadPackageDefinition(packageDefinition);
const grpcObject = this.grpc.loadPackageDefinition(packageDefinition) as unknown as {
grpc: {
health: {
v1: {
Health: new (
target: string,
credentials: unknown
) => {
Check: (request: { service: string }, options: { deadline: Date }, callback: (err: unknown, response: unknown) => void) => void;
close: () => void;
};
};
};
};
};
const healthService = grpcObject.grpc.health.v1.Health;
let credentials;
@@ -652,7 +755,7 @@ class NetworkService implements INetworkService {
const TIMEOUT_MS = 10000;
const deadline = new Date(Date.now() + TIMEOUT_MS);
const grpcResponse = this.buildStatusResponse({
const grpcResponse = this.buildStatusResponse<GrpcStatusPayload>({
monitor,
overrides: {
status: false,
@@ -663,24 +766,30 @@ class NetworkService implements INetworkService {
const { response, responseTime, error } = await this.timeRequest<GrpcStatusPayload>(() => {
return new Promise<GrpcStatusPayload>((resolve, reject) => {
client.Check({ service: grpcServiceName }, { deadline }, (err: any, response: any) => {
client.Check({ service: grpcServiceName }, { deadline }, (err: unknown, response: unknown) => {
client.close();
if (err) {
const grpcErr = err as { code?: number; details?: string; message?: string };
const payload: GrpcStatusPayload = {
grpcStatusCode: err.code ?? -1,
grpcStatusName: this.getGrpcStatusName(err.code),
grpcStatusCode: grpcErr.code ?? -1,
grpcStatusName: this.getGrpcStatusName(grpcErr.code ?? -1),
serviceName: grpcServiceName,
servingStatus: "UNKNOWN",
};
const grpcError = new AppError({ message: err.details || err.message, service: this.SERVICE_NAME, method: "requestGrpc" });
(grpcError as any).grpcPayload = payload;
(grpcError as any).grpcCode = err.code;
const grpcError = new AppError({
message: grpcErr.details || grpcErr.message || "gRPC error",
service: this.SERVICE_NAME,
method: "requestGrpc",
}) as AppError & { grpcPayload?: GrpcStatusPayload; grpcCode?: number };
grpcError.grpcPayload = payload;
grpcError.grpcCode = grpcErr.code;
reject(grpcError);
return;
}
const servingStatus = response?.status || "UNKNOWN";
const resp = response as { status?: string } | undefined;
const servingStatus = resp?.status ?? "UNKNOWN";
resolve({
grpcStatusCode: 0,
grpcStatusName: "OK",
@@ -692,13 +801,13 @@ class NetworkService implements INetworkService {
});
if (error) {
const grpcError = error as any;
const payload = grpcError.grpcPayload as GrpcStatusPayload | undefined;
const grpcError = error as AppError & { grpcPayload?: GrpcStatusPayload; grpcCode?: number };
const payload = grpcError.grpcPayload;
grpcResponse.status = false;
grpcResponse.code = grpcError.grpcCode ?? this.NETWORK_ERROR;
grpcResponse.message = grpcError.message || "gRPC health check failed";
grpcResponse.message = grpcError.message ?? "gRPC health check failed";
grpcResponse.responseTime = responseTime;
grpcResponse.payload = payload || null;
grpcResponse.payload = payload ?? null;
return grpcResponse;
}
@@ -714,10 +823,14 @@ class NetworkService implements INetworkService {
grpcResponse.payload = grpcPayload;
return grpcResponse;
} catch (err: any) {
err.service = this.SERVICE_NAME;
err.method = "requestGrpc";
throw err;
} catch (err: unknown) {
const originalMessage = err instanceof Error ? err.message : String(err);
throw new AppError({
message: originalMessage || "Error performing gRPC health check",
service: this.SERVICE_NAME,
method: "requestGrpc",
details: { url: monitor.url, port: monitor.port, grpcServiceName: monitor.grpcServiceName },
});
}
}
@@ -822,7 +935,7 @@ class NetworkService implements INetworkService {
}
// Other network requests unrelated to monitoring:
async requestWebhook(type: string, url: string, body: any) {
async requestWebhook(type: string, url: string, body: unknown) {
try {
const response = await this.axios.post(url, body, {
headers: {
@@ -837,19 +950,29 @@ class NetworkService implements INetworkService {
message: `Successfully sent ${type} notification`,
payload: response.data,
};
} catch (error: any) {
} catch (err: unknown) {
this.logger.warn({
message: error.message,
message: err instanceof Error ? err.message : String(err),
service: this.SERVICE_NAME,
method: "requestWebhook",
});
if (err && typeof err === "object" && "response" in err) {
const axiosError = err as { response?: { status?: number; data?: unknown } };
return {
type: "webhook",
status: false,
code: axiosError.response?.status ?? this.NETWORK_ERROR,
message: `Failed to send ${type} notification`,
payload: axiosError.response?.data,
};
}
return {
type: "webhook",
status: false,
code: error.response?.status || this.NETWORK_ERROR,
code: this.NETWORK_ERROR,
message: `Failed to send ${type} notification`,
payload: error.response?.data,
};
}
}
@@ -869,11 +992,17 @@ class NetworkService implements INetworkService {
if (response?.data?.status !== "success") return false;
return true;
} catch (error: any) {
error.details = error.response?.data;
error.service = this.SERVICE_NAME;
error.method = "requestPagerDuty";
throw error;
} catch (err: unknown) {
const originalMessage = err instanceof Error ? err.message : String(err);
throw new AppError({
message: originalMessage || "Error sending PagerDuty notification",
service: this.SERVICE_NAME,
method: "requestPagerDuty",
details: {
responseData: err && typeof err === "object" && "response" in err ? (err as { response?: { data?: unknown } }).response?.data : undefined,
},
});
}
}
@@ -907,18 +1036,35 @@ class NetworkService implements INetworkService {
code: response.status,
message: "Successfully sent Matrix notification",
};
} catch (error: any) {
} catch (err: unknown) {
if (err instanceof Error) {
this.logger.warn({
message: err.message,
service: this.SERVICE_NAME,
method: "requestMatrix",
});
if (err && typeof err === "object" && "response" in err) {
const axiosError = err as { response?: { status?: number; data?: unknown } };
return {
status: false,
code: axiosError.response?.status || this.NETWORK_ERROR,
message: "Failed to send Matrix notification",
payload: axiosError.response?.data,
};
}
}
this.logger.warn({
message: error.message,
message: String(err),
service: this.SERVICE_NAME,
method: "requestMatrix",
});
return {
status: false,
code: error.response?.status || this.NETWORK_ERROR,
code: this.NETWORK_ERROR,
message: "Failed to send Matrix notification",
payload: error.response?.data,
};
}
}
@@ -7,6 +7,12 @@ import type {
Check,
HardwareStatusPayload,
PageSpeedStatusPayload,
PingStatusPayload,
HttpStatusPayload,
DockerStatusPayload,
PortStatusPayload,
GameStatusPayload,
GrpcStatusPayload,
CheckSnapshot,
MonitorStats,
} from "@/types/index.js";
@@ -17,7 +23,17 @@ export interface IStatusService {
updateRunningStats({ monitor, networkResponse }: { monitor: Monitor; networkResponse: any }): Promise<boolean>;
handleIncidentForCheck(check: any, monitor: Monitor, action: any, errorContext?: string): Promise<void>;
updateMonitorStatus(
statusResponse: MonitorStatusResponse<PageSpeedStatusPayload | HardwareStatusPayload | undefined>,
statusResponse: MonitorStatusResponse<
| PingStatusPayload
| HttpStatusPayload
| PageSpeedStatusPayload
| HardwareStatusPayload
| DockerStatusPayload
| PortStatusPayload
| GameStatusPayload
| GrpcStatusPayload
| undefined
>,
check: Check
): Promise<StatusChangeResult>;
}
@@ -205,7 +221,17 @@ export class StatusService implements IStatusService {
};
updateMonitorStatus = async (
statusResponse: MonitorStatusResponse<PageSpeedStatusPayload | HardwareStatusPayload | undefined>,
statusResponse: MonitorStatusResponse<
| PingStatusPayload
| HttpStatusPayload
| PageSpeedStatusPayload
| HardwareStatusPayload
| DockerStatusPayload
| PortStatusPayload
| GameStatusPayload
| GrpcStatusPayload
| undefined
>,
check: Check
): Promise<StatusChangeResult> => {
try {
+10 -1
View File
@@ -14,7 +14,16 @@ import type {
MonitorStatus,
} from "@/types/index.js";
export interface MonitorStatusResponse<T = any> {
export interface MonitorStatusResponse<
T =
| HttpStatusPayload
| PingStatusPayload
| PageSpeedStatusPayload
| HardwareStatusPayload
| DockerStatusPayload
| GameStatusPayload
| GrpcStatusPayload,
> {
monitorId: string;
teamId: string;
type: MonitorType;
+2 -2
View File
@@ -3,14 +3,14 @@ export interface AppErrorConfig {
status?: number;
service?: string | null;
method?: string | null;
details?: any;
details?: unknown;
}
export class AppError extends Error {
private status: number;
private service: string | null;
private method: string | null;
private details: any;
private details: unknown;
constructor({ message, status = 500, service = null, method = null, details = null }: AppErrorConfig) {
super(message);
+11 -15
View File
@@ -1,22 +1,18 @@
import sharp from "sharp";
const GenerateAvatarImage = async (file: Express.Multer.File) => {
try {
// Resize to target 64 * 64
let resizedImageBuffer = await sharp(file.buffer)
.resize({
width: 64,
height: 64,
fit: "cover",
})
.toBuffer();
// Resize to target 64 * 64
const resizedImageBuffer = await sharp(file.buffer)
.resize({
width: 64,
height: 64,
fit: "cover",
})
.toBuffer();
//Get b64 string
const base64Image = resizedImageBuffer.toString("base64");
return base64Image;
} catch (error) {
throw error;
}
//Get b64 string
const base64Image = resizedImageBuffer.toString("base64");
return base64Image;
};
export { GenerateAvatarImage };
+5 -5
View File
@@ -44,7 +44,7 @@ class Logger implements ILogger {
this.maxCacheSize = 1000;
const consoleFormat = format.printf((info: Logform.TransformableInfo) => {
const { level, service, method, details, timestamp, stack } = info;
let message = info.message as string;
const message = info.message as string;
let formattedMessage: string = message;
let formattedDetails: string | undefined;
@@ -57,10 +57,10 @@ class Logger implements ILogger {
}
let msg = `${timestamp} ${level}:`;
service && (msg += ` [${service}]`);
method && (msg += `(${method})`);
formattedMessage && (msg += ` ${formattedMessage}`);
formattedDetails && (msg += ` (details: ${formattedDetails})`);
if (service) msg += ` [${service}]`;
if (method) msg += `(${method})`;
if (formattedMessage) msg += ` ${formattedMessage}`;
if (formattedDetails) msg += ` (details: ${formattedDetails})`;
if (typeof stack === "string") {
const stackTrace = stack
+1
View File
@@ -8,6 +8,7 @@
},
"outDir": "./dist",
"strict": true,
"noImplicitAny": true,
"esModuleInterop": true,
"module": "nodenext",
"moduleResolution": "nodenext",