Initial commit
This commit is contained in:
66
internal/config/default.go
Normal file
66
internal/config/default.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/spf13/viper"
|
||||
"hub.cybercinch.nz/guisea/go-template/internal/config/key"
|
||||
)
|
||||
|
||||
// fields is the config fields with their default values and descriptions
|
||||
var fields = []*Field{
|
||||
// LOGS
|
||||
{
|
||||
key.LogsWrite,
|
||||
true,
|
||||
"Write logs to file",
|
||||
},
|
||||
{
|
||||
key.LogsLevel,
|
||||
"info",
|
||||
`Logs level.
|
||||
Available options are: (from less to most verbose)
|
||||
fatal, error, warn, info, debug`,
|
||||
},
|
||||
{
|
||||
key.LogsReportCaller,
|
||||
false,
|
||||
"Whether the logger should report the caller location.",
|
||||
},
|
||||
//{
|
||||
// key.TenantId,
|
||||
// "some_client_id",
|
||||
// "The TenantID to use with Xero.",
|
||||
//},
|
||||
//{
|
||||
// key.BankAccountId,
|
||||
// "a-random-bank-account-id",
|
||||
// "Guid for the xero account to use.",
|
||||
//},
|
||||
// END LOGS
|
||||
// BEANSTALK
|
||||
//{
|
||||
// key.BeanstalkServer,
|
||||
// "localhost",
|
||||
// "The Beanstalk Server to use",
|
||||
//},
|
||||
//{
|
||||
// key.BeanstalkPort,
|
||||
// "11300",
|
||||
// "The port to communicate with Beanstalk server",
|
||||
//},
|
||||
//{
|
||||
// key.BeanstalkTube,
|
||||
// "visa-transactions",
|
||||
// "The tube to use to find our transactions in.",
|
||||
//},
|
||||
}
|
||||
|
||||
func setDefaults() {
|
||||
Default = make(map[string]*Field, len(fields))
|
||||
for _, f := range fields {
|
||||
Default[f.Key] = f
|
||||
viper.SetDefault(f.Key, f.DefaultValue)
|
||||
viper.MustBindEnv(f.Key)
|
||||
}
|
||||
}
|
||||
|
||||
var Default map[string]*Field
|
||||
90
internal/config/field.go
Normal file
90
internal/config/field.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/spf13/viper"
|
||||
"hub.cybercinch.nz/guisea/go-template/internal/app"
|
||||
|
||||
"hub.cybercinch.nz/guisea/go-template/internal/color"
|
||||
)
|
||||
|
||||
type Field struct {
|
||||
Key string
|
||||
DefaultValue any
|
||||
Description string
|
||||
}
|
||||
|
||||
// typeName returns the type of the field without reflection
|
||||
func (f *Field) typeName() string {
|
||||
switch f.DefaultValue.(type) {
|
||||
case string:
|
||||
return "string"
|
||||
case int:
|
||||
return "int"
|
||||
case bool:
|
||||
return "bool"
|
||||
case []string:
|
||||
return "[]string"
|
||||
case []int:
|
||||
return "[]int"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
var prettyTemplate = lo.Must(template.New("pretty").Funcs(template.FuncMap{
|
||||
"faint": lipgloss.NewStyle().Faint(true).Render,
|
||||
"bold": lipgloss.NewStyle().Bold(true).Render,
|
||||
"purple": lipgloss.NewStyle().Foreground(color.Purple).Render,
|
||||
"blue": lipgloss.NewStyle().Foreground(color.Blue).Render,
|
||||
"cyan": lipgloss.NewStyle().Foreground(color.Cyan).Render,
|
||||
"value": func(k string) any { return viper.Get(k) },
|
||||
"hl": func(v any) string {
|
||||
switch value := v.(type) {
|
||||
case bool:
|
||||
b := strconv.FormatBool(value)
|
||||
if value {
|
||||
return lipgloss.NewStyle().Foreground(color.Green).Render(b)
|
||||
}
|
||||
|
||||
return lipgloss.NewStyle().Foreground(color.Red).Render(b)
|
||||
case string:
|
||||
return lipgloss.NewStyle().Foreground(color.Yellow).Render(value)
|
||||
default:
|
||||
return fmt.Sprint(value)
|
||||
}
|
||||
},
|
||||
"typename": func(v any) string { return reflect.TypeOf(v).String() },
|
||||
}).Parse(`{{ faint .Description }}
|
||||
{{ blue "Key:" }} {{ purple .Key }}
|
||||
{{ blue "Env:" }} {{ .Env }}
|
||||
{{ blue "Value:" }} {{ hl (value .Key) }}
|
||||
{{ blue "Default:" }} {{ hl (.DefaultValue) }}
|
||||
{{ blue "Type:" }} {{ typename .DefaultValue }}`))
|
||||
|
||||
func (f *Field) Pretty() string {
|
||||
var b strings.Builder
|
||||
|
||||
lo.Must0(prettyTemplate.Execute(&b, f))
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (f *Field) Env() string {
|
||||
env := strings.ToUpper(EnvKeyReplacer.Replace(f.Key))
|
||||
appPrefix := strings.ToUpper(app.Name + "_")
|
||||
|
||||
if strings.HasPrefix(env, appPrefix) {
|
||||
return env
|
||||
}
|
||||
|
||||
return appPrefix + env
|
||||
}
|
||||
38
internal/config/init.go
Normal file
38
internal/config/init.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"hub.cybercinch.nz/guisea/go-template/internal/app"
|
||||
"hub.cybercinch.nz/guisea/go-template/internal/filesystem"
|
||||
"hub.cybercinch.nz/guisea/go-template/internal/where"
|
||||
)
|
||||
|
||||
// ConfigFormat is the format of the config file
|
||||
// Available options are: json, yaml, toml
|
||||
const ConfigFormat = "yaml"
|
||||
|
||||
var EnvKeyReplacer = strings.NewReplacer(".", "_")
|
||||
|
||||
func Init() error {
|
||||
viper.SetConfigName(app.Name)
|
||||
viper.SetConfigType(ConfigFormat)
|
||||
viper.SetFs(filesystem.Api())
|
||||
viper.AddConfigPath(where.Config())
|
||||
viper.SetTypeByDefaultValue(true)
|
||||
viper.SetEnvPrefix(app.Name)
|
||||
viper.SetEnvKeyReplacer(EnvKeyReplacer)
|
||||
|
||||
setDefaults()
|
||||
|
||||
err := viper.ReadInConfig()
|
||||
|
||||
switch err.(type) {
|
||||
case viper.ConfigFileNotFoundError:
|
||||
// Use defaults then
|
||||
return nil
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
7
internal/config/key/keys.go
Normal file
7
internal/config/key/keys.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package key
|
||||
|
||||
const (
|
||||
LogsWrite = "logs.write"
|
||||
LogsLevel = "logs.level"
|
||||
LogsReportCaller = "logs.show_caller"
|
||||
)
|
||||
Reference in New Issue
Block a user