diff --git a/server/src/database/database.module.spec.ts b/server/src/database/database.module.spec.ts index 237bc13..ac2747a 100644 --- a/server/src/database/database.module.spec.ts +++ b/server/src/database/database.module.spec.ts @@ -1,7 +1,7 @@ import { Test } from '@nestjs/testing'; import { ConfigModule as NestConfigModule } from '@nestjs/config'; import configuration from '../config/configuration'; -import { DatabaseModule } from './database.module'; +import { DatabaseModule, assertDatabaseUrlAllowed } from './database.module'; import { PrismaClient } from '../../generated/prisma/client'; /** @@ -55,4 +55,39 @@ describe('DatabaseModule', () => { expect(typeof client.$disconnect).toBe('function'); await moduleRef.close(); }); + + describe('assertDatabaseUrlAllowed', () => { + it('throws when URL is empty or undefined', () => { + expect(() => assertDatabaseUrlAllowed('', 'development')).toThrow( + /DATABASE_URL is not configured/, + ); + expect(() => assertDatabaseUrlAllowed(undefined, 'development')).toThrow( + /DATABASE_URL is not configured/, + ); + }); + + it('throws when URL is file: in production', () => { + expect(() => + assertDatabaseUrlAllowed('file:./dev.db', 'production'), + ).toThrow(/not allowed when NODE_ENV=production/); + }); + + it('does not throw when URL is file: in development or test', () => { + expect(() => + assertDatabaseUrlAllowed('file:./dev.db', 'development'), + ).not.toThrow(); + expect(() => + assertDatabaseUrlAllowed('file:./dev.db', 'test'), + ).not.toThrow(); + }); + + it('does not throw for non-file database URL in production', () => { + expect(() => + assertDatabaseUrlAllowed( + 'postgresql://user:pass@localhost:5432/db', + 'production', + ), + ).not.toThrow(); + }); + }); }); diff --git a/server/src/database/database.module.ts b/server/src/database/database.module.ts index 31d2316..5f4c609 100644 --- a/server/src/database/database.module.ts +++ b/server/src/database/database.module.ts @@ -8,7 +8,15 @@ import { PrismaPg } from '@prisma/adapter-pg'; * production, so a misconfigured deploy fails fast at startup instead of * silently running against a throwaway local file. */ -export function assertDatabaseUrlAllowed(url: string, nodeEnv: string): void { +export function assertDatabaseUrlAllowed( + url: string | undefined, + nodeEnv: string, +): void { + if (!url) { + throw new Error( + 'DATABASE_URL is not configured or resolved to an empty value.', + ); + } if (nodeEnv === 'production' && url.startsWith('file:')) { throw new Error( `DATABASE_URL resolves to a local file ("${url}"), which is not allowed when NODE_ENV=production. Set DATABASE_URL to a real database connection string.`,