| 113 | } |
| 114 | |
| 115 | func Load() (*Config, error) { |
| 116 | cfg := &Config{ |
| 117 | BaseURL: defaultBase, |
| 118 | sources: map[string]Source{"base_url": SourceDefault}, |
| 119 | } |
| 120 | |
| 121 | // Layer 1: global config |
| 122 | if err := cfg.loadFile(globalConfigPath(), SourceGlobal); err != nil { |
| 123 | return nil, err |
| 124 | } |
| 125 | |
| 126 | // Layer 2: local config (.hey/config.json walking up) |
| 127 | if local := localConfigPath(); local != "" { |
| 128 | if err := cfg.loadFile(local, SourceLocal); err != nil { |
| 129 | return nil, err |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | // Layer 3: environment variables |
| 134 | if env := os.Getenv("HEY_BASE_URL"); env != "" { |
| 135 | cfg.BaseURL = env |
| 136 | cfg.sources["base_url"] = SourceEnv |
| 137 | } |
| 138 | |
| 139 | // Validate base URL |
| 140 | if err := validateBaseURL(cfg.BaseURL); err != nil { |
| 141 | return nil, err |
| 142 | } |
| 143 | |
| 144 | return cfg, nil |
| 145 | } |
| 146 | |
| 147 | func (c *Config) loadFile(path string, source Source) error { |
| 148 | if path == "" { |