turbopack_dev_server/source/
issue_context.rs

1use anyhow::Result;
2use turbo_rcstr::{RcStr, rcstr};
3use turbo_tasks::{ResolvedVc, Vc};
4use turbo_tasks_fs::FileSystemPath;
5use turbopack_core::{
6    introspect::{Introspectable, IntrospectableChildren},
7    issue::IssueDescriptionExt,
8};
9
10use super::{
11    ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataVary, ContentSources,
12    GetContentSourceContent,
13    route_tree::{MapGetContentSourceContent, RouteTree},
14};
15
16#[turbo_tasks::value]
17pub struct IssueFilePathContentSource {
18    file_path: Option<FileSystemPath>,
19    description: RcStr,
20    source: ResolvedVc<Box<dyn ContentSource>>,
21}
22
23#[turbo_tasks::value_impl]
24impl IssueFilePathContentSource {
25    #[turbo_tasks::function]
26    pub fn new_file_path(
27        file_path: FileSystemPath,
28        description: RcStr,
29        source: ResolvedVc<Box<dyn ContentSource>>,
30    ) -> Vc<Self> {
31        IssueFilePathContentSource {
32            file_path: Some(file_path),
33            description,
34            source,
35        }
36        .cell()
37    }
38
39    #[turbo_tasks::function]
40    pub fn new_description(
41        description: RcStr,
42        source: ResolvedVc<Box<dyn ContentSource>>,
43    ) -> Vc<Self> {
44        IssueFilePathContentSource {
45            file_path: None,
46            description,
47            source,
48        }
49        .cell()
50    }
51}
52
53#[turbo_tasks::value_impl]
54impl ContentSource for IssueFilePathContentSource {
55    #[turbo_tasks::function]
56    async fn get_routes(self: ResolvedVc<Self>) -> Result<Vc<RouteTree>> {
57        let this = self.await?;
58        let routes = content_source_get_routes_operation(this.source)
59            .issue_file_path(this.file_path.clone(), &*this.description)
60            .await?
61            .connect();
62        Ok(routes.map_routes(Vc::upcast(
63            IssueContextContentSourceMapper { source: self }.cell(),
64        )))
65    }
66
67    #[turbo_tasks::function]
68    fn get_children(&self) -> Vc<ContentSources> {
69        Vc::cell(vec![self.source])
70    }
71}
72
73#[turbo_tasks::function(operation)]
74fn content_source_get_routes_operation(
75    source: ResolvedVc<Box<dyn ContentSource>>,
76) -> Vc<RouteTree> {
77    source.get_routes()
78}
79
80#[turbo_tasks::value]
81struct IssueContextContentSourceMapper {
82    source: ResolvedVc<IssueFilePathContentSource>,
83}
84
85#[turbo_tasks::value_impl]
86impl MapGetContentSourceContent for IssueContextContentSourceMapper {
87    #[turbo_tasks::function]
88    fn map_get_content(
89        &self,
90        get_content: ResolvedVc<Box<dyn GetContentSourceContent>>,
91    ) -> Vc<Box<dyn GetContentSourceContent>> {
92        Vc::upcast(
93            IssueContextGetContentSourceContent {
94                get_content,
95                source: self.source,
96            }
97            .cell(),
98        )
99    }
100}
101
102#[turbo_tasks::value]
103struct IssueContextGetContentSourceContent {
104    get_content: ResolvedVc<Box<dyn GetContentSourceContent>>,
105    source: ResolvedVc<IssueFilePathContentSource>,
106}
107
108#[turbo_tasks::value_impl]
109impl GetContentSourceContent for IssueContextGetContentSourceContent {
110    #[turbo_tasks::function]
111    async fn vary(&self) -> Result<Vc<ContentSourceDataVary>> {
112        let source = self.source.await?;
113        Ok(get_content_source_vary_operation(self.get_content)
114            .issue_file_path(source.file_path.clone(), &*source.description)
115            .await?
116            .connect())
117    }
118
119    #[turbo_tasks::function]
120    async fn get(&self, path: RcStr, data: ContentSourceData) -> Result<Vc<ContentSourceContent>> {
121        let source = self.source.await?;
122        Ok(
123            get_content_source_get_operation(self.get_content, path, data)
124                .issue_file_path(source.file_path.clone(), &*source.description)
125                .await?
126                .connect(),
127        )
128    }
129}
130
131#[turbo_tasks::function(operation)]
132fn get_content_source_vary_operation(
133    get_content: ResolvedVc<Box<dyn GetContentSourceContent>>,
134) -> Vc<ContentSourceDataVary> {
135    get_content.vary()
136}
137
138#[turbo_tasks::function(operation)]
139fn get_content_source_get_operation(
140    get_content: ResolvedVc<Box<dyn GetContentSourceContent>>,
141    path: RcStr,
142    data: ContentSourceData,
143) -> Vc<ContentSourceContent> {
144    get_content.get(path, data)
145}
146
147#[turbo_tasks::value_impl]
148impl Introspectable for IssueFilePathContentSource {
149    #[turbo_tasks::function]
150    fn ty(&self) -> Result<Vc<RcStr>> {
151        Ok(
152            if let Some(source) = ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.source) {
153                source.ty()
154            } else {
155                Vc::cell(rcstr!("IssueContextContentSource"))
156            },
157        )
158    }
159
160    #[turbo_tasks::function]
161    async fn title(&self) -> Result<Vc<RcStr>> {
162        Ok(
163            if let Some(source) = ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.source) {
164                let title = source.title().await?;
165                Vc::cell(format!("{}: {}", self.description, title).into())
166            } else {
167                Vc::cell(self.description.clone())
168            },
169        )
170    }
171
172    #[turbo_tasks::function]
173    fn details(&self) -> Result<Vc<RcStr>> {
174        Ok(
175            if let Some(source) = ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.source) {
176                source.details()
177            } else {
178                Vc::cell(RcStr::default())
179            },
180        )
181    }
182
183    #[turbo_tasks::function]
184    fn children(&self) -> Result<Vc<IntrospectableChildren>> {
185        Ok(
186            if let Some(source) = ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.source) {
187                source.children()
188            } else {
189                Vc::cell(Default::default())
190            },
191        )
192    }
193}