graphql 1.9.18 → 1.13.24
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/core.rb +21 -10
- data/lib/generators/graphql/enum_generator.rb +4 -10
- data/lib/generators/graphql/field_extractor.rb +31 -0
- data/lib/generators/graphql/input_generator.rb +50 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
- data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +2 -0
- data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +44 -7
- data/lib/generators/graphql/interface_generator.rb +7 -7
- data/lib/generators/graphql/loader_generator.rb +1 -0
- data/lib/generators/graphql/mutation_create_generator.rb +22 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
- data/lib/generators/graphql/mutation_generator.rb +6 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +28 -12
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +63 -0
- data/lib/generators/graphql/relay_generator.rb +21 -0
- data/lib/generators/graphql/scalar_generator.rb +4 -2
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +8 -0
- data/lib/generators/graphql/templates/base_edge.erb +8 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/enum.erb +7 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +16 -12
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +6 -2
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +3 -1
- data/lib/generators/graphql/templates/mutation_create.erb +20 -0
- data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
- data/lib/generators/graphql/templates/mutation_update.erb +21 -0
- data/lib/generators/graphql/templates/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +7 -3
- data/lib/generators/graphql/templates/query_type.erb +3 -3
- data/lib/generators/graphql/templates/scalar.erb +5 -1
- data/lib/generators/graphql/templates/schema.erb +22 -27
- data/lib/generators/graphql/templates/union.erb +6 -2
- data/lib/generators/graphql/type_generator.rb +47 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/analyze_query.rb +7 -0
- data/lib/graphql/analysis/ast/field_usage.rb +29 -2
- data/lib/graphql/analysis/ast/query_complexity.rb +174 -67
- data/lib/graphql/analysis/ast/visitor.rb +16 -7
- data/lib/graphql/analysis/ast.rb +21 -11
- data/lib/graphql/argument.rb +8 -36
- data/lib/graphql/backtrace/inspect_result.rb +0 -1
- data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
- data/lib/graphql/backtrace/table.rb +44 -5
- data/lib/graphql/backtrace/traced_error.rb +0 -1
- data/lib/graphql/backtrace/tracer.rb +40 -9
- data/lib/graphql/backtrace.rb +28 -19
- data/lib/graphql/backwards_compatibility.rb +2 -1
- data/lib/graphql/base_type.rb +10 -4
- data/lib/graphql/boolean_type.rb +1 -1
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
- data/lib/graphql/compatibility/execution_specification.rb +1 -0
- data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
- data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
- data/lib/graphql/dataloader/null_dataloader.rb +22 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +155 -0
- data/lib/graphql/dataloader.rb +308 -0
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/define/assign_enum_value.rb +1 -1
- data/lib/graphql/define/assign_global_id_field.rb +2 -2
- data/lib/graphql/define/assign_object_field.rb +1 -1
- data/lib/graphql/define/defined_object_proxy.rb +5 -8
- data/lib/graphql/define/instance_definable.rb +60 -110
- data/lib/graphql/define/type_definer.rb +5 -5
- data/lib/graphql/deprecated_dsl.rb +18 -5
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/directive/deprecated_directive.rb +1 -12
- data/lib/graphql/directive/include_directive.rb +1 -1
- data/lib/graphql/directive/skip_directive.rb +1 -1
- data/lib/graphql/directive.rb +9 -6
- data/lib/graphql/enum_type.rb +14 -74
- data/lib/graphql/execution/directive_checks.rb +2 -2
- data/lib/graphql/execution/errors.rb +110 -8
- data/lib/graphql/execution/execute.rb +8 -1
- data/lib/graphql/execution/instrumentation.rb +1 -1
- data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
- data/lib/graphql/execution/interpreter/arguments.rb +88 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
- data/lib/graphql/execution/interpreter/resolve.rb +37 -25
- data/lib/graphql/execution/interpreter/runtime.rb +721 -386
- data/lib/graphql/execution/interpreter.rb +42 -19
- data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
- data/lib/graphql/execution/lazy.rb +5 -1
- data/lib/graphql/execution/lookahead.rb +39 -114
- data/lib/graphql/execution/multiplex.rb +50 -25
- data/lib/graphql/field.rb +15 -119
- data/lib/graphql/filter.rb +1 -1
- data/lib/graphql/float_type.rb +1 -1
- data/lib/graphql/function.rb +5 -30
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/input_object_type.rb +9 -25
- data/lib/graphql/int_type.rb +1 -1
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/interface_type.rb +10 -24
- data/lib/graphql/internal_representation/document.rb +2 -2
- data/lib/graphql/internal_representation/rewrite.rb +1 -1
- data/lib/graphql/internal_representation/scope.rb +2 -2
- data/lib/graphql/internal_representation/visit.rb +2 -2
- data/lib/graphql/introspection/base_object.rb +2 -5
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +12 -6
- data/lib/graphql/introspection/entry_points.rb +9 -9
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +9 -5
- data/lib/graphql/introspection/input_value_type.rb +41 -11
- data/lib/graphql/introspection/introspection_query.rb +6 -92
- data/lib/graphql/introspection/schema_type.rb +12 -12
- data/lib/graphql/introspection/type_type.rb +27 -17
- data/lib/graphql/introspection.rb +99 -0
- data/lib/graphql/invalid_null_error.rb +18 -0
- data/lib/graphql/language/block_string.rb +20 -5
- data/lib/graphql/language/cache.rb +37 -0
- data/lib/graphql/language/definition_slice.rb +21 -10
- data/lib/graphql/language/document_from_schema_definition.rb +116 -63
- data/lib/graphql/language/lexer.rb +53 -27
- data/lib/graphql/language/lexer.rl +5 -3
- data/lib/graphql/language/nodes.rb +67 -93
- data/lib/graphql/language/parser.rb +929 -896
- data/lib/graphql/language/parser.y +125 -102
- data/lib/graphql/language/printer.rb +11 -2
- data/lib/graphql/language/sanitized_printer.rb +222 -0
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/language/visitor.rb +2 -2
- data/lib/graphql/language.rb +3 -1
- data/lib/graphql/name_validator.rb +2 -7
- data/lib/graphql/non_null_type.rb +0 -10
- data/lib/graphql/object_type.rb +47 -58
- data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
- data/lib/graphql/pagination/array_connection.rb +77 -0
- data/lib/graphql/pagination/connection.rb +226 -0
- data/lib/graphql/pagination/connections.rb +160 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +226 -0
- data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
- data/lib/graphql/pagination.rb +6 -0
- data/lib/graphql/parse_error.rb +0 -1
- data/lib/graphql/query/arguments.rb +6 -4
- data/lib/graphql/query/arguments_cache.rb +1 -2
- data/lib/graphql/query/context.rb +52 -7
- data/lib/graphql/query/executor.rb +0 -1
- data/lib/graphql/query/fingerprint.rb +26 -0
- data/lib/graphql/query/input_validation_result.rb +32 -6
- data/lib/graphql/query/literal_input.rb +31 -11
- data/lib/graphql/query/null_context.rb +24 -8
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
- data/lib/graphql/query/serial_execution.rb +1 -0
- data/lib/graphql/query/validation_pipeline.rb +6 -4
- data/lib/graphql/query/variable_validation_error.rb +3 -3
- data/lib/graphql/query/variables.rb +50 -10
- data/lib/graphql/query.rb +77 -18
- data/lib/graphql/railtie.rb +9 -1
- data/lib/graphql/rake_task/validate.rb +3 -0
- data/lib/graphql/rake_task.rb +12 -9
- data/lib/graphql/relay/array_connection.rb +10 -12
- data/lib/graphql/relay/base_connection.rb +30 -13
- data/lib/graphql/relay/connection_instrumentation.rb +4 -4
- data/lib/graphql/relay/connection_type.rb +18 -4
- data/lib/graphql/relay/edge_type.rb +1 -0
- data/lib/graphql/relay/edges_instrumentation.rb +1 -2
- data/lib/graphql/relay/global_id_resolve.rb +1 -2
- data/lib/graphql/relay/mutation.rb +3 -87
- data/lib/graphql/relay/node.rb +3 -0
- data/lib/graphql/relay/page_info.rb +1 -1
- data/lib/graphql/relay/range_add.rb +27 -9
- data/lib/graphql/relay/relation_connection.rb +8 -10
- data/lib/graphql/relay/type_extensions.rb +2 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/scalar_type.rb +18 -60
- data/lib/graphql/schema/addition.rb +247 -0
- data/lib/graphql/schema/argument.rb +274 -18
- data/lib/graphql/schema/base_64_encoder.rb +2 -0
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
- data/lib/graphql/schema/build_from_definition.rb +320 -219
- data/lib/graphql/schema/built_in_types.rb +5 -5
- data/lib/graphql/schema/default_type_error.rb +2 -0
- data/lib/graphql/schema/directive/deprecated.rb +18 -0
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +57 -0
- data/lib/graphql/schema/directive/include.rb +2 -2
- data/lib/graphql/schema/directive/skip.rb +2 -2
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +130 -6
- data/lib/graphql/schema/enum.rb +121 -12
- data/lib/graphql/schema/enum_value.rb +24 -7
- data/lib/graphql/schema/field/connection_extension.rb +46 -20
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +465 -181
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/find_inherited_value.rb +17 -1
- data/lib/graphql/schema/finder.rb +16 -14
- data/lib/graphql/schema/input_object.rb +172 -37
- data/lib/graphql/schema/interface.rb +39 -25
- data/lib/graphql/schema/introspection_system.rb +106 -38
- data/lib/graphql/schema/late_bound_type.rb +3 -2
- data/lib/graphql/schema/list.rb +65 -1
- data/lib/graphql/schema/loader.rb +145 -102
- data/lib/graphql/schema/member/accepts_definition.rb +15 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +34 -28
- data/lib/graphql/schema/member/build_type.rb +19 -8
- data/lib/graphql/schema/member/cached_graphql_definition.rb +34 -2
- data/lib/graphql/schema/member/has_arguments.rb +206 -13
- data/lib/graphql/schema/member/has_ast_node.rb +20 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
- data/lib/graphql/schema/member/has_directives.rb +98 -0
- data/lib/graphql/schema/member/has_fields.rb +97 -32
- data/lib/graphql/schema/member/has_interfaces.rb +100 -0
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
- data/lib/graphql/schema/member/has_validators.rb +31 -0
- data/lib/graphql/schema/member/instrumentation.rb +0 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/member.rb +11 -0
- data/lib/graphql/schema/middleware_chain.rb +1 -1
- data/lib/graphql/schema/mutation.rb +4 -0
- data/lib/graphql/schema/non_null.rb +37 -1
- data/lib/graphql/schema/object.rb +51 -38
- data/lib/graphql/schema/possible_types.rb +9 -4
- data/lib/graphql/schema/printer.rb +16 -35
- data/lib/graphql/schema/relay_classic_mutation.rb +40 -4
- data/lib/graphql/schema/resolver/has_payload_type.rb +34 -4
- data/lib/graphql/schema/resolver.rb +133 -79
- data/lib/graphql/schema/scalar.rb +43 -3
- data/lib/graphql/schema/subscription.rb +57 -21
- data/lib/graphql/schema/timeout.rb +29 -15
- data/lib/graphql/schema/timeout_middleware.rb +3 -1
- data/lib/graphql/schema/traversal.rb +2 -2
- data/lib/graphql/schema/type_expression.rb +21 -13
- data/lib/graphql/schema/type_membership.rb +19 -5
- data/lib/graphql/schema/union.rb +44 -3
- data/lib/graphql/schema/unique_within_type.rb +1 -2
- data/lib/graphql/schema/validation.rb +14 -4
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
- data/lib/graphql/schema/validator/format_validator.rb +48 -0
- data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
- data/lib/graphql/schema/validator/length_validator.rb +59 -0
- data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
- data/lib/graphql/schema/validator/required_validator.rb +82 -0
- data/lib/graphql/schema/validator.rb +171 -0
- data/lib/graphql/schema/warden.rb +193 -34
- data/lib/graphql/schema.rb +882 -247
- data/lib/graphql/static_validation/all_rules.rb +2 -0
- data/lib/graphql/static_validation/base_visitor.rb +17 -10
- data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +51 -26
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +45 -83
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +94 -51
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
- data/lib/graphql/static_validation/type_stack.rb +2 -2
- data/lib/graphql/static_validation/validation_context.rb +13 -3
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +43 -9
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/string_type.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +123 -22
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
- data/lib/graphql/subscriptions/event.rb +84 -30
- data/lib/graphql/subscriptions/instrumentation.rb +10 -6
- data/lib/graphql/subscriptions/serialize.rb +53 -6
- data/lib/graphql/subscriptions/subscription_root.rb +15 -5
- data/lib/graphql/subscriptions.rb +117 -49
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
- data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +32 -15
- data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_tracing.rb +66 -10
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
- data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
- data/lib/graphql/tracing/scout_tracing.rb +19 -0
- data/lib/graphql/tracing/skylight_tracing.rb +9 -1
- data/lib/graphql/tracing/statsd_tracing.rb +42 -0
- data/lib/graphql/tracing.rb +15 -35
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +10 -3
- data/lib/graphql/types/iso_8601_date.rb +16 -8
- data/lib/graphql/types/iso_8601_date_time.rb +32 -10
- data/lib/graphql/types/relay/base_connection.rb +6 -88
- data/lib/graphql/types/relay/base_edge.rb +2 -34
- data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
- data/lib/graphql/types/relay/default_relay.rb +31 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
- data/lib/graphql/types/relay/has_node_field.rb +41 -0
- data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
- data/lib/graphql/types/relay/node.rb +2 -4
- data/lib/graphql/types/relay/node_behaviors.rb +15 -0
- data/lib/graphql/types/relay/node_field.rb +3 -22
- data/lib/graphql/types/relay/nodes_field.rb +16 -18
- data/lib/graphql/types/relay/page_info.rb +2 -14
- data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
- data/lib/graphql/types/relay.rb +11 -3
- data/lib/graphql/types/string.rb +8 -2
- data/lib/graphql/unauthorized_error.rb +2 -2
- data/lib/graphql/union_type.rb +5 -25
- data/lib/graphql/unresolved_type_error.rb +2 -2
- data/lib/graphql/upgrader/member.rb +1 -0
- data/lib/graphql/upgrader/schema.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +87 -31
- data/readme.md +3 -6
- metadata +126 -124
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
- data/lib/graphql/literal_validation_error.rb +0 -6
- data/lib/graphql/types/relay/base_field.rb +0 -22
- data/lib/graphql/types/relay/base_interface.rb +0 -29
- data/lib/graphql/types/relay/base_object.rb +0 -26
data/lib/graphql/schema.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
require "graphql/schema/addition"
|
|
2
3
|
require "graphql/schema/base_64_encoder"
|
|
3
4
|
require "graphql/schema/catchall_middleware"
|
|
4
5
|
require "graphql/schema/default_parse_error"
|
|
@@ -21,6 +22,7 @@ require "graphql/schema/validation"
|
|
|
21
22
|
require "graphql/schema/warden"
|
|
22
23
|
require "graphql/schema/build_from_definition"
|
|
23
24
|
|
|
25
|
+
require "graphql/schema/validator"
|
|
24
26
|
require "graphql/schema/member"
|
|
25
27
|
require "graphql/schema/wrapper"
|
|
26
28
|
require "graphql/schema/list"
|
|
@@ -36,9 +38,11 @@ require "graphql/schema/scalar"
|
|
|
36
38
|
require "graphql/schema/object"
|
|
37
39
|
require "graphql/schema/union"
|
|
38
40
|
require "graphql/schema/directive"
|
|
41
|
+
require "graphql/schema/directive/deprecated"
|
|
39
42
|
require "graphql/schema/directive/include"
|
|
40
43
|
require "graphql/schema/directive/skip"
|
|
41
44
|
require "graphql/schema/directive/feature"
|
|
45
|
+
require "graphql/schema/directive/flagged"
|
|
42
46
|
require "graphql/schema/directive/transform"
|
|
43
47
|
require "graphql/schema/type_membership"
|
|
44
48
|
|
|
@@ -55,7 +59,6 @@ module GraphQL
|
|
|
55
59
|
# - types for exposing your application
|
|
56
60
|
# - query analyzers for assessing incoming queries (including max depth & max complexity restrictions)
|
|
57
61
|
# - execution strategies for running incoming queries
|
|
58
|
-
# - middleware for interacting with execution
|
|
59
62
|
#
|
|
60
63
|
# Schemas start with root types, {Schema#query}, {Schema#mutation} and {Schema#subscription}.
|
|
61
64
|
# The schema will traverse the tree of fields & types, using those as starting points.
|
|
@@ -67,14 +70,10 @@ module GraphQL
|
|
|
67
70
|
# Schemas can specify how queries should be executed against them.
|
|
68
71
|
# `query_execution_strategy`, `mutation_execution_strategy` and `subscription_execution_strategy`
|
|
69
72
|
# each apply to corresponding root types.
|
|
70
|
-
#
|
|
71
|
-
# A schema accepts a `Relay::GlobalNodeIdentification` instance for use with Relay IDs.
|
|
72
|
-
#
|
|
73
|
+
# #
|
|
73
74
|
# @example defining a schema
|
|
74
|
-
# MySchema
|
|
75
|
+
# class MySchema < GraphQL::Schema
|
|
75
76
|
# query QueryType
|
|
76
|
-
# middleware PermissionMiddleware
|
|
77
|
-
# rescue_from(ActiveRecord::RecordNotFound) { "Not found" }
|
|
78
77
|
# # If types are only connected by way of interfaces, they must be added here
|
|
79
78
|
# orphan_types ImageType, AudioType
|
|
80
79
|
# end
|
|
@@ -82,12 +81,89 @@ module GraphQL
|
|
|
82
81
|
class Schema
|
|
83
82
|
extend Forwardable
|
|
84
83
|
extend GraphQL::Schema::Member::AcceptsDefinition
|
|
84
|
+
extend GraphQL::Schema::Member::HasAstNode
|
|
85
85
|
include GraphQL::Define::InstanceDefinable
|
|
86
|
+
extend GraphQL::Define::InstanceDefinable::DeprecatedDefine
|
|
86
87
|
extend GraphQL::Schema::FindInheritedValue
|
|
87
88
|
|
|
88
|
-
|
|
89
|
+
class DuplicateTypeNamesError < GraphQL::Error
|
|
90
|
+
def initialize(type_name:, first_definition:, second_definition:, path:)
|
|
91
|
+
super("Multiple definitions for `#{type_name}`. Previously found #{first_definition.inspect} (#{first_definition.class}), then found #{second_definition.inspect} (#{second_definition.class}) at #{path.join(".")}")
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
class DuplicateNamesError < GraphQL::Error; end
|
|
96
|
+
|
|
97
|
+
class UnresolvedLateBoundTypeError < GraphQL::Error
|
|
98
|
+
attr_reader :type
|
|
99
|
+
def initialize(type:)
|
|
100
|
+
@type = type
|
|
101
|
+
super("Late bound type was never found: #{type.inspect}")
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
module LazyHandlingMethods
|
|
106
|
+
# Call the given block at the right time, either:
|
|
107
|
+
# - Right away, if `value` is not registered with `lazy_resolve`
|
|
108
|
+
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
|
109
|
+
# @api private
|
|
110
|
+
def after_lazy(value, &block)
|
|
111
|
+
if lazy?(value)
|
|
112
|
+
GraphQL::Execution::Lazy.new do
|
|
113
|
+
result = sync_lazy(value)
|
|
114
|
+
# The returned result might also be lazy, so check it, too
|
|
115
|
+
after_lazy(result, &block)
|
|
116
|
+
end
|
|
117
|
+
else
|
|
118
|
+
yield(value) if block_given?
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Override this method to handle lazy objects in a custom way.
|
|
123
|
+
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
|
124
|
+
# @return [Object] A GraphQL-ready (non-lazy) object
|
|
125
|
+
# @api private
|
|
126
|
+
def sync_lazy(value)
|
|
127
|
+
lazy_method = lazy_method_name(value)
|
|
128
|
+
if lazy_method
|
|
129
|
+
synced_value = value.public_send(lazy_method)
|
|
130
|
+
sync_lazy(synced_value)
|
|
131
|
+
else
|
|
132
|
+
value
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
|
|
137
|
+
def lazy_method_name(obj)
|
|
138
|
+
lazy_methods.get(obj)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# @return [Boolean] True if this object should be lazily resolved
|
|
142
|
+
def lazy?(obj)
|
|
143
|
+
!!lazy_method_name(obj)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Return a lazy if any of `maybe_lazies` are lazy,
|
|
147
|
+
# otherwise, call the block eagerly and return the result.
|
|
148
|
+
# @param maybe_lazies [Array]
|
|
149
|
+
# @api private
|
|
150
|
+
def after_any_lazies(maybe_lazies)
|
|
151
|
+
if maybe_lazies.any? { |l| lazy?(l) }
|
|
152
|
+
GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
|
|
153
|
+
yield result
|
|
154
|
+
end
|
|
155
|
+
else
|
|
156
|
+
yield maybe_lazies
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
include LazyHandlingMethods
|
|
162
|
+
extend LazyHandlingMethods
|
|
163
|
+
|
|
164
|
+
deprecated_accepts_definitions \
|
|
89
165
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
|
90
|
-
:max_depth, :max_complexity, :default_max_page_size,
|
|
166
|
+
:validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
|
|
91
167
|
:orphan_types, :resolve_type, :type_error, :parse_error,
|
|
92
168
|
:error_bubbling,
|
|
93
169
|
:raise_definition_error,
|
|
@@ -101,7 +177,7 @@ module GraphQL
|
|
|
101
177
|
disable_introspection_entry_points: ->(schema) { schema.disable_introspection_entry_points = true },
|
|
102
178
|
disable_schema_introspection_entry_point: ->(schema) { schema.disable_schema_introspection_entry_point = true },
|
|
103
179
|
disable_type_introspection_entry_point: ->(schema) { schema.disable_type_introspection_entry_point = true },
|
|
104
|
-
directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.
|
|
180
|
+
directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.graphql_name] = d; m } },
|
|
105
181
|
directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
|
|
106
182
|
instrument: ->(schema, type, instrumenter, after_built_ins: false) {
|
|
107
183
|
if type == :field && after_built_ins
|
|
@@ -111,7 +187,7 @@ module GraphQL
|
|
|
111
187
|
},
|
|
112
188
|
query_analyzer: ->(schema, analyzer) {
|
|
113
189
|
if analyzer == GraphQL::Authorization::Analyzer
|
|
114
|
-
warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
|
190
|
+
GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
|
115
191
|
end
|
|
116
192
|
schema.query_analyzers << analyzer
|
|
117
193
|
},
|
|
@@ -126,7 +202,7 @@ module GraphQL
|
|
|
126
202
|
attr_accessor \
|
|
127
203
|
:query, :mutation, :subscription,
|
|
128
204
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
|
129
|
-
:max_depth, :max_complexity, :default_max_page_size,
|
|
205
|
+
:validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
|
|
130
206
|
:orphan_types, :directives,
|
|
131
207
|
:query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
|
|
132
208
|
:cursor_encoder,
|
|
@@ -156,12 +232,24 @@ module GraphQL
|
|
|
156
232
|
# [Boolean] True if this object disables the introspection entry point fields
|
|
157
233
|
attr_accessor :disable_introspection_entry_points
|
|
158
234
|
|
|
235
|
+
def disable_introspection_entry_points?
|
|
236
|
+
!!@disable_introspection_entry_points
|
|
237
|
+
end
|
|
238
|
+
|
|
159
239
|
# [Boolean] True if this object disables the __schema introspection entry point field
|
|
160
240
|
attr_accessor :disable_schema_introspection_entry_point
|
|
161
241
|
|
|
242
|
+
def disable_schema_introspection_entry_point?
|
|
243
|
+
!!@disable_schema_introspection_entry_point
|
|
244
|
+
end
|
|
245
|
+
|
|
162
246
|
# [Boolean] True if this object disables the __type introspection entry point field
|
|
163
247
|
attr_accessor :disable_type_introspection_entry_point
|
|
164
248
|
|
|
249
|
+
def disable_type_introspection_entry_point?
|
|
250
|
+
!!@disable_type_introspection_entry_point
|
|
251
|
+
end
|
|
252
|
+
|
|
165
253
|
class << self
|
|
166
254
|
attr_writer :default_execution_strategy
|
|
167
255
|
end
|
|
@@ -175,8 +263,6 @@ module GraphQL
|
|
|
175
263
|
attr_reader :tracers
|
|
176
264
|
|
|
177
265
|
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"].freeze
|
|
178
|
-
EMPTY_ARRAY = [].freeze
|
|
179
|
-
EMPTY_HASH = {}.freeze
|
|
180
266
|
|
|
181
267
|
attr_reader :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
|
|
182
268
|
|
|
@@ -184,7 +270,10 @@ module GraphQL
|
|
|
184
270
|
@tracers = []
|
|
185
271
|
@definition_error = nil
|
|
186
272
|
@orphan_types = []
|
|
187
|
-
@directives =
|
|
273
|
+
@directives = {}
|
|
274
|
+
self.class.default_directives.each do |name, dir|
|
|
275
|
+
@directives[name] = dir.graphql_definition
|
|
276
|
+
end
|
|
188
277
|
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
|
189
278
|
@middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
|
190
279
|
@query_analyzers = []
|
|
@@ -198,11 +287,11 @@ module GraphQL
|
|
|
198
287
|
@lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
|
|
199
288
|
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
|
200
289
|
@cursor_encoder = Base64Encoder
|
|
201
|
-
#
|
|
290
|
+
# For schema instances, default to legacy runtime modules
|
|
202
291
|
@analysis_engine = GraphQL::Analysis
|
|
203
|
-
@query_execution_strategy =
|
|
204
|
-
@mutation_execution_strategy =
|
|
205
|
-
@subscription_execution_strategy =
|
|
292
|
+
@query_execution_strategy = GraphQL::Execution::Execute
|
|
293
|
+
@mutation_execution_strategy = GraphQL::Execution::Execute
|
|
294
|
+
@subscription_execution_strategy = GraphQL::Execution::Execute
|
|
206
295
|
@default_mask = GraphQL::Schema::NullMask
|
|
207
296
|
@rebuilding_artifacts = false
|
|
208
297
|
@context_class = GraphQL::Query::Context
|
|
@@ -217,12 +306,11 @@ module GraphQL
|
|
|
217
306
|
|
|
218
307
|
# @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
|
|
219
308
|
def interpreter?
|
|
220
|
-
|
|
309
|
+
query_execution_strategy == GraphQL::Execution::Interpreter &&
|
|
310
|
+
mutation_execution_strategy == GraphQL::Execution::Interpreter &&
|
|
311
|
+
subscription_execution_strategy == GraphQL::Execution::Interpreter
|
|
221
312
|
end
|
|
222
313
|
|
|
223
|
-
# @api private
|
|
224
|
-
attr_writer :interpreter
|
|
225
|
-
|
|
226
314
|
def inspect
|
|
227
315
|
"#<#{self.class.name} ...>"
|
|
228
316
|
end
|
|
@@ -270,24 +358,7 @@ module GraphQL
|
|
|
270
358
|
# For forwards-compatibility with Schema classes
|
|
271
359
|
alias :graphql_definition :itself
|
|
272
360
|
|
|
273
|
-
|
|
274
|
-
# @param string_or_document [String, GraphQL::Language::Nodes::Document]
|
|
275
|
-
# @return [Array<GraphQL::StaticValidation::Error >]
|
|
276
|
-
def validate(string_or_document, rules: nil, context: nil)
|
|
277
|
-
doc = if string_or_document.is_a?(String)
|
|
278
|
-
GraphQL.parse(string_or_document)
|
|
279
|
-
else
|
|
280
|
-
string_or_document
|
|
281
|
-
end
|
|
282
|
-
query = GraphQL::Query.new(self, document: doc, context: context)
|
|
283
|
-
validator_opts = { schema: self }
|
|
284
|
-
rules && (validator_opts[:rules] = rules)
|
|
285
|
-
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
|
286
|
-
res = validator.validate(query)
|
|
287
|
-
res[:errors]
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
def define(**kwargs, &block)
|
|
361
|
+
def deprecated_define(**kwargs, &block)
|
|
291
362
|
super
|
|
292
363
|
ensure_defined
|
|
293
364
|
# Assert that all necessary configs are present:
|
|
@@ -335,6 +406,10 @@ module GraphQL
|
|
|
335
406
|
end
|
|
336
407
|
end
|
|
337
408
|
|
|
409
|
+
def get_type(type_name)
|
|
410
|
+
@types[type_name]
|
|
411
|
+
end
|
|
412
|
+
|
|
338
413
|
# @api private
|
|
339
414
|
def introspection_system
|
|
340
415
|
@introspection_system ||= begin
|
|
@@ -346,9 +421,13 @@ module GraphQL
|
|
|
346
421
|
# Returns a list of Arguments and Fields referencing a certain type
|
|
347
422
|
# @param type_name [String]
|
|
348
423
|
# @return [Hash]
|
|
349
|
-
def references_to(type_name)
|
|
424
|
+
def references_to(type_name = nil)
|
|
350
425
|
rebuild_artifacts unless defined?(@type_reference_map)
|
|
351
|
-
|
|
426
|
+
if type_name
|
|
427
|
+
@type_reference_map.fetch(type_name, [])
|
|
428
|
+
else
|
|
429
|
+
@type_reference_map
|
|
430
|
+
end
|
|
352
431
|
end
|
|
353
432
|
|
|
354
433
|
# Returns a list of Union types in which a type is a member
|
|
@@ -423,11 +502,11 @@ module GraphQL
|
|
|
423
502
|
# @param field_name [String]
|
|
424
503
|
# @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
|
|
425
504
|
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
|
426
|
-
def get_field(parent_type, field_name)
|
|
505
|
+
def get_field(parent_type, field_name, _context = GraphQL::Query::NullContext)
|
|
427
506
|
with_definition_error_check do
|
|
428
507
|
parent_type_name = case parent_type
|
|
429
|
-
when GraphQL::BaseType
|
|
430
|
-
parent_type.
|
|
508
|
+
when GraphQL::BaseType, Class, Module
|
|
509
|
+
parent_type.graphql_name
|
|
431
510
|
when String
|
|
432
511
|
parent_type
|
|
433
512
|
else
|
|
@@ -453,8 +532,8 @@ module GraphQL
|
|
|
453
532
|
@instrumented_field_map[type.graphql_name]
|
|
454
533
|
end
|
|
455
534
|
|
|
456
|
-
def type_from_ast(ast_node)
|
|
457
|
-
GraphQL::Schema::TypeExpression.build_type(self
|
|
535
|
+
def type_from_ast(ast_node, context:)
|
|
536
|
+
GraphQL::Schema::TypeExpression.build_type(self, ast_node)
|
|
458
537
|
end
|
|
459
538
|
|
|
460
539
|
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
|
@@ -462,11 +541,20 @@ module GraphQL
|
|
|
462
541
|
# @param context [GraphQL::Query::Context] The context for the current query
|
|
463
542
|
# @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
|
|
464
543
|
def possible_types(type_defn, context = GraphQL::Query::NullContext)
|
|
465
|
-
|
|
466
|
-
|
|
544
|
+
if context == GraphQL::Query::NullContext
|
|
545
|
+
@possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
|
|
546
|
+
@possible_types.possible_types(type_defn, context)
|
|
547
|
+
else
|
|
548
|
+
# Use the incoming context to cache this instance --
|
|
549
|
+
# if it were cached on the schema, we'd have a memory leak
|
|
550
|
+
# https://github.com/rmosolgo/graphql-ruby/issues/2878
|
|
551
|
+
ns = context.namespace(:possible_types)
|
|
552
|
+
per_query_possible_types = ns[:possible_types] ||= GraphQL::Schema::PossibleTypes.new(self)
|
|
553
|
+
per_query_possible_types.possible_types(type_defn, context)
|
|
554
|
+
end
|
|
467
555
|
end
|
|
468
556
|
|
|
469
|
-
# @see [GraphQL::Schema::Warden]
|
|
557
|
+
# @see [GraphQL::Schema::Warden] Restricted access to root types
|
|
470
558
|
# @return [GraphQL::ObjectType, nil]
|
|
471
559
|
def root_type_for_operation(operation)
|
|
472
560
|
case operation
|
|
@@ -607,9 +695,41 @@ module GraphQL
|
|
|
607
695
|
|
|
608
696
|
# Can't delegate to `class`
|
|
609
697
|
alias :_schema_class :class
|
|
610
|
-
def_delegators :_schema_class, :
|
|
698
|
+
def_delegators :_schema_class, :unauthorized_object, :unauthorized_field, :inaccessible_fields
|
|
611
699
|
def_delegators :_schema_class, :directive
|
|
612
700
|
def_delegators :_schema_class, :error_handler
|
|
701
|
+
def_delegators :_schema_class, :validate
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
# Given this schema member, find the class-based definition object
|
|
705
|
+
# whose `method_name` should be treated as an application hook
|
|
706
|
+
# @see {.visible?}
|
|
707
|
+
# @see {.accessible?}
|
|
708
|
+
def call_on_type_class(member, method_name, context, default:)
|
|
709
|
+
member = if member.respond_to?(:type_class)
|
|
710
|
+
member.type_class
|
|
711
|
+
else
|
|
712
|
+
member
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
if member.respond_to?(:relay_node_type) && (t = member.relay_node_type)
|
|
716
|
+
member = t
|
|
717
|
+
end
|
|
718
|
+
|
|
719
|
+
if member.respond_to?(method_name)
|
|
720
|
+
member.public_send(method_name, context)
|
|
721
|
+
else
|
|
722
|
+
default
|
|
723
|
+
end
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
def visible?(member, context)
|
|
727
|
+
call_on_type_class(member, :visible?, context, default: true)
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
def accessible?(member, context)
|
|
731
|
+
call_on_type_class(member, :accessible?, context, default: true)
|
|
732
|
+
end
|
|
613
733
|
|
|
614
734
|
# A function to call when {#execute} receives an invalid query string
|
|
615
735
|
#
|
|
@@ -655,30 +775,30 @@ module GraphQL
|
|
|
655
775
|
# @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
|
|
656
776
|
# @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
|
|
657
777
|
# @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
|
|
658
|
-
# @
|
|
659
|
-
|
|
778
|
+
# @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
|
|
779
|
+
# @return [Class] the schema described by `document`
|
|
780
|
+
def self.from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
|
|
660
781
|
# If the file ends in `.graphql`, treat it like a filepath
|
|
661
|
-
|
|
662
|
-
|
|
782
|
+
if definition_or_path.end_with?(".graphql")
|
|
783
|
+
GraphQL::Schema::BuildFromDefinition.from_definition_path(
|
|
784
|
+
definition_or_path,
|
|
785
|
+
default_resolve: default_resolve,
|
|
786
|
+
parser: parser,
|
|
787
|
+
using: using,
|
|
788
|
+
)
|
|
663
789
|
else
|
|
664
|
-
|
|
790
|
+
GraphQL::Schema::BuildFromDefinition.from_definition(
|
|
791
|
+
definition_or_path,
|
|
792
|
+
default_resolve: default_resolve,
|
|
793
|
+
parser: parser,
|
|
794
|
+
using: using,
|
|
795
|
+
)
|
|
665
796
|
end
|
|
666
|
-
GraphQL::Schema::BuildFromDefinition.from_definition(definition, default_resolve: default_resolve, parser: parser)
|
|
667
797
|
end
|
|
668
798
|
|
|
669
799
|
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
|
670
800
|
class InvalidDocumentError < Error; end;
|
|
671
801
|
|
|
672
|
-
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered wtih {#lazy_resolve}.
|
|
673
|
-
def lazy_method_name(obj)
|
|
674
|
-
@lazy_methods.get(obj)
|
|
675
|
-
end
|
|
676
|
-
|
|
677
|
-
# @return [Boolean] True if this object should be lazily resolved
|
|
678
|
-
def lazy?(obj)
|
|
679
|
-
!!lazy_method_name(obj)
|
|
680
|
-
end
|
|
681
|
-
|
|
682
802
|
# Return the GraphQL IDL for the schema
|
|
683
803
|
# @param context [Hash]
|
|
684
804
|
# @param only [<#call(member, ctx)>]
|
|
@@ -703,7 +823,7 @@ module GraphQL
|
|
|
703
823
|
# @param except [<#call(member, ctx)>]
|
|
704
824
|
# @return [Hash] GraphQL result
|
|
705
825
|
def as_json(only: nil, except: nil, context: {})
|
|
706
|
-
execute(Introspection
|
|
826
|
+
execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
|
|
707
827
|
end
|
|
708
828
|
|
|
709
829
|
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
|
@@ -713,65 +833,138 @@ module GraphQL
|
|
|
713
833
|
JSON.pretty_generate(as_json(*args))
|
|
714
834
|
end
|
|
715
835
|
|
|
836
|
+
def new_connections?
|
|
837
|
+
!!connections
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
attr_accessor :connections
|
|
841
|
+
|
|
716
842
|
class << self
|
|
717
843
|
extend Forwardable
|
|
718
844
|
# For compatibility, these methods all:
|
|
719
845
|
# - Cause the Schema instance to be created, if it hasn't been created yet
|
|
720
846
|
# - Delegate to that instance
|
|
721
847
|
# Eventually, the methods will be moved into this class, removing the need for the singleton.
|
|
722
|
-
def_delegators :
|
|
723
|
-
# Schema structure
|
|
724
|
-
:as_json, :to_json, :to_document, :to_definition, :ast_node,
|
|
848
|
+
def_delegators :deprecated_graphql_definition,
|
|
725
849
|
# Execution
|
|
726
|
-
:execute, :multiplex,
|
|
727
|
-
:static_validator, :introspection_system,
|
|
728
|
-
:query_analyzers, :tracers, :instrumenters,
|
|
729
850
|
:execution_strategy_for_operation,
|
|
730
|
-
:validate, :multiplex_analyzers, :lazy?, :lazy_method_name, :after_lazy, :sync_lazy,
|
|
731
851
|
# Configuration
|
|
732
|
-
:
|
|
733
|
-
:max_complexity=, :max_depth=,
|
|
734
|
-
:error_bubbling=,
|
|
735
|
-
:metadata,
|
|
736
|
-
:default_mask,
|
|
737
|
-
:default_filter, :redefine,
|
|
852
|
+
:metadata, :redefine,
|
|
738
853
|
:id_from_object_proc, :object_from_id_proc,
|
|
739
854
|
:id_from_object=, :object_from_id=,
|
|
740
|
-
:remove_handler
|
|
741
|
-
# Members
|
|
742
|
-
:types, :get_fields, :find,
|
|
743
|
-
:root_type_for_operation,
|
|
744
|
-
:subscriptions,
|
|
745
|
-
:union_memberships,
|
|
746
|
-
:get_field, :root_types, :references_to, :type_from_ast,
|
|
747
|
-
:possible_types,
|
|
748
|
-
:disable_introspection_entry_points=,
|
|
749
|
-
:disable_schema_introspection_entry_point=,
|
|
750
|
-
:disable_type_introspection_entry_point=
|
|
855
|
+
:remove_handler
|
|
751
856
|
|
|
752
|
-
def
|
|
753
|
-
|
|
857
|
+
def deprecated_graphql_definition
|
|
858
|
+
graphql_definition(silence_deprecation_warning: true)
|
|
754
859
|
end
|
|
755
860
|
|
|
756
|
-
|
|
757
|
-
|
|
861
|
+
# @return [GraphQL::Subscriptions]
|
|
862
|
+
attr_accessor :subscriptions
|
|
863
|
+
|
|
864
|
+
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
|
865
|
+
# @see {#as_json}
|
|
866
|
+
# @return [String]
|
|
867
|
+
def to_json(**args)
|
|
868
|
+
JSON.pretty_generate(as_json(**args))
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
|
872
|
+
# @param context [Hash]
|
|
873
|
+
# @param only [<#call(member, ctx)>]
|
|
874
|
+
# @param except [<#call(member, ctx)>]
|
|
875
|
+
# @return [Hash] GraphQL result
|
|
876
|
+
def as_json(only: nil, except: nil, context: {})
|
|
877
|
+
execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
|
|
878
|
+
end
|
|
879
|
+
|
|
880
|
+
# Return the GraphQL IDL for the schema
|
|
881
|
+
# @param context [Hash]
|
|
882
|
+
# @param only [<#call(member, ctx)>]
|
|
883
|
+
# @param except [<#call(member, ctx)>]
|
|
884
|
+
# @return [String]
|
|
885
|
+
def to_definition(only: nil, except: nil, context: {})
|
|
886
|
+
GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
|
|
887
|
+
end
|
|
888
|
+
|
|
889
|
+
# Return the GraphQL::Language::Document IDL AST for the schema
|
|
890
|
+
# @return [GraphQL::Language::Document]
|
|
891
|
+
def to_document
|
|
892
|
+
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
|
893
|
+
end
|
|
894
|
+
|
|
895
|
+
# @return [String, nil]
|
|
896
|
+
def description(new_description = nil)
|
|
897
|
+
if new_description
|
|
898
|
+
@description = new_description
|
|
899
|
+
elsif defined?(@description)
|
|
900
|
+
@description
|
|
901
|
+
else
|
|
902
|
+
find_inherited_value(:description, nil)
|
|
903
|
+
end
|
|
904
|
+
end
|
|
905
|
+
|
|
906
|
+
def find(path)
|
|
907
|
+
if !@finder
|
|
908
|
+
@find_cache = {}
|
|
909
|
+
@finder ||= GraphQL::Schema::Finder.new(self)
|
|
910
|
+
end
|
|
911
|
+
@find_cache[path] ||= @finder.find(path)
|
|
912
|
+
end
|
|
913
|
+
|
|
914
|
+
def graphql_definition(silence_deprecation_warning: false)
|
|
915
|
+
@graphql_definition ||= begin
|
|
916
|
+
unless silence_deprecation_warning
|
|
917
|
+
message = "Legacy `.graphql_definition` objects are deprecated and will be removed in GraphQL-Ruby 2.0. Use a class-based definition instead."
|
|
918
|
+
caller_message = "\n\nCalled on #{self.inspect} from:\n #{caller(1, 25).map { |l| " #{l}" }.join("\n")}"
|
|
919
|
+
GraphQL::Deprecation.warn(message + caller_message)
|
|
920
|
+
end
|
|
921
|
+
to_graphql(silence_deprecation_warning: silence_deprecation_warning)
|
|
922
|
+
end
|
|
923
|
+
end
|
|
924
|
+
|
|
925
|
+
def default_filter
|
|
926
|
+
GraphQL::Filter.new(except: default_mask)
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
def default_mask(new_mask = nil)
|
|
930
|
+
if new_mask
|
|
931
|
+
@own_default_mask = new_mask
|
|
932
|
+
else
|
|
933
|
+
@own_default_mask || find_inherited_value(:default_mask, Schema::NullMask)
|
|
934
|
+
end
|
|
935
|
+
end
|
|
936
|
+
|
|
937
|
+
def static_validator
|
|
938
|
+
GraphQL::StaticValidation::Validator.new(schema: self)
|
|
939
|
+
end
|
|
940
|
+
|
|
941
|
+
def use(plugin, **kwargs)
|
|
942
|
+
if kwargs.any?
|
|
943
|
+
plugin.use(self, **kwargs)
|
|
944
|
+
else
|
|
945
|
+
plugin.use(self)
|
|
946
|
+
end
|
|
947
|
+
own_plugins << [plugin, kwargs]
|
|
758
948
|
end
|
|
759
949
|
|
|
760
950
|
def plugins
|
|
761
951
|
find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
|
|
762
952
|
end
|
|
763
953
|
|
|
954
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
|
764
955
|
def to_graphql
|
|
765
956
|
schema_defn = self.new
|
|
766
957
|
schema_defn.raise_definition_error = true
|
|
767
|
-
schema_defn.query = query
|
|
768
|
-
schema_defn.mutation = mutation
|
|
769
|
-
schema_defn.subscription = subscription
|
|
958
|
+
schema_defn.query = query && query.graphql_definition(silence_deprecation_warning: true)
|
|
959
|
+
schema_defn.mutation = mutation && mutation.graphql_definition(silence_deprecation_warning: true)
|
|
960
|
+
schema_defn.subscription = subscription && subscription.graphql_definition(silence_deprecation_warning: true)
|
|
961
|
+
schema_defn.validate_timeout = validate_timeout
|
|
962
|
+
schema_defn.validate_max_errors = validate_max_errors
|
|
770
963
|
schema_defn.max_complexity = max_complexity
|
|
771
964
|
schema_defn.error_bubbling = error_bubbling
|
|
772
965
|
schema_defn.max_depth = max_depth
|
|
773
966
|
schema_defn.default_max_page_size = default_max_page_size
|
|
774
|
-
schema_defn.orphan_types = orphan_types
|
|
967
|
+
schema_defn.orphan_types = orphan_types.map { |t| t.graphql_definition(silence_deprecation_warning: true) }
|
|
775
968
|
schema_defn.disable_introspection_entry_points = disable_introspection_entry_points?
|
|
776
969
|
schema_defn.disable_schema_introspection_entry_point = disable_schema_introspection_entry_point?
|
|
777
970
|
schema_defn.disable_type_introspection_entry_point = disable_type_introspection_entry_point?
|
|
@@ -788,81 +981,319 @@ module GraphQL
|
|
|
788
981
|
schema_defn.cursor_encoder = cursor_encoder
|
|
789
982
|
schema_defn.tracers.concat(tracers)
|
|
790
983
|
schema_defn.query_analyzers.concat(query_analyzers)
|
|
984
|
+
schema_defn.analysis_engine = analysis_engine
|
|
791
985
|
|
|
792
986
|
schema_defn.middleware.concat(all_middleware)
|
|
793
987
|
schema_defn.multiplex_analyzers.concat(multiplex_analyzers)
|
|
794
988
|
schema_defn.query_execution_strategy = query_execution_strategy
|
|
795
989
|
schema_defn.mutation_execution_strategy = mutation_execution_strategy
|
|
796
990
|
schema_defn.subscription_execution_strategy = subscription_execution_strategy
|
|
797
|
-
|
|
991
|
+
schema_defn.default_mask = default_mask
|
|
992
|
+
instrumenters.each do |step, insts|
|
|
798
993
|
insts.each do |inst|
|
|
799
994
|
schema_defn.instrumenters[step] << inst
|
|
800
995
|
end
|
|
801
996
|
end
|
|
802
|
-
|
|
997
|
+
|
|
998
|
+
lazy_methods.each do |lazy_class, value_method|
|
|
803
999
|
schema_defn.lazy_methods.set(lazy_class, value_method)
|
|
804
1000
|
end
|
|
805
|
-
|
|
1001
|
+
|
|
1002
|
+
error_handler.each_rescue do |err_class, handler|
|
|
806
1003
|
schema_defn.rescue_from(err_class, &handler)
|
|
807
1004
|
end
|
|
808
1005
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
schema_defn
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
1006
|
+
schema_defn.subscriptions ||= self.subscriptions
|
|
1007
|
+
|
|
1008
|
+
if !schema_defn.interpreter?
|
|
1009
|
+
schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
|
|
1010
|
+
end
|
|
1011
|
+
|
|
1012
|
+
if new_connections?
|
|
1013
|
+
schema_defn.connections = self.connections
|
|
1014
|
+
end
|
|
1015
|
+
|
|
1016
|
+
schema_defn.send(:rebuild_artifacts)
|
|
1017
|
+
|
|
1018
|
+
schema_defn
|
|
1019
|
+
end
|
|
1020
|
+
|
|
1021
|
+
# Build a map of `{ name => type }` and return it
|
|
1022
|
+
# @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
|
|
1023
|
+
# @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
|
|
1024
|
+
def types(context = GraphQL::Query::NullContext)
|
|
1025
|
+
all_types = non_introspection_types.merge(introspection_system.types)
|
|
1026
|
+
visible_types = {}
|
|
1027
|
+
all_types.each do |k, v|
|
|
1028
|
+
visible_types[k] =if v.is_a?(Array)
|
|
1029
|
+
visible_t = nil
|
|
1030
|
+
v.each do |t|
|
|
1031
|
+
if t.visible?(context)
|
|
1032
|
+
if visible_t.nil?
|
|
1033
|
+
visible_t = t
|
|
1034
|
+
else
|
|
1035
|
+
raise DuplicateNamesError, "Found two visible type definitions for `#{k}`: #{visible_t.inspect}, #{t.inspect}"
|
|
1036
|
+
end
|
|
1037
|
+
end
|
|
1038
|
+
end
|
|
1039
|
+
visible_t
|
|
1040
|
+
else
|
|
1041
|
+
v
|
|
1042
|
+
end
|
|
1043
|
+
end
|
|
1044
|
+
visible_types
|
|
1045
|
+
end
|
|
1046
|
+
|
|
1047
|
+
# @param type_name [String]
|
|
1048
|
+
# @return [Module, nil] A type, or nil if there's no type called `type_name`
|
|
1049
|
+
def get_type(type_name, context = GraphQL::Query::NullContext)
|
|
1050
|
+
local_entry = own_types[type_name]
|
|
1051
|
+
type_defn = case local_entry
|
|
1052
|
+
when nil
|
|
1053
|
+
nil
|
|
1054
|
+
when Array
|
|
1055
|
+
visible_t = nil
|
|
1056
|
+
warden = Warden.from_context(context)
|
|
1057
|
+
local_entry.each do |t|
|
|
1058
|
+
if warden.visible_type?(t, context)
|
|
1059
|
+
if visible_t.nil?
|
|
1060
|
+
visible_t = t
|
|
816
1061
|
else
|
|
817
|
-
|
|
1062
|
+
raise DuplicateNamesError, "Found two visible type definitions for `#{type_name}`: #{visible_t.inspect}, #{t.inspect}"
|
|
818
1063
|
end
|
|
819
1064
|
end
|
|
820
1065
|
end
|
|
1066
|
+
visible_t
|
|
1067
|
+
when Module
|
|
1068
|
+
local_entry
|
|
1069
|
+
else
|
|
1070
|
+
raise "Invariant: unexpected own_types[#{type_name.inspect}]: #{local_entry.inspect}"
|
|
821
1071
|
end
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
1072
|
+
|
|
1073
|
+
type_defn ||
|
|
1074
|
+
introspection_system.types[type_name] || # todo context-specific introspection?
|
|
1075
|
+
(superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
|
|
1076
|
+
end
|
|
1077
|
+
|
|
1078
|
+
# @api private
|
|
1079
|
+
attr_writer :connections
|
|
1080
|
+
|
|
1081
|
+
# @return [GraphQL::Pagination::Connections] if installed
|
|
1082
|
+
def connections
|
|
1083
|
+
if defined?(@connections)
|
|
1084
|
+
@connections
|
|
1085
|
+
else
|
|
1086
|
+
inherited_connections = find_inherited_value(:connections, nil)
|
|
1087
|
+
# This schema is part of an inheritance chain which is using new connections,
|
|
1088
|
+
# make a new instance, so we don't pollute the upstream one.
|
|
1089
|
+
if inherited_connections
|
|
1090
|
+
@connections = Pagination::Connections.new(schema: self)
|
|
1091
|
+
else
|
|
1092
|
+
nil
|
|
1093
|
+
end
|
|
825
1094
|
end
|
|
826
|
-
|
|
1095
|
+
end
|
|
827
1096
|
|
|
828
|
-
|
|
1097
|
+
def new_connections?
|
|
1098
|
+
!!connections
|
|
829
1099
|
end
|
|
830
1100
|
|
|
831
1101
|
def query(new_query_object = nil)
|
|
832
1102
|
if new_query_object
|
|
833
|
-
@query_object
|
|
1103
|
+
if @query_object
|
|
1104
|
+
raise GraphQL::Error, "Second definition of `query(...)` (#{new_query_object.inspect}) is invalid, already configured with #{@query_object.inspect}"
|
|
1105
|
+
else
|
|
1106
|
+
@query_object = new_query_object
|
|
1107
|
+
add_type_and_traverse(new_query_object, root: true)
|
|
1108
|
+
nil
|
|
1109
|
+
end
|
|
834
1110
|
else
|
|
835
|
-
|
|
836
|
-
query_object.respond_to?(:graphql_definition) ? query_object.graphql_definition : query_object
|
|
1111
|
+
@query_object || find_inherited_value(:query)
|
|
837
1112
|
end
|
|
838
1113
|
end
|
|
839
1114
|
|
|
840
1115
|
def mutation(new_mutation_object = nil)
|
|
841
1116
|
if new_mutation_object
|
|
842
|
-
@mutation_object
|
|
1117
|
+
if @mutation_object
|
|
1118
|
+
raise GraphQL::Error, "Second definition of `mutation(...)` (#{new_mutation_object.inspect}) is invalid, already configured with #{@mutation_object.inspect}"
|
|
1119
|
+
else
|
|
1120
|
+
@mutation_object = new_mutation_object
|
|
1121
|
+
add_type_and_traverse(new_mutation_object, root: true)
|
|
1122
|
+
nil
|
|
1123
|
+
end
|
|
843
1124
|
else
|
|
844
|
-
|
|
845
|
-
mutation_object.respond_to?(:graphql_definition) ? mutation_object.graphql_definition : mutation_object
|
|
1125
|
+
@mutation_object || find_inherited_value(:mutation)
|
|
846
1126
|
end
|
|
847
1127
|
end
|
|
848
1128
|
|
|
849
1129
|
def subscription(new_subscription_object = nil)
|
|
850
1130
|
if new_subscription_object
|
|
851
|
-
@subscription_object
|
|
1131
|
+
if @subscription_object
|
|
1132
|
+
raise GraphQL::Error, "Second definition of `subscription(...)` (#{new_subscription_object.inspect}) is invalid, already configured with #{@subscription_object.inspect}"
|
|
1133
|
+
else
|
|
1134
|
+
@subscription_object = new_subscription_object
|
|
1135
|
+
add_subscription_extension_if_necessary
|
|
1136
|
+
add_type_and_traverse(new_subscription_object, root: true)
|
|
1137
|
+
nil
|
|
1138
|
+
end
|
|
1139
|
+
else
|
|
1140
|
+
@subscription_object || find_inherited_value(:subscription)
|
|
1141
|
+
end
|
|
1142
|
+
end
|
|
1143
|
+
|
|
1144
|
+
# @see [GraphQL::Schema::Warden] Restricted access to root types
|
|
1145
|
+
# @return [GraphQL::ObjectType, nil]
|
|
1146
|
+
def root_type_for_operation(operation)
|
|
1147
|
+
case operation
|
|
1148
|
+
when "query"
|
|
1149
|
+
query
|
|
1150
|
+
when "mutation"
|
|
1151
|
+
mutation
|
|
1152
|
+
when "subscription"
|
|
1153
|
+
subscription
|
|
1154
|
+
else
|
|
1155
|
+
raise ArgumentError, "unknown operation type: #{operation}"
|
|
1156
|
+
end
|
|
1157
|
+
end
|
|
1158
|
+
|
|
1159
|
+
def root_types
|
|
1160
|
+
@root_types
|
|
1161
|
+
end
|
|
1162
|
+
|
|
1163
|
+
# @param type [Module] The type definition whose possible types you want to see
|
|
1164
|
+
# @return [Hash<String, Module>] All possible types, if no `type` is given.
|
|
1165
|
+
# @return [Array<Module>] Possible types for `type`, if it's given.
|
|
1166
|
+
def possible_types(type = nil, context = GraphQL::Query::NullContext)
|
|
1167
|
+
if type
|
|
1168
|
+
# TODO duck-typing `.possible_types` would probably be nicer here
|
|
1169
|
+
if type.kind.union?
|
|
1170
|
+
type.possible_types(context: context)
|
|
1171
|
+
else
|
|
1172
|
+
stored_possible_types = own_possible_types[type.graphql_name]
|
|
1173
|
+
visible_possible_types = if stored_possible_types && type.kind.interface?
|
|
1174
|
+
stored_possible_types.select do |possible_type|
|
|
1175
|
+
# Use `.graphql_name` comparison to match legacy vs class-based types.
|
|
1176
|
+
# When we don't need to support legacy `.define` types, use `.include?(type)` instead.
|
|
1177
|
+
possible_type.interfaces(context).any? { |interface| interface.graphql_name == type.graphql_name }
|
|
1178
|
+
end
|
|
1179
|
+
else
|
|
1180
|
+
stored_possible_types
|
|
1181
|
+
end
|
|
1182
|
+
visible_possible_types ||
|
|
1183
|
+
introspection_system.possible_types[type.graphql_name] ||
|
|
1184
|
+
(
|
|
1185
|
+
superclass.respond_to?(:possible_types) ?
|
|
1186
|
+
superclass.possible_types(type, context) :
|
|
1187
|
+
EMPTY_ARRAY
|
|
1188
|
+
)
|
|
1189
|
+
end
|
|
1190
|
+
else
|
|
1191
|
+
find_inherited_value(:possible_types, EMPTY_HASH)
|
|
1192
|
+
.merge(own_possible_types)
|
|
1193
|
+
.merge(introspection_system.possible_types)
|
|
1194
|
+
end
|
|
1195
|
+
end
|
|
1196
|
+
|
|
1197
|
+
def union_memberships(type = nil)
|
|
1198
|
+
if type
|
|
1199
|
+
own_um = own_union_memberships.fetch(type.graphql_name, EMPTY_ARRAY)
|
|
1200
|
+
inherited_um = find_inherited_value(:union_memberships, EMPTY_HASH).fetch(type.graphql_name, EMPTY_ARRAY)
|
|
1201
|
+
own_um + inherited_um
|
|
1202
|
+
else
|
|
1203
|
+
joined_um = own_union_memberships.dup
|
|
1204
|
+
find_inherited_value(:union_memberhips, EMPTY_HASH).each do |k, v|
|
|
1205
|
+
um = joined_um[k] ||= []
|
|
1206
|
+
um.concat(v)
|
|
1207
|
+
end
|
|
1208
|
+
joined_um
|
|
1209
|
+
end
|
|
1210
|
+
end
|
|
1211
|
+
|
|
1212
|
+
# @api private
|
|
1213
|
+
# @see GraphQL::Dataloader
|
|
1214
|
+
def dataloader_class
|
|
1215
|
+
@dataloader_class || GraphQL::Dataloader::NullDataloader
|
|
1216
|
+
end
|
|
1217
|
+
|
|
1218
|
+
attr_writer :dataloader_class
|
|
1219
|
+
|
|
1220
|
+
def references_to(to_type = nil, from: nil)
|
|
1221
|
+
@own_references_to ||= Hash.new { |h, k| h[k] = [] }
|
|
1222
|
+
if to_type
|
|
1223
|
+
if !to_type.is_a?(String)
|
|
1224
|
+
to_type = to_type.graphql_name
|
|
1225
|
+
end
|
|
1226
|
+
|
|
1227
|
+
if from
|
|
1228
|
+
@own_references_to[to_type] << from
|
|
1229
|
+
else
|
|
1230
|
+
own_refs = @own_references_to[to_type]
|
|
1231
|
+
inherited_refs = find_inherited_value(:references_to, EMPTY_HASH)[to_type] || EMPTY_ARRAY
|
|
1232
|
+
own_refs + inherited_refs
|
|
1233
|
+
end
|
|
1234
|
+
else
|
|
1235
|
+
# `@own_references_to` can be quite large for big schemas,
|
|
1236
|
+
# and generally speaking, we won't inherit any values.
|
|
1237
|
+
# So optimize the most common case -- don't create a duplicate Hash.
|
|
1238
|
+
inherited_value = find_inherited_value(:references_to, EMPTY_HASH)
|
|
1239
|
+
if inherited_value.any?
|
|
1240
|
+
inherited_value.merge(@own_references_to)
|
|
1241
|
+
else
|
|
1242
|
+
@own_references_to
|
|
1243
|
+
end
|
|
1244
|
+
end
|
|
1245
|
+
end
|
|
1246
|
+
|
|
1247
|
+
def type_from_ast(ast_node, context: nil)
|
|
1248
|
+
type_owner = context ? context.warden : self
|
|
1249
|
+
GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
|
|
1250
|
+
end
|
|
1251
|
+
|
|
1252
|
+
def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext)
|
|
1253
|
+
parent_type = case type_or_name
|
|
1254
|
+
when LateBoundType
|
|
1255
|
+
get_type(type_or_name.name, context)
|
|
1256
|
+
when String
|
|
1257
|
+
get_type(type_or_name, context)
|
|
1258
|
+
when Module
|
|
1259
|
+
type_or_name
|
|
852
1260
|
else
|
|
853
|
-
|
|
854
|
-
|
|
1261
|
+
raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
|
|
1262
|
+
end
|
|
1263
|
+
|
|
1264
|
+
if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
|
|
1265
|
+
field
|
|
1266
|
+
elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
|
|
1267
|
+
entry_point_field
|
|
1268
|
+
elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
|
|
1269
|
+
dynamic_field
|
|
1270
|
+
else
|
|
1271
|
+
nil
|
|
855
1272
|
end
|
|
856
1273
|
end
|
|
857
1274
|
|
|
1275
|
+
def get_fields(type, context = GraphQL::Query::NullContext)
|
|
1276
|
+
type.fields(context)
|
|
1277
|
+
end
|
|
1278
|
+
|
|
858
1279
|
def introspection(new_introspection_namespace = nil)
|
|
859
1280
|
if new_introspection_namespace
|
|
860
1281
|
@introspection = new_introspection_namespace
|
|
1282
|
+
# reset this cached value:
|
|
1283
|
+
@introspection_system = nil
|
|
861
1284
|
else
|
|
862
1285
|
@introspection || find_inherited_value(:introspection)
|
|
863
1286
|
end
|
|
864
1287
|
end
|
|
865
1288
|
|
|
1289
|
+
def introspection_system
|
|
1290
|
+
if !@introspection_system
|
|
1291
|
+
@introspection_system = Schema::IntrospectionSystem.new(self)
|
|
1292
|
+
@introspection_system.resolve_late_bindings
|
|
1293
|
+
end
|
|
1294
|
+
@introspection_system
|
|
1295
|
+
end
|
|
1296
|
+
|
|
866
1297
|
def cursor_encoder(new_encoder = nil)
|
|
867
1298
|
if new_encoder
|
|
868
1299
|
@cursor_encoder = new_encoder
|
|
@@ -902,14 +1333,77 @@ module GraphQL
|
|
|
902
1333
|
end
|
|
903
1334
|
end
|
|
904
1335
|
|
|
1336
|
+
attr_writer :validate_timeout
|
|
1337
|
+
|
|
1338
|
+
def validate_timeout(new_validate_timeout = nil)
|
|
1339
|
+
if new_validate_timeout
|
|
1340
|
+
@validate_timeout = new_validate_timeout
|
|
1341
|
+
elsif defined?(@validate_timeout)
|
|
1342
|
+
@validate_timeout
|
|
1343
|
+
else
|
|
1344
|
+
find_inherited_value(:validate_timeout)
|
|
1345
|
+
end
|
|
1346
|
+
end
|
|
1347
|
+
|
|
1348
|
+
# Validate a query string according to this schema.
|
|
1349
|
+
# @param string_or_document [String, GraphQL::Language::Nodes::Document]
|
|
1350
|
+
# @return [Array<GraphQL::StaticValidation::Error >]
|
|
1351
|
+
def validate(string_or_document, rules: nil, context: nil)
|
|
1352
|
+
doc = if string_or_document.is_a?(String)
|
|
1353
|
+
GraphQL.parse(string_or_document)
|
|
1354
|
+
else
|
|
1355
|
+
string_or_document
|
|
1356
|
+
end
|
|
1357
|
+
query = GraphQL::Query.new(self, document: doc, context: context)
|
|
1358
|
+
validator_opts = { schema: self }
|
|
1359
|
+
rules && (validator_opts[:rules] = rules)
|
|
1360
|
+
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
|
1361
|
+
res = validator.validate(query, timeout: validate_timeout, max_errors: validate_max_errors)
|
|
1362
|
+
res[:errors]
|
|
1363
|
+
end
|
|
1364
|
+
|
|
1365
|
+
attr_writer :validate_max_errors
|
|
1366
|
+
|
|
1367
|
+
def validate_max_errors(new_validate_max_errors = nil)
|
|
1368
|
+
if new_validate_max_errors
|
|
1369
|
+
@validate_max_errors = new_validate_max_errors
|
|
1370
|
+
elsif defined?(@validate_max_errors)
|
|
1371
|
+
@validate_max_errors
|
|
1372
|
+
else
|
|
1373
|
+
find_inherited_value(:validate_max_errors)
|
|
1374
|
+
end
|
|
1375
|
+
end
|
|
1376
|
+
|
|
1377
|
+
attr_writer :max_complexity
|
|
1378
|
+
|
|
905
1379
|
def max_complexity(max_complexity = nil)
|
|
906
1380
|
if max_complexity
|
|
907
1381
|
@max_complexity = max_complexity
|
|
1382
|
+
elsif defined?(@max_complexity)
|
|
1383
|
+
@max_complexity
|
|
908
1384
|
else
|
|
909
|
-
|
|
1385
|
+
find_inherited_value(:max_complexity)
|
|
910
1386
|
end
|
|
911
1387
|
end
|
|
912
1388
|
|
|
1389
|
+
attr_writer :analysis_engine
|
|
1390
|
+
|
|
1391
|
+
def analysis_engine
|
|
1392
|
+
@analysis_engine || find_inherited_value(:analysis_engine, self.default_analysis_engine)
|
|
1393
|
+
end
|
|
1394
|
+
|
|
1395
|
+
def using_ast_analysis?
|
|
1396
|
+
analysis_engine == GraphQL::Analysis::AST
|
|
1397
|
+
end
|
|
1398
|
+
|
|
1399
|
+
def interpreter?
|
|
1400
|
+
query_execution_strategy == GraphQL::Execution::Interpreter &&
|
|
1401
|
+
mutation_execution_strategy == GraphQL::Execution::Interpreter &&
|
|
1402
|
+
subscription_execution_strategy == GraphQL::Execution::Interpreter
|
|
1403
|
+
end
|
|
1404
|
+
|
|
1405
|
+
attr_writer :interpreter
|
|
1406
|
+
|
|
913
1407
|
def error_bubbling(new_error_bubbling = nil)
|
|
914
1408
|
if !new_error_bubbling.nil?
|
|
915
1409
|
@error_bubbling = new_error_bubbling
|
|
@@ -918,24 +1412,36 @@ module GraphQL
|
|
|
918
1412
|
end
|
|
919
1413
|
end
|
|
920
1414
|
|
|
1415
|
+
attr_writer :error_bubbling
|
|
1416
|
+
|
|
1417
|
+
attr_writer :max_depth
|
|
1418
|
+
|
|
921
1419
|
def max_depth(new_max_depth = nil)
|
|
922
1420
|
if new_max_depth
|
|
923
1421
|
@max_depth = new_max_depth
|
|
1422
|
+
elsif defined?(@max_depth)
|
|
1423
|
+
@max_depth
|
|
924
1424
|
else
|
|
925
|
-
|
|
1425
|
+
find_inherited_value(:max_depth)
|
|
926
1426
|
end
|
|
927
1427
|
end
|
|
928
1428
|
|
|
929
1429
|
def disable_introspection_entry_points
|
|
930
1430
|
@disable_introspection_entry_points = true
|
|
1431
|
+
# TODO: this clears the cache made in `def types`. But this is not a great solution.
|
|
1432
|
+
@introspection_system = nil
|
|
931
1433
|
end
|
|
932
1434
|
|
|
933
1435
|
def disable_schema_introspection_entry_point
|
|
934
1436
|
@disable_schema_introspection_entry_point = true
|
|
1437
|
+
# TODO: this clears the cache made in `def types`. But this is not a great solution.
|
|
1438
|
+
@introspection_system = nil
|
|
935
1439
|
end
|
|
936
1440
|
|
|
937
1441
|
def disable_type_introspection_entry_point
|
|
938
1442
|
@disable_type_introspection_entry_point = true
|
|
1443
|
+
# TODO: this clears the cache made in `def types`. But this is not a great solution.
|
|
1444
|
+
@introspection_system = nil
|
|
939
1445
|
end
|
|
940
1446
|
|
|
941
1447
|
def disable_introspection_entry_points?
|
|
@@ -964,6 +1470,8 @@ module GraphQL
|
|
|
964
1470
|
|
|
965
1471
|
def orphan_types(*new_orphan_types)
|
|
966
1472
|
if new_orphan_types.any?
|
|
1473
|
+
new_orphan_types = new_orphan_types.flatten
|
|
1474
|
+
add_type_and_traverse(new_orphan_types, root: false)
|
|
967
1475
|
own_orphan_types.concat(new_orphan_types.flatten)
|
|
968
1476
|
end
|
|
969
1477
|
|
|
@@ -974,7 +1482,15 @@ module GraphQL
|
|
|
974
1482
|
if superclass <= GraphQL::Schema
|
|
975
1483
|
superclass.default_execution_strategy
|
|
976
1484
|
else
|
|
977
|
-
@default_execution_strategy ||= GraphQL::Execution::
|
|
1485
|
+
@default_execution_strategy ||= GraphQL::Execution::Interpreter
|
|
1486
|
+
end
|
|
1487
|
+
end
|
|
1488
|
+
|
|
1489
|
+
def default_analysis_engine
|
|
1490
|
+
if superclass <= GraphQL::Schema
|
|
1491
|
+
superclass.default_analysis_engine
|
|
1492
|
+
else
|
|
1493
|
+
@default_analysis_engine ||= GraphQL::Analysis::AST
|
|
978
1494
|
end
|
|
979
1495
|
end
|
|
980
1496
|
|
|
@@ -988,12 +1504,31 @@ module GraphQL
|
|
|
988
1504
|
|
|
989
1505
|
def rescue_from(*err_classes, &handler_block)
|
|
990
1506
|
err_classes.each do |err_class|
|
|
991
|
-
|
|
1507
|
+
error_handler.rescue_from(err_class, handler_block)
|
|
992
1508
|
end
|
|
993
1509
|
end
|
|
994
1510
|
|
|
995
|
-
|
|
996
|
-
|
|
1511
|
+
# rubocop:disable Lint/DuplicateMethods
|
|
1512
|
+
module ResolveTypeWithType
|
|
1513
|
+
def resolve_type(type, obj, ctx)
|
|
1514
|
+
first_resolved_type, resolved_value = if type.is_a?(Module) && type.respond_to?(:resolve_type)
|
|
1515
|
+
type.resolve_type(obj, ctx)
|
|
1516
|
+
else
|
|
1517
|
+
super
|
|
1518
|
+
end
|
|
1519
|
+
|
|
1520
|
+
after_lazy(first_resolved_type) do |resolved_type|
|
|
1521
|
+
if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind)) || resolved_type.is_a?(GraphQL::BaseType)
|
|
1522
|
+
if resolved_value
|
|
1523
|
+
[resolved_type, resolved_value]
|
|
1524
|
+
else
|
|
1525
|
+
resolved_type
|
|
1526
|
+
end
|
|
1527
|
+
else
|
|
1528
|
+
raise ".resolve_type should return a type definition, but got #{resolved_type.inspect} (#{resolved_type.class}) from `resolve_type(#{type}, #{obj}, #{ctx})`"
|
|
1529
|
+
end
|
|
1530
|
+
end
|
|
1531
|
+
end
|
|
997
1532
|
end
|
|
998
1533
|
|
|
999
1534
|
def resolve_type(type, obj, ctx)
|
|
@@ -1003,6 +1538,15 @@ module GraphQL
|
|
|
1003
1538
|
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
|
|
1004
1539
|
end
|
|
1005
1540
|
end
|
|
1541
|
+
# rubocop:enable Lint/DuplicateMethods
|
|
1542
|
+
|
|
1543
|
+
def inherited(child_class)
|
|
1544
|
+
if self == GraphQL::Schema
|
|
1545
|
+
child_class.directives(default_directives.values)
|
|
1546
|
+
end
|
|
1547
|
+
child_class.singleton_class.prepend(ResolveTypeWithType)
|
|
1548
|
+
super
|
|
1549
|
+
end
|
|
1006
1550
|
|
|
1007
1551
|
def object_from_id(node_id, ctx)
|
|
1008
1552
|
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to load by ID (tried to load from id `#{node_id}`)"
|
|
@@ -1012,12 +1556,12 @@ module GraphQL
|
|
|
1012
1556
|
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.id_from_object(object, type, ctx) must be implemented to create global ids (tried to create an id for `#{object.inspect}`)"
|
|
1013
1557
|
end
|
|
1014
1558
|
|
|
1015
|
-
def visible?(member,
|
|
1016
|
-
|
|
1559
|
+
def visible?(member, ctx)
|
|
1560
|
+
member.type_class.visible?(ctx)
|
|
1017
1561
|
end
|
|
1018
1562
|
|
|
1019
|
-
def accessible?(member,
|
|
1020
|
-
|
|
1563
|
+
def accessible?(member, ctx)
|
|
1564
|
+
member.type_class.accessible?(ctx)
|
|
1021
1565
|
end
|
|
1022
1566
|
|
|
1023
1567
|
# This hook is called when a client tries to access one or more
|
|
@@ -1071,18 +1615,30 @@ module GraphQL
|
|
|
1071
1615
|
DefaultTypeError.call(type_err, ctx)
|
|
1072
1616
|
end
|
|
1073
1617
|
|
|
1074
|
-
|
|
1618
|
+
# A function to call when {#execute} receives an invalid query string
|
|
1619
|
+
#
|
|
1620
|
+
# The default is to add the error to `context.errors`
|
|
1621
|
+
# @param err [GraphQL::ParseError] The error encountered during parsing
|
|
1622
|
+
# @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
|
|
1623
|
+
# @return void
|
|
1624
|
+
def parse_error(parse_err, ctx)
|
|
1625
|
+
ctx.errors.push(parse_err)
|
|
1626
|
+
end
|
|
1075
1627
|
|
|
1076
|
-
# @return [GraphQL::Execution::Errors
|
|
1628
|
+
# @return [GraphQL::Execution::Errors]
|
|
1077
1629
|
def error_handler
|
|
1078
|
-
@error_handler ||= GraphQL::Execution::Errors
|
|
1630
|
+
@error_handler ||= GraphQL::Execution::Errors.new(self)
|
|
1079
1631
|
end
|
|
1080
1632
|
|
|
1081
1633
|
def lazy_resolve(lazy_class, value_method)
|
|
1082
|
-
|
|
1634
|
+
lazy_methods.set(lazy_class, value_method)
|
|
1083
1635
|
end
|
|
1084
1636
|
|
|
1085
1637
|
def instrument(instrument_step, instrumenter, options = {})
|
|
1638
|
+
if instrument_step == :field
|
|
1639
|
+
GraphQL::Deprecation.warn "Field instrumentation (#{instrumenter.inspect}) will be removed in GraphQL-Ruby 2.0, please upgrade to field extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
|
|
1640
|
+
end
|
|
1641
|
+
|
|
1086
1642
|
step = if instrument_step == :field && options[:after_built_ins]
|
|
1087
1643
|
:field_after_built_ins
|
|
1088
1644
|
else
|
|
@@ -1092,24 +1648,29 @@ module GraphQL
|
|
|
1092
1648
|
own_instrumenters[step] << instrumenter
|
|
1093
1649
|
end
|
|
1094
1650
|
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1651
|
+
# Add several directives at once
|
|
1652
|
+
# @param new_directives [Class]
|
|
1653
|
+
def directives(*new_directives)
|
|
1654
|
+
if new_directives.any?
|
|
1655
|
+
new_directives.flatten.each { |d| directive(d) }
|
|
1098
1656
|
end
|
|
1099
1657
|
|
|
1100
1658
|
find_inherited_value(:directives, default_directives).merge(own_directives)
|
|
1101
1659
|
end
|
|
1102
1660
|
|
|
1661
|
+
# Attach a single directive to this schema
|
|
1662
|
+
# @param new_directive [Class]
|
|
1663
|
+
# @return void
|
|
1103
1664
|
def directive(new_directive)
|
|
1104
|
-
|
|
1665
|
+
add_type_and_traverse(new_directive, root: false)
|
|
1105
1666
|
end
|
|
1106
1667
|
|
|
1107
1668
|
def default_directives
|
|
1108
|
-
{
|
|
1109
|
-
"include" => GraphQL::Directive::
|
|
1110
|
-
"skip" => GraphQL::Directive::
|
|
1111
|
-
"deprecated" => GraphQL::Directive::
|
|
1112
|
-
}
|
|
1669
|
+
@default_directives ||= {
|
|
1670
|
+
"include" => GraphQL::Schema::Directive::Include,
|
|
1671
|
+
"skip" => GraphQL::Schema::Directive::Skip,
|
|
1672
|
+
"deprecated" => GraphQL::Schema::Directive::Deprecated,
|
|
1673
|
+
}.freeze
|
|
1113
1674
|
end
|
|
1114
1675
|
|
|
1115
1676
|
def tracer(new_tracer)
|
|
@@ -1122,7 +1683,7 @@ module GraphQL
|
|
|
1122
1683
|
|
|
1123
1684
|
def query_analyzer(new_analyzer)
|
|
1124
1685
|
if new_analyzer == GraphQL::Authorization::Analyzer
|
|
1125
|
-
warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
|
1686
|
+
GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
|
1126
1687
|
end
|
|
1127
1688
|
own_query_analyzers << new_analyzer
|
|
1128
1689
|
end
|
|
@@ -1133,9 +1694,11 @@ module GraphQL
|
|
|
1133
1694
|
|
|
1134
1695
|
def middleware(new_middleware = nil)
|
|
1135
1696
|
if new_middleware
|
|
1697
|
+
GraphQL::Deprecation.warn "Middleware will be removed in GraphQL-Ruby 2.0, please upgrade to Field Extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
|
|
1136
1698
|
own_middleware << new_middleware
|
|
1137
1699
|
else
|
|
1138
|
-
|
|
1700
|
+
# TODO make sure this is cached when running a query
|
|
1701
|
+
MiddlewareChain.new(steps: all_middleware, final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
|
1139
1702
|
end
|
|
1140
1703
|
end
|
|
1141
1704
|
|
|
@@ -1147,33 +1710,184 @@ module GraphQL
|
|
|
1147
1710
|
find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
|
|
1148
1711
|
end
|
|
1149
1712
|
|
|
1713
|
+
def sanitized_printer(new_sanitized_printer = nil)
|
|
1714
|
+
if new_sanitized_printer
|
|
1715
|
+
@own_sanitized_printer = new_sanitized_printer
|
|
1716
|
+
else
|
|
1717
|
+
@own_sanitized_printer || GraphQL::Language::SanitizedPrinter
|
|
1718
|
+
end
|
|
1719
|
+
end
|
|
1720
|
+
|
|
1721
|
+
# Execute a query on itself.
|
|
1722
|
+
# @see {Query#initialize} for arguments.
|
|
1723
|
+
# @return [Hash] query result, ready to be serialized as JSON
|
|
1724
|
+
def execute(query_str = nil, **kwargs)
|
|
1725
|
+
if query_str
|
|
1726
|
+
kwargs[:query] = query_str
|
|
1727
|
+
end
|
|
1728
|
+
# Some of the query context _should_ be passed to the multiplex, too
|
|
1729
|
+
multiplex_context = if (ctx = kwargs[:context])
|
|
1730
|
+
{
|
|
1731
|
+
backtrace: ctx[:backtrace],
|
|
1732
|
+
tracers: ctx[:tracers],
|
|
1733
|
+
dataloader: ctx[:dataloader],
|
|
1734
|
+
}
|
|
1735
|
+
else
|
|
1736
|
+
{}
|
|
1737
|
+
end
|
|
1738
|
+
# Since we're running one query, don't run a multiplex-level complexity analyzer
|
|
1739
|
+
all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
|
|
1740
|
+
all_results[0]
|
|
1741
|
+
end
|
|
1742
|
+
|
|
1743
|
+
# Execute several queries on itself, concurrently.
|
|
1744
|
+
#
|
|
1745
|
+
# @example Run several queries at once
|
|
1746
|
+
# context = { ... }
|
|
1747
|
+
# queries = [
|
|
1748
|
+
# { query: params[:query_1], variables: params[:variables_1], context: context },
|
|
1749
|
+
# { query: params[:query_2], variables: params[:variables_2], context: context },
|
|
1750
|
+
# ]
|
|
1751
|
+
# results = MySchema.multiplex(queries)
|
|
1752
|
+
# render json: {
|
|
1753
|
+
# result_1: results[0],
|
|
1754
|
+
# result_2: results[1],
|
|
1755
|
+
# }
|
|
1756
|
+
#
|
|
1757
|
+
# @see {Query#initialize} for query keyword arguments
|
|
1758
|
+
# @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
|
|
1759
|
+
# @param queries [Array<Hash>] Keyword arguments for each query
|
|
1760
|
+
# @param context [Hash] Multiplex-level context
|
|
1761
|
+
# @return [Array<Hash>] One result for each query in the input
|
|
1762
|
+
def multiplex(queries, **kwargs)
|
|
1763
|
+
schema = if interpreter?
|
|
1764
|
+
self
|
|
1765
|
+
else
|
|
1766
|
+
graphql_definition
|
|
1767
|
+
end
|
|
1768
|
+
GraphQL::Execution::Multiplex.run_all(schema, queries, **kwargs)
|
|
1769
|
+
end
|
|
1770
|
+
|
|
1771
|
+
def instrumenters
|
|
1772
|
+
inherited_instrumenters = find_inherited_value(:instrumenters) || Hash.new { |h,k| h[k] = [] }
|
|
1773
|
+
inherited_instrumenters.merge(own_instrumenters) do |_step, inherited, own|
|
|
1774
|
+
inherited + own
|
|
1775
|
+
end
|
|
1776
|
+
end
|
|
1777
|
+
|
|
1778
|
+
# @api private
|
|
1779
|
+
def add_subscription_extension_if_necessary
|
|
1780
|
+
if interpreter? && !defined?(@subscription_extension_added) && subscription && self.subscriptions
|
|
1781
|
+
@subscription_extension_added = true
|
|
1782
|
+
if subscription.singleton_class.ancestors.include?(Subscriptions::SubscriptionRoot)
|
|
1783
|
+
GraphQL::Deprecation.warn("`extend Subscriptions::SubscriptionRoot` is no longer required; you may remove it from #{self}'s `subscription` root type (#{subscription}).")
|
|
1784
|
+
else
|
|
1785
|
+
subscription.all_field_definitions.each do |field|
|
|
1786
|
+
field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
|
|
1787
|
+
end
|
|
1788
|
+
end
|
|
1789
|
+
end
|
|
1790
|
+
end
|
|
1791
|
+
|
|
1792
|
+
def query_stack_error(query, err)
|
|
1793
|
+
query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
|
|
1794
|
+
end
|
|
1795
|
+
|
|
1150
1796
|
private
|
|
1151
1797
|
|
|
1152
|
-
|
|
1153
|
-
|
|
1798
|
+
# @param t [Module, Array<Module>]
|
|
1799
|
+
# @return [void]
|
|
1800
|
+
def add_type_and_traverse(t, root:)
|
|
1801
|
+
if root
|
|
1802
|
+
@root_types ||= []
|
|
1803
|
+
@root_types << t
|
|
1804
|
+
end
|
|
1805
|
+
new_types = Array(t)
|
|
1806
|
+
addition = Schema::Addition.new(schema: self, own_types: own_types, new_types: new_types)
|
|
1807
|
+
addition.types.each do |name, types_entry| # rubocop:disable Development/ContextIsPassedCop -- build-time, not query-time
|
|
1808
|
+
if (prev_entry = own_types[name])
|
|
1809
|
+
prev_entries = case prev_entry
|
|
1810
|
+
when Array
|
|
1811
|
+
prev_entry
|
|
1812
|
+
when Module
|
|
1813
|
+
own_types[name] = [prev_entry]
|
|
1814
|
+
else
|
|
1815
|
+
raise "Invariant: unexpected prev_entry at #{name.inspect} when adding #{t.inspect}"
|
|
1816
|
+
end
|
|
1817
|
+
|
|
1818
|
+
case types_entry
|
|
1819
|
+
when Array
|
|
1820
|
+
prev_entries.concat(types_entry)
|
|
1821
|
+
prev_entries.uniq! # in case any are being re-visited
|
|
1822
|
+
when Module
|
|
1823
|
+
if !prev_entries.include?(types_entry)
|
|
1824
|
+
prev_entries << types_entry
|
|
1825
|
+
end
|
|
1826
|
+
else
|
|
1827
|
+
raise "Invariant: unexpected types_entry at #{name} when adding #{t.inspect}"
|
|
1828
|
+
end
|
|
1829
|
+
else
|
|
1830
|
+
if types_entry.is_a?(Array)
|
|
1831
|
+
types_entry.uniq!
|
|
1832
|
+
end
|
|
1833
|
+
own_types[name] = types_entry
|
|
1834
|
+
end
|
|
1835
|
+
end
|
|
1836
|
+
|
|
1837
|
+
own_possible_types.merge!(addition.possible_types) { |key, old_val, new_val| old_val + new_val }
|
|
1838
|
+
own_union_memberships.merge!(addition.union_memberships)
|
|
1839
|
+
|
|
1840
|
+
addition.references.each { |thing, pointers|
|
|
1841
|
+
pointers.each { |pointer| references_to(thing, from: pointer) }
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
addition.directives.each { |dir_class| own_directives[dir_class.graphql_name] = dir_class }
|
|
1845
|
+
|
|
1846
|
+
addition.arguments_with_default_values.each do |arg|
|
|
1847
|
+
arg.validate_default_value
|
|
1848
|
+
end
|
|
1154
1849
|
end
|
|
1155
1850
|
|
|
1156
|
-
def
|
|
1157
|
-
@
|
|
1851
|
+
def lazy_methods
|
|
1852
|
+
if !defined?(@lazy_methods)
|
|
1853
|
+
if inherited_map = find_inherited_value(:lazy_methods)
|
|
1854
|
+
# this isn't _completely_ inherited :S (Things added after `dup` won't work)
|
|
1855
|
+
@lazy_methods = inherited_map.dup
|
|
1856
|
+
else
|
|
1857
|
+
@lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
|
|
1858
|
+
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
|
1859
|
+
@lazy_methods.set(GraphQL::Dataloader::Request, :load)
|
|
1860
|
+
end
|
|
1861
|
+
end
|
|
1862
|
+
@lazy_methods
|
|
1863
|
+
end
|
|
1864
|
+
|
|
1865
|
+
def own_types
|
|
1866
|
+
@own_types ||= {}
|
|
1158
1867
|
end
|
|
1159
1868
|
|
|
1160
|
-
def
|
|
1161
|
-
|
|
1869
|
+
def non_introspection_types
|
|
1870
|
+
find_inherited_value(:non_introspection_types, EMPTY_HASH).merge(own_types)
|
|
1871
|
+
end
|
|
1872
|
+
|
|
1873
|
+
def own_plugins
|
|
1874
|
+
@own_plugins ||= []
|
|
1162
1875
|
end
|
|
1163
1876
|
|
|
1164
1877
|
def own_orphan_types
|
|
1165
1878
|
@own_orphan_types ||= []
|
|
1166
1879
|
end
|
|
1167
1880
|
|
|
1168
|
-
def
|
|
1169
|
-
@
|
|
1881
|
+
def own_possible_types
|
|
1882
|
+
@own_possible_types ||= {}
|
|
1170
1883
|
end
|
|
1171
1884
|
|
|
1172
|
-
def
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1885
|
+
def own_union_memberships
|
|
1886
|
+
@own_union_memberships ||= {}
|
|
1887
|
+
end
|
|
1888
|
+
|
|
1889
|
+
def own_directives
|
|
1890
|
+
@own_directives ||= {}
|
|
1177
1891
|
end
|
|
1178
1892
|
|
|
1179
1893
|
def own_instrumenters
|
|
@@ -1199,93 +1913,14 @@ module GraphQL
|
|
|
1199
1913
|
def own_multiplex_analyzers
|
|
1200
1914
|
@own_multiplex_analyzers ||= []
|
|
1201
1915
|
end
|
|
1202
|
-
|
|
1203
|
-
# Given this schema member, find the class-based definition object
|
|
1204
|
-
# whose `method_name` should be treated as an application hook
|
|
1205
|
-
# @see {.visible?}
|
|
1206
|
-
# @see {.accessible?}
|
|
1207
|
-
# @see {.authorized?}
|
|
1208
|
-
def call_on_type_class(member, method_name, *args, default:)
|
|
1209
|
-
member = if member.respond_to?(:metadata) && member.metadata
|
|
1210
|
-
member.metadata[:type_class] || member
|
|
1211
|
-
else
|
|
1212
|
-
member
|
|
1213
|
-
end
|
|
1214
|
-
|
|
1215
|
-
if member.respond_to?(:relay_node_type) && (t = member.relay_node_type)
|
|
1216
|
-
member = t
|
|
1217
|
-
end
|
|
1218
|
-
|
|
1219
|
-
if member.respond_to?(method_name)
|
|
1220
|
-
member.public_send(method_name, *args)
|
|
1221
|
-
else
|
|
1222
|
-
default
|
|
1223
|
-
end
|
|
1224
|
-
end
|
|
1225
|
-
end
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
def self.inherited(child_class)
|
|
1229
|
-
child_class.singleton_class.class_eval do
|
|
1230
|
-
prepend(MethodWrappers)
|
|
1231
|
-
end
|
|
1232
1916
|
end
|
|
1233
1917
|
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
def resolve_type(type, obj, ctx = :__undefined__)
|
|
1237
|
-
graphql_definition.check_resolved_type(type, obj, ctx) do |ok_type, ok_obj, ok_ctx|
|
|
1238
|
-
super(ok_type, ok_obj, ok_ctx)
|
|
1239
|
-
end
|
|
1240
|
-
end
|
|
1918
|
+
def dataloader_class
|
|
1919
|
+
self.class.dataloader_class
|
|
1241
1920
|
end
|
|
1242
1921
|
|
|
1243
|
-
#
|
|
1244
|
-
|
|
1245
|
-
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
|
1246
|
-
# @api private
|
|
1247
|
-
def after_lazy(value)
|
|
1248
|
-
if lazy?(value)
|
|
1249
|
-
GraphQL::Execution::Lazy.new do
|
|
1250
|
-
result = sync_lazy(value)
|
|
1251
|
-
# The returned result might also be lazy, so check it, too
|
|
1252
|
-
after_lazy(result) do |final_result|
|
|
1253
|
-
yield(final_result) if block_given?
|
|
1254
|
-
end
|
|
1255
|
-
end
|
|
1256
|
-
else
|
|
1257
|
-
yield(value) if block_given?
|
|
1258
|
-
end
|
|
1259
|
-
end
|
|
1260
|
-
|
|
1261
|
-
# Override this method to handle lazy objects in a custom way.
|
|
1262
|
-
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
|
1263
|
-
# @param ctx [GraphQL::Query::Context] the context for this query
|
|
1264
|
-
# @return [Object] A GraphQL-ready (non-lazy) object
|
|
1265
|
-
def self.sync_lazy(value)
|
|
1266
|
-
if block_given?
|
|
1267
|
-
# This was already hit by the instance, just give it back
|
|
1268
|
-
yield(value)
|
|
1269
|
-
else
|
|
1270
|
-
# This was called directly on the class, hit the instance
|
|
1271
|
-
# which has the lazy method map
|
|
1272
|
-
self.graphql_definition.sync_lazy(value)
|
|
1273
|
-
end
|
|
1274
|
-
end
|
|
1275
|
-
|
|
1276
|
-
# @see Schema.sync_lazy for a hook to override
|
|
1277
|
-
# @api private
|
|
1278
|
-
def sync_lazy(value)
|
|
1279
|
-
self.class.sync_lazy(value) { |v|
|
|
1280
|
-
lazy_method = lazy_method_name(v)
|
|
1281
|
-
if lazy_method
|
|
1282
|
-
synced_value = value.public_send(lazy_method)
|
|
1283
|
-
sync_lazy(synced_value)
|
|
1284
|
-
else
|
|
1285
|
-
v
|
|
1286
|
-
end
|
|
1287
|
-
}
|
|
1288
|
-
end
|
|
1922
|
+
# Install these here so that subclasses will also install it.
|
|
1923
|
+
use(GraphQL::Pagination::Connections)
|
|
1289
1924
|
|
|
1290
1925
|
protected
|
|
1291
1926
|
|