changepacks_node/
workspace.rs1use 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}