This commit is contained in:
Lukas Wurzinger 2024-12-04 21:37:26 +01:00
commit 65b8fd210a
7 changed files with 208 additions and 0 deletions

3
.envrc Normal file
View file

@ -0,0 +1,3 @@
source_url "https://raw.githubusercontent.com/cachix/devenv/82c0147677e510b247d8b9165c54f73d32dfd899/direnvrc" "sha256-7u4iDd1nZpxL4tCzmPG0dQgC5V+/44Ba+tHkPob1v2k="
use devenv

6
.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
.devenv*
devenv.local.nix
.direnv
.pre-commit-config.yaml

116
devenv.lock Normal file
View file

@ -0,0 +1,116 @@
{
"nodes": {
"devenv": {
"locked": {
"dir": "src/modules",
"lastModified": 1732896163,
"owner": "cachix",
"repo": "devenv",
"rev": "2c928a199d56191d7a53f29ccafa56238c8ce4e5",
"type": "github"
},
"original": {
"dir": "src/modules",
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1732722421,
"owner": "edolstra",
"repo": "flake-compat",
"rev": "9ed2ac151eada2306ca8c418ebd97807bb08f6ac",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1733212471,
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1733220138,
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "bcb68885668cccec12276bbb379f8f2557aa06ce",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1732021966,
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "3308484d1a443fc5bc92012435d79e80458fe43c",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"devenv": "devenv",
"nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks"
}
}
},
"root": "root",
"version": 7
}

3
devenv.nix Normal file
View file

@ -0,0 +1,3 @@
{
languages.go.enable = true;
}

3
devenv.yaml Normal file
View file

@ -0,0 +1,3 @@
inputs:
nixpkgs:
url: github:NixOS/nixpkgs/nixos-unstable

3
go.mod Normal file
View file

@ -0,0 +1,3 @@
module github.com/lukaswrz/gonfig
go 1.23.3

74
gonfig.go Normal file
View file

@ -0,0 +1,74 @@
// Package gonfig provides utilities for reading, unmarshaling, and validating
// configuration files.
package gonfig
import (
"errors"
"fmt"
"os"
)
// Validator defines an interface for validating a configuration of type T. It
// ensures that the provided configuration meets required constraints.
type Validator[T any] interface {
// Validate checks the provided configuration and returns an error if it is
// invalid.
Validate(config T) []error
}
// ReadConfig reads a configuration file, unmarshals its content into the given
// configuration object, and validates it using the provided validator. If the
// primary path is empty, it searches for the configuration file in the
// fallback paths. The function returns the resolved path to the configuration
// file or a list of errors if the file cannot be located, read, unmarshaled,
// or validated.
func ReadConfig[T any](path string, paths []string, c *T, unmarshal func([]byte, *T) error, validator Validator[T]) (string, []error) {
var err error
path, err = findConfig(path, paths)
if err != nil {
return "", []error{err}
}
content, err := os.ReadFile(path)
if err != nil {
return "", []error{fmt.Errorf("unable to read configuration file %s: %w", path, err)}
}
err = unmarshal(content, c)
if err != nil {
return "", []error{fmt.Errorf("unable to unmarshal configuration file %s: %w", path, err)}
}
return path, validator.Validate(*c)
}
// findConfig determines the path to the configuration file by using the
// provided primary path or searching through a list of fallback paths if the
// primary path is empty. If no valid file is found, or if the specified file is
// inaccessible, an error is returned.
func findConfig(path string, paths []string) (string, error) {
var err error
if path == "" {
for _, p := range paths {
_, err = os.Stat(p)
if err != nil {
continue
}
path = p
}
if path == "" {
return "", errors.New("could not locate configuration file")
}
} else {
_, err = os.Stat(path)
if err != nil {
return "", fmt.Errorf("could not stat configuration file %s: %w", path, err)
}
}
return path, nil
}