provisioning-outreach/presentations/rust-laspalmas-250926/auroraframe/scripts/dev.nu

339 lines
11 KiB
Text
Raw Permalink Normal View History

#!/usr/bin/env nu
# Development workflow script
use ../config/build.config.nu
use build.nu build_page
use utils.nu *
use optimize-html.nu *
use optimize-css.nu *
use optimize-svg.nu *
# Development server with auto-rebuild
def main [
--port(-p): int = 8080 # Development server port
--watch(-w) # Enable file watching
--no-browser(-n) # Don't open browser automatically
--verbose(-v) # Verbose output
] {
let config = (load_config)
print "🚀 Starting development environment..."
# Initial build
print "📦 Building development version..."
try {
build_page --dev
} catch {
print "❌ Build failed"
return
}
if $watch {
# Start server and file watcher with better server detection
start_dev_server_with_watch $config $port $no_browser $verbose
} else {
# Start development server only
start_dev_server $config.dist_dir $port $no_browser
}
}
# File watcher for auto-rebuild
def start_file_watcher [config: record, verbose: bool] {
print "👁️ Starting file watcher..."
let watch_files = [
$"($config.src_dir)/index.html",
$"($config.css_src)/modules/*.css",
$"($config.css_src)/main.css",
$"($config.css_src)/svg-data.css",
$"($config.svg_src)/*.svg"
]
# Expand glob patterns
let expanded_files = ($watch_files | each { |pattern|
if ($pattern | str contains "*") {
glob $pattern
} else {
[$pattern]
}
} | flatten | where ($it | path exists))
print $"📂 Watching ($expanded_files | length) files for changes..."
# Watch in background job
watch_files $expanded_files { |files|
print "\n🔄 Files changed!"
print "🔨 Rebuilding..."
# Quick development build
try {
build_page --dev
print "✅ Rebuild completed"
} catch {
print "❌ Rebuild failed"
}
}
}
# Start development server
def start_dev_server [directory: string, port: int, no_browser: bool] {
print $"🌐 Starting development server..."
print $"📁 Serving: ($directory)"
print $"🔗 URL: http://localhost:($port)"
if not $no_browser {
# Try to open browser (platform-specific)
try {
if ($nu.os-info.name == "macos") {
open $"http://localhost:($port)"
} else if ($nu.os-info.name == "linux") {
xdg-open $"http://localhost:($port)"
} else if ($nu.os-info.name == "windows") {
start $"http://localhost:($port)"
}
} catch {
print $"💡 Open http://localhost:($port) in your browser"
}
}
# Start simple HTTP server
serve_dev $port $directory
}
# Start development server with file watching
def start_dev_server_with_watch [config: record, port: int, no_browser: bool, verbose: bool] {
print $"🌐 Starting development server with file watching..."
print $"📁 Serving: ($config.dist_dir)"
print $"🔗 URL: http://localhost:($port)"
# Check what HTTP servers are available
let has_simple_server = (which simple-http-server | length) > 0
let has_python3 = (which python3 | length) > 0
let has_python = (which python | length) > 0
if $has_simple_server or $has_python3 or $has_python {
print ""
print "🚀 Starting HTTP server in background..."
# Start HTTP server in background
let server_cmd = if $has_simple_server {
print " Using simple-http-server (recommended)"
$"cd ($config.dist_dir) && simple-http-server --port ($port) --index"
} else if $has_python3 {
print " Using Python3 HTTP server"
$"cd ($config.dist_dir) && python3 -m http.server ($port)"
} else {
print " Using Python2 HTTP server"
$"cd ($config.dist_dir) && python -m SimpleHTTPServer ($port)"
}
# Start server in background using shell
try {
^bash -c $"($server_cmd) > /dev/null 2>&1 &"
print $"📡 HTTP server started on port ($port)"
} catch { |err|
print $"❌ Failed to start server: ($err.msg)"
print " Try starting manually:"
print $" ($server_cmd)"
}
if not $no_browser {
print "🌐 Opening browser..."
# Try to open browser (platform-specific) without delay to avoid Ctrl+C issues
try {
if ($nu.os-info.name == "macos") {
open $"http://localhost:($port)"
} else if ($nu.os-info.name == "linux") {
xdg-open $"http://localhost:($port)"
} else if ($nu.os-info.name == "windows") {
start $"http://localhost:($port)"
}
} catch {
print $"💡 Manually open http://localhost:($port) in your browser"
}
}
print "👁️ File watcher will now monitor for changes..."
print $"🌐 Server running at: http://localhost:($port)"
print ""
print "💡 Usage:"
print " • Files will auto-rebuild when changed"
print " • Press Ctrl+C to stop (error message is normal)"
print $" • Cleanup server when done: nu scripts/dev.nu cleanup ($port)"
print ""
# Start file watcher - let it run until interrupted
# The error message on Ctrl+C is normal Nushell behavior
start_file_watcher $config $verbose
} else {
print "❌ No HTTP server found."
print " Install one of the following:"
print " - simple-http-server: cargo install basic-http-server"
print " - Python: Install via system package manager"
print $" Then restart the development server."
# Still run file watcher for builds
start_file_watcher $config $verbose
}
}
# Quick development build
def "main build" [] {
print "🔨 Quick development build..."
try {
build_page --dev
print "✅ Build completed"
} catch { |err|
print $"❌ Build failed: ($err)"
}
}
# Clean development build
def "main clean" [] {
let config = (load_config)
print "🧹 Cleaning development build..."
if ($config.dist_dir | path exists) {
rm -rf $config.dist_dir
}
print "✅ Clean completed"
}
# Development build with analysis
def "main analyze" [] {
print "📊 Building with analysis..."
try {
build_page --dev --analyze --verbose
print "✅ Analysis completed"
} catch { |err|
print $"❌ Analysis failed: ($err)"
}
}
# Lint and validate source files
def "main lint" [] {
let config = (load_config)
print "🔍 Linting source files..."
# Validate HTML
let html_file = $"($config.src_dir)/index.html"
if ($html_file | path exists) {
let html_content = (open $html_file)
let validation = (validate_html_structure $html_content)
if $validation.valid_structure {
print "✅ HTML structure is valid"
} else {
print "❌ HTML structure issues found:"
if not $validation.has_doctype { print " - Missing DOCTYPE" }
if not $validation.has_title { print " - Missing title tag" }
if not $validation.has_head { print " - Missing head section" }
if not $validation.has_body { print " - Missing body tag" }
}
}
# Validate CSS modules
let css_modules = (glob $"($config.css_src)/modules/*.css")
print $"🎨 Checking ($css_modules | length) CSS modules..."
$css_modules | each { |css_file|
let css_content = (open $css_file)
let analysis = (analyze_css $css_content)
print $" ($css_file | path basename): ($analysis.size_bytes) bytes, ($analysis.rule_lines) rules"
# Check for common issues
if ($css_content | str contains "!important") {
print $" ⚠️ Contains !important declarations"
}
if ($css_content | str contains "position: absolute") and (($css_content | str length) > 500) {
print $" ⚠️ Heavy use of absolute positioning"
}
}
# Validate SVG files
let svg_files = (glob $"($config.svg_src)/*.svg")
print $"🖼️ Checking ($svg_files | length) SVG files..."
$svg_files | each { |svg_file|
let svg_content = (open $svg_file)
let validation = (validate_svg $svg_content)
if $validation.valid {
print $" ✅ ($svg_file | path basename): Valid"
} else {
print $" ❌ ($svg_file | path basename): Invalid SVG"
}
}
print "🔍 Lint completed"
}
# Preview production build locally
def "main preview" [--port(-p): int = 8080] {
print "📦 Building production version for preview..."
try {
build_page --clean --verbose --analyze
let config = (load_config)
print "🌐 Starting preview server..."
serve_dev $port $config.dist_dir
} catch { |err|
print $"❌ Preview failed: ($err)"
}
}
# Cleanup development server processes
def cleanup_dev_server [port: int] {
print "🧹 Cleaning up background processes..."
# Kill any servers running on this port
let cleanup_commands = [
$"pkill -f 'http.server ($port)'",
$"pkill -f 'simple-http-server.*--port ($port)'",
$"pkill -f 'SimpleHTTPServer ($port)'",
$"lsof -ti:($port) | xargs kill -9"
]
$cleanup_commands | each { |cmd|
try {
^bash -c $cmd
} catch {
# Ignore errors - process might not exist
null
}
}
print "✅ Cleanup completed"
}
# Manual cleanup command
def "main cleanup" [port?: int = 8080] {
cleanup_dev_server $port
}
# Development help
def "main help" [] {
print "🛠️ Development Commands:"
print "========================"
print " nu scripts/dev.nu - Start development server with file watching"
print " nu scripts/dev.nu build - Quick development build"
print " nu scripts/dev.nu clean - Clean development build"
print " nu scripts/dev.nu analyze - Build with file size analysis"
print " nu scripts/dev.nu lint - Lint and validate source files"
print " nu scripts/dev.nu preview - Preview production build locally"
print " nu scripts/dev.nu cleanup <PORT> - Manually stop background servers"
print " nu scripts/dev.nu help - Show this help"
print ""
print "Options:"
print " --port, -p <PORT> - Development server port (default: 8080)"
print " --watch, -w - Enable file watching for auto-rebuild"
print " --no-browser, -n - Don't open browser automatically"
print " --verbose, -v - Verbose output"
print ""
print "Examples:"
print " nu scripts/dev.nu --watch --port 3000"
print " nu scripts/dev.nu preview --port 8080"
print " nu scripts/dev.nu analyze"
}