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