turbopack_resolve/
resolve_options_context.rs

1use anyhow::Result;
2use turbo_rcstr::RcStr;
3use turbo_tasks::{ResolvedVc, ValueDefault, Vc};
4use turbo_tasks_fs::FileSystemPath;
5use turbopack_core::{
6    condition::ContextCondition,
7    environment::Environment,
8    resolve::{
9        options::{ImportMap, ResolvedMap},
10        plugin::{AfterResolvePlugin, BeforeResolvePlugin},
11    },
12};
13
14#[turbo_tasks::value(shared)]
15#[derive(Default, Clone)]
16pub struct ResolveOptionsContext {
17    #[serde(default)]
18    pub emulate_environment: Option<ResolvedVc<Environment>>,
19    #[serde(default)]
20    pub enable_types: bool,
21    #[serde(default)]
22    pub enable_typescript: bool,
23    #[serde(default)]
24    pub enable_react: bool,
25    #[serde(default)]
26    pub enable_node_native_modules: bool,
27    #[serde(default)]
28    // Enable resolving of .mjs files without the .mjs extension
29    pub enable_mjs_extension: bool,
30    #[serde(default)]
31    /// Enable resolving of the node_modules folder when within the provided
32    /// directory
33    pub enable_node_modules: Option<ResolvedVc<FileSystemPath>>,
34    #[serde(default)]
35    /// A specific path to a tsconfig.json file to use for resolving modules. If `None`, one will
36    /// be looked up through the filesystem
37    pub tsconfig_path: Option<ResolvedVc<FileSystemPath>>,
38    #[serde(default)]
39    /// Mark well-known Node.js modules as external imports and load them using
40    /// native `require`. e.g. url, querystring, os
41    pub enable_node_externals: bool,
42    /// Mark well-known Edge modules as external imports and load them using
43    /// native `require`. e.g. buffer, events, assert
44    pub enable_edge_node_externals: bool,
45    #[serde(default)]
46    /// Enables the "browser" field and export condition in package.json
47    pub browser: bool,
48    #[serde(default)]
49    /// Enables the "module" field and export condition in package.json
50    pub module: bool,
51    #[serde(default)]
52    pub custom_conditions: Vec<RcStr>,
53    #[serde(default)]
54    pub custom_extensions: Option<Vec<RcStr>>,
55    #[serde(default)]
56    /// An additional import map to use when resolving modules.
57    ///
58    /// If set, this import map will be applied to `ResolveOption::import_map`.
59    /// It is always applied last, so any mapping defined within will take
60    /// precedence over any other (e.g. tsconfig.json `compilerOptions.paths`).
61    pub import_map: Option<ResolvedVc<ImportMap>>,
62    #[serde(default)]
63    /// An import map to fall back to when a request could not be resolved.
64    ///
65    /// If set, this import map will be applied to
66    /// `ResolveOption::fallback_import_map`. It is always applied last, so
67    /// any mapping defined within will take precedence over any other.
68    pub fallback_import_map: Option<ResolvedVc<ImportMap>>,
69    #[serde(default)]
70    /// An additional resolved map to use after modules have been resolved.
71    pub resolved_map: Option<ResolvedVc<ResolvedMap>>,
72    #[serde(default)]
73    /// A list of rules to use a different resolve option context for certain
74    /// context paths. The first matching is used.
75    pub rules: Vec<(ContextCondition, ResolvedVc<ResolveOptionsContext>)>,
76    #[serde(default)]
77    /// Plugins which get applied before and after resolving.
78    pub after_resolve_plugins: Vec<ResolvedVc<Box<dyn AfterResolvePlugin>>>,
79    pub before_resolve_plugins: Vec<ResolvedVc<Box<dyn BeforeResolvePlugin>>>,
80    /// Warn instead of error for resolve errors
81    pub loose_errors: bool,
82
83    #[serde(default)]
84    pub placeholder_for_future_extensions: (),
85}
86
87#[turbo_tasks::value_impl]
88impl ResolveOptionsContext {
89    #[turbo_tasks::function]
90    pub async fn with_types_enabled(self: Vc<Self>) -> Result<Vc<Self>> {
91        let mut clone = self.owned().await?;
92        clone.enable_types = true;
93        clone.enable_typescript = true;
94        Ok(Self::cell(clone))
95    }
96
97    /// Returns a new [Vc<ResolveOptionsContext>] with its import map extended
98    /// to include the given import map.
99    #[turbo_tasks::function]
100    pub async fn with_extended_import_map(
101        self: Vc<Self>,
102        import_map: Vc<ImportMap>,
103    ) -> Result<Vc<Self>> {
104        let mut resolve_options_context = self.owned().await?;
105        resolve_options_context.import_map = Some(
106            resolve_options_context
107                .import_map
108                .map(|current_import_map| current_import_map.extend(import_map))
109                .unwrap_or(import_map)
110                .to_resolved()
111                .await?,
112        );
113        Ok(resolve_options_context.into())
114    }
115
116    /// Returns a new [Vc<ResolveOptionsContext>] with its fallback import map
117    /// extended to include the given import map.
118    #[turbo_tasks::function]
119    pub async fn with_extended_fallback_import_map(
120        self: Vc<Self>,
121        fallback_import_map: Vc<ImportMap>,
122    ) -> Result<Vc<Self>> {
123        let mut resolve_options_context = self.owned().await?;
124        resolve_options_context.fallback_import_map = Some(
125            resolve_options_context
126                .fallback_import_map
127                .map(|current_fallback_import_map| {
128                    current_fallback_import_map.extend(fallback_import_map)
129                })
130                .unwrap_or(fallback_import_map)
131                .to_resolved()
132                .await?,
133        );
134        Ok(resolve_options_context.into())
135    }
136}
137
138#[turbo_tasks::value_impl]
139impl ValueDefault for ResolveOptionsContext {
140    #[turbo_tasks::function]
141    fn value_default() -> Vc<Self> {
142        Self::cell(Default::default())
143    }
144}