diff --git a/package-lock.json b/package-lock.json index 96c9eef8..4475c5f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "uptime-kuma", - "version": "1.23.0", + "version": "1.23.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "uptime-kuma", - "version": "1.23.0", + "version": "1.23.1", "license": "MIT", "dependencies": { "@grpc/grpc-js": "~1.7.3", diff --git a/server/database.js b/server/database.js index 6af8b9b0..ac62c964 100644 --- a/server/database.js +++ b/server/database.js @@ -134,7 +134,10 @@ class Database { } /** - * + * Read the database config + * @throws {Error} If the config is invalid + * @typedef {string|undefined} envString + * @returns {{type: "sqlite"} | {type:envString, hostname:envString, port:envString, database:envString, username:envString, password:envString}} Database config */ static readDBConfig() { let dbConfig; @@ -153,7 +156,9 @@ class Database { } /** - * @param dbConfig + * @typedef {string|undefined} envString + * @param {{type: "sqlite"} | {type:envString, hostname:envString, port:envString, database:envString, username:envString, password:envString}} dbConfig the database configuration that should be written + * @returns {void} */ static writeDBConfig(dbConfig) { fs.writeFileSync(path.join(Database.dataDir, "db-config.json"), JSON.stringify(dbConfig, null, 4)); @@ -161,10 +166,8 @@ class Database { /** * Connect to the database - * @param {boolean} testMode Should the connection be - * started in test mode? - * @param {boolean} autoloadModels Should models be - * automatically loaded? + * @param {boolean} testMode Should the connection be started in test mode? + * @param {boolean} autoloadModels Should models be automatically loaded? * @param {boolean} noLog Should logs not be output? * @returns {Promise} */ @@ -292,8 +295,9 @@ class Database { } /** - * @param testMode - * @param noLog + @param {boolean} testMode Should the connection be started in test mode? + @param {boolean} noLog Should logs not be output? + @returns {Promise} */ static async initSQLite(testMode, noLog) { await R.exec("PRAGMA foreign_keys = ON"); @@ -321,7 +325,8 @@ class Database { } /** - * + * Initialize MariaDB + * @returns {Promise} */ static async initMariaDB() { log.debug("db", "Checking if MariaDB database exists..."); @@ -368,6 +373,7 @@ class Database { /** * Patch the database for SQLite + * @returns {Promise} * @deprecated */ static async patchSqlite() { @@ -650,7 +656,7 @@ class Database { } /** - * + * @returns {string} Get the SQL for the current time plus a number of hours */ static sqlHourOffset() { if (Database.dbConfig.type === "sqlite") { diff --git a/server/embedded-mariadb.js b/server/embedded-mariadb.js index d6395db4..8aa7134b 100644 --- a/server/embedded-mariadb.js +++ b/server/embedded-mariadb.js @@ -18,13 +18,17 @@ class EmbeddedMariaDB { socketPath = this.runDir + "/mysqld.sock"; + /** + * @type {ChildProcessWithoutNullStreams} + * @private + */ childProcess = null; running = false; started = false; /** - * @returns {EmbeddedMariaDB} + * @returns {EmbeddedMariaDB} The singleton instance */ static getInstance() { if (!EmbeddedMariaDB.instance) { @@ -34,14 +38,15 @@ class EmbeddedMariaDB { } /** - * + * @returns {boolean} If the singleton instance is created */ static hasInstance() { return !!EmbeddedMariaDB.instance; } /** - * + * Start the embedded MariaDB + * @returns {Promise|void} A promise that resolves when the MariaDB is started or void if it is already started */ start() { if (this.childProcess) { @@ -103,7 +108,8 @@ class EmbeddedMariaDB { } /** - * + * Stop all the child processes + * @returns {void} */ stop() { if (this.childProcess) { @@ -113,7 +119,8 @@ class EmbeddedMariaDB { } /** - * + * Install MariaDB if it is not installed and make sure the `runDir` directory exists + * @returns {void} */ initDB() { if (!fs.existsSync(this.mariadbDataDir)) { @@ -146,7 +153,8 @@ class EmbeddedMariaDB { } /** - * + * Initialise the "kuma" database in mariadb if it does not exist + * @returns {Promise} */ async initDBAfterStarted() { const connection = mysql.createConnection({ diff --git a/server/model/monitor.js b/server/model/monitor.js index 461b97e5..09d0f2b5 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -291,7 +291,8 @@ class Monitor extends BeanModel { } /** - * + * Get if game dig should only use the port which was provided + * @returns {boolean} gamedig should only use the provided port */ getGameDigGivenPortOnly() { return Boolean(this.gamedigGivenPortOnly); diff --git a/server/setup-database.js b/server/setup-database.js index 0c408365..920d4237 100644 --- a/server/setup-database.js +++ b/server/setup-database.js @@ -8,24 +8,32 @@ const { allowDevAllOrigin } = require("./util-server"); const mysql = require("mysql2/promise"); /** - * A standalone express app that is used to setup database + * A standalone express app that is used to setup a database * It is used when db-config.json and kuma.db are not found or invalid - * Once it is configured, it will shutdown and start the main server + * Once it is configured, it will shut down and start the main server */ class SetupDatabase { - /** * Show Setup Page * @type {boolean} */ needSetup = true; + /** + * If the server has finished the setup + * @type {boolean} + * @private + */ runningSetup = false; - + /** + * @inheritDoc + * @type {UptimeKumaServer} + * @private + */ server; /** - * @param args - * @param server + * @param {object} args The arguments passed from the command line + * @param {UptimeKumaServer} server the main server instance */ constructor(args, server) { this.server = server; @@ -76,21 +84,25 @@ class SetupDatabase { /** * Show Setup Page + * @returns {boolean} true if the setup page should be shown */ isNeedSetup() { return this.needSetup; } /** - * + * Check if the embedded MariaDB is enabled + * @returns {boolean} true if the embedded MariaDB is enabled */ isEnabledEmbeddedMariaDB() { return process.env.UPTIME_KUMA_ENABLE_EMBEDDED_MARIADB === "1"; } /** - * @param hostname - * @param port + * Start the setup-database server + * @param {string} hostname where the server is listening + * @param {number} port where the server is listening + * @returns {Promise} */ start(hostname, port) { return new Promise((resolve) => { diff --git a/server/uptime-calculator.js b/server/uptime-calculator.js index e21a7bd1..b6e8346f 100644 --- a/server/uptime-calculator.js +++ b/server/uptime-calculator.js @@ -8,6 +8,10 @@ const { R } = require("redbean-node"); * Calculates the uptime of a monitor. */ class UptimeCalculator { + /** + * @private + * @type {{string:UptimeCalculator}} + */ static list = {}; @@ -17,11 +21,16 @@ class UptimeCalculator { */ static currentDate = null; + /** + * monitorID the id of the monitor + * @type {number} + */ monitorID; /** * Recent 24-hour uptime, each item is a 1-minute interval * Key: {number} DivisionKey + * @type {LimitQueue} */ minutelyUptimeDataList = new LimitQueue(24 * 60); @@ -38,8 +47,10 @@ class UptimeCalculator { lastMinutelyStatBean = null; /** - * @param monitorID - * @returns {Promise} + * Get the uptime calculator for a monitor + * Initializes and returns the monitor if it does not exist + * @param {number} monitorID the id of the monitor + * @returns {Promise} UptimeCalculator */ static async getUptimeCalculator(monitorID) { if (!UptimeCalculator.list[monitorID]) { @@ -50,7 +61,9 @@ class UptimeCalculator { } /** - * @param monitorID + * Remove a monitor from the list + * @param {number} monitorID the id of the monitor + * @returns {Promise} */ static async remove(monitorID) { delete UptimeCalculator.list[monitorID]; @@ -74,7 +87,9 @@ class UptimeCalculator { } /** - * @param {number} monitorID + * Initialize the uptime calculator for a monitor + * @param {number} monitorID the id of the monitor + * @returns {Promise} */ async init(monitorID) { this.monitorID = monitorID; @@ -300,8 +315,8 @@ class UptimeCalculator { /** * Flat status to UP or DOWN - * @param {number} status - * @returns {number} + * @param {number} status the status which schould be turned into a flat status + * @returns {UP|DOWN|PENDING} The flat status * @throws {Error} Invalid status */ flatStatus(status) { @@ -317,8 +332,10 @@ class UptimeCalculator { } /** - * @param {number} num - * @param {string} type "day" | "minute" + * @param {number} num the number of data points which are expected to be returned + * @param {"day" | "minute"} type the type of data which is expected to be returned + * @returns {UptimeDataResult} UptimeDataResult + * @throws {Error} The maximum number of minutes greater than 1440 */ getData(num, type = "day") { let key; diff --git a/server/utils/array-with-key.js b/server/utils/array-with-key.js index 847bc24f..94afc792 100644 --- a/server/utils/array-with-key.js +++ b/server/utils/array-with-key.js @@ -1,20 +1,22 @@ /** * An object that can be used as an array with a key * Like PHP's array + * @template K + * @template V */ class ArrayWithKey { - __stack = []; - /** - * + * All keys that are stored in the current object + * @type {K[]} + * @private */ - constructor() { - - } + __stack = []; /** - * @param key - * @param value + * Push an element to the end of the array + * @param {K} key The key of the element + * @param {V} value The value of the element + * @returns {void} */ push(key, value) { this[key] = value; @@ -22,7 +24,8 @@ class ArrayWithKey { } /** - * + * Get the last element and remove it from the array + * @returns {V|undefined} The first value, or undefined if there is no element to pop */ pop() { let key = this.__stack.pop(); @@ -32,7 +35,8 @@ class ArrayWithKey { } /** - * + * Get the last key + * @returns {K|null} The last key, or null if the array is empty */ getLastKey() { if (this.__stack.length === 0) { @@ -42,7 +46,8 @@ class ArrayWithKey { } /** - * + * Get the first element + * @returns {{key:K,value:V}|null} The first element, or null if the array is empty */ shift() { let key = this.__stack.shift(); @@ -55,15 +60,16 @@ class ArrayWithKey { } /** - * + * Get the length of the array + * @returns {number} Amount of elements stored */ length() { return this.__stack.length; } /** - * Get the last element - * @returns {*|null} The last element, or null if the array is empty + * Get the last value + * @returns {V|null} The last element without removing it, or null if the array is empty */ last() { let key = this.getLastKey(); diff --git a/server/utils/limit-queue.js b/server/utils/limit-queue.js index a4744f4a..9da6d410 100644 --- a/server/utils/limit-queue.js +++ b/server/utils/limit-queue.js @@ -6,11 +6,22 @@ const { ArrayWithKey } = require("./array-with-key"); */ class LimitQueue extends ArrayWithKey { + /** + * The limit of the queue after which the first element will be removed + * @private + * @type {number} + */ __limit; + /** + * The callback function when the queue exceeds the limit + * @private + * @callback onExceedCallback + * @param {{key:K,value:V}|nul} item + */ __onExceed = null; /** - * @param {number} limit + * @param {number} limit The limit of the queue after which the first element will be removed */ constructor(limit) { super(); diff --git a/src/components/settings/Notifications.vue b/src/components/settings/Notifications.vue index 6819cece..99a8077f 100644 --- a/src/components/settings/Notifications.vue +++ b/src/components/settings/Notifications.vue @@ -166,6 +166,7 @@ export default { /** * Loads toast timeout settings from storage to component data. + * @returns {void} */ loadToastTimeoutSettings() { const successTimeout = localStorage.toastSuccessTimeout; diff --git a/src/layouts/Layout.vue b/src/layouts/Layout.vue index 034fe40c..3abbc401 100644 --- a/src/layouts/Layout.vue +++ b/src/layouts/Layout.vue @@ -197,6 +197,7 @@ export default { methods: { /** * Clear all toast notifications. + * @returns {void} */ clearToasts() { toast.clear(); diff --git a/test/backend-test/test-uptime-calculator.js b/test/backend-test/test-uptime-calculator.js index 469904bf..b4ccc312 100644 --- a/test/backend-test/test-uptime-calculator.js +++ b/test/backend-test/test-uptime-calculator.js @@ -353,18 +353,18 @@ test("Test get1YearUptime (1 check per day)", async (t) => { /** * Code from here: https://stackoverflow.com/a/64550489/1097815 + * @returns {{rss: string, heapTotal: string, heapUsed: string, external: string}} Current memory usage */ function memoryUsage() { const formatMemoryUsage = (data) => `${Math.round(data / 1024 / 1024 * 100) / 100} MB`; const memoryData = process.memoryUsage(); - const memoryUsage = { + return { rss: `${formatMemoryUsage(memoryData.rss)} -> Resident Set Size - total memory allocated for the process execution`, heapTotal: `${formatMemoryUsage(memoryData.heapTotal)} -> total size of the allocated heap`, heapUsed: `${formatMemoryUsage(memoryData.heapUsed)} -> actual memory used during the execution`, external: `${formatMemoryUsage(memoryData.external)} -> V8 external memory`, }; - return memoryUsage; } test("Worst case", async (t) => {