graphql 1.12.12 → 2.2.14
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 +3 -8
- 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 +14 -4
- data/lib/generators/graphql/interface_generator.rb +7 -7
- 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 +5 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +10 -38
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +23 -12
- 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 +2 -0
- data/lib/generators/graphql/templates/base_edge.erb +2 -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_resolver.erb +6 -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 +5 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +4 -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 +2 -0
- data/lib/generators/graphql/templates/object.erb +4 -2
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/scalar.erb +3 -1
- data/lib/generators/graphql/templates/schema.erb +19 -2
- data/lib/generators/graphql/templates/union.erb +4 -2
- data/lib/generators/graphql/type_generator.rb +46 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/ast/analyzer.rb +7 -0
- data/lib/graphql/analysis/ast/field_usage.rb +55 -1
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +88 -140
- data/lib/graphql/analysis/ast/query_depth.rb +7 -3
- data/lib/graphql/analysis/ast/visitor.rb +50 -42
- data/lib/graphql/analysis/ast.rb +26 -23
- data/lib/graphql/analysis.rb +0 -7
- data/lib/graphql/backtrace/table.rb +4 -22
- data/lib/graphql/backtrace/trace.rb +93 -0
- data/lib/graphql/backtrace/tracer.rb +8 -6
- data/lib/graphql/backtrace.rb +3 -8
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/dataloader/async_dataloader.rb +85 -0
- data/lib/graphql/dataloader/null_dataloader.rb +3 -1
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +120 -31
- data/lib/graphql/dataloader.rb +168 -142
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/dig.rb +1 -1
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/errors.rb +12 -81
- data/lib/graphql/execution/interpreter/arguments.rb +2 -2
- data/lib/graphql/execution/interpreter/arguments_cache.rb +36 -34
- data/lib/graphql/execution/interpreter/resolve.rb +32 -2
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +170 -0
- data/lib/graphql/execution/interpreter/runtime.rb +414 -341
- data/lib/graphql/execution/interpreter.rb +122 -80
- data/lib/graphql/execution/lazy.rb +11 -21
- data/lib/graphql/execution/lookahead.rb +125 -54
- data/lib/graphql/execution/multiplex.rb +4 -172
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +5 -3
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +11 -18
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +3 -3
- data/lib/graphql/introspection/input_value_type.rb +10 -4
- data/lib/graphql/introspection/schema_type.rb +12 -5
- data/lib/graphql/introspection/type_type.rb +25 -12
- data/lib/graphql/introspection.rb +6 -2
- data/lib/graphql/language/block_string.rb +37 -25
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +78 -65
- data/lib/graphql/language/lexer.rb +345 -1467
- data/lib/graphql/language/nodes.rb +145 -91
- data/lib/graphql/language/parser.rb +701 -1921
- data/lib/graphql/language/printer.rb +351 -155
- data/lib/graphql/language/sanitized_printer.rb +25 -27
- data/lib/graphql/language/static_visitor.rb +167 -0
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/language/visitor.rb +188 -141
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/name_validator.rb +0 -4
- data/lib/graphql/pagination/active_record_relation_connection.rb +37 -8
- data/lib/graphql/pagination/array_connection.rb +8 -6
- data/lib/graphql/pagination/connection.rb +61 -7
- data/lib/graphql/pagination/connections.rb +22 -23
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/pagination/relation_connection.rb +60 -28
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +109 -189
- data/lib/graphql/query/input_validation_result.rb +10 -1
- data/lib/graphql/query/null_context.rb +14 -29
- data/lib/graphql/query/validation_pipeline.rb +15 -39
- data/lib/graphql/query/variable_validation_error.rb +2 -2
- data/lib/graphql/query/variables.rb +35 -17
- data/lib/graphql/query.rb +78 -65
- data/lib/graphql/railtie.rb +8 -109
- data/lib/graphql/rake_task/validate.rb +1 -1
- data/lib/graphql/rake_task.rb +30 -11
- data/lib/graphql/relay/range_add.rb +9 -16
- 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 +78 -45
- data/lib/graphql/schema/always_visible.rb +10 -0
- data/lib/graphql/schema/argument.rb +134 -80
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +60 -38
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +2 -2
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/one_of.rb +24 -0
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive/transform.rb +2 -2
- data/lib/graphql/schema/directive.rb +33 -21
- data/lib/graphql/schema/enum.rb +93 -46
- data/lib/graphql/schema/enum_value.rb +4 -21
- data/lib/graphql/schema/field/connection_extension.rb +6 -16
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +432 -337
- data/lib/graphql/schema/field_extension.rb +86 -2
- data/lib/graphql/schema/find_inherited_value.rb +3 -7
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/has_single_input_argument.rb +156 -0
- data/lib/graphql/schema/input_object.rb +88 -90
- data/lib/graphql/schema/interface.rb +19 -59
- data/lib/graphql/schema/introspection_system.rb +6 -9
- data/lib/graphql/schema/late_bound_type.rb +8 -2
- data/lib/graphql/schema/list.rb +18 -7
- data/lib/graphql/schema/loader.rb +3 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -19
- data/lib/graphql/schema/member/build_type.rb +16 -13
- data/lib/graphql/schema/member/has_arguments.rb +288 -84
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +149 -31
- data/lib/graphql/schema/member/has_interfaces.rb +143 -0
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
- data/lib/graphql/schema/member/validates_input.rb +6 -6
- data/lib/graphql/schema/member.rb +1 -6
- data/lib/graphql/schema/mutation.rb +0 -9
- data/lib/graphql/schema/non_null.rb +7 -7
- data/lib/graphql/schema/object.rb +30 -119
- data/lib/graphql/schema/printer.rb +23 -25
- data/lib/graphql/schema/relay_classic_mutation.rb +13 -90
- data/lib/graphql/schema/resolver/has_payload_type.rb +46 -11
- data/lib/graphql/schema/resolver.rb +101 -102
- data/lib/graphql/schema/scalar.rb +20 -21
- data/lib/graphql/schema/subscription.rb +45 -17
- data/lib/graphql/schema/timeout.rb +25 -29
- data/lib/graphql/schema/type_expression.rb +1 -1
- data/lib/graphql/schema/type_membership.rb +21 -4
- data/lib/graphql/schema/union.rb +15 -15
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- 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 +3 -1
- data/lib/graphql/schema/validator/format_validator.rb +4 -5
- data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/length_validator.rb +5 -3
- data/lib/graphql/schema/validator/numericality_validator.rb +13 -2
- data/lib/graphql/schema/validator/required_validator.rb +29 -15
- data/lib/graphql/schema/validator.rb +35 -27
- data/lib/graphql/schema/warden.rb +259 -132
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +658 -989
- data/lib/graphql/static_validation/all_rules.rb +3 -1
- data/lib/graphql/static_validation/base_visitor.rb +14 -28
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -2
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +21 -4
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +13 -13
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +54 -28
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -3
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +13 -7
- data/lib/graphql/static_validation/validation_context.rb +16 -6
- data/lib/graphql/static_validation/validator.rb +11 -27
- data/lib/graphql/static_validation.rb +0 -3
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +46 -9
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
- data/lib/graphql/subscriptions/event.rb +75 -37
- data/lib/graphql/subscriptions/serialize.rb +25 -3
- data/lib/graphql/subscriptions.rb +59 -47
- data/lib/graphql/testing/helpers.rb +129 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
- data/lib/graphql/tracing/appoptics_trace.rb +251 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
- data/lib/graphql/tracing/appsignal_trace.rb +77 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
- data/lib/graphql/tracing/data_dog_trace.rb +183 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +25 -15
- data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +10 -28
- data/lib/graphql/tracing/legacy_trace.rb +69 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +45 -0
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_trace.rb +118 -0
- data/lib/graphql/tracing/platform_tracing.rb +46 -49
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +4 -2
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/sentry_trace.rb +112 -0
- data/lib/graphql/tracing/statsd_trace.rb +56 -0
- data/lib/graphql/tracing/trace.rb +76 -0
- data/lib/graphql/tracing.rb +20 -41
- data/lib/graphql/type_kinds.rb +6 -3
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/iso_8601_date.rb +17 -6
- data/lib/graphql/types/iso_8601_date_time.rb +12 -1
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/base_connection.rb +16 -6
- data/lib/graphql/types/relay/connection_behaviors.rb +82 -32
- data/lib/graphql/types/relay/edge_behaviors.rb +36 -7
- data/lib/graphql/types/relay/has_node_field.rb +2 -2
- data/lib/graphql/types/relay/has_nodes_field.rb +2 -2
- data/lib/graphql/types/relay/node_behaviors.rb +12 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
- data/lib/graphql/types/relay.rb +0 -3
- data/lib/graphql/types/string.rb +2 -2
- data/lib/graphql/types.rb +1 -0
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +33 -95
- data/readme.md +13 -6
- metadata +102 -185
- data/lib/graphql/analysis/analyze_query.rb +0 -98
- data/lib/graphql/analysis/field_usage.rb +0 -45
- data/lib/graphql/analysis/max_query_complexity.rb +0 -26
- data/lib/graphql/analysis/max_query_depth.rb +0 -26
- data/lib/graphql/analysis/query_complexity.rb +0 -88
- data/lib/graphql/analysis/query_depth.rb +0 -43
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -131
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
- data/lib/graphql/backwards_compatibility.rb +0 -61
- data/lib/graphql/base_type.rb +0 -230
- data/lib/graphql/boolean_type.rb +0 -2
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
- data/lib/graphql/compatibility/execution_specification.rb +0 -436
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
- 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 -240
- 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 -47
- data/lib/graphql/deprecation.rb +0 -13
- data/lib/graphql/directive/deprecated_directive.rb +0 -2
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -111
- data/lib/graphql/enum_type.rb +0 -129
- data/lib/graphql/execution/execute.rb +0 -333
- data/lib/graphql/execution/flatten.rb +0 -40
- data/lib/graphql/execution/lazy/resolve.rb +0 -91
- data/lib/graphql/execution/typecast.rb +0 -50
- data/lib/graphql/field/resolve.rb +0 -59
- data/lib/graphql/field.rb +0 -226
- data/lib/graphql/filter.rb +0 -53
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -128
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -138
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -72
- data/lib/graphql/internal_representation/document.rb +0 -27
- data/lib/graphql/internal_representation/node.rb +0 -206
- data/lib/graphql/internal_representation/print.rb +0 -51
- data/lib/graphql/internal_representation/rewrite.rb +0 -184
- data/lib/graphql/internal_representation/scope.rb +0 -88
- data/lib/graphql/internal_representation/visit.rb +0 -36
- data/lib/graphql/internal_representation.rb +0 -7
- data/lib/graphql/language/lexer.rl +0 -262
- data/lib/graphql/language/parser.y +0 -543
- data/lib/graphql/list_type.rb +0 -80
- data/lib/graphql/non_null_type.rb +0 -71
- data/lib/graphql/object_type.rb +0 -130
- data/lib/graphql/query/arguments.rb +0 -189
- data/lib/graphql/query/arguments_cache.rb +0 -24
- data/lib/graphql/query/executor.rb +0 -52
- data/lib/graphql/query/literal_input.rb +0 -136
- data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
- data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
- data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
- data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
- data/lib/graphql/query/serial_execution.rb +0 -40
- data/lib/graphql/relay/array_connection.rb +0 -83
- data/lib/graphql/relay/base_connection.rb +0 -189
- data/lib/graphql/relay/connection_instrumentation.rb +0 -54
- data/lib/graphql/relay/connection_resolve.rb +0 -43
- data/lib/graphql/relay/connection_type.rb +0 -41
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -19
- data/lib/graphql/relay/edges_instrumentation.rb +0 -40
- data/lib/graphql/relay/global_id_resolve.rb +0 -18
- data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
- data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
- data/lib/graphql/relay/mutation/resolve.rb +0 -56
- data/lib/graphql/relay/mutation/result.rb +0 -38
- data/lib/graphql/relay/mutation.rb +0 -106
- data/lib/graphql/relay/node.rb +0 -39
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -188
- data/lib/graphql/relay/type_extensions.rb +0 -32
- data/lib/graphql/scalar_type.rb +0 -91
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- 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 -17
- data/lib/graphql/schema/member/accepts_definition.rb +0 -152
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -31
- data/lib/graphql/schema/member/instrumentation.rb +0 -131
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/possible_types.rb +0 -44
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -88
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -313
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/instrumentation.rb +0 -79
- data/lib/graphql/subscriptions/subscription_root.rb +0 -76
- data/lib/graphql/tracing/skylight_tracing.rb +0 -70
- data/lib/graphql/types/relay/default_relay.rb +0 -27
- data/lib/graphql/types/relay/node_field.rb +0 -25
- data/lib/graphql/types/relay/nodes_field.rb +0 -27
- data/lib/graphql/union_type.rb +0 -115
- data/lib/graphql/upgrader/member.rb +0 -937
- data/lib/graphql/upgrader/schema.rb +0 -38
data/lib/graphql/schema.rb
CHANGED
@@ -1,24 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require "logger"
|
2
3
|
require "graphql/schema/addition"
|
4
|
+
require "graphql/schema/always_visible"
|
3
5
|
require "graphql/schema/base_64_encoder"
|
4
|
-
require "graphql/schema/catchall_middleware"
|
5
|
-
require "graphql/schema/default_parse_error"
|
6
|
-
require "graphql/schema/default_type_error"
|
7
6
|
require "graphql/schema/find_inherited_value"
|
8
7
|
require "graphql/schema/finder"
|
9
8
|
require "graphql/schema/invalid_type_error"
|
10
9
|
require "graphql/schema/introspection_system"
|
11
10
|
require "graphql/schema/late_bound_type"
|
12
|
-
require "graphql/schema/middleware_chain"
|
13
11
|
require "graphql/schema/null_mask"
|
14
|
-
require "graphql/schema/possible_types"
|
15
|
-
require "graphql/schema/rescue_middleware"
|
16
12
|
require "graphql/schema/timeout"
|
17
|
-
require "graphql/schema/timeout_middleware"
|
18
|
-
require "graphql/schema/traversal"
|
19
13
|
require "graphql/schema/type_expression"
|
20
14
|
require "graphql/schema/unique_within_type"
|
21
|
-
require "graphql/schema/validation"
|
22
15
|
require "graphql/schema/warden"
|
23
16
|
require "graphql/schema/build_from_definition"
|
24
17
|
|
@@ -40,14 +33,17 @@ require "graphql/schema/union"
|
|
40
33
|
require "graphql/schema/directive"
|
41
34
|
require "graphql/schema/directive/deprecated"
|
42
35
|
require "graphql/schema/directive/include"
|
36
|
+
require "graphql/schema/directive/one_of"
|
43
37
|
require "graphql/schema/directive/skip"
|
44
38
|
require "graphql/schema/directive/feature"
|
45
39
|
require "graphql/schema/directive/flagged"
|
46
40
|
require "graphql/schema/directive/transform"
|
41
|
+
require "graphql/schema/directive/specified_by"
|
47
42
|
require "graphql/schema/type_membership"
|
48
43
|
|
49
44
|
require "graphql/schema/resolver"
|
50
45
|
require "graphql/schema/mutation"
|
46
|
+
require "graphql/schema/has_single_input_argument"
|
51
47
|
require "graphql/schema/relay_classic_mutation"
|
52
48
|
require "graphql/schema/subscription"
|
53
49
|
|
@@ -67,10 +63,6 @@ module GraphQL
|
|
67
63
|
# Schemas can restrict large incoming queries with `max_depth` and `max_complexity` configurations.
|
68
64
|
# (These configurations can be overridden by specific calls to {Schema#execute})
|
69
65
|
#
|
70
|
-
# Schemas can specify how queries should be executed against them.
|
71
|
-
# `query_execution_strategy`, `mutation_execution_strategy` and `subscription_execution_strategy`
|
72
|
-
# each apply to corresponding root types.
|
73
|
-
# #
|
74
66
|
# @example defining a schema
|
75
67
|
# class MySchema < GraphQL::Schema
|
76
68
|
# query QueryType
|
@@ -79,16 +71,16 @@ module GraphQL
|
|
79
71
|
# end
|
80
72
|
#
|
81
73
|
class Schema
|
82
|
-
extend Forwardable
|
83
|
-
extend GraphQL::Schema::Member::AcceptsDefinition
|
84
74
|
extend GraphQL::Schema::Member::HasAstNode
|
85
|
-
include GraphQL::Define::InstanceDefinable
|
86
|
-
extend GraphQL::Define::InstanceDefinable::DeprecatedDefine
|
87
75
|
extend GraphQL::Schema::FindInheritedValue
|
88
76
|
|
89
|
-
class
|
90
|
-
|
91
|
-
|
77
|
+
class DuplicateNamesError < GraphQL::Error
|
78
|
+
attr_reader :duplicated_name
|
79
|
+
def initialize(duplicated_name:, duplicated_definition_1:, duplicated_definition_2:)
|
80
|
+
@duplicated_name = duplicated_name
|
81
|
+
super(
|
82
|
+
"Found two visible definitions for `#{duplicated_name}`: #{duplicated_definition_1}, #{duplicated_definition_2}"
|
83
|
+
)
|
92
84
|
end
|
93
85
|
end
|
94
86
|
|
@@ -100,760 +92,169 @@ module GraphQL
|
|
100
92
|
end
|
101
93
|
end
|
102
94
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
#
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
95
|
+
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
96
|
+
class InvalidDocumentError < Error; end;
|
97
|
+
|
98
|
+
class << self
|
99
|
+
# Create schema with the result of an introspection query.
|
100
|
+
# @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
|
101
|
+
# @return [Class<GraphQL::Schema>] the schema described by `input`
|
102
|
+
def from_introspection(introspection_result)
|
103
|
+
GraphQL::Schema::Loader.load(introspection_result)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Create schema from an IDL schema or file containing an IDL definition.
|
107
|
+
# @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
|
108
|
+
# @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
|
109
|
+
# @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
|
110
|
+
# @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
|
111
|
+
# @return [Class] the schema described by `document`
|
112
|
+
def from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
|
113
|
+
# If the file ends in `.graphql` or `.graphqls`, treat it like a filepath
|
114
|
+
if definition_or_path.end_with?(".graphql") || definition_or_path.end_with?(".graphqls")
|
115
|
+
GraphQL::Schema::BuildFromDefinition.from_definition_path(
|
116
|
+
self,
|
117
|
+
definition_or_path,
|
118
|
+
default_resolve: default_resolve,
|
119
|
+
parser: parser,
|
120
|
+
using: using,
|
121
|
+
)
|
115
122
|
else
|
116
|
-
|
123
|
+
GraphQL::Schema::BuildFromDefinition.from_definition(
|
124
|
+
self,
|
125
|
+
definition_or_path,
|
126
|
+
default_resolve: default_resolve,
|
127
|
+
parser: parser,
|
128
|
+
using: using,
|
129
|
+
)
|
117
130
|
end
|
118
131
|
end
|
119
132
|
|
120
|
-
|
121
|
-
|
122
|
-
# @return [Object] A GraphQL-ready (non-lazy) object
|
123
|
-
# @api private
|
124
|
-
def sync_lazy(value)
|
125
|
-
lazy_method = lazy_method_name(value)
|
126
|
-
if lazy_method
|
127
|
-
synced_value = value.public_send(lazy_method)
|
128
|
-
sync_lazy(synced_value)
|
129
|
-
else
|
130
|
-
value
|
131
|
-
end
|
133
|
+
def deprecated_graphql_definition
|
134
|
+
graphql_definition(silence_deprecation_warning: true)
|
132
135
|
end
|
133
136
|
|
134
|
-
# @return [
|
135
|
-
def
|
136
|
-
|
137
|
+
# @return [GraphQL::Subscriptions]
|
138
|
+
def subscriptions(inherited: true)
|
139
|
+
defined?(@subscriptions) ? @subscriptions : (inherited ? find_inherited_value(:subscriptions, nil) : nil)
|
137
140
|
end
|
138
141
|
|
139
|
-
|
140
|
-
|
141
|
-
!!lazy_method_name(obj)
|
142
|
+
def subscriptions=(new_implementation)
|
143
|
+
@subscriptions = new_implementation
|
142
144
|
end
|
143
145
|
|
144
|
-
#
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
end
|
146
|
+
# @param new_mode [Symbol] If configured, this will be used when `context: { trace_mode: ... }` isn't set.
|
147
|
+
def default_trace_mode(new_mode = nil)
|
148
|
+
if new_mode
|
149
|
+
@default_trace_mode = new_mode
|
150
|
+
elsif defined?(@default_trace_mode)
|
151
|
+
@default_trace_mode
|
152
|
+
elsif superclass.respond_to?(:default_trace_mode)
|
153
|
+
superclass.default_trace_mode
|
153
154
|
else
|
154
|
-
|
155
|
+
:default
|
155
156
|
end
|
156
157
|
end
|
157
|
-
end
|
158
|
-
|
159
|
-
include LazyHandlingMethods
|
160
|
-
extend LazyHandlingMethods
|
161
|
-
|
162
|
-
accepts_definitions \
|
163
|
-
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
164
|
-
:validate_timeout, :max_depth, :max_complexity, :default_max_page_size,
|
165
|
-
:orphan_types, :resolve_type, :type_error, :parse_error,
|
166
|
-
:error_bubbling,
|
167
|
-
:raise_definition_error,
|
168
|
-
:object_from_id, :id_from_object,
|
169
|
-
:default_mask,
|
170
|
-
:cursor_encoder,
|
171
|
-
# If these are given as classes, normalize them. Accept `nil` when building from string.
|
172
|
-
query: ->(schema, t) { schema.query = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
173
|
-
mutation: ->(schema, t) { schema.mutation = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
174
|
-
subscription: ->(schema, t) { schema.subscription = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
175
|
-
disable_introspection_entry_points: ->(schema) { schema.disable_introspection_entry_points = true },
|
176
|
-
disable_schema_introspection_entry_point: ->(schema) { schema.disable_schema_introspection_entry_point = true },
|
177
|
-
disable_type_introspection_entry_point: ->(schema) { schema.disable_type_introspection_entry_point = true },
|
178
|
-
directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.graphql_name] = d; m } },
|
179
|
-
directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
|
180
|
-
instrument: ->(schema, type, instrumenter, after_built_ins: false) {
|
181
|
-
if type == :field && after_built_ins
|
182
|
-
type = :field_after_built_ins
|
183
|
-
end
|
184
|
-
schema.instrumenters[type] << instrumenter
|
185
|
-
},
|
186
|
-
query_analyzer: ->(schema, analyzer) {
|
187
|
-
if analyzer == GraphQL::Authorization::Analyzer
|
188
|
-
GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
189
|
-
end
|
190
|
-
schema.query_analyzers << analyzer
|
191
|
-
},
|
192
|
-
multiplex_analyzer: ->(schema, analyzer) { schema.multiplex_analyzers << analyzer },
|
193
|
-
middleware: ->(schema, middleware) { schema.middleware << middleware },
|
194
|
-
lazy_resolve: ->(schema, lazy_class, lazy_value_method) { schema.lazy_methods.set(lazy_class, lazy_value_method) },
|
195
|
-
rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block) },
|
196
|
-
tracer: ->(schema, tracer) { schema.tracers.push(tracer) }
|
197
|
-
|
198
|
-
ensure_defined :introspection_system
|
199
|
-
|
200
|
-
attr_accessor \
|
201
|
-
:query, :mutation, :subscription,
|
202
|
-
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
203
|
-
:validate_timeout, :max_depth, :max_complexity, :default_max_page_size,
|
204
|
-
:orphan_types, :directives,
|
205
|
-
:query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
|
206
|
-
:cursor_encoder,
|
207
|
-
:ast_node,
|
208
|
-
:raise_definition_error,
|
209
|
-
:introspection_namespace,
|
210
|
-
:analysis_engine
|
211
|
-
|
212
|
-
# [Boolean] True if this object bubbles validation errors up from a field into its parent InputObject, if there is one.
|
213
|
-
attr_accessor :error_bubbling
|
214
|
-
|
215
|
-
# Single, long-lived instance of the provided subscriptions class, if there is one.
|
216
|
-
# @return [GraphQL::Subscriptions]
|
217
|
-
attr_accessor :subscriptions
|
218
|
-
|
219
|
-
# @return [MiddlewareChain] MiddlewareChain which is applied to fields during execution
|
220
|
-
attr_accessor :middleware
|
221
|
-
|
222
|
-
# @return [<#call(member, ctx)>] A callable for filtering members of the schema
|
223
|
-
# @see {Query.new} for query-specific filters with `except:`
|
224
|
-
attr_accessor :default_mask
|
225
|
-
|
226
|
-
# @see {GraphQL::Query::Context} The parent class of these classes
|
227
|
-
# @return [Class] Instantiated for each query
|
228
|
-
attr_accessor :context_class
|
229
|
-
|
230
|
-
# [Boolean] True if this object disables the introspection entry point fields
|
231
|
-
attr_accessor :disable_introspection_entry_points
|
232
|
-
|
233
|
-
def disable_introspection_entry_points?
|
234
|
-
!!@disable_introspection_entry_points
|
235
|
-
end
|
236
|
-
|
237
|
-
# [Boolean] True if this object disables the __schema introspection entry point field
|
238
|
-
attr_accessor :disable_schema_introspection_entry_point
|
239
|
-
|
240
|
-
def disable_schema_introspection_entry_point?
|
241
|
-
!!@disable_schema_introspection_entry_point
|
242
|
-
end
|
243
|
-
|
244
|
-
# [Boolean] True if this object disables the __type introspection entry point field
|
245
|
-
attr_accessor :disable_type_introspection_entry_point
|
246
|
-
|
247
|
-
def disable_type_introspection_entry_point?
|
248
|
-
!!@disable_type_introspection_entry_point
|
249
|
-
end
|
250
|
-
|
251
|
-
class << self
|
252
|
-
attr_writer :default_execution_strategy
|
253
|
-
end
|
254
|
-
|
255
|
-
def default_filter
|
256
|
-
GraphQL::Filter.new(except: default_mask)
|
257
|
-
end
|
258
|
-
|
259
|
-
# @return [Array<#trace(key, data)>] Tracers applied to every query
|
260
|
-
# @see {Query#tracers} for query-specific tracers
|
261
|
-
attr_reader :tracers
|
262
|
-
|
263
|
-
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"].freeze
|
264
|
-
|
265
|
-
attr_reader :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
|
266
|
-
|
267
|
-
def initialize
|
268
|
-
@tracers = []
|
269
|
-
@definition_error = nil
|
270
|
-
@orphan_types = []
|
271
|
-
@directives = {}
|
272
|
-
self.class.default_directives.each do |name, dir|
|
273
|
-
@directives[name] = dir.graphql_definition
|
274
|
-
end
|
275
|
-
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
276
|
-
@middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
277
|
-
@query_analyzers = []
|
278
|
-
@multiplex_analyzers = []
|
279
|
-
@resolve_type_proc = nil
|
280
|
-
@object_from_id_proc = nil
|
281
|
-
@id_from_object_proc = nil
|
282
|
-
@type_error_proc = DefaultTypeError
|
283
|
-
@parse_error_proc = DefaultParseError
|
284
|
-
@instrumenters = Hash.new { |h, k| h[k] = [] }
|
285
|
-
@lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
|
286
|
-
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
287
|
-
@cursor_encoder = Base64Encoder
|
288
|
-
# For schema instances, default to legacy runtime modules
|
289
|
-
@analysis_engine = GraphQL::Analysis
|
290
|
-
@query_execution_strategy = GraphQL::Execution::Execute
|
291
|
-
@mutation_execution_strategy = GraphQL::Execution::Execute
|
292
|
-
@subscription_execution_strategy = GraphQL::Execution::Execute
|
293
|
-
@default_mask = GraphQL::Schema::NullMask
|
294
|
-
@rebuilding_artifacts = false
|
295
|
-
@context_class = GraphQL::Query::Context
|
296
|
-
@introspection_namespace = nil
|
297
|
-
@introspection_system = nil
|
298
|
-
@interpreter = false
|
299
|
-
@error_bubbling = false
|
300
|
-
@disable_introspection_entry_points = false
|
301
|
-
@disable_schema_introspection_entry_point = false
|
302
|
-
@disable_type_introspection_entry_point = false
|
303
|
-
end
|
304
|
-
|
305
|
-
# @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
|
306
|
-
def interpreter?
|
307
|
-
query_execution_strategy == GraphQL::Execution::Interpreter &&
|
308
|
-
mutation_execution_strategy == GraphQL::Execution::Interpreter &&
|
309
|
-
subscription_execution_strategy == GraphQL::Execution::Interpreter
|
310
|
-
end
|
311
|
-
|
312
|
-
def inspect
|
313
|
-
"#<#{self.class.name} ...>"
|
314
|
-
end
|
315
|
-
|
316
|
-
def initialize_copy(other)
|
317
|
-
super
|
318
|
-
@orphan_types = other.orphan_types.dup
|
319
|
-
@directives = other.directives.dup
|
320
|
-
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
321
|
-
@middleware = other.middleware.dup
|
322
|
-
@query_analyzers = other.query_analyzers.dup
|
323
|
-
@multiplex_analyzers = other.multiplex_analyzers.dup
|
324
|
-
@tracers = other.tracers.dup
|
325
|
-
@possible_types = GraphQL::Schema::PossibleTypes.new(self)
|
326
|
-
|
327
|
-
@lazy_methods = other.lazy_methods.dup
|
328
|
-
|
329
|
-
@instrumenters = Hash.new { |h, k| h[k] = [] }
|
330
|
-
other.instrumenters.each do |key, insts|
|
331
|
-
@instrumenters[key].concat(insts)
|
332
|
-
end
|
333
|
-
|
334
|
-
if other.rescues?
|
335
|
-
@rescue_middleware = other.rescue_middleware
|
336
|
-
end
|
337
158
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
def remove_handler(*args, &block)
|
349
|
-
rescue_middleware.remove_handler(*args, &block)
|
350
|
-
end
|
351
|
-
|
352
|
-
def using_ast_analysis?
|
353
|
-
@analysis_engine == GraphQL::Analysis::AST
|
354
|
-
end
|
355
|
-
|
356
|
-
# For forwards-compatibility with Schema classes
|
357
|
-
alias :graphql_definition :itself
|
358
|
-
|
359
|
-
def deprecated_define(**kwargs, &block)
|
360
|
-
super
|
361
|
-
ensure_defined
|
362
|
-
# Assert that all necessary configs are present:
|
363
|
-
validation_error = Validation.validate(self)
|
364
|
-
validation_error && raise(GraphQL::RequiredImplementationMissingError, validation_error)
|
365
|
-
rebuild_artifacts
|
366
|
-
|
367
|
-
@definition_error = nil
|
368
|
-
nil
|
369
|
-
rescue StandardError => err
|
370
|
-
if @raise_definition_error || err.is_a?(CyclicalDefinitionError) || err.is_a?(GraphQL::RequiredImplementationMissingError)
|
371
|
-
raise
|
372
|
-
else
|
373
|
-
# Raise this error _later_ to avoid messing with Rails constant loading
|
374
|
-
@definition_error = err
|
375
|
-
end
|
376
|
-
nil
|
377
|
-
end
|
378
|
-
|
379
|
-
# Attach `instrumenter` to this schema for instrumenting events of `instrumentation_type`.
|
380
|
-
# @param instrumentation_type [Symbol]
|
381
|
-
# @param instrumenter
|
382
|
-
# @return [void]
|
383
|
-
def instrument(instrumentation_type, instrumenter)
|
384
|
-
@instrumenters[instrumentation_type] << instrumenter
|
385
|
-
if instrumentation_type == :field
|
386
|
-
rebuild_artifacts
|
387
|
-
end
|
388
|
-
end
|
389
|
-
|
390
|
-
# @return [Array<GraphQL::BaseType>] The root types of this schema
|
391
|
-
def root_types
|
392
|
-
@root_types ||= begin
|
393
|
-
rebuild_artifacts
|
394
|
-
@root_types
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
399
|
-
# @return [GraphQL::Schema::TypeMap] `{ name => type }` pairs of types in this schema
|
400
|
-
def types
|
401
|
-
@types ||= begin
|
402
|
-
rebuild_artifacts
|
403
|
-
@types
|
404
|
-
end
|
405
|
-
end
|
406
|
-
|
407
|
-
def get_type(type_name)
|
408
|
-
@types[type_name]
|
409
|
-
end
|
410
|
-
|
411
|
-
# @api private
|
412
|
-
def introspection_system
|
413
|
-
@introspection_system ||= begin
|
414
|
-
rebuild_artifacts
|
415
|
-
@introspection_system
|
416
|
-
end
|
417
|
-
end
|
418
|
-
|
419
|
-
# Returns a list of Arguments and Fields referencing a certain type
|
420
|
-
# @param type_name [String]
|
421
|
-
# @return [Hash]
|
422
|
-
def references_to(type_name = nil)
|
423
|
-
rebuild_artifacts unless defined?(@type_reference_map)
|
424
|
-
if type_name
|
425
|
-
@type_reference_map.fetch(type_name, [])
|
426
|
-
else
|
427
|
-
@type_reference_map
|
428
|
-
end
|
429
|
-
end
|
430
|
-
|
431
|
-
# Returns a list of Union types in which a type is a member
|
432
|
-
# @param type [GraphQL::ObjectType]
|
433
|
-
# @return [Array<GraphQL::UnionType>] list of union types of which the type is a member
|
434
|
-
def union_memberships(type)
|
435
|
-
rebuild_artifacts unless defined?(@union_memberships)
|
436
|
-
@union_memberships.fetch(type.name, [])
|
437
|
-
end
|
438
|
-
|
439
|
-
# Execute a query on itself. Raises an error if the schema definition is invalid.
|
440
|
-
# @see {Query#initialize} for arguments.
|
441
|
-
# @return [Hash] query result, ready to be serialized as JSON
|
442
|
-
def execute(query_str = nil, **kwargs)
|
443
|
-
if query_str
|
444
|
-
kwargs[:query] = query_str
|
445
|
-
end
|
446
|
-
# Some of the query context _should_ be passed to the multiplex, too
|
447
|
-
multiplex_context = if (ctx = kwargs[:context])
|
448
|
-
{
|
449
|
-
backtrace: ctx[:backtrace],
|
450
|
-
tracers: ctx[:tracers],
|
451
|
-
}
|
452
|
-
else
|
453
|
-
{}
|
454
|
-
end
|
455
|
-
# Since we're running one query, don't run a multiplex-level complexity analyzer
|
456
|
-
all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
|
457
|
-
all_results[0]
|
458
|
-
end
|
459
|
-
|
460
|
-
# Execute several queries on itself. Raises an error if the schema definition is invalid.
|
461
|
-
# @example Run several queries at once
|
462
|
-
# context = { ... }
|
463
|
-
# queries = [
|
464
|
-
# { query: params[:query_1], variables: params[:variables_1], context: context },
|
465
|
-
# { query: params[:query_2], variables: params[:variables_2], context: context },
|
466
|
-
# ]
|
467
|
-
# results = MySchema.multiplex(queries)
|
468
|
-
# render json: {
|
469
|
-
# result_1: results[0],
|
470
|
-
# result_2: results[1],
|
471
|
-
# }
|
472
|
-
#
|
473
|
-
# @see {Query#initialize} for query keyword arguments
|
474
|
-
# @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
|
475
|
-
# @param queries [Array<Hash>] Keyword arguments for each query
|
476
|
-
# @param context [Hash] Multiplex-level context
|
477
|
-
# @return [Array<Hash>] One result for each query in the input
|
478
|
-
def multiplex(queries, **kwargs)
|
479
|
-
with_definition_error_check {
|
480
|
-
GraphQL::Execution::Multiplex.run_all(self, queries, **kwargs)
|
481
|
-
}
|
482
|
-
end
|
483
|
-
|
484
|
-
# Search for a schema member using a string path
|
485
|
-
# @example Finding a Field
|
486
|
-
# Schema.find("Ensemble.musicians")
|
487
|
-
#
|
488
|
-
# @see {GraphQL::Schema::Finder} for more examples
|
489
|
-
# @param path [String] A dot-separated path to the member
|
490
|
-
# @raise [Schema::Finder::MemberNotFoundError] if path could not be found
|
491
|
-
# @return [GraphQL::BaseType, GraphQL::Field, GraphQL::Argument, GraphQL::Directive] A GraphQL Schema Member
|
492
|
-
def find(path)
|
493
|
-
rebuild_artifacts unless defined?(@finder)
|
494
|
-
@find_cache[path] ||= @finder.find(path)
|
495
|
-
end
|
496
|
-
|
497
|
-
# Resolve field named `field_name` for type `parent_type`.
|
498
|
-
# Handles dynamic fields `__typename`, `__type` and `__schema`, too
|
499
|
-
# @param parent_type [String, GraphQL::BaseType]
|
500
|
-
# @param field_name [String]
|
501
|
-
# @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
|
502
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
503
|
-
def get_field(parent_type, field_name)
|
504
|
-
with_definition_error_check do
|
505
|
-
parent_type_name = case parent_type
|
506
|
-
when GraphQL::BaseType, Class, Module
|
507
|
-
parent_type.graphql_name
|
508
|
-
when String
|
509
|
-
parent_type
|
510
|
-
else
|
511
|
-
raise "Unexpected parent_type: #{parent_type}"
|
159
|
+
def trace_class(new_class = nil)
|
160
|
+
if new_class
|
161
|
+
# If any modules were already added for `:default`,
|
162
|
+
# re-apply them here
|
163
|
+
mods = trace_modules_for(:default)
|
164
|
+
mods.each { |mod| new_class.include(mod) }
|
165
|
+
trace_mode(:default, new_class)
|
166
|
+
backtrace_class = Class.new(new_class)
|
167
|
+
backtrace_class.include(GraphQL::Backtrace::Trace)
|
168
|
+
trace_mode(:default_backtrace, backtrace_class)
|
512
169
|
end
|
170
|
+
trace_class_for(:default, build: true)
|
171
|
+
end
|
513
172
|
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
173
|
+
# @return [Class] Return the trace class to use for this mode, looking one up on the superclass if this Schema doesn't have one defined.
|
174
|
+
def trace_class_for(mode, build: false)
|
175
|
+
if (trace_class = own_trace_modes[mode])
|
176
|
+
trace_class
|
177
|
+
elsif superclass.respond_to?(:trace_class_for) && (trace_class = superclass.trace_class_for(mode, build: false))
|
178
|
+
trace_class
|
179
|
+
elsif build
|
180
|
+
own_trace_modes[mode] = build_trace_mode(mode)
|
521
181
|
else
|
522
182
|
nil
|
523
183
|
end
|
524
184
|
end
|
525
|
-
end
|
526
|
-
|
527
|
-
# Fields for this type, after instrumentation is applied
|
528
|
-
# @return [Hash<String, GraphQL::Field>]
|
529
|
-
def get_fields(type)
|
530
|
-
@instrumented_field_map[type.graphql_name]
|
531
|
-
end
|
532
185
|
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
# https://github.com/rmosolgo/graphql-ruby/issues/2878
|
549
|
-
ns = context.namespace(:possible_types)
|
550
|
-
per_query_possible_types = ns[:possible_types] ||= GraphQL::Schema::PossibleTypes.new(self)
|
551
|
-
per_query_possible_types.possible_types(type_defn, context)
|
552
|
-
end
|
553
|
-
end
|
554
|
-
|
555
|
-
# @see [GraphQL::Schema::Warden] Resticted access to root types
|
556
|
-
# @return [GraphQL::ObjectType, nil]
|
557
|
-
def root_type_for_operation(operation)
|
558
|
-
case operation
|
559
|
-
when "query"
|
560
|
-
query
|
561
|
-
when "mutation"
|
562
|
-
mutation
|
563
|
-
when "subscription"
|
564
|
-
subscription
|
565
|
-
else
|
566
|
-
raise ArgumentError, "unknown operation type: #{operation}"
|
567
|
-
end
|
568
|
-
end
|
569
|
-
|
570
|
-
def execution_strategy_for_operation(operation)
|
571
|
-
case operation
|
572
|
-
when "query"
|
573
|
-
query_execution_strategy
|
574
|
-
when "mutation"
|
575
|
-
mutation_execution_strategy
|
576
|
-
when "subscription"
|
577
|
-
subscription_execution_strategy
|
578
|
-
else
|
579
|
-
raise ArgumentError, "unknown operation type: #{operation}"
|
580
|
-
end
|
581
|
-
end
|
582
|
-
|
583
|
-
# Determine the GraphQL type for a given object.
|
584
|
-
# This is required for unions and interfaces (including Relay's `Node` interface)
|
585
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
586
|
-
# @param type [GraphQL::UnionType, GraphQL:InterfaceType] the abstract type which is being resolved
|
587
|
-
# @param object [Any] An application object which GraphQL is currently resolving on
|
588
|
-
# @param ctx [GraphQL::Query::Context] The context for the current query
|
589
|
-
# @return [GraphQL::ObjectType] The type for exposing `object` in GraphQL
|
590
|
-
def resolve_type(type, object, ctx = :__undefined__)
|
591
|
-
check_resolved_type(type, object, ctx) do |ok_type, ok_object, ok_ctx|
|
592
|
-
if @resolve_type_proc.nil?
|
593
|
-
raise(GraphQL::RequiredImplementationMissingError, "Can't determine GraphQL type for: #{ok_object.inspect}, define `resolve_type (type, obj, ctx) -> { ... }` inside `Schema.define`.")
|
594
|
-
end
|
595
|
-
@resolve_type_proc.call(ok_type, ok_object, ok_ctx)
|
596
|
-
end
|
597
|
-
end
|
598
|
-
|
599
|
-
# This is a compatibility hack so that instance-level and class-level
|
600
|
-
# methods can get correctness checks without calling one another
|
601
|
-
# @api private
|
602
|
-
def check_resolved_type(type, object, ctx = :__undefined__)
|
603
|
-
if ctx == :__undefined__
|
604
|
-
# Old method signature
|
605
|
-
ctx = object
|
606
|
-
object = type
|
607
|
-
type = nil
|
186
|
+
# Configure `trace_class` to be used whenever `context: { trace_mode: mode_name }` is requested.
|
187
|
+
# {default_trace_mode} is used when no `trace_mode: ...` is requested.
|
188
|
+
#
|
189
|
+
# When a `trace_class` is added this way, it will _not_ receive other modules added with `trace_with(...)`
|
190
|
+
# unless `trace_mode` is explicitly given. (This class will not recieve any default trace modules.)
|
191
|
+
#
|
192
|
+
# Subclasses of the schema will use `trace_class` as a base class for this mode and those
|
193
|
+
# subclass also will _not_ receive default tracing modules.
|
194
|
+
#
|
195
|
+
# @param mode_name [Symbol]
|
196
|
+
# @param trace_class [Class] subclass of GraphQL::Tracing::Trace
|
197
|
+
# @return void
|
198
|
+
def trace_mode(mode_name, trace_class)
|
199
|
+
own_trace_modes[mode_name] = trace_class
|
200
|
+
nil
|
608
201
|
end
|
609
202
|
|
610
|
-
|
611
|
-
|
203
|
+
def own_trace_modes
|
204
|
+
@own_trace_modes ||= {}
|
612
205
|
end
|
613
206
|
|
614
|
-
|
615
|
-
type = type.graphql_definition
|
207
|
+
module DefaultTraceClass
|
616
208
|
end
|
617
209
|
|
618
|
-
|
619
|
-
type_proc = type && type.resolve_type_proc
|
620
|
-
type_result = if type_proc
|
621
|
-
type_proc.call(object, ctx)
|
622
|
-
else
|
623
|
-
yield(type, object, ctx)
|
624
|
-
end
|
210
|
+
private_constant :DefaultTraceClass
|
625
211
|
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
212
|
+
def build_trace_mode(mode)
|
213
|
+
case mode
|
214
|
+
when :default
|
215
|
+
# Use the superclass's default mode if it has one, or else start an inheritance chain at the built-in base class.
|
216
|
+
base_class = (superclass.respond_to?(:trace_class_for) && superclass.trace_class_for(mode)) || GraphQL::Tracing::Trace
|
217
|
+
Class.new(base_class) do
|
218
|
+
include DefaultTraceClass
|
632
219
|
end
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
resolved_type_result
|
220
|
+
when :default_backtrace
|
221
|
+
schema_base_class = trace_class_for(:default, build: true)
|
222
|
+
Class.new(schema_base_class) do
|
223
|
+
include(GraphQL::Backtrace::Trace)
|
638
224
|
end
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
def object_from_id(id, ctx)
|
653
|
-
if @object_from_id_proc.nil?
|
654
|
-
raise(GraphQL::RequiredImplementationMissingError, "Can't fetch an object for id \"#{id}\" because the schema's `object_from_id (id, ctx) -> { ... }` function is not defined")
|
655
|
-
else
|
656
|
-
@object_from_id_proc.call(id, ctx)
|
657
|
-
end
|
658
|
-
end
|
659
|
-
|
660
|
-
# @param new_proc [#call] A new callable for fetching objects by ID
|
661
|
-
def object_from_id=(new_proc)
|
662
|
-
@object_from_id_proc = new_proc
|
663
|
-
end
|
664
|
-
|
665
|
-
# When we encounter a type error during query execution, we call this hook.
|
666
|
-
#
|
667
|
-
# You can use this hook to write a log entry,
|
668
|
-
# add a {GraphQL::ExecutionError} to the response (with `ctx.add_error`)
|
669
|
-
# or raise an exception and halt query execution.
|
670
|
-
#
|
671
|
-
# @example A `nil` is encountered by a non-null field
|
672
|
-
# type_error ->(err, query_ctx) {
|
673
|
-
# err.is_a?(GraphQL::InvalidNullError) # => true
|
674
|
-
# }
|
675
|
-
#
|
676
|
-
# @example An object doesn't resolve to one of a {UnionType}'s members
|
677
|
-
# type_error ->(err, query_ctx) {
|
678
|
-
# err.is_a?(GraphQL::UnresolvedTypeError) # => true
|
679
|
-
# }
|
680
|
-
#
|
681
|
-
# @see {DefaultTypeError} is the default behavior.
|
682
|
-
# @param err [GraphQL::TypeError] The error encountered during execution
|
683
|
-
# @param ctx [GraphQL::Query::Context] The context for the field where the error occurred
|
684
|
-
# @return void
|
685
|
-
def type_error(err, ctx)
|
686
|
-
@type_error_proc.call(err, ctx)
|
687
|
-
end
|
688
|
-
|
689
|
-
# @param new_proc [#call] A new callable for handling type errors during execution
|
690
|
-
def type_error=(new_proc)
|
691
|
-
@type_error_proc = new_proc
|
692
|
-
end
|
693
|
-
|
694
|
-
# Can't delegate to `class`
|
695
|
-
alias :_schema_class :class
|
696
|
-
def_delegators :_schema_class, :unauthorized_object, :unauthorized_field, :inaccessible_fields
|
697
|
-
def_delegators :_schema_class, :directive
|
698
|
-
def_delegators :_schema_class, :error_handler
|
699
|
-
def_delegators :_schema_class, :validate
|
700
|
-
|
701
|
-
|
702
|
-
# Given this schema member, find the class-based definition object
|
703
|
-
# whose `method_name` should be treated as an application hook
|
704
|
-
# @see {.visible?}
|
705
|
-
# @see {.accessible?}
|
706
|
-
def call_on_type_class(member, method_name, context, default:)
|
707
|
-
member = if member.respond_to?(:type_class)
|
708
|
-
member.type_class
|
709
|
-
else
|
710
|
-
member
|
711
|
-
end
|
225
|
+
else
|
226
|
+
# First, see if the superclass has a custom-defined class for this.
|
227
|
+
# Then, if it doesn't, use this class's default trace
|
228
|
+
base_class = (superclass.respond_to?(:trace_class_for) && superclass.trace_class_for(mode)) || trace_class_for(:default, build: true)
|
229
|
+
# Prepare the default trace class if it hasn't been initialized yet
|
230
|
+
base_class ||= (own_trace_modes[:default] = build_trace_mode(:default))
|
231
|
+
mods = trace_modules_for(mode)
|
232
|
+
if base_class < DefaultTraceClass
|
233
|
+
mods = trace_modules_for(:default) + mods
|
234
|
+
end
|
235
|
+
# Copy the existing default options into this mode's options
|
236
|
+
default_options = trace_options_for(:default)
|
237
|
+
add_trace_options_for(mode, default_options)
|
712
238
|
|
713
|
-
|
714
|
-
|
239
|
+
Class.new(base_class) do
|
240
|
+
mods.any? && include(*mods)
|
241
|
+
end
|
242
|
+
end
|
715
243
|
end
|
716
244
|
|
717
|
-
|
718
|
-
|
719
|
-
else
|
720
|
-
default
|
245
|
+
def own_trace_modules
|
246
|
+
@own_trace_modules ||= Hash.new { |h, k| h[k] = [] }
|
721
247
|
end
|
722
|
-
end
|
723
248
|
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
# A function to call when {#execute} receives an invalid query string
|
733
|
-
#
|
734
|
-
# @see {DefaultParseError} is the default behavior.
|
735
|
-
# @param err [GraphQL::ParseError] The error encountered during parsing
|
736
|
-
# @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
|
737
|
-
# @return void
|
738
|
-
def parse_error(err, ctx)
|
739
|
-
@parse_error_proc.call(err, ctx)
|
740
|
-
end
|
741
|
-
|
742
|
-
# @param new_proc [#call] A new callable for handling parse errors during execution
|
743
|
-
def parse_error=(new_proc)
|
744
|
-
@parse_error_proc = new_proc
|
745
|
-
end
|
746
|
-
|
747
|
-
# Get a unique identifier from this object
|
748
|
-
# @param object [Any] An application object
|
749
|
-
# @param type [GraphQL::BaseType] The current type definition
|
750
|
-
# @param ctx [GraphQL::Query::Context] the context for the current query
|
751
|
-
# @return [String] a unique identifier for `object` which clients can use to refetch it
|
752
|
-
def id_from_object(object, type, ctx)
|
753
|
-
if @id_from_object_proc.nil?
|
754
|
-
raise(GraphQL::RequiredImplementationMissingError, "Can't generate an ID for #{object.inspect} of type #{type}, schema's `id_from_object` must be defined")
|
755
|
-
else
|
756
|
-
@id_from_object_proc.call(object, type, ctx)
|
757
|
-
end
|
758
|
-
end
|
759
|
-
|
760
|
-
# @param new_proc [#call] A new callable for generating unique IDs
|
761
|
-
def id_from_object=(new_proc)
|
762
|
-
@id_from_object_proc = new_proc
|
763
|
-
end
|
764
|
-
|
765
|
-
# Create schema with the result of an introspection query.
|
766
|
-
# @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
|
767
|
-
# @return [GraphQL::Schema] the schema described by `input`
|
768
|
-
def self.from_introspection(introspection_result)
|
769
|
-
GraphQL::Schema::Loader.load(introspection_result)
|
770
|
-
end
|
771
|
-
|
772
|
-
# Create schema from an IDL schema or file containing an IDL definition.
|
773
|
-
# @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
|
774
|
-
# @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
|
775
|
-
# @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
|
776
|
-
# @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
|
777
|
-
# @return [Class] the schema described by `document`
|
778
|
-
def self.from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
|
779
|
-
# If the file ends in `.graphql`, treat it like a filepath
|
780
|
-
if definition_or_path.end_with?(".graphql")
|
781
|
-
GraphQL::Schema::BuildFromDefinition.from_definition_path(
|
782
|
-
definition_or_path,
|
783
|
-
default_resolve: default_resolve,
|
784
|
-
parser: parser,
|
785
|
-
using: using,
|
786
|
-
)
|
787
|
-
else
|
788
|
-
GraphQL::Schema::BuildFromDefinition.from_definition(
|
789
|
-
definition_or_path,
|
790
|
-
default_resolve: default_resolve,
|
791
|
-
parser: parser,
|
792
|
-
using: using,
|
793
|
-
)
|
249
|
+
# @return [Array<Module>] Modules added for tracing in `trace_mode`, including inherited ones
|
250
|
+
def trace_modules_for(trace_mode)
|
251
|
+
modules = own_trace_modules[trace_mode]
|
252
|
+
if superclass.respond_to?(:trace_modules_for)
|
253
|
+
modules += superclass.trace_modules_for(trace_mode)
|
254
|
+
end
|
255
|
+
modules
|
794
256
|
end
|
795
|
-
end
|
796
|
-
|
797
|
-
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
798
|
-
class InvalidDocumentError < Error; end;
|
799
|
-
|
800
|
-
# Return the GraphQL IDL for the schema
|
801
|
-
# @param context [Hash]
|
802
|
-
# @param only [<#call(member, ctx)>]
|
803
|
-
# @param except [<#call(member, ctx)>]
|
804
|
-
# @return [String]
|
805
|
-
def to_definition(only: nil, except: nil, context: {})
|
806
|
-
GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
|
807
|
-
end
|
808
|
-
|
809
|
-
# Return the GraphQL::Language::Document IDL AST for the schema
|
810
|
-
# @param context [Hash]
|
811
|
-
# @param only [<#call(member, ctx)>]
|
812
|
-
# @param except [<#call(member, ctx)>]
|
813
|
-
# @return [GraphQL::Language::Document]
|
814
|
-
def to_document(only: nil, except: nil, context: {})
|
815
|
-
GraphQL::Language::DocumentFromSchemaDefinition.new(self, only: only, except: except, context: context).document
|
816
|
-
end
|
817
|
-
|
818
|
-
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
819
|
-
# @param context [Hash]
|
820
|
-
# @param only [<#call(member, ctx)>]
|
821
|
-
# @param except [<#call(member, ctx)>]
|
822
|
-
# @return [Hash] GraphQL result
|
823
|
-
def as_json(only: nil, except: nil, context: {})
|
824
|
-
execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
|
825
|
-
end
|
826
|
-
|
827
|
-
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
828
|
-
# @see {#as_json}
|
829
|
-
# @return [String]
|
830
|
-
def to_json(*args)
|
831
|
-
JSON.pretty_generate(as_json(*args))
|
832
|
-
end
|
833
|
-
|
834
|
-
def new_connections?
|
835
|
-
!!connections
|
836
|
-
end
|
837
|
-
|
838
|
-
attr_accessor :connections
|
839
257
|
|
840
|
-
class << self
|
841
|
-
extend Forwardable
|
842
|
-
# For compatibility, these methods all:
|
843
|
-
# - Cause the Schema instance to be created, if it hasn't been created yet
|
844
|
-
# - Delegate to that instance
|
845
|
-
# Eventually, the methods will be moved into this class, removing the need for the singleton.
|
846
|
-
def_delegators :graphql_definition,
|
847
|
-
# Execution
|
848
|
-
:execution_strategy_for_operation,
|
849
|
-
# Configuration
|
850
|
-
:metadata, :redefine,
|
851
|
-
:id_from_object_proc, :object_from_id_proc,
|
852
|
-
:id_from_object=, :object_from_id=,
|
853
|
-
:remove_handler
|
854
|
-
|
855
|
-
# @return [GraphQL::Subscriptions]
|
856
|
-
attr_accessor :subscriptions
|
857
258
|
|
858
259
|
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
859
260
|
# @see {#as_json}
|
@@ -866,18 +267,29 @@ module GraphQL
|
|
866
267
|
# @param context [Hash]
|
867
268
|
# @param only [<#call(member, ctx)>]
|
868
269
|
# @param except [<#call(member, ctx)>]
|
270
|
+
# @param include_deprecated_args [Boolean] If true, deprecated arguments will be included in the JSON response
|
271
|
+
# @param include_schema_description [Boolean] If true, the schema's description will be queried and included in the response
|
272
|
+
# @param include_is_repeatable [Boolean] If true, `isRepeatable: true|false` will be included with the schema's directives
|
273
|
+
# @param include_specified_by_url [Boolean] If true, scalar types' `specifiedByUrl:` will be included in the response
|
274
|
+
# @param include_is_one_of [Boolean] If true, `isOneOf: true|false` will be included with input objects
|
869
275
|
# @return [Hash] GraphQL result
|
870
|
-
def as_json(
|
871
|
-
|
276
|
+
def as_json(context: {}, include_deprecated_args: true, include_schema_description: false, include_is_repeatable: false, include_specified_by_url: false, include_is_one_of: false)
|
277
|
+
introspection_query = Introspection.query(
|
278
|
+
include_deprecated_args: include_deprecated_args,
|
279
|
+
include_schema_description: include_schema_description,
|
280
|
+
include_is_repeatable: include_is_repeatable,
|
281
|
+
include_is_one_of: include_is_one_of,
|
282
|
+
include_specified_by_url: include_specified_by_url,
|
283
|
+
)
|
284
|
+
|
285
|
+
execute(introspection_query, context: context).to_h
|
872
286
|
end
|
873
287
|
|
874
288
|
# Return the GraphQL IDL for the schema
|
875
289
|
# @param context [Hash]
|
876
|
-
# @param only [<#call(member, ctx)>]
|
877
|
-
# @param except [<#call(member, ctx)>]
|
878
290
|
# @return [String]
|
879
|
-
def to_definition(
|
880
|
-
GraphQL::Schema::Printer.print_schema(self,
|
291
|
+
def to_definition(context: {})
|
292
|
+
GraphQL::Schema::Printer.print_schema(self, context: context)
|
881
293
|
end
|
882
294
|
|
883
295
|
# Return the GraphQL::Language::Document IDL AST for the schema
|
@@ -886,6 +298,17 @@ module GraphQL
|
|
886
298
|
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
887
299
|
end
|
888
300
|
|
301
|
+
# @return [String, nil]
|
302
|
+
def description(new_description = nil)
|
303
|
+
if new_description
|
304
|
+
@description = new_description
|
305
|
+
elsif defined?(@description)
|
306
|
+
@description
|
307
|
+
else
|
308
|
+
find_inherited_value(:description, nil)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
889
312
|
def find(path)
|
890
313
|
if !@finder
|
891
314
|
@find_cache = {}
|
@@ -894,22 +317,6 @@ module GraphQL
|
|
894
317
|
@find_cache[path] ||= @finder.find(path)
|
895
318
|
end
|
896
319
|
|
897
|
-
def graphql_definition
|
898
|
-
@graphql_definition ||= to_graphql
|
899
|
-
end
|
900
|
-
|
901
|
-
def default_filter
|
902
|
-
GraphQL::Filter.new(except: default_mask)
|
903
|
-
end
|
904
|
-
|
905
|
-
def default_mask(new_mask = nil)
|
906
|
-
if new_mask
|
907
|
-
@own_default_mask = new_mask
|
908
|
-
else
|
909
|
-
@own_default_mask || find_inherited_value(:default_mask, Schema::NullMask)
|
910
|
-
end
|
911
|
-
end
|
912
|
-
|
913
320
|
def static_validator
|
914
321
|
GraphQL::StaticValidation::Validator.new(schema: self)
|
915
322
|
end
|
@@ -927,84 +334,70 @@ module GraphQL
|
|
927
334
|
find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
|
928
335
|
end
|
929
336
|
|
930
|
-
def to_graphql
|
931
|
-
schema_defn = self.new
|
932
|
-
schema_defn.raise_definition_error = true
|
933
|
-
schema_defn.query = query && query.graphql_definition
|
934
|
-
schema_defn.mutation = mutation && mutation.graphql_definition
|
935
|
-
schema_defn.subscription = subscription && subscription.graphql_definition
|
936
|
-
schema_defn.validate_timeout = validate_timeout
|
937
|
-
schema_defn.max_complexity = max_complexity
|
938
|
-
schema_defn.error_bubbling = error_bubbling
|
939
|
-
schema_defn.max_depth = max_depth
|
940
|
-
schema_defn.default_max_page_size = default_max_page_size
|
941
|
-
schema_defn.orphan_types = orphan_types.map(&:graphql_definition)
|
942
|
-
schema_defn.disable_introspection_entry_points = disable_introspection_entry_points?
|
943
|
-
schema_defn.disable_schema_introspection_entry_point = disable_schema_introspection_entry_point?
|
944
|
-
schema_defn.disable_type_introspection_entry_point = disable_type_introspection_entry_point?
|
945
|
-
|
946
|
-
prepped_dirs = {}
|
947
|
-
directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
|
948
|
-
schema_defn.directives = prepped_dirs
|
949
|
-
schema_defn.introspection_namespace = introspection
|
950
|
-
schema_defn.resolve_type = method(:resolve_type)
|
951
|
-
schema_defn.object_from_id = method(:object_from_id)
|
952
|
-
schema_defn.id_from_object = method(:id_from_object)
|
953
|
-
schema_defn.type_error = method(:type_error)
|
954
|
-
schema_defn.context_class = context_class
|
955
|
-
schema_defn.cursor_encoder = cursor_encoder
|
956
|
-
schema_defn.tracers.concat(tracers)
|
957
|
-
schema_defn.query_analyzers.concat(query_analyzers)
|
958
|
-
schema_defn.analysis_engine = analysis_engine
|
959
|
-
|
960
|
-
schema_defn.middleware.concat(all_middleware)
|
961
|
-
schema_defn.multiplex_analyzers.concat(multiplex_analyzers)
|
962
|
-
schema_defn.query_execution_strategy = query_execution_strategy
|
963
|
-
schema_defn.mutation_execution_strategy = mutation_execution_strategy
|
964
|
-
schema_defn.subscription_execution_strategy = subscription_execution_strategy
|
965
|
-
schema_defn.default_mask = default_mask
|
966
|
-
instrumenters.each do |step, insts|
|
967
|
-
insts.each do |inst|
|
968
|
-
schema_defn.instrumenters[step] << inst
|
969
|
-
end
|
970
|
-
end
|
971
|
-
|
972
|
-
lazy_methods.each do |lazy_class, value_method|
|
973
|
-
schema_defn.lazy_methods.set(lazy_class, value_method)
|
974
|
-
end
|
975
|
-
|
976
|
-
error_handler.each_rescue do |err_class, handler|
|
977
|
-
schema_defn.rescue_from(err_class, &handler)
|
978
|
-
end
|
979
|
-
|
980
|
-
schema_defn.subscriptions ||= self.subscriptions
|
981
|
-
|
982
|
-
if !schema_defn.interpreter?
|
983
|
-
schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
|
984
|
-
end
|
985
|
-
|
986
|
-
if new_connections?
|
987
|
-
schema_defn.connections = self.connections
|
988
|
-
end
|
989
|
-
|
990
|
-
schema_defn.send(:rebuild_artifacts)
|
991
|
-
|
992
|
-
schema_defn
|
993
|
-
end
|
994
|
-
|
995
337
|
# Build a map of `{ name => type }` and return it
|
996
338
|
# @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
|
997
339
|
# @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
|
998
|
-
def types
|
999
|
-
non_introspection_types.merge(introspection_system.types)
|
340
|
+
def types(context = GraphQL::Query::NullContext.instance)
|
341
|
+
all_types = non_introspection_types.merge(introspection_system.types)
|
342
|
+
visible_types = {}
|
343
|
+
all_types.each do |k, v|
|
344
|
+
visible_types[k] =if v.is_a?(Array)
|
345
|
+
visible_t = nil
|
346
|
+
v.each do |t|
|
347
|
+
if t.visible?(context)
|
348
|
+
if visible_t.nil?
|
349
|
+
visible_t = t
|
350
|
+
else
|
351
|
+
raise DuplicateNamesError.new(
|
352
|
+
duplicated_name: k, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
353
|
+
)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
visible_t
|
358
|
+
else
|
359
|
+
v
|
360
|
+
end
|
361
|
+
end
|
362
|
+
visible_types
|
1000
363
|
end
|
1001
364
|
|
1002
365
|
# @param type_name [String]
|
1003
366
|
# @return [Module, nil] A type, or nil if there's no type called `type_name`
|
1004
|
-
def get_type(type_name)
|
1005
|
-
own_types[type_name]
|
1006
|
-
|
1007
|
-
|
367
|
+
def get_type(type_name, context = GraphQL::Query::NullContext.instance)
|
368
|
+
local_entry = own_types[type_name]
|
369
|
+
type_defn = case local_entry
|
370
|
+
when nil
|
371
|
+
nil
|
372
|
+
when Array
|
373
|
+
visible_t = nil
|
374
|
+
warden = Warden.from_context(context)
|
375
|
+
local_entry.each do |t|
|
376
|
+
if warden.visible_type?(t, context)
|
377
|
+
if visible_t.nil?
|
378
|
+
visible_t = t
|
379
|
+
else
|
380
|
+
raise DuplicateNamesError.new(
|
381
|
+
duplicated_name: type_name, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
382
|
+
)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
visible_t
|
387
|
+
when Module
|
388
|
+
local_entry
|
389
|
+
else
|
390
|
+
raise "Invariant: unexpected own_types[#{type_name.inspect}]: #{local_entry.inspect}"
|
391
|
+
end
|
392
|
+
|
393
|
+
type_defn ||
|
394
|
+
introspection_system.types[type_name] || # todo context-specific introspection?
|
395
|
+
(superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
|
396
|
+
end
|
397
|
+
|
398
|
+
# @return [Boolean] Does this schema have _any_ definition for a type named `type_name`, regardless of visibility?
|
399
|
+
def has_defined_type?(type_name)
|
400
|
+
own_types.key?(type_name) || introspection_system.types.key?(type_name) || (superclass.respond_to?(:has_defined_type?) ? superclass.has_defined_type?(type_name) : false)
|
1008
401
|
end
|
1009
402
|
|
1010
403
|
# @api private
|
@@ -1073,7 +466,7 @@ module GraphQL
|
|
1073
466
|
end
|
1074
467
|
end
|
1075
468
|
|
1076
|
-
# @see [GraphQL::Schema::Warden]
|
469
|
+
# @see [GraphQL::Schema::Warden] Restricted access to root types
|
1077
470
|
# @return [GraphQL::ObjectType, nil]
|
1078
471
|
def root_type_for_operation(operation)
|
1079
472
|
case operation
|
@@ -1092,10 +485,22 @@ module GraphQL
|
|
1092
485
|
@root_types
|
1093
486
|
end
|
1094
487
|
|
488
|
+
def warden_class
|
489
|
+
if defined?(@warden_class)
|
490
|
+
@warden_class
|
491
|
+
elsif superclass.respond_to?(:warden_class)
|
492
|
+
superclass.warden_class
|
493
|
+
else
|
494
|
+
GraphQL::Schema::Warden
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
attr_writer :warden_class
|
499
|
+
|
1095
500
|
# @param type [Module] The type definition whose possible types you want to see
|
1096
501
|
# @return [Hash<String, Module>] All possible types, if no `type` is given.
|
1097
502
|
# @return [Array<Module>] Possible types for `type`, if it's given.
|
1098
|
-
def possible_types(type = nil, context = GraphQL::Query::NullContext)
|
503
|
+
def possible_types(type = nil, context = GraphQL::Query::NullContext.instance)
|
1099
504
|
if type
|
1100
505
|
# TODO duck-typing `.possible_types` would probably be nicer here
|
1101
506
|
if type.kind.union?
|
@@ -1104,9 +509,7 @@ module GraphQL
|
|
1104
509
|
stored_possible_types = own_possible_types[type.graphql_name]
|
1105
510
|
visible_possible_types = if stored_possible_types && type.kind.interface?
|
1106
511
|
stored_possible_types.select do |possible_type|
|
1107
|
-
|
1108
|
-
# When we don't need to support legacy `.define` types, use `.include?(type)` instead.
|
1109
|
-
possible_type.interfaces(context).any? { |interface| interface.graphql_name == type.graphql_name }
|
512
|
+
possible_type.interfaces(context).include?(type)
|
1110
513
|
end
|
1111
514
|
else
|
1112
515
|
stored_possible_types
|
@@ -1150,18 +553,17 @@ module GraphQL
|
|
1150
553
|
attr_writer :dataloader_class
|
1151
554
|
|
1152
555
|
def references_to(to_type = nil, from: nil)
|
1153
|
-
@own_references_to ||=
|
556
|
+
@own_references_to ||= {}
|
1154
557
|
if to_type
|
1155
558
|
if !to_type.is_a?(String)
|
1156
559
|
to_type = to_type.graphql_name
|
1157
560
|
end
|
1158
561
|
|
1159
562
|
if from
|
1160
|
-
@own_references_to[to_type]
|
563
|
+
refs = @own_references_to[to_type] ||= []
|
564
|
+
refs << from
|
1161
565
|
else
|
1162
|
-
|
1163
|
-
inherited_refs = find_inherited_value(:references_to, EMPTY_HASH)[to_type] || EMPTY_ARRAY
|
1164
|
-
own_refs + inherited_refs
|
566
|
+
get_references_to(to_type) || EMPTY_ARRAY
|
1165
567
|
end
|
1166
568
|
else
|
1167
569
|
# `@own_references_to` can be quite large for big schemas,
|
@@ -1181,19 +583,19 @@ module GraphQL
|
|
1181
583
|
GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
|
1182
584
|
end
|
1183
585
|
|
1184
|
-
def get_field(type_or_name, field_name)
|
586
|
+
def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext.instance)
|
1185
587
|
parent_type = case type_or_name
|
1186
588
|
when LateBoundType
|
1187
|
-
get_type(type_or_name.name)
|
589
|
+
get_type(type_or_name.name, context)
|
1188
590
|
when String
|
1189
|
-
get_type(type_or_name)
|
591
|
+
get_type(type_or_name, context)
|
1190
592
|
when Module
|
1191
593
|
type_or_name
|
1192
594
|
else
|
1193
|
-
raise
|
595
|
+
raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
|
1194
596
|
end
|
1195
597
|
|
1196
|
-
if parent_type.kind.fields? && (field = parent_type.get_field(field_name))
|
598
|
+
if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
|
1197
599
|
field
|
1198
600
|
elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
|
1199
601
|
entry_point_field
|
@@ -1204,8 +606,8 @@ module GraphQL
|
|
1204
606
|
end
|
1205
607
|
end
|
1206
608
|
|
1207
|
-
def get_fields(type)
|
1208
|
-
type.fields
|
609
|
+
def get_fields(type, context = GraphQL::Query::NullContext.instance)
|
610
|
+
type.fields(context)
|
1209
611
|
end
|
1210
612
|
|
1211
613
|
def introspection(new_introspection_namespace = nil)
|
@@ -1241,27 +643,47 @@ module GraphQL
|
|
1241
643
|
end
|
1242
644
|
end
|
1243
645
|
|
1244
|
-
def
|
646
|
+
def default_page_size(new_default_page_size = nil)
|
647
|
+
if new_default_page_size
|
648
|
+
@default_page_size = new_default_page_size
|
649
|
+
else
|
650
|
+
@default_page_size || find_inherited_value(:default_page_size)
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
654
|
+
def query_execution_strategy(new_query_execution_strategy = nil, deprecation_warning: true)
|
655
|
+
if deprecation_warning
|
656
|
+
warn "GraphQL::Schema.query_execution_strategy is deprecated without replacement. Use `GraphQL::Query.new` directly to create and execute a custom query instead."
|
657
|
+
warn " #{caller(1, 1).first}"
|
658
|
+
end
|
1245
659
|
if new_query_execution_strategy
|
1246
660
|
@query_execution_strategy = new_query_execution_strategy
|
1247
661
|
else
|
1248
|
-
@query_execution_strategy ||
|
662
|
+
@query_execution_strategy || (superclass.respond_to?(:query_execution_strategy) ? superclass.query_execution_strategy(deprecation_warning: false) : self.default_execution_strategy)
|
1249
663
|
end
|
1250
664
|
end
|
1251
665
|
|
1252
|
-
def mutation_execution_strategy(new_mutation_execution_strategy = nil)
|
666
|
+
def mutation_execution_strategy(new_mutation_execution_strategy = nil, deprecation_warning: true)
|
667
|
+
if deprecation_warning
|
668
|
+
warn "GraphQL::Schema.mutation_execution_strategy is deprecated without replacement. Use `GraphQL::Query.new` directly to create and execute a custom query instead."
|
669
|
+
warn " #{caller(1, 1).first}"
|
670
|
+
end
|
1253
671
|
if new_mutation_execution_strategy
|
1254
672
|
@mutation_execution_strategy = new_mutation_execution_strategy
|
1255
673
|
else
|
1256
|
-
@mutation_execution_strategy ||
|
674
|
+
@mutation_execution_strategy || (superclass.respond_to?(:mutation_execution_strategy) ? superclass.mutation_execution_strategy(deprecation_warning: false) : self.default_execution_strategy)
|
1257
675
|
end
|
1258
676
|
end
|
1259
677
|
|
1260
|
-
def subscription_execution_strategy(new_subscription_execution_strategy = nil)
|
678
|
+
def subscription_execution_strategy(new_subscription_execution_strategy = nil, deprecation_warning: true)
|
679
|
+
if deprecation_warning
|
680
|
+
warn "GraphQL::Schema.subscription_execution_strategy is deprecated without replacement. Use `GraphQL::Query.new` directly to create and execute a custom query instead."
|
681
|
+
warn " #{caller(1, 1).first}"
|
682
|
+
end
|
1261
683
|
if new_subscription_execution_strategy
|
1262
684
|
@subscription_execution_strategy = new_subscription_execution_strategy
|
1263
685
|
else
|
1264
|
-
@subscription_execution_strategy ||
|
686
|
+
@subscription_execution_strategy || (superclass.respond_to?(:subscription_execution_strategy) ? superclass.subscription_execution_strategy(deprecation_warning: false) : self.default_execution_strategy)
|
1265
687
|
end
|
1266
688
|
end
|
1267
689
|
|
@@ -1286,14 +708,34 @@ module GraphQL
|
|
1286
708
|
else
|
1287
709
|
string_or_document
|
1288
710
|
end
|
1289
|
-
query =
|
711
|
+
query = query_class.new(self, document: doc, context: context)
|
1290
712
|
validator_opts = { schema: self }
|
1291
713
|
rules && (validator_opts[:rules] = rules)
|
1292
714
|
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
1293
|
-
res = validator.validate(query, timeout: validate_timeout)
|
715
|
+
res = validator.validate(query, timeout: validate_timeout, max_errors: validate_max_errors)
|
1294
716
|
res[:errors]
|
1295
717
|
end
|
1296
718
|
|
719
|
+
def query_class(new_query_class = NOT_CONFIGURED)
|
720
|
+
if NOT_CONFIGURED.equal?(new_query_class)
|
721
|
+
@query_class || (superclass.respond_to?(:query_class) ? superclass.query_class : GraphQL::Query)
|
722
|
+
else
|
723
|
+
@query_class = new_query_class
|
724
|
+
end
|
725
|
+
end
|
726
|
+
|
727
|
+
attr_writer :validate_max_errors
|
728
|
+
|
729
|
+
def validate_max_errors(new_validate_max_errors = nil)
|
730
|
+
if new_validate_max_errors
|
731
|
+
@validate_max_errors = new_validate_max_errors
|
732
|
+
elsif defined?(@validate_max_errors)
|
733
|
+
@validate_max_errors
|
734
|
+
else
|
735
|
+
find_inherited_value(:validate_max_errors)
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
1297
739
|
attr_writer :max_complexity
|
1298
740
|
|
1299
741
|
def max_complexity(max_complexity = nil)
|
@@ -1313,19 +755,18 @@ module GraphQL
|
|
1313
755
|
end
|
1314
756
|
|
1315
757
|
def using_ast_analysis?
|
1316
|
-
|
758
|
+
true
|
1317
759
|
end
|
1318
760
|
|
1319
761
|
def interpreter?
|
1320
|
-
|
1321
|
-
mutation_execution_strategy == GraphQL::Execution::Interpreter &&
|
1322
|
-
subscription_execution_strategy == GraphQL::Execution::Interpreter
|
762
|
+
true
|
1323
763
|
end
|
1324
764
|
|
1325
765
|
attr_writer :interpreter
|
1326
766
|
|
1327
767
|
def error_bubbling(new_error_bubbling = nil)
|
1328
768
|
if !new_error_bubbling.nil?
|
769
|
+
warn("error_bubbling(#{new_error_bubbling.inspect}) is deprecated; the default value of `false` will be the only option in GraphQL-Ruby 3.0")
|
1329
770
|
@error_bubbling = new_error_bubbling
|
1330
771
|
else
|
1331
772
|
@error_bubbling.nil? ? find_inherited_value(:error_bubbling) : @error_bubbling
|
@@ -1336,9 +777,10 @@ module GraphQL
|
|
1336
777
|
|
1337
778
|
attr_writer :max_depth
|
1338
779
|
|
1339
|
-
def max_depth(new_max_depth = nil)
|
780
|
+
def max_depth(new_max_depth = nil, count_introspection_fields: true)
|
1340
781
|
if new_max_depth
|
1341
782
|
@max_depth = new_max_depth
|
783
|
+
@count_introspection_fields = count_introspection_fields
|
1342
784
|
elsif defined?(@max_depth)
|
1343
785
|
@max_depth
|
1344
786
|
else
|
@@ -1346,6 +788,14 @@ module GraphQL
|
|
1346
788
|
end
|
1347
789
|
end
|
1348
790
|
|
791
|
+
def count_introspection_fields
|
792
|
+
if defined?(@count_introspection_fields)
|
793
|
+
@count_introspection_fields
|
794
|
+
else
|
795
|
+
find_inherited_value(:count_introspection_fields, true)
|
796
|
+
end
|
797
|
+
end
|
798
|
+
|
1349
799
|
def disable_introspection_entry_points
|
1350
800
|
@disable_introspection_entry_points = true
|
1351
801
|
# TODO: this clears the cache made in `def types`. But this is not a great solution.
|
@@ -1388,15 +838,43 @@ module GraphQL
|
|
1388
838
|
end
|
1389
839
|
end
|
1390
840
|
|
841
|
+
# @param new_extra_types [Module] Type definitions to include in printing and introspection, even though they aren't referenced in the schema
|
842
|
+
# @return [Array<Module>] Type definitions added to this schema
|
843
|
+
def extra_types(*new_extra_types)
|
844
|
+
if new_extra_types.any?
|
845
|
+
new_extra_types = new_extra_types.flatten
|
846
|
+
@own_extra_types ||= []
|
847
|
+
@own_extra_types.concat(new_extra_types)
|
848
|
+
end
|
849
|
+
inherited_et = find_inherited_value(:extra_types, nil)
|
850
|
+
if inherited_et
|
851
|
+
if @own_extra_types
|
852
|
+
inherited_et + @own_extra_types
|
853
|
+
else
|
854
|
+
inherited_et
|
855
|
+
end
|
856
|
+
else
|
857
|
+
@own_extra_types || EMPTY_ARRAY
|
858
|
+
end
|
859
|
+
end
|
860
|
+
|
1391
861
|
def orphan_types(*new_orphan_types)
|
1392
862
|
if new_orphan_types.any?
|
1393
863
|
new_orphan_types = new_orphan_types.flatten
|
1394
864
|
add_type_and_traverse(new_orphan_types, root: false)
|
1395
|
-
@orphan_types = new_orphan_types
|
1396
865
|
own_orphan_types.concat(new_orphan_types.flatten)
|
1397
866
|
end
|
1398
867
|
|
1399
|
-
find_inherited_value(:orphan_types,
|
868
|
+
inherited_ot = find_inherited_value(:orphan_types, nil)
|
869
|
+
if inherited_ot
|
870
|
+
if own_orphan_types.any?
|
871
|
+
inherited_ot + own_orphan_types
|
872
|
+
else
|
873
|
+
inherited_ot
|
874
|
+
end
|
875
|
+
else
|
876
|
+
own_orphan_types
|
877
|
+
end
|
1400
878
|
end
|
1401
879
|
|
1402
880
|
def default_execution_strategy
|
@@ -1415,6 +893,26 @@ module GraphQL
|
|
1415
893
|
end
|
1416
894
|
end
|
1417
895
|
|
896
|
+
def default_logger(new_default_logger = NOT_CONFIGURED)
|
897
|
+
if NOT_CONFIGURED.equal?(new_default_logger)
|
898
|
+
if defined?(@default_logger)
|
899
|
+
@default_logger
|
900
|
+
elsif superclass.respond_to?(:default_logger)
|
901
|
+
superclass.default_logger
|
902
|
+
elsif defined?(Rails) && Rails.respond_to?(:logger) && (rails_logger = Rails.logger)
|
903
|
+
rails_logger
|
904
|
+
else
|
905
|
+
def_logger = Logger.new($stdout)
|
906
|
+
def_logger.info! # It doesn't output debug info by default
|
907
|
+
def_logger
|
908
|
+
end
|
909
|
+
elsif new_default_logger == nil
|
910
|
+
@default_logger = Logger.new(IO::NULL)
|
911
|
+
else
|
912
|
+
@default_logger = new_default_logger
|
913
|
+
end
|
914
|
+
end
|
915
|
+
|
1418
916
|
def context_class(new_context_class = nil)
|
1419
917
|
if new_context_class
|
1420
918
|
@context_class = new_context_class
|
@@ -1425,26 +923,63 @@ module GraphQL
|
|
1425
923
|
|
1426
924
|
def rescue_from(*err_classes, &handler_block)
|
1427
925
|
err_classes.each do |err_class|
|
1428
|
-
|
926
|
+
Execution::Errors.register_rescue_from(err_class, error_handlers[:subclass_handlers], handler_block)
|
927
|
+
end
|
928
|
+
end
|
929
|
+
|
930
|
+
NEW_HANDLER_HASH = ->(h, k) {
|
931
|
+
h[k] = {
|
932
|
+
class: k,
|
933
|
+
handler: nil,
|
934
|
+
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
935
|
+
}
|
936
|
+
}
|
937
|
+
|
938
|
+
def error_handlers
|
939
|
+
@error_handlers ||= {
|
940
|
+
class: nil,
|
941
|
+
handler: nil,
|
942
|
+
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
943
|
+
}
|
944
|
+
end
|
945
|
+
|
946
|
+
# @api private
|
947
|
+
def handle_or_reraise(context, err)
|
948
|
+
handler = Execution::Errors.find_handler_for(self, err.class)
|
949
|
+
if handler
|
950
|
+
obj = context[:current_object]
|
951
|
+
args = context[:current_arguments]
|
952
|
+
args = args && args.respond_to?(:keyword_arguments) ? args.keyword_arguments : nil
|
953
|
+
field = context[:current_field]
|
954
|
+
if obj.is_a?(GraphQL::Schema::Object)
|
955
|
+
obj = obj.object
|
956
|
+
end
|
957
|
+
handler[:handler].call(err, obj, args, context, field)
|
958
|
+
else
|
959
|
+
raise err
|
1429
960
|
end
|
1430
961
|
end
|
1431
962
|
|
1432
963
|
# rubocop:disable Lint/DuplicateMethods
|
1433
964
|
module ResolveTypeWithType
|
1434
965
|
def resolve_type(type, obj, ctx)
|
1435
|
-
|
966
|
+
maybe_lazy_resolve_type_result = if type.is_a?(Module) && type.respond_to?(:resolve_type)
|
1436
967
|
type.resolve_type(obj, ctx)
|
1437
968
|
else
|
1438
969
|
super
|
1439
970
|
end
|
1440
971
|
|
1441
|
-
after_lazy(
|
1442
|
-
if
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
972
|
+
after_lazy(maybe_lazy_resolve_type_result) do |resolve_type_result|
|
973
|
+
if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
|
974
|
+
resolved_type = resolve_type_result[0]
|
975
|
+
resolved_value = resolve_type_result[1]
|
976
|
+
else
|
977
|
+
resolved_type = resolve_type_result
|
978
|
+
resolved_value = obj
|
979
|
+
end
|
980
|
+
|
981
|
+
if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind))
|
982
|
+
[resolved_type, resolved_value]
|
1448
983
|
else
|
1449
984
|
raise ".resolve_type should return a type definition, but got #{resolved_type.inspect} (#{resolved_type.class}) from `resolve_type(#{type}, #{obj}, #{ctx})`"
|
1450
985
|
end
|
@@ -1453,17 +988,19 @@ module GraphQL
|
|
1453
988
|
end
|
1454
989
|
|
1455
990
|
def resolve_type(type, obj, ctx)
|
1456
|
-
|
1457
|
-
type
|
1458
|
-
else
|
1459
|
-
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})"
|
1460
|
-
end
|
991
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types, Interface types, or `loads:` (tried to resolve: #{type.name})"
|
1461
992
|
end
|
1462
993
|
# rubocop:enable Lint/DuplicateMethods
|
1463
994
|
|
1464
995
|
def inherited(child_class)
|
1465
996
|
if self == GraphQL::Schema
|
1466
997
|
child_class.directives(default_directives.values)
|
998
|
+
child_class.extend(SubclassGetReferencesTo)
|
999
|
+
end
|
1000
|
+
# Make sure the child class has these built out, so that
|
1001
|
+
# subclasses can be modified by later calls to `trace_with`
|
1002
|
+
own_trace_modes.each do |name, _class|
|
1003
|
+
child_class.own_trace_modes[name] = child_class.build_trace_mode(name)
|
1467
1004
|
end
|
1468
1005
|
child_class.singleton_class.prepend(ResolveTypeWithType)
|
1469
1006
|
super
|
@@ -1478,23 +1015,16 @@ module GraphQL
|
|
1478
1015
|
end
|
1479
1016
|
|
1480
1017
|
def visible?(member, ctx)
|
1481
|
-
member.
|
1018
|
+
member.visible?(ctx)
|
1482
1019
|
end
|
1483
1020
|
|
1484
|
-
def
|
1485
|
-
|
1021
|
+
def schema_directive(dir_class, **options)
|
1022
|
+
@own_schema_directives ||= []
|
1023
|
+
Member::HasDirectives.add_directive(self, @own_schema_directives, dir_class, options)
|
1486
1024
|
end
|
1487
1025
|
|
1488
|
-
|
1489
|
-
|
1490
|
-
#
|
1491
|
-
# By default, an error is added to the response. Override this hook to
|
1492
|
-
# track metrics or return a different error to the client.
|
1493
|
-
#
|
1494
|
-
# @param error [InaccessibleFieldsError] The analysis error for this check
|
1495
|
-
# @return [AnalysisError, nil] Return an error to skip the query
|
1496
|
-
def inaccessible_fields(error)
|
1497
|
-
error
|
1026
|
+
def schema_directives
|
1027
|
+
Member::HasDirectives.get_directives(self, @own_schema_directives, :schema_directives)
|
1498
1028
|
end
|
1499
1029
|
|
1500
1030
|
# This hook is called when an object fails an `authorized?` check.
|
@@ -1532,41 +1062,39 @@ module GraphQL
|
|
1532
1062
|
unauthorized_object(unauthorized_error)
|
1533
1063
|
end
|
1534
1064
|
|
1535
|
-
def type_error(
|
1536
|
-
|
1065
|
+
def type_error(type_error, ctx)
|
1066
|
+
case type_error
|
1067
|
+
when GraphQL::InvalidNullError
|
1068
|
+
ctx.errors << type_error
|
1069
|
+
when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
|
1070
|
+
raise type_error
|
1071
|
+
when GraphQL::IntegerDecodingError
|
1072
|
+
nil
|
1073
|
+
end
|
1537
1074
|
end
|
1538
1075
|
|
1539
1076
|
# A function to call when {#execute} receives an invalid query string
|
1540
1077
|
#
|
1541
1078
|
# The default is to add the error to `context.errors`
|
1542
|
-
# @param
|
1079
|
+
# @param parse_err [GraphQL::ParseError] The error encountered during parsing
|
1543
1080
|
# @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
|
1544
1081
|
# @return void
|
1545
1082
|
def parse_error(parse_err, ctx)
|
1546
1083
|
ctx.errors.push(parse_err)
|
1547
1084
|
end
|
1548
1085
|
|
1549
|
-
# @return [GraphQL::Execution::Errors]
|
1550
|
-
def error_handler
|
1551
|
-
@error_handler ||= GraphQL::Execution::Errors.new(self)
|
1552
|
-
end
|
1553
|
-
|
1554
1086
|
def lazy_resolve(lazy_class, value_method)
|
1555
1087
|
lazy_methods.set(lazy_class, value_method)
|
1556
1088
|
end
|
1557
1089
|
|
1558
1090
|
def instrument(instrument_step, instrumenter, options = {})
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
step = if instrument_step == :field && options[:after_built_ins]
|
1564
|
-
:field_after_built_ins
|
1565
|
-
else
|
1566
|
-
instrument_step
|
1567
|
-
end
|
1091
|
+
warn <<~WARN
|
1092
|
+
Schema.instrument is deprecated, use `trace_with` instead: https://graphql-ruby.org/queries/tracing.html"
|
1093
|
+
(From `#{self}.instrument(#{instrument_step}, #{instrumenter})` at #{caller(1, 1).first})
|
1568
1094
|
|
1569
|
-
|
1095
|
+
WARN
|
1096
|
+
trace_with(Tracing::LegacyHooksTrace)
|
1097
|
+
own_instrumenters[instrument_step] << instrumenter
|
1570
1098
|
end
|
1571
1099
|
|
1572
1100
|
# Add several directives at once
|
@@ -1576,7 +1104,12 @@ module GraphQL
|
|
1576
1104
|
new_directives.flatten.each { |d| directive(d) }
|
1577
1105
|
end
|
1578
1106
|
|
1579
|
-
find_inherited_value(:directives, default_directives)
|
1107
|
+
inherited_dirs = find_inherited_value(:directives, default_directives)
|
1108
|
+
if own_directives.any?
|
1109
|
+
inherited_dirs.merge(own_directives)
|
1110
|
+
else
|
1111
|
+
inherited_dirs
|
1112
|
+
end
|
1580
1113
|
end
|
1581
1114
|
|
1582
1115
|
# Attach a single directive to this schema
|
@@ -1591,10 +1124,17 @@ module GraphQL
|
|
1591
1124
|
"include" => GraphQL::Schema::Directive::Include,
|
1592
1125
|
"skip" => GraphQL::Schema::Directive::Skip,
|
1593
1126
|
"deprecated" => GraphQL::Schema::Directive::Deprecated,
|
1127
|
+
"oneOf" => GraphQL::Schema::Directive::OneOf,
|
1128
|
+
"specifiedBy" => GraphQL::Schema::Directive::SpecifiedBy,
|
1594
1129
|
}.freeze
|
1595
1130
|
end
|
1596
1131
|
|
1597
1132
|
def tracer(new_tracer)
|
1133
|
+
default_trace = trace_class_for(:default, build: true)
|
1134
|
+
if default_trace.nil? || !(default_trace < GraphQL::Tracing::CallLegacyTracers)
|
1135
|
+
trace_with(GraphQL::Tracing::CallLegacyTracers)
|
1136
|
+
end
|
1137
|
+
|
1598
1138
|
own_tracers << new_tracer
|
1599
1139
|
end
|
1600
1140
|
|
@@ -1602,25 +1142,96 @@ module GraphQL
|
|
1602
1142
|
find_inherited_value(:tracers, EMPTY_ARRAY) + own_tracers
|
1603
1143
|
end
|
1604
1144
|
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1145
|
+
# Mix `trace_mod` into this schema's `Trace` class so that its methods
|
1146
|
+
# will be called at runtime.
|
1147
|
+
#
|
1148
|
+
# @param trace_mod [Module] A module that implements tracing methods
|
1149
|
+
# @param mode [Symbol] Trace module will only be used for this trade mode
|
1150
|
+
# @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
|
1151
|
+
# @return [void]
|
1152
|
+
def trace_with(trace_mod, mode: :default, **options)
|
1153
|
+
if mode.is_a?(Array)
|
1154
|
+
mode.each { |m| trace_with(trace_mod, mode: m, **options) }
|
1155
|
+
else
|
1156
|
+
tc = own_trace_modes[mode] ||= build_trace_mode(mode)
|
1157
|
+
tc.include(trace_mod)
|
1158
|
+
own_trace_modules[mode] << trace_mod
|
1159
|
+
add_trace_options_for(mode, options)
|
1160
|
+
if mode == :default
|
1161
|
+
# This module is being added as a default tracer. If any other mode classes
|
1162
|
+
# have already been created, but get their default behavior from a superclass,
|
1163
|
+
# Then mix this into this schema's subclass.
|
1164
|
+
# (But don't mix it into mode classes that aren't default-based.)
|
1165
|
+
own_trace_modes.each do |other_mode_name, other_mode_class|
|
1166
|
+
if other_mode_class < DefaultTraceClass
|
1167
|
+
# Don't add it back to the inheritance tree if it's already there
|
1168
|
+
if !(other_mode_class < trace_mod)
|
1169
|
+
other_mode_class.include(trace_mod)
|
1170
|
+
end
|
1171
|
+
# Add any options so they'll be available
|
1172
|
+
add_trace_options_for(other_mode_name, options)
|
1173
|
+
end
|
1174
|
+
end
|
1175
|
+
end
|
1608
1176
|
end
|
1609
|
-
|
1177
|
+
nil
|
1610
1178
|
end
|
1611
1179
|
|
1612
|
-
|
1613
|
-
|
1180
|
+
# The options hash for this trace mode
|
1181
|
+
# @return [Hash]
|
1182
|
+
def trace_options_for(mode)
|
1183
|
+
@trace_options_for_mode ||= {}
|
1184
|
+
@trace_options_for_mode[mode] ||= begin
|
1185
|
+
# It may be time to create an options hash for a mode that wasn't registered yet.
|
1186
|
+
# Mix in the default options in that case.
|
1187
|
+
default_options = mode == :default ? EMPTY_HASH : trace_options_for(:default)
|
1188
|
+
# Make sure this returns a new object so that other hashes aren't modified later
|
1189
|
+
if superclass.respond_to?(:trace_options_for)
|
1190
|
+
superclass.trace_options_for(mode).merge(default_options)
|
1191
|
+
else
|
1192
|
+
default_options.dup
|
1193
|
+
end
|
1194
|
+
end
|
1614
1195
|
end
|
1615
1196
|
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1619
|
-
|
1197
|
+
# Create a trace instance which will include the trace modules specified for the optional mode.
|
1198
|
+
#
|
1199
|
+
# If no `mode:` is given, then {default_trace_mode} will be used.
|
1200
|
+
#
|
1201
|
+
# @param mode [Symbol] Trace modules for this trade mode will be included
|
1202
|
+
# @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
|
1203
|
+
# @return [Tracing::Trace]
|
1204
|
+
def new_trace(mode: nil, **options)
|
1205
|
+
target = options[:query] || options[:multiplex]
|
1206
|
+
mode ||= target && target.context[:trace_mode]
|
1207
|
+
|
1208
|
+
trace_mode = if mode
|
1209
|
+
mode
|
1210
|
+
elsif target && target.context[:backtrace]
|
1211
|
+
if default_trace_mode != :default
|
1212
|
+
raise ArgumentError, "Can't use `context[:backtrace]` with a custom default trace mode (`#{dm.inspect}`)"
|
1213
|
+
else
|
1214
|
+
own_trace_modes[:default_backtrace] ||= build_trace_mode(:default_backtrace)
|
1215
|
+
options_trace_mode = :default
|
1216
|
+
:default_backtrace
|
1217
|
+
end
|
1620
1218
|
else
|
1621
|
-
|
1622
|
-
MiddlewareChain.new(steps: all_middleware, final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
1219
|
+
default_trace_mode
|
1623
1220
|
end
|
1221
|
+
|
1222
|
+
options_trace_mode ||= trace_mode
|
1223
|
+
base_trace_options = trace_options_for(options_trace_mode)
|
1224
|
+
trace_options = base_trace_options.merge(options)
|
1225
|
+
trace_class_for_mode = trace_class_for(trace_mode, build: true)
|
1226
|
+
trace_class_for_mode.new(**trace_options)
|
1227
|
+
end
|
1228
|
+
|
1229
|
+
def query_analyzer(new_analyzer)
|
1230
|
+
own_query_analyzers << new_analyzer
|
1231
|
+
end
|
1232
|
+
|
1233
|
+
def query_analyzers
|
1234
|
+
find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
|
1624
1235
|
end
|
1625
1236
|
|
1626
1237
|
def multiplex_analyzer(new_analyzer)
|
@@ -1631,6 +1242,14 @@ module GraphQL
|
|
1631
1242
|
find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
|
1632
1243
|
end
|
1633
1244
|
|
1245
|
+
def sanitized_printer(new_sanitized_printer = nil)
|
1246
|
+
if new_sanitized_printer
|
1247
|
+
@own_sanitized_printer = new_sanitized_printer
|
1248
|
+
else
|
1249
|
+
@own_sanitized_printer || GraphQL::Language::SanitizedPrinter
|
1250
|
+
end
|
1251
|
+
end
|
1252
|
+
|
1634
1253
|
# Execute a query on itself.
|
1635
1254
|
# @see {Query#initialize} for arguments.
|
1636
1255
|
# @return [Hash] query result, ready to be serialized as JSON
|
@@ -1643,6 +1262,9 @@ module GraphQL
|
|
1643
1262
|
{
|
1644
1263
|
backtrace: ctx[:backtrace],
|
1645
1264
|
tracers: ctx[:tracers],
|
1265
|
+
trace: ctx[:trace],
|
1266
|
+
dataloader: ctx[:dataloader],
|
1267
|
+
trace_mode: ctx[:trace_mode],
|
1646
1268
|
}
|
1647
1269
|
else
|
1648
1270
|
{}
|
@@ -1667,17 +1289,12 @@ module GraphQL
|
|
1667
1289
|
# }
|
1668
1290
|
#
|
1669
1291
|
# @see {Query#initialize} for query keyword arguments
|
1670
|
-
# @see {Execution::Multiplex#
|
1292
|
+
# @see {Execution::Multiplex#run_all} for multiplex keyword arguments
|
1671
1293
|
# @param queries [Array<Hash>] Keyword arguments for each query
|
1672
1294
|
# @param context [Hash] Multiplex-level context
|
1673
1295
|
# @return [Array<Hash>] One result for each query in the input
|
1674
1296
|
def multiplex(queries, **kwargs)
|
1675
|
-
|
1676
|
-
self
|
1677
|
-
else
|
1678
|
-
graphql_definition
|
1679
|
-
end
|
1680
|
-
GraphQL::Execution::Multiplex.run_all(schema, queries, **kwargs)
|
1297
|
+
GraphQL::Execution::Interpreter.run_all(self, queries, **kwargs)
|
1681
1298
|
end
|
1682
1299
|
|
1683
1300
|
def instrumenters
|
@@ -1689,12 +1306,10 @@ module GraphQL
|
|
1689
1306
|
|
1690
1307
|
# @api private
|
1691
1308
|
def add_subscription_extension_if_necessary
|
1692
|
-
if
|
1309
|
+
if !defined?(@subscription_extension_added) && subscription && self.subscriptions
|
1693
1310
|
@subscription_extension_added = true
|
1694
|
-
|
1695
|
-
|
1696
|
-
else
|
1697
|
-
subscription.fields.each do |name, field|
|
1311
|
+
subscription.all_field_definitions.each do |field|
|
1312
|
+
if !field.extensions.any? { |ext| ext.is_a?(Subscriptions::DefaultSubscriptionResolveExtension) }
|
1698
1313
|
field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
|
1699
1314
|
end
|
1700
1315
|
end
|
@@ -1705,8 +1320,68 @@ module GraphQL
|
|
1705
1320
|
query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
|
1706
1321
|
end
|
1707
1322
|
|
1323
|
+
# Call the given block at the right time, either:
|
1324
|
+
# - Right away, if `value` is not registered with `lazy_resolve`
|
1325
|
+
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
1326
|
+
# @api private
|
1327
|
+
def after_lazy(value, &block)
|
1328
|
+
if lazy?(value)
|
1329
|
+
GraphQL::Execution::Lazy.new do
|
1330
|
+
result = sync_lazy(value)
|
1331
|
+
# The returned result might also be lazy, so check it, too
|
1332
|
+
after_lazy(result, &block)
|
1333
|
+
end
|
1334
|
+
else
|
1335
|
+
yield(value) if block_given?
|
1336
|
+
end
|
1337
|
+
end
|
1338
|
+
|
1339
|
+
# Override this method to handle lazy objects in a custom way.
|
1340
|
+
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
1341
|
+
# @return [Object] A GraphQL-ready (non-lazy) object
|
1342
|
+
# @api private
|
1343
|
+
def sync_lazy(value)
|
1344
|
+
lazy_method = lazy_method_name(value)
|
1345
|
+
if lazy_method
|
1346
|
+
synced_value = value.public_send(lazy_method)
|
1347
|
+
sync_lazy(synced_value)
|
1348
|
+
else
|
1349
|
+
value
|
1350
|
+
end
|
1351
|
+
end
|
1352
|
+
|
1353
|
+
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
|
1354
|
+
def lazy_method_name(obj)
|
1355
|
+
lazy_methods.get(obj)
|
1356
|
+
end
|
1357
|
+
|
1358
|
+
# @return [Boolean] True if this object should be lazily resolved
|
1359
|
+
def lazy?(obj)
|
1360
|
+
!!lazy_method_name(obj)
|
1361
|
+
end
|
1362
|
+
|
1363
|
+
# Return a lazy if any of `maybe_lazies` are lazy,
|
1364
|
+
# otherwise, call the block eagerly and return the result.
|
1365
|
+
# @param maybe_lazies [Array]
|
1366
|
+
# @api private
|
1367
|
+
def after_any_lazies(maybe_lazies)
|
1368
|
+
if maybe_lazies.any? { |l| lazy?(l) }
|
1369
|
+
GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
|
1370
|
+
yield result
|
1371
|
+
end
|
1372
|
+
else
|
1373
|
+
yield maybe_lazies
|
1374
|
+
end
|
1375
|
+
end
|
1376
|
+
|
1708
1377
|
private
|
1709
1378
|
|
1379
|
+
def add_trace_options_for(mode, new_options)
|
1380
|
+
t_opts = trace_options_for(mode)
|
1381
|
+
t_opts.merge!(new_options)
|
1382
|
+
nil
|
1383
|
+
end
|
1384
|
+
|
1710
1385
|
# @param t [Module, Array<Module>]
|
1711
1386
|
# @return [void]
|
1712
1387
|
def add_type_and_traverse(t, root:)
|
@@ -1716,7 +1391,36 @@ module GraphQL
|
|
1716
1391
|
end
|
1717
1392
|
new_types = Array(t)
|
1718
1393
|
addition = Schema::Addition.new(schema: self, own_types: own_types, new_types: new_types)
|
1719
|
-
|
1394
|
+
addition.types.each do |name, types_entry| # rubocop:disable Development/ContextIsPassedCop -- build-time, not query-time
|
1395
|
+
if (prev_entry = own_types[name])
|
1396
|
+
prev_entries = case prev_entry
|
1397
|
+
when Array
|
1398
|
+
prev_entry
|
1399
|
+
when Module
|
1400
|
+
own_types[name] = [prev_entry]
|
1401
|
+
else
|
1402
|
+
raise "Invariant: unexpected prev_entry at #{name.inspect} when adding #{t.inspect}"
|
1403
|
+
end
|
1404
|
+
|
1405
|
+
case types_entry
|
1406
|
+
when Array
|
1407
|
+
prev_entries.concat(types_entry)
|
1408
|
+
prev_entries.uniq! # in case any are being re-visited
|
1409
|
+
when Module
|
1410
|
+
if !prev_entries.include?(types_entry)
|
1411
|
+
prev_entries << types_entry
|
1412
|
+
end
|
1413
|
+
else
|
1414
|
+
raise "Invariant: unexpected types_entry at #{name} when adding #{t.inspect}"
|
1415
|
+
end
|
1416
|
+
else
|
1417
|
+
if types_entry.is_a?(Array)
|
1418
|
+
types_entry.uniq!
|
1419
|
+
end
|
1420
|
+
own_types[name] = types_entry
|
1421
|
+
end
|
1422
|
+
end
|
1423
|
+
|
1720
1424
|
own_possible_types.merge!(addition.possible_types) { |key, old_val, new_val| old_val + new_val }
|
1721
1425
|
own_union_memberships.merge!(addition.union_memberships)
|
1722
1426
|
|
@@ -1739,7 +1443,7 @@ module GraphQL
|
|
1739
1443
|
else
|
1740
1444
|
@lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
|
1741
1445
|
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
1742
|
-
@lazy_methods.set(GraphQL::Dataloader::Request, :
|
1446
|
+
@lazy_methods.set(GraphQL::Dataloader::Request, :load_with_deprecation_warning)
|
1743
1447
|
end
|
1744
1448
|
end
|
1745
1449
|
@lazy_methods
|
@@ -1785,68 +1489,33 @@ module GraphQL
|
|
1785
1489
|
@defined_query_analyzers ||= []
|
1786
1490
|
end
|
1787
1491
|
|
1788
|
-
def all_middleware
|
1789
|
-
find_inherited_value(:all_middleware, EMPTY_ARRAY) + own_middleware
|
1790
|
-
end
|
1791
|
-
|
1792
|
-
def own_middleware
|
1793
|
-
@own_middleware ||= []
|
1794
|
-
end
|
1795
|
-
|
1796
1492
|
def own_multiplex_analyzers
|
1797
1493
|
@own_multiplex_analyzers ||= []
|
1798
1494
|
end
|
1799
|
-
end
|
1800
|
-
|
1801
|
-
def dataloader_class
|
1802
|
-
self.class.dataloader_class
|
1803
|
-
end
|
1804
|
-
|
1805
|
-
# Install these here so that subclasses will also install it.
|
1806
|
-
use(GraphQL::Pagination::Connections)
|
1807
|
-
|
1808
|
-
protected
|
1809
1495
|
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
1813
|
-
|
1814
|
-
# Lazily create a middleware and add it to the schema
|
1815
|
-
# (Don't add it if it's not used)
|
1816
|
-
def rescue_middleware
|
1817
|
-
@rescue_middleware ||= GraphQL::Schema::RescueMiddleware.new.tap { |m| middleware.insert(0, m) }
|
1818
|
-
end
|
1819
|
-
|
1820
|
-
private
|
1821
|
-
|
1822
|
-
def rebuild_artifacts
|
1823
|
-
if @rebuilding_artifacts
|
1824
|
-
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."
|
1825
|
-
else
|
1826
|
-
@rebuilding_artifacts = true
|
1827
|
-
@introspection_system = Schema::IntrospectionSystem.new(self)
|
1828
|
-
traversal = Traversal.new(self)
|
1829
|
-
@types = traversal.type_map
|
1830
|
-
@root_types = [query, mutation, subscription]
|
1831
|
-
@instrumented_field_map = traversal.instrumented_field_map
|
1832
|
-
@type_reference_map = traversal.type_reference_map
|
1833
|
-
@union_memberships = traversal.union_memberships
|
1834
|
-
@find_cache = {}
|
1835
|
-
@finder = Finder.new(self)
|
1836
|
-
end
|
1837
|
-
ensure
|
1838
|
-
@rebuilding_artifacts = false
|
1839
|
-
end
|
1840
|
-
|
1841
|
-
class CyclicalDefinitionError < GraphQL::Error
|
1496
|
+
# This is overridden in subclasses to check the inheritance chain
|
1497
|
+
def get_references_to(type_name)
|
1498
|
+
@own_references_to[type_name]
|
1499
|
+
end
|
1842
1500
|
end
|
1843
1501
|
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1502
|
+
module SubclassGetReferencesTo
|
1503
|
+
def get_references_to(type_name)
|
1504
|
+
own_refs = @own_references_to[type_name]
|
1505
|
+
inherited_refs = superclass.references_to(type_name)
|
1506
|
+
if inherited_refs&.any?
|
1507
|
+
if own_refs&.any?
|
1508
|
+
own_refs + inherited_refs
|
1509
|
+
else
|
1510
|
+
inherited_refs
|
1511
|
+
end
|
1512
|
+
else
|
1513
|
+
own_refs
|
1514
|
+
end
|
1849
1515
|
end
|
1850
1516
|
end
|
1517
|
+
|
1518
|
+
# Install these here so that subclasses will also install it.
|
1519
|
+
self.connections = GraphQL::Pagination::Connections.new(schema: self)
|
1851
1520
|
end
|
1852
1521
|
end
|