Added JSDoc to ESLint (#3529)

* Added JSDoc to eslint rules

Signed-off-by: Matthew Nickson <mnickson@sidingsmedia.com>

* Fixed JSDoc eslint errors

Signed-off-by: Matthew Nickson <mnickson@sidingsmedia.com>

* Update the check-linters workflow to Node.js 20

---------

Signed-off-by: Matthew Nickson <mnickson@sidingsmedia.com>
Co-authored-by: Louis Lam <louislam@users.noreply.github.com>
npm-publish
Matthew Nickson 1 year ago committed by GitHub
parent da4f4e3d76
commit 8a92054c2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -14,6 +14,7 @@ module.exports = {
extends: [ extends: [
"eslint:recommended", "eslint:recommended",
"plugin:vue/vue3-recommended", "plugin:vue/vue3-recommended",
"plugin:jsdoc/recommended-error",
], ],
parser: "vue-eslint-parser", parser: "vue-eslint-parser",
parserOptions: { parserOptions: {
@ -21,6 +22,9 @@ module.exports = {
sourceType: "module", sourceType: "module",
requireConfigFile: false, requireConfigFile: false,
}, },
plugins: [
"jsdoc"
],
rules: { rules: {
"yoda": "error", "yoda": "error",
eqeqeq: [ "warn", "smart" ], eqeqeq: [ "warn", "smart" ],
@ -97,7 +101,42 @@ module.exports = {
}], }],
"no-control-regex": "off", "no-control-regex": "off",
"one-var": [ "error", "never" ], "one-var": [ "error", "never" ],
"max-statements-per-line": [ "error", { "max": 1 }] "max-statements-per-line": [ "error", { "max": 1 }],
"jsdoc/check-tag-names": [
"error",
{
"definedTags": [ "link" ]
}
],
"jsdoc/no-undefined-types": "off",
"jsdoc/no-defaults": [
"error",
{ "noOptionalParamNames": true }
],
"jsdoc/require-throws": "error",
"jsdoc/require-jsdoc": [
"error",
{
"require": {
"FunctionDeclaration": true,
"MethodDefinition": true,
}
}
],
"jsdoc/no-blank-block-descriptions": "error",
"jsdoc/require-returns-check": [
"error",
{ "reportMissingReturnForUndefinedTypes": false }
],
"jsdoc/require-returns": [
"error",
{
"forceRequireReturn": true,
"forceReturnsWithAsync": true
}
],
"jsdoc/require-param-type": "error",
"jsdoc/require-param-description": "error"
}, },
"overrides": [ "overrides": [
{ {

@ -71,10 +71,10 @@ jobs:
- run: git config --global core.autocrlf false # Mainly for Windows - run: git config --global core.autocrlf false # Mainly for Windows
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Use Node.js 14 - name: Use Node.js 20
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 14 node-version: 20
- run: npm install - run: npm install
- run: npm run lint - run: npm run lint

@ -36,6 +36,8 @@ if (! exists) {
/** /**
* Commit updated files * Commit updated files
* @param {string} version Version to update to * @param {string} version Version to update to
* @returns {void}
* @throws Error committing files
*/ */
function commit(version) { function commit(version) {
let msg = "Update to " + version; let msg = "Update to " + version;
@ -55,6 +57,7 @@ function commit(version) {
/** /**
* Create a tag with the specified version * Create a tag with the specified version
* @param {string} version Tag to create * @param {string} version Tag to create
* @returns {void}
*/ */
function tag(version) { function tag(version) {
let res = childProcess.spawnSync("git", [ "tag", version ]); let res = childProcess.spawnSync("git", [ "tag", version ]);
@ -68,6 +71,7 @@ function tag(version) {
* Check if a tag exists for the specified version * Check if a tag exists for the specified version
* @param {string} version Version to check * @param {string} version Version to check
* @returns {boolean} Does the tag already exist * @returns {boolean} Does the tag already exist
* @throws Version is not valid
*/ */
function tagExists(version) { function tagExists(version) {
if (! version) { if (! version) {

@ -15,6 +15,7 @@ download(url);
/** /**
* Downloads the latest version of the dist from a GitHub release. * Downloads the latest version of the dist from a GitHub release.
* @param {string} url The URL to download from. * @param {string} url The URL to download from.
* @returns {void}
* *
* Generated by Trelent * Generated by Trelent
*/ */

@ -4,12 +4,12 @@ const fs = require("fs");
* to avoid the runtime deprecation warning triggered for using `fs.rmdirSync` with `{ recursive: true }` in Node.js v16, * to avoid the runtime deprecation warning triggered for using `fs.rmdirSync` with `{ recursive: true }` in Node.js v16,
* or the `recursive` property removing completely in the future Node.js version. * or the `recursive` property removing completely in the future Node.js version.
* See the link below. * See the link below.
*
* @todo Once we drop the support for Node.js v14 (or at least versions before v14.14.0), we can safely replace this function with `fs.rmSync`, since `fs.rmSync` was add in Node.js v14.14.0 and currently we supports all the Node.js v14 versions that include the versions before the v14.14.0, and this function have almost the same signature with `fs.rmSync`. * @todo Once we drop the support for Node.js v14 (or at least versions before v14.14.0), we can safely replace this function with `fs.rmSync`, since `fs.rmSync` was add in Node.js v14.14.0 and currently we supports all the Node.js v14 versions that include the versions before the v14.14.0, and this function have almost the same signature with `fs.rmSync`.
* @link https://nodejs.org/docs/latest-v16.x/api/deprecations.html#dep0147-fsrmdirpath--recursive-true- the deprecation infomation of `fs.rmdirSync` * @link https://nodejs.org/docs/latest-v16.x/api/deprecations.html#dep0147-fsrmdirpath--recursive-true- the deprecation infomation of `fs.rmdirSync`
* @link https://nodejs.org/docs/latest-v16.x/api/fs.html#fsrmsyncpath-options the document of `fs.rmSync` * @link https://nodejs.org/docs/latest-v16.x/api/fs.html#fsrmsyncpath-options the document of `fs.rmSync`
* @param {fs.PathLike} path Valid types for path values in "fs". * @param {fs.PathLike} path Valid types for path values in "fs".
* @param {fs.RmDirOptions} [options] options for `fs.rmdirSync`, if `fs.rmSync` is available and property `recursive` is true, it will automatically have property `force` with value `true`. * @param {fs.RmDirOptions} options options for `fs.rmdirSync`, if `fs.rmSync` is available and property `recursive` is true, it will automatically have property `force` with value `true`.
* @returns {void}
*/ */
const rmSync = (path, options) => { const rmSync = (path, options) => {
if (typeof fs.rmSync === "function") { if (typeof fs.rmSync === "function") {

@ -138,7 +138,7 @@ server.listen({
/** /**
* Get human readable request type from request code * Get human readable request type from request code
* @param {number} code Request code to translate * @param {number} code Request code to translate
* @returns {string} Human readable request type * @returns {string|void} Human readable request type
*/ */
function type(code) { function type(code) {
for (let name in Packet.TYPE) { for (let name in Packet.TYPE) {

@ -7,11 +7,17 @@ class SimpleMqttServer {
aedes = require("aedes")(); aedes = require("aedes")();
server = require("net").createServer(this.aedes.handle); server = require("net").createServer(this.aedes.handle);
/**
* @param {number} port Port to listen on
*/
constructor(port) { constructor(port) {
this.port = port; this.port = port;
} }
/** Start the MQTT server */ /**
* Start the MQTT server
* @returns {void}
*/
start() { start() {
this.server.listen(this.port, () => { this.server.listen(this.port, () => {
console.log("server started and listening on port ", this.port); console.log("server started and listening on port ", this.port);

@ -12,6 +12,7 @@ import rmSync from "../fs-rmSync.js";
* created with this code if one does not already exist * created with this code if one does not already exist
* @param {string} baseLang The second base language file to copy. This * @param {string} baseLang The second base language file to copy. This
* will be ignored if set to "en" as en.js is copied by default * will be ignored if set to "en" as en.js is copied by default
* @returns {void}
*/ */
function copyFiles(langCode, baseLang) { function copyFiles(langCode, baseLang) {
if (fs.existsSync("./languages")) { if (fs.existsSync("./languages")) {
@ -33,7 +34,8 @@ function copyFiles(langCode, baseLang) {
/** /**
* Update the specified language file * Update the specified language file
* @param {string} langCode Language code to update * @param {string} langCode Language code to update
* @param {string} baseLang Second language to copy keys from * @param {string} baseLangCode Second language to copy keys from
* @returns {void}
*/ */
async function updateLanguage(langCode, baseLangCode) { async function updateLanguage(langCode, baseLangCode) {
const en = (await import("./languages/en.js")).default; const en = (await import("./languages/en.js")).default;

@ -39,6 +39,8 @@ if (! exists) {
/** /**
* Commit updated files * Commit updated files
* @param {string} version Version to update to * @param {string} version Version to update to
* @returns {void}
* @throws Error when committing files
*/ */
function commit(version) { function commit(version) {
let msg = "Update to " + version; let msg = "Update to " + version;
@ -55,6 +57,7 @@ function commit(version) {
/** /**
* Create a tag with the specified version * Create a tag with the specified version
* @param {string} version Tag to create * @param {string} version Tag to create
* @returns {void}
*/ */
function tag(version) { function tag(version) {
let res = childProcess.spawnSync("git", [ "tag", version ]); let res = childProcess.spawnSync("git", [ "tag", version ]);
@ -65,6 +68,7 @@ function tag(version) {
* Check if a tag exists for the specified version * Check if a tag exists for the specified version
* @param {string} version Version to check * @param {string} version Version to check
* @returns {boolean} Does the tag already exist * @returns {boolean} Does the tag already exist
* @throws Version is not valid
*/ */
function tagExists(version) { function tagExists(version) {
if (! version) { if (! version) {

@ -13,6 +13,7 @@ updateWiki(newVersion);
/** /**
* Update the wiki with new version number * Update the wiki with new version number
* @param {string} newVersion Version to update to * @param {string} newVersion Version to update to
* @returns {void}
*/ */
function updateWiki(newVersion) { function updateWiki(newVersion) {
const wikiDir = "./tmp/wiki"; const wikiDir = "./tmp/wiki";
@ -46,6 +47,7 @@ function updateWiki(newVersion) {
/** /**
* Check if a directory exists and then delete it * Check if a directory exists and then delete it
* @param {string} dir Directory to delete * @param {string} dir Directory to delete
* @returns {void}
*/ */
function safeDelete(dir) { function safeDelete(dir) {
if (fs.existsSync(dir)) { if (fs.existsSync(dir)) {

104
package-lock.json generated

@ -103,6 +103,7 @@
"dns2": "~2.0.1", "dns2": "~2.0.1",
"dompurify": "~2.4.3", "dompurify": "~2.4.3",
"eslint": "~8.14.0", "eslint": "~8.14.0",
"eslint-plugin-jsdoc": "^46.4.6",
"eslint-plugin-vue": "~8.7.1", "eslint-plugin-vue": "~8.7.1",
"favico.js": "~0.3.10", "favico.js": "~0.3.10",
"jest": "~29.6.1", "jest": "~29.6.1",
@ -3456,6 +3457,20 @@
"ms": "^2.1.1" "ms": "^2.1.1"
} }
}, },
"node_modules/@es-joy/jsdoccomment": {
"version": "0.40.1",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz",
"integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==",
"dev": true,
"dependencies": {
"comment-parser": "1.4.0",
"esquery": "^1.5.0",
"jsdoc-type-pratt-parser": "~4.0.0"
},
"engines": {
"node": ">=16"
}
},
"node_modules/@esbuild/android-arm": { "node_modules/@esbuild/android-arm": {
"version": "0.18.20", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
@ -6227,6 +6242,15 @@
} }
] ]
}, },
"node_modules/are-docs-informative": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
"integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
"dev": true,
"engines": {
"node": ">=14"
}
},
"node_modules/are-we-there-yet": { "node_modules/are-we-there-yet": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
@ -6992,6 +7016,18 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/builtin-modules": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
"integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
"dev": true,
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/bulk-write-stream": { "node_modules/bulk-write-stream": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/bulk-write-stream/-/bulk-write-stream-2.0.1.tgz", "resolved": "https://registry.npmjs.org/bulk-write-stream/-/bulk-write-stream-2.0.1.tgz",
@ -7533,6 +7569,15 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/comment-parser": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz",
"integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==",
"dev": true,
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/commist": { "node_modules/commist": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz",
@ -8967,6 +9012,41 @@
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/eslint-plugin-jsdoc": {
"version": "46.4.6",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.6.tgz",
"integrity": "sha512-z4SWYnJfOqftZI+b3RM9AtWL1vF/sLWE/LlO9yOKDof9yN2+n3zOdOJTGX/pRE/xnPsooOLG2Rq6e4d+XW3lNw==",
"dev": true,
"dependencies": {
"@es-joy/jsdoccomment": "~0.40.1",
"are-docs-informative": "^0.0.2",
"comment-parser": "1.4.0",
"debug": "^4.3.4",
"escape-string-regexp": "^4.0.0",
"esquery": "^1.5.0",
"is-builtin-module": "^3.2.1",
"semver": "^7.5.4",
"spdx-expression-parse": "^3.0.1"
},
"engines": {
"node": ">=16"
},
"peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0"
}
},
"node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint-plugin-vue": { "node_modules/eslint-plugin-vue": {
"version": "8.7.1", "version": "8.7.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz",
@ -10845,6 +10925,21 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/is-builtin-module": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
"integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
"dev": true,
"dependencies": {
"builtin-modules": "^3.3.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-callable": { "node_modules/is-callable": {
"version": "1.2.7", "version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@ -13025,6 +13120,15 @@
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
"dev": true "dev": true
}, },
"node_modules/jsdoc-type-pratt-parser": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
"integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
"dev": true,
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/jsesc": { "node_modules/jsesc": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",

@ -165,6 +165,7 @@
"dns2": "~2.0.1", "dns2": "~2.0.1",
"dompurify": "~2.4.3", "dompurify": "~2.4.3",
"eslint": "~8.14.0", "eslint": "~8.14.0",
"eslint-plugin-jsdoc": "^46.4.6",
"eslint-plugin-vue": "~8.7.1", "eslint-plugin-vue": "~8.7.1",
"favico.js": "~0.3.10", "favico.js": "~0.3.10",
"jest": "~29.6.1", "jest": "~29.6.1",

@ -9,9 +9,9 @@ const dayjs = require("dayjs");
/** /**
* Login to web app * Login to web app
* @param {string} username * @param {string} username Username to login with
* @param {string} password * @param {string} password Password to login with
* @returns {Promise<(Bean|null)>} * @returns {Promise<(Bean|null)>} User or null if login failed
*/ */
exports.login = async function (username, password) { exports.login = async function (username, password) {
if (typeof username !== "string" || typeof password !== "string") { if (typeof username !== "string" || typeof password !== "string") {
@ -39,6 +39,7 @@ exports.login = async function (username, password) {
/** /**
* Validate a provided API key * Validate a provided API key
* @param {string} key API key to verify * @param {string} key API key to verify
* @returns {boolean} API is ok?
*/ */
async function verifyAPIKey(key) { async function verifyAPIKey(key) {
if (typeof key !== "string") { if (typeof key !== "string") {
@ -73,9 +74,10 @@ async function verifyAPIKey(key) {
/** /**
* Custom authorizer for express-basic-auth * Custom authorizer for express-basic-auth
* @param {string} username * @param {string} username Username to login with
* @param {string} password * @param {string} password Password to login with
* @param {authCallback} callback * @param {authCallback} callback Callback to handle login result
* @returns {void}
*/ */
function apiAuthorizer(username, password, callback) { function apiAuthorizer(username, password, callback) {
// API Rate Limit // API Rate Limit
@ -99,9 +101,10 @@ function apiAuthorizer(username, password, callback) {
/** /**
* Custom authorizer for express-basic-auth * Custom authorizer for express-basic-auth
* @param {string} username * @param {string} username Username to login with
* @param {string} password * @param {string} password Password to login with
* @param {authCallback} callback * @param {authCallback} callback Callback to handle login result
* @returns {void}
*/ */
function userAuthorizer(username, password, callback) { function userAuthorizer(username, password, callback) {
// Login Rate Limit // Login Rate Limit
@ -126,7 +129,8 @@ function userAuthorizer(username, password, callback) {
* Use basic auth if auth is not disabled * Use basic auth if auth is not disabled
* @param {express.Request} req Express request object * @param {express.Request} req Express request object
* @param {express.Response} res Express response object * @param {express.Response} res Express response object
* @param {express.NextFunction} next * @param {express.NextFunction} next Next handler in chain
* @returns {void}
*/ */
exports.basicAuth = async function (req, res, next) { exports.basicAuth = async function (req, res, next) {
const middleware = basicAuth({ const middleware = basicAuth({
@ -148,7 +152,8 @@ exports.basicAuth = async function (req, res, next) {
* Use use API Key if API keys enabled, else use basic auth * Use use API Key if API keys enabled, else use basic auth
* @param {express.Request} req Express request object * @param {express.Request} req Express request object
* @param {express.Response} res Express response object * @param {express.Response} res Express response object
* @param {express.NextFunction} next * @param {express.NextFunction} next Next handler in chain
* @returns {void}
*/ */
exports.apiAuth = async function (req, res, next) { exports.apiAuth = async function (req, res, next) {
if (!await Settings.get("disableAuth")) { if (!await Settings.get("disableAuth")) {

@ -15,6 +15,7 @@ class CacheableDnsHttpAgent {
/** /**
* Register/Disable cacheable to global agents * Register/Disable cacheable to global agents
* @returns {void}
*/ */
static async update() { static async update() {
log.debug("CacheableDnsHttpAgent", "update"); log.debug("CacheableDnsHttpAgent", "update");
@ -40,14 +41,15 @@ class CacheableDnsHttpAgent {
/** /**
* Attach cacheable to HTTP agent * Attach cacheable to HTTP agent
* @param {http.Agent} agent Agent to install * @param {http.Agent} agent Agent to install
* @returns {void}
*/ */
static install(agent) { static install(agent) {
this.cacheable.install(agent); this.cacheable.install(agent);
} }
/** /**
* @var {https.AgentOptions} agentOptions * @param {https.AgentOptions} agentOptions Options to pass to HTTPS agent
* @return {https.Agent} * @returns {https.Agent} The new HTTPS agent
*/ */
static getHttpsAgent(agentOptions) { static getHttpsAgent(agentOptions) {
if (!this.enable) { if (!this.enable) {
@ -63,8 +65,8 @@ class CacheableDnsHttpAgent {
} }
/** /**
* @var {http.AgentOptions} agentOptions * @param {http.AgentOptions} agentOptions Options to pass to the HTTP agent
* @return {https.Agents} * @returns {https.Agents} The new HTTP agent
*/ */
static getHttpAgent(agentOptions) { static getHttpAgent(agentOptions) {
if (!this.enable) { if (!this.enable) {

@ -12,7 +12,7 @@ const checkVersion = require("./check-version");
/** /**
* Send list of notification providers to client * Send list of notification providers to client
* @param {Socket} socket Socket.io socket instance * @param {Socket} socket Socket.io socket instance
* @returns {Promise<Bean[]>} * @returns {Promise<Bean[]>} List of notifications
*/ */
async function sendNotificationList(socket) { async function sendNotificationList(socket) {
const timeLogger = new TimeLogger(); const timeLogger = new TimeLogger();
@ -40,8 +40,8 @@ async function sendNotificationList(socket) {
* Send Heartbeat History list to socket * Send Heartbeat History list to socket
* @param {Socket} socket Socket.io instance * @param {Socket} socket Socket.io instance
* @param {number} monitorID ID of monitor to send heartbeat history * @param {number} monitorID ID of monitor to send heartbeat history
* @param {boolean} [toUser=false] True = send to all browsers with the same user id, False = send to the current browser only * @param {boolean} toUser True = send to all browsers with the same user id, False = send to the current browser only
* @param {boolean} [overwrite=false] Overwrite client-side's heartbeat list * @param {boolean} overwrite Overwrite client-side's heartbeat list
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite = false) { async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite = false) {
@ -71,8 +71,8 @@ async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite =
* Important Heart beat list (aka event list) * Important Heart beat list (aka event list)
* @param {Socket} socket Socket.io instance * @param {Socket} socket Socket.io instance
* @param {number} monitorID ID of monitor to send heartbeat history * @param {number} monitorID ID of monitor to send heartbeat history
* @param {boolean} [toUser=false] True = send to all browsers with the same user id, False = send to the current browser only * @param {boolean} toUser True = send to all browsers with the same user id, False = send to the current browser only
* @param {boolean} [overwrite=false] Overwrite client-side's heartbeat list * @param {boolean} overwrite Overwrite client-side's heartbeat list
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async function sendImportantHeartbeatList(socket, monitorID, toUser = false, overwrite = false) { async function sendImportantHeartbeatList(socket, monitorID, toUser = false, overwrite = false) {
@ -100,7 +100,7 @@ async function sendImportantHeartbeatList(socket, monitorID, toUser = false, ove
/** /**
* Emit proxy list to client * Emit proxy list to client
* @param {Socket} socket Socket.io socket instance * @param {Socket} socket Socket.io socket instance
* @return {Promise<Bean[]>} * @returns {Promise<Bean[]>} List of proxies
*/ */
async function sendProxyList(socket) { async function sendProxyList(socket) {
const timeLogger = new TimeLogger(); const timeLogger = new TimeLogger();
@ -141,7 +141,7 @@ async function sendAPIKeyList(socket) {
/** /**
* Emits the version information to the client. * Emits the version information to the client.
* @param {Socket} socket Socket.io socket instance * @param {Socket} socket Socket.io socket instance
* @param {boolean} hideVersion * @param {boolean} hideVersion Should we hide the version information in the response?
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async function sendInfo(socket, hideVersion = false) { async function sendInfo(socket, hideVersion = false) {
@ -165,7 +165,7 @@ async function sendInfo(socket, hideVersion = false) {
/** /**
* Send list of docker hosts to client * Send list of docker hosts to client
* @param {Socket} socket Socket.io socket instance * @param {Socket} socket Socket.io socket instance
* @returns {Promise<Bean[]>} * @returns {Promise<Bean[]>} List of docker hosts
*/ */
async function sendDockerHostList(socket) { async function sendDockerHostList(socket) {
const timeLogger = new TimeLogger(); const timeLogger = new TimeLogger();

@ -101,7 +101,8 @@ class Database {
/** /**
* Initialize the data directory * Initialize the data directory
* @param {Object} args Arguments to initialize DB with * @param {object} args Arguments to initialize DB with
* @returns {void}
*/ */
static initDataDir(args) { static initDataDir(args) {
// Data Directory (must be end with "/") // Data Directory (must be end with "/")
@ -154,11 +155,11 @@ class Database {
/** /**
* Connect to the database * Connect to the database
* @param {boolean} [testMode=false] Should the connection be * @param {boolean} testMode Should the connection be
* started in test mode? * started in test mode?
* @param {boolean} [autoloadModels=true] Should models be * @param {boolean} autoloadModels Should models be
* automatically loaded? * automatically loaded?
* @param {boolean} [noLog=false] Should logs not be output? * @param {boolean} noLog Should logs not be output?
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static async connect(testMode = false, autoloadModels = true, noLog = false) { static async connect(testMode = false, autoloadModels = true, noLog = false) {
@ -312,6 +313,10 @@ class Database {
} }
} }
/**
* Patch the database
* @returns {void}
*/
static async patch() { static async patch() {
// Still need to keep this for old versions of Uptime Kuma // Still need to keep this for old versions of Uptime Kuma
if (Database.dbConfig.type === "sqlite") { if (Database.dbConfig.type === "sqlite") {
@ -497,8 +502,8 @@ class Database {
* Patch database using new patching process * Patch database using new patching process
* Used it patch2() only * Used it patch2() only
* @private * @private
* @param sqlFilename * @param {string} sqlFilename Name of SQL file to load
* @param databasePatchedFiles * @param {object} databasePatchedFiles Patch status of database files
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static async patch2Recursion(sqlFilename, databasePatchedFiles) { static async patch2Recursion(sqlFilename, databasePatchedFiles) {
@ -533,7 +538,7 @@ class Database {
/** /**
* Load an SQL file and execute it * Load an SQL file and execute it
* @param filename Filename of SQL file to import * @param {string} filename Filename of SQL file to import
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static async importSQLFile(filename) { static async importSQLFile(filename) {
@ -567,7 +572,7 @@ class Database {
/** /**
* Aquire a direct connection to database * Aquire a direct connection to database
* @returns {any} * @returns {any} Database connection
*/ */
static getBetterSQLite3Database() { static getBetterSQLite3Database() {
return R.knex.client.acquireConnection(); return R.knex.client.acquireConnection();
@ -604,7 +609,10 @@ class Database {
process.removeListener("unhandledRejection", listener); process.removeListener("unhandledRejection", listener);
} }
/** Get the size of the database */ /**
* Get the size of the database
* @returns {number} Size of database
*/
static getSize() { static getSize() {
log.debug("db", "Database.getSize()"); log.debug("db", "Database.getSize()");
let stats = fs.statSync(Database.sqlitePath); let stats = fs.statSync(Database.sqlitePath);

@ -14,10 +14,10 @@ class DockerHost {
/** /**
* Save a docker host * Save a docker host
* @param {Object} dockerHost Docker host to save * @param {object} dockerHost Docker host to save
* @param {?number} dockerHostID ID of the docker host to update * @param {?number} dockerHostID ID of the docker host to update
* @param {number} userID ID of the user who adds the docker host * @param {number} userID ID of the user who adds the docker host
* @returns {Promise<Bean>} * @returns {Promise<Bean>} Updated docker host
*/ */
static async save(dockerHost, dockerHostID, userID) { static async save(dockerHost, dockerHostID, userID) {
let bean; let bean;
@ -64,7 +64,7 @@ class DockerHost {
/** /**
* Fetches the amount of containers on the Docker host * Fetches the amount of containers on the Docker host
* @param {Object} dockerHost Docker host to check for * @param {object} dockerHost Docker host to check for
* @returns {number} Total amount of containers on the host * @returns {number} Total amount of containers on the host
*/ */
static async testDockerHost(dockerHost) { static async testDockerHost(dockerHost) {
@ -108,6 +108,8 @@ class DockerHost {
/** /**
* Since axios 0.27.X, it does not accept `tcp://` protocol. * Since axios 0.27.X, it does not accept `tcp://` protocol.
* Change it to `http://` on the fly in order to fix it. (https://github.com/louislam/uptime-kuma/issues/2165) * Change it to `http://` on the fly in order to fix it. (https://github.com/louislam/uptime-kuma/issues/2165)
* @param {any} url URL to fix
* @returns {any} URL with tcp:// replaced by http://
*/ */
static patchDockerURL(url) { static patchDockerURL(url) {
if (typeof url === "string") { if (typeof url === "string") {
@ -129,11 +131,10 @@ class DockerHost {
* 'data/docker-tls/example.com/' would be searched for certificate files), * 'data/docker-tls/example.com/' would be searched for certificate files),
* then 'ca.pem', 'key.pem' and 'cert.pem' files are included in the agent options. * then 'ca.pem', 'key.pem' and 'cert.pem' files are included in the agent options.
* File names can also be overridden via 'DOCKER_TLS_FILE_NAME_(CA|KEY|CERT)'. * File names can also be overridden via 'DOCKER_TLS_FILE_NAME_(CA|KEY|CERT)'.
* * @param {string} dockerType i.e. "tcp" or "socket"
* @param {String} dockerType i.e. "tcp" or "socket" * @param {string} url The docker host URL rewritten to https://
* @param {String} url The docker host URL rewritten to https:// * @returns {object} HTTP agent options
* @return {Object} */
* */
static getHttpsAgentOptions(dockerType, url) { static getHttpsAgentOptions(dockerType, url) {
let baseOptions = { let baseOptions = {
maxCachedSessions: 0, maxCachedSessions: 0,

@ -3,8 +3,8 @@ const jsesc = require("jsesc");
/** /**
* Returns a string that represents the javascript that is required to insert the Google Analytics scripts * Returns a string that represents the javascript that is required to insert the Google Analytics scripts
* into a webpage. * into a webpage.
* @param tagId Google UA/G/AW/DC Property ID to use with the Google Analytics script. * @param {string} tagId Google UA/G/AW/DC Property ID to use with the Google Analytics script.
* @returns {string} * @returns {string} HTML script tags to inject into page
*/ */
function getGoogleAnalyticsScript(tagId) { function getGoogleAnalyticsScript(tagId) {
let escapedTagId = jsesc(tagId, { isScriptContext: true }); let escapedTagId = jsesc(tagId, { isScriptContext: true });

@ -10,7 +10,7 @@ let ImageDataURI = (() => {
/** /**
* Decode the data:image/ URI * Decode the data:image/ URI
* @param {string} dataURI data:image/ URI to decode * @param {string} dataURI data:image/ URI to decode
* @returns {?Object} An object with properties "imageType" and "dataBase64". * @returns {?object} An object with properties "imageType" and "dataBase64".
* The former is the image type, e.g., "png", and the latter is a base64 * The former is the image type, e.g., "png", and the latter is a base64
* encoded string of the image's binary data. If it fails to parse, returns * encoded string of the image's binary data. If it fails to parse, returns
* null instead of an object. * null instead of an object.
@ -52,8 +52,8 @@ let ImageDataURI = (() => {
/** /**
* Write data URI to file * Write data URI to file
* @param {string} dataURI data:image/ URI * @param {string} dataURI data:image/ URI
* @param {string} [filePath] Path to write file to * @param {string} filePath Path to write file to
* @returns {Promise<string>} * @returns {Promise<string|void>} Write file error
*/ */
function outputFile(dataURI, filePath) { function outputFile(dataURI, filePath) {
filePath = filePath || "./"; filePath = filePath || "./";

@ -39,7 +39,10 @@ const initBackgroundJobs = async function () {
}; };
/** Stop all background jobs if running */ /**
* Stop all background jobs if running
* @returns {void}
*/
const stopBackgroundJobs = function () { const stopBackgroundJobs = function () {
for (const job of jobs) { for (const job of jobs) {
if (job.croner) { if (job.croner) {

@ -7,7 +7,7 @@ const DEFAULT_KEEP_PERIOD = 180;
/** /**
* Clears old data from the heartbeat table of the database. * Clears old data from the heartbeat table of the database.
* @return {Promise<void>} A promise that resolves when the data has been cleared. * @returns {Promise<void>} A promise that resolves when the data has been cleared.
*/ */
const clearOldData = async () => { const clearOldData = async () => {

@ -4,7 +4,7 @@ const Database = require("../database");
/** /**
* Run incremental_vacuum and checkpoint the WAL. * Run incremental_vacuum and checkpoint the WAL.
* @return {Promise<void>} A promise that resolves when the process is finished. * @returns {Promise<void>} A promise that resolves when the process is finished.
*/ */
const incrementalVacuum = async () => { const incrementalVacuum = async () => {

@ -19,7 +19,7 @@ class APIKey extends BeanModel {
/** /**
* Returns an object that ready to parse to JSON * Returns an object that ready to parse to JSON
* @returns {Object} * @returns {object} Object ready to parse
*/ */
toJSON() { toJSON() {
return { return {
@ -37,7 +37,7 @@ class APIKey extends BeanModel {
/** /**
* Returns an object that ready to parse to JSON with sensitive fields * Returns an object that ready to parse to JSON with sensitive fields
* removed * removed
* @returns {Object} * @returns {object} Object ready to parse
*/ */
toPublicJSON() { toPublicJSON() {
return { return {
@ -53,9 +53,9 @@ class APIKey extends BeanModel {
/** /**
* Create a new API Key and store it in the database * Create a new API Key and store it in the database
* @param {Object} key Object sent by client * @param {object} key Object sent by client
* @param {int} userID ID of socket user * @param {int} userID ID of socket user
* @returns {Promise<bean>} * @returns {Promise<bean>} API key
*/ */
static async save(key, userID) { static async save(key, userID) {
let bean; let bean;

@ -3,7 +3,7 @@ const { BeanModel } = require("redbean-node/dist/bean-model");
class DockerHost extends BeanModel { class DockerHost extends BeanModel {
/** /**
* Returns an object that ready to parse to JSON * Returns an object that ready to parse to JSON
* @returns {Object} * @returns {object} Object ready to parse
*/ */
toJSON() { toJSON() {
return { return {

@ -4,10 +4,12 @@ const { R } = require("redbean-node");
class Group extends BeanModel { class Group extends BeanModel {
/** /**
* Return an object that ready to parse to JSON for public * Return an object that ready to parse to JSON for public Only show
* Only show necessary data to public * necessary data to public
* @param {boolean} [showTags=false] Should the JSON include monitor tags * @param {boolean} showTags Should the JSON include monitor tags
* @returns {Object} * @param {boolean} certExpiry Should JSON include info about
* certificate expiry?
* @returns {object} Object ready to parse
*/ */
async toPublicJSON(showTags = false, certExpiry = false) { async toPublicJSON(showTags = false, certExpiry = false) {
let monitorBeanList = await this.getMonitorList(); let monitorBeanList = await this.getMonitorList();
@ -27,7 +29,7 @@ class Group extends BeanModel {
/** /**
* Get all monitors * Get all monitors
* @returns {Bean[]} * @returns {Bean[]} List of monitors
*/ */
async getMonitorList() { async getMonitorList() {
return R.convertToBeans("monitor", await R.getAll(` return R.convertToBeans("monitor", await R.getAll(`

@ -12,7 +12,7 @@ class Heartbeat extends BeanModel {
/** /**
* Return an object that ready to parse to JSON for public * Return an object that ready to parse to JSON for public
* Only show necessary data to public * Only show necessary data to public
* @returns {Object} * @returns {object} Object ready to parse
*/ */
toPublicJSON() { toPublicJSON() {
return { return {
@ -25,7 +25,7 @@ class Heartbeat extends BeanModel {
/** /**
* Return an object that ready to parse to JSON * Return an object that ready to parse to JSON
* @returns {Object} * @returns {object} Object ready to parse
*/ */
toJSON() { toJSON() {
return { return {

@ -5,7 +5,7 @@ class Incident extends BeanModel {
/** /**
* Return an object that ready to parse to JSON for public * Return an object that ready to parse to JSON for public
* Only show necessary data to public * Only show necessary data to public
* @returns {Object} * @returns {object} Object ready to parse
*/ */
toPublicJSON() { toPublicJSON() {
return { return {

@ -11,7 +11,7 @@ class Maintenance extends BeanModel {
/** /**
* Return an object that ready to parse to JSON for public * Return an object that ready to parse to JSON for public
* Only show necessary data to public * Only show necessary data to public
* @returns {Object} * @returns {object} Object ready to parse
*/ */
async toPublicJSON() { async toPublicJSON() {
@ -98,7 +98,7 @@ class Maintenance extends BeanModel {
/** /**
* Return an object that ready to parse to JSON * Return an object that ready to parse to JSON
* @param {string} timezone If not specified, the timeRange will be in UTC * @param {string} timezone If not specified, the timeRange will be in UTC
* @returns {Object} * @returns {object} Object ready to parse
*/ */
async toJSON(timezone = null) { async toJSON(timezone = null) {
return this.toPublicJSON(timezone); return this.toPublicJSON(timezone);
@ -142,7 +142,7 @@ class Maintenance extends BeanModel {
/** /**
* Convert data from socket to bean * Convert data from socket to bean
* @param {Bean} bean Bean to fill in * @param {Bean} bean Bean to fill in
* @param {Object} obj Data to fill bean with * @param {object} obj Data to fill bean with
* @returns {Bean} Filled bean * @returns {Bean} Filled bean
*/ */
static async jsonToBean(bean, obj) { static async jsonToBean(bean, obj) {
@ -188,7 +188,7 @@ class Maintenance extends BeanModel {
/** /**
* Throw error if cron is invalid * Throw error if cron is invalid
* @param cron * @param {string|Date} cron Pattern or date
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static async validateCron(cron) { static async validateCron(cron) {
@ -198,6 +198,8 @@ class Maintenance extends BeanModel {
/** /**
* Run the cron * Run the cron
* @param {boolean} throwError Should an error be thrown on failure
* @returns {Promise<void>}
*/ */
async run(throwError = false) { async run(throwError = false) {
if (this.beanMeta.job) { if (this.beanMeta.job) {
@ -290,6 +292,10 @@ class Maintenance extends BeanModel {
} }
} }
/**
* Get timeslots where maintenance is running
* @returns {object|null} Maintenance time slot
*/
getRunningTimeslot() { getRunningTimeslot() {
let start = dayjs(this.beanMeta.job.nextRun(dayjs().add(-this.duration, "second").toDate())); let start = dayjs(this.beanMeta.job.nextRun(dayjs().add(-this.duration, "second").toDate()));
let end = start.add(this.duration, "second"); let end = start.add(this.duration, "second");
@ -305,6 +311,10 @@ class Maintenance extends BeanModel {
} }
} }
/**
* Stop the maintenance
* @returns {void}
*/
stop() { stop() {
if (this.beanMeta.job) { if (this.beanMeta.job) {
this.beanMeta.job.stop(); this.beanMeta.job.stop();
@ -312,10 +322,18 @@ class Maintenance extends BeanModel {
} }
} }
/**
* Is this maintenance currently active
* @returns {boolean} The maintenance is active?
*/
async isUnderMaintenance() { async isUnderMaintenance() {
return (await this.getStatus()) === "under-maintenance"; return (await this.getStatus()) === "under-maintenance";
} }
/**
* Get the timezone of the maintenance
* @returns {string} timezone
*/
async getTimezone() { async getTimezone() {
if (!this.timezone || this.timezone === "SAME_AS_SERVER") { if (!this.timezone || this.timezone === "SAME_AS_SERVER") {
return await UptimeKumaServer.getInstance().getTimezone(); return await UptimeKumaServer.getInstance().getTimezone();
@ -323,10 +341,18 @@ class Maintenance extends BeanModel {
return this.timezone; return this.timezone;
} }
/**
* Get offset for timezone
* @returns {string} offset
*/
async getTimezoneOffset() { async getTimezoneOffset() {
return dayjs.tz(dayjs(), await this.getTimezone()).format("Z"); return dayjs.tz(dayjs(), await this.getTimezone()).format("Z");
} }
/**
* Get the current status of the maintenance
* @returns {string} Current status
*/
async getStatus() { async getStatus() {
if (!this.active) { if (!this.active) {
return "inactive"; return "inactive";

@ -34,9 +34,12 @@ const Database = require("../database");
class Monitor extends BeanModel { class Monitor extends BeanModel {
/** /**
* Return an object that ready to parse to JSON for public * Return an object that ready to parse to JSON for public Only show
* Only show necessary data to public * necessary data to public
* @returns {Object} * @param {boolean} showTags Include tags in JSON
* @param {boolean} certExpiry Include certificate expiry info in
* JSON
* @returns {object} Object ready to parse
*/ */
async toPublicJSON(showTags = false, certExpiry = false) { async toPublicJSON(showTags = false, certExpiry = false) {
let obj = { let obj = {
@ -65,7 +68,9 @@ class Monitor extends BeanModel {
/** /**
* Return an object that ready to parse to JSON * Return an object that ready to parse to JSON
* @returns {Object} * @param {boolean} includeSensitiveData Include sensitive data in
* JSON
* @returns {object} Object ready to parse
*/ */
async toJSON(includeSensitiveData = true) { async toJSON(includeSensitiveData = true) {
@ -184,7 +189,7 @@ class Monitor extends BeanModel {
/** /**
* Checks if the monitor is active based on itself and its parents * Checks if the monitor is active based on itself and its parents
* @returns {Promise<Boolean>} * @returns {Promise<boolean>} Is the monitor active?
*/ */
async isActive() { async isActive() {
const parentActive = await Monitor.isParentActive(this.id); const parentActive = await Monitor.isParentActive(this.id);
@ -194,7 +199,8 @@ class Monitor extends BeanModel {
/** /**
* Get all tags applied to this monitor * Get all tags applied to this monitor
* @returns {Promise<LooseObject<any>[]>} * @returns {Promise<LooseObject<any>[]>} List of tags on the
* monitor
*/ */
async getTags() { async getTags() {
return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ? ORDER BY tag.name", [ this.id ]); return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ? ORDER BY tag.name", [ this.id ]);
@ -203,7 +209,8 @@ class Monitor extends BeanModel {
/** /**
* Gets certificate expiry for this monitor * Gets certificate expiry for this monitor
* @param {number} monitorID ID of monitor to send * @param {number} monitorID ID of monitor to send
* @returns {Promise<LooseObject<any>>} * @returns {Promise<LooseObject<any>>} Certificate expiry info for
* monitor
*/ */
async getCertExpiry(monitorID) { async getCertExpiry(monitorID) {
let tlsInfoBean = await R.findOne("monitor_tls_info", "monitor_id = ?", [ let tlsInfoBean = await R.findOne("monitor_tls_info", "monitor_id = ?", [
@ -228,7 +235,9 @@ class Monitor extends BeanModel {
/** /**
* Encode user and password to Base64 encoding * Encode user and password to Base64 encoding
* for HTTP "basic" auth, as per RFC-7617 * for HTTP "basic" auth, as per RFC-7617
* @returns {string} * @param {string} user Username to encode
* @param {string} pass Password to encode
* @returns {string} Encoded username:password
*/ */
encodeBase64(user, pass) { encodeBase64(user, pass) {
return Buffer.from(user + ":" + pass).toString("base64"); return Buffer.from(user + ":" + pass).toString("base64");
@ -236,7 +245,7 @@ class Monitor extends BeanModel {
/** /**
* Is the TLS expiry notification enabled? * Is the TLS expiry notification enabled?
* @returns {boolean} * @returns {boolean} Enabled?
*/ */
isEnabledExpiryNotification() { isEnabledExpiryNotification() {
return Boolean(this.expiryNotification); return Boolean(this.expiryNotification);
@ -244,7 +253,7 @@ class Monitor extends BeanModel {
/** /**
* Parse to boolean * Parse to boolean
* @returns {boolean} * @returns {boolean} Should TLS errors be ignored?
*/ */
getIgnoreTls() { getIgnoreTls() {
return Boolean(this.ignoreTls); return Boolean(this.ignoreTls);
@ -252,7 +261,7 @@ class Monitor extends BeanModel {
/** /**
* Parse to boolean * Parse to boolean
* @returns {boolean} * @returns {boolean} Is the monitor in upside down mode?
*/ */
isUpsideDown() { isUpsideDown() {
return Boolean(this.upsideDown); return Boolean(this.upsideDown);
@ -260,7 +269,7 @@ class Monitor extends BeanModel {
/** /**
* Parse to boolean * Parse to boolean
* @returns {boolean} * @returns {boolean} Invert keyword match?
*/ */
isInvertKeyword() { isInvertKeyword() {
return Boolean(this.invertKeyword); return Boolean(this.invertKeyword);
@ -268,7 +277,7 @@ class Monitor extends BeanModel {
/** /**
* Parse to boolean * Parse to boolean
* @returns {boolean} * @returns {boolean} Enable TLS for gRPC?
*/ */
getGrpcEnableTls() { getGrpcEnableTls() {
return Boolean(this.grpcEnableTls); return Boolean(this.grpcEnableTls);
@ -276,7 +285,7 @@ class Monitor extends BeanModel {
/** /**
* Get accepted status codes * Get accepted status codes
* @returns {Object} * @returns {object} Accepted status codes
*/ */
getAcceptedStatuscodes() { getAcceptedStatuscodes() {
return JSON.parse(this.accepted_statuscodes_json); return JSON.parse(this.accepted_statuscodes_json);
@ -289,6 +298,7 @@ class Monitor extends BeanModel {
/** /**
* Start monitor * Start monitor
* @param {Server} io Socket server instance * @param {Server} io Socket server instance
* @returns {void}
*/ */
start(io) { start(io) {
let previousBeat = null; let previousBeat = null;
@ -980,7 +990,10 @@ class Monitor extends BeanModel {
}; };
/** Get a heartbeat and handle errors */ /**
* Get a heartbeat and handle errors7
* @returns {void}
*/
const safeBeat = async () => { const safeBeat = async () => {
try { try {
await beat(); await beat();
@ -1008,10 +1021,10 @@ class Monitor extends BeanModel {
/** /**
* Make a request using axios * Make a request using axios
* @param {Object} options Options for Axios * @param {object} options Options for Axios
* @param {boolean} finalCall Should this be the final call i.e * @param {boolean} finalCall Should this be the final call i.e
* don't retry on faliure * don't retry on failure
* @returns {Object} Axios response * @returns {object} Axios response
*/ */
async makeAxiosRequest(options, finalCall = false) { async makeAxiosRequest(options, finalCall = false) {
try { try {
@ -1046,7 +1059,10 @@ class Monitor extends BeanModel {
} }
} }
/** Stop monitor */ /**
* Stop monitor
* @returns {void}
*/
stop() { stop() {
clearTimeout(this.heartbeatInterval); clearTimeout(this.heartbeatInterval);
this.isStop = true; this.isStop = true;
@ -1056,7 +1072,7 @@ class Monitor extends BeanModel {
/** /**
* Get prometheus instance * Get prometheus instance
* @returns {Prometheus|undefined} * @returns {Prometheus|undefined} Current prometheus instance
*/ */
getPrometheus() { getPrometheus() {
return this.prometheus; return this.prometheus;
@ -1066,7 +1082,7 @@ class Monitor extends BeanModel {
* Helper Method: * Helper Method:
* returns URL object for further usage * returns URL object for further usage
* returns null if url is invalid * returns null if url is invalid
* @returns {(null|URL)} * @returns {(null|URL)} Monitor URL
*/ */
getUrl() { getUrl() {
try { try {
@ -1078,8 +1094,8 @@ class Monitor extends BeanModel {
/** /**
* Store TLS info to database * Store TLS info to database
* @param checkCertificateResult * @param {object} checkCertificateResult Certificate to update
* @returns {Promise<Object>} * @returns {Promise<object>} Updated certificate
*/ */
async updateTlsInfo(checkCertificateResult) { async updateTlsInfo(checkCertificateResult) {
let tlsInfoBean = await R.findOne("monitor_tls_info", "monitor_id = ?", [ let tlsInfoBean = await R.findOne("monitor_tls_info", "monitor_id = ?", [
@ -1126,6 +1142,7 @@ class Monitor extends BeanModel {
* @param {Server} io Socket server instance * @param {Server} io Socket server instance
* @param {number} monitorID ID of monitor to send * @param {number} monitorID ID of monitor to send
* @param {number} userID ID of user to send to * @param {number} userID ID of user to send to
* @returns {void}
*/ */
static async sendStats(io, monitorID, userID) { static async sendStats(io, monitorID, userID) {
const hasClients = getTotalClientInRoom(io, userID) > 0; const hasClients = getTotalClientInRoom(io, userID) > 0;
@ -1143,6 +1160,10 @@ class Monitor extends BeanModel {
/** /**
* Send the average ping to user * Send the average ping to user
* @param {number} duration Hours * @param {number} duration Hours
* @param {Server} io Socket instance to send data to
* @param {number} monitorID ID of monitor to read
* @param {number} userID ID of user to send data to
* @returns {void}
*/ */
static async sendAvgPing(duration, io, monitorID, userID) { static async sendAvgPing(duration, io, monitorID, userID) {
const timeLogger = new TimeLogger(); const timeLogger = new TimeLogger();
@ -1168,6 +1189,7 @@ class Monitor extends BeanModel {
* @param {Server} io Socket server instance * @param {Server} io Socket server instance
* @param {number} monitorID ID of monitor to send * @param {number} monitorID ID of monitor to send
* @param {number} userID ID of user to send to * @param {number} userID ID of user to send to
* @returns {void}
*/ */
static async sendCertInfo(io, monitorID, userID) { static async sendCertInfo(io, monitorID, userID) {
let tlsInfo = await R.findOne("monitor_tls_info", "monitor_id = ?", [ let tlsInfo = await R.findOne("monitor_tls_info", "monitor_id = ?", [
@ -1184,6 +1206,8 @@ class Monitor extends BeanModel {
* https://www.uptrends.com/support/kb/reporting/calculation-of-uptime-and-downtime * https://www.uptrends.com/support/kb/reporting/calculation-of-uptime-and-downtime
* @param {number} duration Hours * @param {number} duration Hours
* @param {number} monitorID ID of monitor to calculate * @param {number} monitorID ID of monitor to calculate
* @param {boolean} forceNoCache Should the uptime be recalculated?
* @returns {number} Uptime of monitor
*/ */
static async calcUptime(duration, monitorID, forceNoCache = false) { static async calcUptime(duration, monitorID, forceNoCache = false) {
@ -1264,6 +1288,7 @@ class Monitor extends BeanModel {
* @param {Server} io Socket server instance * @param {Server} io Socket server instance
* @param {number} monitorID ID of monitor to send * @param {number} monitorID ID of monitor to send
* @param {number} userID ID of user to send to * @param {number} userID ID of user to send to
* @returns {void}
*/ */
static async sendUptime(duration, io, monitorID, userID) { static async sendUptime(duration, io, monitorID, userID) {
const uptime = await this.calcUptime(duration, monitorID); const uptime = await this.calcUptime(duration, monitorID);
@ -1338,6 +1363,7 @@ class Monitor extends BeanModel {
* @param {boolean} isFirstBeat Is this beat the first of this monitor? * @param {boolean} isFirstBeat Is this beat the first of this monitor?
* @param {Monitor} monitor The monitor to send a notificaton about * @param {Monitor} monitor The monitor to send a notificaton about
* @param {Bean} bean Status information about monitor * @param {Bean} bean Status information about monitor
* @returns {void}
*/ */
static async sendNotification(isFirstBeat, monitor, bean) { static async sendNotification(isFirstBeat, monitor, bean) {
if (!isFirstBeat || bean.status === DOWN) { if (!isFirstBeat || bean.status === DOWN) {
@ -1378,7 +1404,7 @@ class Monitor extends BeanModel {
/** /**
* Get list of notification providers for a given monitor * Get list of notification providers for a given monitor
* @param {Monitor} monitor Monitor to get notification providers for * @param {Monitor} monitor Monitor to get notification providers for
* @returns {Promise<LooseObject<any>[]>} * @returns {Promise<LooseObject<any>[]>} List of notifications
*/ */
static async getNotificationList(monitor) { static async getNotificationList(monitor) {
let notificationList = await R.getAll("SELECT notification.* FROM notification, monitor_notification WHERE monitor_id = ? AND monitor_notification.notification_id = notification.id ", [ let notificationList = await R.getAll("SELECT notification.* FROM notification, monitor_notification WHERE monitor_id = ? AND monitor_notification.notification_id = notification.id ", [
@ -1389,7 +1415,8 @@ class Monitor extends BeanModel {
/** /**
* checks certificate chain for expiring certificates * checks certificate chain for expiring certificates
* @param {Object} tlsInfoObject Information about certificate * @param {object} tlsInfoObject Information about certificate
* @returns {void}
*/ */
async checkCertExpiryNotifications(tlsInfoObject) { async checkCertExpiryNotifications(tlsInfoObject) {
if (tlsInfoObject && tlsInfoObject.certInfo && tlsInfoObject.certInfo.daysRemaining) { if (tlsInfoObject && tlsInfoObject.certInfo && tlsInfoObject.certInfo.daysRemaining) {
@ -1476,7 +1503,7 @@ class Monitor extends BeanModel {
/** /**
* Get the status of the previous heartbeat * Get the status of the previous heartbeat
* @param {number} monitorID ID of monitor to check * @param {number} monitorID ID of monitor to check
* @returns {Promise<LooseObject<any>>} * @returns {Promise<LooseObject<any>>} Previous heartbeat
*/ */
static async getPreviousHeartbeat(monitorID) { static async getPreviousHeartbeat(monitorID) {
return await R.getRow(` return await R.getRow(`
@ -1490,7 +1517,7 @@ class Monitor extends BeanModel {
/** /**
* Check if monitor is under maintenance * Check if monitor is under maintenance
* @param {number} monitorID ID of monitor to check * @param {number} monitorID ID of monitor to check
* @returns {Promise<boolean>} * @returns {Promise<boolean>} Is the monitor under maintenance
*/ */
static async isUnderMaintenance(monitorID) { static async isUnderMaintenance(monitorID) {
const maintenanceIDList = await R.getCol(` const maintenanceIDList = await R.getCol(`
@ -1513,7 +1540,11 @@ class Monitor extends BeanModel {
return false; return false;
} }
/** Make sure monitor interval is between bounds */ /**
* Make sure monitor interval is between bounds
* @returns {void}
* @throws Interval is outside of range
*/
validate() { validate() {
if (this.interval > MAX_INTERVAL_SECOND) { if (this.interval > MAX_INTERVAL_SECOND) {
throw new Error(`Interval cannot be more than ${MAX_INTERVAL_SECOND} seconds`); throw new Error(`Interval cannot be more than ${MAX_INTERVAL_SECOND} seconds`);
@ -1526,7 +1557,7 @@ class Monitor extends BeanModel {
/** /**
* Gets Parent of the monitor * Gets Parent of the monitor
* @param {number} monitorID ID of monitor to get * @param {number} monitorID ID of monitor to get
* @returns {Promise<LooseObject<any>>} * @returns {Promise<LooseObject<any>>} Parent
*/ */
static async getParent(monitorID) { static async getParent(monitorID) {
return await R.getRow(` return await R.getRow(`
@ -1542,7 +1573,7 @@ class Monitor extends BeanModel {
/** /**
* Gets all Children of the monitor * Gets all Children of the monitor
* @param {number} monitorID ID of monitor to get * @param {number} monitorID ID of monitor to get
* @returns {Promise<LooseObject<any>>} * @returns {Promise<LooseObject<any>>} Children
*/ */
static async getChildren(monitorID) { static async getChildren(monitorID) {
return await R.getAll(` return await R.getAll(`
@ -1555,7 +1586,7 @@ class Monitor extends BeanModel {
/** /**
* Gets Full Path-Name (Groups and Name) * Gets Full Path-Name (Groups and Name)
* @returns {Promise<String>} * @returns {Promise<string>} Full path name of this monitor
*/ */
async getPathName() { async getPathName() {
let path = this.name; let path = this.name;
@ -1576,7 +1607,7 @@ class Monitor extends BeanModel {
/** /**
* Gets recursive all child ids * Gets recursive all child ids
* @param {number} monitorID ID of the monitor to get * @param {number} monitorID ID of the monitor to get
* @returns {Promise<Array>} * @returns {Promise<Array>} IDs of all children
*/ */
static async getAllChildrenIDs(monitorID) { static async getAllChildrenIDs(monitorID) {
const childs = await Monitor.getChildren(monitorID); const childs = await Monitor.getChildren(monitorID);
@ -1609,7 +1640,7 @@ class Monitor extends BeanModel {
/** /**
* Checks recursive if parent (ancestors) are active * Checks recursive if parent (ancestors) are active
* @param {number} monitorID ID of the monitor to get * @param {number} monitorID ID of the monitor to get
* @returns {Promise<Boolean>} * @returns {Promise<boolean>} Is the parent monitor active?
*/ */
static async isParentActive(monitorID) { static async isParentActive(monitorID) {
const parent = await Monitor.getParent(monitorID); const parent = await Monitor.getParent(monitorID);

@ -3,7 +3,7 @@ const { BeanModel } = require("redbean-node/dist/bean-model");
class Proxy extends BeanModel { class Proxy extends BeanModel {
/** /**
* Return an object that ready to parse to JSON * Return an object that ready to parse to JSON
* @returns {Object} * @returns {object} Object ready to parse
*/ */
toJSON() { toJSON() {
return { return {

@ -14,10 +14,11 @@ class StatusPage extends BeanModel {
static domainMappingList = { }; static domainMappingList = { };
/** /**
* * Handle responses to status page
* @param {Response} response * @param {Response} response Response object
* @param {string} indexHTML * @param {string} indexHTML HTML to render
* @param {string} slug * @param {string} slug Status page slug
* @returns {void}
*/ */
static async handleStatusPageResponse(response, indexHTML, slug) { static async handleStatusPageResponse(response, indexHTML, slug) {
let statusPage = await R.findOne("status_page", " slug = ? ", [ let statusPage = await R.findOne("status_page", " slug = ? ", [
@ -33,8 +34,9 @@ class StatusPage extends BeanModel {
/** /**
* SSR for status pages * SSR for status pages
* @param {string} indexHTML * @param {string} indexHTML HTML page to render
* @param {StatusPage} statusPage * @param {StatusPage} statusPage Status page populate HTML with
* @returns {void}
*/ */
static async renderHTML(indexHTML, statusPage) { static async renderHTML(indexHTML, statusPage) {
const $ = cheerio.load(indexHTML); const $ = cheerio.load(indexHTML);
@ -87,7 +89,8 @@ class StatusPage extends BeanModel {
/** /**
* Get all status page data in one call * Get all status page data in one call
* @param {StatusPage} statusPage * @param {StatusPage} statusPage Status page to get data for
* @returns {object} Status page data
*/ */
static async getStatusPageData(statusPage) { static async getStatusPageData(statusPage) {
const config = await statusPage.toPublicJSON(); const config = await statusPage.toPublicJSON();
@ -142,7 +145,7 @@ class StatusPage extends BeanModel {
* Send status page list to client * Send status page list to client
* @param {Server} io io Socket server instance * @param {Server} io io Socket server instance
* @param {Socket} socket Socket.io instance * @param {Socket} socket Socket.io instance
* @returns {Promise<Bean[]>} * @returns {Promise<Bean[]>} Status page list
*/ */
static async sendStatusPageList(io, socket) { static async sendStatusPageList(io, socket) {
let result = {}; let result = {};
@ -159,7 +162,7 @@ class StatusPage extends BeanModel {
/** /**
* Update list of domain names * Update list of domain names
* @param {string[]} domainNameList * @param {string[]} domainNameList List of status page domains
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async updateDomainNameList(domainNameList) { async updateDomainNameList(domainNameList) {
@ -203,7 +206,7 @@ class StatusPage extends BeanModel {
/** /**
* Get list of domain names * Get list of domain names
* @returns {Object[]} * @returns {object[]} List of status page domains
*/ */
getDomainNameList() { getDomainNameList() {
let domainList = []; let domainList = [];
@ -219,7 +222,7 @@ class StatusPage extends BeanModel {
/** /**
* Return an object that ready to parse to JSON * Return an object that ready to parse to JSON
* @returns {Object} * @returns {object} Object ready to parse
*/ */
async toJSON() { async toJSON() {
return { return {
@ -243,7 +246,7 @@ class StatusPage extends BeanModel {
/** /**
* Return an object that ready to parse to JSON for public * Return an object that ready to parse to JSON for public
* Only show necessary data to public * Only show necessary data to public
* @returns {Object} * @returns {object} Object ready to parse
*/ */
async toPublicJSON() { async toPublicJSON() {
return { return {
@ -264,7 +267,8 @@ class StatusPage extends BeanModel {
/** /**
* Convert slug to status page ID * Convert slug to status page ID
* @param {string} slug * @param {string} slug Status page slug
* @returns {Promise<number>} ID of status page
*/ */
static async slugToID(slug) { static async slugToID(slug) {
return await R.getCell("SELECT id FROM status_page WHERE slug = ? ", [ return await R.getCell("SELECT id FROM status_page WHERE slug = ? ", [
@ -274,7 +278,7 @@ class StatusPage extends BeanModel {
/** /**
* Get path to the icon for the page * Get path to the icon for the page
* @returns {string} * @returns {string} Path
*/ */
getIcon() { getIcon() {
if (!this.icon) { if (!this.icon) {
@ -287,7 +291,7 @@ class StatusPage extends BeanModel {
/** /**
* Get list of maintenances * Get list of maintenances
* @param {number} statusPageId ID of status page to get maintenance for * @param {number} statusPageId ID of status page to get maintenance for
* @returns {Object} Object representing maintenances sanitized for public * @returns {object} Object representing maintenances sanitized for public
*/ */
static async getMaintenanceList(statusPageId) { static async getMaintenanceList(statusPageId) {
try { try {

@ -4,7 +4,7 @@ class Tag extends BeanModel {
/** /**
* Return an object that ready to parse to JSON * Return an object that ready to parse to JSON
* @returns {Object} * @returns {object} Object ready to parse
*/ */
toJSON() { toJSON() {
return { return {

@ -7,7 +7,7 @@ class User extends BeanModel {
* Reset user password * Reset user password
* Fix #1510, as in the context reset-password.js, there is no auto model mapping. Call this static function instead. * Fix #1510, as in the context reset-password.js, there is no auto model mapping. Call this static function instead.
* @param {number} userID ID of user to update * @param {number} userID ID of user to update
* @param {string} newPassword * @param {string} newPassword Users new password
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static async resetPassword(userID, newPassword) { static async resetPassword(userID, newPassword) {
@ -19,7 +19,7 @@ class User extends BeanModel {
/** /**
* Reset this users password * Reset this users password
* @param {string} newPassword * @param {string} newPassword Users new password
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async resetPassword(newPassword) { async resetPassword(newPassword) {

@ -3,10 +3,10 @@ class MonitorType {
name = undefined; name = undefined;
/** /**
* * Run the monitoring check on the given monitor
* @param {Monitor} monitor * @param {Monitor} monitor Monitor to check
* @param {Heartbeat} heartbeat * @param {Heartbeat} heartbeat Monitor heartbeat to update
* @param {UptimeKumaServer} server * @param {UptimeKumaServer} server Uptime Kuma server
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async check(monitor, heartbeat, server) { async check(monitor, heartbeat, server) {

@ -51,6 +51,11 @@ if (process.platform === "win32") {
log.debug("chrome", allowedList); log.debug("chrome", allowedList);
/**
* Is the executable path allowed?
* @param {string} executablePath Path to executable
* @returns {Promise<boolean>} The executable is allowed?
*/
async function isAllowedChromeExecutable(executablePath) { async function isAllowedChromeExecutable(executablePath) {
console.log(config.args); console.log(config.args);
if (config.args["allow-all-chrome-exec"] || process.env.UPTIME_KUMA_ALLOW_ALL_CHROME_EXEC === "1") { if (config.args["allow-all-chrome-exec"] || process.env.UPTIME_KUMA_ALLOW_ALL_CHROME_EXEC === "1") {
@ -61,6 +66,11 @@ async function isAllowedChromeExecutable(executablePath) {
return allowedList.includes(executablePath); return allowedList.includes(executablePath);
} }
/**
* Get the current instance of the browser. If there isn't one, create
* it.
* @returns {Promise<Browser>} The browser
*/
async function getBrowser() { async function getBrowser() {
if (!browser) { if (!browser) {
let executablePath = await Settings.get("chromeExecutable"); let executablePath = await Settings.get("chromeExecutable");
@ -75,6 +85,11 @@ async function getBrowser() {
return browser; return browser;
} }
/**
* Prepare the chrome executable path
* @param {string} executablePath Path to chrome executable
* @returns {Promise<string>} Executable path
*/
async function prepareChromeExecutable(executablePath) { async function prepareChromeExecutable(executablePath) {
// Special code for using the playwright_chromium // Special code for using the playwright_chromium
if (typeof executablePath === "string" && executablePath.toLocaleLowerCase() === "#playwright_chromium") { if (typeof executablePath === "string" && executablePath.toLocaleLowerCase() === "#playwright_chromium") {
@ -121,6 +136,12 @@ async function prepareChromeExecutable(executablePath) {
return executablePath; return executablePath;
} }
/**
* Find the chrome executable
* @param {any[]} executables Executables to search through
* @returns {any} Executable
* @throws Could not find executable
*/
function findChrome(executables) { function findChrome(executables) {
// Use the last working executable, so we don't have to search for it again // Use the last working executable, so we don't have to search for it again
if (lastAutoDetectChromeExecutable) { if (lastAutoDetectChromeExecutable) {
@ -138,6 +159,10 @@ function findChrome(executables) {
throw new Error("Chromium not found, please specify Chromium executable path in the settings page."); throw new Error("Chromium not found, please specify Chromium executable path in the settings page.");
} }
/**
* Reset chrome
* @returns {Promise<void>}
*/
async function resetChrome() { async function resetChrome() {
if (browser) { if (browser) {
await browser.close(); await browser.close();
@ -147,8 +172,8 @@ async function resetChrome() {
/** /**
* Test if the chrome executable is valid and return the version * Test if the chrome executable is valid and return the version
* @param executablePath * @param {string} executablePath Path to executable
* @returns {Promise<string>} * @returns {Promise<string>} Chrome version
*/ */
async function testChrome(executablePath) { async function testChrome(executablePath) {
try { try {
@ -175,6 +200,9 @@ class RealBrowserMonitorType extends MonitorType {
name = "real-browser"; name = "real-browser";
/**
* @inheritdoc
*/
async check(monitor, heartbeat, server) { async check(monitor, heartbeat, server) {
const browser = await getBrowser(); const browser = await getBrowser();
const context = await browser.newContext(); const context = await browser.newContext();

@ -13,9 +13,9 @@ class TailscalePing extends MonitorType {
/** /**
* Checks the ping status of the URL associated with the monitor. * Checks the ping status of the URL associated with the monitor.
* It then parses the Tailscale ping command output to update the heatrbeat. * It then parses the Tailscale ping command output to update the heatrbeat.
* * @param {object} monitor The monitor object associated with the check.
* @param {Object} monitor - The monitor object associated with the check. * @param {object} heartbeat The heartbeat object to update.
* @param {Object} heartbeat - The heartbeat object to update. * @returns {Promise<void>}
* @throws Will throw an error if checking Tailscale ping encounters any error * @throws Will throw an error if checking Tailscale ping encounters any error
*/ */
async check(monitor, heartbeat) { async check(monitor, heartbeat) {
@ -31,9 +31,9 @@ class TailscalePing extends MonitorType {
/** /**
* Runs the Tailscale ping command to the given URL. * Runs the Tailscale ping command to the given URL.
* * @param {string} hostname The hostname to ping.
* @param {string} hostname - The hostname to ping. * @param {number} interval Interval to send ping
* @returns {Promise<string>} - A Promise that resolves to the output of the Tailscale ping command * @returns {Promise<string>} A Promise that resolves to the output of the Tailscale ping command
* @throws Will throw an error if the command execution encounters any error. * @throws Will throw an error if the command execution encounters any error.
*/ */
async runTailscalePing(hostname, interval) { async runTailscalePing(hostname, interval) {
@ -61,9 +61,9 @@ class TailscalePing extends MonitorType {
/** /**
* Parses the output of the Tailscale ping command to update the heartbeat. * Parses the output of the Tailscale ping command to update the heartbeat.
* * @param {string} tailscaleOutput The output of the Tailscale ping command.
* @param {string} tailscaleOutput - The output of the Tailscale ping command. * @param {object} heartbeat The heartbeat object to update.
* @param {Object} heartbeat - The heartbeat object to update. * @returns {void}
* @throws Will throw an eror if the output contains any unexpected string. * @throws Will throw an eror if the output contains any unexpected string.
*/ */
parseTailscaleOutput(tailscaleOutput, heartbeat) { parseTailscaleOutput(tailscaleOutput, heartbeat) {

@ -6,6 +6,9 @@ class Alerta extends NotificationProvider {
name = "alerta"; name = "alerta";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -7,6 +7,9 @@ class AlertNow extends NotificationProvider {
name = "AlertNow"; name = "AlertNow";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -7,6 +7,9 @@ const qs = require("qs");
class AliyunSMS extends NotificationProvider { class AliyunSMS extends NotificationProvider {
name = "AliyunSMS"; name = "AliyunSMS";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
@ -78,9 +81,9 @@ class AliyunSMS extends NotificationProvider {
/** /**
* Aliyun request sign * Aliyun request sign
* @param {Object} param Parameters object to sign * @param {object} param Parameters object to sign
* @param {string} AccessKeySecret Secret key to sign parameters with * @param {string} AccessKeySecret Secret key to sign parameters with
* @returns {string} * @returns {string} Base64 encoded request
*/ */
sign(param, AccessKeySecret) { sign(param, AccessKeySecret) {
let param2 = {}; let param2 = {};
@ -122,7 +125,7 @@ class AliyunSMS extends NotificationProvider {
/** /**
* Convert status constant to string * Convert status constant to string
* @param {const} status The status constant * @param {const} status The status constant
* @returns {string} * @returns {string} Status
*/ */
statusToString(status) { statusToString(status) {
switch (status) { switch (status) {

@ -5,6 +5,9 @@ class Apprise extends NotificationProvider {
name = "apprise"; name = "apprise";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const args = [ "-vv", "-b", msg, notification.appriseURL ]; const args = [ "-vv", "-b", msg, notification.appriseURL ];
if (notification.title) { if (notification.title) {

@ -18,6 +18,9 @@ const successMessage = "Successes!";
class Bark extends NotificationProvider { class Bark extends NotificationProvider {
name = "Bark"; name = "Bark";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let barkEndpoint = notification.barkEndpoint; let barkEndpoint = notification.barkEndpoint;
@ -45,8 +48,9 @@ class Bark extends NotificationProvider {
/** /**
* Add additional parameter for better on device styles (iOS 15 * Add additional parameter for better on device styles (iOS 15
* optimized) * optimized)
* @param {BeanModel} notification Notification to send
* @param {string} postUrl URL to append parameters to * @param {string} postUrl URL to append parameters to
* @returns {string} * @returns {string} Additional URL parameters
*/ */
appendAdditionalParameters(notification, postUrl) { appendAdditionalParameters(notification, postUrl) {
// set icon to uptime kuma icon, 11kb should be fine // set icon to uptime kuma icon, 11kb should be fine
@ -70,7 +74,8 @@ class Bark extends NotificationProvider {
/** /**
* Check if result is successful * Check if result is successful
* @param {Object} result Axios response object * @param {object} result Axios response object
* @returns {void}
* @throws {Error} The status code is not in range 2xx * @throws {Error} The status code is not in range 2xx
*/ */
checkResult(result) { checkResult(result) {
@ -84,10 +89,11 @@ class Bark extends NotificationProvider {
/** /**
* Send the message * Send the message
* @param {BeanModel} notification Notification to send
* @param {string} title Message title * @param {string} title Message title
* @param {string} subtitle Message * @param {string} subtitle Message
* @param {string} endpoint Endpoint to send request to * @param {string} endpoint Endpoint to send request to
* @returns {string} * @returns {string} Success message
*/ */
async postNotification(notification, title, subtitle, endpoint) { async postNotification(notification, title, subtitle, endpoint) {
// url encode title and subtitle // url encode title and subtitle

@ -5,6 +5,9 @@ class ClickSendSMS extends NotificationProvider {
name = "clicksendsms"; name = "clicksendsms";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -6,6 +6,9 @@ const Crypto = require("crypto");
class DingDing extends NotificationProvider { class DingDing extends NotificationProvider {
name = "DingDing"; name = "DingDing";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
@ -39,8 +42,8 @@ class DingDing extends NotificationProvider {
/** /**
* Send message to DingDing * Send message to DingDing
* @param {BeanModel} notification * @param {BeanModel} notification Notification to send
* @param {Object} params Parameters of message * @param {object} params Parameters of message
* @returns {boolean} True if successful else false * @returns {boolean} True if successful else false
*/ */
async sendToDingDing(notification, params) { async sendToDingDing(notification, params) {
@ -66,7 +69,7 @@ class DingDing extends NotificationProvider {
* DingDing sign * DingDing sign
* @param {Date} timestamp Timestamp of message * @param {Date} timestamp Timestamp of message
* @param {string} secretKey Secret key to sign data with * @param {string} secretKey Secret key to sign data with
* @returns {string} * @returns {string} Base64 encoded signature
*/ */
sign(timestamp, secretKey) { sign(timestamp, secretKey) {
return Crypto return Crypto
@ -78,7 +81,7 @@ class DingDing extends NotificationProvider {
/** /**
* Convert status constant to string * Convert status constant to string
* @param {const} status The status constant * @param {const} status The status constant
* @returns {string} * @returns {string} Status
*/ */
statusToString(status) { statusToString(status) {
// TODO: Move to notification-provider.js to avoid repetition in classes // TODO: Move to notification-provider.js to avoid repetition in classes

@ -6,6 +6,9 @@ class Discord extends NotificationProvider {
name = "discord"; name = "discord";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -5,6 +5,9 @@ const { DOWN, UP } = require("../../src/util");
class Feishu extends NotificationProvider { class Feishu extends NotificationProvider {
name = "Feishu"; name = "Feishu";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
let feishuWebHookUrl = notification.feishuWebHookUrl; let feishuWebHookUrl = notification.feishuWebHookUrl;

@ -7,6 +7,9 @@ const successMessage = "Sent Successfully.";
class FlashDuty extends NotificationProvider { class FlashDuty extends NotificationProvider {
name = "FlashDuty"; name = "FlashDuty";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
try { try {
if (heartbeatJSON == null) { if (heartbeatJSON == null) {
@ -33,12 +36,12 @@ class FlashDuty extends NotificationProvider {
this.throwGeneralAxiosError(error); this.throwGeneralAxiosError(error);
} }
} }
/** /**
* Generate a monitor url from the monitors infomation * Generate a monitor url from the monitors infomation
* @param {Object} monitorInfo Monitor details * @param {object} monitorInfo Monitor details
* @returns {string|undefined} * @returns {string|undefined} Monitor URL
*/ */
genMonitorUrl(monitorInfo) { genMonitorUrl(monitorInfo) {
if (monitorInfo.type === "port" && monitorInfo.port) { if (monitorInfo.type === "port" && monitorInfo.port) {
return monitorInfo.hostname + ":" + monitorInfo.port; return monitorInfo.hostname + ":" + monitorInfo.port;
@ -54,9 +57,9 @@ class FlashDuty extends NotificationProvider {
* @param {BeanModel} notification Message title * @param {BeanModel} notification Message title
* @param {string} title Message * @param {string} title Message
* @param {string} body Message * @param {string} body Message
* @param {Object} monitorInfo Monitor details * @param {object} monitorInfo Monitor details
* @param {string} eventStatus Monitor status (Info, Warning, Critical, Ok) * @param {string} eventStatus Monitor status (Info, Warning, Critical, Ok)
* @returns {string} * @returns {string} Success message
*/ */
async postNotification(notification, title, body, monitorInfo, eventStatus) { async postNotification(notification, title, body, monitorInfo, eventStatus) {
const options = { const options = {

@ -5,6 +5,9 @@ class FreeMobile extends NotificationProvider {
name = "FreeMobile"; name = "FreeMobile";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -6,6 +6,9 @@ class GoAlert extends NotificationProvider {
name = "GoAlert"; name = "GoAlert";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -8,6 +8,9 @@ class GoogleChat extends NotificationProvider {
name = "GoogleChat"; name = "GoogleChat";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -5,6 +5,9 @@ class Gorush extends NotificationProvider {
name = "gorush"; name = "gorush";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -5,6 +5,9 @@ class Gotify extends NotificationProvider {
name = "gotify"; name = "gotify";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -6,6 +6,9 @@ const defaultNotificationService = "notify";
class HomeAssistant extends NotificationProvider { class HomeAssistant extends NotificationProvider {
name = "HomeAssistant"; name = "HomeAssistant";
/**
* @inheritdoc
*/
async send(notification, message, monitor = null, heartbeat = null) { async send(notification, message, monitor = null, heartbeat = null) {
const notificationService = notification?.notificationService || defaultNotificationService; const notificationService = notification?.notificationService || defaultNotificationService;

@ -5,6 +5,9 @@ class Kook extends NotificationProvider {
name = "Kook"; name = "Kook";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
let url = "https://www.kookapp.cn/api/v3/message/create"; let url = "https://www.kookapp.cn/api/v3/message/create";

@ -6,6 +6,9 @@ class Line extends NotificationProvider {
name = "line"; name = "line";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -7,6 +7,9 @@ class LineNotify extends NotificationProvider {
name = "LineNotify"; name = "LineNotify";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -6,6 +6,9 @@ class LunaSea extends NotificationProvider {
name = "lunasea"; name = "lunasea";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
let lunaseaurl = ""; let lunaseaurl = "";

@ -6,6 +6,9 @@ const { log } = require("../../src/util");
class Matrix extends NotificationProvider { class Matrix extends NotificationProvider {
name = "matrix"; name = "matrix";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -6,6 +6,9 @@ class Mattermost extends NotificationProvider {
name = "mattermost"; name = "mattermost";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -33,6 +33,9 @@ if (semver.lt(nodeVersion, "16.0.0")) {
class Nostr extends NotificationProvider { class Nostr extends NotificationProvider {
name = "nostr"; name = "nostr";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
// All DMs should have same timestamp // All DMs should have same timestamp
const createdAt = Math.floor(Date.now() / 1000); const createdAt = Math.floor(Date.now() / 1000);
@ -86,6 +89,11 @@ class Nostr extends NotificationProvider {
return `${successfulRelays}/${relays.length} relays connected.`; return `${successfulRelays}/${relays.length} relays connected.`;
} }
/**
* Get the private key for the sender
* @param {string} sender Sender to retrieve key for
* @returns {nip19.DecodeResult} Private key
*/
async getPrivateKey(sender) { async getPrivateKey(sender) {
try { try {
const senderDecodeResult = await nip19.decode(sender); const senderDecodeResult = await nip19.decode(sender);
@ -96,6 +104,11 @@ class Nostr extends NotificationProvider {
} }
} }
/**
* Get public keys for recipients
* @param {string} recipients Newline delimited list of recipients
* @returns {nip19.DecodeResult[]} Public keys
*/
async getPublicKeys(recipients) { async getPublicKeys(recipients) {
const recipientsList = recipients.split("\n"); const recipientsList = recipients.split("\n");
const publicKeys = []; const publicKeys = [];

@ -2,16 +2,16 @@ class NotificationProvider {
/** /**
* Notification Provider Name * Notification Provider Name
* @type string * @type {string}
*/ */
name = undefined; name = undefined;
/** /**
* Send a notification * Send a notification
* @param {BeanModel} notification * @param {BeanModel} notification Notification to send
* @param {string} msg General Message * @param {string} msg General Message
* @param {?Object} monitorJSON Monitor details (For Up/Down only) * @param {?object} monitorJSON Monitor details (For Up/Down only)
* @param {?Object} heartbeatJSON Heartbeat details (For Up/Down only) * @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
* @returns {Promise<string>} Return Successful Message * @returns {Promise<string>} Return Successful Message
* @throws Error with fail msg * @throws Error with fail msg
*/ */
@ -22,6 +22,7 @@ class NotificationProvider {
/** /**
* Throws an error * Throws an error
* @param {any} error The error to throw * @param {any} error The error to throw
* @returns {void}
* @throws {any} The error specified * @throws {any} The error specified
*/ */
throwGeneralAxiosError(error) { throwGeneralAxiosError(error) {

@ -6,6 +6,9 @@ class Ntfy extends NotificationProvider {
name = "ntfy"; name = "ntfy";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -5,6 +5,9 @@ class Octopush extends NotificationProvider {
name = "octopush"; name = "octopush";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -5,6 +5,9 @@ class OneBot extends NotificationProvider {
name = "OneBot"; name = "OneBot";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -68,11 +68,11 @@ class Opsgenie extends NotificationProvider {
} }
/** /**
* * Make POST request to Opsgenie
* @param {BeanModel} notification * @param {BeanModel} notification Notification to send
* @param {string} url Request url * @param {string} url Request url
* @param {Object} data Request body * @param {object} data Request body
* @returns {Promise<string>} * @returns {Promise<string>} Success message
*/ */
async post(notification, url, data) { async post(notification, url, data) {
let config = { let config = {

@ -39,7 +39,8 @@ class PagerDuty extends NotificationProvider {
/** /**
* Check if result is successful, result code should be in range 2xx * Check if result is successful, result code should be in range 2xx
* @param {Object} result Axios response object * @param {object} result Axios response object
* @returns {void}
* @throws {Error} The status code is not in range 2xx * @throws {Error} The status code is not in range 2xx
*/ */
checkResult(result) { checkResult(result) {
@ -56,9 +57,9 @@ class PagerDuty extends NotificationProvider {
* @param {BeanModel} notification Message title * @param {BeanModel} notification Message title
* @param {string} title Message title * @param {string} title Message title
* @param {string} body Message * @param {string} body Message
* @param {Object} monitorInfo Monitor details (For Up/Down only) * @param {object} monitorInfo Monitor details (For Up/Down only)
* @param {?string} eventAction Action event for PagerDuty (trigger, acknowledge, resolve) * @param {?string} eventAction Action event for PagerDuty (trigger, acknowledge, resolve)
* @returns {string} * @returns {Promise<string>} Success message
*/ */
async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") { async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") {

@ -32,7 +32,8 @@ class PagerTree extends NotificationProvider {
/** /**
* Check if result is successful, result code should be in range 2xx * Check if result is successful, result code should be in range 2xx
* @param {Object} result Axios response object * @param {object} result Axios response object
* @returns {void}
* @throws {Error} The status code is not in range 2xx * @throws {Error} The status code is not in range 2xx
*/ */
checkResult(result) { checkResult(result) {
@ -48,9 +49,10 @@ class PagerTree extends NotificationProvider {
* Send the message * Send the message
* @param {BeanModel} notification Message title * @param {BeanModel} notification Message title
* @param {string} title Message title * @param {string} title Message title
* @param {Object} monitorJSON Monitor details (For Up/Down only) * @param {object} monitorJSON Monitor details (For Up/Down only)
* @param {object} heartbeatJSON Heartbeat details (For Up/Down only)
* @param {?string} eventAction Action event for PagerTree (create, resolve) * @param {?string} eventAction Action event for PagerTree (create, resolve)
* @returns {string} * @returns {Promise<string>} Success state
*/ */
async postNotification(notification, title, monitorJSON, heartbeatJSON, eventAction = "create") { async postNotification(notification, title, monitorJSON, heartbeatJSON, eventAction = "create") {

@ -5,6 +5,9 @@ class PromoSMS extends NotificationProvider {
name = "promosms"; name = "promosms";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -7,6 +7,9 @@ class Pushbullet extends NotificationProvider {
name = "pushbullet"; name = "pushbullet";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -6,6 +6,9 @@ class PushDeer extends NotificationProvider {
name = "PushDeer"; name = "PushDeer";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
let endpoint = "/message/push"; let endpoint = "/message/push";

@ -5,6 +5,9 @@ class Pushover extends NotificationProvider {
name = "pushover"; name = "pushover";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
let pushoverlink = "https://api.pushover.net/1/messages.json"; let pushoverlink = "https://api.pushover.net/1/messages.json";

@ -5,6 +5,9 @@ class Pushy extends NotificationProvider {
name = "pushy"; name = "pushy";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -8,6 +8,9 @@ class RocketChat extends NotificationProvider {
name = "rocket.chat"; name = "rocket.chat";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -6,6 +6,9 @@ class ServerChan extends NotificationProvider {
name = "ServerChan"; name = "ServerChan";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {
@ -23,8 +26,8 @@ class ServerChan extends NotificationProvider {
/** /**
* Get the formatted title for message * Get the formatted title for message
* @param {?Object} monitorJSON Monitor details (For Up/Down only) * @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
* @param {?Object} heartbeatJSON Heartbeat details (For Up/Down only) * @param {?object} monitorJSON Monitor details (For Up/Down only)
* @returns {string} Formatted title * @returns {string} Formatted title
*/ */
checkStatus(heartbeatJSON, monitorJSON) { checkStatus(heartbeatJSON, monitorJSON) {

@ -5,6 +5,9 @@ class SerwerSMS extends NotificationProvider {
name = "serwersms"; name = "serwersms";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -5,6 +5,9 @@ class Signal extends NotificationProvider {
name = "signal"; name = "signal";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -10,7 +10,9 @@ class Slack extends NotificationProvider {
/** /**
* Deprecated property notification.slackbutton * Deprecated property notification.slackbutton
* Set it as primary base url if this is not yet set. * Set it as primary base url if this is not yet set.
* @deprecated
* @param {string} url The primary base URL to use * @param {string} url The primary base URL to use
* @returns {Promise<void>}
*/ */
static async deprecateURL(url) { static async deprecateURL(url) {
let currentPrimaryBaseURL = await setting("primaryBaseURL"); let currentPrimaryBaseURL = await setting("primaryBaseURL");
@ -25,6 +27,9 @@ class Slack extends NotificationProvider {
} }
} }
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -4,6 +4,9 @@ const axios = require("axios");
class SMSC extends NotificationProvider { class SMSC extends NotificationProvider {
name = "smsc"; name = "smsc";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -5,6 +5,9 @@ class SMSEagle extends NotificationProvider {
name = "SMSEagle"; name = "SMSEagle";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -5,6 +5,9 @@ class SMSManager extends NotificationProvider {
name = "SMSManager"; name = "SMSManager";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
try { try {
let data = { let data = {

@ -6,6 +6,9 @@ class SMTP extends NotificationProvider {
name = "smtp"; name = "smtp";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const config = { const config = {

@ -37,7 +37,8 @@ class Splunk extends NotificationProvider {
/** /**
* Check if result is successful, result code should be in range 2xx * Check if result is successful, result code should be in range 2xx
* @param {Object} result Axios response object * @param {object} result Axios response object
* @returns {void}
* @throws {Error} The status code is not in range 2xx * @throws {Error} The status code is not in range 2xx
*/ */
checkResult(result) { checkResult(result) {
@ -54,9 +55,9 @@ class Splunk extends NotificationProvider {
* @param {BeanModel} notification Message title * @param {BeanModel} notification Message title
* @param {string} title Message title * @param {string} title Message title
* @param {string} body Message * @param {string} body Message
* @param {Object} monitorInfo Monitor details (For Up/Down only) * @param {object} monitorInfo Monitor details (For Up/Down only)
* @param {?string} eventAction Action event for PagerDuty (trigger, acknowledge, resolve) * @param {?string} eventAction Action event for PagerDuty (trigger, acknowledge, resolve)
* @returns {string} * @returns {Promise<string>} Success state
*/ */
async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") { async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") {

@ -6,6 +6,9 @@ class Squadcast extends NotificationProvider {
name = "squadcast"; name = "squadcast";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -7,6 +7,9 @@ class Stackfield extends NotificationProvider {
name = "stackfield"; name = "stackfield";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null) { async send(notification, msg, monitorJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
try { try {

@ -9,7 +9,7 @@ class Teams extends NotificationProvider {
* Generate the message to send * Generate the message to send
* @param {const} status The status constant * @param {const} status The status constant
* @param {string} monitorName Name of monitor * @param {string} monitorName Name of monitor
* @returns {string} * @returns {string} Status message
*/ */
_statusMessageFactory = (status, monitorName) => { _statusMessageFactory = (status, monitorName) => {
if (status === DOWN) { if (status === DOWN) {
@ -37,11 +37,12 @@ class Teams extends NotificationProvider {
/** /**
* Generate payload for notification * Generate payload for notification
* @param {const} status The status of the monitor * @param {object} args Method arguments
* @param {string} monitorMessage Message to send * @param {const} args.status The status of the monitor
* @param {string} monitorName Name of monitor affected * @param {string} args.monitorMessage Message to send
* @param {string} monitorUrl URL of monitor affected * @param {string} args.monitorName Name of monitor affected
* @returns {Object} * @param {string} args.monitorUrl URL of monitor affected
* @returns {object} Notification payload
*/ */
_notificationPayloadFactory = ({ _notificationPayloadFactory = ({
status, status,
@ -96,7 +97,8 @@ class Teams extends NotificationProvider {
/** /**
* Send the notification * Send the notification
* @param {string} webhookUrl URL to send the request to * @param {string} webhookUrl URL to send the request to
* @param {Object} payload Payload generated by _notificationPayloadFactory * @param {object} payload Payload generated by _notificationPayloadFactory
* @returns {Promise<void>}
*/ */
_sendNotification = async (webhookUrl, payload) => { _sendNotification = async (webhookUrl, payload) => {
await axios.post(webhookUrl, payload); await axios.post(webhookUrl, payload);
@ -116,6 +118,9 @@ class Teams extends NotificationProvider {
return this._sendNotification(webhookUrl, payload); return this._sendNotification(webhookUrl, payload);
}; };
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -5,6 +5,9 @@ class TechulusPush extends NotificationProvider {
name = "PushByTechulus"; name = "PushByTechulus";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -5,6 +5,9 @@ class Telegram extends NotificationProvider {
name = "telegram"; name = "telegram";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -5,6 +5,9 @@ class Twilio extends NotificationProvider {
name = "twilio"; name = "twilio";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -7,6 +7,9 @@ class Webhook extends NotificationProvider {
name = "webhook"; name = "webhook";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -6,6 +6,9 @@ class WeCom extends NotificationProvider {
name = "WeCom"; name = "WeCom";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";
@ -26,9 +29,9 @@ class WeCom extends NotificationProvider {
/** /**
* Generate the message to send * Generate the message to send
* @param {Object} heartbeatJSON Heartbeat details (For Up/Down only) * @param {object} heartbeatJSON Heartbeat details (For Up/Down only)
* @param {string} msg General message * @param {string} msg General message
* @returns {Object} * @returns {object} Message
*/ */
composeMessage(heartbeatJSON, msg) { composeMessage(heartbeatJSON, msg) {
let title; let title;

@ -10,7 +10,7 @@ class ZohoCliq extends NotificationProvider {
* Generate the message to send * Generate the message to send
* @param {const} status The status constant * @param {const} status The status constant
* @param {string} monitorName Name of monitor * @param {string} monitorName Name of monitor
* @returns {string} * @returns {string} Status message
*/ */
_statusMessageFactory = (status, monitorName) => { _statusMessageFactory = (status, monitorName) => {
if (status === DOWN) { if (status === DOWN) {
@ -25,6 +25,7 @@ class ZohoCliq extends NotificationProvider {
* Send the notification * Send the notification
* @param {string} webhookUrl URL to send the request to * @param {string} webhookUrl URL to send the request to
* @param {Array} payload Payload generated by _notificationPayloadFactory * @param {Array} payload Payload generated by _notificationPayloadFactory
* @returns {Promise<void>}
*/ */
_sendNotification = async (webhookUrl, payload) => { _sendNotification = async (webhookUrl, payload) => {
await axios.post(webhookUrl, { text: payload.join("\n") }); await axios.post(webhookUrl, { text: payload.join("\n") });
@ -32,11 +33,12 @@ class ZohoCliq extends NotificationProvider {
/** /**
* Generate payload for notification * Generate payload for notification
* @param {const} status The status of the monitor * @param {object} args Method arguments
* @param {string} monitorMessage Message to send * @param {const} args.status The status of the monitor
* @param {string} monitorName Name of monitor affected * @param {string} args.monitorMessage Message to send
* @param {string} monitorUrl URL of monitor affected * @param {string} args.monitorName Name of monitor affected
* @returns {Array} * @param {string} args.monitorUrl URL of monitor affected
* @returns {Array} Notification payload
*/ */
_notificationPayloadFactory = ({ _notificationPayloadFactory = ({
status, status,
@ -74,6 +76,9 @@ class ZohoCliq extends NotificationProvider {
return this._sendNotification(webhookUrl, payload); return this._sendNotification(webhookUrl, payload);
}; };
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully."; let okMsg = "Sent Successfully.";

@ -58,7 +58,12 @@ class Notification {
providerList = {}; providerList = {};
/** Initialize the notification providers */ /**
* Initialize the notification providers
* @returns {void}
* @throws Notification provider does not have a name
* @throws Duplicate notification providers in list
*/
static init() { static init() {
log.info("notification", "Prepare Notification Providers"); log.info("notification", "Prepare Notification Providers");
@ -133,10 +138,10 @@ class Notification {
/** /**
* Send a notification * Send a notification
* @param {BeanModel} notification * @param {BeanModel} notification Notification to send
* @param {string} msg General Message * @param {string} msg General Message
* @param {Object} monitorJSON Monitor details (For Up/Down only) * @param {object} monitorJSON Monitor details (For Up/Down only)
* @param {Object} heartbeatJSON Heartbeat details (For Up/Down only) * @param {object} heartbeatJSON Heartbeat details (For Up/Down only)
* @returns {Promise<string>} Successful msg * @returns {Promise<string>} Successful msg
* @throws Error with fail msg * @throws Error with fail msg
*/ */
@ -150,10 +155,10 @@ class Notification {
/** /**
* Save a notification * Save a notification
* @param {Object} notification Notification to save * @param {object} notification Notification to save
* @param {?number} notificationID ID of notification to update * @param {?number} notificationID ID of notification to update
* @param {number} userID ID of user who adds notification * @param {number} userID ID of user who adds notification
* @returns {Promise<Bean>} * @returns {Promise<Bean>} Notification that was saved
*/ */
static async save(notification, notificationID, userID) { static async save(notification, notificationID, userID) {
let bean; let bean;

@ -4,8 +4,8 @@ const saltRounds = 10;
/** /**
* Hash a password * Hash a password
* @param {string} password * @param {string} password Password to hash
* @returns {string} * @returns {string} Hash
*/ */
exports.generate = function (password) { exports.generate = function (password) {
return bcrypt.hashSync(password, saltRounds); return bcrypt.hashSync(password, saltRounds);
@ -13,8 +13,8 @@ exports.generate = function (password) {
/** /**
* Verify a password against a hash * Verify a password against a hash
* @param {string} password * @param {string} password Password to verify
* @param {string} hash * @param {string} hash Hash to verify against
* @returns {boolean} Does the password match the hash? * @returns {boolean} Does the password match the hash?
*/ */
exports.verify = function (password, hash) { exports.verify = function (password, hash) {
@ -27,8 +27,8 @@ exports.verify = function (password, hash) {
/** /**
* Is the hash a SHA1 hash * Is the hash a SHA1 hash
* @param {string} hash * @param {string} hash Hash to check
* @returns {boolean} * @returns {boolean} Is SHA1 hash?
*/ */
function isSHA1(hash) { function isSHA1(hash) {
return (typeof hash === "string" && hash.startsWith("sha1")); return (typeof hash === "string" && hash.startsWith("sha1"));
@ -36,7 +36,8 @@ function isSHA1(hash) {
/** /**
* Does the hash need to be rehashed? * Does the hash need to be rehashed?
* @returns {boolean} * @param {string} hash Hash to check
* @returns {boolean} Needs to be rehashed?
*/ */
exports.needRehash = function (hash) { exports.needRehash = function (hash) {
return isSHA1(hash); return isSHA1(hash);

@ -36,7 +36,7 @@ class Prometheus {
monitorLabelValues = {}; monitorLabelValues = {};
/** /**
* @param {Object} monitor Monitor object to monitor * @param {object} monitor Monitor object to monitor
*/ */
constructor(monitor) { constructor(monitor) {
this.monitorLabelValues = { this.monitorLabelValues = {
@ -50,8 +50,9 @@ class Prometheus {
/** /**
* Update the metrics page * Update the metrics page
* @param {Object} heartbeat Heartbeat details * @param {object} heartbeat Heartbeat details
* @param {Object} tlsInfo TLS details * @param {object} tlsInfo TLS details
* @returns {void}
*/ */
update(heartbeat, tlsInfo) { update(heartbeat, tlsInfo) {
@ -99,7 +100,10 @@ class Prometheus {
} }
} }
/** Remove monitor from prometheus */ /**
* Remove monitor from prometheus
* @returns {void}
*/
remove() { remove() {
try { try {
monitorCertDaysRemaining.remove(this.monitorLabelValues); monitorCertDaysRemaining.remove(this.monitorLabelValues);

@ -11,11 +11,10 @@ class Proxy {
/** /**
* Saves and updates given proxy entity * Saves and updates given proxy entity
* * @param {object} proxy Proxy to store
* @param proxy * @param {number} proxyID ID of proxy to update
* @param proxyID * @param {number} userID ID of user the proxy belongs to
* @param userID * @returns {Promise<Bean>} Updated proxy
* @return {Promise<Bean>}
*/ */
static async save(proxy, proxyID, userID) { static async save(proxy, proxyID, userID) {
let bean; let bean;
@ -65,10 +64,9 @@ class Proxy {
/** /**
* Deletes proxy with given id and removes it from monitors * Deletes proxy with given id and removes it from monitors
* * @param {number} proxyID ID of proxy to delete
* @param proxyID * @param {number} userID ID of proxy owner
* @param userID * @returns {Promise<void>}
* @return {Promise<void>}
*/ */
static async delete(proxyID, userID) { static async delete(proxyID, userID) {
const bean = await R.findOne("proxy", " id = ? AND user_id = ? ", [ proxyID, userID ]); const bean = await R.findOne("proxy", " id = ? AND user_id = ? ", [ proxyID, userID ]);
@ -86,10 +84,10 @@ class Proxy {
/** /**
* Create HTTP and HTTPS agents related with given proxy bean object * Create HTTP and HTTPS agents related with given proxy bean object
* * @param {object} proxy proxy bean object
* @param proxy proxy bean object * @param {object} options http and https agent options
* @param options http and https agent options * @returns {{httpAgent: Agent, httpsAgent: Agent}} New HTTP and HTTPS agents
* @return {{httpAgent: Agent, httpsAgent: Agent}} * @throws Proxy protocol is unsupported
*/ */
static createAgents(proxy, options) { static createAgents(proxy, options) {
const { httpAgentOptions, httpsAgentOptions } = options || {}; const { httpAgentOptions, httpsAgentOptions } = options || {};
@ -171,10 +169,9 @@ class Proxy {
/** /**
* Applies given proxy id to monitors * Applies given proxy id to monitors
* * @param {number} proxyID ID of proxy to apply
* @param proxyID * @param {number} userID ID of proxy owner
* @param userID * @returns {Promise<void>}
* @return {Promise<void>}
*/ */
async function applyProxyEveryMonitor(proxyID, userID) { async function applyProxyEveryMonitor(proxyID, userID) {
// Find all monitors with id and proxy id // Find all monitors with id and proxy id

@ -3,7 +3,7 @@ const { log } = require("../src/util");
class KumaRateLimiter { class KumaRateLimiter {
/** /**
* @param {Object} config Rate limiter configuration object * @param {object} config Rate limiter configuration object
*/ */
constructor(config) { constructor(config) {
this.errorMessage = config.errorMessage; this.errorMessage = config.errorMessage;
@ -13,14 +13,14 @@ class KumaRateLimiter {
/** /**
* Callback for pass * Callback for pass
* @callback passCB * @callback passCB
* @param {Object} err Too many requests * @param {object} err Too many requests
*/ */
/** /**
* Should the request be passed through * Should the request be passed through
* @param {passCB} callback * @param {passCB} callback Callback function to call with decision
* @param {number} [num=1] Number of tokens to remove * @param {number} num Number of tokens to remove
* @returns {Promise<boolean>} * @returns {Promise<boolean>} Should the request be allowed?
*/ */
async pass(callback, num = 1) { async pass(callback, num = 1) {
const remainingRequests = await this.removeTokens(num); const remainingRequests = await this.removeTokens(num);
@ -39,8 +39,8 @@ class KumaRateLimiter {
/** /**
* Remove a given number of tokens * Remove a given number of tokens
* @param {number} [num=1] Number of tokens to remove * @param {number} num Number of tokens to remove
* @returns {Promise<number>} * @returns {Promise<number>} Number of remaining tokens
*/ */
async removeTokens(num = 1) { async removeTokens(num = 1) {
return await this.rateLimiter.removeTokens(num); return await this.rateLimiter.removeTokens(num);

@ -1699,8 +1699,8 @@ async function updateMonitorNotification(monitorID, notificationIDList) {
/** /**
* Check if a given user owns a specific monitor * Check if a given user owns a specific monitor
* @param {number} userID * @param {number} userID ID of user to check
* @param {number} monitorID * @param {number} monitorID ID of monitor to check
* @returns {Promise<void>} * @returns {Promise<void>}
* @throws {Error} The specified user does not own the monitor * @throws {Error} The specified user does not own the monitor
*/ */
@ -1719,7 +1719,7 @@ async function checkOwner(userID, monitorID) {
* Function called after user login * Function called after user login
* This function is used to send the heartbeat list of a monitor. * This function is used to send the heartbeat list of a monitor.
* @param {Socket} socket Socket.io instance * @param {Socket} socket Socket.io instance
* @param {Object} user User object * @param {object} user User object
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async function afterLogin(socket, user) { async function afterLogin(socket, user) {
@ -1760,7 +1760,7 @@ async function afterLogin(socket, user) {
/** /**
* Initialize the database * Initialize the database
* @param {boolean} [testMode=false] Should the connection be * @param {boolean} testMode Should the connection be
* started in test mode? * started in test mode?
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
@ -1852,7 +1852,10 @@ async function pauseMonitor(userID, monitorID) {
} }
} }
/** Resume active monitors */ /**
* Resume active monitors
* @returns {Promise<void>}
*/
async function startMonitors() { async function startMonitors() {
let list = await R.find("monitor", " active = 1 "); let list = await R.find("monitor", " active = 1 ");
@ -1896,7 +1899,10 @@ async function shutdownFunction(signal) {
Settings.stopCacheCleaner(); Settings.stopCacheCleaner();
} }
/** Final function called before application exits */ /**
* Final function called before application exits
* @returns {void}
*/
function finalFunction() { function finalFunction() {
log.info("server", "Graceful shutdown successful!"); log.info("server", "Graceful shutdown successful!");
} }

@ -96,7 +96,7 @@ class Settings {
/** /**
* Get settings based on type * Get settings based on type
* @param {string} type The type of setting * @param {string} type The type of setting
* @returns {Promise<Bean>} * @returns {Promise<Bean>} Settings
*/ */
static async getSettings(type) { static async getSettings(type) {
let list = await R.getAll("SELECT `key`, `value` FROM setting WHERE `type` = ? ", [ let list = await R.getAll("SELECT `key`, `value` FROM setting WHERE `type` = ? ", [
@ -119,7 +119,7 @@ class Settings {
/** /**
* Set settings based on type * Set settings based on type
* @param {string} type Type of settings to set * @param {string} type Type of settings to set
* @param {Object} data Values of settings * @param {object} data Values of settings
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static async setSettings(type, data) { static async setSettings(type, data) {
@ -150,8 +150,9 @@ class Settings {
} }
/** /**
* * Delete selected keys from settings cache
* @param {string[]} keyList * @param {string[]} keyList Keys to remove
* @returns {void}
*/ */
static deleteCache(keyList) { static deleteCache(keyList) {
for (let key of keyList) { for (let key of keyList) {
@ -159,6 +160,10 @@ class Settings {
} }
} }
/**
* Stop the cache cleaner if running
* @returns {void}
*/
static stopCacheCleaner() { static stopCacheCleaner() {
if (Settings.cacheCleaner) { if (Settings.cacheCleaner) {
clearInterval(Settings.cacheCleaner); clearInterval(Settings.cacheCleaner);

@ -9,8 +9,9 @@ const { Settings } = require("../settings");
const { sendAPIKeyList } = require("../client"); const { sendAPIKeyList } = require("../client");
/** /**
* Handlers for Maintenance * Handlers for API keys
* @param {Socket} socket Socket.io instance * @param {Socket} socket Socket.io instance
* @returns {void}
*/ */
module.exports.apiKeySocketHandler = (socket) => { module.exports.apiKeySocketHandler = (socket) => {
// Add a new api key // Add a new api key

@ -11,6 +11,7 @@ const cloudflared = new CloudflaredTunnel();
* Change running state * Change running state
* @param {string} running Is it running? * @param {string} running Is it running?
* @param {string} message Message to pass * @param {string} message Message to pass
* @returns {void}
*/ */
cloudflared.change = (running, message) => { cloudflared.change = (running, message) => {
io.to("cloudflared").emit(prefix + "running", running); io.to("cloudflared").emit(prefix + "running", running);
@ -19,7 +20,8 @@ cloudflared.change = (running, message) => {
/** /**
* Emit an error message * Emit an error message
* @param {string} errorMessage * @param {string} errorMessage Error message to send
* @returns {void}
*/ */
cloudflared.error = (errorMessage) => { cloudflared.error = (errorMessage) => {
io.to("cloudflared").emit(prefix + "errorMessage", errorMessage); io.to("cloudflared").emit(prefix + "errorMessage", errorMessage);
@ -28,6 +30,7 @@ cloudflared.error = (errorMessage) => {
/** /**
* Handler for cloudflared * Handler for cloudflared
* @param {Socket} socket Socket.io instance * @param {Socket} socket Socket.io instance
* @returns {void}
*/ */
module.exports.cloudflaredSocketHandler = (socket) => { module.exports.cloudflaredSocketHandler = (socket) => {
@ -89,6 +92,7 @@ module.exports.cloudflaredSocketHandler = (socket) => {
/** /**
* Automatically start cloudflared * Automatically start cloudflared
* @param {string} token Cloudflared tunnel token * @param {string} token Cloudflared tunnel token
* @returns {Promise<void>}
*/ */
module.exports.autoStart = async (token) => { module.exports.autoStart = async (token) => {
if (!token) { if (!token) {
@ -106,7 +110,10 @@ module.exports.autoStart = async (token) => {
} }
}; };
/** Stop cloudflared */ /**
* Stop cloudflared
* @returns {Promise<void>}
*/
module.exports.stop = async () => { module.exports.stop = async () => {
log.info("cloudflared", "Stop cloudflared"); log.info("cloudflared", "Stop cloudflared");
if (cloudflared) { if (cloudflared) {

@ -4,6 +4,7 @@ const Database = require("../database");
/** /**
* Handlers for database * Handlers for database
* @param {Socket} socket Socket.io instance * @param {Socket} socket Socket.io instance
* @returns {void}
*/ */
module.exports = (socket) => { module.exports = (socket) => {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save