mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-23 23:18:10 +02:00
feat: implement dynamic database connection reloading
This commit is contained in:
1 parent
80d125f933
commit
0e0d999027
2 files changed
+62
-23
No files matched your search
+57
-23
@@ -1,43 +1,77 @@
|
|||||||
import { drizzle as nodeDrizzle } from "drizzle-orm/node-postgres";
|
import { drizzle, NodePgDatabase } from "drizzle-orm/node-postgres";
|
||||||
import { Pool } from "pg";
|
import { Pool } from "pg";
|
||||||
import * as schema from "./schema";
|
import * as schema from "./schema";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
let connectionString = process.env.DATABASE_URL;
|
let pool: Pool | null = null;
|
||||||
|
let currentDb: NodePgDatabase<typeof schema> | null = null;
|
||||||
|
|
||||||
function maskUrl(url: string | undefined) {
|
function maskUrl(url: string | undefined) {
|
||||||
if (!url) return "undefined";
|
if (!url) return "undefined";
|
||||||
return url.replace(/:([^@]+)@/, ":****@");
|
return url.replace(/:([^@]+)@/, ":****@");
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("[DB] Initial DATABASE_URL (env):", maskUrl(connectionString));
|
/**
|
||||||
|
* Initializes or returns the current database instance.
|
||||||
|
*/
|
||||||
|
export function getDb() {
|
||||||
|
if (currentDb) return currentDb;
|
||||||
|
|
||||||
// On tente de lire la config sauvegardée via l'UI
|
let connectionString = process.env.DATABASE_URL;
|
||||||
try {
|
|
||||||
const CONFIG_PATH = path.join(process.cwd(), "data", ".db-config.json");
|
console.log("[DB] Initializing connection...");
|
||||||
if (fs.existsSync(CONFIG_PATH)) {
|
console.log("[DB] Env DATABASE_URL:", maskUrl(process.env.DATABASE_URL));
|
||||||
console.log("[DB] Found config file at:", CONFIG_PATH);
|
|
||||||
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
|
try {
|
||||||
if (config.url) {
|
const CONFIG_PATH = path.join(process.cwd(), "data", ".db-config.json");
|
||||||
connectionString = config.url;
|
if (fs.existsSync(CONFIG_PATH)) {
|
||||||
console.log("[DB] Using saved database URL:", maskUrl(connectionString));
|
console.log("[DB] Found config file at:", CONFIG_PATH);
|
||||||
|
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
|
||||||
|
if (config.url) {
|
||||||
|
connectionString = config.url;
|
||||||
|
console.log("[DB] Using saved database URL:", maskUrl(connectionString));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn("[DB] Config file found but no 'url' key present.");
|
console.log("[DB] No saved config file found. Using environment variable.");
|
||||||
}
|
}
|
||||||
} else {
|
} catch (err) {
|
||||||
console.log("[DB] No saved config file found at:", CONFIG_PATH, "(Falling back to env)");
|
console.error("[DB] Error reading config file:", err);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
console.error("[DB] Error reading database config file:", err);
|
if (!connectionString) {
|
||||||
|
console.error("[DB] CRITICAL: No database connection string available!");
|
||||||
|
}
|
||||||
|
|
||||||
|
pool = new Pool({
|
||||||
|
connectionString,
|
||||||
|
});
|
||||||
|
|
||||||
|
currentDb = drizzle(pool, { schema });
|
||||||
|
return currentDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!connectionString) {
|
/**
|
||||||
console.error("[DB] CRITICAL: No database connection string available!");
|
* Resets the current database connection.
|
||||||
|
* Called when settings are updated via the UI.
|
||||||
|
*/
|
||||||
|
export function refreshDb() {
|
||||||
|
console.log("[DB] Refreshing database connection...");
|
||||||
|
if (pool) {
|
||||||
|
pool.end().catch(err => console.error("[DB] Error closing pool:", err));
|
||||||
|
pool = null;
|
||||||
|
}
|
||||||
|
currentDb = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pool = new Pool({
|
/**
|
||||||
connectionString,
|
* Proxy for the 'db' instance.
|
||||||
|
* Allows existing imports (import { db } from "@/db") to work
|
||||||
|
* while the underlying instance can be hot-swapped.
|
||||||
|
*/
|
||||||
|
export const db = new Proxy({} as NodePgDatabase<typeof schema>, {
|
||||||
|
get(target, prop, receiver) {
|
||||||
|
const d = getDb();
|
||||||
|
return Reflect.get(d, prop, receiver);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const db = nodeDrizzle(pool, { schema });
|
|
||||||
@@ -41,6 +41,11 @@ export async function saveDatabaseSettings(url: string) {
|
|||||||
|
|
||||||
await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2));
|
await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2));
|
||||||
console.log("Database configuration saved to:", CONFIG_FILE);
|
console.log("Database configuration saved to:", CONFIG_FILE);
|
||||||
|
|
||||||
|
// Refresh the shared DB instance immediately
|
||||||
|
const { refreshDb } = await import("@/db");
|
||||||
|
refreshDb();
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||||
|
|||||||
Reference in new issue
Block a user