package_json_parser 0.0.16

A parser for package.json
Documentation
use jsonc_parser::ast::ObjectProp;
use serde::{Deserialize, Serialize};
use validator::ValidateUrl;

use crate::ext::{Validator, validation_error, value_range};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Repository {
  #[serde(skip_serializing_if = "Option::is_none")]
  pub r#type: Option<String>,

  #[serde(skip_serializing_if = "Option::is_none")]
  pub url: Option<String>,

  #[serde(skip_serializing_if = "Option::is_none")]
  pub directory: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(untagged)]
pub enum RepositoryOrString {
  Repository(Repository),
  String(String),
}

impl Validator for RepositoryOrString {
  fn validate(&self, repository: Option<&ObjectProp>) -> miette::Result<()> {
    match self {
      RepositoryOrString::Repository(repos) => {
        if let Some(url) = repos.url.as_ref() {
          if !url.validate_url() {
            return Err(validation_error(
              "Invalid url",
              Some("invalid_url"),
              "Please provide a valid url",
              value_range(repository, &["url"]),
              "Invalid url",
            ));
          }
        }
        Ok(())
      }
      RepositoryOrString::String(string) => {
        if !string.validate_url() {
          return Err(validation_error(
            "Invalid url",
            Some("invalid_url"),
            "Please provide a valid url",
            value_range(repository, &[]),
            "Invalid url",
          ));
        }
        Ok(())
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use crate::PackageJsonParser;

  #[test]
  fn should_pass_validate_repository() {
    let jsones = [
      r#"{"repository": {"type": "git", "url": "https://github.com/rust-lang/rust", "directory": "src"}}"#,
      r#"{"repository": "https://github.com/rust-lang/rust"}"#,
    ];

    for json in jsones {
      let res = PackageJsonParser::parse_str(json).unwrap();
      let res = res.validate();
      assert!(res.is_ok());
    }
  }

  #[test]
  fn should_fail_validate_repository() {
    let jsones = [
      r#"{"repository": {"type": "git", "url": "invalid", "directory": "src"}}"#,
      r#"{"repository": "invalid"}"#,
    ];

    for json in jsones {
      let res = PackageJsonParser::parse_str(json).unwrap();
      let res = res.validate();
      assert!(res.is_err());
    }
  }
}