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