fix(config): align yaml path validation

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-03-31 18:22:59 +00:00
parent 8d29e924e8
commit 2dbb8fb6ba
2 changed files with 43 additions and 0 deletions

View file

@ -106,6 +106,9 @@ func configTypeForPath(path string) (string, error) {
if ext == "" && filepath.Base(path) == ".env" {
return "env", nil
}
if ext == "" {
return "yaml", nil
}
switch ext {
case ".yaml", ".yml":
@ -236,6 +239,13 @@ func (c *Config) Path() string {
// Returns the parsed data as a map, or an error if the file cannot be read or parsed.
// Deprecated: Use Config.LoadFile instead.
func Load(m coreio.Medium, path string) (map[string]any, error) {
switch ext := strings.ToLower(filepath.Ext(path)); ext {
case "", ".yaml", ".yml":
// These paths are safe to treat as YAML sources.
default:
return nil, coreerr.E("config.Load", "unsupported config file type: "+path, nil)
}
content, err := m.Read(path)
if err != nil {
return nil, coreerr.E("config.Load", "failed to read config file: "+path, err)

View file

@ -239,6 +239,15 @@ func TestLoad_Bad(t *testing.T) {
assert.Contains(t, err.Error(), "failed to read config file")
}
func TestLoad_UnsupportedPath_Bad(t *testing.T) {
m := coreio.NewMockMedium()
m.Files["/tmp/test/config.json"] = `{"app":{"name":"core"}}`
_, err := Load(m, "/tmp/test/config.json")
assert.Error(t, err)
assert.Contains(t, err.Error(), "unsupported config file type")
}
func TestLoad_InvalidYAML_Bad(t *testing.T) {
m := coreio.NewMockMedium()
m.Files["/tmp/test/config.yaml"] = "invalid: yaml: content: [[[["
@ -261,6 +270,19 @@ func TestConfig_LoadFile_JSON_Good(t *testing.T) {
assert.Equal(t, "core", name)
}
func TestConfig_LoadFile_Extensionless_Good(t *testing.T) {
m := coreio.NewMockMedium()
m.Files["/tmp/test/config"] = "app:\n name: core\n"
cfg, err := New(WithMedium(m), WithPath("/tmp/test/config"))
assert.NoError(t, err)
var name string
err = cfg.Get("app.name", &name)
assert.NoError(t, err)
assert.Equal(t, "core", name)
}
func TestConfig_LoadFile_TOML_Good(t *testing.T) {
m := coreio.NewMockMedium()
m.Files["/tmp/test/config.toml"] = "app = { name = \"core\" }\n"
@ -312,6 +334,17 @@ func TestSave_Good(t *testing.T) {
assert.Contains(t, content, "key: value")
}
func TestSave_Extensionless_Good(t *testing.T) {
m := coreio.NewMockMedium()
err := Save(m, "/tmp/test/config", map[string]any{"key": "value"})
assert.NoError(t, err)
content, readErr := m.Read("/tmp/test/config")
assert.NoError(t, readErr)
assert.Contains(t, content, "key: value")
}
func TestSave_UnsupportedPath_Bad(t *testing.T) {
m := coreio.NewMockMedium()