rust_jsr_registry/types/
meta.rs

1use std::collections::HashMap;
2use semver::Version;
3use serde::{Deserialize, Serialize};
4use crate::{fetcher::GetProviderScope, priv_as_ref, priv_from_info, priv_impl_getinfo};
5pub use crate::serde::{VersionDateTimeMap, TimeInfo as NpmCompTimeInfo};
6
7use super::{error::NpmCompParseError, package::NpmCompPackage};
8#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
9/// Versions info from [Meta::versions]
10pub struct VersionInfo {
11    /// Detect if version is yanked (archived)
12    #[serde(default)]
13    pub yanked: bool
14}
15/// Creates a builder for [Meta]
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct MetaBuilder {
18    /// Package scope
19    ///
20    /// ## Example
21    ///
22    /// `dunno` from `@dunno/object`
23    pub scope: String,
24    /// Package name
25    ///
26    /// ## Example
27    ///
28    /// `object` from `@dunno/object`
29    pub name: String,
30}
31/// Creates a builder for [Meta]
32impl MetaBuilder {
33    /// Creates a builder for [Meta]
34    #[allow(clippy::new_without_default)]
35    pub fn new() -> Self {
36        return Self {
37            scope:"".to_string(),
38            name:"".to_string()
39        };
40    }
41    /// Convert JSR-to-npm equivalent package name to normal one
42    /// 
43    /// It needs either [crate::fetcher::FetcherBuilder] or [crate::fetcher::Fetcher] since it needs [crate::fetcher::FetcherBuilder::provider_scope] to detect the scope owned in npm-side
44    /// 
45    /// ## Panics
46    /// 
47    /// Throw panic if it cant parse, use [Self::try_from_npm_comp_name] to handle it
48    pub fn from_npm_comp_name<T:GetProviderScope>(gts:impl AsRef<T>, value:impl Into<String>) -> Self {
49        return Self::try_from_npm_comp_name(gts, value).expect("Failed to parse string to MetaBuilder");
50    }
51    /// Convert JSR-to-npm equivalent package name to normal one, as [Result]
52    /// 
53    /// It needs either [crate::fetcher::FetcherBuilder] or [crate::fetcher::Fetcher] since it needs [crate::fetcher::FetcherBuilder::provider_scope] to detect the scope owned in npm-side
54    pub fn try_from_npm_comp_name<T:GetProviderScope>(gts:impl AsRef<T>, value:impl Into<String>) -> Result<Self, NpmCompParseError> {
55        let builder_ref = gts.as_ref();
56        let prov = builder_ref.get_provider_scope().to_string();
57        let v = value.into();
58        if !v.starts_with(format!("@{}/", prov).as_str()) {
59            return Err(NpmCompParseError::DosentStartWithPrefix(prov.to_string()));
60        }
61        let calc = 2+prov.len();
62        let parts: Vec<&str> = v[calc..].split("__").collect();
63    
64        if parts.len() != 2 {
65            return Err(NpmCompParseError::CompFormat);
66        }
67    
68        return Ok(Self {
69            scope: parts[0].to_string(), 
70            name: parts[1].to_string()
71        })
72    }
73    priv_from_info!();
74}
75priv_as_ref!(MetaBuilder);
76priv_impl_getinfo!(MetaBuilder);
77
78/// The package metadata result
79/// 
80/// See https://jsr.io/docs/api#package-metadata
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct Meta {
83    /// Package scope
84    ///
85    /// ## Example
86    ///
87    /// `dunno` from `@dunno/object`
88    pub scope: String,
89    /// Package name
90    ///
91    /// ## Example
92    ///
93    /// `object` from `@dunno/object`
94    pub name: String,
95    /// Latest version from one of [Self::versions]
96    pub latest: Version,
97    /// List of versions founded from metadata
98    pub versions: HashMap<Version, VersionInfo>,
99}
100impl PartialEq for Meta {
101    fn eq(&self, other: &Self) -> bool {
102        return self.scope == other.scope && self.name == other.name && self.latest.to_string() == other.latest.to_string();
103    }
104}
105impl Eq for Meta {}
106priv_impl_getinfo!(Meta);
107priv_as_ref!(Meta); 
108
109/// Distribution tags for [NpmCompMeta::dist_tags]
110#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct NpmCompDistTags {
112    /// Latest version of the package
113    pub latest:Version
114}
115
116/// JSR-to-npm equivalent package meta
117#[derive(Debug, Clone, Serialize, Deserialize)]
118#[serde(rename_all = "kebab-case")]
119pub struct NpmCompMeta {
120    /// JSR-to-npm equivalent package name
121    /// 
122    /// Note: this is different than normal [Meta::name].
123    /// 
124    /// If your [MetaBuilder] contains like this
125    /// 
126    /// ```
127    /// MetaBuilder::new()
128    ///     .set_scope("dunno")
129    ///     .set_name("object")
130    /// ```
131    /// 
132    /// It would be added like this, right?
133    /// 
134    /// ```
135    /// {
136    ///     scope: "dunno",
137    ///     name: "object"
138    /// }
139    /// ```
140    /// 
141    /// Since the scope (in JSR) is actually fake on npm, it would be listed as
142    /// 
143    /// `@<jsr provider scope>/<jsr package scope>__<jsr package name>`
144    /// 
145    /// So, this [Self::name] is equivalent to
146    /// 
147    /// `@jsr/dunno__object`
148    pub name:String,
149    /// Get versions
150    pub versions:HashMap<Version, NpmCompPackage>,
151    /// Package desription
152    pub description:String,
153    /// Distribution tags (only contain `latest` for now) 
154    /// 
155    /// See https://jsr.io/docs/api#npm-compatibility-registry-api on `dist-tags`
156    pub dist_tags:NpmCompDistTags,
157    /// Timestamp for package activities
158    pub time:NpmCompTimeInfo
159}
160priv_as_ref!(NpmCompMeta);