feat: smart config
This commit is contained in:
7
internal/config/admin.go
Normal file
7
internal/config/admin.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
type AdminConfig struct {
|
||||||
|
Name string `env:"GUARD_ADMIN_NAME" default:"Admin"`
|
||||||
|
Email string `env:"GUARD_ADMIN_EMAIL" required:"true"`
|
||||||
|
Password string `env:"GUARD_ADMIN_PASSWORD" required:"true"`
|
||||||
|
}
|
8
internal/config/jwt.go
Normal file
8
internal/config/jwt.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
type JwtConfig struct {
|
||||||
|
PrivateKey string `env:"GUARD_JWT_PRIVATE" required:"true"`
|
||||||
|
PublicKey string `env:"GUARD_JWT_PUBLIC" required:"true"`
|
||||||
|
KID string `env:"GUARD_JWT_KID" default:"guard-rsa"`
|
||||||
|
Issuer string `env:"GUARD_JWT_ISSUER" required:"true"`
|
||||||
|
}
|
7
internal/config/minio.go
Normal file
7
internal/config/minio.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
type MinioConfig struct {
|
||||||
|
Endpoint string `env:"GUARD_MINIO_ENDPOINT" default:"localhost:9000"`
|
||||||
|
AccessKey string `env:"GUARD_MINIO_ACCESS_KEY" required:"true"`
|
||||||
|
SecretKey string `env:"GUARD_MINIO_SECRET_KEY" required:"true"`
|
||||||
|
}
|
98
internal/config/mod.go
Normal file
98
internal/config/mod.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AppConfig struct {
|
||||||
|
Port string `env:"GUARD_PORT" default:"3001"`
|
||||||
|
Host string `env:"GUARD_HOST" default:"127.0.0.1"`
|
||||||
|
DatabaseURL string `env:"GUARD_DB_URL" required:"true"`
|
||||||
|
Admin AdminConfig
|
||||||
|
Jwt JwtConfig
|
||||||
|
Minio MinioConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadEnv(target any) error {
|
||||||
|
v := reflect.ValueOf(target)
|
||||||
|
if v.Kind() != reflect.Pointer || v.Elem().Kind() != reflect.Struct {
|
||||||
|
return &InvalidTargetError{}
|
||||||
|
}
|
||||||
|
return loadStruct(v.Elem(), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
type InvalidTargetError struct{}
|
||||||
|
|
||||||
|
func (e *InvalidTargetError) Error() string {
|
||||||
|
return "target must be a pointer to a struct"
|
||||||
|
}
|
||||||
|
|
||||||
|
var ErrMissingRequiredEnv = errors.New("missing required environment variable")
|
||||||
|
|
||||||
|
func loadStruct(v reflect.Value, prefix string) error {
|
||||||
|
t := v.Type()
|
||||||
|
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
field := t.Field(i)
|
||||||
|
valueField := v.Field(i)
|
||||||
|
|
||||||
|
if !valueField.CanSet() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
envKey := field.Tag.Get("env")
|
||||||
|
if envKey == "" {
|
||||||
|
envKey = strings.ToUpper(prefix + "_" + field.Name)
|
||||||
|
envKey = strings.TrimPrefix(envKey, "_")
|
||||||
|
}
|
||||||
|
|
||||||
|
required := field.Tag.Get("required") == "true"
|
||||||
|
defaultVal := field.Tag.Get("default")
|
||||||
|
|
||||||
|
if field.Type.Kind() == reflect.Struct {
|
||||||
|
err := loadStruct(valueField, envKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
envVal := os.Getenv(envKey)
|
||||||
|
|
||||||
|
if envVal == "" {
|
||||||
|
if defaultVal != "" {
|
||||||
|
envVal = defaultVal
|
||||||
|
} else if required {
|
||||||
|
return fmt.Errorf("%w: %s", ErrMissingRequiredEnv, envKey)
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch field.Type.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
valueField.SetString(envVal)
|
||||||
|
case reflect.Int, reflect.Int64:
|
||||||
|
i, err := strconv.ParseInt(envVal, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid int for %s: %w", envKey, err)
|
||||||
|
}
|
||||||
|
valueField.SetInt(i)
|
||||||
|
case reflect.Bool:
|
||||||
|
b, err := strconv.ParseBool(envVal)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid bool for %s: %w", envKey, err)
|
||||||
|
}
|
||||||
|
valueField.SetBool(b)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported type for field %s", field.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Reference in New Issue
Block a user