Skip to content

Commit

Permalink
Create NodeURLs struct for URL related things, move some used code …
Browse files Browse the repository at this point in the history
…to struct functions
  • Loading branch information
catuhana committed Jul 4, 2024
1 parent 1a60cde commit aa16189
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 62 deletions.
29 changes: 6 additions & 23 deletions src/cli/install.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use anyhow::Context;
use clap::Args;

use super::NueCommand;
Expand Down Expand Up @@ -27,38 +26,22 @@ impl NueCommand for CommandArguments {
let progress_bar = indicatif::ProgressBar::new_spinner();
progress_bar.enable_steady_tick(std::time::Duration::from_millis(120));

// TODO: Deduplicate this, exact same code is also in `list.rs`
progress_bar.set_message("Fetching releases...");
let response = reqwest::get("https://nodejs.org/download/release/index.json")
.await
.context(
"Failed to fetch releases from `https://nodejs.org/download/release/index.json`",
)?;
if !response.status().is_success() {
anyhow::bail!("Failed to fetch releases: {}", response.status());
}

progress_bar.set_message("Parsing releases...");
let releases_json: Vec<types::node::Release> = response
.json()
.await
.context("Failed to parse releases JSON")?;
let releases = types::node::URLs::default().fetch_releases().await?;

progress_bar.set_message("Filtering releases based on input...");
progress_bar.set_message("Filtering releases...");
let latest_release = match &self.version {
VersionInputs::VersionString(version) => releases_json
VersionInputs::VersionString(version) => releases
.iter()
.find(|release| format!("{}", release.version).starts_with(version)),
VersionInputs::Lts(Some(code_name)) => releases_json.iter().find(|release| {
VersionInputs::Lts(Some(code_name)) => releases.iter().find(|release| {
matches!(
&release.lts,
types::node::LTS::CodeName(name) if *name.to_lowercase() == *code_name
)
}),
VersionInputs::Lts(None) => releases_json
.iter()
.find(|release| release.lts.is_code_name()),
VersionInputs::Latest => releases_json.iter().max_by_key(|release| &release.version),
VersionInputs::Lts(None) => releases.iter().find(|release| release.lts.is_code_name()),
VersionInputs::Latest => releases.iter().max_by_key(|release| &release.version),
};

progress_bar.finish_and_clear();
Expand Down
41 changes: 13 additions & 28 deletions src/cli/list.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use anyhow::Context;
use clap::Args;
use inquire::Select;

Expand Down Expand Up @@ -33,24 +32,10 @@ impl NueCommand for CommandArguments {
progress_bar.enable_steady_tick(std::time::Duration::from_millis(120));

progress_bar.set_message("Fetching releases...");
let response = reqwest::get("https://nodejs.org/download/release/index.json")
.await
.context(
"Failed to fetch releases from `https://nodejs.org/download/release/index.json`",
)?;

if !response.status().is_success() {
anyhow::bail!("Failed to fetch releases: {}", response.status());
}

progress_bar.set_message("Parsing releases...");
let releases_json: Vec<types::node::Release> = response
.json()
.await
.context("Failed to parse releases JSON")?;
let releases = types::node::URLs::default().fetch_releases().await?;

progress_bar.set_message("Filtering releases...");
let releases: Vec<_> = releases_json.into_iter().filter(|release| {
let releases: Vec<_> = releases.into_iter().filter(|release| {
if !release.is_supported_by_current_platform() {
return false
}
Expand Down Expand Up @@ -89,20 +74,20 @@ impl NueCommand for CommandArguments {
.with_page_size(16)
.prompt_skippable()
{
let selected_version = if selected_version.contains(' ') {
selected_version
.split_whitespace()
.nth(0)
.expect("version not found, somehow.")
} else {
&selected_version
};
let release = releases
.iter()
.find(|release| {
format!("v{}", release.version)
== selected_version.split_whitespace().nth(0).unwrap()
})
.expect("release not found, somehow.");

println!(
"Run `nue install {}` to install this version.",
selected_version.hyperlink(format!(
"https://github.com/nodejs/node/releases/tag/{selected_version}"
))
release
.version
.to_string()
.hyperlink(release.get_github_release_url())
);
}

Expand Down
2 changes: 2 additions & 0 deletions src/types/node/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod lts;
mod release;
mod urls;

pub use lts::NodeLTS as LTS;
pub use release::NodeRelease as Release;
pub use urls::NodeURLs as URLs;
33 changes: 22 additions & 11 deletions src/types/node/release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,7 @@ impl NodeRelease {
anyhow::bail!("This release is not supported by the current platform.");
}

let response = reqwest::get(format!(
"https://nodejs.org/dist/v{}/node-v{}-{}.tar.gz",
self.version,
self.version,
types::platforms::Platform::get_system_platform()
))
.await?;
let response = reqwest::get(self.get_download_url()).await?;
if !response.status().is_success() {
anyhow::bail!("Failed to download release: {}", response.status());
}
Expand All @@ -42,10 +36,9 @@ impl NodeRelease {
)?.progress_chars("#>-"));
download_progress_bar.set_message(format!(
"Downloading and unpacking version v{}",
self.version.to_string().hyperlink(format!(
"https://github.com/nodejs/node/releases/tag/{}",
self.version
)),
self.version
.to_string()
.hyperlink(self.get_github_release_url()),
));

let data_stream = response
Expand All @@ -62,6 +55,24 @@ impl NodeRelease {
Ok(())
}

pub fn get_download_url(&self) -> String {
format!(
"{}/v{}/node-v{}-{}.tar.gz",
types::node::URLs::default().get_distribution_path(),
self.version,
self.version,
types::platforms::Platform::get_system_platform()
)
}

pub fn get_github_release_url(&self) -> String {
format!(
"{}/releases/tag/v{}",
types::node::URLs::default().github,
self.version
)
}

pub fn is_supported_by_current_platform(&self) -> bool {
self.files.iter().any(|file| {
file.contains(&types::platforms::Platform::get_system_platform().to_string())
Expand Down
43 changes: 43 additions & 0 deletions src/types/node/urls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use anyhow::Context;

use crate::types;

#[derive(Debug)]
pub struct NodeURLs {
pub home: &'static str,
pub github: &'static str,
}

impl NodeURLs {
pub async fn fetch_releases(&self) -> anyhow::Result<Vec<types::node::Release>> {
let response = reqwest::get(self.get_releases_index()).await?;

if !response.status().is_success() {
anyhow::bail!("Failed to fetch releases: {}", response.status());
}

let releases_json = response
.json()
.await
.context("Failed to parse releases JSON")?;

Ok(releases_json)
}

pub fn get_releases_index(&self) -> String {
format!("{}/dist/index.json", self.home)
}

pub fn get_distribution_path(&self) -> String {
format!("{}/dist", self.home)
}
}

impl Default for NodeURLs {
fn default() -> Self {
Self {
home: "https://nodejs.org",
github: "https://github.com/nodejs/node",
}
}
}

0 comments on commit aa16189

Please sign in to comment.