Skip to content

Commit

Permalink
APIS-7864 (#151)
Browse files Browse the repository at this point in the history
  • Loading branch information
mmandolesi-g authored Sep 11, 2024
1 parent 0a0f31a commit 44c4442
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 3 deletions.
2 changes: 2 additions & 0 deletions generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
)

const disclaimer = "// Code generated by github.com/GannettDigital/jstransform; DO NOT EDIT."
const scalarAny = "scalar Any"
const msgpSuffix = "_msgp"
const msgpMode = gen.Encode | gen.Decode | gen.Marshal | gen.Unmarshal | gen.Size | gen.Test

Expand Down Expand Up @@ -60,6 +61,7 @@ type BuildArgs struct {
FieldNameMap map[string]string
GraphQLTypeNameMap map[string]string // Changes the "type ABC" name of GraphQL schema.
EmbedAllOf bool
ScalarAny bool
}

// BuildStructs is a backward-compatibility wrapper for BuildStructsWithArgs.
Expand Down
22 changes: 21 additions & 1 deletion generate/graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ func buildGraphQLFile(schemaPath, name, packageName string, args BuildArgs) erro
return fmt.Errorf("failed writing GraphQL: %w", err)
}

if args.ScalarAny {
if _, err := fmt.Fprintf(gfile, "\n%s\n", scalarAny); err != nil {
return fmt.Errorf("failed writing GraphQL: %w", err)
}
}

if !filepath.IsAbs(schemaPath) {
schemaPath = filepath.Join(filepath.Dir(args.SchemaPath), schemaPath)
}
Expand Down Expand Up @@ -475,6 +481,13 @@ func (gof *goGQL) walkFunc(path string, i jsonschema.Instance) error {
gqlTypeList = append(gqlTypeList, "null")
}

// Special case for when the properties field of an object is `{}`. Put `Any` instead of the struct name and
// ignore the empty child struct.
if len(i.Properties) == 0 {
gqlTypeList = []string{"Any"}
obj.buildType = "ignored"
}

return gen.addField([]string{name}, gqlTypeList, jsonschema.Instance{Description: i.Description, Type: []string{structType}, Target: i.Target, GraphQLArguments: i.GraphQLArguments})
}

Expand Down Expand Up @@ -653,6 +666,11 @@ func (gen *gqlExtractedField) addField(tree []string, gqlTypeName []string, inst
gen.fieldOrder = append(gen.fieldOrder, totalName)
gen.requiredFields[totalName] = true
case "object":
// Special case for when the properties field of an object is `{}`. Put `Any` instead of an empty field name.
if len(inst.Properties) == 0 {
f.jsonType = "Any"
}

f.requiredFields = make(map[string]bool, len(inst.Required))
for _, name := range inst.Required {
f.requiredFields[name] = true
Expand Down Expand Up @@ -702,7 +720,9 @@ func (ef *gqlExtractedField) graphqlType(required, pointers bool) (string, strin
graphqlType = ef.jsonType
}
if graphqlType != "DateTime" && (regularType && !ef.nullable || required || !pointers) {
graphqlType += "!"
if ef.jsonType != "Any" {
graphqlType += "!"
}
}

var graphqlArguments string
Expand Down
11 changes: 9 additions & 2 deletions generate/graphql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package generate
// For now a direct copy of 'struct_test.go' tests.
import (
"bytes"
"encoding/json"
"os"
"reflect"
"strings"
Expand Down Expand Up @@ -77,7 +78,10 @@ func TestGraphQLAddField(t *testing.T) {
description: "Struct field",
fields: make(map[string]*gqlExtractedField),
tree: []string{"structfield"},
instance: jsonschema.Instance{Type: []string{"object"}},
instance: jsonschema.Instance{
Type: []string{"object"},
Properties: map[string]json.RawMessage{"test": nil},
},
want: gqlExtractedFields{
"structfield": &gqlExtractedField{
name: "Structfield",
Expand Down Expand Up @@ -375,8 +379,9 @@ func TestGraphQLGeneratedStruct(t *testing.T) {
}

if !reflect.DeepEqual(got, want) {
_ = os.WriteFile(test.wantFilePath+".got", got, 0600)
t.Errorf("Test %q\nwant: %s\ngot: %s", test.description, want, got)
t.Errorf("Test %q\nwant: %v\ngot: %v", test.description, []byte(want), []byte(got))
t.Errorf("Test %q\nwant: %v\ngot: %v", test.description, want, got)
lwant := strings.Split(string(want), "\n")
lgot := strings.Split(string(got), "\n")
for idx := range lwant {
Expand All @@ -385,6 +390,8 @@ func TestGraphQLGeneratedStruct(t *testing.T) {
t.Logf("line %d\nwant: %v\ngot: %v", idx, []byte(lwant[idx]), []byte(lgot[idx]))
}
}
} else {
_ = os.Remove(test.wantFilePath + ".got")
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions generate/graphql_test_data/complex.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ interface Complex @goModel(model: ".Complex") {

datePhotoTaken: DateTime

"empty map"
inlineLink: Any

orientation: String!

originalSize (! {
Expand Down
7 changes: 7 additions & 0 deletions generate/graphql_test_data/complex.json
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,13 @@
]
}
}
},
"inlineLink": {
"$id":"/properties/attributes/properties/inlineLink",
"type": "object",
"description": "empty map",
"additionalProperties": true,
"properties": {}
}
},
"required": [
Expand Down
3 changes: 3 additions & 0 deletions generate/graphql_test_data/nonest/complex.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ interface Complex @goModel(model: ".Complex") {

datePhotoTaken: DateTime

"empty map"
inlineLink: Any

orientation: String!

originalSize: ComplexOriginalSize!
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func main() {
genAvro := flag.Bool("avro", false, "generate Avro schema and serialization methods")
genMessagePack := flag.Bool("msgp", false, "generate MessagePack serialization methods")
genGraphQL := flag.Bool("graphql", false, "generate GraphQL schema")
scalarAny := flag.Bool("scalarAny", false, "write `scalar Any` to the top of the graphql file")
outputPathGraphQL := flag.String("outputPathGraphQL", "", "The output path where to write GraphQL schema.")
importPath := flag.String("importPath", "", "The import path used as the base for generated code, required for Avro")

Expand Down Expand Up @@ -107,6 +108,7 @@ func main() {
FieldNameMap: renameFields.kv,
GraphQLTypeNameMap: renameGQLType.kv,
EmbedAllOf: *embedAllOf,
ScalarAny: *scalarAny,
}); err != nil {
fmt.Printf("Golang Struct generation failed: %v\n", err)
os.Exit(4)
Expand Down

0 comments on commit 44c4442

Please sign in to comment.