-
Notifications
You must be signed in to change notification settings - Fork 2
/
config.go
63 lines (52 loc) · 1.28 KB
/
config.go
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
package fdk
import (
"context"
"encoding/json"
"net/http"
)
// Cfg marks the configuration type parameter. Any config
// type must have a validation method, OK, defined on it.
type Cfg interface {
OK() error
}
// SkipCfg indicates the config is not needed and will skip
// the config loading procedure.
type SkipCfg struct{}
// OK is a noop validation.
func (n SkipCfg) OK() error {
return nil
}
type cfgErr struct {
err error
apiErr APIError
}
func readCfg[T Cfg](ctx context.Context) (T, *cfgErr) {
var cfg T
switch any(cfg).(type) {
// exceptional case, where a func does not need/want a config
// otherwise, we'll decode into the target type
case SkipCfg, *SkipCfg:
return *new(T), nil
}
cfgB, err := loadConfigBytes(ctx)
if err != nil {
return *new(T), &cfgErr{
err: err,
apiErr: APIError{Code: http.StatusInternalServerError, Message: "failed to read config source"},
}
}
err = json.Unmarshal(cfgB, &cfg)
if err != nil {
return *new(T), &cfgErr{
err: err,
apiErr: APIError{Code: http.StatusBadRequest, Message: "failed to unmarshal config into config type"},
}
}
err = cfg.OK()
if err != nil {
return *new(T), &cfgErr{
apiErr: APIError{Code: http.StatusBadRequest, Message: "config is invalid: " + err.Error()},
}
}
return cfg, nil
}