turbopack_dev_server/source/
issue_context.rs1use anyhow::Result;
2use turbo_rcstr::RcStr;
3use turbo_tasks::{ResolvedVc, Value, 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<ResolvedVc<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: ResolvedVc<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.map(|v| *v), &*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.map(|v| *v), &*source.description)
115 .await?
116 .connect())
117 }
118
119 #[turbo_tasks::function]
120 async fn get(
121 &self,
122 path: RcStr,
123 data: Value<ContentSourceData>,
124 ) -> Result<Vc<ContentSourceContent>> {
125 let source = self.source.await?;
126 Ok(
127 get_content_source_get_operation(self.get_content, path, data)
128 .issue_file_path(source.file_path.map(|v| *v), &*source.description)
129 .await?
130 .connect(),
131 )
132 }
133}
134
135#[turbo_tasks::function(operation)]
136fn get_content_source_vary_operation(
137 get_content: ResolvedVc<Box<dyn GetContentSourceContent>>,
138) -> Vc<ContentSourceDataVary> {
139 get_content.vary()
140}
141
142#[turbo_tasks::function(operation)]
143fn get_content_source_get_operation(
144 get_content: ResolvedVc<Box<dyn GetContentSourceContent>>,
145 path: RcStr,
146 data: Value<ContentSourceData>,
147) -> Vc<ContentSourceContent> {
148 get_content.get(path, data)
149}
150
151#[turbo_tasks::value_impl]
152impl Introspectable for IssueFilePathContentSource {
153 #[turbo_tasks::function]
154 async fn ty(&self) -> Result<Vc<RcStr>> {
155 Ok(
156 if let Some(source) = ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.source) {
157 source.ty()
158 } else {
159 Vc::cell("IssueContextContentSource".into())
160 },
161 )
162 }
163
164 #[turbo_tasks::function]
165 async fn title(&self) -> Result<Vc<RcStr>> {
166 Ok(
167 if let Some(source) = ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.source) {
168 let title = source.title().await?;
169 Vc::cell(format!("{}: {}", self.description, title).into())
170 } else {
171 Vc::cell(self.description.clone())
172 },
173 )
174 }
175
176 #[turbo_tasks::function]
177 async fn details(&self) -> Result<Vc<RcStr>> {
178 Ok(
179 if let Some(source) = ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.source) {
180 source.details()
181 } else {
182 Vc::cell(RcStr::default())
183 },
184 )
185 }
186
187 #[turbo_tasks::function]
188 async fn children(&self) -> Result<Vc<IntrospectableChildren>> {
189 Ok(
190 if let Some(source) = ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.source) {
191 source.children()
192 } else {
193 Vc::cell(Default::default())
194 },
195 )
196 }
197}