changepacks_node/
workspace.rs

1use anyhow::Result;
2use async_trait::async_trait;
3use changepacks_core::{Language, UpdateType, Workspace};
4use changepacks_utils::{detect_indent, next_version};
5use serde::Serialize;
6use std::path::{Path, PathBuf};
7use tokio::fs::{read_to_string, write};
8
9#[derive(Debug)]
10pub struct NodeWorkspace {
11    path: PathBuf,
12    relative_path: PathBuf,
13    version: Option<String>,
14    name: Option<String>,
15    is_changed: bool,
16}
17
18impl NodeWorkspace {
19    pub fn new(
20        name: Option<String>,
21        version: Option<String>,
22        path: PathBuf,
23        relative_path: PathBuf,
24    ) -> Self {
25        Self {
26            path,
27            relative_path,
28            name,
29            version,
30            is_changed: false,
31        }
32    }
33}
34
35#[async_trait]
36impl Workspace for NodeWorkspace {
37    fn name(&self) -> Option<&str> {
38        self.name.as_deref()
39    }
40
41    fn path(&self) -> &Path {
42        &self.path
43    }
44
45    fn version(&self) -> Option<&str> {
46        self.version.as_deref()
47    }
48
49    async fn update_version(&self, update_type: UpdateType) -> Result<()> {
50        let next_version = next_version(
51            self.version.as_ref().unwrap_or(&String::from("0.0.0")),
52            update_type,
53        )?;
54
55        let package_json_raw = read_to_string(Path::new(&self.path)).await?;
56        let postfix = if package_json_raw.ends_with("\n") {
57            "\n"
58        } else {
59            ""
60        };
61        let indent = detect_indent(&package_json_raw);
62        let mut package_json: serde_json::Value = serde_json::from_str(&package_json_raw)?;
63        package_json["version"] = serde_json::Value::String(next_version.clone());
64        let ind = &b" ".repeat(indent);
65        let formatter = serde_json::ser::PrettyFormatter::with_indent(ind);
66        let writer = Vec::new();
67        let mut ser = serde_json::Serializer::with_formatter(writer, formatter);
68        package_json.serialize(&mut ser)?;
69        write(
70            &self.path,
71            String::from_utf8(ser.into_inner())?.to_string() + postfix,
72        )
73        .await?;
74        Ok(())
75    }
76
77    fn language(&self) -> Language {
78        Language::Node
79    }
80
81    fn is_changed(&self) -> bool {
82        self.is_changed
83    }
84
85    fn set_changed(&mut self, changed: bool) {
86        self.is_changed = changed;
87    }
88
89    fn relative_path(&self) -> &Path {
90        &self.relative_path
91    }
92}