11import { log } from '@/lib/logger' ;
2- import { parse } from './transform' ;
32import { readFileSync } from 'node:fs' ;
3+ import { parse } from './transform' ;
44
55export type EnvType = 'string' | 'string[]' | 'number' | 'boolean' | 'byte' | 'ms' | 'json' ;
6- export function env ( property : string , env : string | string [ ] , type : EnvType , isDb : boolean = false ) {
6+ export function env ( property : string , env : string , type : EnvType , isDb : boolean = false ) {
77 return {
88 variable : env ,
99 property,
@@ -16,7 +16,14 @@ export const ENVS = [
1616 env ( 'core.port' , 'CORE_PORT' , 'number' ) ,
1717 env ( 'core.hostname' , 'CORE_HOSTNAME' , 'string' ) ,
1818 env ( 'core.secret' , 'CORE_SECRET' , 'string' ) ,
19- env ( 'core.databaseUrl' , [ 'DATABASE_URL' , 'CORE_DATABASE_URL' ] , 'string' ) ,
19+
20+ env ( 'core.databaseUrl' , 'DATABASE_URL' , 'string' ) ,
21+ // or
22+ env ( 'core.database.username' , 'DATABASE_USERNAME' , 'string' , true ) ,
23+ env ( 'core.database.password' , 'DATABASE_PASSWORD' , 'string' , true ) ,
24+ env ( 'core.database.host' , 'DATABASE_HOST' , 'string' , true ) ,
25+ env ( 'core.database.port' , 'DATABASE_PORT' , 'number' , true ) ,
26+ env ( 'core.database.name' , 'DATABASE_NAME' , 'string' , true ) ,
2027
2128 env ( 'datasource.type' , 'DATASOURCE_TYPE' , 'string' ) ,
2229 env ( 'datasource.s3.accessKeyId' , 'DATASOURCE_S3_ACCESS_KEY_ID' , 'string' ) ,
@@ -161,11 +168,62 @@ export const PROP_TO_ENV: Record<string, string | string[]> = Object.fromEntries
161168 ENVS . map ( ( env ) => [ env . property , env . variable ] ) ,
162169) ;
163170
171+ export const REQUIRED_DB_VARS = [
172+ 'DATABASE_USERNAME' ,
173+ 'DATABASE_PASSWORD' ,
174+ 'DATABASE_HOST' ,
175+ 'DATABASE_PORT' ,
176+ 'DATABASE_NAME' ,
177+ ] ;
178+
164179type EnvResult = {
165180 env : Record < string , any > ;
166181 dbEnv : Record < string , any > ;
167182} ;
168183
184+ export function checkDbVars ( ) : boolean {
185+ if ( process . env . DATABASE_URL ) return true ;
186+
187+ for ( let i = 0 ; i !== REQUIRED_DB_VARS . length ; ++ i ) {
188+ if ( process . env [ REQUIRED_DB_VARS [ i ] ] === undefined ) {
189+ return false ;
190+ }
191+ }
192+
193+ return true ;
194+ }
195+
196+ export function readDbVars ( ) : Record < string , string > {
197+ const logger = log ( 'config' ) . c ( 'readDbVars' ) ;
198+
199+ if ( process . env . DATABASE_URL ) return { DATABASE_URL : process . env . DATABASE_URL } ;
200+
201+ const dbVars : Record < string , string > = { } ;
202+ for ( let i = 0 ; i !== REQUIRED_DB_VARS . length ; ++ i ) {
203+ const value = process . env [ REQUIRED_DB_VARS [ i ] ] ;
204+ const valueFileName = process . env [ `${ REQUIRED_DB_VARS [ i ] } _FILE` ] ;
205+ if ( valueFileName ) {
206+ try {
207+ dbVars [ REQUIRED_DB_VARS [ i ] ] = readFileSync ( valueFileName , 'utf-8' ) . trim ( ) ;
208+ } catch {
209+ logger . error ( `Failed to read database env value from file for ${ REQUIRED_DB_VARS [ i ] } . Exiting...` ) ;
210+ process . exit ( 1 ) ;
211+ }
212+ } else if ( value ) {
213+ dbVars [ REQUIRED_DB_VARS [ i ] ] = value ;
214+ }
215+ }
216+
217+ if ( ! Object . keys ( dbVars ) . length || Object . keys ( dbVars ) . length !== REQUIRED_DB_VARS . length ) {
218+ logger . error (
219+ `No database environment variables found (DATABASE_URL or all of [${ REQUIRED_DB_VARS . join ( ', ' ) } ]), exiting...` ,
220+ ) ;
221+ process . exit ( 1 ) ;
222+ }
223+
224+ return dbVars ;
225+ }
226+
169227export function readEnv ( ) : EnvResult {
170228 const logger = log ( 'config' ) . c ( 'readEnv' ) ;
171229 const envResult : EnvResult = {
@@ -175,9 +233,6 @@ export function readEnv(): EnvResult {
175233
176234 for ( let i = 0 ; i !== ENVS . length ; ++ i ) {
177235 const env = ENVS [ i ] ;
178- if ( Array . isArray ( env . variable ) ) {
179- env . variable = env . variable . find ( ( v ) => process . env [ v ] !== undefined ) || 'DATABASE_URL' ;
180- }
181236
182237 let value = process . env [ env . variable ] ;
183238 const valueFileName = process . env [ `${ env . variable } _FILE` ] ;
0 commit comments