turbopack_dev_server/source/
combined.rs1use anyhow::Result;
2use turbo_rcstr::RcStr;
3use turbo_tasks::{ResolvedVc, TryJoinIterExt, Vc};
4use turbopack_core::introspect::{Introspectable, IntrospectableChildren};
5
6use super::{
7 ContentSource,
8 route_tree::{RouteTree, RouteTrees},
9};
10use crate::source::ContentSources;
11
12#[turbo_tasks::value(shared)]
17pub struct CombinedContentSource {
18 pub sources: Vec<ResolvedVc<Box<dyn ContentSource>>>,
19}
20
21impl CombinedContentSource {
22 pub fn new(sources: Vec<ResolvedVc<Box<dyn ContentSource>>>) -> Vc<Self> {
23 CombinedContentSource { sources }.cell()
24 }
25}
26
27#[turbo_tasks::value_impl]
28impl ContentSource for CombinedContentSource {
29 #[turbo_tasks::function]
30 async fn get_routes(&self) -> Result<Vc<RouteTree>> {
31 let all_routes = self
32 .sources
33 .iter()
34 .map(|s| async move { s.get_routes().to_resolved().await })
35 .try_join()
36 .await?;
37 Ok(Vc::<RouteTrees>::cell(all_routes).merge())
38 }
39
40 #[turbo_tasks::function]
41 fn get_children(&self) -> Vc<ContentSources> {
42 Vc::cell(self.sources.clone())
43 }
44}
45
46#[turbo_tasks::value_impl]
47impl Introspectable for CombinedContentSource {
48 #[turbo_tasks::function]
49 fn ty(&self) -> Vc<RcStr> {
50 Vc::cell("combined content source".into())
51 }
52
53 #[turbo_tasks::function]
54 async fn title(&self) -> Result<Vc<RcStr>> {
55 let titles = self
56 .sources
57 .iter()
58 .map(|&source| async move {
59 Ok(
60 if let Some(source) =
61 ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(source)
62 {
63 Some(source.title().await?)
64 } else {
65 None
66 },
67 )
68 })
69 .try_join()
70 .await?;
71 let mut titles = titles.into_iter().flatten().collect::<Vec<_>>();
72 titles.sort();
73 const NUMBER_OF_TITLES_TO_DISPLAY: usize = 5;
74 let mut titles = titles
75 .iter()
76 .map(|t| t.as_str())
77 .filter(|t| !t.is_empty())
78 .take(NUMBER_OF_TITLES_TO_DISPLAY + 1)
79 .collect::<Vec<_>>();
80 if titles.len() > NUMBER_OF_TITLES_TO_DISPLAY {
81 titles[NUMBER_OF_TITLES_TO_DISPLAY] = "...";
82 }
83 Ok(Vc::cell(titles.join(", ").into()))
84 }
85
86 #[turbo_tasks::function]
87 async fn children(&self) -> Result<Vc<IntrospectableChildren>> {
88 let source = ResolvedVc::cell("source".into());
89 Ok(Vc::cell(
90 self.sources
91 .iter()
92 .copied()
93 .map(|s| async move { Ok(ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(s)) })
94 .try_join()
95 .await?
96 .into_iter()
97 .flatten()
98 .map(|i| (source, i))
99 .collect(),
100 ))
101 }
102}