Skip to content

Commit b75b919

Browse files
authored
feat: Add JSON "codegen" output (#1565)
* feat: Add JSON codegen output
1 parent b6ebb42 commit b75b919

File tree

13 files changed

+1193
-263
lines changed

13 files changed

+1193
-263
lines changed

internal/cmd/generate.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"strings"
1313

1414
"github.com/kyleconroy/sqlc/internal/codegen/golang"
15+
"github.com/kyleconroy/sqlc/internal/codegen/json"
1516
"github.com/kyleconroy/sqlc/internal/codegen/kotlin"
1617
"github.com/kyleconroy/sqlc/internal/codegen/python"
1718
"github.com/kyleconroy/sqlc/internal/compiler"
@@ -138,6 +139,12 @@ func Generate(ctx context.Context, e Env, dir, filename string, stderr io.Writer
138139
Gen: config.SQLGen{Python: sql.Gen.Python},
139140
})
140141
}
142+
if sql.Gen.JSON != nil {
143+
pairs = append(pairs, outPair{
144+
SQL: sql,
145+
Gen: config.SQLGen{JSON: sql.Gen.JSON},
146+
})
147+
}
141148
}
142149

143150
for _, sql := range pairs {
@@ -205,6 +212,9 @@ func Generate(ctx context.Context, e Env, dir, filename string, stderr io.Writer
205212
case sql.Gen.Python != nil:
206213
out = combo.Python.Out
207214
genfunc = python.Generate
215+
case sql.Gen.JSON != nil:
216+
out = combo.JSON.Out
217+
genfunc = json.Generate
208218
default:
209219
panic("missing language backend")
210220
}

internal/cmd/shim.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ func pluginSettings(cs config.CombinedSettings) *plugin.Settings {
5959
Python: pluginPythonCode(cs.Python),
6060
Kotlin: pluginKotlinCode(cs.Kotlin),
6161
Go: pluginGoCode(cs.Go),
62+
Json: pluginJSONCode(cs.JSON),
6263
}
6364
}
6465

@@ -124,6 +125,13 @@ func pluginKotlinCode(s config.SQLKotlin) *plugin.KotlinCode {
124125
}
125126
}
126127

128+
func pluginJSONCode(s config.SQLJSON) *plugin.JSONCode {
129+
return &plugin.JSONCode{
130+
Out: s.Out,
131+
Indent: s.Indent,
132+
}
133+
}
134+
127135
func pluginCatalog(c *catalog.Catalog) *plugin.Catalog {
128136
var schemas []*plugin.Schema
129137
for _, s := range c.Schemas {

internal/codegen/json/gen.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package json
2+
3+
import (
4+
ejson "encoding/json"
5+
6+
"google.golang.org/protobuf/encoding/protojson"
7+
8+
"github.com/kyleconroy/sqlc/internal/plugin"
9+
)
10+
11+
func Generate(req *plugin.CodeGenRequest) (*plugin.CodeGenResponse, error) {
12+
indent := ""
13+
if req.Settings != nil && req.Settings.Json != nil {
14+
indent = req.Settings.Json.Indent
15+
}
16+
// The output of protojson has randomized whitespace
17+
// https://github.com/golang/protobuf/issues/1082
18+
m := &protojson.MarshalOptions{
19+
EmitUnpopulated: true,
20+
Indent: "",
21+
UseProtoNames: true,
22+
}
23+
data, err := m.Marshal(req)
24+
if err != nil {
25+
return nil, err
26+
}
27+
var rm ejson.RawMessage = data
28+
blob, err := ejson.MarshalIndent(rm, "", indent)
29+
if err != nil {
30+
return nil, err
31+
}
32+
return &plugin.CodeGenResponse{
33+
Files: []*plugin.File{
34+
{
35+
Name: "codegen_request.json",
36+
Contents: append(blob, '\n'),
37+
},
38+
},
39+
}, nil
40+
}

internal/config/config.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ type SQLGen struct {
114114
Go *SQLGo `json:"go,omitempty" yaml:"go"`
115115
Kotlin *SQLKotlin `json:"kotlin,omitempty" yaml:"kotlin"`
116116
Python *SQLPython `json:"python,omitempty" yaml:"python"`
117+
JSON *SQLJSON `json:"json,omitempty" yaml:"json"`
117118
}
118119

119120
type SQLGo struct {
@@ -155,6 +156,11 @@ type SQLPython struct {
155156
EmitPydanticModels bool `json:"emit_pydantic_models,omitempty" yaml:"emit_pydantic_models"`
156157
}
157158

159+
type SQLJSON struct {
160+
Out string `json:"out" yaml:"out"`
161+
Indent string `json:"indent,omitempty" yaml:"indent"`
162+
}
163+
158164
type Override struct {
159165
// name of the golang type to use, e.g. `github.com/segmentio/ksuid.KSUID`
160166
GoType GoType `json:"go_type" yaml:"go_type"`
@@ -352,6 +358,7 @@ type CombinedSettings struct {
352358
Go SQLGo
353359
Kotlin SQLKotlin
354360
Python SQLPython
361+
JSON SQLJSON
355362
Rename map[string]string
356363
Overrides []Override
357364
}
@@ -379,5 +386,8 @@ func Combine(conf Config, pkg SQL) CombinedSettings {
379386
cs.Python = *pkg.Gen.Python
380387
cs.Overrides = append(cs.Overrides, pkg.Gen.Python.Overrides...)
381388
}
389+
if pkg.Gen.JSON != nil {
390+
cs.JSON = *pkg.Gen.JSON
391+
}
382392
return cs
383393
}

internal/config/v_two.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ func v2ParseConfig(rd io.Reader) (Config, error) {
7575
}
7676
}
7777
}
78+
if conf.SQL[j].Gen.JSON != nil {
79+
if conf.SQL[j].Gen.JSON.Out == "" {
80+
return conf, ErrNoOutPath
81+
}
82+
}
7883
}
7984
return conf, nil
8085
}

internal/endtoend/endtoend_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,10 @@ func cmpDirectory(t *testing.T, dir string, actual map[string]string) {
116116
if file.IsDir() {
117117
return nil
118118
}
119-
if !strings.HasSuffix(path, ".go") && !strings.HasSuffix(path, ".kt") && !strings.HasSuffix(path, ".py") {
119+
if !strings.HasSuffix(path, ".go") && !strings.HasSuffix(path, ".kt") && !strings.HasSuffix(path, ".py") && !strings.HasSuffix(path, ".json") {
120+
return nil
121+
}
122+
if filepath.Base(path) == "sqlc.json" {
120123
return nil
121124
}
122125
if strings.Contains(path, "/kotlin/build") {
@@ -126,7 +129,8 @@ func cmpDirectory(t *testing.T, dir string, actual map[string]string) {
126129
return nil
127130
}
128131
if strings.Contains(path, "/python/.venv") || strings.Contains(path, "/python/src/tests/") ||
129-
strings.HasSuffix(path, "__init__.py") || strings.Contains(path, "/python/src/dbtest/") {
132+
strings.HasSuffix(path, "__init__.py") || strings.Contains(path, "/python/src/dbtest/") ||
133+
strings.Contains(path, "/python/.mypy_cache") {
130134
return nil
131135
}
132136
blob, err := os.ReadFile(path)

0 commit comments

Comments
 (0)