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
data/lib/graphql/schema.rb
CHANGED
@@ -19,7 +19,6 @@ require "graphql/schema/validation"
|
|
19
19
|
require "graphql/schema/warden"
|
20
20
|
require "graphql/schema/build_from_definition"
|
21
21
|
|
22
|
-
|
23
22
|
require "graphql/schema/member"
|
24
23
|
require "graphql/schema/wrapper"
|
25
24
|
require "graphql/schema/list"
|
@@ -27,15 +26,23 @@ require "graphql/schema/non_null"
|
|
27
26
|
require "graphql/schema/argument"
|
28
27
|
require "graphql/schema/enum_value"
|
29
28
|
require "graphql/schema/enum"
|
29
|
+
require "graphql/schema/field_extension"
|
30
30
|
require "graphql/schema/field"
|
31
31
|
require "graphql/schema/input_object"
|
32
32
|
require "graphql/schema/interface"
|
33
|
+
require "graphql/schema/scalar"
|
34
|
+
require "graphql/schema/object"
|
35
|
+
require "graphql/schema/union"
|
36
|
+
require "graphql/schema/directive"
|
37
|
+
require "graphql/schema/directive/include"
|
38
|
+
require "graphql/schema/directive/skip"
|
39
|
+
require "graphql/schema/directive/feature"
|
40
|
+
require "graphql/schema/directive/transform"
|
41
|
+
|
33
42
|
require "graphql/schema/resolver"
|
34
43
|
require "graphql/schema/mutation"
|
35
44
|
require "graphql/schema/relay_classic_mutation"
|
36
|
-
require "graphql/schema/
|
37
|
-
require "graphql/schema/scalar"
|
38
|
-
require "graphql/schema/union"
|
45
|
+
require "graphql/schema/subscription"
|
39
46
|
|
40
47
|
module GraphQL
|
41
48
|
# A GraphQL schema which may be queried with {GraphQL::Query}.
|
@@ -78,22 +85,29 @@ module GraphQL
|
|
78
85
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
79
86
|
:max_depth, :max_complexity, :default_max_page_size,
|
80
87
|
:orphan_types, :resolve_type, :type_error, :parse_error,
|
88
|
+
:error_bubbling,
|
81
89
|
:raise_definition_error,
|
82
90
|
:object_from_id, :id_from_object,
|
83
91
|
:default_mask,
|
84
92
|
:cursor_encoder,
|
85
|
-
directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.name] = d; m
|
93
|
+
directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.name] = d; m } },
|
94
|
+
directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
|
86
95
|
instrument: ->(schema, type, instrumenter, after_built_ins: false) {
|
87
96
|
if type == :field && after_built_ins
|
88
97
|
type = :field_after_built_ins
|
89
98
|
end
|
90
99
|
schema.instrumenters[type] << instrumenter
|
91
100
|
},
|
92
|
-
query_analyzer: ->(schema, analyzer) {
|
101
|
+
query_analyzer: ->(schema, analyzer) {
|
102
|
+
if analyzer == GraphQL::Authorization::Analyzer
|
103
|
+
warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
104
|
+
end
|
105
|
+
schema.query_analyzers << analyzer
|
106
|
+
},
|
93
107
|
multiplex_analyzer: ->(schema, analyzer) { schema.multiplex_analyzers << analyzer },
|
94
108
|
middleware: ->(schema, middleware) { schema.middleware << middleware },
|
95
109
|
lazy_resolve: ->(schema, lazy_class, lazy_value_method) { schema.lazy_methods.set(lazy_class, lazy_value_method) },
|
96
|
-
rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block)},
|
110
|
+
rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block) },
|
97
111
|
tracer: ->(schema, tracer) { schema.tracers.push(tracer) }
|
98
112
|
|
99
113
|
attr_accessor \
|
@@ -105,7 +119,11 @@ module GraphQL
|
|
105
119
|
:cursor_encoder,
|
106
120
|
:ast_node,
|
107
121
|
:raise_definition_error,
|
108
|
-
:introspection_namespace
|
122
|
+
:introspection_namespace,
|
123
|
+
:analysis_engine
|
124
|
+
|
125
|
+
# [Boolean] True if this object bubbles validation errors up from a field into its parent InputObject, if there is one.
|
126
|
+
attr_accessor :error_bubbling
|
109
127
|
|
110
128
|
# Single, long-lived instance of the provided subscriptions class, if there is one.
|
111
129
|
# @return [GraphQL::Subscriptions]
|
@@ -134,9 +152,6 @@ module GraphQL
|
|
134
152
|
# @see {Query#tracers} for query-specific tracers
|
135
153
|
attr_reader :tracers
|
136
154
|
|
137
|
-
self.default_execution_strategy = GraphQL::Execution::Execute
|
138
|
-
|
139
|
-
DIRECTIVES = [GraphQL::Directive::IncludeDirective, GraphQL::Directive::SkipDirective, GraphQL::Directive::DeprecatedDirective]
|
140
155
|
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
|
141
156
|
|
142
157
|
attr_reader :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
|
@@ -145,7 +160,7 @@ module GraphQL
|
|
145
160
|
@tracers = []
|
146
161
|
@definition_error = nil
|
147
162
|
@orphan_types = []
|
148
|
-
@directives =
|
163
|
+
@directives = self.class.default_directives
|
149
164
|
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
150
165
|
@middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
151
166
|
@query_analyzers = []
|
@@ -160,6 +175,7 @@ module GraphQL
|
|
160
175
|
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
161
176
|
@cursor_encoder = Base64Encoder
|
162
177
|
# Default to the built-in execution strategy:
|
178
|
+
@analysis_engine = GraphQL::Analysis
|
163
179
|
@query_execution_strategy = self.class.default_execution_strategy
|
164
180
|
@mutation_execution_strategy = self.class.default_execution_strategy
|
165
181
|
@subscription_execution_strategy = self.class.default_execution_strategy
|
@@ -168,6 +184,20 @@ module GraphQL
|
|
168
184
|
@context_class = GraphQL::Query::Context
|
169
185
|
@introspection_namespace = nil
|
170
186
|
@introspection_system = nil
|
187
|
+
@interpreter = false
|
188
|
+
@error_bubbling = false
|
189
|
+
end
|
190
|
+
|
191
|
+
# @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
|
192
|
+
def interpreter?
|
193
|
+
@interpreter
|
194
|
+
end
|
195
|
+
|
196
|
+
# @api private
|
197
|
+
attr_writer :interpreter
|
198
|
+
|
199
|
+
def inspect
|
200
|
+
"#<#{self.class.name} ...>"
|
171
201
|
end
|
172
202
|
|
173
203
|
def initialize_copy(other)
|
@@ -206,12 +236,16 @@ module GraphQL
|
|
206
236
|
rescue_middleware.remove_handler(*args, &block)
|
207
237
|
end
|
208
238
|
|
239
|
+
def using_ast_analysis?
|
240
|
+
@analysis_engine == GraphQL::Analysis::AST
|
241
|
+
end
|
242
|
+
|
209
243
|
# For forwards-compatibility with Schema classes
|
210
244
|
alias :graphql_definition :itself
|
211
245
|
|
212
246
|
# Validate a query string according to this schema.
|
213
247
|
# @param string_or_document [String, GraphQL::Language::Nodes::Document]
|
214
|
-
# @return [Array<GraphQL::StaticValidation::
|
248
|
+
# @return [Array<GraphQL::StaticValidation::Error >]
|
215
249
|
def validate(string_or_document, rules: nil)
|
216
250
|
doc = if string_or_document.is_a?(String)
|
217
251
|
GraphQL.parse(string_or_document)
|
@@ -389,7 +423,7 @@ module GraphQL
|
|
389
423
|
# Fields for this type, after instrumentation is applied
|
390
424
|
# @return [Hash<String, GraphQL::Field>]
|
391
425
|
def get_fields(type)
|
392
|
-
@instrumented_field_map[type.
|
426
|
+
@instrumented_field_map[type.graphql_name]
|
393
427
|
end
|
394
428
|
|
395
429
|
def type_from_ast(ast_node)
|
@@ -475,17 +509,20 @@ module GraphQL
|
|
475
509
|
yield(type, object, ctx)
|
476
510
|
end
|
477
511
|
|
478
|
-
if type_result.respond_to?(:graphql_definition)
|
479
|
-
type_result = type_result.graphql_definition
|
480
|
-
end
|
481
|
-
|
482
512
|
if type_result.nil?
|
483
513
|
nil
|
484
|
-
elsif !type_result.is_a?(GraphQL::BaseType)
|
485
|
-
type_str = "#{type_result} (#{type_result.class.name})"
|
486
|
-
raise "resolve_type(#{object}) returned #{type_str}, but it should return a GraphQL type"
|
487
514
|
else
|
488
|
-
type_result
|
515
|
+
after_lazy(type_result) do |resolved_type_result|
|
516
|
+
if resolved_type_result.respond_to?(:graphql_definition)
|
517
|
+
resolved_type_result = resolved_type_result.graphql_definition
|
518
|
+
end
|
519
|
+
if !resolved_type_result.is_a?(GraphQL::BaseType)
|
520
|
+
type_str = "#{resolved_type_result} (#{resolved_type_result.class.name})"
|
521
|
+
raise "resolve_type(#{object}) returned #{type_str}, but it should return a GraphQL type"
|
522
|
+
else
|
523
|
+
resolved_type_result
|
524
|
+
end
|
525
|
+
end
|
489
526
|
end
|
490
527
|
end
|
491
528
|
|
@@ -542,7 +579,8 @@ module GraphQL
|
|
542
579
|
|
543
580
|
# Can't delegate to `class`
|
544
581
|
alias :_schema_class :class
|
545
|
-
def_delegators :_schema_class, :visible?, :accessible?, :authorized?, :unauthorized_object, :inaccessible_fields
|
582
|
+
def_delegators :_schema_class, :visible?, :accessible?, :authorized?, :unauthorized_object, :unauthorized_field, :inaccessible_fields
|
583
|
+
def_delegators :_schema_class, :directive
|
546
584
|
|
547
585
|
# A function to call when {#execute} receives an invalid query string
|
548
586
|
#
|
@@ -656,10 +694,12 @@ module GraphQL
|
|
656
694
|
:execute, :multiplex,
|
657
695
|
:static_validator, :introspection_system,
|
658
696
|
:query_analyzers, :tracers, :instrumenters,
|
659
|
-
:
|
660
|
-
:validate, :multiplex_analyzers, :lazy?, :lazy_method_name, :after_lazy,
|
697
|
+
:execution_strategy_for_operation,
|
698
|
+
:validate, :multiplex_analyzers, :lazy?, :lazy_method_name, :after_lazy, :sync_lazy,
|
661
699
|
# Configuration
|
700
|
+
:analysis_engine, :analysis_engine=, :using_ast_analysis?, :interpreter?,
|
662
701
|
:max_complexity=, :max_depth=,
|
702
|
+
:error_bubbling=,
|
663
703
|
:metadata,
|
664
704
|
:default_mask,
|
665
705
|
:default_filter, :redefine,
|
@@ -693,10 +733,14 @@ module GraphQL
|
|
693
733
|
schema_defn.mutation = mutation
|
694
734
|
schema_defn.subscription = subscription
|
695
735
|
schema_defn.max_complexity = max_complexity
|
736
|
+
schema_defn.error_bubbling = error_bubbling
|
696
737
|
schema_defn.max_depth = max_depth
|
697
738
|
schema_defn.default_max_page_size = default_max_page_size
|
698
739
|
schema_defn.orphan_types = orphan_types
|
699
|
-
|
740
|
+
|
741
|
+
prepped_dirs = {}
|
742
|
+
directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
|
743
|
+
schema_defn.directives = prepped_dirs
|
700
744
|
schema_defn.introspection_namespace = introspection
|
701
745
|
schema_defn.resolve_type = method(:resolve_type)
|
702
746
|
schema_defn.object_from_id = method(:object_from_id)
|
@@ -706,15 +750,17 @@ module GraphQL
|
|
706
750
|
schema_defn.cursor_encoder = cursor_encoder
|
707
751
|
schema_defn.tracers.concat(defined_tracers)
|
708
752
|
schema_defn.query_analyzers.concat(defined_query_analyzers)
|
709
|
-
|
753
|
+
|
710
754
|
schema_defn.middleware.concat(defined_middleware)
|
711
755
|
schema_defn.multiplex_analyzers.concat(defined_multiplex_analyzers)
|
756
|
+
schema_defn.query_execution_strategy = query_execution_strategy
|
757
|
+
schema_defn.mutation_execution_strategy = mutation_execution_strategy
|
758
|
+
schema_defn.subscription_execution_strategy = subscription_execution_strategy
|
712
759
|
defined_instrumenters.each do |step, insts|
|
713
760
|
insts.each do |inst|
|
714
761
|
schema_defn.instrumenters[step] << inst
|
715
762
|
end
|
716
763
|
end
|
717
|
-
schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
|
718
764
|
lazy_classes.each do |lazy_class, value_method|
|
719
765
|
schema_defn.lazy_methods.set(lazy_class, value_method)
|
720
766
|
end
|
@@ -737,6 +783,10 @@ module GraphQL
|
|
737
783
|
end
|
738
784
|
end
|
739
785
|
end
|
786
|
+
# Do this after `plugins` since Interpreter is a plugin
|
787
|
+
if schema_defn.query_execution_strategy != GraphQL::Execution::Interpreter
|
788
|
+
schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
|
789
|
+
end
|
740
790
|
schema_defn.send(:rebuild_artifacts)
|
741
791
|
|
742
792
|
schema_defn
|
@@ -789,6 +839,30 @@ module GraphQL
|
|
789
839
|
end
|
790
840
|
end
|
791
841
|
|
842
|
+
def query_execution_strategy(new_query_execution_strategy = nil)
|
843
|
+
if new_query_execution_strategy
|
844
|
+
@query_execution_strategy = new_query_execution_strategy
|
845
|
+
else
|
846
|
+
@query_execution_strategy || self.default_execution_strategy
|
847
|
+
end
|
848
|
+
end
|
849
|
+
|
850
|
+
def mutation_execution_strategy(new_mutation_execution_strategy = nil)
|
851
|
+
if new_mutation_execution_strategy
|
852
|
+
@mutation_execution_strategy = new_mutation_execution_strategy
|
853
|
+
else
|
854
|
+
@mutation_execution_strategy || self.default_execution_strategy
|
855
|
+
end
|
856
|
+
end
|
857
|
+
|
858
|
+
def subscription_execution_strategy(new_subscription_execution_strategy = nil)
|
859
|
+
if new_subscription_execution_strategy
|
860
|
+
@subscription_execution_strategy = new_subscription_execution_strategy
|
861
|
+
else
|
862
|
+
@subscription_execution_strategy || self.default_execution_strategy
|
863
|
+
end
|
864
|
+
end
|
865
|
+
|
792
866
|
def max_complexity(max_complexity = nil)
|
793
867
|
if max_complexity
|
794
868
|
@max_complexity = max_complexity
|
@@ -797,6 +871,14 @@ module GraphQL
|
|
797
871
|
end
|
798
872
|
end
|
799
873
|
|
874
|
+
def error_bubbling(new_error_bubbling = nil)
|
875
|
+
if !new_error_bubbling.nil?
|
876
|
+
@error_bubbling = new_error_bubbling
|
877
|
+
else
|
878
|
+
@error_bubbling
|
879
|
+
end
|
880
|
+
end
|
881
|
+
|
800
882
|
def max_depth(new_max_depth = nil)
|
801
883
|
if new_max_depth
|
802
884
|
@max_depth = new_max_depth
|
@@ -817,7 +899,7 @@ module GraphQL
|
|
817
899
|
if superclass <= GraphQL::Schema
|
818
900
|
superclass.default_execution_strategy
|
819
901
|
else
|
820
|
-
@default_execution_strategy
|
902
|
+
@default_execution_strategy ||= GraphQL::Execution::Execute
|
821
903
|
end
|
822
904
|
end
|
823
905
|
|
@@ -829,17 +911,23 @@ module GraphQL
|
|
829
911
|
end
|
830
912
|
end
|
831
913
|
|
832
|
-
def rescue_from(
|
914
|
+
def rescue_from(*err_classes, &handler_block)
|
833
915
|
@rescues ||= {}
|
834
|
-
|
916
|
+
err_classes.each do |err_class|
|
917
|
+
@rescues[err_class] = handler_block
|
918
|
+
end
|
835
919
|
end
|
836
920
|
|
837
921
|
def resolve_type(type, obj, ctx)
|
838
|
-
|
922
|
+
if type.kind.object?
|
923
|
+
type
|
924
|
+
else
|
925
|
+
raise NotImplementedError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
|
926
|
+
end
|
839
927
|
end
|
840
928
|
|
841
929
|
def object_from_id(node_id, ctx)
|
842
|
-
raise NotImplementedError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to
|
930
|
+
raise NotImplementedError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to load by ID (tried to load from id `#{node_id}`)"
|
843
931
|
end
|
844
932
|
|
845
933
|
def id_from_object(object, type, ctx)
|
@@ -873,7 +961,7 @@ module GraphQL
|
|
873
961
|
# By default, this hook just replaces the unauthorized object with `nil`.
|
874
962
|
#
|
875
963
|
# Whatever value is returned from this method will be used instead of the
|
876
|
-
# unauthorized object (accessible
|
964
|
+
# unauthorized object (accessible as `unauthorized_error.object`). If an
|
877
965
|
# error is raised, then `nil` will be used.
|
878
966
|
#
|
879
967
|
# If you want to add an error to the `"errors"` key, raise a {GraphQL::ExecutionError}
|
@@ -885,6 +973,22 @@ module GraphQL
|
|
885
973
|
nil
|
886
974
|
end
|
887
975
|
|
976
|
+
# This hook is called when a field fails an `authorized?` check.
|
977
|
+
#
|
978
|
+
# By default, this hook implements the same behavior as unauthorized_object.
|
979
|
+
#
|
980
|
+
# Whatever value is returned from this method will be used instead of the
|
981
|
+
# unauthorized field . If an error is raised, then `nil` will be used.
|
982
|
+
#
|
983
|
+
# If you want to add an error to the `"errors"` key, raise a {GraphQL::ExecutionError}
|
984
|
+
# in this hook.
|
985
|
+
#
|
986
|
+
# @param unauthorized_error [GraphQL::UnauthorizedFieldError]
|
987
|
+
# @return [Field] The returned field will be put in the GraphQL response
|
988
|
+
def unauthorized_field(unauthorized_error)
|
989
|
+
unauthorized_object(unauthorized_error)
|
990
|
+
end
|
991
|
+
|
888
992
|
def type_error(type_err, ctx)
|
889
993
|
DefaultTypeError.call(type_err, ctx)
|
890
994
|
end
|
@@ -907,7 +1011,19 @@ module GraphQL
|
|
907
1011
|
@directives = new_directives.reduce({}) { |m, d| m[d.name] = d; m }
|
908
1012
|
end
|
909
1013
|
|
910
|
-
@directives ||=
|
1014
|
+
@directives ||= default_directives
|
1015
|
+
end
|
1016
|
+
|
1017
|
+
def directive(new_directive)
|
1018
|
+
directives[new_directive.graphql_name] = new_directive
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
def default_directives
|
1022
|
+
{
|
1023
|
+
"include" => GraphQL::Directive::IncludeDirective,
|
1024
|
+
"skip" => GraphQL::Directive::SkipDirective,
|
1025
|
+
"deprecated" => GraphQL::Directive::DeprecatedDirective,
|
1026
|
+
}
|
911
1027
|
end
|
912
1028
|
|
913
1029
|
def tracer(new_tracer)
|
@@ -915,6 +1031,9 @@ module GraphQL
|
|
915
1031
|
end
|
916
1032
|
|
917
1033
|
def query_analyzer(new_analyzer)
|
1034
|
+
if new_analyzer == GraphQL::Authorization::Analyzer
|
1035
|
+
warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
1036
|
+
end
|
918
1037
|
defined_query_analyzers << new_analyzer
|
919
1038
|
end
|
920
1039
|
|
@@ -962,7 +1081,7 @@ module GraphQL
|
|
962
1081
|
# @see {.accessible?}
|
963
1082
|
# @see {.authorized?}
|
964
1083
|
def call_on_type_class(member, method_name, *args, default:)
|
965
|
-
member = if member.respond_to?(:metadata)
|
1084
|
+
member = if member.respond_to?(:metadata) && member.metadata
|
966
1085
|
member.metadata[:type_class] || member
|
967
1086
|
else
|
968
1087
|
member
|
@@ -1001,9 +1120,9 @@ module GraphQL
|
|
1001
1120
|
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
1002
1121
|
# @api private
|
1003
1122
|
def after_lazy(value)
|
1004
|
-
if (
|
1123
|
+
if lazy?(value)
|
1005
1124
|
GraphQL::Execution::Lazy.new do
|
1006
|
-
result = value
|
1125
|
+
result = sync_lazy(value)
|
1007
1126
|
# The returned result might also be lazy, so check it, too
|
1008
1127
|
after_lazy(result) do |final_result|
|
1009
1128
|
yield(final_result) if block_given?
|
@@ -1014,6 +1133,35 @@ module GraphQL
|
|
1014
1133
|
end
|
1015
1134
|
end
|
1016
1135
|
|
1136
|
+
# Override this method to handle lazy objects in a custom way.
|
1137
|
+
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
1138
|
+
# @param ctx [GraphQL::Query::Context] the context for this query
|
1139
|
+
# @return [Object] A GraphQL-ready (non-lazy) object
|
1140
|
+
def self.sync_lazy(value)
|
1141
|
+
if block_given?
|
1142
|
+
# This was already hit by the instance, just give it back
|
1143
|
+
yield(value)
|
1144
|
+
else
|
1145
|
+
# This was called directly on the class, hit the instance
|
1146
|
+
# which has the lazy method map
|
1147
|
+
self.graphql_definition.sync_lazy(value)
|
1148
|
+
end
|
1149
|
+
end
|
1150
|
+
|
1151
|
+
# @see Schema.sync_lazy for a hook to override
|
1152
|
+
# @api private
|
1153
|
+
def sync_lazy(value)
|
1154
|
+
self.class.sync_lazy(value) { |v|
|
1155
|
+
lazy_method = lazy_method_name(v)
|
1156
|
+
if lazy_method
|
1157
|
+
synced_value = value.public_send(lazy_method)
|
1158
|
+
sync_lazy(synced_value)
|
1159
|
+
else
|
1160
|
+
v
|
1161
|
+
end
|
1162
|
+
}
|
1163
|
+
end
|
1164
|
+
|
1017
1165
|
protected
|
1018
1166
|
|
1019
1167
|
def rescues?
|
@@ -11,9 +11,10 @@ module GraphQL
|
|
11
11
|
GraphQL::StaticValidation::DirectivesAreDefined,
|
12
12
|
GraphQL::StaticValidation::DirectivesAreInValidLocations,
|
13
13
|
GraphQL::StaticValidation::UniqueDirectivesPerLocation,
|
14
|
+
GraphQL::StaticValidation::OperationNamesAreValid,
|
15
|
+
GraphQL::StaticValidation::FragmentNamesAreUnique,
|
14
16
|
GraphQL::StaticValidation::FragmentsAreFinite,
|
15
17
|
GraphQL::StaticValidation::FragmentsAreNamed,
|
16
|
-
GraphQL::StaticValidation::FragmentNamesAreUnique,
|
17
18
|
GraphQL::StaticValidation::FragmentsAreUsed,
|
18
19
|
GraphQL::StaticValidation::FragmentTypesExist,
|
19
20
|
GraphQL::StaticValidation::FragmentsAreOnCompositeTypes,
|
@@ -24,6 +25,7 @@ module GraphQL
|
|
24
25
|
GraphQL::StaticValidation::ArgumentsAreDefined,
|
25
26
|
GraphQL::StaticValidation::ArgumentLiteralsAreCompatible,
|
26
27
|
GraphQL::StaticValidation::RequiredArgumentsArePresent,
|
28
|
+
GraphQL::StaticValidation::RequiredInputObjectAttributesArePresent,
|
27
29
|
GraphQL::StaticValidation::ArgumentNamesAreUnique,
|
28
30
|
GraphQL::StaticValidation::VariableNamesAreUnique,
|
29
31
|
GraphQL::StaticValidation::VariablesAreInputTypes,
|
@@ -32,7 +34,6 @@ module GraphQL
|
|
32
34
|
GraphQL::StaticValidation::VariableUsagesAreAllowed,
|
33
35
|
GraphQL::StaticValidation::MutationRootExists,
|
34
36
|
GraphQL::StaticValidation::SubscriptionRootExists,
|
35
|
-
GraphQL::StaticValidation::OperationNamesAreValid,
|
36
37
|
]
|
37
38
|
end
|
38
39
|
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module StaticValidation
|
4
|
+
class BaseVisitor < GraphQL::Language::Visitor
|
5
|
+
def initialize(document, context)
|
6
|
+
@path = []
|
7
|
+
@object_types = []
|
8
|
+
@directives = []
|
9
|
+
@field_definitions = []
|
10
|
+
@argument_definitions = []
|
11
|
+
@directive_definitions = []
|
12
|
+
@context = context
|
13
|
+
@schema = context.schema
|
14
|
+
super(document)
|
15
|
+
end
|
16
|
+
|
17
|
+
# This will be overwritten by {InternalRepresentation::Rewrite} if it's included
|
18
|
+
def rewrite_document
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :context
|
23
|
+
|
24
|
+
# @return [Array<GraphQL::ObjectType>] Types whose scope we've entered
|
25
|
+
attr_reader :object_types
|
26
|
+
|
27
|
+
# @return [Array<String>] The nesting of the current position in the AST
|
28
|
+
def path
|
29
|
+
@path.dup
|
30
|
+
end
|
31
|
+
|
32
|
+
# Build a class to visit the AST and perform validation,
|
33
|
+
# or use a pre-built class if rules is `ALL_RULES` or empty.
|
34
|
+
# @param rules [Array<Module, Class>]
|
35
|
+
# @param rewrite [Boolean] if `false`, don't include rewrite
|
36
|
+
# @return [Class] A class for validating `rules` during visitation
|
37
|
+
def self.including_rules(rules, rewrite: true)
|
38
|
+
if rules.empty?
|
39
|
+
if rewrite
|
40
|
+
NoValidateVisitor
|
41
|
+
else
|
42
|
+
# It's not doing _anything?!?_
|
43
|
+
BaseVisitor
|
44
|
+
end
|
45
|
+
elsif rules == ALL_RULES
|
46
|
+
if rewrite
|
47
|
+
DefaultVisitor
|
48
|
+
else
|
49
|
+
InterpreterVisitor
|
50
|
+
end
|
51
|
+
else
|
52
|
+
visitor_class = Class.new(self) do
|
53
|
+
include(GraphQL::StaticValidation::DefinitionDependencies)
|
54
|
+
end
|
55
|
+
|
56
|
+
rules.reverse_each do |r|
|
57
|
+
# If it's a class, it gets attached later.
|
58
|
+
if !r.is_a?(Class)
|
59
|
+
visitor_class.include(r)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
if rewrite
|
64
|
+
visitor_class.include(GraphQL::InternalRepresentation::Rewrite)
|
65
|
+
end
|
66
|
+
visitor_class.include(ContextMethods)
|
67
|
+
visitor_class
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
module ContextMethods
|
72
|
+
def on_operation_definition(node, parent)
|
73
|
+
object_type = @schema.root_type_for_operation(node.operation_type)
|
74
|
+
@object_types.push(object_type)
|
75
|
+
@path.push("#{node.operation_type}#{node.name ? " #{node.name}" : ""}")
|
76
|
+
super
|
77
|
+
@object_types.pop
|
78
|
+
@path.pop
|
79
|
+
end
|
80
|
+
|
81
|
+
def on_fragment_definition(node, parent)
|
82
|
+
on_fragment_with_type(node) do
|
83
|
+
@path.push("fragment #{node.name}")
|
84
|
+
super
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def on_inline_fragment(node, parent)
|
89
|
+
on_fragment_with_type(node) do
|
90
|
+
@path.push("...#{node.type ? " on #{node.type.to_query_string}" : ""}")
|
91
|
+
super
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def on_field(node, parent)
|
96
|
+
parent_type = @object_types.last
|
97
|
+
field_definition = @schema.get_field(parent_type, node.name)
|
98
|
+
@field_definitions.push(field_definition)
|
99
|
+
if !field_definition.nil?
|
100
|
+
next_object_type = field_definition.type.unwrap
|
101
|
+
@object_types.push(next_object_type)
|
102
|
+
else
|
103
|
+
@object_types.push(nil)
|
104
|
+
end
|
105
|
+
@path.push(node.alias || node.name)
|
106
|
+
super
|
107
|
+
@field_definitions.pop
|
108
|
+
@object_types.pop
|
109
|
+
@path.pop
|
110
|
+
end
|
111
|
+
|
112
|
+
def on_directive(node, parent)
|
113
|
+
directive_defn = @schema.directives[node.name]
|
114
|
+
@directive_definitions.push(directive_defn)
|
115
|
+
super
|
116
|
+
@directive_definitions.pop
|
117
|
+
end
|
118
|
+
|
119
|
+
def on_argument(node, parent)
|
120
|
+
argument_defn = if (arg = @argument_definitions.last)
|
121
|
+
arg_type = arg.type.unwrap
|
122
|
+
if arg_type.kind.input_object?
|
123
|
+
arg_type.input_fields[node.name]
|
124
|
+
else
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
elsif (directive_defn = @directive_definitions.last)
|
128
|
+
directive_defn.arguments[node.name]
|
129
|
+
elsif (field_defn = @field_definitions.last)
|
130
|
+
field_defn.arguments[node.name]
|
131
|
+
else
|
132
|
+
nil
|
133
|
+
end
|
134
|
+
|
135
|
+
@argument_definitions.push(argument_defn)
|
136
|
+
@path.push(node.name)
|
137
|
+
super
|
138
|
+
@argument_definitions.pop
|
139
|
+
@path.pop
|
140
|
+
end
|
141
|
+
|
142
|
+
def on_fragment_spread(node, parent)
|
143
|
+
@path.push("... #{node.name}")
|
144
|
+
super
|
145
|
+
@path.pop
|
146
|
+
end
|
147
|
+
|
148
|
+
# @return [GraphQL::BaseType] The current object type
|
149
|
+
def type_definition
|
150
|
+
@object_types.last
|
151
|
+
end
|
152
|
+
|
153
|
+
# @return [GraphQL::BaseType] The type which the current type came from
|
154
|
+
def parent_type_definition
|
155
|
+
@object_types[-2]
|
156
|
+
end
|
157
|
+
|
158
|
+
# @return [GraphQL::Field, nil] The most-recently-entered GraphQL::Field, if currently inside one
|
159
|
+
def field_definition
|
160
|
+
@field_definitions.last
|
161
|
+
end
|
162
|
+
|
163
|
+
# @return [GraphQL::Directive, nil] The most-recently-entered GraphQL::Directive, if currently inside one
|
164
|
+
def directive_definition
|
165
|
+
@directive_definitions.last
|
166
|
+
end
|
167
|
+
|
168
|
+
# @return [GraphQL::Argument, nil] The most-recently-entered GraphQL::Argument, if currently inside one
|
169
|
+
def argument_definition
|
170
|
+
# Don't get the _last_ one because that's the current one.
|
171
|
+
# Get the second-to-last one, which is the parent of the current one.
|
172
|
+
@argument_definitions[-2]
|
173
|
+
end
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
def on_fragment_with_type(node)
|
178
|
+
object_type = if node.type
|
179
|
+
@schema.types.fetch(node.type.name, nil)
|
180
|
+
else
|
181
|
+
@object_types.last
|
182
|
+
end
|
183
|
+
@object_types.push(object_type)
|
184
|
+
yield(node)
|
185
|
+
@object_types.pop
|
186
|
+
@path.pop
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
private
|
191
|
+
|
192
|
+
def add_error(error, path: nil)
|
193
|
+
error.path ||= (path || @path.dup)
|
194
|
+
context.errors << error
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module StaticValidation
|
4
|
+
class DefaultVisitor < BaseVisitor
|
5
|
+
include(GraphQL::StaticValidation::DefinitionDependencies)
|
6
|
+
|
7
|
+
StaticValidation::ALL_RULES.reverse_each do |r|
|
8
|
+
include(r)
|
9
|
+
end
|
10
|
+
|
11
|
+
include(GraphQL::InternalRepresentation::Rewrite)
|
12
|
+
include(ContextMethods)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|