Files
fit/internal/config/config.go
scott 3168a4ef96
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 2m44s
Rename the app from tracker to fit
The directory, the repo and the hostname are all fit; the module path,
the image, the namespace and the data file were still tracker. Nothing
is deployed yet, so this is free now and would not be later.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 22:03:33 -07:00

48 lines
1.3 KiB
Go

package config
import (
"fmt"
"os"
"strings"
"time"
)
// Config is the runtime configuration, populated from the environment.
// Everything here is deployment shape; the things that get tuned mid-challenge
// (start date, targets) live in the data file instead, so changing a target
// does not mean a redeploy.
type Config struct {
Addr string
BaseURL string // public origin, e.g. https://fit.scottyah.com
DataPath string // JSON file on the mounted volume
TZ *time.Location
}
// Load reads configuration from the environment, applying defaults. It returns
// an error only for settings that have no safe default.
func Load() (*Config, error) {
c := &Config{
Addr: env("ADDR", ":8080"),
BaseURL: strings.TrimRight(env("BASE_URL", "http://localhost:8080"), "/"),
DataPath: env("DATA_PATH", "data/fit.json"),
}
// The whole app is date arithmetic, so a wrong timezone silently logs
// entries against the wrong day. Fail loudly rather than fall back to UTC.
tzName := env("TZ_NAME", "America/Los_Angeles")
loc, err := time.LoadLocation(tzName)
if err != nil {
return nil, fmt.Errorf("TZ_NAME %q: %w", tzName, err)
}
c.TZ = loc
return c, nil
}
func env(key, def string) string {
if v := os.Getenv(key); v != "" {
return v
}
return def
}