| 43 | } |
| 44 | |
| 45 | export function processEnv( |
| 46 | loadedEnvFiles: LoadedEnvFiles, |
| 47 | dir?: string, |
| 48 | log: Log = console, |
| 49 | forceReload = false, |
| 50 | onReload?: (envFilePath: string) => void |
| 51 | ) { |
| 52 | if (!initialEnv) { |
| 53 | initialEnv = Object.assign({}, process.env) |
| 54 | } |
| 55 | // only reload env when forceReload is specified |
| 56 | if ( |
| 57 | !forceReload && |
| 58 | (process.env.__NEXT_PROCESSED_ENV || loadedEnvFiles.length === 0) |
| 59 | ) { |
| 60 | return [process.env as Env] |
| 61 | } |
| 62 | // flag that we processed the environment values already. |
| 63 | process.env.__NEXT_PROCESSED_ENV = 'true' |
| 64 | |
| 65 | const origEnv = Object.assign({}, initialEnv) |
| 66 | const parsed: dotenv.DotenvParseOutput = {} |
| 67 | |
| 68 | for (const envFile of loadedEnvFiles) { |
| 69 | try { |
| 70 | let result: dotenv.DotenvConfigOutput = {} |
| 71 | result.parsed = dotenv.parse(envFile.contents) |
| 72 | |
| 73 | result = dotenvExpand(result) |
| 74 | |
| 75 | if ( |
| 76 | result.parsed && |
| 77 | !previousLoadedEnvFiles.some( |
| 78 | (item) => |
| 79 | item.contents === envFile.contents && item.path === envFile.path |
| 80 | ) |
| 81 | ) { |
| 82 | onReload?.(envFile.path) |
| 83 | } |
| 84 | |
| 85 | for (const key of Object.keys(result.parsed || {})) { |
| 86 | if ( |
| 87 | typeof parsed[key] === 'undefined' && |
| 88 | typeof origEnv[key] === 'undefined' |
| 89 | ) { |
| 90 | // We're being imprecise in the type system - assume parsed[key] can be undefined |
| 91 | // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain |
| 92 | parsed[key] = result.parsed?.[key]! |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | // Add the parsed env to the loadedEnvFiles |
| 97 | envFile.env = result.parsed || {} |
| 98 | } catch (err) { |
| 99 | log.error( |
| 100 | `Failed to load env from ${path.join(dir || '', envFile.path)}`, |
| 101 | err |
| 102 | ) |