package config import ( "fmt" "os" "path/filepath" "strings" "github.com/joho/godotenv" ) type Config struct { // Supabase Configuration SupabaseProjectURL string // Edge Function Endpoints (auto-generated from SupabaseProjectURL) DeviceAuthURL string AgentAuthURL string // Agent Configuration TokenPath string MetricsInterval int // Debug/Development Debug bool } var DefaultConfig = Config{ TokenPath: "./token.json", MetricsInterval: 30, Debug: false, } // LoadConfig loads configuration from environment variables and .env file func LoadConfig() (*Config, error) { config := DefaultConfig // Try to load .env file from current directory or parent directories envFile := findEnvFile() if envFile != "" { if err := godotenv.Load(envFile); err != nil { fmt.Printf("Warning: Could not load .env file from %s: %v\n", envFile, err) } else { fmt.Printf("Loaded configuration from %s\n", envFile) } } // Load from environment variables if url := os.Getenv("SUPABASE_PROJECT_URL"); url != "" { config.SupabaseProjectURL = url } if tokenPath := os.Getenv("TOKEN_PATH"); tokenPath != "" { config.TokenPath = tokenPath } if debug := os.Getenv("DEBUG"); debug == "true" || debug == "1" { config.Debug = true } // Auto-generate edge function URLs from project URL if config.SupabaseProjectURL != "" { config.DeviceAuthURL = fmt.Sprintf("%s/functions/v1/device-auth", config.SupabaseProjectURL) config.AgentAuthURL = fmt.Sprintf("%s/functions/v1/agent-auth-api", config.SupabaseProjectURL) } // Validate required configuration if err := config.Validate(); err != nil { return nil, fmt.Errorf("configuration validation failed: %w", err) } return &config, nil } // Validate checks if all required configuration is present func (c *Config) Validate() error { var missing []string if c.SupabaseProjectURL == "" { missing = append(missing, "SUPABASE_PROJECT_URL") } if c.DeviceAuthURL == "" { missing = append(missing, "DEVICE_AUTH_URL (or SUPABASE_PROJECT_URL)") } if c.AgentAuthURL == "" { missing = append(missing, "AGENT_AUTH_URL (or SUPABASE_PROJECT_URL)") } if len(missing) > 0 { return fmt.Errorf("missing required environment variables: %s", strings.Join(missing, ", ")) } return nil } // findEnvFile looks for .env file in current directory and parent directories func findEnvFile() string { dir, err := os.Getwd() if err != nil { return "" } for { envPath := filepath.Join(dir, ".env") if _, err := os.Stat(envPath); err == nil { return envPath } parent := filepath.Dir(dir) if parent == dir { break } dir = parent } return "" } // PrintConfig prints the current configuration (masking sensitive values) func (c *Config) PrintConfig() { if !c.Debug { return } fmt.Println("Configuration:") fmt.Printf(" Supabase Project URL: %s\n", c.SupabaseProjectURL) fmt.Printf(" Metrics Interval: %d seconds\n", c.MetricsInterval) fmt.Printf(" Debug: %v\n", c.Debug) }