package config import ( "flag" "fmt" "os" "strconv" "strings" ) type Config struct { FilePath string Host string Port int Debug bool Quiet bool LogReads bool LogFile string AuthRole string } func strEnv(key, fallback string) string { if v, ok := os.LookupEnv(key); ok { return v } return fallback } func intEnv(key string, fallback int) int { if v, ok := os.LookupEnv(key); ok { if n, err := strconv.Atoi(v); err == nil { return n } } return fallback } func boolEnvOrDefault(key string, fallback bool) bool { if v, ok := os.LookupEnv(key); ok { switch strings.ToLower(v) { case "1", "true", "yes": return true default: return false } } return fallback } func Load() (*Config, error) { c := &Config{ FilePath: "data/sample.xlsx", Host: "localhost", Port: 3000, Debug: false, Quiet: false, LogReads: true, AuthRole: "writer", } flag.StringVar(&c.FilePath, "file", strEnv("RESTXLSX_FILE", c.FilePath), "Path to xlsx/xlsm file") flag.StringVar(&c.Host, "host", strEnv("RESTXLSX_HOST", c.Host), "Listen host") flag.IntVar(&c.Port, "port", intEnv("RESTXLSX_PORT", c.Port), "HTTP listen port") flag.BoolVar(&c.Debug, "debug", boolEnvOrDefault("RESTXLSX_DEBUG", c.Debug), "Enable debug mode (swagger ui, etc.)") quietFlag := flag.Bool("quiet", false, "Suppress stdout output") flag.BoolVar(&c.LogReads, "log-reads", boolEnvOrDefault("RESTXLSX_LOG_READS", c.LogReads), "Log read operations") flag.StringVar(&c.LogFile, "log-file", strEnv("RESTXLSX_LOG_FILE", c.LogFile), "Optional log file path") flag.StringVar(&c.AuthRole, "auth", strEnv("RESTXLSX_AUTH", c.AuthRole), "Fallback auth role: admin, writer, reader (used when no OIDC token present)") flag.Parse() if *quietFlag || strings.EqualFold(os.Getenv("RESTXLSX_CONSOLE"), "quiet") { c.Quiet = true } c.AuthRole = strings.ToLower(c.AuthRole) switch c.AuthRole { case "admin", "writer", "reader": default: return nil, fmt.Errorf("invalid auth role %q: must be admin, writer, or reader", c.AuthRole) } if !strings.HasSuffix(strings.ToLower(c.FilePath), ".xlsx") && !strings.HasSuffix(strings.ToLower(c.FilePath), ".xlsm") { return nil, fmt.Errorf("unsupported file format: %s (must be .xlsx or .xlsm)", c.FilePath) } return c, nil }