graphql 1.9.17 → 2.0.21
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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- 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 +45 -8
- 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 +49 -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 +25 -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/ast/field_usage.rb +31 -2
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +175 -68
- data/lib/graphql/analysis/ast/query_depth.rb +0 -1
- data/lib/graphql/analysis/ast/visitor.rb +54 -38
- data/lib/graphql/analysis/ast.rb +16 -16
- data/lib/graphql/analysis.rb +0 -7
- data/lib/graphql/backtrace/inspect_result.rb +0 -1
- data/lib/graphql/backtrace/table.rb +37 -16
- data/lib/graphql/backtrace/trace.rb +96 -0
- data/lib/graphql/backtrace/traced_error.rb +0 -1
- data/lib/graphql/backtrace/tracer.rb +39 -9
- data/lib/graphql/backtrace.rb +26 -18
- data/lib/graphql/dataloader/null_dataloader.rb +24 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +164 -0
- data/lib/graphql/dataloader.rb +311 -0
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/dig.rb +1 -1
- data/lib/graphql/execution/directive_checks.rb +2 -2
- data/lib/graphql/execution/errors.rb +77 -45
- 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 +104 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
- data/lib/graphql/execution/interpreter/resolve.rb +62 -24
- data/lib/graphql/execution/interpreter/runtime.rb +830 -417
- data/lib/graphql/execution/interpreter.rb +206 -74
- data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
- data/lib/graphql/execution/lazy.rb +11 -21
- data/lib/graphql/execution/lookahead.rb +65 -136
- data/lib/graphql/execution/multiplex.rb +6 -152
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/filter.rb +8 -3
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +18 -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/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +5 -18
- 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 +34 -17
- data/lib/graphql/introspection.rb +100 -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 +136 -78
- data/lib/graphql/language/lexer.rb +216 -1462
- data/lib/graphql/language/nodes.rb +129 -132
- data/lib/graphql/language/parser.rb +994 -932
- data/lib/graphql/language/parser.y +152 -120
- data/lib/graphql/language/printer.rb +48 -23
- data/lib/graphql/language/sanitized_printer.rb +222 -0
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/language/visitor.rb +192 -84
- data/lib/graphql/language.rb +3 -1
- data/lib/graphql/name_validator.rb +2 -7
- data/lib/graphql/pagination/active_record_relation_connection.rb +77 -0
- data/lib/graphql/pagination/array_connection.rb +79 -0
- data/lib/graphql/pagination/connection.rb +253 -0
- data/lib/graphql/pagination/connections.rb +135 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +228 -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/context.rb +205 -203
- data/lib/graphql/query/fingerprint.rb +26 -0
- data/lib/graphql/query/input_validation_result.rb +33 -7
- data/lib/graphql/query/null_context.rb +22 -9
- data/lib/graphql/query/validation_pipeline.rb +16 -38
- data/lib/graphql/query/variable_validation_error.rb +3 -3
- data/lib/graphql/query/variables.rb +39 -12
- data/lib/graphql/query.rb +95 -43
- data/lib/graphql/railtie.rb +6 -102
- data/lib/graphql/rake_task/validate.rb +4 -1
- data/lib/graphql/rake_task.rb +41 -10
- data/lib/graphql/relay/range_add.rb +17 -10
- data/lib/graphql/relay.rb +0 -15
- 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/schema/addition.rb +245 -0
- data/lib/graphql/schema/argument.rb +285 -36
- 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 +348 -205
- data/lib/graphql/schema/built_in_types.rb +5 -5
- 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/one_of.rb +12 -0
- data/lib/graphql/schema/directive/skip.rb +2 -2
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +134 -15
- data/lib/graphql/schema/enum.rb +137 -39
- data/lib/graphql/schema/enum_value.rb +17 -23
- data/lib/graphql/schema/field/connection_extension.rb +50 -20
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +504 -331
- data/lib/graphql/schema/field_extension.rb +86 -2
- data/lib/graphql/schema/find_inherited_value.rb +12 -1
- data/lib/graphql/schema/finder.rb +16 -14
- data/lib/graphql/schema/input_object.rb +182 -60
- data/lib/graphql/schema/interface.rb +24 -49
- data/lib/graphql/schema/introspection_system.rb +103 -37
- data/lib/graphql/schema/late_bound_type.rb +9 -2
- data/lib/graphql/schema/list.rb +61 -3
- data/lib/graphql/schema/loader.rb +144 -96
- data/lib/graphql/schema/member/base_dsl_methods.rb +41 -37
- data/lib/graphql/schema/member/build_type.rb +24 -15
- data/lib/graphql/schema/member/has_arguments.rb +310 -26
- data/lib/graphql/schema/member/has_ast_node.rb +32 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +24 -0
- data/lib/graphql/schema/member/has_directives.rb +118 -0
- data/lib/graphql/schema/member/has_fields.rb +166 -44
- data/lib/graphql/schema/member/has_interfaces.rb +129 -0
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
- data/lib/graphql/schema/member/has_validators.rb +57 -0
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
- data/lib/graphql/schema/member/type_system_helpers.rb +20 -3
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/member.rb +11 -6
- data/lib/graphql/schema/mutation.rb +4 -9
- data/lib/graphql/schema/non_null.rb +34 -4
- data/lib/graphql/schema/object.rb +36 -60
- data/lib/graphql/schema/printer.rb +16 -35
- data/lib/graphql/schema/relay_classic_mutation.rb +91 -44
- data/lib/graphql/schema/resolver/has_payload_type.rb +51 -11
- data/lib/graphql/schema/resolver.rb +147 -94
- data/lib/graphql/schema/scalar.rb +40 -15
- data/lib/graphql/schema/subscription.rb +60 -31
- data/lib/graphql/schema/timeout.rb +45 -35
- data/lib/graphql/schema/type_expression.rb +21 -13
- data/lib/graphql/schema/type_membership.rb +23 -6
- data/lib/graphql/schema/union.rb +49 -15
- data/lib/graphql/schema/unique_within_type.rb +1 -2
- 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 +213 -35
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +857 -884
- data/lib/graphql/static_validation/all_rules.rb +3 -0
- data/lib/graphql/static_validation/base_visitor.rb +21 -31
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -2
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +69 -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 +12 -6
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -14
- 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 +15 -7
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +96 -53
- 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/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -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 +13 -7
- 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 +32 -20
- data/lib/graphql/static_validation.rb +1 -2
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +129 -22
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
- data/lib/graphql/subscriptions/event.rb +84 -35
- data/lib/graphql/subscriptions/instrumentation.rb +0 -47
- data/lib/graphql/subscriptions/serialize.rb +53 -6
- data/lib/graphql/subscriptions.rb +137 -57
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
- data/lib/graphql/tracing/appoptics_trace.rb +231 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
- data/lib/graphql/tracing/appsignal_trace.rb +77 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
- data/lib/graphql/tracing/data_dog_trace.rb +148 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +34 -2
- data/lib/graphql/tracing/legacy_trace.rb +65 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
- data/lib/graphql/tracing/notifications_trace.rb +42 -0
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_trace.rb +109 -0
- data/lib/graphql/tracing/platform_tracing.rb +76 -35
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +5 -2
- data/lib/graphql/tracing/prometheus_tracing.rb +11 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/scout_tracing.rb +19 -0
- data/lib/graphql/tracing/statsd_trace.rb +56 -0
- data/lib/graphql/tracing/statsd_tracing.rb +42 -0
- data/lib/graphql/tracing/trace.rb +75 -0
- data/lib/graphql/tracing.rb +23 -67
- data/lib/graphql/type_kinds.rb +6 -3
- 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 +20 -9
- data/lib/graphql/types/iso_8601_date_time.rb +36 -10
- data/lib/graphql/types/relay/base_connection.rb +18 -90
- data/lib/graphql/types/relay/base_edge.rb +2 -34
- data/lib/graphql/types/relay/connection_behaviors.rb +176 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +75 -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 +25 -0
- data/lib/graphql/types/relay/page_info.rb +2 -14
- data/lib/graphql/types/relay/page_info_behaviors.rb +30 -0
- data/lib/graphql/types/relay.rb +10 -5
- data/lib/graphql/types/string.rb +8 -2
- data/lib/graphql/unauthorized_error.rb +2 -2
- data/lib/graphql/unresolved_type_error.rb +2 -2
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +63 -65
- data/readme.md +3 -6
- metadata +127 -236
- data/lib/graphql/analysis/analyze_query.rb +0 -91
- data/lib/graphql/analysis/field_usage.rb +0 -45
- data/lib/graphql/analysis/max_query_complexity.rb +0 -26
- data/lib/graphql/analysis/max_query_depth.rb +0 -26
- data/lib/graphql/analysis/query_complexity.rb +0 -88
- data/lib/graphql/analysis/query_depth.rb +0 -43
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -159
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backwards_compatibility.rb +0 -60
- data/lib/graphql/base_type.rb +0 -226
- data/lib/graphql/boolean_type.rb +0 -2
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
- data/lib/graphql/compatibility/execution_specification.rb +0 -435
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -213
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -91
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -264
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -680
- data/lib/graphql/compatibility.rb +0 -5
- data/lib/graphql/define/assign_argument.rb +0 -12
- data/lib/graphql/define/assign_connection.rb +0 -13
- data/lib/graphql/define/assign_enum_value.rb +0 -18
- data/lib/graphql/define/assign_global_id_field.rb +0 -11
- data/lib/graphql/define/assign_mutation_function.rb +0 -34
- data/lib/graphql/define/assign_object_field.rb +0 -42
- data/lib/graphql/define/defined_object_proxy.rb +0 -50
- data/lib/graphql/define/instance_definable.rb +0 -300
- data/lib/graphql/define/no_definition_error.rb +0 -7
- data/lib/graphql/define/non_null_with_bang.rb +0 -16
- data/lib/graphql/define/type_definer.rb +0 -31
- data/lib/graphql/define.rb +0 -31
- data/lib/graphql/deprecated_dsl.rb +0 -42
- data/lib/graphql/directive/deprecated_directive.rb +0 -13
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -104
- data/lib/graphql/enum_type.rb +0 -193
- data/lib/graphql/execution/execute.rb +0 -326
- data/lib/graphql/execution/flatten.rb +0 -40
- data/lib/graphql/execution/instrumentation.rb +0 -92
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
- data/lib/graphql/execution/lazy/resolve.rb +0 -91
- data/lib/graphql/execution/typecast.rb +0 -50
- data/lib/graphql/field/resolve.rb +0 -59
- data/lib/graphql/field.rb +0 -330
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -153
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -154
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -86
- data/lib/graphql/internal_representation/document.rb +0 -27
- data/lib/graphql/internal_representation/node.rb +0 -206
- data/lib/graphql/internal_representation/print.rb +0 -51
- data/lib/graphql/internal_representation/rewrite.rb +0 -184
- data/lib/graphql/internal_representation/scope.rb +0 -88
- data/lib/graphql/internal_representation/visit.rb +0 -36
- data/lib/graphql/internal_representation.rb +0 -7
- data/lib/graphql/language/lexer.rl +0 -258
- data/lib/graphql/list_type.rb +0 -80
- data/lib/graphql/literal_validation_error.rb +0 -6
- data/lib/graphql/non_null_type.rb +0 -81
- data/lib/graphql/object_type.rb +0 -141
- data/lib/graphql/query/arguments.rb +0 -187
- data/lib/graphql/query/arguments_cache.rb +0 -25
- data/lib/graphql/query/executor.rb +0 -53
- data/lib/graphql/query/literal_input.rb +0 -116
- data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
- data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
- data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
- data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
- data/lib/graphql/query/serial_execution.rb +0 -39
- data/lib/graphql/relay/array_connection.rb +0 -85
- data/lib/graphql/relay/base_connection.rb +0 -172
- data/lib/graphql/relay/connection_instrumentation.rb +0 -54
- data/lib/graphql/relay/connection_resolve.rb +0 -43
- data/lib/graphql/relay/connection_type.rb +0 -40
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -18
- data/lib/graphql/relay/edges_instrumentation.rb +0 -40
- data/lib/graphql/relay/global_id_resolve.rb +0 -18
- data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
- data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
- data/lib/graphql/relay/mutation/resolve.rb +0 -56
- data/lib/graphql/relay/mutation/result.rb +0 -38
- data/lib/graphql/relay/mutation.rb +0 -190
- data/lib/graphql/relay/node.rb +0 -36
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -190
- data/lib/graphql/relay/type_extensions.rb +0 -30
- data/lib/graphql/scalar_type.rb +0 -133
- data/lib/graphql/schema/catchall_middleware.rb +0 -35
- data/lib/graphql/schema/default_parse_error.rb +0 -10
- data/lib/graphql/schema/default_type_error.rb +0 -15
- data/lib/graphql/schema/member/accepts_definition.rb +0 -152
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -26
- data/lib/graphql/schema/member/instrumentation.rb +0 -132
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/possible_types.rb +0 -39
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -86
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -303
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/subscription_root.rb +0 -66
- data/lib/graphql/tracing/skylight_tracing.rb +0 -62
- 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/types/relay/node_field.rb +0 -43
- data/lib/graphql/types/relay/nodes_field.rb +0 -45
- data/lib/graphql/union_type.rb +0 -128
- data/lib/graphql/upgrader/member.rb +0 -936
- data/lib/graphql/upgrader/schema.rb +0 -37
data/lib/graphql/schema.rb
CHANGED
@@ -1,26 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require "graphql/schema/addition"
|
2
3
|
require "graphql/schema/base_64_encoder"
|
3
|
-
require "graphql/schema/catchall_middleware"
|
4
|
-
require "graphql/schema/default_parse_error"
|
5
|
-
require "graphql/schema/default_type_error"
|
6
4
|
require "graphql/schema/find_inherited_value"
|
7
5
|
require "graphql/schema/finder"
|
8
6
|
require "graphql/schema/invalid_type_error"
|
9
7
|
require "graphql/schema/introspection_system"
|
10
8
|
require "graphql/schema/late_bound_type"
|
11
|
-
require "graphql/schema/middleware_chain"
|
12
9
|
require "graphql/schema/null_mask"
|
13
|
-
require "graphql/schema/possible_types"
|
14
|
-
require "graphql/schema/rescue_middleware"
|
15
10
|
require "graphql/schema/timeout"
|
16
|
-
require "graphql/schema/timeout_middleware"
|
17
|
-
require "graphql/schema/traversal"
|
18
11
|
require "graphql/schema/type_expression"
|
19
12
|
require "graphql/schema/unique_within_type"
|
20
|
-
require "graphql/schema/validation"
|
21
13
|
require "graphql/schema/warden"
|
22
14
|
require "graphql/schema/build_from_definition"
|
23
15
|
|
16
|
+
require "graphql/schema/validator"
|
24
17
|
require "graphql/schema/member"
|
25
18
|
require "graphql/schema/wrapper"
|
26
19
|
require "graphql/schema/list"
|
@@ -36,9 +29,12 @@ require "graphql/schema/scalar"
|
|
36
29
|
require "graphql/schema/object"
|
37
30
|
require "graphql/schema/union"
|
38
31
|
require "graphql/schema/directive"
|
32
|
+
require "graphql/schema/directive/deprecated"
|
39
33
|
require "graphql/schema/directive/include"
|
34
|
+
require "graphql/schema/directive/one_of"
|
40
35
|
require "graphql/schema/directive/skip"
|
41
36
|
require "graphql/schema/directive/feature"
|
37
|
+
require "graphql/schema/directive/flagged"
|
42
38
|
require "graphql/schema/directive/transform"
|
43
39
|
require "graphql/schema/type_membership"
|
44
40
|
|
@@ -55,7 +51,6 @@ module GraphQL
|
|
55
51
|
# - types for exposing your application
|
56
52
|
# - query analyzers for assessing incoming queries (including max depth & max complexity restrictions)
|
57
53
|
# - execution strategies for running incoming queries
|
58
|
-
# - middleware for interacting with execution
|
59
54
|
#
|
60
55
|
# Schemas start with root types, {Schema#query}, {Schema#mutation} and {Schema#subscription}.
|
61
56
|
# The schema will traverse the tree of fields & types, using those as starting points.
|
@@ -68,784 +63,493 @@ module GraphQL
|
|
68
63
|
# `query_execution_strategy`, `mutation_execution_strategy` and `subscription_execution_strategy`
|
69
64
|
# each apply to corresponding root types.
|
70
65
|
#
|
71
|
-
# A schema accepts a `Relay::GlobalNodeIdentification` instance for use with Relay IDs.
|
72
|
-
#
|
73
66
|
# @example defining a schema
|
74
|
-
# MySchema
|
67
|
+
# class MySchema < GraphQL::Schema
|
75
68
|
# query QueryType
|
76
|
-
# middleware PermissionMiddleware
|
77
|
-
# rescue_from(ActiveRecord::RecordNotFound) { "Not found" }
|
78
69
|
# # If types are only connected by way of interfaces, they must be added here
|
79
70
|
# orphan_types ImageType, AudioType
|
80
71
|
# end
|
81
72
|
#
|
82
73
|
class Schema
|
83
|
-
extend
|
84
|
-
extend GraphQL::Schema::Member::AcceptsDefinition
|
85
|
-
include GraphQL::Define::InstanceDefinable
|
74
|
+
extend GraphQL::Schema::Member::HasAstNode
|
86
75
|
extend GraphQL::Schema::FindInheritedValue
|
87
76
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
:cursor_encoder,
|
97
|
-
# If these are given as classes, normalize them. Accept `nil` when building from string.
|
98
|
-
query: ->(schema, t) { schema.query = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
99
|
-
mutation: ->(schema, t) { schema.mutation = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
100
|
-
subscription: ->(schema, t) { schema.subscription = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
101
|
-
disable_introspection_entry_points: ->(schema) { schema.disable_introspection_entry_points = true },
|
102
|
-
directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.name] = d; m } },
|
103
|
-
directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
|
104
|
-
instrument: ->(schema, type, instrumenter, after_built_ins: false) {
|
105
|
-
if type == :field && after_built_ins
|
106
|
-
type = :field_after_built_ins
|
107
|
-
end
|
108
|
-
schema.instrumenters[type] << instrumenter
|
109
|
-
},
|
110
|
-
query_analyzer: ->(schema, analyzer) {
|
111
|
-
if analyzer == GraphQL::Authorization::Analyzer
|
112
|
-
warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
113
|
-
end
|
114
|
-
schema.query_analyzers << analyzer
|
115
|
-
},
|
116
|
-
multiplex_analyzer: ->(schema, analyzer) { schema.multiplex_analyzers << analyzer },
|
117
|
-
middleware: ->(schema, middleware) { schema.middleware << middleware },
|
118
|
-
lazy_resolve: ->(schema, lazy_class, lazy_value_method) { schema.lazy_methods.set(lazy_class, lazy_value_method) },
|
119
|
-
rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block) },
|
120
|
-
tracer: ->(schema, tracer) { schema.tracers.push(tracer) }
|
121
|
-
|
122
|
-
ensure_defined :introspection_system
|
123
|
-
|
124
|
-
attr_accessor \
|
125
|
-
:query, :mutation, :subscription,
|
126
|
-
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
127
|
-
:max_depth, :max_complexity, :default_max_page_size,
|
128
|
-
:orphan_types, :directives,
|
129
|
-
:query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
|
130
|
-
:cursor_encoder,
|
131
|
-
:ast_node,
|
132
|
-
:raise_definition_error,
|
133
|
-
:introspection_namespace,
|
134
|
-
:analysis_engine
|
135
|
-
|
136
|
-
# [Boolean] True if this object bubbles validation errors up from a field into its parent InputObject, if there is one.
|
137
|
-
attr_accessor :error_bubbling
|
138
|
-
|
139
|
-
# Single, long-lived instance of the provided subscriptions class, if there is one.
|
140
|
-
# @return [GraphQL::Subscriptions]
|
141
|
-
attr_accessor :subscriptions
|
142
|
-
|
143
|
-
# @return [MiddlewareChain] MiddlewareChain which is applied to fields during execution
|
144
|
-
attr_accessor :middleware
|
145
|
-
|
146
|
-
# @return [<#call(member, ctx)>] A callable for filtering members of the schema
|
147
|
-
# @see {Query.new} for query-specific filters with `except:`
|
148
|
-
attr_accessor :default_mask
|
149
|
-
|
150
|
-
# @see {GraphQL::Query::Context} The parent class of these classes
|
151
|
-
# @return [Class] Instantiated for each query
|
152
|
-
attr_accessor :context_class
|
153
|
-
|
154
|
-
# [Boolean] True if this object disables the introspection entry point fields
|
155
|
-
attr_accessor :disable_introspection_entry_points
|
156
|
-
|
157
|
-
class << self
|
158
|
-
attr_writer :default_execution_strategy
|
159
|
-
end
|
160
|
-
|
161
|
-
def default_filter
|
162
|
-
GraphQL::Filter.new(except: default_mask)
|
163
|
-
end
|
164
|
-
|
165
|
-
# @return [Array<#trace(key, data)>] Tracers applied to every query
|
166
|
-
# @see {Query#tracers} for query-specific tracers
|
167
|
-
attr_reader :tracers
|
168
|
-
|
169
|
-
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"].freeze
|
170
|
-
EMPTY_ARRAY = [].freeze
|
171
|
-
EMPTY_HASH = {}.freeze
|
172
|
-
|
173
|
-
attr_reader :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
|
174
|
-
|
175
|
-
def initialize
|
176
|
-
@tracers = []
|
177
|
-
@definition_error = nil
|
178
|
-
@orphan_types = []
|
179
|
-
@directives = self.class.default_directives
|
180
|
-
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
181
|
-
@middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
182
|
-
@query_analyzers = []
|
183
|
-
@multiplex_analyzers = []
|
184
|
-
@resolve_type_proc = nil
|
185
|
-
@object_from_id_proc = nil
|
186
|
-
@id_from_object_proc = nil
|
187
|
-
@type_error_proc = DefaultTypeError
|
188
|
-
@parse_error_proc = DefaultParseError
|
189
|
-
@instrumenters = Hash.new { |h, k| h[k] = [] }
|
190
|
-
@lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
|
191
|
-
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
192
|
-
@cursor_encoder = Base64Encoder
|
193
|
-
# Default to the built-in execution strategy:
|
194
|
-
@analysis_engine = GraphQL::Analysis
|
195
|
-
@query_execution_strategy = self.class.default_execution_strategy
|
196
|
-
@mutation_execution_strategy = self.class.default_execution_strategy
|
197
|
-
@subscription_execution_strategy = self.class.default_execution_strategy
|
198
|
-
@default_mask = GraphQL::Schema::NullMask
|
199
|
-
@rebuilding_artifacts = false
|
200
|
-
@context_class = GraphQL::Query::Context
|
201
|
-
@introspection_namespace = nil
|
202
|
-
@introspection_system = nil
|
203
|
-
@interpreter = false
|
204
|
-
@error_bubbling = false
|
205
|
-
@disable_introspection_entry_points = false
|
206
|
-
end
|
207
|
-
|
208
|
-
# @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
|
209
|
-
def interpreter?
|
210
|
-
@interpreter
|
77
|
+
class DuplicateNamesError < GraphQL::Error
|
78
|
+
attr_reader :duplicated_name
|
79
|
+
def initialize(duplicated_name:, duplicated_definition_1:, duplicated_definition_2:)
|
80
|
+
@duplicated_name = duplicated_name
|
81
|
+
super(
|
82
|
+
"Found two visible definitions for `#{duplicated_name}`: #{duplicated_definition_1}, #{duplicated_definition_2}"
|
83
|
+
)
|
84
|
+
end
|
211
85
|
end
|
212
86
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
87
|
+
class UnresolvedLateBoundTypeError < GraphQL::Error
|
88
|
+
attr_reader :type
|
89
|
+
def initialize(type:)
|
90
|
+
@type = type
|
91
|
+
super("Late bound type was never found: #{type.inspect}")
|
92
|
+
end
|
218
93
|
end
|
219
94
|
|
220
|
-
|
221
|
-
|
222
|
-
@orphan_types = other.orphan_types.dup
|
223
|
-
@directives = other.directives.dup
|
224
|
-
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
225
|
-
@middleware = other.middleware.dup
|
226
|
-
@query_analyzers = other.query_analyzers.dup
|
227
|
-
@multiplex_analyzers = other.multiplex_analyzers.dup
|
228
|
-
@tracers = other.tracers.dup
|
229
|
-
@possible_types = GraphQL::Schema::PossibleTypes.new(self)
|
230
|
-
|
231
|
-
@lazy_methods = other.lazy_methods.dup
|
95
|
+
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
96
|
+
class InvalidDocumentError < Error; end;
|
232
97
|
|
233
|
-
|
234
|
-
|
235
|
-
|
98
|
+
class << self
|
99
|
+
# Create schema with the result of an introspection query.
|
100
|
+
# @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
|
101
|
+
# @return [Class<GraphQL::Schema>] the schema described by `input`
|
102
|
+
def from_introspection(introspection_result)
|
103
|
+
GraphQL::Schema::Loader.load(introspection_result)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Create schema from an IDL schema or file containing an IDL definition.
|
107
|
+
# @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
|
108
|
+
# @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
|
109
|
+
# @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
|
110
|
+
# @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
|
111
|
+
# @return [Class] the schema described by `document`
|
112
|
+
def from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
|
113
|
+
# If the file ends in `.graphql` or `.graphqls`, treat it like a filepath
|
114
|
+
if definition_or_path.end_with?(".graphql") || definition_or_path.end_with?(".graphqls")
|
115
|
+
GraphQL::Schema::BuildFromDefinition.from_definition_path(
|
116
|
+
self,
|
117
|
+
definition_or_path,
|
118
|
+
default_resolve: default_resolve,
|
119
|
+
parser: parser,
|
120
|
+
using: using,
|
121
|
+
)
|
122
|
+
else
|
123
|
+
GraphQL::Schema::BuildFromDefinition.from_definition(
|
124
|
+
self,
|
125
|
+
definition_or_path,
|
126
|
+
default_resolve: default_resolve,
|
127
|
+
parser: parser,
|
128
|
+
using: using,
|
129
|
+
)
|
130
|
+
end
|
236
131
|
end
|
237
132
|
|
238
|
-
|
239
|
-
|
133
|
+
def deprecated_graphql_definition
|
134
|
+
graphql_definition(silence_deprecation_warning: true)
|
240
135
|
end
|
241
136
|
|
242
|
-
#
|
243
|
-
|
244
|
-
|
245
|
-
@introspection_system = nil
|
246
|
-
end
|
247
|
-
|
248
|
-
def rescue_from(*args, &block)
|
249
|
-
rescue_middleware.rescue_from(*args, &block)
|
250
|
-
end
|
251
|
-
|
252
|
-
def remove_handler(*args, &block)
|
253
|
-
rescue_middleware.remove_handler(*args, &block)
|
254
|
-
end
|
255
|
-
|
256
|
-
def using_ast_analysis?
|
257
|
-
@analysis_engine == GraphQL::Analysis::AST
|
258
|
-
end
|
259
|
-
|
260
|
-
# For forwards-compatibility with Schema classes
|
261
|
-
alias :graphql_definition :itself
|
262
|
-
|
263
|
-
# Validate a query string according to this schema.
|
264
|
-
# @param string_or_document [String, GraphQL::Language::Nodes::Document]
|
265
|
-
# @return [Array<GraphQL::StaticValidation::Error >]
|
266
|
-
def validate(string_or_document, rules: nil, context: nil)
|
267
|
-
doc = if string_or_document.is_a?(String)
|
268
|
-
GraphQL.parse(string_or_document)
|
269
|
-
else
|
270
|
-
string_or_document
|
271
|
-
end
|
272
|
-
query = GraphQL::Query.new(self, document: doc, context: context)
|
273
|
-
validator_opts = { schema: self }
|
274
|
-
rules && (validator_opts[:rules] = rules)
|
275
|
-
validator = GraphQL::StaticValidation::Validator.new(validator_opts)
|
276
|
-
res = validator.validate(query)
|
277
|
-
res[:errors]
|
278
|
-
end
|
279
|
-
|
280
|
-
def define(**kwargs, &block)
|
281
|
-
super
|
282
|
-
ensure_defined
|
283
|
-
# Assert that all necessary configs are present:
|
284
|
-
validation_error = Validation.validate(self)
|
285
|
-
validation_error && raise(GraphQL::RequiredImplementationMissingError, validation_error)
|
286
|
-
rebuild_artifacts
|
287
|
-
|
288
|
-
@definition_error = nil
|
289
|
-
nil
|
290
|
-
rescue StandardError => err
|
291
|
-
if @raise_definition_error || err.is_a?(CyclicalDefinitionError) || err.is_a?(GraphQL::RequiredImplementationMissingError)
|
292
|
-
raise
|
293
|
-
else
|
294
|
-
# Raise this error _later_ to avoid messing with Rails constant loading
|
295
|
-
@definition_error = err
|
296
|
-
end
|
297
|
-
nil
|
298
|
-
end
|
299
|
-
|
300
|
-
# Attach `instrumenter` to this schema for instrumenting events of `instrumentation_type`.
|
301
|
-
# @param instrumentation_type [Symbol]
|
302
|
-
# @param instrumenter
|
303
|
-
# @return [void]
|
304
|
-
def instrument(instrumentation_type, instrumenter)
|
305
|
-
@instrumenters[instrumentation_type] << instrumenter
|
306
|
-
if instrumentation_type == :field
|
307
|
-
rebuild_artifacts
|
137
|
+
# @return [GraphQL::Subscriptions]
|
138
|
+
def subscriptions(inherited: true)
|
139
|
+
defined?(@subscriptions) ? @subscriptions : (inherited ? find_inherited_value(:subscriptions, nil) : nil)
|
308
140
|
end
|
309
|
-
end
|
310
141
|
|
311
|
-
|
312
|
-
|
313
|
-
@root_types ||= begin
|
314
|
-
rebuild_artifacts
|
315
|
-
@root_types
|
142
|
+
def subscriptions=(new_implementation)
|
143
|
+
@subscriptions = new_implementation
|
316
144
|
end
|
317
|
-
end
|
318
145
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
146
|
+
def trace_class(new_class = nil)
|
147
|
+
if new_class
|
148
|
+
trace_mode(:default, new_class)
|
149
|
+
backtrace_class = Class.new(new_class)
|
150
|
+
backtrace_class.include(GraphQL::Backtrace::Trace)
|
151
|
+
trace_mode(:default_backtrace, backtrace_class)
|
152
|
+
end
|
153
|
+
trace_class_for(:default)
|
325
154
|
end
|
326
|
-
end
|
327
155
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
156
|
+
# @return [Class] Return the trace class to use for this mode, looking one up on the superclass if this Schema doesn't have one defined.
|
157
|
+
def trace_class_for(mode)
|
158
|
+
@trace_modes ||= {}
|
159
|
+
@trace_modes[mode] ||= begin
|
160
|
+
base_class = if superclass.respond_to?(:trace_class_for)
|
161
|
+
superclass.trace_class_for(mode)
|
162
|
+
elsif mode == :default_backtrace
|
163
|
+
GraphQL::Backtrace::DefaultBacktraceTrace
|
164
|
+
else
|
165
|
+
GraphQL::Tracing::Trace
|
166
|
+
end
|
167
|
+
Class.new(base_class)
|
168
|
+
end
|
333
169
|
end
|
334
|
-
end
|
335
170
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
# @param type [GraphQL::ObjectType]
|
346
|
-
# @return [Array<GraphQL::UnionType>] list of union types of which the type is a member
|
347
|
-
def union_memberships(type)
|
348
|
-
rebuild_artifacts unless defined?(@union_memberships)
|
349
|
-
@union_memberships.fetch(type.name, [])
|
350
|
-
end
|
351
|
-
|
352
|
-
# Execute a query on itself. Raises an error if the schema definition is invalid.
|
353
|
-
# @see {Query#initialize} for arguments.
|
354
|
-
# @return [Hash] query result, ready to be serialized as JSON
|
355
|
-
def execute(query_str = nil, **kwargs)
|
356
|
-
if query_str
|
357
|
-
kwargs[:query] = query_str
|
358
|
-
end
|
359
|
-
# Some of the query context _should_ be passed to the multiplex, too
|
360
|
-
multiplex_context = if (ctx = kwargs[:context])
|
361
|
-
{
|
362
|
-
backtrace: ctx[:backtrace],
|
363
|
-
tracers: ctx[:tracers],
|
364
|
-
}
|
365
|
-
else
|
366
|
-
{}
|
171
|
+
# Configure `trace_class` to be used whenever `context: { trace_mode: mode_name }` is requested.
|
172
|
+
# `:default` is used when no `trace_mode: ...` is requested.
|
173
|
+
# @param mode_name [Symbol]
|
174
|
+
# @param trace_class [Class] subclass of GraphQL::Tracing::Trace
|
175
|
+
# @return void
|
176
|
+
def trace_mode(mode_name, trace_class)
|
177
|
+
@trace_modes ||= {}
|
178
|
+
@trace_modes[mode_name] = trace_class
|
179
|
+
nil
|
367
180
|
end
|
368
|
-
# Since we're running one query, don't run a multiplex-level complexity analyzer
|
369
|
-
all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
|
370
|
-
all_results[0]
|
371
|
-
end
|
372
|
-
|
373
|
-
# Execute several queries on itself. Raises an error if the schema definition is invalid.
|
374
|
-
# @example Run several queries at once
|
375
|
-
# context = { ... }
|
376
|
-
# queries = [
|
377
|
-
# { query: params[:query_1], variables: params[:variables_1], context: context },
|
378
|
-
# { query: params[:query_2], variables: params[:variables_2], context: context },
|
379
|
-
# ]
|
380
|
-
# results = MySchema.multiplex(queries)
|
381
|
-
# render json: {
|
382
|
-
# result_1: results[0],
|
383
|
-
# result_2: results[1],
|
384
|
-
# }
|
385
|
-
#
|
386
|
-
# @see {Query#initialize} for query keyword arguments
|
387
|
-
# @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
|
388
|
-
# @param queries [Array<Hash>] Keyword arguments for each query
|
389
|
-
# @param context [Hash] Multiplex-level context
|
390
|
-
# @return [Array<Hash>] One result for each query in the input
|
391
|
-
def multiplex(queries, **kwargs)
|
392
|
-
with_definition_error_check {
|
393
|
-
GraphQL::Execution::Multiplex.run_all(self, queries, **kwargs)
|
394
|
-
}
|
395
|
-
end
|
396
|
-
|
397
|
-
# Search for a schema member using a string path
|
398
|
-
# @example Finding a Field
|
399
|
-
# Schema.find("Ensemble.musicians")
|
400
|
-
#
|
401
|
-
# @see {GraphQL::Schema::Finder} for more examples
|
402
|
-
# @param path [String] A dot-separated path to the member
|
403
|
-
# @raise [Schema::Finder::MemberNotFoundError] if path could not be found
|
404
|
-
# @return [GraphQL::BaseType, GraphQL::Field, GraphQL::Argument, GraphQL::Directive] A GraphQL Schema Member
|
405
|
-
def find(path)
|
406
|
-
rebuild_artifacts unless defined?(@finder)
|
407
|
-
@find_cache[path] ||= @finder.find(path)
|
408
|
-
end
|
409
181
|
|
410
|
-
# Resolve field named `field_name` for type `parent_type`.
|
411
|
-
# Handles dynamic fields `__typename`, `__type` and `__schema`, too
|
412
|
-
# @param parent_type [String, GraphQL::BaseType]
|
413
|
-
# @param field_name [String]
|
414
|
-
# @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
|
415
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
416
|
-
def get_field(parent_type, field_name)
|
417
|
-
with_definition_error_check do
|
418
|
-
parent_type_name = case parent_type
|
419
|
-
when GraphQL::BaseType
|
420
|
-
parent_type.name
|
421
|
-
when String
|
422
|
-
parent_type
|
423
|
-
else
|
424
|
-
raise "Unexpected parent_type: #{parent_type}"
|
425
|
-
end
|
426
182
|
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
183
|
+
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
184
|
+
# @see {#as_json}
|
185
|
+
# @return [String]
|
186
|
+
def to_json(**args)
|
187
|
+
JSON.pretty_generate(as_json(**args))
|
188
|
+
end
|
189
|
+
|
190
|
+
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
191
|
+
# @param context [Hash]
|
192
|
+
# @param only [<#call(member, ctx)>]
|
193
|
+
# @param except [<#call(member, ctx)>]
|
194
|
+
# @param include_deprecated_args [Boolean] If true, deprecated arguments will be included in the JSON response
|
195
|
+
# @param include_schema_description [Boolean] If true, the schema's description will be queried and included in the response
|
196
|
+
# @param include_is_repeatable [Boolean] If true, `isRepeatable: true|false` will be included with the schema's directives
|
197
|
+
# @param include_specified_by_url [Boolean] If true, scalar types' `specifiedByUrl:` will be included in the response
|
198
|
+
# @param include_is_one_of [Boolean] If true, `isOneOf: true|false` will be included with input objects
|
199
|
+
# @return [Hash] GraphQL result
|
200
|
+
def as_json(only: nil, except: nil, context: {}, include_deprecated_args: true, include_schema_description: false, include_is_repeatable: false, include_specified_by_url: false, include_is_one_of: false)
|
201
|
+
introspection_query = Introspection.query(
|
202
|
+
include_deprecated_args: include_deprecated_args,
|
203
|
+
include_schema_description: include_schema_description,
|
204
|
+
include_is_repeatable: include_is_repeatable,
|
205
|
+
include_is_one_of: include_is_one_of,
|
206
|
+
include_specified_by_url: include_specified_by_url,
|
207
|
+
)
|
208
|
+
|
209
|
+
execute(introspection_query, only: only, except: except, context: context).to_h
|
210
|
+
end
|
211
|
+
|
212
|
+
# Return the GraphQL IDL for the schema
|
213
|
+
# @param context [Hash]
|
214
|
+
# @param only [<#call(member, ctx)>]
|
215
|
+
# @param except [<#call(member, ctx)>]
|
216
|
+
# @return [String]
|
217
|
+
def to_definition(only: nil, except: nil, context: {})
|
218
|
+
GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
|
219
|
+
end
|
220
|
+
|
221
|
+
# Return the GraphQL::Language::Document IDL AST for the schema
|
222
|
+
# @return [GraphQL::Language::Document]
|
223
|
+
def to_document
|
224
|
+
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
225
|
+
end
|
226
|
+
|
227
|
+
# @return [String, nil]
|
228
|
+
def description(new_description = nil)
|
229
|
+
if new_description
|
230
|
+
@description = new_description
|
231
|
+
elsif defined?(@description)
|
232
|
+
@description
|
434
233
|
else
|
435
|
-
nil
|
234
|
+
find_inherited_value(:description, nil)
|
436
235
|
end
|
437
236
|
end
|
438
|
-
end
|
439
|
-
|
440
|
-
# Fields for this type, after instrumentation is applied
|
441
|
-
# @return [Hash<String, GraphQL::Field>]
|
442
|
-
def get_fields(type)
|
443
|
-
@instrumented_field_map[type.graphql_name]
|
444
|
-
end
|
445
|
-
|
446
|
-
def type_from_ast(ast_node)
|
447
|
-
GraphQL::Schema::TypeExpression.build_type(self.types, ast_node)
|
448
|
-
end
|
449
|
-
|
450
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
451
|
-
# @param type_defn [GraphQL::InterfaceType, GraphQL::UnionType] the type whose members you want to retrieve
|
452
|
-
# @param context [GraphQL::Query::Context] The context for the current query
|
453
|
-
# @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
|
454
|
-
def possible_types(type_defn, context = GraphQL::Query::NullContext)
|
455
|
-
@possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
|
456
|
-
@possible_types.possible_types(type_defn, context)
|
457
|
-
end
|
458
237
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
when "mutation"
|
466
|
-
mutation
|
467
|
-
when "subscription"
|
468
|
-
subscription
|
469
|
-
else
|
470
|
-
raise ArgumentError, "unknown operation type: #{operation}"
|
238
|
+
def find(path)
|
239
|
+
if !@finder
|
240
|
+
@find_cache = {}
|
241
|
+
@finder ||= GraphQL::Schema::Finder.new(self)
|
242
|
+
end
|
243
|
+
@find_cache[path] ||= @finder.find(path)
|
471
244
|
end
|
472
|
-
end
|
473
245
|
|
474
|
-
|
475
|
-
|
476
|
-
when "query"
|
477
|
-
query_execution_strategy
|
478
|
-
when "mutation"
|
479
|
-
mutation_execution_strategy
|
480
|
-
when "subscription"
|
481
|
-
subscription_execution_strategy
|
482
|
-
else
|
483
|
-
raise ArgumentError, "unknown operation type: #{operation}"
|
246
|
+
def default_filter
|
247
|
+
GraphQL::Filter.new(except: default_mask, silence_deprecation_warning: true)
|
484
248
|
end
|
485
|
-
end
|
486
249
|
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
# @param ctx [GraphQL::Query::Context] The context for the current query
|
493
|
-
# @return [GraphQL::ObjectType] The type for exposing `object` in GraphQL
|
494
|
-
def resolve_type(type, object, ctx = :__undefined__)
|
495
|
-
check_resolved_type(type, object, ctx) do |ok_type, ok_object, ok_ctx|
|
496
|
-
if @resolve_type_proc.nil?
|
497
|
-
raise(GraphQL::RequiredImplementationMissingError, "Can't determine GraphQL type for: #{ok_object.inspect}, define `resolve_type (type, obj, ctx) -> { ... }` inside `Schema.define`.")
|
250
|
+
def default_mask(new_mask = nil)
|
251
|
+
if new_mask
|
252
|
+
@own_default_mask = new_mask
|
253
|
+
else
|
254
|
+
@own_default_mask || find_inherited_value(:default_mask, Schema::NullMask)
|
498
255
|
end
|
499
|
-
@resolve_type_proc.call(ok_type, ok_object, ok_ctx)
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
|
-
# This is a compatibility hack so that instance-level and class-level
|
504
|
-
# methods can get correctness checks without calling one another
|
505
|
-
# @api private
|
506
|
-
def check_resolved_type(type, object, ctx = :__undefined__)
|
507
|
-
if ctx == :__undefined__
|
508
|
-
# Old method signature
|
509
|
-
ctx = object
|
510
|
-
object = type
|
511
|
-
type = nil
|
512
256
|
end
|
513
257
|
|
514
|
-
|
515
|
-
|
258
|
+
def static_validator
|
259
|
+
GraphQL::StaticValidation::Validator.new(schema: self)
|
516
260
|
end
|
517
261
|
|
518
|
-
|
519
|
-
|
262
|
+
def use(plugin, **kwargs)
|
263
|
+
if kwargs.any?
|
264
|
+
plugin.use(self, **kwargs)
|
265
|
+
else
|
266
|
+
plugin.use(self)
|
267
|
+
end
|
268
|
+
own_plugins << [plugin, kwargs]
|
520
269
|
end
|
521
270
|
|
522
|
-
|
523
|
-
|
524
|
-
type_result = if type_proc
|
525
|
-
type_proc.call(object, ctx)
|
526
|
-
else
|
527
|
-
yield(type, object, ctx)
|
271
|
+
def plugins
|
272
|
+
find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
|
528
273
|
end
|
529
274
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
if
|
538
|
-
|
539
|
-
|
275
|
+
# Build a map of `{ name => type }` and return it
|
276
|
+
# @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
|
277
|
+
# @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
|
278
|
+
def types(context = GraphQL::Query::NullContext)
|
279
|
+
all_types = non_introspection_types.merge(introspection_system.types)
|
280
|
+
visible_types = {}
|
281
|
+
all_types.each do |k, v|
|
282
|
+
visible_types[k] =if v.is_a?(Array)
|
283
|
+
visible_t = nil
|
284
|
+
v.each do |t|
|
285
|
+
if t.visible?(context)
|
286
|
+
if visible_t.nil?
|
287
|
+
visible_t = t
|
288
|
+
else
|
289
|
+
raise DuplicateNamesError.new(
|
290
|
+
duplicated_name: k, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
291
|
+
)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
visible_t
|
540
296
|
else
|
541
|
-
|
297
|
+
v
|
542
298
|
end
|
543
299
|
end
|
300
|
+
visible_types
|
544
301
|
end
|
545
|
-
end
|
546
302
|
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
303
|
+
# @param type_name [String]
|
304
|
+
# @return [Module, nil] A type, or nil if there's no type called `type_name`
|
305
|
+
def get_type(type_name, context = GraphQL::Query::NullContext)
|
306
|
+
local_entry = own_types[type_name]
|
307
|
+
type_defn = case local_entry
|
308
|
+
when nil
|
309
|
+
nil
|
310
|
+
when Array
|
311
|
+
visible_t = nil
|
312
|
+
warden = Warden.from_context(context)
|
313
|
+
local_entry.each do |t|
|
314
|
+
if warden.visible_type?(t, context)
|
315
|
+
if visible_t.nil?
|
316
|
+
visible_t = t
|
317
|
+
else
|
318
|
+
raise DuplicateNamesError.new(
|
319
|
+
duplicated_name: type_name, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
320
|
+
)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
visible_t
|
325
|
+
when Module
|
326
|
+
local_entry
|
327
|
+
else
|
328
|
+
raise "Invariant: unexpected own_types[#{type_name.inspect}]: #{local_entry.inspect}"
|
329
|
+
end
|
551
330
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
# @return [Any] The application object identified by `id`
|
556
|
-
def object_from_id(id, ctx)
|
557
|
-
if @object_from_id_proc.nil?
|
558
|
-
raise(GraphQL::RequiredImplementationMissingError, "Can't fetch an object for id \"#{id}\" because the schema's `object_from_id (id, ctx) -> { ... }` function is not defined")
|
559
|
-
else
|
560
|
-
@object_from_id_proc.call(id, ctx)
|
331
|
+
type_defn ||
|
332
|
+
introspection_system.types[type_name] || # todo context-specific introspection?
|
333
|
+
(superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
|
561
334
|
end
|
562
|
-
end
|
563
|
-
|
564
|
-
# @param new_proc [#call] A new callable for fetching objects by ID
|
565
|
-
def object_from_id=(new_proc)
|
566
|
-
@object_from_id_proc = new_proc
|
567
|
-
end
|
568
335
|
|
569
|
-
|
570
|
-
|
571
|
-
# You can use this hook to write a log entry,
|
572
|
-
# add a {GraphQL::ExecutionError} to the response (with `ctx.add_error`)
|
573
|
-
# or raise an exception and halt query execution.
|
574
|
-
#
|
575
|
-
# @example A `nil` is encountered by a non-null field
|
576
|
-
# type_error ->(err, query_ctx) {
|
577
|
-
# err.is_a?(GraphQL::InvalidNullError) # => true
|
578
|
-
# }
|
579
|
-
#
|
580
|
-
# @example An object doesn't resolve to one of a {UnionType}'s members
|
581
|
-
# type_error ->(err, query_ctx) {
|
582
|
-
# err.is_a?(GraphQL::UnresolvedTypeError) # => true
|
583
|
-
# }
|
584
|
-
#
|
585
|
-
# @see {DefaultTypeError} is the default behavior.
|
586
|
-
# @param err [GraphQL::TypeError] The error encountered during execution
|
587
|
-
# @param ctx [GraphQL::Query::Context] The context for the field where the error occurred
|
588
|
-
# @return void
|
589
|
-
def type_error(err, ctx)
|
590
|
-
@type_error_proc.call(err, ctx)
|
591
|
-
end
|
592
|
-
|
593
|
-
# @param new_proc [#call] A new callable for handling type errors during execution
|
594
|
-
def type_error=(new_proc)
|
595
|
-
@type_error_proc = new_proc
|
596
|
-
end
|
597
|
-
|
598
|
-
# Can't delegate to `class`
|
599
|
-
alias :_schema_class :class
|
600
|
-
def_delegators :_schema_class, :visible?, :accessible?, :authorized?, :unauthorized_object, :unauthorized_field, :inaccessible_fields
|
601
|
-
def_delegators :_schema_class, :directive
|
602
|
-
def_delegators :_schema_class, :error_handler
|
603
|
-
|
604
|
-
# A function to call when {#execute} receives an invalid query string
|
605
|
-
#
|
606
|
-
# @see {DefaultParseError} is the default behavior.
|
607
|
-
# @param err [GraphQL::ParseError] The error encountered during parsing
|
608
|
-
# @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
|
609
|
-
# @return void
|
610
|
-
def parse_error(err, ctx)
|
611
|
-
@parse_error_proc.call(err, ctx)
|
612
|
-
end
|
613
|
-
|
614
|
-
# @param new_proc [#call] A new callable for handling parse errors during execution
|
615
|
-
def parse_error=(new_proc)
|
616
|
-
@parse_error_proc = new_proc
|
617
|
-
end
|
336
|
+
# @api private
|
337
|
+
attr_writer :connections
|
618
338
|
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
339
|
+
# @return [GraphQL::Pagination::Connections] if installed
|
340
|
+
def connections
|
341
|
+
if defined?(@connections)
|
342
|
+
@connections
|
343
|
+
else
|
344
|
+
inherited_connections = find_inherited_value(:connections, nil)
|
345
|
+
# This schema is part of an inheritance chain which is using new connections,
|
346
|
+
# make a new instance, so we don't pollute the upstream one.
|
347
|
+
if inherited_connections
|
348
|
+
@connections = Pagination::Connections.new(schema: self)
|
349
|
+
else
|
350
|
+
nil
|
351
|
+
end
|
352
|
+
end
|
629
353
|
end
|
630
|
-
end
|
631
|
-
|
632
|
-
# @param new_proc [#call] A new callable for generating unique IDs
|
633
|
-
def id_from_object=(new_proc)
|
634
|
-
@id_from_object_proc = new_proc
|
635
|
-
end
|
636
|
-
|
637
|
-
# Create schema with the result of an introspection query.
|
638
|
-
# @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
|
639
|
-
# @return [GraphQL::Schema] the schema described by `input`
|
640
|
-
def self.from_introspection(introspection_result)
|
641
|
-
GraphQL::Schema::Loader.load(introspection_result)
|
642
|
-
end
|
643
|
-
|
644
|
-
# Create schema from an IDL schema or file containing an IDL definition.
|
645
|
-
# @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
|
646
|
-
# @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
|
647
|
-
# @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
|
648
|
-
# @return [GraphQL::Schema] the schema described by `document`
|
649
|
-
def self.from_definition(definition_or_path, default_resolve: BuildFromDefinition::DefaultResolve, parser: BuildFromDefinition::DefaultParser)
|
650
|
-
# If the file ends in `.graphql`, treat it like a filepath
|
651
|
-
definition = if definition_or_path.end_with?(".graphql")
|
652
|
-
File.read(definition_or_path)
|
653
|
-
else
|
654
|
-
definition_or_path
|
655
|
-
end
|
656
|
-
GraphQL::Schema::BuildFromDefinition.from_definition(definition, default_resolve: default_resolve, parser: parser)
|
657
|
-
end
|
658
|
-
|
659
|
-
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
660
|
-
class InvalidDocumentError < Error; end;
|
661
|
-
|
662
|
-
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered wtih {#lazy_resolve}.
|
663
|
-
def lazy_method_name(obj)
|
664
|
-
@lazy_methods.get(obj)
|
665
|
-
end
|
666
|
-
|
667
|
-
# @return [Boolean] True if this object should be lazily resolved
|
668
|
-
def lazy?(obj)
|
669
|
-
!!lazy_method_name(obj)
|
670
|
-
end
|
671
|
-
|
672
|
-
# Return the GraphQL IDL for the schema
|
673
|
-
# @param context [Hash]
|
674
|
-
# @param only [<#call(member, ctx)>]
|
675
|
-
# @param except [<#call(member, ctx)>]
|
676
|
-
# @return [String]
|
677
|
-
def to_definition(only: nil, except: nil, context: {})
|
678
|
-
GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
|
679
|
-
end
|
680
|
-
|
681
|
-
# Return the GraphQL::Language::Document IDL AST for the schema
|
682
|
-
# @return [GraphQL::Language::Document]
|
683
|
-
def to_document
|
684
|
-
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
685
|
-
end
|
686
|
-
|
687
|
-
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
688
|
-
# @param context [Hash]
|
689
|
-
# @param only [<#call(member, ctx)>]
|
690
|
-
# @param except [<#call(member, ctx)>]
|
691
|
-
# @return [Hash] GraphQL result
|
692
|
-
def as_json(only: nil, except: nil, context: {})
|
693
|
-
execute(Introspection::INTROSPECTION_QUERY, only: only, except: except, context: context).to_h
|
694
|
-
end
|
695
|
-
|
696
|
-
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
697
|
-
# @see {#as_json}
|
698
|
-
# @return [String]
|
699
|
-
def to_json(*args)
|
700
|
-
JSON.pretty_generate(as_json(*args))
|
701
|
-
end
|
702
354
|
|
703
|
-
|
704
|
-
|
705
|
-
# For compatibility, these methods all:
|
706
|
-
# - Cause the Schema instance to be created, if it hasn't been created yet
|
707
|
-
# - Delegate to that instance
|
708
|
-
# Eventually, the methods will be moved into this class, removing the need for the singleton.
|
709
|
-
def_delegators :graphql_definition,
|
710
|
-
# Schema structure
|
711
|
-
:as_json, :to_json, :to_document, :to_definition, :ast_node,
|
712
|
-
# Execution
|
713
|
-
:execute, :multiplex,
|
714
|
-
:static_validator, :introspection_system,
|
715
|
-
:query_analyzers, :tracers, :instrumenters,
|
716
|
-
:execution_strategy_for_operation,
|
717
|
-
:validate, :multiplex_analyzers, :lazy?, :lazy_method_name, :after_lazy, :sync_lazy,
|
718
|
-
# Configuration
|
719
|
-
:analysis_engine, :analysis_engine=, :using_ast_analysis?, :interpreter?,
|
720
|
-
:max_complexity=, :max_depth=,
|
721
|
-
:error_bubbling=,
|
722
|
-
:metadata,
|
723
|
-
:default_mask,
|
724
|
-
:default_filter, :redefine,
|
725
|
-
:id_from_object_proc, :object_from_id_proc,
|
726
|
-
:id_from_object=, :object_from_id=,
|
727
|
-
:remove_handler,
|
728
|
-
# Members
|
729
|
-
:types, :get_fields, :find,
|
730
|
-
:root_type_for_operation,
|
731
|
-
:subscriptions,
|
732
|
-
:union_memberships,
|
733
|
-
:get_field, :root_types, :references_to, :type_from_ast,
|
734
|
-
:possible_types,
|
735
|
-
:disable_introspection_entry_points=
|
736
|
-
|
737
|
-
def graphql_definition
|
738
|
-
@graphql_definition ||= to_graphql
|
739
|
-
end
|
740
|
-
|
741
|
-
def use(plugin, options = {})
|
742
|
-
own_plugins << [plugin, options]
|
355
|
+
def new_connections?
|
356
|
+
!!connections
|
743
357
|
end
|
744
358
|
|
745
|
-
def
|
746
|
-
|
359
|
+
def query(new_query_object = nil)
|
360
|
+
if new_query_object
|
361
|
+
if @query_object
|
362
|
+
raise GraphQL::Error, "Second definition of `query(...)` (#{new_query_object.inspect}) is invalid, already configured with #{@query_object.inspect}"
|
363
|
+
else
|
364
|
+
@query_object = new_query_object
|
365
|
+
add_type_and_traverse(new_query_object, root: true)
|
366
|
+
nil
|
367
|
+
end
|
368
|
+
else
|
369
|
+
@query_object || find_inherited_value(:query)
|
370
|
+
end
|
747
371
|
end
|
748
372
|
|
749
|
-
def
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
schema_defn.max_depth = max_depth
|
758
|
-
schema_defn.default_max_page_size = default_max_page_size
|
759
|
-
schema_defn.orphan_types = orphan_types
|
760
|
-
schema_defn.disable_introspection_entry_points = disable_introspection_entry_points?
|
761
|
-
|
762
|
-
prepped_dirs = {}
|
763
|
-
directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
|
764
|
-
schema_defn.directives = prepped_dirs
|
765
|
-
schema_defn.introspection_namespace = introspection
|
766
|
-
schema_defn.resolve_type = method(:resolve_type)
|
767
|
-
schema_defn.object_from_id = method(:object_from_id)
|
768
|
-
schema_defn.id_from_object = method(:id_from_object)
|
769
|
-
schema_defn.type_error = method(:type_error)
|
770
|
-
schema_defn.context_class = context_class
|
771
|
-
schema_defn.cursor_encoder = cursor_encoder
|
772
|
-
schema_defn.tracers.concat(tracers)
|
773
|
-
schema_defn.query_analyzers.concat(query_analyzers)
|
774
|
-
|
775
|
-
schema_defn.middleware.concat(all_middleware)
|
776
|
-
schema_defn.multiplex_analyzers.concat(multiplex_analyzers)
|
777
|
-
schema_defn.query_execution_strategy = query_execution_strategy
|
778
|
-
schema_defn.mutation_execution_strategy = mutation_execution_strategy
|
779
|
-
schema_defn.subscription_execution_strategy = subscription_execution_strategy
|
780
|
-
all_instrumenters.each do |step, insts|
|
781
|
-
insts.each do |inst|
|
782
|
-
schema_defn.instrumenters[step] << inst
|
373
|
+
def mutation(new_mutation_object = nil)
|
374
|
+
if new_mutation_object
|
375
|
+
if @mutation_object
|
376
|
+
raise GraphQL::Error, "Second definition of `mutation(...)` (#{new_mutation_object.inspect}) is invalid, already configured with #{@mutation_object.inspect}"
|
377
|
+
else
|
378
|
+
@mutation_object = new_mutation_object
|
379
|
+
add_type_and_traverse(new_mutation_object, root: true)
|
380
|
+
nil
|
783
381
|
end
|
382
|
+
else
|
383
|
+
@mutation_object || find_inherited_value(:mutation)
|
784
384
|
end
|
785
|
-
|
786
|
-
|
385
|
+
end
|
386
|
+
|
387
|
+
def subscription(new_subscription_object = nil)
|
388
|
+
if new_subscription_object
|
389
|
+
if @subscription_object
|
390
|
+
raise GraphQL::Error, "Second definition of `subscription(...)` (#{new_subscription_object.inspect}) is invalid, already configured with #{@subscription_object.inspect}"
|
391
|
+
else
|
392
|
+
@subscription_object = new_subscription_object
|
393
|
+
add_subscription_extension_if_necessary
|
394
|
+
add_type_and_traverse(new_subscription_object, root: true)
|
395
|
+
nil
|
396
|
+
end
|
397
|
+
else
|
398
|
+
@subscription_object || find_inherited_value(:subscription)
|
787
399
|
end
|
788
|
-
|
789
|
-
|
400
|
+
end
|
401
|
+
|
402
|
+
# @see [GraphQL::Schema::Warden] Restricted access to root types
|
403
|
+
# @return [GraphQL::ObjectType, nil]
|
404
|
+
def root_type_for_operation(operation)
|
405
|
+
case operation
|
406
|
+
when "query"
|
407
|
+
query
|
408
|
+
when "mutation"
|
409
|
+
mutation
|
410
|
+
when "subscription"
|
411
|
+
subscription
|
412
|
+
else
|
413
|
+
raise ArgumentError, "unknown operation type: #{operation}"
|
790
414
|
end
|
415
|
+
end
|
791
416
|
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
417
|
+
def root_types
|
418
|
+
@root_types
|
419
|
+
end
|
420
|
+
|
421
|
+
# @param type [Module] The type definition whose possible types you want to see
|
422
|
+
# @return [Hash<String, Module>] All possible types, if no `type` is given.
|
423
|
+
# @return [Array<Module>] Possible types for `type`, if it's given.
|
424
|
+
def possible_types(type = nil, context = GraphQL::Query::NullContext)
|
425
|
+
if type
|
426
|
+
# TODO duck-typing `.possible_types` would probably be nicer here
|
427
|
+
if type.kind.union?
|
428
|
+
type.possible_types(context: context)
|
429
|
+
else
|
430
|
+
stored_possible_types = own_possible_types[type.graphql_name]
|
431
|
+
visible_possible_types = if stored_possible_types && type.kind.interface?
|
432
|
+
stored_possible_types.select do |possible_type|
|
433
|
+
possible_type.interfaces(context).include?(type)
|
801
434
|
end
|
435
|
+
else
|
436
|
+
stored_possible_types
|
802
437
|
end
|
438
|
+
visible_possible_types ||
|
439
|
+
introspection_system.possible_types[type.graphql_name] ||
|
440
|
+
(
|
441
|
+
superclass.respond_to?(:possible_types) ?
|
442
|
+
superclass.possible_types(type, context) :
|
443
|
+
EMPTY_ARRAY
|
444
|
+
)
|
803
445
|
end
|
446
|
+
else
|
447
|
+
find_inherited_value(:possible_types, EMPTY_HASH)
|
448
|
+
.merge(own_possible_types)
|
449
|
+
.merge(introspection_system.possible_types)
|
804
450
|
end
|
805
|
-
|
806
|
-
|
807
|
-
|
451
|
+
end
|
452
|
+
|
453
|
+
def union_memberships(type = nil)
|
454
|
+
if type
|
455
|
+
own_um = own_union_memberships.fetch(type.graphql_name, EMPTY_ARRAY)
|
456
|
+
inherited_um = find_inherited_value(:union_memberships, EMPTY_HASH).fetch(type.graphql_name, EMPTY_ARRAY)
|
457
|
+
own_um + inherited_um
|
458
|
+
else
|
459
|
+
joined_um = own_union_memberships.dup
|
460
|
+
find_inherited_value(:union_memberhips, EMPTY_HASH).each do |k, v|
|
461
|
+
um = joined_um[k] ||= []
|
462
|
+
um.concat(v)
|
463
|
+
end
|
464
|
+
joined_um
|
808
465
|
end
|
809
|
-
|
466
|
+
end
|
810
467
|
|
811
|
-
|
468
|
+
# @api private
|
469
|
+
# @see GraphQL::Dataloader
|
470
|
+
def dataloader_class
|
471
|
+
@dataloader_class || GraphQL::Dataloader::NullDataloader
|
812
472
|
end
|
813
473
|
|
814
|
-
|
815
|
-
|
816
|
-
|
474
|
+
attr_writer :dataloader_class
|
475
|
+
|
476
|
+
def references_to(to_type = nil, from: nil)
|
477
|
+
@own_references_to ||= Hash.new { |h, k| h[k] = [] }
|
478
|
+
if to_type
|
479
|
+
if !to_type.is_a?(String)
|
480
|
+
to_type = to_type.graphql_name
|
481
|
+
end
|
482
|
+
|
483
|
+
if from
|
484
|
+
@own_references_to[to_type] << from
|
485
|
+
else
|
486
|
+
own_refs = @own_references_to[to_type]
|
487
|
+
inherited_refs = find_inherited_value(:references_to, EMPTY_HASH)[to_type] || EMPTY_ARRAY
|
488
|
+
own_refs + inherited_refs
|
489
|
+
end
|
817
490
|
else
|
818
|
-
|
819
|
-
|
491
|
+
# `@own_references_to` can be quite large for big schemas,
|
492
|
+
# and generally speaking, we won't inherit any values.
|
493
|
+
# So optimize the most common case -- don't create a duplicate Hash.
|
494
|
+
inherited_value = find_inherited_value(:references_to, EMPTY_HASH)
|
495
|
+
if inherited_value.any?
|
496
|
+
inherited_value.merge(@own_references_to)
|
497
|
+
else
|
498
|
+
@own_references_to
|
499
|
+
end
|
820
500
|
end
|
821
501
|
end
|
822
502
|
|
823
|
-
def
|
824
|
-
|
825
|
-
|
503
|
+
def type_from_ast(ast_node, context: nil)
|
504
|
+
type_owner = context ? context.warden : self
|
505
|
+
GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
|
506
|
+
end
|
507
|
+
|
508
|
+
def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext)
|
509
|
+
parent_type = case type_or_name
|
510
|
+
when LateBoundType
|
511
|
+
get_type(type_or_name.name, context)
|
512
|
+
when String
|
513
|
+
get_type(type_or_name, context)
|
514
|
+
when Module
|
515
|
+
type_or_name
|
826
516
|
else
|
827
|
-
|
828
|
-
mutation_object.respond_to?(:graphql_definition) ? mutation_object.graphql_definition : mutation_object
|
517
|
+
raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
|
829
518
|
end
|
830
|
-
end
|
831
519
|
|
832
|
-
|
833
|
-
|
834
|
-
|
520
|
+
if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
|
521
|
+
field
|
522
|
+
elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
|
523
|
+
entry_point_field
|
524
|
+
elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
|
525
|
+
dynamic_field
|
835
526
|
else
|
836
|
-
|
837
|
-
subscription_object.respond_to?(:graphql_definition) ? subscription_object.graphql_definition : subscription_object
|
527
|
+
nil
|
838
528
|
end
|
839
529
|
end
|
840
530
|
|
531
|
+
def get_fields(type, context = GraphQL::Query::NullContext)
|
532
|
+
type.fields(context)
|
533
|
+
end
|
534
|
+
|
841
535
|
def introspection(new_introspection_namespace = nil)
|
842
536
|
if new_introspection_namespace
|
843
537
|
@introspection = new_introspection_namespace
|
538
|
+
# reset this cached value:
|
539
|
+
@introspection_system = nil
|
844
540
|
else
|
845
541
|
@introspection || find_inherited_value(:introspection)
|
846
542
|
end
|
847
543
|
end
|
848
544
|
|
545
|
+
def introspection_system
|
546
|
+
if !@introspection_system
|
547
|
+
@introspection_system = Schema::IntrospectionSystem.new(self)
|
548
|
+
@introspection_system.resolve_late_bindings
|
549
|
+
end
|
550
|
+
@introspection_system
|
551
|
+
end
|
552
|
+
|
849
553
|
def cursor_encoder(new_encoder = nil)
|
850
554
|
if new_encoder
|
851
555
|
@cursor_encoder = new_encoder
|
@@ -861,6 +565,14 @@ module GraphQL
|
|
861
565
|
end
|
862
566
|
end
|
863
567
|
|
568
|
+
def default_page_size(new_default_page_size = nil)
|
569
|
+
if new_default_page_size
|
570
|
+
@default_page_size = new_default_page_size
|
571
|
+
else
|
572
|
+
@default_page_size || find_inherited_value(:default_page_size)
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
864
576
|
def query_execution_strategy(new_query_execution_strategy = nil)
|
865
577
|
if new_query_execution_strategy
|
866
578
|
@query_execution_strategy = new_query_execution_strategy
|
@@ -885,14 +597,75 @@ module GraphQL
|
|
885
597
|
end
|
886
598
|
end
|
887
599
|
|
600
|
+
attr_writer :validate_timeout
|
601
|
+
|
602
|
+
def validate_timeout(new_validate_timeout = nil)
|
603
|
+
if new_validate_timeout
|
604
|
+
@validate_timeout = new_validate_timeout
|
605
|
+
elsif defined?(@validate_timeout)
|
606
|
+
@validate_timeout
|
607
|
+
else
|
608
|
+
find_inherited_value(:validate_timeout)
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
# Validate a query string according to this schema.
|
613
|
+
# @param string_or_document [String, GraphQL::Language::Nodes::Document]
|
614
|
+
# @return [Array<GraphQL::StaticValidation::Error >]
|
615
|
+
def validate(string_or_document, rules: nil, context: nil)
|
616
|
+
doc = if string_or_document.is_a?(String)
|
617
|
+
GraphQL.parse(string_or_document)
|
618
|
+
else
|
619
|
+
string_or_document
|
620
|
+
end
|
621
|
+
query = GraphQL::Query.new(self, document: doc, context: context)
|
622
|
+
validator_opts = { schema: self }
|
623
|
+
rules && (validator_opts[:rules] = rules)
|
624
|
+
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
625
|
+
res = validator.validate(query, timeout: validate_timeout, max_errors: validate_max_errors)
|
626
|
+
res[:errors]
|
627
|
+
end
|
628
|
+
|
629
|
+
attr_writer :validate_max_errors
|
630
|
+
|
631
|
+
def validate_max_errors(new_validate_max_errors = nil)
|
632
|
+
if new_validate_max_errors
|
633
|
+
@validate_max_errors = new_validate_max_errors
|
634
|
+
elsif defined?(@validate_max_errors)
|
635
|
+
@validate_max_errors
|
636
|
+
else
|
637
|
+
find_inherited_value(:validate_max_errors)
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
641
|
+
attr_writer :max_complexity
|
642
|
+
|
888
643
|
def max_complexity(max_complexity = nil)
|
889
644
|
if max_complexity
|
890
645
|
@max_complexity = max_complexity
|
646
|
+
elsif defined?(@max_complexity)
|
647
|
+
@max_complexity
|
891
648
|
else
|
892
|
-
|
649
|
+
find_inherited_value(:max_complexity)
|
893
650
|
end
|
894
651
|
end
|
895
652
|
|
653
|
+
attr_writer :analysis_engine
|
654
|
+
|
655
|
+
def analysis_engine
|
656
|
+
@analysis_engine || find_inherited_value(:analysis_engine, self.default_analysis_engine)
|
657
|
+
end
|
658
|
+
|
659
|
+
def using_ast_analysis?
|
660
|
+
true
|
661
|
+
end
|
662
|
+
|
663
|
+
def interpreter?
|
664
|
+
true
|
665
|
+
end
|
666
|
+
|
667
|
+
attr_writer :interpreter
|
668
|
+
|
896
669
|
def error_bubbling(new_error_bubbling = nil)
|
897
670
|
if !new_error_bubbling.nil?
|
898
671
|
@error_bubbling = new_error_bubbling
|
@@ -901,16 +674,36 @@ module GraphQL
|
|
901
674
|
end
|
902
675
|
end
|
903
676
|
|
677
|
+
attr_writer :error_bubbling
|
678
|
+
|
679
|
+
attr_writer :max_depth
|
680
|
+
|
904
681
|
def max_depth(new_max_depth = nil)
|
905
682
|
if new_max_depth
|
906
683
|
@max_depth = new_max_depth
|
684
|
+
elsif defined?(@max_depth)
|
685
|
+
@max_depth
|
907
686
|
else
|
908
|
-
|
687
|
+
find_inherited_value(:max_depth)
|
909
688
|
end
|
910
689
|
end
|
911
690
|
|
912
691
|
def disable_introspection_entry_points
|
913
692
|
@disable_introspection_entry_points = true
|
693
|
+
# TODO: this clears the cache made in `def types`. But this is not a great solution.
|
694
|
+
@introspection_system = nil
|
695
|
+
end
|
696
|
+
|
697
|
+
def disable_schema_introspection_entry_point
|
698
|
+
@disable_schema_introspection_entry_point = true
|
699
|
+
# TODO: this clears the cache made in `def types`. But this is not a great solution.
|
700
|
+
@introspection_system = nil
|
701
|
+
end
|
702
|
+
|
703
|
+
def disable_type_introspection_entry_point
|
704
|
+
@disable_type_introspection_entry_point = true
|
705
|
+
# TODO: this clears the cache made in `def types`. But this is not a great solution.
|
706
|
+
@introspection_system = nil
|
914
707
|
end
|
915
708
|
|
916
709
|
def disable_introspection_entry_points?
|
@@ -921,8 +714,26 @@ module GraphQL
|
|
921
714
|
end
|
922
715
|
end
|
923
716
|
|
717
|
+
def disable_schema_introspection_entry_point?
|
718
|
+
if instance_variable_defined?(:@disable_schema_introspection_entry_point)
|
719
|
+
@disable_schema_introspection_entry_point
|
720
|
+
else
|
721
|
+
find_inherited_value(:disable_schema_introspection_entry_point?, false)
|
722
|
+
end
|
723
|
+
end
|
724
|
+
|
725
|
+
def disable_type_introspection_entry_point?
|
726
|
+
if instance_variable_defined?(:@disable_type_introspection_entry_point)
|
727
|
+
@disable_type_introspection_entry_point
|
728
|
+
else
|
729
|
+
find_inherited_value(:disable_type_introspection_entry_point?, false)
|
730
|
+
end
|
731
|
+
end
|
732
|
+
|
924
733
|
def orphan_types(*new_orphan_types)
|
925
734
|
if new_orphan_types.any?
|
735
|
+
new_orphan_types = new_orphan_types.flatten
|
736
|
+
add_type_and_traverse(new_orphan_types, root: false)
|
926
737
|
own_orphan_types.concat(new_orphan_types.flatten)
|
927
738
|
end
|
928
739
|
|
@@ -933,7 +744,15 @@ module GraphQL
|
|
933
744
|
if superclass <= GraphQL::Schema
|
934
745
|
superclass.default_execution_strategy
|
935
746
|
else
|
936
|
-
@default_execution_strategy ||= GraphQL::Execution::
|
747
|
+
@default_execution_strategy ||= GraphQL::Execution::Interpreter
|
748
|
+
end
|
749
|
+
end
|
750
|
+
|
751
|
+
def default_analysis_engine
|
752
|
+
if superclass <= GraphQL::Schema
|
753
|
+
superclass.default_analysis_engine
|
754
|
+
else
|
755
|
+
@default_analysis_engine ||= GraphQL::Analysis::AST
|
937
756
|
end
|
938
757
|
end
|
939
758
|
|
@@ -947,12 +766,68 @@ module GraphQL
|
|
947
766
|
|
948
767
|
def rescue_from(*err_classes, &handler_block)
|
949
768
|
err_classes.each do |err_class|
|
950
|
-
|
769
|
+
Execution::Errors.register_rescue_from(err_class, error_handlers[:subclass_handlers], handler_block)
|
770
|
+
end
|
771
|
+
end
|
772
|
+
|
773
|
+
NEW_HANDLER_HASH = ->(h, k) {
|
774
|
+
h[k] = {
|
775
|
+
class: k,
|
776
|
+
handler: nil,
|
777
|
+
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
778
|
+
}
|
779
|
+
}
|
780
|
+
|
781
|
+
def error_handlers
|
782
|
+
@error_handlers ||= {
|
783
|
+
class: nil,
|
784
|
+
handler: nil,
|
785
|
+
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
786
|
+
}
|
787
|
+
end
|
788
|
+
|
789
|
+
# @api private
|
790
|
+
def handle_or_reraise(context, err)
|
791
|
+
handler = Execution::Errors.find_handler_for(self, err.class)
|
792
|
+
if handler
|
793
|
+
obj = context[:current_object]
|
794
|
+
args = context[:current_arguments]
|
795
|
+
args = args && args.respond_to?(:keyword_arguments) ? args.keyword_arguments : nil
|
796
|
+
field = context[:current_field]
|
797
|
+
if obj.is_a?(GraphQL::Schema::Object)
|
798
|
+
obj = obj.object
|
799
|
+
end
|
800
|
+
handler[:handler].call(err, obj, args, context, field)
|
801
|
+
else
|
802
|
+
raise err
|
951
803
|
end
|
952
804
|
end
|
953
805
|
|
954
|
-
|
955
|
-
|
806
|
+
# rubocop:disable Lint/DuplicateMethods
|
807
|
+
module ResolveTypeWithType
|
808
|
+
def resolve_type(type, obj, ctx)
|
809
|
+
maybe_lazy_resolve_type_result = if type.is_a?(Module) && type.respond_to?(:resolve_type)
|
810
|
+
type.resolve_type(obj, ctx)
|
811
|
+
else
|
812
|
+
super
|
813
|
+
end
|
814
|
+
|
815
|
+
after_lazy(maybe_lazy_resolve_type_result) do |resolve_type_result|
|
816
|
+
if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
|
817
|
+
resolved_type = resolve_type_result[0]
|
818
|
+
resolved_value = resolve_type_result[1]
|
819
|
+
else
|
820
|
+
resolved_type = resolve_type_result
|
821
|
+
resolved_value = obj
|
822
|
+
end
|
823
|
+
|
824
|
+
if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind))
|
825
|
+
[resolved_type, resolved_value]
|
826
|
+
else
|
827
|
+
raise ".resolve_type should return a type definition, but got #{resolved_type.inspect} (#{resolved_type.class}) from `resolve_type(#{type}, #{obj}, #{ctx})`"
|
828
|
+
end
|
829
|
+
end
|
830
|
+
end
|
956
831
|
end
|
957
832
|
|
958
833
|
def resolve_type(type, obj, ctx)
|
@@ -962,6 +837,15 @@ module GraphQL
|
|
962
837
|
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})"
|
963
838
|
end
|
964
839
|
end
|
840
|
+
# rubocop:enable Lint/DuplicateMethods
|
841
|
+
|
842
|
+
def inherited(child_class)
|
843
|
+
if self == GraphQL::Schema
|
844
|
+
child_class.directives(default_directives.values)
|
845
|
+
end
|
846
|
+
child_class.singleton_class.prepend(ResolveTypeWithType)
|
847
|
+
super
|
848
|
+
end
|
965
849
|
|
966
850
|
def object_from_id(node_id, ctx)
|
967
851
|
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}`)"
|
@@ -971,24 +855,17 @@ module GraphQL
|
|
971
855
|
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}`)"
|
972
856
|
end
|
973
857
|
|
974
|
-
def visible?(member,
|
975
|
-
|
858
|
+
def visible?(member, ctx)
|
859
|
+
member.visible?(ctx)
|
976
860
|
end
|
977
861
|
|
978
|
-
def
|
979
|
-
|
862
|
+
def schema_directive(dir_class, **options)
|
863
|
+
@own_schema_directives ||= []
|
864
|
+
Member::HasDirectives.add_directive(self, @own_schema_directives, dir_class, options)
|
980
865
|
end
|
981
866
|
|
982
|
-
|
983
|
-
|
984
|
-
#
|
985
|
-
# By default, an error is added to the response. Override this hook to
|
986
|
-
# track metrics or return a different error to the client.
|
987
|
-
#
|
988
|
-
# @param error [InaccessibleFieldsError] The analysis error for this check
|
989
|
-
# @return [AnalysisError, nil] Return an error to skip the query
|
990
|
-
def inaccessible_fields(error)
|
991
|
-
error
|
867
|
+
def schema_directives
|
868
|
+
Member::HasDirectives.get_directives(self, @own_schema_directives, :schema_directives)
|
992
869
|
end
|
993
870
|
|
994
871
|
# This hook is called when an object fails an `authorized?` check.
|
@@ -1026,52 +903,68 @@ module GraphQL
|
|
1026
903
|
unauthorized_object(unauthorized_error)
|
1027
904
|
end
|
1028
905
|
|
1029
|
-
def type_error(
|
1030
|
-
|
906
|
+
def type_error(type_error, ctx)
|
907
|
+
case type_error
|
908
|
+
when GraphQL::InvalidNullError
|
909
|
+
ctx.errors << type_error
|
910
|
+
when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
|
911
|
+
raise type_error
|
912
|
+
when GraphQL::IntegerDecodingError
|
913
|
+
nil
|
914
|
+
end
|
1031
915
|
end
|
1032
916
|
|
1033
|
-
|
1034
|
-
|
1035
|
-
#
|
1036
|
-
|
1037
|
-
|
917
|
+
# A function to call when {#execute} receives an invalid query string
|
918
|
+
#
|
919
|
+
# The default is to add the error to `context.errors`
|
920
|
+
# @param parse_err [GraphQL::ParseError] The error encountered during parsing
|
921
|
+
# @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
|
922
|
+
# @return void
|
923
|
+
def parse_error(parse_err, ctx)
|
924
|
+
ctx.errors.push(parse_err)
|
1038
925
|
end
|
1039
926
|
|
1040
927
|
def lazy_resolve(lazy_class, value_method)
|
1041
|
-
|
928
|
+
lazy_methods.set(lazy_class, value_method)
|
1042
929
|
end
|
1043
930
|
|
1044
931
|
def instrument(instrument_step, instrumenter, options = {})
|
1045
|
-
|
1046
|
-
:field_after_built_ins
|
1047
|
-
else
|
1048
|
-
instrument_step
|
1049
|
-
end
|
1050
|
-
|
1051
|
-
own_instrumenters[step] << instrumenter
|
932
|
+
own_instrumenters[instrument_step] << instrumenter
|
1052
933
|
end
|
1053
934
|
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
935
|
+
# Add several directives at once
|
936
|
+
# @param new_directives [Class]
|
937
|
+
def directives(*new_directives)
|
938
|
+
if new_directives.any?
|
939
|
+
new_directives.flatten.each { |d| directive(d) }
|
1057
940
|
end
|
1058
941
|
|
1059
942
|
find_inherited_value(:directives, default_directives).merge(own_directives)
|
1060
943
|
end
|
1061
944
|
|
945
|
+
# Attach a single directive to this schema
|
946
|
+
# @param new_directive [Class]
|
947
|
+
# @return void
|
1062
948
|
def directive(new_directive)
|
1063
|
-
|
949
|
+
add_type_and_traverse(new_directive, root: false)
|
1064
950
|
end
|
1065
951
|
|
1066
952
|
def default_directives
|
1067
|
-
{
|
1068
|
-
"include" => GraphQL::Directive::
|
1069
|
-
"skip" => GraphQL::Directive::
|
1070
|
-
"deprecated" => GraphQL::Directive::
|
1071
|
-
|
953
|
+
@default_directives ||= {
|
954
|
+
"include" => GraphQL::Schema::Directive::Include,
|
955
|
+
"skip" => GraphQL::Schema::Directive::Skip,
|
956
|
+
"deprecated" => GraphQL::Schema::Directive::Deprecated,
|
957
|
+
"oneOf" => GraphQL::Schema::Directive::OneOf,
|
958
|
+
}.freeze
|
1072
959
|
end
|
1073
960
|
|
1074
961
|
def tracer(new_tracer)
|
962
|
+
if defined?(@trace_modes) && !(trace_class_for(:default) < GraphQL::Tracing::LegacyTrace)
|
963
|
+
raise ArgumentError, "Can't add tracer after configuring a `trace_class`, use GraphQL::Tracing::LegacyTrace to merge legacy tracers into a trace class instead."
|
964
|
+
else
|
965
|
+
trace_mode(:default, Class.new(GraphQL::Tracing::LegacyTrace))
|
966
|
+
end
|
967
|
+
|
1075
968
|
own_tracers << new_tracer
|
1076
969
|
end
|
1077
970
|
|
@@ -1079,215 +972,295 @@ module GraphQL
|
|
1079
972
|
find_inherited_value(:tracers, EMPTY_ARRAY) + own_tracers
|
1080
973
|
end
|
1081
974
|
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
975
|
+
# Mix `trace_mod` into this schema's `Trace` class so that its methods
|
976
|
+
# will be called at runtime.
|
977
|
+
#
|
978
|
+
# @param trace_mod [Module] A module that implements tracing methods
|
979
|
+
# @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
|
980
|
+
# @return [void]
|
981
|
+
def trace_with(trace_mod, **options)
|
982
|
+
trace_options.merge!(options)
|
983
|
+
trace_class.include(trace_mod)
|
1087
984
|
end
|
1088
985
|
|
1089
|
-
def
|
1090
|
-
|
986
|
+
def trace_options
|
987
|
+
@trace_options ||= superclass.respond_to?(:trace_options) ? superclass.trace_options.dup : {}
|
1091
988
|
end
|
1092
989
|
|
1093
|
-
def
|
1094
|
-
if
|
1095
|
-
|
990
|
+
def new_trace(**options)
|
991
|
+
if defined?(@trace_options)
|
992
|
+
options = trace_options.merge(options)
|
993
|
+
end
|
994
|
+
trace_mode = if (target = options[:query] || options[:multiplex]) && target.context[:backtrace]
|
995
|
+
:default_backtrace
|
1096
996
|
else
|
1097
|
-
|
997
|
+
:default
|
1098
998
|
end
|
999
|
+
trace = trace_class_for(trace_mode).new(**options)
|
1000
|
+
trace
|
1099
1001
|
end
|
1100
1002
|
|
1101
|
-
def
|
1102
|
-
|
1003
|
+
def query_analyzer(new_analyzer)
|
1004
|
+
own_query_analyzers << new_analyzer
|
1103
1005
|
end
|
1104
1006
|
|
1105
|
-
def
|
1106
|
-
find_inherited_value(:
|
1007
|
+
def query_analyzers
|
1008
|
+
find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
|
1107
1009
|
end
|
1108
1010
|
|
1109
|
-
|
1110
|
-
|
1111
|
-
def lazy_classes
|
1112
|
-
@lazy_classes ||= {}
|
1011
|
+
def multiplex_analyzer(new_analyzer)
|
1012
|
+
own_multiplex_analyzers << new_analyzer
|
1113
1013
|
end
|
1114
1014
|
|
1115
|
-
def
|
1116
|
-
|
1015
|
+
def multiplex_analyzers
|
1016
|
+
find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
|
1117
1017
|
end
|
1118
1018
|
|
1119
|
-
def
|
1120
|
-
|
1019
|
+
def sanitized_printer(new_sanitized_printer = nil)
|
1020
|
+
if new_sanitized_printer
|
1021
|
+
@own_sanitized_printer = new_sanitized_printer
|
1022
|
+
else
|
1023
|
+
@own_sanitized_printer || GraphQL::Language::SanitizedPrinter
|
1024
|
+
end
|
1121
1025
|
end
|
1122
1026
|
|
1123
|
-
|
1124
|
-
|
1027
|
+
# Execute a query on itself.
|
1028
|
+
# @see {Query#initialize} for arguments.
|
1029
|
+
# @return [Hash] query result, ready to be serialized as JSON
|
1030
|
+
def execute(query_str = nil, **kwargs)
|
1031
|
+
if query_str
|
1032
|
+
kwargs[:query] = query_str
|
1033
|
+
end
|
1034
|
+
# Some of the query context _should_ be passed to the multiplex, too
|
1035
|
+
multiplex_context = if (ctx = kwargs[:context])
|
1036
|
+
{
|
1037
|
+
backtrace: ctx[:backtrace],
|
1038
|
+
tracers: ctx[:tracers],
|
1039
|
+
dataloader: ctx[:dataloader],
|
1040
|
+
}
|
1041
|
+
else
|
1042
|
+
{}
|
1043
|
+
end
|
1044
|
+
# Since we're running one query, don't run a multiplex-level complexity analyzer
|
1045
|
+
all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
|
1046
|
+
all_results[0]
|
1125
1047
|
end
|
1126
1048
|
|
1127
|
-
|
1128
|
-
|
1049
|
+
# Execute several queries on itself, concurrently.
|
1050
|
+
#
|
1051
|
+
# @example Run several queries at once
|
1052
|
+
# context = { ... }
|
1053
|
+
# queries = [
|
1054
|
+
# { query: params[:query_1], variables: params[:variables_1], context: context },
|
1055
|
+
# { query: params[:query_2], variables: params[:variables_2], context: context },
|
1056
|
+
# ]
|
1057
|
+
# results = MySchema.multiplex(queries)
|
1058
|
+
# render json: {
|
1059
|
+
# result_1: results[0],
|
1060
|
+
# result_2: results[1],
|
1061
|
+
# }
|
1062
|
+
#
|
1063
|
+
# @see {Query#initialize} for query keyword arguments
|
1064
|
+
# @see {Execution::Multiplex#run_all} for multiplex keyword arguments
|
1065
|
+
# @param queries [Array<Hash>] Keyword arguments for each query
|
1066
|
+
# @param context [Hash] Multiplex-level context
|
1067
|
+
# @return [Array<Hash>] One result for each query in the input
|
1068
|
+
def multiplex(queries, **kwargs)
|
1069
|
+
GraphQL::Execution::Interpreter.run_all(self, queries, **kwargs)
|
1129
1070
|
end
|
1130
1071
|
|
1131
|
-
def
|
1132
|
-
inherited_instrumenters = find_inherited_value(:
|
1072
|
+
def instrumenters
|
1073
|
+
inherited_instrumenters = find_inherited_value(:instrumenters) || Hash.new { |h,k| h[k] = [] }
|
1133
1074
|
inherited_instrumenters.merge(own_instrumenters) do |_step, inherited, own|
|
1134
1075
|
inherited + own
|
1135
1076
|
end
|
1136
1077
|
end
|
1137
1078
|
|
1138
|
-
|
1139
|
-
|
1079
|
+
# @api private
|
1080
|
+
def add_subscription_extension_if_necessary
|
1081
|
+
if !defined?(@subscription_extension_added) && subscription && self.subscriptions
|
1082
|
+
@subscription_extension_added = true
|
1083
|
+
subscription.all_field_definitions.each do |field|
|
1084
|
+
if !field.extensions.any? { |ext| ext.is_a?(Subscriptions::DefaultSubscriptionResolveExtension) }
|
1085
|
+
field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
|
1086
|
+
end
|
1087
|
+
end
|
1088
|
+
end
|
1140
1089
|
end
|
1141
1090
|
|
1142
|
-
def
|
1143
|
-
|
1091
|
+
def query_stack_error(query, err)
|
1092
|
+
query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
|
1144
1093
|
end
|
1145
1094
|
|
1146
|
-
|
1147
|
-
|
1095
|
+
# Call the given block at the right time, either:
|
1096
|
+
# - Right away, if `value` is not registered with `lazy_resolve`
|
1097
|
+
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
1098
|
+
# @api private
|
1099
|
+
def after_lazy(value, &block)
|
1100
|
+
if lazy?(value)
|
1101
|
+
GraphQL::Execution::Lazy.new do
|
1102
|
+
result = sync_lazy(value)
|
1103
|
+
# The returned result might also be lazy, so check it, too
|
1104
|
+
after_lazy(result, &block)
|
1105
|
+
end
|
1106
|
+
else
|
1107
|
+
yield(value) if block_given?
|
1108
|
+
end
|
1148
1109
|
end
|
1149
1110
|
|
1150
|
-
|
1151
|
-
|
1111
|
+
# Override this method to handle lazy objects in a custom way.
|
1112
|
+
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
1113
|
+
# @return [Object] A GraphQL-ready (non-lazy) object
|
1114
|
+
# @api private
|
1115
|
+
def sync_lazy(value)
|
1116
|
+
lazy_method = lazy_method_name(value)
|
1117
|
+
if lazy_method
|
1118
|
+
synced_value = value.public_send(lazy_method)
|
1119
|
+
sync_lazy(synced_value)
|
1120
|
+
else
|
1121
|
+
value
|
1122
|
+
end
|
1152
1123
|
end
|
1153
1124
|
|
1154
|
-
|
1155
|
-
|
1125
|
+
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
|
1126
|
+
def lazy_method_name(obj)
|
1127
|
+
lazy_methods.get(obj)
|
1156
1128
|
end
|
1157
1129
|
|
1158
|
-
|
1159
|
-
|
1130
|
+
# @return [Boolean] True if this object should be lazily resolved
|
1131
|
+
def lazy?(obj)
|
1132
|
+
!!lazy_method_name(obj)
|
1160
1133
|
end
|
1161
1134
|
|
1162
|
-
#
|
1163
|
-
#
|
1164
|
-
# @
|
1165
|
-
# @
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1135
|
+
# Return a lazy if any of `maybe_lazies` are lazy,
|
1136
|
+
# otherwise, call the block eagerly and return the result.
|
1137
|
+
# @param maybe_lazies [Array]
|
1138
|
+
# @api private
|
1139
|
+
def after_any_lazies(maybe_lazies)
|
1140
|
+
if maybe_lazies.any? { |l| lazy?(l) }
|
1141
|
+
GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
|
1142
|
+
yield result
|
1143
|
+
end
|
1170
1144
|
else
|
1171
|
-
|
1145
|
+
yield maybe_lazies
|
1172
1146
|
end
|
1147
|
+
end
|
1173
1148
|
|
1174
|
-
|
1175
|
-
|
1149
|
+
private
|
1150
|
+
|
1151
|
+
# @param t [Module, Array<Module>]
|
1152
|
+
# @return [void]
|
1153
|
+
def add_type_and_traverse(t, root:)
|
1154
|
+
if root
|
1155
|
+
@root_types ||= []
|
1156
|
+
@root_types << t
|
1176
1157
|
end
|
1158
|
+
new_types = Array(t)
|
1159
|
+
addition = Schema::Addition.new(schema: self, own_types: own_types, new_types: new_types)
|
1160
|
+
addition.types.each do |name, types_entry| # rubocop:disable Development/ContextIsPassedCop -- build-time, not query-time
|
1161
|
+
if (prev_entry = own_types[name])
|
1162
|
+
prev_entries = case prev_entry
|
1163
|
+
when Array
|
1164
|
+
prev_entry
|
1165
|
+
when Module
|
1166
|
+
own_types[name] = [prev_entry]
|
1167
|
+
else
|
1168
|
+
raise "Invariant: unexpected prev_entry at #{name.inspect} when adding #{t.inspect}"
|
1169
|
+
end
|
1177
1170
|
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1171
|
+
case types_entry
|
1172
|
+
when Array
|
1173
|
+
prev_entries.concat(types_entry)
|
1174
|
+
prev_entries.uniq! # in case any are being re-visited
|
1175
|
+
when Module
|
1176
|
+
if !prev_entries.include?(types_entry)
|
1177
|
+
prev_entries << types_entry
|
1178
|
+
end
|
1179
|
+
else
|
1180
|
+
raise "Invariant: unexpected types_entry at #{name} when adding #{t.inspect}"
|
1181
|
+
end
|
1182
|
+
else
|
1183
|
+
if types_entry.is_a?(Array)
|
1184
|
+
types_entry.uniq!
|
1185
|
+
end
|
1186
|
+
own_types[name] = types_entry
|
1187
|
+
end
|
1182
1188
|
end
|
1183
|
-
end
|
1184
|
-
end
|
1185
1189
|
|
1190
|
+
own_possible_types.merge!(addition.possible_types) { |key, old_val, new_val| old_val + new_val }
|
1191
|
+
own_union_memberships.merge!(addition.union_memberships)
|
1186
1192
|
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1193
|
+
addition.references.each { |thing, pointers|
|
1194
|
+
pointers.each { |pointer| references_to(thing, from: pointer) }
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
addition.directives.each { |dir_class| own_directives[dir_class.graphql_name] = dir_class }
|
1192
1198
|
|
1193
|
-
|
1194
|
-
|
1195
|
-
def resolve_type(type, obj, ctx = :__undefined__)
|
1196
|
-
graphql_definition.check_resolved_type(type, obj, ctx) do |ok_type, ok_obj, ok_ctx|
|
1197
|
-
super(ok_type, ok_obj, ok_ctx)
|
1199
|
+
addition.arguments_with_default_values.each do |arg|
|
1200
|
+
arg.validate_default_value
|
1198
1201
|
end
|
1199
1202
|
end
|
1200
|
-
end
|
1201
1203
|
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
after_lazy(result) do |final_result|
|
1212
|
-
yield(final_result) if block_given?
|
1204
|
+
def lazy_methods
|
1205
|
+
if !defined?(@lazy_methods)
|
1206
|
+
if inherited_map = find_inherited_value(:lazy_methods)
|
1207
|
+
# this isn't _completely_ inherited :S (Things added after `dup` won't work)
|
1208
|
+
@lazy_methods = inherited_map.dup
|
1209
|
+
else
|
1210
|
+
@lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
|
1211
|
+
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
1212
|
+
@lazy_methods.set(GraphQL::Dataloader::Request, :load)
|
1213
1213
|
end
|
1214
1214
|
end
|
1215
|
-
|
1216
|
-
yield(value) if block_given?
|
1215
|
+
@lazy_methods
|
1217
1216
|
end
|
1218
|
-
end
|
1219
1217
|
|
1220
|
-
|
1221
|
-
|
1222
|
-
# @param ctx [GraphQL::Query::Context] the context for this query
|
1223
|
-
# @return [Object] A GraphQL-ready (non-lazy) object
|
1224
|
-
def self.sync_lazy(value)
|
1225
|
-
if block_given?
|
1226
|
-
# This was already hit by the instance, just give it back
|
1227
|
-
yield(value)
|
1228
|
-
else
|
1229
|
-
# This was called directly on the class, hit the instance
|
1230
|
-
# which has the lazy method map
|
1231
|
-
self.graphql_definition.sync_lazy(value)
|
1218
|
+
def own_types
|
1219
|
+
@own_types ||= {}
|
1232
1220
|
end
|
1233
|
-
end
|
1234
1221
|
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
self.class.sync_lazy(value) { |v|
|
1239
|
-
lazy_method = lazy_method_name(v)
|
1240
|
-
if lazy_method
|
1241
|
-
synced_value = value.public_send(lazy_method)
|
1242
|
-
sync_lazy(synced_value)
|
1243
|
-
else
|
1244
|
-
v
|
1245
|
-
end
|
1246
|
-
}
|
1247
|
-
end
|
1222
|
+
def non_introspection_types
|
1223
|
+
find_inherited_value(:non_introspection_types, EMPTY_HASH).merge(own_types)
|
1224
|
+
end
|
1248
1225
|
|
1249
|
-
|
1226
|
+
def own_plugins
|
1227
|
+
@own_plugins ||= []
|
1228
|
+
end
|
1250
1229
|
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1230
|
+
def own_orphan_types
|
1231
|
+
@own_orphan_types ||= []
|
1232
|
+
end
|
1254
1233
|
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
@rescue_middleware ||= GraphQL::Schema::RescueMiddleware.new.tap { |m| middleware.insert(0, m) }
|
1259
|
-
end
|
1234
|
+
def own_possible_types
|
1235
|
+
@own_possible_types ||= {}
|
1236
|
+
end
|
1260
1237
|
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
if @rebuilding_artifacts
|
1265
|
-
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."
|
1266
|
-
else
|
1267
|
-
@rebuilding_artifacts = true
|
1268
|
-
@introspection_system = Schema::IntrospectionSystem.new(self)
|
1269
|
-
traversal = Traversal.new(self)
|
1270
|
-
@types = traversal.type_map
|
1271
|
-
@root_types = [query, mutation, subscription]
|
1272
|
-
@instrumented_field_map = traversal.instrumented_field_map
|
1273
|
-
@type_reference_map = traversal.type_reference_map
|
1274
|
-
@union_memberships = traversal.union_memberships
|
1275
|
-
@find_cache = {}
|
1276
|
-
@finder = Finder.new(self)
|
1277
|
-
end
|
1278
|
-
ensure
|
1279
|
-
@rebuilding_artifacts = false
|
1280
|
-
end
|
1238
|
+
def own_union_memberships
|
1239
|
+
@own_union_memberships ||= {}
|
1240
|
+
end
|
1281
1241
|
|
1282
|
-
|
1283
|
-
|
1242
|
+
def own_directives
|
1243
|
+
@own_directives ||= {}
|
1244
|
+
end
|
1245
|
+
|
1246
|
+
def own_instrumenters
|
1247
|
+
@own_instrumenters ||= Hash.new { |h,k| h[k] = [] }
|
1248
|
+
end
|
1249
|
+
|
1250
|
+
def own_tracers
|
1251
|
+
@own_tracers ||= []
|
1252
|
+
end
|
1253
|
+
|
1254
|
+
def own_query_analyzers
|
1255
|
+
@defined_query_analyzers ||= []
|
1256
|
+
end
|
1284
1257
|
|
1285
|
-
|
1286
|
-
|
1287
|
-
raise @definition_error
|
1288
|
-
else
|
1289
|
-
yield
|
1258
|
+
def own_multiplex_analyzers
|
1259
|
+
@own_multiplex_analyzers ||= []
|
1290
1260
|
end
|
1291
1261
|
end
|
1262
|
+
|
1263
|
+
# Install these here so that subclasses will also install it.
|
1264
|
+
self.connections = GraphQL::Pagination::Connections.new(schema: self)
|
1292
1265
|
end
|
1293
1266
|
end
|