update_kit/checker/sources/
mod.rs1pub mod brew_api;
2pub mod custom_manifest;
3pub mod github;
4pub mod jsr;
5pub mod npm_registry;
6
7use crate::config::VersionSourceConfig;
8use crate::errors::UpdateKitError;
9use crate::types::AssetInfo;
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct VersionInfo {
15 pub version: String,
16 pub release_url: Option<String>,
17 pub release_notes: Option<String>,
18 pub assets: Option<Vec<AssetInfo>>,
19 pub published_at: Option<String>,
20}
21
22#[derive(Debug)]
24pub enum VersionSourceResult {
25 Found {
26 info: VersionInfo,
27 etag: Option<String>,
28 },
29 NotModified {
30 etag: String,
31 },
32 Error {
33 reason: String,
34 status: Option<u16>,
35 },
36}
37
38#[derive(Debug, Default)]
40pub struct FetchOptions {
41 pub etag: Option<String>,
42}
43
44#[derive(Debug, Default, Clone)]
46pub struct FetchVersionsOptions {
47 pub limit: Option<usize>,
48 pub cursor: Option<String>,
49}
50
51#[derive(Debug)]
53pub enum VersionListResult {
54 Success {
55 versions: Vec<VersionInfo>,
56 next_cursor: Option<String>,
57 total_count: Option<usize>,
58 },
59 Error {
60 reason: String,
61 },
62}
63
64#[async_trait::async_trait]
66pub trait VersionSource: Send + Sync {
67 fn name(&self) -> &str;
69
70 async fn fetch_latest(&self, options: FetchOptions) -> VersionSourceResult;
72
73 async fn fetch_versions(
75 &self,
76 _options: FetchVersionsOptions,
77 ) -> Result<VersionListResult, UpdateKitError> {
78 Err(UpdateKitError::UnsupportedOperation(
79 "fetch_versions not supported".into(),
80 ))
81 }
82}
83
84pub fn create_version_source(config: VersionSourceConfig) -> Box<dyn VersionSource> {
86 match config {
87 VersionSourceConfig::Github {
88 owner,
89 repo,
90 token,
91 api_base_url,
92 } => Box::new(github::GitHubReleasesSource::new(
93 owner,
94 repo,
95 token,
96 api_base_url,
97 )),
98 VersionSourceConfig::Npm {
99 package_name,
100 registry_url,
101 } => Box::new(npm_registry::NpmRegistrySource::new(
102 package_name,
103 registry_url,
104 )),
105 VersionSourceConfig::Jsr { scope, name } => {
106 Box::new(jsr::JsrSource::new(scope, name))
107 }
108 VersionSourceConfig::Brew { cask_name } => {
109 Box::new(brew_api::BrewSource::new(cask_name))
110 }
111 VersionSourceConfig::Custom { url, version_field } => {
112 Box::new(custom_manifest::CustomManifestSource::new(url, version_field))
113 }
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_create_github_source() {
123 let source = create_version_source(VersionSourceConfig::Github {
124 owner: "user".into(),
125 repo: "repo".into(),
126 token: None,
127 api_base_url: None,
128 });
129 assert_eq!(source.name(), "github");
130 }
131
132 #[test]
133 fn test_create_npm_source() {
134 let source = create_version_source(VersionSourceConfig::Npm {
135 package_name: "my-pkg".into(),
136 registry_url: None,
137 });
138 assert_eq!(source.name(), "npm");
139 }
140
141 #[test]
142 fn test_create_jsr_source() {
143 let source = create_version_source(VersionSourceConfig::Jsr {
144 scope: "scope".into(),
145 name: "pkg".into(),
146 });
147 assert_eq!(source.name(), "jsr");
148 }
149
150 #[test]
151 fn test_create_brew_source() {
152 let source = create_version_source(VersionSourceConfig::Brew {
153 cask_name: "my-cask".into(),
154 });
155 assert_eq!(source.name(), "brew");
156 }
157
158 #[test]
159 fn test_create_custom_source() {
160 let source = create_version_source(VersionSourceConfig::Custom {
161 url: "https://example.com/version.json".into(),
162 version_field: Some("version".into()),
163 });
164 assert_eq!(source.name(), "custom");
165 }
166}