next_napi_bindings/next_api/
analyze.rs1use std::{iter::once, sync::Arc};
2
3use anyhow::Result;
4use next_api::{
5 analyze::{
6 AnalyzeDataOutputAsset, ModulesDataOutputAsset, combine_output_assets, combine_traced_files,
7 },
8 project::ProjectContainer,
9 route::EndpointGroupKey,
10};
11use turbo_tasks::{Effects, ReadRef, ResolvedVc, TryJoinIterExt, Vc};
12use turbo_tasks_fs::FileSystemPath;
13use turbopack_core::{
14 issue::PlainIssue,
15 output::{OutputAsset, OutputAssets},
16};
17
18use crate::next_api::utils::strongly_consistent_catch_collectables;
19
20#[turbo_tasks::value(serialization = "skip")]
21pub struct WriteAnalyzeResult {
22 pub issues: Arc<Vec<ReadRef<PlainIssue>>>,
23 pub effects: Arc<Effects>,
24}
25
26#[turbo_tasks::function(operation, root)]
27pub async fn write_analyze_data_with_issues_operation(
28 project: ResolvedVc<ProjectContainer>,
29 app_dir_only: bool,
30) -> Result<Vc<WriteAnalyzeResult>> {
31 let analyze_data_op = write_analyze_data_with_issues_operation_inner(project, app_dir_only);
32 let filter = project.project().issue_filter().await?;
33
34 let (_analyze_data, issues, effects) =
35 strongly_consistent_catch_collectables(analyze_data_op, &filter).await?;
36
37 Ok(WriteAnalyzeResult { issues, effects }.cell())
38}
39
40#[turbo_tasks::function(operation, root)]
41async fn write_analyze_data_with_issues_operation_inner(
42 project: ResolvedVc<ProjectContainer>,
43 app_dir_only: bool,
44) -> Result<()> {
45 let analyze_data_op = get_analyze_data_operation(project, app_dir_only);
46
47 project
48 .project()
49 .emit_all_output_assets(analyze_data_op)
50 .as_side_effect()
51 .await?;
52
53 Ok(())
54}
55
56#[turbo_tasks::function(operation)]
57async fn get_analyze_data_operation(
58 container: ResolvedVc<ProjectContainer>,
59 app_dir_only: bool,
60) -> Result<Vc<OutputAssets>> {
61 let project = container.project();
62 let project = project.with_next_config(project.next_config().with_analyze_config());
63
64 let analyze_output_root = project
65 .node_root()
66 .owned()
67 .await?
68 .join("diagnostics/analyze/data")?;
69 let whole_app_module_graphs = project.whole_app_module_graphs();
70 let analyze_output_root = &analyze_output_root;
71 let endpoint_groups = project.get_all_endpoint_groups(app_dir_only).await?;
72
73 let mut combined_output_assets: Vec<ResolvedVc<Box<dyn OutputAsset>>> = vec![];
76 let mut combined_traced_files: Vec<FileSystemPath> = vec![];
77 for (key, endpoint_group) in endpoint_groups.iter() {
78 if matches!(
79 key,
80 EndpointGroupKey::PagesApp | EndpointGroupKey::PagesDocument
81 ) {
82 combined_output_assets.extend(endpoint_group.output_assets().await?.iter().copied());
83 combined_traced_files.extend(endpoint_group.traced_files().await?.iter().cloned());
84 }
85 }
86
87 let has_combined = !combined_output_assets.is_empty();
88 let combined_assets_vc = Vc::cell(combined_output_assets);
89 let combined_traced_vc = Vc::cell(combined_traced_files);
90
91 let analyze_data = endpoint_groups
92 .iter()
93 .map(async |(key, endpoint_group)| {
94 let output_assets = if has_combined
95 && !matches!(
96 key,
97 EndpointGroupKey::PagesApp | EndpointGroupKey::PagesDocument
98 ) {
99 combine_output_assets(endpoint_group.output_assets(), combined_assets_vc)
102 } else {
103 endpoint_group.output_assets()
104 };
105 let traced_files = if has_combined
106 && !matches!(
107 key,
108 EndpointGroupKey::PagesApp | EndpointGroupKey::PagesDocument
109 ) {
110 combine_traced_files(endpoint_group.traced_files(), combined_traced_vc)
113 } else {
114 endpoint_group.traced_files()
115 };
116 let analyze_data = AnalyzeDataOutputAsset::new(
117 analyze_output_root
118 .join(&key.to_string())?
119 .join("analyze.data")?,
120 output_assets,
121 traced_files,
122 )
123 .to_resolved()
124 .await?;
125
126 Ok(ResolvedVc::upcast(analyze_data))
127 })
128 .try_join()
129 .await?;
130
131 let modules_data = ResolvedVc::upcast(
132 ModulesDataOutputAsset::new(
133 analyze_output_root.join("modules.data")?,
134 *whole_app_module_graphs.await?.full,
135 )
136 .to_resolved()
137 .await?,
138 );
139
140 Ok(Vc::cell(
141 analyze_data
142 .iter()
143 .cloned()
144 .chain(once(modules_data))
145 .collect(),
146 ))
147}