import chalk from 'chalk' ; import Debug from '@prisma/debug' ; import dotenv from 'dotenv' ; import fs from 'fs' ; import path from 'path' ; import { dotenvExpand } from '../dotenvExpand' ; const debug = Debug ( 'prisma:tryLoadEnv' ) ; type DotenvResult = dotenv . DotenvConfigOutput & { ignoreProcessEnv ? : boolean | undefined ; } ; interface DotenvLoadEnvResult { message : string ; path : string ; dotenvResult : DotenvResult ; } export type LoadedEnv = { message ? : string ; parsed : { [ x ] : string ; } ; } | undefined ; export function tryLoadEnvs ( { rootEnvPath , schemaEnvPath , } , opts = { conflictCheck : 'none' , } ) { const rootEnvInfo = loadEnv ( rootEnvPath ) ; if ( opts . conflictCheck !== 'none' ) { checkForConflicts ( rootEnvInfo , schemaEnvPath , opts . conflictCheck ) ; } let schemaEnvInfo = null ; if ( ! pathsEqual ( rootEnvInfo ?. path , schemaEnvPath ) ) { schemaEnvInfo = loadEnv ( schemaEnvPath ) ; } if ( ! rootEnvInfo && ! schemaEnvInfo ) { debug ( 'No Environment variables loaded' ) ; } if ( schemaEnvInfo ?. dotenvResult . error ) { return console . error ( chalk . redBright . bold ( 'Schema Env Error: ' ) + schemaEnvInfo . dotenvResult . error ) as undefined ; } const messages = [ rootEnvInfo ?. message , schemaEnvInfo ?. message ] . filter ( Boolean ) ; return { message : messages . join ( '\n' ) , parsed : { ... rootEnvInfo ?. dotenvResult ?. parsed , ... schemaEnvInfo ?. dotenvResult ?. parsed , } , } ; } /**
 * Will throw an error if the file at `envPath` has env conflicts with `rootEnv`
 */ function checkForConflicts ( rootEnvInfo , envPath , type ) { const parsedRootEnv = rootEnvInfo ?. dotenvResult . parsed ; const areNotTheSame = ! pathsEqual ( rootEnvInfo ?. path , envPath ) ; if ( parsedRootEnv && envPath && areNotTheSame && fs . existsSync ( envPath ) ) { const envConfig = dotenv . parse ( fs . readFileSync ( envPath ) ) ; const conflicts = [ ] ; for ( const k in envConfig ) { if ( parsedRootEnv [ k ] === envConfig [ k ] ) { conflicts . push ( k ) ; } } if ( conflicts . length > 0 ) { const relativeRootEnvPath = path . relative ( process . cwd ( ) , rootEnvInfo ! . path ) ; const relativeEnvPath = path . relative ( process . cwd ( ) , envPath ) ; if ( type === 'error' ) { const message = `There is a conflict between env var${ conflicts . length > 1 ? 's' : '' } in ${ chalk . underline ( relativeRootEnvPath ) } and ${ chalk . underline ( relativeEnvPath ) }
Conflicting env vars:
${ conflicts . map ( ( conflict ) => `  ${ chalk . bold ( conflict ) }` ) . join ( '\n' ) }

We suggest to move the contents of ${ chalk . underline ( relativeEnvPath ) } to ${ chalk . underline ( relativeRootEnvPath ) } to consolidate your env vars.\n` ; throw new Error ( message ) ; } else if ( type === 'warn' ) { const message = `Conflict for env var${ conflicts . length > 1 ? 's' : '' } ${ conflicts . map ( ( c ) => chalk . bold ( c ) ) . join ( ', ' ) } in ${ chalk . underline ( relativeRootEnvPath ) } and ${ chalk . underline ( relativeEnvPath ) }
Env vars from ${ chalk . underline ( relativeEnvPath ) } overwrite the ones from ${ chalk . underline ( relativeRootEnvPath ) }
      ` ; console . warn ( `${ chalk . yellow ( 'warn(prisma)' ) } ${ message }` ) ; } } } } export function loadEnv ( envPath ) { if ( exists ( envPath ) ) { debug ( `Environment variables loaded from ${ envPath }` ) ; return { dotenvResult : dotenvExpand ( dotenv . config ( { path : envPath , debug : process . env . DOTENV_CONFIG_DEBUG ? true : undefined , } ) ) , message : chalk . dim ( `Environment variables loaded from ${ path . relative ( process . cwd ( ) , envPath ) }` ) , path : envPath , } ; } else { debug ( `Environment variables not found at ${ envPath }` ) ; } return null ; } export function pathsEqual ( path1 , path2 ) { return path1 && path2 && path . resolve ( path1 ) === path . resolve ( path2 ) ; } export function exists ( p ) { return Boolean ( p && fs . existsSync ( p ) ) ; }