...
1 package configx
2
3 import (
4 "context"
5 "io/ioutil"
6 "path/filepath"
7 "strings"
8
9 "github.com/knadh/koanf"
10 "github.com/knadh/koanf/parsers/json"
11 "github.com/knadh/koanf/parsers/toml"
12 "github.com/knadh/koanf/parsers/yaml"
13
14 "github.com/ory/x/stringslice"
15
16 "github.com/pkg/errors"
17
18 "github.com/ory/x/watcherx"
19 )
20
21
22 type KoanfFile struct {
23 subKey string
24 path string
25 ctx context.Context
26 parser koanf.Parser
27 }
28
29
30 func NewKoanfFile(ctx context.Context, path string) (*KoanfFile, error) {
31 return NewKoanfFileSubKey(ctx, path, "")
32 }
33
34 func NewKoanfFileSubKey(ctx context.Context, path, subKey string) (*KoanfFile, error) {
35 kf := &KoanfFile{
36 path: filepath.Clean(path),
37 ctx: ctx,
38 subKey: subKey,
39 }
40
41 switch e := filepath.Ext(path); e {
42 case ".toml":
43 kf.parser = toml.Parser()
44 case ".json":
45 kf.parser = json.Parser()
46 case ".yaml", ".yml":
47 kf.parser = yaml.Parser()
48 default:
49 return nil, errors.Errorf("unknown config file extension: %s", e)
50 }
51
52 return kf, nil
53 }
54
55
56 func (f *KoanfFile) ReadBytes() ([]byte, error) {
57 return nil, errors.New("file provider does not support this method")
58 }
59
60
61 func (f *KoanfFile) Read() (map[string]interface{}, error) {
62 fc, err := ioutil.ReadFile(f.path)
63 if err != nil {
64 return nil, errors.WithStack(err)
65 }
66
67 v, err := f.parser.Unmarshal(fc)
68 if err != nil {
69 return nil, errors.WithStack(err)
70 }
71
72 if f.subKey == "" {
73 return v, nil
74 }
75
76 path := strings.Split(f.subKey, Delimiter)
77 for _, k := range stringslice.Reverse(path) {
78 v = map[string]interface{}{
79 k: v,
80 }
81 }
82
83 return v, nil
84 }
85
86
87
88 func (f *KoanfFile) WatchChannel(c watcherx.EventChannel) (watcherx.Watcher, error) {
89 return watcherx.WatchFile(f.ctx, f.path, c)
90 }
91
View as plain text