Skip to main content

turbopack_resolve/
resolve_options_context.rs

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