├── .chglog ├── CHANGELOG-full-history.tpl.md └── config.yml ├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── GOVERSION.txt │ ├── check-coverage │ ├── check-federation │ ├── check-fmt │ ├── check-generate │ ├── check-gomod.sh │ ├── check-init │ ├── check-integration │ ├── coverage.yml │ ├── fmt-and-generate.yml │ ├── gomod-clean.yml │ ├── integration.yml │ ├── lint.yml │ ├── report.yml │ ├── security.yml │ └── test.yml ├── .gitignore ├── .golangci.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── RELEASE-CHECKLIST.md ├── TESTING.md ├── _examples ├── chat │ ├── .gitignore │ ├── .gqlgen.yml │ ├── chat_test.go │ ├── generated.go │ ├── models_gen.go │ ├── package.json │ ├── public │ │ └── index.html │ ├── readme.md │ ├── resolvers.go │ ├── schema.graphql │ ├── server │ │ └── server.go │ ├── src │ │ ├── App.js │ │ ├── Room.js │ │ ├── components │ │ │ └── room.js │ │ ├── graphql-sse.ts │ │ ├── graphql-ws.js │ │ ├── index.js │ │ └── react-app-env.d.ts │ └── tsconfig.json ├── config │ ├── .gqlgen.yml │ ├── generated.go │ ├── model.go │ ├── models_gen.go │ ├── resolver.go │ ├── schema.graphql │ ├── schema.resolvers.go │ ├── server │ │ └── server.go │ ├── todo.graphql │ ├── todo.resolvers.go │ ├── user.graphql │ └── user.resolvers.go ├── dataloader │ ├── .gqlgen.yml │ ├── addressloader_gen.go │ ├── dataloader_test.go │ ├── dataloaders.go │ ├── generated.go │ ├── itemsliceloader_gen.go │ ├── models_gen.go │ ├── ordersliceloader_gen.go │ ├── readme.md │ ├── resolvers.go │ ├── schema.graphql │ └── server │ │ └── server.go ├── deferexample │ ├── generated.go │ ├── gqlgen.yml │ ├── models_gen.go │ ├── resolver.go │ ├── schema.graphql │ ├── schema.resolvers.go │ └── server │ │ └── server.go ├── embedding │ ├── parent.graphqls │ └── subdir │ │ ├── cfgdir │ │ ├── generate_in_gendir.yml │ │ └── generate_in_subdir.yml │ │ ├── directives.generated.go │ │ ├── embedding_test.go │ │ ├── entity.generated.go │ │ ├── federation_gen.go │ │ ├── gendir │ │ ├── federation_gen.go │ │ ├── generated.go │ │ └── model.go │ │ ├── model.go │ │ ├── prelude.generated.go │ │ ├── resolvers.go │ │ ├── root.generated.go │ │ ├── root_.generated.go │ │ ├── schemadir │ │ └── root.graphqls │ │ └── subdir.graphqls ├── enum │ ├── api │ │ ├── enum.go │ │ ├── exec.go │ │ ├── model.go │ │ └── resolver.go │ ├── cmd │ │ └── main.go │ ├── enum.graphqls │ ├── gen.go │ ├── gqlgen.yaml │ └── model │ │ └── model.go ├── federation │ ├── accounts │ │ ├── gqlgen.yml │ │ ├── graph │ │ │ ├── entity.resolvers.go │ │ │ ├── federation.go │ │ │ ├── generated.go │ │ │ ├── model │ │ │ │ ├── model.go │ │ │ │ └── models_gen.go │ │ │ ├── resolver.go │ │ │ ├── schema.graphqls │ │ │ └── schema.resolvers.go │ │ ├── schema │ │ │ └── schema.go │ │ └── server.go │ ├── all │ │ └── main.go │ ├── gateway │ │ └── index.js │ ├── integration-test.js │ ├── jest.config.js │ ├── package.json │ ├── products │ │ ├── gqlgen.yml │ │ ├── graph │ │ │ ├── entity.resolvers.go │ │ │ ├── federation.go │ │ │ ├── generated.go │ │ │ ├── model │ │ │ │ ├── model.go │ │ │ │ └── models_gen.go │ │ │ ├── products.go │ │ │ ├── resolver.go │ │ │ ├── schema.graphqls │ │ │ └── schema.resolvers.go │ │ ├── schema │ │ │ └── schema.go │ │ └── server.go │ ├── readme.md │ ├── reviews │ │ ├── gqlgen.yml │ │ ├── graph │ │ │ ├── entity.resolvers.go │ │ │ ├── federation.go │ │ │ ├── generated.go │ │ │ ├── model │ │ │ │ ├── models.go │ │ │ │ └── models_gen.go │ │ │ ├── resolver.go │ │ │ ├── reviews.go │ │ │ ├── schema.graphqls │ │ │ └── schema.resolvers.go │ │ ├── schema │ │ │ └── schema.go │ │ └── server.go │ ├── start.sh │ └── subgraphs │ │ └── subgraphs.go ├── fileupload │ ├── .gqlgen.yml │ ├── fileupload_test.go │ ├── generated.go │ ├── model │ │ └── generated.go │ ├── readme.md │ ├── schema.graphql │ ├── server │ │ └── server.go │ ├── stubs.go │ └── testfiles │ │ ├── a.txt │ │ ├── b.txt │ │ └── c.txt ├── go.mod ├── go.sum ├── large-project-structure │ ├── integration │ │ ├── go.mod │ │ ├── go.sum │ │ ├── integration.go │ │ └── schema.graphqls │ ├── main │ │ ├── go.mod │ │ ├── go.sum │ │ ├── gqlgen.yml │ │ ├── graph │ │ │ ├── generated.go │ │ │ ├── model │ │ │ │ └── models_gen.go │ │ │ ├── resolver.go │ │ │ ├── schema.graphqls │ │ │ └── schema.resolvers.go │ │ ├── server.go │ │ └── tools.go │ └── shared │ │ ├── go.mod │ │ ├── go.sum │ │ ├── schema.graphqls │ │ └── shared.go ├── mini-habr-with-subscriptions │ ├── .env │ ├── Dockerfile │ ├── README.md │ ├── cmd │ │ ├── db_connection │ │ │ ├── cache.go │ │ │ └── database.go │ │ ├── main.go │ │ └── server │ │ │ └── server.go │ ├── docker-compose.yml │ ├── go.mod │ ├── go.sum │ ├── gqlgen.yml │ ├── graph │ │ ├── generated.go │ │ ├── model │ │ │ └── models_gen.go │ │ ├── resolver.go │ │ ├── schema.graphqls │ │ ├── schema.resolvers.go │ │ └── subscription.go │ ├── internal │ │ ├── handlers │ │ │ ├── comment_mutation │ │ │ │ ├── interface.go │ │ │ │ └── mutations.go │ │ │ ├── comment_query │ │ │ │ ├── interface.go │ │ │ │ └── query.go │ │ │ ├── post_mutation │ │ │ │ ├── interface.go │ │ │ │ └── mutations.go │ │ │ └── post_query │ │ │ │ ├── interface.go │ │ │ │ └── query.go │ │ ├── model │ │ │ └── model.go │ │ ├── pkg │ │ │ ├── cursor │ │ │ │ └── cursor.go │ │ │ └── errs │ │ │ │ └── errors.go │ │ └── storage │ │ │ ├── db │ │ │ └── resolvers.go │ │ │ ├── in-memory │ │ │ └── resolvers.go │ │ │ └── interface.go │ ├── migrations │ │ └── 001_create_tables.up.sql │ └── tools │ │ └── tools.go ├── readme.md ├── scalars │ ├── .gqlgen.yml │ ├── external │ │ └── model.go │ ├── generated.go │ ├── model │ │ ├── generated.go │ │ └── model.go │ ├── resolvers.go │ ├── scalar_test.go │ ├── schema.graphql │ └── server │ │ └── server.go ├── selection │ ├── .gqlgen.yml │ ├── generated.go │ ├── models_gen.go │ ├── readme.md │ ├── schema.graphql │ ├── selection.go │ ├── selection_test.go │ └── server │ │ └── server.go ├── starwars │ ├── .gqlgen.yml │ ├── benchmarks_test.go │ ├── generated │ │ └── exec.go │ ├── models │ │ ├── generated.go │ │ └── model.go │ ├── readme.md │ ├── resolvers.go │ ├── schema.graphql │ ├── server │ │ └── server.go │ └── starwars_test.go ├── todo │ ├── generated.go │ ├── gqlgen.yml │ ├── models.go │ ├── models_gen.go │ ├── readme.md │ ├── schema.graphql │ ├── server │ │ └── server.go │ ├── todo.go │ └── todo_test.go ├── tools.go ├── type-system-extension │ ├── README.md │ ├── directive.go │ ├── generated.go │ ├── gqlgen.yml │ ├── models_gen.go │ ├── resolver.go │ ├── schemas │ │ ├── enum-extension.graphql │ │ ├── input-object-extension.graphql │ │ ├── interface-extension.graphql │ │ ├── object-extension.graphql │ │ ├── scalar-extension.graphql │ │ ├── schema-extension.graphql │ │ ├── schema.graphql │ │ ├── type-extension.graphql │ │ └── union-extension.graphql │ └── server │ │ └── server.go ├── uuid │ ├── gqlgen.yml │ ├── graph │ │ ├── generated.go │ │ ├── model │ │ │ └── models_gen.go │ │ ├── resolver.go │ │ ├── schema.graphqls │ │ └── schema.resolvers.go │ └── server.go └── websocket-initfunc │ ├── graph │ ├── generated.go │ ├── model │ │ └── models_gen.go │ └── resolver.go │ └── server │ ├── Makefile │ ├── go.mod │ ├── go.sum │ ├── gqlgen.yml │ ├── graph │ ├── generated.go │ ├── model │ │ └── models_gen.go │ ├── resolver.go │ ├── schema.graphqls │ └── schema.resolvers.go │ ├── readme.md │ └── server.go ├── api ├── generate.go ├── generate_test.go ├── option.go ├── option_test.go └── testdata │ ├── default │ ├── gqlgen.yml │ └── graph │ │ ├── model │ │ └── doc.go │ │ └── schema.graphqls │ ├── federation2 │ ├── gqlgen.yml │ └── graph │ │ ├── model │ │ └── doc.go │ │ └── schema.graphqls │ └── workerlimit │ ├── gqlgen.yml │ └── graph │ ├── model │ └── doc.go │ └── schema.graphqls ├── bin └── release ├── client ├── client.go ├── client_test.go ├── errors.go ├── incremental_http.go ├── options.go ├── readme.md ├── sse.go ├── websocket.go ├── withfilesoption.go └── withfilesoption_test.go ├── codegen ├── args.go ├── args.gotpl ├── complexity.go ├── config │ ├── binder.go │ ├── binder_test.go │ ├── config.go │ ├── config_test.go │ ├── exec.go │ ├── initialisms.go │ ├── initialisms_test.go │ ├── package.go │ ├── package_test.go │ ├── resolver.go │ ├── resolver_test.go │ └── testdata │ │ ├── autobinding │ │ ├── chat │ │ │ └── model.go │ │ └── scalars │ │ │ └── model │ │ │ └── model.go │ │ ├── binding │ │ └── model.go │ │ ├── cfg │ │ ├── glob.yml │ │ ├── glob │ │ │ ├── bar │ │ │ │ └── bar with spaces.graphql │ │ │ └── foo │ │ │ │ └── foo.graphql │ │ ├── goInitialisms.yml │ │ ├── gqlgen.yml │ │ ├── malformedconfig.yml │ │ ├── otherdir │ │ │ └── .gitkeep │ │ ├── outer │ │ ├── subdir │ │ │ ├── gqlgen.yaml │ │ │ └── inner │ │ ├── unknownkeys.yml │ │ └── unwalkable.yml │ │ ├── defaultconfig │ │ └── schema.graphql │ │ ├── enum │ │ └── model.go │ │ └── example.go ├── data.go ├── data_test.go ├── directive.go ├── directive_test.go ├── directives.gotpl ├── field.go ├── field.gotpl ├── field_test.go ├── generate.go ├── generated!.gotpl ├── input.gotpl ├── interface.go ├── interface.gotpl ├── object.go ├── object.gotpl ├── root_.gotpl ├── templates │ ├── import.go │ ├── import_test.go │ ├── templates.go │ ├── templates_test.go │ ├── test.gotpl │ ├── test_.gotpl │ └── testdata │ │ ├── a │ │ └── bar │ │ │ └── bar.go │ │ ├── b │ │ └── bar │ │ │ └── bar.go │ │ └── pkg_mismatch │ │ └── turtles.go ├── testserver │ ├── compliant-int │ │ ├── compliant_int_test.go │ │ ├── generated-compliant-strict │ │ │ ├── models.go │ │ │ ├── resolver.go │ │ │ ├── schema.go │ │ │ └── stub.go │ │ ├── generated-default │ │ │ ├── models.go │ │ │ ├── resolver.go │ │ │ ├── schema.go │ │ │ └── stub.go │ │ ├── gqlgen_compliant_strict.yml │ │ ├── gqlgen_default.yml │ │ └── schema.graphql │ ├── empty.go │ ├── followschema │ │ ├── builtinscalar.generated.go │ │ ├── builtinscalar.graphql │ │ ├── bytes.go │ │ ├── complexity.generated.go │ │ ├── complexity.graphql │ │ ├── complexity_test.go │ │ ├── defaults.generated.go │ │ ├── defaults.graphql │ │ ├── defaults_test.go │ │ ├── defer.generated.go │ │ ├── defer.graphql │ │ ├── directive.generated.go │ │ ├── directive.graphql │ │ ├── directive_test.go │ │ ├── embedded.generated.go │ │ ├── embedded.go │ │ ├── embedded.graphql │ │ ├── embedded_test.go │ │ ├── enum.generated.go │ │ ├── enum.graphql │ │ ├── enums_test.go │ │ ├── fields_order.generated.go │ │ ├── fields_order.go │ │ ├── fields_order.graphql │ │ ├── fields_order_test.go │ │ ├── generated_test.go │ │ ├── gqlgen.yml │ │ ├── input_test.go │ │ ├── interfaces.generated.go │ │ ├── interfaces.go │ │ ├── interfaces.graphql │ │ ├── interfaces_test.go │ │ ├── introspection │ │ │ └── it.go │ │ ├── introspection_test.go │ │ ├── invalid-packagename │ │ │ └── invalid-identifier.go │ │ ├── issue896.generated.go │ │ ├── issue896.graphql │ │ ├── loops.generated.go │ │ ├── loops.graphql │ │ ├── maps.generated.go │ │ ├── maps.go │ │ ├── maps.graphql │ │ ├── maps_test.go │ │ ├── middleware_test.go │ │ ├── modelmethod_test.go │ │ ├── models-gen.go │ │ ├── models.go │ │ ├── mutation_with_custom_scalar.generated.go │ │ ├── mutation_with_custom_scalar.go │ │ ├── mutation_with_custom_scalar.graphql │ │ ├── mutation_with_custom_scalar_test.go │ │ ├── nulls.generated.go │ │ ├── nulls.graphql │ │ ├── nulls_test.go │ │ ├── otherpkg │ │ │ └── model.go │ │ ├── panics.generated.go │ │ ├── panics.graphql │ │ ├── panics_test.go │ │ ├── prelude.generated.go │ │ ├── primitive_objects.generated.go │ │ ├── primitive_objects.graphql │ │ ├── primitive_objects_test.go │ │ ├── ptr_to_any.generated.go │ │ ├── ptr_to_any.go │ │ ├── ptr_to_any.graphql │ │ ├── ptr_to_any_test.go │ │ ├── ptr_to_ptr_input.generated.go │ │ ├── ptr_to_ptr_input.go │ │ ├── ptr_to_ptr_input.graphql │ │ ├── ptr_to_ptr_input_test.go │ │ ├── ptr_to_slice.generated.go │ │ ├── ptr_to_slice.go │ │ ├── ptr_to_slice.graphql │ │ ├── ptr_to_slice_test.go │ │ ├── recursive.go │ │ ├── resolver.go │ │ ├── response_extension_test.go │ │ ├── root_.generated.go │ │ ├── scalar_context.generated.go │ │ ├── scalar_context.go │ │ ├── scalar_context.graphql │ │ ├── scalar_context_test.go │ │ ├── scalar_default.generated.go │ │ ├── scalar_default.graphql │ │ ├── scalar_default_test.go │ │ ├── schema.generated.go │ │ ├── schema.graphql │ │ ├── skip-include.generated.go │ │ ├── skip-include.graphql │ │ ├── slices.generated.go │ │ ├── slices.graphql │ │ ├── slices_test.go │ │ ├── stub.go │ │ ├── subscription_test.go │ │ ├── thirdparty.go │ │ ├── time_test.go │ │ ├── typefallback.generated.go │ │ ├── typefallback.graphql │ │ ├── typefallback_test.go │ │ ├── useptr.generated.go │ │ ├── useptr.graphql │ │ ├── useptr_test.go │ │ ├── v-ok.generated.go │ │ ├── v-ok.go │ │ ├── v-ok.graphql │ │ ├── v-ok_test.go │ │ ├── validtypes.generated.go │ │ ├── validtypes.graphql │ │ ├── validtypes_test.go │ │ ├── variadic.generated.go │ │ ├── variadic.go │ │ ├── variadic.graphql │ │ ├── weird_type_cases.generated.go │ │ ├── weird_type_cases.graphql │ │ ├── wrapped_type.generated.go │ │ ├── wrapped_type.go │ │ ├── wrapped_type.graphql │ │ └── wrapped_type_test.go │ ├── generated_test.go │ ├── nullabledirectives │ │ ├── directive.graphql │ │ ├── directive_test.go │ │ ├── generated │ │ │ ├── directive.generated.go │ │ │ ├── models │ │ │ │ └── models-gen.go │ │ │ ├── prelude.generated.go │ │ │ ├── resolvers │ │ │ │ └── resolver.go │ │ │ └── root_.generated.go │ │ ├── gqlgen.yml │ │ └── stub.go │ ├── singlefile │ │ ├── builtinscalar.graphql │ │ ├── bytes.go │ │ ├── complexity.graphql │ │ ├── complexity_test.go │ │ ├── defaults.graphql │ │ ├── defaults_test.go │ │ ├── defer.graphql │ │ ├── defer_test.go │ │ ├── directive.graphql │ │ ├── directive_test.go │ │ ├── embedded.go │ │ ├── embedded.graphql │ │ ├── embedded_test.go │ │ ├── enum.graphql │ │ ├── enums_test.go │ │ ├── fields_order.go │ │ ├── fields_order.graphql │ │ ├── fields_order_test.go │ │ ├── generated.go │ │ ├── generated_test.go │ │ ├── gqlgen.yml │ │ ├── input_test.go │ │ ├── interfaces.go │ │ ├── interfaces.graphql │ │ ├── interfaces_test.go │ │ ├── introspection │ │ │ └── it.go │ │ ├── introspection_test.go │ │ ├── invalid-packagename │ │ │ └── invalid-identifier.go │ │ ├── issue896.graphql │ │ ├── loops.graphql │ │ ├── maps.go │ │ ├── maps.graphql │ │ ├── maps_test.go │ │ ├── middleware_test.go │ │ ├── modelmethod_test.go │ │ ├── models-gen.go │ │ ├── models.go │ │ ├── mutation_with_custom_scalar.go │ │ ├── mutation_with_custom_scalar.graphql │ │ ├── mutation_with_custom_scalar_test.go │ │ ├── nulls.graphql │ │ ├── nulls_test.go │ │ ├── otherpkg │ │ │ └── model.go │ │ ├── panics.graphql │ │ ├── panics_test.go │ │ ├── primitive_objects.graphql │ │ ├── primitive_objects_test.go │ │ ├── ptr_to_any.go │ │ ├── ptr_to_any.graphql │ │ ├── ptr_to_any_test.go │ │ ├── ptr_to_ptr_input.go │ │ ├── ptr_to_ptr_input.graphql │ │ ├── ptr_to_ptr_input_test.go │ │ ├── ptr_to_slice.go │ │ ├── ptr_to_slice.graphql │ │ ├── ptr_to_slice_test.go │ │ ├── recursive.go │ │ ├── resolver.go │ │ ├── response_extension_test.go │ │ ├── scalar_context.go │ │ ├── scalar_context.graphql │ │ ├── scalar_context_test.go │ │ ├── scalar_default.graphql │ │ ├── scalar_default_test.go │ │ ├── schema.graphql │ │ ├── skip-include.graphql │ │ ├── skip_include_test.go │ │ ├── slices.graphql │ │ ├── slices_test.go │ │ ├── stub.go │ │ ├── subscription_test.go │ │ ├── thirdparty.go │ │ ├── time_test.go │ │ ├── typefallback.graphql │ │ ├── typefallback_test.go │ │ ├── useptr.graphql │ │ ├── useptr_test.go │ │ ├── v-ok.go │ │ ├── v-ok.graphql │ │ ├── v-ok_test.go │ │ ├── validtypes.graphql │ │ ├── validtypes_test.go │ │ ├── variadic.go │ │ ├── variadic.graphql │ │ ├── variadic_test.go │ │ ├── weird_type_cases.graphql │ │ ├── wrapped_type.go │ │ ├── wrapped_type.graphql │ │ └── wrapped_type_test.go │ └── usefunctionsyntaxforexecutioncontext │ │ ├── directive.go │ │ ├── generated.go │ │ ├── generated_test.go │ │ ├── gqlgen.yml │ │ ├── models-gen.go │ │ ├── resolver.go │ │ ├── stub.go │ │ └── test.graphql ├── type.go ├── type.gotpl └── util.go ├── complexity ├── complexity.go └── complexity_test.go ├── docs ├── build.sh ├── config.yml ├── content │ ├── _introduction.md │ ├── config.md │ ├── feature-comparison.md │ ├── getting-started.md │ ├── introduction.md │ ├── recipes │ │ ├── authentication.md │ │ ├── cors.md │ │ ├── enum.md │ │ ├── extra_fields.md │ │ ├── federation.md │ │ ├── gin.md │ │ ├── migration-0.11.md │ │ ├── modelgen-hook.md │ │ └── subscriptions.md │ └── reference │ │ ├── apq.md │ │ ├── changesets.md │ │ ├── complexity.md │ │ ├── dataloaders.md │ │ ├── directives.md │ │ ├── errors.md │ │ ├── field-collection.md │ │ ├── file-upload.md │ │ ├── introspection.md │ │ ├── model-generation.md │ │ ├── name-collision.md │ │ ├── plugins.md │ │ ├── resolvers.md │ │ └── scalars.md ├── layouts │ ├── 404.html │ ├── _default │ │ ├── baseof.html │ │ └── single.html │ ├── index.html │ ├── partials │ │ ├── gqlgen.svg │ │ ├── sidebar.html │ │ ├── version-banner.html │ │ └── version-switcher.html │ └── sitemap.xml ├── readme.md └── static │ ├── external-link-alt.svg │ ├── favicon.ico │ ├── main.css │ ├── main.js │ ├── request_anatomy.png │ ├── schema_layout.png │ └── syntax.css ├── go.mod ├── go.sum ├── graphql ├── any.go ├── bool.go ├── bool_test.go ├── cache.go ├── cache_test.go ├── coercion.go ├── coercion_test.go ├── context_field.go ├── context_field_test.go ├── context_operation.go ├── context_operation_test.go ├── context_path.go ├── context_path_test.go ├── context_response.go ├── context_response_test.go ├── context_root_field.go ├── context_root_field_test.go ├── deferred.go ├── duration.go ├── duration_test.go ├── errcode │ └── codes.go ├── error.go ├── executable_schema.go ├── executable_schema_mock.go ├── executor │ ├── executor.go │ ├── executor_test.go │ ├── extensions.go │ └── testexecutor │ │ └── testexecutor.go ├── fieldset.go ├── fieldset_test.go ├── float.go ├── float_test.go ├── handler.go ├── handler │ ├── apollofederatedtracingv1 │ │ ├── generated │ │ │ ├── apollo_trace.pb.go │ │ │ └── apollo_trace.proto │ │ ├── logger │ │ │ ├── logger.go │ │ │ └── logger_test.go │ │ ├── tracing.go │ │ ├── tracing_test.go │ │ └── tree_builder.go │ ├── apollotracing │ │ ├── tracer.go │ │ └── tracer_test.go │ ├── debug │ │ └── tracer.go │ ├── extension │ │ ├── apq.go │ │ ├── apq_test.go │ │ ├── complexity.go │ │ ├── complexity_test.go │ │ ├── introspection.go │ │ └── introspection_test.go │ ├── lru │ │ └── lru.go │ ├── server.go │ ├── server_test.go │ ├── testserver │ │ └── testserver.go │ └── transport │ │ ├── error.go │ │ ├── headers.go │ │ ├── headers_test.go │ │ ├── http_form_multipart.go │ │ ├── http_form_multipart_test.go │ │ ├── http_form_urlencode_test.go │ │ ├── http_form_urlencoded.go │ │ ├── http_get.go │ │ ├── http_get_test.go │ │ ├── http_graphql.go │ │ ├── http_graphql_test.go │ │ ├── http_multipart_mixed.go │ │ ├── http_multipart_mixed_test.go │ │ ├── http_post.go │ │ ├── http_post_test.go │ │ ├── options.go │ │ ├── options_test.go │ │ ├── reader.go │ │ ├── reader_test.go │ │ ├── sse.go │ │ ├── sse_test.go │ │ ├── util.go │ │ ├── websocket.go │ │ ├── websocket_close_reason.go │ │ ├── websocket_graphql_transport_ws.go │ │ ├── websocket_graphqlws.go │ │ ├── websocket_init.go │ │ ├── websocket_resolver_error.go │ │ ├── websocket_subprotocol.go │ │ └── websocket_test.go ├── handler_test.go ├── id.go ├── id_test.go ├── input.go ├── int.go ├── int_test.go ├── introspection │ ├── introspection.go │ ├── query.go │ ├── schema.go │ ├── schema_test.go │ ├── type.go │ └── type_test.go ├── jsonw.go ├── jsonw_test.go ├── map.go ├── omittable.go ├── omittable_go123_test.go ├── omittable_go124_test.go ├── omittable_test.go ├── oneshot.go ├── playground │ ├── altair_playground.go │ ├── altair_playground_test.go │ ├── apollo_sandbox_playground.go │ ├── apollo_sandbox_playground_test.go │ ├── helper_test.go │ ├── playground.go │ └── playground_test.go ├── recovery.go ├── response.go ├── root.go ├── stats.go ├── string.go ├── string_test.go ├── time.go ├── time_test.go ├── uint.go ├── uint_test.go ├── upload.go ├── uuid.go ├── uuid_test.go └── version.go ├── handler └── handler.go ├── init-templates ├── gqlgen.yml.gotmpl └── schema.graphqls ├── integration ├── .gitignore ├── README.md ├── codegen.ts ├── graphql.config.yml ├── package-lock.json ├── package.json ├── server │ ├── cmd │ │ └── integration │ │ │ └── server.go │ ├── generated.go │ ├── gqlgen.yml │ ├── models-go │ │ ├── element.go │ │ ├── generated.go │ │ └── viewer.go │ ├── remote_api │ │ └── user.go │ ├── resolver.go │ ├── schema │ │ ├── schema.graphql │ │ ├── testomitempty.graphql │ │ └── user.graphql │ └── testomitempty │ │ └── testmodel.go ├── src │ ├── __test__ │ │ └── integration.spec.ts │ ├── generated │ │ ├── .gitignore │ │ ├── fragment-masking.ts │ │ ├── gql.ts │ │ ├── graphql.ts │ │ ├── index.ts │ │ └── schema-expected.graphql │ └── queries │ │ ├── coercion.graphql │ │ ├── complexity.graphql │ │ ├── date.graphql │ │ ├── error.graphql │ │ ├── jsonEncoding.graphql │ │ ├── path.graphql │ │ └── viewer.graphql └── tsconfig.json ├── internal ├── code │ ├── alias.go │ ├── alias_test.go │ ├── compare.go │ ├── compare_test.go │ ├── imports.go │ ├── imports_test.go │ ├── packages.go │ ├── packages_test.go │ ├── testdata │ │ ├── a │ │ │ └── a.go │ │ ├── b │ │ │ └── b.go │ │ ├── c │ │ │ └── c.go │ │ └── p │ │ │ └── p.go │ ├── util.go │ └── util_test.go ├── imports │ ├── prune.go │ ├── prune_test.go │ └── testdata │ │ ├── unused.expected.go │ │ └── unused.go ├── rewrite │ ├── rewriter.go │ ├── rewriter_test.go │ └── testdata │ │ └── example.go └── tools.go ├── main.go ├── plugin ├── federation │ ├── constants.go │ ├── entity.go │ ├── federation.go │ ├── federation.gotpl │ ├── federation_computedrequires_test.go │ ├── federation_entityresolver_test.go │ ├── federation_explicitrequires_test.go │ ├── federation_test.go │ ├── federation_use_function_syntax_for_execution_context_test.go │ ├── fedruntime │ │ └── runtime.go │ ├── fieldset │ │ ├── fieldset.go │ │ └── fieldset_test.go │ ├── readme.md │ ├── requires.gotpl │ ├── test_data │ │ ├── model │ │ │ └── federation.go │ │ └── model2 │ │ │ └── federation.go │ └── testdata │ │ ├── allthethings │ │ ├── generated │ │ │ └── federation.go │ │ ├── gqlgen.yml │ │ ├── model │ │ │ └── federation.go │ │ └── schema.graphql │ │ ├── computedrequires │ │ ├── entity.resolvers.go │ │ ├── errors.go │ │ ├── generated │ │ │ ├── exec.go │ │ │ ├── federation.go │ │ │ └── models │ │ │ │ └── models.go │ │ ├── gqlgen.yml │ │ ├── main │ │ │ └── server.go │ │ ├── resolver.go │ │ ├── schema.graphql │ │ └── schema.resolvers.go │ │ ├── entities │ │ ├── nokey.graphql │ │ └── nokey.yml │ │ ├── entityinterfaces │ │ ├── generated │ │ │ ├── exec.go │ │ │ ├── federation.go │ │ │ └── models_gen.go │ │ ├── interface.graphql │ │ └── interface.yml │ │ ├── entityresolver │ │ ├── entity.resolvers.go │ │ ├── generated │ │ │ ├── errors.go │ │ │ ├── exec.go │ │ │ ├── federation.go │ │ │ └── model │ │ │ │ └── models.go │ │ ├── gqlgen.yml │ │ ├── resolver.go │ │ ├── schema.graphql │ │ └── schema.resolvers.go │ │ ├── explicitrequires │ │ ├── entity.resolvers.go │ │ ├── generated │ │ │ ├── errors.go │ │ │ ├── exec.go │ │ │ ├── federation.go │ │ │ ├── federation.requires.go │ │ │ └── models.go │ │ ├── gqlgen.yml │ │ ├── resolver.go │ │ ├── schema.graphql │ │ └── schema.resolvers.go │ │ ├── federation2 │ │ ├── federation2.graphql │ │ ├── federation2.yml │ │ └── generated │ │ │ └── federation.go │ │ ├── interfaces │ │ ├── extends.graphqls │ │ ├── extends.yml │ │ ├── key.graphqls │ │ ├── key.yml │ │ ├── unused_key.graphqls │ │ └── unused_key.yml │ │ ├── multi │ │ ├── multi.graphqls │ │ └── multi.yml │ │ ├── schema │ │ ├── customquerytype.graphql │ │ └── customquerytype.yml │ │ └── usefunctionsyntaxforexecutioncontext │ │ ├── entity.resolvers.go │ │ ├── generated │ │ ├── errors.go │ │ ├── exec.go │ │ ├── federation.go │ │ └── model │ │ │ └── models.go │ │ ├── gqlgen.yml │ │ ├── resolver.go │ │ ├── schema.graphql │ │ └── schema.resolvers.go ├── modelgen │ ├── internal │ │ └── extrafields │ │ │ └── types.go │ ├── models.go │ ├── models.gotpl │ ├── models_test.go │ ├── out │ │ ├── existing.go │ │ ├── generated.go │ │ └── generated_omit_root_models.go │ ├── out_enable_model_json_omitempty_tag_false │ │ ├── existing.go │ │ └── generated.go │ ├── out_enable_model_json_omitempty_tag_false_omitempty_tag_false_omitzero_tag_nil │ │ └── generated.go │ ├── out_enable_model_json_omitempty_tag_false_omitempty_tag_false_omitzero_tag_true │ │ └── generated.go │ ├── out_enable_model_json_omitempty_tag_false_omitzero_tag_false │ │ ├── existing.go │ │ └── generated.go │ ├── out_enable_model_json_omitempty_tag_false_omitzero_tag_nil │ │ ├── existing.go │ │ └── generated.go │ ├── out_enable_model_json_omitempty_tag_false_omitzero_tag_true │ │ ├── existing.go │ │ └── generated.go │ ├── out_enable_model_json_omitempty_tag_nil │ │ ├── existing.go │ │ └── generated.go │ ├── out_enable_model_json_omitempty_tag_true │ │ ├── existing.go │ │ └── generated.go │ ├── out_enable_model_json_omitzero_tag_false │ │ ├── existing.go │ │ └── generated.go │ ├── out_enable_model_json_omitzero_tag_nil │ │ ├── existing.go │ │ └── generated.go │ ├── out_enable_model_json_omitzero_tag_true │ │ ├── existing.go │ │ └── generated.go │ ├── out_nullable_input_omittable │ │ ├── existing.go │ │ └── generated.go │ ├── out_omit_resolver_fields │ │ └── generated.go │ ├── out_struct_pointers │ │ ├── existing.go │ │ └── generated.go │ ├── testdata │ │ ├── customModelTemplate.gotpl │ │ ├── gqlgen.yml │ │ ├── gqlgen_custom_model_template.yml │ │ ├── gqlgen_enable_model_json_omitempty_tag_false.yml │ │ ├── gqlgen_enable_model_json_omitempty_tag_false_omitzero_tag_false.yml │ │ ├── gqlgen_enable_model_json_omitempty_tag_false_omitzero_tag_nil.yml │ │ ├── gqlgen_enable_model_json_omitempty_tag_false_omitzero_tag_true.yml │ │ ├── gqlgen_enable_model_json_omitempty_tag_nil.yml │ │ ├── gqlgen_enable_model_json_omitempty_tag_true.yml │ │ ├── gqlgen_enable_model_json_omitzero_tag_false.yml │ │ ├── gqlgen_enable_model_json_omitzero_tag_nil.yml │ │ ├── gqlgen_enable_model_json_omitzero_tag_true.yml │ │ ├── gqlgen_nullable_input_omittable.yml │ │ ├── gqlgen_omit_resolver_fields.yml │ │ ├── gqlgen_omit_root_models.yml │ │ ├── gqlgen_struct_field_pointers.yml │ │ ├── schema.graphql │ │ ├── schema_omit_resolver_fields.graphql │ │ └── schema_omit_root_models.graphql │ └── types.go ├── plugin.go ├── resolvergen │ ├── resolver.go │ ├── resolver.gotpl │ ├── resolver_test.go │ └── testdata │ │ ├── filetemplate │ │ ├── gqlgen.yml │ │ └── out │ │ │ ├── model.go │ │ │ ├── resolver.go │ │ │ ├── schema.custom.go │ │ │ └── schema.custom.go.txt │ │ ├── followschema │ │ ├── gqlgen.yml │ │ └── out │ │ │ ├── model.go │ │ │ ├── resolver.go │ │ │ ├── schema.resolvers.go │ │ │ └── schema.resolvers.go.txt │ │ ├── invalid_model_path │ │ └── gqlgen.yml │ │ ├── omit_template_comment │ │ ├── gqlgen.yml │ │ └── out │ │ │ ├── resolver.go │ │ │ └── schema.resolvers.go │ │ ├── resolver_implementor │ │ ├── gqlgen.yml │ │ └── out │ │ │ ├── model.go │ │ │ ├── resolver.go │ │ │ └── schema.resolvers.go │ │ ├── resolvertemplate │ │ ├── customResolverTemplate.gotpl │ │ ├── gqlgen.yml │ │ └── out │ │ │ ├── resolver.go │ │ │ └── schema.resolvers.go │ │ ├── return_values │ │ ├── gqlgen.yml │ │ ├── ignored.go │ │ ├── model.go │ │ ├── resolvers.go │ │ ├── return_values_test.go │ │ └── schema.graphqls │ │ ├── schema.graphql │ │ ├── singlefile │ │ ├── gqlgen.yml │ │ └── out │ │ │ ├── model.go │ │ │ └── resolver.go │ │ └── singlefile_preserve │ │ ├── gqlgen.yml │ │ └── out │ │ ├── model.go │ │ └── resolver.go ├── servergen │ ├── server.go │ └── server.gotpl └── stubgen │ ├── stubs.go │ └── stubs.gotpl └── testdata ├── gomod-with-leading-comments.mod └── gqlgen.go /.chglog/config.yml: -------------------------------------------------------------------------------- 1 | style: github 2 | template: CHANGELOG-full-history.tpl.md 3 | info: 4 | title: CHANGELOG 5 | repository_url: https://github.com/99designs/gqlgen 6 | options: 7 | commits: 8 | # filters: 9 | # Type: [] 10 | commit_groups: 11 | # title_maps: [] 12 | header: 13 | pattern: "^(.*)$" 14 | pattern_maps: 15 | - Subject 16 | notes: 17 | keywords: 18 | - BREAKING CHANGE -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | /**/node_modules 2 | /codegen/tests/gen 3 | /vendor 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 4 10 | 11 | [*.{go,gotpl}] 12 | indent_style = tab 13 | 14 | [*.yml] 15 | indent_size = 2 16 | 17 | # These often end up with go code inside, so lets keep tabs 18 | [*.{html,md}] 19 | indent_size = 2 20 | indent_style = tab 21 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /codegen/templates/data.go linguist-generated 2 | /_examples/dataloader/*_gen.go linguist-generated 3 | generated.go linguist-generated 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### What happened? 2 | 3 | ### What did you expect? 4 | 5 | ### Minimal graphql.schema and models to reproduce 6 | 7 | ### versions 8 | - `go run github.com/99designs/gqlgen version`? 9 | - `go version`? 10 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Describe your PR and link to any relevant issues. 2 | 3 | I have: 4 | - [ ] Added tests covering the bug / feature (see [testing](https://github.com/99designs/gqlgen/blob/master/TESTING.md)) 5 | - [ ] Updated any relevant documentation (see [docs](https://github.com/99designs/gqlgen/tree/master/docs/content)) 6 | -------------------------------------------------------------------------------- /.github/workflows/GOVERSION.txt: -------------------------------------------------------------------------------- 1 | 1.23.0 2 | -------------------------------------------------------------------------------- /.github/workflows/check-federation: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | export GO111MODULE=on 5 | cd _examples/federation 6 | 7 | ./start.sh & 8 | 9 | sleep 5 10 | curl -s --connect-timeout 5 \ 11 | --max-time 10 \ 12 | --retry 5 \ 13 | --retry-delay 5 \ 14 | --retry-max-time 40 \ 15 | --retry-connrefused \ 16 | localhost:4003 > /dev/null 17 | 18 | sleep 1 19 | 20 | echo "### running jest integration spec" 21 | export NODE_OPTIONS="--experimental-vm-modules" 22 | npx jest --color 23 | 24 | -------------------------------------------------------------------------------- /.github/workflows/check-fmt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exuo pipefail 4 | export GO111MODULE=on 5 | export GOTOOLCHAIN=local 6 | go fmt ./... 7 | cd _examples && go fmt ./... 8 | if [[ $(git --no-pager diff) ]] ; then 9 | echo "you need to run "go fmt" and commit the changes" 10 | git --no-pager diff 11 | exit 1 12 | fi 13 | -------------------------------------------------------------------------------- /.github/workflows/check-generate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -exuo pipefail 3 | export GO111MODULE=on 4 | echo Generating code 5 | go generate ./... 6 | if [[ $(git --no-pager diff) ]] ; then 7 | echo "you need to run "go generate ./..." and commit the changes" 8 | git --no-pager diff 9 | exit 1 10 | fi 11 | -------------------------------------------------------------------------------- /.github/workflows/check-gomod.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | export GOVERSION="$(cat GOVERSION.txt)" 6 | export GOTOOLCHAIN="go${GOVERSION}" 7 | go get go@${GOVERSION} || true 8 | go get toolchain@none || true 9 | go mod tidy || true 10 | 11 | STATUS=$( git status --porcelain go.mod go.sum ) 12 | if [ ! -z "$STATUS" ]; then 13 | echo "Running go mod tidy modified go.mod and/or go.sum" 14 | echo "Please run the following then make a git commit:" 15 | echo "go get go@${GOVERSION}" 16 | echo "go get toolchain@none" 17 | echo "go mod tidy" 18 | echo "export GOTOOLCHAIN=${GOTOOLCHAIN}" 19 | exit 1 20 | fi 21 | exit 0 -------------------------------------------------------------------------------- /.github/workflows/check-init: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | export GO111MODULE=on 5 | gqlgen_dir=$(pwd) 6 | cd $(mktemp -d) 7 | go mod init inittest 8 | printf '//go:build tools\npackage tools\nimport _ "github.com/99designs/gqlgen"' | gofmt > tools.go 9 | go mod tidy 10 | go mod edit -replace=github.com/99designs/gqlgen="$gqlgen_dir" 11 | go mod tidy 12 | 13 | if ! go run github.com/99designs/gqlgen init ; then 14 | echo "gqlgen init failed" 15 | exit 125 16 | fi 17 | 18 | if ! go run github.com/99designs/gqlgen generate ; then 19 | echo "gqlgen generate failed" 20 | exit 125 21 | fi 22 | -------------------------------------------------------------------------------- /.github/workflows/check-integration: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | export GO111MODULE=on 5 | cd integration 6 | 7 | date 8 | go run ./server/cmd/integration/server.go & 9 | 10 | sleep 5 11 | curl -s --connect-timeout 5 \ 12 | --max-time 10 \ 13 | --retry 5 \ 14 | --retry-delay 5 \ 15 | --retry-max-time 40 \ 16 | --retry-connrefused \ 17 | localhost:8080 > /dev/null 18 | 19 | 20 | echo "### validating introspected schema" 21 | npm run gen 22 | 23 | if ! diff <(tail -n +3 src/generated/schema-expected.graphql) <(tail -n +3 src/generated/schema-fetched.graphql) ; then 24 | echo "The expected schema has changed, you need to update schema-expected.graphql with any expected changes" 25 | exit 1 26 | fi 27 | 28 | echo "### running integration spec" 29 | npm run test 30 | -------------------------------------------------------------------------------- /.github/workflows/gomod-clean.yml: -------------------------------------------------------------------------------- 1 | name: GoModVersion 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | types: [ opened, synchronize ] 8 | env: 9 | GOTOOLCHAIN: local 10 | # When a new revision is pushed to a PR, cancel all in-progress CI runs for that 11 | # PR. See https://docs.github.com/en/actions/using-jobs/using-concurrency 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 14 | cancel-in-progress: true 15 | jobs: 16 | gomodclean: 17 | strategy: 18 | matrix: 19 | go: ["1.23"] 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | - uses: actions/setup-go@v5 24 | with: 25 | go-version: ${{ matrix.go }} 26 | - run: .github/workflows/check-fmt 27 | -------------------------------------------------------------------------------- /.github/workflows/report.yml: -------------------------------------------------------------------------------- 1 | name: test report 2 | on: 3 | workflow_run: 4 | workflows: ["Test"] 5 | types: 6 | - completed 7 | 8 | permissions: 9 | checks: write 10 | 11 | jobs: 12 | checks: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Download Test Report 16 | uses: dawidd6/action-download-artifact@v10 17 | with: 18 | name: junit-test-results 19 | workflow: ${{ github.event.workflow.id }} 20 | run_id: ${{ github.event.workflow_run.id }} 21 | - name: Publish Test Report 22 | uses: mikepenz/action-junit-report@v5 23 | with: 24 | commit: ${{github.event.workflow_run.head_sha}} 25 | report_paths: '**/*.xml' 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /docs/public 3 | /docs/.hugo_build.lock 4 | /_examples/chat/node_modules 5 | /integration/node_modules 6 | /integration/schema-fetched.graphql 7 | /_examples/chat/package-lock.json 8 | /_examples/federation/package-lock.json 9 | /_examples/federation/node_modules 10 | /codegen/gen 11 | /gen 12 | 13 | /.vscode 14 | .idea/ 15 | *.test 16 | *.out 17 | gqlgen 18 | *.exe 19 | 20 | node_modules 21 | 22 | # generated files 23 | /api/testdata/default/graph/generated.go 24 | /api/testdata/federation2/graph/federation.go 25 | /api/testdata/federation2/graph/generated.go -------------------------------------------------------------------------------- /RELEASE-CHECKLIST.md: -------------------------------------------------------------------------------- 1 | # When gqlgen gets released, the following things need to happen 2 | Assuming the next version is $NEW_VERSION=v0.16.0 or something like that. 3 | 4 | 1. Run the https://github.com/99designs/gqlgen/blob/master/bin/release: 5 | ``` 6 | ./bin/release $NEW_VERSION 7 | ``` 8 | 2. git-chglog -o CHANGELOG.md 9 | 3. go generate ./... 10 | 4. git commit and push the CHANGELOG.md 11 | 5. Go to https://github.com/99designs/gqlgen/releases and draft new release, autogenerate the release notes, and Create a discussion for this release 12 | 6. Comment on the release discussion with any really important notes (breaking changes) 13 | 14 | I used https://github.com/git-chglog/git-chglog to automate the changelog maintenance process for now. We could just as easily use go releaser to make the whole thing automated. 15 | -------------------------------------------------------------------------------- /_examples/chat/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | /corpus 9 | 10 | # production 11 | /build 12 | 13 | # misc 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | -------------------------------------------------------------------------------- /_examples/chat/.gqlgen.yml: -------------------------------------------------------------------------------- 1 | models: 2 | Chatroom: 3 | model: github.com/99designs/gqlgen/_examples/chat.Chatroom 4 | -------------------------------------------------------------------------------- /_examples/chat/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package chat 4 | 5 | import ( 6 | "time" 7 | ) 8 | 9 | type Message struct { 10 | ID string `json:"id"` 11 | Text string `json:"text"` 12 | CreatedBy string `json:"createdBy"` 13 | CreatedAt time.Time `json:"createdAt"` 14 | Subscription *Subscription `json:"subscription"` 15 | } 16 | 17 | type Mutation struct { 18 | } 19 | 20 | type Query struct { 21 | } 22 | 23 | type Subscription struct { 24 | } 25 | -------------------------------------------------------------------------------- /_examples/chat/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React App 8 | 9 | 10 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /_examples/chat/schema.graphql: -------------------------------------------------------------------------------- 1 | type Chatroom { 2 | name: String! 3 | messages: [Message!]! 4 | subscription: Subscription! 5 | } 6 | 7 | type Message { 8 | id: ID! 9 | text: String! 10 | createdBy: String! 11 | createdAt: Time! 12 | subscription: Subscription! 13 | } 14 | 15 | type Query { 16 | room(name: String!): Chatroom 17 | } 18 | 19 | type Mutation { 20 | post(text: String!, username: String!, roomName: String!): Message! 21 | } 22 | 23 | type Subscription { 24 | messageAdded(roomName: String!): Message! 25 | } 26 | 27 | scalar Time 28 | 29 | directive @user(username: String!) on SUBSCRIPTION 30 | -------------------------------------------------------------------------------- /_examples/chat/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /_examples/chat/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "noEmit": true, 20 | "jsx": "preserve" 21 | }, 22 | "include": [ 23 | "src" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /_examples/config/.gqlgen.yml: -------------------------------------------------------------------------------- 1 | # .gqlgen.yml _examples 2 | # 3 | # Refer to https://gqlgen.com/config/ 4 | # for detailed .gqlgen.yml documentation. 5 | 6 | schema: "*.graphql" 7 | exec: 8 | filename: generated.go 9 | model: 10 | filename: models_gen.go 11 | resolver: 12 | type: Resolver 13 | layout: follow-schema 14 | dir: . 15 | 16 | models: 17 | Todo: # Object 18 | fields: 19 | text: 20 | fieldName: Description # Field 21 | NewTodo: # Input 22 | fields: 23 | userId: 24 | fieldName: UserID # Field 25 | -------------------------------------------------------------------------------- /_examples/config/model.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import "fmt" 4 | 5 | type User struct { 6 | ID string 7 | FirstName, LastName string 8 | Role UserRole 9 | } 10 | 11 | func (user *User) FullName() string { 12 | return fmt.Sprintf("%s %s", user.FirstName, user.LastName) 13 | } 14 | 15 | type UserRole struct { 16 | RoleName string 17 | } 18 | -------------------------------------------------------------------------------- /_examples/config/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package config 4 | 5 | type Mutation struct { 6 | } 7 | 8 | type NewTodo struct { 9 | Text string `json:"text"` 10 | UserID string `json:"userId"` 11 | } 12 | 13 | type Query struct { 14 | } 15 | 16 | type Todo struct { 17 | ID string `json:"id"` 18 | DatabaseID int `json:"databaseId"` 19 | Description string `json:"text"` 20 | Done bool `json:"done"` 21 | User *User `json:"user"` 22 | Query *Query `json:"query"` 23 | Mutation *Mutation `json:"mutation"` 24 | } 25 | -------------------------------------------------------------------------------- /_examples/config/resolver.go: -------------------------------------------------------------------------------- 1 | //go:generate go run ../../testdata/gqlgen.go 2 | 3 | package config 4 | 5 | func New() Config { 6 | c := Config{ 7 | Resolvers: &Resolver{ 8 | todos: []*Todo{ 9 | {DatabaseID: 1, Description: "A todo not to forget", Done: false}, 10 | {DatabaseID: 2, Description: "This is the most important", Done: false}, 11 | {DatabaseID: 3, Description: "Please do this or else", Done: false}, 12 | }, 13 | nextID: 3, 14 | }, 15 | } 16 | return c 17 | } 18 | 19 | type Resolver struct { 20 | todos []*Todo 21 | nextID int 22 | } 23 | -------------------------------------------------------------------------------- /_examples/config/schema.graphql: -------------------------------------------------------------------------------- 1 | directive @goModel( 2 | model: String 3 | models: [String!] 4 | ) on OBJECT | INPUT_OBJECT | SCALAR | ENUM | INTERFACE | UNION 5 | directive @goField( 6 | forceResolver: Boolean 7 | name: String 8 | omittable: Boolean 9 | type: String 10 | ) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION 11 | 12 | type Query { 13 | todos: [Todo!]! 14 | } 15 | 16 | type Mutation { 17 | createTodo(input: NewTodo!): Todo! 18 | } 19 | -------------------------------------------------------------------------------- /_examples/config/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | todo "github.com/99designs/gqlgen/_examples/config" 8 | "github.com/99designs/gqlgen/graphql/handler" 9 | "github.com/99designs/gqlgen/graphql/handler/transport" 10 | "github.com/99designs/gqlgen/graphql/playground" 11 | ) 12 | 13 | func main() { 14 | srv := handler.New( 15 | todo.NewExecutableSchema(todo.New()), 16 | ) 17 | srv.AddTransport(transport.GET{}) 18 | srv.AddTransport(transport.POST{}) 19 | 20 | http.Handle("/", playground.Handler("Todo", "/query")) 21 | http.Handle("/query", srv) 22 | log.Fatal(http.ListenAndServe(":8081", nil)) 23 | } 24 | -------------------------------------------------------------------------------- /_examples/config/todo.graphql: -------------------------------------------------------------------------------- 1 | type Todo { 2 | id: ID! @goField(forceResolver: true) 3 | databaseId: Int! 4 | text: String! 5 | done: Boolean! 6 | user: User! 7 | query: Query! 8 | mutation: Mutation! 9 | } 10 | 11 | input NewTodo { 12 | text: String! 13 | userId: String! 14 | } 15 | -------------------------------------------------------------------------------- /_examples/config/todo.resolvers.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | // This file will be automatically regenerated based on the schema, any resolver implementations 4 | // will be copied through when generating and any unknown code will be moved to the end. 5 | // Code generated by github.com/99designs/gqlgen version v0.17.73-dev 6 | 7 | import ( 8 | "context" 9 | "fmt" 10 | ) 11 | 12 | // ID is the resolver for the id field. 13 | func (r *todoResolver) ID(ctx context.Context, obj *Todo) (string, error) { 14 | if obj.ID != "" { 15 | return obj.ID, nil 16 | } 17 | 18 | obj.ID = fmt.Sprintf("TODO:%d", obj.DatabaseID) 19 | 20 | return obj.ID, nil 21 | } 22 | 23 | // Todo returns TodoResolver implementation. 24 | func (r *Resolver) Todo() TodoResolver { return &todoResolver{r} } 25 | 26 | type todoResolver struct{ *Resolver } 27 | -------------------------------------------------------------------------------- /_examples/config/user.graphql: -------------------------------------------------------------------------------- 1 | type User 2 | @goModel(model:"github.com/99designs/gqlgen/_examples/config.User") { 3 | id: ID! 4 | name: String! @goField(name:"FullName") 5 | role: role! 6 | } 7 | 8 | type role 9 | @goModel(model:"github.com/99designs/gqlgen/_examples/config.UserRole") { 10 | name: String! 11 | } 12 | -------------------------------------------------------------------------------- /_examples/config/user.resolvers.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | // This file will be automatically regenerated based on the schema, any resolver implementations 4 | // will be copied through when generating and any unknown code will be moved to the end. 5 | // Code generated by github.com/99designs/gqlgen version v0.17.73-dev 6 | 7 | import ( 8 | "context" 9 | ) 10 | 11 | // Name is the resolver for the name field. 12 | func (r *roleResolver) Name(ctx context.Context, obj *UserRole) (string, error) { 13 | if obj == nil { 14 | return "", nil 15 | } 16 | return obj.RoleName, nil 17 | } 18 | 19 | // Role returns RoleResolver implementation. 20 | func (r *Resolver) Role() RoleResolver { return &roleResolver{r} } 21 | 22 | type roleResolver struct{ *Resolver } 23 | -------------------------------------------------------------------------------- /_examples/dataloader/.gqlgen.yml: -------------------------------------------------------------------------------- 1 | models: 2 | Order: 3 | model: github.com/99designs/gqlgen/_examples/dataloader.Order 4 | Customer: 5 | model: github.com/99designs/gqlgen/_examples/dataloader.Customer 6 | -------------------------------------------------------------------------------- /_examples/dataloader/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package dataloader 4 | 5 | type Address struct { 6 | ID int `json:"id"` 7 | Street string `json:"street"` 8 | Country string `json:"country"` 9 | } 10 | 11 | type Item struct { 12 | Name string `json:"name"` 13 | } 14 | 15 | type Query struct { 16 | } 17 | -------------------------------------------------------------------------------- /_examples/dataloader/readme.md: -------------------------------------------------------------------------------- 1 | ### dataloader 2 | 3 | This example uses [dataloaden](https://github.com/vektah/dataloaden) to avoiding n+1 queries. 4 | 5 | 6 | There is also [nicksrandall/dataloader](https://github.com/nicksrandall/dataloader) if you wanted to avoid 7 | doing more codegeneration. 8 | -------------------------------------------------------------------------------- /_examples/dataloader/schema.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | customers: [Customer!] 3 | 4 | # these methods are here to test code generation of nested arrays 5 | torture1d(customerIds: [Int!]): [Customer!] 6 | torture2d(customerIds: [[Int!]]): [[Customer!]] 7 | } 8 | 9 | type Customer { 10 | id: Int! 11 | name: String! 12 | address: Address 13 | orders: [Order!] 14 | } 15 | 16 | type Address { 17 | id: Int! 18 | street: String! 19 | country: String! 20 | } 21 | 22 | type Order { 23 | id: Int! 24 | date: Time! 25 | amount: Float! 26 | items: [Item!] 27 | } 28 | 29 | type Item { 30 | name: String! 31 | } 32 | scalar Time 33 | -------------------------------------------------------------------------------- /_examples/dataloader/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/99designs/gqlgen/_examples/dataloader" 8 | "github.com/99designs/gqlgen/graphql/handler" 9 | "github.com/99designs/gqlgen/graphql/handler/transport" 10 | "github.com/99designs/gqlgen/graphql/playground" 11 | ) 12 | 13 | func main() { 14 | router := http.NewServeMux() 15 | 16 | srv := handler.New( 17 | dataloader.NewExecutableSchema(dataloader.Config{Resolvers: &dataloader.Resolver{}}), 18 | ) 19 | srv.AddTransport(transport.GET{}) 20 | srv.AddTransport(transport.POST{}) 21 | 22 | router.Handle("/", playground.Handler("Dataloader", "/query")) 23 | router.Handle("/query", srv) 24 | 25 | log.Println("connect to http://localhost:8082/ for graphql playground") 26 | log.Fatal(http.ListenAndServe(":8082", dataloader.LoaderMiddleware(router))) 27 | } 28 | -------------------------------------------------------------------------------- /_examples/deferexample/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: "*.graphql" 2 | 3 | exec: 4 | filename: generated.go 5 | 6 | model: 7 | filename: models_gen.go 8 | 9 | resolver: 10 | layout: follow-schema 11 | dir: . 12 | filename_template: "{name}.resolvers.go" 13 | 14 | call_argument_directives_with_null: true 15 | 16 | models: 17 | ID: 18 | model: 19 | - github.com/99designs/gqlgen/graphql.ID 20 | Todo: 21 | fields: 22 | user: 23 | resolver: true 24 | extraFields: 25 | userID: 26 | type: "string" 27 | -------------------------------------------------------------------------------- /_examples/deferexample/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package deferexample 4 | 5 | type Mutation struct { 6 | } 7 | 8 | type NewTodo struct { 9 | Text string `json:"text"` 10 | UserID string `json:"userId"` 11 | } 12 | 13 | type Query struct { 14 | } 15 | 16 | type Todo struct { 17 | ID string `json:"id"` 18 | Text string `json:"text"` 19 | Done bool `json:"done"` 20 | User *User `json:"user"` 21 | userID string `json:"-"` 22 | } 23 | 24 | type User struct { 25 | ID string `json:"id"` 26 | Name string `json:"name"` 27 | } 28 | -------------------------------------------------------------------------------- /_examples/deferexample/resolver.go: -------------------------------------------------------------------------------- 1 | package deferexample 2 | 3 | import "sync" 4 | 5 | type Resolver struct { 6 | mu sync.RWMutex 7 | todos []*Todo 8 | } 9 | -------------------------------------------------------------------------------- /_examples/deferexample/schema.graphql: -------------------------------------------------------------------------------- 1 | # GraphQL schema example 2 | # 3 | # https://gqlgen.com/getting-started/ 4 | 5 | type Todo { 6 | id: ID! 7 | text: String! 8 | done: Boolean! 9 | user: User! 10 | } 11 | 12 | type User { 13 | id: ID! 14 | name: String! 15 | } 16 | 17 | type Query { 18 | todos: [Todo!]! 19 | } 20 | 21 | input NewTodo { 22 | text: String! 23 | userId: String! 24 | } 25 | 26 | type Mutation { 27 | createTodo(input: NewTodo!): Todo! 28 | } 29 | -------------------------------------------------------------------------------- /_examples/embedding/parent.graphqls: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | parentdir: String! 3 | } 4 | -------------------------------------------------------------------------------- /_examples/embedding/subdir/cfgdir/generate_in_gendir.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - schemadir/*.graphqls 3 | - ../*.graphqls 4 | - '*.graphqls' 5 | exec: 6 | dir: gendir 7 | filename: gendir/generated.go 8 | package: gendir 9 | 10 | federation: 11 | filename: gendir/federation_gen.go 12 | package: gendir 13 | 14 | model: 15 | filename: gendir/model.go 16 | package: gendir -------------------------------------------------------------------------------- /_examples/embedding/subdir/cfgdir/generate_in_subdir.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - schemadir/*.graphqls 3 | - ../*.graphqls 4 | - '*.graphqls' 5 | exec: 6 | layout: follow-schema 7 | dir: . 8 | package: subdir 9 | 10 | federation: 11 | filename: federation_gen.go 12 | package: subdir 13 | 14 | model: 15 | filename: model.go 16 | package: subdir -------------------------------------------------------------------------------- /_examples/embedding/subdir/federation_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package subdir 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "strings" 9 | 10 | "github.com/99designs/gqlgen/plugin/federation/fedruntime" 11 | ) 12 | 13 | var ( 14 | ErrUnknownType = errors.New("unknown type") 15 | ErrTypeNotFound = errors.New("type not found") 16 | ) 17 | 18 | func (ec *executionContext) __resolve__service(ctx context.Context) (fedruntime.Service, error) { 19 | if ec.DisableIntrospection { 20 | return fedruntime.Service{}, errors.New("federated introspection disabled") 21 | } 22 | 23 | var sdl []string 24 | 25 | for _, src := range sources { 26 | if src.BuiltIn { 27 | continue 28 | } 29 | sdl = append(sdl, src.Input) 30 | } 31 | 32 | return fedruntime.Service{ 33 | SDL: strings.Join(sdl, "\n"), 34 | }, nil 35 | } 36 | -------------------------------------------------------------------------------- /_examples/embedding/subdir/gendir/federation_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package gendir 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "strings" 9 | 10 | "github.com/99designs/gqlgen/plugin/federation/fedruntime" 11 | ) 12 | 13 | var ( 14 | ErrUnknownType = errors.New("unknown type") 15 | ErrTypeNotFound = errors.New("type not found") 16 | ) 17 | 18 | func (ec *executionContext) __resolve__service(ctx context.Context) (fedruntime.Service, error) { 19 | if ec.DisableIntrospection { 20 | return fedruntime.Service{}, errors.New("federated introspection disabled") 21 | } 22 | 23 | var sdl []string 24 | 25 | for _, src := range sources { 26 | if src.BuiltIn { 27 | continue 28 | } 29 | sdl = append(sdl, src.Input) 30 | } 31 | 32 | return fedruntime.Service{ 33 | SDL: strings.Join(sdl, "\n"), 34 | }, nil 35 | } 36 | -------------------------------------------------------------------------------- /_examples/embedding/subdir/gendir/model.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package gendir 4 | 5 | type Query struct { 6 | } 7 | -------------------------------------------------------------------------------- /_examples/embedding/subdir/model.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package subdir 4 | 5 | type Query struct { 6 | } 7 | -------------------------------------------------------------------------------- /_examples/embedding/subdir/schemadir/root.graphqls: -------------------------------------------------------------------------------- 1 | type Query { 2 | inSchemadir: String! 3 | } 4 | -------------------------------------------------------------------------------- /_examples/embedding/subdir/subdir.graphqls: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | subdir: String! 3 | } 4 | -------------------------------------------------------------------------------- /_examples/enum/api/model.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | type InPackage bool 4 | 5 | const ( 6 | InPackageTrue InPackage = true 7 | InPackageFalse InPackage = false 8 | ) 9 | -------------------------------------------------------------------------------- /_examples/enum/api/resolver.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type Resolver struct{} 8 | -------------------------------------------------------------------------------- /_examples/enum/cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/99designs/gqlgen/_examples/enum/api" 8 | "github.com/99designs/gqlgen/graphql/handler" 9 | "github.com/99designs/gqlgen/graphql/handler/transport" 10 | "github.com/99designs/gqlgen/graphql/playground" 11 | ) 12 | 13 | func main() { 14 | srv := handler.New( 15 | api.NewExecutableSchema(api.Config{Resolvers: &api.Resolver{}}), 16 | ) 17 | 18 | srv.AddTransport(transport.Options{}) 19 | srv.AddTransport(transport.GET{}) 20 | srv.AddTransport(transport.POST{}) 21 | 22 | http.Handle("/", playground.Handler("Enum", "/query")) 23 | http.Handle("/query", srv) 24 | log.Fatal(http.ListenAndServe(":8081", nil)) 25 | } 26 | -------------------------------------------------------------------------------- /_examples/enum/gen.go: -------------------------------------------------------------------------------- 1 | //go:generate go run ../../testdata/gqlgen.go 2 | 3 | package enum 4 | -------------------------------------------------------------------------------- /_examples/federation/accounts/graph/model/model.go: -------------------------------------------------------------------------------- 1 | package model 2 | -------------------------------------------------------------------------------- /_examples/federation/accounts/graph/model/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package model 4 | 5 | type EmailHost struct { 6 | ID string `json:"id"` 7 | Name string `json:"name"` 8 | } 9 | 10 | func (EmailHost) IsEntity() {} 11 | 12 | type Query struct { 13 | } 14 | 15 | type User struct { 16 | ID string `json:"id"` 17 | Host *EmailHost `json:"host"` 18 | Email string `json:"email"` 19 | Username string `json:"username"` 20 | } 21 | 22 | func (User) IsEntity() {} 23 | -------------------------------------------------------------------------------- /_examples/federation/accounts/graph/resolver.go: -------------------------------------------------------------------------------- 1 | // This file will not be regenerated automatically. 2 | // 3 | // It serves as dependency injection for your app, add any dependencies you require here. 4 | package graph 5 | 6 | import "github.com/99designs/gqlgen/_examples/federation/accounts/graph/model" 7 | 8 | type Resolver struct{} 9 | 10 | func (r *Resolver) HostForUserID(id string) (*model.EmailHost, error) { 11 | return &model.EmailHost{ 12 | ID: id, 13 | Name: "Email Host " + id, 14 | }, nil 15 | } 16 | -------------------------------------------------------------------------------- /_examples/federation/accounts/graph/schema.graphqls: -------------------------------------------------------------------------------- 1 | directive @goField( 2 | forceResolver: Boolean 3 | name: String 4 | omittable: Boolean 5 | type: String 6 | ) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION 7 | 8 | extend type Query { 9 | me: User 10 | } 11 | 12 | type EmailHost @key(fields: "id") { 13 | id: String! 14 | name: String! 15 | } 16 | 17 | type User @key(fields: "id") { 18 | id: ID! 19 | host: EmailHost! @goField(forceResolver: true) 20 | email: String! 21 | username: String! 22 | } 23 | -------------------------------------------------------------------------------- /_examples/federation/accounts/schema/schema.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/99designs/gqlgen/_examples/federation/accounts/graph" 5 | ) 6 | 7 | const DefaultPort = "4001" 8 | 9 | var Schema = graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}}) 10 | -------------------------------------------------------------------------------- /_examples/federation/gateway/index.js: -------------------------------------------------------------------------------- 1 | import { ApolloServer } from '@apollo/server'; 2 | import { startStandaloneServer } from '@apollo/server/standalone'; 3 | import { ApolloGateway,IntrospectAndCompose } from '@apollo/gateway'; 4 | 5 | const gateway = new ApolloGateway({ 6 | supergraphSdl: new IntrospectAndCompose({ 7 | subgraphs: [ 8 | { name: 'accounts', url: 'http://localhost:4001/query' }, 9 | { name: 'products', url: 'http://localhost:4002/query' }, 10 | { name: 'reviews', url: 'http://localhost:4003/query' } 11 | ], 12 | }), 13 | }); 14 | 15 | const server = new ApolloServer({ 16 | gateway, 17 | subscriptions: false, 18 | }); 19 | 20 | // Note the top-level `await`! 21 | const { url } = await startStandaloneServer(server); 22 | console.log(`🚀 Server ready at ${url}`); 23 | -------------------------------------------------------------------------------- /_examples/federation/jest.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | transform: {}, 3 | testEnvironment: "node", 4 | testMatch: ["/**/*-test.js"], 5 | testPathIgnorePatterns: ["/node_modules/"], 6 | moduleFileExtensions: ["js"], 7 | modulePaths: ["/node_modules"], 8 | // transform: { 9 | // '^.+\\.jsx?$': 'babel-jest', 10 | // }, 11 | }; 12 | -------------------------------------------------------------------------------- /_examples/federation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gateway", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "gateway/index.js", 6 | "type": "module", 7 | "scripts": { 8 | "start-gateway": "node gateway/index.js", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@apollo/gateway": "^2.7.1", 15 | "@apollo/server": "^4.10.0", 16 | "graphql": "^16.8.1" 17 | }, 18 | "devDependencies": { 19 | "@apollo/client": "^3.9.4", 20 | "cross-fetch": "^4.0.0", 21 | "jest": "^29.7.0", 22 | "node-fetch": "^3.3.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /_examples/federation/products/graph/model/model.go: -------------------------------------------------------------------------------- 1 | package model 2 | -------------------------------------------------------------------------------- /_examples/federation/products/graph/model/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package model 4 | 5 | type Manufacturer struct { 6 | ID string `json:"id"` 7 | Name string `json:"name"` 8 | } 9 | 10 | func (Manufacturer) IsEntity() {} 11 | 12 | type Product struct { 13 | ID string `json:"id"` 14 | Manufacturer *Manufacturer `json:"manufacturer"` 15 | Upc string `json:"upc"` 16 | Name string `json:"name"` 17 | Price int `json:"price"` 18 | } 19 | 20 | func (Product) IsEntity() {} 21 | 22 | type Query struct { 23 | } 24 | -------------------------------------------------------------------------------- /_examples/federation/products/graph/products.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import "github.com/99designs/gqlgen/_examples/federation/products/graph/model" 4 | 5 | var hats = []*model.Product{ 6 | { 7 | ID: "111", 8 | Manufacturer: &model.Manufacturer{ 9 | ID: "1234", 10 | Name: "Millinery 1234", 11 | }, 12 | Upc: "top-1", 13 | Name: "Trilby", 14 | Price: 11, 15 | }, 16 | { 17 | ID: "222", 18 | Manufacturer: &model.Manufacturer{ 19 | ID: "2345", 20 | Name: "Millinery 2345", 21 | }, 22 | Upc: "top-2", 23 | Name: "Fedora", 24 | Price: 22, 25 | }, 26 | { 27 | ID: "333", 28 | Manufacturer: &model.Manufacturer{ 29 | ID: "2345", 30 | Name: "Millinery 2345", 31 | }, 32 | Upc: "top-3", 33 | Name: "Boater", 34 | Price: 33, 35 | }, 36 | } 37 | -------------------------------------------------------------------------------- /_examples/federation/products/graph/resolver.go: -------------------------------------------------------------------------------- 1 | // This file will not be regenerated automatically. 2 | // 3 | // It serves as dependency injection for your app, add any dependencies you require here. 4 | package graph 5 | 6 | type Resolver struct{} 7 | -------------------------------------------------------------------------------- /_examples/federation/products/graph/schema.graphqls: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | topProducts(first: Int = 5): [Product] 3 | } 4 | 5 | type Manufacturer @key(fields: "id") { 6 | id: String! 7 | name: String! 8 | } 9 | 10 | type Product @key(fields: "manufacturer { id } id") @key(fields: "upc") { 11 | id: String! 12 | manufacturer: Manufacturer! 13 | upc: String! 14 | name: String! 15 | price: Int! 16 | } 17 | -------------------------------------------------------------------------------- /_examples/federation/products/graph/schema.resolvers.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | // This file will be automatically regenerated based on the schema, any resolver implementations 4 | // will be copied through when generating and any unknown code will be moved to the end. 5 | // Code generated by github.com/99designs/gqlgen version v0.17.73-dev 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/99designs/gqlgen/_examples/federation/products/graph/model" 11 | ) 12 | 13 | // TopProducts is the resolver for the topProducts field. 14 | func (r *queryResolver) TopProducts(ctx context.Context, first *int) ([]*model.Product, error) { 15 | return hats, nil 16 | } 17 | 18 | // Query returns QueryResolver implementation. 19 | func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } 20 | 21 | type queryResolver struct{ *Resolver } 22 | -------------------------------------------------------------------------------- /_examples/federation/products/schema/schema.go: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import ( 4 | "github.com/99designs/gqlgen/_examples/federation/products/graph" 5 | ) 6 | 7 | const DefaultPort = "4002" 8 | 9 | var Schema = graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}}) 10 | -------------------------------------------------------------------------------- /_examples/federation/readme.md: -------------------------------------------------------------------------------- 1 | ### Federation 2 | 3 | [Read the docs](https://gqlgen.com/recipes/federation/) 4 | 5 | ## Testing 6 | 7 | If you want to set breakpoints and debug the federation example, you can first run the subgraphs using: 8 | 9 | $ go run ./all/main.go 10 | 11 | Then start the gateway using 12 | $ npm run start-gateway 13 | 14 | You can then connect your preferred Golang debugger to the Go process as you make requests to the router. 15 | -------------------------------------------------------------------------------- /_examples/federation/reviews/graph/model/models.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | type Product struct { 4 | ID string `json:"id"` 5 | Manufacturer *Manufacturer `json:"manufacturer"` 6 | Reviews []*Review `json:"reviews"` 7 | } 8 | 9 | func (Product) IsEntity() {} 10 | 11 | type Review struct { 12 | Body string 13 | Author *User 14 | Product *Product 15 | HostIDEmail string 16 | } 17 | 18 | type User struct { 19 | ID string `json:"id"` 20 | Host *EmailHost `json:"host"` 21 | Email string `json:"email"` 22 | } 23 | 24 | func (User) IsEntity() {} 25 | -------------------------------------------------------------------------------- /_examples/federation/reviews/graph/model/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package model 4 | 5 | type EmailHost struct { 6 | ID string `json:"id"` 7 | } 8 | 9 | func (EmailHost) IsEntity() {} 10 | 11 | type Manufacturer struct { 12 | ID string `json:"id"` 13 | } 14 | 15 | func (Manufacturer) IsEntity() {} 16 | 17 | type ProductByManufacturerIDAndIDsInput struct { 18 | ManufacturerID string `json:"ManufacturerID"` 19 | ID string `json:"ID"` 20 | } 21 | 22 | type Query struct { 23 | } 24 | -------------------------------------------------------------------------------- /_examples/federation/reviews/graph/reviews.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import "github.com/99designs/gqlgen/_examples/federation/reviews/graph/model" 4 | 5 | var reviews = []*model.Review{ 6 | { 7 | Body: "A highly effective form of birth control.", 8 | Product: &model.Product{ID: "111", Manufacturer: &model.Manufacturer{ID: "1234"}}, 9 | Author: &model.User{ID: "1234"}, 10 | }, 11 | { 12 | Body: "Fedoras are one of the most fashionable hats around and can look great with a variety of outfits.", 13 | Product: &model.Product{ID: "222", Manufacturer: &model.Manufacturer{ID: "2345"}}, 14 | Author: &model.User{ID: "1234"}, 15 | }, 16 | { 17 | Body: "This is the last straw. Hat you will wear. 11/10", 18 | Product: &model.Product{ID: "333", Manufacturer: &model.Manufacturer{ID: "2345"}}, 19 | Author: &model.User{ID: "7777"}, 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /_examples/federation/reviews/schema/schema.go: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import ( 4 | "github.com/99designs/gqlgen/_examples/federation/reviews/graph" 5 | ) 6 | 7 | const DefaultPort = "4003" 8 | 9 | var Schema = graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}}) 10 | -------------------------------------------------------------------------------- /_examples/federation/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function cleanup { 4 | kill "$ACCOUNTS_PID" 5 | kill "$PRODUCTS_PID" 6 | kill "$REVIEWS_PID" 7 | } 8 | trap cleanup EXIT 9 | 10 | go build -o /tmp/srv-accounts ./accounts 11 | go build -o /tmp/srv-products ./products 12 | go build -o /tmp/srv-reviews ./reviews 13 | 14 | /tmp/srv-accounts & 15 | ACCOUNTS_PID=$! 16 | 17 | /tmp/srv-products & 18 | PRODUCTS_PID=$! 19 | 20 | /tmp/srv-reviews & 21 | REVIEWS_PID=$! 22 | 23 | sleep 1 24 | 25 | node gateway/index.js 26 | -------------------------------------------------------------------------------- /_examples/fileupload/.gqlgen.yml: -------------------------------------------------------------------------------- 1 | model: 2 | filename: model/generated.go 3 | -------------------------------------------------------------------------------- /_examples/fileupload/model/generated.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package model 4 | 5 | import ( 6 | "github.com/99designs/gqlgen/graphql" 7 | ) 8 | 9 | // The `File` type, represents the response of uploading a file. 10 | type File struct { 11 | ID int `json:"id"` 12 | Name string `json:"name"` 13 | Content string `json:"content"` 14 | ContentType string `json:"contentType"` 15 | } 16 | 17 | // The `Mutation` type, represents all updates we can make to our data. 18 | type Mutation struct { 19 | } 20 | 21 | // The `Query` type, represents all of the entry points into our object graph. 22 | type Query struct { 23 | } 24 | 25 | // The `UploadFile` type, represents the request for uploading a file with certain payload. 26 | type UploadFile struct { 27 | ID int `json:"id"` 28 | File graphql.Upload `json:"file"` 29 | } 30 | -------------------------------------------------------------------------------- /_examples/fileupload/testfiles/a.txt: -------------------------------------------------------------------------------- 1 | Alpha file content 2 | -------------------------------------------------------------------------------- /_examples/fileupload/testfiles/b.txt: -------------------------------------------------------------------------------- 1 | Bravo file content 2 | -------------------------------------------------------------------------------- /_examples/fileupload/testfiles/c.txt: -------------------------------------------------------------------------------- 1 | Charlie file content 2 | -------------------------------------------------------------------------------- /_examples/large-project-structure/integration/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/99designs/gqlgen/_examples/large-project-structure/integration 2 | 3 | go 1.24.1 4 | 5 | require github.com/99designs/gqlgen/_examples/large-project-structure/main v0.0.0 6 | 7 | replace github.com/99designs/gqlgen/_examples/large-project-structure/main => ../main 8 | 9 | replace github.com/99designs/gqlgen/_examples/large-project-structure/shared => ../shared 10 | 11 | require ( 12 | github.com/99designs/gqlgen v0.17.70 // indirect 13 | github.com/agnivade/levenshtein v1.2.1 // indirect 14 | github.com/google/uuid v1.6.0 // indirect 15 | github.com/sosodev/duration v1.3.1 // indirect 16 | github.com/vektah/gqlparser/v2 v2.5.23 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /_examples/large-project-structure/integration/schema.graphqls: -------------------------------------------------------------------------------- 1 | type Test { 2 | id: ID! 3 | } 4 | 5 | type CustomZeekIntel implements ZeekIntel{ 6 | id: ID! 7 | name: String! 8 | 9 | extraField: String! 10 | } 11 | 12 | input CustomInput { 13 | limit: Int 14 | error: Boolean 15 | } 16 | 17 | extend type Query { 18 | tezz: Test! 19 | getYaSome(input: CustomInput): [CustomZeekIntel!]! 20 | } 21 | 22 | type Indicator { 23 | id: ID! 24 | indicator: String! 25 | indicatorType: String! 26 | metaSource: String! 27 | } 28 | 29 | input IndicatorInput { 30 | indicator: String! 31 | indicatorType: String! 32 | metaSource: String! 33 | } 34 | 35 | extend type Mutation { 36 | addIndicator(input: IndicatorInput!): Indicator! 37 | } -------------------------------------------------------------------------------- /_examples/large-project-structure/main/graph/resolver.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/99designs/gqlgen/_examples/large-project-structure/main/graph/model" 7 | ) 8 | 9 | // This file will not be regenerated automatically. 10 | // 11 | // It serves as dependency injection for your app, add any dependencies you require here. 12 | 13 | // Define an interface for each resolver method 14 | type ExternalQueryResolver interface { 15 | // Example query resolver 16 | Tezz(ctx context.Context) (*model.Test, error) 17 | // Example query resolver with args 18 | GetYaSome(context.Context, *model.CustomInput) ([]*model.CustomZeekIntel, error) 19 | 20 | // Example mutation resolver with args 21 | AddIndicator(context.Context, model.IndicatorInput) (*model.Indicator, error) 22 | } 23 | 24 | type Resolver struct { 25 | ExternalQueryResolver 26 | } 27 | -------------------------------------------------------------------------------- /_examples/large-project-structure/main/graph/schema.graphqls: -------------------------------------------------------------------------------- 1 | # GraphQL schema example 2 | # 3 | # https://gqlgen.com/getting-started/ 4 | 5 | type Todo { 6 | id: ID! 7 | text: String! 8 | done: Boolean! 9 | user: User! 10 | } 11 | 12 | type User { 13 | id: ID! 14 | name: String! 15 | } 16 | 17 | type Query { 18 | todos: [Todo!]! 19 | } 20 | 21 | input NewTodo { 22 | text: String! 23 | userId: String! 24 | } 25 | 26 | type Mutation { 27 | createTodo(input: NewTodo!): Todo! 28 | } 29 | -------------------------------------------------------------------------------- /_examples/large-project-structure/main/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | 3 | package tools 4 | 5 | import ( 6 | _ "github.com/99designs/gqlgen" 7 | ) 8 | -------------------------------------------------------------------------------- /_examples/large-project-structure/shared/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/99designs/gqlgen/_examples/large-project-structure/shared 2 | 3 | go 1.24.1 4 | -------------------------------------------------------------------------------- /_examples/large-project-structure/shared/go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/99designs/gqlgen/0fce010415029b53fc75b00c6dc85394f44402db/_examples/large-project-structure/shared/go.sum -------------------------------------------------------------------------------- /_examples/large-project-structure/shared/schema.graphqls: -------------------------------------------------------------------------------- 1 | # GraphQL schema example 2 | # 3 | # https://gqlgen.com/getting-started/ 4 | 5 | interface ZeekIntel { 6 | id: ID! 7 | name: String! 8 | } 9 | -------------------------------------------------------------------------------- /_examples/large-project-structure/shared/shared.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | import "embed" 4 | 5 | //go:embed "schema.graphqls" 6 | var sourcesFS embed.FS 7 | -------------------------------------------------------------------------------- /_examples/mini-habr-with-subscriptions/.env: -------------------------------------------------------------------------------- 1 | TIMEOUT=4s 2 | IDLE_TIMEOUT=60s 3 | SERVER_PORT=8080 4 | DB_PROTOCOL=postgres 5 | DB_USER=mini 6 | DB_PASSWORD=mini_passwd 7 | DB_NAME=mini_habr 8 | DB_HOST=db 9 | DB_PORT=5432 10 | DB_OPTIONS=sslmode=disable 11 | REDIS_PORT1=6379 12 | REDIS_PORT2=6379 13 | REDIS_PASSWORD=redis_passwd 14 | REDIS_DB=0 15 | -------------------------------------------------------------------------------- /_examples/mini-habr-with-subscriptions/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY . . 6 | 7 | RUN go build -o main ./cmd/main.go 8 | 9 | EXPOSE 8080 10 | 11 | CMD ["./main"] -------------------------------------------------------------------------------- /_examples/mini-habr-with-subscriptions/internal/handlers/comment_mutation/interface.go: -------------------------------------------------------------------------------- 1 | package commentmutation 2 | 3 | import ( 4 | "github.com/gqlgen/_examples/mini-habr-with-subscriptions/internal/model" 5 | ) 6 | 7 | type CommentMutationImp interface { 8 | AddComment(postID int64, newComment *model.NewComment) (*model.Comment, error) 9 | } 10 | -------------------------------------------------------------------------------- /_examples/mini-habr-with-subscriptions/internal/handlers/comment_query/interface.go: -------------------------------------------------------------------------------- 1 | package commentquery 2 | 3 | import ( 4 | "github.com/gqlgen/_examples/mini-habr-with-subscriptions/internal/model" 5 | ) 6 | 7 | type CommentQueryImp interface { 8 | GetCommentsBranch(postID int64, path string) ([]*model.Comment, error) 9 | GetCommentPath(parentID int64) (string, error) 10 | } 11 | -------------------------------------------------------------------------------- /_examples/mini-habr-with-subscriptions/internal/handlers/post_mutation/interface.go: -------------------------------------------------------------------------------- 1 | package postmutation 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/gqlgen/_examples/mini-habr-with-subscriptions/internal/model" 6 | ) 7 | 8 | type PostMutImp interface { 9 | AddPost(newPost *model.NewPost) (*model.Post, error) 10 | UpdateEnableCommentToPost(postID int64, authorID uuid.UUID, commentsEnabled bool) (*model.Post, error) 11 | } 12 | -------------------------------------------------------------------------------- /_examples/mini-habr-with-subscriptions/internal/handlers/post_query/interface.go: -------------------------------------------------------------------------------- 1 | package postquery 2 | 3 | import ( 4 | "github.com/gqlgen/_examples/mini-habr-with-subscriptions/internal/model" 5 | ) 6 | 7 | type PostQueryImp interface { 8 | GetAllPosts() ([]*model.Post, error) 9 | GetPost(postID int64) (*model.Post, error) 10 | } 11 | -------------------------------------------------------------------------------- /_examples/mini-habr-with-subscriptions/internal/pkg/errs/errors.go: -------------------------------------------------------------------------------- 1 | package errs 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | var ( 8 | ErrPostNotExist = errors.New("post not exist") 9 | ErrUnauthorizedAccess = errors.New("user doesn't have access rights") 10 | ErrPostsNotExist = errors.New("no posts have been created yet") 11 | ErrCommentsNotExist = errors.New("no comments have been created yet") 12 | ErrPostNotCached = errors.New("post not cached yet") 13 | ErrPathNotExist = errors.New("path not exist") 14 | ErrParentCommentNotExist = errors.New("parent comment not exist yet") 15 | ErrIncorrectCommentLength = errors.New("incorrect comment length") 16 | ErrCommentsNotEnabled = errors.New("сomments on the post are not allowed") 17 | ) 18 | -------------------------------------------------------------------------------- /_examples/mini-habr-with-subscriptions/internal/storage/interface.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/gqlgen/_examples/mini-habr-with-subscriptions/internal/model" 6 | ) 7 | 8 | type StorageImp interface { 9 | AddPost(newPost *model.NewPost) (*model.Post, error) 10 | AddComment(postID int64, newComment *model.NewComment) (*model.Comment, error) 11 | UpdateEnableCommentToPost(postID int64, authorID uuid.UUID, commentsEnabled bool) (*model.Post, error) 12 | GetAllPosts() ([]*model.Post, error) 13 | GetPost(postID int64) (*model.Post, error) 14 | GetCommentsBranch(postID int64, path string) ([]*model.Comment, error) 15 | GetCommentPath(parentID int64) (string, error) 16 | } 17 | -------------------------------------------------------------------------------- /_examples/mini-habr-with-subscriptions/tools/tools.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | _ "github.com/99designs/gqlgen" 5 | _ "github.com/99designs/gqlgen/graphql/introspection" 6 | ) 7 | -------------------------------------------------------------------------------- /_examples/readme.md: -------------------------------------------------------------------------------- 1 | ### examples 2 | 3 | - todo: A simple todo checklist. A good place to get the basics down 4 | - starwars: A starwars movie database. It has examples of advanced graphql features 5 | - dataloader: How to avoid n+1 database query problems 6 | -------------------------------------------------------------------------------- /_examples/scalars/.gqlgen.yml: -------------------------------------------------------------------------------- 1 | model: 2 | filename: model/generated.go 3 | 4 | models: 5 | User: 6 | model: github.com/99designs/gqlgen/_examples/scalars/model.User 7 | Timestamp: 8 | model: github.com/99designs/gqlgen/_examples/scalars/model.Timestamp 9 | SearchArgs: 10 | model: github.com/99designs/gqlgen/_examples/scalars/model.SearchArgs 11 | Point: 12 | model: github.com/99designs/gqlgen/_examples/scalars/model.Point 13 | ID: 14 | model: github.com/99designs/gqlgen/_examples/scalars/model.ID 15 | Tier: 16 | model: github.com/99designs/gqlgen/_examples/scalars/model.Tier 17 | Banned: 18 | model: github.com/99designs/gqlgen/_examples/scalars/model.Banned 19 | DarkMode: 20 | model: github.com/99designs/gqlgen/_examples/scalars/model.Preferences 21 | -------------------------------------------------------------------------------- /_examples/scalars/external/model.go: -------------------------------------------------------------------------------- 1 | package external 2 | 3 | type ObjectID int 4 | -------------------------------------------------------------------------------- /_examples/scalars/model/generated.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package model 4 | 5 | import ( 6 | "github.com/99designs/gqlgen/_examples/scalars/external" 7 | ) 8 | 9 | type Address struct { 10 | ID external.ObjectID `json:"id"` 11 | Location *Point `json:"location,omitempty"` 12 | } 13 | 14 | type Query struct { 15 | } 16 | -------------------------------------------------------------------------------- /_examples/scalars/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/99designs/gqlgen/_examples/scalars" 8 | "github.com/99designs/gqlgen/graphql/handler" 9 | "github.com/99designs/gqlgen/graphql/handler/transport" 10 | "github.com/99designs/gqlgen/graphql/playground" 11 | ) 12 | 13 | func main() { 14 | srv := handler.New( 15 | scalars.NewExecutableSchema(scalars.Config{Resolvers: &scalars.Resolver{}}), 16 | ) 17 | srv.AddTransport(transport.GET{}) 18 | srv.AddTransport(transport.POST{}) 19 | 20 | http.Handle("/", playground.Handler("Starwars", "/query")) 21 | http.Handle("/query", srv) 22 | 23 | log.Fatal(http.ListenAndServe(":8084", nil)) 24 | } 25 | -------------------------------------------------------------------------------- /_examples/selection/.gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: schema.graphql 2 | model: 3 | filename: models_gen.go 4 | exec: 5 | filename: generated.go 6 | -------------------------------------------------------------------------------- /_examples/selection/readme.md: -------------------------------------------------------------------------------- 1 | ### selection app 2 | 3 | This is the simplest example of a graphql server. 4 | 5 | to run this server 6 | ```bash 7 | go run ./server/server.go 8 | ``` 9 | 10 | and open http://localhost:8086 in your browser 11 | -------------------------------------------------------------------------------- /_examples/selection/schema.graphql: -------------------------------------------------------------------------------- 1 | interface Event { 2 | selection: [String!] 3 | collected: [String!] 4 | } 5 | 6 | type Post implements Event { 7 | message: String! 8 | sent: Time! 9 | selection: [String!] 10 | collected: [String!] 11 | } 12 | 13 | type Like implements Event { 14 | reaction: String! 15 | sent: Time! 16 | selection: [String!] 17 | collected: [String!] 18 | } 19 | 20 | type Query { 21 | events: [Event!] 22 | } 23 | 24 | scalar Time 25 | -------------------------------------------------------------------------------- /_examples/selection/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/99designs/gqlgen/_examples/selection" 8 | "github.com/99designs/gqlgen/graphql/handler" 9 | "github.com/99designs/gqlgen/graphql/handler/transport" 10 | "github.com/99designs/gqlgen/graphql/playground" 11 | ) 12 | 13 | func main() { 14 | srv := handler.New( 15 | selection.NewExecutableSchema(selection.Config{Resolvers: &selection.Resolver{}}), 16 | ) 17 | srv.AddTransport(transport.GET{}) 18 | srv.AddTransport(transport.POST{}) 19 | 20 | http.Handle("/", playground.Handler("Selection Demo", "/query")) 21 | http.Handle("/query", srv) 22 | log.Fatal(http.ListenAndServe(":8086", nil)) 23 | } 24 | -------------------------------------------------------------------------------- /_examples/starwars/.gqlgen.yml: -------------------------------------------------------------------------------- 1 | exec: 2 | filename: generated/exec.go 3 | model: 4 | filename: models/generated.go 5 | package: models 6 | 7 | autobind: 8 | - github.com/99designs/gqlgen/_examples/starwars/models 9 | 10 | models: 11 | ReviewInput: 12 | model: models.Review 13 | Starship: 14 | fields: 15 | length: 16 | resolver: true 17 | -------------------------------------------------------------------------------- /_examples/starwars/readme.md: -------------------------------------------------------------------------------- 1 | ### starwars example 2 | 3 | This server demonstrates a few advanced features of graphql: 4 | - connections 5 | - unions 6 | - interfaces 7 | - enums 8 | 9 | to run this server 10 | ```bash 11 | go run ./server/server.go 12 | ``` 13 | 14 | and open http://localhost:8080 in your browser 15 | -------------------------------------------------------------------------------- /_examples/todo/gqlgen.yml: -------------------------------------------------------------------------------- 1 | models: 2 | Todo: 3 | model: github.com/99designs/gqlgen/_examples/todo.Todo 4 | ID: 5 | model: # override the default id marshaller to use ints 6 | - github.com/99designs/gqlgen/graphql.IntID 7 | - github.com/99designs/gqlgen/graphql.ID 8 | -------------------------------------------------------------------------------- /_examples/todo/models.go: -------------------------------------------------------------------------------- 1 | package todo 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | 8 | "github.com/99designs/gqlgen/graphql" 9 | ) 10 | 11 | type Ownable interface { 12 | Owner() *User 13 | } 14 | 15 | type Todo struct { 16 | ID int 17 | Text string 18 | Done bool 19 | owner *User 20 | } 21 | 22 | func (t Todo) Owner() *User { 23 | return t.owner 24 | } 25 | 26 | type User struct { 27 | ID int 28 | Name string 29 | } 30 | 31 | type Number int 32 | 33 | func (e *Number) UnmarshalGQLContext(ctx context.Context, v any) error { 34 | num, err := graphql.UnmarshalInt(v) 35 | if err != nil { 36 | return err 37 | } 38 | *e = Number(num) 39 | return nil 40 | } 41 | 42 | func (e Number) MarshalGQLContext(_ context.Context, w io.Writer) error { 43 | fmt.Fprint(w, e) 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /_examples/todo/readme.md: -------------------------------------------------------------------------------- 1 | ### todo app 2 | 3 | This is the simplest example of a graphql server. 4 | 5 | to run this server 6 | ```bash 7 | go run ./server/server.go 8 | ``` 9 | 10 | and open http://localhost:8081 in your browser 11 | -------------------------------------------------------------------------------- /_examples/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | 3 | package main 4 | 5 | import ( 6 | _ "github.com/vektah/dataloaden" 7 | _ "golang.org/x/text" 8 | ) 9 | -------------------------------------------------------------------------------- /_examples/type-system-extension/README.md: -------------------------------------------------------------------------------- 1 | # Type System Extension example 2 | 3 | https://graphql.github.io/graphql-spec/draft/#sec-Type-System-Extensions 4 | 5 | ``` 6 | $ go run ./server/server.go 7 | 2018/10/25 12:46:45 connect to http://localhost:8080/ for GraphQL playground 8 | 9 | $ curl -X POST 'http://localhost:8080/query' --data-binary '{"query":"{ todos { id text state verified } }"}' 10 | {"data":{"todos":[{"id":"Todo:1","text":"Buy a cat food","state":"NOT_YET","verified":false},{"id":"Todo:2","text":"Check cat water","state":"DONE","verified":true},{"id":"Todo:3","text":"Check cat meal","state":"DONE","verified":true}]}} 11 | ``` 12 | -------------------------------------------------------------------------------- /_examples/type-system-extension/gqlgen.yml: -------------------------------------------------------------------------------- 1 | # .gqlgen.yml example 2 | # 3 | # Refer to https://gqlgen.com/config/ 4 | # for detailed .gqlgen.yml documentation. 5 | 6 | schema: 7 | - ./schemas/*.graphql 8 | 9 | exec: 10 | filename: generated.go 11 | model: 12 | filename: models_gen.go 13 | -------------------------------------------------------------------------------- /_examples/type-system-extension/schemas/enum-extension.graphql: -------------------------------------------------------------------------------- 1 | directive @enumLogging on ENUM 2 | 3 | extend enum State @enumLogging 4 | -------------------------------------------------------------------------------- /_examples/type-system-extension/schemas/input-object-extension.graphql: -------------------------------------------------------------------------------- 1 | directive @inputLogging on INPUT_OBJECT 2 | 3 | extend input TodoInput @inputLogging 4 | -------------------------------------------------------------------------------- /_examples/type-system-extension/schemas/interface-extension.graphql: -------------------------------------------------------------------------------- 1 | directive @interfaceLogging on INTERFACE 2 | 3 | extend interface Node @interfaceLogging 4 | -------------------------------------------------------------------------------- /_examples/type-system-extension/schemas/object-extension.graphql: -------------------------------------------------------------------------------- 1 | directive @objectLogging on OBJECT 2 | 3 | extend type Todo @objectLogging 4 | -------------------------------------------------------------------------------- /_examples/type-system-extension/schemas/scalar-extension.graphql: -------------------------------------------------------------------------------- 1 | directive @scalarLogging on SCALAR 2 | 3 | extend scalar ID @scalarLogging 4 | -------------------------------------------------------------------------------- /_examples/type-system-extension/schemas/schema-extension.graphql: -------------------------------------------------------------------------------- 1 | extend schema { 2 | mutation: MyMutation 3 | } 4 | 5 | extend type MyQuery { 6 | todo(id: ID!): Todo 7 | } 8 | 9 | type MyMutation { 10 | createTodo(todo: TodoInput!): Todo! 11 | } 12 | 13 | input TodoInput { 14 | text: String! 15 | } 16 | -------------------------------------------------------------------------------- /_examples/type-system-extension/schemas/schema.graphql: -------------------------------------------------------------------------------- 1 | # GraphQL schema example 2 | # 3 | # https://gqlgen.com/getting-started/ 4 | 5 | schema { 6 | query: MyQuery 7 | } 8 | 9 | interface Node { 10 | id: ID! 11 | } 12 | 13 | type Todo implements Node { 14 | id: ID! 15 | text: String! 16 | state: State! 17 | } 18 | 19 | type MyQuery { 20 | todos: [Todo!]! 21 | } 22 | 23 | union Data = Todo 24 | 25 | enum State { 26 | NOT_YET 27 | DONE 28 | } 29 | -------------------------------------------------------------------------------- /_examples/type-system-extension/schemas/type-extension.graphql: -------------------------------------------------------------------------------- 1 | directive @fieldLogging on FIELD_DEFINITION 2 | 3 | extend type Todo { 4 | verified: Boolean! @fieldLogging 5 | } 6 | -------------------------------------------------------------------------------- /_examples/type-system-extension/schemas/union-extension.graphql: -------------------------------------------------------------------------------- 1 | directive @unionLogging on UNION 2 | 3 | extend union Data @unionLogging 4 | -------------------------------------------------------------------------------- /_examples/uuid/graph/model/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package model 4 | 5 | import ( 6 | "github.com/google/uuid" 7 | ) 8 | 9 | type Mutation struct { 10 | } 11 | 12 | type NewTodo struct { 13 | Text string `json:"text"` 14 | UserID string `json:"userId"` 15 | UID uuid.UUID `json:"uid"` 16 | } 17 | 18 | type Query struct { 19 | } 20 | 21 | type Todo struct { 22 | ID string `json:"id"` 23 | Text string `json:"text"` 24 | Done bool `json:"done"` 25 | UID uuid.UUID `json:"uid"` 26 | } 27 | -------------------------------------------------------------------------------- /_examples/uuid/graph/resolver.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type Resolver struct{} 8 | -------------------------------------------------------------------------------- /_examples/uuid/graph/schema.graphqls: -------------------------------------------------------------------------------- 1 | # GraphQL schema example 2 | # 3 | # https://gqlgen.com/getting-started/ 4 | 5 | type Todo { 6 | id: ID! 7 | text: String! 8 | done: Boolean! 9 | uid: UUID! 10 | } 11 | 12 | 13 | type Query { 14 | todos: [Todo!]! 15 | } 16 | 17 | input NewTodo { 18 | text: String! 19 | userId: String! 20 | uid: UUID! 21 | } 22 | 23 | type Mutation { 24 | createTodo(input: NewTodo!): Todo! 25 | } 26 | 27 | scalar UUID 28 | -------------------------------------------------------------------------------- /_examples/websocket-initfunc/graph/model/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package model 4 | 5 | type Query struct { 6 | } 7 | -------------------------------------------------------------------------------- /_examples/websocket-initfunc/graph/resolver.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type Resolver struct{} 8 | -------------------------------------------------------------------------------- /_examples/websocket-initfunc/server/Makefile: -------------------------------------------------------------------------------- 1 | bin_name=server 2 | 3 | build: 4 | @echo "building binary..." 5 | # go generate gives missing go sum entry for module errors 6 | # https://github.com/99designs/gqlgen/issues/1483 7 | # you will need to first do a go get -u github.com/99designs/gqlgen 8 | go run -mod=mod github.com/99designs/gqlgen generate . 9 | go build -o ${bin_name} server.go 10 | -------------------------------------------------------------------------------- /_examples/websocket-initfunc/server/graph/model/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package model 4 | 5 | type Dummy struct { 6 | ID string `json:"id"` 7 | Text string `json:"text"` 8 | Done bool `json:"done"` 9 | } 10 | -------------------------------------------------------------------------------- /_examples/websocket-initfunc/server/graph/resolver.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type Resolver struct{} 8 | -------------------------------------------------------------------------------- /_examples/websocket-initfunc/server/graph/schema.graphqls: -------------------------------------------------------------------------------- 1 | # GraphQL schema example 2 | # 3 | 4 | type Dummy { 5 | id: ID! 6 | text: String! 7 | done: Boolean! 8 | } 9 | 10 | type Mutation { 11 | postMessageTo(subscriber: String!, content: String!): ID! 12 | } 13 | 14 | type Subscription { 15 | subscribe(subscriber: String!): String! 16 | } 17 | -------------------------------------------------------------------------------- /_examples/websocket-initfunc/server/readme.md: -------------------------------------------------------------------------------- 1 | # WebSocket Init App 2 | 3 | Example server app using websocket `InitFunc`. 4 | 5 | ## Build and Run the server app 6 | 7 | First get an update from gqlgen: 8 | ```bash 9 | go mod tidy 10 | go get -u github.com/99designs/gqlgen 11 | ``` 12 | 13 | Next just make the build: 14 | ```bash 15 | make build 16 | ``` 17 | 18 | Run the server: 19 | ```bash 20 | ./server 21 | 2022/07/07 16:49:46 connect to http://localhost:8080/ for GraphQL playground 22 | ``` 23 | 24 | You may now implement a websocket client to subscribe for websocket messages. -------------------------------------------------------------------------------- /api/testdata/default/graph/model/doc.go: -------------------------------------------------------------------------------- 1 | package model 2 | -------------------------------------------------------------------------------- /api/testdata/default/graph/schema.graphqls: -------------------------------------------------------------------------------- 1 | # GraphQL schema example 2 | # 3 | # https://gqlgen.com/getting-started/ 4 | 5 | type Todo { 6 | id: ID! 7 | text: String! 8 | done: Boolean! 9 | user: User! 10 | } 11 | 12 | type User { 13 | id: ID! 14 | name: String! 15 | } 16 | 17 | type Query { 18 | todos: [Todo!]! 19 | } 20 | 21 | input NewTodo { 22 | text: String! 23 | userId: String! 24 | } 25 | 26 | type Mutation { 27 | createTodo(input: NewTodo!): Todo! 28 | } 29 | -------------------------------------------------------------------------------- /api/testdata/federation2/graph/model/doc.go: -------------------------------------------------------------------------------- 1 | package model 2 | -------------------------------------------------------------------------------- /api/testdata/federation2/graph/schema.graphqls: -------------------------------------------------------------------------------- 1 | # GraphQL schema example 2 | # 3 | # https://gqlgen.com/getting-started/ 4 | extend schema 5 | @link(url: "https://specs.apollo.dev/federation/v2.7", 6 | import: ["@key", "@shareable", "@provides", "@external", "@tag", "@extends", "@override", "@inaccessible"]) 7 | 8 | type Todo { 9 | id: ID! 10 | text: String! 11 | done: Boolean! 12 | user: User! 13 | } 14 | 15 | type User { 16 | id: ID! 17 | name: String! 18 | } 19 | 20 | type Query { 21 | todos: [Todo!]! 22 | } 23 | 24 | input NewTodo { 25 | text: String! 26 | userId: String! 27 | } 28 | 29 | type Mutation { 30 | createTodo(input: NewTodo!): Todo! 31 | } 32 | -------------------------------------------------------------------------------- /api/testdata/workerlimit/graph/model/doc.go: -------------------------------------------------------------------------------- 1 | package model 2 | -------------------------------------------------------------------------------- /api/testdata/workerlimit/graph/schema.graphqls: -------------------------------------------------------------------------------- 1 | # GraphQL schema example 2 | # 3 | # https://gqlgen.com/getting-started/ 4 | 5 | type Todo { 6 | id: ID! 7 | text: String! 8 | done: Boolean! 9 | user: User! 10 | } 11 | 12 | type User { 13 | id: ID! 14 | name: String! 15 | } 16 | 17 | type Query { 18 | todos: [Todo!]! 19 | } 20 | 21 | input NewTodo { 22 | text: String! 23 | userId: String! 24 | } 25 | 26 | type Mutation { 27 | createTodo(input: NewTodo!): Todo! 28 | } 29 | -------------------------------------------------------------------------------- /client/errors.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import "encoding/json" 4 | 5 | // RawJsonError is a json formatted error from a GraphQL server. 6 | type RawJsonError struct { 7 | json.RawMessage 8 | } 9 | 10 | func (r RawJsonError) Error() string { 11 | return string(r.RawMessage) 12 | } 13 | -------------------------------------------------------------------------------- /client/readme.md: -------------------------------------------------------------------------------- 1 | This client is used internally for testing. I wanted a simple graphql client sent user specified queries. 2 | 3 | You might want to look at: 4 | - https://github.com/shurcooL/graphql: Uses reflection to build queries from structs. 5 | - https://github.com/machinebox/graphql: Probably would have been a perfect fit, but it uses form encoding instead of json... 6 | - [Khan/genqlient](https://github.com/Khan/genqlient) - Generate go GraphQL client from GraphQL query 7 | - [infiotinc/gqlgenc](https://github.com/infiotinc/gqlgenc) - Generate go GraphQL client from GraphQL query 8 | - [Yamashou/gqlgenc](https://github.com/Yamashou/gqlgenc) - Generate go GraphQL client from GraphQL query 9 | -------------------------------------------------------------------------------- /codegen/complexity.go: -------------------------------------------------------------------------------- 1 | package codegen 2 | 3 | func (o *Object) UniqueFields() map[string][]*Field { 4 | m := map[string][]*Field{} 5 | 6 | for _, f := range o.Fields { 7 | m[f.GoFieldName] = append(m[f.GoFieldName], f) 8 | } 9 | 10 | return m 11 | } 12 | -------------------------------------------------------------------------------- /codegen/config/testdata/autobinding/chat/model.go: -------------------------------------------------------------------------------- 1 | package chat 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type Message struct { 8 | ID string `json:"id"` 9 | Text string `json:"text"` 10 | CreatedBy string `json:"createdBy"` 11 | CreatedAt time.Time `json:"createdAt"` 12 | } 13 | 14 | type ProductSku string 15 | 16 | const ( 17 | ProductSkuTrial ProductSku = "Trial" 18 | ) 19 | 20 | type ChatAPI struct { 21 | ID string `json:"id"` 22 | } 23 | -------------------------------------------------------------------------------- /codegen/config/testdata/autobinding/scalars/model/model.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "strings" 7 | ) 8 | 9 | type Banned bool 10 | 11 | func (b Banned) MarshalGQL(w io.Writer) { 12 | if b { 13 | w.Write([]byte("true")) 14 | } else { 15 | w.Write([]byte("false")) 16 | } 17 | } 18 | 19 | func (b *Banned) UnmarshalGQL(v any) error { 20 | switch v := v.(type) { 21 | case string: 22 | *b = strings.ToLower(v) == "true" 23 | return nil 24 | case bool: 25 | *b = Banned(v) 26 | return nil 27 | default: 28 | return fmt.Errorf("%T is not a bool", v) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /codegen/config/testdata/binding/model.go: -------------------------------------------------------------------------------- 1 | package binding 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | 8 | "github.com/99designs/gqlgen/graphql" 9 | ) 10 | 11 | type Number int 12 | 13 | func (e *Number) UnmarshalGQL(v any) error { 14 | num, err := graphql.UnmarshalInt(v) 15 | if err != nil { 16 | return err 17 | } 18 | *e = Number(num) 19 | return nil 20 | } 21 | 22 | func (e Number) MarshalGQL(w io.Writer) error { 23 | fmt.Fprint(w, e) 24 | return nil 25 | } 26 | 27 | type ContextNumber int 28 | 29 | func (e *ContextNumber) UnmarshalGQLContext(ctx context.Context, v any) error { 30 | num, err := graphql.UnmarshalInt(v) 31 | if err != nil { 32 | return err 33 | } 34 | *e = Number(num) 35 | return nil 36 | } 37 | 38 | func (e ContextNumber) MarshalGQLContext(_ context.Context, w io.Writer) error { 39 | fmt.Fprint(w, e) 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/glob.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - testdata/cfg/glob/**/*.graphql 3 | exec: 4 | filename: generated.go 5 | model: 6 | filename: models_gen.go 7 | resolver: 8 | filename: resolver.go 9 | type: Resolver 10 | -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/glob/bar/bar with spaces.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | todos: [Todo!]! 3 | } 4 | 5 | input NewTodo { 6 | text: String! 7 | userId: String! 8 | } 9 | 10 | type Mutation { 11 | createTodo(input: NewTodo!): Todo! 12 | } 13 | -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/glob/foo/foo.graphql: -------------------------------------------------------------------------------- 1 | type Todo { 2 | id: ID! 3 | text: String! 4 | done: Boolean! 5 | user: User! 6 | } 7 | 8 | type User { 9 | id: ID! 10 | name: String! 11 | } 12 | -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/goInitialisms.yml: -------------------------------------------------------------------------------- 1 | go_initialisms: 2 | replace_defaults: true 3 | initialisms: 4 | - 'CC' 5 | - 'BCC' 6 | -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: outer 2 | -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/malformedconfig.yml: -------------------------------------------------------------------------------- 1 | asdf 2 | -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/otherdir/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/99designs/gqlgen/0fce010415029b53fc75b00c6dc85394f44402db/codegen/config/testdata/cfg/otherdir/.gitkeep -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/outer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/99designs/gqlgen/0fce010415029b53fc75b00c6dc85394f44402db/codegen/config/testdata/cfg/outer -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/subdir/gqlgen.yaml: -------------------------------------------------------------------------------- 1 | schema: inner 2 | -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/subdir/inner: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/99designs/gqlgen/0fce010415029b53fc75b00c6dc85394f44402db/codegen/config/testdata/cfg/subdir/inner -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/unknownkeys.yml: -------------------------------------------------------------------------------- 1 | schema: outer 2 | unknown: foo 3 | -------------------------------------------------------------------------------- /codegen/config/testdata/cfg/unwalkable.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - not_walkable/**/*.graphql 3 | exec: 4 | filename: generated.go 5 | model: 6 | filename: models_gen.go 7 | resolver: 8 | filename: resolver.go 9 | type: Resolver 10 | -------------------------------------------------------------------------------- /codegen/config/testdata/defaultconfig/schema.graphql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/99designs/gqlgen/0fce010415029b53fc75b00c6dc85394f44402db/codegen/config/testdata/defaultconfig/schema.graphql -------------------------------------------------------------------------------- /codegen/config/testdata/enum/model.go: -------------------------------------------------------------------------------- 1 | package enum 2 | 3 | type Bar int 4 | 5 | const ( 6 | BarOne Bar = iota + 1 7 | BarTwo 8 | ) 9 | 10 | const ( 11 | BazOne = iota + 1 12 | BazTwo 13 | ) 14 | -------------------------------------------------------------------------------- /codegen/config/testdata/example.go: -------------------------------------------------------------------------------- 1 | package config_test_data 2 | -------------------------------------------------------------------------------- /codegen/templates/test.gotpl: -------------------------------------------------------------------------------- 1 | this is my test package 2 | -------------------------------------------------------------------------------- /codegen/templates/test_.gotpl: -------------------------------------------------------------------------------- 1 | this will not be included 2 | -------------------------------------------------------------------------------- /codegen/templates/testdata/a/bar/bar.go: -------------------------------------------------------------------------------- 1 | package bar 2 | -------------------------------------------------------------------------------- /codegen/templates/testdata/b/bar/bar.go: -------------------------------------------------------------------------------- 1 | package bar 2 | -------------------------------------------------------------------------------- /codegen/templates/testdata/pkg_mismatch/turtles.go: -------------------------------------------------------------------------------- 1 | package turtles 2 | -------------------------------------------------------------------------------- /codegen/testserver/compliant-int/generated-compliant-strict/models.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package generated 4 | 5 | type Input struct { 6 | N *int32 `json:"n,omitempty"` 7 | } 8 | 9 | type Input64 struct { 10 | N *int `json:"n,omitempty"` 11 | } 12 | 13 | type Query struct { 14 | } 15 | 16 | type Result struct { 17 | N int32 `json:"n"` 18 | } 19 | 20 | type Result64 struct { 21 | N int `json:"n"` 22 | } 23 | -------------------------------------------------------------------------------- /codegen/testserver/compliant-int/generated-default/models.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package generated 4 | 5 | type Input struct { 6 | N *int `json:"n,omitempty"` 7 | } 8 | 9 | type Input64 struct { 10 | N *int `json:"n,omitempty"` 11 | } 12 | 13 | type Query struct { 14 | } 15 | 16 | type Result struct { 17 | N int `json:"n"` 18 | } 19 | 20 | type Result64 struct { 21 | N int `json:"n"` 22 | } 23 | -------------------------------------------------------------------------------- /codegen/testserver/compliant-int/gqlgen_compliant_strict.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "*.graphql" 3 | skip_validation: true 4 | exec: 5 | package: generated 6 | filename: generated-compliant-strict/schema.go 7 | model: 8 | package: generated 9 | filename: generated-compliant-strict/models.go 10 | resolver: 11 | package: generated 12 | filename: generated-compliant-strict/resolver.go 13 | 14 | models: 15 | Int: 16 | model: 17 | - github.com/99designs/gqlgen/graphql.Int32 18 | Int64: 19 | model: 20 | - github.com/99designs/gqlgen/graphql.Int 21 | - github.com/99designs/gqlgen/graphql.Int64 22 | -------------------------------------------------------------------------------- /codegen/testserver/compliant-int/gqlgen_default.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "*.graphql" 3 | skip_validation: true 4 | exec: 5 | package: generated 6 | filename: generated-default/schema.go 7 | model: 8 | package: generated 9 | filename: generated-default/models.go 10 | resolver: 11 | package: generated 12 | filename: generated-default/resolver.go 13 | -------------------------------------------------------------------------------- /codegen/testserver/compliant-int/schema.graphql: -------------------------------------------------------------------------------- 1 | scalar Int64 2 | 3 | input Input { 4 | n: Int 5 | } 6 | 7 | input Input64 { 8 | n: Int64 9 | } 10 | 11 | type Result { 12 | n: Int! 13 | } 14 | 15 | type Result64 { 16 | n: Int64! 17 | } 18 | 19 | type Query { 20 | echoIntToInt(n: Int): Int! 21 | echoInt64ToInt64(n: Int64): Int64! 22 | echoIntInputToIntObject(input: Input!): Result 23 | echoInt64InputToInt64Object(input: Input64!): Result64 24 | } 25 | -------------------------------------------------------------------------------- /codegen/testserver/empty.go: -------------------------------------------------------------------------------- 1 | package testserver 2 | 3 | // Empty file to silence go build error complaining that codegen/testserver/ has no non-test Go source files. 4 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/builtinscalar.graphql: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | Since gqlgen defines default implementation for a Map scalar, this tests that the builtin is _not_ 4 | added to the TypeMap 5 | """ 6 | type Map { 7 | id: ID! 8 | } 9 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/bytes.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | 7 | "github.com/99designs/gqlgen/graphql" 8 | ) 9 | 10 | func MarshalBytes(b []byte) graphql.Marshaler { 11 | return graphql.WriterFunc(func(w io.Writer) { 12 | _, _ = fmt.Fprintf(w, "%q", string(b)) 13 | }) 14 | } 15 | 16 | func UnmarshalBytes(v any) ([]byte, error) { 17 | switch v := v.(type) { 18 | case string: 19 | return []byte(v), nil 20 | case *string: 21 | return []byte(*v), nil 22 | case []byte: 23 | return v, nil 24 | default: 25 | return nil, fmt.Errorf("%T is not []byte", v) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/complexity.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | overlapping: OverlappingFields 3 | } 4 | 5 | type OverlappingFields { 6 | oneFoo: Int! @goField(name: "foo") 7 | twoFoo: Int! @goField(name: "foo") 8 | oldFoo: Int! @goField(name: "foo", forceResolver: true) 9 | newFoo: Int! 10 | new_foo: Int! 11 | } 12 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/defaults.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | defaultParameters( 3 | falsyBoolean: Boolean = false 4 | truthyBoolean: Boolean = true 5 | ): DefaultParametersMirror! 6 | } 7 | 8 | extend type Mutation { 9 | defaultInput(input: DefaultInput!): DefaultParametersMirror! 10 | } 11 | 12 | input DefaultInput { 13 | falsyBoolean: Boolean = false 14 | truthyBoolean: Boolean = true 15 | } 16 | 17 | type DefaultParametersMirror { 18 | falsyBoolean: Boolean 19 | truthyBoolean: Boolean 20 | } 21 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/defer.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | deferSingle: DeferModel 3 | deferMultiple: [DeferModel!] 4 | } 5 | 6 | type DeferModel { 7 | id: ID! 8 | name: String! 9 | values: [String!]! @goField(forceResolver: true) 10 | } 11 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/embedded.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | embeddedCase1: EmbeddedCase1 3 | embeddedCase2: EmbeddedCase2 4 | embeddedCase3: EmbeddedCase3 5 | } 6 | 7 | type EmbeddedCase1 @goModel(model:"followschema.EmbeddedCase1") { 8 | exportedEmbeddedPointerExportedMethod: String! 9 | } 10 | 11 | type EmbeddedCase2 @goModel(model:"followschema.EmbeddedCase2") { 12 | unexportedEmbeddedPointerExportedMethod: String! 13 | } 14 | 15 | type EmbeddedCase3 @goModel(model:"followschema.EmbeddedCase3") { 16 | unexportedEmbeddedInterfaceExportedMethod: String! 17 | } 18 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/enum.graphql: -------------------------------------------------------------------------------- 1 | enum EnumTest { 2 | OK 3 | NG 4 | } 5 | 6 | input InputWithEnumValue { 7 | enum: EnumTest! 8 | } 9 | 10 | extend type Query { 11 | enumInInput(input: InputWithEnumValue): EnumTest! 12 | } 13 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/fields_order.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | type FieldsOrderInput struct { 4 | FirstField *string `json:"firstField"` 5 | } 6 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/fields_order.graphql: -------------------------------------------------------------------------------- 1 | type FieldsOrderPayload { 2 | firstFieldValue: String 3 | } 4 | 5 | input FieldsOrderInput { 6 | firstField: String 7 | overrideFirstField: String 8 | } 9 | 10 | extend type Mutation { 11 | overrideValueViaInput(input: FieldsOrderInput!): FieldsOrderPayload! 12 | } 13 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "*.graphql" 3 | skip_validation: true 4 | exec: 5 | layout: follow-schema 6 | dir: . 7 | package: followschema 8 | model: 9 | filename: models-gen.go 10 | package: followschema 11 | resolver: 12 | filename: resolver.go 13 | package: followschema 14 | type: Resolver 15 | 16 | autobind: 17 | - "github.com/99designs/gqlgen/codegen/testserver" 18 | - "github.com/99designs/gqlgen/codegen/testserver/followschema" 19 | - "github.com/99designs/gqlgen/codegen/testserver/followschema/introspection" 20 | - "github.com/99designs/gqlgen/codegen/testserver/followschema/invalid-packagename" 21 | 22 | models: 23 | Email: 24 | model: "github.com/99designs/gqlgen/codegen/testserver/followschema.Email" 25 | StringFromContextFunction: 26 | model: "github.com/99designs/gqlgen/codegen/testserver/followschema.StringFromContextFunction" 27 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/introspection/it.go: -------------------------------------------------------------------------------- 1 | package introspection 2 | 3 | type It struct { 4 | ID string 5 | } 6 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/invalid-packagename/invalid-identifier.go: -------------------------------------------------------------------------------- 1 | package invalid_packagename 2 | 3 | type InvalidIdentifier struct { 4 | ID int 5 | } 6 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/issue896.graphql: -------------------------------------------------------------------------------- 1 | # This example should build stable output. If the file content starts 2 | # alternating nondeterministically between two outputs, then see 3 | # https://github.com/99designs/gqlgen/issues/896. 4 | 5 | extend schema { 6 | query: Query 7 | subscription: Subscription 8 | } 9 | 10 | type CheckIssue896 {id: Int} 11 | 12 | extend type Query { 13 | issue896a: [CheckIssue896!] # Note the "!" or lack thereof. 14 | } 15 | 16 | extend type Subscription { 17 | issue896b: [CheckIssue896] # Note the "!" or lack thereof. 18 | } 19 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/loops.graphql: -------------------------------------------------------------------------------- 1 | type LoopA { 2 | b: LoopB! 3 | } 4 | 5 | type LoopB { 6 | a: LoopA! 7 | } 8 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/maps.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | import ( 4 | "io" 5 | "strconv" 6 | ) 7 | 8 | type MapNested struct { 9 | Value CustomScalar 10 | } 11 | 12 | type CustomScalar struct { 13 | value int64 14 | } 15 | 16 | func (s *CustomScalar) UnmarshalGQL(v any) (err error) { 17 | switch v := v.(type) { 18 | case string: 19 | s.value, err = strconv.ParseInt(v, 10, 64) 20 | case int64: 21 | s.value = v 22 | } 23 | return 24 | } 25 | 26 | func (s CustomScalar) MarshalGQL(w io.Writer) { 27 | _, _ = w.Write([]byte(strconv.Quote(strconv.FormatInt(s.value, 10)))) 28 | } 29 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/mutation_with_custom_scalar.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "io" 7 | "regexp" 8 | ) 9 | 10 | var re = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") 11 | 12 | type Email string 13 | 14 | func (value *Email) UnmarshalGQL(v any) error { 15 | input, ok := v.(string) 16 | if !ok { 17 | return errors.New("email expects a string value") 18 | } 19 | if !re.MatchString(input) { 20 | return errors.New("invalid email format") 21 | } 22 | *value = Email(input) 23 | return nil 24 | } 25 | 26 | func (value Email) MarshalGQL(w io.Writer) { 27 | output, _ := json.Marshal(string(value)) 28 | w.Write(output) 29 | } 30 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/mutation_with_custom_scalar.graphql: -------------------------------------------------------------------------------- 1 | extend type Mutation { 2 | updateSomething(input: SpecialInput!): String! 3 | } 4 | 5 | scalar Email 6 | 7 | input SpecialInput { 8 | nesting: NestedInput! 9 | } 10 | 11 | input NestedInput { 12 | field: Email! 13 | } 14 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/nulls.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | errorBubble: Error 3 | errorBubbleList: [Error!] 4 | errorList: [Error] 5 | errors: Errors 6 | valid: String! 7 | invalid: String! 8 | } 9 | 10 | extend type Subscription { 11 | errorRequired: Error! 12 | } 13 | 14 | type Errors { 15 | a: Error! 16 | b: Error! 17 | c: Error! 18 | d: Error! 19 | e: Error! 20 | } 21 | 22 | type Error { 23 | id: ID! 24 | errorOnNonRequiredField: String 25 | errorOnRequiredField: String! 26 | nilOnRequiredField: String! 27 | } 28 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/otherpkg/model.go: -------------------------------------------------------------------------------- 1 | package otherpkg 2 | 3 | type ( 4 | Scalar string 5 | Map map[string]string 6 | Slice []string 7 | ) 8 | 9 | type Struct struct { 10 | Name Scalar 11 | Desc *Scalar 12 | } 13 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/panics.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | panics: Panics 3 | } 4 | 5 | type Panics { 6 | fieldScalarMarshal: [MarshalPanic!]! 7 | fieldFuncMarshal(u: [MarshalPanic!]!): [MarshalPanic!]! 8 | argUnmarshal(u: [MarshalPanic!]!): Boolean! 9 | 10 | } 11 | 12 | scalar MarshalPanic 13 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/primitive_objects.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | primitiveObject: [Primitive!]! 3 | primitiveStringObject: [PrimitiveString!]! 4 | } 5 | 6 | type Primitive { 7 | value: Int! 8 | squared: Int! 9 | } 10 | 11 | type PrimitiveString { 12 | value: String! 13 | doubled: String! 14 | len: Int! 15 | } 16 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/ptr_to_any.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | type PtrToAnyContainer struct { 4 | PtrToAny *any 5 | } 6 | 7 | func (c *PtrToAnyContainer) Binding() *any { 8 | return c.PtrToAny 9 | } 10 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/ptr_to_any.graphql: -------------------------------------------------------------------------------- 1 | scalar Any 2 | 3 | type PtrToAnyContainer { 4 | ptrToAny: Any 5 | binding: Any 6 | } 7 | 8 | extend type Query { 9 | ptrToAnyContainer: PtrToAnyContainer! 10 | } 11 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/ptr_to_ptr_input.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | type PtrToPtrOuter struct { 4 | Name string 5 | Inner *PtrToPtrInner 6 | StupidInner *******PtrToPtrInner 7 | } 8 | 9 | type PtrToPtrInner struct { 10 | Key string 11 | Value string 12 | } 13 | 14 | type UpdatePtrToPtrOuter struct { 15 | Name *string 16 | Inner **UpdatePtrToPtrInner 17 | StupidInner ********UpdatePtrToPtrInner 18 | } 19 | 20 | type UpdatePtrToPtrInner struct { 21 | Key *string 22 | Value *string 23 | } 24 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/ptr_to_ptr_input.graphql: -------------------------------------------------------------------------------- 1 | type PtrToPtrOuter { 2 | name: String! 3 | inner: PtrToPtrInner 4 | stupidInner: PtrToPtrInner 5 | } 6 | 7 | type PtrToPtrInner { 8 | key: String! 9 | value: String! 10 | } 11 | 12 | input UpdatePtrToPtrOuter { 13 | name: String 14 | inner: UpdatePtrToPtrInner 15 | stupidInner: UpdatePtrToPtrInner 16 | } 17 | 18 | input UpdatePtrToPtrInner { 19 | key: String 20 | value: String 21 | } 22 | 23 | extend type Mutation { 24 | updatePtrToPtr(input: UpdatePtrToPtrOuter!): PtrToPtrOuter! 25 | } 26 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/ptr_to_slice.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | type PtrToSliceContainer struct { 4 | PtrToSlice *[]string 5 | } 6 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/ptr_to_slice.graphql: -------------------------------------------------------------------------------- 1 | type PtrToSliceContainer { 2 | ptrToSlice: [String!] 3 | } 4 | 5 | extend type Query { 6 | ptrToSliceContainer: PtrToSliceContainer! 7 | } 8 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/recursive.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | type RecursiveInputSlice struct { 4 | Self []RecursiveInputSlice 5 | } 6 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/scalar_context.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | infinity: Float! 3 | stringFromContextInterface: StringFromContextInterface! 4 | stringFromContextFunction: StringFromContextFunction! 5 | } 6 | 7 | scalar StringFromContextInterface 8 | scalar StringFromContextFunction 9 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/scalar_default.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | defaultScalar(arg: DefaultScalarImplementation! = "default"): DefaultScalarImplementation! 3 | } 4 | 5 | """ This doesnt have an implementation in the typemap, so it should act like a string """ 6 | scalar DefaultScalarImplementation 7 | 8 | type EmbeddedDefaultScalar { 9 | value: DefaultScalarImplementation 10 | } 11 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/skip-include.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | skipInclude: SkipIncludeTestType 3 | } 4 | 5 | type SkipIncludeTestType { 6 | a: String 7 | b: String 8 | } 9 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/slices.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | slices: Slices 3 | scalarSlice: Bytes! 4 | } 5 | 6 | type Slices { 7 | test1: [String] 8 | test2: [String!] 9 | test3: [String]! 10 | test4: [String!]! 11 | } 12 | 13 | scalar Bytes 14 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/thirdparty.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "strconv" 7 | 8 | "github.com/99designs/gqlgen/graphql" 9 | ) 10 | 11 | type ThirdParty struct { 12 | str string 13 | } 14 | 15 | func MarshalThirdParty(tp ThirdParty) graphql.Marshaler { 16 | return graphql.WriterFunc(func(w io.Writer) { 17 | _, err := io.WriteString(w, strconv.Quote(tp.str)) 18 | if err != nil { 19 | panic(err) 20 | } 21 | }) 22 | } 23 | 24 | func UnmarshalThirdParty(input any) (ThirdParty, error) { 25 | switch input := input.(type) { 26 | case string: 27 | return ThirdParty{str: input}, nil 28 | default: 29 | return ThirdParty{}, fmt.Errorf("unknown type for input: %s", input) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/typefallback.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | fallback(arg: FallbackToStringEncoding!): FallbackToStringEncoding! 3 | } 4 | 5 | enum FallbackToStringEncoding { 6 | A 7 | B 8 | C 9 | } 10 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/useptr.graphql: -------------------------------------------------------------------------------- 1 | type A { 2 | id: ID! 3 | } 4 | 5 | type B { 6 | id: ID! 7 | } 8 | 9 | union TestUnion = A | B 10 | 11 | extend type Query { 12 | optionalUnion: TestUnion 13 | } 14 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/useptr_test.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestUserPtr(t *testing.T) { 11 | s := &Stub{} 12 | r := reflect.TypeOf(s.QueryResolver.OptionalUnion) 13 | require.Equal(t, reflect.Interface, r.Out(0).Kind()) 14 | } 15 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/v-ok.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | // VOkCaseValue model 4 | type VOkCaseValue struct{} 5 | 6 | func (v VOkCaseValue) Value() (string, bool) { 7 | return "hi", true 8 | } 9 | 10 | // VOkCaseNil model 11 | type VOkCaseNil struct{} 12 | 13 | func (v VOkCaseNil) Value() (string, bool) { 14 | return "", false 15 | } 16 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/v-ok.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | vOkCaseValue: VOkCaseValue 3 | vOkCaseNil: VOkCaseNil 4 | } 5 | 6 | type VOkCaseValue @goModel(model:"followschema.VOkCaseValue") { 7 | value: String 8 | } 9 | 10 | type VOkCaseNil @goModel(model:"followschema.VOkCaseNil") { 11 | value: String 12 | } 13 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/variadic.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | import ( 4 | "context" 5 | "strconv" 6 | ) 7 | 8 | type VariadicModel struct{} 9 | 10 | type VariadicModelOption func(*VariadicModel) 11 | 12 | func (v VariadicModel) Value(ctx context.Context, rank int, opts ...VariadicModelOption) (string, error) { 13 | return strconv.Itoa(rank), nil 14 | } 15 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/variadic.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | variadicModel: VariadicModel 3 | } 4 | 5 | type VariadicModel { 6 | value(rank: Int!): String 7 | } 8 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/weird_type_cases.graphql: -------------------------------------------------------------------------------- 1 | # regression test for https://github.com/99designs/gqlgen/issues/583 2 | 3 | type asdfIt { id: ID! } 4 | type iIt { id: ID! } 5 | type AIt { id: ID! } 6 | type XXIt { id: ID! } 7 | type AbIt { id: ID! } 8 | type XxIt { id: ID! } 9 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/wrapped_type.go: -------------------------------------------------------------------------------- 1 | package followschema 2 | 3 | import "github.com/99designs/gqlgen/codegen/testserver/followschema/otherpkg" 4 | 5 | type ( 6 | WrappedScalar = otherpkg.Scalar 7 | WrappedStruct otherpkg.Struct 8 | WrappedMap otherpkg.Map 9 | WrappedSlice otherpkg.Slice 10 | ) 11 | -------------------------------------------------------------------------------- /codegen/testserver/followschema/wrapped_type.graphql: -------------------------------------------------------------------------------- 1 | # regression test for https://github.com/99designs/gqlgen/issues/721 2 | 3 | extend type Query { 4 | wrappedStruct: WrappedStruct! 5 | wrappedScalar: WrappedScalar! 6 | wrappedMap: WrappedMap! 7 | wrappedSlice: WrappedSlice! 8 | } 9 | 10 | type WrappedStruct { name: WrappedScalar!, desc: WrappedScalar } 11 | scalar WrappedScalar 12 | type WrappedMap { get(key: String!): String! } 13 | type WrappedSlice { get(idx: Int!): String! } 14 | -------------------------------------------------------------------------------- /codegen/testserver/nullabledirectives/directive.graphql: -------------------------------------------------------------------------------- 1 | directive @populate(value: String!) on ARGUMENT_DEFINITION 2 | directive @noop on ARGUMENT_DEFINITION 3 | 4 | type Query { 5 | directiveSingleNullableArg( 6 | arg1: String @populate(value: "test") @noop, 7 | ): String 8 | } 9 | -------------------------------------------------------------------------------- /codegen/testserver/nullabledirectives/generated/models/models-gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package models 4 | 5 | type Query struct { 6 | } 7 | -------------------------------------------------------------------------------- /codegen/testserver/nullabledirectives/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "*.graphql" 3 | skip_validation: true 4 | exec: 5 | layout: follow-schema 6 | dir: generated 7 | package: generated 8 | model: 9 | filename: generated/models/models-gen.go 10 | package: models 11 | resolver: 12 | filename: generated/resolvers/resolver.go 13 | package: resolver 14 | type: Resolver 15 | 16 | call_argument_directives_with_null: true 17 | -------------------------------------------------------------------------------- /codegen/testserver/nullabledirectives/stub.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package followschema 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/99designs/gqlgen/codegen/testserver/nullabledirectives/generated" 9 | ) 10 | 11 | type Stub struct { 12 | QueryResolver struct { 13 | DirectiveSingleNullableArg func(ctx context.Context, arg1 *string) (*string, error) 14 | } 15 | } 16 | 17 | func (r *Stub) Query() generated.QueryResolver { 18 | return &stubQuery{r} 19 | } 20 | 21 | type stubQuery struct{ *Stub } 22 | 23 | func (r *stubQuery) DirectiveSingleNullableArg(ctx context.Context, arg1 *string) (*string, error) { 24 | return r.QueryResolver.DirectiveSingleNullableArg(ctx, arg1) 25 | } 26 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/builtinscalar.graphql: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | Since gqlgen defines default implementation for a Map scalar, this tests that the builtin is _not_ 4 | added to the TypeMap 5 | """ 6 | type Map { 7 | id: ID! 8 | } 9 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/bytes.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | 7 | "github.com/99designs/gqlgen/graphql" 8 | ) 9 | 10 | func MarshalBytes(b []byte) graphql.Marshaler { 11 | return graphql.WriterFunc(func(w io.Writer) { 12 | _, _ = fmt.Fprintf(w, "%q", string(b)) 13 | }) 14 | } 15 | 16 | func UnmarshalBytes(v any) ([]byte, error) { 17 | switch v := v.(type) { 18 | case string: 19 | return []byte(v), nil 20 | case *string: 21 | return []byte(*v), nil 22 | case []byte: 23 | return v, nil 24 | default: 25 | return nil, fmt.Errorf("%T is not []byte", v) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/complexity.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | overlapping: OverlappingFields 3 | } 4 | 5 | type OverlappingFields { 6 | oneFoo: Int! @goField(name: "foo") 7 | twoFoo: Int! @goField(name: "foo") 8 | oldFoo: Int! @goField(name: "foo", forceResolver: true) 9 | newFoo: Int! 10 | new_foo: Int! 11 | } 12 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/defaults.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | defaultParameters( 3 | falsyBoolean: Boolean = false 4 | truthyBoolean: Boolean = true 5 | ): DefaultParametersMirror! 6 | } 7 | 8 | extend type Mutation { 9 | defaultInput(input: DefaultInput!): DefaultParametersMirror! 10 | } 11 | 12 | input DefaultInput { 13 | falsyBoolean: Boolean = false 14 | truthyBoolean: Boolean = true 15 | } 16 | 17 | type DefaultParametersMirror { 18 | falsyBoolean: Boolean 19 | truthyBoolean: Boolean 20 | } 21 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/defer.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | deferSingle: DeferModel 3 | deferMultiple: [DeferModel!] 4 | } 5 | 6 | type DeferModel { 7 | id: ID! 8 | name: String! 9 | values: [String!]! @goField(forceResolver: true) 10 | } 11 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/embedded.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | embeddedCase1: EmbeddedCase1 3 | embeddedCase2: EmbeddedCase2 4 | embeddedCase3: EmbeddedCase3 5 | } 6 | 7 | type EmbeddedCase1 @goModel(model:"singlefile.EmbeddedCase1") { 8 | exportedEmbeddedPointerExportedMethod: String! 9 | } 10 | 11 | type EmbeddedCase2 @goModel(model:"singlefile.EmbeddedCase2") { 12 | unexportedEmbeddedPointerExportedMethod: String! 13 | } 14 | 15 | type EmbeddedCase3 @goModel(model:"singlefile.EmbeddedCase3") { 16 | unexportedEmbeddedInterfaceExportedMethod: String! 17 | } 18 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/enum.graphql: -------------------------------------------------------------------------------- 1 | enum EnumTest { 2 | OK 3 | NG 4 | } 5 | 6 | input InputWithEnumValue { 7 | enum: EnumTest! 8 | } 9 | 10 | extend type Query { 11 | enumInInput(input: InputWithEnumValue): EnumTest! 12 | } 13 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/fields_order.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | type FieldsOrderInput struct { 4 | FirstField *string `json:"firstField"` 5 | } 6 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/fields_order.graphql: -------------------------------------------------------------------------------- 1 | type FieldsOrderPayload { 2 | firstFieldValue: String 3 | } 4 | 5 | input FieldsOrderInput { 6 | firstField: String 7 | overrideFirstField: String 8 | } 9 | 10 | extend type Mutation { 11 | overrideValueViaInput(input: FieldsOrderInput!): FieldsOrderPayload! 12 | } 13 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "*.graphql" 3 | skip_validation: true 4 | exec: 5 | filename: generated.go 6 | package: singlefile 7 | model: 8 | filename: models-gen.go 9 | package: singlefile 10 | resolver: 11 | filename: resolver.go 12 | package: singlefile 13 | type: Resolver 14 | 15 | autobind: 16 | - "github.com/99designs/gqlgen/codegen/testserver" 17 | - "github.com/99designs/gqlgen/codegen/testserver/singlefile" 18 | - "github.com/99designs/gqlgen/codegen/testserver/singlefile/introspection" 19 | - "github.com/99designs/gqlgen/codegen/testserver/singlefile/invalid-packagename" 20 | 21 | models: 22 | Email: 23 | model: "github.com/99designs/gqlgen/codegen/testserver/singlefile.Email" 24 | StringFromContextFunction: 25 | model: "github.com/99designs/gqlgen/codegen/testserver/singlefile.StringFromContextFunction" 26 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/introspection/it.go: -------------------------------------------------------------------------------- 1 | package introspection 2 | 3 | type It struct { 4 | ID string 5 | } 6 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/invalid-packagename/invalid-identifier.go: -------------------------------------------------------------------------------- 1 | package invalid_packagename 2 | 3 | type InvalidIdentifier struct { 4 | ID int 5 | } 6 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/issue896.graphql: -------------------------------------------------------------------------------- 1 | # This example should build stable output. If the file content starts 2 | # alternating nondeterministically between two outputs, then see 3 | # https://github.com/99designs/gqlgen/issues/896. 4 | 5 | extend schema { 6 | query: Query 7 | subscription: Subscription 8 | } 9 | 10 | type CheckIssue896 {id: Int} 11 | 12 | extend type Query { 13 | issue896a: [CheckIssue896!] # Note the "!" or lack thereof. 14 | } 15 | 16 | extend type Subscription { 17 | issue896b: [CheckIssue896] # Note the "!" or lack thereof. 18 | } 19 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/loops.graphql: -------------------------------------------------------------------------------- 1 | type LoopA { 2 | b: LoopB! 3 | } 4 | 5 | type LoopB { 6 | a: LoopA! 7 | } 8 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/maps.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | import ( 4 | "io" 5 | "strconv" 6 | ) 7 | 8 | type MapNested struct { 9 | Value CustomScalar 10 | } 11 | 12 | type CustomScalar struct { 13 | value int64 14 | } 15 | 16 | func (s *CustomScalar) UnmarshalGQL(v any) (err error) { 17 | switch v := v.(type) { 18 | case string: 19 | s.value, err = strconv.ParseInt(v, 10, 64) 20 | case int64: 21 | s.value = v 22 | } 23 | return 24 | } 25 | 26 | func (s CustomScalar) MarshalGQL(w io.Writer) { 27 | _, _ = w.Write([]byte(strconv.Quote(strconv.FormatInt(s.value, 10)))) 28 | } 29 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/mutation_with_custom_scalar.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "io" 7 | "regexp" 8 | ) 9 | 10 | var re = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") 11 | 12 | type Email string 13 | 14 | func (value *Email) UnmarshalGQL(v any) error { 15 | input, ok := v.(string) 16 | if !ok { 17 | return errors.New("email expects a string value") 18 | } 19 | if !re.MatchString(input) { 20 | return errors.New("invalid email format") 21 | } 22 | *value = Email(input) 23 | return nil 24 | } 25 | 26 | func (value Email) MarshalGQL(w io.Writer) { 27 | output, _ := json.Marshal(string(value)) 28 | w.Write(output) 29 | } 30 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/mutation_with_custom_scalar.graphql: -------------------------------------------------------------------------------- 1 | extend type Mutation { 2 | updateSomething(input: SpecialInput!): String! 3 | } 4 | 5 | scalar Email 6 | 7 | input SpecialInput { 8 | nesting: NestedInput! 9 | } 10 | 11 | input NestedInput { 12 | field: Email! 13 | } 14 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/nulls.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | errorBubble: Error 3 | errorBubbleList: [Error!] 4 | errorList: [Error] 5 | errors: Errors 6 | valid: String! 7 | invalid: String! 8 | } 9 | 10 | extend type Subscription { 11 | errorRequired: Error! 12 | } 13 | 14 | type Errors { 15 | a: Error! 16 | b: Error! 17 | c: Error! 18 | d: Error! 19 | e: Error! 20 | } 21 | 22 | type Error { 23 | id: ID! 24 | errorOnNonRequiredField: String 25 | errorOnRequiredField: String! 26 | nilOnRequiredField: String! 27 | } 28 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/otherpkg/model.go: -------------------------------------------------------------------------------- 1 | package otherpkg 2 | 3 | type ( 4 | Scalar string 5 | Map map[string]string 6 | Slice []string 7 | ) 8 | 9 | type Struct struct { 10 | Name Scalar 11 | Desc *Scalar 12 | } 13 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/panics.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | panics: Panics 3 | } 4 | 5 | type Panics { 6 | fieldScalarMarshal: [MarshalPanic!]! 7 | fieldFuncMarshal(u: [MarshalPanic!]!): [MarshalPanic!]! 8 | argUnmarshal(u: [MarshalPanic!]!): Boolean! 9 | 10 | } 11 | 12 | scalar MarshalPanic 13 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/primitive_objects.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | primitiveObject: [Primitive!]! 3 | primitiveStringObject: [PrimitiveString!]! 4 | } 5 | 6 | type Primitive { 7 | value: Int! 8 | squared: Int! 9 | } 10 | 11 | type PrimitiveString { 12 | value: String! 13 | doubled: String! 14 | len: Int! 15 | } 16 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/ptr_to_any.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | type PtrToAnyContainer struct { 4 | PtrToAny *any 5 | } 6 | 7 | func (c *PtrToAnyContainer) Binding() *any { 8 | return c.PtrToAny 9 | } 10 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/ptr_to_any.graphql: -------------------------------------------------------------------------------- 1 | scalar Any 2 | 3 | type PtrToAnyContainer { 4 | ptrToAny: Any 5 | binding: Any 6 | } 7 | 8 | extend type Query { 9 | ptrToAnyContainer: PtrToAnyContainer! 10 | } 11 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/ptr_to_ptr_input.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | type PtrToPtrOuter struct { 4 | Name string 5 | Inner *PtrToPtrInner 6 | StupidInner *******PtrToPtrInner 7 | } 8 | 9 | type PtrToPtrInner struct { 10 | Key string 11 | Value string 12 | } 13 | 14 | type UpdatePtrToPtrOuter struct { 15 | Name *string 16 | Inner **UpdatePtrToPtrInner 17 | StupidInner ********UpdatePtrToPtrInner 18 | } 19 | 20 | type UpdatePtrToPtrInner struct { 21 | Key *string 22 | Value *string 23 | } 24 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/ptr_to_ptr_input.graphql: -------------------------------------------------------------------------------- 1 | type PtrToPtrOuter { 2 | name: String! 3 | inner: PtrToPtrInner 4 | stupidInner: PtrToPtrInner 5 | } 6 | 7 | type PtrToPtrInner { 8 | key: String! 9 | value: String! 10 | } 11 | 12 | input UpdatePtrToPtrOuter { 13 | name: String 14 | inner: UpdatePtrToPtrInner 15 | stupidInner: UpdatePtrToPtrInner 16 | } 17 | 18 | input UpdatePtrToPtrInner { 19 | key: String 20 | value: String 21 | } 22 | 23 | extend type Mutation { 24 | updatePtrToPtr(input: UpdatePtrToPtrOuter!): PtrToPtrOuter! 25 | } 26 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/ptr_to_slice.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | type PtrToSliceContainer struct { 4 | PtrToSlice *[]string 5 | } 6 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/ptr_to_slice.graphql: -------------------------------------------------------------------------------- 1 | type PtrToSliceContainer { 2 | ptrToSlice: [String!] 3 | } 4 | 5 | extend type Query { 6 | ptrToSliceContainer: PtrToSliceContainer! 7 | } 8 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/recursive.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | type RecursiveInputSlice struct { 4 | Self []RecursiveInputSlice 5 | } 6 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/scalar_context.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | infinity: Float! 3 | stringFromContextInterface: StringFromContextInterface! 4 | stringFromContextFunction: StringFromContextFunction! 5 | } 6 | 7 | scalar StringFromContextInterface 8 | scalar StringFromContextFunction 9 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/scalar_default.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | defaultScalar(arg: DefaultScalarImplementation! = "default"): DefaultScalarImplementation! 3 | } 4 | 5 | """ This doesnt have an implementation in the typemap, so it should act like a string """ 6 | scalar DefaultScalarImplementation 7 | 8 | type EmbeddedDefaultScalar { 9 | value: DefaultScalarImplementation 10 | } 11 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/skip-include.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | skipInclude: SkipIncludeTestType 3 | } 4 | 5 | type SkipIncludeTestType { 6 | a: String 7 | b: String 8 | } 9 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/slices.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | slices: Slices 3 | scalarSlice: Bytes! 4 | } 5 | 6 | type Slices { 7 | test1: [String] 8 | test2: [String!] 9 | test3: [String]! 10 | test4: [String!]! 11 | } 12 | 13 | scalar Bytes 14 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/thirdparty.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "strconv" 7 | 8 | "github.com/99designs/gqlgen/graphql" 9 | ) 10 | 11 | type ThirdParty struct { 12 | str string 13 | } 14 | 15 | func MarshalThirdParty(tp ThirdParty) graphql.Marshaler { 16 | return graphql.WriterFunc(func(w io.Writer) { 17 | _, err := io.WriteString(w, strconv.Quote(tp.str)) 18 | if err != nil { 19 | panic(err) 20 | } 21 | }) 22 | } 23 | 24 | func UnmarshalThirdParty(input any) (ThirdParty, error) { 25 | switch input := input.(type) { 26 | case string: 27 | return ThirdParty{str: input}, nil 28 | default: 29 | return ThirdParty{}, fmt.Errorf("unknown type for input: %s", input) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/typefallback.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | fallback(arg: FallbackToStringEncoding!): FallbackToStringEncoding! 3 | } 4 | 5 | enum FallbackToStringEncoding { 6 | A 7 | B 8 | C 9 | } 10 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/useptr.graphql: -------------------------------------------------------------------------------- 1 | type A { 2 | id: ID! 3 | } 4 | 5 | type B { 6 | id: ID! 7 | } 8 | 9 | union TestUnion = A | B 10 | 11 | extend type Query { 12 | optionalUnion: TestUnion 13 | } 14 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/useptr_test.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestUserPtr(t *testing.T) { 11 | s := &Stub{} 12 | r := reflect.TypeOf(s.QueryResolver.OptionalUnion) 13 | require.Equal(t, reflect.Interface, r.Out(0).Kind()) 14 | } 15 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/v-ok.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | // VOkCaseValue model 4 | type VOkCaseValue struct{} 5 | 6 | func (v VOkCaseValue) Value() (string, bool) { 7 | return "hi", true 8 | } 9 | 10 | // VOkCaseNil model 11 | type VOkCaseNil struct{} 12 | 13 | func (v VOkCaseNil) Value() (string, bool) { 14 | return "", false 15 | } 16 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/v-ok.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | vOkCaseValue: VOkCaseValue 3 | vOkCaseNil: VOkCaseNil 4 | } 5 | 6 | type VOkCaseValue @goModel(model:"singlefile.VOkCaseValue") { 7 | value: String 8 | } 9 | 10 | type VOkCaseNil @goModel(model:"singlefile.VOkCaseNil") { 11 | value: String 12 | } 13 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/variadic.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | import ( 4 | "context" 5 | "strconv" 6 | ) 7 | 8 | type VariadicModel struct{} 9 | 10 | type VariadicModelOption func(*VariadicModel) 11 | 12 | func (v VariadicModel) Value(ctx context.Context, rank int, opts ...VariadicModelOption) (string, error) { 13 | return strconv.Itoa(rank), nil 14 | } 15 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/variadic.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | variadicModel: VariadicModel 3 | } 4 | 5 | type VariadicModel { 6 | value(rank: Int!): String 7 | } 8 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/weird_type_cases.graphql: -------------------------------------------------------------------------------- 1 | # regression test for https://github.com/99designs/gqlgen/issues/583 2 | 3 | type asdfIt { id: ID! } 4 | type iIt { id: ID! } 5 | type AIt { id: ID! } 6 | type XXIt { id: ID! } 7 | type AbIt { id: ID! } 8 | type XxIt { id: ID! } 9 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/wrapped_type.go: -------------------------------------------------------------------------------- 1 | package singlefile 2 | 3 | import "github.com/99designs/gqlgen/codegen/testserver/singlefile/otherpkg" 4 | 5 | type ( 6 | WrappedScalar = otherpkg.Scalar 7 | WrappedStruct otherpkg.Struct 8 | WrappedMap otherpkg.Map 9 | WrappedSlice otherpkg.Slice 10 | ) 11 | -------------------------------------------------------------------------------- /codegen/testserver/singlefile/wrapped_type.graphql: -------------------------------------------------------------------------------- 1 | # regression test for https://github.com/99designs/gqlgen/issues/721 2 | 3 | extend type Query { 4 | wrappedStruct: WrappedStruct! 5 | wrappedScalar: WrappedScalar! 6 | wrappedMap: WrappedMap! 7 | wrappedSlice: WrappedSlice! 8 | } 9 | 10 | type WrappedStruct { name: WrappedScalar!, desc: WrappedScalar } 11 | scalar WrappedScalar 12 | type WrappedMap { get(key: String!): String! } 13 | type WrappedSlice { get(idx: Int!): String! } 14 | -------------------------------------------------------------------------------- /codegen/testserver/usefunctionsyntaxforexecutioncontext/directive.go: -------------------------------------------------------------------------------- 1 | package usefunctionsyntaxforexecutioncontext 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "github.com/99designs/gqlgen/graphql" 8 | ) 9 | 10 | // LogDirective implementation 11 | func LogDirective(ctx context.Context, obj any, next graphql.Resolver, message *string) (res any, err error) { 12 | log.Printf("Log Directive: %s", *message) 13 | 14 | // Proceed with the next resolver in the chain 15 | return next(ctx) 16 | } 17 | -------------------------------------------------------------------------------- /codegen/testserver/usefunctionsyntaxforexecutioncontext/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "*.graphql" 3 | skip_validation: true 4 | use_function_syntax_for_execution_context: true 5 | exec: 6 | filename: generated.go 7 | package: usefunctionsyntaxforexecutioncontext 8 | model: 9 | filename: models-gen.go 10 | package: usefunctionsyntaxforexecutioncontext 11 | resolver: 12 | filename: resolver.go 13 | package: usefunctionsyntaxforexecutioncontext 14 | type: Resolver 15 | 16 | autobind: 17 | - "github.com/99designs/gqlgen/codegen/testserver" 18 | - "github.com/99designs/gqlgen/codegen/testserver/usefunctionsyntaxforexecutioncontext" 19 | 20 | models: 21 | Email: 22 | model: "github.com/99designs/gqlgen/codegen/testserver/singlefile.Email" 23 | StringFromContextFunction: 24 | model: "github.com/99designs/gqlgen/codegen/testserver/singlefile.StringFromContextFunction" 25 | -------------------------------------------------------------------------------- /docs/config.yml: -------------------------------------------------------------------------------- 1 | baseurl: https://gqlgen.com/ 2 | metadataformat: yaml 3 | title: gqlgen 4 | enableGitInfo: true 5 | pygmentsCodeFences: true 6 | pygmentsUseClasses: true 7 | canonifyURLs: true 8 | 9 | params: 10 | name: gqlgen 11 | description: graphql servers the easy way 12 | 13 | menu: 14 | main: 15 | - name: Introduction 16 | url: / 17 | weight: -10 18 | - name: Reference 19 | identifier: reference 20 | weight: 5 21 | - name: Recipes 22 | identifier: recipes 23 | weight: 10 24 | - name: pkg.go.dev → 25 | parent: reference 26 | url: https://pkg.go.dev/github.com/99designs/gqlgen 27 | 28 | security: 29 | funcs: 30 | getenv: 31 | - '^HUGO_' 32 | - 'VERSIONS' 33 | - 'CURRENT_VERSION' 34 | 35 | go_initialisms: 36 | replace_defaults: false 37 | initialisms: 38 | - 'CC' 39 | - 'BCC' 40 | -------------------------------------------------------------------------------- /docs/content/_introduction.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /docs/content/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | linkTitle: Introduction 3 | title: Type-safe GraphQL for Go 4 | type: homepage 5 | date: 2018-03-17T13:06:47+11:00 6 | --- 7 | -------------------------------------------------------------------------------- /docs/layouts/404.html: -------------------------------------------------------------------------------- 1 | {{ define "main" }} 2 |

Page not found

3 | 4 | I'm sorry, but the requested page wasn’t found on the server. 5 | {{ end }} -------------------------------------------------------------------------------- /docs/layouts/_default/single.html: -------------------------------------------------------------------------------- 1 | {{ define "main" }} 2 |
3 |
4 |

{{ .LinkTitle }}

5 |
{{ .Title }}
6 | 9 | [edit] 10 | 11 |
12 |
13 | 14 |
15 |
16 | {{partial "version-banner"}} 17 | {{ .Content }} 18 |
19 |
20 | {{ end }} 21 | -------------------------------------------------------------------------------- /docs/layouts/index.html: -------------------------------------------------------------------------------- 1 | {{ define "main" }} 2 | {{ range where .Site.Pages "Type" "homepage" }} 3 |
4 | {{ .Description }} 5 |
6 |

{{ .LinkTitle }}

7 |
{{ .Title }}
8 |
9 |
10 | 11 |
12 |
13 | {{partial "version-banner"}} 14 | {{ .Content }} 15 | {{.Scratch.Set "intro" (readFile "content/_introduction.md")}} 16 | {{.Scratch.Set "intro" (split (.Scratch.Get "intro") "\n")}} 17 | {{.Scratch.Set "intro" (after 2 (.Scratch.Get "intro"))}} 18 | {{.Scratch.Set "intro" (delimit (.Scratch.Get "intro") "\n")}} 19 | {{.Scratch.Get "intro"|markdownify}} 20 |
21 |
22 | {{ end }} 23 | {{ end }} 24 | -------------------------------------------------------------------------------- /docs/layouts/partials/version-banner.html: -------------------------------------------------------------------------------- 1 | {{ $currentVersion := getenv "CURRENT_VERSION" }} 2 | {{ $versionString := getenv "VERSIONS" }} 3 | {{ $versions := split $versionString "," }} 4 | {{ $latestVersion := index $versions 0 }} 5 | 6 | {{ if (eq $currentVersion "master") }} 7 |
8 | You are looking at the docs for the unreleased master branch. The latest version is {{ $latestVersion }}. 9 |
10 | {{ else if not (eq $latestVersion $currentVersion) }} 11 |
12 | You are looking at the docs for an older version ({{ $currentVersion }}). The latest version is {{ $latestVersion }}. 13 |
14 | {{ end }} 15 | -------------------------------------------------------------------------------- /docs/layouts/partials/version-switcher.html: -------------------------------------------------------------------------------- 1 | {{ $VersionString := getenv "VERSIONS" }} 2 | {{ $Versions := split $VersionString "," }} 3 | {{ $currentVersion := getenv "CURRENT_VERSION" }} 4 | 5 |
6 | {{ $currentVersion }} 7 |
8 | {{$currentVersion}} 9 | {{ range $i, $version := $Versions }} 10 | {{ if not (eq $currentVersion $version) }} 11 | {{$version}} 12 | {{ end }} 13 | {{ end }} 14 |
15 |
16 | -------------------------------------------------------------------------------- /docs/layouts/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | {{ range .Data.Pages }} 3 | {{ if or .Description (eq .Kind "home") }} 4 | 5 | {{ .Permalink }} 6 | {{ if not .Lastmod.IsZero }}{{ safeHTML ( .Lastmod.Format "2006-01-02T15:04:05-07:00" ) }}{{ end }} 7 | {{ with .Sitemap.ChangeFreq }}{{ . }}{{ end }} 8 | {{ if ge .Sitemap.Priority 0.0 }}{{ .Sitemap.Priority }}{{ end }} 9 | 10 | {{ end }} 11 | {{ end }} 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/readme.md: -------------------------------------------------------------------------------- 1 | Documentation 2 | ==== 3 | 4 | This directory contains the markdown source files for the static doc site hosted at [gqlgen.com](https://gqlgen.com) 5 | 6 | 7 | ## Install hugo 8 | 9 | Before working with these docs you will need to install hugo, see [Quickstart](https://gohugo.io/getting-started/quick-start/) for instructions. 10 | 11 | 12 | ## Editing docs 13 | 14 | When editing docs run `hugo serve` and a live reload server will start, then navigate to http://localhost:1313 in your browser. Any changes made will be updated in the browser. 15 | 16 | 17 | ## Publishing docs 18 | 19 | Docs are hosted using [render.com](https://render.com/) and will be automatically deployed when merging to master. 20 | 21 | -------------------------------------------------------------------------------- /docs/static/external-link-alt.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /docs/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/99designs/gqlgen/0fce010415029b53fc75b00c6dc85394f44402db/docs/static/favicon.ico -------------------------------------------------------------------------------- /docs/static/request_anatomy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/99designs/gqlgen/0fce010415029b53fc75b00c6dc85394f44402db/docs/static/request_anatomy.png -------------------------------------------------------------------------------- /docs/static/schema_layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/99designs/gqlgen/0fce010415029b53fc75b00c6dc85394f44402db/docs/static/schema_layout.png -------------------------------------------------------------------------------- /graphql/any.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | ) 7 | 8 | func MarshalAny(v any) Marshaler { 9 | return WriterFunc(func(w io.Writer) { 10 | err := json.NewEncoder(w).Encode(v) 11 | if err != nil { 12 | panic(err) 13 | } 14 | }) 15 | } 16 | 17 | func UnmarshalAny(v any) (any, error) { 18 | return v, nil 19 | } 20 | -------------------------------------------------------------------------------- /graphql/bool.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | func MarshalBoolean(b bool) Marshaler { 11 | str := strconv.FormatBool(b) 12 | return WriterFunc(func(w io.Writer) { w.Write([]byte(str)) }) 13 | } 14 | 15 | func UnmarshalBoolean(v any) (bool, error) { 16 | switch v := v.(type) { 17 | case string: 18 | return strings.EqualFold(v, "true"), nil 19 | case int: 20 | return v != 0, nil 21 | case bool: 22 | return v, nil 23 | case nil: 24 | return false, nil 25 | default: 26 | return false, fmt.Errorf("%T is not a bool", v) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /graphql/bool_test.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestBoolean(t *testing.T) { 11 | assert.Equal(t, "true", doBooleanMarshal(true)) 12 | assert.Equal(t, "false", doBooleanMarshal(false)) 13 | } 14 | 15 | func doBooleanMarshal(b bool) string { 16 | var buf bytes.Buffer 17 | MarshalBoolean(b).MarshalGQL(&buf) 18 | return buf.String() 19 | } 20 | -------------------------------------------------------------------------------- /graphql/context_field_test.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | "github.com/vektah/gqlparser/v2/ast" 9 | ) 10 | 11 | func TestGetResolverContext(t *testing.T) { 12 | require.Nil(t, GetFieldContext(context.Background())) 13 | 14 | rc := &FieldContext{} 15 | require.Equal(t, rc, GetFieldContext(WithFieldContext(context.Background(), rc))) 16 | } 17 | 18 | func testContext(sel ast.SelectionSet) context.Context { 19 | ctx := context.Background() 20 | 21 | rqCtx := &OperationContext{} 22 | ctx = WithOperationContext(ctx, rqCtx) 23 | 24 | root := &FieldContext{ 25 | Field: CollectedField{ 26 | Selections: sel, 27 | }, 28 | } 29 | ctx = WithFieldContext(ctx, root) 30 | 31 | return ctx 32 | } 33 | -------------------------------------------------------------------------------- /graphql/context_path_test.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestGetFieldInputContext(t *testing.T) { 11 | require.Nil(t, GetFieldContext(context.Background())) 12 | 13 | rc := &PathContext{} 14 | require.Equal(t, rc, GetPathContext(WithPathContext(context.Background(), rc))) 15 | } 16 | -------------------------------------------------------------------------------- /graphql/context_root_field.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | const rootResolverCtx key = "root_resolver_context" 8 | 9 | type RootFieldContext struct { 10 | // The name of the type this field belongs to 11 | Object string 12 | // The raw field 13 | Field CollectedField 14 | } 15 | 16 | func GetRootFieldContext(ctx context.Context) *RootFieldContext { 17 | if val, ok := ctx.Value(rootResolverCtx).(*RootFieldContext); ok { 18 | return val 19 | } 20 | return nil 21 | } 22 | 23 | func WithRootFieldContext(ctx context.Context, rc *RootFieldContext) context.Context { 24 | return context.WithValue(ctx, rootResolverCtx, rc) 25 | } 26 | -------------------------------------------------------------------------------- /graphql/context_root_field_test.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestGetRootFieldContext(t *testing.T) { 11 | require.Nil(t, GetRootFieldContext(context.Background())) 12 | 13 | rc := &RootFieldContext{} 14 | require.Equal(t, rc, GetRootFieldContext(WithRootFieldContext(context.Background(), rc))) 15 | } 16 | -------------------------------------------------------------------------------- /graphql/deferred.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/vektah/gqlparser/v2/ast" 7 | "github.com/vektah/gqlparser/v2/gqlerror" 8 | ) 9 | 10 | type Deferrable struct { 11 | Label string 12 | } 13 | 14 | type DeferredGroup struct { 15 | Path ast.Path 16 | Label string 17 | FieldSet *FieldSet 18 | Context context.Context 19 | } 20 | 21 | type DeferredResult struct { 22 | Path ast.Path 23 | Label string 24 | Result Marshaler 25 | Errors gqlerror.List 26 | } 27 | -------------------------------------------------------------------------------- /graphql/duration.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | 7 | dur "github.com/sosodev/duration" 8 | ) 9 | 10 | // UnmarshalDuration returns the duration from a string in ISO8601 format 11 | func UnmarshalDuration(v any) (time.Duration, error) { 12 | input, ok := v.(string) 13 | if !ok { 14 | return 0, errors.New("input must be a string") 15 | } 16 | 17 | d2, err := dur.Parse(input) 18 | if err != nil { 19 | return 0, err 20 | } 21 | return d2.ToTimeDuration(), nil 22 | } 23 | 24 | // MarshalDuration returns the duration on ISO8601 format 25 | func MarshalDuration(d time.Duration) Marshaler { 26 | return MarshalString(dur.Format(d)) 27 | } 28 | -------------------------------------------------------------------------------- /graphql/duration_test.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | "time" 7 | 8 | "github.com/stretchr/testify/assert" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func TestDurationMarshaling(t *testing.T) { 13 | t.Run("UnmarshalDuration", func(t *testing.T) { 14 | d, err := UnmarshalDuration("P2Y") 15 | require.NoError(t, err) 16 | 17 | assert.InEpsilon(t, float64(365*24*2), d.Hours(), 0.02) 18 | }) 19 | t.Run("MarshalDuration", func(t *testing.T) { 20 | m := MarshalDuration(time.Hour * 365 * 24 * 2) 21 | 22 | buf := new(bytes.Buffer) 23 | m.MarshalGQL(buf) 24 | 25 | assert.Equal(t, "\"P2Y\"", buf.String()) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /graphql/fieldset_test.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | "github.com/vektah/gqlparser/v2/ast" 9 | ) 10 | 11 | func TestFieldSet_MarshalGQL(t *testing.T) { 12 | t.Run("Should_Deduplicate_Keys", func(t *testing.T) { 13 | fs := NewFieldSet([]CollectedField{ 14 | {Field: &ast.Field{Alias: "__typename"}}, 15 | {Field: &ast.Field{Alias: "__typename"}}, 16 | }) 17 | fs.Values[0] = MarshalString("A") 18 | fs.Values[1] = MarshalString("A") 19 | 20 | b := bytes.NewBuffer(nil) 21 | fs.MarshalGQL(b) 22 | 23 | assert.JSONEq(t, "{\"__typename\":\"A\"}", b.String()) 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /graphql/float_test.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestFloat(t *testing.T) { 11 | assert.Equal(t, "123", m2s(MarshalFloat(123))) 12 | assert.Equal(t, "1.2345678901", m2s(MarshalFloat(1.2345678901))) 13 | assert.Equal(t, "1.2345678901234567", m2s(MarshalFloat(1.234567890123456789))) 14 | assert.Equal(t, "1.2e+20", m2s(MarshalFloat(1.2e+20))) 15 | assert.Equal(t, "1.2e-20", m2s(MarshalFloat(1.2e-20))) 16 | } 17 | 18 | func m2s(m Marshaler) string { 19 | var b bytes.Buffer 20 | m.MarshalGQL(&b) 21 | return b.String() 22 | } 23 | -------------------------------------------------------------------------------- /graphql/handler/apollofederatedtracingv1/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import "log" 4 | 5 | // Logger is an interface that can be implemented to log errors that occur during the tracing process 6 | // This can use the default Go logger or a custom logger (e.g. logrus or zap) 7 | type Logger interface { 8 | Print(args any) 9 | Println(args any) 10 | Printf(format string, args any) 11 | } 12 | 13 | func NewNoopLogger() *NoopLogger { 14 | return &NoopLogger{ 15 | log.New(NullWriter(1), "", log.LstdFlags), 16 | } 17 | } 18 | 19 | type NullWriter int 20 | 21 | func (NullWriter) Write([]byte) (int, error) { return 0, nil } 22 | 23 | type NoopLogger struct { 24 | *log.Logger 25 | } 26 | 27 | func (l *NoopLogger) Print(args any) {} 28 | 29 | func (l *NoopLogger) Printf(format string, args any) {} 30 | 31 | func (l *NoopLogger) Println(v any) {} 32 | -------------------------------------------------------------------------------- /graphql/handler/apollofederatedtracingv1/logger/logger_test.go: -------------------------------------------------------------------------------- 1 | package logger_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/99designs/gqlgen/graphql/handler/apollofederatedtracingv1/logger" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestNoopLogger_Print(t *testing.T) { 11 | l := logger.NewNoopLogger() 12 | assert.NotPanics(t, func() { 13 | l.Print("test") 14 | }) 15 | } 16 | 17 | func TestNoopLogger_Printf(t *testing.T) { 18 | l := logger.NewNoopLogger() 19 | assert.NotPanics(t, func() { 20 | l.Printf("test %s", "formatted") 21 | }) 22 | } 23 | 24 | func TestNoopLogger_Println(t *testing.T) { 25 | l := logger.NewNoopLogger() 26 | assert.NotPanics(t, func() { 27 | l.Println("test") 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /graphql/handler/extension/introspection.go: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/vektah/gqlparser/v2/gqlerror" 7 | 8 | "github.com/99designs/gqlgen/graphql" 9 | ) 10 | 11 | // EnableIntrospection enables clients to reflect all of the types available on the graph. 12 | type Introspection struct{} 13 | 14 | var _ interface { 15 | graphql.OperationContextMutator 16 | graphql.HandlerExtension 17 | } = Introspection{} 18 | 19 | func (c Introspection) ExtensionName() string { 20 | return "Introspection" 21 | } 22 | 23 | func (c Introspection) Validate(schema graphql.ExecutableSchema) error { 24 | return nil 25 | } 26 | 27 | func (c Introspection) MutateOperationContext(ctx context.Context, opCtx *graphql.OperationContext) *gqlerror.Error { 28 | opCtx.DisableIntrospection = false 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /graphql/handler/extension/introspection_test.go: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | "github.com/vektah/gqlparser/v2/gqlerror" 9 | 10 | "github.com/99designs/gqlgen/graphql" 11 | ) 12 | 13 | func TestIntrospection(t *testing.T) { 14 | opCtx := &graphql.OperationContext{ 15 | DisableIntrospection: true, 16 | } 17 | err := Introspection{}.MutateOperationContext(context.Background(), opCtx) 18 | require.Equal(t, (*gqlerror.Error)(nil), err) 19 | require.False(t, opCtx.DisableIntrospection) 20 | } 21 | -------------------------------------------------------------------------------- /graphql/handler/lru/lru.go: -------------------------------------------------------------------------------- 1 | package lru 2 | 3 | import ( 4 | "context" 5 | 6 | lru "github.com/hashicorp/golang-lru/v2" 7 | 8 | "github.com/99designs/gqlgen/graphql" 9 | ) 10 | 11 | type LRU[T any] struct { 12 | lru *lru.Cache[string, T] 13 | } 14 | 15 | var _ graphql.Cache[any] = &LRU[any]{} 16 | 17 | func New[T any](size int) *LRU[T] { 18 | cache, err := lru.New[string, T](size) 19 | if err != nil { 20 | // An error is only returned for non-positive cache size 21 | // and we already checked for that. 22 | panic("unexpected error creating cache: " + err.Error()) 23 | } 24 | return &LRU[T]{cache} 25 | } 26 | 27 | func (l LRU[T]) Get(ctx context.Context, key string) (value T, ok bool) { 28 | return l.lru.Get(key) 29 | } 30 | 31 | func (l LRU[T]) Add(ctx context.Context, key string, value T) { 32 | l.lru.Add(key, value) 33 | } 34 | -------------------------------------------------------------------------------- /graphql/handler/transport/error.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | 8 | "github.com/vektah/gqlparser/v2/gqlerror" 9 | 10 | "github.com/99designs/gqlgen/graphql" 11 | ) 12 | 13 | // SendError sends a best effort error to a raw response writer. It assumes the client can understand the standard 14 | // json error response 15 | func SendError(w http.ResponseWriter, code int, errors ...*gqlerror.Error) { 16 | w.WriteHeader(code) 17 | b, err := json.Marshal(&graphql.Response{Errors: errors}) 18 | if err != nil { 19 | panic(err) 20 | } 21 | _, _ = w.Write(b) 22 | } 23 | 24 | // SendErrorf wraps SendError to add formatted messages 25 | func SendErrorf(w http.ResponseWriter, code int, format string, args ...any) { 26 | SendError(w, code, &gqlerror.Error{Message: fmt.Sprintf(format, args...)}) 27 | } 28 | -------------------------------------------------------------------------------- /graphql/handler/transport/util.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | 8 | "github.com/vektah/gqlparser/v2/gqlerror" 9 | 10 | "github.com/99designs/gqlgen/graphql" 11 | ) 12 | 13 | func writeJson(w io.Writer, response *graphql.Response) { 14 | b, err := json.Marshal(response) 15 | if err != nil { 16 | panic(fmt.Errorf("unable to marshal %s: %w", string(response.Data), err)) 17 | } 18 | w.Write(b) 19 | } 20 | 21 | func writeJsonError(w io.Writer, msg string) { 22 | writeJson(w, &graphql.Response{Errors: gqlerror.List{{Message: msg}}}) 23 | } 24 | 25 | func writeJsonErrorf(w io.Writer, format string, args ...any) { 26 | writeJson(w, &graphql.Response{Errors: gqlerror.List{{Message: fmt.Sprintf(format, args...)}}}) 27 | } 28 | 29 | func writeJsonGraphqlError(w io.Writer, err ...*gqlerror.Error) { 30 | writeJson(w, &graphql.Response{Errors: err}) 31 | } 32 | -------------------------------------------------------------------------------- /graphql/handler/transport/websocket_close_reason.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | // A private key for context that only this package can access. This is important 8 | // to prevent collisions between different context uses 9 | var closeReasonCtxKey = &wsCloseReasonContextKey{"close-reason"} 10 | 11 | type wsCloseReasonContextKey struct { 12 | name string 13 | } 14 | 15 | func AppendCloseReason(ctx context.Context, reason string) context.Context { 16 | return context.WithValue(ctx, closeReasonCtxKey, reason) 17 | } 18 | 19 | func closeReasonForContext(ctx context.Context) string { 20 | reason, _ := ctx.Value(closeReasonCtxKey).(string) 21 | return reason 22 | } 23 | -------------------------------------------------------------------------------- /graphql/map.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | ) 8 | 9 | func MarshalMap(val map[string]any) Marshaler { 10 | return WriterFunc(func(w io.Writer) { 11 | err := json.NewEncoder(w).Encode(val) 12 | if err != nil { 13 | panic(err) 14 | } 15 | }) 16 | } 17 | 18 | func UnmarshalMap(v any) (map[string]any, error) { 19 | if m, ok := v.(map[string]any); ok { 20 | return m, nil 21 | } 22 | 23 | return nil, fmt.Errorf("%T is not a map", v) 24 | } 25 | -------------------------------------------------------------------------------- /graphql/oneshot.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import "context" 4 | 5 | func OneShot(resp *Response) ResponseHandler { 6 | var oneshot bool 7 | 8 | return func(context context.Context) *Response { 9 | if oneshot { 10 | return nil 11 | } 12 | oneshot = true 13 | 14 | return resp 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /graphql/playground/altair_playground_test.go: -------------------------------------------------------------------------------- 1 | package playground 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | ) 7 | 8 | func TestAltairHandler_Integrity(t *testing.T) { 9 | testResourceIntegrity(t, func(title, endpoint string) http.HandlerFunc { return AltairHandler(title, endpoint, nil) }) 10 | } 11 | -------------------------------------------------------------------------------- /graphql/playground/apollo_sandbox_playground_test.go: -------------------------------------------------------------------------------- 1 | package playground 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | ) 7 | 8 | func TestApolloSandboxHandler_Integrity(t *testing.T) { 9 | testResourceIntegrity(t, func(title, endpoint string) http.HandlerFunc { 10 | return ApolloSandboxHandler(title, endpoint) 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /graphql/recovery.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "runtime/debug" 8 | 9 | "github.com/vektah/gqlparser/v2/gqlerror" 10 | ) 11 | 12 | type RecoverFunc func(ctx context.Context, err any) (userMessage error) 13 | 14 | func DefaultRecover(ctx context.Context, err any) error { 15 | fmt.Fprintln(os.Stderr, err) 16 | fmt.Fprintln(os.Stderr) 17 | debug.PrintStack() 18 | 19 | return gqlerror.Errorf("internal system error") 20 | } 21 | -------------------------------------------------------------------------------- /graphql/root.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | type Query struct{} 4 | 5 | type Mutation struct{} 6 | 7 | type Subscription struct{} 8 | -------------------------------------------------------------------------------- /graphql/time.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "strconv" 7 | "time" 8 | ) 9 | 10 | func MarshalTime(t time.Time) Marshaler { 11 | if t.IsZero() { 12 | return Null 13 | } 14 | 15 | return WriterFunc(func(w io.Writer) { 16 | io.WriteString(w, strconv.Quote(t.Format(time.RFC3339Nano))) 17 | }) 18 | } 19 | 20 | func UnmarshalTime(v any) (time.Time, error) { 21 | if tmpStr, ok := v.(string); ok { 22 | return time.Parse(time.RFC3339Nano, tmpStr) 23 | } 24 | return time.Time{}, errors.New("time should be RFC3339Nano formatted string") 25 | } 26 | -------------------------------------------------------------------------------- /graphql/time_test.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "bytes" 5 | "strconv" 6 | "testing" 7 | "time" 8 | 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func TestTime(t *testing.T) { 13 | t.Run("symmetry", func(t *testing.T) { 14 | initialTime := time.Now() 15 | buf := bytes.NewBuffer([]byte{}) 16 | MarshalTime(initialTime).MarshalGQL(buf) 17 | 18 | str, err := strconv.Unquote(buf.String()) 19 | require.NoError(t, err) 20 | newTime, err := UnmarshalTime(str) 21 | require.NoError(t, err) 22 | 23 | require.True(t, initialTime.Equal(newTime), "expected times %v and %v to equal", initialTime, newTime) 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /graphql/upload.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | ) 7 | 8 | type Upload struct { 9 | File io.ReadSeeker 10 | Filename string 11 | Size int64 12 | ContentType string 13 | } 14 | 15 | func MarshalUpload(f Upload) Marshaler { 16 | return WriterFunc(func(w io.Writer) { 17 | io.Copy(w, f.File) 18 | }) 19 | } 20 | 21 | func UnmarshalUpload(v any) (Upload, error) { 22 | upload, ok := v.(Upload) 23 | if !ok { 24 | return Upload{}, fmt.Errorf("%T is not an Upload", v) 25 | } 26 | return upload, nil 27 | } 28 | -------------------------------------------------------------------------------- /graphql/uuid.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/google/uuid" 7 | ) 8 | 9 | func MarshalUUID(id uuid.UUID) Marshaler { 10 | if id == uuid.Nil { 11 | return Null 12 | } 13 | return MarshalString(id.String()) 14 | } 15 | 16 | func UnmarshalUUID(v any) (uuid.UUID, error) { 17 | switch v := v.(type) { 18 | case string: 19 | return uuid.Parse(v) 20 | case []byte: 21 | return uuid.ParseBytes(v) 22 | default: 23 | return uuid.Nil, fmt.Errorf("%T is not a uuid", v) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /graphql/version.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | const Version = "v0.17.73-dev" 4 | -------------------------------------------------------------------------------- /init-templates/schema.graphqls: -------------------------------------------------------------------------------- 1 | # GraphQL schema example 2 | # 3 | # https://gqlgen.com/getting-started/ 4 | 5 | type Todo { 6 | id: ID! 7 | text: String! 8 | done: Boolean! 9 | user: User! 10 | } 11 | 12 | type User { 13 | id: ID! 14 | name: String! 15 | } 16 | 17 | type Query { 18 | todos: [Todo!]! 19 | } 20 | 21 | input NewTodo { 22 | text: String! 23 | userId: String! 24 | } 25 | 26 | type Mutation { 27 | createTodo(input: NewTodo!): Todo! 28 | } 29 | -------------------------------------------------------------------------------- /integration/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /integration/README.md: -------------------------------------------------------------------------------- 1 | # Integration tests 2 | 3 | These tests run a gqlgen server against the apollo client to test real world connectivity. 4 | 5 | First start the go server 6 | ```bash 7 | go run server/cmd/integration/server.go 8 | ``` 9 | 10 | And in another terminal: 11 | ```bash 12 | cd integration 13 | npm ci 14 | npm run test 15 | ``` 16 | -------------------------------------------------------------------------------- /integration/codegen.ts: -------------------------------------------------------------------------------- 1 | import type { CodegenConfig } from '@graphql-codegen/cli'; 2 | 3 | const config: CodegenConfig = { 4 | overwrite: true, 5 | schema: process.env.VITE_SERVER_URL ?? 'http://localhost:8080/query', 6 | documents: 'src/**/*.graphql', 7 | generates: { 8 | 'src/generated/': { 9 | preset: 'client-preset' 10 | }, 11 | 'src/generated/schema-fetched.graphql': { 12 | plugins: ['schema-ast'], 13 | }, 14 | 'src/generated/schema-introspection.json': { 15 | plugins: ['introspection'], 16 | } 17 | }, 18 | }; 19 | 20 | export default config; 21 | -------------------------------------------------------------------------------- /integration/graphql.config.yml: -------------------------------------------------------------------------------- 1 | name: Schema 2 | schema: src/generated/schema-expected.graphql 3 | extensions: 4 | endpoints: 5 | dev: 6 | url: http://localhost:8080/query 7 | introspect: true 8 | -------------------------------------------------------------------------------- /integration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "integration", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "test": "vitest", 8 | "gen": "graphql-codegen --config codegen.ts" 9 | }, 10 | "devDependencies": { 11 | "@apollo/client": "^3.13.8", 12 | "@graphql-codegen/cli": "^5.0.6", 13 | "@graphql-codegen/client-preset": "^4.8.0", 14 | "@graphql-codegen/introspection": "^4.0.3", 15 | "@graphql-codegen/schema-ast": "^4.1.0", 16 | "cross-fetch": "^4.1.0", 17 | "graphql": "^16.11.0", 18 | "graphql-codegen": "^0.4.0", 19 | "graphql-sse": "^2.5.4", 20 | "graphql-ws": "^6.0.5", 21 | "typescript": "^5.8.3", 22 | "urql": "^4.2.2", 23 | "vite": "^6.3.5", 24 | "vitest": "^3.1.4" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /integration/server/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - schema/**/*.graphql 3 | 4 | exec: 5 | filename: generated.go 6 | model: 7 | filename: models-go/generated.go 8 | 9 | struct_tag: json 10 | 11 | autobind: 12 | - "github.com/99designs/gqlgen/integration/server/testomitempty" 13 | 14 | models: 15 | Element: 16 | model: github.com/99designs/gqlgen/integration/server/models-go.Element 17 | Viewer: 18 | model: github.com/99designs/gqlgen/integration/server/models-go.Viewer 19 | User: 20 | model: github.com/99designs/gqlgen/integration/server/remote_api.User 21 | fields: 22 | likes: 23 | resolver: true 24 | -------------------------------------------------------------------------------- /integration/server/models-go/element.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type Element struct { 4 | ID int 5 | } 6 | 7 | func (e *Element) Mismatched() []Element { 8 | return []Element{*e} 9 | } 10 | -------------------------------------------------------------------------------- /integration/server/models-go/viewer.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "github.com/99designs/gqlgen/integration/server/remote_api" 4 | 5 | type Viewer struct { 6 | User *remote_api.User 7 | } 8 | -------------------------------------------------------------------------------- /integration/server/remote_api/user.go: -------------------------------------------------------------------------------- 1 | package remote_api 2 | 3 | type User struct { 4 | Name string 5 | Likes []string 6 | PhoneNumber string 7 | } 8 | -------------------------------------------------------------------------------- /integration/server/schema/testomitempty.graphql: -------------------------------------------------------------------------------- 1 | type RemoteModelWithOmitempty { 2 | newDesc: String 3 | } 4 | -------------------------------------------------------------------------------- /integration/server/schema/user.graphql: -------------------------------------------------------------------------------- 1 | type User { 2 | name: String! 3 | likes: [String!]! 4 | phoneNumber: String @deprecated 5 | query: Query! 6 | } 7 | -------------------------------------------------------------------------------- /integration/server/testomitempty/testmodel.go: -------------------------------------------------------------------------------- 1 | package testomitempty 2 | 3 | type RemoteModelWithOmitempty struct { 4 | Description string `json:"newDesc,omitempty"` 5 | } 6 | -------------------------------------------------------------------------------- /integration/src/generated/.gitignore: -------------------------------------------------------------------------------- 1 | schema-fetched.graphql 2 | schema-introspection.json 3 | -------------------------------------------------------------------------------- /integration/src/generated/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./fragment-masking"; 2 | export * from "./gql"; -------------------------------------------------------------------------------- /integration/src/queries/coercion.graphql: -------------------------------------------------------------------------------- 1 | query coercion($value: [ListCoercion!]){ 2 | coercion(value: $value ) 3 | } 4 | -------------------------------------------------------------------------------- /integration/src/queries/complexity.graphql: -------------------------------------------------------------------------------- 1 | query complexity($value: Int!) { 2 | complexity(value: $value) 3 | } 4 | -------------------------------------------------------------------------------- /integration/src/queries/date.graphql: -------------------------------------------------------------------------------- 1 | query date($filter: DateFilter!) { 2 | date(filter: $filter) 3 | } 4 | -------------------------------------------------------------------------------- /integration/src/queries/error.graphql: -------------------------------------------------------------------------------- 1 | query error($type: ErrorType) { 2 | error(type: $type) 3 | } 4 | -------------------------------------------------------------------------------- /integration/src/queries/jsonEncoding.graphql: -------------------------------------------------------------------------------- 1 | query jsonEncoding { 2 | jsonEncoding 3 | } 4 | -------------------------------------------------------------------------------- /integration/src/queries/path.graphql: -------------------------------------------------------------------------------- 1 | query path { 2 | path { 3 | cc:child { 4 | error 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /integration/src/queries/viewer.graphql: -------------------------------------------------------------------------------- 1 | query viewer { 2 | viewer { 3 | user { 4 | name 5 | phoneNumber 6 | query { 7 | jsonEncoding 8 | } 9 | ...userFragment @defer 10 | } 11 | } 12 | } 13 | 14 | fragment userFragment on User { 15 | likes 16 | } 17 | -------------------------------------------------------------------------------- /integration/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true 21 | }, 22 | "include": ["src"] 23 | } 24 | -------------------------------------------------------------------------------- /internal/code/testdata/a/a.go: -------------------------------------------------------------------------------- 1 | package a 2 | 3 | var A = "A" 4 | -------------------------------------------------------------------------------- /internal/code/testdata/b/b.go: -------------------------------------------------------------------------------- 1 | package b 2 | 3 | import "github.com/99designs/gqlgen/internal/code/testdata/a" 4 | 5 | var B = a.A + " B" 6 | -------------------------------------------------------------------------------- /internal/code/testdata/c/c.go: -------------------------------------------------------------------------------- 1 | package c 2 | 3 | import ( 4 | "github.com/99designs/gqlgen/internal/code/testdata/b" 5 | ) 6 | 7 | var C = b.B + " C" 8 | -------------------------------------------------------------------------------- /internal/code/testdata/p/p.go: -------------------------------------------------------------------------------- 1 | //go:build private 2 | 3 | // This file is excluded from the build unless the "private" build tag is set. 4 | // This is used to test loading private packages. 5 | // See internal/code/packages_test.go for more details. 6 | package p 7 | 8 | import ( 9 | "github.com/99designs/gqlgen/internal/code/testdata/b" 10 | ) 11 | 12 | var P = b.C + " P" 13 | -------------------------------------------------------------------------------- /internal/code/util_test.go: -------------------------------------------------------------------------------- 1 | package code 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestNormalizeVendor(t *testing.T) { 10 | require.Equal(t, "bar/baz", NormalizeVendor("foo/vendor/bar/baz")) 11 | require.Equal(t, "[]bar/baz", NormalizeVendor("[]foo/vendor/bar/baz")) 12 | require.Equal(t, "*bar/baz", NormalizeVendor("*foo/vendor/bar/baz")) 13 | require.Equal(t, "*[]*bar/baz", NormalizeVendor("*[]*foo/vendor/bar/baz")) 14 | require.Equal(t, "[]*bar/baz", NormalizeVendor("[]*foo/vendor/bar/baz")) 15 | } 16 | -------------------------------------------------------------------------------- /internal/imports/prune_test.go: -------------------------------------------------------------------------------- 1 | package imports 2 | 3 | import ( 4 | "os" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/require" 9 | 10 | "github.com/99designs/gqlgen/internal/code" 11 | ) 12 | 13 | func TestPrune(t *testing.T) { 14 | // prime the packages cache so that it's not considered uninitialized 15 | 16 | b, err := Prune("testdata/unused.go", mustReadFile("testdata/unused.go"), code.NewPackages()) 17 | require.NoError(t, err) 18 | require.Equal(t, strings.ReplaceAll(string(mustReadFile("testdata/unused.expected.go")), "\r\n", "\n"), string(b)) 19 | } 20 | 21 | func mustReadFile(filename string) []byte { 22 | b, err := os.ReadFile(filename) 23 | if err != nil { 24 | panic(err) 25 | } 26 | return b 27 | } 28 | -------------------------------------------------------------------------------- /internal/imports/testdata/unused.expected.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | a "fmt" 5 | "time" 6 | 7 | _ "underscore" 8 | ) 9 | 10 | type foo struct { 11 | Time time.Time `json:"text"` 12 | } 13 | 14 | func fn() { 15 | a.Println("hello") 16 | } 17 | 18 | type Message struct { 19 | ID string `json:"id"` 20 | Text string `json:"text"` 21 | CreatedBy string `json:"createdBy"` 22 | CreatedAt time.Time `json:"createdAt"` 23 | } 24 | -------------------------------------------------------------------------------- /internal/imports/testdata/unused.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | a "fmt" 5 | "time" 6 | 7 | _ "underscore" 8 | ) 9 | 10 | type foo struct { 11 | Time time.Time `json:"text"` 12 | } 13 | 14 | func fn() { 15 | a.Println("hello") 16 | } 17 | 18 | type Message struct { 19 | ID string `json:"id"` 20 | Text string `json:"text"` 21 | CreatedBy string `json:"createdBy"` 22 | CreatedAt time.Time `json:"createdAt"` 23 | } 24 | -------------------------------------------------------------------------------- /internal/rewrite/testdata/example.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | lol "bytes" 5 | "fmt" 6 | ) 7 | 8 | type Foo struct { 9 | Field int 10 | } 11 | 12 | func (m *Foo) Method(arg int) { 13 | // leading comment 14 | 15 | // field comment 16 | m.Field++ 17 | 18 | // trailing comment 19 | } 20 | 21 | func (m *Foo) String() string { 22 | var buf lol.Buffer 23 | buf.WriteString(fmt.Sprintf("%d", m.Field)) 24 | return buf.String() 25 | } 26 | -------------------------------------------------------------------------------- /internal/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | 3 | package main 4 | 5 | import ( 6 | _ "github.com/matryer/moq" 7 | ) 8 | -------------------------------------------------------------------------------- /plugin/federation/fedruntime/runtime.go: -------------------------------------------------------------------------------- 1 | package fedruntime 2 | 3 | // Service is the service object that the 4 | // generated.go file will return for the _service 5 | // query 6 | type Service struct { 7 | SDL string `json:"sdl"` 8 | } 9 | 10 | // Everything with a @key implements this 11 | type Entity interface { 12 | IsEntity() 13 | } 14 | 15 | // Used for the Link directive 16 | type Link any 17 | -------------------------------------------------------------------------------- /plugin/federation/requires.gotpl: -------------------------------------------------------------------------------- 1 | {{ range .ExistingImports }} 2 | {{ if ne .Alias "" }} 3 | {{ reserveImport .ImportPath .Alias }} 4 | {{ else }} 5 | {{ reserveImport .ImportPath }} 6 | {{ end }} 7 | {{ end }} 8 | 9 | {{ range .Populators -}} 10 | {{ if .Comment -}} 11 | // {{.Comment}} 12 | {{- else -}} 13 | // {{.FuncName}} is the requires populator for the {{.Entity.Def.Name}} entity. 14 | {{- end }} 15 | func (ec *executionContext) {{.FuncName}}(ctx context.Context, entity *{{.Entity.GetTypeInfo}}, reps map[string]any) error { 16 | {{.Implementation}} 17 | } 18 | {{ end }} 19 | 20 | {{ .OriginalSource }} 21 | -------------------------------------------------------------------------------- /plugin/federation/test_data/model2/federation.go: -------------------------------------------------------------------------------- 1 | package model2 2 | 3 | type FieldSet string 4 | 5 | type Hello struct { 6 | Name string 7 | Secondary string 8 | } 9 | 10 | func (Hello) IsEntity() {} 11 | 12 | type World struct { 13 | Foo string 14 | Bar int 15 | } 16 | 17 | func (World) IsEntity() {} 18 | 19 | type ExternalExtension struct { 20 | UPC string 21 | Reviews []*World 22 | } 23 | 24 | func (ExternalExtension) IsEntity() {} 25 | 26 | type NestedKey struct { 27 | ID string 28 | Hello *Hello 29 | } 30 | 31 | func (NestedKey) IsEntity() {} 32 | 33 | type MoreNesting struct { 34 | ID string 35 | World *World 36 | } 37 | 38 | func (MoreNesting) IsEntity() {} 39 | 40 | type VeryNestedKey struct { 41 | ID string 42 | Hello *Hello 43 | World *World 44 | Nested *NestedKey 45 | More *MoreNesting 46 | } 47 | 48 | func (VeryNestedKey) IsEntity() {} 49 | -------------------------------------------------------------------------------- /plugin/federation/testdata/allthethings/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/allthethings/schema.graphql" 3 | exec: 4 | filename: testdata/allthethings/generated/exec.go 5 | federation: 6 | filename: testdata/allthethings/generated/federation.go 7 | 8 | autobind: 9 | - "github.com/99designs/gqlgen/plugin/federation/testdata/allthethings/model" 10 | -------------------------------------------------------------------------------- /plugin/federation/testdata/computedrequires/errors.go: -------------------------------------------------------------------------------- 1 | package computedrequires 2 | 3 | import "errors" 4 | 5 | // Errors defined for retained code that we want to stick around between generations. 6 | var ( 7 | ErrResolvingHelloWithErrorsByName = errors.New("error resolving HelloWithErrorsByName") 8 | ErrEmptyKeyResolvingHelloWithErrorsByName = errors.New("error (empty key) resolving HelloWithErrorsByName") 9 | ) 10 | -------------------------------------------------------------------------------- /plugin/federation/testdata/computedrequires/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/computedrequires/schema.graphql" 3 | exec: 4 | filename: testdata/computedrequires/generated/exec.go 5 | package: generated 6 | federation: 7 | filename: testdata/computedrequires/generated/federation.go 8 | package: generated 9 | version: 2 10 | options: 11 | computed_requires: true 12 | model: 13 | package: model 14 | filename: testdata/computedrequires/generated/models/models.go 15 | resolver: 16 | filename: testdata/computedrequires/resolver.go 17 | layout: follow-schema 18 | dir: testdata/computedrequires 19 | package: computedrequires 20 | 21 | omit_complexity: true 22 | call_argument_directives_with_null: true 23 | -------------------------------------------------------------------------------- /plugin/federation/testdata/computedrequires/resolver.go: -------------------------------------------------------------------------------- 1 | package computedrequires 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type Resolver struct{} 8 | -------------------------------------------------------------------------------- /plugin/federation/testdata/entities/nokey.graphql: -------------------------------------------------------------------------------- 1 | type Hello { 2 | name: String! 3 | } 4 | 5 | type Query { 6 | hello: Hello! 7 | } 8 | 9 | -------------------------------------------------------------------------------- /plugin/federation/testdata/entities/nokey.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/entities/nokey.graphql" 3 | exec: 4 | filename: testdata/entities/generated/exec.go 5 | federation: 6 | filename: testdata/entities/generated/federation.go 7 | 8 | autobind: 9 | - "github.com/99designs/gqlgen/plugin/federation/test_data/model" 10 | -------------------------------------------------------------------------------- /plugin/federation/testdata/entityinterfaces/generated/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package generated 4 | 5 | type Hello interface { 6 | IsEntity() 7 | IsHello() 8 | GetID() string 9 | GetTitle() string 10 | } 11 | 12 | type Query struct { 13 | } 14 | 15 | type World struct { 16 | ID string `json:"id"` 17 | Title string `json:"title"` 18 | } 19 | 20 | func (World) IsHello() {} 21 | func (this World) GetID() string { return this.ID } 22 | func (this World) GetTitle() string { return this.Title } 23 | 24 | func (World) IsEntity() {} 25 | -------------------------------------------------------------------------------- /plugin/federation/testdata/entityinterfaces/interface.graphql: -------------------------------------------------------------------------------- 1 | extend schema 2 | @link(url: "https://specs.apollo.dev/federation/v2.3", 3 | import: ["@key"]) 4 | 5 | interface Hello @key(fields: "id"){ 6 | id: String! 7 | title: String! 8 | } 9 | 10 | type World implements Hello @key(fields: "id") { 11 | id: String! 12 | title: String! 13 | } -------------------------------------------------------------------------------- /plugin/federation/testdata/entityinterfaces/interface.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/entityinterfaces/interface.graphql" 3 | exec: 4 | filename: testdata/entityinterfaces/generated/exec.go 5 | federation: 6 | filename: testdata/entityinterfaces/generated/federation.go 7 | version: 2 8 | model: 9 | filename: testdata/entityinterfaces/generated/models_gen.go -------------------------------------------------------------------------------- /plugin/federation/testdata/entityresolver/generated/errors.go: -------------------------------------------------------------------------------- 1 | package generated 2 | 3 | import "errors" 4 | 5 | // Errors defined for retained code that we want to stick around between generations. 6 | var ( 7 | ErrResolvingHelloWithErrorsByName = errors.New("error resolving HelloWithErrorsByName") 8 | ErrEmptyKeyResolvingHelloWithErrorsByName = errors.New("error (empty key) resolving HelloWithErrorsByName") 9 | ) 10 | -------------------------------------------------------------------------------- /plugin/federation/testdata/entityresolver/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/entityresolver/schema.graphql" 3 | exec: 4 | filename: testdata/entityresolver/generated/exec.go 5 | federation: 6 | filename: testdata/entityresolver/generated/federation.go 7 | model: 8 | filename: testdata/entityresolver/generated/model/models.go 9 | package: model 10 | resolver: 11 | filename: testdata/entityresolver/resolver.go 12 | layout: follow-schema 13 | dir: testdata/entityresolver 14 | package: entityresolver 15 | -------------------------------------------------------------------------------- /plugin/federation/testdata/entityresolver/resolver.go: -------------------------------------------------------------------------------- 1 | package entityresolver 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type Resolver struct{} 8 | 9 | // FindWorldWithMultipleKeysByHelloNameAndFooBarValue shows we hit the FindWorldWithMultipleKeysByHelloNameAndFoo resolver 10 | const FindWorldWithMultipleKeysByHelloNameAndFooBarValue = 99 11 | -------------------------------------------------------------------------------- /plugin/federation/testdata/entityresolver/schema.resolvers.go: -------------------------------------------------------------------------------- 1 | package entityresolver 2 | 3 | // This file will be automatically regenerated based on the schema, any resolver implementations 4 | // will be copied through when generating and any unknown code will be moved to the end. 5 | -------------------------------------------------------------------------------- /plugin/federation/testdata/explicitrequires/generated/errors.go: -------------------------------------------------------------------------------- 1 | package generated 2 | 3 | import "errors" 4 | 5 | // Errors defined for retained code that we want to stick around between generations. 6 | var ( 7 | ErrResolvingHelloWithErrorsByName = errors.New("error resolving HelloWithErrorsByName") 8 | ErrEmptyKeyResolvingHelloWithErrorsByName = errors.New("error (empty key) resolving HelloWithErrorsByName") 9 | ) 10 | -------------------------------------------------------------------------------- /plugin/federation/testdata/explicitrequires/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/explicitrequires/schema.graphql" 3 | exec: 4 | filename: testdata/explicitrequires/generated/exec.go 5 | federation: 6 | filename: testdata/explicitrequires/generated/federation.go 7 | options: 8 | explicit_requires: true 9 | model: 10 | filename: testdata/explicitrequires/generated/models.go 11 | resolver: 12 | filename: testdata/explicitrequires/resolver.go 13 | layout: follow-schema 14 | dir: testdata/explicitrequires 15 | package: explicitrequires 16 | omit_complexity: true 17 | -------------------------------------------------------------------------------- /plugin/federation/testdata/explicitrequires/resolver.go: -------------------------------------------------------------------------------- 1 | package explicitrequires 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type Resolver struct{} 8 | -------------------------------------------------------------------------------- /plugin/federation/testdata/explicitrequires/schema.resolvers.go: -------------------------------------------------------------------------------- 1 | package explicitrequires 2 | 3 | // This file will be automatically regenerated based on the schema, any resolver implementations 4 | // will be copied through when generating and any unknown code will be moved to the end. 5 | -------------------------------------------------------------------------------- /plugin/federation/testdata/federation2/federation2.graphql: -------------------------------------------------------------------------------- 1 | extend schema 2 | @link(url: "https://specs.apollo.dev/federation/v2.7", 3 | import: ["@key", "@shareable", "@provides", "@external", "@tag", "@extends", "@override", "@inaccessible", "@interfaceObject", "@policy"]) 4 | 5 | schema { 6 | query: CustomQuery 7 | } 8 | 9 | type Hello @key(fields:"name", resolvable: false) { 10 | name: String! @override(from: "old-service", label: "percent(5)") 11 | } 12 | 13 | type World @key(fields: "foo bar", resolvable: false) { 14 | foo: String! 15 | bar: Int! 16 | } 17 | 18 | extend type ExternalExtension @key(fields: " upc ") { 19 | upc: String! 20 | reviews: [Hello] 21 | } 22 | 23 | type CustomQuery { 24 | hello: Hello! 25 | } 26 | -------------------------------------------------------------------------------- /plugin/federation/testdata/federation2/federation2.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/federation2/federation2.graphql" 3 | exec: 4 | filename: testdata/federation2/generated/exec.go 5 | federation: 6 | filename: testdata/federation2/generated/federation.go 7 | version: 2 8 | 9 | autobind: 10 | - "github.com/99designs/gqlgen/plugin/federation/test_data/model2" 11 | -------------------------------------------------------------------------------- /plugin/federation/testdata/interfaces/extends.graphqls: -------------------------------------------------------------------------------- 1 | interface Hello @extends { 2 | name: String! 3 | secondary: String! 4 | } 5 | 6 | extend type World implements Hello @key(fields: "name") { 7 | name: String! @external 8 | secondary: String! 9 | 10 | tertiary: String! 11 | } 12 | -------------------------------------------------------------------------------- /plugin/federation/testdata/interfaces/extends.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/interfaces/extends.graphqls" 3 | exec: 4 | filename: testdata/interfaces/generated/exec.go 5 | federation: 6 | filename: testdata/interfaces/generated/federation.go 7 | -------------------------------------------------------------------------------- /plugin/federation/testdata/interfaces/key.graphqls: -------------------------------------------------------------------------------- 1 | extend interface Hello @key(fields: "name") { 2 | name: String! 3 | secondary: String! 4 | } 5 | 6 | type World implements Hello @key(fields: "name") { 7 | name: String! 8 | secondary: String! 9 | } 10 | -------------------------------------------------------------------------------- /plugin/federation/testdata/interfaces/key.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/interfaces/key.graphqls" 3 | exec: 4 | filename: testdata/interfaces/generated/exec.go 5 | federation: 6 | filename: testdata/interfaces/generated/federation.go 7 | -------------------------------------------------------------------------------- /plugin/federation/testdata/interfaces/unused_key.graphqls: -------------------------------------------------------------------------------- 1 | extend interface Hello @key(fields: "name") { 2 | name: String! 3 | secondary: String! 4 | } 5 | -------------------------------------------------------------------------------- /plugin/federation/testdata/interfaces/unused_key.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/interfaces/unused_key.graphqls" 3 | exec: 4 | filename: testdata/interfaces/generated/exec.go 5 | federation: 6 | filename: testdata/interfaces/generated/federation.go 7 | -------------------------------------------------------------------------------- /plugin/federation/testdata/multi/multi.graphqls: -------------------------------------------------------------------------------- 1 | extend schema 2 | @link(url: "https://specs.apollo.dev/federation/v2.7", 3 | import: ["@key"]) 4 | 5 | directive @entityResolver(multi: Boolean) on OBJECT 6 | 7 | type Hello @key(fields: "name") @entityResolver(multi: true) { 8 | name: String! 9 | secondary: String! 10 | } 11 | -------------------------------------------------------------------------------- /plugin/federation/testdata/multi/multi.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/multi/multi.graphqls" 3 | exec: 4 | filename: testdata/multi/generated/exec.go 5 | federation: 6 | version: 2 7 | filename: testdata/multi/generated/federation.go 8 | omit_slice_element_pointers: true -------------------------------------------------------------------------------- /plugin/federation/testdata/schema/customquerytype.graphql: -------------------------------------------------------------------------------- 1 | schema { 2 | query: CustomQuery 3 | } 4 | 5 | type Hello { 6 | name: String! 7 | } 8 | 9 | type CustomQuery { 10 | hello: Hello! 11 | } 12 | 13 | -------------------------------------------------------------------------------- /plugin/federation/testdata/schema/customquerytype.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema/customquerytype.graphql" 3 | exec: 4 | filename: testdata/schema/generated/exec.go 5 | federation: 6 | filename: testdata/schema/generated/federation.go 7 | 8 | autobind: 9 | - "github.com/99designs/gqlgen/plugin/federation/test_data/model" 10 | -------------------------------------------------------------------------------- /plugin/federation/testdata/usefunctionsyntaxforexecutioncontext/generated/errors.go: -------------------------------------------------------------------------------- 1 | package generated 2 | 3 | import "errors" 4 | 5 | // Errors defined for retained code that we want to stick around between generations. 6 | var ( 7 | ErrResolvingHelloWithErrorsByName = errors.New("error resolving HelloWithErrorsByName") 8 | ErrEmptyKeyResolvingHelloWithErrorsByName = errors.New("error (empty key) resolving HelloWithErrorsByName") 9 | ) 10 | -------------------------------------------------------------------------------- /plugin/federation/testdata/usefunctionsyntaxforexecutioncontext/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/usefunctionsyntaxforexecutioncontext/schema.graphql" 3 | use_function_syntax_for_execution_context: true 4 | exec: 5 | filename: testdata/usefunctionsyntaxforexecutioncontext/generated/exec.go 6 | federation: 7 | filename: testdata/usefunctionsyntaxforexecutioncontext/generated/federation.go 8 | model: 9 | filename: testdata/usefunctionsyntaxforexecutioncontext/generated/model/models.go 10 | package: model 11 | resolver: 12 | filename: testdata/usefunctionsyntaxforexecutioncontext/resolver.go 13 | layout: follow-schema 14 | dir: testdata/usefunctionsyntaxforexecutioncontext 15 | package: usefunctionsyntaxforexecutioncontext 16 | -------------------------------------------------------------------------------- /plugin/federation/testdata/usefunctionsyntaxforexecutioncontext/resolver.go: -------------------------------------------------------------------------------- 1 | package usefunctionsyntaxforexecutioncontext 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type Resolver struct{} 8 | 9 | // FindWorldWithMultipleKeysByHelloNameAndFooBarValue shows we hit the FindWorldWithMultipleKeysByHelloNameAndFoo resolver 10 | const FindWorldWithMultipleKeysByHelloNameAndFooBarValue = 99 11 | -------------------------------------------------------------------------------- /plugin/federation/testdata/usefunctionsyntaxforexecutioncontext/schema.resolvers.go: -------------------------------------------------------------------------------- 1 | package usefunctionsyntaxforexecutioncontext 2 | 3 | // This file will be automatically regenerated based on the schema, any resolver implementations 4 | // will be copied through when generating and any unknown code will be moved to the end. 5 | -------------------------------------------------------------------------------- /plugin/modelgen/internal/extrafields/types.go: -------------------------------------------------------------------------------- 1 | package extrafields 2 | 3 | type Type struct{} 4 | -------------------------------------------------------------------------------- /plugin/modelgen/out/existing.go: -------------------------------------------------------------------------------- 1 | package out 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/out_enable_model_json_omitempty_tag_false/existing.go: -------------------------------------------------------------------------------- 1 | package out_enable_model_json_omitempty_tag_false 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/out_enable_model_json_omitempty_tag_false_omitzero_tag_false/existing.go: -------------------------------------------------------------------------------- 1 | package out_enable_model_json_omitempty_tag_false_omitzero_tag_false 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/out_enable_model_json_omitempty_tag_false_omitzero_tag_nil/existing.go: -------------------------------------------------------------------------------- 1 | package out_enable_model_json_omitempty_tag_false_omitzero_tag_nil 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/out_enable_model_json_omitempty_tag_false_omitzero_tag_true/existing.go: -------------------------------------------------------------------------------- 1 | package out_enable_model_json_omitempty_tag_false_omitzero_tag_true 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/out_enable_model_json_omitempty_tag_nil/existing.go: -------------------------------------------------------------------------------- 1 | package out_enable_model_json_omitempty_tag_nil 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/out_enable_model_json_omitempty_tag_true/existing.go: -------------------------------------------------------------------------------- 1 | package out_enable_model_json_omitempty_tag_true 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/out_enable_model_json_omitzero_tag_false/existing.go: -------------------------------------------------------------------------------- 1 | package out_enable_model_json_omitzero_tag_false 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/out_enable_model_json_omitzero_tag_nil/existing.go: -------------------------------------------------------------------------------- 1 | package out_enable_model_json_omitzero_tag_nil 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/out_enable_model_json_omitzero_tag_true/existing.go: -------------------------------------------------------------------------------- 1 | package out_enable_model_json_omitzero_tag_true 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/out_nullable_input_omittable/existing.go: -------------------------------------------------------------------------------- 1 | package out_nullable_input_omittable 2 | 3 | import ( 4 | "github.com/99designs/gqlgen/graphql" 5 | ) 6 | 7 | type ExistingType struct { 8 | Name *string `json:"name"` 9 | Enum *ExistingEnum `json:"enum"` 10 | Int ExistingInterface `json:"int"` 11 | Existing *MissingTypeNullable `json:"existing"` 12 | } 13 | 14 | type ExistingModel struct { 15 | Name string 16 | Enum ExistingEnum 17 | Int ExistingInterface 18 | } 19 | 20 | type ExistingInput struct { 21 | Name graphql.Omittable[string] 22 | Enum graphql.Omittable[ExistingEnum] 23 | Int graphql.Omittable[ExistingInterface] 24 | } 25 | 26 | type ExistingEnum string 27 | 28 | type ExistingInterface interface { 29 | IsExistingInterface() 30 | } 31 | 32 | type ExistingUnion interface { 33 | IsExistingUnion() 34 | } 35 | -------------------------------------------------------------------------------- /plugin/modelgen/out_omit_resolver_fields/generated.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package out_omit_resolver_fields 4 | 5 | type Base struct { 6 | StandardField string `json:"StandardField" database:"BaseStandardField"` 7 | } 8 | 9 | type Query struct { 10 | } 11 | -------------------------------------------------------------------------------- /plugin/modelgen/out_struct_pointers/existing.go: -------------------------------------------------------------------------------- 1 | package out_struct_pointers 2 | 3 | type ExistingType struct { 4 | Name *string `json:"name"` 5 | Enum *ExistingEnum `json:"enum"` 6 | Int ExistingInterface `json:"int"` 7 | Existing *MissingTypeNullable `json:"existing"` 8 | } 9 | 10 | type ExistingModel struct { 11 | Name string 12 | Enum ExistingEnum 13 | Int ExistingInterface 14 | } 15 | 16 | type ExistingInput struct { 17 | Name string 18 | Enum ExistingEnum 19 | Int ExistingInterface 20 | } 21 | 22 | type ExistingEnum string 23 | 24 | type ExistingInterface interface { 25 | IsExistingInterface() 26 | } 27 | 28 | type ExistingUnion interface { 29 | IsExistingUnion() 30 | } 31 | -------------------------------------------------------------------------------- /plugin/modelgen/testdata/gqlgen_omit_resolver_fields.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema_omit_resolver_fields.graphql" 3 | 4 | exec: 5 | filename: out_omit_resolver_fields/ignored.go 6 | model: 7 | filename: out_omit_resolver_fields/generated.go 8 | 9 | omit_resolver_fields: true 10 | -------------------------------------------------------------------------------- /plugin/modelgen/testdata/gqlgen_omit_root_models.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema_omit_root_models.graphql" 3 | 4 | exec: 5 | filename: out/ignored.go 6 | model: 7 | filename: out/generated_omit_root_models.go 8 | 9 | omit_root_models: true 10 | -------------------------------------------------------------------------------- /plugin/modelgen/testdata/schema_omit_resolver_fields.graphql: -------------------------------------------------------------------------------- 1 | directive @goTag( 2 | key: String! 3 | value: String 4 | ) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION 5 | 6 | directive @goField( 7 | forceResolver: Boolean 8 | name: String 9 | omittable: Boolean 10 | type: String 11 | ) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION | INTERFACE 12 | 13 | type Base { 14 | StandardField: String! 15 | ResolverField: String! @goField(forceResolver: true) 16 | } 17 | -------------------------------------------------------------------------------- /plugin/modelgen/testdata/schema_omit_root_models.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | thisShoudlntGetGenerated: Boolean 3 | } 4 | 5 | type Mutation { 6 | thisShoudlntGetGenerated: Boolean 7 | } 8 | 9 | type Subscription { 10 | thisShoudlntGetGenerated: Boolean 11 | } 12 | 13 | enum SomeContent { 14 | This 15 | Is 16 | A 17 | Test 18 | } 19 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/filetemplate/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema.graphql" 3 | 4 | exec: 5 | filename: testdata/singlefile/out/ignored.go 6 | model: 7 | filename: testdata/singlefile/out/generated.go 8 | resolver: 9 | type: CustomResolverType 10 | layout: follow-schema 11 | dir: testdata/filetemplate/out 12 | filename_template: "{name}.custom.go" 13 | 14 | models: 15 | Resolver: 16 | model: github.com/99designs/gqlgen/plugin/resolvergen/testdata/singlefile/out.Resolver 17 | 18 | omit_gqlgen_version_in_file_notice: true 19 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/filetemplate/out/model.go: -------------------------------------------------------------------------------- 1 | package customresolver 2 | 3 | import "context" 4 | 5 | type Resolver struct{} 6 | 7 | type QueryResolver interface { 8 | Resolver(ctx context.Context) (*Resolver, error) 9 | } 10 | 11 | type ResolverResolver interface { 12 | Name(ctx context.Context, obj *Resolver) (string, error) 13 | } 14 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/filetemplate/out/resolver.go: -------------------------------------------------------------------------------- 1 | package customresolver 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type CustomResolverType struct{} 8 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/followschema/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema.graphql" 3 | 4 | exec: 5 | filename: testdata/singlefile/out/ignored.go 6 | model: 7 | filename: testdata/singlefile/out/generated.go 8 | resolver: 9 | type: CustomResolverType 10 | layout: follow-schema 11 | dir: testdata/followschema/out 12 | 13 | models: 14 | Resolver: 15 | model: github.com/99designs/gqlgen/plugin/resolvergen/testdata/singlefile/out.Resolver 16 | 17 | omit_gqlgen_version_in_file_notice: true 18 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/followschema/out/model.go: -------------------------------------------------------------------------------- 1 | package customresolver 2 | 3 | import "context" 4 | 5 | type Resolver struct{} 6 | 7 | type QueryResolver interface { 8 | Resolver(ctx context.Context) (*Resolver, error) 9 | } 10 | 11 | type ResolverResolver interface { 12 | Name(ctx context.Context, obj *Resolver) (string, error) 13 | } 14 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/followschema/out/resolver.go: -------------------------------------------------------------------------------- 1 | package customresolver 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type CustomResolverType struct{} 8 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/invalid_model_path/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema.graphql" 3 | 4 | models: 5 | Resolver: 6 | model: github.com/99designs/invalid/invalid/invalid/nope.Resolver 7 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/omit_template_comment/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema.graphql" 3 | 4 | exec: 5 | filename: testdata/singlefile/out/ignored.go 6 | model: 7 | filename: testdata/singlefile/out/generated.go 8 | resolver: 9 | type: CustomResolverType 10 | layout: follow-schema 11 | dir: testdata/omit_template_comment/out 12 | omit_template_comment: true 13 | 14 | models: 15 | Resolver: 16 | model: github.com/99designs/gqlgen/plugin/resolvergen/testdata/singlefile/out.Resolver 17 | 18 | omit_gqlgen_version_in_file_notice: true 19 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/omit_template_comment/out/resolver.go: -------------------------------------------------------------------------------- 1 | package out 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type CustomResolverType struct{} 8 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/resolver_implementor/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema.graphql" 3 | 4 | exec: 5 | filename: testdata/resolver_implementor/out/ignored.go 6 | model: 7 | filename: testdata/resolver_implementor/out/generated.go 8 | resolver: 9 | type: CustomResolverType 10 | layout: follow-schema 11 | dir: testdata/resolver_implementor/out 12 | 13 | models: 14 | Resolver: 15 | model: github.com/99designs/gqlgen/plugin/resolvergen/testdata/resolver_implementor/out.Resolver 16 | 17 | omit_gqlgen_version_in_file_notice: true 18 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/resolver_implementor/out/model.go: -------------------------------------------------------------------------------- 1 | package customresolver 2 | 3 | import "context" 4 | 5 | type Resolver struct{} 6 | 7 | type QueryResolver interface { 8 | Resolver(ctx context.Context) (*Resolver, error) 9 | } 10 | 11 | type ResolverResolver interface { 12 | Name(ctx context.Context, obj *Resolver) (string, error) 13 | } 14 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/resolver_implementor/out/resolver.go: -------------------------------------------------------------------------------- 1 | package customresolver 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type CustomResolverType struct{} 8 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/resolvertemplate/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema.graphql" 3 | 4 | exec: 5 | filename: testdata/singlefile/out/ignored.go 6 | model: 7 | filename: testdata/singlefile/out/generated.go 8 | resolver: 9 | type: CustomResolverType 10 | layout: follow-schema 11 | dir: testdata/resolvertemplate/out 12 | filename_template: "{name}.resolvers.go" 13 | resolver_template: "testdata/resolvertemplate/customResolverTemplate.gotpl" 14 | 15 | models: 16 | Resolver: 17 | model: github.com/99designs/gqlgen/plugin/resolvergen/testdata/singlefile/out.Resolver 18 | 19 | omit_gqlgen_version_in_file_notice: true 20 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/resolvertemplate/out/resolver.go: -------------------------------------------------------------------------------- 1 | package out 2 | 3 | // This file will not be regenerated automatically. 4 | // 5 | // It serves as dependency injection for your app, add any dependencies you require here. 6 | 7 | type CustomResolverType struct{} 8 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/return_values/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - schema.graphqls 3 | 4 | exec: 5 | filename: ignored.go 6 | model: 7 | filename: model.go 8 | resolver: 9 | filename: resolvers.go 10 | 11 | resolvers_always_return_pointers: false 12 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/return_values/model.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package return_values 4 | 5 | type User struct { 6 | ID string `json:"id"` 7 | Name string `json:"name"` 8 | } 9 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/return_values/resolvers.go: -------------------------------------------------------------------------------- 1 | package return_values 2 | 3 | // THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES. 4 | 5 | import ( 6 | "context" 7 | ) 8 | 9 | type Resolver struct{} 10 | 11 | // // foo 12 | func (r *queryResolver) User(ctx context.Context) (User, error) { 13 | panic("not implemented") 14 | } 15 | 16 | // // foo 17 | func (r *queryResolver) UserPointer(ctx context.Context) (*User, error) { 18 | panic("not implemented") 19 | } 20 | 21 | // Query returns QueryResolver implementation. 22 | func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } 23 | 24 | type queryResolver struct{ *Resolver } 25 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/return_values/return_values_test.go: -------------------------------------------------------------------------------- 1 | package return_values 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | //go:generate rm -f resolvers.go 11 | //go:generate go run ../../../../testdata/gqlgen.go -config gqlgen.yml 12 | 13 | func TestResolverReturnTypes(t *testing.T) { 14 | // verify that the return value of the User resolver is a struct, not a pointer 15 | require.Equal(t, "struct", reflect.TypeOf((&queryResolver{}).User).Out(0).Kind().String()) 16 | // the UserPointer resolver should return a pointer 17 | require.Equal(t, "ptr", reflect.TypeOf((&queryResolver{}).UserPointer).Out(0).Kind().String()) 18 | } 19 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/return_values/schema.graphqls: -------------------------------------------------------------------------------- 1 | type User { 2 | id: ID! 3 | name: String! 4 | } 5 | 6 | type Query { 7 | user: User! 8 | userPointer: User 9 | } 10 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/schema.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | resolver: Resolver! 3 | } 4 | 5 | type Resolver { 6 | name: String! 7 | } 8 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/singlefile/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema.graphql" 3 | 4 | exec: 5 | filename: testdata/singlefile/out/ignored.go 6 | model: 7 | filename: testdata/singlefile/out/generated.go 8 | resolver: 9 | filename: testdata/singlefile/out/resolver.go 10 | type: CustomResolverType 11 | preserve_resolver: false 12 | 13 | models: 14 | Resolver: 15 | model: github.com/99designs/gqlgen/plugin/resolvergen/testdata/singlefile/out.Resolver 16 | 17 | omit_gqlgen_version_in_file_notice: true 18 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/singlefile/out/model.go: -------------------------------------------------------------------------------- 1 | package customresolver 2 | 3 | import "context" 4 | 5 | type Resolver struct{} 6 | 7 | type QueryResolver interface { 8 | Resolver(ctx context.Context) (*Resolver, error) 9 | } 10 | 11 | type ResolverResolver interface { 12 | Name(ctx context.Context, obj *Resolver) (string, error) 13 | } 14 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/singlefile_preserve/gqlgen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - "testdata/schema.graphql" 3 | 4 | exec: 5 | filename: testdata/singlefile_preserve/out/ignored.go 6 | model: 7 | filename: testdata/singlefile_preserve/out/generated.go 8 | resolver: 9 | filename: testdata/singlefile_preserve/out/resolver.go 10 | type: CustomResolverType 11 | preserve_resolver: true 12 | 13 | models: 14 | Resolver: 15 | model: github.com/99designs/gqlgen/plugin/resolvergen/testdata/singlefile_preserve/out.Resolver 16 | 17 | omit_gqlgen_version_in_file_notice: true 18 | -------------------------------------------------------------------------------- /plugin/resolvergen/testdata/singlefile_preserve/out/model.go: -------------------------------------------------------------------------------- 1 | package customresolver 2 | 3 | import "context" 4 | 5 | type Resolver struct{} 6 | 7 | type QueryResolver interface { 8 | Resolver(ctx context.Context) (*Resolver, error) 9 | } 10 | 11 | type ResolverResolver interface { 12 | Name(ctx context.Context, obj *Resolver) (string, error) 13 | } 14 | -------------------------------------------------------------------------------- /testdata/gomod-with-leading-comments.mod: -------------------------------------------------------------------------------- 1 | // main module of gqlgen 2 | 3 | // and another module to test stripping of comment lines 4 | 5 | module github.com/99designs/gqlgen // replace it for new project 6 | 7 | go 1.18 8 | --------------------------------------------------------------------------------