1mod discover;
13mod error;
14mod extract;
15mod http;
16mod index;
17mod installer;
18mod mise;
19mod paths;
20mod platform;
21mod progress;
22mod resolver;
23mod self_install;
24mod shasums;
25mod sources;
26mod spec;
27
28pub use discover::{
29 InstallOrigin, InstalledNode, list_installed, mise_node_installs_dir, node_on_path,
30 probe_path_node,
31};
32pub use error::Error;
33pub use mise::mise_on_path;
34pub use paths::{install_dir, runtime_dir};
35pub use platform::Platform;
36pub use progress::{DownloadProgress, InstallPhase, NoopProgress};
37pub use resolver::{NodeRuntime, Resolution, ResolvedFrom};
38pub use self_install::{
39 InstalledAube, available_aube_versions, find_installed_aube, install_aube, list_installed_aube,
40 release_target_triple, self_dir,
41};
42pub use shasums::{sha256_from_sri, sri_sha256};
43pub use sources::{effective_request, find_version_file};
44pub use spec::{NodeRequest, NodeSpec, RequestSource};
45
46use std::collections::BTreeMap;
47
48pub const DEFAULT_MIRROR_BASE: &str = "https://nodejs.org/download/release";
52
53pub const UNOFFICIAL_BASE: &str = "https://unofficial-builds.nodejs.org/download/release";
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
60pub enum InstallerMode {
61 #[default]
63 Auto,
64 Mise,
66 Aube,
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
71pub enum NetworkMode {
72 #[default]
73 Online,
74 Offline,
76}
77
78#[derive(Debug, Clone, Default)]
80pub struct RuntimeConfig {
81 pub installer: InstallerMode,
82 pub mirror: Option<String>,
85 pub network: NetworkMode,
86 pub retries: u32,
88}
89
90impl RuntimeConfig {
91 pub fn new() -> Self {
92 RuntimeConfig {
93 retries: 2,
94 ..Default::default()
95 }
96 }
97
98 pub(crate) fn mirror_base(&self) -> String {
101 match &self.mirror {
102 Some(m) => m.trim_end_matches('/').to_string(),
103 None => DEFAULT_MIRROR_BASE.to_string(),
104 }
105 }
106
107 pub(crate) fn artifact_base(&self, platform: &Platform) -> String {
112 if self.mirror.is_none() && platform.libc.as_deref() == Some("musl") {
113 UNOFFICIAL_BASE.to_string()
114 } else {
115 self.mirror_base()
116 }
117 }
118}
119
120#[derive(Debug, Clone, PartialEq, Eq)]
124pub struct PinnedNode {
125 pub version: node_semver::Version,
126 pub variants: Vec<PinnedVariant>,
127}
128
129impl PinnedNode {
130 pub fn variant_for(&self, os: &str, cpu: &str, libc: Option<&str>) -> Option<&PinnedVariant> {
131 self.variants
132 .iter()
133 .find(|v| v.os == os && v.cpu == cpu && v.libc.as_deref() == libc)
134 }
135}
136
137#[derive(Debug, Clone, PartialEq, Eq)]
141pub struct PinnedVariant {
142 pub os: String,
143 pub cpu: String,
144 pub libc: Option<String>,
145 pub archive: String,
146 pub url: String,
147 pub integrity_sri: String,
148 pub bin: BTreeMap<String, String>,
149 pub prefix: Option<String>,
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155
156 #[test]
157 fn mirror_bases() {
158 let mut cfg = RuntimeConfig::new();
159 assert_eq!(cfg.mirror_base(), DEFAULT_MIRROR_BASE);
160 cfg.mirror = Some("https://npmmirror.com/mirrors/node/".to_string());
161 assert_eq!(cfg.mirror_base(), "https://npmmirror.com/mirrors/node");
162
163 let musl = Platform {
164 os: "linux".into(),
165 cpu: "x64".into(),
166 libc: Some("musl".into()),
167 };
168 assert_eq!(
170 cfg.artifact_base(&musl),
171 "https://npmmirror.com/mirrors/node"
172 );
173 cfg.mirror = None;
174 assert_eq!(cfg.artifact_base(&musl), UNOFFICIAL_BASE);
175 let glibc = Platform {
176 os: "linux".into(),
177 cpu: "x64".into(),
178 libc: None,
179 };
180 assert_eq!(cfg.artifact_base(&glibc), DEFAULT_MIRROR_BASE);
181 }
182}