Files
edr-platform/apps/edr-payment-api/src/config/ensure-schema.ts
2026-06-11 15:25:24 +03:00

53 lines
1.7 KiB
TypeScript

import { Client } from "pg";
const IDENTIFIER = /^[a-z_][a-z0-9_]*$/;
function connectionEnv() {
return {
host: process.env.DB_HOST ?? "localhost",
port: parseInt(process.env.DB_PORT ?? "5432", 10),
user: process.env.DB_USER ?? "edr",
password: process.env.DB_PASSWORD ?? "",
};
}
/**
* Dev/bootstrap convenience: make sure the `edr_payment` schema exists in the shared
* database before TypeORM initializes (the migrations table itself lives in the schema, so
* migrations cannot create it). In production the schema/grants are provisioned out-of-band
* by ops; this is then a no-op.
*/
export async function ensurePaymentSchema(): Promise<void> {
const database = process.env.DB_NAME ?? "edr_database";
const schema = process.env.DB_SCHEMA ?? "edr_payment";
if (!IDENTIFIER.test(database) || !IDENTIFIER.test(schema)) {
throw new Error(
`Invalid DB_NAME/DB_SCHEMA identifier: ${database}/${schema}`,
);
}
let client = new Client({ ...connectionEnv(), database });
try {
await client.connect();
} catch (err) {
// 3D000 = database does not exist — create it from the maintenance DB, then reconnect.
if ((err as { code?: string }).code !== "3D000") throw err;
await client.end().catch(() => undefined);
const admin = new Client({ ...connectionEnv(), database: "postgres" });
await admin.connect();
try {
await admin.query(`CREATE DATABASE "${database}"`);
} finally {
await admin.end();
}
client = new Client({ ...connectionEnv(), database });
await client.connect();
}
try {
await client.query(`CREATE SCHEMA IF NOT EXISTS "${schema}"`);
} finally {
await client.end();
}
}