graphql 1.8.7 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install_generator.rb +2 -1
- data/lib/generators/graphql/scalar_generator.rb +20 -0
- data/lib/generators/graphql/templates/base_scalar.erb +4 -0
- data/lib/generators/graphql/templates/scalar.erb +13 -0
- data/lib/graphql/analysis/ast/analyzer.rb +62 -0
- data/lib/graphql/analysis/ast/field_usage.rb +28 -0
- data/lib/graphql/analysis/ast/max_query_complexity.rb +23 -0
- data/lib/graphql/analysis/ast/max_query_depth.rb +18 -0
- data/lib/graphql/analysis/ast/query_complexity.rb +114 -0
- data/lib/graphql/analysis/ast/query_depth.rb +66 -0
- data/lib/graphql/analysis/ast/visitor.rb +255 -0
- data/lib/graphql/analysis/ast.rb +82 -0
- data/lib/graphql/analysis.rb +1 -0
- data/lib/graphql/argument.rb +5 -0
- data/lib/graphql/authorization.rb +1 -0
- data/lib/graphql/backwards_compatibility.rb +1 -1
- data/lib/graphql/base_type.rb +1 -1
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -2
- data/lib/graphql/compatibility/schema_parser_specification.rb +2 -6
- data/lib/graphql/dig.rb +19 -0
- data/lib/graphql/directive/include_directive.rb +1 -7
- data/lib/graphql/directive/skip_directive.rb +1 -8
- data/lib/graphql/directive.rb +13 -1
- data/lib/graphql/enum_type.rb +8 -0
- data/lib/graphql/execution/execute.rb +36 -17
- data/lib/graphql/execution/instrumentation.rb +2 -0
- data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
- data/lib/graphql/execution/interpreter/hash_response.rb +46 -0
- data/lib/graphql/execution/interpreter/resolve.rb +58 -0
- data/lib/graphql/execution/interpreter/runtime.rb +597 -0
- data/lib/graphql/execution/interpreter.rb +99 -0
- data/lib/graphql/execution/lazy.rb +8 -1
- data/lib/graphql/execution/lookahead.rb +351 -0
- data/lib/graphql/execution/multiplex.rb +37 -29
- data/lib/graphql/execution.rb +2 -0
- data/lib/graphql/execution_error.rb +1 -1
- data/lib/graphql/field.rb +1 -7
- data/lib/graphql/integer_encoding_error.rb +12 -0
- data/lib/graphql/internal_representation/rewrite.rb +127 -142
- data/lib/graphql/introspection/dynamic_fields.rb +8 -2
- data/lib/graphql/introspection/entry_points.rb +11 -6
- data/lib/graphql/introspection/enum_value_type.rb +4 -0
- data/lib/graphql/introspection/schema_type.rb +7 -2
- data/lib/graphql/introspection/type_type.rb +9 -5
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/language/block_string.rb +37 -0
- data/lib/graphql/language/document_from_schema_definition.rb +10 -7
- data/lib/graphql/language/lexer.rb +55 -36
- data/lib/graphql/language/lexer.rl +8 -3
- data/lib/graphql/language/nodes.rb +440 -362
- data/lib/graphql/language/parser.rb +56 -56
- data/lib/graphql/language/parser.y +12 -12
- data/lib/graphql/language/printer.rb +2 -2
- data/lib/graphql/language/visitor.rb +158 -15
- data/lib/graphql/language.rb +0 -1
- data/lib/graphql/literal_validation_error.rb +6 -0
- data/lib/graphql/query/arguments.rb +3 -2
- data/lib/graphql/query/arguments_cache.rb +1 -1
- data/lib/graphql/query/context.rb +14 -5
- data/lib/graphql/query/executor.rb +1 -1
- data/lib/graphql/query/result.rb +1 -1
- data/lib/graphql/query/validation_pipeline.rb +35 -11
- data/lib/graphql/query/variable_validation_error.rb +10 -1
- data/lib/graphql/query.rb +16 -2
- data/lib/graphql/relay/base_connection.rb +2 -0
- data/lib/graphql/relay/connection_instrumentation.rb +3 -1
- data/lib/graphql/relay/connection_resolve.rb +1 -1
- data/lib/graphql/relay/node.rb +2 -28
- data/lib/graphql/relay/relation_connection.rb +1 -1
- data/lib/graphql/schema/argument.rb +13 -5
- data/lib/graphql/schema/base_64_encoder.rb +4 -4
- data/lib/graphql/schema/build_from_definition.rb +2 -4
- data/lib/graphql/schema/default_type_error.rb +1 -1
- data/lib/graphql/schema/directive/feature.rb +66 -0
- data/lib/graphql/schema/directive/include.rb +25 -0
- data/lib/graphql/schema/directive/skip.rb +25 -0
- data/lib/graphql/schema/directive/transform.rb +48 -0
- data/lib/graphql/schema/directive.rb +103 -0
- data/lib/graphql/schema/enum_value.rb +3 -2
- data/lib/graphql/schema/field/connection_extension.rb +50 -0
- data/lib/graphql/schema/field/scope_extension.rb +18 -0
- data/lib/graphql/schema/field.rb +273 -64
- data/lib/graphql/schema/field_extension.rb +69 -0
- data/lib/graphql/schema/input_object.rb +16 -8
- data/lib/graphql/schema/interface.rb +1 -0
- data/lib/graphql/schema/loader.rb +22 -16
- data/lib/graphql/schema/member/base_dsl_methods.rb +8 -2
- data/lib/graphql/schema/member/build_type.rb +33 -1
- data/lib/graphql/schema/member/has_arguments.rb +6 -2
- data/lib/graphql/schema/member/has_fields.rb +18 -70
- data/lib/graphql/schema/member/has_path.rb +25 -0
- data/lib/graphql/schema/member/instrumentation.rb +10 -7
- data/lib/graphql/schema/member.rb +2 -0
- data/lib/graphql/schema/mutation.rb +6 -48
- data/lib/graphql/schema/non_null.rb +5 -1
- data/lib/graphql/schema/object.rb +18 -4
- data/lib/graphql/schema/printer.rb +1 -1
- data/lib/graphql/schema/relay_classic_mutation.rb +42 -9
- data/lib/graphql/schema/resolver/has_payload_type.rb +65 -0
- data/lib/graphql/schema/resolver.rb +45 -20
- data/lib/graphql/schema/subscription.rb +97 -0
- data/lib/graphql/schema/traversal.rb +11 -7
- data/lib/graphql/schema.rb +186 -38
- data/lib/graphql/static_validation/all_rules.rb +3 -2
- data/lib/graphql/static_validation/base_visitor.rb +199 -0
- data/lib/graphql/static_validation/default_visitor.rb +15 -0
- data/lib/graphql/static_validation/definition_dependencies.rb +62 -68
- data/lib/graphql/static_validation/{message.rb → error.rb} +11 -11
- data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
- data/lib/graphql/static_validation/literal_validator.rb +54 -11
- data/lib/graphql/static_validation/no_validate_visitor.rb +10 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +87 -16
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +31 -0
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +11 -11
- data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +52 -8
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +35 -0
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -15
- data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +19 -14
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +17 -19
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +30 -14
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +356 -29
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +32 -0
- data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +20 -13
- data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +37 -29
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +25 -17
- data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +12 -10
- data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +7 -11
- data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +16 -16
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +21 -14
- data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +10 -14
- data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +30 -30
- data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
- data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +25 -17
- data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +17 -18
- data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +47 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +10 -14
- data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +28 -17
- data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +35 -27
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +15 -14
- data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +41 -30
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +18 -14
- data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +73 -65
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
- data/lib/graphql/static_validation/validation_context.rb +8 -51
- data/lib/graphql/static_validation/validator.rb +23 -15
- data/lib/graphql/static_validation.rb +5 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -2
- data/lib/graphql/subscriptions/event.rb +28 -5
- data/lib/graphql/subscriptions/subscription_root.rb +66 -0
- data/lib/graphql/subscriptions.rb +16 -2
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +0 -1
- data/lib/graphql/tracing/appsignal_tracing.rb +1 -1
- data/lib/graphql/tracing/data_dog_tracing.rb +1 -1
- data/lib/graphql/tracing/new_relic_tracing.rb +3 -3
- data/lib/graphql/tracing/platform_tracing.rb +17 -1
- data/lib/graphql/tracing/prometheus_tracing.rb +1 -1
- data/lib/graphql/tracing/scout_tracing.rb +1 -1
- data/lib/graphql/tracing/skylight_tracing.rb +3 -3
- data/lib/graphql/tracing.rb +8 -8
- data/lib/graphql/types/float.rb +1 -1
- data/lib/graphql/types/int.rb +11 -2
- data/lib/graphql/types/iso_8601_date_time.rb +15 -1
- data/lib/graphql/types/relay/base_connection.rb +15 -1
- data/lib/graphql/types/relay/node.rb +0 -1
- data/lib/graphql/types/relay/node_field.rb +43 -0
- data/lib/graphql/types/relay/nodes_field.rb +45 -0
- data/lib/graphql/types/relay.rb +2 -0
- data/lib/graphql/unauthorized_error.rb +4 -0
- data/lib/graphql/unauthorized_field_error.rb +23 -0
- data/lib/graphql/upgrader/member.rb +5 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +6 -1
- data/readme.md +7 -7
- data/spec/dummy/Gemfile +1 -1
- data/spec/dummy/Gemfile.lock +157 -0
- data/spec/dummy/app/channels/graphql_channel.rb +22 -11
- data/spec/dummy/config/locales/en.yml +1 -1
- data/spec/dummy/log/test.log +199 -0
- data/spec/dummy/test/test_helper.rb +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/graphql/analysis/analyze_query_spec.rb +1 -1
- data/spec/graphql/analysis/ast/field_usage_spec.rb +51 -0
- data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +120 -0
- data/spec/graphql/analysis/ast/max_query_depth_spec.rb +114 -0
- data/spec/graphql/analysis/ast/query_complexity_spec.rb +299 -0
- data/spec/graphql/analysis/ast/query_depth_spec.rb +108 -0
- data/spec/graphql/analysis/ast_spec.rb +269 -0
- data/spec/graphql/authorization_spec.rb +120 -23
- data/spec/graphql/base_type_spec.rb +6 -4
- data/spec/graphql/enum_type_spec.rb +6 -1
- data/spec/graphql/execution/execute_spec.rb +9 -9
- data/spec/graphql/execution/instrumentation_spec.rb +19 -0
- data/spec/graphql/execution/interpreter_spec.rb +485 -0
- data/spec/graphql/execution/lazy_spec.rb +67 -1
- data/spec/graphql/execution/lookahead_spec.rb +363 -0
- data/spec/graphql/execution/multiplex_spec.rb +31 -3
- data/spec/graphql/execution/typecast_spec.rb +20 -20
- data/spec/graphql/execution_error_spec.rb +110 -96
- data/spec/graphql/field_spec.rb +1 -1
- data/spec/graphql/input_object_type_spec.rb +13 -352
- data/spec/graphql/int_type_spec.rb +19 -0
- data/spec/graphql/interface_type_spec.rb +4 -4
- data/spec/graphql/internal_representation/rewrite_spec.rb +2 -0
- data/spec/graphql/introspection/input_value_type_spec.rb +1 -1
- data/spec/graphql/introspection/type_type_spec.rb +1 -2
- data/spec/graphql/language/document_from_schema_definition_spec.rb +2 -2
- data/spec/graphql/language/lexer_spec.rb +72 -3
- data/spec/graphql/language/nodes_spec.rb +20 -0
- data/spec/graphql/language/printer_spec.rb +18 -6
- data/spec/graphql/language/visitor_spec.rb +320 -14
- data/spec/graphql/non_null_type_spec.rb +1 -1
- data/spec/graphql/object_type_spec.rb +32 -27
- data/spec/graphql/query/arguments_spec.rb +21 -0
- data/spec/graphql/query/context_spec.rb +28 -0
- data/spec/graphql/query/executor_spec.rb +40 -36
- data/spec/graphql/query_spec.rb +12 -6
- data/spec/graphql/schema/argument_spec.rb +35 -1
- data/spec/graphql/schema/build_from_definition_spec.rb +144 -29
- data/spec/graphql/schema/catchall_middleware_spec.rb +16 -15
- data/spec/graphql/schema/directive/feature_spec.rb +81 -0
- data/spec/graphql/schema/directive/transform_spec.rb +39 -0
- data/spec/graphql/schema/enum_spec.rb +12 -3
- data/spec/graphql/schema/enum_value_spec.rb +11 -0
- data/spec/graphql/schema/field_extension_spec.rb +115 -0
- data/spec/graphql/schema/field_spec.rb +47 -7
- data/spec/graphql/schema/input_object_spec.rb +95 -0
- data/spec/graphql/schema/instrumentation_spec.rb +3 -0
- data/spec/graphql/schema/interface_spec.rb +8 -2
- data/spec/graphql/schema/introspection_system_spec.rb +9 -1
- data/spec/graphql/schema/loader_spec.rb +5 -0
- data/spec/graphql/schema/member/accepts_definition_spec.rb +4 -0
- data/spec/graphql/schema/member/build_type_spec.rb +46 -0
- data/spec/graphql/schema/member/scoped_spec.rb +19 -3
- data/spec/graphql/schema/mutation_spec.rb +5 -3
- data/spec/graphql/schema/object_spec.rb +9 -1
- data/spec/graphql/schema/printer_spec.rb +255 -93
- data/spec/graphql/schema/relay_classic_mutation_spec.rb +133 -0
- data/spec/graphql/schema/resolver_spec.rb +173 -9
- data/spec/graphql/schema/scalar_spec.rb +6 -0
- data/spec/graphql/schema/subscription_spec.rb +416 -0
- data/spec/graphql/schema/traversal_spec.rb +10 -10
- data/spec/graphql/schema/type_expression_spec.rb +2 -2
- data/spec/graphql/schema/union_spec.rb +7 -0
- data/spec/graphql/schema/validation_spec.rb +1 -1
- data/spec/graphql/schema/warden_spec.rb +145 -88
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +213 -73
- data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +72 -29
- data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +4 -2
- data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +4 -2
- data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +10 -5
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -5
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +131 -5
- data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +2 -1
- data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +6 -3
- data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +4 -2
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +4 -2
- data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +2 -1
- data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +6 -3
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +22 -2
- data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +2 -1
- data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +6 -3
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +13 -4
- data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +58 -0
- data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +2 -1
- data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +14 -7
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +14 -7
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +8 -4
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +8 -4
- data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +23 -3
- data/spec/graphql/static_validation/type_stack_spec.rb +10 -19
- data/spec/graphql/static_validation/validator_spec.rb +50 -2
- data/spec/graphql/subscriptions_spec.rb +27 -16
- data/spec/graphql/tracing/new_relic_tracing_spec.rb +16 -0
- data/spec/graphql/tracing/platform_tracing_spec.rb +59 -37
- data/spec/graphql/tracing/prometheus_tracing_spec.rb +3 -0
- data/spec/graphql/tracing/skylight_tracing_spec.rb +16 -0
- data/spec/graphql/types/iso_8601_date_time_spec.rb +29 -2
- data/spec/graphql/union_type_spec.rb +2 -2
- data/spec/graphql/upgrader/member_spec.rb +67 -0
- data/spec/{graphql → integration/mongoid/graphql}/relay/mongo_relation_connection_spec.rb +11 -22
- data/spec/integration/mongoid/spec_helper.rb +2 -0
- data/spec/{support → integration/mongoid}/star_trek/data.rb +0 -0
- data/spec/{support → integration/mongoid}/star_trek/schema.rb +56 -34
- data/spec/{support/star_wars → integration/rails}/data.rb +1 -0
- data/spec/{support → integration/rails/generators}/base_generator_test.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/enum_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/install_generator_spec.rb +1 -1
- data/spec/{generators → integration/rails/generators}/graphql/interface_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/loader_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/mutation_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/object_generator_spec.rb +0 -0
- data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +28 -0
- data/spec/{generators → integration/rails/generators}/graphql/union_generator_spec.rb +0 -0
- data/spec/integration/rails/graphql/input_object_type_spec.rb +364 -0
- data/spec/{graphql → integration/rails/graphql}/query/variables_spec.rb +7 -7
- data/spec/{graphql → integration/rails/graphql}/relay/array_connection_spec.rb +9 -9
- data/spec/{graphql → integration/rails/graphql}/relay/base_connection_spec.rb +11 -3
- data/spec/{graphql → integration/rails/graphql}/relay/connection_instrumentation_spec.rb +19 -22
- data/spec/{graphql → integration/rails/graphql}/relay/connection_resolve_spec.rb +16 -0
- data/spec/{graphql → integration/rails/graphql}/relay/connection_type_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/edge_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/mutation_spec.rb +48 -0
- data/spec/{graphql → integration/rails/graphql}/relay/node_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/page_info_spec.rb +22 -22
- data/spec/{graphql → integration/rails/graphql}/relay/range_add_spec.rb +4 -4
- data/spec/{graphql → integration/rails/graphql}/relay/relation_connection_spec.rb +56 -27
- data/spec/{graphql → integration/rails/graphql}/schema_spec.rb +15 -11
- data/spec/{graphql → integration/rails/graphql}/tracing/active_support_notifications_tracing_spec.rb +16 -9
- data/spec/integration/rails/spec_helper.rb +25 -0
- data/spec/integration/tmp/app/graphql/types/family_type.rb +9 -0
- data/spec/spec_helper.rb +23 -39
- data/spec/support/dummy/data.rb +20 -17
- data/spec/support/dummy/schema.rb +315 -305
- data/spec/support/error_bubbling_helpers.rb +23 -0
- data/spec/support/jazz.rb +213 -46
- data/spec/support/lazy_helpers.rb +69 -27
- data/spec/support/new_relic.rb +3 -0
- data/spec/support/skylight.rb +3 -0
- data/spec/support/star_wars/schema.rb +131 -81
- data/spec/support/static_validation_helpers.rb +9 -5
- metadata +418 -261
- data/lib/graphql/language/comments.rb +0 -45
- data/lib/graphql/static_validation/arguments_validator.rb +0 -50
- data/spec/graphql/schema/member/has_fields_spec.rb +0 -129
- data/spec/rails_dependency_sanity_spec.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb79bf185d3d89d53f50ad5f0ae1cc93e3480acb
|
4
|
+
data.tar.gz: 46c04d4e296ea2b3b520d6df50f82d76da5ec641
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78e070c3df4abd9e2d649ba0e5f1e7fdcef9b0241572a30bf233d516fa28b7eee9afa0fd2d650db835556dff87f4eddb344aefce8825019569aa7e55ff28f780
|
7
|
+
data.tar.gz: eb138cb5d2274c815ea42ec2eff4371cf34023ad817e4009302cb6de6da7deea213ccfaa2169d86a6a8c2b684f9e4fc8bd0780060163a764960d22af1a48bb25
|
@@ -17,6 +17,7 @@ module Graphql
|
|
17
17
|
# - base_input_object.rb
|
18
18
|
# - base_interface.rb
|
19
19
|
# - base_object.rb
|
20
|
+
# - base_scalar.rb
|
20
21
|
# - base_union.rb
|
21
22
|
# - query_type.rb
|
22
23
|
# - loaders/
|
@@ -92,7 +93,7 @@ module Graphql
|
|
92
93
|
create_dir("#{options[:directory]}/types")
|
93
94
|
template("schema.erb", schema_file_path)
|
94
95
|
|
95
|
-
["base_object", "base_enum", "base_input_object", "base_interface", "base_union"].each do |base_type|
|
96
|
+
["base_object", "base_enum", "base_input_object", "base_interface", "base_scalar", "base_union"].each do |base_type|
|
96
97
|
template("#{base_type}.erb", "#{options[:directory]}/types/#{base_type}.rb")
|
97
98
|
end
|
98
99
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'generators/graphql/type_generator'
|
3
|
+
|
4
|
+
module Graphql
|
5
|
+
module Generators
|
6
|
+
# Generate a scalar type by given name.
|
7
|
+
#
|
8
|
+
# ```
|
9
|
+
# rails g graphql:scalar Date
|
10
|
+
# ```
|
11
|
+
class ScalarGenerator < TypeGeneratorBase
|
12
|
+
desc "Create a GraphQL::ScalarType with the given name"
|
13
|
+
source_root File.expand_path('../templates', __FILE__)
|
14
|
+
|
15
|
+
def create_type_file
|
16
|
+
template "scalar.erb", "#{options[:directory]}/types/#{type_file_name}.rb"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Types
|
2
|
+
class <%= type_ruby_name.split('::')[-1] %> < Types::BaseScalar
|
3
|
+
def self.coerce_input(input_value, context)
|
4
|
+
# Override this to prepare a client-provided GraphQL value for your Ruby code
|
5
|
+
input_value
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.coerce_result(ruby_value, context)
|
9
|
+
# Override this to serialize a Ruby value for the GraphQL response
|
10
|
+
ruby_value.to_s
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Analysis
|
4
|
+
module AST
|
5
|
+
# Query analyzer for query ASTs. Query analyzers respond to visitor style methods
|
6
|
+
# but are prefixed by `enter` and `leave`.
|
7
|
+
#
|
8
|
+
# @param [GraphQL::Query] The query to analyze
|
9
|
+
class Analyzer
|
10
|
+
def initialize(query)
|
11
|
+
@query = query
|
12
|
+
end
|
13
|
+
|
14
|
+
# Analyzer hook to decide at analysis time whether a query should
|
15
|
+
# be analyzed or not.
|
16
|
+
# @return [Boolean] If the query should be analyzed or not
|
17
|
+
def analyze?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# The result for this analyzer. Returning {GraphQL::AnalysisError} results
|
22
|
+
# in a query error.
|
23
|
+
# @return [Any] The analyzer result
|
24
|
+
def result
|
25
|
+
raise NotImplementedError
|
26
|
+
end
|
27
|
+
|
28
|
+
# Don't use make_visit_method because it breaks `super`
|
29
|
+
def self.build_visitor_hooks(member_name)
|
30
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
31
|
+
def on_enter_#{member_name}(node, parent, visitor)
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_leave_#{member_name}(node, parent, visitor)
|
35
|
+
end
|
36
|
+
EOS
|
37
|
+
end
|
38
|
+
|
39
|
+
build_visitor_hooks :argument
|
40
|
+
build_visitor_hooks :directive
|
41
|
+
build_visitor_hooks :document
|
42
|
+
build_visitor_hooks :enum
|
43
|
+
build_visitor_hooks :field
|
44
|
+
build_visitor_hooks :fragment_spread
|
45
|
+
build_visitor_hooks :inline_fragment
|
46
|
+
build_visitor_hooks :input_object
|
47
|
+
build_visitor_hooks :list_type
|
48
|
+
build_visitor_hooks :non_null_type
|
49
|
+
build_visitor_hooks :null_value
|
50
|
+
build_visitor_hooks :operation_definition
|
51
|
+
build_visitor_hooks :type_name
|
52
|
+
build_visitor_hooks :variable_definition
|
53
|
+
build_visitor_hooks :variable_identifier
|
54
|
+
build_visitor_hooks :abstract_node
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
attr_reader :query
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Analysis
|
4
|
+
module AST
|
5
|
+
class FieldUsage < Analyzer
|
6
|
+
def initialize(query)
|
7
|
+
super
|
8
|
+
@used_fields = Set.new
|
9
|
+
@used_deprecated_fields = Set.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_leave_field(parent, node, visitor)
|
13
|
+
field_defn = visitor.field_definition
|
14
|
+
field = "#{visitor.parent_type_definition.name}.#{field_defn.name}"
|
15
|
+
@used_fields << field
|
16
|
+
@used_deprecated_fields << field if field_defn.deprecation_reason
|
17
|
+
end
|
18
|
+
|
19
|
+
def result
|
20
|
+
{
|
21
|
+
used_fields: @used_fields.to_a,
|
22
|
+
used_deprecated_fields: @used_deprecated_fields.to_a
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "./query_complexity"
|
3
|
+
module GraphQL
|
4
|
+
module Analysis
|
5
|
+
module AST
|
6
|
+
# Used under the hood to implement complexity validation,
|
7
|
+
# see {Schema#max_complexity} and {Query#max_complexity}
|
8
|
+
class MaxQueryComplexity < QueryComplexity
|
9
|
+
def result
|
10
|
+
return if query.max_complexity.nil?
|
11
|
+
|
12
|
+
total_complexity = super
|
13
|
+
|
14
|
+
if total_complexity > query.max_complexity
|
15
|
+
GraphQL::AnalysisError.new("Query has complexity of #{total_complexity}, which exceeds max complexity of #{query.max_complexity}")
|
16
|
+
else
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Analysis
|
4
|
+
module AST
|
5
|
+
class MaxQueryDepth < QueryDepth
|
6
|
+
def result
|
7
|
+
return unless query.max_depth
|
8
|
+
|
9
|
+
if @max_depth > query.max_depth
|
10
|
+
GraphQL::AnalysisError.new("Query has depth of #{@max_depth}, which exceeds max depth of #{query.max_depth}")
|
11
|
+
else
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Analysis
|
4
|
+
# Calculate the complexity of a query, using {Field#complexity} values.
|
5
|
+
module AST
|
6
|
+
class QueryComplexity < Analyzer
|
7
|
+
# State for the query complexity calcuation:
|
8
|
+
# - `complexities_on_type` holds complexity scores for each type in an IRep node
|
9
|
+
def initialize(query)
|
10
|
+
super
|
11
|
+
@complexities_on_type = [TypeComplexity.new]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Overide this method to use the complexity result
|
15
|
+
def result
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_enter_field(node, parent, visitor)
|
20
|
+
# We don't want to visit fragment definitions,
|
21
|
+
# we'll visit them when we hit the spreads instead
|
22
|
+
return if visitor.visiting_fragment_definition?
|
23
|
+
return if visitor.skipping?
|
24
|
+
|
25
|
+
@complexities_on_type.push(TypeComplexity.new)
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_leave_field(node, parent, visitor)
|
29
|
+
# We don't want to visit fragment definitions,
|
30
|
+
# we'll visit them when we hit the spreads instead
|
31
|
+
return if visitor.visiting_fragment_definition?
|
32
|
+
return if visitor.skipping?
|
33
|
+
|
34
|
+
type_complexities = @complexities_on_type.pop
|
35
|
+
child_complexity = type_complexities.max_possible_complexity
|
36
|
+
own_complexity = get_complexity(node, visitor.field_definition, child_complexity, visitor)
|
37
|
+
|
38
|
+
parent_type = visitor.parent_type_definition
|
39
|
+
possible_types = if parent_type.kind.abstract?
|
40
|
+
query.possible_types(parent_type)
|
41
|
+
else
|
42
|
+
[parent_type]
|
43
|
+
end
|
44
|
+
|
45
|
+
key = selection_key(visitor.response_path, visitor.query)
|
46
|
+
|
47
|
+
possible_types.each do |type|
|
48
|
+
@complexities_on_type.last.merge(type, key, own_complexity)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def on_enter_fragment_spread(node, _, visitor)
|
53
|
+
visitor.enter_fragment_spread_inline(node)
|
54
|
+
end
|
55
|
+
|
56
|
+
def on_leave_fragment_spread(node, _, visitor)
|
57
|
+
visitor.leave_fragment_spread_inline(node)
|
58
|
+
end
|
59
|
+
|
60
|
+
def result
|
61
|
+
@complexities_on_type.last.max_possible_complexity
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def selection_key(response_path, query)
|
67
|
+
# We add the query object id to support multiplex queries
|
68
|
+
# even if they have the same response path, they should
|
69
|
+
# always be added.
|
70
|
+
response_path.join(".") + "-#{query.object_id}"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Get a complexity value for a field,
|
74
|
+
# by getting the number or calling its proc
|
75
|
+
def get_complexity(ast_node, field_defn, child_complexity, visitor)
|
76
|
+
# Return if we've visited this response path before (not counting duplicates)
|
77
|
+
defined_complexity = field_defn.complexity
|
78
|
+
|
79
|
+
arguments = visitor.arguments_for(ast_node, field_defn)
|
80
|
+
|
81
|
+
case defined_complexity
|
82
|
+
when Proc
|
83
|
+
defined_complexity.call(query.context, arguments, child_complexity)
|
84
|
+
when Numeric
|
85
|
+
defined_complexity + (child_complexity || 0)
|
86
|
+
else
|
87
|
+
raise("Invalid complexity: #{defined_complexity.inspect} on #{field_defn.name}")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Selections on an object may apply differently depending on what is _actually_ returned by the resolve function.
|
92
|
+
# Find the maximum possible complexity among those combinations.
|
93
|
+
class TypeComplexity
|
94
|
+
def initialize
|
95
|
+
@types = Hash.new { |h, k| h[k] = {} }
|
96
|
+
end
|
97
|
+
|
98
|
+
# Return the max possible complexity for types in this selection
|
99
|
+
def max_possible_complexity
|
100
|
+
@types.map do |type, fields|
|
101
|
+
fields.values.inject(:+)
|
102
|
+
end.max
|
103
|
+
end
|
104
|
+
|
105
|
+
# Store the complexity for the branch on `type_defn`.
|
106
|
+
# Later we will see if this is the max complexity among branches.
|
107
|
+
def merge(type_defn, key, complexity)
|
108
|
+
@types[type_defn][key] = complexity
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Analysis
|
4
|
+
# A query reducer for measuring the depth of a given query.
|
5
|
+
#
|
6
|
+
# @example Logging the depth of a query
|
7
|
+
# class LogQueryDepth < GraphQL::Analysis::QueryDepth
|
8
|
+
# def on_analysis_end
|
9
|
+
# log("GraphQL query depth: #{@max_depth}")
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# Schema.execute(query_str)
|
14
|
+
# # GraphQL query depth: 8
|
15
|
+
#
|
16
|
+
module AST
|
17
|
+
class QueryDepth < Analyzer
|
18
|
+
def initialize(query)
|
19
|
+
@max_depth = 0
|
20
|
+
@current_depth = 0
|
21
|
+
@skip_depth = 0
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_enter_field(node, parent, visitor)
|
26
|
+
return if visitor.skipping? || visitor.visiting_fragment_definition?
|
27
|
+
|
28
|
+
# Don't validate introspection fields or skipped nodes
|
29
|
+
if GraphQL::Schema::DYNAMIC_FIELDS.include?(visitor.field_definition.name)
|
30
|
+
@skip_depth += 1
|
31
|
+
elsif @skip_depth > 0
|
32
|
+
# we're inside an introspection query or skipped node
|
33
|
+
else
|
34
|
+
@current_depth += 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def on_leave_field(node, parent, visitor)
|
39
|
+
return if visitor.skipping? || visitor.visiting_fragment_definition?
|
40
|
+
|
41
|
+
# Don't validate introspection fields or skipped nodes
|
42
|
+
if GraphQL::Schema::DYNAMIC_FIELDS.include?(visitor.field_definition.name)
|
43
|
+
@skip_depth -= 1
|
44
|
+
else
|
45
|
+
if @max_depth < @current_depth
|
46
|
+
@max_depth = @current_depth
|
47
|
+
end
|
48
|
+
@current_depth -= 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def on_enter_fragment_spread(node, _, visitor)
|
53
|
+
visitor.enter_fragment_spread_inline(node)
|
54
|
+
end
|
55
|
+
|
56
|
+
def on_leave_fragment_spread(node, _, visitor)
|
57
|
+
visitor.leave_fragment_spread_inline(node)
|
58
|
+
end
|
59
|
+
|
60
|
+
def result
|
61
|
+
@max_depth
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,255 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Analysis
|
4
|
+
module AST
|
5
|
+
# Depth first traversal through a query AST, calling AST analyzers
|
6
|
+
# along the way.
|
7
|
+
#
|
8
|
+
# The visitor is a special case of GraphQL::Language::Visitor, visiting
|
9
|
+
# only the selected operation, providing helpers for common use cases such
|
10
|
+
# as skipped fields and visiting fragment spreads.
|
11
|
+
#
|
12
|
+
# @see {GraphQL::Analysis::AST::Analyzer} AST Analyzers for queries
|
13
|
+
class Visitor < GraphQL::Language::Visitor
|
14
|
+
def initialize(query:, analyzers:)
|
15
|
+
@analyzers = analyzers
|
16
|
+
@path = []
|
17
|
+
@object_types = []
|
18
|
+
@directives = []
|
19
|
+
@field_definitions = []
|
20
|
+
@argument_definitions = []
|
21
|
+
@directive_definitions = []
|
22
|
+
@query = query
|
23
|
+
@schema = query.schema
|
24
|
+
@response_path = []
|
25
|
+
@skip_stack = [false]
|
26
|
+
super(query.selected_operation)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [GraphQL::Query] the query being visited
|
30
|
+
attr_reader :query
|
31
|
+
|
32
|
+
# @return [Array<GraphQL::ObjectType>] Types whose scope we've entered
|
33
|
+
attr_reader :object_types
|
34
|
+
|
35
|
+
def visit
|
36
|
+
return unless @document
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
# Visit Helpers
|
41
|
+
|
42
|
+
# @return [GraphQL::Query::Arguments] Arguments for this node, merging default values, literal values and query variables
|
43
|
+
# @see {GraphQL::Query#arguments_for}
|
44
|
+
def arguments_for(ast_node, field_definition)
|
45
|
+
@query.arguments_for(ast_node, field_definition)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Boolean] If the visitor is currently inside a fragment definition
|
49
|
+
def visiting_fragment_definition?
|
50
|
+
@in_fragment_def
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [Boolean] If the current node should be skipped because of a skip or include directive
|
54
|
+
def skipping?
|
55
|
+
@skipping
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Array<String>] The path to the response key for the current field
|
59
|
+
def response_path
|
60
|
+
@response_path.dup
|
61
|
+
end
|
62
|
+
|
63
|
+
# Visitor Hooks
|
64
|
+
|
65
|
+
def on_operation_definition(node, parent)
|
66
|
+
object_type = @schema.root_type_for_operation(node.operation_type)
|
67
|
+
@object_types.push(object_type)
|
68
|
+
@path.push("#{node.operation_type}#{node.name ? " #{node.name}" : ""}")
|
69
|
+
call_analyzers(:on_enter_operation_definition, node, parent)
|
70
|
+
super
|
71
|
+
call_analyzers(:on_leave_operation_definition, node, parent)
|
72
|
+
@object_types.pop
|
73
|
+
@path.pop
|
74
|
+
end
|
75
|
+
|
76
|
+
def on_fragment_definition(node, parent)
|
77
|
+
on_fragment_with_type(node) do
|
78
|
+
@path.push("fragment #{node.name}")
|
79
|
+
@in_fragment_def = false
|
80
|
+
call_analyzers(:on_enter_fragment_definition, node, parent)
|
81
|
+
super
|
82
|
+
@in_fragment_def = false
|
83
|
+
call_analyzers(:on_leave_fragment_definition, node, parent)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def on_inline_fragment(node, parent)
|
88
|
+
on_fragment_with_type(node) do
|
89
|
+
@path.push("...#{node.type ? " on #{node.type.name}" : ""}")
|
90
|
+
call_analyzers(:on_enter_inline_fragment, node, parent)
|
91
|
+
super
|
92
|
+
call_analyzers(:on_leave_inline_fragment, node, parent)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def on_field(node, parent)
|
97
|
+
@response_path.push(node.alias || node.name)
|
98
|
+
parent_type = @object_types.last
|
99
|
+
field_definition = @schema.get_field(parent_type, node.name)
|
100
|
+
@field_definitions.push(field_definition)
|
101
|
+
if !field_definition.nil?
|
102
|
+
next_object_type = field_definition.type.unwrap
|
103
|
+
@object_types.push(next_object_type)
|
104
|
+
else
|
105
|
+
@object_types.push(nil)
|
106
|
+
end
|
107
|
+
@path.push(node.alias || node.name)
|
108
|
+
|
109
|
+
@skipping = @skip_stack.last || skip?(node)
|
110
|
+
@skip_stack << @skipping
|
111
|
+
|
112
|
+
call_analyzers(:on_enter_field, node, parent)
|
113
|
+
super
|
114
|
+
|
115
|
+
@skipping = @skip_stack.pop
|
116
|
+
|
117
|
+
call_analyzers(:on_leave_field, node, parent)
|
118
|
+
@response_path.pop
|
119
|
+
@field_definitions.pop
|
120
|
+
@object_types.pop
|
121
|
+
@path.pop
|
122
|
+
end
|
123
|
+
|
124
|
+
def on_directive(node, parent)
|
125
|
+
directive_defn = @schema.directives[node.name]
|
126
|
+
@directive_definitions.push(directive_defn)
|
127
|
+
call_analyzers(:on_enter_directive, node, parent)
|
128
|
+
super
|
129
|
+
call_analyzers(:on_leave_directive, node, parent)
|
130
|
+
@directive_definitions.pop
|
131
|
+
end
|
132
|
+
|
133
|
+
def on_argument(node, parent)
|
134
|
+
argument_defn = if (arg = @argument_definitions.last)
|
135
|
+
arg_type = arg.type.unwrap
|
136
|
+
if arg_type.kind.input_object?
|
137
|
+
arg_type.input_fields[node.name]
|
138
|
+
else
|
139
|
+
nil
|
140
|
+
end
|
141
|
+
elsif (directive_defn = @directive_definitions.last)
|
142
|
+
directive_defn.arguments[node.name]
|
143
|
+
elsif (field_defn = @field_definitions.last)
|
144
|
+
field_defn.arguments[node.name]
|
145
|
+
else
|
146
|
+
nil
|
147
|
+
end
|
148
|
+
|
149
|
+
@argument_definitions.push(argument_defn)
|
150
|
+
@path.push(node.name)
|
151
|
+
call_analyzers(:on_enter_argument, node, parent)
|
152
|
+
super
|
153
|
+
call_analyzers(:on_leave_argument, node, parent)
|
154
|
+
@argument_definitions.pop
|
155
|
+
@path.pop
|
156
|
+
end
|
157
|
+
|
158
|
+
def on_fragment_spread(node, parent)
|
159
|
+
@path.push("... #{node.name}")
|
160
|
+
call_analyzers(:on_enter_fragment_spread, node, parent)
|
161
|
+
super
|
162
|
+
call_analyzers(:on_leave_fragment_spread, node, parent)
|
163
|
+
@path.pop
|
164
|
+
end
|
165
|
+
|
166
|
+
def on_abstract_node(node, parent)
|
167
|
+
call_analyzers(:on_enter_abstract_node, node, parent)
|
168
|
+
super
|
169
|
+
call_analyzers(:on_leave_abstract_node, node, parent)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Visit a fragment spread inline instead of visiting the definition
|
173
|
+
# by itself.
|
174
|
+
def enter_fragment_spread_inline(fragment_spread)
|
175
|
+
fragment_def = query.fragments[fragment_spread.name]
|
176
|
+
|
177
|
+
object_type = if fragment_def.type
|
178
|
+
query.schema.types.fetch(fragment_def.type.name, nil)
|
179
|
+
else
|
180
|
+
object_types.last
|
181
|
+
end
|
182
|
+
|
183
|
+
object_types << object_type
|
184
|
+
|
185
|
+
fragment_def.selections.each do |selection|
|
186
|
+
visit_node(selection, fragment_def)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Visit a fragment spread inline instead of visiting the definition
|
191
|
+
# by itself.
|
192
|
+
def leave_fragment_spread_inline(_fragment_spread)
|
193
|
+
object_types.pop
|
194
|
+
end
|
195
|
+
|
196
|
+
# @return [GraphQL::BaseType] The current object type
|
197
|
+
def type_definition
|
198
|
+
@object_types.last
|
199
|
+
end
|
200
|
+
|
201
|
+
# @return [GraphQL::BaseType] The type which the current type came from
|
202
|
+
def parent_type_definition
|
203
|
+
@object_types[-2]
|
204
|
+
end
|
205
|
+
|
206
|
+
# @return [GraphQL::Field, nil] The most-recently-entered GraphQL::Field, if currently inside one
|
207
|
+
def field_definition
|
208
|
+
@field_definitions.last
|
209
|
+
end
|
210
|
+
|
211
|
+
# @return [GraphQL::Field, nil] The GraphQL field which returned the object that the current field belongs to
|
212
|
+
def previous_field_definition
|
213
|
+
@field_definitions[-2]
|
214
|
+
end
|
215
|
+
|
216
|
+
# @return [GraphQL::Directive, nil] The most-recently-entered GraphQL::Directive, if currently inside one
|
217
|
+
def directive_definition
|
218
|
+
@directive_definitions.last
|
219
|
+
end
|
220
|
+
|
221
|
+
# @return [GraphQL::Argument, nil] The most-recently-entered GraphQL::Argument, if currently inside one
|
222
|
+
def argument_definition
|
223
|
+
# Don't get the _last_ one because that's the current one.
|
224
|
+
# Get the second-to-last one, which is the parent of the current one.
|
225
|
+
@argument_definitions[-2]
|
226
|
+
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
def skip?(ast_node)
|
231
|
+
dir = ast_node.directives
|
232
|
+
dir.any? && !GraphQL::Execution::DirectiveChecks.include?(dir, query)
|
233
|
+
end
|
234
|
+
|
235
|
+
def call_analyzers(method, node, parent)
|
236
|
+
@analyzers.each do |analyzer|
|
237
|
+
analyzer.public_send(method, node, parent, self)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def on_fragment_with_type(node)
|
242
|
+
object_type = if node.type
|
243
|
+
@schema.types.fetch(node.type.name, nil)
|
244
|
+
else
|
245
|
+
@object_types.last
|
246
|
+
end
|
247
|
+
@object_types.push(object_type)
|
248
|
+
yield(node)
|
249
|
+
@object_types.pop
|
250
|
+
@path.pop
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|