turbopack_env/
try_env.rs

1use anyhow::Result;
2use turbo_tasks::{ResolvedVc, Vc};
3use turbo_tasks_env::{DotenvProcessEnv, EnvMap, ProcessEnv};
4use turbo_tasks_fs::FileSystemPath;
5use turbopack_core::issue::{IssueExt, StyledString};
6
7use crate::ProcessEnvIssue;
8
9#[turbo_tasks::value]
10pub struct TryDotenvProcessEnv {
11    dotenv: ResolvedVc<DotenvProcessEnv>,
12    prior: ResolvedVc<Box<dyn ProcessEnv>>,
13    path: ResolvedVc<FileSystemPath>,
14}
15
16#[turbo_tasks::value_impl]
17impl TryDotenvProcessEnv {
18    #[turbo_tasks::function]
19    pub async fn new(
20        prior: ResolvedVc<Box<dyn ProcessEnv>>,
21        path: ResolvedVc<FileSystemPath>,
22    ) -> Result<Vc<Self>> {
23        let dotenv = DotenvProcessEnv::new(Some(*prior), *path)
24            .to_resolved()
25            .await?;
26        Ok(TryDotenvProcessEnv {
27            dotenv,
28            prior,
29            path,
30        }
31        .cell())
32    }
33}
34
35#[turbo_tasks::value_impl]
36impl ProcessEnv for TryDotenvProcessEnv {
37    #[turbo_tasks::function]
38    async fn read_all(&self) -> Result<Vc<EnvMap>> {
39        let dotenv = self.dotenv;
40        let prior = dotenv.read_prior();
41
42        // Ensure prior succeeds. If it doesn't, then we don't want to attempt to read
43        // the dotenv file (and potentially emit an Issue), just trust that the prior
44        // will have emitted its own.
45        prior.await?;
46
47        let vars = dotenv.read_all_with_prior(prior);
48        match vars.await {
49            Ok(_) => Ok(vars),
50            Err(e) => {
51                // If parsing the dotenv file fails (but getting the prior value didn't), then
52                // we want to emit an Issue and fall back to the prior's read.
53                ProcessEnvIssue {
54                    path: self.path,
55                    // read_all_with_prior will wrap a current error with a context containing the
56                    // failing file, which we don't really care about (we report the filepath as the
57                    // Issue context, not the description). So extract the real error.
58                    description: StyledString::Text(e.root_cause().to_string().into())
59                        .resolved_cell(),
60                }
61                .resolved_cell()
62                .emit();
63                Ok(prior)
64            }
65        }
66    }
67}