c3c15585ff
## Summary Cosmetic-only follow-up to #70. Collapses one over-cautious multi-line `throw new Error(...)` into a single line that fits within the project's 100-char `printWidth`. The reformat was produced by lint-staged **during** the amend that landed #70, but applied to the working tree only — the modification never made it back into the staged content of the amend. The merged commit therefore carries the un-prettified version. Spotted locally with `pnpm exec prettier --check apps/portal-bff/src/config/check-database-url.ts` failing. Left unchecked, the next PR's `check` job would break at `format:check` for unrelated reasons. ## Test plan - [ ] CI green on this PR (`format:check` clean). - [ ] No behavioural change — only whitespace. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #71
53 lines
2.1 KiB
TypeScript
53 lines
2.1 KiB
TypeScript
/**
|
|
* Sanity-check `DATABASE_URL` early in bootstrap so a malformed value
|
|
* fails fast with a clear, actionable message instead of an opaque
|
|
* Prisma error deep into the request lifecycle.
|
|
*
|
|
* The most common malformation is a literal special character in
|
|
* POSTGRES_PASSWORD that the contributor forgot to URL-encode (`@`,
|
|
* `#`, `:`, `/`, `?`, `%`, `&`, `=`, `+`, `;` all require it). This
|
|
* is the same family of bug that bit pgweb in #63 — pgweb's compose
|
|
* was switched to discrete CLI flags to bypass URL parsing entirely,
|
|
* but Prisma requires a URL string, so we have no equivalent escape
|
|
* hatch here. Documentation + early validation are the v1 fix.
|
|
*/
|
|
|
|
const URL_ENCODE_HINT =
|
|
'If POSTGRES_PASSWORD contains special characters (@ # : / ? % & = + ;), ' +
|
|
'they must be URL-encoded in DATABASE_URL — e.g., "@" → "%40", "#" → "%23". ' +
|
|
'See apps/portal-bff/.env.example for the canonical form.';
|
|
|
|
export function assertDatabaseUrl(): void {
|
|
const raw = process.env['DATABASE_URL'];
|
|
if (!raw) {
|
|
throw new Error(
|
|
'DATABASE_URL is not set. Copy apps/portal-bff/.env.example to ' +
|
|
'apps/portal-bff/.env and adjust.',
|
|
);
|
|
}
|
|
|
|
let parsed: URL;
|
|
try {
|
|
parsed = new URL(raw);
|
|
} catch {
|
|
throw new Error(`DATABASE_URL is not a valid URL. ${URL_ENCODE_HINT}`);
|
|
}
|
|
|
|
if (parsed.protocol !== 'postgresql:' && parsed.protocol !== 'postgres:') {
|
|
throw new Error(`DATABASE_URL must use the "postgresql://" scheme; got "${parsed.protocol}".`);
|
|
}
|
|
|
|
// Heuristic — multiple "@" before the path almost always means the
|
|
// password contains a literal "@" that should have been encoded.
|
|
// Splitting on the parsed pathname isolates the userinfo+host
|
|
// segment without depending on scheme-specific quirks.
|
|
const beforePath = raw.split(parsed.pathname || '/')[0] ?? raw;
|
|
const atCount = (beforePath.match(/@/g) ?? []).length;
|
|
if (atCount > 1) {
|
|
throw new Error(
|
|
`DATABASE_URL has ${atCount} "@" before the database path — your password almost ` +
|
|
`certainly needs URL-encoding. ${URL_ENCODE_HINT}`,
|
|
);
|
|
}
|
|
}
|