This repository has been archived on 2026-06-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
master-ai/vibn-frontend/scripts/sync-db-url-from-coolify.mjs

146 lines
4.2 KiB
JavaScript

#!/usr/bin/env node
/**
* Pull postgres external URL from Coolify API and write DATABASE_URL + POSTGRES_URL in .env.local.
*
* Loads (in order): ../.coolify.env, .env, .env.local (Coolify wins for COOLIFY_* from parent file).
*
* Identify DB by (first match):
* COOLIFY_DATABASE_UUID — exact
* COOLIFY_DATABASE_NAME — default: vibn-postgres
* argv[2] — uuid or name substring
*
* Requires: COOLIFY_URL, COOLIFY_API_TOKEN
*/
import { config } from "dotenv";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
const repoRoot = path.join(root, "..");
config({ path: path.join(repoRoot, ".coolify.env") });
config({ path: path.join(root, ".env") });
config({ path: path.join(root, ".env.local"), override: true });
const COOLIFY_URL = (process.env.COOLIFY_URL ?? "").replace(/\/$/, "");
const token = process.env.COOLIFY_API_TOKEN ?? "";
const arg = process.argv[2];
function fail(msg) {
console.error(msg);
process.exit(1);
}
if (!COOLIFY_URL || !token) {
fail("Missing COOLIFY_URL or COOLIFY_API_TOKEN (e.g. set in master-ai/.coolify.env).");
}
function normalizeDatabaseUrl(url) {
if (!url || typeof url !== "string") return "";
return url.replace(/^postgres:\/\//i, "postgresql://");
}
async function coolifyFetch(path) {
const res = await fetch(`${COOLIFY_URL}/api/v1${path}`, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
});
if (!res.ok) {
const text = await res.text();
fail(`Coolify API ${res.status} ${path}: ${text.slice(0, 500)}`);
}
return res.json();
}
function pickDatabase(list) {
const uuid = process.env.COOLIFY_DATABASE_UUID?.trim();
const nameDefault = process.env.COOLIFY_DATABASE_NAME || "vibn-postgres";
if (uuid) {
const d = list.find((x) => x.uuid === uuid);
if (d) return d;
fail(`No database with COOLIFY_DATABASE_UUID=${uuid}.`);
}
if (arg?.trim()) {
const a = arg.trim().toLowerCase();
const byUuid = list.find((x) => x.uuid === arg.trim());
if (byUuid) return byUuid;
const byName = list.find(
(x) =>
String(x.name ?? "")
.toLowerCase()
.includes(a) ||
String(x.uuid ?? "")
.toLowerCase()
.includes(a)
);
if (byName) return byName;
fail(`No database matching "${arg}".`);
}
const byName = list.find(
(x) => String(x.name ?? "").toLowerCase() === nameDefault.toLowerCase()
);
if (byName) return byName;
fail(
`No database named "${nameDefault}". Set COOLIFY_DATABASE_UUID or pass uuid/name as argument.`
);
}
async function main() {
const list = await coolifyFetch("/databases");
if (!Array.isArray(list) || list.length === 0) {
fail("Coolify returned no databases.");
}
const picked = pickDatabase(list);
const detail = await coolifyFetch(`/databases/${picked.uuid}`);
const raw = detail.external_db_url;
const databaseUrl = normalizeDatabaseUrl(raw);
if (!databaseUrl) {
fail(
"No external_db_url from Coolify. Enable public exposure and set a host port on the Postgres service, then restart."
);
}
const envLocalPath = path.join(root, ".env.local");
if (!fs.existsSync(envLocalPath)) {
fail(`Missing ${envLocalPath}; create it first (copy from .env.example).`);
}
let body = fs.readFileSync(envLocalPath, "utf8");
const lines = body.split(/\r?\n/);
const setLine = (key, value) => {
const next = `${key}=${value}`;
let seen = false;
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith(`${key}=`)) {
lines[i] = next;
seen = true;
break;
}
}
if (!seen) lines.push(next);
};
setLine("DATABASE_URL", databaseUrl);
setLine("POSTGRES_URL", databaseUrl);
fs.writeFileSync(envLocalPath, lines.join("\n") + (body.endsWith("\n") ? "\n" : ""), "utf8");
console.log(
`Updated DATABASE_URL and POSTGRES_URL in .env.local from Coolify (${picked.name}, ${picked.uuid}).`
);
console.log(`Public port from API: ${detail.public_port ?? "(n/a)"}; is_public: ${detail.is_public ?? "(n/a)"}`);
}
main().catch((e) => {
console.error(e);
process.exit(1);
});