74 lines
2.2 KiB
Go
74 lines
2.2 KiB
Go
// Package keyvalue provides tools to convert any config struct using go-simpler/env struct
|
|
// tagged configuration structures into a sortable slice of key-values, and a printer to render
|
|
// them as a bash shell script to set the variables from a configuration file.
|
|
package keyvalue
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"reflect"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// KV is a key/value pair.
|
|
type KV struct{ Key, Value string }
|
|
|
|
// KVSlice is a collection of key/value pairs.
|
|
type KVSlice []KV
|
|
|
|
func (kv KVSlice) Len() int { return len(kv) }
|
|
func (kv KVSlice) Less(i, j int) bool { return kv[i].Key < kv[j].Key }
|
|
func (kv KVSlice) Swap(i, j int) { kv[i], kv[j] = kv[j], kv[i] }
|
|
|
|
// EnvKV turns a struct with `env` keys (used with go-simpler/env) into a standard formatted
|
|
// environment variable key/value pair list, one per line. If a pointer to a struct is passed,
|
|
// it will be automatically dereferenced. This allows the composition of the config in this file
|
|
// with an extended form with a customized variant of realy to produce correct environment
|
|
// variables both read and write.
|
|
func EnvKV(cfg any) (m KVSlice) {
|
|
// Handle pointer types by dereferencing them
|
|
v := reflect.ValueOf(cfg)
|
|
if v.Kind() == reflect.Ptr {
|
|
if v.IsNil() {
|
|
return // Return empty slice for nil pointers
|
|
}
|
|
return EnvKV(v.Elem().Interface())
|
|
}
|
|
|
|
t := v.Type()
|
|
for i := 0; i < t.NumField(); i++ {
|
|
k := t.Field(i).Tag.Get("env")
|
|
fieldValue := v.Field(i).Interface()
|
|
var val string
|
|
switch u := fieldValue.(type) {
|
|
case string:
|
|
val = u
|
|
case int, int64, int32, uint64, uint32, bool, time.Duration:
|
|
val = fmt.Sprint(fieldValue)
|
|
case []string:
|
|
if len(u) > 0 {
|
|
val = strings.Join(u, ",")
|
|
}
|
|
}
|
|
// this can happen with embedded structs
|
|
if k == "" {
|
|
continue
|
|
}
|
|
m = append(m, KV{k, val})
|
|
}
|
|
return
|
|
}
|
|
|
|
// PrintEnv renders the key/values of a config struct to a provided io.Writer.
|
|
// If a pointer to a struct is passed, it will be automatically dereferenced.
|
|
func PrintEnv(cfg any, printer io.Writer) {
|
|
_, _ = fmt.Fprintln(printer, "#!/usr/bin/env bash")
|
|
kvs := EnvKV(cfg)
|
|
sort.Sort(kvs)
|
|
for _, v := range kvs {
|
|
_, _ = fmt.Fprintf(printer, "export %s=%s\n", v.Key, v.Value)
|
|
}
|
|
}
|