graphql 1.7.6 → 1.8.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/function_generator.rb +1 -1
- data/lib/generators/graphql/install_generator.rb +14 -8
- data/lib/generators/graphql/loader_generator.rb +1 -1
- data/lib/generators/graphql/mutation_generator.rb +6 -1
- data/lib/generators/graphql/templates/function.erb +2 -2
- data/lib/generators/graphql/templates/loader.erb +2 -2
- data/lib/generators/graphql/templates/schema.erb +1 -1
- data/lib/graphql/argument.rb +25 -19
- data/lib/graphql/backtrace/tracer.rb +16 -22
- data/lib/graphql/backtrace.rb +1 -1
- data/lib/graphql/backwards_compatibility.rb +2 -3
- data/lib/graphql/base_type.rb +31 -31
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +14 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +117 -0
- data/lib/graphql/define/assign_object_field.rb +5 -12
- data/lib/graphql/deprecated_dsl.rb +42 -0
- data/lib/graphql/directive.rb +1 -0
- data/lib/graphql/enum_type.rb +3 -1
- data/lib/graphql/execution/execute.rb +21 -13
- data/lib/graphql/execution/instrumentation.rb +82 -0
- data/lib/graphql/execution/lazy/lazy_method_map.rb +1 -1
- data/lib/graphql/execution/lazy/resolve.rb +1 -3
- data/lib/graphql/execution/multiplex.rb +12 -29
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/field.rb +21 -4
- data/lib/graphql/function.rb +14 -0
- data/lib/graphql/input_object_type.rb +3 -1
- data/lib/graphql/interface_type.rb +5 -3
- data/lib/graphql/internal_representation/node.rb +26 -14
- data/lib/graphql/internal_representation/visit.rb +3 -6
- data/lib/graphql/introspection/base_object.rb +16 -0
- data/lib/graphql/introspection/directive_location_enum.rb +11 -7
- data/lib/graphql/introspection/directive_type.rb +23 -16
- data/lib/graphql/introspection/dynamic_fields.rb +11 -0
- data/lib/graphql/introspection/entry_points.rb +29 -0
- data/lib/graphql/introspection/enum_value_type.rb +16 -11
- data/lib/graphql/introspection/field_type.rb +21 -12
- data/lib/graphql/introspection/input_value_type.rb +26 -23
- data/lib/graphql/introspection/schema_field.rb +7 -2
- data/lib/graphql/introspection/schema_type.rb +36 -22
- data/lib/graphql/introspection/type_by_name_field.rb +10 -2
- data/lib/graphql/introspection/type_kind_enum.rb +10 -6
- data/lib/graphql/introspection/type_type.rb +85 -23
- data/lib/graphql/introspection/typename_field.rb +1 -0
- data/lib/graphql/introspection.rb +3 -10
- data/lib/graphql/language/block_string.rb +47 -0
- data/lib/graphql/language/document_from_schema_definition.rb +280 -0
- data/lib/graphql/language/generation.rb +3 -182
- data/lib/graphql/language/lexer.rb +144 -69
- data/lib/graphql/language/lexer.rl +15 -4
- data/lib/graphql/language/nodes.rb +141 -78
- data/lib/graphql/language/parser.rb +677 -630
- data/lib/graphql/language/parser.y +18 -12
- data/lib/graphql/language/printer.rb +361 -0
- data/lib/graphql/language/token.rb +10 -3
- data/lib/graphql/language.rb +3 -0
- data/lib/graphql/non_null_type.rb +1 -1
- data/lib/graphql/object_type.rb +1 -6
- data/lib/graphql/query/arguments.rb +63 -32
- data/lib/graphql/query/context.rb +32 -2
- data/lib/graphql/query/literal_input.rb +4 -1
- data/lib/graphql/query/null_context.rb +1 -1
- data/lib/graphql/query/result.rb +1 -1
- data/lib/graphql/query/variables.rb +21 -3
- data/lib/graphql/query.rb +19 -6
- data/lib/graphql/railtie.rb +109 -0
- data/lib/graphql/relay/connection_resolve.rb +3 -0
- data/lib/graphql/relay/connection_type.rb +5 -3
- data/lib/graphql/relay/edge_type.rb +2 -1
- data/lib/graphql/relay/global_id_resolve.rb +5 -1
- data/lib/graphql/relay/mongo_relation_connection.rb +40 -0
- data/lib/graphql/relay/mutation/instrumentation.rb +1 -1
- data/lib/graphql/relay/mutation/resolve.rb +5 -1
- data/lib/graphql/relay/relation_connection.rb +14 -19
- data/lib/graphql/relay/type_extensions.rb +30 -0
- data/lib/graphql/relay.rb +2 -0
- data/lib/graphql/scalar_type.rb +14 -2
- data/lib/graphql/schema/argument.rb +92 -0
- data/lib/graphql/schema/build_from_definition.rb +64 -18
- data/lib/graphql/schema/enum.rb +85 -0
- data/lib/graphql/schema/enum_value.rb +74 -0
- data/lib/graphql/schema/field.rb +372 -0
- data/lib/graphql/schema/finder.rb +153 -0
- data/lib/graphql/schema/input_object.rb +87 -0
- data/lib/graphql/schema/interface.rb +105 -0
- data/lib/graphql/schema/introspection_system.rb +93 -0
- data/lib/graphql/schema/late_bound_type.rb +32 -0
- data/lib/graphql/schema/list.rb +32 -0
- data/lib/graphql/schema/loader.rb +2 -2
- data/lib/graphql/schema/member/accepts_definition.rb +152 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +100 -0
- data/lib/graphql/schema/member/build_type.rb +137 -0
- data/lib/graphql/schema/member/cached_graphql_definition.rb +26 -0
- data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
- data/lib/graphql/schema/member/has_arguments.rb +50 -0
- data/lib/graphql/schema/member/has_fields.rb +130 -0
- data/lib/graphql/schema/member/instrumentation.rb +115 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +34 -0
- data/lib/graphql/schema/member.rb +28 -0
- data/lib/graphql/schema/middleware_chain.rb +5 -1
- data/lib/graphql/schema/mutation.rb +138 -0
- data/lib/graphql/schema/non_null.rb +38 -0
- data/lib/graphql/schema/object.rb +81 -0
- data/lib/graphql/schema/printer.rb +33 -266
- data/lib/graphql/schema/relay_classic_mutation.rb +87 -0
- data/lib/graphql/schema/rescue_middleware.rb +8 -7
- data/lib/graphql/schema/resolver.rb +122 -0
- data/lib/graphql/schema/scalar.rb +35 -0
- data/lib/graphql/schema/traversal.rb +102 -22
- data/lib/graphql/schema/union.rb +36 -0
- data/lib/graphql/schema/validation.rb +3 -2
- data/lib/graphql/schema.rb +381 -12
- data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
- data/lib/graphql/static_validation/literal_validator.rb +16 -4
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +15 -8
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +11 -1
- data/lib/graphql/static_validation/validation_context.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -5
- data/lib/graphql/subscriptions/instrumentation.rb +5 -1
- data/lib/graphql/subscriptions/serialize.rb +2 -0
- data/lib/graphql/subscriptions.rb +90 -16
- data/lib/graphql/tracing/data_dog_tracing.rb +49 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +26 -0
- data/lib/graphql/tracing/platform_tracing.rb +20 -7
- data/lib/graphql/tracing/scout_tracing.rb +2 -2
- data/lib/graphql/tracing.rb +1 -0
- data/lib/graphql/unresolved_type_error.rb +3 -2
- data/lib/graphql/upgrader/member.rb +894 -0
- data/lib/graphql/upgrader/schema.rb +37 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +5 -25
- data/readme.md +2 -2
- data/spec/dummy/app/channels/graphql_channel.rb +23 -2
- data/spec/dummy/log/development.log +239 -0
- data/spec/dummy/log/test.log +410 -0
- data/spec/dummy/test/system/action_cable_subscription_test.rb +4 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-xYZjAnuuzgR79fcznLTQtSdh6AARxu8FcQ_J6p7L3U.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/13/13HiV12xyoQvT-1L39ZzLwMZxjyaGMiENmfw7f-QTIc.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3W/3Wtf5pCWdqq0AB-iB0Y9uUNrTkruRxIEf1XFn_BETU0.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5i/5iguGafb4hOn8262Kn8Q37ogNN9MxxQKGKNzHAzUcvI.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8m/8mj2T6yy847Mc2Z7k3Xzh8O91hhVJt3NrPe8ASNDlIA.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/DT/DTQyMpr4ABZYQetsdRJ5A7S4jf1r3ie4FGOR7GZBNSs.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Dq/DqJ5_yJPrP5iLlOQyTQsjAVI5FE5LCVDkED0f7GgsSo.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rw/RwDuCV-XpnCtjNkvhpJfBuxXMk0b5AD3L9eR6M-wcy0.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UL/ULdjhhb0bRuqmaG7XSZlFYzGYCXTDnqZuJBTWRlzqgw.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Up/UpPNgh0yYoUsyMDh5zWqe_U6qJIyTC6-dxMMAs1vvlM.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wg/Wguh-szFGTI1gaL6npYwPekMXflugRei7F_mOyRucXg.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/X-/X-khLYMA9mqFRPg3zAi86mREDxpKl4bdKYp3uF6WHos.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bi/BIkdhfxsezxM4q-HZ4oCNTq97WEJTigcq0tpX2cDvbY.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ff/FfxmA4CMHQZT7exx0G7NS1Wpcnny0vzp-Jhc2H36bp8.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gE/gEiiG4GZNy_djEjK2pHm_NgA-gyhLZhdQvo0Yt96GqE.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gn/gnA9ZSqpjccNL2m8pe_jBvY6SinXlCzXDWyop83Od8s.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lO/lOAan3cMwCE_Hli6gsDML88xFNfn0nxPmvrSkW7eEOw.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m1/M1pv8MJEPLXGLvS8QxVh3DSO9cI4mRt5FHFWdrvUj6o.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m7/m77qH7ZqH0_0SmwJbiKGDd-aLau1Dav847DC6ge46zY.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sj/sjRjnjRB37lH2vrgtkdJ8Cz84__IJ978IuKTM7HcztI.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/um/um1JrirR4hJhK-1rE-HywlyCi5ibgxHVrReiujZBWJM.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v4/v4fwVytD7ITcE0_GDbslZEYud8a5Okm85fV1o7SDl6g.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v_/v_0PAQt0iipQjFP5zjgkkk9Stnpf4VzvnMv67d1Keuw.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wd/wdT9U4MKxe1PyqNjVuCKMpCl3dxGCIRJIlwUTfh2DQU.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xI/xIaxut_fEIhKBDqljTNwYaADK9kj3gG0ESrfHs-5_og.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y0/y0SJOqIx2fn1SKqOkAihsQow0trRJrSIyAswufVuoA8.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zg/zgpzeaX-KZErHyGJ1aBH3ZusweNXMneVZule88XsIJI.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zYFltDy-8VC-uKq2BVEiJJyYXNFvVzAKuMlR3ZIYZsk.cache +0 -0
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/fixtures/upgrader/account.original.rb +19 -0
- data/spec/fixtures/upgrader/account.transformed.rb +20 -0
- data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
- data/spec/fixtures/upgrader/blame_range.transformed.rb +30 -0
- data/spec/fixtures/upgrader/date_time.original.rb +24 -0
- data/spec/fixtures/upgrader/date_time.transformed.rb +23 -0
- data/spec/fixtures/upgrader/delete_project.original.rb +28 -0
- data/spec/fixtures/upgrader/delete_project.transformed.rb +27 -0
- data/spec/fixtures/upgrader/gist_order_field.original.rb +14 -0
- data/spec/fixtures/upgrader/gist_order_field.transformed.rb +13 -0
- data/spec/fixtures/upgrader/increment_count.original.rb +59 -0
- data/spec/fixtures/upgrader/increment_count.transformed.rb +50 -0
- data/spec/fixtures/upgrader/photo.original.rb +10 -0
- data/spec/fixtures/upgrader/photo.transformed.rb +12 -0
- data/spec/fixtures/upgrader/release_order.original.rb +15 -0
- data/spec/fixtures/upgrader/release_order.transformed.rb +14 -0
- data/spec/fixtures/upgrader/starrable.original.rb +49 -0
- data/spec/fixtures/upgrader/starrable.transformed.rb +46 -0
- data/spec/fixtures/upgrader/subscribable.original.rb +55 -0
- data/spec/fixtures/upgrader/subscribable.transformed.rb +51 -0
- data/spec/fixtures/upgrader/type_x.original.rb +65 -0
- data/spec/fixtures/upgrader/type_x.transformed.rb +56 -0
- data/spec/generators/graphql/function_generator_spec.rb +26 -0
- data/spec/generators/graphql/install_generator_spec.rb +1 -1
- data/spec/generators/graphql/loader_generator_spec.rb +24 -0
- data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
- data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
- data/spec/graphql/argument_spec.rb +21 -0
- data/spec/graphql/backtrace_spec.rb +10 -0
- data/spec/graphql/base_type_spec.rb +42 -0
- data/spec/graphql/boolean_type_spec.rb +3 -3
- data/spec/graphql/directive_spec.rb +3 -1
- data/spec/graphql/enum_type_spec.rb +18 -5
- data/spec/graphql/execution/execute_spec.rb +4 -4
- data/spec/graphql/execution/instrumentation_spec.rb +165 -0
- data/spec/graphql/execution/multiplex_spec.rb +2 -2
- data/spec/graphql/execution_error_spec.rb +18 -0
- data/spec/graphql/float_type_spec.rb +2 -2
- data/spec/graphql/id_type_spec.rb +1 -1
- data/spec/graphql/input_object_type_spec.rb +15 -2
- data/spec/graphql/int_type_spec.rb +2 -2
- data/spec/graphql/interface_type_spec.rb +12 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
- data/spec/graphql/introspection/schema_type_spec.rb +2 -0
- data/spec/graphql/language/block_string_spec.rb +70 -0
- data/spec/graphql/language/document_from_schema_definition_spec.rb +770 -0
- data/spec/graphql/language/generation_spec.rb +21 -186
- data/spec/graphql/language/lexer_spec.rb +21 -1
- data/spec/graphql/language/nodes_spec.rb +21 -12
- data/spec/graphql/language/parser_spec.rb +1 -1
- data/spec/graphql/language/printer_spec.rb +203 -0
- data/spec/graphql/object_type_spec.rb +22 -0
- data/spec/graphql/query/arguments_spec.rb +25 -15
- data/spec/graphql/query/context_spec.rb +18 -0
- data/spec/graphql/query/executor_spec.rb +2 -1
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -8
- data/spec/graphql/query/variables_spec.rb +42 -1
- data/spec/graphql/query_spec.rb +31 -5
- data/spec/graphql/rake_task_spec.rb +3 -1
- data/spec/graphql/relay/base_connection_spec.rb +1 -1
- data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
- data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
- data/spec/graphql/relay/connection_type_spec.rb +1 -1
- data/spec/graphql/relay/mongo_relation_connection_spec.rb +474 -0
- data/spec/graphql/relay/mutation_spec.rb +9 -7
- data/spec/graphql/relay/range_add_spec.rb +5 -1
- data/spec/graphql/relay/relation_connection_spec.rb +65 -1
- data/spec/graphql/schema/argument_spec.rb +87 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +89 -5
- data/spec/graphql/schema/enum_spec.rb +74 -0
- data/spec/graphql/schema/field_spec.rb +225 -0
- data/spec/graphql/schema/finder_spec.rb +135 -0
- data/spec/graphql/schema/input_object_spec.rb +111 -0
- data/spec/graphql/schema/instrumentation_spec.rb +40 -0
- data/spec/graphql/schema/interface_spec.rb +185 -0
- data/spec/graphql/schema/introspection_system_spec.rb +39 -0
- data/spec/graphql/schema/member/accepts_definition_spec.rb +111 -0
- data/spec/graphql/schema/member/build_type_spec.rb +17 -0
- data/spec/graphql/schema/member/has_fields_spec.rb +129 -0
- data/spec/graphql/schema/member/type_system_helpers_spec.rb +63 -0
- data/spec/graphql/schema/mutation_spec.rb +148 -0
- data/spec/graphql/schema/object_spec.rb +175 -0
- data/spec/graphql/schema/printer_spec.rb +111 -15
- data/spec/graphql/schema/relay_classic_mutation_spec.rb +38 -0
- data/spec/graphql/schema/rescue_middleware_spec.rb +11 -0
- data/spec/graphql/schema/resolver_spec.rb +131 -0
- data/spec/graphql/schema/scalar_spec.rb +95 -0
- data/spec/graphql/schema/traversal_spec.rb +31 -0
- data/spec/graphql/schema/union_spec.rb +65 -0
- data/spec/graphql/schema/validation_spec.rb +1 -1
- data/spec/graphql/schema/warden_spec.rb +11 -11
- data/spec/graphql/schema_spec.rb +55 -12
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -2
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
- data/spec/graphql/string_type_spec.rb +3 -3
- data/spec/graphql/subscriptions_spec.rb +273 -184
- data/spec/graphql/tracing/active_support_notifications_tracing_spec.rb +1 -1
- data/spec/graphql/tracing/new_relic_tracing_spec.rb +47 -0
- data/spec/graphql/tracing/platform_tracing_spec.rb +60 -1
- data/spec/graphql/union_type_spec.rb +1 -1
- data/spec/graphql/upgrader/member_spec.rb +516 -0
- data/spec/graphql/upgrader/schema_spec.rb +82 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/dummy/schema.rb +53 -24
- data/spec/support/jazz.rb +544 -0
- data/spec/support/lazy_helpers.rb +21 -23
- data/spec/support/new_relic.rb +24 -0
- data/spec/support/star_trek/data.rb +109 -0
- data/spec/support/star_trek/schema.rb +388 -0
- data/spec/support/star_wars/data.rb +6 -7
- data/spec/support/star_wars/schema.rb +127 -171
- metadata +233 -11
- data/lib/graphql/introspection/arguments_field.rb +0 -7
- data/lib/graphql/introspection/enum_values_field.rb +0 -18
- data/lib/graphql/introspection/fields_field.rb +0 -13
- data/lib/graphql/introspection/input_fields_field.rb +0 -12
- data/lib/graphql/introspection/interfaces_field.rb +0 -11
- data/lib/graphql/introspection/of_type_field.rb +0 -6
- data/lib/graphql/introspection/possible_types_field.rb +0 -11
data/lib/graphql/schema.rb
CHANGED
@@ -3,7 +3,10 @@ require "graphql/schema/base_64_encoder"
|
|
3
3
|
require "graphql/schema/catchall_middleware"
|
4
4
|
require "graphql/schema/default_parse_error"
|
5
5
|
require "graphql/schema/default_type_error"
|
6
|
+
require "graphql/schema/finder"
|
6
7
|
require "graphql/schema/invalid_type_error"
|
8
|
+
require "graphql/schema/introspection_system"
|
9
|
+
require "graphql/schema/late_bound_type"
|
7
10
|
require "graphql/schema/middleware_chain"
|
8
11
|
require "graphql/schema/null_mask"
|
9
12
|
require "graphql/schema/possible_types"
|
@@ -16,6 +19,23 @@ require "graphql/schema/validation"
|
|
16
19
|
require "graphql/schema/warden"
|
17
20
|
require "graphql/schema/build_from_definition"
|
18
21
|
|
22
|
+
|
23
|
+
require "graphql/schema/member"
|
24
|
+
require "graphql/schema/list"
|
25
|
+
require "graphql/schema/non_null"
|
26
|
+
require "graphql/schema/argument"
|
27
|
+
require "graphql/schema/enum_value"
|
28
|
+
require "graphql/schema/enum"
|
29
|
+
require "graphql/schema/field"
|
30
|
+
require "graphql/schema/input_object"
|
31
|
+
require "graphql/schema/interface"
|
32
|
+
require "graphql/schema/resolver"
|
33
|
+
require "graphql/schema/mutation"
|
34
|
+
require "graphql/schema/relay_classic_mutation"
|
35
|
+
require "graphql/schema/object"
|
36
|
+
require "graphql/schema/scalar"
|
37
|
+
require "graphql/schema/union"
|
38
|
+
|
19
39
|
module GraphQL
|
20
40
|
# A GraphQL schema which may be queried with {GraphQL::Query}.
|
21
41
|
#
|
@@ -49,6 +69,7 @@ module GraphQL
|
|
49
69
|
# end
|
50
70
|
#
|
51
71
|
class Schema
|
72
|
+
extend GraphQL::Schema::Member::AcceptsDefinition
|
52
73
|
include GraphQL::Define::InstanceDefinable
|
53
74
|
accepts_definitions \
|
54
75
|
:query, :mutation, :subscription,
|
@@ -80,7 +101,9 @@ module GraphQL
|
|
80
101
|
:orphan_types, :directives,
|
81
102
|
:query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
|
82
103
|
:cursor_encoder,
|
83
|
-
:
|
104
|
+
:ast_node,
|
105
|
+
:raise_definition_error,
|
106
|
+
:introspection_namespace
|
84
107
|
|
85
108
|
# Single, long-lived instance of the provided subscriptions class, if there is one.
|
86
109
|
# @return [GraphQL::Subscriptions]
|
@@ -93,6 +116,10 @@ module GraphQL
|
|
93
116
|
# @see {Query.new} for query-specific filters with `except:`
|
94
117
|
attr_accessor :default_mask
|
95
118
|
|
119
|
+
# @see {GraphQL::Query::Context} The parent class of these classes
|
120
|
+
# @return [Class] Instantiated for each query
|
121
|
+
attr_accessor :context_class
|
122
|
+
|
96
123
|
class << self
|
97
124
|
attr_accessor :default_execution_strategy
|
98
125
|
end
|
@@ -137,6 +164,9 @@ module GraphQL
|
|
137
164
|
@subscription_execution_strategy = self.class.default_execution_strategy
|
138
165
|
@default_mask = GraphQL::Schema::NullMask
|
139
166
|
@rebuilding_artifacts = false
|
167
|
+
@context_class = GraphQL::Query::Context
|
168
|
+
@introspection_namespace = nil
|
169
|
+
@introspection_system = nil
|
140
170
|
end
|
141
171
|
|
142
172
|
def initialize_copy(other)
|
@@ -164,6 +194,7 @@ module GraphQL
|
|
164
194
|
# This will be rebuilt when it's requested
|
165
195
|
# or during a later `define` call
|
166
196
|
@types = nil
|
197
|
+
@introspection_system = nil
|
167
198
|
end
|
168
199
|
|
169
200
|
def rescue_from(*args, &block)
|
@@ -174,6 +205,9 @@ module GraphQL
|
|
174
205
|
rescue_middleware.remove_handler(*args, &block)
|
175
206
|
end
|
176
207
|
|
208
|
+
# For forwards-compatibility with Schema classes
|
209
|
+
alias :graphql_definition :itself
|
210
|
+
|
177
211
|
# Validate a query string according to this schema.
|
178
212
|
# @param string_or_document [String, GraphQL::Language::Nodes::Document]
|
179
213
|
# @return [Array<GraphQL::StaticValidation::Message>]
|
@@ -239,6 +273,14 @@ module GraphQL
|
|
239
273
|
end
|
240
274
|
end
|
241
275
|
|
276
|
+
# @api private
|
277
|
+
def introspection_system
|
278
|
+
@introspection_system ||= begin
|
279
|
+
rebuild_artifacts
|
280
|
+
@introspection_system
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
242
284
|
# Returns a list of Arguments and Fields referencing a certain type
|
243
285
|
# @param type_name [String]
|
244
286
|
# @return [Hash]
|
@@ -300,6 +342,19 @@ module GraphQL
|
|
300
342
|
}
|
301
343
|
end
|
302
344
|
|
345
|
+
# Search for a schema member using a string path
|
346
|
+
# @example Finding a Field
|
347
|
+
# Schema.find("Ensemble.musicians")
|
348
|
+
#
|
349
|
+
# @see {GraphQL::Schema::Finder} for more examples
|
350
|
+
# @param path [String] A dot-separated path to the member
|
351
|
+
# @raise [Schema::Finder::MemberNotFoundError] if path could not be found
|
352
|
+
# @return [GraphQL::BaseType, GraphQL::Field, GraphQL::Argument, GraphQL::Directive] A GraphQL Schema Member
|
353
|
+
def find(path)
|
354
|
+
rebuild_artifacts unless defined?(@finder)
|
355
|
+
@find_cache[path] ||= @finder.find(path)
|
356
|
+
end
|
357
|
+
|
303
358
|
# Resolve field named `field_name` for type `parent_type`.
|
304
359
|
# Handles dynamic fields `__typename`, `__type` and `__schema`, too
|
305
360
|
# @param parent_type [String, GraphQL::BaseType]
|
@@ -320,12 +375,10 @@ module GraphQL
|
|
320
375
|
defined_field = @instrumented_field_map[parent_type_name][field_name]
|
321
376
|
if defined_field
|
322
377
|
defined_field
|
323
|
-
elsif
|
324
|
-
|
325
|
-
elsif
|
326
|
-
|
327
|
-
elsif field_name == "__type" && parent_type == query
|
328
|
-
GraphQL::Introspection::TypeByNameField
|
378
|
+
elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
|
379
|
+
entry_point_field
|
380
|
+
elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
|
381
|
+
dynamic_field
|
329
382
|
else
|
330
383
|
nil
|
331
384
|
end
|
@@ -386,6 +439,18 @@ module GraphQL
|
|
386
439
|
# @param ctx [GraphQL::Query::Context] The context for the current query
|
387
440
|
# @return [GraphQL::ObjectType] The type for exposing `object` in GraphQL
|
388
441
|
def resolve_type(type, object, ctx = :__undefined__)
|
442
|
+
check_resolved_type(type, object, ctx) do |ok_type, ok_object, ok_ctx|
|
443
|
+
if @resolve_type_proc.nil?
|
444
|
+
raise(NotImplementedError, "Can't determine GraphQL type for: #{ok_object.inspect}, define `resolve_type (type, obj, ctx) -> { ... }` inside `Schema.define`.")
|
445
|
+
end
|
446
|
+
@resolve_type_proc.call(ok_type, ok_object, ok_ctx)
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
# This is a compatibility hack so that instance-level and class-level
|
451
|
+
# methods can get correctness checks without calling one another
|
452
|
+
# @api private
|
453
|
+
def check_resolved_type(type, object, ctx = :__undefined__)
|
389
454
|
if ctx == :__undefined__
|
390
455
|
# Old method signature
|
391
456
|
ctx = object
|
@@ -393,15 +458,20 @@ module GraphQL
|
|
393
458
|
type = nil
|
394
459
|
end
|
395
460
|
|
461
|
+
if object.is_a?(GraphQL::Schema::Object)
|
462
|
+
object = object.object
|
463
|
+
end
|
464
|
+
|
396
465
|
# Prefer a type-local function; fall back to the schema-level function
|
397
466
|
type_proc = type && type.resolve_type_proc
|
398
467
|
type_result = if type_proc
|
399
468
|
type_proc.call(object, ctx)
|
400
469
|
else
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
470
|
+
yield(type, object, ctx)
|
471
|
+
end
|
472
|
+
|
473
|
+
if type_result.respond_to?(:graphql_definition)
|
474
|
+
type_result = type_result.graphql_definition
|
405
475
|
end
|
406
476
|
|
407
477
|
if type_result.nil?
|
@@ -542,13 +612,19 @@ module GraphQL
|
|
542
612
|
GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
|
543
613
|
end
|
544
614
|
|
615
|
+
# Return the GraphQL::Language::Document IDL AST for the schema
|
616
|
+
# @return [GraphQL::Language::Document]
|
617
|
+
def to_document
|
618
|
+
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
619
|
+
end
|
620
|
+
|
545
621
|
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
546
622
|
# @param context [Hash]
|
547
623
|
# @param only [<#call(member, ctx)>]
|
548
624
|
# @param except [<#call(member, ctx)>]
|
549
625
|
# @return [Hash] GraphQL result
|
550
626
|
def as_json(only: nil, except: nil, context: {})
|
551
|
-
execute(Introspection::INTROSPECTION_QUERY, only: only, except: except, context: context)
|
627
|
+
execute(Introspection::INTROSPECTION_QUERY, only: only, except: except, context: context).to_h
|
552
628
|
end
|
553
629
|
|
554
630
|
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
@@ -558,6 +634,295 @@ module GraphQL
|
|
558
634
|
JSON.pretty_generate(as_json(*args))
|
559
635
|
end
|
560
636
|
|
637
|
+
class << self
|
638
|
+
extend Forwardable
|
639
|
+
# For compatibility, these methods all:
|
640
|
+
# - Cause the Schema instance to be created, if it hasn't been created yet
|
641
|
+
# - Delegate to that instance
|
642
|
+
# Eventually, the methods will be moved into this class, removing the need for the singleton.
|
643
|
+
def_delegators :graphql_definition,
|
644
|
+
# Schema structure
|
645
|
+
:as_json, :to_json, :to_document, :to_definition,
|
646
|
+
# Execution
|
647
|
+
:execute, :multiplex,
|
648
|
+
:static_validator, :introspection_system,
|
649
|
+
:query_analyzers, :middleware, :tracers, :instrumenters,
|
650
|
+
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
651
|
+
:validate, :multiplex_analyzers, :lazy?, :lazy_method_name,
|
652
|
+
# Configuration
|
653
|
+
:max_complexity=, :max_depth=,
|
654
|
+
:metadata,
|
655
|
+
:default_filter, :redefine,
|
656
|
+
:id_from_object_proc, :object_from_id_proc,
|
657
|
+
:id_from_object=, :object_from_id=, :type_error,
|
658
|
+
:remove_handler,
|
659
|
+
# Members
|
660
|
+
:types, :get_fields, :find,
|
661
|
+
:root_type_for_operation,
|
662
|
+
:subscriptions,
|
663
|
+
:union_memberships,
|
664
|
+
:get_field, :root_types, :references_to, :type_from_ast,
|
665
|
+
:possible_types, :get_field
|
666
|
+
|
667
|
+
def graphql_definition
|
668
|
+
@graphql_definition ||= to_graphql
|
669
|
+
end
|
670
|
+
|
671
|
+
def use(plugin, options = {})
|
672
|
+
plugins << [plugin, options]
|
673
|
+
end
|
674
|
+
|
675
|
+
def plugins
|
676
|
+
@plugins ||= []
|
677
|
+
end
|
678
|
+
|
679
|
+
def to_graphql
|
680
|
+
schema_defn = self.new
|
681
|
+
schema_defn.raise_definition_error = true
|
682
|
+
schema_defn.query = query
|
683
|
+
schema_defn.mutation = mutation
|
684
|
+
schema_defn.subscription = subscription
|
685
|
+
schema_defn.max_complexity = max_complexity
|
686
|
+
schema_defn.max_depth = max_depth
|
687
|
+
schema_defn.default_max_page_size = default_max_page_size
|
688
|
+
schema_defn.orphan_types = orphan_types
|
689
|
+
schema_defn.directives = directives
|
690
|
+
schema_defn.introspection_namespace = introspection
|
691
|
+
schema_defn.resolve_type = method(:resolve_type)
|
692
|
+
schema_defn.object_from_id = method(:object_from_id)
|
693
|
+
schema_defn.id_from_object = method(:id_from_object)
|
694
|
+
schema_defn.type_error = method(:type_error)
|
695
|
+
schema_defn.context_class = context_class
|
696
|
+
schema_defn.cursor_encoder = cursor_encoder
|
697
|
+
schema_defn.tracers.concat(defined_tracers)
|
698
|
+
schema_defn.query_analyzers.concat(defined_query_analyzers)
|
699
|
+
schema_defn.middleware.concat(defined_middleware)
|
700
|
+
schema_defn.multiplex_analyzers.concat(defined_multiplex_analyzers)
|
701
|
+
defined_instrumenters.each do |step, insts|
|
702
|
+
insts.each do |inst|
|
703
|
+
schema_defn.instrumenters[step] << inst
|
704
|
+
end
|
705
|
+
end
|
706
|
+
schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
|
707
|
+
lazy_classes.each do |lazy_class, value_method|
|
708
|
+
schema_defn.lazy_methods.set(lazy_class, value_method)
|
709
|
+
end
|
710
|
+
if @rescues
|
711
|
+
@rescues.each do |err_class, handler|
|
712
|
+
schema_defn.rescue_from(err_class, &handler)
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
if plugins.any?
|
717
|
+
schema_plugins = plugins
|
718
|
+
# TODO don't depend on .define
|
719
|
+
schema_defn = schema_defn.redefine do
|
720
|
+
schema_plugins.each do |plugin, options|
|
721
|
+
if options.any?
|
722
|
+
use(plugin, **options)
|
723
|
+
else
|
724
|
+
use(plugin)
|
725
|
+
end
|
726
|
+
end
|
727
|
+
end
|
728
|
+
end
|
729
|
+
schema_defn.send(:rebuild_artifacts)
|
730
|
+
|
731
|
+
schema_defn
|
732
|
+
end
|
733
|
+
|
734
|
+
def query(new_query_object = nil)
|
735
|
+
if new_query_object
|
736
|
+
@query_object = new_query_object
|
737
|
+
else
|
738
|
+
@query_object.respond_to?(:graphql_definition) ? @query_object.graphql_definition : @query_object
|
739
|
+
end
|
740
|
+
end
|
741
|
+
|
742
|
+
def mutation(new_mutation_object = nil)
|
743
|
+
if new_mutation_object
|
744
|
+
@mutation_object = new_mutation_object
|
745
|
+
else
|
746
|
+
@mutation_object.respond_to?(:graphql_definition) ? @mutation_object.graphql_definition : @mutation_object
|
747
|
+
end
|
748
|
+
end
|
749
|
+
|
750
|
+
def subscription(new_subscription_object = nil)
|
751
|
+
if new_subscription_object
|
752
|
+
@subscription_object = new_subscription_object
|
753
|
+
else
|
754
|
+
@subscription_object.respond_to?(:graphql_definition) ? @subscription_object.graphql_definition : @subscription_object
|
755
|
+
end
|
756
|
+
end
|
757
|
+
|
758
|
+
def introspection(new_introspection_namespace = nil)
|
759
|
+
if new_introspection_namespace
|
760
|
+
@introspection = new_introspection_namespace
|
761
|
+
else
|
762
|
+
@introspection
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
766
|
+
def cursor_encoder(new_encoder = nil)
|
767
|
+
if new_encoder
|
768
|
+
@cursor_encoder = new_encoder
|
769
|
+
end
|
770
|
+
@cursor_encoder || Base64Encoder
|
771
|
+
end
|
772
|
+
|
773
|
+
def default_max_page_size(new_default_max_page_size = nil)
|
774
|
+
if new_default_max_page_size
|
775
|
+
@default_max_page_size = new_default_max_page_size
|
776
|
+
else
|
777
|
+
@default_max_page_size
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
781
|
+
def max_complexity(max_complexity = nil)
|
782
|
+
if max_complexity
|
783
|
+
@max_complexity = max_complexity
|
784
|
+
else
|
785
|
+
@max_complexity
|
786
|
+
end
|
787
|
+
end
|
788
|
+
|
789
|
+
def max_depth(new_max_depth = nil)
|
790
|
+
if new_max_depth
|
791
|
+
@max_depth = new_max_depth
|
792
|
+
else
|
793
|
+
@max_depth
|
794
|
+
end
|
795
|
+
end
|
796
|
+
|
797
|
+
def orphan_types(*new_orphan_types)
|
798
|
+
if new_orphan_types.any?
|
799
|
+
@orphan_types = new_orphan_types.flatten
|
800
|
+
else
|
801
|
+
@orphan_types || []
|
802
|
+
end
|
803
|
+
end
|
804
|
+
|
805
|
+
def default_execution_strategy
|
806
|
+
if superclass <= GraphQL::Schema
|
807
|
+
superclass.default_execution_strategy
|
808
|
+
else
|
809
|
+
@default_execution_strategy
|
810
|
+
end
|
811
|
+
end
|
812
|
+
|
813
|
+
def context_class(new_context_class = nil)
|
814
|
+
if new_context_class
|
815
|
+
@context_class = new_context_class
|
816
|
+
else
|
817
|
+
@context_class || GraphQL::Query::Context
|
818
|
+
end
|
819
|
+
end
|
820
|
+
|
821
|
+
def rescue_from(err_class, &handler_block)
|
822
|
+
@rescues ||= {}
|
823
|
+
@rescues[err_class] = handler_block
|
824
|
+
end
|
825
|
+
|
826
|
+
def resolve_type(type, obj, ctx)
|
827
|
+
raise NotImplementedError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
|
828
|
+
end
|
829
|
+
|
830
|
+
def object_from_id(node_id, ctx)
|
831
|
+
raise NotImplementedError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to use the `node` field (tried to load from id `#{node_id}`)"
|
832
|
+
end
|
833
|
+
|
834
|
+
def id_from_object(object, type, ctx)
|
835
|
+
raise NotImplementedError, "#{self.name}.id_from_object(object, type, ctx) must be implemented to create global ids (tried to create an id for `#{object.inspect}`)"
|
836
|
+
end
|
837
|
+
|
838
|
+
def type_error(type_err, ctx)
|
839
|
+
DefaultTypeError.call(type_err, ctx)
|
840
|
+
end
|
841
|
+
|
842
|
+
def lazy_resolve(lazy_class, value_method)
|
843
|
+
lazy_classes[lazy_class] = value_method
|
844
|
+
end
|
845
|
+
|
846
|
+
def instrument(instrument_step, instrumenter, options = {})
|
847
|
+
step = if instrument_step == :field && options[:after_built_ins]
|
848
|
+
:field_after_built_ins
|
849
|
+
else
|
850
|
+
instrument_step
|
851
|
+
end
|
852
|
+
defined_instrumenters[step] << instrumenter
|
853
|
+
end
|
854
|
+
|
855
|
+
def directives(new_directives = nil)
|
856
|
+
if new_directives
|
857
|
+
@directives = new_directives.reduce({}) { |m, d| m[d.name] = d; m }
|
858
|
+
end
|
859
|
+
|
860
|
+
@directives ||= directives(DIRECTIVES)
|
861
|
+
end
|
862
|
+
|
863
|
+
def tracer(new_tracer)
|
864
|
+
defined_tracers << new_tracer
|
865
|
+
end
|
866
|
+
|
867
|
+
def query_analyzer(new_analyzer)
|
868
|
+
defined_query_analyzers << new_analyzer
|
869
|
+
end
|
870
|
+
|
871
|
+
def middleware(new_middleware = nil)
|
872
|
+
if new_middleware
|
873
|
+
defined_middleware << new_middleware
|
874
|
+
else
|
875
|
+
graphql_definition.middleware
|
876
|
+
end
|
877
|
+
end
|
878
|
+
|
879
|
+
def multiplex_analyzer(new_analyzer)
|
880
|
+
defined_multiplex_analyzers << new_analyzer
|
881
|
+
end
|
882
|
+
|
883
|
+
private
|
884
|
+
|
885
|
+
def lazy_classes
|
886
|
+
@lazy_classes ||= {}
|
887
|
+
end
|
888
|
+
|
889
|
+
def defined_instrumenters
|
890
|
+
@defined_instrumenters ||= Hash.new { |h,k| h[k] = [] }
|
891
|
+
end
|
892
|
+
|
893
|
+
def defined_tracers
|
894
|
+
@defined_tracers ||= []
|
895
|
+
end
|
896
|
+
|
897
|
+
def defined_query_analyzers
|
898
|
+
@defined_query_analyzers ||= []
|
899
|
+
end
|
900
|
+
|
901
|
+
def defined_middleware
|
902
|
+
@defined_middleware ||= []
|
903
|
+
end
|
904
|
+
|
905
|
+
def defined_multiplex_analyzers
|
906
|
+
@defined_multiplex_analyzers ||= []
|
907
|
+
end
|
908
|
+
end
|
909
|
+
|
910
|
+
|
911
|
+
def self.inherited(child_class)
|
912
|
+
child_class.singleton_class.class_eval do
|
913
|
+
prepend(MethodWrappers)
|
914
|
+
end
|
915
|
+
end
|
916
|
+
|
917
|
+
module MethodWrappers
|
918
|
+
# Wrap the user-provided resolve-type in a correctness check
|
919
|
+
def resolve_type(type, obj, ctx = :__undefined__)
|
920
|
+
graphql_definition.check_resolved_type(type, obj, ctx) do |ok_type, ok_obj, ok_ctx|
|
921
|
+
super(ok_type, ok_obj, ok_ctx)
|
922
|
+
end
|
923
|
+
end
|
924
|
+
end
|
925
|
+
|
561
926
|
protected
|
562
927
|
|
563
928
|
def rescues?
|
@@ -578,6 +943,7 @@ module GraphQL
|
|
578
943
|
GraphQL::Relay::ConnectionInstrumentation,
|
579
944
|
GraphQL::Relay::EdgesInstrumentation,
|
580
945
|
GraphQL::Relay::Mutation::Instrumentation,
|
946
|
+
GraphQL::Schema::Member::Instrumentation,
|
581
947
|
]
|
582
948
|
|
583
949
|
def rebuild_artifacts
|
@@ -585,12 +951,15 @@ module GraphQL
|
|
585
951
|
raise CyclicalDefinitionError, "Part of the schema build process re-triggered the schema build process, causing an infinite loop. Avoid using Schema#types, Schema#possible_types, and Schema#get_field during schema build."
|
586
952
|
else
|
587
953
|
@rebuilding_artifacts = true
|
954
|
+
@introspection_system = Schema::IntrospectionSystem.new(self)
|
588
955
|
traversal = Traversal.new(self)
|
589
956
|
@types = traversal.type_map
|
590
957
|
@root_types = [query, mutation, subscription]
|
591
958
|
@instrumented_field_map = traversal.instrumented_field_map
|
592
959
|
@type_reference_map = traversal.type_reference_map
|
593
960
|
@union_memberships = traversal.union_memberships
|
961
|
+
@find_cache = {}
|
962
|
+
@finder = Finder.new(self)
|
594
963
|
end
|
595
964
|
ensure
|
596
965
|
@rebuilding_artifacts = false
|
@@ -16,23 +16,35 @@ module GraphQL
|
|
16
16
|
elsif type.kind.list?
|
17
17
|
item_type = type.of_type
|
18
18
|
ensure_array(ast_value).all? { |val| validate(val, item_type) }
|
19
|
-
elsif
|
19
|
+
elsif ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
|
20
|
+
true
|
21
|
+
elsif type.kind.scalar? && constant_scalar?(ast_value)
|
20
22
|
type.valid_input?(ast_value, @context)
|
21
23
|
elsif type.kind.enum? && ast_value.is_a?(GraphQL::Language::Nodes::Enum)
|
22
24
|
type.valid_input?(ast_value.name, @context)
|
23
25
|
elsif type.kind.input_object? && ast_value.is_a?(GraphQL::Language::Nodes::InputObject)
|
24
26
|
required_input_fields_are_present(type, ast_value) &&
|
25
27
|
present_input_field_values_are_valid(type, ast_value)
|
26
|
-
elsif ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
|
27
|
-
true
|
28
28
|
else
|
29
29
|
false
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
33
|
private
|
35
34
|
|
35
|
+
# The GraphQL grammar supports variables embedded within scalars but graphql.js
|
36
|
+
# doesn't support it so we won't either for simplicity
|
37
|
+
def constant_scalar?(ast_value)
|
38
|
+
if ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
|
39
|
+
false
|
40
|
+
elsif ast_value.is_a?(Array)
|
41
|
+
ast_value.all? { |element| constant_scalar?(element) }
|
42
|
+
elsif ast_value.is_a?(GraphQL::Language::Nodes::InputObject)
|
43
|
+
ast_value.arguments.all? { |arg| constant_scalar?(arg.value) }
|
44
|
+
else
|
45
|
+
true
|
46
|
+
end
|
47
|
+
end
|
36
48
|
|
37
49
|
def required_input_fields_are_present(type, ast_node)
|
38
50
|
required_field_names = @warden.arguments(type)
|
@@ -16,14 +16,14 @@ module GraphQL
|
|
16
16
|
private
|
17
17
|
|
18
18
|
def validate_field(context, ast_field, parent_type, parent)
|
19
|
-
if parent_type.kind.union? && ast_field.name != '__typename'
|
20
|
-
context.errors << message("Selections can't be made directly on unions (see selections on #{parent_type.name})", parent, context: context)
|
21
|
-
return GraphQL::Language::Visitor::SKIP
|
22
|
-
end
|
23
|
-
|
24
19
|
field = context.warden.get_field(parent_type, ast_field.name)
|
20
|
+
|
25
21
|
if field.nil?
|
26
|
-
|
22
|
+
if parent_type.kind.union?
|
23
|
+
context.errors << message("Selections can't be made directly on unions (see selections on #{parent_type.name})", parent, context: context)
|
24
|
+
else
|
25
|
+
context.errors << message("Field '#{ast_field.name}' doesn't exist on type '#{parent_type.name}'", ast_field, context: context)
|
26
|
+
end
|
27
27
|
return GraphQL::Language::Visitor::SKIP
|
28
28
|
end
|
29
29
|
end
|
@@ -24,7 +24,11 @@ module GraphQL
|
|
24
24
|
msg = if resolved_type.nil?
|
25
25
|
nil
|
26
26
|
elsif resolved_type.kind.scalar? && ast_node.selections.any?
|
27
|
-
|
27
|
+
if ast_node.selections.first.is_a?(GraphQL::Language::Nodes::InlineFragment)
|
28
|
+
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.name} but has inline fragments [#{ast_node.selections.map(&:type).map(&:name).join(", ")}])"
|
29
|
+
else
|
30
|
+
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.name} but has selections [#{ast_node.selections.map(&:name).join(", ")}])"
|
31
|
+
end
|
28
32
|
elsif resolved_type.kind.object? && ast_node.selections.none?
|
29
33
|
"Objects must have selections (%{node_name} returns #{resolved_type.name} but has no selections)"
|
30
34
|
else
|
@@ -2,6 +2,9 @@
|
|
2
2
|
module GraphQL
|
3
3
|
module StaticValidation
|
4
4
|
class FieldsWillMerge
|
5
|
+
# Special handling for fields without arguments
|
6
|
+
NO_ARGS = {}.freeze
|
7
|
+
|
5
8
|
def validate(context)
|
6
9
|
context.each_irep_node do |node|
|
7
10
|
if node.ast_nodes.size > 1
|
@@ -16,15 +19,19 @@ module GraphQL
|
|
16
19
|
|
17
20
|
# Check for incompatible / non-identical arguments on this node:
|
18
21
|
args = node.ast_nodes.map do |n|
|
19
|
-
n.arguments.
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
if n.arguments.any?
|
23
|
+
n.arguments.reduce({}) do |memo, a|
|
24
|
+
arg_value = a.value
|
25
|
+
memo[a.name] = case arg_value
|
26
|
+
when GraphQL::Language::Nodes::AbstractNode
|
27
|
+
arg_value.to_query_string
|
28
|
+
else
|
29
|
+
GraphQL::Language.serialize(arg_value)
|
30
|
+
end
|
31
|
+
memo
|
26
32
|
end
|
27
|
-
|
33
|
+
else
|
34
|
+
NO_ARGS
|
28
35
|
end
|
29
36
|
end
|
30
37
|
args.uniq!
|
@@ -102,7 +102,17 @@ module GraphQL
|
|
102
102
|
def follow_spreads(node, parent_variables, spreads_for_context, fragment_definitions, visited_fragments)
|
103
103
|
spreads = spreads_for_context[node] - visited_fragments
|
104
104
|
spreads.each do |spread_name|
|
105
|
-
def_node
|
105
|
+
def_node = nil
|
106
|
+
variables = nil
|
107
|
+
# Implement `.find` by hand to avoid Ruby's internal allocations
|
108
|
+
fragment_definitions.each do |frag_def_node, vars|
|
109
|
+
if frag_def_node.name == spread_name
|
110
|
+
def_node = frag_def_node
|
111
|
+
variables = vars
|
112
|
+
break
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
106
116
|
next if !def_node
|
107
117
|
visited_fragments << spread_name
|
108
118
|
variables.each do |name, child_usage|
|
@@ -12,7 +12,7 @@ module GraphQL
|
|
12
12
|
# It also provides limited access to the {TypeStack} instance,
|
13
13
|
# which tracks state as you climb in and out of different fields.
|
14
14
|
class ValidationContext
|
15
|
-
extend
|
15
|
+
extend Forwardable
|
16
16
|
|
17
17
|
attr_reader :query, :schema,
|
18
18
|
:document, :errors, :visitor,
|