turbopack_env/
dotenv.rs

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