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 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(rcstr!("combined content source"))
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 Ok(Vc::cell(
89 self.sources
90 .iter()
91 .copied()
92 .map(|s| async move { Ok(ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(s)) })
93 .try_join()
94 .await?
95 .into_iter()
96 .flatten()
97 .map(|i| (rcstr!("source"), i))
98 .collect(),
99 ))
100 }
101}