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<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<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    /// Collect affecting sources for each resolve result.  Useful for tracing.
83    pub collect_affecting_sources: bool,
84
85    #[serde(default)]
86    pub placeholder_for_future_extensions: (),
87}
88
89#[turbo_tasks::value_impl]
90impl ResolveOptionsContext {
91    #[turbo_tasks::function]
92    pub async fn with_types_enabled(self: Vc<Self>) -> Result<Vc<Self>> {
93        let mut clone = self.owned().await?;
94        clone.enable_types = true;
95        clone.enable_typescript = true;
96        Ok(Self::cell(clone))
97    }
98
99    /// Returns a new [Vc<ResolveOptionsContext>] with its import map extended
100    /// to include the given import map.
101    #[turbo_tasks::function]
102    pub async fn with_extended_import_map(
103        self: Vc<Self>,
104        import_map: Vc<ImportMap>,
105    ) -> Result<Vc<Self>> {
106        let mut resolve_options_context = self.owned().await?;
107        resolve_options_context.import_map = Some(
108            resolve_options_context
109                .import_map
110                .map(|current_import_map| current_import_map.extend(import_map))
111                .unwrap_or(import_map)
112                .to_resolved()
113                .await?,
114        );
115        Ok(resolve_options_context.into())
116    }
117
118    /// Returns a new [Vc<ResolveOptionsContext>] with its fallback import map
119    /// extended to include the given import map.
120    #[turbo_tasks::function]
121    pub async fn with_extended_fallback_import_map(
122        self: Vc<Self>,
123        fallback_import_map: Vc<ImportMap>,
124    ) -> Result<Vc<Self>> {
125        let mut resolve_options_context = self.owned().await?;
126        resolve_options_context.fallback_import_map = Some(
127            resolve_options_context
128                .fallback_import_map
129                .map(|current_fallback_import_map| {
130                    current_fallback_import_map.extend(fallback_import_map)
131                })
132                .unwrap_or(fallback_import_map)
133                .to_resolved()
134                .await?,
135        );
136        Ok(resolve_options_context.into())
137    }
138}
139
140#[turbo_tasks::value_impl]
141impl ValueDefault for ResolveOptionsContext {
142    #[turbo_tasks::function]
143    fn value_default() -> Vc<Self> {
144        Self::cell(Default::default())
145    }
146}