mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-02-26 13:35:56 +00:00
Compare commits
No commits in common. "fb4f51c7eaa5af06a8bdd82792e87b1ca866bc13" and "3a20e4726d9f8fe063129e00792d9f3dfe3a5649" have entirely different histories.
fb4f51c7ea
...
3a20e4726d
4 changed files with 117 additions and 20 deletions
70
extra/check-knex-filenames.mjs
Normal file
70
extra/check-knex-filenames.mjs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import fs from "fs";
|
||||||
|
const dir = "./db/knex_migrations";
|
||||||
|
|
||||||
|
// Get the file list (ending with .js) from the directory
|
||||||
|
const files = fs.readdirSync(dir).filter((file) => file !== "README.md");
|
||||||
|
|
||||||
|
// They are wrong, but they had been merged, so allowed.
|
||||||
|
const exceptionList = [
|
||||||
|
"2024-08-24-000-add-cache-bust.js",
|
||||||
|
"2024-10-1315-rabbitmq-monitor.js",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Correct format: YYYY-MM-DD-HHmm-description.js
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
if (exceptionList.includes(file)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check ending with .js
|
||||||
|
if (!file.endsWith(".js")) {
|
||||||
|
console.error(`It should end with .js: ${file}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = file.split("-");
|
||||||
|
|
||||||
|
// Should be at least 5 parts
|
||||||
|
if (parts.length < 5) {
|
||||||
|
console.error(`Invalid format: ${file}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First part should be a year >= 2024
|
||||||
|
const year = parseInt(parts[0], 10);
|
||||||
|
if (isNaN(year) || year < 2023) {
|
||||||
|
console.error(`Invalid year: ${file}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second part should be a month
|
||||||
|
const month = parseInt(parts[1], 10);
|
||||||
|
if (isNaN(month) || month < 1 || month > 12) {
|
||||||
|
console.error(`Invalid month: ${file}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third part should be a day
|
||||||
|
const day = parseInt(parts[2], 10);
|
||||||
|
if (isNaN(day) || day < 1 || day > 31) {
|
||||||
|
console.error(`Invalid day: ${file}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fourth part should be HHmm
|
||||||
|
const time = parts[3];
|
||||||
|
|
||||||
|
// Check length is 4
|
||||||
|
if (time.length !== 4) {
|
||||||
|
console.error(`Invalid time: ${file}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hour = parseInt(time.substring(0, 2), 10);
|
||||||
|
const minute = parseInt(time.substring(2), 10);
|
||||||
|
if (isNaN(hour) || hour < 0 || hour > 23 || isNaN(minute) || minute < 0 || minute > 59) {
|
||||||
|
console.error(`Invalid time: ${file}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,6 @@ const { Settings } = require("./settings");
|
||||||
const { UptimeCalculator } = require("./uptime-calculator");
|
const { UptimeCalculator } = require("./uptime-calculator");
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
const { SimpleMigrationServer } = require("./utils/simple-migration-server");
|
const { SimpleMigrationServer } = require("./utils/simple-migration-server");
|
||||||
const KumaColumnCompiler = require("./utils/knex/lib/dialects/mysql2/schema/mysql2-columncompiler");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database & App Data Folder
|
* Database & App Data Folder
|
||||||
|
@ -191,6 +190,14 @@ class Database {
|
||||||
fs.writeFileSync(path.join(Database.dataDir, "db-config.json"), JSON.stringify(dbConfig, null, 4));
|
fs.writeFileSync(path.join(Database.dataDir, "db-config.json"), JSON.stringify(dbConfig, null, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the MySQL2 Knex client
|
||||||
|
* @returns {KumaMySQL2} MySQL2 Knex client
|
||||||
|
*/
|
||||||
|
static getMySQL2KnexClient() {
|
||||||
|
return require("./utils/knex/lib/dialects/mysql2/index");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to the database
|
* Connect to the database
|
||||||
* @param {boolean} testMode Should the connection be started in test mode?
|
* @param {boolean} testMode Should the connection be started in test mode?
|
||||||
|
@ -199,14 +206,6 @@ class Database {
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
static async connect(testMode = false, autoloadModels = true, noLog = false) {
|
static async connect(testMode = false, autoloadModels = true, noLog = false) {
|
||||||
// Patch "mysql2" knex client
|
|
||||||
// Workaround: Tried extending the ColumnCompiler class, but it didn't work for unknown reasons, so I override the function via prototype
|
|
||||||
const { getDialectByNameOrAlias } = require("knex/lib/dialects");
|
|
||||||
const mysql2 = getDialectByNameOrAlias("mysql2");
|
|
||||||
mysql2.prototype.columnCompiler = function () {
|
|
||||||
return new KumaColumnCompiler(this, ...arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
const acquireConnectionTimeout = 120 * 1000;
|
const acquireConnectionTimeout = 120 * 1000;
|
||||||
let dbConfig;
|
let dbConfig;
|
||||||
try {
|
try {
|
||||||
|
@ -270,7 +269,7 @@ class Database {
|
||||||
connection.end();
|
connection.end();
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
client: "mysql2",
|
client: Database.getMySQL2KnexClient(),
|
||||||
connection: {
|
connection: {
|
||||||
host: dbConfig.hostname,
|
host: dbConfig.hostname,
|
||||||
port: dbConfig.port,
|
port: dbConfig.port,
|
||||||
|
@ -293,7 +292,7 @@ class Database {
|
||||||
await embeddedMariaDB.start();
|
await embeddedMariaDB.start();
|
||||||
log.info("mariadb", "Embedded MariaDB started");
|
log.info("mariadb", "Embedded MariaDB started");
|
||||||
config = {
|
config = {
|
||||||
client: "mysql2",
|
client: Database.getMySQL2KnexClient(),
|
||||||
connection: {
|
connection: {
|
||||||
socketPath: embeddedMariaDB.socketPath,
|
socketPath: embeddedMariaDB.socketPath,
|
||||||
user: "node",
|
user: "node",
|
||||||
|
|
20
server/utils/knex/lib/dialects/mysql2/index.js
Normal file
20
server/utils/knex/lib/dialects/mysql2/index.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
const ClientMySQL2 = require("knex/lib/dialects/mysql2/index");
|
||||||
|
const KumaColumnCompiler = require("./schema/mysql2-columncompiler");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed MySQL2 client class.
|
||||||
|
* - Fix: Default value for TEXT fields is not supported.
|
||||||
|
*/
|
||||||
|
class KumaMySQL2 extends ClientMySQL2 {
|
||||||
|
|
||||||
|
driverName = "mysql2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
columnCompiler() {
|
||||||
|
return new KumaColumnCompiler(this, ...arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = KumaMySQL2;
|
|
@ -1,21 +1,29 @@
|
||||||
const ColumnCompilerMySQL = require("knex/lib/dialects/mysql/schema/mysql-columncompiler");
|
const ColumnCompilerMySQL = require("knex/lib/dialects/mysql/schema/mysql-columncompiler");
|
||||||
const { formatDefault } = require("knex/lib/formatter/formatterUtils");
|
const { isObject } = require("knex/lib/util/is");
|
||||||
const { log } = require("../../../../../../../src/util");
|
|
||||||
|
|
||||||
class KumaColumnCompiler extends ColumnCompilerMySQL {
|
class KumaColumnCompiler extends ColumnCompilerMySQL {
|
||||||
/**
|
/**
|
||||||
* Override defaultTo method to handle default value for TEXT fields
|
* Diff: Override defaultTo method to handle default value for TEXT fields
|
||||||
* @param {any} value Value
|
* @param {any} value Value
|
||||||
* @returns {string|void} Default value (Don't understand why it can return void or string, but it's the original code, lol)
|
* @returns {string|void} Default value (Don't understand why it can return void or string, but it's the original code, lol)
|
||||||
*/
|
*/
|
||||||
defaultTo(value) {
|
defaultTo(value) {
|
||||||
if (this.type === "text" && typeof value === "string") {
|
// MySQL defaults to null by default, but breaks down if you pass it explicitly
|
||||||
log.debug("defaultTo", `${this.args[0]}: ${this.type} ${value} ${typeof value}`);
|
// Note that in MySQL versions up to 5.7, logic related to updating
|
||||||
// MySQL 8.0 is required and only if the value is written as an expression: https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html
|
// timestamps when no explicit value is passed is quite insane - https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_explicit_defaults_for_timestamp
|
||||||
// MariaDB 10.2 is required: https://mariadb.com/kb/en/text/
|
if (value === null || value === undefined) {
|
||||||
return `default (${formatDefault(value, this.type, this.client)})`;
|
return;
|
||||||
}
|
}
|
||||||
return super.defaultTo.apply(this, arguments);
|
if ((this.type === "json" || this.type === "jsonb") && isObject(value)) {
|
||||||
|
// Default value for json will work only it is an expression
|
||||||
|
return `default ('${JSON.stringify(value)}')`;
|
||||||
|
}
|
||||||
|
const defaultVal = super.defaultTo.apply(this, arguments);
|
||||||
|
|
||||||
|
// louislam deleted: (this.type !== "blob" && this.type.indexOf("text") === -1)
|
||||||
|
// Other code is the same as the original code
|
||||||
|
// See: https://github.com/louislam/uptime-kuma/pull/5048#discussion_r1818076626
|
||||||
|
return defaultVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue