#!/usr/bin/env nu # start-tracking-service.nu - Start the vapora-tracking background service # Follows NuShell 0.108+ guidelines with explicit types def main [ --port: int = 3000 # Server port --database: string = "sqlite://tracking.db" # Database URL --watch-dirs: string = "." # Projects to watch (default: current directory) --verbose = false ]: void { if $verbose { print "🚀 Starting Vapora Tracking Service..." print $" Port: [$port]" print $" Database: [$database]" print $" Watch: [$watch-dirs]" } # Rule 3: Early validation validate-environment # Rule 13: Predictable naming let pid-file = "/tmp/vapora-tracking.pid" let log-file = "/tmp/vapora-tracking.log" # Check if service is already running if check-service-running $pid-file { print "⚠️ Tracking service is already running" print $" PID: (cat $pid-file)" return } print "📝 Starting service..." print $" Logs: [$log-file]" # Start the service in background # Rule 17: Expression interpolation # Assumes script is run from repository root or VAPORA_ROOT env var is set let vapora-root = ($env.VAPORA_ROOT? | default $env.PWD) let command = $"cd ($vapora-root) && cargo run -p vapora-backend --release -- --tracking-port ($port) --tracking-database ($database)" # Start in background with output redirection let result = ( do { # Create startup script let startup-script = " #!/bin/bash $command >> $log-file 2>&1 & echo $! > $pid-file " sh --stdin <<< $startup-script } | complete ) if $result.exit_code != 0 { print $"❌ Failed to start service" print $" Error: ($result.stderr)" return } # Wait for service to start print "⏳ Waiting for service to start..." sleep 2s # Rule 11: Never swallow errors if not (check-service-running $pid-file) { print "❌ Service failed to start" print $" Check logs: ($log-file)" return } let service-pid = (cat $pid-file) print $"✅ Service started successfully!" print $" PID: [$service-pid]" print $" API: http://localhost:($port)/api/v1/tracking" print $"" print "Available commands:" print " /sync-tracking - Sync all projects" print " /log-change 'summary' - Log a change" print " /add-todo 'title' - Add a TODO" print " /track-status - Show status" print $" To stop the service: kill ($service-pid) or use stop-tracking-service To view logs: tail -f ($log-file) " } # Rule 1: Single purpose - validates environment def validate-environment []: void { # Rule 11: Never swallow errors if not (which cargo | is-not-empty) { error make { msg: "❌ Cargo not found. Install Rust from https://rustup.rs" } } # Check for Cargo.toml to validate we're in a Rust workspace let vapora-root = ($env.VAPORA_ROOT? | default $env.PWD) if not ($"($vapora-root)/Cargo.toml" | path exists) { error make { msg: $"❌ Vapora workspace not found. Set VAPORA_ROOT env var or run from repository root. Current: ($vapora-root)" } } } # Rule 1: Single purpose - checks if service is running def check-service-running [pid-file: string]: bool { if not ($pid-file | path exists) { return false } try { let pid = (cat $pid-file) let is-running = (ps aux | grep $pid | grep -v grep | is-not-empty) $is-running } catch { false } }