1use anyhow::Result;
2use tracing::Instrument;
3use turbo_tasks::{TryFlatJoinIterExt, Vc};
4use turbo_tasks_fs::{FileSystemPath, rebase};
5use turbopack_core::{
6 asset::Asset,
7 output::{ExpandedOutputAssets, OutputAsset, OutputAssets},
8 reference::all_assets_from_entries,
9};
10
11#[turbo_tasks::function]
17pub async fn emit_all_assets(
18 assets: Vc<OutputAssets>,
19 node_root: FileSystemPath,
20 client_relative_path: FileSystemPath,
21 client_output_path: FileSystemPath,
22) -> Result<()> {
23 emit_assets(
24 all_assets_from_entries(assets),
25 node_root,
26 client_relative_path,
27 client_output_path,
28 )
29 .as_side_effect()
30 .await?;
31 Ok(())
32}
33
34#[turbo_tasks::function]
40pub async fn emit_assets(
41 assets: Vc<ExpandedOutputAssets>,
42 node_root: FileSystemPath,
43 client_relative_path: FileSystemPath,
44 client_output_path: FileSystemPath,
45) -> Result<()> {
46 let _: Vec<()> = assets
47 .await?
48 .iter()
49 .copied()
50 .map(|asset| {
51 let node_root = node_root.clone();
52 let client_relative_path = client_relative_path.clone();
53 let client_output_path = client_output_path.clone();
54
55 async move {
56 let path = asset.path().owned().await?;
57 let span = tracing::info_span!("emit asset", name = %path.value_to_string().await?);
58 async move {
59 Ok(if path.is_inside_ref(&node_root) {
60 Some(emit(*asset).as_side_effect().await?)
61 } else if path.is_inside_ref(&client_relative_path) {
62 Some(
66 emit_rebase(*asset, client_relative_path, client_output_path)
67 .as_side_effect()
68 .await?,
69 )
70 } else {
71 None
72 })
73 }
74 .instrument(span)
75 .await
76 }
77 })
78 .try_flat_join()
79 .await?;
80 Ok(())
81}
82
83#[turbo_tasks::function]
84async fn emit(asset: Vc<Box<dyn OutputAsset>>) -> Result<()> {
85 asset
86 .content()
87 .resolve()
88 .await?
89 .write(asset.path().owned().await?)
90 .as_side_effect()
91 .await?;
92 Ok(())
93}
94
95#[turbo_tasks::function]
96async fn emit_rebase(
97 asset: Vc<Box<dyn OutputAsset>>,
98 from: FileSystemPath,
99 to: FileSystemPath,
100) -> Result<()> {
101 let path = rebase(asset.path().owned().await?, from, to)
102 .owned()
103 .await?;
104 let content = asset.content();
105 content
106 .resolve()
107 .await?
108 .write(path)
109 .as_side_effect()
110 .await?;
111 Ok(())
112}