turbopack_dev_server/source/
issue_context.rs1use 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}