Skip to content

Commit

Permalink
fix: remove public Query field from go generated types (#6849)
Browse files Browse the repository at this point in the history
* fix: remove public Query field from go generated types

This could cause name clashes and was annoying. Thankfully, there's only
one legitimate need for this field to be public - interfaces.

We can provide a workaround for this with the new `WithGraphQLQuery`
method on generated types, which resets the underlying type, and sets
the query.

Signed-off-by: Justin Chadwell <me@jedevc.com>

* fix: explicitly handle WithGraphQLQuery on top-level Client

Signed-off-by: Justin Chadwell <me@jedevc.com>

---------

Signed-off-by: Justin Chadwell <me@jedevc.com>
  • Loading branch information
jedevc committed Mar 8, 2024
1 parent c1b0b5b commit 80dbb1d
Show file tree
Hide file tree
Showing 5 changed files with 774 additions and 562 deletions.
62 changes: 36 additions & 26 deletions cmd/codegen/generator/go/templates/module_interfaces.go
Expand Up @@ -146,6 +146,7 @@ func (spec *parsedIfaceType) ImplementationCode() (*Statement, error) {
Add(spec.concreteStructDefCode()).Line().Line().
Add(spec.idDefCode()).Line().Line().
Add(spec.loadFromIDMethodCode()).Line().Line().
Add(spec.withGraphQLQuery()).Line().Line().
Add(spec.graphqlTypeMethodCode()).Line().Line().
Add(spec.graphqlIDTypeMethodCode()).Line().Line().
Add(spec.graphqlIDMethodCode()).Line().Line().
Expand Down Expand Up @@ -201,7 +202,7 @@ func (spec *parsedIfaceType) concreteStructCachedFieldName(method *funcTypeSpec)
The struct definition for the concrete implementation of the interface. e.g.:
type customIfaceImpl struct {
Query *querybuilder.Selection
query *querybuilder.Selection
id *CustomIfaceID
str *string
int *int
Expand All @@ -210,7 +211,7 @@ The struct definition for the concrete implementation of the interface. e.g.:
*/
func (spec *parsedIfaceType) concreteStructDefCode() *Statement {
return Type().Id(spec.concreteStructName()).StructFunc(func(g *Group) {
g.Id("Query").Op("*").Qual("querybuilder", "Selection")
g.Id("query").Op("*").Qual("querybuilder", "Selection")
g.Id("id").Op("*").Id(spec.idTypeName())

for _, method := range spec.methods {
Expand All @@ -230,10 +231,11 @@ func (spec *parsedIfaceType) concreteStructDefCode() *Statement {
The Load*FromID method attached to the top-level Client struct for this interface. e.g.:
func LoadCustomIfaceFromID(r *Client, id CustomIfaceID) CustomIface {
q := r.Query.Select("loadTestCustomIfaceFromID")
q = querybuilder.Query().Client(r.GraphQLClient())
q = q.Select("loadTestCustomIfaceFromID")
q = q.Arg("id", id)
return &customIfaceImpl{
Query: q,
query: q,
}
}
*/
Expand All @@ -243,14 +245,32 @@ func (spec *parsedIfaceType) loadFromIDMethodCode() *Statement {
Params(Id("r").Op("*").Id("Client"), Id("id").Id(spec.idTypeName())).
Params(Id(spec.name)).
BlockFunc(func(g *Group) {
g.Id("q").Op(":=").Id("r").Dot("Query").Dot("Select").Call(Lit(loadFromIDGQLFieldName(spec)))
g.Id("q").Op(":=").Id("querybuilder").Dot("Query").Call().Dot("Client").Call(Id("r").Dot("GraphQLClient").Call())
g.Id("q").Op("=").Id("q").Dot("Select").Call(Lit(loadFromIDGQLFieldName(spec)))
g.Id("q").Op("=").Id("q").Dot("Arg").Call(Lit("id"), Id("id"))
g.Return(Op("&").Id(spec.concreteStructName()).Values(Dict{
Id("Query"): Id("q"),
Id("query"): Id("q"),
}))
})
}

/*
The WithGraphQLQuery sets the underlying query for the impl.
func (r *customIfaceImpl) WithGraphQLQuery(q *querybuilder.Selection) CustomIface {
return &customIfaceImpl{query: q}
}
*/
func (spec *parsedIfaceType) withGraphQLQuery() *Statement {
return Func().Params(Id("r").Op("*").Id(spec.concreteStructName())).
Id("WithGraphQLQuery").
Params(Id("q").Op("*").Id("querybuilder").Dot("Selection")).
Params(Id(spec.name)).
BlockFunc(func(g *Group) {
g.Return(Op("&").Id(spec.concreteStructName()).Values(Dict{Id("query"): Id("q")}))
})
}

/*
The XXX_GraphQLType method attached to the concrete implementation of the interface. e.g.:
Expand Down Expand Up @@ -387,7 +407,7 @@ The code for the given interface method's concrete implementation attached to co
implementation struct. e.g.:
func (r *customIfaceImpl) WithSomeArg(ctx context.Context, someArg string) CustomIface {
q := r.Query.Select("withSomeArg")
q := r.query.Select("withSomeArg")
q = q.Arg("someArg", someArg)
// concreteMethodExecuteQueryCode...
Expand Down Expand Up @@ -433,7 +453,7 @@ func (spec *parsedIfaceType) concreteMethodCode(method *funcTypeSpec) (*Statemen
BlockFunc(func(g *Group) {
g.Add(spec.concreteMethodCheckCachedFieldCode(method))

g.Id("q").Op(":=").Id("r").Dot("Query").Dot("Select").Call(Lit(gqlFieldName))
g.Id("q").Op(":=").Id("r").Dot("query").Dot("Select").Call(Lit(gqlFieldName))
for _, argSpec := range method.argSpecs {
if argSpec.typeSpec == nil {
// skip context
Expand All @@ -458,7 +478,7 @@ func (spec *parsedIfaceType) concreteMethodExecuteQueryCode(method *funcTypeSpec
/*
Void return, just need to return error. e.g.:
q := r.Query.Select("void")
q := r.query.Select("void")
var response Void
q = q.Bind(&response)
return q.Execute(ctx)
Expand All @@ -478,7 +498,7 @@ func (spec *parsedIfaceType) concreteMethodExecuteQueryCode(method *funcTypeSpec
/*
Just return the primitive type response + error. e.g.:
q := r.Query.Select("str")
q := r.query.Select("str")
var response string
q = q.Bind(&response)
return response, q.Execute(ctx)
Expand All @@ -499,18 +519,14 @@ func (spec *parsedIfaceType) concreteMethodExecuteQueryCode(method *funcTypeSpec
/*
Just object type with chained query (no error). e.g.:
return &customIfaceImpl{
Query: q,
}
return (&customIfaceImpl{}).WithGraphQLQuery(q)
*/

implTypeCode, err := spec.concreteMethodImplTypeCode(method.returnSpec)
if err != nil {
return nil, fmt.Errorf("failed to generate return type code: %w", err)
}
s.Return(Op("&").Add(implTypeCode).Values(Dict{
Id("Query"): Id("q"),
}))
s.Return(Params(Op("&").Add(implTypeCode).Values()).Dot("WithGraphQLQuery").Call(Id("q")))

case *parsedSliceType:
switch underlyingReturnType := returnType.underlying.(type) {
Expand All @@ -533,7 +549,7 @@ func (spec *parsedIfaceType) concreteMethodExecuteQueryCode(method *funcTypeSpec
id := idResult.Id
results = append(results, &Directory{
Query: q.Query.Root().Select("loadDirectoryFromID").Arg("id", id),
query: q.query.Root().Select("loadDirectoryFromID").Arg("id", id),
})
}
return results, nil
Expand All @@ -560,15 +576,9 @@ func (spec *parsedIfaceType) concreteMethodExecuteQueryCode(method *funcTypeSpec
}
s.Var().Id("results").Index().Add(underlyingReturnTypeCode).Line()
s.For(List(Id("_"), Id("idResult")).Op(":=").Range().Id("idResults")).BlockFunc(func(g *Group) {
g.Id("id").Op(":=").Id("idResult").Dot("Id").Line()
d := Dict{
Id("Query"): Id("r").Dot("Query").Dot("Root").Call().Dot("Select").Call(Lit(loadFromIDQueryName)).Dot("Arg").Call(Lit("id"), Id("id")),
// FIXME: this is a nice optimization, but we can't enable
// it since the private "id" field can only be accessed on
// local structs
// Id("id"): Op("&").Id("id"),
}
g.Id("results").Op("=").Append(Id("results"), Op("&").Add(underlyingImplTypeCode).Values(d))
g.Id("id").Op(":=").Id("idResult").Dot("Id")
query := Id("r").Dot("query").Dot("Root").Call().Dot("Select").Call(Lit(loadFromIDQueryName)).Dot("Arg").Call(Lit("id"), Id("id"))
g.Id("results").Op("=").Append(Id("results"), Params(Op("&").Add(underlyingImplTypeCode).Values()).Dot("WithGraphQLQuery").Call(query))
}).Line()

s.Return(Id("results"), Nil())
Expand Down
Expand Up @@ -115,7 +115,7 @@ func (e *ExecError) Unwrap() error {

{{ if IsModuleCode }}
type Client struct {
Query *querybuilder.Selection
query *querybuilder.Selection
client graphql.Client
}

Expand All @@ -124,7 +124,7 @@ var dag *Client
func init() {
gqlClient, q := getClientParams()
dag = &Client{
Query: q.Client(gqlClient),
query: q.Client(gqlClient),
client: gqlClient,
}
}
Expand Down
19 changes: 14 additions & 5 deletions cmd/codegen/generator/go/templates/src/_types/object.go.tmpl
@@ -1,7 +1,7 @@
{{- if ne .Name "Query" }}
{{ .Description | Comment }}
type {{ .Name | FormatName }} struct {
Query *querybuilder.Selection
query *querybuilder.Selection

{{ range $field := .Fields }}
{{- if $field.TypeRef.IsScalar }}
Expand All @@ -11,7 +11,6 @@ type {{ .Name | FormatName }} struct {
}
{{- end }}


{{- if . | IsSelfChainable }}
type With{{ .Name | FormatName }}Func func(r *{{ .Name | FormatName }}) *{{ .Name | FormatName }}

Expand All @@ -24,6 +23,16 @@ func (r *{{ $.Name | FormatName }}) With(f With{{ .Name | FormatName }}Func) *{{

{{- end }}


func (r *{{ .Name | FormatName }}) WithGraphQLQuery(q *querybuilder.Selection) *{{ $.Name | FormatName }} {
return &{{ .Name | FormatName }}{
query: q,
{{- if eq .Name "Query" }}
client: r.client,
{{ end }}
}
}

{{ range $field := .Fields }}
{{- if $field.Args.HasOptionals }}
// {{ $field | FieldOptionsStructName }} contains options for {{ $.Name | FormatName }}.{{ $field.Name | FormatName }}
Expand Down Expand Up @@ -60,7 +69,7 @@ type {{ $field | FieldOptionsStructName }} struct {
return *r.{{ $field.Name }}, nil
}
{{- end }}
q := r.Query.Select("{{ $field.Name }}")
q := r.query.Select("{{ $field.Name }}")

{{- if $field.Args.HasOptionals }}
for i := len(opts) - 1; i >= 0; i-- {
Expand All @@ -87,7 +96,7 @@ type {{ $field | FieldOptionsStructName }} struct {
{{- else if $field.TypeRef.IsObject }}
{{ $typeName := $field.TypeRef | FormatOutputType }}
return &{{ $field.TypeRef | FormatOutputType }} {
Query: q,
query: q,
{{- if eq $typeName "Client" }}
client: r.client,
{{ end }}
Expand All @@ -110,7 +119,7 @@ type {{ $field | FieldOptionsStructName }} struct {
for i := range fields {
val := {{ $field.TypeRef | FormatOutputType | FormatArrayToSingleType }}{{"{"}}{{ $field | GetArrayField | FormatArrayField }}{{"}"}}
{{- if $eleType | IsIDableObject }}
val.Query = q.Root().Select("load{{$eleType | ObjectName}}FromID").Arg("id", fields[i].Id)
val.query = q.Root().Select("load{{$eleType | ObjectName}}FromID").Arg("id", fields[i].Id)
{{- end }}
out = append(out, val)
}
Expand Down
4 changes: 2 additions & 2 deletions sdk/go/client.go
Expand Up @@ -17,7 +17,7 @@ import (
type Client struct {
conn engineconn.EngineConn

Query *querybuilder.Selection
query *querybuilder.Selection
client graphql.Client
}

Expand Down Expand Up @@ -75,7 +75,7 @@ func Connect(ctx context.Context, opts ...ClientOpt) (*Client, error) {
gql := errorWrappedClient{graphql.NewClient("http://"+conn.Host()+"/query", conn)}

c := &Client{
Query: querybuilder.Query().Client(gql),
query: querybuilder.Query().Client(gql),
client: gql,
conn: conn,
}
Expand Down

0 comments on commit 80dbb1d

Please sign in to comment.