graphql 1.12.12 → 2.4.8
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 +60 -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 +8 -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 +22 -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/analyzer.rb +89 -0
- data/lib/graphql/analysis/field_usage.rb +65 -28
- data/lib/graphql/analysis/max_query_complexity.rb +11 -17
- data/lib/graphql/analysis/max_query_depth.rb +13 -19
- data/lib/graphql/analysis/query_complexity.rb +156 -61
- data/lib/graphql/analysis/query_depth.rb +38 -23
- data/lib/graphql/analysis/visitor.rb +283 -0
- data/lib/graphql/analysis.rb +90 -6
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/inspect_result.rb +0 -12
- 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/current.rb +52 -0
- data/lib/graphql/dataloader/async_dataloader.rb +89 -0
- data/lib/graphql/dataloader/null_dataloader.rb +4 -2
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +125 -33
- data/lib/graphql/dataloader.rb +193 -143
- 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/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments.rb +2 -2
- data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -36
- data/lib/graphql/execution/interpreter/resolve.rb +38 -4
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +175 -0
- data/lib/graphql/execution/interpreter/runtime.rb +447 -403
- data/lib/graphql/execution/interpreter.rb +126 -80
- data/lib/graphql/execution/lazy.rb +11 -21
- data/lib/graphql/execution/lookahead.rb +133 -55
- 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 +6 -4
- 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 +4 -4
- data/lib/graphql/introspection/input_value_type.rb +10 -4
- data/lib/graphql/introspection/schema_type.rb +17 -15
- data/lib/graphql/introspection/type_type.rb +29 -16
- data/lib/graphql/introspection.rb +6 -2
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/language/block_string.rb +37 -25
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +122 -81
- data/lib/graphql/language/lexer.rb +364 -1467
- data/lib/graphql/language/nodes.rb +197 -106
- data/lib/graphql/language/parser.rb +799 -1920
- data/lib/graphql/language/printer.rb +372 -160
- data/lib/graphql/language/sanitized_printer.rb +25 -27
- data/lib/graphql/language/static_visitor.rb +167 -0
- data/lib/graphql/language/visitor.rb +188 -141
- data/lib/graphql/language.rb +62 -1
- 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 +146 -222
- data/lib/graphql/query/input_validation_result.rb +10 -1
- data/lib/graphql/query/null_context.rb +15 -32
- data/lib/graphql/query/validation_pipeline.rb +15 -39
- data/lib/graphql/query/variable_validation_error.rb +3 -3
- data/lib/graphql/query/variables.rb +35 -17
- data/lib/graphql/query.rb +149 -82
- data/lib/graphql/railtie.rb +15 -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/graphql/field_type_in_block.rb +144 -0
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
- data/lib/graphql/rubocop.rb +6 -0
- data/lib/graphql/schema/addition.rb +98 -54
- data/lib/graphql/schema/always_visible.rb +14 -0
- data/lib/graphql/schema/argument.rb +179 -82
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +77 -39
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +4 -4
- 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 +36 -22
- data/lib/graphql/schema/enum.rb +158 -63
- data/lib/graphql/schema/enum_value.rb +12 -21
- data/lib/graphql/schema/field/connection_extension.rb +7 -17
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +521 -359
- 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 +160 -0
- data/lib/graphql/schema/input_object.rb +148 -99
- data/lib/graphql/schema/interface.rb +41 -64
- data/lib/graphql/schema/introspection_system.rb +12 -26
- data/lib/graphql/schema/late_bound_type.rb +12 -2
- data/lib/graphql/schema/list.rb +18 -7
- data/lib/graphql/schema/loader.rb +6 -5
- data/lib/graphql/schema/member/base_dsl_methods.rb +32 -18
- data/lib/graphql/schema/member/build_type.rb +16 -13
- data/lib/graphql/schema/member/has_arguments.rb +270 -86
- 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 +169 -31
- data/lib/graphql/schema/member/has_interfaces.rb +143 -0
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- 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 +16 -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 +7 -9
- data/lib/graphql/schema/non_null.rb +7 -7
- data/lib/graphql/schema/object.rb +38 -119
- data/lib/graphql/schema/printer.rb +24 -25
- data/lib/graphql/schema/relay_classic_mutation.rb +13 -91
- data/lib/graphql/schema/resolver/has_payload_type.rb +46 -11
- data/lib/graphql/schema/resolver.rb +118 -115
- data/lib/graphql/schema/scalar.rb +20 -21
- data/lib/graphql/schema/subscription.rb +95 -21
- data/lib/graphql/schema/timeout.rb +25 -29
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/type_membership.rb +21 -4
- data/lib/graphql/schema/union.rb +16 -16
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +62 -0
- 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 +56 -18
- data/lib/graphql/schema/validator.rb +38 -28
- data/lib/graphql/schema/visibility/migration.rb +188 -0
- data/lib/graphql/schema/visibility/profile.rb +359 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +294 -0
- data/lib/graphql/schema/warden.rb +423 -134
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +1015 -1057
- data/lib/graphql/static_validation/all_rules.rb +3 -1
- data/lib/graphql/static_validation/base_visitor.rb +15 -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 +24 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +4 -3
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +13 -7
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +15 -13
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +13 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +62 -35
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
- 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 +7 -5
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +14 -8
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +14 -8
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
- data/lib/graphql/static_validation/validation_context.rb +32 -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 +49 -11
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +40 -1
- data/lib/graphql/subscriptions/event.rb +87 -38
- data/lib/graphql/subscriptions/serialize.rb +27 -3
- data/lib/graphql/subscriptions.rb +63 -49
- data/lib/graphql/testing/helpers.rb +155 -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 +253 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +4 -2
- data/lib/graphql/tracing/appsignal_trace.rb +79 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +17 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +185 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +27 -15
- data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +11 -28
- data/lib/graphql/tracing/legacy_trace.rb +12 -0
- data/lib/graphql/tracing/new_relic_trace.rb +77 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +45 -0
- data/lib/graphql/tracing/notifications_tracing.rb +61 -0
- data/lib/graphql/tracing/null_trace.rb +9 -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 +6 -2
- data/lib/graphql/tracing/prometheus_trace.rb +94 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +5 -3
- data/lib/graphql/tracing/scout_trace.rb +74 -0
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +114 -0
- data/lib/graphql/tracing/statsd_trace.rb +58 -0
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +79 -0
- data/lib/graphql/tracing.rb +29 -52
- data/lib/graphql/type_kinds.rb +7 -4
- 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 +92 -32
- data/lib/graphql/types/relay/edge_behaviors.rb +46 -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 +11 -2
- data/lib/graphql/types/relay.rb +0 -3
- data/lib/graphql/types/string.rb +2 -2
- data/lib/graphql/types.rb +18 -10
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +82 -137
- data/readme.md +13 -6
- metadata +127 -186
- data/lib/graphql/analysis/analyze_query.rb +0 -98
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -28
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -23
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -234
- data/lib/graphql/analysis/ast/query_depth.rb +0 -56
- data/lib/graphql/analysis/ast/visitor.rb +0 -268
- data/lib/graphql/analysis/ast.rb +0 -91
- 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/language/token.rb +0 -38
- 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/invalid_type_error.rb +0 -7
- 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
@@ -1,98 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module GraphQL
|
3
|
-
module Analysis
|
4
|
-
module_function
|
5
|
-
|
6
|
-
def use(schema_class)
|
7
|
-
schema = schema_class.is_a?(Class) ? schema_class : schema_class.target
|
8
|
-
schema.analysis_engine = self
|
9
|
-
end
|
10
|
-
|
11
|
-
# @return [void]
|
12
|
-
def analyze_multiplex(multiplex, analyzers)
|
13
|
-
multiplex.trace("analyze_multiplex", { multiplex: multiplex }) do
|
14
|
-
reducer_states = analyzers.map { |r| ReducerState.new(r, multiplex) }
|
15
|
-
query_results = multiplex.queries.map do |query|
|
16
|
-
if query.valid?
|
17
|
-
analyze_query(query, query.analyzers, multiplex_states: reducer_states)
|
18
|
-
else
|
19
|
-
[]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
multiplex_results = reducer_states.map(&:finalize_reducer)
|
24
|
-
multiplex_errors = analysis_errors(multiplex_results)
|
25
|
-
|
26
|
-
multiplex.queries.each_with_index do |query, idx|
|
27
|
-
query.analysis_errors = multiplex_errors + analysis_errors(query_results[idx])
|
28
|
-
end
|
29
|
-
end
|
30
|
-
nil
|
31
|
-
end
|
32
|
-
|
33
|
-
# Visit `query`'s internal representation, calling `analyzers` along the way.
|
34
|
-
#
|
35
|
-
# - First, query analyzers are filtered down by calling `.analyze?(query)`, if they respond to that method
|
36
|
-
# - Then, query analyzers are initialized by calling `.initial_value(query)`, if they respond to that method.
|
37
|
-
# - Then, they receive `.call(memo, visit_type, irep_node)`, where visit type is `:enter` or `:leave`.
|
38
|
-
# - Last, they receive `.final_value(memo)`, if they respond to that method.
|
39
|
-
#
|
40
|
-
# It returns an array of final `memo` values in the order that `analyzers` were passed in.
|
41
|
-
#
|
42
|
-
# @param query [GraphQL::Query]
|
43
|
-
# @param analyzers [Array<#call>] Objects that respond to `#call(memo, visit_type, irep_node)`
|
44
|
-
# @return [Array<Any>] Results from those analyzers
|
45
|
-
def analyze_query(query, analyzers, multiplex_states: [])
|
46
|
-
GraphQL::Deprecation.warn "Legacy analysis will be removed in GraphQL-Ruby 2.0, please upgrade to AST Analysis: https://graphql-ruby.org/queries/ast_analysis.html (schema: #{query.schema})"
|
47
|
-
|
48
|
-
query.trace("analyze_query", { query: query }) do
|
49
|
-
analyzers_to_run = analyzers.select do |analyzer|
|
50
|
-
if analyzer.respond_to?(:analyze?)
|
51
|
-
analyzer.analyze?(query)
|
52
|
-
else
|
53
|
-
true
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
reducer_states = analyzers_to_run.map { |r| ReducerState.new(r, query) } + multiplex_states
|
58
|
-
|
59
|
-
irep = query.internal_representation
|
60
|
-
|
61
|
-
irep.operation_definitions.each do |name, op_node|
|
62
|
-
reduce_node(op_node, reducer_states)
|
63
|
-
end
|
64
|
-
|
65
|
-
reducer_states.map(&:finalize_reducer)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
module_function
|
72
|
-
|
73
|
-
# Enter the node, visit its children, then leave the node.
|
74
|
-
def reduce_node(irep_node, reducer_states)
|
75
|
-
visit_analyzers(:enter, irep_node, reducer_states)
|
76
|
-
|
77
|
-
irep_node.typed_children.each do |type_defn, children|
|
78
|
-
children.each do |name, child_irep_node|
|
79
|
-
reduce_node(child_irep_node, reducer_states)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
visit_analyzers(:leave, irep_node, reducer_states)
|
84
|
-
end
|
85
|
-
|
86
|
-
def visit_analyzers(visit_type, irep_node, reducer_states)
|
87
|
-
reducer_states.each do |reducer_state|
|
88
|
-
next_memo = reducer_state.call(visit_type, irep_node)
|
89
|
-
|
90
|
-
reducer_state.memo = next_memo
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def analysis_errors(results)
|
95
|
-
results.flatten.select { |r| r.is_a?(GraphQL::AnalysisError) }
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
@@ -1,84 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module GraphQL
|
3
|
-
module Analysis
|
4
|
-
module AST
|
5
|
-
# Query analyzer for query ASTs. Query analyzers respond to visitor style methods
|
6
|
-
# but are prefixed by `enter` and `leave`.
|
7
|
-
#
|
8
|
-
# When an analyzer is initialized with a Multiplex, you can always get the current query from
|
9
|
-
# `visitor.query` in the visit methods.
|
10
|
-
#
|
11
|
-
# @param [GraphQL::Query, GraphQL::Execution::Multiplex] The query or multiplex to analyze
|
12
|
-
class Analyzer
|
13
|
-
def initialize(subject)
|
14
|
-
@subject = subject
|
15
|
-
|
16
|
-
if subject.is_a?(GraphQL::Query)
|
17
|
-
@query = subject
|
18
|
-
@multiplex = nil
|
19
|
-
else
|
20
|
-
@multiplex = subject
|
21
|
-
@query = nil
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# Analyzer hook to decide at analysis time whether a query should
|
26
|
-
# be analyzed or not.
|
27
|
-
# @return [Boolean] If the query should be analyzed or not
|
28
|
-
def analyze?
|
29
|
-
true
|
30
|
-
end
|
31
|
-
|
32
|
-
# The result for this analyzer. Returning {GraphQL::AnalysisError} results
|
33
|
-
# in a query error.
|
34
|
-
# @return [Any] The analyzer result
|
35
|
-
def result
|
36
|
-
raise GraphQL::RequiredImplementationMissingError
|
37
|
-
end
|
38
|
-
|
39
|
-
class << self
|
40
|
-
private
|
41
|
-
|
42
|
-
def build_visitor_hooks(member_name)
|
43
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
44
|
-
def on_enter_#{member_name}(node, parent, visitor)
|
45
|
-
end
|
46
|
-
|
47
|
-
def on_leave_#{member_name}(node, parent, visitor)
|
48
|
-
end
|
49
|
-
EOS
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
build_visitor_hooks :argument
|
54
|
-
build_visitor_hooks :directive
|
55
|
-
build_visitor_hooks :document
|
56
|
-
build_visitor_hooks :enum
|
57
|
-
build_visitor_hooks :field
|
58
|
-
build_visitor_hooks :fragment_spread
|
59
|
-
build_visitor_hooks :inline_fragment
|
60
|
-
build_visitor_hooks :input_object
|
61
|
-
build_visitor_hooks :list_type
|
62
|
-
build_visitor_hooks :non_null_type
|
63
|
-
build_visitor_hooks :null_value
|
64
|
-
build_visitor_hooks :operation_definition
|
65
|
-
build_visitor_hooks :type_name
|
66
|
-
build_visitor_hooks :variable_definition
|
67
|
-
build_visitor_hooks :variable_identifier
|
68
|
-
build_visitor_hooks :abstract_node
|
69
|
-
|
70
|
-
protected
|
71
|
-
|
72
|
-
# @return [GraphQL::Query, GraphQL::Execution::Multiplex] Whatever this analyzer is analyzing
|
73
|
-
attr_reader :subject
|
74
|
-
|
75
|
-
# @return [GraphQL::Query, nil] `nil` if this analyzer is visiting a multiplex
|
76
|
-
# (When this is `nil`, use `visitor.query` inside visit methods to get the current query)
|
77
|
-
attr_reader :query
|
78
|
-
|
79
|
-
# @return [GraphQL::Execution::Multiplex, nil] `nil` if this analyzer is visiting a query
|
80
|
-
attr_reader :multiplex
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module GraphQL
|
3
|
-
module Analysis
|
4
|
-
module AST
|
5
|
-
class FieldUsage < Analyzer
|
6
|
-
def initialize(query)
|
7
|
-
super
|
8
|
-
@used_fields = Set.new
|
9
|
-
@used_deprecated_fields = Set.new
|
10
|
-
end
|
11
|
-
|
12
|
-
def on_leave_field(node, parent, visitor)
|
13
|
-
field_defn = visitor.field_definition
|
14
|
-
field = "#{visitor.parent_type_definition.graphql_name}.#{field_defn.graphql_name}"
|
15
|
-
@used_fields << field
|
16
|
-
@used_deprecated_fields << field if field_defn.deprecation_reason
|
17
|
-
end
|
18
|
-
|
19
|
-
def result
|
20
|
-
{
|
21
|
-
used_fields: @used_fields.to_a,
|
22
|
-
used_deprecated_fields: @used_deprecated_fields.to_a
|
23
|
-
}
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require_relative "./query_complexity"
|
3
|
-
module GraphQL
|
4
|
-
module Analysis
|
5
|
-
module AST
|
6
|
-
# Used under the hood to implement complexity validation,
|
7
|
-
# see {Schema#max_complexity} and {Query#max_complexity}
|
8
|
-
class MaxQueryComplexity < QueryComplexity
|
9
|
-
def result
|
10
|
-
return if subject.max_complexity.nil?
|
11
|
-
|
12
|
-
total_complexity = max_possible_complexity
|
13
|
-
|
14
|
-
if total_complexity > subject.max_complexity
|
15
|
-
GraphQL::AnalysisError.new("Query has complexity of #{total_complexity}, which exceeds max complexity of #{subject.max_complexity}")
|
16
|
-
else
|
17
|
-
nil
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module GraphQL
|
3
|
-
module Analysis
|
4
|
-
module AST
|
5
|
-
class MaxQueryDepth < QueryDepth
|
6
|
-
def result
|
7
|
-
configured_max_depth = if query
|
8
|
-
query.max_depth
|
9
|
-
else
|
10
|
-
multiplex.schema.max_depth
|
11
|
-
end
|
12
|
-
|
13
|
-
if configured_max_depth && @max_depth > configured_max_depth
|
14
|
-
GraphQL::AnalysisError.new("Query has depth of #{@max_depth}, which exceeds max depth of #{configured_max_depth}")
|
15
|
-
else
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,234 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module GraphQL
|
3
|
-
module Analysis
|
4
|
-
# Calculate the complexity of a query, using {Field#complexity} values.
|
5
|
-
module AST
|
6
|
-
class QueryComplexity < Analyzer
|
7
|
-
# State for the query complexity calculation:
|
8
|
-
# - `complexities_on_type` holds complexity scores for each type in an IRep node
|
9
|
-
def initialize(query)
|
10
|
-
super
|
11
|
-
@complexities_on_type_by_query = {}
|
12
|
-
end
|
13
|
-
|
14
|
-
# Overide this method to use the complexity result
|
15
|
-
def result
|
16
|
-
max_possible_complexity
|
17
|
-
end
|
18
|
-
|
19
|
-
class ScopedTypeComplexity
|
20
|
-
# A single proc for {#scoped_children} hashes. Use this to avoid repeated allocations,
|
21
|
-
# since the lexical binding isn't important.
|
22
|
-
HASH_CHILDREN = ->(h, k) { h[k] = {} }
|
23
|
-
|
24
|
-
attr_reader :field_definition, :response_path, :query
|
25
|
-
|
26
|
-
# @param node [Language::Nodes::Field] The AST node; used for providing argument values when necessary
|
27
|
-
# @param field_definition [GraphQL::Field, GraphQL::Schema::Field] Used for getting the `.complexity` configuration
|
28
|
-
# @param query [GraphQL::Query] Used for `query.possible_types`
|
29
|
-
# @param response_path [Array<String>] The path to the response key for the field
|
30
|
-
def initialize(node, field_definition, query, response_path)
|
31
|
-
@node = node
|
32
|
-
@field_definition = field_definition
|
33
|
-
@query = query
|
34
|
-
@response_path = response_path
|
35
|
-
@scoped_children = nil
|
36
|
-
end
|
37
|
-
|
38
|
-
# Returns true if this field has no selections, ie, it's a scalar.
|
39
|
-
# We need a quick way to check whether we should continue traversing.
|
40
|
-
def terminal?
|
41
|
-
@scoped_children.nil?
|
42
|
-
end
|
43
|
-
|
44
|
-
# This value is only calculated when asked for to avoid needless hash allocations.
|
45
|
-
# Also, if it's never asked for, we determine that this scope complexity
|
46
|
-
# is a scalar field ({#terminal?}).
|
47
|
-
# @return [Hash<Hash<Class => ScopedTypeComplexity>]
|
48
|
-
def scoped_children
|
49
|
-
@scoped_children ||= Hash.new(&HASH_CHILDREN)
|
50
|
-
end
|
51
|
-
|
52
|
-
def own_complexity(child_complexity)
|
53
|
-
defined_complexity = @field_definition.complexity
|
54
|
-
case defined_complexity
|
55
|
-
when Proc
|
56
|
-
arguments = @query.arguments_for(@node, @field_definition)
|
57
|
-
defined_complexity.call(@query.context, arguments.keyword_arguments, child_complexity)
|
58
|
-
when Numeric
|
59
|
-
defined_complexity + child_complexity
|
60
|
-
else
|
61
|
-
raise("Invalid complexity: #{defined_complexity.inspect} on #{@field_definition.name}")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def on_enter_field(node, parent, visitor)
|
67
|
-
# We don't want to visit fragment definitions,
|
68
|
-
# we'll visit them when we hit the spreads instead
|
69
|
-
return if visitor.visiting_fragment_definition?
|
70
|
-
return if visitor.skipping?
|
71
|
-
parent_type = visitor.parent_type_definition
|
72
|
-
field_key = node.alias || node.name
|
73
|
-
# Find the complexity calculation for this field --
|
74
|
-
# if we're re-entering a selection, we'll already have one.
|
75
|
-
# Otherwise, make a new one and store it.
|
76
|
-
#
|
77
|
-
# `node` and `visitor.field_definition` may appear from a cache,
|
78
|
-
# but I think that's ok. If the arguments _didn't_ match,
|
79
|
-
# then the query would have been rejected as invalid.
|
80
|
-
complexities_on_type = @complexities_on_type_by_query[visitor.query] ||= [ScopedTypeComplexity.new(nil, nil, query, visitor.response_path)]
|
81
|
-
|
82
|
-
complexity = complexities_on_type.last.scoped_children[parent_type][field_key] ||= ScopedTypeComplexity.new(node, visitor.field_definition, visitor.query, visitor.response_path)
|
83
|
-
# Push it on the stack.
|
84
|
-
complexities_on_type.push(complexity)
|
85
|
-
end
|
86
|
-
|
87
|
-
def on_leave_field(node, parent, visitor)
|
88
|
-
# We don't want to visit fragment definitions,
|
89
|
-
# we'll visit them when we hit the spreads instead
|
90
|
-
return if visitor.visiting_fragment_definition?
|
91
|
-
return if visitor.skipping?
|
92
|
-
complexities_on_type = @complexities_on_type_by_query[visitor.query]
|
93
|
-
complexities_on_type.pop
|
94
|
-
end
|
95
|
-
|
96
|
-
private
|
97
|
-
|
98
|
-
# @return [Integer]
|
99
|
-
def max_possible_complexity
|
100
|
-
@complexities_on_type_by_query.reduce(0) do |total, (query, complexities_on_type)|
|
101
|
-
root_complexity = complexities_on_type.last
|
102
|
-
# Use this entry point to calculate the total complexity
|
103
|
-
total_complexity_for_query = merged_max_complexity_for_scopes(query, [root_complexity.scoped_children])
|
104
|
-
total + total_complexity_for_query
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# @param query [GraphQL::Query] Used for `query.possible_types`
|
109
|
-
# @param scoped_children_hashes [Array<Hash>] Array of scoped children hashes
|
110
|
-
# @return [Integer]
|
111
|
-
def merged_max_complexity_for_scopes(query, scoped_children_hashes)
|
112
|
-
# Figure out what scopes are possible here.
|
113
|
-
# Use a hash, but ignore the values; it's just a fast way to work with the keys.
|
114
|
-
all_scopes = {}
|
115
|
-
scoped_children_hashes.each do |h|
|
116
|
-
all_scopes.merge!(h)
|
117
|
-
end
|
118
|
-
|
119
|
-
# If an abstract scope is present, but _all_ of its concrete types
|
120
|
-
# are also in the list, remove it from the list of scopes to check,
|
121
|
-
# because every possible type is covered by a concrete type.
|
122
|
-
# (That is, there are no remainder types to check.)
|
123
|
-
prev_keys = all_scopes.keys
|
124
|
-
prev_keys.each do |scope|
|
125
|
-
next unless scope.kind.abstract?
|
126
|
-
|
127
|
-
missing_concrete_types = query.possible_types(scope).select { |t| !all_scopes.key?(t) }
|
128
|
-
# This concrete type is possible _only_ as a member of the abstract type.
|
129
|
-
# So, attribute to it the complexity which belongs to the abstract type.
|
130
|
-
missing_concrete_types.each do |concrete_scope|
|
131
|
-
all_scopes[concrete_scope] = all_scopes[scope]
|
132
|
-
end
|
133
|
-
all_scopes.delete(scope)
|
134
|
-
end
|
135
|
-
|
136
|
-
# This will hold `{ type => int }` pairs, one for each possible branch
|
137
|
-
complexity_by_scope = {}
|
138
|
-
|
139
|
-
# For each scope,
|
140
|
-
# find the lexical selections that might apply to it,
|
141
|
-
# and gather them together into an array.
|
142
|
-
# Then, treat the set of selection hashes
|
143
|
-
# as a set and calculate the complexity for them as a unit
|
144
|
-
all_scopes.each do |scope, _|
|
145
|
-
# These will be the selections on `scope`
|
146
|
-
children_for_scope = []
|
147
|
-
scoped_children_hashes.each do |sc_h|
|
148
|
-
sc_h.each do |inner_scope, children_hash|
|
149
|
-
if applies_to?(query, scope, inner_scope)
|
150
|
-
children_for_scope << children_hash
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
# Calculate the complexity for `scope`, merging all
|
156
|
-
# possible lexical branches.
|
157
|
-
complexity_value = merged_max_complexity(query, children_for_scope)
|
158
|
-
complexity_by_scope[scope] = complexity_value
|
159
|
-
end
|
160
|
-
|
161
|
-
# Return the max complexity among all scopes
|
162
|
-
complexity_by_scope.each_value.max
|
163
|
-
end
|
164
|
-
|
165
|
-
def applies_to?(query, left_scope, right_scope)
|
166
|
-
if left_scope == right_scope
|
167
|
-
# This can happen when several branches are being analyzed together
|
168
|
-
true
|
169
|
-
else
|
170
|
-
# Check if these two scopes have _any_ types in common.
|
171
|
-
possible_right_types = query.possible_types(right_scope)
|
172
|
-
possible_left_types = query.possible_types(left_scope)
|
173
|
-
!(possible_right_types & possible_left_types).empty?
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
# A hook which is called whenever a field's max complexity is calculated.
|
178
|
-
# Override this method to capture individual field complexity details.
|
179
|
-
#
|
180
|
-
# @param scoped_type_complexity [ScopedTypeComplexity]
|
181
|
-
# @param max_complexity [Numeric] Field's maximum complexity including child complexity
|
182
|
-
# @param child_complexity [Numeric, nil] Field's child complexity
|
183
|
-
def field_complexity(scoped_type_complexity, max_complexity:, child_complexity: nil)
|
184
|
-
end
|
185
|
-
|
186
|
-
# @param children_for_scope [Array<Hash>] An array of `scoped_children[scope]` hashes
|
187
|
-
# (`{field_key => complexity}`)
|
188
|
-
# @return [Integer] Complexity value for all these selections in the current scope
|
189
|
-
def merged_max_complexity(query, children_for_scope)
|
190
|
-
all_keys = []
|
191
|
-
children_for_scope.each do |c|
|
192
|
-
all_keys.concat(c.keys)
|
193
|
-
end
|
194
|
-
all_keys.uniq!
|
195
|
-
complexity_for_keys = {}
|
196
|
-
|
197
|
-
all_keys.each do |child_key|
|
198
|
-
scoped_children_for_key = nil
|
199
|
-
complexity_for_key = nil
|
200
|
-
children_for_scope.each do |children_hash|
|
201
|
-
next unless children_hash.key?(child_key)
|
202
|
-
|
203
|
-
complexity_for_key = children_hash[child_key]
|
204
|
-
if complexity_for_key.terminal?
|
205
|
-
# Assume that all terminals would return the same complexity
|
206
|
-
# Since it's a terminal, its child complexity is zero.
|
207
|
-
complexity = complexity_for_key.own_complexity(0)
|
208
|
-
complexity_for_keys[child_key] = complexity
|
209
|
-
|
210
|
-
field_complexity(complexity_for_key, max_complexity: complexity, child_complexity: nil)
|
211
|
-
else
|
212
|
-
scoped_children_for_key ||= []
|
213
|
-
scoped_children_for_key << complexity_for_key.scoped_children
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
next unless scoped_children_for_key
|
218
|
-
|
219
|
-
child_complexity = merged_max_complexity_for_scopes(query, scoped_children_for_key)
|
220
|
-
# This is the _last_ one we visited; assume it's representative.
|
221
|
-
max_complexity = complexity_for_key.own_complexity(child_complexity)
|
222
|
-
|
223
|
-
field_complexity(complexity_for_key, max_complexity: max_complexity, child_complexity: child_complexity)
|
224
|
-
|
225
|
-
complexity_for_keys[child_key] = max_complexity
|
226
|
-
end
|
227
|
-
|
228
|
-
# Calculate the child complexity by summing the complexity of all selections
|
229
|
-
complexity_for_keys.each_value.inject(0, &:+)
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module GraphQL
|
3
|
-
module Analysis
|
4
|
-
# A query reducer for measuring the depth of a given query.
|
5
|
-
#
|
6
|
-
# See https://graphql-ruby.org/queries/ast_analysis.html for more examples.
|
7
|
-
#
|
8
|
-
# @example Logging the depth of a query
|
9
|
-
# class LogQueryDepth < GraphQL::Analysis::QueryDepth
|
10
|
-
# def result
|
11
|
-
# log("GraphQL query depth: #{@max_depth}")
|
12
|
-
# end
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# # In your Schema file:
|
16
|
-
#
|
17
|
-
# class MySchema < GraphQL::Schema
|
18
|
-
# use GraphQL::Analysis::AST
|
19
|
-
# query_analyzer LogQueryDepth
|
20
|
-
# end
|
21
|
-
#
|
22
|
-
# # When you run the query, the depth will get logged:
|
23
|
-
#
|
24
|
-
# Schema.execute(query_str)
|
25
|
-
# # GraphQL query depth: 8
|
26
|
-
#
|
27
|
-
module AST
|
28
|
-
class QueryDepth < Analyzer
|
29
|
-
def initialize(query)
|
30
|
-
@max_depth = 0
|
31
|
-
@current_depth = 0
|
32
|
-
super
|
33
|
-
end
|
34
|
-
|
35
|
-
def on_enter_field(node, parent, visitor)
|
36
|
-
return if visitor.skipping? || visitor.visiting_fragment_definition?
|
37
|
-
|
38
|
-
@current_depth += 1
|
39
|
-
end
|
40
|
-
|
41
|
-
def on_leave_field(node, parent, visitor)
|
42
|
-
return if visitor.skipping? || visitor.visiting_fragment_definition?
|
43
|
-
|
44
|
-
if @max_depth < @current_depth
|
45
|
-
@max_depth = @current_depth
|
46
|
-
end
|
47
|
-
@current_depth -= 1
|
48
|
-
end
|
49
|
-
|
50
|
-
def result
|
51
|
-
@max_depth
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|