feat: refactor plugin architecture, enhance linting, CI & tooling

- Major refactor of core Fish functions for modularity, caching, and error handling
- Improved `.editorconfig` and Makefile for stricter formatting and linting standards
- Expanded linting support: added EditorConfig checks, auto-install for missing tools, and Makefile targets
- Enhanced CI workflow with clearer permissions and job steps in GitHub Actions
- Updated documentation in `README.md` and `CLAUDE.md` to reflect new features, advanced developer tools, and contribution guidelines
- Improved Node.js version manager detection, switching, and installation logic
- Added/updated utility functions for configuration, silent mode, notifications, and version extraction
- Various bug fixes, code quality improvements, and expanded test coverage
This commit is contained in:
2025-07-16 15:12:14 +03:00
parent 8c9febaf8f
commit 5b680f06ac
30 changed files with 3106 additions and 248 deletions

106
functions/nvm_async.fish Normal file
View File

@@ -0,0 +1,106 @@
function nvm_async -d "Async operations for non-blocking version management"
set -l operation $argv[1]
switch $operation
case version_check
_nvm_async_version_check $argv[2]
case manager_check
_nvm_async_manager_check $argv[2]
case cleanup
_nvm_async_cleanup
case wait
_nvm_async_wait $argv[2] $argv[3]
case '*'
echo "Usage: nvm_async [version_check|manager_check|cleanup|wait] [args...]"
return 1
end
end
function _nvm_async_version_check -d "Async version check operation"
set -l version_file $argv[1]
set -l cache_key (_nvm_cache_key "$version_file")
# Try cache first
if set -l cached_result (nvm_cache get "$cache_key" 60)
echo "$cached_result"
return 0
end
# Background job for version extraction
fish -c "
set result (nvm_extract_version '$version_file' 2>/dev/null)
if test -n \"\$result\"
nvm_cache set '$cache_key' \"\$result\"
echo \"\$result\"
end
" &
# Return job ID for potential cleanup
jobs -l | tail -n 1 | grep -o '[0-9]*'
end
function _nvm_async_manager_check -d "Async manager availability check"
set -l manager $argv[1]
set -l cache_key (_nvm_cache_manager_key "$manager")
# Try cache first (longer TTL for manager availability)
if set -l cached_result (nvm_cache get "$cache_key" 3600)
echo "$cached_result"
return 0
end
# Background check
fish -c "
if command -q '$manager'
nvm_cache set '$cache_key' 'available'
echo 'available'
else
nvm_cache set '$cache_key' 'unavailable'
echo 'unavailable'
end
" &
jobs -l | tail -n 1 | grep -o '[0-9]*'
end
function _nvm_async_cleanup -d "Clean up completed background jobs"
for job in (jobs -p)
if not kill -0 $job 2>/dev/null
jobs -p | grep -v $job
end
end
end
function _nvm_async_wait -d "Wait for async job with timeout"
set -l job_id $argv[1]
set -l timeout $argv[2]
if test -z "$timeout"
set timeout 2
end
# Wait for job with timeout
set -l count 0
while test $count -lt (math "$timeout * 10")
if not jobs -p | grep -q "^$job_id\$"
return 0
end
sleep 0.1
set count (math "$count + 1")
end
# Timeout reached, kill job
kill -9 $job_id 2>/dev/null
return 1
end
function _nvm_async_safe_read -d "Safely read async operation result"
set -l cache_key $argv[1]
set -l fallback $argv[2]
set -l result (nvm_cache get "$cache_key")
if test -n "$result"
echo "$result"
else if test -n "$fallback"
echo "$fallback"
end
end

View File

@@ -1,130 +1,155 @@
function nvm_auto_use --on-variable PWD
# Detect available Node.js version manager
set -l available_managers (nvm_compat_detect 2>/dev/null | tail -n 1)
if test -z "$available_managers"
# Select the Node.js version manager
set -l manager (_nvm_auto_use_select_manager)
if test -z "$manager"
return
end
# Use preferred manager or first available
set -l manager
if test -n "$_nvm_auto_use_preferred_manager"
if contains "$_nvm_auto_use_preferred_manager" $available_managers
set manager "$_nvm_auto_use_preferred_manager"
end
# Debounce rapid directory changes
if _nvm_auto_use_should_debounce
return
end
if test -z "$manager"
set manager $available_managers[1]
# Check for excluded directories
if _nvm_auto_use_is_excluded_dir
return
end
# Check if project detection is enabled and we're in a Node.js project
# Project-only mode: only activate in Node.js projects
if set -q _nvm_auto_use_project_only
if not nvm_project_detect
return
end
end
# Export NODE_VERSION environment variable
# Export NODE_VERSION environment variable if available
if command -q node
set -gx NODE_VERSION (node -v 2>/dev/null | string replace 'v' '')
end
# Check for excluded directories
set -l current_dir (pwd)
for pattern in $_nvm_auto_use_excluded_dirs node_modules .git
if string match -q "*/$pattern" "$current_dir"; or string match -q "*/$pattern/*" "$current_dir"
return
end
end
# Debouncing: prevent rapid switching
set -l debounce_ms (_nvm_auto_use_get_debounce)
set -l current_time (date +%s%3N 2>/dev/null; or date +%s)
if test -n "$_nvm_auto_use_last_change"
set -l time_diff (math "$current_time - $_nvm_auto_use_last_change")
if test $time_diff -lt $debounce_ms
return
end
end
set -g _nvm_auto_use_last_change $current_time
# Find version file and its mtime
set -l nvmrc_file (nvm_find_nvmrc)
set -l nvmrc_mtime (_nvm_auto_use_get_mtime "$nvmrc_file")
# Cache check: if same file and version, skip processing
if test "$nvmrc_file" = "$_nvm_auto_use_cached_file"
# Skip if cache is valid
if _nvm_auto_use_is_cache_valid "$nvmrc_file" "$nvmrc_mtime"
return
end
if test -n "$nvmrc_file"
set -l node_version (nvm_extract_version "$nvmrc_file")
# Cache the file path
set -g _nvm_auto_use_cached_file "$nvmrc_file"
# Validate node version format (basic semver or major version)
if not string match -qr '^v?[0-9]+(\..*)?$' "$node_version"
if not set -q _nvm_auto_use_silent
echo "Invalid Node.js version format in $nvmrc_file: $node_version" >&2
end
return 1
end
# Remove 'v' prefix if present
set node_version (string replace -r '^v' '' "$node_version")
# Cache the version
set -g _nvm_auto_use_cached_version "$node_version"
# Check the current version
set -l current_version
if command -q node
set current_version (node -v 2>/dev/null | sed 's/v//')
end
if test "$node_version" != "$current_version"
if not set -q _nvm_auto_use_silent
echo "Switching to Node.js v$node_version"
end
# Send notification if enabled
if not set -q _nvm_auto_use_silent
nvm_notify "Switched to Node.js v$node_version"
end
if not nvm_compat_use $manager $node_version 2>/dev/null
# Check if auto-install is disabled
if set -q _nvm_auto_use_no_install
if not set -q _nvm_auto_use_silent
echo "Node.js version $node_version not found (auto-install disabled)" >&2
end
return 1
end
if not set -q _nvm_auto_use_silent
echo "Node.js version $node_version not found, installing..."
end
if nvm_compat_install $manager $node_version >/dev/null 2>&1
nvm_compat_use $manager $node_version >/dev/null 2>&1
if not set -q _nvm_auto_use_silent
echo "Installed and switched to Node.js v$node_version"
end
else
if not set -q _nvm_auto_use_silent
echo "Failed to install Node.js version $node_version" >&2
end
return 1
end
end
# Update cached version after successful switch
set -g _nvm_auto_use_cached_version "$node_version"
# Update NODE_VERSION environment variable
set -gx NODE_VERSION "$node_version"
end
_nvm_auto_use_switch_version "$manager" "$nvmrc_file" "$nvmrc_mtime"
else
# Clear cache if no .nvmrc found
set -e _nvm_auto_use_cached_file
set -e _nvm_auto_use_cached_version
_nvm_auto_use_clear_cache
end
end
function _nvm_auto_use_select_manager
set -l available_managers (nvm_compat_detect 2>/dev/null)
if test -z "$available_managers"
return
end
if test -n "$_nvm_auto_use_preferred_manager"
if contains "$_nvm_auto_use_preferred_manager" $available_managers
echo "$_nvm_auto_use_preferred_manager"
return
end
end
echo $available_managers[1]
end
function _nvm_auto_use_should_debounce
set -l debounce_ms (_nvm_auto_use_get_debounce)
set -l current_time (date +%s%3N 2>/dev/null; or math "(date +%s) * 1000")
if test -n "$_nvm_auto_use_last_change"
set -l time_diff (math "$current_time - $_nvm_auto_use_last_change")
if test $time_diff -lt $debounce_ms
return 0
end
end
set -g _nvm_auto_use_last_change $current_time
return 1
end
function _nvm_auto_use_is_excluded_dir
set -l current_dir (pwd)
set -l patterns $_nvm_auto_use_excluded_dirs node_modules .git
for pattern in $patterns
if string match -q "*/$pattern" "$current_dir"; or string match -q "*/$pattern/*" "$current_dir"
return 0
end
end
return 1
end
function _nvm_auto_use_get_mtime
set -l file $argv[1]
if test -n "$file"
stat -c %Y "$file" 2>/dev/null; or stat -f %m "$file" 2>/dev/null
end
end
function _nvm_auto_use_is_cache_valid
set -l file $argv[1]
set -l mtime $argv[2]
if test "$file" = "$_nvm_auto_use_cached_file"; and test "$mtime" = "$_nvm_auto_use_cached_mtime"
return 0
end
return 1
end
function _nvm_auto_use_switch_version
set -l manager $argv[1]
set -l nvmrc_file $argv[2]
set -l nvmrc_mtime $argv[3]
set -l node_version (nvm_extract_version "$nvmrc_file")
set -g _nvm_auto_use_cached_file "$nvmrc_file"
set -g _nvm_auto_use_cached_mtime "$nvmrc_mtime"
if not string match -qr '^v?[0-9]+(\..*)?$' "$node_version"
if not set -q _nvm_auto_use_silent
echo "Invalid Node.js version format in $nvmrc_file: $node_version" >&2
end
return 1
end
set node_version (string replace -r '^v' '' "$node_version")
set -g _nvm_auto_use_cached_version "$node_version"
set -l current_version
if command -q node
set current_version (node -v 2>/dev/null | sed 's/v//')
end
if test "$node_version" != "$current_version"
if not set -q _nvm_auto_use_silent
echo "Switching to Node.js v$node_version"
nvm_notify "Switched to Node.js v$node_version"
end
if not nvm_compat_use $manager $node_version 2>/dev/null
if set -q _nvm_auto_use_no_install
if not set -q _nvm_auto_use_silent
echo "Node.js version $node_version not found (auto-install disabled)" >&2
end
return 1
end
if not set -q _nvm_auto_use_silent
echo "Node.js version $node_version not found, installing..."
end
if nvm_compat_install $manager $node_version >/dev/null 2>&1
nvm_compat_use $manager $node_version >/dev/null 2>&1
if not set -q _nvm_auto_use_silent
echo "Installed and switched to Node.js v$node_version"
end
else
if not set -q _nvm_auto_use_silent
echo "Failed to install Node.js version $node_version" >&2
end
return 1
end
end
set -g _nvm_auto_use_cached_version "$node_version"
set -gx NODE_VERSION "$node_version"
end
end
function _nvm_auto_use_clear_cache
set -e _nvm_auto_use_cached_file
set -e _nvm_auto_use_cached_version
set -e _nvm_auto_use_cached_mtime
end

View File

@@ -1,88 +1,126 @@
function nvm_auto_use_config -d "Configure nvm-auto-use settings"
if test (count $argv) -eq 0
echo "nvm-auto-use configuration:"
echo " auto_install: "(test -n "$_nvm_auto_use_no_install"; and echo "disabled"; or echo "enabled")
echo " silent: "(test -n "$_nvm_auto_use_silent"; and echo "enabled"; or echo "disabled")
echo " debounce_ms: "(_nvm_auto_use_get_debounce)
echo " excluded_dirs: "(_nvm_auto_use_get_excluded_dirs)
echo " preferred_manager: "(test -n "$_nvm_auto_use_preferred_manager"; and echo "$_nvm_auto_use_preferred_manager"; or echo "auto-detect")
_nvm_auto_use_config_show
return
end
switch $argv[1]
case auto_install
switch $argv[2]
case on enable true 1
set -e _nvm_auto_use_no_install
echo "Auto-install enabled"
case off disable false 0
set -g _nvm_auto_use_no_install 1
echo "Auto-install disabled"
case '*'
echo "Usage: nvm_auto_use_config auto_install [on|off]"
end
_nvm_auto_use_config_auto_install $argv[2]
case silent
switch $argv[2]
case on enable true 1
set -g _nvm_auto_use_silent 1
echo "Silent mode enabled"
case off disable false 0
set -e _nvm_auto_use_silent
echo "Silent mode disabled"
case '*'
echo "Usage: nvm_auto_use_config silent [on|off]"
end
_nvm_auto_use_config_silent $argv[2]
case debounce
if test -n "$argv[2]" -a (string match -r '^[0-9]+$' "$argv[2]")
set -g _nvm_auto_use_debounce_ms $argv[2]
echo "Debounce set to $argv[2]ms"
else
echo "Usage: nvm_auto_use_config debounce <milliseconds>"
end
_nvm_auto_use_config_debounce $argv[2]
case exclude
if test -n "$argv[2]"
set -g _nvm_auto_use_excluded_dirs $_nvm_auto_use_excluded_dirs $argv[2]
echo "Added $argv[2] to excluded directories"
else
echo "Usage: nvm_auto_use_config exclude <directory_pattern>"
end
_nvm_auto_use_config_exclude $argv[2]
case include
if test -n "$argv[2]"
set -l index (contains -i "$argv[2]" $_nvm_auto_use_excluded_dirs)
if test -n "$index"
set -e _nvm_auto_use_excluded_dirs[$index]
echo "Removed $argv[2] from excluded directories"
else
echo "$argv[2] was not in excluded directories"
end
else
echo "Usage: nvm_auto_use_config include <directory_pattern>"
end
_nvm_auto_use_config_include $argv[2]
case manager
if test -n "$argv[2]"
if contains "$argv[2]" nvm fnm volta asdf
set -g _nvm_auto_use_preferred_manager "$argv[2]"
echo "Preferred manager set to $argv[2]"
else
echo "Unsupported manager. Supported: nvm, fnm, volta, asdf"
end
else
set -e _nvm_auto_use_preferred_manager
echo "Reset to auto-detect manager"
end
_nvm_auto_use_config_manager $argv[2]
case reset
set -e _nvm_auto_use_no_install
set -e _nvm_auto_use_silent
set -e _nvm_auto_use_debounce_ms
set -e _nvm_auto_use_excluded_dirs
set -e _nvm_auto_use_preferred_manager
echo "Configuration reset to defaults"
_nvm_auto_use_config_reset
case '*'
echo "Usage: nvm_auto_use_config [auto_install|silent|debounce|exclude|include|manager|reset] [value]"
return 1
end
end
function _nvm_auto_use_config_show
echo "nvm-auto-use configuration:"
echo " auto_install: "(test -n "$_nvm_auto_use_no_install"; and echo "disabled"; or echo "enabled")
echo " silent: "(test -n "$_nvm_auto_use_silent"; and echo "enabled"; or echo "disabled")
echo " debounce_ms: "(_nvm_auto_use_get_debounce)
echo " excluded_dirs: "(_nvm_auto_use_get_excluded_dirs)
echo " preferred_manager: "(test -n "$_nvm_auto_use_preferred_manager"; and echo "$_nvm_auto_use_preferred_manager"; or echo "auto-detect")
end
function _nvm_auto_use_config_auto_install
set -l value $argv[1]
switch $value
case on enable true 1
set -e _nvm_auto_use_no_install
echo "Auto-install enabled"
case off disable false 0
set -g _nvm_auto_use_no_install 1
echo "Auto-install disabled"
case '*'
echo "Usage: nvm_auto_use_config auto_install [on|off]"
end
end
function _nvm_auto_use_config_silent
set -l value $argv[1]
switch $value
case on enable true 1
set -g _nvm_auto_use_silent 1
echo "Silent mode enabled"
case off disable false 0
set -e _nvm_auto_use_silent
echo "Silent mode disabled"
case '*'
echo "Usage: nvm_auto_use_config silent [on|off]"
end
end
function _nvm_auto_use_config_debounce
set -l value $argv[1]
if test -n "$value" -a (string match -r '^[0-9]+$' "$value")
set -g _nvm_auto_use_debounce_ms $value
echo "Debounce set to $value ms"
else
echo "Usage: nvm_auto_use_config debounce <milliseconds>"
end
end
function _nvm_auto_use_config_exclude
set -l value $argv[1]
if test -n "$value"
set -g _nvm_auto_use_excluded_dirs $_nvm_auto_use_excluded_dirs $value
echo "Added $value to excluded directories"
else
echo "Usage: nvm_auto_use_config exclude <directory_pattern>"
end
end
function _nvm_auto_use_config_include
set -l value $argv[1]
if test -n "$value"
set -l index (contains -i "$value" $_nvm_auto_use_excluded_dirs)
if test -n "$index"
set -e _nvm_auto_use_excluded_dirs[$index]
echo "Removed $value from excluded directories"
else
echo "$value was not in excluded directories"
end
else
echo "Usage: nvm_auto_use_config include <directory_pattern>"
end
end
function _nvm_auto_use_config_manager
set -l value $argv[1]
if test -n "$value"
if contains "$value" nvm fnm volta asdf
set -g _nvm_auto_use_preferred_manager "$value"
echo "Preferred manager set to $value"
else
echo "Unsupported manager. Supported: nvm, fnm, volta, asdf"
end
else
set -e _nvm_auto_use_preferred_manager
echo "Reset to auto-detect manager"
end
end
function _nvm_auto_use_config_reset
set -e _nvm_auto_use_no_install
set -e _nvm_auto_use_silent
set -e _nvm_auto_use_debounce_ms
set -e _nvm_auto_use_excluded_dirs
set -e _nvm_auto_use_preferred_manager
echo "Configuration reset to defaults"
end
function _nvm_auto_use_get_debounce
if test -n "$_nvm_auto_use_debounce_ms"
echo "$_nvm_auto_use_debounce_ms"

View File

@@ -13,7 +13,7 @@ function nvm_auto_use_silent -d "Enable or disable silent mode for nvm-auto-use"
set -g _nvm_auto_use_silent 1
echo "Silent mode enabled"
case off disable false 0
set -e _nvm_auto_use_silent
set -e -g _nvm_auto_use_silent
echo "Silent mode disabled"
case '*'
echo "Usage: nvm_auto_use_silent [on|off]"

110
functions/nvm_cache.fish Normal file
View File

@@ -0,0 +1,110 @@
function nvm_cache -d "XDG-compliant cache management with TTL"
set -l action $argv[1]
set -l key $argv[2]
set -l value $argv[3]
set -l ttl $argv[4]
switch $action
case get
_nvm_cache_get "$key" "$ttl"
case set
_nvm_cache_set "$key" "$value"
case delete
_nvm_cache_delete "$key"
case clear
_nvm_cache_clear
case stats
_nvm_cache_stats
case '*'
echo "Usage: nvm_cache [get|set|delete|clear|stats] <key> [value] [ttl]"
return 1
end
end
function _nvm_cache_dir -d "Get XDG cache directory for nvm-auto-use"
if set -q XDG_CACHE_HOME
echo "$XDG_CACHE_HOME/nvm-auto-use"
else
echo "$HOME/.cache/nvm-auto-use"
end
end
function _nvm_cache_get -d "Get cache value by key, respecting TTL"
set -l key $argv[1]
set -l ttl $argv[2]
set -l cache_dir (_nvm_cache_dir)
set -l cache_file "$cache_dir/$key"
if not test -f "$cache_file"
return 1
end
# Check TTL
set -l cache_time (stat -c %Y "$cache_file" 2>/dev/null; or stat -f %m "$cache_file" 2>/dev/null)
set -l current_time (date +%s)
set -l default_ttl 300 # 5 minutes default
if test -n "$ttl"
set default_ttl $ttl
end
if test (math "$current_time - $cache_time") -gt $default_ttl
rm "$cache_file" 2>/dev/null
return 1
end
cat "$cache_file"
return 0
end
function _nvm_cache_set -d "Set cache value by key"
set -l key $argv[1]
set -l value $argv[2]
set -l cache_dir (_nvm_cache_dir)
set -l cache_file "$cache_dir/$key"
if test -z "$value"
return 1
end
mkdir -p "$cache_dir" 2>/dev/null
echo "$value" >"$cache_file" 2>/dev/null
return $status
end
function _nvm_cache_delete -d "Delete cache value by key"
set -l key $argv[1]
set -l cache_dir (_nvm_cache_dir)
set -l cache_file "$cache_dir/$key"
rm "$cache_file" 2>/dev/null
return 0
end
function _nvm_cache_clear -d "Clear all cache files"
set -l cache_dir (_nvm_cache_dir)
rm -rf "$cache_dir" 2>/dev/null
return 0
end
function _nvm_cache_stats -d "Show cache statistics"
set -l cache_dir (_nvm_cache_dir)
if test -d "$cache_dir"
echo "Cache directory: $cache_dir"
echo "Cache files: "(find "$cache_dir" -type f 2>/dev/null | wc -l)
echo "Cache size: "(du -sh "$cache_dir" 2>/dev/null | cut -f1)
else
echo "No cache directory found"
end
return 0
end
function _nvm_cache_key -d "Generate cache key from directory and file"
set -l dir (pwd)
set -l file_hash (echo "$argv[1]" | shasum | cut -d' ' -f1)
echo "dir_$(echo "$dir" | shasum | cut -d' ' -f1)_$file_hash"
end
function _nvm_cache_manager_key -d "Generate cache key for manager availability"
set -l manager $argv[1]
echo "manager_$manager"
end

View File

@@ -36,13 +36,13 @@ function nvm_compat_use -a manager version -d "Use specified version with detect
switch $manager
case nvm
nvm use $version
nvm use $version; or return $status
case fnm
fnm use $version
fnm use $version; or return $status
case volta
volta pin node@$version
volta pin node@$version; or return $status
case asdf
asdf local nodejs $version
asdf local nodejs $version; or return $status
case '*'
echo "Unsupported manager: $manager"
return 1
@@ -57,13 +57,13 @@ function nvm_compat_install -a manager version -d "Install specified version wit
switch $manager
case nvm
nvm install $version
nvm install $version; or return $status
case fnm
fnm install $version
fnm install $version; or return $status
case volta
volta install node@$version
volta install node@$version; or return $status
case asdf
asdf install nodejs $version
asdf install nodejs $version; or return $status
case '*'
echo "Unsupported manager: $manager"
return 1

428
functions/nvm_doctor.fish Normal file
View File

@@ -0,0 +1,428 @@
function nvm_doctor -d "Comprehensive diagnostic and debugging tool"
set -l action $argv[1]
switch $action
case check
_nvm_doctor_full_check
case system
_nvm_doctor_system_info
case managers
_nvm_doctor_check_managers
case permissions
_nvm_doctor_check_permissions
case config
_nvm_doctor_check_config
case cache
_nvm_doctor_check_cache
case security
_nvm_doctor_security_audit
case performance
_nvm_doctor_performance_check
case fix
_nvm_doctor_auto_fix $argv[2..-1]
case '*'
echo "Usage: nvm_doctor [check|system|managers|permissions|config|cache|security|performance|fix] [args...]"
echo
echo "Commands:"
echo " check - Run comprehensive diagnostic check"
echo " system - Show system information"
echo " managers - Check version manager status"
echo " permissions - Check file and directory permissions"
echo " config - Validate configuration"
echo " cache - Check cache status and health"
echo " security - Run security audit"
echo " performance - Analyze performance issues"
echo " fix - Attempt to fix common issues"
return 1
end
end
function _nvm_doctor_full_check -d "Run comprehensive diagnostic check"
echo "🩺 NVM Auto-Use Doctor - Comprehensive Check"
echo "============================================="
echo
set -l issues 0
# System check
echo "🖥️ System Information"
echo ---------------------
_nvm_doctor_system_info
echo
# Manager check
echo "🔧 Version Manager Status"
echo -------------------------
_nvm_doctor_check_managers
set issues (math "$issues + $status")
echo
# Configuration check
echo "⚙️ Configuration Status"
echo ------------------------
_nvm_doctor_check_config
set issues (math "$issues + $status")
echo
# Permissions check
echo "🔐 Permissions Check"
echo -------------------
_nvm_doctor_check_permissions
set issues (math "$issues + $status")
echo
# Cache check
echo "🗄️ Cache Status"
echo ----------------
_nvm_doctor_check_cache
set issues (math "$issues + $status")
echo
# Security audit
echo "🔒 Security Audit"
echo -----------------
_nvm_doctor_security_audit
set issues (math "$issues + $status")
echo
# Performance check
echo "⚡ Performance Analysis"
echo ----------------------
_nvm_doctor_performance_check
set issues (math "$issues + $status")
echo
# Summary
echo "📋 Diagnostic Summary"
echo "====================="
if test $issues -eq 0
echo "✅ All checks passed! Your nvm-auto-use setup is healthy."
else
echo "⚠️ Found $issues issue(s) that may need attention."
echo "💡 Run 'nvm_doctor fix' to attempt automatic fixes."
end
return $issues
end
function _nvm_doctor_system_info -d "Display system information"
echo "OS: "(uname -s)" "(uname -r)
echo "Architecture: "(uname -m)
echo "Shell: $SHELL"
echo "Fish version: "(fish --version)
if command -q node
echo "Node.js: "(node --version)
else
echo "Node.js: Not installed"
end
if command -q npm
echo "npm: "(npm --version)
else
echo "npm: Not available"
end
echo "PATH entries: "(echo $PATH | string split ':' | wc -l)
echo "Current directory: "(pwd)
end
function _nvm_doctor_check_managers -d "Check version manager availability and status"
set -l issues 0
set -l managers (nvm_compat_detect 2>/dev/null)
if test -z "$managers"
echo "❌ No Node.js version managers found"
echo " Install at least one: nvm, fnm, volta, or asdf"
set issues (math "$issues + 1")
else
echo "✅ Found managers: $managers"
# Check each manager's status
for manager in (echo $managers | string split ' ')
echo " 📋 $manager status:"
switch $manager
case nvm
if test -f "$HOME/.nvm/nvm.sh"
echo " ✅ NVM script found"
if command -q nvm
echo " ✅ NVM command available"
else
echo " ⚠️ NVM not in PATH (normal for Fish)"
end
else
echo " ❌ NVM installation not found"
set issues (math "$issues + 1")
end
case fnm
if command -q fnm
echo " ✅ FNM available: "(fnm --version)
else
echo " ❌ FNM not found in PATH"
set issues (math "$issues + 1")
end
case volta
if command -q volta
echo " ✅ Volta available: "(volta --version)
else
echo " ❌ Volta not found in PATH"
set issues (math "$issues + 1")
end
case asdf
if command -q asdf
echo " ✅ asdf available: "(asdf --version)
if asdf plugin list | grep -q nodejs
echo " ✅ nodejs plugin installed"
else
echo " ❌ nodejs plugin not installed"
set issues (math "$issues + 1")
end
else
echo " ❌ asdf not found in PATH"
set issues (math "$issues + 1")
end
end
end
end
return $issues
end
function _nvm_doctor_check_permissions -d "Check file and directory permissions"
set -l issues 0
# Check Fish functions directory
set -l functions_dir (dirname (status current-filename))
if test -d "$functions_dir"
echo "✅ Functions directory accessible: $functions_dir"
# Check individual function files
for func_file in "$functions_dir"/nvm_*.fish
if test -r "$func_file"
echo "$(basename $func_file) readable"
else
echo "$(basename $func_file) not readable"
set issues (math "$issues + 1")
end
end
else
echo "❌ Functions directory not found"
set issues (math "$issues + 1")
end
# Check cache directory permissions
set -l cache_dir
if set -q XDG_CACHE_HOME
set cache_dir "$XDG_CACHE_HOME/nvm-auto-use"
else
set cache_dir "$HOME/.cache/nvm-auto-use"
end
if test -d "$cache_dir"
if test -w "$cache_dir"
echo "✅ Cache directory writable: $cache_dir"
else
echo "❌ Cache directory not writable: $cache_dir"
set issues (math "$issues + 1")
end
else
echo " Cache directory doesn't exist (will be created as needed)"
end
# Check current directory permissions for version files
if test -r "."
echo "✅ Current directory readable"
for version_file in .nvmrc .node-version .tool-versions package.json
if test -f "$version_file"
if test -r "$version_file"
echo "$version_file readable"
else
echo "$version_file not readable"
set issues (math "$issues + 1")
end
end
end
else
echo "❌ Current directory not readable"
set issues (math "$issues + 1")
end
return $issues
end
function _nvm_doctor_check_config -d "Validate configuration"
set -l issues 0
echo "Configuration variables:"
# Check debounce setting
set -l debounce (_nvm_auto_use_get_debounce 2>/dev/null)
if test -n "$debounce"
echo " ✅ Debounce: ${debounce}ms"
else
echo " Debounce: Default (500ms)"
end
# Check excluded directories
set -l excluded (_nvm_auto_use_get_excluded_dirs 2>/dev/null)
echo " ✅ Excluded dirs: $excluded"
# Check auto-install setting
if set -q _nvm_auto_use_no_install
echo " ✅ Auto-install: Disabled"
else
echo " ✅ Auto-install: Enabled"
end
# Check silent mode
if set -q _nvm_auto_use_silent
echo " ✅ Silent mode: Enabled"
else
echo " ✅ Silent mode: Disabled"
end
# Check preferred manager
if set -q _nvm_auto_use_preferred_manager
echo " ✅ Preferred manager: $_nvm_auto_use_preferred_manager"
else
echo " ✅ Preferred manager: Auto-detect"
end
# Validate security policies
echo "Security policies:"
nvm_security policy list 2>/dev/null || echo " No security policies set"
return $issues
end
function _nvm_doctor_check_cache -d "Check cache status and health"
set -l issues 0
# Get cache stats
nvm_cache stats
# Check for corrupted cache files
set -l cache_dir
if set -q XDG_CACHE_HOME
set cache_dir "$XDG_CACHE_HOME/nvm-auto-use"
else
set cache_dir "$HOME/.cache/nvm-auto-use"
end
if test -d "$cache_dir"
set -l cache_files (find "$cache_dir" -type f 2>/dev/null)
for cache_file in $cache_files
if test -s "$cache_file"
echo "$(basename $cache_file) valid"
else
echo " ⚠️ $(basename $cache_file) empty (may be normal)"
end
end
# Check for very old cache files
set -l old_files (find "$cache_dir" -type f -mtime +7 2>/dev/null)
if test -n "$old_files"
echo " Found "(echo "$old_files" | wc -l)" cache files older than 7 days"
end
else
echo " No cache directory found"
end
return $issues
end
function _nvm_doctor_security_audit -d "Run security audit"
nvm_security audit
end
function _nvm_doctor_performance_check -d "Analyze performance issues"
set -l issues 0
echo "Performance analysis:"
# Check for excessive cache files
set -l cache_dir
if set -q XDG_CACHE_HOME
set cache_dir "$XDG_CACHE_HOME/nvm-auto-use"
else
set cache_dir "$HOME/.cache/nvm-auto-use"
end
if test -d "$cache_dir"
set -l cache_count (find "$cache_dir" -type f 2>/dev/null | wc -l)
if test $cache_count -gt 100
echo " ⚠️ Large number of cache files ($cache_count) - consider cleanup"
set issues (math "$issues + 1")
else
echo " ✅ Reasonable cache size ($cache_count files)"
end
end
# Check for very long directory paths
set -l current_path (pwd)
set -l path_length (string length "$current_path")
if test $path_length -gt 200
echo " ⚠️ Very long current path may slow operations: $path_length characters"
set issues (math "$issues + 1")
else
echo " ✅ Path length reasonable: $path_length characters"
end
# Check for deep directory nesting
set -l depth (echo "$current_path" | string replace -a '/' '\n' | wc -l)
if test $depth -gt 15
echo " ⚠️ Deep directory nesting may slow file searches: $depth levels"
set issues (math "$issues + 1")
else
echo " ✅ Directory depth reasonable: $depth levels"
end
return $issues
end
function _nvm_doctor_auto_fix -d "Attempt to fix common issues"
set -l fix_type $argv[1]
echo "🔧 Attempting automatic fixes..."
switch $fix_type
case cache
echo "Cleaning up cache..."
nvm_cache clear
echo "✅ Cache cleared"
case permissions
echo "Fixing cache directory permissions..."
set -l cache_dir
if set -q XDG_CACHE_HOME
set cache_dir "$XDG_CACHE_HOME/nvm-auto-use"
else
set cache_dir "$HOME/.cache/nvm-auto-use"
end
mkdir -p "$cache_dir" 2>/dev/null
chmod 755 "$cache_dir" 2>/dev/null
echo "✅ Cache directory permissions fixed"
case config
echo "Resetting configuration to defaults..."
nvm_auto_use_config reset
echo "✅ Configuration reset"
case all
echo "Running all available fixes..."
_nvm_doctor_auto_fix cache
_nvm_doctor_auto_fix permissions
echo "✅ All fixes completed"
case '*'
echo "Available fix types:"
echo " cache - Clear cache files"
echo " permissions - Fix directory permissions"
echo " config - Reset configuration"
echo " all - Run all fixes"
return 1
end
end

View File

@@ -0,0 +1,168 @@
function nvm_error_recovery -d "Error recovery and graceful degradation"
set -l operation $argv[1]
set -l error_context $argv[2]
switch $operation
case manager_failure
set -l manager $argv[2]
set -l target_version $argv[3]
echo "⚠️ $manager failed to switch to version $target_version" >&2
# Try fallback managers
set -l fallback_managers (nvm_compat_detect | string split ' ')
for fallback in $fallback_managers
if test "$fallback" != "$manager"
echo "🔄 Trying fallback manager: $fallback" >&2
if _nvm_error_recovery_try_manager "$fallback" "$target_version"
echo "✅ Successfully switched using $fallback" >&2
return 0
end
end
end
echo "❌ All managers failed. Staying on current version." >&2
return 1
case version_not_found
set -l manager $argv[2]
set -l requested_version $argv[3]
echo "⚠️ Version $requested_version not found" >&2
# Try to find similar versions
set -l suggestions (_nvm_error_recovery_suggest_versions "$manager" "$requested_version")
if test -n "$suggestions"
echo "💡 Available similar versions: $suggestions" >&2
# Auto-select best match if auto_install is disabled
if set -q _nvm_auto_use_no_install
set -l best_match (echo "$suggestions" | string split ' ' | head -n 1)
echo "🔄 Trying closest match: $best_match" >&2
if _nvm_error_recovery_try_manager "$manager" "$best_match"
return 0
end
end
end
return 1
case network_failure
echo "⚠️ Network failure during version operation" >&2
# Check if we have a cached version list
set -l cache_key "versions_$(echo $argv[2] | shasum | cut -d' ' -f1)"
if set -l cached_versions (nvm_cache get "$cache_key" 86400) # 24 hour TTL
echo "📦 Using cached version information" >&2
echo "$cached_versions"
return 0
end
echo "❌ No cached version information available" >&2
return 1
case permission_denied
set -l operation_type $argv[2]
echo "⚠️ Permission denied for $operation_type" >&2
switch $operation_type
case install
echo "💡 Try running with appropriate permissions or check manager configuration" >&2
case switch
echo "💡 Check if the version is already installed or try with sudo" >&2
end
return 1
case timeout
set -l operation_type $argv[2]
set -l timeout_duration $argv[3]
echo "⏱️ Operation '$operation_type' timed out after $timeout_duration seconds" >&2
echo "💡 Consider checking network connection or increasing timeout" >&2
# Kill any hanging processes
nvm_async cleanup
return 1
case corruption
set -l file_path $argv[2]
echo "⚠️ Corrupted file detected: $file_path" >&2
# Try to recover from backup or regenerate
if test -f "$file_path.backup"
echo "🔄 Restoring from backup" >&2
cp "$file_path.backup" "$file_path"
return 0
end
echo "❌ No backup available, manual intervention required" >&2
return 1
case '*'
echo "Unknown error recovery operation: $operation" >&2
return 1
end
end
function _nvm_error_recovery_try_manager -d "Try using a specific manager"
set -l manager $argv[1]
set -l version $argv[2]
if not command -q "$manager"
return 1
end
switch $manager
case nvm
nvm use "$version" 2>/dev/null
case fnm
fnm use "$version" 2>/dev/null
case volta
volta pin "node@$version" 2>/dev/null
case asdf
asdf local nodejs "$version" 2>/dev/null
case '*'
return 1
end
end
function _nvm_error_recovery_suggest_versions -d "Suggest similar available versions"
set -l manager $argv[1]
set -l requested $argv[2]
# Extract major version for suggestions
set -l major (echo "$requested" | string replace -r '^v?([0-9]+).*' '$1')
# Try to get available versions (with error handling)
set -l available_versions
switch $manager
case nvm
set available_versions (nvm list-remote 2>/dev/null | grep "^v$major\." | head -n 5)
case fnm
set available_versions (fnm list-remote 2>/dev/null | grep "^v$major\." | head -n 5)
case asdf
set available_versions (asdf list-all nodejs 2>/dev/null | grep "^$major\." | head -n 5)
end
echo "$available_versions" | string join ' '
end
function _nvm_error_recovery_log -d "Log error for debugging"
set -l error_type $argv[1]
set -l details $argv[2]
# Log to XDG cache directory
set -l log_dir
if set -q XDG_CACHE_HOME
set log_dir "$XDG_CACHE_HOME/nvm-auto-use"
else
set log_dir "$HOME/.cache/nvm-auto-use"
end
mkdir -p "$log_dir" 2>/dev/null
set -l log_file "$log_dir/error.log"
set -l timestamp (date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] $error_type: $details" >>"$log_file"
end

View File

@@ -35,11 +35,15 @@ function nvm_extract_version -a file_path -d "Extract Node.js version from vario
# Standard .nvmrc or .node-version file
set -l version (cat "$actual_file" | string trim)
if test -n "$version"
# Strip leading 'v'
set version (string replace -r '^v' '' "$version")
# Handle nvm aliases
switch "$version"
case 'lts/*' lts latest stable node
if command -q nvm
set version (nvm version-remote "$version" 2>/dev/null | string replace 'v' '')
else if command -q node
set version (node -v 2>/dev/null | string replace -r '^v' '')
end
end
echo "$version"

View File

@@ -8,13 +8,18 @@ function nvm_notify -a message -d "Send notification for Node.js version changes
return
end
# Try different notification methods
if command -q osascript # macOS
# Try different notification methods until one succeeds
if command -q osascript
osascript -e "display notification \"$message\" with title \"nvm-auto-use\""
else if command -q notify-send # Linux
return
end
if command -q notify-send
notify-send nvm-auto-use "$message"
else if command -q terminal-notifier # macOS alternative
return
end
if command -q terminal-notifier
terminal-notifier -title nvm-auto-use -message "$message"
return
end
end

View File

@@ -0,0 +1,354 @@
function nvm_recommendations -d "Smart recommendations for Node.js versions and configurations"
set -l action $argv[1]
switch $action
case suggest_version
_nvm_recommend_version $argv[2..-1]
case upgrade_path
_nvm_recommend_upgrade $argv[2..-1]
case security_update
_nvm_recommend_security_update
case performance
_nvm_recommend_performance
case compatibility
_nvm_recommend_compatibility $argv[2..-1]
case manager
_nvm_recommend_manager
case config
_nvm_recommend_config
case '*'
echo "Usage: nvm_recommendations [suggest_version|upgrade_path|security_update|performance|compatibility|manager|config] [args...]"
return 1
end
end
function _nvm_recommend_version -d "Recommend appropriate Node.js version"
set -l context $argv[1] # 'new_project', 'existing_project', 'migration'
echo "🔍 Analyzing project for Node.js version recommendation..."
# Check for existing version constraints
set -l constraints (_nvm_analyze_version_constraints)
set -l current_version
if command -q node
set current_version (node --version | string replace 'v' '')
end
# Get available managers and their capabilities
set -l available_managers (nvm_compat_detect | string split ' ')
echo
echo "📋 Recommendation Analysis:"
echo "============================"
# Project type detection
set -l project_type (_nvm_detect_project_type)
echo "Project type: $project_type"
if test -n "$current_version"
echo "Current version: $current_version"
end
if test -n "$constraints"
echo "Detected constraints: $constraints"
end
# Generate recommendations
echo
echo "💡 Recommendations:"
echo "==================="
switch $context
case new_project
_nvm_recommend_for_new_project "$project_type"
case existing_project
_nvm_recommend_for_existing_project "$project_type" "$current_version"
case migration
_nvm_recommend_for_migration "$current_version"
case '*'
_nvm_recommend_general "$project_type" "$current_version"
end
end
function _nvm_recommend_for_new_project -d "Recommendations for new projects"
set -l project_type $argv[1]
switch $project_type
case react
echo "• Node.js 18.17.0+ (LTS) - Recommended for React projects"
echo "• Consider Node.js 20.x for latest features"
echo "• Avoid odd-numbered versions (development releases)"
case vue
echo "• Node.js 16.20.0+ - Minimum for Vue 3"
echo "• Node.js 18.17.0+ (LTS) - Recommended"
case angular
echo "• Node.js 18.13.0+ - Required for Angular 15+"
echo "• Node.js 18.17.0+ (LTS) - Recommended"
case nextjs
echo "• Node.js 18.17.0+ - Required for Next.js 13+"
echo "• Node.js 20.x for best performance"
case typescript
echo "• Node.js 18.17.0+ (LTS) - Excellent TypeScript support"
echo "• Node.js 20.x for latest TypeScript features"
case backend
echo "• Node.js 18.17.0+ (LTS) - Stable for production"
echo "• Consider Node.js 20.x for performance improvements"
case '*'
echo "• Node.js 18.17.0+ (LTS) - Safe choice for most projects"
echo "• Node.js 20.x for latest features and performance"
end
echo
echo "💭 General Guidelines:"
echo "• Use LTS versions for production projects"
echo "• Test with latest version for future compatibility"
echo "• Pin exact versions in CI/CD environments"
end
function _nvm_recommend_for_existing_project -d "Recommendations for existing projects"
set -l project_type $argv[1]
set -l current_version $argv[2]
if test -z "$current_version"
echo "• Install Node.js to get version-specific recommendations"
return
end
# Check if current version is LTS
set -l is_lts (_nvm_check_if_lts "$current_version")
set -l is_outdated (_nvm_check_if_outdated "$current_version")
if test "$is_outdated" = true
echo "⚠️ Current version ($current_version) is outdated"
echo "• Consider upgrading to latest LTS for security updates"
# Suggest upgrade path
set -l upgrade_target (_nvm_suggest_upgrade_target "$current_version")
if test -n "$upgrade_target"
echo "• Recommended upgrade: $upgrade_target"
end
else if test "$is_lts" = false
echo " Current version ($current_version) is not LTS"
echo "• Consider switching to LTS for stability"
else
echo "✅ Current version ($current_version) is good"
echo "• No immediate action needed"
end
# Dependency compatibility check
if test -f "package.json"
echo
echo "📦 Dependency Analysis:"
_nvm_analyze_dependencies
end
end
function _nvm_recommend_upgrade -d "Recommend upgrade path"
set -l current_version $argv[1]
if test -z "$current_version"
if command -q node
set current_version (node --version | string replace 'v' '')
else
echo "❌ No Node.js version specified or installed"
return 1
end
end
echo "🔄 Upgrade Path Analysis for Node.js $current_version"
echo "=================================================="
# Check for security issues
nvm_security check_cve "$current_version"
set -l has_vulnerabilities $status
if test $has_vulnerabilities -ne 0
echo
echo "🚨 SECURITY: Immediate upgrade recommended due to vulnerabilities"
end
# Suggest upgrade targets
set -l major_version (echo "$current_version" | string replace -r '^([0-9]+)\..*' '$1')
set -l next_lts (_nvm_get_next_lts "$major_version")
echo
echo "📈 Upgrade Options:"
echo "• Patch upgrade: Stay within current minor version"
echo "• Minor upgrade: Upgrade to latest in major version $major_version"
if test -n "$next_lts"
echo "• Major upgrade: Node.js $next_lts (LTS)"
end
echo
echo "🧪 Testing Strategy:"
echo "1. Test in development environment first"
echo "2. Run full test suite"
echo "3. Check for breaking changes in release notes"
echo "4. Update CI/CD pipelines"
echo "5. Deploy to staging before production"
end
function _nvm_recommend_security_update -d "Recommend security-focused updates"
echo "🔒 Security Update Recommendations"
echo "=================================="
if command -q node
set -l current_version (node --version | string replace 'v' '')
echo "Current version: $current_version"
# Check for vulnerabilities
nvm_security check_cve "$current_version"
set -l has_vulnerabilities $status
if test $has_vulnerabilities -ne 0
echo
echo "🚨 ACTION REQUIRED: Security vulnerabilities found"
echo "• Upgrade immediately to patch security issues"
# Suggest secure versions
set -l secure_versions (_nvm_get_secure_versions)
if test -n "$secure_versions"
echo "• Recommended secure versions: $secure_versions"
end
else
echo
echo "✅ No known vulnerabilities in current version"
echo "• Keep monitoring for security updates"
end
else
echo "❌ Node.js not installed - cannot assess security status"
end
echo
echo "🛡️ Security Best Practices:"
echo "• Keep Node.js updated to latest patch versions"
echo "• Subscribe to Node.js security announcements"
echo "• Use npm audit for dependency vulnerabilities"
echo "• Pin specific versions in production"
end
function _nvm_recommend_performance -d "Performance optimization recommendations"
echo "⚡ Performance Optimization Recommendations"
echo "=========================================="
if command -q node
set -l current_version (node --version | string replace 'v' '')
set -l major_version (echo "$current_version" | string replace -r '^([0-9]+)\..*' '$1')
echo "Current version: $current_version"
echo
# Version-specific performance notes
switch $major_version
case 16
echo "📈 Upgrade to Node.js 18+ for:"
echo "• Better V8 engine performance"
echo "• Improved startup time"
echo "• Enhanced memory usage"
case 18
echo "📈 Consider Node.js 20+ for:"
echo "• Latest V8 optimizations"
echo "• Improved module loading"
echo "• Better async performance"
case 20 21
echo "✅ You're using a modern Node.js version"
echo "• Good performance characteristics"
echo "• Consider latest patch for micro-optimizations"
case '*'
echo "⚠️ Consider upgrading to Node.js 18+ for better performance"
end
end
echo
echo "🎯 Performance Tips:"
echo "• Use --max-old-space-size for memory-intensive apps"
echo "• Enable --experimental-loader for faster imports"
echo "• Consider --enable-source-maps for better debugging"
echo "• Profile with --cpu-prof and --heap-prof"
end
function _nvm_detect_project_type -d "Detect project type from files"
if test -f "package.json"
set -l deps (cat package.json 2>/dev/null)
if echo "$deps" | grep -q '"react"'
echo react
else if echo "$deps" | grep -q '"vue"'
echo vue
else if echo "$deps" | grep -q '"@angular"'
echo angular
else if echo "$deps" | grep -q '"next"'
echo nextjs
else if echo "$deps" | grep -q '"typescript"'
echo typescript
else if echo "$deps" | grep -q '"express"\|"fastify"\|"koa"'
echo backend
else
echo node
end
else
echo general
end
end
function _nvm_analyze_version_constraints -d "Analyze existing version constraints"
set -l constraints
# Check package.json engines
if test -f "package.json" -a command -q jq
set -l engine_constraint (jq -r '.engines.node // empty' package.json 2>/dev/null)
if test -n "$engine_constraint"
set constraints $constraints "package.json: $engine_constraint"
end
end
# Check .nvmrc
if test -f ".nvmrc"
set -l nvmrc_version (cat .nvmrc | string trim)
set constraints $constraints ".nvmrc: $nvmrc_version"
end
echo "$constraints" | string join '; '
end
function _nvm_check_if_lts -d "Check if version is LTS"
set -l version $argv[1]
set -l major (echo "$version" | string replace -r '^([0-9]+)\..*' '$1')
# LTS versions: 16, 18, 20 (even numbers)
if test (math "$major % 2") -eq 0
echo true
else
echo false
end
end
function _nvm_check_if_outdated -d "Check if version is outdated"
set -l version $argv[1]
set -l major (echo "$version" | string replace -r '^([0-9]+)\..*' '$1')
# Simplified check - versions below 16 are definitely outdated
if test $major -lt 16
echo true
else
echo false
end
end
function _nvm_get_next_lts -d "Get next LTS version"
set -l current_major $argv[1]
set -l next_lts
# Determine next LTS based on current major
switch $current_major
case 14 15 16 17
set next_lts "18.17.0"
case 18 19
set next_lts "20.5.0"
case '*'
set next_lts "20.5.0"
end
echo "$next_lts"
end

278
functions/nvm_security.fish Normal file
View File

@@ -0,0 +1,278 @@
function nvm_security -d "Security validation and vulnerability checking"
set -l action $argv[1]
switch $action
case check_version
set -l version $argv[2]
_nvm_security_validate_version "$version"
case check_cve
set -l version $argv[2]
_nvm_security_check_vulnerabilities "$version"
case validate_source
set -l source $argv[2]
_nvm_security_validate_source "$source"
case audit
_nvm_security_audit_current
case policy
set -l policy_action $argv[2]
_nvm_security_policy "$policy_action" $argv[3..-1]
case '*'
echo "Usage: nvm_security [check_version|check_cve|validate_source|audit|policy] [args...]"
return 1
end
end
function _nvm_security_validate_version -d "Validate version string format and safety"
set -l version $argv[1]
# Remove leading 'v' if present
set version (string replace -r '^v' '' "$version")
# Check for valid semver format
if not string match -qr '^\d+\.\d+\.\d+' "$version"
echo "⚠️ Invalid version format: $version" >&2
return 1
end
# Check for suspicious characters
if string match -qr '[;&|`$(){}[\]<>]' "$version"
echo "🚨 Suspicious characters in version: $version" >&2
return 1
end
# Check against minimum supported version
set -l min_version (nvm_security policy get min_version)
if test -n "$min_version"
if _nvm_security_version_compare "$version" "$min_version" -lt
echo "⚠️ Version $version is below minimum required ($min_version)" >&2
return 1
end
end
# Check against maximum allowed version
set -l max_version (nvm_security policy get max_version)
if test -n "$max_version"
if _nvm_security_version_compare "$version" "$max_version" -gt
echo "⚠️ Version $version is above maximum allowed ($max_version)" >&2
return 1
end
end
return 0
end
function _nvm_security_check_vulnerabilities -d "Check version for known vulnerabilities"
set -l version $argv[1]
# Cache key for CVE data
set -l cache_key "cve_check_$(echo $version | shasum | cut -d' ' -f1)"
# Check cache first (24 hour TTL)
if set -l cached_result (nvm_cache get "$cache_key" 86400)
if test "$cached_result" = vulnerable
echo "🚨 Version $version has known vulnerabilities (cached)" >&2
return 1
else if test "$cached_result" = safe
echo "✅ Version $version appears safe (cached)" >&2
return 0
end
end
# Check against known vulnerable versions (offline first)
set -l vulnerable_versions "
16.0.0
16.1.0
16.2.0
18.0.0
18.1.0
"
if string match -q "*$version*" "$vulnerable_versions"
echo "🚨 Version $version has known vulnerabilities" >&2
nvm_cache set "$cache_key" vulnerable
return 1
end
# Try online CVE check if available
if command -q curl
_nvm_security_online_cve_check "$version" "$cache_key"
else
echo " Cannot perform online CVE check (curl not available)" >&2
nvm_cache set "$cache_key" unknown
return 0
end
end
function _nvm_security_online_cve_check -d "Perform online CVE check"
set -l version $argv[1]
set -l cache_key $argv[2]
# Background job for CVE checking to avoid blocking
fish -c "
set cve_result (curl -s --max-time 5 'https://nodejs.org/en/about/security/' 2>/dev/null)
if test \$status -eq 0
if echo \"\$cve_result\" | grep -qi '$version'
nvm_cache set '$cache_key' 'vulnerable'
echo '🚨 Version $version found in security advisories' >&2
else
nvm_cache set '$cache_key' 'safe'
echo '✅ Version $version appears safe' >&2
end
else
nvm_cache set '$cache_key' 'unknown'
echo ' Unable to verify security status online' >&2
end
" &
return 0
end
function _nvm_security_validate_source -d "Validate version file source"
set -l source_file $argv[1]
if not test -f "$source_file"
echo "⚠️ Source file not found: $source_file" >&2
return 1
end
# Check file permissions
if test -w "$source_file" -a (stat -c %a "$source_file" 2>/dev/null || stat -f %Mp%Lp "$source_file" 2>/dev/null) = 777
echo "⚠️ Insecure permissions on $source_file (world-writable)" >&2
end
# Check for suspicious content
set -l content (cat "$source_file")
if string match -qr '[;&|`$(){}[\]<>]' "$content"
echo "🚨 Suspicious content in $source_file" >&2
return 1
end
return 0
end
function _nvm_security_audit_current -d "Audit current Node.js installation"
echo "🔍 Security audit for current Node.js installation"
echo
# Current version info
if command -q node
set -l current_version (node --version 2>/dev/null | string replace 'v' '')
echo "Current version: $current_version"
# Check current version security
nvm_security check_version "$current_version"
nvm_security check_cve "$current_version"
# Check npm security if available
if command -q npm
echo
echo "📦 NPM audit (if available):"
npm audit --audit-level moderate 2>/dev/null || echo "NPM audit not available or no package.json found"
end
else
echo "❌ Node.js not found in PATH"
end
echo
echo "🔧 Version managers found:"
nvm_compat_detect
echo
echo "📋 Security policies:"
nvm_security policy list
end
function _nvm_security_policy -d "Manage security policies"
set -l action $argv[1]
switch $action
case set
set -l key $argv[2]
set -l value $argv[3]
switch $key
case min_version
set -g _nvm_security_min_version "$value"
echo "Set minimum version to: $value"
case max_version
set -g _nvm_security_max_version "$value"
echo "Set maximum version to: $value"
case allow_prerelease
set -g _nvm_security_allow_prerelease "$value"
echo "Allow prerelease versions: $value"
case '*'
echo "Unknown policy key: $key" >&2
return 1
end
case get
set -l key $argv[2]
switch $key
case min_version
echo "$_nvm_security_min_version"
case max_version
echo "$_nvm_security_max_version"
case allow_prerelease
echo "$_nvm_security_allow_prerelease"
case '*'
echo "Unknown policy key: $key" >&2
return 1
end
case list
echo "Security policies:"
echo " min_version: $_nvm_security_min_version"
echo " max_version: $_nvm_security_max_version"
echo " allow_prerelease: $_nvm_security_allow_prerelease"
case reset
set -e _nvm_security_min_version
set -e _nvm_security_max_version
set -e _nvm_security_allow_prerelease
echo "Security policies reset to defaults"
case '*'
echo "Usage: nvm_security policy [set|get|list|reset] [key] [value]"
return 1
end
end
function _nvm_security_version_compare -d "Compare semantic versions"
set -l version1 $argv[1]
set -l version2 $argv[2]
set -l operator $argv[3]
# Simple semver comparison
set -l v1_parts (string split '.' "$version1")
set -l v2_parts (string split '.' "$version2")
for i in (seq 1 3)
set -l v1_part (echo $v1_parts[$i] | string replace -r '[^0-9].*' '')
set -l v2_part (echo $v2_parts[$i] | string replace -r '[^0-9].*' '')
if test -z "$v1_part"
set v1_part 0
end
if test -z "$v2_part"
set v2_part 0
end
if test $v1_part -lt $v2_part
test "$operator" = -lt
return $status
else if test $v1_part -gt $v2_part
test "$operator" = -gt
return $status
end
end
# Versions are equal
test "$operator" = -eq
return $status
end

View File

@@ -9,10 +9,13 @@ end
function nvm_version_status -d "Show detailed Node.js version status"
if command -q node
set -l version (node -v 2>/dev/null)
set -l npm_version (npm -v 2>/dev/null)
set -l version (node -v 2>/dev/null | string replace -r '^v' '')
set -l npm_version
if command -q npm
set npm_version (npm -v 2>/dev/null)
end
echo "Node.js: $version"
echo "Node.js: v$version"
if test -n "$npm_version"
echo "npm: v$npm_version"
end