#!/usr/bin/env nu # Rustelo Prerequisites Installer # Installs Rust, Node.js/pnpm, Nushell, and Just for Rustelo development def main [ --skip-rust # Skip Rust installation --skip-node # Skip Node.js/pnpm installation --skip-nushell # Skip Nushell installation --skip-just # Skip Just installation --verbose (-v) # Verbose output ] { print "🚀 Installing Rustelo Prerequisites..." print "" let os_info = get_os_info if $verbose { print $"Detected OS: ($os_info.os) on ($os_info.arch)" print "" } # Install Rust if not $skip_rust { install_rust $os_info $verbose } # Install Node.js and pnpm if not $skip_node { install_node $os_info $verbose } # Install Nushell if not $skip_nushell { install_nushell $os_info $verbose } # Install Just if not $skip_just { install_just $os_info $verbose } print "" print "✅ Prerequisites installation complete!" print "" print "🎯 Next steps:" print " 1. Restart your terminal or run: source ~/.bashrc (or ~/.zshrc)" print " 2. Verify installations: nu scripts/verify-prerequisites.nu" print " 3. Create your first project: rustelo new my-website" print "" } def get_os_info [] { let os = (sys | get host.name) let arch = (sys | get host.cpu | first | get brand | str replace ".*" "unknown") if ($env.OS? | default "" | str contains "Windows") { { os: "windows", arch: "x86_64" } } else if (which uname | is-not-empty) { let uname_os = (uname -s) let uname_arch = (uname -m) match [$uname_os, $uname_arch] { ["Darwin", "x86_64"] => { os: "macos", arch: "x86_64" } ["Darwin", "arm64"] => { os: "macos", arch: "aarch64" } ["Linux", "x86_64"] => { os: "linux", arch: "x86_64" } ["Linux", "aarch64"] => { os: "linux", arch: "aarch64" } _ => { os: "linux", arch: "x86_64" } } } else { { os: "linux", arch: "x86_64" } } } def install_rust [os_info: record, verbose: bool] { print "📦 Installing Rust..." if (which rustc | is-not-empty) { let version = (rustc --version | str trim) print $" ✅ Rust already installed: ($version)" return } match $os_info.os { "windows" => { print " 🔽 Downloading Rust installer for Windows..." print " ⚠️ Please run the installer manually from: https://rustup.rs/" } _ => { print " 🔽 Installing Rust via rustup..." if $verbose { bash -c "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y" } else { bash -c "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y" | ignore } # Source the cargo env $env.PATH = ($env.PATH | split row ":" | append $"($env.HOME)/.cargo/bin" | uniq) } } print " ✅ Rust installation complete" } def install_node [os_info: record, verbose: bool] { print "📦 Installing Node.js and pnpm..." # Check if Node.js is already installed if (which node | is-not-empty) { let node_version = (node --version | str trim) print $" ✅ Node.js already installed: ($node_version)" # Check pnpm if (which pnpm | is-not-empty) { let pnpm_version = (pnpm --version | str trim) print $" ✅ pnpm already installed: ($pnpm_version)" return } } match $os_info.os { "macos" => { if (which brew | is-not-empty) { print " 🔽 Installing via Homebrew..." if $verbose { brew install node pnpm } else { brew install node pnpm | ignore } } else { print " ⚠️ Homebrew not found. Please install Node.js manually from: https://nodejs.org/" print " Then run: npm install -g pnpm" } } "linux" => { # Try different package managers if (which apt | is-not-empty) { print " 🔽 Installing via apt..." if $verbose { sudo apt update sudo apt install -y nodejs npm sudo npm install -g pnpm } else { sudo apt update | ignore sudo apt install -y nodejs npm | ignore sudo npm install -g pnpm | ignore } } else if (which dnf | is-not-empty) { print " 🔽 Installing via dnf..." if $verbose { sudo dnf install -y nodejs npm sudo npm install -g pnpm } else { sudo dnf install -y nodejs npm | ignore sudo npm install -g pnpm | ignore } } else if (which pacman | is-not-empty) { print " 🔽 Installing via pacman..." if $verbose { sudo pacman -S nodejs npm sudo npm install -g pnpm } else { sudo pacman -S nodejs npm | ignore sudo npm install -g pnpm | ignore } } else { print " ⚠️ Package manager not found. Please install Node.js manually from: https://nodejs.org/" print " Then run: npm install -g pnpm" } } "windows" => { if (which winget | is-not-empty) { print " 🔽 Installing via winget..." if $verbose { winget install OpenJS.NodeJS npm install -g pnpm } else { winget install OpenJS.NodeJS | ignore npm install -g pnpm | ignore } } else { print " ⚠️ winget not found. Please install Node.js manually from: https://nodejs.org/" print " Then run: npm install -g pnpm" } } } print " ✅ Node.js and pnpm installation complete" } def install_nushell [os_info: record, verbose: bool] { print "📦 Installing Nushell..." if (which nu | is-not-empty) { let version = (nu --version | str trim) print $" ✅ Nushell already installed: ($version)" return } match $os_info.os { "macos" => { if (which brew | is-not-empty) { print " 🔽 Installing via Homebrew..." if $verbose { brew install nushell } else { brew install nushell | ignore } } else { install_nushell_from_github $os_info $verbose } } "linux" => { # Try package managers first if (which cargo | is-not-empty) and (which apt | is-not-empty) { print " 🔽 Installing via cargo (recommended)..." if $verbose { cargo install nu --features=extra } else { cargo install nu --features=extra | ignore } } else { install_nushell_from_github $os_info $verbose } } "windows" => { if (which winget | is-not-empty) { print " 🔽 Installing via winget..." if $verbose { winget install nushell.nushell } else { winget install nushell.nushell | ignore } } else if (which cargo | is-not-empty) { print " 🔽 Installing via cargo..." if $verbose { cargo install nu --features=extra } else { cargo install nu --features=extra | ignore } } else { print " ⚠️ Please install Nushell manually from: https://github.com/nushell/nushell/releases" } } } print " ✅ Nushell installation complete" } def install_nushell_from_github [os_info: record, verbose: bool] { print " 🔽 Installing from GitHub releases..." let arch_map = { "x86_64": "x86_64", "aarch64": "aarch64", "arm64": "aarch64" } let os_map = { "linux": "unknown-linux-gnu", "macos": "apple-darwin", "windows": "pc-windows-msvc" } let arch = ($arch_map | get ($os_info.arch | default "x86_64")) let os_suffix = ($os_map | get ($os_info.os | default "linux")) let extension = if ($os_info.os == "windows") { "zip" } else { "tar.gz" } let filename = $"nu-0.88.1-($arch)-($os_suffix).($extension)" let url = $"https://github.com/nushell/nushell/releases/download/0.88.1/($filename)" print $" 📥 Downloading: ($filename)" try { if ($os_info.os == "windows") { # Windows ZIP extraction curl -fsSL $url -o $"/tmp/($filename)" # Manual extraction needed on Windows print " ⚠️ Please extract the downloaded file and add nu.exe to your PATH" } else { # Unix tar.gz extraction let extract_cmd = $"curl -fsSL ($url) | tar -xz && sudo mv nu* /usr/local/bin/" if $verbose { bash -c $extract_cmd } else { bash -c $extract_cmd | ignore } } } catch { print " ❌ Failed to download Nushell. Please install manually from:" print " https://github.com/nushell/nushell/releases" } } def install_just [os_info: record, verbose: bool] { print "📦 Installing Just..." if (which just | is-not-empty) { let version = (just --version | str trim) print $" ✅ Just already installed: ($version)" return } match $os_info.os { "macos" => { if (which brew | is-not-empty) { print " 🔽 Installing via Homebrew..." if $verbose { brew install just } else { brew install just | ignore } } else if (which cargo | is-not-empty) { print " 🔽 Installing via cargo..." if $verbose { cargo install just } else { cargo install just | ignore } } } "linux" => { if (which cargo | is-not-empty) { print " 🔽 Installing via cargo..." if $verbose { cargo install just } else { cargo install just | ignore } } else { install_just_from_github $os_info $verbose } } "windows" => { if (which cargo | is-not-empty) { print " 🔽 Installing via cargo..." if $verbose { cargo install just } else { cargo install just | ignore } } else { print " ⚠️ Please install Just manually: cargo install just" print " Or download from: https://github.com/casey/just/releases" } } } print " ✅ Just installation complete" } def install_just_from_github [os_info: record, verbose: bool] { print " 🔽 Installing from GitHub releases..." let arch = match $os_info.arch { "aarch64" => "aarch64", "arm64" => "aarch64", _ => "x86_64" } let os_suffix = match $os_info.os { "linux" => "unknown-linux-musl", "macos" => "apple-darwin", _ => "unknown-linux-musl" } let filename = $"just-1.16.0-($arch)-($os_suffix).tar.gz" let url = $"https://github.com/casey/just/releases/download/1.16.0/($filename)" try { let extract_cmd = $"curl -fsSL ($url) | tar -xz && sudo mv just /usr/local/bin/" if $verbose { bash -c $extract_cmd } else { bash -c $extract_cmd | ignore } } catch { print " ❌ Failed to download Just. Please install via cargo: cargo install just" } } # Run the installer main