package_json_parser/def/
package_manager.rs1use std::ops::Range;
2
3use derive_more::{Deref, DerefMut};
4use jsonc_parser::{ast::ObjectProp, common::Ranged};
5use miette::{LabeledSpan, MietteDiagnostic, Severity};
6use serde::{Deserialize, Serialize};
7
8use crate::ext::Validator;
9
10#[derive(Debug, PartialEq, Serialize, Deserialize, Eq, Clone, Deref, DerefMut)]
11pub struct PackageManager(String);
12
13impl PackageManager {
14 fn get_package_manager_range(&self, prop: Option<&ObjectProp>) -> Option<Range<usize>> {
15 prop
16 .and_then(|prop| prop.value.as_string_lit())
17 .map(|value| value.range())
18 .map(|range| range.start..range.end)
19 }
20}
21
22impl Validator for PackageManager {
23 fn validate(&self, prop: Option<&ObjectProp>) -> miette::Result<()> {
24 let regex = lazy_regex::regex_is_match!(r#"(npm|pnpm|yarn|bun)@\d+\.\d+\.\d+(-.+)?"#, &self);
25
26 if regex {
27 return Ok(());
28 }
29
30 let range = self.get_package_manager_range(prop);
31
32 let mut diagnostic = MietteDiagnostic::new("Invalid package manager".to_string())
33 .with_help("Please provide a valid package manager")
34 .with_severity(Severity::Error)
35 .with_code("invalid_package_manager");
36
37 if let Some(range) = range {
38 let label = LabeledSpan::at(range, "here".to_string());
39 diagnostic = diagnostic.with_labels(vec![label]);
40 }
41
42 return Err(miette::miette!(diagnostic));
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use crate::PackageJsonParser;
49
50 #[test]
51 fn should_pass_validate_package_manager() {
52 let jsones = [
53 r#"{"packageManager": "npm@1.0.0"}"#,
54 r#"{"packageManager": "pnpm@1.0.0"}"#,
55 r#"{"packageManager": "yarn@1.0.0"}"#,
56 r#"{"packageManager": "bun@1.0.0"}"#,
57 ];
58
59 for json in jsones {
60 let res = PackageJsonParser::parse_str(json).unwrap();
61 let res = res.validate();
62 assert!(res.is_ok());
63 }
64 }
65
66 #[test]
67 fn should_fail_validate_package_manager() {
68 let jsones = [r#"{"packageManager": "invalid"}"#];
69
70 for json in jsones {
71 let res = PackageJsonParser::parse_str(json).unwrap();
72 let res = res.validate();
73 assert!(res.is_err());
74 }
75 }
76}