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::{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    pub custom_conditions: Vec<RcStr>,
57    pub custom_extensions: Option<Vec<RcStr>>,
58    /// An additional import map to use when resolving modules.
59    ///
60    /// If set, this import map will be applied to `ResolveOption::import_map`.
61    /// It is always applied last, so any mapping defined within will take
62    /// precedence over any other (e.g. tsconfig.json `compilerOptions.paths`).
63    pub import_map: Option<ResolvedVc<ImportMap>>,
64    /// An import map to fall back to when a request could not be resolved.
65    ///
66    /// If set, this import map will be applied to
67    /// `ResolveOption::fallback_import_map`. It is always applied last, so
68    /// any mapping defined within will take precedence over any other.
69    pub fallback_import_map: Option<ResolvedVc<ImportMap>>,
70    /// An additional resolved map to use after modules have been resolved.
71    pub resolved_map: Option<ResolvedVc<ResolvedMap>>,
72    /// A list of rules to use a different resolve option context for certain
73    /// context paths. The first matching is used.
74    pub rules: Vec<(ContextCondition, ResolvedVc<ResolveOptionsContext>)>,
75    /// Plugins which get applied before and after resolving.
76    pub after_resolve_plugins: Vec<ResolvedVc<Box<dyn AfterResolvePlugin>>>,
77    pub before_resolve_plugins: Vec<ResolvedVc<Box<dyn BeforeResolvePlugin>>>,
78    /// Warn instead of error for resolve errors
79    pub loose_errors: bool,
80    /// Collect affecting sources for each resolve result.  Useful for tracing.
81    pub collect_affecting_sources: bool,
82
83    pub placeholder_for_future_extensions: (),
84}
85
86#[turbo_tasks::value_impl]
87impl ResolveOptionsContext {
88    #[turbo_tasks::function]
89    pub async fn with_types_enabled(self: Vc<Self>) -> Result<Vc<Self>> {
90        let mut clone = self.owned().await?;
91        clone.enable_types = true;
92        clone.enable_typescript = true;
93        Ok(Self::cell(clone))
94    }
95
96    /// Returns a new [`Vc<ResolveOptionsContext>`][Self] with its import map extended to include
97    /// the given import map.
98    #[turbo_tasks::function]
99    pub async fn with_extended_import_map(
100        self: Vc<Self>,
101        import_map: Vc<ImportMap>,
102    ) -> Result<Vc<Self>> {
103        let mut resolve_options_context = self.owned().await?;
104        resolve_options_context.import_map = Some(
105            resolve_options_context
106                .import_map
107                .map(|current_import_map| current_import_map.extend(import_map))
108                .unwrap_or(import_map)
109                .to_resolved()
110                .await?,
111        );
112        Ok(resolve_options_context.cell())
113    }
114
115    /// Returns a new [`Vc<ResolveOptionsContext>`][Self] with its fallback import map extended to
116    /// include the given import map.
117    #[turbo_tasks::function]
118    pub async fn with_extended_fallback_import_map(
119        self: Vc<Self>,
120        fallback_import_map: Vc<ImportMap>,
121    ) -> Result<Vc<Self>> {
122        let mut resolve_options_context = self.owned().await?;
123        resolve_options_context.fallback_import_map = Some(
124            resolve_options_context
125                .fallback_import_map
126                .map(|current_fallback_import_map| {
127                    current_fallback_import_map.extend(fallback_import_map)
128                })
129                .unwrap_or(fallback_import_map)
130                .to_resolved()
131                .await?,
132        );
133        Ok(resolve_options_context.cell())
134    }
135}
136
137#[turbo_tasks::value_impl]
138impl ValueDefault for ResolveOptionsContext {
139    #[turbo_tasks::function]
140    fn value_default() -> Vc<Self> {
141        Self::cell(Default::default())
142    }
143}