turbopack_core/resolve/
plugin.rs1use anyhow::Result;
2use turbo_rcstr::RcStr;
3use turbo_tasks::{ReadRef, ResolvedVc, Vc};
4use turbo_tasks_fs::{FileSystemPath, glob::Glob};
5
6use crate::{
7 reference_type::ReferenceType,
8 resolve::{ResolveResultOption, parse::Request},
9};
10
11#[turbo_tasks::value(serialization = "skip")]
17pub enum AfterResolvePluginCondition {
18 Glob {
21 root: Option<FileSystemPath>,
22 glob: ReadRef<Glob>,
23 },
24 Always,
26 Never,
27}
28
29#[turbo_tasks::value_impl]
30impl AfterResolvePluginCondition {
31 #[turbo_tasks::function]
32 pub async fn new_with_glob(
33 root: Option<FileSystemPath>,
34 glob: ResolvedVc<Glob>,
35 ) -> Result<Vc<Self>> {
36 let glob = glob.await?;
37 Ok(AfterResolvePluginCondition::Glob { root, glob }.cell())
38 }
39}
40
41impl AfterResolvePluginCondition {
42 pub fn matches(&self, fs_path: &FileSystemPath) -> bool {
44 match self {
45 AfterResolvePluginCondition::Glob { root, glob } => {
46 let path = match root {
47 Some(root) => root.get_path_to(fs_path),
48 None => Some(&*fs_path.path),
49 };
50 path.is_some_and(|p| glob.matches(p))
51 }
52 AfterResolvePluginCondition::Always => true,
53 AfterResolvePluginCondition::Never => false,
54 }
55 }
56}
57
58#[turbo_tasks::value(shared, serialization = "skip")]
60pub enum BeforeResolvePluginCondition {
61 Request(ReadRef<Glob>),
62 Modules(ReadRef<Vec<RcStr>>),
63 Always,
65 Never,
66}
67
68#[turbo_tasks::value_impl]
69impl BeforeResolvePluginCondition {
70 #[turbo_tasks::function]
71 pub async fn from_modules(modules: ResolvedVc<Vec<RcStr>>) -> Result<Vc<Self>> {
72 Ok(BeforeResolvePluginCondition::Modules(modules.await?).cell())
73 }
74
75 #[turbo_tasks::function]
76 pub async fn from_request_glob(glob: ResolvedVc<Glob>) -> Result<Vc<Self>> {
77 Ok(BeforeResolvePluginCondition::Request(glob.await?).cell())
78 }
79}
80
81impl BeforeResolvePluginCondition {
82 pub fn matches(&self, request: &Request) -> bool {
84 match self {
85 BeforeResolvePluginCondition::Request(glob) => match request.request() {
86 Some(request) => glob.matches(request.as_str()),
87 None => false,
88 },
89 BeforeResolvePluginCondition::Modules(modules) => {
90 if let Request::Module { module, .. } = request {
91 modules.iter().any(|m| module.is_match(m))
92 } else {
93 false
94 }
95 }
96 BeforeResolvePluginCondition::Always => true,
97 BeforeResolvePluginCondition::Never => false,
98 }
99 }
100}
101
102#[turbo_tasks::value_trait]
103pub trait BeforeResolvePlugin {
104 fn before_resolve_condition(&self) -> Vc<BeforeResolvePluginCondition>;
105
106 #[turbo_tasks::function]
107 fn before_resolve(
108 self: Vc<Self>,
109 lookup_path: FileSystemPath,
110 reference_type: ReferenceType,
111 request: Vc<Request>,
112 ) -> Vc<ResolveResultOption>;
113}
114
115#[turbo_tasks::value_trait]
116pub trait AfterResolvePlugin {
117 fn after_resolve_condition(&self) -> Vc<AfterResolvePluginCondition>;
119
120 #[turbo_tasks::function]
124 fn after_resolve(
125 self: Vc<Self>,
126 fs_path: FileSystemPath,
127 lookup_path: FileSystemPath,
128 reference_type: ReferenceType,
129 request: Vc<Request>,
130 ) -> Vc<ResolveResultOption>;
131}