651 lines
22 KiB
Plaintext
651 lines
22 KiB
Plaintext
|
|
#!/usr/bin/env nu
|
|||
|
|
|
|||
|
|
# Rustelo Prerequisites Verification
|
|||
|
|
# Verifies that all required tools are properly installed and working
|
|||
|
|
|
|||
|
|
def main [
|
|||
|
|
--verbose (-v) # Show detailed version information
|
|||
|
|
--fix-path # Attempt to fix PATH issues
|
|||
|
|
--format (-f): string = "human" # Output format: human, json, yaml, toml
|
|||
|
|
] {
|
|||
|
|
# Validate format parameter
|
|||
|
|
if $format not-in ["human", "json", "yaml", "toml"] {
|
|||
|
|
print $"Error: Invalid format '($format)'. Supported formats: human, json, yaml, toml"
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Collect all system and prerequisite information
|
|||
|
|
let system_info = if $verbose or $format != "human" {
|
|||
|
|
collect_system_info
|
|||
|
|
} else {
|
|||
|
|
{}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let rust_status = collect_rust_info $verbose
|
|||
|
|
let node_status = collect_node_info $verbose
|
|||
|
|
let nushell_status = collect_nushell_info $verbose
|
|||
|
|
let just_status = collect_just_info $verbose
|
|||
|
|
let additional_tools = collect_additional_tools_info $verbose
|
|||
|
|
|
|||
|
|
# Compile results
|
|||
|
|
let prerequisites = {
|
|||
|
|
rust: $rust_status,
|
|||
|
|
node: $node_status,
|
|||
|
|
nushell: $nushell_status,
|
|||
|
|
just: $just_status
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let all_required_ok = (
|
|||
|
|
$rust_status.installed and
|
|||
|
|
$node_status.installed and
|
|||
|
|
$nushell_status.installed and
|
|||
|
|
$just_status.installed
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
let issues = (
|
|||
|
|
[$rust_status, $node_status, $nushell_status, $just_status]
|
|||
|
|
| where not installed
|
|||
|
|
| get issue
|
|||
|
|
| where $it != null
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# Create comprehensive result object
|
|||
|
|
let result = {
|
|||
|
|
timestamp: (date now | format date '%Y-%m-%dT%H:%M:%S%.3fZ'),
|
|||
|
|
system: $system_info,
|
|||
|
|
prerequisites: $prerequisites,
|
|||
|
|
additional_tools: $additional_tools,
|
|||
|
|
summary: {
|
|||
|
|
all_prerequisites_met: $all_required_ok,
|
|||
|
|
total_issues: ($issues | length),
|
|||
|
|
issues: $issues
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Output in requested format
|
|||
|
|
match $format {
|
|||
|
|
"human" => { output_human $result $verbose $fix_path },
|
|||
|
|
"json" => { $result | to json },
|
|||
|
|
"yaml" => { $result | to yaml },
|
|||
|
|
"toml" => { $result | to toml }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Data collection functions for structured output
|
|||
|
|
def collect_system_info [] {
|
|||
|
|
let os_name = try {
|
|||
|
|
let uname_s = (^uname -s | str trim)
|
|||
|
|
match $uname_s {
|
|||
|
|
"Darwin" => "macOS",
|
|||
|
|
"Linux" => "Linux",
|
|||
|
|
"MINGW64_NT" => "Windows",
|
|||
|
|
_ => $uname_s
|
|||
|
|
}
|
|||
|
|
} catch {
|
|||
|
|
try { (sys host | get name) } catch { "unknown" }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let arch = try {
|
|||
|
|
let uname_m = (^uname -m | str trim)
|
|||
|
|
match $uname_m {
|
|||
|
|
"arm64" => "Apple Silicon (ARM64)",
|
|||
|
|
"x86_64" => "Intel x64",
|
|||
|
|
"aarch64" => "ARM64",
|
|||
|
|
_ => $uname_m
|
|||
|
|
}
|
|||
|
|
} catch {
|
|||
|
|
try { (sys host | get cpu | first | get brand) } catch { "unknown" }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let kernel = try {
|
|||
|
|
(^uname -r | str trim)
|
|||
|
|
} catch {
|
|||
|
|
try { (sys host | get kernel_version) } catch { "unknown" }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let detailed_os = if ($os_name == "macOS") {
|
|||
|
|
let version = try { (^sw_vers -productVersion | str trim) } catch { "" }
|
|||
|
|
let name = try { (^sw_vers -productName | str trim) } catch { "" }
|
|||
|
|
if ($version != "" and $name != "") {
|
|||
|
|
$"($name) ($version)"
|
|||
|
|
} else {
|
|||
|
|
$os_name
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
$os_name
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
os: $detailed_os,
|
|||
|
|
arch: $arch,
|
|||
|
|
kernel: $kernel,
|
|||
|
|
shell: ($env.SHELL? | default 'unknown')
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def collect_rust_info [verbose: bool] {
|
|||
|
|
if (which rustc | is-not-empty) and (which cargo | is-not-empty) {
|
|||
|
|
let rustc_version = try { (rustc --version | str trim) } catch { "unknown" }
|
|||
|
|
let cargo_version = try { (cargo --version | str trim) } catch { "unknown" }
|
|||
|
|
let toolchain = try { (rustup show active-toolchain | str trim) } catch { "unknown" }
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
installed: true,
|
|||
|
|
rustc_version: $rustc_version,
|
|||
|
|
cargo_version: $cargo_version,
|
|||
|
|
toolchain: $toolchain,
|
|||
|
|
issue: null
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
{
|
|||
|
|
installed: false,
|
|||
|
|
rustc_version: null,
|
|||
|
|
cargo_version: null,
|
|||
|
|
toolchain: null,
|
|||
|
|
issue: "Rust compiler (rustc) and Cargo not found. Install from https://rustup.rs/"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def collect_node_info [verbose: bool] {
|
|||
|
|
let node_ok = (which node | is-not-empty)
|
|||
|
|
let pnpm_ok = (which pnpm | is-not-empty)
|
|||
|
|
let npm_ok = (which npm | is-not-empty)
|
|||
|
|
|
|||
|
|
let node_version = if $node_ok { try { (node --version | str trim) } catch { null } } else { null }
|
|||
|
|
let pnpm_version = if $pnpm_ok { try { (pnpm --version | str trim) } catch { null } } else { null }
|
|||
|
|
let npm_version = if $npm_ok { try { (npm --version | str trim) } catch { null } } else { null }
|
|||
|
|
|
|||
|
|
if $node_ok and $pnpm_ok {
|
|||
|
|
{
|
|||
|
|
installed: true,
|
|||
|
|
node_version: $node_version,
|
|||
|
|
pnpm_version: $pnpm_version,
|
|||
|
|
npm_version: $npm_version,
|
|||
|
|
issue: null
|
|||
|
|
}
|
|||
|
|
} else if $node_ok and not $pnpm_ok {
|
|||
|
|
{
|
|||
|
|
installed: false,
|
|||
|
|
node_version: $node_version,
|
|||
|
|
pnpm_version: null,
|
|||
|
|
npm_version: $npm_version,
|
|||
|
|
issue: "pnpm package manager not found. Install with: npm install -g pnpm"
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
{
|
|||
|
|
installed: false,
|
|||
|
|
node_version: null,
|
|||
|
|
pnpm_version: null,
|
|||
|
|
npm_version: null,
|
|||
|
|
issue: "Node.js and pnpm not found. Install Node.js from https://nodejs.org/ then run: npm install -g pnpm"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def collect_nushell_info [verbose: bool] {
|
|||
|
|
if (which nu | is-not-empty) {
|
|||
|
|
let version = try { (nu --version | lines | first | str trim) } catch { "unknown" }
|
|||
|
|
let features = try { (nu -c "version | get features" | str join ", ") } catch { "unknown" }
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
installed: true,
|
|||
|
|
version: $version,
|
|||
|
|
features: $features,
|
|||
|
|
current_shell: ($env.SHELL? | default "unknown"),
|
|||
|
|
issue: null
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
{
|
|||
|
|
installed: false,
|
|||
|
|
version: null,
|
|||
|
|
features: null,
|
|||
|
|
current_shell: ($env.SHELL? | default "unknown"),
|
|||
|
|
issue: "Nushell shell not found. Install from https://github.com/nushell/nushell/releases or via package manager"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def collect_just_info [verbose: bool] {
|
|||
|
|
if (which just | is-not-empty) {
|
|||
|
|
let version = try { (just --version | str trim) } catch { "unknown" }
|
|||
|
|
let justfile_exists = ("justfile" | path exists) or ("Justfile" | path exists)
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
installed: true,
|
|||
|
|
version: $version,
|
|||
|
|
justfile_found: $justfile_exists,
|
|||
|
|
issue: null
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
{
|
|||
|
|
installed: false,
|
|||
|
|
version: null,
|
|||
|
|
justfile_found: false,
|
|||
|
|
issue: "Just command runner not found. Install with: cargo install just"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def collect_additional_tools_info [verbose: bool] {
|
|||
|
|
let tools = [
|
|||
|
|
{
|
|||
|
|
name: "git",
|
|||
|
|
installed: (which git | is-not-empty),
|
|||
|
|
version: (if (which git | is-not-empty) { try { (git --version | str replace "git version " "") } catch { "unknown" } } else { null })
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "sqlite",
|
|||
|
|
installed: (which sqlite3 | is-not-empty),
|
|||
|
|
version: (if (which sqlite3 | is-not-empty) { try { (sqlite3 --version | split row " " | first) } catch { "unknown" } } else { null })
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "docker",
|
|||
|
|
installed: (which docker | is-not-empty),
|
|||
|
|
version: (if (which docker | is-not-empty) { try { (docker --version | str replace "Docker version " "" | split row "," | first) } catch { "unknown" } } else { null })
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "vscode",
|
|||
|
|
installed: ((which code | is-not-empty) or ("/Applications/Visual Studio Code.app" | path exists)),
|
|||
|
|
version: (if (which code | is-not-empty) {
|
|||
|
|
try { (code --version | lines | first) } catch { "available" }
|
|||
|
|
} else if ("/Applications/Visual Studio Code.app" | path exists) {
|
|||
|
|
"installed (app bundle)"
|
|||
|
|
} else {
|
|||
|
|
null
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "zed",
|
|||
|
|
installed: ((which zed | is-not-empty) or ("/Applications/Zed.app" | path exists)),
|
|||
|
|
version: (if (which zed | is-not-empty) {
|
|||
|
|
try { (zed --version | str trim) } catch { "available" }
|
|||
|
|
} else if ("/Applications/Zed.app" | path exists) {
|
|||
|
|
"installed (app bundle)"
|
|||
|
|
} else {
|
|||
|
|
null
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "claude-code",
|
|||
|
|
installed: ((which claude-code | is-not-empty) or (which claude | is-not-empty) or ("/Applications/Claude.app" | path exists)),
|
|||
|
|
version: (if (which claude-code | is-not-empty) {
|
|||
|
|
try { (claude-code --version | str trim) } catch { "available" }
|
|||
|
|
} else if (which claude | is-not-empty) {
|
|||
|
|
try { (claude --version | str trim) } catch { "available" }
|
|||
|
|
} else if ("/Applications/Claude.app" | path exists) {
|
|||
|
|
"installed (app bundle)"
|
|||
|
|
} else {
|
|||
|
|
null
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "neovim",
|
|||
|
|
installed: (which nvim | is-not-empty),
|
|||
|
|
version: (if (which nvim | is-not-empty) { try { (nvim --version | lines | first | str replace "NVIM " "") } catch { "available" } } else { null })
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "gemini",
|
|||
|
|
installed: ((which gemini | is-not-empty) or ("/Applications/Gemini 2- The Duplicate Finder.app" | path exists)),
|
|||
|
|
version: (if (which gemini | is-not-empty) {
|
|||
|
|
try { (gemini --version | str trim) } catch { "available" }
|
|||
|
|
} else if ("/Applications/Gemini 2- The Duplicate Finder.app" | path exists) {
|
|||
|
|
"installed (app bundle)"
|
|||
|
|
} else { null })
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "codex",
|
|||
|
|
installed: (which codex | is-not-empty),
|
|||
|
|
version: (if (which codex | is-not-empty) { try { (codex --version | str trim) } catch { "available" } } else { null })
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
$tools
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def output_human [result: record, verbose: bool, fix_path: bool] {
|
|||
|
|
print "🔍 Verifying Rustelo Prerequisites..."
|
|||
|
|
print ""
|
|||
|
|
|
|||
|
|
# Show system information if verbose
|
|||
|
|
if $verbose and ($result.system | is-not-empty) {
|
|||
|
|
print ""
|
|||
|
|
print "💻 System Information:"
|
|||
|
|
print $" OS: ($result.system.os)"
|
|||
|
|
print $" Arch: ($result.system.arch)"
|
|||
|
|
print $" Kernel: ($result.system.kernel)"
|
|||
|
|
print $" Shell: ($result.system.shell)"
|
|||
|
|
print ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Show prerequisites
|
|||
|
|
let prereqs = $result.prerequisites
|
|||
|
|
|
|||
|
|
if $prereqs.rust.installed {
|
|||
|
|
print $"✅ Rust: ($prereqs.rust.rustc_version)"
|
|||
|
|
if $verbose {
|
|||
|
|
print $" Cargo: ($prereqs.rust.cargo_version)"
|
|||
|
|
print $" Toolchain: ($prereqs.rust.toolchain)"
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
print "❌ Rust: Not found"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if $prereqs.node.installed {
|
|||
|
|
print $"✅ Node.js: ($prereqs.node.node_version)"
|
|||
|
|
print $"✅ pnpm: ($prereqs.node.pnpm_version)"
|
|||
|
|
if $verbose and ($prereqs.node.npm_version != null) {
|
|||
|
|
print $" npm: ($prereqs.node.npm_version)"
|
|||
|
|
}
|
|||
|
|
} else if ($prereqs.node.node_version != null) {
|
|||
|
|
print $"✅ Node.js: ($prereqs.node.node_version)"
|
|||
|
|
print "❌ pnpm: Not found"
|
|||
|
|
} else {
|
|||
|
|
print "❌ Node.js: Not found"
|
|||
|
|
print "❌ pnpm: Not found"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if $prereqs.nushell.installed {
|
|||
|
|
print $"✅ Nushell: ($prereqs.nushell.version)"
|
|||
|
|
if $verbose {
|
|||
|
|
print $" Current shell: ($prereqs.nushell.current_shell)"
|
|||
|
|
print $" Features: ($prereqs.nushell.features)"
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
print "❌ Nushell: Not found"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if $prereqs.just.installed {
|
|||
|
|
print $"✅ Just: ($prereqs.just.version)"
|
|||
|
|
if $verbose and $prereqs.just.justfile_found {
|
|||
|
|
print " ✅ justfile found in current directory"
|
|||
|
|
} else if $verbose {
|
|||
|
|
print " ⚠️ No justfile found in current directory"
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
print "❌ Just: Not found"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Show additional tools
|
|||
|
|
print ""
|
|||
|
|
print "🔧 Additional Development Tools:"
|
|||
|
|
for tool in $result.additional_tools {
|
|||
|
|
if $tool.installed {
|
|||
|
|
match $tool.name {
|
|||
|
|
"vscode" => { print $"✅ VS Code: ($tool.version)" },
|
|||
|
|
"zed" => { print $"✅ Zed Editor: ($tool.version)" },
|
|||
|
|
"claude-code" => { print $"✅ Claude Code: ($tool.version)" },
|
|||
|
|
"neovim" => { print $"✅ Neovim: ($tool.version)" },
|
|||
|
|
"mvps" => { print $"✅ MVPS: ($tool.version)" },
|
|||
|
|
_ => { print $"✅ ($tool.name | str title-case): ($tool.version)" }
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
match $tool.name {
|
|||
|
|
"git" => { print "⚠️ Git: Not found (recommended for version control)" },
|
|||
|
|
"sqlite" => { print "⚠️ SQLite: Not found (useful for local database development)" },
|
|||
|
|
"docker" => { print "ℹ️ Docker: Not found (optional, for containerized deployment)" },
|
|||
|
|
"vscode" => { print "ℹ️ VS Code: Not found (popular code editor)" },
|
|||
|
|
"zed" => { print "ℹ️ Zed Editor: Not found (modern collaborative editor)" },
|
|||
|
|
"claude-code" => { print "ℹ️ Claude Code: Not found (AI-powered coding assistant)" },
|
|||
|
|
"neovim" => { print "ℹ️ Neovim: Not found (vim-based editor)" },
|
|||
|
|
"mvps" => { print "ℹ️ MVPS: Not found (development tool)" }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print ""
|
|||
|
|
|
|||
|
|
if $result.summary.all_prerequisites_met {
|
|||
|
|
print "✅ All prerequisites are properly installed!"
|
|||
|
|
print ""
|
|||
|
|
print "🚀 You're ready to create Rustelo projects:"
|
|||
|
|
print " rustelo new my-website"
|
|||
|
|
print " cd my-website"
|
|||
|
|
print " just dev"
|
|||
|
|
print ""
|
|||
|
|
} else {
|
|||
|
|
print "❌ Some prerequisites are missing or have issues:"
|
|||
|
|
print ""
|
|||
|
|
for issue in $result.summary.issues {
|
|||
|
|
print $" • ($issue)"
|
|||
|
|
}
|
|||
|
|
print ""
|
|||
|
|
print "🔧 To fix these issues:"
|
|||
|
|
print " nu scripts/install-prerequisites.nu"
|
|||
|
|
print ""
|
|||
|
|
if $fix_path {
|
|||
|
|
attempt_path_fix
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def check_rust [verbose: bool] {
|
|||
|
|
if (which rustc | is-not-empty) and (which cargo | is-not-empty) {
|
|||
|
|
let rustc_version = (rustc --version | str trim)
|
|||
|
|
let cargo_version = (cargo --version | str trim)
|
|||
|
|
|
|||
|
|
print $"✅ Rust: ($rustc_version)"
|
|||
|
|
if $verbose {
|
|||
|
|
print $" Cargo: ($cargo_version)"
|
|||
|
|
print $" Toolchain: (rustup show active-toolchain | str trim)"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
{ ok: true, issue: null }
|
|||
|
|
} else {
|
|||
|
|
print "❌ Rust: Not found"
|
|||
|
|
{ ok: false, issue: "Rust compiler (rustc) and Cargo not found. Install from https://rustup.rs/" }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def check_node [verbose: bool] {
|
|||
|
|
let node_ok = (which node | is-not-empty)
|
|||
|
|
let pnpm_ok = (which pnpm | is-not-empty)
|
|||
|
|
|
|||
|
|
if $node_ok and $pnpm_ok {
|
|||
|
|
let node_version = (node --version | str trim)
|
|||
|
|
let pnpm_version = (pnpm --version | str trim)
|
|||
|
|
|
|||
|
|
print $"✅ Node.js: ($node_version)"
|
|||
|
|
print $"✅ pnpm: ($pnpm_version)"
|
|||
|
|
|
|||
|
|
if $verbose {
|
|||
|
|
let npm_version = if (which npm | is-not-empty) { (npm --version | str trim) } else { "not found" }
|
|||
|
|
print $" npm: ($npm_version)"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
{ ok: true, issue: null }
|
|||
|
|
} else if $node_ok and not $pnpm_ok {
|
|||
|
|
let node_version = (node --version | str trim)
|
|||
|
|
print $"✅ Node.js: ($node_version)"
|
|||
|
|
print "❌ pnpm: Not found"
|
|||
|
|
{ ok: false, issue: "pnpm package manager not found. Install with: npm install -g pnpm" }
|
|||
|
|
} else {
|
|||
|
|
print "❌ Node.js: Not found"
|
|||
|
|
print "❌ pnpm: Not found"
|
|||
|
|
{ ok: false, issue: "Node.js and pnpm not found. Install Node.js from https://nodejs.org/ then run: npm install -g pnpm" }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def check_nushell [verbose: bool] {
|
|||
|
|
if (which nu | is-not-empty) {
|
|||
|
|
let version = (nu --version | lines | first | str trim)
|
|||
|
|
print $"✅ Nushell: ($version)"
|
|||
|
|
|
|||
|
|
if $verbose {
|
|||
|
|
# Check if current shell is nushell
|
|||
|
|
let current_shell = ($env.SHELL? | default "unknown")
|
|||
|
|
print $" Current shell: ($current_shell)"
|
|||
|
|
|
|||
|
|
# Check nushell features
|
|||
|
|
try {
|
|||
|
|
let features = (nu -c "version | get features" | str join ", ")
|
|||
|
|
print $" Features: ($features)"
|
|||
|
|
} catch {
|
|||
|
|
print " Features: Could not determine"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
{ ok: true, issue: null }
|
|||
|
|
} else {
|
|||
|
|
print "❌ Nushell: Not found"
|
|||
|
|
{ ok: false, issue: "Nushell shell not found. Install from https://github.com/nushell/nushell/releases or via package manager" }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def check_just [verbose: bool] {
|
|||
|
|
if (which just | is-not-empty) {
|
|||
|
|
let version = (just --version | str trim)
|
|||
|
|
print $"✅ Just: ($version)"
|
|||
|
|
|
|||
|
|
if $verbose {
|
|||
|
|
# Check if justfile exists in current directory
|
|||
|
|
if ("justfile" | path exists) {
|
|||
|
|
print " ✅ justfile found in current directory"
|
|||
|
|
} else if ("Justfile" | path exists) {
|
|||
|
|
print " ✅ Justfile found in current directory"
|
|||
|
|
} else {
|
|||
|
|
print " ⚠️ No justfile found in current directory"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
{ ok: true, issue: null }
|
|||
|
|
} else {
|
|||
|
|
print "❌ Just: Not found"
|
|||
|
|
{ ok: false, issue: "Just command runner not found. Install with: cargo install just" }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def check_additional_tools [verbose: bool] {
|
|||
|
|
print ""
|
|||
|
|
print "🔧 Additional Development Tools:"
|
|||
|
|
|
|||
|
|
# Git
|
|||
|
|
if (which git | is-not-empty) {
|
|||
|
|
let version = (git --version | str replace "git version " "")
|
|||
|
|
print $"✅ Git: ($version)"
|
|||
|
|
} else {
|
|||
|
|
print "⚠️ Git: Not found (recommended for version control)"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# SQLite (useful for local development)
|
|||
|
|
if (which sqlite3 | is-not-empty) {
|
|||
|
|
let version = (sqlite3 --version | split row " " | first)
|
|||
|
|
print $"✅ SQLite: ($version)"
|
|||
|
|
} else {
|
|||
|
|
print "⚠️ SQLite: Not found (useful for local database development)"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Docker (for containerized deployments)
|
|||
|
|
if (which docker | is-not-empty) {
|
|||
|
|
let version = (docker --version | str replace "Docker version " "" | split row "," | first)
|
|||
|
|
print $"✅ Docker: ($version)"
|
|||
|
|
} else {
|
|||
|
|
print "ℹ️ Docker: Not found (optional, for containerized deployment)"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# VS Code or other editors with Rust support
|
|||
|
|
if (which code | is-not-empty) {
|
|||
|
|
print "✅ VS Code: Available"
|
|||
|
|
} else if (which nvim | is-not-empty) {
|
|||
|
|
print "✅ Neovim: Available"
|
|||
|
|
} else if (which vim | is-not-empty) {
|
|||
|
|
print "✅ Vim: Available"
|
|||
|
|
} else {
|
|||
|
|
print "ℹ️ Editor: Consider installing VS Code with rust-analyzer extension"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def attempt_path_fix [] {
|
|||
|
|
print ""
|
|||
|
|
print "🔧 Attempting to fix PATH issues..."
|
|||
|
|
|
|||
|
|
let home = $env.HOME
|
|||
|
|
let cargo_bin = $"($home)/.cargo/bin"
|
|||
|
|
let local_bin = "/usr/local/bin"
|
|||
|
|
|
|||
|
|
# Check if cargo bin is in PATH
|
|||
|
|
if not ($env.PATH | split row ":" | any { |p| $p == $cargo_bin }) {
|
|||
|
|
print $"Adding ($cargo_bin) to PATH..."
|
|||
|
|
$env.PATH = ($env.PATH | split row ":" | append $cargo_bin | uniq)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Check if local bin is in PATH
|
|||
|
|
if not ($env.PATH | split row ":" | any { |p| $p == $local_bin }) {
|
|||
|
|
print $"Adding ($local_bin) to PATH..."
|
|||
|
|
$env.PATH = ($env.PATH | split row ":" | append $local_bin | uniq)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Suggest shell configuration updates
|
|||
|
|
print ""
|
|||
|
|
print "💡 To make PATH changes permanent, add these lines to your shell config:"
|
|||
|
|
print ""
|
|||
|
|
|
|||
|
|
let shell_config = match ($env.SHELL? | default "") {
|
|||
|
|
$path if ($path | str ends-with "zsh") => "~/.zshrc",
|
|||
|
|
$path if ($path | str ends-with "bash") => "~/.bashrc",
|
|||
|
|
$path if ($path | str ends-with "fish") => "~/.config/fish/config.fish",
|
|||
|
|
_ => "~/.bashrc"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print $" echo 'export PATH=\"$PATH:($cargo_bin):($local_bin)\"' >> ($shell_config)"
|
|||
|
|
print " source ($shell_config)"
|
|||
|
|
print ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Show system information if verbose
|
|||
|
|
def show_system_info [] {
|
|||
|
|
print ""
|
|||
|
|
print "💻 System Information:"
|
|||
|
|
|
|||
|
|
# Get system info properly for different platforms
|
|||
|
|
let os_name = try {
|
|||
|
|
let uname_s = (^uname -s | str trim)
|
|||
|
|
match $uname_s {
|
|||
|
|
"Darwin" => "macOS",
|
|||
|
|
"Linux" => "Linux",
|
|||
|
|
"MINGW64_NT" => "Windows",
|
|||
|
|
_ => $uname_s
|
|||
|
|
}
|
|||
|
|
} catch {
|
|||
|
|
try { (sys host | get name) } catch { "unknown" }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let arch = try {
|
|||
|
|
let uname_m = (^uname -m | str trim)
|
|||
|
|
match $uname_m {
|
|||
|
|
"arm64" => "Apple Silicon (ARM64)",
|
|||
|
|
"x86_64" => "Intel x64",
|
|||
|
|
"aarch64" => "ARM64",
|
|||
|
|
_ => $uname_m
|
|||
|
|
}
|
|||
|
|
} catch {
|
|||
|
|
try { (sys host | get cpu | first | get brand) } catch { "unknown" }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let kernel = try {
|
|||
|
|
(^uname -r | str trim)
|
|||
|
|
} catch {
|
|||
|
|
try { (sys host | get kernel_version) } catch { "unknown" }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Get more detailed OS info on macOS
|
|||
|
|
let detailed_os = if ($os_name == "macOS") {
|
|||
|
|
let version = try { (^sw_vers -productVersion | str trim) } catch { "" }
|
|||
|
|
let name = try { (^sw_vers -productName | str trim) } catch { "" }
|
|||
|
|
if ($version != "" and $name != "") {
|
|||
|
|
$"($name) ($version)"
|
|||
|
|
} else {
|
|||
|
|
$os_name
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
$os_name
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print $" OS: ($detailed_os)"
|
|||
|
|
print $" Arch: ($arch)"
|
|||
|
|
print $" Kernel: ($kernel)"
|
|||
|
|
print $" Shell: ($env.SHELL? | default 'unknown')"
|
|||
|
|
print ""
|
|||
|
|
}
|
|||
|
|
|