├── .github
└── workflows
│ ├── codeql-analysis.yml
│ ├── v1.yml
│ └── v2.yml
├── .gitignore
├── .golangci.yml
├── LICENSE
├── Makefile
├── README.md
├── cmd
├── directiveUnmarshalCode.go
├── gen.go
└── root.go
├── doc.go
├── examples
├── chat
│ ├── .gitignore
│ ├── .gqlgen.yml
│ ├── chat_test.go
│ ├── generated.go
│ ├── go.mod
│ ├── go.sum
│ ├── handler.go
│ ├── models_gen.go
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ └── index.html
│ ├── readme.md
│ ├── resolvers.go
│ ├── schema.graphql
│ ├── server
│ │ └── server.go
│ ├── src
│ │ ├── App.js
│ │ ├── Room.js
│ │ ├── components
│ │ │ └── room.js
│ │ └── index.js
│ ├── start-server.sh
│ └── util.go
├── federation
│ ├── README.md
│ ├── accounts
│ │ ├── gqlgen.yml
│ │ ├── graph
│ │ │ ├── entity.resolvers.go
│ │ │ ├── generated
│ │ │ │ ├── federation.go
│ │ │ │ └── generated.go
│ │ │ ├── handler.go
│ │ │ ├── model
│ │ │ │ └── models_gen.go
│ │ │ ├── resolver.go
│ │ │ ├── schema.graphqls
│ │ │ └── schema.resolvers.go
│ │ └── server.go
│ ├── gateway
│ │ ├── datasource_poller.go
│ │ ├── gateway.go
│ │ ├── http
│ │ │ ├── handler.go
│ │ │ ├── http.go
│ │ │ └── ws.go
│ │ └── main.go
│ ├── go.mod
│ ├── go.sum
│ ├── products
│ │ ├── gqlgen.yml
│ │ ├── graph
│ │ │ ├── entity.resolvers.go
│ │ │ ├── generated
│ │ │ │ ├── federation.go
│ │ │ │ └── generated.go
│ │ │ ├── handler.go
│ │ │ ├── model
│ │ │ │ └── models_gen.go
│ │ │ ├── products.go
│ │ │ ├── resolver.go
│ │ │ ├── schema.graphqls
│ │ │ ├── schema.resolvers.go
│ │ │ └── variables.go
│ │ └── server.go
│ ├── reviews
│ │ ├── gqlgen.yml
│ │ ├── graph
│ │ │ ├── entity.resolvers.go
│ │ │ ├── generated
│ │ │ │ ├── federation.go
│ │ │ │ └── generated.go
│ │ │ ├── handler.go
│ │ │ ├── model
│ │ │ │ ├── models.go
│ │ │ │ └── models_gen.go
│ │ │ ├── resolver.go
│ │ │ ├── reviews.go
│ │ │ ├── schema.graphqls
│ │ │ └── schema.resolvers.go
│ │ └── server.go
│ └── start.sh
└── kafka_pubsub
│ ├── README.md
│ ├── docker-compose-cluster.yml
│ ├── docker-compose.yml
│ ├── go.mod
│ ├── go.sum
│ ├── kafka_jaas.conf
│ ├── main.go
│ ├── transactional_producer
│ ├── README.md
│ ├── go.mod
│ ├── go.sum
│ └── main.go
│ └── tyk-api-definition.json
├── go.mod
├── go.sum
├── internal
└── pkg
│ ├── quotes
│ ├── quotes.go
│ └── quotes_test.go
│ ├── unsafebytes
│ ├── unsafebytes.go
│ └── unsafebytes_test.go
│ ├── unsafeparser
│ └── unsafeparser.go
│ └── unsafeprinter
│ └── unsafeprinter.go
├── main.go
├── pkg
├── ast
│ ├── ast.go
│ ├── ast_argument.go
│ ├── ast_description.go
│ ├── ast_directive.go
│ ├── ast_directive_definition.go
│ ├── ast_enum_type_definition.go
│ ├── ast_enum_type_extension.go
│ ├── ast_enum_value_definition.go
│ ├── ast_field.go
│ ├── ast_field_alias.go
│ ├── ast_field_definition.go
│ ├── ast_fragment_definition.go
│ ├── ast_fragment_spread.go
│ ├── ast_inline_fragment.go
│ ├── ast_input_object_type_definition.go
│ ├── ast_input_object_type_extension.go
│ ├── ast_input_value_definition.go
│ ├── ast_interface_type_definition.go
│ ├── ast_interface_type_extension.go
│ ├── ast_node.go
│ ├── ast_node_kind.go
│ ├── ast_node_kind_test.go
│ ├── ast_object_field.go
│ ├── ast_object_type_definition.go
│ ├── ast_object_type_definition_test.go
│ ├── ast_object_type_extension.go
│ ├── ast_operation_definition.go
│ ├── ast_operation_definition_test.go
│ ├── ast_root_operation_type_definition.go
│ ├── ast_root_operation_type_definition_test.go
│ ├── ast_scalar_type_definition.go
│ ├── ast_scalar_type_extension.go
│ ├── ast_schema_definition.go
│ ├── ast_schema_extension.go
│ ├── ast_selection.go
│ ├── ast_string.go
│ ├── ast_test.go
│ ├── ast_type.go
│ ├── ast_type_test.go
│ ├── ast_union_type_definition.go
│ ├── ast_union_type_extension.go
│ ├── ast_val_boolean_value.go
│ ├── ast_val_enum_value.go
│ ├── ast_val_float_value.go
│ ├── ast_val_int_value.go
│ ├── ast_val_list_value.go
│ ├── ast_val_object_value.go
│ ├── ast_val_string_value.go
│ ├── ast_val_variable_value.go
│ ├── ast_value.go
│ ├── ast_value_test.go
│ ├── ast_variable_definition.go
│ ├── directive_location.go
│ ├── directive_location_string.go
│ ├── directive_location_test.go
│ ├── document_pool.go
│ ├── helpers.go
│ ├── index.go
│ ├── index_test.go
│ ├── input.go
│ └── path.go
├── astimport
│ ├── astimport.go
│ └── astimport_test.go
├── astnormalization
│ ├── astnormalization.go
│ ├── astnormalization_test.go
│ ├── definition_normalization.go
│ ├── definition_normalization_test.go
│ ├── directive_include_skip.go
│ ├── directive_include_skip_test.go
│ ├── enum_type_extending.go
│ ├── enum_type_extending_test.go
│ ├── extends_directive.go
│ ├── extends_directive_test.go
│ ├── field_deduplication.go
│ ├── field_deduplication_test.go
│ ├── field_selection_merging.go
│ ├── field_selection_merging_test.go
│ ├── fragment_definition_removal.go
│ ├── fragment_spread_inlining.go
│ ├── fragment_spread_inlining_test.go
│ ├── fragmentspread_depth.go
│ ├── fragmentspread_depth_test.go
│ ├── implicit_extend_root_operation.go
│ ├── implicit_extend_root_operation_test.go
│ ├── implicit_schema_definition.go
│ ├── implicit_schema_definition_test.go
│ ├── inject_input_default_values.go
│ ├── inject_input_default_values_test.go
│ ├── inline_fragment_merging.go
│ ├── inline_fragment_merging_test.go
│ ├── input_coercion_for_list.go
│ ├── input_coercion_for_list_test.go
│ ├── input_object_type_extending.go
│ ├── input_object_type_extending_test.go
│ ├── interface_type_extending.go
│ ├── interface_type_extending_test.go
│ ├── object_type_extending.go
│ ├── object_type_extending_test.go
│ ├── remove_self_aliasing.go
│ ├── remove_self_aliasing_test.go
│ ├── remove_type_extensions.go
│ ├── remove_type_extensions_test.go
│ ├── scalar_type_extending.go
│ ├── scalar_type_extending_test.go
│ ├── subgraph_sdl_normalization.go
│ ├── subgraph_sdl_normalization_test.go
│ ├── union_type_extending.go
│ ├── union_type_extending_test.go
│ ├── variables_default_value_extraction.go
│ ├── variables_default_value_extraction_test.go
│ ├── variables_extraction.go
│ ├── variables_extraction_test.go
│ ├── variables_unused_deletion.go
│ └── variables_unused_deletion_test.go
├── astparser
│ ├── errors.go
│ ├── parser.go
│ ├── parser_test.go
│ ├── parser_token_helpers.go
│ ├── testdata
│ │ ├── big_schema.graphql
│ │ ├── github.schema.graphql
│ │ ├── introspection_normalized.graphql
│ │ ├── introspectionquery.graphql
│ │ ├── starwars.schema.graphql
│ │ └── todo.graphql
│ └── tokenizer.go
├── astprinter
│ ├── astprinter.go
│ ├── astprinter_test.go
│ ├── fixtures
│ │ ├── introspectionquery.golden
│ │ └── starwars_schema_definition.golden
│ └── testdata
│ │ ├── introspectionquery.graphql
│ │ └── starwars.schema.graphql
├── asttransform
│ ├── asttransform.go
│ ├── baseschema.go
│ ├── baseschema_test.go
│ ├── fixtures
│ │ ├── complete.golden
│ │ ├── custom_query_name.golden
│ │ ├── mutation_only.golden
│ │ ├── schema_missing.golden
│ │ ├── simple.golden
│ │ ├── subscription_only.golden
│ │ ├── subscription_renamed.golden
│ │ └── with_mutation_subscription.golden
│ └── typename_visitor.go
├── astvalidation
│ ├── definition_validation.go
│ ├── definition_validation_test.go
│ ├── operation_rule_all_variable_uses_defined.go
│ ├── operation_rule_all_variables_used.go
│ ├── operation_rule_argument_uniqueness.go
│ ├── operation_rule_directives_defined.go
│ ├── operation_rule_directives_in_valid_locations.go
│ ├── operation_rule_directives_unique_per_location.go
│ ├── operation_rule_document_contains_executable_operation.go
│ ├── operation_rule_field_selection_merging.go
│ ├── operation_rule_fragments.go
│ ├── operation_rule_known_arguments.go
│ ├── operation_rule_lone_anonymous_operation.go
│ ├── operation_rule_operation_name_uniqueness.go
│ ├── operation_rule_required_arguments.go
│ ├── operation_rule_subscription_single_root_field.go
│ ├── operation_rule_valid_arguments.go
│ ├── operation_rule_validate_field_selections.go
│ ├── operation_rule_values.go
│ ├── operation_rule_variable_uniqueness.go
│ ├── operation_rule_variables_are_input_types.go
│ ├── operation_validation.go
│ ├── operation_validation_test.go
│ ├── overlapping_fields_test.go
│ ├── reference
│ │ ├── .gitignore
│ │ ├── __tests__
│ │ │ ├── ExecutableDefinitionsRule-test.js
│ │ │ ├── FieldsOnCorrectTypeRule-test.js
│ │ │ ├── FragmentsOnCompositeTypesRule-test.js
│ │ │ ├── KnownArgumentNamesRule-test.js
│ │ │ ├── KnownDirectivesRule-test.js
│ │ │ ├── KnownFragmentNamesRule-test.js
│ │ │ ├── KnownTypeNamesRule-test.js
│ │ │ ├── LoneAnonymousOperationRule-test.js
│ │ │ ├── LoneSchemaDefinitionRule-test.js
│ │ │ ├── NoDeprecatedCustomRule-test.js
│ │ │ ├── NoFragmentCyclesRule-test.js
│ │ │ ├── NoSchemaIntrospectionCustomRule-test.js
│ │ │ ├── NoUndefinedVariablesRule-test.js
│ │ │ ├── NoUnusedFragmentsRule-test.js
│ │ │ ├── NoUnusedVariablesRule-test.js
│ │ │ ├── OverlappingFieldsCanBeMergedRule-test.js
│ │ │ ├── PossibleFragmentSpreadsRule-test.js
│ │ │ ├── PossibleTypeExtensionsRule-test.js
│ │ │ ├── ProvidedRequiredArgumentsRule-test.js
│ │ │ ├── ScalarLeafsRule-test.js
│ │ │ ├── SingleFieldSubscriptionsRule-test.js
│ │ │ ├── UniqueArgumentNamesRule-test.js
│ │ │ ├── UniqueDirectiveNamesRule-test.js
│ │ │ ├── UniqueDirectivesPerLocationRule-test.js
│ │ │ ├── UniqueEnumValueNamesRule-test.js
│ │ │ ├── UniqueFieldDefinitionNamesRule-test.js
│ │ │ ├── UniqueFragmentNamesRule-test.js
│ │ │ ├── UniqueInputFieldNamesRule-test.js
│ │ │ ├── UniqueOperationNamesRule-test.js
│ │ │ ├── UniqueOperationTypesRule-test.js
│ │ │ ├── UniqueTypeNamesRule-test.js
│ │ │ ├── UniqueVariableNamesRule-test.js
│ │ │ ├── ValuesOfCorrectTypeRule-test.js
│ │ │ ├── VariablesAreInputTypesRule-test.js
│ │ │ ├── VariablesInAllowedPositionRule-test.js
│ │ │ ├── harness.js
│ │ │ └── validation-test.js
│ │ ├── gen.sh
│ │ ├── main.go
│ │ ├── replacements.yml
│ │ └── testsgo
│ │ │ ├── ExecutableDefinitionsRule_test.go
│ │ │ ├── FieldsOnCorrectTypeRule_test.go
│ │ │ ├── FragmentsOnCompositeTypesRule_test.go
│ │ │ ├── KnownArgumentNamesRule_test.go
│ │ │ ├── KnownDirectivesRule_test.go
│ │ │ ├── KnownFragmentNamesRule_test.go
│ │ │ ├── KnownTypeNamesRule_test.go
│ │ │ ├── LoneAnonymousOperationRule_test.go
│ │ │ ├── LoneSchemaDefinitionRule_test.go
│ │ │ ├── NoFragmentCyclesRule_test.go
│ │ │ ├── NoUndefinedVariablesRule_test.go
│ │ │ ├── NoUnusedFragmentsRule_test.go
│ │ │ ├── NoUnusedVariablesRule_test.go
│ │ │ ├── OverlappingFieldsCanBeMergedRule_test.go
│ │ │ ├── PossibleFragmentSpreadsRule_test.go
│ │ │ ├── PossibleTypeExtensionsRule_test.go
│ │ │ ├── ProvidedRequiredArgumentsRule_test.go
│ │ │ ├── ScalarLeafsRule_test.go
│ │ │ ├── SingleFieldSubscriptionsRule_test.go
│ │ │ ├── UniqueArgumentNamesRule_test.go
│ │ │ ├── UniqueDirectiveNamesRule_test.go
│ │ │ ├── UniqueDirectivesPerLocationRule_test.go
│ │ │ ├── UniqueEnumValueNamesRule_test.go
│ │ │ ├── UniqueFieldDefinitionNamesRule_test.go
│ │ │ ├── UniqueFragmentNamesRule_test.go
│ │ │ ├── UniqueInputFieldNamesRule_test.go
│ │ │ ├── UniqueOperationNamesRule_test.go
│ │ │ ├── UniqueOperationTypesRule_test.go
│ │ │ ├── UniqueTypeNamesRule_test.go
│ │ │ ├── UniqueVariableNamesRule_test.go
│ │ │ ├── ValuesOfCorrectTypeRule_test.go
│ │ │ ├── VariablesAreInputTypesRule_test.go
│ │ │ ├── VariablesInAllowedPositionRule_test.go
│ │ │ ├── harness_test.go
│ │ │ └── test_schema.graphql
│ ├── rule.go
│ ├── rule_implement_transitive_interfaces.go
│ ├── rule_implement_transitive_interfaces_test.go
│ ├── rule_implementing_types_are_supersets.go
│ ├── rule_implementing_types_are_supersets_test.go
│ ├── rule_known_type_names.go
│ ├── rule_known_type_names_test.go
│ ├── rule_populated_type_bodies.go
│ ├── rule_populated_type_bodies_test.go
│ ├── rule_require_defined_types_for_extensions.go
│ ├── rule_require_defined_types_for_extensions_test.go
│ ├── rule_unique_enum_value_names.go
│ ├── rule_unique_enum_value_names_test.go
│ ├── rule_unique_field_definition_names.go
│ ├── rule_unique_field_definition_names_test.go
│ ├── rule_unique_operation_types.go
│ ├── rule_unique_operation_types_test.go
│ ├── rule_unique_type_names.go
│ ├── rule_unique_type_names_test.go
│ ├── rule_unique_union_member_types.go
│ ├── rule_unique_union_member_types_test.go
│ ├── validation_state.go
│ └── validation_state_string.go
├── astvisitor
│ ├── astvisitor.go
│ ├── fixtures
│ │ ├── path.golden
│ │ ├── schema_visitor.golden
│ │ ├── visitor.golden
│ │ └── visitor_skip.golden
│ ├── simplevisitor.go
│ ├── simplevisitor_test.go
│ ├── visitor.go
│ └── visitor_test.go
├── codegen
│ ├── codegen.go
│ ├── codegen_test.go
│ ├── fixtures
│ │ └── DataSource.golden
│ ├── manual.go
│ ├── manual_test.go
│ └── testdata
│ │ └── schema.graphql
├── engine
│ ├── datasource
│ │ ├── graphql_datasource
│ │ │ ├── batch.go
│ │ │ ├── batch_test.go
│ │ │ ├── graphql_datasource.go
│ │ │ ├── graphql_datasource_test.go
│ │ │ ├── graphql_sse_handler.go
│ │ │ ├── graphql_sse_handler_test.go
│ │ │ ├── graphql_subscription_client.go
│ │ │ ├── graphql_subscription_client_test.go
│ │ │ ├── graphql_tws_handler.go
│ │ │ ├── graphql_tws_handler_test.go
│ │ │ ├── graphql_ws_handler.go
│ │ │ ├── graphql_ws_handler_test.go
│ │ │ └── graphql_ws_proto_types.go
│ │ ├── httpclient
│ │ │ ├── httpclient.go
│ │ │ ├── httpclient_test.go
│ │ │ └── nethttpclient.go
│ │ ├── introspection_datasource
│ │ │ ├── config_factory.go
│ │ │ ├── factory.go
│ │ │ ├── fixtures
│ │ │ │ ├── enum_values_with_deprecated.golden
│ │ │ │ ├── enum_values_without_deprecated.golden
│ │ │ │ ├── fields_with_deprecated.golden
│ │ │ │ ├── fields_without_deprecated.golden
│ │ │ │ ├── not_existing_type.golden
│ │ │ │ ├── schema_introspection.golden
│ │ │ │ ├── schema_introspection_with_custom_root_operation_types.golden
│ │ │ │ └── type_introspection.golden
│ │ │ ├── input.go
│ │ │ ├── input_test.go
│ │ │ ├── planner.go
│ │ │ ├── planner_test.go
│ │ │ ├── source.go
│ │ │ └── source_test.go
│ │ ├── kafka_datasource
│ │ │ ├── config.go
│ │ │ ├── config_test.go
│ │ │ ├── kafka_consumer_group.go
│ │ │ ├── kafka_consumer_group_test.go
│ │ │ ├── kafka_datasource.go
│ │ │ ├── kafka_datasource_test.go
│ │ │ └── sarama_config_parameters_test.go
│ │ ├── rest_datasource
│ │ │ ├── rest_datasource.go
│ │ │ └── rest_datasource_test.go
│ │ └── staticdatasource
│ │ │ ├── static_datasource.go
│ │ │ └── static_datasource_test.go
│ ├── datasourcetesting
│ │ └── datasourcetesting.go
│ ├── plan
│ │ ├── analyze_plan_kind.go
│ │ ├── analyze_plan_kind_test.go
│ │ ├── local_type_field_extractor.go
│ │ ├── local_type_field_extractor_test.go
│ │ ├── plan.go
│ │ ├── plan_closer_test.go
│ │ ├── plan_test.go
│ │ ├── required_field_extractor.go
│ │ └── required_field_extractor_test.go
│ └── resolve
│ │ ├── dataloader.go
│ │ ├── dataloader.md
│ │ ├── dataloader_test.go
│ │ ├── defer_test.go
│ │ ├── engine.md
│ │ ├── fetcher.go
│ │ ├── inputtemplate.go
│ │ ├── inputtemplate_test.go
│ │ ├── resolve.go
│ │ ├── resolve_mock_test.go
│ │ ├── resolve_test.go
│ │ ├── stream_test.go
│ │ ├── testdata
│ │ ├── defer_1.json
│ │ ├── defer_2.json
│ │ ├── defer_3.json
│ │ ├── posts.json
│ │ ├── response_without_defer.json
│ │ ├── stream_1.json
│ │ ├── stream_2.json
│ │ ├── stream_3.json
│ │ ├── stream_4.json
│ │ ├── stream_5.json
│ │ ├── stream_6.json
│ │ ├── stream_7.json
│ │ ├── stream_8.json
│ │ ├── stream_9.json
│ │ └── users.json
│ │ └── variable.go
├── escape
│ ├── bytes.go
│ ├── bytes_test.go
│ └── escape.go
├── execution
│ ├── datasource
│ │ ├── datasource.go
│ │ ├── datasource_graphql.go
│ │ ├── datasource_http_json.go
│ │ ├── datasource_http_polling_stream.go
│ │ ├── datasource_mqtt.go
│ │ ├── datasource_pipeline.go
│ │ ├── datasource_schema.go
│ │ ├── datasource_static.go
│ │ ├── datasource_type.go
│ │ └── hooks.go
│ ├── datasource_config.go
│ ├── datasource_graphql_test.go
│ ├── datasource_http_json_test.go
│ ├── datasource_pipeline_test.go
│ ├── execution.go
│ ├── execution_test.go
│ ├── fixtures
│ │ ├── execution.golden
│ │ ├── handler_render_graphql_definitions.golden
│ │ ├── introspection_execution.golden
│ │ └── render_graphql_definitions.golden
│ ├── graphql_definitions
│ │ ├── directives
│ │ │ ├── graphql_datasource.graphql
│ │ │ ├── http_json_datasource.graphql
│ │ │ ├── http_polling_stream_datasource.graphql
│ │ │ ├── mapping.graphql
│ │ │ ├── mqtt_datasource.graphql
│ │ │ ├── nats_datasource.graphql
│ │ │ ├── pipeline_datasource.graphql
│ │ │ ├── static_datasource.graphql
│ │ │ ├── transformation.graphql
│ │ │ └── wasm_datasource.graphql
│ │ ├── enums
│ │ │ ├── http_method.graphql
│ │ │ ├── mapping_mode.graphql
│ │ │ ├── parameter_source.graphql
│ │ │ └── transformation_mode.graphql
│ │ └── inputs
│ │ │ ├── header.graphql
│ │ │ ├── parameter.graphql
│ │ │ └── statuscode_typename_mapping.graphql
│ ├── handler.go
│ ├── handler_test.go
│ ├── jsonvaluetype.go
│ ├── jsonvaluetype_string.go
│ ├── jsonvaluetype_test.go
│ ├── planning.go
│ ├── planning_test.go
│ ├── testdata
│ │ ├── memory.wasm
│ │ └── simple_pipeline.json
│ ├── transformation.go
│ └── transformation_test.go
├── fastbuffer
│ ├── fastbuffer.go
│ └── fastbuffer_test.go
├── federation
│ ├── fixtures
│ │ └── federated_schema.golden
│ ├── schema.go
│ ├── schema_test.go
│ └── sdlmerge
│ │ ├── collect_entities.go
│ │ ├── collect_entities_test.go
│ │ ├── enum_type_extending.go
│ │ ├── enum_type_extending_test.go
│ │ ├── input_type_extending.go
│ │ ├── input_type_extending_test.go
│ │ ├── interface_type_extending.go
│ │ ├── interface_type_extending_test.go
│ │ ├── merge_duplicated_fields.go
│ │ ├── object_type_extending.go
│ │ ├── object_type_extending_test.go
│ │ ├── remove_duplicate_fielded_shared_types.go
│ │ ├── remove_duplicate_fielded_shared_types_test.go
│ │ ├── remove_duplicate_fieldless_shared_types.go
│ │ ├── remove_duplicate_fieldless_shared_types_test.go
│ │ ├── remove_empty_object_type_definition.go
│ │ ├── remove_empty_object_type_definition_test.go
│ │ ├── remove_field_definition_by_directive.go
│ │ ├── remove_field_definition_by_directive_test.go
│ │ ├── remove_field_definition_directive.go
│ │ ├── remove_field_definition_directive_test.go
│ │ ├── remove_interface_definition_directive.go
│ │ ├── remove_interface_definition_directive_test.go
│ │ ├── remove_object_type_definition_directive.go
│ │ ├── remove_object_type_definition_directive_test.go
│ │ ├── remove_type_extensions.go
│ │ ├── remove_type_extensions_test.go
│ │ ├── scalar_type_extending.go
│ │ ├── scalar_type_extending_test.go
│ │ ├── sdlmerge.go
│ │ ├── sdlmerge_test.go
│ │ ├── shared_types.go
│ │ ├── testdata
│ │ └── validate-subgraph
│ │ │ ├── lack-definition-non-null.graphqls
│ │ │ ├── lack-definition.graphqls
│ │ │ ├── lack-extend-definition-non-null.graphqls
│ │ │ ├── lack-extend-definition.graphqls
│ │ │ ├── well-defined-non-null.graphqls
│ │ │ └── well-defined.graphqls
│ │ ├── union_type_extending.go
│ │ └── union_type_extending_test.go
├── graphql
│ ├── complexity.go
│ ├── config_factory_federation.go
│ ├── config_factory_federation_test.go
│ ├── config_factory_proxy.go
│ ├── config_factory_proxy_test.go
│ ├── engine_config_v2.go
│ ├── engine_config_v2_test.go
│ ├── errors.go
│ ├── errors_test.go
│ ├── execution_engine.go
│ ├── execution_engine_test.go
│ ├── execution_engine_v2.go
│ ├── execution_engine_v2_custom.go
│ ├── execution_engine_v2_custom_test.go
│ ├── execution_engine_v2_test.go
│ ├── extractor.go
│ ├── extractor_test.go
│ ├── fixtures
│ │ └── introspection_response.golden
│ ├── input_validation.go
│ ├── input_validation_test.go
│ ├── lookup.go
│ ├── lookup_test.go
│ ├── normalization.go
│ ├── normalization_test.go
│ ├── request.go
│ ├── request_fields_validator.go
│ ├── request_fields_validator_test.go
│ ├── request_test.go
│ ├── response.go
│ ├── schema.go
│ ├── schema_test.go
│ ├── starwars_helpers_test.go
│ ├── subscription.go
│ ├── types.go
│ ├── validation.go
│ └── validation_test.go
├── graphqlerrors
│ └── location.go
├── graphqljsonschema
│ ├── jsonschema.go
│ └── jsonschema_test.go
├── http
│ ├── handler.go
│ ├── handler_test.go
│ ├── http.go
│ ├── ws.go
│ ├── ws_connection_init.json
│ ├── ws_start.json
│ └── ws_test.go
├── imports
│ ├── fixtures
│ │ ├── render_result.golden
│ │ ├── scanner_regex.golden
│ │ ├── scanner_regex_render.golden
│ │ └── scanner_result.golden
│ ├── graphql_file.go
│ ├── graphql_file_test.go
│ ├── imports.go
│ ├── imports_test.go
│ └── testdata
│ │ ├── cycle
│ │ ├── a
│ │ │ └── a.graphql
│ │ └── b
│ │ │ └── b.graphql
│ │ ├── deep
│ │ └── deeper
│ │ │ ├── custom_types.graphql
│ │ │ └── non_graphql.txt
│ │ ├── import_cycle.graphql
│ │ ├── nested
│ │ └── nested.graphql
│ │ ├── nested2
│ │ └── nested2.graphql
│ │ ├── regexonly
│ │ ├── flat.graphql
│ │ ├── mutation.graphql
│ │ └── query.graphql
│ │ ├── scalars
│ │ └── json.graphql
│ │ ├── schema.graphql
│ │ └── types
│ │ ├── mutation.graphql
│ │ └── query.graphql
├── introspection
│ ├── converter.go
│ ├── converter_test.go
│ ├── fixtures
│ │ ├── interfaces_implementing_interfaces.golden
│ │ ├── starwars.golden
│ │ └── starwars_introspected.golden
│ ├── generator.go
│ ├── generator_test.go
│ ├── introspection.go
│ ├── introspection_enum.go
│ ├── introspection_test.go
│ └── testdata
│ │ ├── interfaces_implementing_interfaces.graphql
│ │ ├── out_swapi_introspection_response.json
│ │ ├── starwars.schema.graphql
│ │ └── swapi_introspection_response.json
├── lexer
│ ├── fixtures
│ │ └── introspection_lexed.golden
│ ├── identkeyword
│ │ ├── identkeyword.go
│ │ └── identkeyword_string.go
│ ├── keyword
│ │ ├── keyword.go
│ │ └── keyword_string.go
│ ├── lexer.go
│ ├── lexer_test.go
│ ├── literal
│ │ └── literal.go
│ ├── position
│ │ └── position.go
│ ├── runes
│ │ └── runes.go
│ └── token
│ │ └── token.go
├── middleware
│ ├── middleware.go
│ └── operation_complexity
│ │ ├── operation_complexity.go
│ │ └── operation_complexity_test.go
├── operationreport
│ ├── externalerror.go
│ ├── externalerror_test.go
│ ├── operationreport.go
│ └── operationreport_test.go
├── playground
│ ├── files
│ │ ├── favicon.png
│ │ ├── logo.png
│ │ ├── playground.css
│ │ ├── playground.html
│ │ └── playground.js
│ ├── fixtures
│ │ └── handlers.golden
│ ├── playground.go
│ └── playground_test.go
├── pool
│ ├── bytesbuffer.go
│ ├── fastbuffer.go
│ └── hash64.go
├── postprocess
│ ├── datasourceinput.go
│ ├── datasourceinput_test.go
│ ├── defer.go
│ ├── defer_test.go
│ ├── fetchinput.go
│ ├── injectheader.go
│ ├── injectheader_test.go
│ ├── modifyheader.go
│ ├── modifyheader_test.go
│ ├── postprocess.go
│ ├── postprocess_test.go
│ ├── stream.go
│ └── stream_test.go
├── repair
│ ├── repair.go
│ ├── sdl.go
│ └── sdl_test.go
├── starwars
│ ├── starwars.go
│ └── testdata
│ │ ├── mutations
│ │ └── create_review.mutation
│ │ ├── queries
│ │ ├── directives_include.query
│ │ ├── directives_skip.query
│ │ ├── droid_with_arg.query
│ │ ├── droid_with_arg_and_var.query
│ │ ├── fragments.query
│ │ ├── hero_with_aliases.query
│ │ ├── hero_with_operation_name.query
│ │ ├── inline_fragments.query
│ │ ├── interface_fragments_on_union.graphql
│ │ ├── introspection.query
│ │ ├── invalid.query
│ │ ├── invalid_fragments.query
│ │ ├── multi_queries.query
│ │ ├── multi_queries_with_arguments.query
│ │ ├── simple_hero.query
│ │ └── union.query
│ │ ├── star_wars.graphql
│ │ └── subscriptions
│ │ └── remaining_jedis.subscription
├── subscription
│ ├── constants.go
│ ├── context.go
│ ├── context_test.go
│ ├── engine.go
│ ├── engine_mock_test.go
│ ├── engine_test.go
│ ├── executor.go
│ ├── executor_mock_test.go
│ ├── executor_v1.go
│ ├── executor_v2.go
│ ├── handler.go
│ ├── handler_mock_test.go
│ ├── handler_test.go
│ ├── init.go
│ ├── legacy_handler.go
│ ├── legacy_handler_test.go
│ ├── mock_client_test.go
│ ├── time_out.go
│ ├── time_out_test.go
│ ├── transport_client.go
│ ├── transport_client_mock_test.go
│ └── websocket
│ │ ├── client.go
│ │ ├── client_test.go
│ │ ├── engine_mock_test.go
│ │ ├── handler.go
│ │ ├── handler_test.go
│ │ ├── init.go
│ │ ├── protocol_graphql_transport_ws.go
│ │ ├── protocol_graphql_transport_ws_test.go
│ │ ├── protocol_graphql_ws.go
│ │ └── protocol_graphql_ws_test.go
├── testing
│ ├── federationtesting
│ │ ├── accounts
│ │ │ ├── gqlgen.yml
│ │ │ ├── graph
│ │ │ │ ├── entity.resolvers.go
│ │ │ │ ├── generated
│ │ │ │ │ ├── federation.go
│ │ │ │ │ └── generated.go
│ │ │ │ ├── handler.go
│ │ │ │ ├── histories.go
│ │ │ │ ├── model
│ │ │ │ │ └── models_gen.go
│ │ │ │ ├── resolver.go
│ │ │ │ ├── schema.graphqls
│ │ │ │ ├── schema.resolvers.go
│ │ │ │ └── wallets.go
│ │ │ └── handler.go
│ │ ├── federation_intergation_test.go
│ │ ├── gateway
│ │ │ ├── datasource_poller.go
│ │ │ ├── gateway.go
│ │ │ ├── http
│ │ │ │ ├── handler.go
│ │ │ │ ├── http.go
│ │ │ │ └── ws.go
│ │ │ └── main.go
│ │ ├── graphql_client_test.go
│ │ ├── products
│ │ │ ├── gqlgen.yml
│ │ │ ├── graph
│ │ │ │ ├── entity.resolvers.go
│ │ │ │ ├── generated
│ │ │ │ │ ├── federation.go
│ │ │ │ │ └── generated.go
│ │ │ │ ├── handler.go
│ │ │ │ ├── model
│ │ │ │ │ └── models_gen.go
│ │ │ │ ├── products.go
│ │ │ │ ├── resolver.go
│ │ │ │ ├── schema.graphqls
│ │ │ │ ├── schema.resolvers.go
│ │ │ │ └── variables.go
│ │ │ └── handler.go
│ │ ├── reviews
│ │ │ ├── gqlgen.yml
│ │ │ ├── graph
│ │ │ │ ├── attachments.go
│ │ │ │ ├── entity.resolvers.go
│ │ │ │ ├── generated
│ │ │ │ │ ├── federation.go
│ │ │ │ │ └── generated.go
│ │ │ │ ├── handler.go
│ │ │ │ ├── model
│ │ │ │ │ ├── models.go
│ │ │ │ │ └── models_gen.go
│ │ │ │ ├── resolver.go
│ │ │ │ ├── reviews.go
│ │ │ │ ├── schema.graphqls
│ │ │ │ └── schema.resolvers.go
│ │ │ └── handler.go
│ │ ├── testdata
│ │ │ ├── mutations
│ │ │ │ └── mutation_with_variables.query
│ │ │ ├── queries
│ │ │ │ ├── complex_nesting.graphql
│ │ │ │ ├── interface.query
│ │ │ │ ├── interface_fragment_on_object.graphql
│ │ │ │ ├── interface_fragments_on_union.graphql
│ │ │ │ ├── merged_field.graphql
│ │ │ │ ├── multiple_queries.query
│ │ │ │ ├── multiple_queries_with_nested_fragments.query
│ │ │ │ ├── multiple_queries_with_union_return.query
│ │ │ │ ├── multiple_upstream.query
│ │ │ │ ├── object_fragment_on_interface.graphql
│ │ │ │ ├── single_upstream.query
│ │ │ │ └── union.query
│ │ │ └── subscriptions
│ │ │ │ └── subscription.query
│ │ └── util.go
│ ├── goldie
│ │ ├── goldie.go
│ │ ├── goldie_posix.go
│ │ └── goldie_win.go
│ └── subscriptiontesting
│ │ ├── .gqlgen.yml
│ │ ├── chat_test.go
│ │ ├── generated.go
│ │ ├── handler.go
│ │ ├── models_gen.go
│ │ ├── resolvers.go
│ │ ├── schema.graphql
│ │ └── util.go
└── variablevalidator
│ ├── variablevalidator.go
│ └── variablevalidator_test.go
├── reimport.sh
└── v2
├── LICENSE
├── Makefile
├── README.md
├── assets
└── logo.png
├── doc.go
├── examples
├── chat
│ ├── .gitignore
│ ├── .gqlgen.yml
│ ├── chat_test.go
│ ├── generated.go
│ ├── go.mod
│ ├── go.sum
│ ├── handler.go
│ ├── models_gen.go
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ └── index.html
│ ├── readme.md
│ ├── resolvers.go
│ ├── schema.graphql
│ ├── server
│ │ └── server.go
│ ├── src
│ │ ├── App.js
│ │ ├── Room.js
│ │ ├── components
│ │ │ └── room.js
│ │ └── index.js
│ ├── start-server.sh
│ └── util.go
├── federation
│ ├── README.md
│ ├── accounts
│ │ ├── gqlgen.yml
│ │ ├── graph
│ │ │ ├── entity.resolvers.go
│ │ │ ├── generated
│ │ │ │ ├── federation.go
│ │ │ │ └── generated.go
│ │ │ ├── handler.go
│ │ │ ├── model
│ │ │ │ └── models_gen.go
│ │ │ ├── resolver.go
│ │ │ ├── schema.graphqls
│ │ │ └── schema.resolvers.go
│ │ └── server.go
│ ├── gateway
│ │ ├── datasource_poller.go
│ │ ├── gateway.go
│ │ ├── http
│ │ │ ├── handler.go
│ │ │ ├── http.go
│ │ │ └── ws.go
│ │ └── main.go
│ ├── go.mod
│ ├── go.sum
│ ├── products
│ │ ├── gqlgen.yml
│ │ ├── graph
│ │ │ ├── entity.resolvers.go
│ │ │ ├── generated
│ │ │ │ ├── federation.go
│ │ │ │ └── generated.go
│ │ │ ├── handler.go
│ │ │ ├── model
│ │ │ │ └── models_gen.go
│ │ │ ├── products.go
│ │ │ ├── resolver.go
│ │ │ ├── schema.graphqls
│ │ │ ├── schema.resolvers.go
│ │ │ └── variables.go
│ │ └── server.go
│ ├── reviews
│ │ ├── gqlgen.yml
│ │ ├── graph
│ │ │ ├── entity.resolvers.go
│ │ │ ├── generated
│ │ │ │ ├── federation.go
│ │ │ │ └── generated.go
│ │ │ ├── handler.go
│ │ │ ├── model
│ │ │ │ └── models_gen.go
│ │ │ ├── resolver.go
│ │ │ ├── reviews.go
│ │ │ └── schema.graphqls
│ │ └── server.go
│ ├── start.sh
│ └── tools.go
└── kafka_pubsub
│ ├── README.md
│ ├── docker-compose-cluster.yml
│ ├── docker-compose.yml
│ ├── example_datasources.json
│ ├── example_field_configs.json
│ ├── go.mod
│ ├── go.sum
│ ├── kafka_jaas.conf
│ ├── main.go
│ ├── schema.graphql
│ └── transactional_producer
│ ├── README.md
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── go.mod
├── go.sum
├── internal
└── pkg
│ ├── gocompat
│ └── .gitkeep
│ ├── quotes
│ ├── quotes.go
│ └── quotes_test.go
│ ├── unsafebytes
│ ├── unsafebytes.go
│ └── unsafebytes_test.go
│ ├── unsafeparser
│ └── unsafeparser.go
│ ├── unsafeprinter
│ └── unsafeprinter.go
│ └── xcontext
│ └── xcontext.go
└── pkg
├── ast
├── ast.go
├── ast_argument.go
├── ast_description.go
├── ast_directive.go
├── ast_directive_definition.go
├── ast_enum_type_definition.go
├── ast_enum_type_extension.go
├── ast_enum_value_definition.go
├── ast_field.go
├── ast_field_alias.go
├── ast_field_definition.go
├── ast_fragment_definition.go
├── ast_fragment_spread.go
├── ast_inline_fragment.go
├── ast_input_object_type_definition.go
├── ast_input_object_type_extension.go
├── ast_input_value_definition.go
├── ast_interface_type_definition.go
├── ast_interface_type_extension.go
├── ast_node.go
├── ast_node_kind.go
├── ast_node_kind_test.go
├── ast_object_field.go
├── ast_object_type_definition.go
├── ast_object_type_definition_test.go
├── ast_object_type_extension.go
├── ast_operation_definition.go
├── ast_operation_definition_test.go
├── ast_root_operation_type_definition.go
├── ast_root_operation_type_definition_test.go
├── ast_scalar_type_definition.go
├── ast_scalar_type_extension.go
├── ast_schema_definition.go
├── ast_schema_extension.go
├── ast_selection.go
├── ast_string.go
├── ast_test.go
├── ast_type.go
├── ast_type_test.go
├── ast_union_type_definition.go
├── ast_union_type_extension.go
├── ast_val_boolean_value.go
├── ast_val_enum_value.go
├── ast_val_float_value.go
├── ast_val_int_value.go
├── ast_val_list_value.go
├── ast_val_object_value.go
├── ast_val_string_value.go
├── ast_val_variable_value.go
├── ast_value.go
├── ast_value_test.go
├── ast_variable_definition.go
├── directive_location.go
├── directive_location_string.go
├── directive_location_test.go
├── helpers.go
├── index.go
├── index_test.go
├── input.go
└── path.go
├── astimport
├── astimport.go
└── astimport_test.go
├── astjson
├── astjson.go
└── astjson_test.go
├── astnormalization
├── abstract_field_normalizer.go
├── astnormalization.go
├── astnormalization_test.go
├── definition_normalization.go
├── definition_normalization_test.go
├── directive_include_skip.go
├── directive_include_skip_test.go
├── enum_type_extending.go
├── enum_type_extending_test.go
├── extends_directive.go
├── extends_directive_test.go
├── field_deduplication.go
├── field_deduplication_test.go
├── field_selection_merging.go
├── field_selection_merging_test.go
├── fragment_definition_removal.go
├── fragment_spread_inlining.go
├── fragment_spread_inlining_test.go
├── fragmentspread_depth.go
├── fragmentspread_depth_test.go
├── implicit_extend_root_operation.go
├── implicit_extend_root_operation_test.go
├── implicit_schema_definition.go
├── implicit_schema_definition_test.go
├── inject_input_default_values.go
├── inject_input_default_values_test.go
├── inline_fragment_add_on_type.go
├── inline_fragment_add_on_type_test.go
├── inline_fragment_selection_merging.go
├── inline_fragment_selection_merging_test.go
├── inline_selections_from_inline_fragments.go
├── inline_selections_from_inline_fragments_test.go
├── input_coercion_for_list.go
├── input_coercion_for_list_test.go
├── input_object_type_extending.go
├── input_object_type_extending_test.go
├── interface_type_extending.go
├── interface_type_extending_test.go
├── object_type_extending.go
├── object_type_extending_test.go
├── operation_definition_removal.go
├── remove_self_aliasing.go
├── remove_self_aliasing_test.go
├── remove_type_extensions.go
├── remove_type_extensions_test.go
├── scalar_type_extending.go
├── scalar_type_extending_test.go
├── subgraph_sdl_normalization.go
├── subgraph_sdl_normalization_test.go
├── union_type_extending.go
├── union_type_extending_test.go
├── variables_default_value_extraction.go
├── variables_default_value_extraction_test.go
├── variables_extraction.go
├── variables_extraction_test.go
├── variables_unused_deletion.go
└── variables_unused_deletion_test.go
├── astparser
├── errors.go
├── parser.go
├── parser_test.go
├── parser_token_helpers.go
├── testdata
│ ├── big_schema.graphql
│ ├── github.schema.graphql
│ ├── introspection_normalized.graphql
│ ├── introspectionquery.graphql
│ ├── starwars.schema.graphql
│ └── todo.graphql
└── tokenizer.go
├── astprinter
├── astprinter.go
├── astprinter_test.go
├── fixtures
│ ├── introspectionquery.golden
│ └── starwars_schema_definition.golden
└── testdata
│ ├── introspectionquery.graphql
│ └── starwars.schema.graphql
├── asttransform
├── asttransform.go
├── baseschema.go
├── baseschema_test.go
├── fixtures
│ ├── complete.golden
│ ├── custom_query_name.golden
│ ├── mutation_only.golden
│ ├── schema_missing.golden
│ ├── simple.golden
│ ├── subscription_only.golden
│ ├── subscription_renamed.golden
│ └── with_mutation_subscription.golden
└── typename_visitor.go
├── astvalidation
├── definition_validation.go
├── definition_validation_test.go
├── operation_rule_all_variable_uses_defined.go
├── operation_rule_all_variables_used.go
├── operation_rule_argument_uniqueness.go
├── operation_rule_directives_defined.go
├── operation_rule_directives_in_valid_locations.go
├── operation_rule_directives_unique_per_location.go
├── operation_rule_document_contains_executable_operation.go
├── operation_rule_field_selection_merging.go
├── operation_rule_fragments.go
├── operation_rule_known_arguments.go
├── operation_rule_lone_anonymous_operation.go
├── operation_rule_operation_name_uniqueness.go
├── operation_rule_required_arguments.go
├── operation_rule_subscription_single_root_field.go
├── operation_rule_valid_arguments.go
├── operation_rule_validate_field_selections.go
├── operation_rule_values.go
├── operation_rule_variable_uniqueness.go
├── operation_rule_variables_are_input_types.go
├── operation_validation.go
├── operation_validation_test.go
├── overlapping_fields_test.go
├── reference
│ ├── .gitignore
│ ├── __tests__
│ │ ├── ExecutableDefinitionsRule-test.js
│ │ ├── FieldsOnCorrectTypeRule-test.js
│ │ ├── FragmentsOnCompositeTypesRule-test.js
│ │ ├── KnownArgumentNamesRule-test.js
│ │ ├── KnownDirectivesRule-test.js
│ │ ├── KnownFragmentNamesRule-test.js
│ │ ├── KnownTypeNamesRule-test.js
│ │ ├── LoneAnonymousOperationRule-test.js
│ │ ├── LoneSchemaDefinitionRule-test.js
│ │ ├── NoDeprecatedCustomRule-test.js
│ │ ├── NoFragmentCyclesRule-test.js
│ │ ├── NoSchemaIntrospectionCustomRule-test.js
│ │ ├── NoUndefinedVariablesRule-test.js
│ │ ├── NoUnusedFragmentsRule-test.js
│ │ ├── NoUnusedVariablesRule-test.js
│ │ ├── OverlappingFieldsCanBeMergedRule-test.js
│ │ ├── PossibleFragmentSpreadsRule-test.js
│ │ ├── PossibleTypeExtensionsRule-test.js
│ │ ├── ProvidedRequiredArgumentsRule-test.js
│ │ ├── ScalarLeafsRule-test.js
│ │ ├── SingleFieldSubscriptionsRule-test.js
│ │ ├── UniqueArgumentNamesRule-test.js
│ │ ├── UniqueDirectiveNamesRule-test.js
│ │ ├── UniqueDirectivesPerLocationRule-test.js
│ │ ├── UniqueEnumValueNamesRule-test.js
│ │ ├── UniqueFieldDefinitionNamesRule-test.js
│ │ ├── UniqueFragmentNamesRule-test.js
│ │ ├── UniqueInputFieldNamesRule-test.js
│ │ ├── UniqueOperationNamesRule-test.js
│ │ ├── UniqueOperationTypesRule-test.js
│ │ ├── UniqueTypeNamesRule-test.js
│ │ ├── UniqueVariableNamesRule-test.js
│ │ ├── ValuesOfCorrectTypeRule-test.js
│ │ ├── VariablesAreInputTypesRule-test.js
│ │ ├── VariablesInAllowedPositionRule-test.js
│ │ ├── harness.js
│ │ └── validation-test.js
│ ├── gen.sh
│ ├── main.go
│ ├── replacements.yml
│ └── testsgo
│ │ ├── ExecutableDefinitionsRule_test.go
│ │ ├── FieldsOnCorrectTypeRule_test.go
│ │ ├── FragmentsOnCompositeTypesRule_test.go
│ │ ├── KnownArgumentNamesRule_test.go
│ │ ├── KnownDirectivesRule_test.go
│ │ ├── KnownFragmentNamesRule_test.go
│ │ ├── KnownTypeNamesRule_test.go
│ │ ├── LoneAnonymousOperationRule_test.go
│ │ ├── LoneSchemaDefinitionRule_test.go
│ │ ├── NoFragmentCyclesRule_test.go
│ │ ├── NoUndefinedVariablesRule_test.go
│ │ ├── NoUnusedFragmentsRule_test.go
│ │ ├── NoUnusedVariablesRule_test.go
│ │ ├── OverlappingFieldsCanBeMergedRule_test.go
│ │ ├── PossibleFragmentSpreadsRule_test.go
│ │ ├── PossibleTypeExtensionsRule_test.go
│ │ ├── ProvidedRequiredArgumentsRule_test.go
│ │ ├── ScalarLeafsRule_test.go
│ │ ├── SingleFieldSubscriptionsRule_test.go
│ │ ├── UniqueArgumentNamesRule_test.go
│ │ ├── UniqueDirectiveNamesRule_test.go
│ │ ├── UniqueDirectivesPerLocationRule_test.go
│ │ ├── UniqueEnumValueNamesRule_test.go
│ │ ├── UniqueFieldDefinitionNamesRule_test.go
│ │ ├── UniqueFragmentNamesRule_test.go
│ │ ├── UniqueInputFieldNamesRule_test.go
│ │ ├── UniqueOperationNamesRule_test.go
│ │ ├── UniqueOperationTypesRule_test.go
│ │ ├── UniqueTypeNamesRule_test.go
│ │ ├── UniqueVariableNamesRule_test.go
│ │ ├── ValuesOfCorrectTypeRule_test.go
│ │ ├── VariablesAreInputTypesRule_test.go
│ │ ├── VariablesInAllowedPositionRule_test.go
│ │ ├── harness_test.go
│ │ └── test_schema.graphql
├── rule.go
├── rule_implement_transitive_interfaces.go
├── rule_implement_transitive_interfaces_test.go
├── rule_implementing_types_are_supersets.go
├── rule_implementing_types_are_supersets_test.go
├── rule_known_type_names.go
├── rule_known_type_names_test.go
├── rule_populated_type_bodies.go
├── rule_populated_type_bodies_test.go
├── rule_require_defined_types_for_extensions.go
├── rule_require_defined_types_for_extensions_test.go
├── rule_unique_enum_value_names.go
├── rule_unique_enum_value_names_test.go
├── rule_unique_field_definition_names.go
├── rule_unique_field_definition_names_test.go
├── rule_unique_operation_types.go
├── rule_unique_operation_types_test.go
├── rule_unique_type_names.go
├── rule_unique_type_names_test.go
├── rule_unique_union_member_types.go
├── rule_unique_union_member_types_test.go
├── validation_state.go
└── validation_state_string.go
├── astvisitor
├── astvisitor.go
├── fixtures
│ ├── path.golden
│ ├── schema_visitor.golden
│ ├── visitor.golden
│ └── visitor_skip.golden
├── simplevisitor.go
├── simplevisitor_test.go
├── visitor.go
└── visitor_test.go
├── engine
├── datasource
│ ├── graphql_datasource
│ │ ├── entity_interfaces_engine_config.go
│ │ ├── graphql_datasource.go
│ │ ├── graphql_datasource_federation_entity_interfaces_test.go
│ │ ├── graphql_datasource_federation_test.go
│ │ ├── graphql_datasource_test.go
│ │ ├── graphql_sse_handler.go
│ │ ├── graphql_sse_handler_test.go
│ │ ├── graphql_subscription_client.go
│ │ ├── graphql_subscription_client_test.go
│ │ ├── graphql_tws_handler.go
│ │ ├── graphql_tws_handler_test.go
│ │ ├── graphql_ws_handler.go
│ │ ├── graphql_ws_handler_test.go
│ │ ├── graphql_ws_proto_types.go
│ │ ├── representation_variable.go
│ │ └── representation_variable_test.go
│ ├── httpclient
│ │ ├── httpclient.go
│ │ ├── httpclient_test.go
│ │ └── nethttpclient.go
│ ├── introspection_datasource
│ │ ├── config_factory.go
│ │ ├── factory.go
│ │ ├── fixtures
│ │ │ ├── enum_values_with_deprecated.golden
│ │ │ ├── enum_values_without_deprecated.golden
│ │ │ ├── fields_with_deprecated.golden
│ │ │ ├── fields_without_deprecated.golden
│ │ │ ├── not_existing_type.golden
│ │ │ ├── schema_introspection.golden
│ │ │ ├── schema_introspection_with_custom_root_operation_types.golden
│ │ │ └── type_introspection.golden
│ │ ├── input.go
│ │ ├── input_test.go
│ │ ├── planner.go
│ │ ├── planner_test.go
│ │ ├── source.go
│ │ └── source_test.go
│ ├── kafka_datasource
│ │ ├── config.go
│ │ ├── config_test.go
│ │ ├── kafka_consumer_group.go
│ │ ├── kafka_consumer_group_test.go
│ │ ├── kafka_datasource.go
│ │ ├── kafka_datasource_test.go
│ │ └── sarama_config_parameters_test.go
│ ├── pubsub_datasource
│ │ ├── pubsub_datasource.go
│ │ └── pubsub_datasource_test.go
│ ├── rest_datasource
│ │ ├── rest_datasource.go
│ │ └── rest_datasource_test.go
│ └── staticdatasource
│ │ ├── static_datasource.go
│ │ └── static_datasource_test.go
├── datasourcetesting
│ └── datasourcetesting.go
├── plan
│ ├── abstract_selection_rewriter.go
│ ├── abstract_selection_rewriter_helpers.go
│ ├── abstract_selection_rewriter_info.go
│ ├── abstract_selection_rewriter_test.go
│ ├── analyze_plan_kind.go
│ ├── analyze_plan_kind_test.go
│ ├── configuration.go
│ ├── configuration_visitor.go
│ ├── datasource_configuration.go
│ ├── datasource_filter_visitor.go
│ ├── datasource_filter_visitor_test.go
│ ├── federation_metadata.go
│ ├── plan.go
│ ├── planner.go
│ ├── planner_configuration.go
│ ├── planner_test.go
│ ├── provides_fields_visitor.go
│ ├── provides_fields_visitor_test.go
│ ├── required_fields_visitor.go
│ ├── schemausageinfo.go
│ ├── schemausageinfo_test.go
│ ├── skip_include_visitor.go
│ ├── type_field.go
│ └── visitor.go
├── postprocess
│ ├── create_concrete_single_fetch_types.go
│ ├── create_multi_fetch_types.go
│ ├── create_multi_fetch_types_test.go
│ ├── fetchinput.go
│ ├── injectheader.go
│ ├── injectheader_test.go
│ ├── modifyheader.go
│ ├── modifyheader_test.go
│ ├── postprocess.go
│ ├── resolve_input_templates.go
│ └── resolve_input_templates_test.go
└── resolve
│ ├── authorization_test.go
│ ├── buf_pair.go
│ ├── const.go
│ ├── context.go
│ ├── dataloader.md
│ ├── datasource.go
│ ├── engine.md
│ ├── fetch.go
│ ├── inputtemplate.go
│ ├── inputtemplate_test.go
│ ├── loader.go
│ ├── loader_test.go
│ ├── node.go
│ ├── node_array.go
│ ├── node_custom.go
│ ├── node_object.go
│ ├── node_scalar.go
│ ├── resolvable.go
│ ├── resolvable_test.go
│ ├── resolve.go
│ ├── resolve_federation_test.go
│ ├── resolve_mock_test.go
│ ├── resolve_test.go
│ ├── response.go
│ ├── simple_resolver.go
│ ├── testdata
│ ├── defer_1.json
│ ├── defer_2.json
│ ├── defer_3.json
│ ├── posts.json
│ ├── response_without_defer.json
│ ├── stream_1.json
│ ├── stream_2.json
│ ├── stream_3.json
│ ├── stream_4.json
│ ├── stream_5.json
│ ├── stream_6.json
│ ├── stream_7.json
│ ├── stream_8.json
│ ├── stream_9.json
│ └── users.json
│ ├── trace.go
│ ├── variables.go
│ └── variables_renderer.go
├── fastbuffer
├── fastbuffer.go
└── fastbuffer_test.go
├── federation
├── federationdata
│ ├── local_type_field_extractor.go
│ ├── local_type_field_extractor_test.go
│ ├── required_field_extractor.go
│ └── required_field_extractor_test.go
├── fixtures
│ └── federated_schema.golden
├── schema.go
├── schema_test.go
└── sdlmerge
│ ├── collect_entities.go
│ ├── collect_entities_test.go
│ ├── const.go
│ ├── enum_type_extending.go
│ ├── enum_type_extending_test.go
│ ├── input_type_extending.go
│ ├── input_type_extending_test.go
│ ├── interface_type_extending.go
│ ├── interface_type_extending_test.go
│ ├── merge_duplicated_fields.go
│ ├── object_type_extending.go
│ ├── object_type_extending_test.go
│ ├── remove_duplicate_fielded_shared_types.go
│ ├── remove_duplicate_fielded_shared_types_test.go
│ ├── remove_duplicate_fieldless_shared_types.go
│ ├── remove_duplicate_fieldless_shared_types_test.go
│ ├── remove_empty_object_type_definition.go
│ ├── remove_empty_object_type_definition_test.go
│ ├── remove_field_definition_by_directive.go
│ ├── remove_field_definition_by_directive_test.go
│ ├── remove_field_definition_directive.go
│ ├── remove_field_definition_directive_test.go
│ ├── remove_interface_definition_directive.go
│ ├── remove_interface_definition_directive_test.go
│ ├── remove_object_type_definition_directive.go
│ ├── remove_object_type_definition_directive_test.go
│ ├── remove_type_extensions.go
│ ├── remove_type_extensions_test.go
│ ├── scalar_type_extending.go
│ ├── scalar_type_extending_test.go
│ ├── sdlmerge.go
│ ├── sdlmerge_test.go
│ ├── shared_types.go
│ ├── testdata
│ └── validate-subgraph
│ │ ├── lack-definition-non-null.graphqls
│ │ ├── lack-definition.graphqls
│ │ ├── lack-extend-definition-non-null.graphqls
│ │ ├── lack-extend-definition.graphqls
│ │ ├── well-defined-non-null.graphqls
│ │ └── well-defined.graphqls
│ ├── union_type_extending.go
│ └── union_type_extending_test.go
├── graphql
├── complexity.go
├── config_factory_federation.go
├── config_factory_federation_test.go
├── config_factory_proxy.go
├── config_factory_proxy_test.go
├── engine_config_v2.go
├── engine_config_v2_test.go
├── errors.go
├── errors_test.go
├── execution_engine_v2.go
├── execution_engine_v2_custom.go
├── execution_engine_v2_custom_test.go
├── execution_engine_v2_helpers_test.go
├── execution_engine_v2_norace_test.go
├── execution_engine_v2_test.go
├── extractor.go
├── extractor_test.go
├── input_validation.go
├── input_validation_test.go
├── lookup.go
├── lookup_test.go
├── normalization.go
├── normalization_test.go
├── request.go
├── request_fields_validator.go
├── request_fields_validator_test.go
├── request_test.go
├── response.go
├── schema.go
├── schema_test.go
├── starwars_helpers_test.go
├── subscription.go
├── types.go
├── validation.go
└── validation_test.go
├── graphqlerrors
└── location.go
├── graphqljsonschema
├── jsonschema.go
└── jsonschema_test.go
├── imports
├── fixtures
│ ├── render_result.golden
│ ├── render_result_windows.golden
│ ├── scanner_regex.golden
│ ├── scanner_regex_render.golden
│ ├── scanner_regex_windows.golden
│ ├── scanner_result.golden
│ └── scanner_result_windows.golden
├── graphql_file.go
├── graphql_file_test.go
├── imports.go
├── imports_test.go
└── testdata
│ ├── cycle
│ ├── a
│ │ └── a.graphql
│ └── b
│ │ └── b.graphql
│ ├── deep
│ └── deeper
│ │ ├── custom_types.graphql
│ │ └── non_graphql.txt
│ ├── import_cycle.graphql
│ ├── nested
│ └── nested.graphql
│ ├── nested2
│ └── nested2.graphql
│ ├── regexonly
│ ├── flat.graphql
│ ├── mutation.graphql
│ └── query.graphql
│ ├── scalars
│ └── json.graphql
│ ├── schema.graphql
│ └── types
│ ├── mutation.graphql
│ └── query.graphql
├── introspection
├── converter.go
├── converter_test.go
├── fixtures
│ ├── interfaces_implementing_interfaces.golden
│ ├── starwars.golden
│ └── starwars_introspected.golden
├── generator.go
├── generator_test.go
├── introspection.go
├── introspection_enum.go
├── introspection_test.go
└── testdata
│ ├── interfaces_implementing_interfaces.graphql
│ ├── out_swapi_introspection_response.json
│ ├── starwars.schema.graphql
│ └── swapi_introspection_response.json
├── lexer
├── fixtures
│ └── introspection_lexed.golden
├── identkeyword
│ ├── identkeyword.go
│ └── identkeyword_string.go
├── keyword
│ ├── keyword.go
│ └── keyword_string.go
├── lexer.go
├── lexer_test.go
├── literal
│ └── literal.go
├── position
│ └── position.go
├── runes
│ └── runes.go
└── token
│ └── token.go
├── middleware
├── middleware.go
└── operation_complexity
│ ├── operation_complexity.go
│ └── operation_complexity_test.go
├── operationreport
├── externalerror.go
├── externalerror_test.go
├── operationreport.go
└── operationreport_test.go
├── playground
├── files
│ ├── favicon.png
│ ├── logo.png
│ ├── playground.css
│ ├── playground.html
│ └── playground.js
├── fixtures
│ └── handlers.golden
├── playground.go
└── playground_test.go
├── pool
├── bytesbuffer.go
├── fastbuffer.go
└── hash64.go
├── starwars
├── starwars.go
└── testdata
│ ├── mutations
│ └── create_review.mutation
│ ├── queries
│ ├── directives_include.query
│ ├── directives_skip.query
│ ├── droid_with_arg.query
│ ├── droid_with_arg_and_var.query
│ ├── fragments.query
│ ├── hero_with_aliases.query
│ ├── hero_with_operation_name.query
│ ├── inline_fragments.query
│ ├── interface_fragments_on_union.graphql
│ ├── introspection.query
│ ├── invalid.query
│ ├── invalid_fragments.query
│ ├── multi_queries.query
│ ├── multi_queries_with_arguments.query
│ ├── simple_hero.query
│ └── union.query
│ ├── star_wars.graphql
│ └── subscriptions
│ └── remaining_jedis.subscription
├── subscription
├── constants.go
├── context.go
├── context_test.go
├── engine.go
├── engine_mock_test.go
├── engine_test.go
├── executor.go
├── executor_mock_test.go
├── executor_v2.go
├── handler.go
├── handler_mock_test.go
├── handler_test.go
├── init.go
├── legacy_handler.go
├── legacy_handler_test.go
├── mock_client_test.go
├── time_out.go
├── time_out_test.go
├── transport_client.go
├── transport_client_mock_test.go
└── websocket
│ ├── client.go
│ ├── client_test.go
│ ├── engine_mock_test.go
│ ├── handler.go
│ ├── handler_test.go
│ ├── init.go
│ ├── protocol_graphql_transport_ws.go
│ ├── protocol_graphql_transport_ws_test.go
│ ├── protocol_graphql_ws.go
│ └── protocol_graphql_ws_test.go
├── testing
├── federationtesting
│ ├── accounts
│ │ ├── gqlgen.yml
│ │ ├── graph
│ │ │ ├── entity.resolvers.go
│ │ │ ├── generated
│ │ │ │ ├── federation.go
│ │ │ │ └── generated.go
│ │ │ ├── handler.go
│ │ │ ├── histories.go
│ │ │ ├── model
│ │ │ │ └── models_gen.go
│ │ │ ├── resolver.go
│ │ │ ├── schema.graphqls
│ │ │ ├── schema.resolvers.go
│ │ │ └── wallets.go
│ │ └── handler.go
│ ├── federation_integration_test.go
│ ├── gateway
│ │ ├── datasource_poller.go
│ │ ├── gateway.go
│ │ ├── http
│ │ │ ├── handler.go
│ │ │ ├── http.go
│ │ │ └── ws.go
│ │ └── main.go
│ ├── graphql_client_test.go
│ ├── products
│ │ ├── gqlgen.yml
│ │ ├── graph
│ │ │ ├── entity.resolvers.go
│ │ │ ├── generated
│ │ │ │ ├── federation.go
│ │ │ │ └── generated.go
│ │ │ ├── handler.go
│ │ │ ├── model
│ │ │ │ └── models_gen.go
│ │ │ ├── products.go
│ │ │ ├── resolver.go
│ │ │ ├── schema.graphqls
│ │ │ ├── schema.resolvers.go
│ │ │ └── variables.go
│ │ └── handler.go
│ ├── reviews
│ │ ├── gqlgen.yml
│ │ ├── graph
│ │ │ ├── attachments.go
│ │ │ ├── entity.resolvers.go
│ │ │ ├── generated
│ │ │ │ ├── federation.go
│ │ │ │ └── generated.go
│ │ │ ├── handler.go
│ │ │ ├── model
│ │ │ │ ├── models.go
│ │ │ │ └── models_gen.go
│ │ │ ├── resolver.go
│ │ │ ├── reviews.go
│ │ │ ├── schema.graphqls
│ │ │ └── schema.resolvers.go
│ │ └── handler.go
│ ├── testdata
│ │ ├── mutations
│ │ │ └── mutation_with_variables.query
│ │ ├── queries
│ │ │ ├── complex_nesting.graphql
│ │ │ ├── interface.query
│ │ │ ├── interface_fragment_on_object.graphql
│ │ │ ├── interface_fragments_on_union.graphql
│ │ │ ├── merged_field.graphql
│ │ │ ├── multiple_queries.query
│ │ │ ├── multiple_queries_with_nested_fragments.query
│ │ │ ├── multiple_queries_with_union_return.query
│ │ │ ├── multiple_upstream.query
│ │ │ ├── object_fragment_on_interface.graphql
│ │ │ ├── single_upstream.query
│ │ │ └── union.query
│ │ └── subscriptions
│ │ │ └── subscription.query
│ └── util.go
├── flags
│ ├── flags.go
│ └── flags_win.go
├── goldie
│ ├── goldie.go
│ ├── goldie_posix.go
│ └── goldie_win.go
└── subscriptiontesting
│ ├── .gqlgen.yml
│ ├── chat_test.go
│ ├── generated.go
│ ├── handler.go
│ ├── models_gen.go
│ ├── resolvers.go
│ ├── schema.graphql
│ └── util.go
└── variablesvalidation
├── variablesvalidation.go
└── variablesvalidation_test.go
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/*
2 | *.out
3 | *.test
4 | .DS_Store
5 | pkg/parser/testdata/lotto.graphql
6 | *node_modules*
7 | *vendor*
--------------------------------------------------------------------------------
/.golangci.yml:
--------------------------------------------------------------------------------
1 | linters:
2 | disable-all: true
3 | enable:
4 | - gofmt
5 | # - bodyclose
6 | - errcheck
7 | - gosimple
8 | - govet
9 | - ineffassign
10 | - staticcheck
11 | - typecheck
12 | # - unused
13 | # - gosec
14 | # - gci
15 |
16 | linters-settings:
17 | gci:
18 | sections:
19 | - standard
20 | - default
21 | - prefix(github.com/wundergraph)
22 | - prefix(github.com/wundergraph/graphql-go-tools)
23 | issues:
24 | exclude:
25 | - "SA1019: subscription.Message is deprecated: Prefer using TransportClient that is based on byte slices instead of this Message struct."
26 | - "SA1019: rand\\.Seed.*"
27 |
--------------------------------------------------------------------------------
/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 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/examples/chat/.gqlgen.yml:
--------------------------------------------------------------------------------
1 | models:
2 | Chatroom:
3 | model: github.com/TykTechnologies/graphql-go-tools/examples/chat.Chatroom
4 |
--------------------------------------------------------------------------------
/examples/chat/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/TykTechnologies/graphql-go-tools/examples/chat
2 |
3 | go 1.19
4 | require (
5 | github.com/99designs/gqlgen v0.17.20
6 | github.com/gorilla/websocket v1.5.0
7 | github.com/rs/cors v1.7.0
8 | github.com/stretchr/testify v1.7.1
9 | github.com/vektah/gqlparser/v2 v2.5.1
10 | )
11 |
--------------------------------------------------------------------------------
/examples/chat/handler.go:
--------------------------------------------------------------------------------
1 | package chat
2 |
3 | import (
4 | "net/http"
5 | "time"
6 |
7 | "github.com/99designs/gqlgen/graphql/handler"
8 | "github.com/99designs/gqlgen/graphql/handler/extension"
9 | "github.com/99designs/gqlgen/graphql/handler/transport"
10 | "github.com/gorilla/websocket"
11 | )
12 |
13 | func GraphQLEndpointHandler() http.Handler {
14 | srv := handler.New(NewExecutableSchema(New()))
15 |
16 | srv.AddTransport(transport.POST{})
17 | srv.AddTransport(transport.Websocket{
18 | KeepAlivePingInterval: 10 * time.Second,
19 | Upgrader: websocket.Upgrader{
20 | CheckOrigin: func(r *http.Request) bool {
21 | return true
22 | },
23 | },
24 | })
25 | srv.Use(extension.Introspection{})
26 |
27 | return srv
28 | }
29 |
--------------------------------------------------------------------------------
/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 | }
15 |
--------------------------------------------------------------------------------
/examples/chat/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chat",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@apollo/client": "^3.2.3",
7 | "@apollo/react-hooks": "^4.0.0",
8 | "apollo-cache-inmemory": "^1.3.11",
9 | "apollo-link-ws": "^1.0.10",
10 | "apollo-utilities": "^1.0.26",
11 | "graphql": "^14.0.2",
12 | "graphql-tag": "^2.10.0",
13 | "react": "^16.6.3",
14 | "react-dom": "^16.6.3",
15 | "react-scripts": "^2.1.1",
16 | "styled-components": "^5.2.0",
17 | "subscriptions-transport-ws": "^0.9.5"
18 | },
19 | "scripts": {
20 | "start": "cross-env PORT=3080 react-scripts start",
21 | "build": "react-scripts build",
22 | "test": "react-scripts test --env=jsdom",
23 | "eject": "react-scripts eject"
24 | },
25 | "browserslist": [
26 | ">0.2%",
27 | "not dead",
28 | "not ie <= 11",
29 | "not op_mini all"
30 | ],
31 | "devDependencies": {
32 | "cross-env": "^7.0.3"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/examples/chat/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | React App
8 |
9 |
10 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/chat/readme.md:
--------------------------------------------------------------------------------
1 | # Chat Demo
2 |
3 | ## Getting started
4 | 1. Install go modules & npm dependencies
5 | ```shell
6 | go mod download
7 | npm i
8 | ```
9 | 2. Start server and start react client
10 | ```
11 | chmod +x start-server.sh
12 | ./start-server.sh
13 | npm run start
14 | ```
15 |
16 | Example is forked from: [gqlgen](https://github.com/99designs/gqlgen/tree/master/example/chat)
17 |
18 | ## Example(s)
19 | ```graphql
20 | mutation SendMessage {
21 | post(roomName: "#test", username: "me", text: "hello!") {
22 | ...MessageData
23 | }
24 | }
25 |
26 | query GetMessages {
27 | room(name:"#test") {
28 | name
29 | messages {
30 | ...MessageData
31 | }
32 | }
33 | }
34 |
35 | subscription LiveMessages {
36 | messageAdded(roomName: "#test") {
37 | ...MessageData
38 | }
39 | }
40 |
41 | fragment MessageData on Message{
42 | id
43 | text
44 | createdBy
45 | createdAt
46 | }
47 | ```
--------------------------------------------------------------------------------
/examples/chat/schema.graphql:
--------------------------------------------------------------------------------
1 | type Chatroom {
2 | name: String!
3 | messages: [Message!]!
4 | }
5 |
6 | type Message {
7 | id: ID!
8 | text: String!
9 | createdBy: String!
10 | createdAt: Time!
11 | }
12 |
13 | type Query {
14 | room(name:String!): Chatroom
15 | }
16 |
17 | type Mutation {
18 | post(text: String!, username: String!, roomName: String!): Message!
19 | }
20 |
21 | type Subscription {
22 | messageAdded(roomName: String!): Message!
23 | }
24 |
25 | scalar Time
26 |
27 | directive @user(username: String!) on SUBSCRIPTION
28 |
--------------------------------------------------------------------------------
/examples/chat/server/server.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "net/http"
6 |
7 | "github.com/99designs/gqlgen/graphql/playground"
8 | "github.com/rs/cors"
9 |
10 | "github.com/TykTechnologies/graphql-go-tools/examples/chat"
11 | )
12 |
13 | func main() {
14 | c := cors.New(cors.Options{
15 | AllowedOrigins: []string{"http://localhost:3080", "http://localhost:3000"},
16 | AllowCredentials: true,
17 | })
18 |
19 | http.Handle("/", playground.Handler("Chat", "/query"))
20 | http.Handle("/query", c.Handler(chat.GraphQLEndpointHandler()))
21 |
22 | log.Println("Playground running on: http://localhost:8085")
23 | log.Println("Send operations to: http://localhost:8085/query")
24 | log.Fatal(http.ListenAndServe(":8085", nil))
25 | }
26 |
--------------------------------------------------------------------------------
/examples/chat/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import styled from 'styled-components';
3 | import { Room } from './Room';
4 |
5 | const Input = styled.div`
6 | padding: 4px;
7 | margin: 0 0 4px;
8 |
9 | input {
10 | border: 1px solid #ccc;
11 | padding: 2px;
12 | font-size: 14px;
13 | }
14 | `;
15 |
16 | export const App = () => {
17 | const [name, setName] = useState('tester');
18 | const [channel, setChannel] = useState('#gophers');
19 |
20 | return (
21 | <>
22 |
23 | name: setName(e.target.value)} />
24 |
25 |
26 | channel: setChannel(e.target.value)} />
27 |
28 |
29 |
30 | >
31 | );
32 |
33 | };
34 |
--------------------------------------------------------------------------------
/examples/chat/start-server.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | go build -o /tmp/srv-chat ./server
4 | /tmp/srv-chat
5 |
--------------------------------------------------------------------------------
/examples/federation/README.md:
--------------------------------------------------------------------------------
1 | # Federation Demo
2 |
3 | ## Getting started
4 | 1. Install go modules
5 | ```shell
6 | go mod download
7 | ```
8 | 2. Run start script
9 | ```
10 | chmod +x start.sh
11 | ./start.sh
12 | ```
--------------------------------------------------------------------------------
/examples/federation/accounts/graph/handler.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/99designs/gqlgen/graphql/handler"
7 | "github.com/99designs/gqlgen/graphql/handler/debug"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/examples/federation/accounts/graph/generated"
10 | )
11 |
12 | type EndpointOptions struct {
13 | EnableDebug bool
14 | }
15 |
16 | var TestOptions = EndpointOptions{
17 | EnableDebug: false,
18 | }
19 |
20 | func GraphQLEndpointHandler(opts EndpointOptions) http.Handler {
21 | srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &Resolver{}}))
22 | if opts.EnableDebug {
23 | srv.Use(&debug.Tracer{})
24 | }
25 |
26 | return srv
27 | }
28 |
--------------------------------------------------------------------------------
/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 User struct {
6 | ID string `json:"id"`
7 | Username string `json:"username"`
8 | }
9 |
10 | func (User) IsEntity() {}
11 |
--------------------------------------------------------------------------------
/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 | type Resolver struct{}
7 |
--------------------------------------------------------------------------------
/examples/federation/accounts/graph/schema.graphqls:
--------------------------------------------------------------------------------
1 | extend type Query {
2 | me: User
3 | }
4 |
5 | type User @key(fields: "id") {
6 | id: ID!
7 | username: String!
8 | }
9 |
--------------------------------------------------------------------------------
/examples/federation/accounts/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 |
6 | import (
7 | "context"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/examples/federation/accounts/graph/generated"
10 | "github.com/TykTechnologies/graphql-go-tools/examples/federation/accounts/graph/model"
11 | )
12 |
13 | // Me is the resolver for the me field.
14 | func (r *queryResolver) Me(ctx context.Context) (*model.User, error) {
15 | return &model.User{
16 | ID: "1234",
17 | Username: "Me",
18 | }, nil
19 | }
20 |
21 | // Query returns generated.QueryResolver implementation.
22 | func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} }
23 |
24 | type queryResolver struct{ *Resolver }
25 |
--------------------------------------------------------------------------------
/examples/federation/accounts/server.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package main
3 |
4 | import (
5 | "log"
6 | "net/http"
7 | "os"
8 |
9 | "github.com/99designs/gqlgen/graphql/playground"
10 |
11 | "github.com/TykTechnologies/graphql-go-tools/examples/federation/accounts/graph"
12 | )
13 |
14 | const defaultPort = "4001"
15 |
16 | func main() {
17 | port := os.Getenv("PORT")
18 | if port == "" {
19 | port = defaultPort
20 | }
21 |
22 | http.Handle("/", playground.Handler("GraphQL playground", "/query"))
23 | http.Handle("/query", graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true}))
24 |
25 | log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
26 | log.Fatal(http.ListenAndServe(":"+port, nil))
27 | }
28 |
--------------------------------------------------------------------------------
/examples/federation/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/TykTechnologies/graphql-go-tools/examples/federation
2 |
3 | go 1.21.0
4 |
5 | toolchain go1.21.6
6 |
7 | require (
8 | github.com/99designs/gqlgen v0.17.22
9 | github.com/TykTechnologies/graphql-go-tools v1.20.2
10 | github.com/gobwas/ws v1.0.4
11 | github.com/gorilla/websocket v1.5.0
12 | github.com/jensneuse/abstractlogger v0.0.4
13 | github.com/vektah/gqlparser/v2 v2.5.1
14 | go.uber.org/atomic v1.9.0
15 | go.uber.org/zap v1.18.1
16 | )
17 |
18 | replace github.com/TykTechnologies/graphql-go-tools => ../../
19 |
--------------------------------------------------------------------------------
/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 Product struct {
6 | Upc string `json:"upc"`
7 | Name string `json:"name"`
8 | Price int `json:"price"`
9 | InStock int `json:"inStock"`
10 | }
11 |
12 | func (Product) IsEntity() {}
13 |
--------------------------------------------------------------------------------
/examples/federation/products/graph/products.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/examples/federation/products/graph/model"
4 |
5 | var hats = []*model.Product{
6 | {
7 | Upc: "top-1",
8 | Name: "Trilby",
9 | Price: 11,
10 | InStock: 500,
11 | },
12 | {
13 | Upc: "top-2",
14 | Name: "Fedora",
15 | Price: 22,
16 | InStock: 1200,
17 | },
18 | {
19 | Upc: "top-3",
20 | Name: "Boater",
21 | Price: 33,
22 | InStock: 850,
23 | },
24 | }
25 |
--------------------------------------------------------------------------------
/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 | extend type Subscription {
6 | updatedPrice: Product!
7 | updateProductPrice(upc: String!): Product!
8 | stock: [Product!]
9 | }
10 |
11 | type Product @key(fields: "upc") {
12 | upc: String!
13 | name: String!
14 | price: Int!
15 | inStock: Int!
16 | }
--------------------------------------------------------------------------------
/examples/federation/products/graph/variables.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | var (
8 | randomnessEnabled = true
9 | minPrice = 10
10 | maxPrice = 1499
11 | currentPrice = minPrice
12 | updateInterval = time.Second
13 | )
14 |
--------------------------------------------------------------------------------
/examples/federation/products/server.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package main
3 |
4 | import (
5 | "log"
6 | "net/http"
7 | "os"
8 |
9 | "github.com/99designs/gqlgen/graphql/playground"
10 |
11 | "github.com/TykTechnologies/graphql-go-tools/examples/federation/products/graph"
12 | )
13 |
14 | const defaultPort = "4002"
15 |
16 | func main() {
17 | port := os.Getenv("PORT")
18 | if port == "" {
19 | port = defaultPort
20 | }
21 |
22 | http.Handle("/", playground.Handler("GraphQL playground", "/query"))
23 | http.Handle("/query", graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true, EnableRandomness: true}))
24 | http.HandleFunc("/websocket_connections", graph.WebsocketConnectionsHandler)
25 |
26 | log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
27 | log.Fatal(http.ListenAndServe(":"+port, nil))
28 | }
29 |
--------------------------------------------------------------------------------
/examples/federation/reviews/graph/handler.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/99designs/gqlgen/graphql/handler"
7 | "github.com/99designs/gqlgen/graphql/handler/debug"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/examples/federation/reviews/graph/generated"
10 | )
11 |
12 | type EndpointOptions struct {
13 | EnableDebug bool
14 | }
15 |
16 | var TestOptions = EndpointOptions{
17 | EnableDebug: false,
18 | }
19 |
20 | func GraphQLEndpointHandler(opts EndpointOptions) http.Handler {
21 | srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &Resolver{}}))
22 | if opts.EnableDebug {
23 | srv.Use(&debug.Tracer{})
24 | }
25 |
26 | return srv
27 | }
28 |
--------------------------------------------------------------------------------
/examples/federation/reviews/graph/model/models.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | type Product struct {
4 | Upc string `json:"upc"`
5 | }
6 |
7 | func (Product) IsEntity() {}
8 |
9 | type Review struct {
10 | Body string
11 | Author *User
12 | Product *Product
13 | }
14 |
15 | type User struct {
16 | ID string `json:"id"`
17 | }
18 |
19 | func (User) IsEntity() {}
20 |
--------------------------------------------------------------------------------
/examples/federation/reviews/graph/model/models_gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
2 |
3 | package model
4 |
--------------------------------------------------------------------------------
/examples/federation/reviews/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/reviews/graph/reviews.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/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{Upc: "top-1"},
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{Upc: "top-2"},
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{Upc: "top-3"},
19 | Author: &model.User{ID: "7777"},
20 | },
21 | }
22 |
--------------------------------------------------------------------------------
/examples/federation/reviews/graph/schema.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User! @provides(fields: "username")
4 | product: Product!
5 | }
6 |
7 | extend type User @key(fields: "id") {
8 | id: ID! @external
9 | username: String! @external
10 | reviews: [Review]
11 | }
12 |
13 | extend type Product @key(fields: "upc") {
14 | upc: String! @external
15 | reviews: [Review]
16 | }
17 |
--------------------------------------------------------------------------------
/examples/federation/reviews/server.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package main
3 |
4 | import (
5 | "log"
6 | "net/http"
7 | "os"
8 |
9 | "github.com/99designs/gqlgen/graphql/playground"
10 |
11 | "github.com/TykTechnologies/graphql-go-tools/examples/federation/reviews/graph"
12 | )
13 |
14 | const defaultPort = "4003"
15 |
16 | func main() {
17 | port := os.Getenv("PORT")
18 | if port == "" {
19 | port = defaultPort
20 | }
21 |
22 | http.Handle("/", playground.Handler("GraphQL playground", "/query"))
23 | http.Handle("/query", graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true}))
24 |
25 | log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
26 | log.Fatal(http.ListenAndServe(":"+port, nil))
27 | }
28 |
--------------------------------------------------------------------------------
/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 | go build -o /tmp/srv-gateway ./gateway
14 |
15 | /tmp/srv-accounts &
16 | ACCOUNTS_PID=$!
17 |
18 | /tmp/srv-products &
19 | PRODUCTS_PID=$!
20 |
21 | /tmp/srv-reviews &
22 | REVIEWS_PID=$!
23 |
24 | sleep 1
25 |
26 | /tmp/srv-gateway
27 |
--------------------------------------------------------------------------------
/examples/kafka_pubsub/kafka_jaas.conf:
--------------------------------------------------------------------------------
1 | KafkaServer {
2 | org.apache.kafka.common.security.plain.PlainLoginModule required
3 | username="admin"
4 | password="admin-secret"
5 | user_admin="admin-secret"
6 | user_alice="alice-secret";
7 | };
8 | Client{};
--------------------------------------------------------------------------------
/examples/kafka_pubsub/transactional_producer/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/TykTechnologies/graphql-go-tools/examples/kafka_pubsub/transactional_producer
2 |
3 | go 1.19
4 |
5 | require github.com/confluentinc/confluent-kafka-go v1.8.2
6 |
--------------------------------------------------------------------------------
/examples/kafka_pubsub/transactional_producer/go.sum:
--------------------------------------------------------------------------------
1 | github.com/confluentinc/confluent-kafka-go v1.8.2 h1:PBdbvYpyOdFLehj8j+9ba7FL4c4Moxn79gy9cYKxG5E=
2 | github.com/confluentinc/confluent-kafka-go v1.8.2/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg=
3 |
--------------------------------------------------------------------------------
/internal/pkg/quotes/quotes.go:
--------------------------------------------------------------------------------
1 | package quotes
2 |
3 | const (
4 | quoteByte = '"'
5 | quoteStr = string(quoteByte)
6 | )
7 |
8 | // WrapBytes returns a new slice wrapping the given s
9 | // in quotes (") by making a copy.
10 | func WrapBytes(s []byte) []byte {
11 | cp := make([]byte, len(s)+2)
12 | cp[0] = quoteByte
13 | copy(cp[1:], s)
14 | cp[len(s)+1] = quoteByte
15 | return cp
16 | }
17 |
18 | func WrapString(str string) string {
19 | return quoteStr + str + quoteStr
20 | }
21 |
--------------------------------------------------------------------------------
/internal/pkg/quotes/quotes_test.go:
--------------------------------------------------------------------------------
1 | package quotes
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestWrapBytes(t *testing.T) {
10 | testCases := []struct {
11 | s []byte
12 | want []byte
13 | }{
14 | {nil, []byte(`""`)},
15 | {[]byte("foo"), []byte(`"foo"`)},
16 | }
17 | for _, tc := range testCases {
18 | tc := tc
19 | t.Run(string(tc.s), func(t *testing.T) {
20 | r := WrapBytes(tc.s)
21 | assert.Equal(t, tc.want, r)
22 | })
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/internal/pkg/unsafeprinter/unsafeprinter.go:
--------------------------------------------------------------------------------
1 | package unsafeprinter
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/internal/pkg/unsafeparser"
5 | "github.com/TykTechnologies/graphql-go-tools/pkg/ast"
6 | "github.com/TykTechnologies/graphql-go-tools/pkg/astprinter"
7 | )
8 |
9 | func Print(document, definition *ast.Document) string {
10 | str, err := astprinter.PrintString(document, definition)
11 | if err != nil {
12 | panic(err)
13 | }
14 | return str
15 | }
16 |
17 | func PrettyPrint(document, definition *ast.Document) string {
18 | str, err := astprinter.PrintStringIndent(document, definition, " ")
19 | if err != nil {
20 | panic(err)
21 | }
22 | return str
23 | }
24 |
25 | func Prettify(document string) string {
26 | doc := unsafeparser.ParseGraphqlDocumentString(document)
27 | return PrettyPrint(&doc, nil)
28 | }
29 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/cmd"
4 |
5 | func main() {
6 | cmd.Execute()
7 | }
8 |
--------------------------------------------------------------------------------
/pkg/ast/ast_node_kind_test.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | import (
4 | "github.com/stretchr/testify/assert"
5 | "testing"
6 | )
7 |
8 | func TestNodeKindIsAbstractType(t *testing.T) {
9 | t.Run("Interface type returns true", func(t *testing.T) {
10 | assert.Equal(t, NodeKindInterfaceTypeDefinition.IsAbstractType(), true)
11 | })
12 |
13 | t.Run("Union type returns true", func(t *testing.T) {
14 | assert.Equal(t, NodeKindUnionTypeDefinition.IsAbstractType(), true)
15 | })
16 |
17 | t.Run("Enum type returns false", func(t *testing.T) {
18 | assert.Equal(t, NodeKindEnumTypeDefinition.IsAbstractType(), false)
19 | })
20 |
21 | t.Run("Interface type returns false", func(t *testing.T) {
22 | assert.Equal(t, NodeKindObjectTypeDefinition.IsAbstractType(), false)
23 | })
24 |
25 | t.Run("Scalar type returns false", func(t *testing.T) {
26 | assert.Equal(t, NodeKindScalarTypeDefinition.IsAbstractType(), false)
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/ast/ast_schema_extension.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/pkg/lexer/position"
4 |
5 | type SchemaExtension struct {
6 | ExtendLiteral position.Position
7 | SchemaDefinition
8 | }
9 |
--------------------------------------------------------------------------------
/pkg/ast/ast_type_test.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
--------------------------------------------------------------------------------
/pkg/ast/ast_val_boolean_value.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | // BooleanValues
4 | // one of: true, false
5 | type BooleanValue bool
6 |
7 | func (d *Document) BooleanValue(ref int) BooleanValue {
8 | return d.BooleanValues[ref]
9 | }
10 |
11 | func (d *Document) BooleanValuesAreEqual(left, right int) bool {
12 | return d.BooleanValue(left) == d.BooleanValue(right)
13 | }
14 |
--------------------------------------------------------------------------------
/pkg/ast/ast_val_object_value.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/pkg/lexer/position"
4 |
5 | // ObjectValue
6 | // example:
7 | // { lon: 12.43, lat: -53.211 }
8 | type ObjectValue struct {
9 | LBRACE position.Position
10 | Refs []int // ObjectField
11 | RBRACE position.Position
12 | }
13 |
14 | func (d *Document) CopyObjectValue(ref int) int {
15 | refs := d.NewEmptyRefs()
16 | for _, r := range d.ObjectValues[ref].Refs {
17 | refs = append(refs, d.CopyObjectField(r))
18 | }
19 | return d.AddObjectValue(ObjectValue{
20 | Refs: refs,
21 | })
22 | }
23 |
24 | func (d *Document) AddObjectValue(value ObjectValue) (ref int) {
25 | d.ObjectValues = append(d.ObjectValues, value)
26 | return len(d.ObjectValues) - 1
27 | }
28 |
29 | func (d *Document) ImportObjectValue(fieldRefs []int) (ref int) {
30 | return d.AddObjectValue(ObjectValue{
31 | Refs: fieldRefs,
32 | })
33 | }
34 |
--------------------------------------------------------------------------------
/pkg/ast/document_pool.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | import "sync"
4 |
5 | type documentPool struct {
6 | p sync.Pool
7 | }
8 |
9 | func newDocumentPool() *documentPool {
10 | return &documentPool{
11 | p: sync.Pool{
12 | New: func() interface{} {
13 | return newDocumentWithPreAllocation()
14 | },
15 | },
16 | }
17 | }
18 |
19 | func (p *documentPool) Put(b *Document) {
20 | b.Reset()
21 | p.p.Put(b)
22 | }
23 |
24 | func (p *documentPool) Get() *Document {
25 | return p.p.Get().(*Document)
26 | }
27 |
--------------------------------------------------------------------------------
/pkg/ast/helpers.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | // indexOf - simple helper to find an index of a ref within refs slice
4 | func indexOf(refs []int, ref int) (int, bool) {
5 | for i, j := range refs {
6 | if ref == j {
7 | return i, true
8 | }
9 | }
10 | return -1, false
11 | }
12 |
13 | // deleteRef - is a slice trick to remove an item with preserving items order
14 | // Note: danger modifies pointer to the arr
15 | func deleteRef(refs *[]int, index int) {
16 | *refs = append((*refs)[:index], (*refs)[index+1:]...)
17 | }
18 |
--------------------------------------------------------------------------------
/pkg/astnormalization/directive_include_skip_test.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import "testing"
4 |
5 | func TestDirectiveIncludeVisitor(t *testing.T) {
6 | t.Run("remove static include true on inline fragment", func(t *testing.T) {
7 | run(directiveIncludeSkip, testDefinition, `
8 | {
9 | dog {
10 | name: nickname
11 | ... @include(if: true) {
12 | includeName: name @include(if: true)
13 | notIncludeName: name @include(if: false)
14 | notSkipName: name @skip(if: false)
15 | skipName: name @skip(if: true)
16 | }
17 | }
18 | notInclude: dog @include(if: false) {
19 | name
20 | }
21 | skip: dog @skip(if: true) {
22 | name
23 | }
24 | }`, `
25 | {
26 | dog {
27 | name: nickname
28 | ... {
29 | includeName: name
30 | notSkipName: name
31 | }
32 | }
33 | }`)
34 | })
35 | }
36 |
--------------------------------------------------------------------------------
/pkg/astnormalization/fragment_definition_removal.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/pkg/ast"
5 | "github.com/TykTechnologies/graphql-go-tools/pkg/astvisitor"
6 | )
7 |
8 | type FragmentDefinitionRemoval struct {
9 | }
10 |
11 | func removeFragmentDefinitions(walker *astvisitor.Walker) {
12 | visitor := removeFragmentDefinitionsVisitor{}
13 | walker.RegisterLeaveDocumentVisitor(visitor)
14 | }
15 |
16 | type removeFragmentDefinitionsVisitor struct {
17 | }
18 |
19 | func (r removeFragmentDefinitionsVisitor) LeaveDocument(operation, definition *ast.Document) {
20 | for i := range operation.RootNodes {
21 | if operation.RootNodes[i].Kind == ast.NodeKindFragmentDefinition {
22 | operation.RootNodes[i].Kind = ast.NodeKindUnknown
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/pkg/astnormalization/remove_self_aliasing.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/TykTechnologies/graphql-go-tools/pkg/ast"
7 | "github.com/TykTechnologies/graphql-go-tools/pkg/astvisitor"
8 | )
9 |
10 | func removeSelfAliasing(walker *astvisitor.Walker) {
11 | visitor := removeSelfAliasingVisitor{}
12 | walker.RegisterEnterDocumentVisitor(&visitor)
13 | walker.RegisterEnterFieldVisitor(&visitor)
14 | }
15 |
16 | type removeSelfAliasingVisitor struct {
17 | operation *ast.Document
18 | }
19 |
20 | func (r *removeSelfAliasingVisitor) EnterDocument(operation, definition *ast.Document) {
21 | r.operation = operation
22 | }
23 |
24 | func (r *removeSelfAliasingVisitor) EnterField(ref int) {
25 | if !r.operation.Fields[ref].Alias.IsDefined {
26 | return
27 | }
28 | if !bytes.Equal(r.operation.FieldNameBytes(ref), r.operation.FieldAliasBytes(ref)) {
29 | return
30 | }
31 | r.operation.RemoveFieldAlias(ref)
32 | }
33 |
--------------------------------------------------------------------------------
/pkg/astnormalization/remove_self_aliasing_test.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import "testing"
4 |
5 | func TestRemoveSelfAliasing(t *testing.T) {
6 | t.Run("simple", func(t *testing.T) {
7 | run(removeSelfAliasing, testDefinition, `
8 | {dog: dog}`,
9 | `
10 | {dog}`)
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/pkg/astnormalization/remove_type_extensions.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/pkg/ast"
5 | "github.com/TykTechnologies/graphql-go-tools/pkg/astvisitor"
6 | )
7 |
8 | func removeMergedTypeExtensions(walker *astvisitor.Walker) {
9 | visitor := removeMergedTypeExtensionsVisitor{
10 | Walker: walker,
11 | }
12 | walker.RegisterLeaveDocumentVisitor(&visitor)
13 | }
14 |
15 | type removeMergedTypeExtensionsVisitor struct {
16 | *astvisitor.Walker
17 | }
18 |
19 | func (r *removeMergedTypeExtensionsVisitor) LeaveDocument(operation, definition *ast.Document) {
20 | operation.RemoveMergedTypeExtensions()
21 | }
22 |
--------------------------------------------------------------------------------
/pkg/astnormalization/variables_unused_deletion_test.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestUnusedVariableDeletion(t *testing.T) {
8 | t.Run("delete unused variables", func(t *testing.T) {
9 | runWithDeleteUnusedVariables(t, deleteUnusedVariables, variablesExtractionDefinition, `
10 | mutation HttpBinPost($a: HttpBinPostInput $b: String){
11 | httpBinPost(input: $a){
12 | headers {
13 | userAgent
14 | }
15 | data {
16 | foo
17 | }
18 | }
19 | }`, "HttpBinPost", `
20 | mutation HttpBinPost($a: HttpBinPostInput){
21 | httpBinPost(input: $a){
22 | headers {
23 | userAgent
24 | }
25 | data {
26 | foo
27 | }
28 | }
29 | }`, `{"a":{"foo":"bar"},"b":"bat"}`, `{"a":{"foo":"bar"}}`)
30 | })
31 | }
32 |
--------------------------------------------------------------------------------
/pkg/astvalidation/definition_validation_test.go:
--------------------------------------------------------------------------------
1 | package astvalidation
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | "github.com/stretchr/testify/require"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/pkg/astparser"
10 | "github.com/TykTechnologies/graphql-go-tools/pkg/asttransform"
11 | )
12 |
13 | func runDefinitionValidation(t *testing.T, definitionInput string, expectation ValidationState, rules ...Rule) {
14 | definition, report := astparser.ParseGraphqlDocumentString(definitionInput)
15 | require.False(t, report.HasErrors())
16 |
17 | err := asttransform.MergeDefinitionWithBaseSchema(&definition)
18 | require.NoError(t, err)
19 |
20 | validator := &DefinitionValidator{}
21 | for _, rule := range rules {
22 | validator.RegisterRule(rule)
23 | }
24 |
25 | result := validator.Validate(&definition, &report)
26 | assert.Equal(t, expectation, result)
27 | }
28 |
--------------------------------------------------------------------------------
/pkg/astvalidation/reference/.gitignore:
--------------------------------------------------------------------------------
1 | __tests__
--------------------------------------------------------------------------------
/pkg/astvalidation/reference/gen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd testsgo
4 | rm -f *Rule_test.go
5 | cd ..
6 |
7 | go run main.go
8 | gofmt -w testsgo
9 |
--------------------------------------------------------------------------------
/pkg/astvalidation/rule.go:
--------------------------------------------------------------------------------
1 | package astvalidation
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/pkg/astvisitor"
5 | )
6 |
7 | var reservedFieldPrefix = []byte("__")
8 |
9 | // Rule is hook to register callback functions on the Walker
10 | type Rule func(walker *astvisitor.Walker)
11 |
--------------------------------------------------------------------------------
/pkg/astvalidation/rule_unique_union_member_types_test.go:
--------------------------------------------------------------------------------
1 | package astvalidation
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestUniqueMemberTypes(t *testing.T) {
8 | t.Run("Definition", func(t *testing.T) {
9 | t.Run("Union with a single member is valid", func(t *testing.T) {
10 | runDefinitionValidation(t, `
11 | union Foo = Bar
12 | `, Valid, UniqueUnionMemberTypes(),
13 | )
14 | })
15 |
16 | t.Run("Union with many members is valid", func(t *testing.T) {
17 | runDefinitionValidation(t, `
18 | union Foo = Bar | FooBar | BarFoo
19 | `, Valid, UniqueUnionMemberTypes(),
20 | )
21 | })
22 |
23 | t.Run("Union with duplicate members is invalid", func(t *testing.T) {
24 | runDefinitionValidation(t, `
25 | union Foo = Bar | Bar
26 | `, Invalid, UniqueUnionMemberTypes(),
27 | )
28 | })
29 | })
30 | }
31 |
--------------------------------------------------------------------------------
/pkg/astvalidation/validation_state.go:
--------------------------------------------------------------------------------
1 | //go:generate stringer -type=ValidationState -output validation_state_string.go
2 |
3 | package astvalidation
4 |
5 | // ValidationState is the outcome of a validation
6 | type ValidationState int
7 |
8 | const (
9 | UnknownState ValidationState = iota
10 | Valid
11 | Invalid
12 | )
13 |
--------------------------------------------------------------------------------
/pkg/astvalidation/validation_state_string.go:
--------------------------------------------------------------------------------
1 | // Code generated by "stringer -type=ValidationState -output validation_state_string.go"; DO NOT EDIT.
2 |
3 | package astvalidation
4 |
5 | import "strconv"
6 |
7 | func _() {
8 | // An "invalid array index" compiler error signifies that the constant values have changed.
9 | // Re-run the stringer command to generate them again.
10 | var x [1]struct{}
11 | _ = x[UnknownState-0]
12 | _ = x[Valid-1]
13 | _ = x[Invalid-2]
14 | }
15 |
16 | const _ValidationState_name = "UnknownStateValidInvalid"
17 |
18 | var _ValidationState_index = [...]uint8{0, 12, 17, 24}
19 |
20 | func (i ValidationState) String() string {
21 | if i < 0 || i >= ValidationState(len(_ValidationState_index)-1) {
22 | return "ValidationState(" + strconv.FormatInt(int64(i), 10) + ")"
23 | }
24 | return _ValidationState_name[_ValidationState_index[i]:_ValidationState_index[i+1]]
25 | }
26 |
--------------------------------------------------------------------------------
/pkg/astvisitor/astvisitor.go:
--------------------------------------------------------------------------------
1 | // Package astvisitor enables efficient and powerful traversal of GraphQL document AST's.
2 | //
3 | // Visitor has more options to configure the behaviour and offers more meta data than SimpleVisitor.
4 | // SimpleVisitor on the other hand is more performant.
5 | //
6 | // If all Nodes should be visited and not much meta data is needed, go with SimpleVisitor.
7 | // If you only need to visit a subset of Nodes or want specific meta data, e.g. TypeDefinitions you should go with Visitor.
8 | package astvisitor
9 |
--------------------------------------------------------------------------------
/pkg/astvisitor/fixtures/path.golden:
--------------------------------------------------------------------------------
1 | EnterField: posts, path: [query]
2 | EnterField: id, path: [query,posts]
3 | EnterField: description, path: [query,posts]
4 | EnterField: user, path: [query,posts]
5 | EnterField: id, path: [query,posts,user]
6 | EnterField: name, path: [query,posts,user]
7 | EnterField: posts, path: [query]
8 | EnterField: id, path: [query,posts]
9 | EnterField: description, path: [query,posts]
10 | EnterField: user, path: [query,posts]
11 | EnterField: id, path: [query,posts,user]
12 | EnterField: name, path: [query,posts,user]
13 | EnterField: posts, path: [query,posts,user]
14 | EnterField: id, path: [query,posts,user,posts]
15 |
--------------------------------------------------------------------------------
/pkg/astvisitor/fixtures/visitor_skip.golden:
--------------------------------------------------------------------------------
1 | EnterOperationDefinition (PostsUserQuery): ref: 0
2 | EnterSelectionSet(Query): ref: 2
3 | EnterField(posts::Query): ref: 5
4 | EnterSelectionSet(Post): ref: 1
5 | EnterField(id::Post): ref: 0
6 | LeaveField(id::Post): ref: 0
7 | EnterField(description::Post): ref: 1
8 | LeaveField(description::Post): ref: 1
9 | LeaveSelectionSet(Post): ref: 1
10 | LeaveField(posts::Query): ref: 5
11 | LeaveSelectionSet(Query): ref: 2
12 | LeaveOperationDefinition(PostsUserQuery): ref: 0
13 |
14 |
--------------------------------------------------------------------------------
/pkg/astvisitor/simplevisitor_test.go:
--------------------------------------------------------------------------------
1 | package astvisitor
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/TykTechnologies/graphql-go-tools/internal/pkg/unsafeparser"
7 | )
8 |
9 | func BenchmarkSimpleVisitor(b *testing.B) {
10 |
11 | definition := unsafeparser.ParseGraphqlDocumentString(testDefinition)
12 | operation := unsafeparser.ParseGraphqlDocumentString(testOperation)
13 |
14 | visitor := &dummyVisitor{}
15 |
16 | walker := NewSimpleWalker(48)
17 | walker.SetVisitor(visitor)
18 |
19 | b.ResetTimer()
20 | b.ReportAllocs()
21 |
22 | for i := 0; i < b.N; i++ {
23 | must(walker.Walk(&operation, &definition))
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/pkg/engine/datasource/introspection_datasource/factory.go:
--------------------------------------------------------------------------------
1 | package introspection_datasource
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/TykTechnologies/graphql-go-tools/pkg/engine/plan"
7 | "github.com/TykTechnologies/graphql-go-tools/pkg/introspection"
8 | )
9 |
10 | type Factory struct {
11 | introspectionData *introspection.Data
12 | }
13 |
14 | func NewFactory(introspectionData *introspection.Data) *Factory {
15 | return &Factory{introspectionData: introspectionData}
16 | }
17 |
18 | func (f *Factory) Planner(_ context.Context) plan.DataSourcePlanner {
19 | return &Planner{introspectionData: f.introspectionData}
20 | }
21 |
--------------------------------------------------------------------------------
/pkg/engine/datasource/introspection_datasource/fixtures/enum_values_with_deprecated.golden:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "NEWHOPE",
4 | "description": "",
5 | "isDeprecated": false,
6 | "deprecationReason": null
7 | },
8 | {
9 | "name": "EMPIRE",
10 | "description": "",
11 | "isDeprecated": false,
12 | "deprecationReason": null
13 | },
14 | {
15 | "name": "JEDI",
16 | "description": "",
17 | "isDeprecated": true,
18 | "deprecationReason": "No longer supported"
19 | }
20 | ]
21 |
--------------------------------------------------------------------------------
/pkg/engine/datasource/introspection_datasource/fixtures/enum_values_without_deprecated.golden:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "NEWHOPE",
4 | "description": "",
5 | "isDeprecated": false,
6 | "deprecationReason": null
7 | },
8 | {
9 | "name": "EMPIRE",
10 | "description": "",
11 | "isDeprecated": false,
12 | "deprecationReason": null
13 | }
14 | ]
15 |
--------------------------------------------------------------------------------
/pkg/engine/datasource/introspection_datasource/fixtures/fields_without_deprecated.golden:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "droid",
4 | "description": "",
5 | "args": [
6 | {
7 | "name": "id",
8 | "description": "",
9 | "type": {
10 | "kind": "NON_NULL",
11 | "name": null,
12 | "ofType": {
13 | "kind": "SCALAR",
14 | "name": "ID",
15 | "ofType": null
16 | }
17 | },
18 | "defaultValue": null
19 | }
20 | ],
21 | "type": {
22 | "kind": "OBJECT",
23 | "name": "Droid",
24 | "ofType": null
25 | },
26 | "isDeprecated": false,
27 | "deprecationReason": null
28 | }
29 | ]
30 |
--------------------------------------------------------------------------------
/pkg/engine/datasource/introspection_datasource/fixtures/not_existing_type.golden:
--------------------------------------------------------------------------------
1 | null
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/defer_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "users": [
4 | {
5 | "id": 1,
6 | "name": "Leanne Graham",
7 | "posts": null
8 | },
9 | {
10 | "id": 2,
11 | "name": "Ervin Howell",
12 | "posts": null
13 | }
14 | ]
15 | }
16 | }
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/defer_2.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "replace",
4 | "path": "/data/users/0/posts",
5 | "value": [
6 | {
7 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
8 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
9 | },
10 | {
11 | "title": "qui est esse",
12 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
13 | }
14 | ]
15 | }
16 | ]
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/defer_3.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "replace",
4 | "path": "/data/users/1/posts",
5 | "value": [
6 | {
7 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
8 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
9 | },
10 | {
11 | "title": "qui est esse",
12 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
13 | }
14 | ]
15 | }
16 | ]
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/posts.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "userId": 1,
4 | "id": 1,
5 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
6 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
7 | },
8 | {
9 | "userId": 1,
10 | "id": 2,
11 | "title": "qui est esse",
12 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
13 | }
14 | ]
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/stream_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "users": []
4 | }
5 | }
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/stream_2.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "add",
4 | "path": "/data/users/0",
5 | "value": {
6 | "id": 1,
7 | "name": "Leanne Graham"
8 | }
9 | }
10 | ]
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/stream_3.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "add",
4 | "path": "/data/users/1",
5 | "value": {
6 | "id": 2,
7 | "name": "Ervin Howell"
8 | }
9 | }
10 | ]
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/stream_4.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "users": [
4 | {
5 | "id": 1,
6 | "name": "Leanne Graham"
7 | }
8 | ]
9 | }
10 | }
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/stream_5.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "users": [
4 | {
5 | "id": 1,
6 | "name": "Leanne Graham"
7 | },
8 | {
9 | "id": 2,
10 | "name": "Ervin Howell"
11 | }
12 | ]
13 | }
14 | }
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/stream_6.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "add",
4 | "path": "/data/users/0",
5 | "value": {
6 | "id": 1,
7 | "name": "Leanne Graham",
8 | "posts": null
9 | }
10 | }
11 | ]
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/stream_7.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "add",
4 | "path": "/data/users/1",
5 | "value": {
6 | "id": 2,
7 | "name": "Ervin Howell",
8 | "posts": null
9 | }
10 | }
11 | ]
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/stream_8.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "replace",
4 | "path": "/data/users/0/posts",
5 | "value": [
6 | {
7 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
8 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
9 | },
10 | {
11 | "title": "qui est esse",
12 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
13 | }
14 | ]
15 | }
16 | ]
--------------------------------------------------------------------------------
/pkg/engine/resolve/testdata/stream_9.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "replace",
4 | "path": "/data/users/1/posts",
5 | "value": [
6 | {
7 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
8 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
9 | },
10 | {
11 | "title": "qui est esse",
12 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
13 | }
14 | ]
15 | }
16 | ]
--------------------------------------------------------------------------------
/pkg/escape/bytes.go:
--------------------------------------------------------------------------------
1 | package escape
2 |
3 | func Bytes(in, out []byte) []byte {
4 |
5 | out = out[:0]
6 |
7 | for i := range in {
8 | switch in[i] {
9 | case 9:
10 | out = append(out, 92, 116) // \t
11 | case 10:
12 | out = append(out, 92, 110) // \n
13 | case 34:
14 | if i > 0 && in[i-1] == 92 {
15 | out = append(out, 92, 92, 34) // \\"
16 | } else {
17 | out = append(out, 92, 34) // \"
18 | }
19 | case 92:
20 | // if we have `\\` inside string
21 | if in[i-1] == 92 {
22 | // make 4 in a row
23 | out = append(out, 92, 92, 92)
24 | continue
25 | }
26 | fallthrough
27 | default:
28 | out = append(out, in[i])
29 | }
30 | }
31 |
32 | return out
33 | }
34 |
--------------------------------------------------------------------------------
/pkg/escape/escape.go:
--------------------------------------------------------------------------------
1 | // Package escape enables efficient JSON escaping on byte slices.
2 | package escape
3 |
--------------------------------------------------------------------------------
/pkg/execution/datasource/hooks.go:
--------------------------------------------------------------------------------
1 | package datasource
2 |
3 | import (
4 | "net/http"
5 | )
6 |
7 | type HookContext struct {
8 | TypeName string
9 | FieldName string
10 | }
11 |
12 | type Hooks struct {
13 | PreSendHttpHook PreSendHttpHook
14 | PostReceiveHttpHook PostReceiveHttpHook
15 | }
16 |
17 | type PreSendHttpHook interface {
18 | Execute(ctx HookContext, req *http.Request)
19 | }
20 |
21 | type PostReceiveHttpHook interface {
22 | Execute(ctx HookContext, resp *http.Response, body []byte)
23 | }
24 |
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/directives/graphql_datasource.graphql:
--------------------------------------------------------------------------------
1 | directive @GraphQLDataSource (
2 | """
3 | the host of the origin
4 | """
5 | host: String!
6 | """
7 | the url of the origin
8 | """
9 | url: String!
10 | """
11 | the HTTP method the client should use for the request, defaults to GET
12 | """
13 | method: HTTP_METHOD = POST
14 | """
15 | parameters
16 | """
17 | params: [Parameter]
18 | ) on FIELD_DEFINITION
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/directives/mapping.graphql:
--------------------------------------------------------------------------------
1 | """
2 | mapping is the directive to define mappings from response objects to GraphQL fields
3 | """
4 | directive @mapping(
5 | """
6 | mode defines the operating mode of the mapping
7 | """
8 | mode: MAPPING_MODE! = PATH_SELECTOR
9 | """
10 | pathSelector is the optional selector String to customize the mappings
11 | see https://github.com/tidwall/gjson for more information on what syntax is possible
12 | """
13 | pathSelector: String
14 | ) on FIELD_DEFINITION
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/directives/mqtt_datasource.graphql:
--------------------------------------------------------------------------------
1 | """
2 | MQTTDataSource
3 | """
4 | directive @MQTTDataSource (
5 | brokerAddr: String!
6 | clientID: String!
7 | topic: String!
8 | ) on FIELD_DEFINITION
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/directives/nats_datasource.graphql:
--------------------------------------------------------------------------------
1 | """
2 | NatsDataSource
3 | """
4 | directive @NatsDataSource (
5 | addr: String!
6 | topic: String!
7 | ) on FIELD_DEFINITION
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/directives/static_datasource.graphql:
--------------------------------------------------------------------------------
1 | directive @StaticDataSource (
2 | data: String
3 | ) on FIELD_DEFINITION
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/directives/transformation.graphql:
--------------------------------------------------------------------------------
1 | directive @transformation(
2 | mode: TRANSFORMATION_MODE = PIPELINE
3 | pipelineConfigFile: String
4 | pipelineConfigString: String
5 | ) on FIELD_DEFINITION
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/directives/wasm_datasource.graphql:
--------------------------------------------------------------------------------
1 | directive @WasmDataSource (
2 | input: String!
3 | wasmFile: String!
4 | ) on FIELD_DEFINITION
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/enums/http_method.graphql:
--------------------------------------------------------------------------------
1 | enum HTTP_METHOD {
2 | GET
3 | POST
4 | UPDATE
5 | DELETE
6 | }
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/enums/mapping_mode.graphql:
--------------------------------------------------------------------------------
1 | """
2 | MAPPING_MODE is the enum to define the different mapper modes
3 | """
4 | enum MAPPING_MODE {
5 | """
6 | NONE is the mode to skip mappings at all, therefore the parent object will directly get passed to the child
7 | """
8 | NONE
9 | """
10 | PATH_SELECTOR is the mode which applies a path selector string on the parent object before passing it to the child
11 | see https://github.com/tidwall/gjson for more information on what syntax is possible
12 | """
13 | PATH_SELECTOR
14 | }
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/enums/transformation_mode.graphql:
--------------------------------------------------------------------------------
1 | enum TRANSFORMATION_MODE {
2 | PIPELINE
3 | }
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/inputs/header.graphql:
--------------------------------------------------------------------------------
1 | input Header {
2 | key: String!
3 | value: String!
4 | }
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/inputs/parameter.graphql:
--------------------------------------------------------------------------------
1 | """
2 | Parameter is useful to map variables from various sources into the data source executor.
3 | """
4 | input Parameter {
5 | """
6 | this is the name by which the execution engine will access the variable
7 | """
8 | name: String!
9 | """
10 | the kind of the parameter source
11 | currently sources: the context, the enclosing object (at execution time), field variables
12 | """
13 | sourceKind: PARAMETER_SOURCE!
14 | """
15 | name of the parameter on the source
16 | """
17 | sourceName: String!
18 | """
19 | type name of the variable, used to generate a valid GraphQL query for the upstream
20 | """
21 | variableType: String!
22 | }
--------------------------------------------------------------------------------
/pkg/execution/graphql_definitions/inputs/statuscode_typename_mapping.graphql:
--------------------------------------------------------------------------------
1 | input StatusCodeTypeNameMapping {
2 | statusCode: Int!
3 | typeName: String!
4 | }
--------------------------------------------------------------------------------
/pkg/execution/jsonvaluetype_string.go:
--------------------------------------------------------------------------------
1 | // Code generated by "stringer -type=JSONValueType"; DO NOT EDIT.
2 |
3 | package execution
4 |
5 | import "strconv"
6 |
7 | func _() {
8 | // An "invalid array index" compiler error signifies that the constant values have changed.
9 | // Re-run the stringer command to generate them again.
10 | var x [1]struct{}
11 | _ = x[UnknownValueType-0]
12 | _ = x[StringValueType-1]
13 | _ = x[IntegerValueType-2]
14 | _ = x[FloatValueType-3]
15 | _ = x[BooleanValueType-4]
16 | }
17 |
18 | const _JSONValueType_name = "UnknownValueTypeStringValueTypeIntegerValueTypeFloatValueTypeBooleanValueType"
19 |
20 | var _JSONValueType_index = [...]uint8{0, 16, 31, 47, 61, 77}
21 |
22 | func (i JSONValueType) String() string {
23 | if i < 0 || i >= JSONValueType(len(_JSONValueType_index)-1) {
24 | return "JSONValueType(" + strconv.FormatInt(int64(i), 10) + ")"
25 | }
26 | return _JSONValueType_name[_JSONValueType_index[i]:_JSONValueType_index[i+1]]
27 | }
28 |
--------------------------------------------------------------------------------
/pkg/execution/testdata/memory.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TykTechnologies/graphql-go-tools/a8e1ade2da8ecd5b85065c3e8c9364057d6b173c/pkg/execution/testdata/memory.wasm
--------------------------------------------------------------------------------
/pkg/execution/testdata/simple_pipeline.json:
--------------------------------------------------------------------------------
1 | {
2 | "steps": [
3 | {
4 | "kind": "NOOP"
5 | }
6 | ]
7 | }
--------------------------------------------------------------------------------
/pkg/execution/transformation.go:
--------------------------------------------------------------------------------
1 | package execution
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/jensneuse/pipeline/pkg/pipe"
7 | )
8 |
9 | type Transformation interface {
10 | Transform(input []byte) ([]byte, error)
11 | }
12 |
13 | type PipelineTransformation struct {
14 | pipeline pipe.Pipeline
15 | buf bytes.Buffer
16 | }
17 |
18 | func (p *PipelineTransformation) Transform(input []byte) ([]byte, error) {
19 | p.buf.Reset()
20 | err := p.pipeline.Run(bytes.NewReader(input), &p.buf)
21 | return p.buf.Bytes(), err
22 | }
23 |
--------------------------------------------------------------------------------
/pkg/federation/sdlmerge/remove_empty_object_type_definition_test.go:
--------------------------------------------------------------------------------
1 | package sdlmerge
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestRemoveEmptyObjectTypeDefinitionDirective(t *testing.T) {
8 | t.Run("remove object definition without fields", func(t *testing.T) {
9 | run(t, newRemoveEmptyObjectTypeDefinition(), `
10 | type Query {
11 | }
12 | type Cat {
13 | name: String!
14 | }
15 | `, `
16 | type Cat {
17 | name: String!
18 | }
19 | `)
20 | })
21 | }
22 |
--------------------------------------------------------------------------------
/pkg/federation/sdlmerge/remove_field_definition_by_directive_test.go:
--------------------------------------------------------------------------------
1 | package sdlmerge
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestRemoveFieldDirective(t *testing.T) {
8 | t.Run("remove field with specified directive", func(t *testing.T) {
9 | run(
10 | t, newRemoveFieldDefinitions("forDelete"),
11 | `
12 | type Dog {
13 | name: String @notForDelete
14 | favoriteToy: String @forDelete
15 | barkVolume: Int
16 | isHousetrained(atOtherHomes: Boolean): Boolean! @forDelete
17 | doesKnowCommand(dogCommand: DogCommand!): Boolean!
18 | }
19 | `,
20 | `
21 | type Dog {
22 | name: String @notForDelete
23 | barkVolume: Int
24 | doesKnowCommand(dogCommand: DogCommand!): Boolean!
25 | }
26 | `)
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/federation/sdlmerge/remove_field_definition_directive_test.go:
--------------------------------------------------------------------------------
1 | package sdlmerge
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestRemoveFieldDefinitionDirective(t *testing.T) {
8 | t.Run("remove specified directive from field definition", func(t *testing.T) {
9 | run(
10 | t,
11 | newRemoveFieldDefinitionDirective("requires", "provides"),
12 | `
13 | type Dog {
14 | name: String!
15 | age: Int!
16 | code: String @requires(fields: "name age")
17 | owner: Owner @provides(fields: "name")
18 | }
19 | `,
20 | `
21 | type Dog {
22 | name: String!
23 | age: Int!
24 | code: String
25 | owner: Owner
26 | }`,
27 | )
28 | })
29 | }
30 |
--------------------------------------------------------------------------------
/pkg/federation/sdlmerge/remove_type_extensions.go:
--------------------------------------------------------------------------------
1 | package sdlmerge
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/pkg/ast"
5 | "github.com/TykTechnologies/graphql-go-tools/pkg/astvisitor"
6 | )
7 |
8 | func newRemoveMergedTypeExtensions() *removeMergedTypeExtensionsVisitor {
9 | return &removeMergedTypeExtensionsVisitor{}
10 | }
11 |
12 | type removeMergedTypeExtensionsVisitor struct {
13 | }
14 |
15 | func (r *removeMergedTypeExtensionsVisitor) Register(walker *astvisitor.Walker) {
16 | walker.RegisterLeaveDocumentVisitor(r)
17 | }
18 |
19 | func (r *removeMergedTypeExtensionsVisitor) LeaveDocument(operation, definition *ast.Document) {
20 | operation.RemoveMergedTypeExtensions()
21 | }
22 |
--------------------------------------------------------------------------------
/pkg/federation/sdlmerge/testdata/validate-subgraph/lack-definition-non-null.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User! @provides(fields: "username")
4 | product: Product!
5 | }
6 |
7 | #type User @key(fields: "id") {
8 | # id: ID! @external
9 | # username: String! @external
10 | # reviews: [Review]
11 | #}
12 |
13 | extend type Product @key(fields: "upc") {
14 | upc: String! @external
15 | reviews: [Review]
16 | }
17 |
--------------------------------------------------------------------------------
/pkg/federation/sdlmerge/testdata/validate-subgraph/lack-definition.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User @provides(fields: "username")
4 | product: Product
5 | }
6 |
7 | #type User @key(fields: "id") {
8 | # id: ID! @external
9 | # username: String! @external
10 | # reviews: [Review]
11 | #}
12 |
13 | extend type Product @key(fields: "upc") {
14 | upc: String! @external
15 | reviews: [Review]
16 | }
17 |
--------------------------------------------------------------------------------
/pkg/federation/sdlmerge/testdata/validate-subgraph/lack-extend-definition-non-null.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User! @provides(fields: "username")
4 | product: Product!
5 | }
6 |
7 | type User @key(fields: "id") {
8 | id: ID! @external
9 | username: String! @external
10 | reviews: [Review]
11 | }
12 |
13 | #extend type Product @key(fields: "upc") {
14 | # @external
15 | # reviews: [Review] }
16 | #}
17 |
--------------------------------------------------------------------------------
/pkg/federation/sdlmerge/testdata/validate-subgraph/lack-extend-definition.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User @provides(fields: "username")
4 | product: Product
5 | }
6 |
7 | type User @key(fields: "id") {
8 | id: ID! @external
9 | username: String! @external
10 | reviews: [Review]
11 | }
12 |
13 | #extend type Product @key(fields: "upc") {
14 | # upc: String! @external
15 | # reviews: [Review]
16 | #}
17 |
18 |
--------------------------------------------------------------------------------
/pkg/federation/sdlmerge/testdata/validate-subgraph/well-defined-non-null.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User! @provides(fields: "username")
4 | product: Product!
5 | }
6 |
7 | type User @key(fields: "id") {
8 | id: ID! @external
9 | username: String! @external
10 | reviews: [Review]
11 | }
12 |
13 | extend type Product @key(fields: "upc") {
14 | upc: String! @external
15 | reviews: [Review]
16 | }
17 |
--------------------------------------------------------------------------------
/pkg/federation/sdlmerge/testdata/validate-subgraph/well-defined.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User @provides(fields: "username")
4 | product: Product
5 | }
6 |
7 | type User @key(fields: "id") {
8 | id: ID! @external
9 | username: String! @external
10 | reviews: [Review]
11 | }
12 |
13 | extend type Product @key(fields: "upc") {
14 | upc: String! @external
15 | reviews: [Review]
16 | }
17 |
--------------------------------------------------------------------------------
/pkg/graphql/lookup.go:
--------------------------------------------------------------------------------
1 | package graphql
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | type TypeFieldLookupKey string
8 |
9 | func CreateTypeFieldLookupKey(typeName string, fieldName string) TypeFieldLookupKey {
10 | return TypeFieldLookupKey(fmt.Sprintf("%s.%s", typeName, fieldName))
11 | }
12 |
13 | func CreateTypeFieldArgumentsLookupMap(typeFieldArgs []TypeFieldArguments) map[TypeFieldLookupKey]TypeFieldArguments {
14 | if len(typeFieldArgs) == 0 {
15 | return nil
16 | }
17 |
18 | lookupMap := make(map[TypeFieldLookupKey]TypeFieldArguments)
19 | for _, currentTypeFieldArgs := range typeFieldArgs {
20 | lookupMap[CreateTypeFieldLookupKey(currentTypeFieldArgs.TypeName, currentTypeFieldArgs.FieldName)] = currentTypeFieldArgs
21 | }
22 |
23 | return lookupMap
24 | }
25 |
--------------------------------------------------------------------------------
/pkg/graphql/response.go:
--------------------------------------------------------------------------------
1 | package graphql
2 |
3 | import (
4 | "encoding/json"
5 | )
6 |
7 | type Response struct {
8 | Errors Errors `json:"errors,omitempty"`
9 | // TODO: Data
10 | // TODO: Extensions
11 | }
12 |
13 | func (r Response) Marshal() ([]byte, error) {
14 | return json.Marshal(r)
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/graphql/subscription.go:
--------------------------------------------------------------------------------
1 | package graphql
2 |
3 | type SubscriptionType int
4 |
5 | const (
6 | // SubscriptionTypeUnknown is for unknown or undefined subscriptions.
7 | SubscriptionTypeUnknown = iota
8 | // SubscriptionTypeSSE is for Server-Sent Events (SSE) subscriptions.
9 | SubscriptionTypeSSE
10 | // SubscriptionTypeGraphQLWS is for subscriptions using a WebSocket connection with
11 | // 'graphql-ws' as protocol.
12 | SubscriptionTypeGraphQLWS
13 | // SubscriptionTypeGraphQLTransportWS is for subscriptions using a WebSocket connection with
14 | // 'graphql-transport-ws' as protocol.
15 | SubscriptionTypeGraphQLTransportWS
16 | )
17 |
--------------------------------------------------------------------------------
/pkg/graphql/types.go:
--------------------------------------------------------------------------------
1 | package graphql
2 |
3 | type (
4 | Type struct {
5 | Name string `json:"name"`
6 | Fields []string `json:"fields"`
7 | }
8 |
9 | RequestFields map[string]struct{}
10 | RequestTypes map[string]RequestFields
11 | )
12 |
--------------------------------------------------------------------------------
/pkg/graphqlerrors/location.go:
--------------------------------------------------------------------------------
1 | package graphqlerrors
2 |
3 | type Location struct {
4 | Line uint32 `json:"line"`
5 | Column uint32 `json:"column"`
6 | }
7 |
--------------------------------------------------------------------------------
/pkg/http/ws_connection_init.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "connection_init",
3 | "payload": {}
4 | }
--------------------------------------------------------------------------------
/pkg/http/ws_start.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "1",
3 | "type": "start",
4 | "payload": {
5 | "variables": {},
6 | "extensions": {},
7 | "operationName": "stream",
8 | "query": "subscription stream {n stream {n datetimen timezonen abbreviationn }n}n"
9 | }
10 | }
--------------------------------------------------------------------------------
/pkg/imports/fixtures/render_result.golden:
--------------------------------------------------------------------------------
1 | #file: testdata/schema.graphql
2 |
3 |
4 | schema {
5 | query: Query
6 | mutation: Mutation
7 | }
8 |
9 |
10 | #file: testdata/scalars/json.graphql
11 |
12 | scalar JSON
13 |
14 |
15 | #file: testdata/types/query.graphql
16 |
17 | type Query {
18 | foo: Foo
19 | }
20 |
21 |
22 | #file: testdata/nested/nested.graphql
23 |
24 |
25 | type Bar {
26 | baz: Int
27 | }
28 |
29 |
30 | #file: testdata/nested2/nested2.graphql
31 |
32 | type Bat {
33 | bar: String
34 | }
35 |
36 |
37 | #file: testdata/deep/deeper/custom_types.graphql
38 |
39 | type Foo {
40 | field: String
41 | }
42 |
--------------------------------------------------------------------------------
/pkg/imports/fixtures/scanner_regex.golden:
--------------------------------------------------------------------------------
1 | {
2 | "RelativePath": "",
3 | "Imports": [
4 | {
5 | "RelativePath": "testdata/regexonly/flat.graphql",
6 | "Imports": null
7 | },
8 | {
9 | "RelativePath": "testdata/regexonly/mutation.graphql",
10 | "Imports": null
11 | },
12 | {
13 | "RelativePath": "testdata/regexonly/query.graphql",
14 | "Imports": null
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/pkg/imports/fixtures/scanner_regex_render.golden:
--------------------------------------------------------------------------------
1 | schema {
2 | query: Query
3 | mutation: Mutation
4 | }
5 | type Mutation {
6 | bar: String
7 | }
8 | type Query {
9 | foo: String
10 | }
11 |
--------------------------------------------------------------------------------
/pkg/imports/fixtures/scanner_result.golden:
--------------------------------------------------------------------------------
1 | {
2 | "RelativePath": "testdata/schema.graphql",
3 | "Imports": [
4 | {
5 | "RelativePath": "testdata/scalars/json.graphql",
6 | "Imports": null
7 | },
8 | {
9 | "RelativePath": "testdata/types/query.graphql",
10 | "Imports": null
11 | },
12 | {
13 | "RelativePath": "testdata/nested/nested.graphql",
14 | "Imports": [
15 | {
16 | "RelativePath": "testdata/nested2/nested2.graphql",
17 | "Imports": null
18 | }
19 | ]
20 | },
21 | {
22 | "RelativePath": "testdata/deep/deeper/custom_types.graphql",
23 | "Imports": null
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/pkg/imports/graphql_file_test.go:
--------------------------------------------------------------------------------
1 | package imports
2 |
3 | import (
4 | "bytes"
5 | "os"
6 | "testing"
7 |
8 | "github.com/jensneuse/diffview"
9 |
10 | "github.com/TykTechnologies/graphql-go-tools/pkg/testing/goldie"
11 | )
12 |
13 | func TestGraphQLFile_Render(t *testing.T) {
14 | scanner := Scanner{}
15 | file, err := scanner.ScanFile("testdata/schema.graphql")
16 | if err != nil {
17 | t.Fatal(err)
18 | }
19 |
20 | out := bytes.Buffer{}
21 | err = file.Render(true, &out)
22 | if err != nil {
23 | t.Fatal(err)
24 | }
25 |
26 | dump := out.Bytes()
27 |
28 | goldie.Assert(t, "render_result", dump, true)
29 | if t.Failed() {
30 | fixture, err := os.ReadFile("./fixtures/render_result.golden")
31 | if err != nil {
32 | t.Fatal(err)
33 | }
34 |
35 | diffview.NewGoland().DiffViewBytes("render_result", fixture, dump)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/pkg/imports/testdata/cycle/a/a.graphql:
--------------------------------------------------------------------------------
1 | #import "../b/b.graphql"
--------------------------------------------------------------------------------
/pkg/imports/testdata/cycle/b/b.graphql:
--------------------------------------------------------------------------------
1 | #import "../a/a.graphql"
--------------------------------------------------------------------------------
/pkg/imports/testdata/deep/deeper/custom_types.graphql:
--------------------------------------------------------------------------------
1 | type Foo {
2 | field: String
3 | }
--------------------------------------------------------------------------------
/pkg/imports/testdata/deep/deeper/non_graphql.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TykTechnologies/graphql-go-tools/a8e1ade2da8ecd5b85065c3e8c9364057d6b173c/pkg/imports/testdata/deep/deeper/non_graphql.txt
--------------------------------------------------------------------------------
/pkg/imports/testdata/import_cycle.graphql:
--------------------------------------------------------------------------------
1 | #import "cycle/a/a.graphql"
--------------------------------------------------------------------------------
/pkg/imports/testdata/nested/nested.graphql:
--------------------------------------------------------------------------------
1 | #import "../nested2/nested2.graphql"
2 |
3 | type Bar {
4 | baz: Int
5 | }
--------------------------------------------------------------------------------
/pkg/imports/testdata/nested2/nested2.graphql:
--------------------------------------------------------------------------------
1 | type Bat {
2 | bar: String
3 | }
--------------------------------------------------------------------------------
/pkg/imports/testdata/regexonly/flat.graphql:
--------------------------------------------------------------------------------
1 | schema {
2 | query: Query
3 | mutation: Mutation
4 | }
--------------------------------------------------------------------------------
/pkg/imports/testdata/regexonly/mutation.graphql:
--------------------------------------------------------------------------------
1 | type Mutation {
2 | bar: String
3 | }
--------------------------------------------------------------------------------
/pkg/imports/testdata/regexonly/query.graphql:
--------------------------------------------------------------------------------
1 | type Query {
2 | foo: String
3 | }
--------------------------------------------------------------------------------
/pkg/imports/testdata/scalars/json.graphql:
--------------------------------------------------------------------------------
1 | scalar JSON
--------------------------------------------------------------------------------
/pkg/imports/testdata/schema.graphql:
--------------------------------------------------------------------------------
1 | #import "scalars/*.graphql"
2 | #import "types/query.graphql"
3 | #import "nested/nested.graphql"
4 | #import "deep/**/*.graphql"
5 |
6 | schema {
7 | query: Query
8 | mutation: Mutation
9 | }
--------------------------------------------------------------------------------
/pkg/imports/testdata/types/mutation.graphql:
--------------------------------------------------------------------------------
1 | type Mutation {
2 | mutateFoo: Foo
3 | }
--------------------------------------------------------------------------------
/pkg/imports/testdata/types/query.graphql:
--------------------------------------------------------------------------------
1 | type Query {
2 | foo: Foo
3 | }
--------------------------------------------------------------------------------
/pkg/introspection/introspection_test.go:
--------------------------------------------------------------------------------
1 | package introspection
2 |
3 | import (
4 | "encoding/json"
5 | "os"
6 | "testing"
7 | )
8 |
9 | func TestIntrospectionSerialization(t *testing.T) {
10 | inputData, err := os.ReadFile("./testdata/swapi_introspection_response.json")
11 | if err != nil {
12 | panic(err)
13 | }
14 |
15 | var data Data
16 |
17 | err = json.Unmarshal(inputData, &data)
18 | if err != nil {
19 | panic(err)
20 | }
21 |
22 | outputData, err := json.MarshalIndent(data, "", " ")
23 | if err != nil {
24 | panic(err)
25 | }
26 |
27 | err = os.WriteFile("./testdata/out_swapi_introspection_response.json", outputData, os.ModePerm)
28 | if err != nil {
29 | panic(err)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/pkg/introspection/testdata/interfaces_implementing_interfaces.graphql:
--------------------------------------------------------------------------------
1 | interface BaseInterface {
2 | fieldOne: String!
3 | }
4 |
5 | interface SecondInterface implements BaseInterface {
6 | fieldOne: String!
7 | fieldTwo: String!
8 | }
9 |
10 | interface ThirdInterface implements SecondInterface & BaseInterface {
11 | fieldOne: String!
12 | fieldTwo: String!
13 | fieldThree: String!
14 | }
15 |
16 | interface IDType {
17 | id: ID!
18 | }
19 |
20 | interface SoftDelete {
21 | deleted: Boolean!
22 | }
23 |
24 | extend interface SoftDelete implements IDType {
25 | id: ID!
26 | }
27 |
28 | interface Record {
29 | data: String!
30 | }
31 |
32 | extend interface Record implements SoftDelete & IDType {
33 | id: ID!
34 | deleted: Boolean!
35 | }
36 |
--------------------------------------------------------------------------------
/pkg/lexer/keyword/keyword.go:
--------------------------------------------------------------------------------
1 | //go:generate stringer -type=Keyword
2 |
3 | // Package keyword contains all possible GraphQL keywords
4 | package keyword
5 |
6 | type Keyword int
7 |
8 | const (
9 | UNDEFINED Keyword = iota
10 | IDENT
11 | COMMENT
12 | EOF
13 |
14 | COLON
15 | BANG
16 | LT
17 | TAB
18 | SPACE
19 | COMMA
20 | AT
21 | DOT
22 | SPREAD
23 | PIPE
24 | SLASH
25 | EQUALS
26 | SUB
27 | AND
28 | QUOTE
29 |
30 | DOLLAR
31 | STRING
32 | BLOCKSTRING
33 | INTEGER
34 | FLOAT
35 |
36 | LPAREN
37 | RPAREN
38 | LBRACK
39 | RBRACK
40 | LBRACE
41 | RBRACE
42 | )
43 |
--------------------------------------------------------------------------------
/pkg/lexer/runes/runes.go:
--------------------------------------------------------------------------------
1 | // Package runes contains all possible 'special' runes in a GraphQL document
2 | package runes
3 |
4 | const (
5 | EOF = 0
6 | COLON = ':'
7 | BANG = '!'
8 | CARRIAGERETURN = '\r'
9 | LINETERMINATOR = '\n'
10 | TAB = '\t'
11 | SPACE = ' '
12 | COMMA = ','
13 | HASHTAG = '#'
14 | QUOTE = '"'
15 | BACKSLASH = '\\'
16 | DOT = '.'
17 | EXPONENT_LOWER = 'e'
18 | EXPONENT_UPPER = 'E'
19 | AT = '@'
20 | DOLLAR = '$'
21 | PIPE = '|'
22 | SLASH = '/'
23 | EQUALS = '='
24 | SUB = '-'
25 | ADD = '+'
26 | AND = '&'
27 | UNDERSCORE = '_'
28 |
29 | LPAREN = '('
30 | RPAREN = ')'
31 | LBRACK = '['
32 | RBRACK = ']'
33 | LBRACE = '{'
34 | RBRACE = '}'
35 | )
36 |
--------------------------------------------------------------------------------
/pkg/middleware/middleware.go:
--------------------------------------------------------------------------------
1 | // Package middleware contains useful middleware components for GraphQL services, e.g. for complexity analysis.
2 | package middleware
3 |
--------------------------------------------------------------------------------
/pkg/playground/files/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TykTechnologies/graphql-go-tools/a8e1ade2da8ecd5b85065c3e8c9364057d6b173c/pkg/playground/files/favicon.png
--------------------------------------------------------------------------------
/pkg/playground/files/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TykTechnologies/graphql-go-tools/a8e1ade2da8ecd5b85065c3e8c9364057d6b173c/pkg/playground/files/logo.png
--------------------------------------------------------------------------------
/pkg/playground/files/playground.css:
--------------------------------------------------------------------------------
1 | body{margin:0;padding:0;font-family:sans-serif;overflow:hidden}#root{height:100%}body{font-family:Open Sans,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:rgba(0,0,0,.8);line-height:1.5;height:100vh;letter-spacing:.53px;margin-right:-1px!important}a,body,code,h1,h2,h3,h4,html,p,pre,ul{margin:0;padding:0;color:inherit}a:active,a:focus,button:focus,input:focus{outline:none}button,input,submit{border:none}button,input,pre{font-family:Open Sans,sans-serif}code{font-family:Consolas,monospace}
--------------------------------------------------------------------------------
/pkg/playground/fixtures/handlers.golden:
--------------------------------------------------------------------------------
1 | (playground.Handlers) (len=5 cap=5) {
2 | (playground.HandlerConfig) {
3 | Path: (string) (len=11) "/playground",
4 | Handler: (http.HandlerFunc)
5 | },
6 | (playground.HandlerConfig) {
7 | Path: (string) (len=26) "/playground/playground.css",
8 | Handler: (http.HandlerFunc)
9 | },
10 | (playground.HandlerConfig) {
11 | Path: (string) (len=25) "/playground/playground.js",
12 | Handler: (http.HandlerFunc)
13 | },
14 | (playground.HandlerConfig) {
15 | Path: (string) (len=23) "/playground/favicon.png",
16 | Handler: (http.HandlerFunc)
17 | },
18 | (playground.HandlerConfig) {
19 | Path: (string) (len=20) "/playground/logo.png",
20 | Handler: (http.HandlerFunc)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pkg/pool/bytesbuffer.go:
--------------------------------------------------------------------------------
1 | package pool
2 |
3 | import (
4 | "bytes"
5 | "sync"
6 | )
7 |
8 | var (
9 | BytesBuffer = bytesBufferPool{
10 | pool: sync.Pool{
11 | New: func() interface{} {
12 | return bytes.NewBuffer(make([]byte, 0, 1024))
13 | },
14 | },
15 | }
16 | )
17 |
18 | type bytesBufferPool struct {
19 | pool sync.Pool
20 | }
21 |
22 | func (b *bytesBufferPool) Get() *bytes.Buffer {
23 | return b.pool.Get().(*bytes.Buffer)
24 | }
25 |
26 | func (b *bytesBufferPool) Put(buf *bytes.Buffer) {
27 | buf.Reset()
28 | b.pool.Put(buf)
29 | }
30 |
--------------------------------------------------------------------------------
/pkg/pool/fastbuffer.go:
--------------------------------------------------------------------------------
1 | package pool
2 |
3 | import (
4 | "sync"
5 |
6 | "github.com/TykTechnologies/graphql-go-tools/pkg/fastbuffer"
7 | )
8 |
9 | var FastBuffer = fastBufferPool{
10 | pool: sync.Pool{
11 | New: func() interface{} {
12 | return fastbuffer.New()
13 | },
14 | },
15 | }
16 |
17 | type fastBufferPool struct {
18 | pool sync.Pool
19 | }
20 |
21 | func (f *fastBufferPool) Get() *fastbuffer.FastBuffer {
22 | return f.pool.Get().(*fastbuffer.FastBuffer)
23 | }
24 |
25 | func (f *fastBufferPool) Put(buf *fastbuffer.FastBuffer) {
26 | buf.Reset()
27 | f.pool.Put(buf)
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/pool/hash64.go:
--------------------------------------------------------------------------------
1 | package pool
2 |
3 | import (
4 | "hash"
5 | "sync"
6 |
7 | "github.com/cespare/xxhash/v2"
8 | )
9 |
10 | var (
11 | Hash64 = hash64Pool{
12 | pool: sync.Pool{
13 | New: func() interface{} {
14 | return xxhash.New()
15 | },
16 | },
17 | }
18 | )
19 |
20 | type hash64Pool struct {
21 | pool sync.Pool
22 | }
23 |
24 | func (b *hash64Pool) Get() hash.Hash64 {
25 | return b.pool.Get().(hash.Hash64)
26 | }
27 |
28 | func (b *hash64Pool) Put(hash64 hash.Hash64) {
29 | hash64.Reset()
30 | b.pool.Put(hash64)
31 | }
32 |
--------------------------------------------------------------------------------
/pkg/repair/repair.go:
--------------------------------------------------------------------------------
1 | // Package repair helps fixing problems in GraphQL documents
2 | package repair
3 |
--------------------------------------------------------------------------------
/pkg/starwars/testdata/mutations/create_review.mutation:
--------------------------------------------------------------------------------
1 | mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
2 | createReview(episode: $ep, review: $review) {
3 | id
4 | stars
5 | commentary
6 | }
7 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/directives_include.query:
--------------------------------------------------------------------------------
1 | query Hero($withFriends: Boolean!) {
2 | hero {
3 | name
4 | friends @include(if: $withFriends) {
5 | name
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/directives_skip.query:
--------------------------------------------------------------------------------
1 | query Hero($skipFriends: Boolean!) {
2 | hero {
3 | name
4 | friends @skip(if: $skipFriends) {
5 | name
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/droid_with_arg.query:
--------------------------------------------------------------------------------
1 | {
2 | droid(id: "R2D2") {
3 | name
4 | }
5 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/droid_with_arg_and_var.query:
--------------------------------------------------------------------------------
1 | query Droid($droidID: ID!) {
2 | droid(id: $droidID) {
3 | name
4 | }
5 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/fragments.query:
--------------------------------------------------------------------------------
1 | query Fragments($droidID: ID!){
2 | hero {
3 | ...characterFields
4 | }
5 | droid(id: $droidID) {
6 | ...characterFields
7 | }
8 | }
9 |
10 | fragment characterFields on Character {
11 | name
12 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/hero_with_aliases.query:
--------------------------------------------------------------------------------
1 | {
2 | empireHero: hero {
3 | name
4 | }
5 | jediHero: hero {
6 | name
7 | }
8 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/hero_with_operation_name.query:
--------------------------------------------------------------------------------
1 | query Hero {
2 | hero {
3 | name
4 | }
5 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/inline_fragments.query:
--------------------------------------------------------------------------------
1 | {
2 | hero {
3 | friends {
4 | ...on Droid {
5 | name
6 | primaryFunction
7 | }
8 | ...on Human {
9 | name
10 | height
11 | }
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/interface_fragments_on_union.graphql:
--------------------------------------------------------------------------------
1 | query SearchResults {
2 | searchResults {
3 | ...on Character {
4 | name
5 | }
6 | ...on Vehicle {
7 | length
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/invalid.query:
--------------------------------------------------------------------------------
1 | {
2 | hero {
3 | invalid
4 | }
5 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/invalid_fragments.query:
--------------------------------------------------------------------------------
1 | query Fragments($droidID: ID!){
2 | droid(id: $droidID) {
3 | ...reviewFields
4 | }
5 | }
6 |
7 | fragment reviewFields on Review {
8 | id
9 | stars
10 | commentary
11 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/multi_queries.query:
--------------------------------------------------------------------------------
1 | query MultiHeroes {
2 | empireHero: hero {
3 | name
4 | }
5 | jediHero: hero {
6 | name
7 | }
8 | }
9 |
10 | query SingleHero {
11 | hero {
12 | name
13 | }
14 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/multi_queries_with_arguments.query:
--------------------------------------------------------------------------------
1 | query GetDroid {
2 | droid(id: "1") {
3 | name
4 | }
5 | }
6 |
7 | query Search {
8 | search(name: "C3PO") {
9 | ...on Droid {
10 | name
11 | primaryFunction
12 | }
13 | ...on Human {
14 | name
15 | height
16 | }
17 | ...on Starship {
18 | name
19 | length
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/simple_hero.query:
--------------------------------------------------------------------------------
1 | {
2 | hero {
3 | name
4 | }
5 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/queries/union.query:
--------------------------------------------------------------------------------
1 | query Search($name: String!) {
2 | search(name: $name) {
3 | ...on Droid {
4 | name
5 | primaryFunction
6 | }
7 | ...on Human {
8 | name
9 | height
10 | }
11 | ...on Starship {
12 | name
13 | length
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/pkg/starwars/testdata/subscriptions/remaining_jedis.subscription:
--------------------------------------------------------------------------------
1 | subscription {
2 | remainingJedis
3 | }
--------------------------------------------------------------------------------
/pkg/subscription/constants.go:
--------------------------------------------------------------------------------
1 | package subscription
2 |
3 | const (
4 | DefaultKeepAliveInterval = "15s"
5 | DefaultSubscriptionUpdateInterval = "1s"
6 | DefaultReadErrorTimeOut = "5s"
7 | DefaultSubscriptionExecutionTries = 5
8 | )
9 |
--------------------------------------------------------------------------------
/pkg/subscription/executor.go:
--------------------------------------------------------------------------------
1 | package subscription
2 |
3 | //go:generate mockgen -destination=executor_mock_test.go -package=subscription . Executor,ExecutorPool
4 |
5 | import (
6 | "context"
7 |
8 | "github.com/TykTechnologies/graphql-go-tools/pkg/ast"
9 | "github.com/TykTechnologies/graphql-go-tools/pkg/engine/resolve"
10 | )
11 |
12 | // Executor is an abstraction for executing a GraphQL engine
13 | type Executor interface {
14 | Execute(writer resolve.FlushWriter) error
15 | OperationType() ast.OperationType
16 | SetContext(context context.Context)
17 | Reset()
18 | }
19 |
20 | // ExecutorPool is an abstraction for creating executors
21 | type ExecutorPool interface {
22 | Get(payload []byte) (Executor, error)
23 | Put(executor Executor) error
24 | }
25 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/accounts/graph/handler.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/99designs/gqlgen/graphql/handler"
7 | "github.com/99designs/gqlgen/graphql/handler/debug"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/pkg/testing/federationtesting/accounts/graph/generated"
10 | )
11 |
12 | type EndpointOptions struct {
13 | EnableDebug bool
14 | }
15 |
16 | var TestOptions = EndpointOptions{
17 | EnableDebug: false,
18 | }
19 |
20 | func GraphQLEndpointHandler(opts EndpointOptions) http.Handler {
21 | srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &Resolver{}}))
22 | if opts.EnableDebug {
23 | srv.Use(&debug.Tracer{})
24 | }
25 |
26 | return srv
27 | }
28 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/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 | type Resolver struct{}
7 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/accounts/graph/wallets.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/pkg/testing/federationtesting/accounts/graph/model"
4 |
5 | var walletOne = &model.WalletType1{
6 | Currency: "USD",
7 | Amount: 123,
8 | SpecialField1: "some special value 1",
9 | }
10 |
11 | var walletTwo = &model.WalletType2{
12 | Currency: "USD",
13 | Amount: 123,
14 | SpecialField2: "some special value 2",
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/accounts/handler.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package accounts
3 |
4 | import (
5 | "net/http"
6 |
7 | "github.com/TykTechnologies/graphql-go-tools/pkg/testing/federationtesting/accounts/graph"
8 | )
9 |
10 | func Handler() http.Handler {
11 | return graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true})
12 | }
13 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/products/graph/model/models_gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
2 |
3 | package model
4 |
5 | type Product struct {
6 | Upc string `json:"upc"`
7 | Name string `json:"name"`
8 | Price int `json:"price"`
9 | InStock int `json:"inStock"`
10 | }
11 |
12 | func (Product) IsEntity() {}
13 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/products/graph/products.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/pkg/testing/federationtesting/products/graph/model"
5 | )
6 |
7 | var hats []*model.Product
8 |
9 | func Reset() {
10 | hats = []*model.Product{
11 | {
12 | Upc: "top-1",
13 | Name: "Trilby",
14 | Price: 11,
15 | InStock: 500,
16 | },
17 | {
18 | Upc: "top-2",
19 | Name: "Fedora",
20 | Price: 22,
21 | InStock: 1200,
22 | },
23 | {
24 | Upc: "top-3",
25 | Name: "Boater",
26 | Price: 33,
27 | InStock: 850,
28 | },
29 | }
30 | }
31 |
32 | func init() {
33 | Reset()
34 | }
35 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/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 | import (
7 | "time"
8 | )
9 |
10 | type Resolver struct {
11 | updateInterval time.Duration
12 | }
13 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/products/graph/schema.graphqls:
--------------------------------------------------------------------------------
1 | extend type Query {
2 | topProducts(first: Int = 5): [Product]
3 | }
4 |
5 | extend type Subscription {
6 | updatedPrice: Product!
7 | updateProductPrice(upc: String!): Product!
8 | }
9 |
10 | type Product @key(fields: "upc") {
11 | upc: String!
12 | name: String!
13 | price: Int!
14 | inStock: Int!
15 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/products/graph/variables.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | var (
8 | randomnessEnabled = true
9 | minPrice = 10
10 | maxPrice = 1499
11 | currentPrice = minPrice
12 | updateInterval = time.Second
13 | )
14 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/products/handler.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package products
3 |
4 | import (
5 | "net/http"
6 |
7 | "github.com/TykTechnologies/graphql-go-tools/pkg/testing/federationtesting/products/graph"
8 | )
9 |
10 | func Handler() http.Handler {
11 | mux := http.NewServeMux()
12 |
13 | mux.Handle("/", graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true}))
14 | mux.HandleFunc("/websocket_connections", graph.WebsocketConnectionsHandler)
15 |
16 | return mux
17 | }
18 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/reviews/graph/attachments.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/pkg/testing/federationtesting/reviews/graph/model"
4 |
5 | var attachments = []model.Attachment{
6 | model.Question{
7 | Upc: "top-1",
8 | Body: "How do I turn it on?",
9 | },
10 | model.Question{
11 | Upc: "top-3",
12 | Body: "Any recommendations for other teacosies?",
13 | },
14 | model.Rating{
15 | Upc: "top-2",
16 | Body: "The best hat I have ever bought in my life.",
17 | Score: 5,
18 | },
19 | model.Rating{
20 | Upc: "top-3",
21 | Body: "Terrible teacosy!!!",
22 | Score: 0,
23 | },
24 | model.Video{
25 | Upc: "top-2",
26 | Size: 13.37,
27 | },
28 | model.Video{
29 | Upc: "top-3",
30 | Size: 4.20,
31 | },
32 | }
33 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/reviews/graph/handler.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/99designs/gqlgen/graphql/handler"
7 | "github.com/99designs/gqlgen/graphql/handler/debug"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/pkg/testing/federationtesting/reviews/graph/generated"
10 | )
11 |
12 | type EndpointOptions struct {
13 | EnableDebug bool
14 | }
15 |
16 | var TestOptions = EndpointOptions{
17 | EnableDebug: false,
18 | }
19 |
20 | func GraphQLEndpointHandler(opts EndpointOptions) http.Handler {
21 | srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &Resolver{}}))
22 | if opts.EnableDebug {
23 | srv.Use(&debug.Tracer{})
24 | }
25 |
26 | return srv
27 | }
28 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/reviews/graph/model/models.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | type Product struct {
4 | Upc string `json:"upc"`
5 | }
6 |
7 | func (Product) IsEntity() {}
8 |
9 | type Review struct {
10 | Body string
11 | Author *User
12 | Product *Product
13 | }
14 |
15 | type User struct {
16 | ID string `json:"id"`
17 | }
18 |
19 | func (User) IsEntity() {}
20 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/reviews/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 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/reviews/graph/reviews.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/pkg/testing/federationtesting/reviews/graph/model"
5 | )
6 |
7 | var reviews = []*model.Review{
8 | {
9 | Body: "A highly effective form of birth control.",
10 | Product: &model.Product{Upc: "top-1"},
11 | Author: &model.User{ID: "1234"},
12 | },
13 | {
14 | Body: "Fedoras are one of the most fashionable hats around and can look great with a variety of outfits.",
15 | Product: &model.Product{Upc: "top-2"},
16 | Author: &model.User{ID: "1234"},
17 | },
18 | {
19 | Body: "This is the last straw. Hat you will wear. 11/10",
20 | Product: &model.Product{Upc: "top-3"},
21 | Author: &model.User{ID: "7777"},
22 | },
23 | }
24 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/reviews/handler.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package reviews
3 |
4 | import (
5 | "net/http"
6 |
7 | "github.com/TykTechnologies/graphql-go-tools/pkg/testing/federationtesting/reviews/graph"
8 | )
9 |
10 | func Handler() http.Handler {
11 | return graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true})
12 | }
13 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/mutations/mutation_with_variables.query:
--------------------------------------------------------------------------------
1 | mutation AddReview($authorID: String!, $upc: String!, $review: String!) {
2 | addReview(authorID: $authorID upc: $upc, review: $review) {
3 | body
4 | author {
5 | username
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/interface.query:
--------------------------------------------------------------------------------
1 | query MyHistory {
2 | me {
3 | username
4 | history {
5 | ... on Purchase {
6 | wallet {
7 | amount
8 | ... on WalletType1 {
9 | specialField1
10 | }
11 | ... on WalletType2 {
12 | specialField2
13 | }
14 | }
15 | }
16 | ... on Sale {
17 | rating
18 | }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/interface_fragment_on_object.graphql:
--------------------------------------------------------------------------------
1 | query InterfaceFragment {
2 | me {
3 | ... on Identifiable {
4 | id
5 | }
6 | ... on User {
7 | username
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/interface_fragments_on_union.graphql:
--------------------------------------------------------------------------------
1 | query InterfaceFragmentsOnUnion {
2 | histories {
3 | ... on Store {
4 | __typename
5 | location
6 | }
7 | ... on Info {
8 | __typename
9 | quantity
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/merged_field.graphql:
--------------------------------------------------------------------------------
1 | query MergedField {
2 | cat {
3 | name
4 | }
5 | me {
6 | id
7 | username
8 | realName
9 | reviews {
10 | body
11 | }
12 | history {
13 | ... on Sale {
14 | rating
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/multiple_queries.query:
--------------------------------------------------------------------------------
1 | query {
2 | topProducts {
3 | __typename
4 | price
5 | upc
6 | }
7 | me {
8 | __typename
9 | id
10 | username
11 | }
12 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/multiple_queries_with_nested_fragments.query:
--------------------------------------------------------------------------------
1 | fragment ProductFragment on Product {
2 | __typename
3 | price
4 | upc
5 | }
6 |
7 | fragment ReviewFragment on Review {
8 | __typename
9 | product {
10 | ...ProductFragment
11 | }
12 | }
13 |
14 | fragment UserFragment on User {
15 | __typename
16 | id
17 | username
18 | reviews {
19 | ...ReviewFragment
20 | }
21 | }
22 |
23 | query {
24 | topProducts {
25 | ...ProductFragment
26 | }
27 | me {
28 | ...UserFragment
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/multiple_queries_with_union_return.query:
--------------------------------------------------------------------------------
1 | query Histories {
2 | me {
3 | __typename
4 | id
5 | username
6 | }
7 | histories {
8 | __typename
9 | ... on Sale {
10 | product {
11 | __typename
12 | upc
13 | }
14 | rating
15 | }
16 | ... on Purchase {
17 | product {
18 | __typename
19 | upc
20 | }
21 | wallet {
22 | __typename
23 | currency
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/multiple_upstream.query:
--------------------------------------------------------------------------------
1 | query MultipleServers {
2 | topProducts {
3 | name
4 | reviews {
5 | body
6 | author {
7 | username
8 | }
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/object_fragment_on_interface.graphql:
--------------------------------------------------------------------------------
1 | query InterfaceResponse {
2 | identifiable {
3 | __typename
4 | id
5 | ... on User {
6 | username
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/single_upstream.query:
--------------------------------------------------------------------------------
1 | query Me {
2 | me {
3 | id
4 | username
5 | }
6 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/queries/union.query:
--------------------------------------------------------------------------------
1 | query MyHistory {
2 | me {
3 | username
4 | history {
5 | __typename
6 | ... on Purchase {
7 | wallet {
8 | amount
9 | }
10 | }
11 | ... on Sale {
12 | rating
13 | }
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/pkg/testing/federationtesting/testdata/subscriptions/subscription.query:
--------------------------------------------------------------------------------
1 | subscription UpdatePrice($upc: String!) {
2 | updateProductPrice(upc: $upc) {
3 | upc
4 | name
5 | price
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/pkg/testing/goldie/goldie.go:
--------------------------------------------------------------------------------
1 | package goldie
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/sebdah/goldie/v2"
7 | )
8 |
9 | // New creates a new instance of Goldie.
10 | func New(t *testing.T) *goldie.Goldie {
11 | return goldie.New(t, goldie.WithFixtureDir("fixtures"))
12 | }
13 |
--------------------------------------------------------------------------------
/pkg/testing/goldie/goldie_posix.go:
--------------------------------------------------------------------------------
1 | //go:build !windows
2 | // +build !windows
3 |
4 | package goldie
5 |
6 | import (
7 | "testing"
8 | )
9 |
10 | func Assert(t *testing.T, name string, actual []byte, _ ...bool) {
11 | t.Helper()
12 |
13 | New(t).Assert(t, name, actual)
14 | }
15 |
16 | func Update(t *testing.T, name string, actual []byte) {
17 | t.Helper()
18 |
19 | _ = New(t).Update(t, name, actual)
20 | }
21 |
--------------------------------------------------------------------------------
/pkg/testing/goldie/goldie_win.go:
--------------------------------------------------------------------------------
1 | //go:build windows
2 | // +build windows
3 |
4 | package goldie
5 |
6 | import (
7 | "testing"
8 | )
9 |
10 | func Assert(t *testing.T, name string, actual []byte, useOSSuffix ...bool) {
11 | t.Helper()
12 |
13 | if len(useOSSuffix) == 1 && useOSSuffix[0] {
14 | name = name + "_windows"
15 | }
16 |
17 | New(t).Assert(t, name, actual)
18 | }
19 |
20 | func Update(t *testing.T, name string, actual []byte) {
21 | t.Helper()
22 | t.Fatalf("golden files should not be updated on windows")
23 | }
24 |
--------------------------------------------------------------------------------
/pkg/testing/subscriptiontesting/.gqlgen.yml:
--------------------------------------------------------------------------------
1 | models:
2 | Chatroom:
3 | model: github.com/TykTechnologies/graphql-go-tools/pkg/testing/subscriptiontesting.Chatroom
4 |
--------------------------------------------------------------------------------
/pkg/testing/subscriptiontesting/handler.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package subscriptiontesting
3 |
4 | import (
5 | "net/http"
6 | "time"
7 |
8 | "github.com/99designs/gqlgen/graphql/handler"
9 | "github.com/99designs/gqlgen/graphql/handler/extension"
10 | "github.com/99designs/gqlgen/graphql/handler/transport"
11 | "github.com/gorilla/websocket"
12 | )
13 |
14 | func ChatGraphQLEndpointHandler() http.Handler {
15 | srv := handler.New(NewExecutableSchema(New()))
16 |
17 | srv.AddTransport(transport.POST{})
18 | srv.AddTransport(transport.Websocket{
19 | KeepAlivePingInterval: 10 * time.Second,
20 | Upgrader: websocket.Upgrader{
21 | CheckOrigin: func(r *http.Request) bool {
22 | return true
23 | },
24 | },
25 | })
26 | srv.Use(extension.Introspection{})
27 |
28 | return srv
29 | }
30 |
--------------------------------------------------------------------------------
/pkg/testing/subscriptiontesting/models_gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
2 |
3 | package subscriptiontesting
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 | }
15 |
--------------------------------------------------------------------------------
/pkg/testing/subscriptiontesting/schema.graphql:
--------------------------------------------------------------------------------
1 | type Chatroom {
2 | name: String!
3 | messages: [Message!]!
4 | }
5 |
6 | type Message {
7 | id: ID!
8 | text: String!
9 | createdBy: String!
10 | createdAt: Time!
11 | }
12 |
13 | type Query {
14 | room(name:String!): Chatroom
15 | }
16 |
17 | type Mutation {
18 | post(text: String!, username: String!, roomName: String!): Message!
19 | }
20 |
21 | type Subscription {
22 | messageAdded(roomName: String!): Message!
23 | }
24 |
25 | scalar Time
26 |
27 | directive @user(username: String!) on SUBSCRIPTION
28 |
--------------------------------------------------------------------------------
/v2/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TykTechnologies/graphql-go-tools/a8e1ade2da8ecd5b85065c3e8c9364057d6b173c/v2/assets/logo.png
--------------------------------------------------------------------------------
/v2/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 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/v2/examples/chat/.gqlgen.yml:
--------------------------------------------------------------------------------
1 | models:
2 | Chatroom:
3 | model: github.com/TykTechnologies/graphql-go-tools/v2/examples/chat.Chatroom
4 |
--------------------------------------------------------------------------------
/v2/examples/chat/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/TykTechnologies/graphql-go-tools/v2/examples/chat
2 |
3 | go 1.18
4 |
5 | require (
6 | github.com/99designs/gqlgen v0.13.0
7 | github.com/gorilla/websocket v1.4.2
8 | github.com/rs/cors v1.7.0
9 | github.com/stretchr/testify v1.7.0
10 | github.com/vektah/gqlparser/v2 v2.2.0
11 | )
12 |
13 | require (
14 | github.com/agnivade/levenshtein v1.0.3 // indirect
15 | github.com/davecgh/go-spew v1.1.1 // indirect
16 | github.com/hashicorp/golang-lru v0.5.0 // indirect
17 | github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 // indirect
18 | github.com/pmezard/go-difflib v1.0.0 // indirect
19 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
20 | )
21 |
--------------------------------------------------------------------------------
/v2/examples/chat/handler.go:
--------------------------------------------------------------------------------
1 | package chat
2 |
3 | import (
4 | "net/http"
5 | "time"
6 |
7 | "github.com/99designs/gqlgen/graphql/handler"
8 | "github.com/99designs/gqlgen/graphql/handler/extension"
9 | "github.com/99designs/gqlgen/graphql/handler/transport"
10 | "github.com/gorilla/websocket"
11 | )
12 |
13 | func GraphQLEndpointHandler() http.Handler {
14 | srv := handler.New(NewExecutableSchema(New()))
15 |
16 | srv.AddTransport(transport.POST{})
17 | srv.AddTransport(transport.Websocket{
18 | KeepAlivePingInterval: 10 * time.Second,
19 | Upgrader: websocket.Upgrader{
20 | CheckOrigin: func(r *http.Request) bool {
21 | return true
22 | },
23 | },
24 | })
25 | srv.Use(extension.Introspection{})
26 |
27 | return srv
28 | }
29 |
--------------------------------------------------------------------------------
/v2/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 | }
15 |
--------------------------------------------------------------------------------
/v2/examples/chat/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | React App
8 |
9 |
10 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/v2/examples/chat/readme.md:
--------------------------------------------------------------------------------
1 | # Chat Demo
2 |
3 | ## Getting started
4 | 1. Install go modules & npm dependencies
5 | ```shell
6 | go mod download
7 | npm i
8 | ```
9 | 2. Start server and start react client
10 | ```
11 | chmod +x start-server.sh
12 | ./start-server.sh
13 | npm run start
14 | ```
15 |
16 | Example is forked from: [gqlgen](https://github.com/99designs/gqlgen/tree/master/example/chat)
17 |
18 | ## Example(s)
19 | ```graphql
20 | mutation SendMessage {
21 | post(roomName: "#test", username: "me", text: "hello!") {
22 | ...MessageData
23 | }
24 | }
25 |
26 | query GetMessages {
27 | room(name:"#test") {
28 | name
29 | messages {
30 | ...MessageData
31 | }
32 | }
33 | }
34 |
35 | subscription LiveMessages {
36 | messageAdded(roomName: "#test") {
37 | ...MessageData
38 | }
39 | }
40 |
41 | fragment MessageData on Message{
42 | id
43 | text
44 | createdBy
45 | createdAt
46 | }
47 | ```
--------------------------------------------------------------------------------
/v2/examples/chat/schema.graphql:
--------------------------------------------------------------------------------
1 | type Chatroom {
2 | name: String!
3 | messages: [Message!]!
4 | }
5 |
6 | type Message {
7 | id: ID!
8 | text: String!
9 | createdBy: String!
10 | createdAt: Time!
11 | }
12 |
13 | type Query {
14 | room(name:String!): Chatroom
15 | }
16 |
17 | type Mutation {
18 | post(text: String!, username: String!, roomName: String!): Message!
19 | }
20 |
21 | type Subscription {
22 | messageAdded(roomName: String!): Message!
23 | }
24 |
25 | scalar Time
26 |
27 | directive @user(username: String!) on SUBSCRIPTION
28 |
--------------------------------------------------------------------------------
/v2/examples/chat/server/server.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "net/http"
6 |
7 | "github.com/99designs/gqlgen/graphql/playground"
8 | "github.com/rs/cors"
9 |
10 | "github.com/TykTechnologies/graphql-go-tools/v2/examples/chat"
11 | )
12 |
13 | func main() {
14 | c := cors.New(cors.Options{
15 | AllowedOrigins: []string{"http://localhost:3080", "http://localhost:3000"},
16 | AllowCredentials: true,
17 | })
18 |
19 | http.Handle("/", playground.Handler("Chat", "/query"))
20 | http.Handle("/query", c.Handler(chat.GraphQLEndpointHandler()))
21 |
22 | log.Println("Playground running on: http://localhost:8085")
23 | log.Println("Send operations to: http://localhost:8085/query")
24 | log.Fatal(http.ListenAndServe(":8085", nil))
25 | }
26 |
--------------------------------------------------------------------------------
/v2/examples/chat/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import styled from 'styled-components';
3 | import { Room } from './Room';
4 |
5 | const Input = styled.div`
6 | padding: 4px;
7 | margin: 0 0 4px;
8 |
9 | input {
10 | border: 1px solid #ccc;
11 | padding: 2px;
12 | font-size: 14px;
13 | }
14 | `;
15 |
16 | export const App = () => {
17 | const [name, setName] = useState('tester');
18 | const [channel, setChannel] = useState('#gophers');
19 |
20 | return (
21 | <>
22 |
23 | name: setName(e.target.value)} />
24 |
25 |
26 | channel: setChannel(e.target.value)} />
27 |
28 |
29 |
30 | >
31 | );
32 |
33 | };
34 |
--------------------------------------------------------------------------------
/v2/examples/chat/start-server.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | go build -o /tmp/srv-chat ./server
4 | /tmp/srv-chat
5 |
--------------------------------------------------------------------------------
/v2/examples/federation/README.md:
--------------------------------------------------------------------------------
1 | # Federation Demo
2 |
3 | ## Getting started
4 | 1. Install go modules
5 | ```shell
6 | go mod download
7 | ```
8 | 2. Run start script
9 | ```
10 | chmod +x start.sh
11 | ./start.sh
12 | ```
--------------------------------------------------------------------------------
/v2/examples/federation/accounts/graph/handler.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/99designs/gqlgen/graphql/handler"
7 | "github.com/99designs/gqlgen/graphql/handler/debug"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/v2/examples/federation/accounts/graph/generated"
10 | )
11 |
12 | type EndpointOptions struct {
13 | EnableDebug bool
14 | }
15 |
16 | var TestOptions = EndpointOptions{
17 | EnableDebug: false,
18 | }
19 |
20 | func GraphQLEndpointHandler(opts EndpointOptions) http.Handler {
21 | srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &Resolver{}}))
22 | if opts.EnableDebug {
23 | srv.Use(&debug.Tracer{})
24 | }
25 |
26 | return srv
27 | }
28 |
--------------------------------------------------------------------------------
/v2/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 User struct {
6 | ID string `json:"id"`
7 | Username string `json:"username"`
8 | }
9 |
10 | func (User) IsEntity() {}
11 |
--------------------------------------------------------------------------------
/v2/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 | type Resolver struct{}
7 |
--------------------------------------------------------------------------------
/v2/examples/federation/accounts/graph/schema.graphqls:
--------------------------------------------------------------------------------
1 | extend type Query {
2 | me: User
3 | }
4 |
5 | type User @key(fields: "id") {
6 | id: ID!
7 | username: String!
8 | }
9 |
--------------------------------------------------------------------------------
/v2/examples/federation/accounts/server.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package main
3 |
4 | import (
5 | "log"
6 | "net/http"
7 | "os"
8 |
9 | "github.com/99designs/gqlgen/graphql/playground"
10 |
11 | "github.com/TykTechnologies/graphql-go-tools/v2/examples/federation/accounts/graph"
12 | )
13 |
14 | const defaultPort = "4001"
15 |
16 | func main() {
17 | port := os.Getenv("PORT")
18 | if port == "" {
19 | port = defaultPort
20 | }
21 |
22 | http.Handle("/", playground.Handler("GraphQL playground", "/query"))
23 | http.Handle("/query", graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true}))
24 |
25 | log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
26 | log.Fatal(http.ListenAndServe(":"+port, nil))
27 | }
28 |
--------------------------------------------------------------------------------
/v2/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 Product struct {
6 | Upc string `json:"upc"`
7 | Name string `json:"name"`
8 | Price int `json:"price"`
9 | InStock int `json:"inStock"`
10 | }
11 |
12 | func (Product) IsEntity() {}
13 |
--------------------------------------------------------------------------------
/v2/examples/federation/products/graph/products.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/v2/examples/federation/products/graph/model"
4 |
5 | var hats = []*model.Product{
6 | {
7 | Upc: "top-1",
8 | Name: "Trilby",
9 | Price: 11,
10 | InStock: 500,
11 | },
12 | {
13 | Upc: "top-2",
14 | Name: "Fedora",
15 | Price: 22,
16 | InStock: 1200,
17 | },
18 | {
19 | Upc: "top-3",
20 | Name: "Boater",
21 | Price: 33,
22 | InStock: 850,
23 | },
24 | }
25 |
--------------------------------------------------------------------------------
/v2/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 |
--------------------------------------------------------------------------------
/v2/examples/federation/products/graph/schema.graphqls:
--------------------------------------------------------------------------------
1 | extend type Query {
2 | topProducts(first: Int = 5): [Product]
3 | }
4 |
5 | extend type Subscription {
6 | updatedPrice: Product!
7 | updateProductPrice(upc: String!): Product!
8 | stock: [Product!]
9 | }
10 |
11 | type Product @key(fields: "upc") {
12 | upc: String!
13 | name: String!
14 | price: Int!
15 | inStock: Int!
16 | }
--------------------------------------------------------------------------------
/v2/examples/federation/products/graph/variables.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | var (
8 | randomnessEnabled = true
9 | minPrice = 10
10 | maxPrice = 1499
11 | currentPrice = minPrice
12 | updateInterval = time.Second
13 | )
14 |
--------------------------------------------------------------------------------
/v2/examples/federation/products/server.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package main
3 |
4 | import (
5 | "log"
6 | "net/http"
7 | "os"
8 |
9 | "github.com/99designs/gqlgen/graphql/playground"
10 |
11 | "github.com/TykTechnologies/graphql-go-tools/v2/examples/federation/products/graph"
12 | )
13 |
14 | const defaultPort = "4002"
15 |
16 | func main() {
17 | port := os.Getenv("PORT")
18 | if port == "" {
19 | port = defaultPort
20 | }
21 |
22 | http.Handle("/", playground.Handler("GraphQL playground", "/query"))
23 | http.Handle("/query", graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true, EnableRandomness: true}))
24 | http.HandleFunc("/websocket_connections", graph.WebsocketConnectionsHandler)
25 |
26 | log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
27 | log.Fatal(http.ListenAndServe(":"+port, nil))
28 | }
29 |
--------------------------------------------------------------------------------
/v2/examples/federation/reviews/graph/handler.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/99designs/gqlgen/graphql/handler"
7 | "github.com/99designs/gqlgen/graphql/handler/debug"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/v2/examples/federation/reviews/graph/generated"
10 | )
11 |
12 | type EndpointOptions struct {
13 | EnableDebug bool
14 | }
15 |
16 | var TestOptions = EndpointOptions{
17 | EnableDebug: false,
18 | }
19 |
20 | func GraphQLEndpointHandler(opts EndpointOptions) http.Handler {
21 | srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &Resolver{}}))
22 | if opts.EnableDebug {
23 | srv.Use(&debug.Tracer{})
24 | }
25 |
26 | return srv
27 | }
28 |
--------------------------------------------------------------------------------
/v2/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 Product struct {
6 | Upc string `json:"upc"`
7 | Reviews []*Review `json:"reviews"`
8 | }
9 |
10 | func (Product) IsEntity() {}
11 |
12 | type Review struct {
13 | Body string `json:"body"`
14 | Author *User `json:"author"`
15 | Product *Product `json:"product"`
16 | }
17 |
18 | type User struct {
19 | ID string `json:"id"`
20 | Username string `json:"username"`
21 | Reviews []*Review `json:"reviews"`
22 | }
23 |
24 | func (User) IsEntity() {}
25 |
--------------------------------------------------------------------------------
/v2/examples/federation/reviews/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 |
--------------------------------------------------------------------------------
/v2/examples/federation/reviews/graph/reviews.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/v2/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{Upc: "top-1"},
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{Upc: "top-2"},
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{Upc: "top-3"},
19 | Author: &model.User{ID: "7777"},
20 | },
21 | }
22 |
--------------------------------------------------------------------------------
/v2/examples/federation/reviews/graph/schema.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User! @provides(fields: "username")
4 | product: Product!
5 | }
6 |
7 | extend type User @key(fields: "id") {
8 | id: ID! @external
9 | username: String! @external
10 | reviews: [Review]
11 | }
12 |
13 | extend type Product @key(fields: "upc") {
14 | upc: String! @external
15 | reviews: [Review]
16 | }
17 |
--------------------------------------------------------------------------------
/v2/examples/federation/reviews/server.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package main
3 |
4 | import (
5 | "log"
6 | "net/http"
7 | "os"
8 |
9 | "github.com/99designs/gqlgen/graphql/playground"
10 |
11 | "github.com/TykTechnologies/graphql-go-tools/v2/examples/federation/reviews/graph"
12 | )
13 |
14 | const defaultPort = "4003"
15 |
16 | func main() {
17 | port := os.Getenv("PORT")
18 | if port == "" {
19 | port = defaultPort
20 | }
21 |
22 | http.Handle("/", playground.Handler("GraphQL playground", "/query"))
23 | http.Handle("/query", graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true}))
24 |
25 | log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
26 | log.Fatal(http.ListenAndServe(":"+port, nil))
27 | }
28 |
--------------------------------------------------------------------------------
/v2/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 | go build -o /tmp/srv-gateway ./gateway
14 |
15 | /tmp/srv-accounts &
16 | ACCOUNTS_PID=$!
17 |
18 | /tmp/srv-products &
19 | PRODUCTS_PID=$!
20 |
21 | /tmp/srv-reviews &
22 | REVIEWS_PID=$!
23 |
24 | sleep 1
25 |
26 | /tmp/srv-gateway
27 |
--------------------------------------------------------------------------------
/v2/examples/federation/tools.go:
--------------------------------------------------------------------------------
1 | //go:build tools
2 | // +build tools
3 |
4 | package tools
5 |
6 | import (
7 | _ "github.com/99designs/gqlgen"
8 | _ "github.com/99designs/gqlgen/graphql/introspection"
9 | )
10 |
--------------------------------------------------------------------------------
/v2/examples/kafka_pubsub/example_field_configs.json:
--------------------------------------------------------------------------------
1 | {
2 | "type_name": "Query",
3 | "field_name": "topProducts",
4 | "disable_default_mapping": false,
5 | "path": [
6 | "topProducts"
7 | ]
8 | },
9 | {
10 | "type_name": "Subscription",
11 | "field_name": "stock",
12 | "disable_default_mapping": false,
13 | "path": [
14 | "stock"
15 | ]
16 | }
17 | ]
18 |
--------------------------------------------------------------------------------
/v2/examples/kafka_pubsub/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/TykTechnologies/graphql-go-tools/v2/examples/kafka_pubsub
2 |
3 | go 1.15
4 |
5 | require github.com/Shopify/sarama v1.29.1
6 |
--------------------------------------------------------------------------------
/v2/examples/kafka_pubsub/kafka_jaas.conf:
--------------------------------------------------------------------------------
1 | KafkaServer {
2 | org.apache.kafka.common.security.plain.PlainLoginModule required
3 | username="admin"
4 | password="admin-secret"
5 | user_admin="admin-secret"
6 | user_alice="alice-secret";
7 | };
8 | Client{};
--------------------------------------------------------------------------------
/v2/examples/kafka_pubsub/schema.graphql:
--------------------------------------------------------------------------------
1 | type Product {
2 | name: String!
3 | price: Int!
4 | in_stock: Int!
5 | }
6 |
7 | type Query {
8 | topProducts(first: Int): [Product]
9 | }
10 |
11 | type Subscription {
12 | stock(name: String): Product!
13 | }
14 |
--------------------------------------------------------------------------------
/v2/examples/kafka_pubsub/transactional_producer/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/TykTechnologies/graphql-go-tools/v2/examples/kafka_pubsub/transactional_producer
2 |
3 | go 1.18
4 |
5 | require github.com/confluentinc/confluent-kafka-go v1.8.2
6 |
--------------------------------------------------------------------------------
/v2/examples/kafka_pubsub/transactional_producer/go.sum:
--------------------------------------------------------------------------------
1 | github.com/confluentinc/confluent-kafka-go v1.8.2 h1:PBdbvYpyOdFLehj8j+9ba7FL4c4Moxn79gy9cYKxG5E=
2 | github.com/confluentinc/confluent-kafka-go v1.8.2/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg=
3 |
--------------------------------------------------------------------------------
/v2/internal/pkg/gocompat/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TykTechnologies/graphql-go-tools/a8e1ade2da8ecd5b85065c3e8c9364057d6b173c/v2/internal/pkg/gocompat/.gitkeep
--------------------------------------------------------------------------------
/v2/internal/pkg/quotes/quotes.go:
--------------------------------------------------------------------------------
1 | package quotes
2 |
3 | const (
4 | quoteByte = '"'
5 | quoteStr = string(quoteByte)
6 | )
7 |
8 | // WrapBytes returns a new slice wrapping the given s
9 | // in quotes (") by making a copy.
10 | func WrapBytes(s []byte) []byte {
11 | cp := make([]byte, len(s)+2)
12 | cp[0] = quoteByte
13 | copy(cp[1:], s)
14 | cp[len(s)+1] = quoteByte
15 | return cp
16 | }
17 |
18 | func WrapString(str string) string {
19 | return quoteStr + str + quoteStr
20 | }
21 |
--------------------------------------------------------------------------------
/v2/internal/pkg/quotes/quotes_test.go:
--------------------------------------------------------------------------------
1 | package quotes
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestWrapBytes(t *testing.T) {
10 | testCases := []struct {
11 | s []byte
12 | want []byte
13 | }{
14 | {nil, []byte(`""`)},
15 | {[]byte("foo"), []byte(`"foo"`)},
16 | }
17 | for _, tc := range testCases {
18 | tc := tc
19 | t.Run(string(tc.s), func(t *testing.T) {
20 | r := WrapBytes(tc.s)
21 | assert.Equal(t, tc.want, r)
22 | })
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/v2/internal/pkg/unsafeprinter/unsafeprinter.go:
--------------------------------------------------------------------------------
1 | package unsafeprinter
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/v2/internal/pkg/unsafeparser"
5 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/ast"
6 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/astprinter"
7 | )
8 |
9 | func Print(document, definition *ast.Document) string {
10 | str, err := astprinter.PrintString(document, definition)
11 | if err != nil {
12 | panic(err)
13 | }
14 | return str
15 | }
16 |
17 | func PrettyPrint(document, definition *ast.Document) string {
18 | str, err := astprinter.PrintStringIndent(document, definition, " ")
19 | if err != nil {
20 | panic(err)
21 | }
22 | return str
23 | }
24 |
25 | func Prettify(document string) string {
26 | doc := unsafeparser.ParseGraphqlDocumentString(document)
27 | return PrettyPrint(&doc, nil)
28 | }
29 |
--------------------------------------------------------------------------------
/v2/pkg/ast/ast_node_kind_test.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestNodeKindIsAbstractType(t *testing.T) {
10 | t.Run("Interface type returns true", func(t *testing.T) {
11 | assert.Equal(t, NodeKindInterfaceTypeDefinition.IsAbstractType(), true)
12 | })
13 |
14 | t.Run("Union type returns true", func(t *testing.T) {
15 | assert.Equal(t, NodeKindUnionTypeDefinition.IsAbstractType(), true)
16 | })
17 |
18 | t.Run("Enum type returns false", func(t *testing.T) {
19 | assert.Equal(t, NodeKindEnumTypeDefinition.IsAbstractType(), false)
20 | })
21 |
22 | t.Run("Interface type returns false", func(t *testing.T) {
23 | assert.Equal(t, NodeKindObjectTypeDefinition.IsAbstractType(), false)
24 | })
25 |
26 | t.Run("Scalar type returns false", func(t *testing.T) {
27 | assert.Equal(t, NodeKindScalarTypeDefinition.IsAbstractType(), false)
28 | })
29 | }
30 |
--------------------------------------------------------------------------------
/v2/pkg/ast/ast_schema_extension.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/v2/pkg/lexer/position"
4 |
5 | type SchemaExtension struct {
6 | ExtendLiteral position.Position
7 | SchemaDefinition
8 | }
9 |
--------------------------------------------------------------------------------
/v2/pkg/ast/ast_type_test.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
--------------------------------------------------------------------------------
/v2/pkg/ast/ast_val_boolean_value.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | // BooleanValues
4 | // one of: true, false
5 | type BooleanValue bool
6 |
7 | func (d *Document) BooleanValue(ref int) BooleanValue {
8 | return d.BooleanValues[ref]
9 | }
10 |
11 | func (d *Document) BooleanValuesAreEqual(left, right int) bool {
12 | return d.BooleanValue(left) == d.BooleanValue(right)
13 | }
14 |
--------------------------------------------------------------------------------
/v2/pkg/ast/ast_val_object_value.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/v2/pkg/lexer/position"
4 |
5 | // ObjectValue
6 | // example:
7 | // { lon: 12.43, lat: -53.211 }
8 | type ObjectValue struct {
9 | LBRACE position.Position
10 | Refs []int // ObjectField
11 | RBRACE position.Position
12 | }
13 |
14 | func (d *Document) CopyObjectValue(ref int) int {
15 | refs := d.NewEmptyRefs()
16 | for _, r := range d.ObjectValues[ref].Refs {
17 | refs = append(refs, d.CopyObjectField(r))
18 | }
19 | return d.AddObjectValue(ObjectValue{
20 | Refs: refs,
21 | })
22 | }
23 |
24 | func (d *Document) AddObjectValue(value ObjectValue) (ref int) {
25 | d.ObjectValues = append(d.ObjectValues, value)
26 | return len(d.ObjectValues) - 1
27 | }
28 |
29 | func (d *Document) ImportObjectValue(fieldRefs []int) (ref int) {
30 | return d.AddObjectValue(ObjectValue{
31 | Refs: fieldRefs,
32 | })
33 | }
34 |
--------------------------------------------------------------------------------
/v2/pkg/ast/helpers.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | // indexOf - simple helper to find an index of a ref within refs slice
4 | func indexOf(refs []int, ref int) (int, bool) {
5 | for i, j := range refs {
6 | if ref == j {
7 | return i, true
8 | }
9 | }
10 | return -1, false
11 | }
12 |
13 | // deleteRef - is a slice trick to remove an item with preserving items order
14 | // Note: danger modifies pointer to the arr
15 | func deleteRef(refs *[]int, index int) {
16 | *refs = append((*refs)[:index], (*refs)[index+1:]...)
17 | }
18 |
--------------------------------------------------------------------------------
/v2/pkg/astnormalization/fragment_definition_removal.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/ast"
5 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/astvisitor"
6 | )
7 |
8 | type FragmentDefinitionRemoval struct {
9 | }
10 |
11 | func removeFragmentDefinitions(walker *astvisitor.Walker) {
12 | visitor := removeFragmentDefinitionsVisitor{}
13 | walker.RegisterLeaveDocumentVisitor(visitor)
14 | }
15 |
16 | type removeFragmentDefinitionsVisitor struct {
17 | }
18 |
19 | func (r removeFragmentDefinitionsVisitor) LeaveDocument(operation, definition *ast.Document) {
20 | for i := range operation.RootNodes {
21 | if operation.RootNodes[i].Kind == ast.NodeKindFragmentDefinition {
22 | operation.RootNodes[i].Kind = ast.NodeKindUnknown
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/v2/pkg/astnormalization/remove_self_aliasing.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/ast"
7 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/astvisitor"
8 | )
9 |
10 | func removeSelfAliasing(walker *astvisitor.Walker) {
11 | visitor := removeSelfAliasingVisitor{}
12 | walker.RegisterEnterDocumentVisitor(&visitor)
13 | walker.RegisterEnterFieldVisitor(&visitor)
14 | }
15 |
16 | type removeSelfAliasingVisitor struct {
17 | operation *ast.Document
18 | }
19 |
20 | func (r *removeSelfAliasingVisitor) EnterDocument(operation, definition *ast.Document) {
21 | r.operation = operation
22 | }
23 |
24 | func (r *removeSelfAliasingVisitor) EnterField(ref int) {
25 | if !r.operation.Fields[ref].Alias.IsDefined {
26 | return
27 | }
28 | if !bytes.Equal(r.operation.FieldNameBytes(ref), r.operation.FieldAliasBytes(ref)) {
29 | return
30 | }
31 | r.operation.RemoveFieldAlias(ref)
32 | }
33 |
--------------------------------------------------------------------------------
/v2/pkg/astnormalization/remove_self_aliasing_test.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import "testing"
4 |
5 | func TestRemoveSelfAliasing(t *testing.T) {
6 | t.Run("simple", func(t *testing.T) {
7 | run(t, removeSelfAliasing, testDefinition, `
8 | {dog: dog}`,
9 | `
10 | {dog}`)
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/v2/pkg/astnormalization/remove_type_extensions.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/astvisitor"
5 |
6 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/ast"
7 | )
8 |
9 | func removeMergedTypeExtensions(walker *astvisitor.Walker) {
10 | visitor := removeMergedTypeExtensionsVisitor{
11 | Walker: walker,
12 | }
13 | walker.RegisterLeaveDocumentVisitor(&visitor)
14 | }
15 |
16 | type removeMergedTypeExtensionsVisitor struct {
17 | *astvisitor.Walker
18 | }
19 |
20 | func (r *removeMergedTypeExtensionsVisitor) LeaveDocument(operation, definition *ast.Document) {
21 | operation.RemoveMergedTypeExtensions()
22 | }
23 |
--------------------------------------------------------------------------------
/v2/pkg/astnormalization/variables_unused_deletion_test.go:
--------------------------------------------------------------------------------
1 | package astnormalization
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestUnusedVariableDeletion(t *testing.T) {
8 | t.Run("delete unused variables", func(t *testing.T) {
9 | runWithDeleteUnusedVariables(t, deleteUnusedVariables, variablesExtractionDefinition, `
10 | mutation HttpBinPost($a: HttpBinPostInput $b: String){
11 | httpBinPost(input: $a){
12 | headers {
13 | userAgent
14 | }
15 | data {
16 | foo
17 | }
18 | }
19 | }`, "HttpBinPost", `
20 | mutation HttpBinPost($a: HttpBinPostInput){
21 | httpBinPost(input: $a){
22 | headers {
23 | userAgent
24 | }
25 | data {
26 | foo
27 | }
28 | }
29 | }`, `{"a":{"foo":"bar"},"b":"bat"}`, `{"a":{"foo":"bar"}}`)
30 | })
31 | }
32 |
--------------------------------------------------------------------------------
/v2/pkg/astvalidation/definition_validation_test.go:
--------------------------------------------------------------------------------
1 | package astvalidation
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | "github.com/stretchr/testify/require"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/astparser"
10 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/asttransform"
11 | )
12 |
13 | func runDefinitionValidation(t *testing.T, definitionInput string, expectation ValidationState, rules ...Rule) {
14 | definition, report := astparser.ParseGraphqlDocumentString(definitionInput)
15 | require.False(t, report.HasErrors())
16 |
17 | err := asttransform.MergeDefinitionWithBaseSchema(&definition)
18 | require.NoError(t, err)
19 |
20 | validator := &DefinitionValidator{}
21 | for _, rule := range rules {
22 | validator.RegisterRule(rule)
23 | }
24 |
25 | result := validator.Validate(&definition, &report)
26 | assert.Equal(t, expectation, result)
27 | }
28 |
--------------------------------------------------------------------------------
/v2/pkg/astvalidation/reference/.gitignore:
--------------------------------------------------------------------------------
1 | __tests__
--------------------------------------------------------------------------------
/v2/pkg/astvalidation/reference/gen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd testsgo
4 | rm -f *Rule_test.go
5 | cd ..
6 |
7 | go run main.go
8 | gofmt -w testsgo
9 |
--------------------------------------------------------------------------------
/v2/pkg/astvalidation/rule.go:
--------------------------------------------------------------------------------
1 | package astvalidation
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/astvisitor"
5 | )
6 |
7 | var reservedFieldPrefix = []byte("__")
8 |
9 | // Rule is hook to register callback functions on the Walker
10 | type Rule func(walker *astvisitor.Walker)
11 |
--------------------------------------------------------------------------------
/v2/pkg/astvalidation/rule_unique_union_member_types_test.go:
--------------------------------------------------------------------------------
1 | package astvalidation
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestUniqueMemberTypes(t *testing.T) {
8 | t.Run("Definition", func(t *testing.T) {
9 | t.Run("Union with a single member is valid", func(t *testing.T) {
10 | runDefinitionValidation(t, `
11 | union Foo = Bar
12 | `, Valid, UniqueUnionMemberTypes(),
13 | )
14 | })
15 |
16 | t.Run("Union with many members is valid", func(t *testing.T) {
17 | runDefinitionValidation(t, `
18 | union Foo = Bar | FooBar | BarFoo
19 | `, Valid, UniqueUnionMemberTypes(),
20 | )
21 | })
22 |
23 | t.Run("Union with duplicate members is invalid", func(t *testing.T) {
24 | runDefinitionValidation(t, `
25 | union Foo = Bar | Bar
26 | `, Invalid, UniqueUnionMemberTypes(),
27 | )
28 | })
29 | })
30 | }
31 |
--------------------------------------------------------------------------------
/v2/pkg/astvalidation/validation_state.go:
--------------------------------------------------------------------------------
1 | //go:generate stringer -type=ValidationState -output validation_state_string.go
2 |
3 | package astvalidation
4 |
5 | // ValidationState is the outcome of a validation
6 | type ValidationState int
7 |
8 | const (
9 | UnknownState ValidationState = iota
10 | Valid
11 | Invalid
12 | )
13 |
--------------------------------------------------------------------------------
/v2/pkg/astvalidation/validation_state_string.go:
--------------------------------------------------------------------------------
1 | // Code generated by "stringer -type=ValidationState -output validation_state_string.go"; DO NOT EDIT.
2 |
3 | package astvalidation
4 |
5 | import "strconv"
6 |
7 | func _() {
8 | // An "invalid array index" compiler error signifies that the constant values have changed.
9 | // Re-run the stringer command to generate them again.
10 | var x [1]struct{}
11 | _ = x[UnknownState-0]
12 | _ = x[Valid-1]
13 | _ = x[Invalid-2]
14 | }
15 |
16 | const _ValidationState_name = "UnknownStateValidInvalid"
17 |
18 | var _ValidationState_index = [...]uint8{0, 12, 17, 24}
19 |
20 | func (i ValidationState) String() string {
21 | if i < 0 || i >= ValidationState(len(_ValidationState_index)-1) {
22 | return "ValidationState(" + strconv.FormatInt(int64(i), 10) + ")"
23 | }
24 | return _ValidationState_name[_ValidationState_index[i]:_ValidationState_index[i+1]]
25 | }
26 |
--------------------------------------------------------------------------------
/v2/pkg/astvisitor/astvisitor.go:
--------------------------------------------------------------------------------
1 | // Package astvisitor enables efficient and powerful traversal of GraphQL document AST's.
2 | //
3 | // Visitor has more options to configure the behaviour and offers more meta data than SimpleVisitor.
4 | // SimpleVisitor on the other hand is more performant.
5 | //
6 | // If all Nodes should be visited and not much meta data is needed, go with SimpleVisitor.
7 | // If you only need to visit a subset of Nodes or want specific meta data, e.g. TypeDefinitions you should go with Visitor.
8 | package astvisitor
9 |
--------------------------------------------------------------------------------
/v2/pkg/astvisitor/fixtures/path.golden:
--------------------------------------------------------------------------------
1 | EnterField: posts, path: [query]
2 | EnterField: id, path: [query,posts]
3 | EnterField: description, path: [query,posts]
4 | EnterField: user, path: [query,posts]
5 | EnterField: id, path: [query,posts,user]
6 | EnterField: name, path: [query,posts,user]
7 | EnterField: posts, path: [query]
8 | EnterField: id, path: [query,posts]
9 | EnterField: description, path: [query,posts]
10 | EnterField: user, path: [query,posts]
11 | EnterField: id, path: [query,posts,user]
12 | EnterField: name, path: [query,posts,user]
13 | EnterField: posts, path: [query,posts,user]
14 | EnterField: id, path: [query,posts,user,posts]
15 |
--------------------------------------------------------------------------------
/v2/pkg/astvisitor/fixtures/visitor_skip.golden:
--------------------------------------------------------------------------------
1 | EnterOperationDefinition (PostsUserQuery): ref: 0
2 | EnterSelectionSet(Query): ref: 2
3 | EnterField(posts::Query): ref: 5
4 | EnterSelectionSet(Post): ref: 1
5 | EnterField(id::Post): ref: 0
6 | LeaveField(id::Post): ref: 0
7 | EnterField(description::Post): ref: 1
8 | LeaveField(description::Post): ref: 1
9 | LeaveSelectionSet(Post): ref: 1
10 | LeaveField(posts::Query): ref: 5
11 | LeaveSelectionSet(Query): ref: 2
12 | LeaveOperationDefinition(PostsUserQuery): ref: 0
13 |
14 |
--------------------------------------------------------------------------------
/v2/pkg/astvisitor/simplevisitor_test.go:
--------------------------------------------------------------------------------
1 | package astvisitor_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/TykTechnologies/graphql-go-tools/v2/internal/pkg/unsafeparser"
7 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/astvisitor"
8 | )
9 |
10 | func BenchmarkSimpleVisitor(b *testing.B) {
11 |
12 | definition := unsafeparser.ParseGraphqlDocumentString(testDefinition)
13 | operation := unsafeparser.ParseGraphqlDocumentString(testOperation)
14 |
15 | visitor := &dummyVisitor{}
16 |
17 | walker := astvisitor.NewSimpleWalker(48)
18 | walker.SetVisitor(visitor)
19 |
20 | b.ResetTimer()
21 | b.ReportAllocs()
22 |
23 | for i := 0; i < b.N; i++ {
24 | must(walker.Walk(&operation, &definition))
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/v2/pkg/engine/datasource/introspection_datasource/factory.go:
--------------------------------------------------------------------------------
1 | package introspection_datasource
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/engine/plan"
7 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/introspection"
8 | )
9 |
10 | type Factory struct {
11 | introspectionData *introspection.Data
12 | }
13 |
14 | func NewFactory(introspectionData *introspection.Data) *Factory {
15 | return &Factory{introspectionData: introspectionData}
16 | }
17 |
18 | func (f *Factory) Planner(_ context.Context) plan.DataSourcePlanner {
19 | return &Planner{introspectionData: f.introspectionData}
20 | }
21 |
--------------------------------------------------------------------------------
/v2/pkg/engine/datasource/introspection_datasource/fixtures/enum_values_with_deprecated.golden:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "NEWHOPE",
4 | "description": "",
5 | "isDeprecated": false,
6 | "deprecationReason": null
7 | },
8 | {
9 | "name": "EMPIRE",
10 | "description": "",
11 | "isDeprecated": false,
12 | "deprecationReason": null
13 | },
14 | {
15 | "name": "JEDI",
16 | "description": "",
17 | "isDeprecated": true,
18 | "deprecationReason": "No longer supported"
19 | }
20 | ]
21 |
--------------------------------------------------------------------------------
/v2/pkg/engine/datasource/introspection_datasource/fixtures/enum_values_without_deprecated.golden:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "NEWHOPE",
4 | "description": "",
5 | "isDeprecated": false,
6 | "deprecationReason": null
7 | },
8 | {
9 | "name": "EMPIRE",
10 | "description": "",
11 | "isDeprecated": false,
12 | "deprecationReason": null
13 | }
14 | ]
15 |
--------------------------------------------------------------------------------
/v2/pkg/engine/datasource/introspection_datasource/fixtures/fields_without_deprecated.golden:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "droid",
4 | "description": "",
5 | "args": [
6 | {
7 | "name": "id",
8 | "description": "",
9 | "type": {
10 | "kind": "NON_NULL",
11 | "name": null,
12 | "ofType": {
13 | "kind": "SCALAR",
14 | "name": "ID",
15 | "ofType": null
16 | }
17 | },
18 | "defaultValue": null
19 | }
20 | ],
21 | "type": {
22 | "kind": "OBJECT",
23 | "name": "Droid",
24 | "ofType": null
25 | },
26 | "isDeprecated": false,
27 | "deprecationReason": null
28 | }
29 | ]
30 |
--------------------------------------------------------------------------------
/v2/pkg/engine/datasource/introspection_datasource/fixtures/not_existing_type.golden:
--------------------------------------------------------------------------------
1 | null
--------------------------------------------------------------------------------
/v2/pkg/engine/datasource/introspection_datasource/fixtures/type_introspection.golden:
--------------------------------------------------------------------------------
1 | {
2 | "kind": "OBJECT",
3 | "name": "Query",
4 | "description": "",
5 | "inputFields": [],
6 | "interfaces": [],
7 | "possibleTypes": []
8 | }
9 |
--------------------------------------------------------------------------------
/v2/pkg/engine/plan/type_field.go:
--------------------------------------------------------------------------------
1 | package plan
2 |
3 | type TypeField struct {
4 | TypeName string
5 | FieldNames []string
6 | }
7 |
8 | type TypeFields []TypeField
9 |
10 | func (f TypeFields) HasNode(typeName, fieldName string) bool {
11 | for i := range f {
12 | if typeName != f[i].TypeName {
13 | continue
14 | }
15 | for j := range f[i].FieldNames {
16 | if fieldName == f[i].FieldNames[j] {
17 | return true
18 | }
19 | }
20 | }
21 | return false
22 | }
23 |
24 | func (f TypeFields) HasNodeWithTypename(typeName string) bool {
25 | for i := range f {
26 | if typeName != f[i].TypeName {
27 | continue
28 | }
29 | return true
30 | }
31 | return false
32 | }
33 |
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/datasource.go:
--------------------------------------------------------------------------------
1 | package resolve
2 |
3 | import (
4 | "context"
5 | "io"
6 |
7 | "github.com/cespare/xxhash/v2"
8 | )
9 |
10 | type DataSource interface {
11 | Load(ctx context.Context, input []byte, w io.Writer) (err error)
12 | }
13 |
14 | type SubscriptionDataSource interface {
15 | Start(ctx *Context, input []byte, updater SubscriptionUpdater) error
16 | UniqueRequestID(ctx *Context, input []byte, xxh *xxhash.Digest) (err error)
17 | }
18 |
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/node.go:
--------------------------------------------------------------------------------
1 | package resolve
2 |
3 | const (
4 | NodeKindObject NodeKind = iota + 1
5 | NodeKindEmptyObject
6 | NodeKindArray
7 | NodeKindEmptyArray
8 | NodeKindNull
9 | NodeKindString
10 | NodeKindBoolean
11 | NodeKindInteger
12 | NodeKindFloat
13 | NodeKindBigInt
14 | NodeKindCustom
15 | NodeKindScalar
16 | NodeKindStaticString
17 | )
18 |
19 | type Node interface {
20 | NodeKind() NodeKind
21 | NodePath() []string
22 | NodeNullable() bool
23 | }
24 |
25 | type NodeKind int
26 |
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/node_custom.go:
--------------------------------------------------------------------------------
1 | package resolve
2 |
3 | type CustomResolve interface {
4 | Resolve(value []byte) ([]byte, error)
5 | }
6 |
7 | type CustomNode struct {
8 | CustomResolve
9 | Nullable bool
10 | Path []string
11 | }
12 |
13 | func (_ *CustomNode) NodeKind() NodeKind {
14 | return NodeKindCustom
15 | }
16 |
17 | func (c *CustomNode) NodePath() []string {
18 | return c.Path
19 | }
20 |
21 | func (c *CustomNode) NodeNullable() bool {
22 | return c.Nullable
23 | }
24 |
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/defer_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "users": [
4 | {
5 | "id": 1,
6 | "name": "Leanne Graham",
7 | "posts": null
8 | },
9 | {
10 | "id": 2,
11 | "name": "Ervin Howell",
12 | "posts": null
13 | }
14 | ]
15 | }
16 | }
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/defer_2.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "replace",
4 | "path": "/data/users/0/posts",
5 | "value": [
6 | {
7 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
8 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
9 | },
10 | {
11 | "title": "qui est esse",
12 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
13 | }
14 | ]
15 | }
16 | ]
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/defer_3.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "replace",
4 | "path": "/data/users/1/posts",
5 | "value": [
6 | {
7 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
8 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
9 | },
10 | {
11 | "title": "qui est esse",
12 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
13 | }
14 | ]
15 | }
16 | ]
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/posts.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "userId": 1,
4 | "id": 1,
5 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
6 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
7 | },
8 | {
9 | "userId": 1,
10 | "id": 2,
11 | "title": "qui est esse",
12 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
13 | }
14 | ]
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/stream_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "users": []
4 | }
5 | }
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/stream_2.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "add",
4 | "path": "/data/users/0",
5 | "value": {
6 | "id": 1,
7 | "name": "Leanne Graham"
8 | }
9 | }
10 | ]
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/stream_3.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "add",
4 | "path": "/data/users/1",
5 | "value": {
6 | "id": 2,
7 | "name": "Ervin Howell"
8 | }
9 | }
10 | ]
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/stream_4.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "users": [
4 | {
5 | "id": 1,
6 | "name": "Leanne Graham"
7 | }
8 | ]
9 | }
10 | }
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/stream_5.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "users": [
4 | {
5 | "id": 1,
6 | "name": "Leanne Graham"
7 | },
8 | {
9 | "id": 2,
10 | "name": "Ervin Howell"
11 | }
12 | ]
13 | }
14 | }
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/stream_6.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "add",
4 | "path": "/data/users/0",
5 | "value": {
6 | "id": 1,
7 | "name": "Leanne Graham",
8 | "posts": null
9 | }
10 | }
11 | ]
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/stream_7.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "add",
4 | "path": "/data/users/1",
5 | "value": {
6 | "id": 2,
7 | "name": "Ervin Howell",
8 | "posts": null
9 | }
10 | }
11 | ]
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/stream_8.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "replace",
4 | "path": "/data/users/0/posts",
5 | "value": [
6 | {
7 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
8 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
9 | },
10 | {
11 | "title": "qui est esse",
12 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
13 | }
14 | ]
15 | }
16 | ]
--------------------------------------------------------------------------------
/v2/pkg/engine/resolve/testdata/stream_9.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "replace",
4 | "path": "/data/users/1/posts",
5 | "value": [
6 | {
7 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
8 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
9 | },
10 | {
11 | "title": "qui est esse",
12 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
13 | }
14 | ]
15 | }
16 | ]
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/const.go:
--------------------------------------------------------------------------------
1 | package sdlmerge
2 |
3 | const (
4 | KeyDirectiveName = "key"
5 | RequireDirectiveName = "requires"
6 | ProvidesDirectiveName = "provides"
7 | ExternalDirectiveName = "external"
8 | )
9 |
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/remove_empty_object_type_definition_test.go:
--------------------------------------------------------------------------------
1 | package sdlmerge
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestRemoveEmptyObjectTypeDefinitionDirective(t *testing.T) {
8 | t.Run("remove object definition without fields", func(t *testing.T) {
9 | run(t, newRemoveEmptyObjectTypeDefinition(), `
10 | type Query {
11 | }
12 | type Cat {
13 | name: String!
14 | }
15 | `, `
16 | type Cat {
17 | name: String!
18 | }
19 | `)
20 | })
21 | }
22 |
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/remove_field_definition_by_directive_test.go:
--------------------------------------------------------------------------------
1 | package sdlmerge
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestRemoveFieldDirective(t *testing.T) {
8 | t.Run("remove field with specified directive", func(t *testing.T) {
9 | run(
10 | t, newRemoveFieldDefinitions("forDelete"),
11 | `
12 | type Dog {
13 | name: String @notForDelete
14 | favoriteToy: String @forDelete
15 | barkVolume: Int
16 | isHousetrained(atOtherHomes: Boolean): Boolean! @forDelete
17 | doesKnowCommand(dogCommand: DogCommand!): Boolean!
18 | }
19 | `,
20 | `
21 | type Dog {
22 | name: String @notForDelete
23 | barkVolume: Int
24 | doesKnowCommand(dogCommand: DogCommand!): Boolean!
25 | }
26 | `)
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/remove_field_definition_directive_test.go:
--------------------------------------------------------------------------------
1 | package sdlmerge
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestRemoveFieldDefinitionDirective(t *testing.T) {
8 | t.Run("remove specified directive from field definition", func(t *testing.T) {
9 | run(
10 | t,
11 | newRemoveFieldDefinitionDirective("requires", "provides"),
12 | `
13 | type Dog {
14 | name: String!
15 | age: Int!
16 | code: String @requires(fields: "name age")
17 | owner: Owner @provides(fields: "name")
18 | }
19 | `,
20 | `
21 | type Dog {
22 | name: String!
23 | age: Int!
24 | code: String
25 | owner: Owner
26 | }`,
27 | )
28 | })
29 | }
30 |
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/remove_type_extensions.go:
--------------------------------------------------------------------------------
1 | package sdlmerge
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/ast"
5 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/astvisitor"
6 | )
7 |
8 | func newRemoveMergedTypeExtensions() *removeMergedTypeExtensionsVisitor {
9 | return &removeMergedTypeExtensionsVisitor{}
10 | }
11 |
12 | type removeMergedTypeExtensionsVisitor struct {
13 | }
14 |
15 | func (r *removeMergedTypeExtensionsVisitor) Register(walker *astvisitor.Walker) {
16 | walker.RegisterLeaveDocumentVisitor(r)
17 | }
18 |
19 | func (r *removeMergedTypeExtensionsVisitor) LeaveDocument(operation, definition *ast.Document) {
20 | operation.RemoveMergedTypeExtensions()
21 | }
22 |
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/testdata/validate-subgraph/lack-definition-non-null.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User! @provides(fields: "username")
4 | product: Product!
5 | }
6 |
7 | #type User @key(fields: "id") {
8 | # id: ID! @external
9 | # username: String! @external
10 | # reviews: [Review]
11 | #}
12 |
13 | extend type Product @key(fields: "upc") {
14 | upc: String! @external
15 | reviews: [Review]
16 | }
17 |
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/testdata/validate-subgraph/lack-definition.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User @provides(fields: "username")
4 | product: Product
5 | }
6 |
7 | #type User @key(fields: "id") {
8 | # id: ID! @external
9 | # username: String! @external
10 | # reviews: [Review]
11 | #}
12 |
13 | extend type Product @key(fields: "upc") {
14 | upc: String! @external
15 | reviews: [Review]
16 | }
17 |
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/testdata/validate-subgraph/lack-extend-definition-non-null.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User! @provides(fields: "username")
4 | product: Product!
5 | }
6 |
7 | type User @key(fields: "id") {
8 | id: ID! @external
9 | username: String! @external
10 | reviews: [Review]
11 | }
12 |
13 | #extend type Product @key(fields: "upc") {
14 | # @external
15 | # reviews: [Review] }
16 | #}
17 |
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/testdata/validate-subgraph/lack-extend-definition.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User @provides(fields: "username")
4 | product: Product
5 | }
6 |
7 | type User @key(fields: "id") {
8 | id: ID! @external
9 | username: String! @external
10 | reviews: [Review]
11 | }
12 |
13 | #extend type Product @key(fields: "upc") {
14 | # upc: String! @external
15 | # reviews: [Review]
16 | #}
17 |
18 |
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/testdata/validate-subgraph/well-defined-non-null.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User! @provides(fields: "username")
4 | product: Product!
5 | }
6 |
7 | type User @key(fields: "id") {
8 | id: ID! @external
9 | username: String! @external
10 | reviews: [Review]
11 | }
12 |
13 | extend type Product @key(fields: "upc") {
14 | upc: String! @external
15 | reviews: [Review]
16 | }
17 |
--------------------------------------------------------------------------------
/v2/pkg/federation/sdlmerge/testdata/validate-subgraph/well-defined.graphqls:
--------------------------------------------------------------------------------
1 | type Review {
2 | body: String!
3 | author: User @provides(fields: "username")
4 | product: Product
5 | }
6 |
7 | type User @key(fields: "id") {
8 | id: ID! @external
9 | username: String! @external
10 | reviews: [Review]
11 | }
12 |
13 | extend type Product @key(fields: "upc") {
14 | upc: String! @external
15 | reviews: [Review]
16 | }
17 |
--------------------------------------------------------------------------------
/v2/pkg/graphql/lookup.go:
--------------------------------------------------------------------------------
1 | package graphql
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | type TypeFieldLookupKey string
8 |
9 | func CreateTypeFieldLookupKey(typeName string, fieldName string) TypeFieldLookupKey {
10 | return TypeFieldLookupKey(fmt.Sprintf("%s.%s", typeName, fieldName))
11 | }
12 |
13 | func CreateTypeFieldArgumentsLookupMap(typeFieldArgs []TypeFieldArguments) map[TypeFieldLookupKey]TypeFieldArguments {
14 | if len(typeFieldArgs) == 0 {
15 | return nil
16 | }
17 |
18 | lookupMap := make(map[TypeFieldLookupKey]TypeFieldArguments)
19 | for _, currentTypeFieldArgs := range typeFieldArgs {
20 | lookupMap[CreateTypeFieldLookupKey(currentTypeFieldArgs.TypeName, currentTypeFieldArgs.FieldName)] = currentTypeFieldArgs
21 | }
22 |
23 | return lookupMap
24 | }
25 |
--------------------------------------------------------------------------------
/v2/pkg/graphql/response.go:
--------------------------------------------------------------------------------
1 | package graphql
2 |
3 | import (
4 | "encoding/json"
5 | )
6 |
7 | type Response struct {
8 | Errors Errors `json:"errors,omitempty"`
9 | Data any `json:"data"` // we add this here to ensure that "data":null is added to an error response
10 | }
11 |
12 | func (r Response) Marshal() ([]byte, error) {
13 | return json.Marshal(r)
14 | }
15 |
--------------------------------------------------------------------------------
/v2/pkg/graphql/subscription.go:
--------------------------------------------------------------------------------
1 | package graphql
2 |
3 | type SubscriptionType int
4 |
5 | const (
6 | // SubscriptionTypeUnknown is for unknown or undefined subscriptions.
7 | SubscriptionTypeUnknown = iota
8 | // SubscriptionTypeSSE is for Server-Sent Events (SSE) subscriptions.
9 | SubscriptionTypeSSE
10 | // SubscriptionTypeGraphQLWS is for subscriptions using a WebSocket connection with
11 | // 'graphql-ws' as protocol.
12 | SubscriptionTypeGraphQLWS
13 | // SubscriptionTypeGraphQLTransportWS is for subscriptions using a WebSocket connection with
14 | // 'graphql-transport-ws' as protocol.
15 | SubscriptionTypeGraphQLTransportWS
16 | )
17 |
--------------------------------------------------------------------------------
/v2/pkg/graphql/types.go:
--------------------------------------------------------------------------------
1 | package graphql
2 |
3 | type (
4 | Type struct {
5 | Name string `json:"name"`
6 | Fields []string `json:"fields"`
7 | }
8 |
9 | RequestFields map[string]struct{}
10 | RequestTypes map[string]RequestFields
11 | )
12 |
--------------------------------------------------------------------------------
/v2/pkg/graphqlerrors/location.go:
--------------------------------------------------------------------------------
1 | package graphqlerrors
2 |
3 | type Location struct {
4 | Line uint32 `json:"line"`
5 | Column uint32 `json:"column"`
6 | }
7 |
--------------------------------------------------------------------------------
/v2/pkg/imports/fixtures/render_result.golden:
--------------------------------------------------------------------------------
1 | #file: testdata/schema.graphql
2 |
3 |
4 | schema {
5 | query: Query
6 | mutation: Mutation
7 | }
8 |
9 |
10 | #file: testdata/scalars/json.graphql
11 |
12 | scalar JSON
13 |
14 |
15 | #file: testdata/types/query.graphql
16 |
17 | type Query {
18 | foo: Foo
19 | }
20 |
21 |
22 | #file: testdata/nested/nested.graphql
23 |
24 |
25 | type Bar {
26 | baz: Int
27 | }
28 |
29 |
30 | #file: testdata/nested2/nested2.graphql
31 |
32 | type Bat {
33 | bar: String
34 | }
35 |
36 |
37 | #file: testdata/deep/deeper/custom_types.graphql
38 |
39 | type Foo {
40 | field: String
41 | }
42 |
--------------------------------------------------------------------------------
/v2/pkg/imports/fixtures/render_result_windows.golden:
--------------------------------------------------------------------------------
1 | #file: testdata\schema.graphql
2 |
3 |
4 | schema {
5 | query: Query
6 | mutation: Mutation
7 | }
8 |
9 |
10 | #file: testdata\scalars\json.graphql
11 |
12 | scalar JSON
13 |
14 |
15 | #file: testdata\types\query.graphql
16 |
17 | type Query {
18 | foo: Foo
19 | }
20 |
21 |
22 | #file: testdata\nested\nested.graphql
23 |
24 |
25 | type Bar {
26 | baz: Int
27 | }
28 |
29 |
30 | #file: testdata\nested2\nested2.graphql
31 |
32 | type Bat {
33 | bar: String
34 | }
35 |
36 |
37 | #file: testdata\deep\deeper\custom_types.graphql
38 |
39 | type Foo {
40 | field: String
41 | }
42 |
--------------------------------------------------------------------------------
/v2/pkg/imports/fixtures/scanner_regex.golden:
--------------------------------------------------------------------------------
1 | {
2 | "RelativePath": "",
3 | "Imports": [
4 | {
5 | "RelativePath": "testdata/regexonly/flat.graphql",
6 | "Imports": null
7 | },
8 | {
9 | "RelativePath": "testdata/regexonly/mutation.graphql",
10 | "Imports": null
11 | },
12 | {
13 | "RelativePath": "testdata/regexonly/query.graphql",
14 | "Imports": null
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/fixtures/scanner_regex_render.golden:
--------------------------------------------------------------------------------
1 | schema {
2 | query: Query
3 | mutation: Mutation
4 | }
5 | type Mutation {
6 | bar: String
7 | }
8 | type Query {
9 | foo: String
10 | }
11 |
--------------------------------------------------------------------------------
/v2/pkg/imports/fixtures/scanner_regex_windows.golden:
--------------------------------------------------------------------------------
1 | {
2 | "RelativePath": "",
3 | "Imports": [
4 | {
5 | "RelativePath": "testdata\\regexonly\\flat.graphql",
6 | "Imports": null
7 | },
8 | {
9 | "RelativePath": "testdata\\regexonly\\mutation.graphql",
10 | "Imports": null
11 | },
12 | {
13 | "RelativePath": "testdata\\regexonly\\query.graphql",
14 | "Imports": null
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/fixtures/scanner_result.golden:
--------------------------------------------------------------------------------
1 | {
2 | "RelativePath": "testdata/schema.graphql",
3 | "Imports": [
4 | {
5 | "RelativePath": "testdata/scalars/json.graphql",
6 | "Imports": null
7 | },
8 | {
9 | "RelativePath": "testdata/types/query.graphql",
10 | "Imports": null
11 | },
12 | {
13 | "RelativePath": "testdata/nested/nested.graphql",
14 | "Imports": [
15 | {
16 | "RelativePath": "testdata/nested2/nested2.graphql",
17 | "Imports": null
18 | }
19 | ]
20 | },
21 | {
22 | "RelativePath": "testdata/deep/deeper/custom_types.graphql",
23 | "Imports": null
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/fixtures/scanner_result_windows.golden:
--------------------------------------------------------------------------------
1 | {
2 | "RelativePath": "testdata\\schema.graphql",
3 | "Imports": [
4 | {
5 | "RelativePath": "testdata\\scalars\\json.graphql",
6 | "Imports": null
7 | },
8 | {
9 | "RelativePath": "testdata\\types\\query.graphql",
10 | "Imports": null
11 | },
12 | {
13 | "RelativePath": "testdata\\nested\\nested.graphql",
14 | "Imports": [
15 | {
16 | "RelativePath": "testdata\\nested2\\nested2.graphql",
17 | "Imports": null
18 | }
19 | ]
20 | },
21 | {
22 | "RelativePath": "testdata\\deep\\deeper\\custom_types.graphql",
23 | "Imports": null
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/graphql_file_test.go:
--------------------------------------------------------------------------------
1 | package imports
2 |
3 | import (
4 | "bytes"
5 | "os"
6 | "testing"
7 |
8 | "github.com/jensneuse/diffview"
9 |
10 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/goldie"
11 | )
12 |
13 | func TestGraphQLFile_Render(t *testing.T) {
14 | scanner := Scanner{}
15 | file, err := scanner.ScanFile("testdata/schema.graphql")
16 | if err != nil {
17 | t.Fatal(err)
18 | }
19 |
20 | out := bytes.Buffer{}
21 | err = file.Render(true, &out)
22 | if err != nil {
23 | t.Fatal(err)
24 | }
25 |
26 | dump := out.Bytes()
27 |
28 | goldie.Assert(t, "render_result", dump, true)
29 | if t.Failed() {
30 | fixture, err := os.ReadFile("./fixtures/render_result.golden")
31 | if err != nil {
32 | t.Fatal(err)
33 | }
34 |
35 | diffview.NewGoland().DiffViewBytes("render_result", fixture, dump)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/cycle/a/a.graphql:
--------------------------------------------------------------------------------
1 | #import "../b/b.graphql"
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/cycle/b/b.graphql:
--------------------------------------------------------------------------------
1 | #import "../a/a.graphql"
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/deep/deeper/custom_types.graphql:
--------------------------------------------------------------------------------
1 | type Foo {
2 | field: String
3 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/deep/deeper/non_graphql.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TykTechnologies/graphql-go-tools/a8e1ade2da8ecd5b85065c3e8c9364057d6b173c/v2/pkg/imports/testdata/deep/deeper/non_graphql.txt
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/import_cycle.graphql:
--------------------------------------------------------------------------------
1 | #import "cycle/a/a.graphql"
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/nested/nested.graphql:
--------------------------------------------------------------------------------
1 | #import "../nested2/nested2.graphql"
2 |
3 | type Bar {
4 | baz: Int
5 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/nested2/nested2.graphql:
--------------------------------------------------------------------------------
1 | type Bat {
2 | bar: String
3 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/regexonly/flat.graphql:
--------------------------------------------------------------------------------
1 | schema {
2 | query: Query
3 | mutation: Mutation
4 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/regexonly/mutation.graphql:
--------------------------------------------------------------------------------
1 | type Mutation {
2 | bar: String
3 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/regexonly/query.graphql:
--------------------------------------------------------------------------------
1 | type Query {
2 | foo: String
3 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/scalars/json.graphql:
--------------------------------------------------------------------------------
1 | scalar JSON
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/schema.graphql:
--------------------------------------------------------------------------------
1 | #import "scalars/*.graphql"
2 | #import "types/query.graphql"
3 | #import "nested/nested.graphql"
4 | #import "deep/**/*.graphql"
5 |
6 | schema {
7 | query: Query
8 | mutation: Mutation
9 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/types/mutation.graphql:
--------------------------------------------------------------------------------
1 | type Mutation {
2 | mutateFoo: Foo
3 | }
--------------------------------------------------------------------------------
/v2/pkg/imports/testdata/types/query.graphql:
--------------------------------------------------------------------------------
1 | type Query {
2 | foo: Foo
3 | }
--------------------------------------------------------------------------------
/v2/pkg/introspection/introspection_test.go:
--------------------------------------------------------------------------------
1 | package introspection
2 |
3 | import (
4 | "encoding/json"
5 | "os"
6 | "testing"
7 | )
8 |
9 | func TestIntrospectionSerialization(t *testing.T) {
10 | inputData, err := os.ReadFile("./testdata/swapi_introspection_response.json")
11 | if err != nil {
12 | panic(err)
13 | }
14 |
15 | var data Data
16 |
17 | err = json.Unmarshal(inputData, &data)
18 | if err != nil {
19 | panic(err)
20 | }
21 |
22 | outputData, err := json.MarshalIndent(data, "", " ")
23 | if err != nil {
24 | panic(err)
25 | }
26 |
27 | err = os.WriteFile("./testdata/out_swapi_introspection_response.json", outputData, os.ModePerm)
28 | if err != nil {
29 | panic(err)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/v2/pkg/introspection/testdata/interfaces_implementing_interfaces.graphql:
--------------------------------------------------------------------------------
1 | interface BaseInterface {
2 | fieldOne: String!
3 | }
4 |
5 | interface SecondInterface implements BaseInterface {
6 | fieldOne: String!
7 | fieldTwo: String!
8 | }
9 |
10 | interface ThirdInterface implements SecondInterface & BaseInterface {
11 | fieldOne: String!
12 | fieldTwo: String!
13 | fieldThree: String!
14 | }
15 |
16 | interface IDType {
17 | id: ID!
18 | }
19 |
20 | interface SoftDelete {
21 | deleted: Boolean!
22 | }
23 |
24 | extend interface SoftDelete implements IDType {
25 | id: ID!
26 | }
27 |
28 | interface Record {
29 | data: String!
30 | }
31 |
32 | extend interface Record implements SoftDelete & IDType {
33 | id: ID!
34 | deleted: Boolean!
35 | }
36 |
--------------------------------------------------------------------------------
/v2/pkg/lexer/keyword/keyword.go:
--------------------------------------------------------------------------------
1 | //go:generate stringer -type=Keyword
2 |
3 | // Package keyword contains all possible GraphQL keywords
4 | package keyword
5 |
6 | type Keyword int
7 |
8 | const (
9 | UNDEFINED Keyword = iota
10 | IDENT
11 | COMMENT
12 | EOF
13 |
14 | COLON
15 | BANG
16 | LT
17 | TAB
18 | SPACE
19 | COMMA
20 | AT
21 | DOT
22 | SPREAD
23 | PIPE
24 | SLASH
25 | EQUALS
26 | SUB
27 | AND
28 | QUOTE
29 |
30 | DOLLAR
31 | STRING
32 | BLOCKSTRING
33 | INTEGER
34 | FLOAT
35 |
36 | LPAREN
37 | RPAREN
38 | LBRACK
39 | RBRACK
40 | LBRACE
41 | RBRACE
42 | )
43 |
--------------------------------------------------------------------------------
/v2/pkg/lexer/runes/runes.go:
--------------------------------------------------------------------------------
1 | // Package runes contains all possible 'special' runes in a GraphQL document
2 | package runes
3 |
4 | const (
5 | EOF = 0
6 | COLON = ':'
7 | BANG = '!'
8 | CARRIAGERETURN = '\r'
9 | LINETERMINATOR = '\n'
10 | TAB = '\t'
11 | SPACE = ' '
12 | COMMA = ','
13 | HASHTAG = '#'
14 | QUOTE = '"'
15 | BACKSLASH = '\\'
16 | DOT = '.'
17 | EXPONENT_LOWER = 'e'
18 | EXPONENT_UPPER = 'E'
19 | AT = '@'
20 | DOLLAR = '$'
21 | PIPE = '|'
22 | SLASH = '/'
23 | EQUALS = '='
24 | SUB = '-'
25 | ADD = '+'
26 | AND = '&'
27 | UNDERSCORE = '_'
28 |
29 | LPAREN = '('
30 | RPAREN = ')'
31 | LBRACK = '['
32 | RBRACK = ']'
33 | LBRACE = '{'
34 | RBRACE = '}'
35 | )
36 |
--------------------------------------------------------------------------------
/v2/pkg/middleware/middleware.go:
--------------------------------------------------------------------------------
1 | // Package middleware contains useful middleware components for GraphQL services, e.g. for complexity analysis.
2 | package middleware
3 |
--------------------------------------------------------------------------------
/v2/pkg/playground/files/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TykTechnologies/graphql-go-tools/a8e1ade2da8ecd5b85065c3e8c9364057d6b173c/v2/pkg/playground/files/favicon.png
--------------------------------------------------------------------------------
/v2/pkg/playground/files/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TykTechnologies/graphql-go-tools/a8e1ade2da8ecd5b85065c3e8c9364057d6b173c/v2/pkg/playground/files/logo.png
--------------------------------------------------------------------------------
/v2/pkg/playground/files/playground.css:
--------------------------------------------------------------------------------
1 | body{margin:0;padding:0;font-family:sans-serif;overflow:hidden}#root{height:100%}body{font-family:Open Sans,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:rgba(0,0,0,.8);line-height:1.5;height:100vh;letter-spacing:.53px;margin-right:-1px!important}a,body,code,h1,h2,h3,h4,html,p,pre,ul{margin:0;padding:0;color:inherit}a:active,a:focus,button:focus,input:focus{outline:none}button,input,submit{border:none}button,input,pre{font-family:Open Sans,sans-serif}code{font-family:Consolas,monospace}
--------------------------------------------------------------------------------
/v2/pkg/playground/fixtures/handlers.golden:
--------------------------------------------------------------------------------
1 | (playground.Handlers) (len=5 cap=5) {
2 | (playground.HandlerConfig) {
3 | Path: (string) (len=11) "/playground",
4 | Handler: (http.HandlerFunc)
5 | },
6 | (playground.HandlerConfig) {
7 | Path: (string) (len=26) "/playground/playground.css",
8 | Handler: (http.HandlerFunc)
9 | },
10 | (playground.HandlerConfig) {
11 | Path: (string) (len=25) "/playground/playground.js",
12 | Handler: (http.HandlerFunc)
13 | },
14 | (playground.HandlerConfig) {
15 | Path: (string) (len=23) "/playground/favicon.png",
16 | Handler: (http.HandlerFunc)
17 | },
18 | (playground.HandlerConfig) {
19 | Path: (string) (len=20) "/playground/logo.png",
20 | Handler: (http.HandlerFunc)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/v2/pkg/pool/bytesbuffer.go:
--------------------------------------------------------------------------------
1 | package pool
2 |
3 | import (
4 | "bytes"
5 | "sync"
6 | )
7 |
8 | var (
9 | BytesBuffer = bytesBufferPool{
10 | pool: sync.Pool{
11 | New: func() interface{} {
12 | return bytes.NewBuffer(make([]byte, 0, 1024))
13 | },
14 | },
15 | }
16 | )
17 |
18 | type bytesBufferPool struct {
19 | pool sync.Pool
20 | }
21 |
22 | func (b *bytesBufferPool) Get() *bytes.Buffer {
23 | return b.pool.Get().(*bytes.Buffer)
24 | }
25 |
26 | func (b *bytesBufferPool) Put(buf *bytes.Buffer) {
27 | buf.Reset()
28 | b.pool.Put(buf)
29 | }
30 |
--------------------------------------------------------------------------------
/v2/pkg/pool/fastbuffer.go:
--------------------------------------------------------------------------------
1 | package pool
2 |
3 | import (
4 | "sync"
5 |
6 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/fastbuffer"
7 | )
8 |
9 | var FastBuffer = fastBufferPool{
10 | pool: sync.Pool{
11 | New: func() interface{} {
12 | return fastbuffer.New()
13 | },
14 | },
15 | }
16 |
17 | type fastBufferPool struct {
18 | pool sync.Pool
19 | }
20 |
21 | func (f *fastBufferPool) Get() *fastbuffer.FastBuffer {
22 | return f.pool.Get().(*fastbuffer.FastBuffer)
23 | }
24 |
25 | func (f *fastBufferPool) Put(buf *fastbuffer.FastBuffer) {
26 | buf.Reset()
27 | f.pool.Put(buf)
28 | }
29 |
--------------------------------------------------------------------------------
/v2/pkg/pool/hash64.go:
--------------------------------------------------------------------------------
1 | package pool
2 |
3 | import (
4 | "sync"
5 |
6 | "github.com/cespare/xxhash/v2"
7 | )
8 |
9 | var (
10 | Hash64 = hash64Pool{
11 | pool: sync.Pool{
12 | New: func() interface{} {
13 | return xxhash.New()
14 | },
15 | },
16 | }
17 | )
18 |
19 | type hash64Pool struct {
20 | pool sync.Pool
21 | }
22 |
23 | func (b *hash64Pool) Get() *xxhash.Digest {
24 | xxh := b.pool.Get().(*xxhash.Digest)
25 | xxh.Reset()
26 | return xxh
27 | }
28 |
29 | func (b *hash64Pool) Put(xxh *xxhash.Digest) {
30 | b.pool.Put(xxh)
31 | }
32 |
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/mutations/create_review.mutation:
--------------------------------------------------------------------------------
1 | mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
2 | createReview(episode: $ep, review: $review) {
3 | id
4 | stars
5 | commentary
6 | }
7 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/directives_include.query:
--------------------------------------------------------------------------------
1 | query Hero($withFriends: Boolean!) {
2 | hero {
3 | name
4 | friends @include(if: $withFriends) {
5 | name
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/directives_skip.query:
--------------------------------------------------------------------------------
1 | query Hero($skipFriends: Boolean!) {
2 | hero {
3 | name
4 | friends @skip(if: $skipFriends) {
5 | name
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/droid_with_arg.query:
--------------------------------------------------------------------------------
1 | {
2 | droid(id: "R2D2") {
3 | name
4 | }
5 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/droid_with_arg_and_var.query:
--------------------------------------------------------------------------------
1 | query Droid($droidID: ID!) {
2 | droid(id: $droidID) {
3 | name
4 | }
5 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/fragments.query:
--------------------------------------------------------------------------------
1 | query Fragments($droidID: ID!){
2 | hero {
3 | ...characterFields
4 | }
5 | droid(id: $droidID) {
6 | ...characterFields
7 | }
8 | }
9 |
10 | fragment characterFields on Character {
11 | name
12 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/hero_with_aliases.query:
--------------------------------------------------------------------------------
1 | {
2 | empireHero: hero {
3 | name
4 | }
5 | jediHero: hero {
6 | name
7 | }
8 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/hero_with_operation_name.query:
--------------------------------------------------------------------------------
1 | query Hero {
2 | hero {
3 | name
4 | }
5 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/inline_fragments.query:
--------------------------------------------------------------------------------
1 | {
2 | hero {
3 | friends {
4 | ...on Droid {
5 | name
6 | primaryFunction
7 | }
8 | ...on Human {
9 | name
10 | height
11 | }
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/interface_fragments_on_union.graphql:
--------------------------------------------------------------------------------
1 | query SearchResults {
2 | searchResults {
3 | ...on Character {
4 | name
5 | }
6 | ...on Vehicle {
7 | length
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/invalid.query:
--------------------------------------------------------------------------------
1 | {
2 | hero {
3 | invalid
4 | }
5 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/invalid_fragments.query:
--------------------------------------------------------------------------------
1 | query Fragments($droidID: ID!){
2 | droid(id: $droidID) {
3 | ...reviewFields
4 | }
5 | }
6 |
7 | fragment reviewFields on Review {
8 | id
9 | stars
10 | commentary
11 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/multi_queries.query:
--------------------------------------------------------------------------------
1 | query MultiHeroes {
2 | empireHero: hero {
3 | name
4 | }
5 | jediHero: hero {
6 | name
7 | }
8 | }
9 |
10 | query SingleHero {
11 | hero {
12 | name
13 | }
14 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/multi_queries_with_arguments.query:
--------------------------------------------------------------------------------
1 | query GetDroid {
2 | droid(id: "1") {
3 | name
4 | }
5 | }
6 |
7 | query Search {
8 | search(name: "C3PO") {
9 | ...on Droid {
10 | name
11 | primaryFunction
12 | }
13 | ...on Human {
14 | name
15 | height
16 | }
17 | ...on Starship {
18 | name
19 | length
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/simple_hero.query:
--------------------------------------------------------------------------------
1 | {
2 | hero {
3 | name
4 | }
5 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/queries/union.query:
--------------------------------------------------------------------------------
1 | query Search($name: String!) {
2 | search(name: $name) {
3 | ...on Droid {
4 | name
5 | primaryFunction
6 | }
7 | ...on Human {
8 | name
9 | height
10 | }
11 | ...on Starship {
12 | name
13 | length
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/v2/pkg/starwars/testdata/subscriptions/remaining_jedis.subscription:
--------------------------------------------------------------------------------
1 | subscription {
2 | remainingJedis
3 | }
--------------------------------------------------------------------------------
/v2/pkg/subscription/constants.go:
--------------------------------------------------------------------------------
1 | package subscription
2 |
3 | const (
4 | DefaultKeepAliveInterval = "15s"
5 | DefaultSubscriptionUpdateInterval = "1s"
6 | DefaultReadErrorTimeOut = "5s"
7 | DefaultSubscriptionExecutionTries = 5
8 | )
9 |
--------------------------------------------------------------------------------
/v2/pkg/subscription/executor.go:
--------------------------------------------------------------------------------
1 | package subscription
2 |
3 | //go:generate mockgen -destination=executor_mock_test.go -package=subscription . Executor,ExecutorPool
4 |
5 | import (
6 | "context"
7 |
8 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/ast"
9 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/engine/resolve"
10 | )
11 |
12 | // Executor is an abstraction for executing a GraphQL engine
13 | type Executor interface {
14 | Execute(writer resolve.SubscriptionResponseWriter) error
15 | OperationType() ast.OperationType
16 | SetContext(context context.Context)
17 | Reset()
18 | }
19 |
20 | // ExecutorPool is an abstraction for creating executors
21 | type ExecutorPool interface {
22 | Get(payload []byte) (Executor, error)
23 | Put(executor Executor) error
24 | }
25 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/accounts/graph/handler.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/99designs/gqlgen/graphql/handler"
7 | "github.com/99designs/gqlgen/graphql/handler/debug"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/federationtesting/accounts/graph/generated"
10 | )
11 |
12 | type EndpointOptions struct {
13 | EnableDebug bool
14 | }
15 |
16 | var TestOptions = EndpointOptions{
17 | EnableDebug: false,
18 | }
19 |
20 | func GraphQLEndpointHandler(opts EndpointOptions) http.Handler {
21 | srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &Resolver{}}))
22 | if opts.EnableDebug {
23 | srv.Use(&debug.Tracer{})
24 | }
25 |
26 | return srv
27 | }
28 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/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 | type Resolver struct{}
7 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/accounts/graph/wallets.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/federationtesting/accounts/graph/model"
4 |
5 | var walletOne = &model.WalletType1{
6 | Currency: "USD",
7 | Amount: 123,
8 | SpecialField1: "some special value 1",
9 | }
10 |
11 | var walletTwo = &model.WalletType2{
12 | Currency: "USD",
13 | Amount: 123,
14 | SpecialField2: "some special value 2",
15 | }
16 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/accounts/handler.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package accounts
3 |
4 | import (
5 | "net/http"
6 |
7 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/federationtesting/accounts/graph"
8 | )
9 |
10 | func Handler() http.Handler {
11 | return graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true})
12 | }
13 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/products/graph/model/models_gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
2 |
3 | package model
4 |
5 | type Product struct {
6 | Upc string `json:"upc"`
7 | Name string `json:"name"`
8 | Price int `json:"price"`
9 | InStock int `json:"inStock"`
10 | }
11 |
12 | func (Product) IsEntity() {}
13 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/products/graph/products.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/federationtesting/products/graph/model"
5 | )
6 |
7 | var hats []*model.Product
8 |
9 | func Reset() {
10 | hats = []*model.Product{
11 | {
12 | Upc: "top-1",
13 | Name: "Trilby",
14 | Price: 11,
15 | InStock: 500,
16 | },
17 | {
18 | Upc: "top-2",
19 | Name: "Fedora",
20 | Price: 22,
21 | InStock: 1200,
22 | },
23 | {
24 | Upc: "top-3",
25 | Name: "Boater",
26 | Price: 33,
27 | InStock: 850,
28 | },
29 | }
30 | }
31 |
32 | func init() {
33 | Reset()
34 | }
35 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/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 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/products/graph/schema.graphqls:
--------------------------------------------------------------------------------
1 | extend type Query {
2 | topProducts(first: Int = 5): [Product]
3 | }
4 |
5 | extend type Mutation {
6 | setPrice(upc: String!, price: Int!): Product
7 | }
8 |
9 | extend type Subscription {
10 | updatedPrice: Product!
11 | updateProductPrice(upc: String!): Product!
12 | }
13 |
14 | type Product @key(fields: "upc") {
15 | upc: String!
16 | name: String!
17 | price: Int!
18 | inStock: Int!
19 | }
20 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/products/graph/variables.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | var (
8 | randomnessEnabled = true
9 | minPrice = 10
10 | maxPrice = 1499
11 | currentPrice = minPrice
12 | updateInterval = time.Second
13 | )
14 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/products/handler.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package products
3 |
4 | import (
5 | "net/http"
6 |
7 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/federationtesting/products/graph"
8 | )
9 |
10 | func Handler() http.Handler {
11 | mux := http.NewServeMux()
12 |
13 | mux.Handle("/", graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true}))
14 | mux.HandleFunc("/websocket_connections", graph.WebsocketConnectionsHandler)
15 |
16 | return mux
17 | }
18 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/reviews/graph/attachments.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import "github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/federationtesting/reviews/graph/model"
4 |
5 | var attachments = []model.Attachment{
6 | model.Question{
7 | Upc: "top-1",
8 | Body: "How do I turn it on?",
9 | },
10 | model.Question{
11 | Upc: "top-3",
12 | Body: "Any recommendations for other teacosies?",
13 | },
14 | model.Rating{
15 | Upc: "top-2",
16 | Body: "The best hat I have ever bought in my life.",
17 | Score: 5,
18 | },
19 | model.Rating{
20 | Upc: "top-3",
21 | Body: "Terrible teacosy!!!",
22 | Score: 0,
23 | },
24 | model.Video{
25 | Upc: "top-2",
26 | Size: 13.37,
27 | },
28 | model.Video{
29 | Upc: "top-3",
30 | Size: 4.20,
31 | },
32 | }
33 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/reviews/graph/handler.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/99designs/gqlgen/graphql/handler"
7 | "github.com/99designs/gqlgen/graphql/handler/debug"
8 |
9 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/federationtesting/reviews/graph/generated"
10 | )
11 |
12 | type EndpointOptions struct {
13 | EnableDebug bool
14 | }
15 |
16 | var TestOptions = EndpointOptions{
17 | EnableDebug: false,
18 | }
19 |
20 | func GraphQLEndpointHandler(opts EndpointOptions) http.Handler {
21 | srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &Resolver{}}))
22 | if opts.EnableDebug {
23 | srv.Use(&debug.Tracer{})
24 | }
25 |
26 | return srv
27 | }
28 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/reviews/graph/model/models.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | type Product struct {
4 | Upc string `json:"upc"`
5 | }
6 |
7 | func (Product) IsEntity() {}
8 |
9 | type Review struct {
10 | Body string
11 | Author *User
12 | Product *Product
13 | }
14 |
15 | type User struct {
16 | ID string `json:"id"`
17 | }
18 |
19 | func (User) IsEntity() {}
20 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/reviews/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 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/reviews/graph/reviews.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/federationtesting/reviews/graph/model"
5 | )
6 |
7 | var reviews = []*model.Review{
8 | {
9 | Body: "A highly effective form of birth control.",
10 | Product: &model.Product{Upc: "top-1"},
11 | Author: &model.User{ID: "1234"},
12 | },
13 | {
14 | Body: "Fedoras are one of the most fashionable hats around and can look great with a variety of outfits.",
15 | Product: &model.Product{Upc: "top-2"},
16 | Author: &model.User{ID: "1234"},
17 | },
18 | {
19 | Body: "This is the last straw. Hat you will wear. 11/10",
20 | Product: &model.Product{Upc: "top-3"},
21 | Author: &model.User{ID: "7777"},
22 | },
23 | }
24 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/reviews/handler.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package reviews
3 |
4 | import (
5 | "net/http"
6 |
7 | "github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/federationtesting/reviews/graph"
8 | )
9 |
10 | func Handler() http.Handler {
11 | return graph.GraphQLEndpointHandler(graph.EndpointOptions{EnableDebug: true})
12 | }
13 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/mutations/mutation_with_variables.query:
--------------------------------------------------------------------------------
1 | mutation AddReview($authorID: String!, $upc: String!, $review: String!) {
2 | addReview(authorID: $authorID upc: $upc, review: $review) {
3 | body
4 | author {
5 | username
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/interface.query:
--------------------------------------------------------------------------------
1 | query MyHistory {
2 | me {
3 | username
4 | history {
5 | ... on Purchase {
6 | wallet {
7 | amount
8 | ... on WalletType1 {
9 | specialField1
10 | }
11 | ... on WalletType2 {
12 | specialField2
13 | }
14 | }
15 | }
16 | ... on Sale {
17 | rating
18 | }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/interface_fragment_on_object.graphql:
--------------------------------------------------------------------------------
1 | query InterfaceFragment {
2 | me {
3 | ... on Identifiable {
4 | id
5 | }
6 | ... on User {
7 | username
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/interface_fragments_on_union.graphql:
--------------------------------------------------------------------------------
1 | query InterfaceFragmentsOnUnion {
2 | histories {
3 | ... on Store {
4 | __typename
5 | location
6 | }
7 | ... on Info {
8 | __typename
9 | quantity
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/merged_field.graphql:
--------------------------------------------------------------------------------
1 | query MergedField {
2 | cat {
3 | name
4 | }
5 | me {
6 | id
7 | username
8 | realName
9 | reviews {
10 | body
11 | }
12 | history {
13 | ... on Sale {
14 | rating
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/multiple_queries.query:
--------------------------------------------------------------------------------
1 | query {
2 | topProducts {
3 | __typename
4 | price
5 | upc
6 | }
7 | me {
8 | __typename
9 | id
10 | username
11 | }
12 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/multiple_queries_with_nested_fragments.query:
--------------------------------------------------------------------------------
1 | fragment ProductFragment on Product {
2 | __typename
3 | price
4 | upc
5 | }
6 |
7 | fragment ReviewFragment on Review {
8 | __typename
9 | product {
10 | ...ProductFragment
11 | }
12 | }
13 |
14 | fragment UserFragment on User {
15 | __typename
16 | id
17 | username
18 | reviews {
19 | ...ReviewFragment
20 | }
21 | }
22 |
23 | query {
24 | topProducts {
25 | ...ProductFragment
26 | }
27 | me {
28 | ...UserFragment
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/multiple_queries_with_union_return.query:
--------------------------------------------------------------------------------
1 | query Histories {
2 | me {
3 | __typename
4 | id
5 | username
6 | }
7 | histories {
8 | __typename
9 | ... on Sale {
10 | product {
11 | __typename
12 | upc
13 | }
14 | rating
15 | }
16 | ... on Purchase {
17 | product {
18 | __typename
19 | upc
20 | }
21 | wallet {
22 | __typename
23 | currency
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/multiple_upstream.query:
--------------------------------------------------------------------------------
1 | query MultipleServers {
2 | topProducts {
3 | name
4 | reviews {
5 | body
6 | author {
7 | username
8 | }
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/object_fragment_on_interface.graphql:
--------------------------------------------------------------------------------
1 | query InterfaceResponse {
2 | identifiable {
3 | __typename
4 | id
5 | ... on User {
6 | username
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/single_upstream.query:
--------------------------------------------------------------------------------
1 | query Me {
2 | me {
3 | id
4 | username
5 | }
6 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/queries/union.query:
--------------------------------------------------------------------------------
1 | query MyHistory {
2 | me {
3 | username
4 | history {
5 | __typename
6 | ... on Purchase {
7 | wallet {
8 | amount
9 | }
10 | }
11 | ... on Sale {
12 | rating
13 | }
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/v2/pkg/testing/federationtesting/testdata/subscriptions/subscription.query:
--------------------------------------------------------------------------------
1 | subscription UpdatePrice($upc: String!) {
2 | updateProductPrice(upc: $upc) {
3 | upc
4 | name
5 | price
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/v2/pkg/testing/flags/flags.go:
--------------------------------------------------------------------------------
1 | //go:build !windows
2 |
3 | package flags
4 |
5 | const IsWindows = false
6 |
--------------------------------------------------------------------------------
/v2/pkg/testing/flags/flags_win.go:
--------------------------------------------------------------------------------
1 | //go:build windows
2 |
3 | package flags
4 |
5 | const IsWindows = true
6 |
--------------------------------------------------------------------------------
/v2/pkg/testing/goldie/goldie.go:
--------------------------------------------------------------------------------
1 | package goldie
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/sebdah/goldie/v2"
7 | )
8 |
9 | // New creates a new instance of Goldie.
10 | func New(t *testing.T) *goldie.Goldie {
11 | return goldie.New(t, goldie.WithFixtureDir("fixtures"))
12 | }
13 |
--------------------------------------------------------------------------------
/v2/pkg/testing/goldie/goldie_posix.go:
--------------------------------------------------------------------------------
1 | //go:build !windows
2 |
3 | package goldie
4 |
5 | import (
6 | "testing"
7 | )
8 |
9 | func Assert(t *testing.T, name string, actual []byte, _ ...bool) {
10 | t.Helper()
11 |
12 | New(t).Assert(t, name, actual)
13 | }
14 |
15 | func Update(t *testing.T, name string, actual []byte) {
16 | t.Helper()
17 |
18 | _ = New(t).Update(t, name, actual)
19 | }
20 |
--------------------------------------------------------------------------------
/v2/pkg/testing/goldie/goldie_win.go:
--------------------------------------------------------------------------------
1 | //go:build windows
2 |
3 | package goldie
4 |
5 | import (
6 | "testing"
7 | )
8 |
9 | func Assert(t *testing.T, name string, actual []byte, useOSSuffix ...bool) {
10 | t.Helper()
11 |
12 | if len(useOSSuffix) == 1 && useOSSuffix[0] {
13 | name = name + "_windows"
14 | }
15 |
16 | New(t).Assert(t, name, actual)
17 | }
18 |
19 | func Update(t *testing.T, name string, actual []byte) {
20 | t.Helper()
21 | t.Fatalf("golden files should not be updated on windows")
22 | }
23 |
--------------------------------------------------------------------------------
/v2/pkg/testing/subscriptiontesting/.gqlgen.yml:
--------------------------------------------------------------------------------
1 | models:
2 | Chatroom:
3 | model: github.com/TykTechnologies/graphql-go-tools/v2/pkg/testing/subscriptiontesting.Chatroom
4 |
--------------------------------------------------------------------------------
/v2/pkg/testing/subscriptiontesting/handler.go:
--------------------------------------------------------------------------------
1 | //go:generate go run -mod=mod github.com/99designs/gqlgen
2 | package subscriptiontesting
3 |
4 | import (
5 | "net/http"
6 | "time"
7 |
8 | "github.com/99designs/gqlgen/graphql/handler"
9 | "github.com/99designs/gqlgen/graphql/handler/extension"
10 | "github.com/99designs/gqlgen/graphql/handler/transport"
11 | "github.com/gorilla/websocket"
12 | )
13 |
14 | func ChatGraphQLEndpointHandler() http.Handler {
15 | srv := handler.New(NewExecutableSchema(New()))
16 |
17 | srv.AddTransport(transport.POST{})
18 | srv.AddTransport(transport.Websocket{
19 | KeepAlivePingInterval: 10 * time.Second,
20 | Upgrader: websocket.Upgrader{
21 | CheckOrigin: func(r *http.Request) bool {
22 | return true
23 | },
24 | },
25 | })
26 | srv.Use(extension.Introspection{})
27 |
28 | return srv
29 | }
30 |
--------------------------------------------------------------------------------
/v2/pkg/testing/subscriptiontesting/models_gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
2 |
3 | package subscriptiontesting
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 | }
15 |
--------------------------------------------------------------------------------
/v2/pkg/testing/subscriptiontesting/schema.graphql:
--------------------------------------------------------------------------------
1 | type Chatroom {
2 | name: String!
3 | messages: [Message!]!
4 | }
5 |
6 | type Message {
7 | id: ID!
8 | text: String!
9 | createdBy: String!
10 | createdAt: Time!
11 | }
12 |
13 | type Query {
14 | room(name:String!): Chatroom
15 | }
16 |
17 | type Mutation {
18 | post(text: String!, username: String!, roomName: String!): Message!
19 | }
20 |
21 | type Subscription {
22 | messageAdded(roomName: String!): Message!
23 | }
24 |
25 | scalar Time
26 |
27 | directive @user(username: String!) on SUBSCRIPTION
28 |
--------------------------------------------------------------------------------