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
@@ -5,12 +5,17 @@ module GraphQL
|
|
5
5
|
extend GraphQL::Schema::Member::AcceptsDefinition
|
6
6
|
extend Forwardable
|
7
7
|
extend GraphQL::Schema::Member::HasArguments
|
8
|
+
include GraphQL::Dig
|
8
9
|
|
9
|
-
def initialize(values, context:, defaults_used:)
|
10
|
+
def initialize(values = nil, ruby_kwargs: nil, context:, defaults_used:)
|
10
11
|
@context = context
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
if ruby_kwargs
|
13
|
+
@ruby_style_hash = ruby_kwargs
|
14
|
+
else
|
15
|
+
@arguments = self.class.arguments_class.new(values, context: context, defaults_used: defaults_used)
|
16
|
+
# Symbolized, underscored hash:
|
17
|
+
@ruby_style_hash = @arguments.to_kwargs
|
18
|
+
end
|
14
19
|
# Apply prepares, not great to have it duplicated here.
|
15
20
|
self.class.arguments.each do |name, arg_defn|
|
16
21
|
ruby_kwargs_key = arg_defn.keyword
|
@@ -56,13 +61,15 @@ module GraphQL
|
|
56
61
|
def [](key)
|
57
62
|
if @ruby_style_hash.key?(key)
|
58
63
|
@ruby_style_hash[key]
|
59
|
-
|
64
|
+
elsif @arguments
|
60
65
|
@arguments[key]
|
66
|
+
else
|
67
|
+
nil
|
61
68
|
end
|
62
69
|
end
|
63
70
|
|
64
71
|
def key?(key)
|
65
|
-
@ruby_style_hash.key?(key) || @arguments.key?(key)
|
72
|
+
@ruby_style_hash.key?(key) || (@arguments && @arguments.key?(key))
|
66
73
|
end
|
67
74
|
|
68
75
|
# A copy of the Ruby-style hash
|
@@ -78,8 +85,9 @@ module GraphQL
|
|
78
85
|
argument_defn = super
|
79
86
|
# Add a method access
|
80
87
|
arg_name = argument_defn.graphql_definition.name
|
81
|
-
|
82
|
-
|
88
|
+
method_name = Member::BuildType.underscore(arg_name).to_sym
|
89
|
+
define_method(method_name) do
|
90
|
+
@ruby_style_hash[method_name]
|
83
91
|
end
|
84
92
|
end
|
85
93
|
|
@@ -9,6 +9,7 @@ module GraphQL
|
|
9
9
|
include GraphQL::Schema::Member::BaseDSLMethods
|
10
10
|
include GraphQL::Schema::Member::TypeSystemHelpers
|
11
11
|
include GraphQL::Schema::Member::HasFields
|
12
|
+
include GraphQL::Schema::Member::HasPath
|
12
13
|
include GraphQL::Schema::Member::RelayShortcuts
|
13
14
|
include GraphQL::Schema::Member::Scoped
|
14
15
|
|
@@ -55,6 +55,27 @@ module GraphQL
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
+
def extract_default_value(default_value_str, input_value_ast)
|
59
|
+
case input_value_ast
|
60
|
+
when String, Integer, Float, TrueClass, FalseClass
|
61
|
+
input_value_ast
|
62
|
+
when GraphQL::Language::Nodes::Enum
|
63
|
+
input_value_ast.name
|
64
|
+
when GraphQL::Language::Nodes::NullValue
|
65
|
+
nil
|
66
|
+
when GraphQL::Language::Nodes::InputObject
|
67
|
+
input_value_ast.to_h
|
68
|
+
when Array
|
69
|
+
input_value_ast.map { |element| extract_default_value(default_value_str, element) }
|
70
|
+
else
|
71
|
+
raise(
|
72
|
+
"Encountered unexpected type when loading default value. "\
|
73
|
+
"input_value_ast.class is #{input_value_ast.class} "\
|
74
|
+
"default_value is #{default_value_str}"
|
75
|
+
)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
58
79
|
def define_type(type, type_resolver)
|
59
80
|
case type.fetch("kind")
|
60
81
|
when "ENUM"
|
@@ -119,22 +140,7 @@ module GraphQL
|
|
119
140
|
# Reach into the AST for the default value:
|
120
141
|
input_value_ast = dummy_query_ast.definitions.first.variables.first.default_value
|
121
142
|
|
122
|
-
|
123
|
-
when String, Integer, Float, TrueClass, FalseClass, Array
|
124
|
-
input_value_ast
|
125
|
-
when GraphQL::Language::Nodes::Enum
|
126
|
-
input_value_ast.name
|
127
|
-
when GraphQL::Language::Nodes::NullValue
|
128
|
-
nil
|
129
|
-
when GraphQL::Language::Nodes::InputObject
|
130
|
-
input_value_ast.to_h
|
131
|
-
else
|
132
|
-
raise(
|
133
|
-
"Encountered unexpected type when loading default value. "\
|
134
|
-
"input_value_ast.class is #{input_value_ast.class} "\
|
135
|
-
"default_value is #{default_value_str}"
|
136
|
-
)
|
137
|
-
end
|
143
|
+
extract_default_value(default_value_str, input_value_ast)
|
138
144
|
end
|
139
145
|
end
|
140
146
|
|
@@ -55,6 +55,10 @@ module GraphQL
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
+
def introspection?
|
59
|
+
introspection
|
60
|
+
end
|
61
|
+
|
58
62
|
# The mutation this type was derived from, if it was derived from a mutation
|
59
63
|
# @return [Class]
|
60
64
|
def mutation(mutation_class = nil)
|
@@ -79,9 +83,11 @@ module GraphQL
|
|
79
83
|
# The default name is the Ruby constant name,
|
80
84
|
# without any namespaces and with any `-Type` suffix removed
|
81
85
|
def default_graphql_name
|
82
|
-
|
86
|
+
@default_graphql_name ||= begin
|
87
|
+
raise NotImplementedError, 'Anonymous class should declare a `graphql_name`' if name.nil?
|
83
88
|
|
84
|
-
|
89
|
+
name.split("::").last.sub(/Type\Z/, "")
|
90
|
+
end
|
85
91
|
end
|
86
92
|
|
87
93
|
def visible?(context)
|
@@ -33,7 +33,7 @@ module GraphQL
|
|
33
33
|
null = false
|
34
34
|
parse_type(type_expr[0..-2], null: true)
|
35
35
|
else
|
36
|
-
maybe_type =
|
36
|
+
maybe_type = constantize(type_expr)
|
37
37
|
case maybe_type
|
38
38
|
when GraphQL::BaseType
|
39
39
|
maybe_type
|
@@ -125,6 +125,38 @@ module GraphQL
|
|
125
125
|
camelized
|
126
126
|
end
|
127
127
|
|
128
|
+
# Resolves constant from string (based on Rails `ActiveSupport::Inflector.constantize`)
|
129
|
+
def constantize(string)
|
130
|
+
names = string.split('::')
|
131
|
+
|
132
|
+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
133
|
+
Object.const_get(string) if names.empty?
|
134
|
+
|
135
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
136
|
+
names.shift if names.size > 1 && names.first.empty?
|
137
|
+
|
138
|
+
names.inject(Object) do |constant, name|
|
139
|
+
if constant == Object
|
140
|
+
constant.const_get(name)
|
141
|
+
else
|
142
|
+
candidate = constant.const_get(name)
|
143
|
+
next candidate if constant.const_defined?(name, false)
|
144
|
+
next candidate unless Object.const_defined?(name)
|
145
|
+
|
146
|
+
# Go down the ancestors to check if it is owned directly. The check
|
147
|
+
# stops when we reach Object or the end of ancestors tree.
|
148
|
+
constant = constant.ancestors.inject do |const, ancestor|
|
149
|
+
break const if ancestor == Object
|
150
|
+
break ancestor if ancestor.const_defined?(name, false)
|
151
|
+
const
|
152
|
+
end
|
153
|
+
|
154
|
+
# Owner is in Object, so raise.
|
155
|
+
constant.const_get(name, false)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
128
160
|
def underscore(string)
|
129
161
|
string
|
130
162
|
.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') # URLDecoder -> URL_Decoder
|
@@ -29,9 +29,13 @@ module GraphQL
|
|
29
29
|
|
30
30
|
# @return [Hash<String => GraphQL::Schema::Argument] Arguments defined on this thing, keyed by name. Includes inherited definitions
|
31
31
|
def arguments
|
32
|
-
inherited_arguments = ((self.is_a?(Class) && superclass.respond_to?(:arguments)) ? superclass.arguments :
|
32
|
+
inherited_arguments = ((self.is_a?(Class) && superclass.respond_to?(:arguments)) ? superclass.arguments : nil)
|
33
33
|
# Local definitions override inherited ones
|
34
|
-
inherited_arguments
|
34
|
+
if inherited_arguments
|
35
|
+
inherited_arguments.merge(own_arguments)
|
36
|
+
else
|
37
|
+
own_arguments
|
38
|
+
end
|
35
39
|
end
|
36
40
|
|
37
41
|
# @param new_arg_class [Class] A class to use for building argument definitions
|
@@ -4,47 +4,6 @@ module GraphQL
|
|
4
4
|
class Member
|
5
5
|
# Shared code for Object and Interface
|
6
6
|
module HasFields
|
7
|
-
class << self
|
8
|
-
# When this module is added to a class,
|
9
|
-
# add a place for that class's default behaviors
|
10
|
-
def self.extended(child_class)
|
11
|
-
add_default_resolve_module(child_class)
|
12
|
-
super
|
13
|
-
end
|
14
|
-
|
15
|
-
# Create a module which will have instance methods for implementing fields.
|
16
|
-
# These will be `super` methods for fields in interfaces, objects and mutations.
|
17
|
-
# Use an instance variable on the class instead of a constant
|
18
|
-
# so that module namespaces won't be an issue. (If we used constants,
|
19
|
-
# `child_class::DefaultResolve` might find a constant from an included module.)
|
20
|
-
def add_default_resolve_module(child_class)
|
21
|
-
if child_class.instance_variable_get(:@_default_resolve)
|
22
|
-
# This can happen when an object implements an interface,
|
23
|
-
# since that interface has the `included` hook above.
|
24
|
-
return
|
25
|
-
end
|
26
|
-
|
27
|
-
default_resolve_module = Module.new
|
28
|
-
child_class.instance_variable_set(:@_default_resolve, default_resolve_module)
|
29
|
-
child_class.include(default_resolve_module)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# When this is included into interfaces,
|
34
|
-
# add a place for default field behaviors
|
35
|
-
def included(child_class)
|
36
|
-
HasFields.add_default_resolve_module(child_class)
|
37
|
-
# Also, prepare a place for default field implementations
|
38
|
-
super
|
39
|
-
end
|
40
|
-
|
41
|
-
# When a subclass of objects are created,
|
42
|
-
# add a place for that subclass's default field behaviors
|
43
|
-
def inherited(child_class)
|
44
|
-
HasFields.add_default_resolve_module(child_class)
|
45
|
-
super
|
46
|
-
end
|
47
|
-
|
48
7
|
# Add a field to this object or interface with the given definition
|
49
8
|
# @see {GraphQL::Schema::Field#initialize} for method signature
|
50
9
|
# @return [void]
|
@@ -66,16 +25,24 @@ module GraphQL
|
|
66
25
|
all_fields
|
67
26
|
end
|
68
27
|
|
28
|
+
def get_field(field_name)
|
29
|
+
if (f = own_fields[field_name])
|
30
|
+
f
|
31
|
+
else
|
32
|
+
for ancestor in ancestors
|
33
|
+
if ancestor.respond_to?(:own_fields) && f = ancestor.own_fields[field_name]
|
34
|
+
return f
|
35
|
+
end
|
36
|
+
end
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
69
41
|
# Register this field with the class, overriding a previous one if needed.
|
70
|
-
# Also, add a parent method for resolving this field.
|
71
42
|
# @param field_defn [GraphQL::Schema::Field]
|
72
43
|
# @return [void]
|
73
44
|
def add_field(field_defn)
|
74
45
|
own_fields[field_defn.name] = field_defn
|
75
|
-
if !method_defined?(field_defn.method_sym)
|
76
|
-
# Only add the super method if there isn't one already.
|
77
|
-
add_super_method(field_defn.name.inspect, field_defn.method_sym)
|
78
|
-
end
|
79
46
|
nil
|
80
47
|
end
|
81
48
|
|
@@ -94,36 +61,17 @@ module GraphQL
|
|
94
61
|
end
|
95
62
|
|
96
63
|
def global_id_field(field_name)
|
97
|
-
|
64
|
+
id_resolver = GraphQL::Relay::GlobalIdResolve.new(type: self)
|
65
|
+
field field_name, "ID", null: false
|
66
|
+
define_method(field_name) do
|
67
|
+
id_resolver.call(object, {}, context)
|
68
|
+
end
|
98
69
|
end
|
99
70
|
|
100
71
|
# @return [Array<GraphQL::Schema::Field>] Fields defined on this class _specifically_, not parent classes
|
101
72
|
def own_fields
|
102
73
|
@own_fields ||= {}
|
103
74
|
end
|
104
|
-
|
105
|
-
private
|
106
|
-
# Find the magic module for holding super methods,
|
107
|
-
# and add a field named `method_name` for implementing the field
|
108
|
-
# called `field_name`.
|
109
|
-
# It will be the `super` method if the method is overwritten in the class definition.
|
110
|
-
def add_super_method(field_key, method_name)
|
111
|
-
default_resolve_module = @_default_resolve
|
112
|
-
if default_resolve_module.nil?
|
113
|
-
# This should have been set up in one of the inherited or included hooks above,
|
114
|
-
# if it wasn't, it's because those hooks weren't called because `super` wasn't present.
|
115
|
-
raise <<-ERR
|
116
|
-
Uh oh! #{self} doesn't have a default resolve module. This probably means that an `inherited` hook didn't call super.
|
117
|
-
Check `inherited` on #{self}'s superclasses.
|
118
|
-
ERR
|
119
|
-
end
|
120
|
-
default_resolve_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
121
|
-
def #{method_name}(**args)
|
122
|
-
field_inst = self.class.fields[#{field_key}] || raise(%|Failed to find field #{field_key} for \#{self.class} among \#{self.class.fields.keys}|)
|
123
|
-
field_inst.resolve_field_method(self, args, context)
|
124
|
-
end
|
125
|
-
RUBY
|
126
|
-
end
|
127
75
|
end
|
128
76
|
end
|
129
77
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Member
|
6
|
+
module HasPath
|
7
|
+
# @return [String] A description of this member's place in the GraphQL schema
|
8
|
+
def path
|
9
|
+
path_str = if self.respond_to?(:graphql_name)
|
10
|
+
self.graphql_name
|
11
|
+
elsif self.class.respond_to?(:graphql_name)
|
12
|
+
# Instances of resolvers
|
13
|
+
self.class.graphql_name
|
14
|
+
end
|
15
|
+
|
16
|
+
if self.respond_to?(:owner) && owner.respond_to?(:path)
|
17
|
+
path_str = "#{owner.path}.#{path_str}"
|
18
|
+
end
|
19
|
+
|
20
|
+
path_str
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -91,7 +91,7 @@ module GraphQL
|
|
91
91
|
# For lists with nil, we need another nil check here
|
92
92
|
nil
|
93
93
|
else
|
94
|
-
|
94
|
+
concrete_type_or_lazy = case @inner_return_type
|
95
95
|
when GraphQL::UnionType, GraphQL::InterfaceType
|
96
96
|
ctx.query.resolve_type(@inner_return_type, inner_obj)
|
97
97
|
when GraphQL::ObjectType
|
@@ -100,12 +100,15 @@ module GraphQL
|
|
100
100
|
raise "unexpected proxying type #{@inner_return_type} for #{inner_obj} at #{ctx.owner_type}.#{ctx.field.name}"
|
101
101
|
end
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
103
|
+
# .resolve_type may have returned a lazy
|
104
|
+
ctx.schema.after_lazy(concrete_type_or_lazy) do |concrete_type|
|
105
|
+
if concrete_type && (object_class = concrete_type.metadata[:type_class])
|
106
|
+
# use the query-level context here, since it won't be field-specific anyways
|
107
|
+
query_ctx = ctx.query.context
|
108
|
+
object_class.authorized_new(inner_obj, query_ctx)
|
109
|
+
else
|
110
|
+
inner_obj
|
111
|
+
end
|
109
112
|
end
|
110
113
|
end
|
111
114
|
end
|
@@ -3,6 +3,7 @@ require 'graphql/schema/member/accepts_definition'
|
|
3
3
|
require 'graphql/schema/member/base_dsl_methods'
|
4
4
|
require 'graphql/schema/member/cached_graphql_definition'
|
5
5
|
require 'graphql/schema/member/graphql_type_names'
|
6
|
+
require 'graphql/schema/member/has_path'
|
6
7
|
require 'graphql/schema/member/relay_shortcuts'
|
7
8
|
require 'graphql/schema/member/scoped'
|
8
9
|
require 'graphql/schema/member/type_system_helpers'
|
@@ -22,6 +23,7 @@ module GraphQL
|
|
22
23
|
extend TypeSystemHelpers
|
23
24
|
extend Scoped
|
24
25
|
extend RelayShortcuts
|
26
|
+
extend HasPath
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
@@ -60,71 +60,29 @@ module GraphQL
|
|
60
60
|
#
|
61
61
|
class Mutation < GraphQL::Schema::Resolver
|
62
62
|
extend GraphQL::Schema::Member::HasFields
|
63
|
+
extend GraphQL::Schema::Resolver::HasPayloadType
|
63
64
|
|
64
65
|
class << self
|
65
66
|
# Override this method to handle legacy-style usages of `MyMutation.field`
|
66
67
|
def field(*args, &block)
|
67
|
-
if args.
|
68
|
+
if args.empty?
|
68
69
|
raise ArgumentError, "#{name}.field is used for adding fields to this mutation. Use `mutation: #{name}` to attach this mutation instead."
|
69
70
|
else
|
70
71
|
super
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
74
|
-
# Call this method to get the derived return type of the mutation,
|
75
|
-
# or use it as a configuration method to assign a return type
|
76
|
-
# instead of generating one.
|
77
|
-
# @param new_payload_type [Class, nil] If a type definition class is provided, it will be used as the return type of the mutation field
|
78
|
-
# @return [Class] The object type which this mutation returns.
|
79
|
-
def payload_type(new_payload_type = nil)
|
80
|
-
if new_payload_type
|
81
|
-
@payload_type = new_payload_type
|
82
|
-
end
|
83
|
-
@payload_type ||= generate_payload_type
|
84
|
-
end
|
85
|
-
|
86
|
-
alias :type :payload_type
|
87
|
-
alias :type_expr :payload_type
|
88
|
-
|
89
|
-
def field_class(new_class = nil)
|
90
|
-
if new_class
|
91
|
-
@field_class = new_class
|
92
|
-
else
|
93
|
-
@field_class || find_inherited_method(:field_class, GraphQL::Schema::Field)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# An object class to use for deriving return types
|
98
|
-
# @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
|
99
|
-
# @return [Class]
|
100
|
-
def object_class(new_class = nil)
|
101
|
-
if new_class
|
102
|
-
@object_class = new_class
|
103
|
-
end
|
104
|
-
@object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
|
105
|
-
end
|
106
|
-
|
107
75
|
def visible?(context)
|
108
76
|
true
|
109
77
|
end
|
110
78
|
|
111
79
|
private
|
112
80
|
|
113
|
-
#
|
114
|
-
# This value will be cached as `{.payload_type}`.
|
115
|
-
# Override this hook to customize return type generation.
|
81
|
+
# Override this to attach self as `mutation`
|
116
82
|
def generate_payload_type
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
Class.new(object_class) do
|
121
|
-
graphql_name("#{mutation_name}Payload")
|
122
|
-
description("Autogenerated return type of #{mutation_name}")
|
123
|
-
mutation(mutation_class)
|
124
|
-
mutation_fields.each do |name, f|
|
125
|
-
field(name, field: f)
|
126
|
-
end
|
127
|
-
end
|
83
|
+
payload_class = super
|
84
|
+
payload_class.mutation(self)
|
85
|
+
payload_class
|
128
86
|
end
|
129
87
|
end
|
130
88
|
end
|
@@ -35,19 +35,33 @@ module GraphQL
|
|
35
35
|
# @return [GraphQL::Schema::Object, GraphQL::Execution::Lazy]
|
36
36
|
# @raise [GraphQL::UnauthorizedError] if the user-provided hook returns `false`
|
37
37
|
def authorized_new(object, context)
|
38
|
-
|
38
|
+
auth_val = begin
|
39
|
+
authorized?(object, context)
|
40
|
+
# rescue GraphQL::UnauthorizedError => err
|
41
|
+
# context.schema.unauthorized_object(err)
|
42
|
+
end
|
43
|
+
|
44
|
+
context.schema.after_lazy(auth_val) do |is_authorized|
|
39
45
|
if is_authorized
|
40
46
|
self.new(object, context)
|
41
47
|
else
|
42
48
|
# It failed the authorization check, so go to the schema's authorized object hook
|
43
49
|
err = GraphQL::UnauthorizedError.new(object: object, type: self, context: context)
|
44
50
|
# If a new value was returned, wrap that instead of the original value
|
45
|
-
|
46
|
-
|
47
|
-
|
51
|
+
begin
|
52
|
+
new_obj = context.schema.unauthorized_object(err)
|
53
|
+
if new_obj
|
54
|
+
self.new(new_obj, context)
|
55
|
+
else
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
# rescue GraphQL::ExecutionError => err
|
59
|
+
# err
|
48
60
|
end
|
49
61
|
end
|
50
62
|
end
|
63
|
+
# rescue GraphQL::ExecutionError => err
|
64
|
+
# err
|
51
65
|
end
|
52
66
|
end
|
53
67
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require "graphql/types/string"
|
2
3
|
|
3
4
|
module GraphQL
|
4
5
|
class Schema
|
@@ -25,19 +26,51 @@ module GraphQL
|
|
25
26
|
# Relay classic default:
|
26
27
|
null(true)
|
27
28
|
|
28
|
-
# Override {GraphQL::Schema::
|
29
|
+
# Override {GraphQL::Schema::Resolver#resolve_with_support} to
|
29
30
|
# delete `client_mutation_id` from the kwargs.
|
30
|
-
def
|
31
|
-
#
|
32
|
-
|
33
|
-
if
|
34
|
-
|
31
|
+
def resolve_with_support(**inputs)
|
32
|
+
# Without the interpreter, the inputs are unwrapped by an instrumenter.
|
33
|
+
# But when using the interpreter, no instrumenters are applied.
|
34
|
+
if context.interpreter?
|
35
|
+
input = inputs[:input].to_h
|
36
|
+
# Transfer these from the top-level hash to the
|
37
|
+
# shortcutted `input:` object
|
38
|
+
self.class.extras.each do |ext|
|
39
|
+
input[ext] = inputs[ext]
|
40
|
+
end
|
35
41
|
else
|
36
|
-
|
42
|
+
input = inputs
|
43
|
+
end
|
44
|
+
|
45
|
+
if input
|
46
|
+
# This is handled by Relay::Mutation::Resolve, a bit hacky, but here we are.
|
47
|
+
input_kwargs = input.to_h
|
48
|
+
client_mutation_id = input_kwargs.delete(:client_mutation_id)
|
49
|
+
else
|
50
|
+
# Relay Classic Mutations with no `argument`s
|
51
|
+
# don't require `input:`
|
52
|
+
input_kwargs = {}
|
53
|
+
end
|
54
|
+
|
55
|
+
return_value = if input_kwargs.any?
|
56
|
+
super(input_kwargs)
|
57
|
+
else
|
58
|
+
super()
|
37
59
|
end
|
38
|
-
end
|
39
60
|
|
40
|
-
|
61
|
+
# Again, this is done by an instrumenter when using non-interpreter execution.
|
62
|
+
if context.interpreter?
|
63
|
+
context.schema.after_lazy(return_value) do |return_hash|
|
64
|
+
# It might be an error
|
65
|
+
if return_hash.is_a?(Hash)
|
66
|
+
return_hash[:client_mutation_id] = client_mutation_id
|
67
|
+
end
|
68
|
+
return_hash
|
69
|
+
end
|
70
|
+
else
|
71
|
+
return_value
|
72
|
+
end
|
73
|
+
end
|
41
74
|
|
42
75
|
class << self
|
43
76
|
# The base class for generated input object types
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Resolver
|
6
|
+
# Adds `field(...)` helper to resolvers so that they can
|
7
|
+
# generate payload types.
|
8
|
+
#
|
9
|
+
# Or, an already-defined one can be attached with `payload_type(...)`.
|
10
|
+
module HasPayloadType
|
11
|
+
# Call this method to get the derived return type of the mutation,
|
12
|
+
# or use it as a configuration method to assign a return type
|
13
|
+
# instead of generating one.
|
14
|
+
# @param new_payload_type [Class, nil] If a type definition class is provided, it will be used as the return type of the mutation field
|
15
|
+
# @return [Class] The object type which this mutation returns.
|
16
|
+
def payload_type(new_payload_type = nil)
|
17
|
+
if new_payload_type
|
18
|
+
@payload_type = new_payload_type
|
19
|
+
end
|
20
|
+
@payload_type ||= generate_payload_type
|
21
|
+
end
|
22
|
+
|
23
|
+
alias :type :payload_type
|
24
|
+
alias :type_expr :payload_type
|
25
|
+
|
26
|
+
def field_class(new_class = nil)
|
27
|
+
if new_class
|
28
|
+
@field_class = new_class
|
29
|
+
else
|
30
|
+
@field_class || find_inherited_method(:field_class, GraphQL::Schema::Field)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# An object class to use for deriving return types
|
35
|
+
# @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
|
36
|
+
# @return [Class]
|
37
|
+
def object_class(new_class = nil)
|
38
|
+
if new_class
|
39
|
+
@object_class = new_class
|
40
|
+
end
|
41
|
+
@object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# Build a subclass of {.object_class} based on `self`.
|
47
|
+
# This value will be cached as `{.payload_type}`.
|
48
|
+
# Override this hook to customize return type generation.
|
49
|
+
def generate_payload_type
|
50
|
+
resolver_name = graphql_name
|
51
|
+
resolver_fields = fields
|
52
|
+
Class.new(object_class) do
|
53
|
+
graphql_name("#{resolver_name}Payload")
|
54
|
+
description("Autogenerated return type of #{resolver_name}")
|
55
|
+
resolver_fields.each do |name, f|
|
56
|
+
# Reattach the already-defined field here
|
57
|
+
# (The field's `.owner` will still point to the mutation, not the object type, I think)
|
58
|
+
add_field(f)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|