…lines 1–7 unchanged (7 lines)
8use turbopack_core::{
9 environment::Environment, reference_type::ReferenceType, source::Source,
10 source_transform::SourceTransforms,
11};
12use turbopack_css::CssModuleAssetType;
13use turbopack_ecmascript::{
14 EcmascriptInputTransforms, EcmascriptOptions, bytes_source_transform::BytesSourceTransform,
15};
16use turbopack_wasm::source::WebAssemblySourceType;
17
18use crate::module_options::{CustomModuleType, RuleCondition, match_mode::MatchMode};
19
20#[derive(Debug, Clone, TraceRawVcs, PartialEq, Eq, NonLocalValue, Encode, Decode)]
21pub struct ModuleRule {
…lines 22–147 unchanged (126 lines)
148 tag: Option<RcStr>,
149 },
150 StaticUrlCss {
151 /// The tag that is passed to ChunkingContext::asset_url
152 tag: Option<RcStr>,
153 },
154 WebAssembly {
155 source_ty: WebAssemblySourceType,
156 },
157 Custom(ResolvedVc<Box<dyn CustomModuleType>>),
158}
159
160impl Display for ModuleType {
…lines 161–167 unchanged (7 lines)
168 ModuleType::Raw => write!(f, "Raw"),
169 ModuleType::NodeAddon => write!(f, "NodeAddon"),
170 ModuleType::CssModule => write!(f, "CssModule"),
171 ModuleType::Css { .. } => write!(f, "Css"),
172 ModuleType::StaticUrlJs { .. } => write!(f, "StaticUrlJs"),
173 ModuleType::StaticUrlCss { .. } => write!(f, "StaticUrlCss"),
174 ModuleType::WebAssembly { .. } => write!(f, "WebAssembly"),
175 ModuleType::Custom(_) => write!(f, "Custom"),
176 }
177 }
178}
179
180/// User-facing module type names used in configuration.
181///
182/// This enum represents the semantic module types that users can specify in their config
183/// (e.g., next.config.js turbopack rules). Some of these map directly to internal `ModuleType`
184/// variants, while others (like `Bytes`) are implemented via source transforms.
185#[derive(Debug, Clone, PartialEq, Eq)]
186pub enum ConfiguredModuleType {
187 Asset,
188 Ecmascript,
189 Typescript,
190 Css,
191 CssModule,
192 Json,
193 Wasm,
194 Raw,
195 Node,
196 /// Converts any file to an ES module exporting its contents as a Uint8Array.
197 /// Implemented as a source transform, not a ModuleType.
198 Bytes,
199}
200
201impl ConfiguredModuleType {
202 /// Parse a module type string from user configuration.
203 pub fn parse(type_str: &str) -> Result<Self> {
204 Ok(match type_str {
205 "asset" => ConfiguredModuleType::Asset,
206 "ecmascript" => ConfiguredModuleType::Ecmascript,
207 "typescript" => ConfiguredModuleType::Typescript,
208 "css" => ConfiguredModuleType::Css,
209 "css-module" => ConfiguredModuleType::CssModule,
210 "json" => ConfiguredModuleType::Json,
211 "wasm" => ConfiguredModuleType::Wasm,
212 "raw" => ConfiguredModuleType::Raw,
213 "node" => ConfiguredModuleType::Node,
214 "bytes" => ConfiguredModuleType::Bytes,
215 _ => bail!(
216 "Unknown module type: {type_str:?}. Valid types are: asset, ecmascript, \
217 typescript, css, css-module, json, wasm, raw, node, bytes"
218 ),
219 })
220 }
221
222 /// Convert this configured module type into module rule effects.
223 ///
224 /// Some module types (like `Bytes`) are implemented as source transforms rather than
225 /// `ModuleType` variants, allowing them to compose with the standard Ecmascript pipeline.
226 pub async fn into_effect(
227 self,
228 preprocess: ResolvedVc<EcmascriptInputTransforms>,
229 main: ResolvedVc<EcmascriptInputTransforms>,
230 postprocess: ResolvedVc<EcmascriptInputTransforms>,
231 options: ResolvedVc<EcmascriptOptions>,
232 environment: Option<ResolvedVc<Environment>>,
233 ) -> Result<ModuleRuleEffect> {
234 Ok(match self {
235 ConfiguredModuleType::Bytes => {
236 // Use source transform instead of ModuleType - the transform produces .mjs
237 // which gets picked up by the standard Ecmascript rules
238 ModuleRuleEffect::SourceTransforms(ResolvedVc::cell(vec![ResolvedVc::upcast(
239 BytesSourceTransform::new().to_resolved().await?,
240 )]))
241 }
242 ConfiguredModuleType::Asset => {
243 ModuleRuleEffect::ModuleType(ModuleType::StaticUrlJs { tag: None })
244 }
245 ConfiguredModuleType::Ecmascript => {
246 ModuleRuleEffect::ModuleType(ModuleType::Ecmascript {
247 preprocess,
248 main,
249 postprocess,
250 options,
251 })
252 }
253 ConfiguredModuleType::Typescript => {
254 ModuleRuleEffect::ModuleType(ModuleType::Typescript {
255 preprocess,
256 main,
257 postprocess,
258 tsx: false,
259 analyze_types: false,
260 options,
261 })
262 }
263 ConfiguredModuleType::Css => ModuleRuleEffect::ModuleType(ModuleType::Css {
264 ty: CssModuleAssetType::Default,
265 environment,
266 }),
267 ConfiguredModuleType::CssModule => ModuleRuleEffect::ModuleType(ModuleType::CssModule),
268 ConfiguredModuleType::Json => ModuleRuleEffect::ModuleType(ModuleType::Json),
269 ConfiguredModuleType::Wasm => ModuleRuleEffect::ModuleType(ModuleType::WebAssembly {
270 source_ty: WebAssemblySourceType::Binary,
271 }),
272 ConfiguredModuleType::Raw => ModuleRuleEffect::ModuleType(ModuleType::Raw),
273 ConfiguredModuleType::Node => ModuleRuleEffect::ModuleType(ModuleType::NodeAddon),
274 })
275 }
276}
277