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