Replace DBGate with local Adminer
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import { createWriteStream, existsSync, mkdirSync } from "node:fs";
|
||||
import { get } from "node:https";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
|
||||
const adminerFile = resolve("tools/adminer/adminer.php");
|
||||
const localPhp = resolve("tools/php/php.exe");
|
||||
const host = process.env.ADMINER_HOST || "127.0.0.1";
|
||||
const port = process.env.ADMINER_PORT || "8080";
|
||||
const adminerDownloadUrl = process.env.ADMINER_DOWNLOAD_URL || "https://www.adminer.org/latest.php";
|
||||
const phpCommand = existsSync(localPhp) ? localPhp : "php";
|
||||
|
||||
if (!commandExists(phpCommand)) {
|
||||
console.error("Adminer needs PHP CLI. Install PHP first, then run npm run adminer again.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!existsSync(adminerFile)) {
|
||||
mkdirSync(dirname(adminerFile), { recursive: true });
|
||||
await downloadFile(adminerDownloadUrl, adminerFile);
|
||||
}
|
||||
|
||||
const child = spawn(phpCommand, ["-S", `${host}:${port}`, adminerFile], {
|
||||
stdio: "inherit",
|
||||
shell: true,
|
||||
});
|
||||
|
||||
child.on("exit", (code, signal) => {
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal);
|
||||
return;
|
||||
}
|
||||
|
||||
process.exit(code ?? 0);
|
||||
});
|
||||
|
||||
function commandExists(command: string): boolean {
|
||||
const result = spawnSync(command, ["-v"], { stdio: "ignore", shell: true });
|
||||
return result.status === 0;
|
||||
}
|
||||
|
||||
function downloadFile(url: string, target: string): Promise<void> {
|
||||
return new Promise((resolveDownload, rejectDownload) => {
|
||||
const request = get(url, (response) => {
|
||||
if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
||||
downloadFile(response.headers.location, target).then(resolveDownload, rejectDownload);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
rejectDownload(new Error(`Adminer download failed with HTTP ${response.statusCode}`));
|
||||
return;
|
||||
}
|
||||
|
||||
const file = createWriteStream(target);
|
||||
response.pipe(file);
|
||||
file.on("finish", () => {
|
||||
file.close();
|
||||
resolveDownload();
|
||||
});
|
||||
file.on("error", rejectDownload);
|
||||
});
|
||||
|
||||
request.on("error", rejectDownload);
|
||||
});
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
|
||||
const envFile = ".env";
|
||||
const localEnv = fs.existsSync(envFile) ? readEnvFile(envFile) : {};
|
||||
|
||||
const host = localEnv.DB_HOST || "127.0.0.1";
|
||||
const port = localEnv.DB_PORT || "3306";
|
||||
const user = localEnv.DB_USER || "root";
|
||||
const password = localEnv.DB_PASSWORD || "";
|
||||
const catalogDatabase = localEnv.DB_NAME || "9bplus";
|
||||
const scrapeDatabase = localEnv.SCRAPE_DB_NAME || "catalog_scrape";
|
||||
|
||||
const dbgateEnv = {
|
||||
...process.env,
|
||||
CONNECTIONS: "local9bplus,localscrape",
|
||||
|
||||
ENGINE_local9bplus: "mariadb@dbgate-plugin-mysql",
|
||||
SERVER_local9bplus: host,
|
||||
PORT_local9bplus: port,
|
||||
USER_local9bplus: user,
|
||||
PASSWORD_local9bplus: password,
|
||||
DATABASE_local9bplus: catalogDatabase,
|
||||
LABEL_local9bplus: "Local 9bplus DB",
|
||||
READONLY_local9bplus: "1",
|
||||
|
||||
ENGINE_localscrape: "mariadb@dbgate-plugin-mysql",
|
||||
SERVER_localscrape: host,
|
||||
PORT_localscrape: port,
|
||||
USER_localscrape: user,
|
||||
PASSWORD_localscrape: password,
|
||||
DATABASE_localscrape: scrapeDatabase,
|
||||
LABEL_localscrape: "Local scrape DB",
|
||||
READONLY_localscrape: "0",
|
||||
};
|
||||
|
||||
const child = spawn("dbgate-serve", {
|
||||
stdio: "inherit",
|
||||
shell: true,
|
||||
env: dbgateEnv,
|
||||
});
|
||||
|
||||
child.on("exit", (code, signal) => {
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal);
|
||||
return;
|
||||
}
|
||||
|
||||
process.exit(code ?? 0);
|
||||
});
|
||||
|
||||
function readEnvFile(filePath: string): Record<string, string> {
|
||||
return Object.fromEntries(
|
||||
fs.readFileSync(filePath, "utf8")
|
||||
.split(/\r?\n/)
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line && !line.startsWith("#") && line.includes("="))
|
||||
.map((line) => {
|
||||
const separator = line.indexOf("=");
|
||||
return [line.slice(0, separator).trim(), line.slice(separator + 1).trim()];
|
||||
}),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user