plantuml_server_client_rs/
client.rs

1mod create_metadata;
2mod load_metadata;
3mod metadata_store;
4mod request_single;
5mod write_combined;
6
7use crate::encode::Encoder;
8use crate::{Collector, Config, Locate, Metadata, MetadataItem, MetadataVersion};
9use anyhow::{Context as _, Result};
10use metadata_store::MetadataStore;
11use plantuml_parser::PlantUmlFileData;
12
13/// A Client to request to PlantUML Server.
14pub struct Client {
15    config: Config,
16
17    client: reqwest::Client,
18    encoder: Encoder,
19
20    metadata_store: MetadataStore,
21}
22
23impl Client {
24    /// Creates a new [`Client`].
25    ///
26    /// * `config` - A config of `plantuml-server-client`.
27    pub fn new(config: Config) -> Self {
28        let client = reqwest::Client::new();
29        let encoder = Encoder::new();
30        let metadata_store = MetadataStore::new();
31
32        Self {
33            config,
34            client,
35            encoder,
36            metadata_store,
37        }
38    }
39
40    /// Requests by the client
41    ///
42    /// * `input` - A [`Locate`] of input.
43    /// * `output` - A [`Locate`] of output.
44    pub async fn request(&self, input: Locate, output: &Locate) -> Result<MetadataItem> {
45        tracing::info!("method = {:?}", self.config.method);
46        tracing::info!("url_prefix = {:?}", self.config.url_prefix);
47        tracing::info!("format = {:?}", self.config.format);
48        tracing::info!("input = {input:?}");
49        tracing::info!("output = {output:?}");
50
51        let filedata = input.read()?;
52        let base = input.to_path_buf();
53        let filedata = PlantUmlFileData::parse_from_str(filedata)?;
54        let collected = Collector::collect(base.clone(), &filedata)
55            .context("failed to collect files to include")?;
56        tracing::debug!("collected = {collected:?}");
57
58        let mut plantuml_metadata = vec![];
59
60        for (idx, data) in filedata.iter().enumerate() {
61            request_single::RequestSingleClient::from(self)
62                .request_single(
63                    &mut plantuml_metadata,
64                    idx,
65                    data,
66                    &collected,
67                    &input,
68                    output,
69                )
70                .await
71                .with_context(|| format!("failed to request: idx = {idx}"))?;
72        }
73
74        tracing::debug!("plantuml_metadata = {plantuml_metadata:?}");
75        let metadata = create_metadata::CreateMetadataClient::from(self)
76            .create_metadata(collected, plantuml_metadata)
77            .await
78            .context("failed to write metadata")?;
79        tracing::debug!("metadata = {metadata:?}");
80
81        Ok(metadata)
82    }
83
84    pub async fn write_metadata_if_needed(&self, metadatas: Vec<MetadataItem>) -> Result<()> {
85        if let Some(metadata_path) = &self.config.metadata {
86            self.metadata_store
87                .update(metadatas)
88                .context("failed to update metadata store.")?;
89            let metadata = self
90                .metadata_store
91                .metadata()
92                .context("failed to get metadata from store.")?;
93
94            let data = match &self.config.metadata_version {
95                MetadataVersion::V1 => serde_json::to_string(&Metadata::from(metadata)),
96                MetadataVersion::V2 => serde_json::to_string(&metadata),
97            }
98            .context("failed to serialize metadata")?;
99            let data = futures::stream::iter(vec![Ok(data.into())]);
100            let path = Locate::new(Some(metadata_path.clone()));
101            path.write(data).await.context("failed to write metadata")?;
102        }
103
104        Ok(())
105    }
106}