Preconfigure local DBGate connections

This commit is contained in:
2026-08-05 22:08:42 +02:00
parent ffe70e65ac
commit 7a45686952
3 changed files with 65 additions and 1 deletions
+1
View File
@@ -106,6 +106,7 @@ There are three selectable data sources:
- Stores scraper source configuration, manufacturer-to-source mapping, scrape runs, discovered products and assets. - Stores scraper source configuration, manufacturer-to-source mapping, scrape runs, discovered products and assets.
- Supplier/manufacturer website settings such as source URL, search templates, fallback mode, browser engine, headless mode, wait time, notes and enabled/priority flags belong in Local scrape DB, not in the product catalog database. - Supplier/manufacturer website settings such as source URL, search templates, fallback mode, browser engine, headless mode, wait time, notes and enabled/priority flags belong in Local scrape DB, not in the product catalog database.
- The Settings modal should expose an `Open DBGate` action beside `Local scrape DB`; it opens the local DBGate URL from `DBGATE_URL` / `databaseGate.url` for inspecting `catalog_scrape`. - The Settings modal should expose an `Open DBGate` action beside `Local scrape DB`; it opens the local DBGate URL from `DBGATE_URL` / `databaseGate.url` for inspecting `catalog_scrape`.
- Start DBGate only through `npm run dbgate`; the script reads `.env` and preconfigures `Local 9bplus DB` plus `Local scrape DB` as DBGate connections. Do not start raw `dbgate-serve` because it will not receive the project database profiles.
- It must never be used as a fallback for catalog reads. When selected in the UI, existing catalog reads continue using Local 9bplus DB until dedicated scrape-storage endpoints are added. - It must never be used as a fallback for catalog reads. When selected in the UI, existing catalog reads continue using Local 9bplus DB until dedicated scrape-storage endpoints are added.
- The schema is versioned in `sql/local-scrape-db.sql` and can be created with `npm run db:create-scrape`. - The schema is versioned in `sql/local-scrape-db.sql` and can be created with `npm run db:create-scrape`.
- Existing legacy mapping rows from `Local 9bplus DB` can be copied into Local scrape DB with `npm run db:migrate-mapping-to-scrape`. - Existing legacy mapping rows from `Local 9bplus DB` can be copied into Local scrape DB with `npm run db:migrate-mapping-to-scrape`.
+1 -1
View File
@@ -10,7 +10,7 @@
"catalog:dry-run": "tsx src/cli.ts catalog-maker --dry-run", "catalog:dry-run": "tsx src/cli.ts catalog-maker --dry-run",
"db:create-scrape": "tsx scripts/create-local-scrape-db.ts", "db:create-scrape": "tsx scripts/create-local-scrape-db.ts",
"db:migrate-mapping-to-scrape": "tsx scripts/migrate-mapping-to-scrape-db.ts", "db:migrate-mapping-to-scrape": "tsx scripts/migrate-mapping-to-scrape-db.ts",
"dbgate": "dbgate-serve", "dbgate": "tsx scripts/start-dbgate.ts",
"test": "tsx --test test/*.test.ts", "test": "tsx --test test/*.test.ts",
"test:ui": "playwright test", "test:ui": "playwright test",
"test:e2e": "playwright test tests/ui/database.e2e.spec.ts", "test:e2e": "playwright test tests/ui/database.e2e.spec.ts",
+63
View File
@@ -0,0 +1,63 @@
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()];
}),
);
}