...
1 package configx
2
3 import (
4 "encoding/json"
5 "strings"
6
7 "github.com/knadh/koanf/providers/env"
8 "github.com/spf13/cast"
9 "github.com/tidwall/gjson"
10
11 "github.com/ory/x/castx"
12 "github.com/ory/x/jsonschemax"
13 )
14
15 func NewKoanfEnv(prefix string, schema []byte) (*env.Env, error) {
16 id, compiler, err := newCompiler(schema)
17 if err != nil {
18 return nil, err
19 }
20
21 paths, err := jsonschemax.ListPaths(id, compiler)
22 if err != nil {
23 return nil, err
24 }
25
26 decode := func(value string) (v interface{}) {
27 _ = json.Unmarshal([]byte(value), v)
28 return v
29 }
30
31 return env.ProviderWithValue(prefix, ".", func(key string, value string) (string, interface{}) {
32 key = strings.Replace(strings.ToLower(strings.TrimPrefix(key, prefix)), "_", ".", -1)
33 for _, path := range paths {
34 normalized := strings.Replace(path.Name, "_", ".", -1)
35
36 if normalized == key {
37 switch path.TypeHint {
38 case jsonschemax.String:
39 return path.Name, cast.ToString(value)
40 case jsonschemax.Float:
41 return path.Name, cast.ToFloat64(value)
42 case jsonschemax.Int:
43 return path.Name, cast.ToInt64(value)
44 case jsonschemax.Bool:
45 return path.Name, cast.ToBool(value)
46 case jsonschemax.Nil:
47 return path.Name, nil
48 case jsonschemax.BoolSlice:
49 if !gjson.Valid(value) {
50 return path.Name, cast.ToBoolSlice(value)
51 }
52 fallthrough
53 case jsonschemax.StringSlice:
54 if !gjson.Valid(value) {
55 return path.Name, castx.ToStringSlice(value)
56 }
57 fallthrough
58 case jsonschemax.IntSlice:
59 if !gjson.Valid(value) {
60 return path.Name, cast.ToIntSlice(value)
61 }
62 fallthrough
63 case jsonschemax.FloatSlice:
64 if !gjson.Valid(value) {
65 return path.Name, castx.ToFloatSlice(value)
66 }
67 fallthrough
68 case jsonschemax.JSON:
69 return path.Name, decode(value)
70 default:
71 return path.Name, value
72 }
73 }
74 }
75
76 return "", nil
77 }), nil
78 }
79
View as plain text