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