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);