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