1pub mod missing;
3
4use std::path::{Path, PathBuf};
5
6use anyhow::Result;
7use async_trait::async_trait;
8use spin_common::paths::parent_dir;
9use spin_manifest::schema::v2;
10
11use crate::{Diagnosis, Diagnostic, PatientApp};
12
13#[derive(Debug)]
15pub struct PatientWasm {
16 app_dir: PathBuf,
17 component_id: String,
18 component: v2::Component,
19}
20
21#[allow(missing_docs)] impl PatientWasm {
23 fn new(app_dir: impl AsRef<Path>, component_id: String, component: v2::Component) -> Self {
24 Self {
25 app_dir: app_dir.as_ref().to_owned(),
26 component_id,
27 component,
28 }
29 }
30
31 pub fn component_id(&self) -> &str {
32 &self.component_id
33 }
34
35 pub fn source_path(&self) -> Option<&Path> {
36 match &self.component.source {
37 v2::ComponentSource::Local(path) => Some(Path::new(path)),
38 _ => None,
39 }
40 }
41
42 pub fn abs_source_path(&self) -> Option<PathBuf> {
43 match &self.component.source {
44 v2::ComponentSource::Local(path) => {
45 let can_path = Path::new(path)
48 .canonicalize()
49 .unwrap_or(self.app_dir.join(path));
50 Some(can_path)
51 }
52 _ => None,
53 }
54 }
55
56 pub fn has_build(&self) -> bool {
57 self.component.build.is_some()
58 }
59}
60
61#[async_trait]
63pub trait WasmDiagnostic {
64 type Diagnosis: Diagnosis;
66
67 async fn diagnose_wasm(
69 &self,
70 app: &PatientApp,
71 wasm: PatientWasm,
72 ) -> Result<Vec<Self::Diagnosis>>;
73}
74
75#[async_trait]
76impl<T: WasmDiagnostic + Send + Sync> Diagnostic for T {
77 type Diagnosis = <Self as WasmDiagnostic>::Diagnosis;
78
79 async fn diagnose(&self, patient: &PatientApp) -> Result<Vec<Self::Diagnosis>> {
80 let manifest_str = patient.manifest_doc.to_string();
81 let manifest = spin_manifest::manifest_from_str(&manifest_str)?;
82 let app_dir = parent_dir(&patient.manifest_path)?;
83 let mut diagnoses = vec![];
84 for (component_id, component) in manifest.components {
85 let wasm = PatientWasm::new(&app_dir, component_id.to_string(), component);
86 diagnoses.extend(self.diagnose_wasm(patient, wasm).await?);
87 }
88 Ok(diagnoses)
89 }
90}