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/query/result.rb
CHANGED
@@ -14,6 +14,8 @@ module GraphQL
|
|
14
14
|
#
|
15
15
|
# @api private
|
16
16
|
class ValidationPipeline
|
17
|
+
attr_reader :max_depth, :max_complexity
|
18
|
+
|
17
19
|
def initialize(query:, validate:, parse_error:, operation_name_error:, max_depth:, max_complexity:)
|
18
20
|
@validation_errors = []
|
19
21
|
@internal_representation = nil
|
@@ -34,7 +36,7 @@ module GraphQL
|
|
34
36
|
@valid
|
35
37
|
end
|
36
38
|
|
37
|
-
# @return [Array<GraphQL::StaticValidation::
|
39
|
+
# @return [Array<GraphQL::StaticValidation::Error >] Static validation errors for the query string
|
38
40
|
def validation_errors
|
39
41
|
ensure_has_validated
|
40
42
|
@validation_errors
|
@@ -74,11 +76,11 @@ module GraphQL
|
|
74
76
|
@validation_errors.concat(validation_result[:errors])
|
75
77
|
@internal_representation = validation_result[:irep]
|
76
78
|
|
77
|
-
if @validation_errors.
|
79
|
+
if @validation_errors.empty?
|
78
80
|
@validation_errors.concat(@query.variables.errors)
|
79
81
|
end
|
80
82
|
|
81
|
-
if @validation_errors.
|
83
|
+
if @validation_errors.empty?
|
82
84
|
@query_analyzers = build_analyzers(
|
83
85
|
@schema,
|
84
86
|
@max_depth,
|
@@ -87,24 +89,46 @@ module GraphQL
|
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
90
|
-
@valid = @validation_errors.
|
92
|
+
@valid = @validation_errors.empty?
|
91
93
|
end
|
92
94
|
|
93
95
|
# If there are max_* values, add them,
|
94
96
|
# otherwise reuse the schema's list of analyzers.
|
95
97
|
def build_analyzers(schema, max_depth, max_complexity)
|
96
|
-
|
97
|
-
qa = schema.query_analyzers.dup
|
98
|
+
qa = schema.query_analyzers.dup
|
98
99
|
|
99
|
-
|
100
|
-
|
100
|
+
# Filter out the built in authorization analyzer.
|
101
|
+
# It is deprecated and does not have an AST analyzer alternative.
|
102
|
+
qa = qa.select do |analyzer|
|
103
|
+
if analyzer == GraphQL::Authorization::Analyzer && schema.using_ast_analysis?
|
104
|
+
raise "The Authorization analyzer is not supported with AST Analyzers"
|
105
|
+
else
|
106
|
+
true
|
101
107
|
end
|
102
|
-
|
103
|
-
|
108
|
+
end
|
109
|
+
|
110
|
+
if max_depth || max_complexity
|
111
|
+
# Depending on the analysis engine, we must use different analyzers
|
112
|
+
# remove this once everything has switched over to AST analyzers
|
113
|
+
if schema.using_ast_analysis?
|
114
|
+
if max_depth
|
115
|
+
qa << GraphQL::Analysis::AST::MaxQueryDepth
|
116
|
+
end
|
117
|
+
if max_complexity
|
118
|
+
qa << GraphQL::Analysis::AST::MaxQueryComplexity
|
119
|
+
end
|
120
|
+
else
|
121
|
+
if max_depth
|
122
|
+
qa << GraphQL::Analysis::MaxQueryDepth.new(max_depth)
|
123
|
+
end
|
124
|
+
if max_complexity
|
125
|
+
qa << GraphQL::Analysis::MaxQueryComplexity.new(max_complexity)
|
126
|
+
end
|
104
127
|
end
|
128
|
+
|
105
129
|
qa
|
106
130
|
else
|
107
|
-
|
131
|
+
qa
|
108
132
|
end
|
109
133
|
end
|
110
134
|
end
|
@@ -14,7 +14,16 @@ module GraphQL
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def to_h
|
17
|
-
|
17
|
+
# It is possible there are other extension items in this error, so handle
|
18
|
+
# a one level deep merge explicitly. However beyond that only show the
|
19
|
+
# latest value and problems.
|
20
|
+
super.merge({ "extensions" => { "value" => value, "problems" => validation_result.problems }}) do |key, oldValue, newValue|
|
21
|
+
if oldValue.respond_to? merge
|
22
|
+
oldValue.merge(newValue)
|
23
|
+
else
|
24
|
+
newValue
|
25
|
+
end
|
26
|
+
end
|
18
27
|
end
|
19
28
|
end
|
20
29
|
end
|
data/lib/graphql/query.rb
CHANGED
@@ -135,10 +135,23 @@ module GraphQL
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
+
def_delegators :@schema, :interpreter?
|
139
|
+
|
138
140
|
def subscription_update?
|
139
141
|
@subscription_topic && subscription?
|
140
142
|
end
|
141
143
|
|
144
|
+
# A lookahead for the root selections of this query
|
145
|
+
# @return [GraphQL::Execution::Lookahead]
|
146
|
+
def lookahead
|
147
|
+
@lookahead ||= begin
|
148
|
+
ast_node = selected_operation
|
149
|
+
root_type = warden.root_type_for_operation(ast_node.operation_type || "query")
|
150
|
+
root_type = root_type.metadata[:type_class] || raise("Invariant: `lookahead` only works with class-based types")
|
151
|
+
GraphQL::Execution::Lookahead.new(query: self, root_type: root_type, ast_nodes: [ast_node])
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
142
155
|
# @api private
|
143
156
|
def result_values=(result_hash)
|
144
157
|
if @executed
|
@@ -221,11 +234,12 @@ module GraphQL
|
|
221
234
|
with_prepared_ast { @validation_pipeline }
|
222
235
|
end
|
223
236
|
|
224
|
-
def_delegators :validation_pipeline, :validation_errors, :internal_representation,
|
237
|
+
def_delegators :validation_pipeline, :validation_errors, :internal_representation,
|
238
|
+
:analyzers, :ast_analyzers, :max_depth, :max_complexity
|
225
239
|
|
226
240
|
attr_accessor :analysis_errors
|
227
241
|
def valid?
|
228
|
-
validation_pipeline.valid? && analysis_errors.
|
242
|
+
validation_pipeline.valid? && analysis_errors.empty?
|
229
243
|
end
|
230
244
|
|
231
245
|
def warden
|
@@ -32,7 +32,9 @@ module GraphQL
|
|
32
32
|
# - Merging in the default arguments
|
33
33
|
# - Transforming its resolve function to return a connection object
|
34
34
|
def self.instrument(type, field)
|
35
|
-
|
35
|
+
# Don't apply the wrapper to class-based fields, since they
|
36
|
+
# use Schema::Field::ConnectionFilter
|
37
|
+
if field.connection? && !field.metadata[:type_class]
|
36
38
|
connection_arguments = default_arguments.merge(field.arguments)
|
37
39
|
original_resolve = field.resolve_proc
|
38
40
|
original_lazy_resolve = field.lazy_resolve_proc
|
data/lib/graphql/relay/node.rb
CHANGED
@@ -8,13 +8,7 @@ module GraphQL
|
|
8
8
|
# We have to define it fresh each time because
|
9
9
|
# its name will be modified and its description
|
10
10
|
# _may_ be modified.
|
11
|
-
field = GraphQL::
|
12
|
-
type(GraphQL::Relay::Node.interface)
|
13
|
-
description("Fetches an object given its ID.")
|
14
|
-
argument(:id, types.ID.to_non_null_type, "ID of the object.")
|
15
|
-
resolve(GraphQL::Relay::Node::FindNode)
|
16
|
-
relay_node_field(true)
|
17
|
-
end
|
11
|
+
field = GraphQL::Types::Relay::NodeField.graphql_definition
|
18
12
|
|
19
13
|
if kwargs.any? || block
|
20
14
|
field = field.redefine(kwargs, &block)
|
@@ -24,13 +18,7 @@ module GraphQL
|
|
24
18
|
end
|
25
19
|
|
26
20
|
def self.plural_field(**kwargs, &block)
|
27
|
-
field = GraphQL::
|
28
|
-
type(!types[GraphQL::Relay::Node.interface])
|
29
|
-
description("Fetches a list of objects given a list of IDs.")
|
30
|
-
argument(:ids, types.ID.to_non_null_type.to_list_type.to_non_null_type, "IDs of the objects.")
|
31
|
-
resolve(GraphQL::Relay::Node::FindNodes)
|
32
|
-
relay_nodes_field(true)
|
33
|
-
end
|
21
|
+
field = GraphQL::Types::Relay::NodesField.graphql_definition
|
34
22
|
|
35
23
|
if kwargs.any? || block
|
36
24
|
field = field.redefine(kwargs, &block)
|
@@ -43,20 +31,6 @@ module GraphQL
|
|
43
31
|
def self.interface
|
44
32
|
@interface ||= GraphQL::Types::Relay::Node.graphql_definition
|
45
33
|
end
|
46
|
-
|
47
|
-
# A field resolve for finding objects by IDs
|
48
|
-
module FindNodes
|
49
|
-
def self.call(obj, args, ctx)
|
50
|
-
args[:ids].map { |id| ctx.query.schema.object_from_id(id, ctx) }
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# A field resolve for finding an object by ID
|
55
|
-
module FindNode
|
56
|
-
def self.call(obj, args, ctx)
|
57
|
-
ctx.query.schema.object_from_id(args[:id], ctx )
|
58
|
-
end
|
59
|
-
end
|
60
34
|
end
|
61
35
|
end
|
62
36
|
end
|
@@ -124,7 +124,7 @@ module GraphQL
|
|
124
124
|
# If a relation contains a `.group` clause, a `.count` will return a Hash.
|
125
125
|
def relation_count(relation)
|
126
126
|
count_or_hash = if(defined?(ActiveRecord::Relation) && relation.is_a?(ActiveRecord::Relation))
|
127
|
-
relation.count(:all)
|
127
|
+
relation.respond_to?(:unscope)? relation.unscope(:order).count(:all) : relation.count(:all)
|
128
128
|
else # eg, Sequel::Dataset, don't mess up others
|
129
129
|
relation.count
|
130
130
|
end
|
@@ -4,6 +4,7 @@ module GraphQL
|
|
4
4
|
class Argument
|
5
5
|
include GraphQL::Schema::Member::CachedGraphQLDefinition
|
6
6
|
include GraphQL::Schema::Member::AcceptsDefinition
|
7
|
+
include GraphQL::Schema::Member::HasPath
|
7
8
|
|
8
9
|
NO_DEFAULT = :__no_default__
|
9
10
|
|
@@ -27,7 +28,7 @@ module GraphQL
|
|
27
28
|
# @param description [String]
|
28
29
|
# @param default_value [Object]
|
29
30
|
# @param as [Symbol] Override the keyword name when passed to a method
|
30
|
-
# @param prepare [Symbol] A method to call to
|
31
|
+
# @param prepare [Symbol] A method to call to transform this argument's valuebefore sending it to field resolution
|
31
32
|
# @param camelize [Boolean] if true, the name will be camelized when building the schema
|
32
33
|
def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, description: nil, default_value: NO_DEFAULT, as: nil, camelize: true, prepare: nil, owner:, &definition_block)
|
33
34
|
arg_name ||= name
|
@@ -50,6 +51,14 @@ module GraphQL
|
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
54
|
+
# @return [Object] the value used when the client doesn't provide a value for this argument
|
55
|
+
attr_reader :default_value
|
56
|
+
|
57
|
+
# @return [Boolean] True if this argument has a default value
|
58
|
+
def default_value?
|
59
|
+
@default_value != NO_DEFAULT
|
60
|
+
end
|
61
|
+
|
53
62
|
attr_writer :description
|
54
63
|
|
55
64
|
# @return [String] Documentation for this argument
|
@@ -96,12 +105,11 @@ module GraphQL
|
|
96
105
|
# Used by the runtime.
|
97
106
|
# @api private
|
98
107
|
def prepare_value(obj, value)
|
99
|
-
|
100
|
-
when nil
|
108
|
+
if @prepare.nil?
|
101
109
|
value
|
102
|
-
|
110
|
+
elsif @prepare.is_a?(String) || @prepare.is_a?(Symbol)
|
103
111
|
obj.public_send(@prepare, value)
|
104
|
-
|
112
|
+
elsif @prepare.respond_to?(:call)
|
105
113
|
@prepare.call(value, obj.context)
|
106
114
|
else
|
107
115
|
raise "Invalid prepare for #{@owner.name}.name: #{@prepare.inspect}"
|
@@ -6,13 +6,13 @@ module GraphQL
|
|
6
6
|
class Schema
|
7
7
|
# @api private
|
8
8
|
module Base64Encoder
|
9
|
-
def self.encode(
|
10
|
-
|
9
|
+
def self.encode(unencoded_text, nonce: false)
|
10
|
+
Base64Bp.urlsafe_encode64(unencoded_text, padding: false)
|
11
11
|
end
|
12
12
|
|
13
|
-
def self.decode(
|
13
|
+
def self.decode(encoded_text, nonce: false)
|
14
14
|
# urlsafe_decode64 is for forward compatibility
|
15
|
-
Base64Bp.urlsafe_decode64(
|
15
|
+
Base64Bp.urlsafe_decode64(encoded_text)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -64,9 +64,7 @@ module GraphQL
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
GraphQL::Schema
|
68
|
-
directives[built_in_directive.name] = built_in_directive unless directives[built_in_directive.name]
|
69
|
-
end
|
67
|
+
directives = GraphQL::Schema.default_directives.merge(directives)
|
70
68
|
|
71
69
|
if schema_definition
|
72
70
|
if schema_definition.query
|
@@ -113,7 +111,7 @@ module GraphQL
|
|
113
111
|
end
|
114
112
|
|
115
113
|
NullResolveType = ->(type, obj, ctx) {
|
116
|
-
raise(NotImplementedError, "Generated Schema cannot use Interface or Union types for execution.")
|
114
|
+
raise(NotImplementedError, "Generated Schema cannot use Interface or Union types for execution. Implement resolve_type on your resolver.")
|
117
115
|
}
|
118
116
|
|
119
117
|
NullScalarCoerce = ->(val, _ctx) { val }
|
@@ -6,7 +6,7 @@ module GraphQL
|
|
6
6
|
case type_error
|
7
7
|
when GraphQL::InvalidNullError
|
8
8
|
ctx.errors << type_error
|
9
|
-
when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError
|
9
|
+
when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
|
10
10
|
raise type_error
|
11
11
|
end
|
12
12
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class Directive < GraphQL::Schema::Member
|
5
|
+
# An example directive to show how you might interact with the runtime.
|
6
|
+
#
|
7
|
+
# This directive might be used along with a server-side feature flag system like Flipper.
|
8
|
+
#
|
9
|
+
# With that system, you could use this directive to exclude parts of a query
|
10
|
+
# if the current viewer doesn't have certain flags enabled.
|
11
|
+
# (So, this flag would be for internal clients, like your iOS app, not third-party API clients.)
|
12
|
+
#
|
13
|
+
# To use it, you have to implement `.enabled?`, for example:
|
14
|
+
#
|
15
|
+
# @example Implementing the Feature directive
|
16
|
+
# # app/graphql/directives/feature.rb
|
17
|
+
# class Directives::Feature < GraphQL::Schema::Directive::Feature
|
18
|
+
# def self.enabled?(flag_name, _obj, context)
|
19
|
+
# # Translate some GraphQL data for Ruby:
|
20
|
+
# flag_key = flag_name.underscore
|
21
|
+
# current_user = context[:viewer]
|
22
|
+
# # Check the feature flag however your app does it:
|
23
|
+
# MyFeatureFlags.enabled?(current_user, flag_key)
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# @example Flagging a part of the query
|
28
|
+
# viewer {
|
29
|
+
# # This field only runs if `.enabled?("recommendationEngine", obj, context)`
|
30
|
+
# # returns true. Otherwise, it's treated as if it didn't exist.
|
31
|
+
# recommendations @feature(flag: "recommendationEngine") {
|
32
|
+
# name
|
33
|
+
# rating
|
34
|
+
# }
|
35
|
+
# }
|
36
|
+
class Feature < Schema::Directive
|
37
|
+
description "Directs the executor to run this only if a certain server-side feature is enabled."
|
38
|
+
|
39
|
+
locations(
|
40
|
+
GraphQL::Schema::Directive::FIELD,
|
41
|
+
GraphQL::Schema::Directive::FRAGMENT_SPREAD,
|
42
|
+
GraphQL::Schema::Directive::INLINE_FRAGMENT
|
43
|
+
)
|
44
|
+
|
45
|
+
argument :flag, String, required: true,
|
46
|
+
description: "The name of the feature to check before continuing"
|
47
|
+
|
48
|
+
# Implement the Directive API
|
49
|
+
def self.include?(object, arguments, context)
|
50
|
+
flag_name = arguments[:flag]
|
51
|
+
self.enabled?(flag_name, object, context)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Override this method in your app's subclass of this directive.
|
55
|
+
#
|
56
|
+
# @param flag_name [String] The client-provided string of a feature to check
|
57
|
+
# @param object [GraphQL::Schema::Objct] The currently-evaluated GraphQL object instance
|
58
|
+
# @param context [GraphQL::Query::Context]
|
59
|
+
# @return [Boolean] If truthy, execution will continue
|
60
|
+
def self.enabled?(flag_name, object, context)
|
61
|
+
raise NotImplementedError, "Implement `.enabled?(flag_name, object, context)` to return true or false for the feature flag (#{flag_name.inspect})"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class Directive < GraphQL::Schema::Member
|
5
|
+
class Include < GraphQL::Schema::Directive
|
6
|
+
description "Directs the executor to include this field or fragment only when the `if` argument is true."
|
7
|
+
|
8
|
+
locations(
|
9
|
+
GraphQL::Schema::Directive::FIELD,
|
10
|
+
GraphQL::Schema::Directive::FRAGMENT_SPREAD,
|
11
|
+
GraphQL::Schema::Directive::INLINE_FRAGMENT
|
12
|
+
)
|
13
|
+
|
14
|
+
argument :if, Boolean, required: true,
|
15
|
+
description: "Included when true."
|
16
|
+
|
17
|
+
default_directive true
|
18
|
+
|
19
|
+
def self.include?(obj, args, ctx)
|
20
|
+
!!args[:if]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class Directive < GraphQL::Schema::Member
|
5
|
+
class Skip < Schema::Directive
|
6
|
+
description "Directs the executor to skip this field or fragment when the `if` argument is true."
|
7
|
+
|
8
|
+
locations(
|
9
|
+
GraphQL::Schema::Directive::FIELD,
|
10
|
+
GraphQL::Schema::Directive::FRAGMENT_SPREAD,
|
11
|
+
GraphQL::Schema::Directive::INLINE_FRAGMENT
|
12
|
+
)
|
13
|
+
|
14
|
+
argument :if, Boolean, required: true,
|
15
|
+
description: "Skipped when true."
|
16
|
+
|
17
|
+
default_directive true
|
18
|
+
|
19
|
+
def self.include?(obj, args, ctx)
|
20
|
+
!args[:if]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class Directive < GraphQL::Schema::Member
|
5
|
+
# An example directive to show how you might interact with the runtime.
|
6
|
+
#
|
7
|
+
# This directive takes the return value of the tagged part of the query,
|
8
|
+
# and if the named transform is whitelisted and applies to the return value,
|
9
|
+
# it's applied by calling a method with that name.
|
10
|
+
#
|
11
|
+
# @example Installing the directive
|
12
|
+
# class MySchema < GraphQL::Schema
|
13
|
+
# directive(GraphQL::Schema::Directive::Transform)
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# @example Transforming strings
|
17
|
+
# viewer {
|
18
|
+
# username @transform(by: "upcase")
|
19
|
+
# }
|
20
|
+
class Transform < Schema::Directive
|
21
|
+
description "Directs the executor to run named transform on the return value."
|
22
|
+
|
23
|
+
locations(
|
24
|
+
GraphQL::Schema::Directive::FIELD,
|
25
|
+
)
|
26
|
+
|
27
|
+
argument :by, String, required: true,
|
28
|
+
description: "The name of the transform to run if applicable"
|
29
|
+
|
30
|
+
TRANSFORMS = [
|
31
|
+
"upcase",
|
32
|
+
"downcase",
|
33
|
+
# ??
|
34
|
+
]
|
35
|
+
# Implement the Directive API
|
36
|
+
def self.resolve(object, arguments, context)
|
37
|
+
path = context.namespace(:interpreter)[:current_path]
|
38
|
+
return_value = yield
|
39
|
+
transform_name = arguments[:by]
|
40
|
+
if TRANSFORMS.include?(transform_name) && return_value.respond_to?(transform_name)
|
41
|
+
return_value = return_value.public_send(transform_name)
|
42
|
+
context.namespace(:interpreter)[:runtime].write_in_response(path, return_value)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
# Subclasses of this can influence how {GraphQL::Execution::Interpreter} runs queries.
|
6
|
+
#
|
7
|
+
# - {.include?}: if it returns `false`, the field or fragment will be skipped altogether, as if it were absent
|
8
|
+
# - {.resolve}: Wraps field resolution (so it should call `yield` to continue)
|
9
|
+
class Directive < GraphQL::Schema::Member
|
10
|
+
extend GraphQL::Schema::Member::HasArguments
|
11
|
+
class << self
|
12
|
+
def default_graphql_name
|
13
|
+
super.downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
def locations(*new_locations)
|
17
|
+
if new_locations.any?
|
18
|
+
@locations = new_locations
|
19
|
+
else
|
20
|
+
@locations ||= (superclass.respond_to?(:locations) ? superclass.locations : [])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_directive(new_default_directive = nil)
|
25
|
+
if new_default_directive != nil
|
26
|
+
@default_directive = new_default_directive
|
27
|
+
elsif @default_directive.nil?
|
28
|
+
@default_directive = (superclass.respond_to?(:default_directive) ? superclass.default_directive : false)
|
29
|
+
else
|
30
|
+
@default_directive
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_graphql
|
35
|
+
defn = GraphQL::Directive.new
|
36
|
+
defn.name = self.graphql_name
|
37
|
+
defn.description = self.description
|
38
|
+
defn.locations = self.locations
|
39
|
+
defn.default_directive = self.default_directive
|
40
|
+
defn.metadata[:type_class] = self
|
41
|
+
arguments.each do |name, arg_defn|
|
42
|
+
arg_graphql = arg_defn.to_graphql
|
43
|
+
defn.arguments[arg_graphql.name] = arg_graphql
|
44
|
+
end
|
45
|
+
defn
|
46
|
+
end
|
47
|
+
|
48
|
+
# If false, this part of the query won't be evaluated
|
49
|
+
def include?(_object, _arguments, _context)
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
# Continuing is passed as a block; `yield` to continue
|
54
|
+
def resolve(object, arguments, context)
|
55
|
+
yield
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
LOCATIONS = [
|
60
|
+
QUERY = :QUERY,
|
61
|
+
MUTATION = :MUTATION,
|
62
|
+
SUBSCRIPTION = :SUBSCRIPTION,
|
63
|
+
FIELD = :FIELD,
|
64
|
+
FRAGMENT_DEFINITION = :FRAGMENT_DEFINITION,
|
65
|
+
FRAGMENT_SPREAD = :FRAGMENT_SPREAD,
|
66
|
+
INLINE_FRAGMENT = :INLINE_FRAGMENT,
|
67
|
+
SCHEMA = :SCHEMA,
|
68
|
+
SCALAR = :SCALAR,
|
69
|
+
OBJECT = :OBJECT,
|
70
|
+
FIELD_DEFINITION = :FIELD_DEFINITION,
|
71
|
+
ARGUMENT_DEFINITION = :ARGUMENT_DEFINITION,
|
72
|
+
INTERFACE = :INTERFACE,
|
73
|
+
UNION = :UNION,
|
74
|
+
ENUM = :ENUM,
|
75
|
+
ENUM_VALUE = :ENUM_VALUE,
|
76
|
+
INPUT_OBJECT = :INPUT_OBJECT,
|
77
|
+
INPUT_FIELD_DEFINITION = :INPUT_FIELD_DEFINITION,
|
78
|
+
]
|
79
|
+
|
80
|
+
DEFAULT_DEPRECATION_REASON = 'No longer supported'
|
81
|
+
LOCATION_DESCRIPTIONS = {
|
82
|
+
QUERY: 'Location adjacent to a query operation.',
|
83
|
+
MUTATION: 'Location adjacent to a mutation operation.',
|
84
|
+
SUBSCRIPTION: 'Location adjacent to a subscription operation.',
|
85
|
+
FIELD: 'Location adjacent to a field.',
|
86
|
+
FRAGMENT_DEFINITION: 'Location adjacent to a fragment definition.',
|
87
|
+
FRAGMENT_SPREAD: 'Location adjacent to a fragment spread.',
|
88
|
+
INLINE_FRAGMENT: 'Location adjacent to an inline fragment.',
|
89
|
+
SCHEMA: 'Location adjacent to a schema definition.',
|
90
|
+
SCALAR: 'Location adjacent to a scalar definition.',
|
91
|
+
OBJECT: 'Location adjacent to an object type definition.',
|
92
|
+
FIELD_DEFINITION: 'Location adjacent to a field definition.',
|
93
|
+
ARGUMENT_DEFINITION: 'Location adjacent to an argument definition.',
|
94
|
+
INTERFACE: 'Location adjacent to an interface definition.',
|
95
|
+
UNION: 'Location adjacent to a union definition.',
|
96
|
+
ENUM: 'Location adjacent to an enum definition.',
|
97
|
+
ENUM_VALUE: 'Location adjacent to an enum value definition.',
|
98
|
+
INPUT_OBJECT: 'Location adjacent to an input object type definition.',
|
99
|
+
INPUT_FIELD_DEFINITION: 'Location adjacent to an input object field definition.',
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -27,6 +27,7 @@ module GraphQL
|
|
27
27
|
# end
|
28
28
|
class EnumValue < GraphQL::Schema::Member
|
29
29
|
include GraphQL::Schema::Member::AcceptsDefinition
|
30
|
+
include GraphQL::Schema::Member::HasPath
|
30
31
|
|
31
32
|
attr_reader :graphql_name
|
32
33
|
|
@@ -39,7 +40,7 @@ module GraphQL
|
|
39
40
|
def initialize(graphql_name, desc = nil, owner:, description: nil, value: nil, deprecation_reason: nil, &block)
|
40
41
|
@graphql_name = graphql_name.to_s
|
41
42
|
@description = desc || description
|
42
|
-
@value = value
|
43
|
+
@value = value.nil? ? @graphql_name : value
|
43
44
|
@deprecation_reason = deprecation_reason
|
44
45
|
@owner = owner
|
45
46
|
|
@@ -56,7 +57,7 @@ module GraphQL
|
|
56
57
|
end
|
57
58
|
|
58
59
|
def value(new_val = nil)
|
59
|
-
|
60
|
+
unless new_val.nil?
|
60
61
|
@value = new_val
|
61
62
|
end
|
62
63
|
@value
|