Skip to main content

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