File: dotenv.go

package info (click to toggle)
golang-github-knadh-koanf 2.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 808 kB
  • sloc: sh: 31; makefile: 14
file content (93 lines) | stat: -rw-r--r-- 2,037 bytes parent folder | download
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
}