graphql 1.10.2 → 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 +24 -33
- 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 +30 -1
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +125 -117
- data/lib/graphql/analysis/ast/query_depth.rb +0 -1
- data/lib/graphql/analysis/ast/visitor.rb +52 -36
- data/lib/graphql/analysis/ast.rb +7 -8
- data/lib/graphql/analysis.rb +0 -7
- data/lib/graphql/backtrace/inspect_result.rb +0 -1
- data/lib/graphql/backtrace/table.rb +31 -18
- 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/errors.rb +77 -44
- 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 +826 -464
- data/lib/graphql/execution/interpreter.rb +206 -68
- data/lib/graphql/execution/lazy.rb +11 -21
- data/lib/graphql/execution/lookahead.rb +55 -136
- data/lib/graphql/execution/multiplex.rb +6 -162
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/filter.rb +7 -2
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +11 -5
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +4 -17
- 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 +15 -3
- data/lib/graphql/introspection/introspection_query.rb +6 -92
- data/lib/graphql/introspection/schema_type.rb +11 -6
- data/lib/graphql/introspection/type_type.rb +31 -14
- 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/document_from_schema_definition.rb +96 -44
- data/lib/graphql/language/lexer.rb +216 -1462
- data/lib/graphql/language/nodes.rb +126 -129
- data/lib/graphql/language/parser.rb +997 -933
- data/lib/graphql/language/parser.y +148 -118
- 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 +2 -0
- data/lib/graphql/name_validator.rb +2 -7
- data/lib/graphql/pagination/active_record_relation_connection.rb +45 -3
- data/lib/graphql/pagination/array_connection.rb +6 -4
- data/lib/graphql/pagination/connection.rb +105 -23
- data/lib/graphql/pagination/connections.rb +62 -35
- data/lib/graphql/pagination/relation_connection.rb +88 -36
- data/lib/graphql/parse_error.rb +0 -1
- data/lib/graphql/query/context.rb +203 -198
- 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 +36 -12
- data/lib/graphql/query.rb +92 -44
- data/lib/graphql/railtie.rb +6 -102
- data/lib/graphql/rake_task/validate.rb +1 -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 +250 -46
- data/lib/graphql/schema/base_64_encoder.rb +2 -0
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +3 -1
- data/lib/graphql/schema/build_from_definition.rb +243 -89
- data/lib/graphql/schema/directive/deprecated.rb +1 -1
- 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 +1 -1
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +108 -20
- data/lib/graphql/schema/enum.rb +105 -44
- data/lib/graphql/schema/enum_value.rb +15 -25
- data/lib/graphql/schema/field/connection_extension.rb +50 -30
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +476 -331
- data/lib/graphql/schema/field_extension.rb +86 -2
- data/lib/graphql/schema/find_inherited_value.rb +6 -8
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/input_object.rb +133 -121
- data/lib/graphql/schema/interface.rb +17 -45
- data/lib/graphql/schema/introspection_system.rb +3 -8
- data/lib/graphql/schema/late_bound_type.rb +8 -2
- data/lib/graphql/schema/list.rb +25 -8
- data/lib/graphql/schema/loader.rb +139 -103
- data/lib/graphql/schema/member/base_dsl_methods.rb +29 -35
- data/lib/graphql/schema/member/build_type.rb +19 -14
- data/lib/graphql/schema/member/has_arguments.rb +310 -26
- data/lib/graphql/schema/member/has_ast_node.rb +16 -1
- 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 +164 -42
- 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 +3 -3
- data/lib/graphql/schema/member.rb +6 -6
- data/lib/graphql/schema/mutation.rb +4 -9
- data/lib/graphql/schema/non_null.rb +12 -7
- data/lib/graphql/schema/object.rb +35 -69
- data/lib/graphql/schema/printer.rb +16 -34
- data/lib/graphql/schema/relay_classic_mutation.rb +90 -43
- data/lib/graphql/schema/resolver/has_payload_type.rb +51 -11
- data/lib/graphql/schema/resolver.rb +144 -79
- data/lib/graphql/schema/scalar.rb +27 -18
- data/lib/graphql/schema/subscription.rb +55 -26
- data/lib/graphql/schema/timeout.rb +45 -35
- data/lib/graphql/schema/type_expression.rb +1 -1
- data/lib/graphql/schema/type_membership.rb +21 -4
- data/lib/graphql/schema/union.rb +48 -13
- 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 +185 -32
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +471 -1116
- data/lib/graphql/static_validation/all_rules.rb +3 -0
- data/lib/graphql/static_validation/base_visitor.rb +13 -27
- 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 +44 -87
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +28 -22
- 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 +13 -13
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +92 -49
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- 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 +6 -7
- 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 +9 -10
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +14 -8
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +4 -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 +126 -19
- 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 +81 -35
- data/lib/graphql/subscriptions/instrumentation.rb +0 -52
- data/lib/graphql/subscriptions/serialize.rb +53 -6
- data/lib/graphql/subscriptions.rb +113 -58
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -21
- 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 +15 -0
- data/lib/graphql/tracing/data_dog_trace.rb +148 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +26 -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 +1 -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 +64 -43
- 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 +3 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/scout_tracing.rb +11 -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 -71
- 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 -92
- 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/version.rb +1 -1
- data/lib/graphql.rb +54 -65
- data/readme.md +3 -6
- metadata +116 -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 -131
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backwards_compatibility.rb +0 -60
- data/lib/graphql/base_type.rb +0 -230
- 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 -87
- 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 -53
- data/lib/graphql/define/instance_definable.rb +0 -210
- 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 -2
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -107
- data/lib/graphql/enum_type.rb +0 -127
- 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 -222
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -124
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -132
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -65
- 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 -71
- data/lib/graphql/object_type.rb +0 -121
- data/lib/graphql/query/arguments.rb +0 -188
- 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 -136
- 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 -176
- 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 -41
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -19
- 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 -105
- 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 -76
- 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 -31
- 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 -65
- data/lib/graphql/tracing/skylight_tracing.rb +0 -70
- 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 -113
- 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"
|
@@ -38,8 +31,10 @@ require "graphql/schema/union"
|
|
38
31
|
require "graphql/schema/directive"
|
39
32
|
require "graphql/schema/directive/deprecated"
|
40
33
|
require "graphql/schema/directive/include"
|
34
|
+
require "graphql/schema/directive/one_of"
|
41
35
|
require "graphql/schema/directive/skip"
|
42
36
|
require "graphql/schema/directive/feature"
|
37
|
+
require "graphql/schema/directive/flagged"
|
43
38
|
require "graphql/schema/directive/transform"
|
44
39
|
require "graphql/schema/type_membership"
|
45
40
|
|
@@ -67,7 +62,7 @@ module GraphQL
|
|
67
62
|
# Schemas can specify how queries should be executed against them.
|
68
63
|
# `query_execution_strategy`, `mutation_execution_strategy` and `subscription_execution_strategy`
|
69
64
|
# each apply to corresponding root types.
|
70
|
-
#
|
65
|
+
#
|
71
66
|
# @example defining a schema
|
72
67
|
# class MySchema < GraphQL::Schema
|
73
68
|
# query QueryType
|
@@ -76,12 +71,19 @@ module GraphQL
|
|
76
71
|
# end
|
77
72
|
#
|
78
73
|
class Schema
|
79
|
-
extend Forwardable
|
80
|
-
extend GraphQL::Schema::Member::AcceptsDefinition
|
81
74
|
extend GraphQL::Schema::Member::HasAstNode
|
82
|
-
include GraphQL::Define::InstanceDefinable
|
83
75
|
extend GraphQL::Schema::FindInheritedValue
|
84
76
|
|
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
|
85
|
+
end
|
86
|
+
|
85
87
|
class UnresolvedLateBoundTypeError < GraphQL::Error
|
86
88
|
attr_reader :type
|
87
89
|
def initialize(type:)
|
@@ -90,727 +92,121 @@ module GraphQL
|
|
90
92
|
end
|
91
93
|
end
|
92
94
|
|
93
|
-
|
94
|
-
|
95
|
-
:max_depth, :max_complexity, :default_max_page_size,
|
96
|
-
:orphan_types, :resolve_type, :type_error, :parse_error,
|
97
|
-
:error_bubbling,
|
98
|
-
:raise_definition_error,
|
99
|
-
:object_from_id, :id_from_object,
|
100
|
-
:default_mask,
|
101
|
-
:cursor_encoder,
|
102
|
-
# If these are given as classes, normalize them. Accept `nil` when building from string.
|
103
|
-
query: ->(schema, t) { schema.query = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
104
|
-
mutation: ->(schema, t) { schema.mutation = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
105
|
-
subscription: ->(schema, t) { schema.subscription = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
106
|
-
disable_introspection_entry_points: ->(schema) { schema.disable_introspection_entry_points = true },
|
107
|
-
disable_schema_introspection_entry_point: ->(schema) { schema.disable_schema_introspection_entry_point = true },
|
108
|
-
disable_type_introspection_entry_point: ->(schema) { schema.disable_type_introspection_entry_point = true },
|
109
|
-
directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.graphql_name] = d; m } },
|
110
|
-
directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
|
111
|
-
instrument: ->(schema, type, instrumenter, after_built_ins: false) {
|
112
|
-
if type == :field && after_built_ins
|
113
|
-
type = :field_after_built_ins
|
114
|
-
end
|
115
|
-
schema.instrumenters[type] << instrumenter
|
116
|
-
},
|
117
|
-
query_analyzer: ->(schema, analyzer) {
|
118
|
-
if analyzer == GraphQL::Authorization::Analyzer
|
119
|
-
warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
120
|
-
end
|
121
|
-
schema.query_analyzers << analyzer
|
122
|
-
},
|
123
|
-
multiplex_analyzer: ->(schema, analyzer) { schema.multiplex_analyzers << analyzer },
|
124
|
-
middleware: ->(schema, middleware) { schema.middleware << middleware },
|
125
|
-
lazy_resolve: ->(schema, lazy_class, lazy_value_method) { schema.lazy_methods.set(lazy_class, lazy_value_method) },
|
126
|
-
rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block) },
|
127
|
-
tracer: ->(schema, tracer) { schema.tracers.push(tracer) }
|
128
|
-
|
129
|
-
ensure_defined :introspection_system
|
130
|
-
|
131
|
-
attr_accessor \
|
132
|
-
:query, :mutation, :subscription,
|
133
|
-
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
134
|
-
:max_depth, :max_complexity, :default_max_page_size,
|
135
|
-
:orphan_types, :directives,
|
136
|
-
:query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
|
137
|
-
:cursor_encoder,
|
138
|
-
:ast_node,
|
139
|
-
:raise_definition_error,
|
140
|
-
:introspection_namespace,
|
141
|
-
:analysis_engine
|
142
|
-
|
143
|
-
# [Boolean] True if this object bubbles validation errors up from a field into its parent InputObject, if there is one.
|
144
|
-
attr_accessor :error_bubbling
|
145
|
-
|
146
|
-
# Single, long-lived instance of the provided subscriptions class, if there is one.
|
147
|
-
# @return [GraphQL::Subscriptions]
|
148
|
-
attr_accessor :subscriptions
|
149
|
-
|
150
|
-
# @return [MiddlewareChain] MiddlewareChain which is applied to fields during execution
|
151
|
-
attr_accessor :middleware
|
152
|
-
|
153
|
-
# @return [<#call(member, ctx)>] A callable for filtering members of the schema
|
154
|
-
# @see {Query.new} for query-specific filters with `except:`
|
155
|
-
attr_accessor :default_mask
|
156
|
-
|
157
|
-
# @see {GraphQL::Query::Context} The parent class of these classes
|
158
|
-
# @return [Class] Instantiated for each query
|
159
|
-
attr_accessor :context_class
|
160
|
-
|
161
|
-
# [Boolean] True if this object disables the introspection entry point fields
|
162
|
-
attr_accessor :disable_introspection_entry_points
|
163
|
-
|
164
|
-
def disable_introspection_entry_points?
|
165
|
-
!!@disable_introspection_entry_points
|
166
|
-
end
|
167
|
-
|
168
|
-
# [Boolean] True if this object disables the __schema introspection entry point field
|
169
|
-
attr_accessor :disable_schema_introspection_entry_point
|
170
|
-
|
171
|
-
def disable_schema_introspection_entry_point?
|
172
|
-
!!@disable_schema_introspection_entry_point
|
173
|
-
end
|
174
|
-
|
175
|
-
# [Boolean] True if this object disables the __type introspection entry point field
|
176
|
-
attr_accessor :disable_type_introspection_entry_point
|
177
|
-
|
178
|
-
def disable_type_introspection_entry_point?
|
179
|
-
!!@disable_type_introspection_entry_point
|
180
|
-
end
|
95
|
+
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
96
|
+
class InvalidDocumentError < Error; end;
|
181
97
|
|
182
98
|
class << self
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
207
|
-
@middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
208
|
-
@query_analyzers = []
|
209
|
-
@multiplex_analyzers = []
|
210
|
-
@resolve_type_proc = nil
|
211
|
-
@object_from_id_proc = nil
|
212
|
-
@id_from_object_proc = nil
|
213
|
-
@type_error_proc = DefaultTypeError
|
214
|
-
@parse_error_proc = DefaultParseError
|
215
|
-
@instrumenters = Hash.new { |h, k| h[k] = [] }
|
216
|
-
@lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
|
217
|
-
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
218
|
-
@cursor_encoder = Base64Encoder
|
219
|
-
# Default to the built-in execution strategy:
|
220
|
-
@analysis_engine = GraphQL::Analysis
|
221
|
-
@query_execution_strategy = self.class.default_execution_strategy
|
222
|
-
@mutation_execution_strategy = self.class.default_execution_strategy
|
223
|
-
@subscription_execution_strategy = self.class.default_execution_strategy
|
224
|
-
@default_mask = GraphQL::Schema::NullMask
|
225
|
-
@rebuilding_artifacts = false
|
226
|
-
@context_class = GraphQL::Query::Context
|
227
|
-
@introspection_namespace = nil
|
228
|
-
@introspection_system = nil
|
229
|
-
@interpreter = false
|
230
|
-
@error_bubbling = false
|
231
|
-
@disable_introspection_entry_points = false
|
232
|
-
@disable_schema_introspection_entry_point = false
|
233
|
-
@disable_type_introspection_entry_point = false
|
234
|
-
end
|
235
|
-
|
236
|
-
# @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
|
237
|
-
def interpreter?
|
238
|
-
@interpreter
|
239
|
-
end
|
240
|
-
|
241
|
-
# @api private
|
242
|
-
attr_writer :interpreter
|
243
|
-
|
244
|
-
def inspect
|
245
|
-
"#<#{self.class.name} ...>"
|
246
|
-
end
|
247
|
-
|
248
|
-
def initialize_copy(other)
|
249
|
-
super
|
250
|
-
@orphan_types = other.orphan_types.dup
|
251
|
-
@directives = other.directives.dup
|
252
|
-
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
253
|
-
@middleware = other.middleware.dup
|
254
|
-
@query_analyzers = other.query_analyzers.dup
|
255
|
-
@multiplex_analyzers = other.multiplex_analyzers.dup
|
256
|
-
@tracers = other.tracers.dup
|
257
|
-
@possible_types = GraphQL::Schema::PossibleTypes.new(self)
|
258
|
-
|
259
|
-
@lazy_methods = other.lazy_methods.dup
|
260
|
-
|
261
|
-
@instrumenters = Hash.new { |h, k| h[k] = [] }
|
262
|
-
other.instrumenters.each do |key, insts|
|
263
|
-
@instrumenters[key].concat(insts)
|
264
|
-
end
|
265
|
-
|
266
|
-
if other.rescues?
|
267
|
-
@rescue_middleware = other.rescue_middleware
|
268
|
-
end
|
269
|
-
|
270
|
-
# This will be rebuilt when it's requested
|
271
|
-
# or during a later `define` call
|
272
|
-
@types = nil
|
273
|
-
@introspection_system = nil
|
274
|
-
end
|
275
|
-
|
276
|
-
def rescue_from(*args, &block)
|
277
|
-
rescue_middleware.rescue_from(*args, &block)
|
278
|
-
end
|
279
|
-
|
280
|
-
def remove_handler(*args, &block)
|
281
|
-
rescue_middleware.remove_handler(*args, &block)
|
282
|
-
end
|
283
|
-
|
284
|
-
def using_ast_analysis?
|
285
|
-
@analysis_engine == GraphQL::Analysis::AST
|
286
|
-
end
|
287
|
-
|
288
|
-
# For forwards-compatibility with Schema classes
|
289
|
-
alias :graphql_definition :itself
|
290
|
-
|
291
|
-
# Validate a query string according to this schema.
|
292
|
-
# @param string_or_document [String, GraphQL::Language::Nodes::Document]
|
293
|
-
# @return [Array<GraphQL::StaticValidation::Error >]
|
294
|
-
def validate(string_or_document, rules: nil, context: nil)
|
295
|
-
doc = if string_or_document.is_a?(String)
|
296
|
-
GraphQL.parse(string_or_document)
|
297
|
-
else
|
298
|
-
string_or_document
|
299
|
-
end
|
300
|
-
query = GraphQL::Query.new(self, document: doc, context: context)
|
301
|
-
validator_opts = { schema: self }
|
302
|
-
rules && (validator_opts[:rules] = rules)
|
303
|
-
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
304
|
-
res = validator.validate(query)
|
305
|
-
res[:errors]
|
306
|
-
end
|
307
|
-
|
308
|
-
def define(**kwargs, &block)
|
309
|
-
super
|
310
|
-
ensure_defined
|
311
|
-
# Assert that all necessary configs are present:
|
312
|
-
validation_error = Validation.validate(self)
|
313
|
-
validation_error && raise(GraphQL::RequiredImplementationMissingError, validation_error)
|
314
|
-
rebuild_artifacts
|
315
|
-
|
316
|
-
@definition_error = nil
|
317
|
-
nil
|
318
|
-
rescue StandardError => err
|
319
|
-
if @raise_definition_error || err.is_a?(CyclicalDefinitionError) || err.is_a?(GraphQL::RequiredImplementationMissingError)
|
320
|
-
raise
|
321
|
-
else
|
322
|
-
# Raise this error _later_ to avoid messing with Rails constant loading
|
323
|
-
@definition_error = err
|
324
|
-
end
|
325
|
-
nil
|
326
|
-
end
|
327
|
-
|
328
|
-
# Attach `instrumenter` to this schema for instrumenting events of `instrumentation_type`.
|
329
|
-
# @param instrumentation_type [Symbol]
|
330
|
-
# @param instrumenter
|
331
|
-
# @return [void]
|
332
|
-
def instrument(instrumentation_type, instrumenter)
|
333
|
-
@instrumenters[instrumentation_type] << instrumenter
|
334
|
-
if instrumentation_type == :field
|
335
|
-
rebuild_artifacts
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
# @return [Array<GraphQL::BaseType>] The root types of this schema
|
340
|
-
def root_types
|
341
|
-
@root_types ||= begin
|
342
|
-
rebuild_artifacts
|
343
|
-
@root_types
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
348
|
-
# @return [GraphQL::Schema::TypeMap] `{ name => type }` pairs of types in this schema
|
349
|
-
def types
|
350
|
-
@types ||= begin
|
351
|
-
rebuild_artifacts
|
352
|
-
@types
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
def get_type(type_name)
|
357
|
-
@types[type_name]
|
358
|
-
end
|
359
|
-
|
360
|
-
# @api private
|
361
|
-
def introspection_system
|
362
|
-
@introspection_system ||= begin
|
363
|
-
rebuild_artifacts
|
364
|
-
@introspection_system
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
|
-
# Returns a list of Arguments and Fields referencing a certain type
|
369
|
-
# @param type_name [String]
|
370
|
-
# @return [Hash]
|
371
|
-
def references_to(type_name = nil)
|
372
|
-
rebuild_artifacts unless defined?(@type_reference_map)
|
373
|
-
if type_name
|
374
|
-
@type_reference_map.fetch(type_name, [])
|
375
|
-
else
|
376
|
-
@type_reference_map
|
377
|
-
end
|
378
|
-
end
|
379
|
-
|
380
|
-
# Returns a list of Union types in which a type is a member
|
381
|
-
# @param type [GraphQL::ObjectType]
|
382
|
-
# @return [Array<GraphQL::UnionType>] list of union types of which the type is a member
|
383
|
-
def union_memberships(type)
|
384
|
-
rebuild_artifacts unless defined?(@union_memberships)
|
385
|
-
@union_memberships.fetch(type.name, [])
|
386
|
-
end
|
387
|
-
|
388
|
-
# Execute a query on itself. Raises an error if the schema definition is invalid.
|
389
|
-
# @see {Query#initialize} for arguments.
|
390
|
-
# @return [Hash] query result, ready to be serialized as JSON
|
391
|
-
def execute(query_str = nil, **kwargs)
|
392
|
-
if query_str
|
393
|
-
kwargs[:query] = query_str
|
394
|
-
end
|
395
|
-
# Some of the query context _should_ be passed to the multiplex, too
|
396
|
-
multiplex_context = if (ctx = kwargs[:context])
|
397
|
-
{
|
398
|
-
backtrace: ctx[:backtrace],
|
399
|
-
tracers: ctx[:tracers],
|
400
|
-
}
|
401
|
-
else
|
402
|
-
{}
|
403
|
-
end
|
404
|
-
# Since we're running one query, don't run a multiplex-level complexity analyzer
|
405
|
-
all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
|
406
|
-
all_results[0]
|
407
|
-
end
|
408
|
-
|
409
|
-
# Execute several queries on itself. Raises an error if the schema definition is invalid.
|
410
|
-
# @example Run several queries at once
|
411
|
-
# context = { ... }
|
412
|
-
# queries = [
|
413
|
-
# { query: params[:query_1], variables: params[:variables_1], context: context },
|
414
|
-
# { query: params[:query_2], variables: params[:variables_2], context: context },
|
415
|
-
# ]
|
416
|
-
# results = MySchema.multiplex(queries)
|
417
|
-
# render json: {
|
418
|
-
# result_1: results[0],
|
419
|
-
# result_2: results[1],
|
420
|
-
# }
|
421
|
-
#
|
422
|
-
# @see {Query#initialize} for query keyword arguments
|
423
|
-
# @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
|
424
|
-
# @param queries [Array<Hash>] Keyword arguments for each query
|
425
|
-
# @param context [Hash] Multiplex-level context
|
426
|
-
# @return [Array<Hash>] One result for each query in the input
|
427
|
-
def multiplex(queries, **kwargs)
|
428
|
-
with_definition_error_check {
|
429
|
-
GraphQL::Execution::Multiplex.run_all(self, queries, **kwargs)
|
430
|
-
}
|
431
|
-
end
|
432
|
-
|
433
|
-
# Search for a schema member using a string path
|
434
|
-
# @example Finding a Field
|
435
|
-
# Schema.find("Ensemble.musicians")
|
436
|
-
#
|
437
|
-
# @see {GraphQL::Schema::Finder} for more examples
|
438
|
-
# @param path [String] A dot-separated path to the member
|
439
|
-
# @raise [Schema::Finder::MemberNotFoundError] if path could not be found
|
440
|
-
# @return [GraphQL::BaseType, GraphQL::Field, GraphQL::Argument, GraphQL::Directive] A GraphQL Schema Member
|
441
|
-
def find(path)
|
442
|
-
rebuild_artifacts unless defined?(@finder)
|
443
|
-
@find_cache[path] ||= @finder.find(path)
|
444
|
-
end
|
445
|
-
|
446
|
-
# Resolve field named `field_name` for type `parent_type`.
|
447
|
-
# Handles dynamic fields `__typename`, `__type` and `__schema`, too
|
448
|
-
# @param parent_type [String, GraphQL::BaseType]
|
449
|
-
# @param field_name [String]
|
450
|
-
# @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
|
451
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
452
|
-
def get_field(parent_type, field_name)
|
453
|
-
with_definition_error_check do
|
454
|
-
parent_type_name = case parent_type
|
455
|
-
when GraphQL::BaseType, Class, Module
|
456
|
-
parent_type.graphql_name
|
457
|
-
when String
|
458
|
-
parent_type
|
459
|
-
else
|
460
|
-
raise "Unexpected parent_type: #{parent_type}"
|
461
|
-
end
|
462
|
-
|
463
|
-
defined_field = @instrumented_field_map[parent_type_name][field_name]
|
464
|
-
if defined_field
|
465
|
-
defined_field
|
466
|
-
elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
|
467
|
-
entry_point_field
|
468
|
-
elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
|
469
|
-
dynamic_field
|
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
|
+
)
|
470
122
|
else
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
def get_fields(type)
|
479
|
-
@instrumented_field_map[type.graphql_name]
|
480
|
-
end
|
481
|
-
|
482
|
-
def type_from_ast(ast_node, context:)
|
483
|
-
GraphQL::Schema::TypeExpression.build_type(self, ast_node)
|
484
|
-
end
|
485
|
-
|
486
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
487
|
-
# @param type_defn [GraphQL::InterfaceType, GraphQL::UnionType] the type whose members you want to retrieve
|
488
|
-
# @param context [GraphQL::Query::Context] The context for the current query
|
489
|
-
# @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
|
490
|
-
def possible_types(type_defn, context = GraphQL::Query::NullContext)
|
491
|
-
@possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
|
492
|
-
@possible_types.possible_types(type_defn, context)
|
493
|
-
end
|
494
|
-
|
495
|
-
# @see [GraphQL::Schema::Warden] Resticted access to root types
|
496
|
-
# @return [GraphQL::ObjectType, nil]
|
497
|
-
def root_type_for_operation(operation)
|
498
|
-
case operation
|
499
|
-
when "query"
|
500
|
-
query
|
501
|
-
when "mutation"
|
502
|
-
mutation
|
503
|
-
when "subscription"
|
504
|
-
subscription
|
505
|
-
else
|
506
|
-
raise ArgumentError, "unknown operation type: #{operation}"
|
507
|
-
end
|
508
|
-
end
|
509
|
-
|
510
|
-
def execution_strategy_for_operation(operation)
|
511
|
-
case operation
|
512
|
-
when "query"
|
513
|
-
query_execution_strategy
|
514
|
-
when "mutation"
|
515
|
-
mutation_execution_strategy
|
516
|
-
when "subscription"
|
517
|
-
subscription_execution_strategy
|
518
|
-
else
|
519
|
-
raise ArgumentError, "unknown operation type: #{operation}"
|
520
|
-
end
|
521
|
-
end
|
522
|
-
|
523
|
-
# Determine the GraphQL type for a given object.
|
524
|
-
# This is required for unions and interfaces (including Relay's `Node` interface)
|
525
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
526
|
-
# @param type [GraphQL::UnionType, GraphQL:InterfaceType] the abstract type which is being resolved
|
527
|
-
# @param object [Any] An application object which GraphQL is currently resolving on
|
528
|
-
# @param ctx [GraphQL::Query::Context] The context for the current query
|
529
|
-
# @return [GraphQL::ObjectType] The type for exposing `object` in GraphQL
|
530
|
-
def resolve_type(type, object, ctx = :__undefined__)
|
531
|
-
check_resolved_type(type, object, ctx) do |ok_type, ok_object, ok_ctx|
|
532
|
-
if @resolve_type_proc.nil?
|
533
|
-
raise(GraphQL::RequiredImplementationMissingError, "Can't determine GraphQL type for: #{ok_object.inspect}, define `resolve_type (type, obj, ctx) -> { ... }` inside `Schema.define`.")
|
123
|
+
GraphQL::Schema::BuildFromDefinition.from_definition(
|
124
|
+
self,
|
125
|
+
definition_or_path,
|
126
|
+
default_resolve: default_resolve,
|
127
|
+
parser: parser,
|
128
|
+
using: using,
|
129
|
+
)
|
534
130
|
end
|
535
|
-
@resolve_type_proc.call(ok_type, ok_object, ok_ctx)
|
536
131
|
end
|
537
|
-
end
|
538
132
|
|
539
|
-
|
540
|
-
|
541
|
-
# @api private
|
542
|
-
def check_resolved_type(type, object, ctx = :__undefined__)
|
543
|
-
if ctx == :__undefined__
|
544
|
-
# Old method signature
|
545
|
-
ctx = object
|
546
|
-
object = type
|
547
|
-
type = nil
|
133
|
+
def deprecated_graphql_definition
|
134
|
+
graphql_definition(silence_deprecation_warning: true)
|
548
135
|
end
|
549
136
|
|
550
|
-
|
551
|
-
|
137
|
+
# @return [GraphQL::Subscriptions]
|
138
|
+
def subscriptions(inherited: true)
|
139
|
+
defined?(@subscriptions) ? @subscriptions : (inherited ? find_inherited_value(:subscriptions, nil) : nil)
|
552
140
|
end
|
553
141
|
|
554
|
-
|
555
|
-
|
142
|
+
def subscriptions=(new_implementation)
|
143
|
+
@subscriptions = new_implementation
|
556
144
|
end
|
557
145
|
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
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)
|
564
154
|
end
|
565
155
|
|
566
|
-
if
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
if
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
type_str = "#{resolved_type_result} (#{resolved_type_result.class.name})"
|
575
|
-
raise "resolve_type(#{object}) returned #{type_str}, but it should return a GraphQL type"
|
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
|
576
164
|
else
|
577
|
-
|
165
|
+
GraphQL::Tracing::Trace
|
578
166
|
end
|
167
|
+
Class.new(base_class)
|
579
168
|
end
|
580
169
|
end
|
581
|
-
end
|
582
|
-
|
583
|
-
def resolve_type=(new_resolve_type_proc)
|
584
|
-
callable = GraphQL::BackwardsCompatibility.wrap_arity(new_resolve_type_proc, from: 2, to: 3, last: true, name: "Schema#resolve_type(type, obj, ctx)")
|
585
|
-
@resolve_type_proc = callable
|
586
|
-
end
|
587
|
-
|
588
|
-
# Fetch an application object by its unique id
|
589
|
-
# @param id [String] A unique identifier, provided previously by this GraphQL schema
|
590
|
-
# @param ctx [GraphQL::Query::Context] The context for the current query
|
591
|
-
# @return [Any] The application object identified by `id`
|
592
|
-
def object_from_id(id, ctx)
|
593
|
-
if @object_from_id_proc.nil?
|
594
|
-
raise(GraphQL::RequiredImplementationMissingError, "Can't fetch an object for id \"#{id}\" because the schema's `object_from_id (id, ctx) -> { ... }` function is not defined")
|
595
|
-
else
|
596
|
-
@object_from_id_proc.call(id, ctx)
|
597
|
-
end
|
598
|
-
end
|
599
|
-
|
600
|
-
# @param new_proc [#call] A new callable for fetching objects by ID
|
601
|
-
def object_from_id=(new_proc)
|
602
|
-
@object_from_id_proc = new_proc
|
603
|
-
end
|
604
|
-
|
605
|
-
# When we encounter a type error during query execution, we call this hook.
|
606
|
-
#
|
607
|
-
# You can use this hook to write a log entry,
|
608
|
-
# add a {GraphQL::ExecutionError} to the response (with `ctx.add_error`)
|
609
|
-
# or raise an exception and halt query execution.
|
610
|
-
#
|
611
|
-
# @example A `nil` is encountered by a non-null field
|
612
|
-
# type_error ->(err, query_ctx) {
|
613
|
-
# err.is_a?(GraphQL::InvalidNullError) # => true
|
614
|
-
# }
|
615
|
-
#
|
616
|
-
# @example An object doesn't resolve to one of a {UnionType}'s members
|
617
|
-
# type_error ->(err, query_ctx) {
|
618
|
-
# err.is_a?(GraphQL::UnresolvedTypeError) # => true
|
619
|
-
# }
|
620
|
-
#
|
621
|
-
# @see {DefaultTypeError} is the default behavior.
|
622
|
-
# @param err [GraphQL::TypeError] The error encountered during execution
|
623
|
-
# @param ctx [GraphQL::Query::Context] The context for the field where the error occurred
|
624
|
-
# @return void
|
625
|
-
def type_error(err, ctx)
|
626
|
-
@type_error_proc.call(err, ctx)
|
627
|
-
end
|
628
|
-
|
629
|
-
# @param new_proc [#call] A new callable for handling type errors during execution
|
630
|
-
def type_error=(new_proc)
|
631
|
-
@type_error_proc = new_proc
|
632
|
-
end
|
633
|
-
|
634
|
-
# Can't delegate to `class`
|
635
|
-
alias :_schema_class :class
|
636
|
-
def_delegators :_schema_class, :unauthorized_object, :unauthorized_field, :inaccessible_fields
|
637
|
-
def_delegators :_schema_class, :directive
|
638
|
-
def_delegators :_schema_class, :error_handler
|
639
|
-
|
640
|
-
|
641
|
-
# Given this schema member, find the class-based definition object
|
642
|
-
# whose `method_name` should be treated as an application hook
|
643
|
-
# @see {.visible?}
|
644
|
-
# @see {.accessible?}
|
645
|
-
def call_on_type_class(member, method_name, context, default:)
|
646
|
-
member = if member.respond_to?(:type_class)
|
647
|
-
member.type_class
|
648
|
-
else
|
649
|
-
member
|
650
|
-
end
|
651
|
-
|
652
|
-
if member.respond_to?(:relay_node_type) && (t = member.relay_node_type)
|
653
|
-
member = t
|
654
|
-
end
|
655
|
-
|
656
|
-
if member.respond_to?(method_name)
|
657
|
-
member.public_send(method_name, context)
|
658
|
-
else
|
659
|
-
default
|
660
|
-
end
|
661
|
-
end
|
662
|
-
|
663
|
-
def visible?(member, context)
|
664
|
-
call_on_type_class(member, :visible?, context, default: true)
|
665
|
-
end
|
666
|
-
|
667
|
-
def accessible?(member, context)
|
668
|
-
call_on_type_class(member, :accessible?, context, default: true)
|
669
|
-
end
|
670
|
-
|
671
|
-
# A function to call when {#execute} receives an invalid query string
|
672
|
-
#
|
673
|
-
# @see {DefaultParseError} is the default behavior.
|
674
|
-
# @param err [GraphQL::ParseError] The error encountered during parsing
|
675
|
-
# @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
|
676
|
-
# @return void
|
677
|
-
def parse_error(err, ctx)
|
678
|
-
@parse_error_proc.call(err, ctx)
|
679
|
-
end
|
680
|
-
|
681
|
-
# @param new_proc [#call] A new callable for handling parse errors during execution
|
682
|
-
def parse_error=(new_proc)
|
683
|
-
@parse_error_proc = new_proc
|
684
|
-
end
|
685
170
|
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
@id_from_object_proc.call(object, type, ctx)
|
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
|
696
180
|
end
|
697
|
-
end
|
698
|
-
|
699
|
-
# @param new_proc [#call] A new callable for generating unique IDs
|
700
|
-
def id_from_object=(new_proc)
|
701
|
-
@id_from_object_proc = new_proc
|
702
|
-
end
|
703
|
-
|
704
|
-
# Create schema with the result of an introspection query.
|
705
|
-
# @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
|
706
|
-
# @return [GraphQL::Schema] the schema described by `input`
|
707
|
-
def self.from_introspection(introspection_result)
|
708
|
-
GraphQL::Schema::Loader.load(introspection_result)
|
709
|
-
end
|
710
|
-
|
711
|
-
# Create schema from an IDL schema or file containing an IDL definition.
|
712
|
-
# @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
|
713
|
-
# @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
|
714
|
-
# @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
|
715
|
-
# @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
|
716
|
-
# @param interpreter [Boolean] If false, the legacy {Execution::Execute} runtime will be used
|
717
|
-
# @return [Class] the schema described by `document`
|
718
|
-
def self.from_definition(definition_or_path, default_resolve: BuildFromDefinition::DefaultResolve, interpreter: true, parser: BuildFromDefinition::DefaultParser, using: {})
|
719
|
-
# If the file ends in `.graphql`, treat it like a filepath
|
720
|
-
definition = if definition_or_path.end_with?(".graphql")
|
721
|
-
File.read(definition_or_path)
|
722
|
-
else
|
723
|
-
definition_or_path
|
724
|
-
end
|
725
|
-
GraphQL::Schema::BuildFromDefinition.from_definition(definition, default_resolve: default_resolve, parser: parser, using: using, interpreter: interpreter)
|
726
|
-
end
|
727
|
-
|
728
|
-
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
729
|
-
class InvalidDocumentError < Error; end;
|
730
|
-
|
731
|
-
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered wtih {#lazy_resolve}.
|
732
|
-
def lazy_method_name(obj)
|
733
|
-
@lazy_methods.get(obj)
|
734
|
-
end
|
735
181
|
|
736
|
-
# @return [Boolean] True if this object should be lazily resolved
|
737
|
-
def lazy?(obj)
|
738
|
-
!!lazy_method_name(obj)
|
739
|
-
end
|
740
|
-
|
741
|
-
# Return the GraphQL IDL for the schema
|
742
|
-
# @param context [Hash]
|
743
|
-
# @param only [<#call(member, ctx)>]
|
744
|
-
# @param except [<#call(member, ctx)>]
|
745
|
-
# @return [String]
|
746
|
-
def to_definition(only: nil, except: nil, context: {})
|
747
|
-
GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
|
748
|
-
end
|
749
|
-
|
750
|
-
# Return the GraphQL::Language::Document IDL AST for the schema
|
751
|
-
# @param context [Hash]
|
752
|
-
# @param only [<#call(member, ctx)>]
|
753
|
-
# @param except [<#call(member, ctx)>]
|
754
|
-
# @return [GraphQL::Language::Document]
|
755
|
-
def to_document(only: nil, except: nil, context: {})
|
756
|
-
GraphQL::Language::DocumentFromSchemaDefinition.new(self, only: only, except: except, context: context).document
|
757
|
-
end
|
758
|
-
|
759
|
-
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
760
|
-
# @param context [Hash]
|
761
|
-
# @param only [<#call(member, ctx)>]
|
762
|
-
# @param except [<#call(member, ctx)>]
|
763
|
-
# @return [Hash] GraphQL result
|
764
|
-
def as_json(only: nil, except: nil, context: {})
|
765
|
-
execute(Introspection::INTROSPECTION_QUERY, only: only, except: except, context: context).to_h
|
766
|
-
end
|
767
|
-
|
768
|
-
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
769
|
-
# @see {#as_json}
|
770
|
-
# @return [String]
|
771
|
-
def to_json(*args)
|
772
|
-
JSON.pretty_generate(as_json(*args))
|
773
|
-
end
|
774
|
-
|
775
|
-
def new_connections?
|
776
|
-
!!connections
|
777
|
-
end
|
778
|
-
|
779
|
-
attr_accessor :connections
|
780
|
-
|
781
|
-
class << self
|
782
|
-
extend Forwardable
|
783
|
-
# For compatibility, these methods all:
|
784
|
-
# - Cause the Schema instance to be created, if it hasn't been created yet
|
785
|
-
# - Delegate to that instance
|
786
|
-
# Eventually, the methods will be moved into this class, removing the need for the singleton.
|
787
|
-
def_delegators :graphql_definition,
|
788
|
-
# Execution
|
789
|
-
:execution_strategy_for_operation,
|
790
|
-
:validate, :multiplex_analyzers,
|
791
|
-
# Configuration
|
792
|
-
:metadata, :redefine,
|
793
|
-
:id_from_object_proc, :object_from_id_proc,
|
794
|
-
:id_from_object=, :object_from_id=,
|
795
|
-
:remove_handler
|
796
|
-
|
797
|
-
# @return [GraphQL::Subscriptions]
|
798
|
-
attr_accessor :subscriptions
|
799
182
|
|
800
183
|
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
801
184
|
# @see {#as_json}
|
802
185
|
# @return [String]
|
803
|
-
def to_json(
|
804
|
-
JSON.pretty_generate(as_json(
|
186
|
+
def to_json(**args)
|
187
|
+
JSON.pretty_generate(as_json(**args))
|
805
188
|
end
|
806
189
|
|
807
190
|
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
808
191
|
# @param context [Hash]
|
809
192
|
# @param only [<#call(member, ctx)>]
|
810
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
|
811
199
|
# @return [Hash] GraphQL result
|
812
|
-
def as_json(only: nil, except: nil, context: {})
|
813
|
-
|
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
|
814
210
|
end
|
815
211
|
|
816
212
|
# Return the GraphQL IDL for the schema
|
@@ -828,6 +224,17 @@ module GraphQL
|
|
828
224
|
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
829
225
|
end
|
830
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
|
233
|
+
else
|
234
|
+
find_inherited_value(:description, nil)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
831
238
|
def find(path)
|
832
239
|
if !@finder
|
833
240
|
@find_cache = {}
|
@@ -836,12 +243,8 @@ module GraphQL
|
|
836
243
|
@find_cache[path] ||= @finder.find(path)
|
837
244
|
end
|
838
245
|
|
839
|
-
def graphql_definition
|
840
|
-
@graphql_definition ||= to_graphql
|
841
|
-
end
|
842
|
-
|
843
246
|
def default_filter
|
844
|
-
GraphQL::Filter.new(except: default_mask)
|
247
|
+
GraphQL::Filter.new(except: default_mask, silence_deprecation_warning: true)
|
845
248
|
end
|
846
249
|
|
847
250
|
def default_mask(new_mask = nil)
|
@@ -869,81 +272,85 @@ module GraphQL
|
|
869
272
|
find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
|
870
273
|
end
|
871
274
|
|
872
|
-
def to_graphql
|
873
|
-
schema_defn = self.new
|
874
|
-
schema_defn.raise_definition_error = true
|
875
|
-
schema_defn.query = query && query.graphql_definition
|
876
|
-
schema_defn.mutation = mutation && mutation.graphql_definition
|
877
|
-
schema_defn.subscription = subscription && subscription.graphql_definition
|
878
|
-
schema_defn.max_complexity = max_complexity
|
879
|
-
schema_defn.error_bubbling = error_bubbling
|
880
|
-
schema_defn.max_depth = max_depth
|
881
|
-
schema_defn.default_max_page_size = default_max_page_size
|
882
|
-
schema_defn.orphan_types = orphan_types.map(&:graphql_definition)
|
883
|
-
schema_defn.disable_introspection_entry_points = disable_introspection_entry_points?
|
884
|
-
schema_defn.disable_schema_introspection_entry_point = disable_schema_introspection_entry_point?
|
885
|
-
schema_defn.disable_type_introspection_entry_point = disable_type_introspection_entry_point?
|
886
|
-
|
887
|
-
prepped_dirs = {}
|
888
|
-
directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
|
889
|
-
schema_defn.directives = prepped_dirs
|
890
|
-
schema_defn.introspection_namespace = introspection
|
891
|
-
schema_defn.resolve_type = method(:resolve_type)
|
892
|
-
schema_defn.object_from_id = method(:object_from_id)
|
893
|
-
schema_defn.id_from_object = method(:id_from_object)
|
894
|
-
schema_defn.type_error = method(:type_error)
|
895
|
-
schema_defn.context_class = context_class
|
896
|
-
schema_defn.cursor_encoder = cursor_encoder
|
897
|
-
schema_defn.tracers.concat(tracers)
|
898
|
-
schema_defn.query_analyzers.concat(query_analyzers)
|
899
|
-
|
900
|
-
schema_defn.middleware.concat(all_middleware)
|
901
|
-
schema_defn.multiplex_analyzers.concat(multiplex_analyzers)
|
902
|
-
schema_defn.query_execution_strategy = query_execution_strategy
|
903
|
-
schema_defn.mutation_execution_strategy = mutation_execution_strategy
|
904
|
-
schema_defn.subscription_execution_strategy = subscription_execution_strategy
|
905
|
-
schema_defn.default_mask = default_mask
|
906
|
-
instrumenters.each do |step, insts|
|
907
|
-
insts.each do |inst|
|
908
|
-
schema_defn.instrumenters[step] << inst
|
909
|
-
end
|
910
|
-
end
|
911
|
-
|
912
|
-
lazy_methods.each do |lazy_class, value_method|
|
913
|
-
schema_defn.lazy_methods.set(lazy_class, value_method)
|
914
|
-
end
|
915
|
-
|
916
|
-
rescues.each do |err_class, handler|
|
917
|
-
schema_defn.rescue_from(err_class, &handler)
|
918
|
-
end
|
919
|
-
|
920
|
-
schema_defn.subscriptions ||= self.subscriptions
|
921
|
-
|
922
|
-
if !schema_defn.interpreter?
|
923
|
-
schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
|
924
|
-
end
|
925
|
-
schema_defn.send(:rebuild_artifacts)
|
926
|
-
|
927
|
-
schema_defn
|
928
|
-
end
|
929
|
-
|
930
275
|
# Build a map of `{ name => type }` and return it
|
931
276
|
# @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
|
932
277
|
# @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
|
933
|
-
def types
|
934
|
-
non_introspection_types.merge(introspection_system.types)
|
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
|
296
|
+
else
|
297
|
+
v
|
298
|
+
end
|
299
|
+
end
|
300
|
+
visible_types
|
935
301
|
end
|
936
302
|
|
937
303
|
# @param type_name [String]
|
938
304
|
# @return [Module, nil] A type, or nil if there's no type called `type_name`
|
939
|
-
def get_type(type_name)
|
940
|
-
own_types[type_name]
|
941
|
-
|
942
|
-
|
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
|
330
|
+
|
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)
|
943
334
|
end
|
944
335
|
|
336
|
+
# @api private
|
337
|
+
attr_writer :connections
|
338
|
+
|
945
339
|
# @return [GraphQL::Pagination::Connections] if installed
|
946
|
-
|
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
|
353
|
+
end
|
947
354
|
|
948
355
|
def new_connections?
|
949
356
|
!!connections
|
@@ -983,6 +390,7 @@ module GraphQL
|
|
983
390
|
raise GraphQL::Error, "Second definition of `subscription(...)` (#{new_subscription_object.inspect}) is invalid, already configured with #{@subscription_object.inspect}"
|
984
391
|
else
|
985
392
|
@subscription_object = new_subscription_object
|
393
|
+
add_subscription_extension_if_necessary
|
986
394
|
add_type_and_traverse(new_subscription_object, root: true)
|
987
395
|
nil
|
988
396
|
end
|
@@ -991,7 +399,7 @@ module GraphQL
|
|
991
399
|
end
|
992
400
|
end
|
993
401
|
|
994
|
-
# @see [GraphQL::Schema::Warden]
|
402
|
+
# @see [GraphQL::Schema::Warden] Restricted access to root types
|
995
403
|
# @return [GraphQL::ObjectType, nil]
|
996
404
|
def root_type_for_operation(operation)
|
997
405
|
case operation
|
@@ -1019,7 +427,15 @@ module GraphQL
|
|
1019
427
|
if type.kind.union?
|
1020
428
|
type.possible_types(context: context)
|
1021
429
|
else
|
1022
|
-
own_possible_types[type.graphql_name]
|
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)
|
434
|
+
end
|
435
|
+
else
|
436
|
+
stored_possible_types
|
437
|
+
end
|
438
|
+
visible_possible_types ||
|
1023
439
|
introspection_system.possible_types[type.graphql_name] ||
|
1024
440
|
(
|
1025
441
|
superclass.respond_to?(:possible_types) ?
|
@@ -1049,6 +465,14 @@ module GraphQL
|
|
1049
465
|
end
|
1050
466
|
end
|
1051
467
|
|
468
|
+
# @api private
|
469
|
+
# @see GraphQL::Dataloader
|
470
|
+
def dataloader_class
|
471
|
+
@dataloader_class || GraphQL::Dataloader::NullDataloader
|
472
|
+
end
|
473
|
+
|
474
|
+
attr_writer :dataloader_class
|
475
|
+
|
1052
476
|
def references_to(to_type = nil, from: nil)
|
1053
477
|
@own_references_to ||= Hash.new { |h, k| h[k] = [] }
|
1054
478
|
if to_type
|
@@ -1081,19 +505,19 @@ module GraphQL
|
|
1081
505
|
GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
|
1082
506
|
end
|
1083
507
|
|
1084
|
-
def get_field(type_or_name, field_name)
|
508
|
+
def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext)
|
1085
509
|
parent_type = case type_or_name
|
1086
510
|
when LateBoundType
|
1087
|
-
get_type(type_or_name.name)
|
511
|
+
get_type(type_or_name.name, context)
|
1088
512
|
when String
|
1089
|
-
get_type(type_or_name)
|
513
|
+
get_type(type_or_name, context)
|
1090
514
|
when Module
|
1091
515
|
type_or_name
|
1092
516
|
else
|
1093
|
-
raise
|
517
|
+
raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
|
1094
518
|
end
|
1095
519
|
|
1096
|
-
if parent_type.kind.fields? && (field = parent_type.get_field(field_name))
|
520
|
+
if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
|
1097
521
|
field
|
1098
522
|
elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
|
1099
523
|
entry_point_field
|
@@ -1104,8 +528,8 @@ module GraphQL
|
|
1104
528
|
end
|
1105
529
|
end
|
1106
530
|
|
1107
|
-
def get_fields(type)
|
1108
|
-
type.fields
|
531
|
+
def get_fields(type, context = GraphQL::Query::NullContext)
|
532
|
+
type.fields(context)
|
1109
533
|
end
|
1110
534
|
|
1111
535
|
def introspection(new_introspection_namespace = nil)
|
@@ -1141,6 +565,14 @@ module GraphQL
|
|
1141
565
|
end
|
1142
566
|
end
|
1143
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
|
+
|
1144
576
|
def query_execution_strategy(new_query_execution_strategy = nil)
|
1145
577
|
if new_query_execution_strategy
|
1146
578
|
@query_execution_strategy = new_query_execution_strategy
|
@@ -1165,6 +597,47 @@ module GraphQL
|
|
1165
597
|
end
|
1166
598
|
end
|
1167
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
|
+
|
1168
641
|
attr_writer :max_complexity
|
1169
642
|
|
1170
643
|
def max_complexity(max_complexity = nil)
|
@@ -1180,19 +653,15 @@ module GraphQL
|
|
1180
653
|
attr_writer :analysis_engine
|
1181
654
|
|
1182
655
|
def analysis_engine
|
1183
|
-
@analysis_engine || find_inherited_value(:analysis_engine,
|
656
|
+
@analysis_engine || find_inherited_value(:analysis_engine, self.default_analysis_engine)
|
1184
657
|
end
|
1185
658
|
|
1186
659
|
def using_ast_analysis?
|
1187
|
-
|
660
|
+
true
|
1188
661
|
end
|
1189
662
|
|
1190
663
|
def interpreter?
|
1191
|
-
|
1192
|
-
@interpreter
|
1193
|
-
else
|
1194
|
-
find_inherited_value(:interpreter?, false)
|
1195
|
-
end
|
664
|
+
true
|
1196
665
|
end
|
1197
666
|
|
1198
667
|
attr_writer :interpreter
|
@@ -1265,7 +734,6 @@ module GraphQL
|
|
1265
734
|
if new_orphan_types.any?
|
1266
735
|
new_orphan_types = new_orphan_types.flatten
|
1267
736
|
add_type_and_traverse(new_orphan_types, root: false)
|
1268
|
-
@orphan_types = new_orphan_types
|
1269
737
|
own_orphan_types.concat(new_orphan_types.flatten)
|
1270
738
|
end
|
1271
739
|
|
@@ -1276,7 +744,15 @@ module GraphQL
|
|
1276
744
|
if superclass <= GraphQL::Schema
|
1277
745
|
superclass.default_execution_strategy
|
1278
746
|
else
|
1279
|
-
@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
|
1280
756
|
end
|
1281
757
|
end
|
1282
758
|
|
@@ -1290,22 +766,63 @@ module GraphQL
|
|
1290
766
|
|
1291
767
|
def rescue_from(*err_classes, &handler_block)
|
1292
768
|
err_classes.each do |err_class|
|
1293
|
-
|
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
|
1294
803
|
end
|
1295
804
|
end
|
1296
805
|
|
1297
806
|
# rubocop:disable Lint/DuplicateMethods
|
1298
807
|
module ResolveTypeWithType
|
1299
808
|
def resolve_type(type, obj, ctx)
|
1300
|
-
|
809
|
+
maybe_lazy_resolve_type_result = if type.is_a?(Module) && type.respond_to?(:resolve_type)
|
1301
810
|
type.resolve_type(obj, ctx)
|
1302
811
|
else
|
1303
812
|
super
|
1304
813
|
end
|
1305
814
|
|
1306
|
-
after_lazy(
|
1307
|
-
if
|
1308
|
-
resolved_type
|
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]
|
1309
826
|
else
|
1310
827
|
raise ".resolve_type should return a type definition, but got #{resolved_type.inspect} (#{resolved_type.class}) from `resolve_type(#{type}, #{obj}, #{ctx})`"
|
1311
828
|
end
|
@@ -1330,10 +847,6 @@ module GraphQL
|
|
1330
847
|
super
|
1331
848
|
end
|
1332
849
|
|
1333
|
-
def rescues
|
1334
|
-
find_inherited_value(:rescues, EMPTY_HASH).merge(own_rescues)
|
1335
|
-
end
|
1336
|
-
|
1337
850
|
def object_from_id(node_id, ctx)
|
1338
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}`)"
|
1339
852
|
end
|
@@ -1343,23 +856,16 @@ module GraphQL
|
|
1343
856
|
end
|
1344
857
|
|
1345
858
|
def visible?(member, ctx)
|
1346
|
-
member.
|
859
|
+
member.visible?(ctx)
|
1347
860
|
end
|
1348
861
|
|
1349
|
-
def
|
1350
|
-
|
862
|
+
def schema_directive(dir_class, **options)
|
863
|
+
@own_schema_directives ||= []
|
864
|
+
Member::HasDirectives.add_directive(self, @own_schema_directives, dir_class, options)
|
1351
865
|
end
|
1352
866
|
|
1353
|
-
|
1354
|
-
|
1355
|
-
#
|
1356
|
-
# By default, an error is added to the response. Override this hook to
|
1357
|
-
# track metrics or return a different error to the client.
|
1358
|
-
#
|
1359
|
-
# @param error [InaccessibleFieldsError] The analysis error for this check
|
1360
|
-
# @return [AnalysisError, nil] Return an error to skip the query
|
1361
|
-
def inaccessible_fields(error)
|
1362
|
-
error
|
867
|
+
def schema_directives
|
868
|
+
Member::HasDirectives.get_directives(self, @own_schema_directives, :schema_directives)
|
1363
869
|
end
|
1364
870
|
|
1365
871
|
# This hook is called when an object fails an `authorized?` check.
|
@@ -1397,45 +903,40 @@ module GraphQL
|
|
1397
903
|
unauthorized_object(unauthorized_error)
|
1398
904
|
end
|
1399
905
|
|
1400
|
-
def type_error(
|
1401
|
-
|
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
|
1402
915
|
end
|
1403
916
|
|
1404
917
|
# A function to call when {#execute} receives an invalid query string
|
1405
918
|
#
|
1406
919
|
# The default is to add the error to `context.errors`
|
1407
|
-
# @param
|
920
|
+
# @param parse_err [GraphQL::ParseError] The error encountered during parsing
|
1408
921
|
# @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
|
1409
922
|
# @return void
|
1410
923
|
def parse_error(parse_err, ctx)
|
1411
924
|
ctx.errors.push(parse_err)
|
1412
925
|
end
|
1413
|
-
attr_writer :error_handler
|
1414
|
-
|
1415
|
-
# @return [GraphQL::Execution::Errors, Class<GraphQL::Execution::Errors::NullErrorHandler>]
|
1416
|
-
def error_handler
|
1417
|
-
@error_handler ||= GraphQL::Execution::Errors::NullErrorHandler
|
1418
|
-
end
|
1419
926
|
|
1420
927
|
def lazy_resolve(lazy_class, value_method)
|
1421
928
|
lazy_methods.set(lazy_class, value_method)
|
1422
929
|
end
|
1423
930
|
|
1424
931
|
def instrument(instrument_step, instrumenter, options = {})
|
1425
|
-
|
1426
|
-
:field_after_built_ins
|
1427
|
-
else
|
1428
|
-
instrument_step
|
1429
|
-
end
|
1430
|
-
|
1431
|
-
own_instrumenters[step] << instrumenter
|
932
|
+
own_instrumenters[instrument_step] << instrumenter
|
1432
933
|
end
|
1433
934
|
|
1434
935
|
# Add several directives at once
|
1435
936
|
# @param new_directives [Class]
|
1436
|
-
def directives(new_directives
|
1437
|
-
if new_directives
|
1438
|
-
new_directives.each { |d| directive(d) }
|
937
|
+
def directives(*new_directives)
|
938
|
+
if new_directives.any?
|
939
|
+
new_directives.flatten.each { |d| directive(d) }
|
1439
940
|
end
|
1440
941
|
|
1441
942
|
find_inherited_value(:directives, default_directives).merge(own_directives)
|
@@ -1443,20 +944,27 @@ module GraphQL
|
|
1443
944
|
|
1444
945
|
# Attach a single directive to this schema
|
1445
946
|
# @param new_directive [Class]
|
947
|
+
# @return void
|
1446
948
|
def directive(new_directive)
|
1447
949
|
add_type_and_traverse(new_directive, root: false)
|
1448
|
-
own_directives[new_directive.graphql_name] = new_directive
|
1449
950
|
end
|
1450
951
|
|
1451
952
|
def default_directives
|
1452
|
-
{
|
953
|
+
@default_directives ||= {
|
1453
954
|
"include" => GraphQL::Schema::Directive::Include,
|
1454
955
|
"skip" => GraphQL::Schema::Directive::Skip,
|
1455
956
|
"deprecated" => GraphQL::Schema::Directive::Deprecated,
|
1456
|
-
|
957
|
+
"oneOf" => GraphQL::Schema::Directive::OneOf,
|
958
|
+
}.freeze
|
1457
959
|
end
|
1458
960
|
|
1459
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
|
+
|
1460
968
|
own_tracers << new_tracer
|
1461
969
|
end
|
1462
970
|
|
@@ -1464,24 +972,40 @@ module GraphQL
|
|
1464
972
|
find_inherited_value(:tracers, EMPTY_ARRAY) + own_tracers
|
1465
973
|
end
|
1466
974
|
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
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)
|
1472
984
|
end
|
1473
985
|
|
1474
|
-
def
|
1475
|
-
|
986
|
+
def trace_options
|
987
|
+
@trace_options ||= superclass.respond_to?(:trace_options) ? superclass.trace_options.dup : {}
|
1476
988
|
end
|
1477
989
|
|
1478
|
-
def
|
1479
|
-
if
|
1480
|
-
|
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
|
1481
996
|
else
|
1482
|
-
|
1483
|
-
MiddlewareChain.new(steps: all_middleware, final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
997
|
+
:default
|
1484
998
|
end
|
999
|
+
trace = trace_class_for(trace_mode).new(**options)
|
1000
|
+
trace
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
def query_analyzer(new_analyzer)
|
1004
|
+
own_query_analyzers << new_analyzer
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
def query_analyzers
|
1008
|
+
find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
|
1485
1009
|
end
|
1486
1010
|
|
1487
1011
|
def multiplex_analyzer(new_analyzer)
|
@@ -1492,6 +1016,14 @@ module GraphQL
|
|
1492
1016
|
find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
|
1493
1017
|
end
|
1494
1018
|
|
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
|
1025
|
+
end
|
1026
|
+
|
1495
1027
|
# Execute a query on itself.
|
1496
1028
|
# @see {Query#initialize} for arguments.
|
1497
1029
|
# @return [Hash] query result, ready to be serialized as JSON
|
@@ -1504,6 +1036,7 @@ module GraphQL
|
|
1504
1036
|
{
|
1505
1037
|
backtrace: ctx[:backtrace],
|
1506
1038
|
tracers: ctx[:tracers],
|
1039
|
+
dataloader: ctx[:dataloader],
|
1507
1040
|
}
|
1508
1041
|
else
|
1509
1042
|
{}
|
@@ -1528,17 +1061,12 @@ module GraphQL
|
|
1528
1061
|
# }
|
1529
1062
|
#
|
1530
1063
|
# @see {Query#initialize} for query keyword arguments
|
1531
|
-
# @see {Execution::Multiplex#
|
1064
|
+
# @see {Execution::Multiplex#run_all} for multiplex keyword arguments
|
1532
1065
|
# @param queries [Array<Hash>] Keyword arguments for each query
|
1533
1066
|
# @param context [Hash] Multiplex-level context
|
1534
1067
|
# @return [Array<Hash>] One result for each query in the input
|
1535
1068
|
def multiplex(queries, **kwargs)
|
1536
|
-
|
1537
|
-
self
|
1538
|
-
else
|
1539
|
-
graphql_definition
|
1540
|
-
end
|
1541
|
-
GraphQL::Execution::Multiplex.run_all(schema, queries, **kwargs)
|
1069
|
+
GraphQL::Execution::Interpreter.run_all(self, queries, **kwargs)
|
1542
1070
|
end
|
1543
1071
|
|
1544
1072
|
def instrumenters
|
@@ -1548,18 +1076,32 @@ module GraphQL
|
|
1548
1076
|
end
|
1549
1077
|
end
|
1550
1078
|
|
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
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
def query_stack_error(query, err)
|
1092
|
+
query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
|
1093
|
+
end
|
1094
|
+
|
1551
1095
|
# Call the given block at the right time, either:
|
1552
1096
|
# - Right away, if `value` is not registered with `lazy_resolve`
|
1553
1097
|
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
1554
1098
|
# @api private
|
1555
|
-
def after_lazy(value)
|
1099
|
+
def after_lazy(value, &block)
|
1556
1100
|
if lazy?(value)
|
1557
1101
|
GraphQL::Execution::Lazy.new do
|
1558
1102
|
result = sync_lazy(value)
|
1559
1103
|
# The returned result might also be lazy, so check it, too
|
1560
|
-
after_lazy(result)
|
1561
|
-
yield(final_result) if block_given?
|
1562
|
-
end
|
1104
|
+
after_lazy(result, &block)
|
1563
1105
|
end
|
1564
1106
|
else
|
1565
1107
|
yield(value) if block_given?
|
@@ -1568,8 +1110,8 @@ module GraphQL
|
|
1568
1110
|
|
1569
1111
|
# Override this method to handle lazy objects in a custom way.
|
1570
1112
|
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
1571
|
-
# @param ctx [GraphQL::Query::Context] the context for this query
|
1572
1113
|
# @return [Object] A GraphQL-ready (non-lazy) object
|
1114
|
+
# @api private
|
1573
1115
|
def sync_lazy(value)
|
1574
1116
|
lazy_method = lazy_method_name(value)
|
1575
1117
|
if lazy_method
|
@@ -1580,7 +1122,7 @@ module GraphQL
|
|
1580
1122
|
end
|
1581
1123
|
end
|
1582
1124
|
|
1583
|
-
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered
|
1125
|
+
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
|
1584
1126
|
def lazy_method_name(obj)
|
1585
1127
|
lazy_methods.get(obj)
|
1586
1128
|
end
|
@@ -1590,8 +1132,75 @@ module GraphQL
|
|
1590
1132
|
!!lazy_method_name(obj)
|
1591
1133
|
end
|
1592
1134
|
|
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
|
1144
|
+
else
|
1145
|
+
yield maybe_lazies
|
1146
|
+
end
|
1147
|
+
end
|
1148
|
+
|
1593
1149
|
private
|
1594
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
|
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
|
1170
|
+
|
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
|
1188
|
+
end
|
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)
|
1192
|
+
|
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 }
|
1198
|
+
|
1199
|
+
addition.arguments_with_default_values.each do |arg|
|
1200
|
+
arg.validate_default_value
|
1201
|
+
end
|
1202
|
+
end
|
1203
|
+
|
1595
1204
|
def lazy_methods
|
1596
1205
|
if !defined?(@lazy_methods)
|
1597
1206
|
if inherited_map = find_inherited_value(:lazy_methods)
|
@@ -1600,6 +1209,7 @@ module GraphQL
|
|
1600
1209
|
else
|
1601
1210
|
@lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
|
1602
1211
|
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
1212
|
+
@lazy_methods.set(GraphQL::Dataloader::Request, :load)
|
1603
1213
|
end
|
1604
1214
|
end
|
1605
1215
|
@lazy_methods
|
@@ -1617,10 +1227,6 @@ module GraphQL
|
|
1617
1227
|
@own_plugins ||= []
|
1618
1228
|
end
|
1619
1229
|
|
1620
|
-
def own_rescues
|
1621
|
-
@own_rescues ||= {}
|
1622
|
-
end
|
1623
|
-
|
1624
1230
|
def own_orphan_types
|
1625
1231
|
@own_orphan_types ||= []
|
1626
1232
|
end
|
@@ -1649,263 +1255,12 @@ module GraphQL
|
|
1649
1255
|
@defined_query_analyzers ||= []
|
1650
1256
|
end
|
1651
1257
|
|
1652
|
-
def all_middleware
|
1653
|
-
find_inherited_value(:all_middleware, EMPTY_ARRAY) + own_middleware
|
1654
|
-
end
|
1655
|
-
|
1656
|
-
def own_middleware
|
1657
|
-
@own_middleware ||= []
|
1658
|
-
end
|
1659
|
-
|
1660
1258
|
def own_multiplex_analyzers
|
1661
1259
|
@own_multiplex_analyzers ||= []
|
1662
1260
|
end
|
1663
|
-
|
1664
|
-
# @param t [Module, Array<Module>]
|
1665
|
-
# @return [void]
|
1666
|
-
def add_type_and_traverse(t, root:)
|
1667
|
-
if root
|
1668
|
-
@root_types ||= []
|
1669
|
-
@root_types << t
|
1670
|
-
end
|
1671
|
-
late_types = []
|
1672
|
-
new_types = Array(t)
|
1673
|
-
new_types.each { |t| add_type(t, owner: nil, late_types: late_types) }
|
1674
|
-
missed_late_types = 0
|
1675
|
-
while (late_type_vals = late_types.shift)
|
1676
|
-
type_owner, lt = late_type_vals
|
1677
|
-
if lt.is_a?(String)
|
1678
|
-
type = Member::BuildType.constantize(lt)
|
1679
|
-
# Reset the counter, since we might succeed next go-round
|
1680
|
-
missed_late_types = 0
|
1681
|
-
update_type_owner(type_owner, type)
|
1682
|
-
add_type(type, owner: type_owner, late_types: late_types)
|
1683
|
-
elsif lt.is_a?(LateBoundType)
|
1684
|
-
if (type = get_type(lt.graphql_name))
|
1685
|
-
# Reset the counter, since we might succeed next go-round
|
1686
|
-
missed_late_types = 0
|
1687
|
-
update_type_owner(type_owner, type)
|
1688
|
-
add_type(type, owner: type_owner, late_types: late_types)
|
1689
|
-
else
|
1690
|
-
missed_late_types += 1
|
1691
|
-
# Add it back to the list, maybe we'll be able to resolve it later.
|
1692
|
-
late_types << [type_owner, lt]
|
1693
|
-
if missed_late_types == late_types.size
|
1694
|
-
# We've looked at all of them and haven't resolved one.
|
1695
|
-
raise UnresolvedLateBoundTypeError.new(type: lt)
|
1696
|
-
else
|
1697
|
-
# Try the next one
|
1698
|
-
end
|
1699
|
-
end
|
1700
|
-
else
|
1701
|
-
raise ArgumentError, "Unexpected late type: #{lt.inspect}"
|
1702
|
-
end
|
1703
|
-
end
|
1704
|
-
nil
|
1705
|
-
end
|
1706
|
-
|
1707
|
-
def update_type_owner(owner, type)
|
1708
|
-
case owner
|
1709
|
-
when Class
|
1710
|
-
if owner.kind.union?
|
1711
|
-
# It's a union with possible_types
|
1712
|
-
# Replace the item by class name
|
1713
|
-
owner.type_memberships.each { |tm|
|
1714
|
-
possible_type = tm.object_type
|
1715
|
-
if possible_type.is_a?(String) && (possible_type == type.name)
|
1716
|
-
# This is a match of Ruby class names, not graphql names,
|
1717
|
-
# since strings are used to refer to constants.
|
1718
|
-
tm.object_type = type
|
1719
|
-
elsif possible_type.is_a?(LateBoundType) && possible_type.graphql_name == type.graphql_name
|
1720
|
-
tm.object_type = type
|
1721
|
-
end
|
1722
|
-
}
|
1723
|
-
own_possible_types[owner.graphql_name] = owner.possible_types
|
1724
|
-
elsif type.kind.interface? && owner.kind.object?
|
1725
|
-
new_interfaces = owner.interfaces.map do |t|
|
1726
|
-
if t.is_a?(String) && t == type.graphql_name
|
1727
|
-
type
|
1728
|
-
elsif t.is_a?(LateBoundType) && t.graphql_name == type.graphql_name
|
1729
|
-
type
|
1730
|
-
else
|
1731
|
-
t
|
1732
|
-
end
|
1733
|
-
end
|
1734
|
-
owner.implements(*new_interfaces)
|
1735
|
-
end
|
1736
|
-
|
1737
|
-
when nil
|
1738
|
-
# It's a root type
|
1739
|
-
own_types[type.graphql_name] = type
|
1740
|
-
when GraphQL::Schema::Field, GraphQL::Schema::Argument
|
1741
|
-
orig_type = owner.type
|
1742
|
-
# Apply list/non-null wrapper as needed
|
1743
|
-
if orig_type.respond_to?(:of_type)
|
1744
|
-
transforms = []
|
1745
|
-
while (orig_type.respond_to?(:of_type))
|
1746
|
-
if orig_type.kind.non_null?
|
1747
|
-
transforms << :to_non_null_type
|
1748
|
-
elsif orig_type.kind.list?
|
1749
|
-
transforms << :to_list_type
|
1750
|
-
else
|
1751
|
-
raise "Invariant: :of_type isn't non-null or list"
|
1752
|
-
end
|
1753
|
-
orig_type = orig_type.of_type
|
1754
|
-
end
|
1755
|
-
transforms.reverse_each { |t| type = type.public_send(t) }
|
1756
|
-
end
|
1757
|
-
owner.type = type
|
1758
|
-
else
|
1759
|
-
raise "Unexpected update: #{owner.inspect} #{type.inspect}"
|
1760
|
-
end
|
1761
|
-
end
|
1762
|
-
|
1763
|
-
def add_type(type, owner:, late_types:)
|
1764
|
-
if type.respond_to?(:metadata) && type.metadata.is_a?(Hash)
|
1765
|
-
type_class = type.metadata[:type_class]
|
1766
|
-
if type_class.nil?
|
1767
|
-
raise ArgumentError, "Can't add legacy type: #{type} (#{type.class})"
|
1768
|
-
else
|
1769
|
-
type = type_class
|
1770
|
-
end
|
1771
|
-
elsif type.is_a?(String) || type.is_a?(GraphQL::Schema::LateBoundType)
|
1772
|
-
late_types << [owner, type]
|
1773
|
-
return
|
1774
|
-
end
|
1775
|
-
|
1776
|
-
if owner.is_a?(Class) && owner < GraphQL::Schema::Union
|
1777
|
-
um = own_union_memberships[type.graphql_name] ||= []
|
1778
|
-
um << owner
|
1779
|
-
end
|
1780
|
-
|
1781
|
-
if (prev_type = own_types[type.graphql_name])
|
1782
|
-
if prev_type != type
|
1783
|
-
raise ArgumentError, "Conflicting type definitions for `#{type.graphql_name}`: #{prev_type} (#{prev_type.class}), #{type} #{type.class}"
|
1784
|
-
else
|
1785
|
-
# This type was already added
|
1786
|
-
end
|
1787
|
-
elsif type.is_a?(Class) && type < GraphQL::Schema::Directive
|
1788
|
-
type.arguments.each do |_name, arg|
|
1789
|
-
arg_type = arg.type.unwrap
|
1790
|
-
references_to(arg_type, from: arg)
|
1791
|
-
add_type(arg_type, owner: arg, late_types: late_types)
|
1792
|
-
end
|
1793
|
-
else
|
1794
|
-
own_types[type.graphql_name] = type
|
1795
|
-
if type.kind.fields?
|
1796
|
-
type.fields.each do |_name, field|
|
1797
|
-
field_type = field.type.unwrap
|
1798
|
-
references_to(field_type, from: field)
|
1799
|
-
add_type(field_type, owner: field, late_types: late_types)
|
1800
|
-
field.arguments.each do |_name, arg|
|
1801
|
-
arg_type = arg.type.unwrap
|
1802
|
-
references_to(arg_type, from: arg)
|
1803
|
-
add_type(arg_type, owner: arg, late_types: late_types)
|
1804
|
-
end
|
1805
|
-
end
|
1806
|
-
end
|
1807
|
-
if type.kind.input_object?
|
1808
|
-
type.arguments.each do |_name, arg|
|
1809
|
-
arg_type = arg.type.unwrap
|
1810
|
-
references_to(arg_type, from: arg)
|
1811
|
-
add_type(arg_type, owner: arg, late_types: late_types)
|
1812
|
-
end
|
1813
|
-
end
|
1814
|
-
if type.kind.union?
|
1815
|
-
own_possible_types[type.graphql_name] = type.possible_types
|
1816
|
-
type.possible_types.each do |t|
|
1817
|
-
add_type(t, owner: type, late_types: late_types)
|
1818
|
-
end
|
1819
|
-
end
|
1820
|
-
if type.kind.interface?
|
1821
|
-
type.orphan_types.each do |t|
|
1822
|
-
add_type(t, owner: type, late_types: late_types)
|
1823
|
-
end
|
1824
|
-
end
|
1825
|
-
if type.kind.object?
|
1826
|
-
own_possible_types[type.graphql_name] = [type]
|
1827
|
-
type.interfaces.each do |i|
|
1828
|
-
implementers = own_possible_types[i.graphql_name] ||= []
|
1829
|
-
implementers << type
|
1830
|
-
add_type(i, owner: type, late_types: late_types)
|
1831
|
-
end
|
1832
|
-
end
|
1833
|
-
end
|
1834
|
-
end
|
1835
1261
|
end
|
1836
1262
|
|
1837
|
-
#
|
1838
|
-
|
1839
|
-
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
1840
|
-
# @api private
|
1841
|
-
def after_lazy(value)
|
1842
|
-
if lazy?(value)
|
1843
|
-
GraphQL::Execution::Lazy.new do
|
1844
|
-
result = sync_lazy(value)
|
1845
|
-
# The returned result might also be lazy, so check it, too
|
1846
|
-
after_lazy(result) do |final_result|
|
1847
|
-
yield(final_result) if block_given?
|
1848
|
-
end
|
1849
|
-
end
|
1850
|
-
else
|
1851
|
-
yield(value) if block_given?
|
1852
|
-
end
|
1853
|
-
end
|
1854
|
-
|
1855
|
-
# @see Schema.sync_lazy for a hook to override
|
1856
|
-
# @api private
|
1857
|
-
def sync_lazy(value)
|
1858
|
-
lazy_method = lazy_method_name(value)
|
1859
|
-
if lazy_method
|
1860
|
-
synced_value = value.public_send(lazy_method)
|
1861
|
-
sync_lazy(synced_value)
|
1862
|
-
else
|
1863
|
-
value
|
1864
|
-
end
|
1865
|
-
end
|
1866
|
-
|
1867
|
-
protected
|
1868
|
-
|
1869
|
-
def rescues?
|
1870
|
-
!!@rescue_middleware
|
1871
|
-
end
|
1872
|
-
|
1873
|
-
# Lazily create a middleware and add it to the schema
|
1874
|
-
# (Don't add it if it's not used)
|
1875
|
-
def rescue_middleware
|
1876
|
-
@rescue_middleware ||= GraphQL::Schema::RescueMiddleware.new.tap { |m| middleware.insert(0, m) }
|
1877
|
-
end
|
1878
|
-
|
1879
|
-
private
|
1880
|
-
|
1881
|
-
def rebuild_artifacts
|
1882
|
-
if @rebuilding_artifacts
|
1883
|
-
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."
|
1884
|
-
else
|
1885
|
-
@rebuilding_artifacts = true
|
1886
|
-
@introspection_system = Schema::IntrospectionSystem.new(self)
|
1887
|
-
traversal = Traversal.new(self)
|
1888
|
-
@types = traversal.type_map
|
1889
|
-
@root_types = [query, mutation, subscription]
|
1890
|
-
@instrumented_field_map = traversal.instrumented_field_map
|
1891
|
-
@type_reference_map = traversal.type_reference_map
|
1892
|
-
@union_memberships = traversal.union_memberships
|
1893
|
-
@find_cache = {}
|
1894
|
-
@finder = Finder.new(self)
|
1895
|
-
end
|
1896
|
-
ensure
|
1897
|
-
@rebuilding_artifacts = false
|
1898
|
-
end
|
1899
|
-
|
1900
|
-
class CyclicalDefinitionError < GraphQL::Error
|
1901
|
-
end
|
1902
|
-
|
1903
|
-
def with_definition_error_check
|
1904
|
-
if @definition_error
|
1905
|
-
raise @definition_error
|
1906
|
-
else
|
1907
|
-
yield
|
1908
|
-
end
|
1909
|
-
end
|
1263
|
+
# Install these here so that subclasses will also install it.
|
1264
|
+
self.connections = GraphQL::Pagination::Connections.new(schema: self)
|
1910
1265
|
end
|
1911
1266
|
end
|