turbopack_env/
dotenv.rs

1use anyhow::Result;
2use turbo_rcstr::rcstr;
3use turbo_tasks::{Vc, fxindexmap};
4use turbo_tasks_env::{CommandLineProcessEnv, CustomProcessEnv, ProcessEnv};
5use turbo_tasks_fs::FileSystemPath;
6
7use crate::TryDotenvProcessEnv;
8
9/// Loads a series of dotenv files according to the precedence rules set by
10/// https://nextjs.org/docs/app/building-your-application/configuring/environment-variables#environment-variable-load-order
11#[turbo_tasks::function]
12pub async fn load_env(project_path: FileSystemPath) -> Result<Vc<Box<dyn ProcessEnv>>> {
13    let env: Vc<Box<dyn ProcessEnv>> = Vc::upcast(CommandLineProcessEnv::new());
14
15    let node_env = env.read(rcstr!("NODE_ENV")).owned().await?;
16    let node_env = node_env.unwrap_or(rcstr!("development"));
17
18    let env = Vc::upcast(CustomProcessEnv::new(
19        env,
20        Vc::cell(fxindexmap! {
21            rcstr!("NODE_ENV") => node_env.clone(),
22        }),
23    ));
24
25    let mut files = [
26        Some(format!(".env.{node_env}.local").into()),
27        if node_env == "test" {
28            None
29        } else {
30            Some(rcstr!(".env.local"))
31        },
32        Some(format!(".env.{node_env}").into()),
33        Some(rcstr!(".env")),
34    ]
35    .into_iter()
36    .flatten();
37
38    let env = files.try_fold(env, |prior, f| {
39        let path = project_path.join(&f)?;
40        anyhow::Ok(Vc::upcast(TryDotenvProcessEnv::new(prior, path)))
41    })?;
42
43    Ok(env)
44}