1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
// Package dotenv implements a koanf.Parser that parses DOTENV bytes as conf maps.
package dotenv
import (
"fmt"
"strings"
"github.com/joho/godotenv"
"github.com/knadh/koanf/maps"
)
// DotEnv implements a DOTENV parser.
type DotEnv struct {
delim string
prefix string
cb func(key string, value string) (string, interface{})
reverseCB map[string]string
}
// Parser returns a DOTENV Parser.
func Parser() *DotEnv {
return &DotEnv{}
}
// ParserEnv allows to make the DOTENV Parser behave like the env.Provider.
func ParserEnv(prefix, delim string, cb func(s string) string) *DotEnv {
return &DotEnv{
delim: delim,
prefix: prefix,
cb: func(key, value string) (string, interface{}) {
return cb(key), value
},
reverseCB: make(map[string]string),
}
}
// Unmarshal parses the given DOTENV bytes.
func (p *DotEnv) Unmarshal(b []byte) (map[string]interface{}, error) {
// Unmarshal DOTENV from []byte
r, err := godotenv.Unmarshal(string(b))
if err != nil {
return nil, err
}
// Convert a map[string]string to a map[string]interface{}
mp := make(map[string]interface{})
for sourceKey, v := range r {
if !strings.HasPrefix(sourceKey, p.prefix) {
continue
}
if p.cb != nil {
targetKey, value := p.cb(sourceKey, v)
p.reverseCB[targetKey] = sourceKey
mp[targetKey] = value
} else {
mp[sourceKey] = v
}
}
if p.delim != "" {
mp = maps.Unflatten(mp, p.delim)
}
return mp, nil
}
// Marshal marshals the given config map to DOTENV bytes.
func (p *DotEnv) Marshal(o map[string]interface{}) ([]byte, error) {
if p.delim != "" {
o, _ = maps.Flatten(o, nil, p.delim)
}
// Convert a map[string]interface{} to a map[string]string
mp := make(map[string]string)
for targetKey, v := range o {
if sourceKey, found := p.reverseCB[targetKey]; found {
targetKey = sourceKey
}
mp[targetKey] = fmt.Sprint(v)
}
// Unmarshal to string
out, err := godotenv.Marshal(mp)
if err != nil {
return nil, err
}
// Convert to []byte and return
return []byte(out), nil
}
|