diff --git a/Gopkg.lock b/Gopkg.lock index ee8ef62b2c0..c270b02a1e5 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -152,7 +152,7 @@ [[projects]] branch = "master" - digest = "1:f03ae2a33628fa4fc2d6b9e5ea9630ace11ba730a808dff0674f6ee7137c2bc1" + digest = "1:3134a6c3595fe6ec84dc4fff02748d472d45af1ee3e1ffed31edca7dcb5ccad2" name = "github.com/vektah/gqlparser" packages = [ ".", @@ -164,7 +164,7 @@ "validator/rules", ] pruneopts = "UT" - revision = "8236ac024f533cfa991e494ac0e4ead587c10f8e" + revision = "91afa0efa9d134b99ae434c16b5a43e71102b34b" [[projects]] branch = "master" diff --git a/codegen/build.go b/codegen/build.go index 6eb6dba8f8b..fb915185c78 100644 --- a/codegen/build.go +++ b/codegen/build.go @@ -20,6 +20,7 @@ type Build struct { MutationRoot *Object SubscriptionRoot *Object SchemaRaw string + SchemaFilename string } type ModelBuild struct { @@ -76,12 +77,13 @@ func (cfg *Config) bind() (*Build, error) { } b := &Build{ - PackageName: cfg.Exec.Package, - Objects: objects, - Interfaces: cfg.buildInterfaces(namedTypes, prog), - Inputs: inputs, - Imports: imports.finalize(), - SchemaRaw: cfg.SchemaStr, + PackageName: cfg.Exec.Package, + Objects: objects, + Interfaces: cfg.buildInterfaces(namedTypes, prog), + Inputs: inputs, + Imports: imports.finalize(), + SchemaRaw: cfg.SchemaStr, + SchemaFilename: cfg.SchemaFilename, } if cfg.schema.Query != nil { diff --git a/codegen/codegen.go b/codegen/codegen.go index d0e1cb8a506..3b1fe04147c 100644 --- a/codegen/codegen.go +++ b/codegen/codegen.go @@ -11,8 +11,9 @@ import ( "github.com/pkg/errors" "github.com/vektah/gqlgen/codegen/templates" - "github.com/vektah/gqlgen/graphql/introspection" "github.com/vektah/gqlparser" + "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/gqlerror" "golang.org/x/tools/imports" ) @@ -107,9 +108,12 @@ func (cfg *Config) normalize() error { } } - var err error - cfg.schema, err = gqlparser.LoadSchema(introspection.Prelude + cfg.SchemaStr) - return err + var err *gqlerror.Error + cfg.schema, err = gqlparser.LoadSchema(&ast.Source{Name: cfg.SchemaFilename, Input: cfg.SchemaStr}) + if err != nil { + return err + } + return nil } var invalidPackageNameChar = regexp.MustCompile(`[^\w]`) diff --git a/codegen/templates/data.go b/codegen/templates/data.go index 80c2c989882..c7d750d7a0c 100644 --- a/codegen/templates/data.go +++ b/codegen/templates/data.go @@ -3,7 +3,7 @@ package templates var data = map[string]string{ "args.gotpl": "\t{{- if . }}args := map[string]interface{}{} {{end}}\n\t{{- range $i, $arg := . }}\n\t\tvar arg{{$i}} {{$arg.Signature }}\n\t\tif tmp, ok := field.Args[{{$arg.GQLName|quote}}]; ok {\n\t\t\tvar err error\n\t\t\t{{$arg.Unmarshal (print \"arg\" $i) \"tmp\" }}\n\t\t\tif err != nil {\n\t\t\t\tec.Error(ctx, err)\n\t\t\t\t{{- if $arg.Object.Stream }}\n\t\t\t\t\treturn nil\n\t\t\t\t{{- else }}\n\t\t\t\t\treturn graphql.Null\n\t\t\t\t{{- end }}\n\t\t\t}\n\t\t} {{ if $arg.Default }} else {\n\t\t\tvar tmp interface{} = {{ $arg.Default | dump }}\n\t\t\tvar err error\n\t\t\t{{$arg.Unmarshal (print \"arg\" $i) \"tmp\" }}\n\t\t\tif err != nil {\n\t\t\t\tec.Error(ctx, err)\n\t\t\t\t{{- if $arg.Object.Stream }}\n\t\t\t\t\treturn nil\n\t\t\t\t{{- else }}\n\t\t\t\t\treturn graphql.Null\n\t\t\t\t{{- end }}\n\t\t\t}\n\t\t}\n\t\t{{end }}\n\t\targs[{{$arg.GQLName|quote}}] = arg{{$i}}\n\t{{- end -}}\n", "field.gotpl": "{{ $field := . }}\n{{ $object := $field.Object }}\n\n{{- if $object.Stream }}\n\tfunc (ec *executionContext) _{{$object.GQLType}}_{{$field.GQLName}}(ctx context.Context, field graphql.CollectedField) func() graphql.Marshaler {\n\t\t{{- template \"args.gotpl\" $field.Args }}\n\t\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{Field: field})\n\t\tresults, err := ec.resolvers.{{ $object.GQLType }}_{{ $field.GQLName }}({{ $field.CallArgs }})\n\t\tif err != nil {\n\t\t\tec.Error(ctx, err)\n\t\t\treturn nil\n\t\t}\n\t\treturn func() graphql.Marshaler {\n\t\t\tres, ok := <-results\n\t\t\tif !ok {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tvar out graphql.OrderedMap\n\t\t\tout.Add(field.Alias, func() graphql.Marshaler { {{ $field.WriteJson }} }())\n\t\t\treturn &out\n\t\t}\n\t}\n{{ else }}\n\tfunc (ec *executionContext) _{{$object.GQLType}}_{{$field.GQLName}}(ctx context.Context, field graphql.CollectedField, {{if not $object.Root}}obj *{{$object.FullName}}{{end}}) graphql.Marshaler {\n\t\t{{- template \"args.gotpl\" $field.Args }}\n\n\t\t{{- if $field.IsConcurrent }}\n\t\t\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\t\t\tObject: {{$object.GQLType|quote}},\n\t\t\t\tArgs: {{if $field.Args }}args{{else}}nil{{end}},\n\t\t\t\tField: field,\n\t\t\t})\n\t\t\treturn graphql.Defer(func() (ret graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tuserErr := ec.Recover(ctx, r)\n\t\t\t\t\t\tec.Error(ctx, userErr)\n\t\t\t\t\t\tret = graphql.Null\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t{{ else }}\n\t\t\trctx := graphql.GetResolverContext(ctx)\n\t\t\trctx.Object = {{$object.GQLType|quote}}\n\t\t\trctx.Args = {{if $field.Args }}args{{else}}nil{{end}}\n\t\t\trctx.Field = field\n\t\t\trctx.PushField(field.Alias)\n\t\t\tdefer rctx.Pop()\n\t\t{{- end }}\n\n\t\t\t{{- if $field.IsResolver }}\n\t\t\t\tresTmp, err := ec.ResolverMiddleware(ctx, func(ctx context.Context) (interface{}, error) {\n\t\t\t\t\treturn ec.resolvers.{{ $object.GQLType }}_{{ $field.GQLName }}({{ $field.CallArgs }})\n\t\t\t\t})\n\t\t\t\tif err != nil {\n\t\t\t\t\tec.Error(ctx, err)\n\t\t\t\t\treturn graphql.Null\n\t\t\t\t}\n\t\t\t\tif resTmp == nil {\n\t\t\t\t\treturn graphql.Null\n\t\t\t\t}\n\t\t\t\tres := resTmp.({{$field.Signature}})\n\t\t\t{{- else if $field.GoVarName }}\n\t\t\t\tres := obj.{{$field.GoVarName}}\n\t\t\t{{- else if $field.GoMethodName }}\n\t\t\t\t{{- if $field.NoErr }}\n\t\t\t\t\tres := {{$field.GoMethodName}}({{ $field.CallArgs }})\n\t\t\t\t{{- else }}\n\t\t\t\t\tres, err := {{$field.GoMethodName}}({{ $field.CallArgs }})\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tec.Error(ctx, err)\n\t\t\t\t\t\treturn graphql.Null\n\t\t\t\t\t}\n\t\t\t\t{{- end }}\n\t\t\t{{- end }}\n\t\t\t{{ $field.WriteJson }}\n\t\t{{- if $field.IsConcurrent }}\n\t\t\t})\n\t\t{{- end }}\n\t}\n{{ end }}\n", - "generated.gotpl": "// Code generated by github.com/vektah/gqlgen, DO NOT EDIT.\n\npackage {{ .PackageName }}\n\nimport (\n{{- range $import := .Imports }}\n\t{{- $import.Write }}\n{{ end }}\n)\n\n// MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface.\nfunc MakeExecutableSchema(resolvers Resolvers) graphql.ExecutableSchema {\n\treturn &executableSchema{resolvers: resolvers}\n}\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(resolvers ResolverRoot) graphql.ExecutableSchema {\n\treturn MakeExecutableSchema(shortMapper{r: resolvers})\n}\n\ntype Resolvers interface {\n{{- range $object := .Objects -}}\n\t{{ range $field := $object.Fields -}}\n\t\t{{ $field.ResolverDeclaration }}\n\t{{ end }}\n{{- end }}\n}\n\ntype ResolverRoot interface {\n{{- range $object := .Objects -}}\n\t{{ if $object.HasResolvers -}}\n\t\t{{$object.GQLType}}() {{$object.GQLType}}Resolver\n\t{{ end }}\n{{- end }}\n}\n\n{{- range $object := .Objects -}}\n\t{{ if $object.HasResolvers }}\n\t\ttype {{$object.GQLType}}Resolver interface {\n\t\t{{ range $field := $object.Fields -}}\n\t\t\t{{ $field.ShortResolverDeclaration }}\n\t\t{{ end }}\n\t\t}\n\t{{- end }}\n{{- end }}\n\ntype shortMapper struct {\n\tr ResolverRoot\n}\n\n{{- range $object := .Objects -}}\n\t{{ range $field := $object.Fields -}}\n\t\t{{- if $field.IsResolver }}\n\t\t\tfunc (s shortMapper) {{ $field.ResolverDeclaration }} {\n\t\t\t\treturn s.r.{{$field.ShortInvocation}}\n\t\t\t}\n\t\t{{- end }}\n\t{{ end }}\n{{- end }}\n\ntype executableSchema struct {\n\tresolvers Resolvers\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\t{{- if .QueryRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\tdata := ec._{{.QueryRoot.GQLType}}(ctx, op.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\t\t\treturn buf.Bytes()\n\t\t})\n\n\t\treturn &graphql.Response{\n\t\t\tData: buf,\n\t\t\tErrors: ec.Errors,\n\t\t}\n\t{{- else }}\n\t\treturn graphql.ErrorResponse(ctx, \"queries are not supported\")\n\t{{- end }}\n}\n\nfunc (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\t{{- if .MutationRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\tdata := ec._{{.MutationRoot.GQLType}}(ctx, op.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\t\t\treturn buf.Bytes()\n\t\t})\n\n\t\treturn &graphql.Response{\n\t\t\tData: buf,\n\t\t\tErrors: ec.Errors,\n\t\t}\n\t{{- else }}\n\t\treturn graphql.ErrorResponse(ctx, \"mutations are not supported\")\n\t{{- end }}\n}\n\nfunc (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {\n\t{{- if .SubscriptionRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tnext := ec._{{.SubscriptionRoot.GQLType}}(ctx, op.SelectionSet)\n\t\tif ec.Errors != nil {\n\t\t\treturn graphql.OneShot(&graphql.Response{Data: []byte(\"null\"), Errors: ec.Errors})\n\t\t}\n\n\t\tvar buf bytes.Buffer\n\t\treturn func() *graphql.Response {\n\t\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\t\tbuf.Reset()\n\t\t\t\tdata := next()\n\n\t\t\t\tif data == nil {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tdata.MarshalGQL(&buf)\n\t\t\t\treturn buf.Bytes()\n\t\t\t})\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf,\n\t\t\t\tErrors: ec.Errors,\n\t\t\t}\n\t\t}\n\t{{- else }}\n\t\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"subscriptions are not supported\"))\n\t{{- end }}\n}\n\ntype executionContext struct {\n\t*graphql.RequestContext\n\n\tresolvers Resolvers\n}\n\n{{- range $object := .Objects }}\n\t{{ template \"object.gotpl\" $object }}\n\n\t{{- range $field := $object.Fields }}\n\t\t{{ template \"field.gotpl\" $field }}\n\t{{ end }}\n{{- end}}\n\n{{- range $interface := .Interfaces }}\n\t{{ template \"interface.gotpl\" $interface }}\n{{- end }}\n\n{{- range $input := .Inputs }}\n\t{{ template \"input.gotpl\" $input }}\n{{- end }}\n\nfunc (ec *executionContext) introspectSchema() *introspection.Schema {\n\treturn introspection.WrapSchema(parsedSchema)\n}\n\nfunc (ec *executionContext) introspectType(name string) *introspection.Type {\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name])\n}\n\nvar parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + {{.SchemaRaw|rawQuote}})\n", + "generated.gotpl": "// Code generated by github.com/vektah/gqlgen, DO NOT EDIT.\n\npackage {{ .PackageName }}\n\nimport (\n{{- range $import := .Imports }}\n\t{{- $import.Write }}\n{{ end }}\n)\n\n// MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface.\nfunc MakeExecutableSchema(resolvers Resolvers) graphql.ExecutableSchema {\n\treturn &executableSchema{resolvers: resolvers}\n}\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(resolvers ResolverRoot) graphql.ExecutableSchema {\n\treturn MakeExecutableSchema(shortMapper{r: resolvers})\n}\n\ntype Resolvers interface {\n{{- range $object := .Objects -}}\n\t{{ range $field := $object.Fields -}}\n\t\t{{ $field.ResolverDeclaration }}\n\t{{ end }}\n{{- end }}\n}\n\ntype ResolverRoot interface {\n{{- range $object := .Objects -}}\n\t{{ if $object.HasResolvers -}}\n\t\t{{$object.GQLType}}() {{$object.GQLType}}Resolver\n\t{{ end }}\n{{- end }}\n}\n\n{{- range $object := .Objects -}}\n\t{{ if $object.HasResolvers }}\n\t\ttype {{$object.GQLType}}Resolver interface {\n\t\t{{ range $field := $object.Fields -}}\n\t\t\t{{ $field.ShortResolverDeclaration }}\n\t\t{{ end }}\n\t\t}\n\t{{- end }}\n{{- end }}\n\ntype shortMapper struct {\n\tr ResolverRoot\n}\n\n{{- range $object := .Objects -}}\n\t{{ range $field := $object.Fields -}}\n\t\t{{- if $field.IsResolver }}\n\t\t\tfunc (s shortMapper) {{ $field.ResolverDeclaration }} {\n\t\t\t\treturn s.r.{{$field.ShortInvocation}}\n\t\t\t}\n\t\t{{- end }}\n\t{{ end }}\n{{- end }}\n\ntype executableSchema struct {\n\tresolvers Resolvers\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\t{{- if .QueryRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\tdata := ec._{{.QueryRoot.GQLType}}(ctx, op.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\t\t\treturn buf.Bytes()\n\t\t})\n\n\t\treturn &graphql.Response{\n\t\t\tData: buf,\n\t\t\tErrors: ec.Errors,\n\t\t}\n\t{{- else }}\n\t\treturn graphql.ErrorResponse(ctx, \"queries are not supported\")\n\t{{- end }}\n}\n\nfunc (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\t{{- if .MutationRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\tdata := ec._{{.MutationRoot.GQLType}}(ctx, op.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\t\t\treturn buf.Bytes()\n\t\t})\n\n\t\treturn &graphql.Response{\n\t\t\tData: buf,\n\t\t\tErrors: ec.Errors,\n\t\t}\n\t{{- else }}\n\t\treturn graphql.ErrorResponse(ctx, \"mutations are not supported\")\n\t{{- end }}\n}\n\nfunc (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {\n\t{{- if .SubscriptionRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tnext := ec._{{.SubscriptionRoot.GQLType}}(ctx, op.SelectionSet)\n\t\tif ec.Errors != nil {\n\t\t\treturn graphql.OneShot(&graphql.Response{Data: []byte(\"null\"), Errors: ec.Errors})\n\t\t}\n\n\t\tvar buf bytes.Buffer\n\t\treturn func() *graphql.Response {\n\t\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\t\tbuf.Reset()\n\t\t\t\tdata := next()\n\n\t\t\t\tif data == nil {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tdata.MarshalGQL(&buf)\n\t\t\t\treturn buf.Bytes()\n\t\t\t})\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf,\n\t\t\t\tErrors: ec.Errors,\n\t\t\t}\n\t\t}\n\t{{- else }}\n\t\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"subscriptions are not supported\"))\n\t{{- end }}\n}\n\ntype executionContext struct {\n\t*graphql.RequestContext\n\n\tresolvers Resolvers\n}\n\n{{- range $object := .Objects }}\n\t{{ template \"object.gotpl\" $object }}\n\n\t{{- range $field := $object.Fields }}\n\t\t{{ template \"field.gotpl\" $field }}\n\t{{ end }}\n{{- end}}\n\n{{- range $interface := .Interfaces }}\n\t{{ template \"interface.gotpl\" $interface }}\n{{- end }}\n\n{{- range $input := .Inputs }}\n\t{{ template \"input.gotpl\" $input }}\n{{- end }}\n\nfunc (ec *executionContext) introspectSchema() *introspection.Schema {\n\treturn introspection.WrapSchema(parsedSchema)\n}\n\nfunc (ec *executionContext) introspectType(name string) *introspection.Type {\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name])\n}\n\nvar parsedSchema = gqlparser.MustLoadSchema(\n\t&ast.Source{Name: {{.SchemaFilename|quote}}, Input: {{.SchemaRaw|rawQuote}}},\n)\n", "input.gotpl": "\t{{- if .IsMarshaled }}\n\tfunc Unmarshal{{ .GQLType }}(v interface{}) ({{.FullName}}, error) {\n\t\tvar it {{.FullName}}\n\t\tvar asMap = v.(map[string]interface{})\n\t\t{{ range $field := .Fields}}\n\t\t\t{{- if $field.Default}}\n\t\t\t\tif _, present := asMap[{{$field.GQLName|quote}}] ; !present {\n\t\t\t\t\tasMap[{{$field.GQLName|quote}}] = {{ $field.Default | dump }}\n\t\t\t\t}\n\t\t\t{{- end}}\n\t\t{{- end }}\n\n\t\tfor k, v := range asMap {\n\t\t\tswitch k {\n\t\t\t{{- range $field := .Fields }}\n\t\t\tcase {{$field.GQLName|quote}}:\n\t\t\t\tvar err error\n\t\t\t\t{{ $field.Unmarshal (print \"it.\" $field.GoVarName) \"v\" }}\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn it, err\n\t\t\t\t}\n\t\t\t{{- end }}\n\t\t\t}\n\t\t}\n\n\t\treturn it, nil\n\t}\n\t{{- end }}\n", "interface.gotpl": "{{- $interface := . }}\n\nfunc (ec *executionContext) _{{$interface.GQLType}}(ctx context.Context, sel ast.SelectionSet, obj *{{$interface.FullName}}) graphql.Marshaler {\n\tswitch obj := (*obj).(type) {\n\tcase nil:\n\t\treturn graphql.Null\n\t{{- range $implementor := $interface.Implementors }}\n\t\t{{- if $implementor.ValueReceiver }}\n\t\t\tcase {{$implementor.FullName}}:\n\t\t\t\treturn ec._{{$implementor.GQLType}}(ctx, sel, &obj)\n\t\t{{- end}}\n\t\tcase *{{$implementor.FullName}}:\n\t\t\treturn ec._{{$implementor.GQLType}}(ctx, sel, obj)\n\t{{- end }}\n\tdefault:\n\t\tpanic(fmt.Errorf(\"unexpected type %T\", obj))\n\t}\n}\n", "models.gotpl": "// Code generated by github.com/vektah/gqlgen, DO NOT EDIT.\n\npackage {{ .PackageName }}\n\nimport (\n{{- range $import := .Imports }}\n\t{{- $import.Write }}\n{{ end }}\n)\n\n{{ range $model := .Models }}\n\t{{- if .IsInterface }}\n\t\ttype {{.GoType}} interface {}\n\t{{- else }}\n\t\ttype {{.GoType}} struct {\n\t\t\t{{- range $field := .Fields }}\n\t\t\t\t{{- if $field.GoVarName }}\n\t\t\t\t\t{{ $field.GoVarName }} {{$field.Signature}} `json:\"{{$field.GQLName}}\"`\n\t\t\t\t{{- else }}\n\t\t\t\t\t{{ $field.GoFKName }} {{$field.GoFKType}}\n\t\t\t\t{{- end }}\n\t\t\t{{- end }}\n\t\t}\n\t{{- end }}\n{{- end}}\n\n{{ range $enum := .Enums }}\n\ttype {{.GoType}} string\n\tconst (\n\t{{ range $value := .Values -}}\n\t\t{{with .Description}} {{.|prefixLines \"// \"}} {{end}}\n\t\t{{$enum.GoType}}{{ .Name|toCamel }} {{$enum.GoType}} = {{.Name|quote}}\n\t{{- end }}\n\t)\n\n\tfunc (e {{.GoType}}) IsValid() bool {\n\t\tswitch e {\n\t\tcase {{ range $index, $element := .Values}}{{if $index}},{{end}}{{ $enum.GoType }}{{ $element.Name|toCamel }}{{end}}:\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\tfunc (e {{.GoType}}) String() string {\n\t\treturn string(e)\n\t}\n\n\tfunc (e *{{.GoType}}) UnmarshalGQL(v interface{}) error {\n\t\tstr, ok := v.(string)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"enums must be strings\")\n\t\t}\n\n\t\t*e = {{.GoType}}(str)\n\t\tif !e.IsValid() {\n\t\t\treturn fmt.Errorf(\"%s is not a valid {{.GQLType}}\", str)\n\t\t}\n\t\treturn nil\n\t}\n\n\tfunc (e {{.GoType}}) MarshalGQL(w io.Writer) {\n\t\tfmt.Fprint(w, strconv.Quote(e.String()))\n\t}\n\n{{- end }}\n", diff --git a/codegen/templates/generated.gotpl b/codegen/templates/generated.gotpl index 523234c6327..daeece7a4eb 100644 --- a/codegen/templates/generated.gotpl +++ b/codegen/templates/generated.gotpl @@ -168,4 +168,6 @@ func (ec *executionContext) introspectType(name string) *introspection.Type { return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + {{.SchemaRaw|rawQuote}}) +var parsedSchema = gqlparser.MustLoadSchema( + &ast.Source{Name: {{.SchemaFilename|quote}}, Input: {{.SchemaRaw|rawQuote}}}, +) diff --git a/codegen/type_build.go b/codegen/type_build.go index ab70fd317f1..4189763d69b 100644 --- a/codegen/type_build.go +++ b/codegen/type_build.go @@ -81,6 +81,9 @@ func (n NamedTypes) getType(t *ast.Type) *Type { if !t.NonNull { modifiers = append(modifiers, modPtr) } + if n[t.NamedType] == nil { + panic("missing type " + t.NamedType) + } res := &Type{ NamedType: n[t.NamedType], Modifiers: modifiers, diff --git a/example/chat/generated.go b/example/chat/generated.go index b71ec4f3e37..a78511caf40 100644 --- a/example/chat/generated.go +++ b/example/chat/generated.go @@ -1187,7 +1187,8 @@ func (ec *executionContext) introspectType(name string) *introspection.Type { return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `type Chatroom { +var parsedSchema = gqlparser.MustLoadSchema( + &ast.Source{Name: "schema.graphql", Input: `type Chatroom { name: String! messages: [Message!]! } @@ -1212,4 +1213,5 @@ type Subscription { } scalar Time -`) +`}, +) diff --git a/example/dataloader/generated.go b/example/dataloader/generated.go index c5351169c35..7695566c644 100644 --- a/example/dataloader/generated.go +++ b/example/dataloader/generated.go @@ -1297,7 +1297,8 @@ func (ec *executionContext) introspectType(name string) *introspection.Type { return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `type Query { +var parsedSchema = gqlparser.MustLoadSchema( + &ast.Source{Name: "schema.graphql", Input: `type Query { customers: [Customer!] # this method is here to test code generation of nested arrays @@ -1328,4 +1329,5 @@ type Item { name: String! } scalar Time -`) +`}, +) diff --git a/example/scalars/generated.go b/example/scalars/generated.go index e2cf987595a..c9c6314c804 100644 --- a/example/scalars/generated.go +++ b/example/scalars/generated.go @@ -1216,7 +1216,8 @@ func (ec *executionContext) introspectType(name string) *introspection.Type { return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `type Query { +var parsedSchema = gqlparser.MustLoadSchema( + &ast.Source{Name: "schema.graphql", Input: `type Query { user(id: ID!): User search(input: SearchArgs = {location: "37,144", isBanned: false}): [User!]! } @@ -1251,4 +1252,5 @@ enum Tier { scalar Timestamp scalar Point -`) +`}, +) diff --git a/example/selection/generated.go b/example/selection/generated.go index 55dcf9b6325..e46fbd0c97b 100644 --- a/example/selection/generated.go +++ b/example/selection/generated.go @@ -1069,7 +1069,8 @@ func (ec *executionContext) introspectType(name string) *introspection.Type { return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `interface Event { +var parsedSchema = gqlparser.MustLoadSchema( + &ast.Source{Name: "schema.graphql", Input: `interface Event { selection: [String!] collected: [String!] } @@ -1093,4 +1094,5 @@ type Query { } scalar Time -`) +`}, +) diff --git a/example/starwars/generated.go b/example/starwars/generated.go index 05e88d1504a..fc0036b3a82 100644 --- a/example/starwars/generated.go +++ b/example/starwars/generated.go @@ -2325,7 +2325,8 @@ func (ec *executionContext) introspectType(name string) *introspection.Type { return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `# The query type, represents all of the entry points into our object graph +var parsedSchema = gqlparser.MustLoadSchema( + &ast.Source{Name: "schema.graphql", Input: `# The query type, represents all of the entry points into our object graph type Query { hero(episode: Episode = NEWHOPE): Character reviews(episode: Episode!, since: Time): [Review!]! @@ -2456,4 +2457,5 @@ type Starship { } union SearchResult = Human | Droid | Starship scalar Time -`) +`}, +) diff --git a/example/todo/generated.go b/example/todo/generated.go index f93030fa540..142f9f79545 100644 --- a/example/todo/generated.go +++ b/example/todo/generated.go @@ -1184,7 +1184,8 @@ func (ec *executionContext) introspectType(name string) *introspection.Type { return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `schema { +var parsedSchema = gqlparser.MustLoadSchema( + &ast.Source{Name: "schema.graphql", Input: `schema { query: MyQuery mutation: MyMutation } @@ -1210,4 +1211,7 @@ input TodoInput { text: String! done: Boolean } -`) + +scalar Map +`}, +) diff --git a/example/todo/schema.graphql b/example/todo/schema.graphql index 2977e89cddd..8482d0df778 100644 --- a/example/todo/schema.graphql +++ b/example/todo/schema.graphql @@ -24,3 +24,5 @@ input TodoInput { text: String! done: Boolean } + +scalar Map diff --git a/graphql/introspection/inliner/inliner.go b/graphql/introspection/inliner/inliner.go deleted file mode 100644 index 06caaf19434..00000000000 --- a/graphql/introspection/inliner/inliner.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "bytes" - "io/ioutil" - - "strconv" - - "golang.org/x/tools/imports" -) - -func main() { - out := bytes.Buffer{} - out.WriteString("package introspection\n\n") - out.WriteString("var Prelude = ") - - file, err := ioutil.ReadFile("prelude.graphql") - if err != nil { - panic(err) - } - - out.WriteString(strconv.Quote(string(file))) - out.WriteString("\n") - - formatted, err2 := imports.Process("prelude.go", out.Bytes(), nil) - if err2 != nil { - panic(err2) - } - - ioutil.WriteFile("prelude.go", formatted, 0644) -} diff --git a/graphql/introspection/introspection.go b/graphql/introspection/introspection.go index 80682f58460..c8dfc1f0c27 100644 --- a/graphql/introspection/introspection.go +++ b/graphql/introspection/introspection.go @@ -1,5 +1,3 @@ -//go:generate go run ./inliner/inliner.go - // introspection implements the spec defined in https://github.com/facebook/graphql/blob/master/spec/Section%204%20--%20Introspection.md#schema-introspection package introspection diff --git a/graphql/introspection/prelude.go b/graphql/introspection/prelude.go deleted file mode 100644 index ef45909d9b1..00000000000 --- a/graphql/introspection/prelude.go +++ /dev/null @@ -1,3 +0,0 @@ -package introspection - -var Prelude = "# The `Map` scalar type is a simple json object\nscalar Map\n\ntype __Schema {\n types: [__Type!]!\n queryType: __Type!\n mutationType: __Type\n subscriptionType: __Type\n directives: [__Directive!]!\n}\n\ntype __Type {\n kind: __TypeKind!\n name: String\n description: String\n\n # OBJECT and INTERFACE only\n fields(includeDeprecated: Boolean = false): [__Field!]\n\n # OBJECT only\n interfaces: [__Type!]\n\n # INTERFACE and UNION only\n possibleTypes: [__Type!]\n\n # ENUM only\n enumValues(includeDeprecated: Boolean = false): [__EnumValue!]\n\n # INPUT_OBJECT only\n inputFields: [__InputValue!]\n\n # NON_NULL and LIST only\n ofType: __Type\n}\n\ntype __Field {\n name: String!\n description: String\n args: [__InputValue!]!\n type: __Type!\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\ntype __InputValue {\n name: String!\n description: String\n type: __Type!\n defaultValue: String\n}\n\ntype __EnumValue {\n name: String!\n description: String\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\nenum __TypeKind {\n SCALAR\n OBJECT\n INTERFACE\n UNION\n ENUM\n INPUT_OBJECT\n LIST\n NON_NULL\n}\n\ntype __Directive {\n name: String!\n description: String\n locations: [__DirectiveLocation!]!\n args: [__InputValue!]!\n}\n\nenum __DirectiveLocation {\n QUERY\n MUTATION\n SUBSCRIPTION\n FIELD\n FRAGMENT_DEFINITION\n FRAGMENT_SPREAD\n INLINE_FRAGMENT\n SCHEMA\n SCALAR\n OBJECT\n FIELD_DEFINITION\n ARGUMENT_DEFINITION\n INTERFACE\n UNION\n ENUM\n ENUM_VALUE\n INPUT_OBJECT\n INPUT_FIELD_DEFINITION\n}\n" diff --git a/graphql/introspection/prelude.graphql b/graphql/introspection/prelude.graphql deleted file mode 100644 index 1ecf05ebd9c..00000000000 --- a/graphql/introspection/prelude.graphql +++ /dev/null @@ -1,96 +0,0 @@ -# The `Map` scalar type is a simple json object -scalar Map - -type __Schema { - types: [__Type!]! - queryType: __Type! - mutationType: __Type - subscriptionType: __Type - directives: [__Directive!]! -} - -type __Type { - kind: __TypeKind! - name: String - description: String - - # OBJECT and INTERFACE only - fields(includeDeprecated: Boolean = false): [__Field!] - - # OBJECT only - interfaces: [__Type!] - - # INTERFACE and UNION only - possibleTypes: [__Type!] - - # ENUM only - enumValues(includeDeprecated: Boolean = false): [__EnumValue!] - - # INPUT_OBJECT only - inputFields: [__InputValue!] - - # NON_NULL and LIST only - ofType: __Type -} - -type __Field { - name: String! - description: String - args: [__InputValue!]! - type: __Type! - isDeprecated: Boolean! - deprecationReason: String -} - -type __InputValue { - name: String! - description: String - type: __Type! - defaultValue: String -} - -type __EnumValue { - name: String! - description: String - isDeprecated: Boolean! - deprecationReason: String -} - -enum __TypeKind { - SCALAR - OBJECT - INTERFACE - UNION - ENUM - INPUT_OBJECT - LIST - NON_NULL -} - -type __Directive { - name: String! - description: String - locations: [__DirectiveLocation!]! - args: [__InputValue!]! -} - -enum __DirectiveLocation { - QUERY - MUTATION - SUBSCRIPTION - FIELD - FRAGMENT_DEFINITION - FRAGMENT_SPREAD - INLINE_FRAGMENT - SCHEMA - SCALAR - OBJECT - FIELD_DEFINITION - ARGUMENT_DEFINITION - INTERFACE - UNION - ENUM - ENUM_VALUE - INPUT_OBJECT - INPUT_FIELD_DEFINITION -} diff --git a/handler/stub.go b/handler/stub.go index 656fc1b2a87..f613b141f73 100644 --- a/handler/stub.go +++ b/handler/stub.go @@ -15,11 +15,11 @@ type executableSchemaStub struct { var _ graphql.ExecutableSchema = &executableSchemaStub{} func (e *executableSchemaStub) Schema() *ast.Schema { - return gqlparser.MustLoadSchema(` + return gqlparser.MustLoadSchema(&ast.Source{Input: ` schema { query: Query } type Query { me: User! } type User { name: String! } - `) + `}) } func (e *executableSchemaStub) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { diff --git a/test/generated.go b/test/generated.go index 6e1c67b875f..240b8961e06 100644 --- a/test/generated.go +++ b/test/generated.go @@ -1318,7 +1318,8 @@ func (ec *executionContext) introspectType(name string) *introspection.Type { return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `type Element { +var parsedSchema = gqlparser.MustLoadSchema( + &ast.Source{Name: "schema.graphql", Input: `type Element { child: Element! error: Boolean! mismatched: [Boolean!] @@ -1359,4 +1360,5 @@ type Query { } # this is a comment with a ` + "`" + `backtick` + "`" + ` -`) +`}, +)