-
Notifications
You must be signed in to change notification settings - Fork 8
/
conflate.go
167 lines (131 loc) · 3.71 KB
/
conflate.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
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package conflate
import (
"net/url"
)
// Includes is used to specify the top level key that holds the includes array.
var Includes = "includes"
// Conflate contains a 'working' merged data set and optionally a JSON v4 schema.
type Conflate struct {
data interface{}
loader loader
}
// New constructs a new empty Conflate instance.
func New() *Conflate {
initFormatCheckers()
return &Conflate{
loader: loader{
newFiledata: newFiledata,
},
}
}
// FromFiles constructs a new Conflate instance populated with the data from the given files.
func FromFiles(paths ...string) (*Conflate, error) {
c := New()
err := c.AddFiles(paths...)
if err != nil {
return nil, err
}
return c, nil
}
// FromURLs constructs a new Conflate instance populated with the data from the given URLs.
func FromURLs(urls ...*url.URL) (*Conflate, error) {
c := New()
err := c.AddURLs(urls...)
if err != nil {
return nil, err
}
return c, nil
}
// FromData constructs a new Conflate instance populated with the given data.
func FromData(data ...[]byte) (*Conflate, error) {
c := New()
err := c.AddData(data...)
if err != nil {
return nil, err
}
return c, nil
}
// FromGo constructs a new Conflate instance populated with the given golang objects.
func FromGo(data ...interface{}) (*Conflate, error) {
c := New()
err := c.AddGo(data...)
if err != nil {
return nil, err
}
return c, nil
}
// Expand is an option to automatically expand environment variables in data files.
func (c *Conflate) Expand(expand bool) {
if expand {
c.loader.newFiledata = newExpandedFiledata
} else {
c.loader.newFiledata = newFiledata
}
}
// AddFiles recursively merges the data from the given files into the Conflate instance.
func (c *Conflate) AddFiles(paths ...string) error {
urls, err := toURLs(nil, paths...)
if err != nil {
return err
}
return c.AddURLs(urls...)
}
// AddURLs recursively merges the data from the given urls into the Conflate instance.
func (c *Conflate) AddURLs(urls ...*url.URL) error {
data, err := c.loader.loadURLsRecursive(nil, urls...)
if err != nil {
return err
}
return c.mergeData(data...)
}
// AddGo recursively merges the given (json-serializable) golang objects into the Conflate instance.
func (c *Conflate) AddGo(objs ...interface{}) error {
data, err := jsonMarshalAll(objs...)
if err != nil {
return err
}
return c.AddData(data...)
}
// AddData recursively merges the given data into the Conflate instance.
func (c *Conflate) AddData(data ...[]byte) error {
fdata, err := c.loader.wrapFiledatas(data...)
if err != nil {
return err
}
return c.addData(fdata...)
}
// ApplyDefaults sets any nil or missing values in the data, to the default values defined in the JSON v4 schema.
func (c *Conflate) ApplyDefaults(s *Schema) error {
return s.ApplyDefaults(&c.data)
}
// Validate checks the data against the JSON v4 schema.
func (c *Conflate) Validate(s *Schema) error {
return s.Validate(c.data)
}
// Unmarshal extracts the data as a Golang object.
func (c *Conflate) Unmarshal(out interface{}) error {
return jsonMarshalUnmarshal(c.data, out)
}
// MarshalJSON exports the data as JSON.
func (c *Conflate) MarshalJSON() ([]byte, error) {
return jsonMarshal(c.data)
}
// MarshalYAML exports the data as YAML.
func (c *Conflate) MarshalYAML() ([]byte, error) {
return yamlMarshal(c.data)
}
// MarshalTOML exports the data as TOML.
func (c *Conflate) MarshalTOML() ([]byte, error) {
return tomlMarshal(c.data)
}
func (c *Conflate) addData(fdata ...filedata) error {
fdata, err := c.loader.loadDataRecursive(nil, fdata...)
if err != nil {
return err
}
return c.mergeData(fdata...)
}
func (c *Conflate) mergeData(fdata ...filedata) error {
doms := filedatas(fdata).objs()
return mergeTo(&c.data, doms...)
}