Skip to content

Commit 0303c6e

Browse files
committed
feat: improves golang app-config generation, adds 'no-singleton' option
1 parent f7a8966 commit 0303c6e

File tree

3 files changed

+181
-27
lines changed

3 files changed

+181
-27
lines changed

app-config/src/__snapshots__/generate.test.ts.snap

Lines changed: 120 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,44 +14,48 @@ Array [
1414
]
1515
`;
1616
17-
exports[`Golang File Generation creates a simple Go file 1`] = `
17+
exports[`Golang File Generation creates a Go file without singleton 1`] = `
1818
Array [
1919
"// @generated by app-config",
2020
"",
2121
"package main",
2222
"",
2323
"import (",
2424
" \\"encoding/json\\"",
25+
" \\"errors\\"",
26+
" \\"fmt\\"",
2527
" \\"log\\"",
2628
" \\"os\\"",
2729
"",
2830
" \\"github.com/xeipuuv/gojsonschema\\"",
2931
")",
3032
"",
31-
"var config Configuration",
33+
"func LoadConfig() (Configuration, error) {",
34+
" var loadedConfig Configuration",
35+
" var loadedSchema map[string]interface{}",
36+
" var err error",
3237
"",
33-
"func init() {",
3438
" configText := os.Getenv(\\"APP_CONFIG\\")",
3539
" schemaText := os.Getenv(\\"APP_CONFIG_SCHEMA\\")",
3640
"",
3741
" if configText == \\"\\" {",
38-
" log.Panic(\\"The APP_CONFIG environment variable was not set\\")",
42+
" return loadedConfig, errors.New(\\"The APP_CONFIG environment variable was not set\\")",
3943
" }",
4044
"",
4145
" if schemaText == \\"\\" {",
42-
" log.Panic(\\"The APP_CONFIG_SCHEMA environment variable was not set\\")",
46+
" return loadedConfig, errors.New(\\"The APP_CONFIG_SCHEMA environment variable was not set\\")",
4347
" }",
4448
"",
45-
" loadedSchema, err := UnmarshalConfig([]byte(schemaText))",
49+
" err = json.Unmarshal([]byte(schemaText), &loadedSchema)",
4650
"",
4751
" if err != nil {",
48-
" log.Panic(\\"Could not parse APP_CONFIG_SCHEMA environment variable: \\", err)",
52+
" return loadedConfig, fmt.Errorf(\\"Could not parse APP_CONFIG_SCHEMA environment variable: %s\\", err.Error())",
4953
" }",
5054
"",
51-
" loadedConfig, err := UnmarshalConfig([]byte(configText))",
55+
" err = json.Unmarshal([]byte(configText), &loadedConfig)",
5256
"",
5357
" if err != nil {",
54-
" log.Panic(\\"Could not parse APP_CONFIG environment variable: \\", err)",
58+
" return loadedConfig, fmt.Errorf(\\"Could not parse APP_CONFIG environment variable: %s\\", err.Error())",
5559
" }",
5660
"",
5761
" schemaLoader := gojsonschema.NewGoLoader(loadedSchema)",
@@ -60,15 +64,66 @@ Array [
6064
" result, err := gojsonschema.Validate(schemaLoader, documentLoader)",
6165
"",
6266
" if err != nil {",
63-
" log.Panic(\\"Could not validate app-config: \\", err.Error())",
67+
" return loadedConfig, fmt.Errorf(\\"Could not validate App Config: %s\\", err.Error())",
6468
" }",
6569
"",
6670
" if !result.Valid() {",
71+
" errors := \\"\\"",
72+
"",
6773
" for _, desc := range result.Errors() {",
68-
" log.Printf(\\"- %s\\\\n\\", desc)",
74+
" if errors == \\"\\" {",
75+
" errors = fmt.Sprintf(\\"%v\\", desc)",
76+
" } else {",
77+
" errors = fmt.Sprintf(\\"%s, %v\\", errors, desc)",
78+
" }",
6979
" }",
7080
"",
71-
" log.Panic(\\"The app-config value was not valid.\\")",
81+
" return loadedConfig, fmt.Errorf(\\"The App Config value invalid: %s\\", errors)",
82+
" }",
83+
"",
84+
" return loadedConfig, nil",
85+
"}",
86+
"",
87+
"func UnmarshalConfiguration(data []byte) (Configuration, error) {",
88+
" var r Configuration",
89+
" err := json.Unmarshal(data, &r)",
90+
" return r, err",
91+
"}",
92+
"",
93+
"func (r *Configuration) Marshal() ([]byte, error) {",
94+
" return json.Marshal(r)",
95+
"}",
96+
"",
97+
"type Configuration struct {",
98+
" Foo *string \`json:\\"foo,omitempty\\"\`",
99+
"}",
100+
"",
101+
]
102+
`;
103+
104+
exports[`Golang File Generation creates a simple Go file 1`] = `
105+
Array [
106+
"// @generated by app-config",
107+
"",
108+
"package main",
109+
"",
110+
"import (",
111+
" \\"encoding/json\\"",
112+
" \\"errors\\"",
113+
" \\"fmt\\"",
114+
" \\"log\\"",
115+
" \\"os\\"",
116+
"",
117+
" \\"github.com/xeipuuv/gojsonschema\\"",
118+
")",
119+
"",
120+
"var config Configuration",
121+
"",
122+
"func init() {",
123+
" loadedConfig, err := LoadConfig()",
124+
"",
125+
" if err != nil {",
126+
" log.Panic(err.Error())",
72127
" }",
73128
"",
74129
" config = loadedConfig",
@@ -77,6 +132,59 @@ Array [
77132
"func GetConfig() Configuration {",
78133
" return config",
79134
"}",
135+
"func LoadConfig() (Configuration, error) {",
136+
" var loadedConfig Configuration",
137+
" var loadedSchema map[string]interface{}",
138+
" var err error",
139+
"",
140+
" configText := os.Getenv(\\"APP_CONFIG\\")",
141+
" schemaText := os.Getenv(\\"APP_CONFIG_SCHEMA\\")",
142+
"",
143+
" if configText == \\"\\" {",
144+
" return loadedConfig, errors.New(\\"The APP_CONFIG environment variable was not set\\")",
145+
" }",
146+
"",
147+
" if schemaText == \\"\\" {",
148+
" return loadedConfig, errors.New(\\"The APP_CONFIG_SCHEMA environment variable was not set\\")",
149+
" }",
150+
"",
151+
" err = json.Unmarshal([]byte(schemaText), &loadedSchema)",
152+
"",
153+
" if err != nil {",
154+
" return loadedConfig, fmt.Errorf(\\"Could not parse APP_CONFIG_SCHEMA environment variable: %s\\", err.Error())",
155+
" }",
156+
"",
157+
" err = json.Unmarshal([]byte(configText), &loadedConfig)",
158+
"",
159+
" if err != nil {",
160+
" return loadedConfig, fmt.Errorf(\\"Could not parse APP_CONFIG environment variable: %s\\", err.Error())",
161+
" }",
162+
"",
163+
" schemaLoader := gojsonschema.NewGoLoader(loadedSchema)",
164+
" documentLoader := gojsonschema.NewGoLoader(loadedConfig)",
165+
"",
166+
" result, err := gojsonschema.Validate(schemaLoader, documentLoader)",
167+
"",
168+
" if err != nil {",
169+
" return loadedConfig, fmt.Errorf(\\"Could not validate App Config: %s\\", err.Error())",
170+
" }",
171+
"",
172+
" if !result.Valid() {",
173+
" errors := \\"\\"",
174+
"",
175+
" for _, desc := range result.Errors() {",
176+
" if errors == \\"\\" {",
177+
" errors = fmt.Sprintf(\\"%v\\", desc)",
178+
" } else {",
179+
" errors = fmt.Sprintf(\\"%s, %v\\", errors, desc)",
180+
" }",
181+
" }",
182+
"",
183+
" return loadedConfig, fmt.Errorf(\\"The App Config value invalid: %s\\", errors)",
184+
" }",
185+
"",
186+
" return loadedConfig, nil",
187+
"}",
80188
"",
81189
"func UnmarshalConfiguration(data []byte) (Configuration, error) {",
82190
" var r Configuration",

app-config/src/generate.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,22 @@ describe('Golang File Generation', () => {
178178

179179
expect(generated).toMatchSnapshot();
180180
});
181+
182+
it('creates a Go file without singleton', async () => {
183+
const schema = {
184+
type: 'object',
185+
additionalProperties: false,
186+
properties: {
187+
foo: { type: 'string' },
188+
},
189+
} as const;
190+
191+
const generated = await generateQuicktype(schema, 'go', 'Configuration', undefined, undefined, {
192+
'no-singleton': 'true',
193+
});
194+
195+
expect(generated).toMatchSnapshot();
196+
});
181197
});
182198

183199
describe('Rust File Generation', () => {

app-config/src/generate.ts

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ export async function generateQuicktype(
145145
const imports = [
146146
'import (',
147147
' "encoding/json"',
148+
' "errors"',
149+
' "fmt"',
148150
' "log"',
149151
' "os"',
150152
'',
@@ -156,27 +158,47 @@ export async function generateQuicktype(
156158
var config ${name}
157159
158160
func init() {
161+
loadedConfig, err := LoadConfig()
162+
163+
if err != nil {
164+
log.Panic(err.Error())
165+
}
166+
167+
config = loadedConfig
168+
}
169+
170+
func GetConfig() ${name} {
171+
return config
172+
}
173+
`.split('\n');
174+
175+
const loadConfig = stripIndent`
176+
func LoadConfig() (${name}, error) {
177+
var loadedConfig ${name}
178+
var loadedSchema map[string]interface{}
179+
var err error
180+
159181
configText := os.Getenv("APP_CONFIG")
160182
schemaText := os.Getenv("APP_CONFIG_SCHEMA")
161183
162184
if configText == "" {
163-
log.Panic("The APP_CONFIG environment variable was not set")
185+
return loadedConfig, errors.New("The APP_CONFIG environment variable was not set")
164186
}
165187
166188
if schemaText == "" {
167-
log.Panic("The APP_CONFIG_SCHEMA environment variable was not set")
189+
return loadedConfig, errors.New("The APP_CONFIG_SCHEMA environment variable was not set")
168190
}
169191
170-
loadedSchema, err := UnmarshalConfig([]byte(schemaText))
192+
err = json.Unmarshal([]byte(schemaText), &loadedSchema)
171193
172194
if err != nil {
173-
log.Panic("Could not parse APP_CONFIG_SCHEMA environment variable: ", err)
195+
return loadedConfig, fmt.Errorf("Could not parse APP_CONFIG_SCHEMA environment variable: %s", err.Error())
174196
}
175197
176-
loadedConfig, err := UnmarshalConfig([]byte(configText))
198+
err = json.Unmarshal([]byte(configText), &loadedConfig)
177199
178200
if err != nil {
179-
log.Panic("Could not parse APP_CONFIG environment variable: ", err)
201+
return loadedConfig, fmt.Errorf("Could not parse APP_CONFIG environment variable: %s", err.Error())
180202
}
181203
182204
schemaLoader := gojsonschema.NewGoLoader(loadedSchema)
@@ -185,26 +207,34 @@ export async function generateQuicktype(
185207
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
186208
187209
if err != nil {
188-
log.Panic("Could not validate app-config: ", err.Error())
210+
return loadedConfig, fmt.Errorf("Could not validate App Config: %s", err.Error())
189211
}
190212
191213
if !result.Valid() {
214+
errors := ""
215+
192216
for _, desc := range result.Errors() {
193-
log.Printf("- %s\\n", desc)
217+
if errors == "" {
218+
errors = fmt.Sprintf("%v", desc)
219+
} else {
220+
errors = fmt.Sprintf("%s, %v", errors, desc)
221+
}
194222
}
195223
196-
log.Panic("The app-config value was not valid.")
224+
return loadedConfig, fmt.Errorf("The App Config value invalid: %s", errors)
197225
}
198226
199-
config = loadedConfig
200-
}
201-
202-
func GetConfig() ${name} {
203-
return config
227+
return loadedConfig, nil
204228
}
205229
`.split('\n');
206230

207-
lines.splice(importIndex, 1, ...imports, '', ...singleton);
231+
// specify no-singleton to avoid automatic config loading in init() function
232+
if (rendererOptions['no-singleton'] === 'true') {
233+
lines.splice(importIndex, 1, ...imports, '', ...loadConfig);
234+
} else {
235+
lines.splice(importIndex, 1, ...imports, '', ...singleton, ...loadConfig);
236+
}
237+
208238
lines.splice(0, 0, '// @generated by app-config', '');
209239

210240
// get close to gofmt

0 commit comments

Comments
 (0)