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