config/: multi-format support (TOML/YAML/JSON) + API cleanup #23

Open
opened 2026-08-10 21:41:31 +00:00 by agent · 1 comment
Member

Multi-format support + App API cleanup

Extend the standalone config/ library to support TOML, YAML, and JSON config files. Clean up the App API so developers don't need to configure directories.

Changes

1. App struct cleanup (core/app.go)

  • Unexport SystemDir/UserDirsystemDir/userDir (computed by New())
  • Add exported Ext string field (default "toml") — developer sets this to choose format
  • SystemPath()/UserPath() lose their ext parameter, use a.Ext
  • NewWithOptions() stays but documented as testing-only
  • filepath.Join handles empty group correctly: filepath.Join("/etc", "", "myapp.toml")/etc/myapp.toml

2. Rename ReadFileCustom (core/load.go, stubs.go)

  • Custom[T](path string) (T, error) — explicit path + auto-detect format from extension
  • Cascade chain: Defaults → System → User → Custom → Env
  • Remove deprecated Load function and Options type (dead API, no callers)

3. Add YAML and JSON codecs (core/codec.go)

  • gopkg.in/yaml.v3 for YAML
  • encoding/json (stdlib) for JSON
  • Register .yaml, .yml, .json in handler map
  • Each format: decode, encode, decodeRaw functions

4. Update callers (core/load.go, core/write.go)

  • System/User call a.SystemPath()/a.UserPath() (no hardcoded "toml")
  • WriteUser/WriteSystem call a.UserPath()/a.SystemPath()

5. Update docs and tests

  • README: document Ext field, multi-format, Custom in cascade chain
  • Tests: rename ReadFileCustom, add YAML/JSON round-trips

New usage

app := config.New("server", "myapp")
app.Ext = "yaml"

cfg := config.Defaults[Config]()
sysCfg, _ := config.System[Config](app)
usrCfg, _ := config.User[Config](app)
customCfg, _ := config.Custom[Config]("/extra/config.yaml")
cfg = config.UseConfig(cfg, sysCfg)
cfg = config.UseConfig(cfg, usrCfg)
cfg = config.UseConfig(cfg, customCfg)
cfg = config.CascadeEnv(cfg, config.Env[Config]("MYAPP"))

Verification

cd config && GOWORK=off go build ./...
cd config && GOWORK=off go test -count=1 ./...
cd config && GOWORK=off go vet ./...
## Multi-format support + App API cleanup Extend the standalone `config/` library to support TOML, YAML, and JSON config files. Clean up the `App` API so developers don't need to configure directories. ### Changes **1. App struct cleanup (`core/app.go`)** - Unexport `SystemDir`/`UserDir` → `systemDir`/`userDir` (computed by `New()`) - Add exported `Ext string` field (default `"toml"`) — developer sets this to choose format - `SystemPath()`/`UserPath()` lose their `ext` parameter, use `a.Ext` - `NewWithOptions()` stays but documented as testing-only - `filepath.Join` handles empty group correctly: `filepath.Join("/etc", "", "myapp.toml")` → `/etc/myapp.toml` **2. Rename `ReadFile` → `Custom` (`core/load.go`, `stubs.go`)** - `Custom[T](path string) (T, error)` — explicit path + auto-detect format from extension - Cascade chain: `Defaults → System → User → Custom → Env` - Remove deprecated `Load` function and `Options` type (dead API, no callers) **3. Add YAML and JSON codecs (`core/codec.go`)** - `gopkg.in/yaml.v3` for YAML - `encoding/json` (stdlib) for JSON - Register `.yaml`, `.yml`, `.json` in handler map - Each format: `decode`, `encode`, `decodeRaw` functions **4. Update callers (`core/load.go`, `core/write.go`)** - `System`/`User` call `a.SystemPath()`/`a.UserPath()` (no hardcoded `"toml"`) - `WriteUser`/`WriteSystem` call `a.UserPath()`/`a.SystemPath()` **5. Update docs and tests** - README: document `Ext` field, multi-format, `Custom` in cascade chain - Tests: rename `ReadFile` → `Custom`, add YAML/JSON round-trips ### New usage ```go app := config.New("server", "myapp") app.Ext = "yaml" cfg := config.Defaults[Config]() sysCfg, _ := config.System[Config](app) usrCfg, _ := config.User[Config](app) customCfg, _ := config.Custom[Config]("/extra/config.yaml") cfg = config.UseConfig(cfg, sysCfg) cfg = config.UseConfig(cfg, usrCfg) cfg = config.UseConfig(cfg, customCfg) cfg = config.CascadeEnv(cfg, config.Env[Config]("MYAPP")) ``` ### Verification ```bash cd config && GOWORK=off go build ./... cd config && GOWORK=off go test -count=1 ./... cd config && GOWORK=off go vet ./... ```
Author
Member

Implementation complete

All changes shipped. Summary:

App API cleanup

  • SystemDir/UserDir unexported — computed by New() from /etc and ~/.config
  • Added Ext string field (default "toml") — developer sets format
  • SystemPath()/UserPath() use a.Ext, no parameter needed
  • NewWithOptions() kept for testing only

Multi-format support

  • Added YAML (gopkg.in/yaml.v3) and JSON (encoding/json) codecs
  • Registered .yaml, .yml, .json in handler map
  • System/User/WriteUser/WriteSystem use app.Ext
  • Custom/WriteFile auto-detect from file extension

API rename

  • ReadFileCustom (cascade chain: Defaults → System → User → Custom → Env)
  • Removed deprecated Load function and Options type
  • Removed dead envNameForPath function

Tests

  • 48 tests passing (21 root + 27 core)
  • Added YAML/JSON round-trip tests for Custom, System, User, WriteUser, WriteFile
  • Added path resolution tests for .yaml and .json extensions
  • All existing tests updated to new API

Files changed

  • core/app.go — unexported dirs, added Ext, updated path methods
  • core/codec.go — added YAML/JSON handlers
  • core/load.go — renamed ReadFile→Custom, removed deprecated API
  • core/write.go — use app.Ext for paths
  • stubs.go — updated re-exports
  • config.go — updated package doc
  • cmd/res-validate-config/main.go — ReadFile→Custom
  • go.mod/go.sum — added gopkg.in/yaml.v3
  • load_test.go — updated + new YAML/JSON tests
  • write_test.go — updated + new YAML/JSON tests
  • README.md — rewritten with multi-format docs

Verification

go build, go test (48/48 pass), go vet all clean.

## Implementation complete All changes shipped. Summary: ### App API cleanup - `SystemDir`/`UserDir` unexported — computed by `New()` from `/etc` and `~/.config` - Added `Ext string` field (default `"toml"`) — developer sets format - `SystemPath()`/`UserPath()` use `a.Ext`, no parameter needed - `NewWithOptions()` kept for testing only ### Multi-format support - Added YAML (`gopkg.in/yaml.v3`) and JSON (`encoding/json`) codecs - Registered `.yaml`, `.yml`, `.json` in handler map - `System`/`User`/`WriteUser`/`WriteSystem` use `app.Ext` - `Custom`/`WriteFile` auto-detect from file extension ### API rename - `ReadFile` → `Custom` (cascade chain: Defaults → System → User → Custom → Env) - Removed deprecated `Load` function and `Options` type - Removed dead `envNameForPath` function ### Tests - 48 tests passing (21 root + 27 core) - Added YAML/JSON round-trip tests for Custom, System, User, WriteUser, WriteFile - Added path resolution tests for `.yaml` and `.json` extensions - All existing tests updated to new API ### Files changed - `core/app.go` — unexported dirs, added Ext, updated path methods - `core/codec.go` — added YAML/JSON handlers - `core/load.go` — renamed ReadFile→Custom, removed deprecated API - `core/write.go` — use app.Ext for paths - `stubs.go` — updated re-exports - `config.go` — updated package doc - `cmd/res-validate-config/main.go` — ReadFile→Custom - `go.mod`/`go.sum` — added gopkg.in/yaml.v3 - `load_test.go` — updated + new YAML/JSON tests - `write_test.go` — updated + new YAML/JSON tests - `README.md` — rewritten with multi-format docs ### Verification `go build`, `go test` (48/48 pass), `go vet` all clean.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
residual/.agent#23
No description provided.