graphql 2.6.12 → 2.6.13
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.
- checksums.yaml +4 -4
- data/.rdoc_options +4 -0
- data/lib/generators/graphql/core.rb +1 -0
- data/lib/generators/graphql/detailed_trace_generator.rb +1 -0
- data/lib/generators/graphql/enum_generator.rb +1 -0
- data/lib/generators/graphql/field_extractor.rb +1 -0
- data/lib/generators/graphql/input_generator.rb +1 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +1 -0
- data/lib/generators/graphql/install_generator.rb +1 -0
- data/lib/generators/graphql/interface_generator.rb +1 -0
- data/lib/generators/graphql/loader_generator.rb +8 -2
- data/lib/generators/graphql/mutation_create_generator.rb +8 -2
- data/lib/generators/graphql/mutation_delete_generator.rb +8 -2
- data/lib/generators/graphql/mutation_generator.rb +8 -2
- data/lib/generators/graphql/mutation_update_generator.rb +8 -2
- data/lib/generators/graphql/object_generator.rb +1 -0
- data/lib/generators/graphql/orm_mutations_base.rb +8 -2
- data/lib/generators/graphql/relay.rb +1 -0
- data/lib/generators/graphql/relay_generator.rb +1 -0
- data/lib/generators/graphql/scalar_generator.rb +1 -0
- data/lib/generators/graphql/type_generator.rb +38 -8
- data/lib/generators/graphql/union_generator.rb +1 -0
- data/lib/graphql/analysis/analyzer.rb +35 -9
- data/lib/graphql/analysis/field_usage.rb +1 -0
- data/lib/graphql/analysis/max_query_complexity.rb +2 -1
- data/lib/graphql/analysis/max_query_depth.rb +1 -0
- data/lib/graphql/analysis/query_complexity.rb +57 -20
- data/lib/graphql/analysis/query_depth.rb +17 -12
- data/lib/graphql/analysis/visitor.rb +79 -16
- data/lib/graphql/analysis.rb +23 -6
- data/lib/graphql/analysis_error.rb +1 -0
- data/lib/graphql/autoload.rb +30 -7
- data/lib/graphql/backtrace/table.rb +21 -5
- data/lib/graphql/backtrace/traced_error.rb +8 -3
- data/lib/graphql/backtrace.rb +14 -9
- data/lib/graphql/coercion_error.rb +1 -0
- data/lib/graphql/current.rb +44 -19
- data/lib/graphql/dashboard/application_controller.rb +1 -0
- data/lib/graphql/dashboard/detailed_traces.rb +1 -0
- data/lib/graphql/dashboard/installable.rb +1 -0
- data/lib/graphql/dashboard/landings_controller.rb +1 -0
- data/lib/graphql/dashboard/limiters.rb +1 -0
- data/lib/graphql/dashboard/operation_store.rb +1 -0
- data/lib/graphql/dashboard/statics_controller.rb +1 -0
- data/lib/graphql/dashboard/subscriptions.rb +1 -0
- data/lib/graphql/dashboard.rb +36 -22
- data/lib/graphql/dataloader/active_record_association_source.rb +1 -0
- data/lib/graphql/dataloader/active_record_source.rb +1 -0
- data/lib/graphql/dataloader/async_dataloader.rb +8 -7
- data/lib/graphql/dataloader/null_dataloader.rb +4 -3
- data/lib/graphql/dataloader/request.rb +8 -2
- data/lib/graphql/dataloader/request_all.rb +8 -2
- data/lib/graphql/dataloader/source.rb +127 -35
- data/lib/graphql/dataloader.rb +91 -42
- data/lib/graphql/date_encoding_error.rb +2 -1
- data/lib/graphql/dig.rb +12 -3
- data/lib/graphql/duration_encoding_error.rb +2 -1
- data/lib/graphql/execution/directive_checks.rb +8 -3
- data/lib/graphql/execution/errors.rb +20 -6
- data/lib/graphql/execution/field_resolve_step.rb +22 -6
- data/lib/graphql/execution/finalize.rb +12 -6
- data/lib/graphql/execution/input_values.rb +2 -1
- data/lib/graphql/execution/interpreter/argument_value.rb +17 -5
- data/lib/graphql/execution/interpreter/arguments.rb +24 -9
- data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -1
- data/lib/graphql/execution/interpreter/execution_errors.rb +1 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +1 -0
- data/lib/graphql/execution/interpreter/resolve.rb +18 -8
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +4 -1
- data/lib/graphql/execution/interpreter/runtime.rb +66 -23
- data/lib/graphql/execution/interpreter.rb +15 -6
- data/lib/graphql/execution/lazy/lazy_method_map.rb +21 -8
- data/lib/graphql/execution/lazy.rb +34 -10
- data/lib/graphql/execution/load_argument_step.rb +1 -0
- data/lib/graphql/execution/lookahead.rb +137 -54
- data/lib/graphql/execution/multiplex.rb +4 -4
- data/lib/graphql/execution/next.rb +7 -0
- data/lib/graphql/execution/prepare_object_step.rb +1 -0
- data/lib/graphql/execution/resolve_type_step.rb +2 -1
- data/lib/graphql/execution/runner.rb +9 -3
- data/lib/graphql/execution/selections_step.rb +3 -2
- data/lib/graphql/execution.rb +2 -2
- data/lib/graphql/execution_error.rb +19 -10
- data/lib/graphql/float_decoding_error.rb +1 -0
- data/lib/graphql/float_encoding_error.rb +7 -2
- data/lib/graphql/integer_decoding_error.rb +2 -1
- data/lib/graphql/integer_encoding_error.rb +8 -3
- data/lib/graphql/introspection/base_object.rb +3 -1
- data/lib/graphql/introspection/directive_location_enum.rb +1 -0
- data/lib/graphql/introspection/directive_type.rb +1 -0
- data/lib/graphql/introspection/dynamic_fields.rb +1 -0
- data/lib/graphql/introspection/entry_points.rb +1 -0
- data/lib/graphql/introspection/enum_value_type.rb +1 -0
- data/lib/graphql/introspection/field_type.rb +1 -0
- data/lib/graphql/introspection/input_value_type.rb +1 -0
- data/lib/graphql/introspection/introspection_query.rb +1 -0
- data/lib/graphql/introspection/schema_type.rb +1 -0
- data/lib/graphql/introspection/type_kind_enum.rb +1 -0
- data/lib/graphql/introspection/type_type.rb +1 -0
- data/lib/graphql/introspection.rb +1 -0
- data/lib/graphql/invalid_name_error.rb +1 -0
- data/lib/graphql/invalid_null_error.rb +19 -6
- data/lib/graphql/language/block_string.rb +2 -1
- data/lib/graphql/language/cache.rb +10 -4
- data/lib/graphql/language/comment.rb +1 -0
- data/lib/graphql/language/definition_slice.rb +1 -0
- data/lib/graphql/language/document_from_schema_definition.rb +9 -10
- data/lib/graphql/language/generation.rb +23 -9
- data/lib/graphql/language/lexer.rb +5 -0
- data/lib/graphql/language/nodes.rb +2094 -419
- data/lib/graphql/language/parser.rb +17 -11
- data/lib/graphql/language/printer.rb +31 -16
- data/lib/graphql/language/sanitized_printer.rb +16 -5
- data/lib/graphql/language/static_visitor.rb +19 -4
- data/lib/graphql/language/visitor.rb +51 -29
- data/lib/graphql/language.rb +13 -7
- data/lib/graphql/load_application_object_failed_error.rb +14 -5
- data/lib/graphql/name_validator.rb +1 -0
- data/lib/graphql/pagination/active_record_relation_connection.rb +1 -0
- data/lib/graphql/pagination/array_connection.rb +20 -6
- data/lib/graphql/pagination/connection.rb +178 -48
- data/lib/graphql/pagination/connections.rb +21 -14
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -0
- data/lib/graphql/pagination/relation_connection.rb +118 -21
- data/lib/graphql/pagination/sequel_dataset_connection.rb +1 -0
- data/lib/graphql/pagination.rb +1 -0
- data/lib/graphql/parse_error.rb +1 -0
- data/lib/graphql/query/context/scoped_context.rb +2 -1
- data/lib/graphql/query/context.rb +106 -35
- data/lib/graphql/query/fingerprint.rb +15 -7
- data/lib/graphql/query/input_validation_result.rb +1 -0
- data/lib/graphql/query/null_context.rb +1 -0
- data/lib/graphql/query/partial.rb +28 -15
- data/lib/graphql/query/result.rb +15 -5
- data/lib/graphql/query/validation_pipeline.rb +16 -6
- data/lib/graphql/query/variable_validation_error.rb +1 -0
- data/lib/graphql/query/variables.rb +4 -1
- data/lib/graphql/query.rb +193 -49
- data/lib/graphql/railtie.rb +7 -3
- data/lib/graphql/rake_task/validate.rb +72 -17
- data/lib/graphql/rake_task.rb +55 -23
- data/lib/graphql/relay/range_add.rb +32 -21
- data/lib/graphql/relay.rb +1 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +9 -6
- data/lib/graphql/rubocop/graphql/default_required_true.rb +9 -6
- data/lib/graphql/rubocop/graphql/field_type_in_block.rb +12 -8
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +9 -5
- data/lib/graphql/rubocop.rb +1 -0
- data/lib/graphql/runtime_error.rb +1 -0
- data/lib/graphql/runtime_type_error.rb +1 -0
- data/lib/graphql/schema/addition.rb +18 -6
- data/lib/graphql/schema/always_visible.rb +1 -0
- data/lib/graphql/schema/argument.rb +265 -42
- data/lib/graphql/schema/base_64_encoder.rb +2 -2
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -0
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +2 -2
- data/lib/graphql/schema/build_from_definition.rb +94 -27
- data/lib/graphql/schema/built_in_types.rb +1 -0
- data/lib/graphql/schema/directive/deprecated.rb +1 -0
- data/lib/graphql/schema/directive/feature.rb +39 -22
- data/lib/graphql/schema/directive/flagged.rb +6 -1
- data/lib/graphql/schema/directive/include.rb +1 -0
- data/lib/graphql/schema/directive/one_of.rb +1 -0
- data/lib/graphql/schema/directive/skip.rb +1 -0
- data/lib/graphql/schema/directive/specified_by.rb +1 -0
- data/lib/graphql/schema/directive/transform.rb +17 -8
- data/lib/graphql/schema/directive.rb +12 -7
- data/lib/graphql/schema/enum.rb +99 -38
- data/lib/graphql/schema/enum_value.rb +21 -13
- data/lib/graphql/schema/field/connection_extension.rb +10 -2
- data/lib/graphql/schema/field/scope_extension.rb +1 -0
- data/lib/graphql/schema/field.rb +621 -109
- data/lib/graphql/schema/field_extension.rb +89 -34
- data/lib/graphql/schema/find_inherited_value.rb +5 -3
- data/lib/graphql/schema/finder.rb +22 -8
- data/lib/graphql/schema/has_single_input_argument.rb +39 -6
- data/lib/graphql/schema/input_object.rb +40 -13
- data/lib/graphql/schema/interface.rb +33 -17
- data/lib/graphql/schema/introspection_system.rb +7 -3
- data/lib/graphql/schema/late_bound_type.rb +2 -2
- data/lib/graphql/schema/list.rb +15 -4
- data/lib/graphql/schema/loader.rb +23 -12
- data/lib/graphql/schema/member/base_dsl_methods.rb +58 -12
- data/lib/graphql/schema/member/build_type.rb +16 -5
- data/lib/graphql/schema/member/graphql_type_names.rb +10 -6
- data/lib/graphql/schema/member/has_arguments.rb +115 -48
- data/lib/graphql/schema/member/has_ast_node.rb +1 -0
- data/lib/graphql/schema/member/has_authorization.rb +5 -0
- data/lib/graphql/schema/member/has_dataloader.rb +91 -34
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -2
- data/lib/graphql/schema/member/has_directives.rb +38 -10
- data/lib/graphql/schema/member/has_fields.rb +151 -70
- data/lib/graphql/schema/member/has_interfaces.rb +10 -2
- data/lib/graphql/schema/member/has_path.rb +14 -5
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +1 -0
- data/lib/graphql/schema/member/has_validators.rb +19 -4
- data/lib/graphql/schema/member/relay_shortcuts.rb +10 -2
- data/lib/graphql/schema/member/scoped.rb +14 -3
- data/lib/graphql/schema/member/type_system_helpers.rb +36 -6
- data/lib/graphql/schema/member/validates_input.rb +1 -0
- data/lib/graphql/schema/member.rb +9 -2
- data/lib/graphql/schema/mutation.rb +50 -46
- data/lib/graphql/schema/non_null.rb +21 -5
- data/lib/graphql/schema/object.rb +33 -12
- data/lib/graphql/schema/printer.rb +52 -31
- data/lib/graphql/schema/ractor_shareable.rb +6 -2
- data/lib/graphql/schema/relay_classic_mutation.rb +3 -3
- data/lib/graphql/schema/resolver/has_payload_type.rb +29 -7
- data/lib/graphql/schema/resolver.rb +156 -45
- data/lib/graphql/schema/scalar.rb +1 -0
- data/lib/graphql/schema/subscription.rb +67 -28
- data/lib/graphql/schema/timeout.rb +65 -25
- data/lib/graphql/schema/type_expression.rb +14 -5
- data/lib/graphql/schema/type_membership.rb +29 -10
- data/lib/graphql/schema/union.rb +4 -2
- data/lib/graphql/schema/unique_within_type.rb +24 -5
- data/lib/graphql/schema/validator/all_validator.rb +17 -9
- data/lib/graphql/schema/validator/allow_blank_validator.rb +8 -2
- data/lib/graphql/schema/validator/allow_null_validator.rb +8 -2
- data/lib/graphql/schema/validator/exclusion_validator.rb +14 -5
- data/lib/graphql/schema/validator/format_validator.rb +21 -10
- data/lib/graphql/schema/validator/inclusion_validator.rb +15 -6
- data/lib/graphql/schema/validator/length_validator.rb +23 -12
- data/lib/graphql/schema/validator/numericality_validator.rb +29 -16
- data/lib/graphql/schema/validator/required_validator.rb +45 -31
- data/lib/graphql/schema/validator.rb +89 -25
- data/lib/graphql/schema/visibility/migration.rb +14 -7
- data/lib/graphql/schema/visibility/profile.rb +20 -17
- data/lib/graphql/schema/visibility/visit.rb +12 -10
- data/lib/graphql/schema/visibility.rb +24 -20
- data/lib/graphql/schema/warden.rb +117 -31
- data/lib/graphql/schema/wrapper.rb +4 -1
- data/lib/graphql/schema.rb +1046 -300
- data/lib/graphql/static_validation/all_rules.rb +2 -1
- data/lib/graphql/static_validation/base_visitor.rb +48 -8
- data/lib/graphql/static_validation/definition_dependencies.rb +27 -7
- data/lib/graphql/static_validation/error.rb +3 -0
- data/lib/graphql/static_validation/interpreter_visitor.rb +1 -0
- data/lib/graphql/static_validation/literal_validator.rb +1 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +4 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +1 -0
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +3 -0
- data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +1 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +1 -0
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -0
- data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +1 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +3 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +3 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +9 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +295 -134
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +14 -2
- data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +3 -0
- data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +3 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +3 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +3 -0
- data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +3 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +3 -0
- data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +1 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +3 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +1 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +3 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +1 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +3 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +1 -0
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +1 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +4 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +1 -0
- data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +3 -0
- data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +1 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +3 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +1 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +1 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +1 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +4 -1
- data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +1 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +3 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +3 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +207 -51
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +1 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +3 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +1 -0
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +6 -3
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +1 -0
- data/lib/graphql/static_validation/validation_context.rb +3 -2
- data/lib/graphql/static_validation/validation_timeout_error.rb +1 -0
- data/lib/graphql/static_validation/validator.rb +41 -16
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/string_encoding_error.rb +1 -0
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +85 -65
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +10 -4
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +1 -0
- data/lib/graphql/subscriptions/event.rb +25 -6
- data/lib/graphql/subscriptions/serialize.rb +58 -19
- data/lib/graphql/subscriptions.rb +172 -46
- data/lib/graphql/testing/helpers.rb +17 -4
- data/lib/graphql/testing/mock_action_cable.rb +55 -33
- data/lib/graphql/testing.rb +1 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +17 -9
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +2 -1
- data/lib/graphql/tracing/appoptics_trace.rb +2 -1
- data/lib/graphql/tracing/appoptics_tracing.rb +2 -1
- data/lib/graphql/tracing/appsignal_trace.rb +16 -7
- data/lib/graphql/tracing/appsignal_tracing.rb +7 -3
- data/lib/graphql/tracing/call_legacy_tracers.rb +1 -0
- data/lib/graphql/tracing/data_dog_trace.rb +17 -6
- data/lib/graphql/tracing/data_dog_tracing.rb +10 -3
- data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +1 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +1 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +1 -0
- data/lib/graphql/tracing/detailed_trace.rb +105 -42
- data/lib/graphql/tracing/legacy_hooks_trace.rb +5 -0
- data/lib/graphql/tracing/legacy_trace.rb +1 -0
- data/lib/graphql/tracing/monitor_trace.rb +17 -11
- data/lib/graphql/tracing/new_relic_trace.rb +17 -8
- data/lib/graphql/tracing/new_relic_tracing.rb +7 -3
- data/lib/graphql/tracing/notifications_trace.rb +11 -8
- data/lib/graphql/tracing/notifications_tracing.rb +23 -7
- data/lib/graphql/tracing/null_trace.rb +1 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +1 -0
- data/lib/graphql/tracing/perfetto_trace.rb +41 -19
- data/lib/graphql/tracing/platform_trace.rb +3 -1
- data/lib/graphql/tracing/platform_tracing.rb +16 -7
- data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +1 -0
- data/lib/graphql/tracing/prometheus_trace.rb +22 -13
- data/lib/graphql/tracing/prometheus_tracing.rb +1 -0
- data/lib/graphql/tracing/scout_trace.rb +10 -4
- data/lib/graphql/tracing/scout_tracing.rb +7 -3
- data/lib/graphql/tracing/sentry_trace.rb +12 -5
- data/lib/graphql/tracing/statsd_trace.rb +12 -6
- data/lib/graphql/tracing/statsd_tracing.rb +7 -1
- data/lib/graphql/tracing/trace.rb +231 -58
- data/lib/graphql/tracing.rb +25 -9
- data/lib/graphql/type_kinds.rb +2 -1
- data/lib/graphql/types/big_int.rb +1 -0
- data/lib/graphql/types/boolean.rb +1 -0
- data/lib/graphql/types/float.rb +1 -0
- data/lib/graphql/types/id.rb +1 -0
- data/lib/graphql/types/int.rb +2 -1
- data/lib/graphql/types/iso_8601_date.rb +21 -4
- data/lib/graphql/types/iso_8601_date_time.rb +33 -6
- data/lib/graphql/types/iso_8601_duration.rb +42 -9
- data/lib/graphql/types/json.rb +1 -0
- data/lib/graphql/types/relay/base_connection.rb +38 -32
- data/lib/graphql/types/relay/base_edge.rb +15 -9
- data/lib/graphql/types/relay/connection_behaviors.rb +19 -3
- data/lib/graphql/types/relay/edge_behaviors.rb +17 -4
- data/lib/graphql/types/relay/has_node_field.rb +6 -1
- data/lib/graphql/types/relay/has_nodes_field.rb +6 -1
- data/lib/graphql/types/relay/node.rb +1 -0
- data/lib/graphql/types/relay/node_behaviors.rb +5 -1
- data/lib/graphql/types/relay/page_info.rb +1 -0
- data/lib/graphql/types/relay/page_info_behaviors.rb +1 -0
- data/lib/graphql/types/relay.rb +4 -3
- data/lib/graphql/types/string.rb +1 -0
- data/lib/graphql/types.rb +1 -0
- data/lib/graphql/unauthorized_enum_value_error.rb +4 -1
- data/lib/graphql/unauthorized_error.rb +11 -4
- data/lib/graphql/unauthorized_field_error.rb +4 -1
- data/lib/graphql/unresolved_type_error.rb +16 -5
- data/lib/graphql/version.rb +2 -1
- data/lib/graphql.rb +37 -9
- data/readme.md +1 -1
- metadata +89 -5
- data/.yardopts +0 -5
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
2
3
|
|
|
3
4
|
module GraphQL
|
|
4
5
|
module Pagination
|
|
@@ -10,15 +11,33 @@ module GraphQL
|
|
|
10
11
|
#
|
|
11
12
|
# Unlike the previous connection implementation, these default to bidirectional pagination.
|
|
12
13
|
#
|
|
13
|
-
# Pagination arguments and context may be provided at initialization or assigned later (see
|
|
14
|
+
# Pagination arguments and context may be provided at initialization or assigned later (see [Schema::Field::ConnectionExtension](rdoc-ref:Schema::Field::ConnectionExtension)).
|
|
14
15
|
class Connection
|
|
15
16
|
class PaginationImplementationMissingError < GraphQL::Error
|
|
16
17
|
end
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
class << self
|
|
20
|
+
# Subclasses may override `cursor_for` to build their own cursors (for example, value-based cursors).
|
|
21
|
+
# In that case, position-based cursors from the parent class would be wrong, so `cursor_for_position`
|
|
22
|
+
# should call the overridden `cursor_for` instead.
|
|
23
|
+
#
|
|
24
|
+
# The result is cached on each class, since it's the same for every instance.
|
|
25
|
+
def custom_cursor_for?(default_owner) # :nodoc:
|
|
26
|
+
if !defined?(@custom_cursor_for)
|
|
27
|
+
@custom_cursor_for = instance_method(:cursor_for).owner != default_owner
|
|
28
|
+
end
|
|
29
|
+
@custom_cursor_for
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# **Returns**
|
|
34
|
+
#
|
|
35
|
+
# - `Object` — A list object, from the application. This is the unpaginated value passed into the connection.
|
|
19
36
|
attr_reader :items
|
|
20
37
|
|
|
21
|
-
#
|
|
38
|
+
# **Returns**
|
|
39
|
+
#
|
|
40
|
+
# - `GraphQL::Query::Context`
|
|
22
41
|
attr_reader :context
|
|
23
42
|
|
|
24
43
|
def context=(new_ctx)
|
|
@@ -29,13 +48,20 @@ module GraphQL
|
|
|
29
48
|
@context
|
|
30
49
|
end
|
|
31
50
|
|
|
32
|
-
#
|
|
51
|
+
# **Returns**
|
|
52
|
+
#
|
|
53
|
+
# - `Object` — the object this collection belongs to
|
|
33
54
|
attr_accessor :parent
|
|
34
55
|
|
|
35
56
|
# Raw access to client-provided values. (`max_page_size` not applied to first or last.)
|
|
36
57
|
attr_accessor :before_value, :after_value, :first_value, :last_value
|
|
37
58
|
|
|
38
|
-
#
|
|
59
|
+
# **Returns**
|
|
60
|
+
#
|
|
61
|
+
# - `String, nil` — the client-provided cursor. `""` is treated as `nil`.
|
|
62
|
+
#
|
|
63
|
+
# :call-seq:
|
|
64
|
+
# before() -> String | nil
|
|
39
65
|
def before
|
|
40
66
|
if defined?(@before)
|
|
41
67
|
@before
|
|
@@ -44,7 +70,12 @@ module GraphQL
|
|
|
44
70
|
end
|
|
45
71
|
end
|
|
46
72
|
|
|
47
|
-
#
|
|
73
|
+
# **Returns**
|
|
74
|
+
#
|
|
75
|
+
# - `String, nil` — the client-provided cursor. `""` is treated as `nil`.
|
|
76
|
+
#
|
|
77
|
+
# :call-seq:
|
|
78
|
+
# after() -> String | nil
|
|
48
79
|
def after
|
|
49
80
|
if defined?(@after)
|
|
50
81
|
@after
|
|
@@ -53,19 +84,26 @@ module GraphQL
|
|
|
53
84
|
end
|
|
54
85
|
end
|
|
55
86
|
|
|
56
|
-
#
|
|
87
|
+
# **Returns**
|
|
88
|
+
#
|
|
89
|
+
# - `Hash<Symbol => Object>` — The field arguments from the field that returned this connection
|
|
57
90
|
attr_accessor :arguments
|
|
58
91
|
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
92
|
+
# **Parameters**
|
|
93
|
+
#
|
|
94
|
+
# - `items` (`Object`) — some unpaginated collection item, like an `Array` or `ActiveRecord::Relation`
|
|
95
|
+
# - `context` (`Query::Context`)
|
|
96
|
+
# - `parent` (`Object`) — The object this collection belongs to
|
|
97
|
+
# - `first` (`Integer, nil`) — The limit parameter from the client, if it provided one
|
|
98
|
+
# - `after` (`String, nil`) — A cursor for pagination, if the client provided one
|
|
99
|
+
# - `last` (`Integer, nil`) — Limit parameter from the client, if provided
|
|
100
|
+
# - `before` (`String, nil`) — A cursor for pagination, if the client provided one.
|
|
101
|
+
# - `arguments` (`Hash`) — The arguments to the field that returned the collection wrapped by this connection
|
|
102
|
+
# - `max_page_size` (`Integer, nil`) — A configured value to cap the result size. Applied as `first` if neither first or last are given and no `default_page_size` is set.
|
|
103
|
+
# - `default_page_size` (`Integer, nil`) — A configured value to determine the result size when neither first or last are given.
|
|
104
|
+
#
|
|
105
|
+
# :call-seq:
|
|
106
|
+
# initialize(Object items, Object parent:, field:, Query::Context context:, Integer | nil first:, String | nil after:, Integer | nil max_page_size:, Integer | nil default_page_size:, Integer | nil last:, String | nil before:, edge_class:, Hash arguments:)
|
|
69
107
|
def initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, last: nil, before: nil, edge_class: nil, arguments: nil)
|
|
70
108
|
@items = items
|
|
71
109
|
@parent = parent
|
|
@@ -76,7 +114,7 @@ module GraphQL
|
|
|
76
114
|
@last_value = last
|
|
77
115
|
@before_value = before
|
|
78
116
|
@arguments = arguments
|
|
79
|
-
@edge_class = edge_class || self.class
|
|
117
|
+
@edge_class = edge_class || self.class.const_get(:Edge)
|
|
80
118
|
# This is only true if the object was _initialized_ with an override
|
|
81
119
|
# or if one is assigned later.
|
|
82
120
|
@has_max_page_size_override = max_page_size != NOT_CONFIGURED
|
|
@@ -135,13 +173,12 @@ module GraphQL
|
|
|
135
173
|
end
|
|
136
174
|
|
|
137
175
|
attr_writer :first
|
|
138
|
-
#
|
|
139
|
-
#
|
|
140
|
-
#
|
|
141
|
-
#
|
|
142
|
-
#
|
|
143
|
-
#
|
|
144
|
-
# `max_page_size`. If `default_page_size` is nil, use `max_page_size`.
|
|
176
|
+
# **Returns**
|
|
177
|
+
#
|
|
178
|
+
# - `Integer, nil` — A clamped `first` value. (The underlying instance variable doesn't have limits on it.) If neither `first` nor `last` is given, but `default_page_size` is present, default_page_size is used for first. If `default_page_size` is greater than `max_page_size``, it'll be clamped down to `max_page_size`. If `default_page_size` is nil, use `max_page_size`.
|
|
179
|
+
#
|
|
180
|
+
# :call-seq:
|
|
181
|
+
# first() -> Integer | nil
|
|
145
182
|
def first
|
|
146
183
|
@first ||= begin
|
|
147
184
|
capped = limit_pagination_argument(@first_value, max_page_size)
|
|
@@ -155,36 +192,72 @@ module GraphQL
|
|
|
155
192
|
# This is called by `Relay::RangeAdd` -- it can be overridden
|
|
156
193
|
# when `item` needs some modifications based on this connection's state.
|
|
157
194
|
#
|
|
158
|
-
#
|
|
159
|
-
#
|
|
195
|
+
# **Parameters**
|
|
196
|
+
#
|
|
197
|
+
# - `item` (`Object`) — An item newly added to `items`
|
|
198
|
+
#
|
|
199
|
+
# **Returns**
|
|
200
|
+
#
|
|
201
|
+
# - `Edge`
|
|
202
|
+
#
|
|
203
|
+
# :call-seq:
|
|
204
|
+
# range_add_edge(Object item) -> Edge
|
|
160
205
|
def range_add_edge(item)
|
|
161
206
|
edge_class.new(item, self)
|
|
162
207
|
end
|
|
163
208
|
|
|
164
209
|
attr_writer :last
|
|
165
|
-
#
|
|
210
|
+
# **Returns**
|
|
211
|
+
#
|
|
212
|
+
# - `Integer, nil` — A clamped `last` value. (The underlying instance variable doesn't have limits on it)
|
|
213
|
+
#
|
|
214
|
+
# :call-seq:
|
|
215
|
+
# last() -> Integer | nil
|
|
166
216
|
def last
|
|
167
217
|
@last ||= limit_pagination_argument(@last_value, max_page_size)
|
|
168
218
|
end
|
|
169
219
|
|
|
170
|
-
#
|
|
220
|
+
# **Returns**
|
|
221
|
+
#
|
|
222
|
+
# - `Array<Edge>` — [nodes](rdoc-ref:nodes), but wrapped with Edge instances
|
|
223
|
+
#
|
|
224
|
+
# :call-seq:
|
|
225
|
+
# edges() -> Array[Edge]
|
|
171
226
|
def edges
|
|
172
|
-
@edges ||= nodes.map
|
|
227
|
+
@edges ||= nodes.each_with_index.map do |n, index|
|
|
228
|
+
edge = @edge_class.new(n, self)
|
|
229
|
+
edge.graphql_connection_position = index
|
|
230
|
+
edge
|
|
231
|
+
end
|
|
173
232
|
end
|
|
174
233
|
|
|
175
|
-
#
|
|
234
|
+
# **Returns**
|
|
235
|
+
#
|
|
236
|
+
# - `Class` — A wrapper class for edges of this connection
|
|
176
237
|
attr_accessor :edge_class
|
|
177
238
|
|
|
178
|
-
#
|
|
239
|
+
# **Returns**
|
|
240
|
+
#
|
|
241
|
+
# - `GraphQL::Schema::Field` — The field this connection was returned by
|
|
179
242
|
attr_accessor :field
|
|
243
|
+
|
|
244
|
+
# **Returns**
|
|
245
|
+
#
|
|
246
|
+
# - `GraphQL::Execution::Lookahead` Selections on this connection, set by connection fields
|
|
247
|
+
attr_accessor :lookahead
|
|
180
248
|
|
|
181
|
-
#
|
|
249
|
+
# **Returns**
|
|
250
|
+
#
|
|
251
|
+
# - `Array<Object>` — A slice of [items](rdoc-ref:items), constrained by `@first_value`/`@after_value`/`@last_value`/`@before_value`
|
|
252
|
+
#
|
|
253
|
+
# :call-seq:
|
|
254
|
+
# nodes() -> Array[Object]
|
|
182
255
|
def nodes
|
|
183
256
|
raise PaginationImplementationMissingError, "Implement #{self.class}#nodes to paginate `@items`"
|
|
184
257
|
end
|
|
185
258
|
|
|
186
|
-
# A dynamic alias for compatibility with
|
|
187
|
-
#
|
|
259
|
+
# A dynamic alias for compatibility with [GraphQL::Types::Relay::BaseConnection](rdoc-ref:GraphQL::Types::Relay::BaseConnection).
|
|
260
|
+
# **Deprecated:** use [nodes](rdoc-ref:#nodes) instead
|
|
188
261
|
def edge_nodes
|
|
189
262
|
nodes
|
|
190
263
|
end
|
|
@@ -194,35 +267,77 @@ module GraphQL
|
|
|
194
267
|
self
|
|
195
268
|
end
|
|
196
269
|
|
|
197
|
-
#
|
|
270
|
+
# **Returns**
|
|
271
|
+
#
|
|
272
|
+
# - `Boolean` — True if there are more items after this page
|
|
273
|
+
#
|
|
274
|
+
# :call-seq:
|
|
275
|
+
# has_next_page() -> bool
|
|
198
276
|
def has_next_page
|
|
199
277
|
raise PaginationImplementationMissingError, "Implement #{self.class}#has_next_page to return the next-page check"
|
|
200
278
|
end
|
|
201
279
|
|
|
202
|
-
#
|
|
280
|
+
# **Returns**
|
|
281
|
+
#
|
|
282
|
+
# - `Boolean` — True if there were items before these items
|
|
283
|
+
#
|
|
284
|
+
# :call-seq:
|
|
285
|
+
# has_previous_page() -> bool
|
|
203
286
|
def has_previous_page
|
|
204
287
|
raise PaginationImplementationMissingError, "Implement #{self.class}#has_previous_page to return the previous-page check"
|
|
205
288
|
end
|
|
206
289
|
|
|
207
|
-
#
|
|
290
|
+
# **Returns**
|
|
291
|
+
#
|
|
292
|
+
# - `String` — The cursor of the first item in [nodes](rdoc-ref:nodes)
|
|
293
|
+
#
|
|
294
|
+
# :call-seq:
|
|
295
|
+
# start_cursor() -> String
|
|
208
296
|
def start_cursor
|
|
209
|
-
nodes.first &&
|
|
297
|
+
nodes.first && cursor_for_position(nodes.first, 0)
|
|
210
298
|
end
|
|
211
299
|
|
|
212
|
-
#
|
|
300
|
+
# **Returns**
|
|
301
|
+
#
|
|
302
|
+
# - `String` — The cursor of the last item in [nodes](rdoc-ref:nodes)
|
|
303
|
+
#
|
|
304
|
+
# :call-seq:
|
|
305
|
+
# end_cursor() -> String
|
|
213
306
|
def end_cursor
|
|
214
|
-
nodes.last &&
|
|
307
|
+
nodes.last && cursor_for_position(nodes.last, nodes.length - 1)
|
|
215
308
|
end
|
|
216
309
|
|
|
217
310
|
# Return a cursor for this item.
|
|
218
|
-
#
|
|
219
|
-
#
|
|
311
|
+
#
|
|
312
|
+
# **Parameters**
|
|
313
|
+
#
|
|
314
|
+
# - `item` (`Object`) — one of the passed in [items](rdoc-ref:items), taken from [nodes](rdoc-ref:nodes)
|
|
315
|
+
#
|
|
316
|
+
# **Returns**
|
|
317
|
+
#
|
|
318
|
+
# - `String`
|
|
319
|
+
#
|
|
320
|
+
# :call-seq:
|
|
321
|
+
# cursor_for(Object item) -> String
|
|
220
322
|
def cursor_for(item)
|
|
221
323
|
raise PaginationImplementationMissingError, "Implement #{self.class}#cursor_for(item) to return the cursor for #{item.inspect}"
|
|
222
324
|
end
|
|
223
325
|
|
|
326
|
+
def cursor_for_position(item, _position) # :nodoc:
|
|
327
|
+
cursor_for(item)
|
|
328
|
+
end
|
|
329
|
+
|
|
224
330
|
private
|
|
225
331
|
|
|
332
|
+
def cursor_index_for(item, collection)
|
|
333
|
+
@cursor_indexes ||= {}.compare_by_identity.tap do |indexes|
|
|
334
|
+
collection.each_with_index { |node, index| indexes[node] ||= index }
|
|
335
|
+
end
|
|
336
|
+
@cursor_indexes.fetch(item) do
|
|
337
|
+
raise GraphQL::ExecutionError, "Can't generate a cursor for an item outside this connection"
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
226
341
|
def detect_was_authorized_by_scope_items
|
|
227
342
|
if @context &&
|
|
228
343
|
(current_runtime_state = Fiber[:__graphql_runtime_info]) &&
|
|
@@ -233,9 +348,17 @@ module GraphQL
|
|
|
233
348
|
end
|
|
234
349
|
end
|
|
235
350
|
|
|
236
|
-
#
|
|
237
|
-
#
|
|
238
|
-
#
|
|
351
|
+
# **Parameters**
|
|
352
|
+
#
|
|
353
|
+
# - `argument` (`nil, Integer`) — `first` or `last`, as provided by the client
|
|
354
|
+
# - `max_page_size` (`nil, Integer`)
|
|
355
|
+
#
|
|
356
|
+
# **Returns**
|
|
357
|
+
#
|
|
358
|
+
# - `nil, Integer` — `nil` if the input was `nil`, otherwise a value between `0` and `max_page_size`
|
|
359
|
+
#
|
|
360
|
+
# :call-seq:
|
|
361
|
+
# limit_pagination_argument(nil | Integer argument, nil | Integer max_page_size) -> nil | Integer
|
|
239
362
|
def limit_pagination_argument(argument, max_page_size)
|
|
240
363
|
if argument
|
|
241
364
|
if argument < 0
|
|
@@ -255,11 +378,14 @@ module GraphQL
|
|
|
255
378
|
context.schema.cursor_encoder.encode(cursor, nonce: true)
|
|
256
379
|
end
|
|
257
380
|
|
|
258
|
-
# A wrapper around paginated items. It includes a
|
|
381
|
+
# A wrapper around paginated items. It includes a [cursor](rdoc-ref:#cursor) for pagination
|
|
259
382
|
# and could be extended with custom relationship-level data.
|
|
260
383
|
class Edge
|
|
261
384
|
attr_reader :node
|
|
262
385
|
|
|
386
|
+
# The zero-based position of this edge in the page
|
|
387
|
+
attr_accessor :graphql_connection_position # :nodoc:
|
|
388
|
+
|
|
263
389
|
def initialize(node, connection)
|
|
264
390
|
@connection = connection
|
|
265
391
|
@node = node
|
|
@@ -270,7 +396,11 @@ module GraphQL
|
|
|
270
396
|
end
|
|
271
397
|
|
|
272
398
|
def cursor
|
|
273
|
-
@cursor ||= @
|
|
399
|
+
@cursor ||= if @graphql_connection_position
|
|
400
|
+
@connection.cursor_for_position(@node, @graphql_connection_position)
|
|
401
|
+
else
|
|
402
|
+
@connection.cursor_for(@node)
|
|
403
|
+
end
|
|
274
404
|
end
|
|
275
405
|
|
|
276
406
|
def was_authorized_by_scope_items?
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
2
3
|
|
|
3
4
|
module GraphQL
|
|
4
5
|
module Pagination
|
|
@@ -6,17 +7,25 @@ module GraphQL
|
|
|
6
7
|
#
|
|
7
8
|
# Attach as a plugin.
|
|
8
9
|
#
|
|
9
|
-
#
|
|
10
|
-
# class MySchema < GraphQL::Schema
|
|
11
|
-
# connections.add(MyApp::SearchResults, MyApp::SearchResultsConnection)
|
|
12
|
-
# end
|
|
10
|
+
# See [Schema.connections](rdoc-ref:Schema.connections)
|
|
13
11
|
#
|
|
14
|
-
#
|
|
15
|
-
# class MySchema < GraphQL::Schema
|
|
16
|
-
# connections.delete(Array)
|
|
17
|
-
# end
|
|
12
|
+
# **Examples**
|
|
18
13
|
#
|
|
19
|
-
#
|
|
14
|
+
# **Example: Adding a custom wrapper**
|
|
15
|
+
#
|
|
16
|
+
# ```ruby
|
|
17
|
+
# class MySchema < GraphQL::Schema
|
|
18
|
+
# connections.add(MyApp::SearchResults, MyApp::SearchResultsConnection)
|
|
19
|
+
# end
|
|
20
|
+
# ```
|
|
21
|
+
#
|
|
22
|
+
# **Example: Removing default connection support for arrays (they can still be manually wrapped)**
|
|
23
|
+
#
|
|
24
|
+
# ```ruby
|
|
25
|
+
# class MySchema < GraphQL::Schema
|
|
26
|
+
# connections.delete(Array)
|
|
27
|
+
# end
|
|
28
|
+
# ```
|
|
20
29
|
class Connections
|
|
21
30
|
class ImplementationMissingError < GraphQL::Error
|
|
22
31
|
end
|
|
@@ -46,7 +55,7 @@ module GraphQL
|
|
|
46
55
|
end
|
|
47
56
|
|
|
48
57
|
def wrapper_for(items, wrappers: all_wrappers)
|
|
49
|
-
impl = nil
|
|
58
|
+
impl = nil #: untyped
|
|
50
59
|
|
|
51
60
|
items.class.ancestors.each { |cls|
|
|
52
61
|
impl = wrappers[cls]
|
|
@@ -57,8 +66,7 @@ module GraphQL
|
|
|
57
66
|
end
|
|
58
67
|
|
|
59
68
|
# Used by the runtime to wrap values in connection wrappers.
|
|
60
|
-
#
|
|
61
|
-
def wrap(field, parent, items, arguments, context)
|
|
69
|
+
def wrap(field, parent, items, arguments, context) # :nodoc:
|
|
62
70
|
return items if GraphQL::Execution::Interpreter::RawValue === items
|
|
63
71
|
wrappers = context ? context.namespace(:connections)[:all_wrappers] : all_wrappers
|
|
64
72
|
impl = wrapper_for(items, wrappers: wrappers)
|
|
@@ -114,8 +122,7 @@ module GraphQL
|
|
|
114
122
|
end
|
|
115
123
|
end
|
|
116
124
|
# use an override if there is one
|
|
117
|
-
#
|
|
118
|
-
def edge_class_for_field(field)
|
|
125
|
+
def edge_class_for_field(field) # :nodoc:
|
|
119
126
|
conn_type = field.type.unwrap
|
|
120
127
|
conn_type_edge_type = conn_type.respond_to?(:edge_class) && conn_type.edge_class
|
|
121
128
|
if conn_type_edge_type && conn_type_edge_type != Pagination::Connection::Edge
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
2
3
|
require "graphql/pagination/connection"
|
|
3
4
|
require "monitor"
|
|
4
5
|
|
|
@@ -29,6 +30,12 @@ module GraphQL
|
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
def has_next_page
|
|
33
|
+
# If the query loads the page anyway, load it now so its extra row answers this
|
|
34
|
+
if @has_next_page.nil? && peek_next_page? &&
|
|
35
|
+
(lookahead.selects?(:nodes) || lookahead.selects?(:edges) ||
|
|
36
|
+
page_info_selection.selects?(:start_cursor) || page_info_selection.selects?(:end_cursor))
|
|
37
|
+
load_nodes
|
|
38
|
+
end
|
|
32
39
|
if @has_next_page.nil?
|
|
33
40
|
@has_next_page = if before_offset && before_offset > 0
|
|
34
41
|
true
|
|
@@ -47,48 +54,106 @@ module GraphQL
|
|
|
47
54
|
|
|
48
55
|
def cursor_for(item)
|
|
49
56
|
load_nodes
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
position = cursor_index_for(item, nodes)
|
|
58
|
+
offset_cursor_for_position(position)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def cursor_for_position(item, position) # :nodoc:
|
|
62
|
+
if self.class.custom_cursor_for?(RelationConnection)
|
|
63
|
+
super
|
|
64
|
+
else
|
|
65
|
+
offset_cursor_for_position(position)
|
|
66
|
+
end
|
|
53
67
|
end
|
|
54
68
|
|
|
55
69
|
private
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
def offset_cursor_for_position(position)
|
|
72
|
+
# position in nodes + existing offset + 1 (because it's offset, not index)
|
|
73
|
+
offset = position + 1 + (@paged_nodes_offset || 0) - (relation_offset(items) || 0)
|
|
74
|
+
encode(offset.to_s)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# **Parameters**
|
|
78
|
+
#
|
|
79
|
+
# - `relation` (`Object`) — A database query object
|
|
80
|
+
# - `_initial_offset` (`Integer`) — The number of items already excluded from the relation
|
|
81
|
+
# - `size` (`Integer`) — The value against which we check the relation size
|
|
82
|
+
#
|
|
83
|
+
# **Returns**
|
|
84
|
+
#
|
|
85
|
+
# - `Boolean` — True if the number of items in this relation is larger than `size`
|
|
86
|
+
#
|
|
87
|
+
# :call-seq:
|
|
88
|
+
# relation_larger_than(Object relation, Integer _initial_offset, Integer size) -> bool
|
|
61
89
|
def relation_larger_than(relation, _initial_offset, size)
|
|
62
90
|
relation_count(set_limit(relation, size + 1)) == size + 1
|
|
63
91
|
end
|
|
64
92
|
|
|
65
|
-
#
|
|
66
|
-
#
|
|
93
|
+
# **Parameters**
|
|
94
|
+
#
|
|
95
|
+
# - `relation` (`Object`) — A database query object
|
|
96
|
+
#
|
|
97
|
+
# **Returns**
|
|
98
|
+
#
|
|
99
|
+
# - `Integer, nil` — The offset value, or nil if there isn't one
|
|
100
|
+
#
|
|
101
|
+
# :call-seq:
|
|
102
|
+
# relation_offset(Object relation) -> Integer | nil
|
|
67
103
|
def relation_offset(relation)
|
|
68
104
|
raise "#{self.class}#relation_offset(relation) must return the offset value for a #{relation.class} (#{relation.inspect})"
|
|
69
105
|
end
|
|
70
106
|
|
|
71
|
-
#
|
|
72
|
-
#
|
|
107
|
+
# **Parameters**
|
|
108
|
+
#
|
|
109
|
+
# - `relation` (`Object`) — A database query object
|
|
110
|
+
#
|
|
111
|
+
# **Returns**
|
|
112
|
+
#
|
|
113
|
+
# - `Integer, nil` — The limit value, or nil if there isn't one
|
|
114
|
+
#
|
|
115
|
+
# :call-seq:
|
|
116
|
+
# relation_limit(Object relation) -> Integer | nil
|
|
73
117
|
def relation_limit(relation)
|
|
74
118
|
raise "#{self.class}#relation_limit(relation) must return the limit value for a #{relation.class} (#{relation.inspect})"
|
|
75
119
|
end
|
|
76
120
|
|
|
77
|
-
#
|
|
78
|
-
#
|
|
121
|
+
# **Parameters**
|
|
122
|
+
#
|
|
123
|
+
# - `relation` (`Object`) — A database query object
|
|
124
|
+
#
|
|
125
|
+
# **Returns**
|
|
126
|
+
#
|
|
127
|
+
# - `Integer, nil` — The number of items in this relation (hopefully determined without loading all records into memory!)
|
|
128
|
+
#
|
|
129
|
+
# :call-seq:
|
|
130
|
+
# relation_count(Object relation) -> Integer | nil
|
|
79
131
|
def relation_count(relation)
|
|
80
132
|
raise "#{self.class}#relation_count(relation) must return the count of records for a #{relation.class} (#{relation.inspect})"
|
|
81
133
|
end
|
|
82
134
|
|
|
83
|
-
#
|
|
84
|
-
#
|
|
135
|
+
# **Parameters**
|
|
136
|
+
#
|
|
137
|
+
# - `relation` (`Object`) — A database query object
|
|
138
|
+
#
|
|
139
|
+
# **Returns**
|
|
140
|
+
#
|
|
141
|
+
# - `Object` — A modified query object which will return no records
|
|
142
|
+
#
|
|
143
|
+
# :call-seq:
|
|
144
|
+
# null_relation(Object relation) -> Object
|
|
85
145
|
def null_relation(relation)
|
|
86
146
|
raise "#{self.class}#null_relation(relation) must return an empty relation for a #{relation.class} (#{relation.inspect})"
|
|
87
147
|
end
|
|
88
148
|
|
|
89
|
-
#
|
|
149
|
+
# **Returns**
|
|
150
|
+
#
|
|
151
|
+
# - `Integer`
|
|
152
|
+
#
|
|
153
|
+
# :call-seq:
|
|
154
|
+
# offset_from_cursor(cursor) -> Integer
|
|
90
155
|
def offset_from_cursor(cursor)
|
|
91
|
-
offset = Integer(decode(cursor), 10, exception: false)
|
|
156
|
+
offset = Integer(decode(cursor), 10, exception: false) #: Integer?
|
|
92
157
|
if offset.nil? || offset <= 0
|
|
93
158
|
raise GraphQL::ExecutionError, "Invalid cursor: #{cursor.inspect}"
|
|
94
159
|
end
|
|
@@ -170,12 +235,22 @@ module GraphQL
|
|
|
170
235
|
end
|
|
171
236
|
end
|
|
172
237
|
|
|
173
|
-
#
|
|
238
|
+
# **Returns**
|
|
239
|
+
#
|
|
240
|
+
# - `Integer, nil`
|
|
241
|
+
#
|
|
242
|
+
# :call-seq:
|
|
243
|
+
# before_offset() -> Integer | nil
|
|
174
244
|
def before_offset
|
|
175
245
|
@before_offset ||= before && offset_from_cursor(before)
|
|
176
246
|
end
|
|
177
247
|
|
|
178
|
-
#
|
|
248
|
+
# **Returns**
|
|
249
|
+
#
|
|
250
|
+
# - `Integer, nil`
|
|
251
|
+
#
|
|
252
|
+
# :call-seq:
|
|
253
|
+
# after_offset() -> Integer | nil
|
|
179
254
|
def after_offset
|
|
180
255
|
@after_offset ||= after && offset_from_cursor(after)
|
|
181
256
|
end
|
|
@@ -246,12 +321,34 @@ module GraphQL
|
|
|
246
321
|
# `AsyncDataloader` may resolve sibling fields (eg, `edges` and `pageInfo`)
|
|
247
322
|
# in separate Fibers, so several callers can get here before `@nodes` is set.
|
|
248
323
|
(@load_monitor ||= Monitor.new).synchronize do
|
|
249
|
-
|
|
324
|
+
# Not `||=`: Sorbet assumes `@nodes` is still falsy in this block
|
|
325
|
+
@nodes = load_page unless @nodes
|
|
250
326
|
end
|
|
251
327
|
else
|
|
252
|
-
@nodes =
|
|
328
|
+
@nodes = load_page
|
|
253
329
|
end
|
|
254
330
|
end
|
|
331
|
+
|
|
332
|
+
# Fetch one row past `first` so `has_next_page` needs no extra query.
|
|
333
|
+
# Skips arrays (no query to save) and relations limited below `first` (no next page).
|
|
334
|
+
def load_page
|
|
335
|
+
page = limited_nodes
|
|
336
|
+
return page.to_a if page.is_a?(Array) || !peek_next_page? || relation_limit(page) != first
|
|
337
|
+
|
|
338
|
+
rows = set_limit(page, first + 1).to_a
|
|
339
|
+
@has_next_page = rows.size > first
|
|
340
|
+
rows.first(first)
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
# Peek on forward pages that select `hasNextPage`; `last` and `before` keep the separate check
|
|
344
|
+
def peek_next_page?
|
|
345
|
+
return @peek_next_page if defined?(@peek_next_page)
|
|
346
|
+
@peek_next_page = first&.positive? && last.nil? && before.nil? && page_info_selection.selects?(:has_next_page)
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def page_info_selection
|
|
350
|
+
@page_info_selection ||= (lookahead || GraphQL::Execution::Lookahead::NULL_LOOKAHEAD).selection(:page_info)
|
|
351
|
+
end
|
|
255
352
|
end
|
|
256
353
|
end
|
|
257
354
|
end
|
data/lib/graphql/pagination.rb
CHANGED
data/lib/graphql/parse_error.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
2
3
|
module GraphQL
|
|
3
4
|
class Query
|
|
4
5
|
class Context
|
|
@@ -13,7 +14,7 @@ module GraphQL
|
|
|
13
14
|
if @scoped_contexts.nil?
|
|
14
15
|
GraphQL::EmptyObjects::EMPTY_HASH
|
|
15
16
|
else
|
|
16
|
-
merged_ctx = {}
|
|
17
|
+
merged_ctx = {} #: untyped
|
|
17
18
|
each_present_path_ctx do |path_ctx|
|
|
18
19
|
merged_ctx = path_ctx.merge(merged_ctx)
|
|
19
20
|
end
|