package main import ( "encoding/json" "errors" "fmt" "io/fs" "os" "path/filepath" ) const defaultBaseURL = "http://localhost:8010" // Config is the persisted CLI credential state. It is stored as JSON at // credentialsPath with 0600 permissions. type Config struct { BaseURL string Token string } // credentialsPath returns the on-disk location of the credentials file, // os.UserConfigDir()/atlas9/credentials.json. func credentialsPath() (string, error) { dir, err := os.UserConfigDir() if err != nil { return "", fmt.Errorf("locating config dir: %w", err) } return filepath.Join(dir, "atlas9", "credentials.json"), nil } // loadConfig reads the credentials file. A missing file is not an error; it // yields an empty Config. func loadConfig() (Config, error) { var cfg Config path, err := credentialsPath() if err != nil { return cfg, err } data, err := os.ReadFile(path) if errors.Is(err, fs.ErrNotExist) { return cfg, nil } if err != nil { return cfg, fmt.Errorf("reading credentials: %w", err) } if err := json.Unmarshal(data, &cfg); err != nil { return cfg, fmt.Errorf("parsing credentials: %w", err) } return cfg, nil } // saveConfig writes the credentials file with 0600 permissions, creating the // parent directory as needed. func saveConfig(cfg Config) error { path, err := credentialsPath() if err != nil { return err } if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { return fmt.Errorf("creating config dir: %w", err) } data, err := json.MarshalIndent(cfg, "", " ") if err != nil { return err } if err := os.WriteFile(path, data, 0600); err != nil { return fmt.Errorf("writing credentials: %w", err) } return nil } // resolve merges the stored config with flag and environment overrides. The // base URL precedence is flag > environment > file, and finally a built-in // default. The token has no flag: it comes from the ATLAS9_TOKEN env var, else // the stored file. An empty string means "not set" at each layer. func resolve(stored Config, flagURL string) Config { out := stored if v := os.Getenv("ATLAS9_URL"); v != "" { out.BaseURL = v } if v := os.Getenv("ATLAS9_TOKEN"); v != "" { out.Token = v } if flagURL != "" { out.BaseURL = flagURL } if out.BaseURL == "" { out.BaseURL = defaultBaseURL } return out }