graphql 0.16.0 → 2.0.15
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 +5 -5
- data/.yardopts +5 -0
- data/lib/generators/graphql/core.rb +69 -0
- data/lib/generators/graphql/enum_generator.rb +27 -0
- 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/install/templates/base_mutation.erb +10 -0
- data/lib/generators/graphql/install/templates/mutation_type.erb +12 -0
- data/lib/generators/graphql/install_generator.rb +197 -0
- data/lib/generators/graphql/interface_generator.rb +27 -0
- data/lib/generators/graphql/loader_generator.rb +21 -0
- data/lib/generators/graphql/mutation_create_generator.rb +22 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
- data/lib/generators/graphql/mutation_generator.rb +30 -0
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +50 -0
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +49 -0
- data/lib/generators/graphql/relay_generator.rb +21 -0
- data/lib/generators/graphql/scalar_generator.rb +22 -0
- data/lib/generators/graphql/templates/base_argument.erb +6 -0
- data/lib/generators/graphql/templates/base_connection.erb +8 -0
- data/lib/generators/graphql/templates/base_edge.erb +8 -0
- data/lib/generators/graphql/templates/base_enum.erb +6 -0
- data/lib/generators/graphql/templates/base_field.erb +7 -0
- data/lib/generators/graphql/templates/base_input_object.erb +7 -0
- data/lib/generators/graphql/templates/base_interface.erb +9 -0
- data/lib/generators/graphql/templates/base_object.erb +7 -0
- data/lib/generators/graphql/templates/base_scalar.erb +6 -0
- data/lib/generators/graphql/templates/base_union.erb +6 -0
- data/lib/generators/graphql/templates/enum.erb +11 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +52 -0
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +10 -0
- data/lib/generators/graphql/templates/loader.erb +19 -0
- data/lib/generators/graphql/templates/mutation.erb +16 -0
- data/lib/generators/graphql/templates/mutation_create.erb +20 -0
- data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
- data/lib/generators/graphql/templates/mutation_update.erb +21 -0
- data/lib/generators/graphql/templates/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +10 -0
- data/lib/generators/graphql/templates/query_type.erb +15 -0
- data/lib/generators/graphql/templates/scalar.erb +17 -0
- data/lib/generators/graphql/templates/schema.erb +30 -0
- data/lib/generators/graphql/templates/union.erb +9 -0
- data/lib/generators/graphql/type_generator.rb +135 -0
- data/lib/generators/graphql/union_generator.rb +33 -0
- data/lib/graphql/analysis/ast/analyzer.rb +84 -0
- data/lib/graphql/analysis/ast/field_usage.rb +57 -0
- data/lib/graphql/analysis/ast/max_query_complexity.rb +22 -0
- data/lib/graphql/analysis/ast/max_query_depth.rb +22 -0
- data/lib/graphql/analysis/ast/query_complexity.rb +230 -0
- data/lib/graphql/analysis/ast/query_depth.rb +55 -0
- data/lib/graphql/analysis/ast/visitor.rb +269 -0
- data/lib/graphql/analysis/ast.rb +81 -0
- data/lib/graphql/analysis.rb +2 -5
- data/lib/graphql/analysis_error.rb +1 -0
- data/lib/graphql/backtrace/inspect_result.rb +50 -0
- data/lib/graphql/backtrace/table.rb +141 -0
- data/lib/graphql/backtrace/traced_error.rb +54 -0
- data/lib/graphql/backtrace/tracer.rb +80 -0
- data/lib/graphql/backtrace.rb +58 -0
- data/lib/graphql/coercion_error.rb +13 -0
- data/lib/graphql/dataloader/null_dataloader.rb +24 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +164 -0
- data/lib/graphql/dataloader.rb +311 -0
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/dig.rb +19 -0
- data/lib/graphql/execution/directive_checks.rb +37 -0
- data/lib/graphql/execution/errors.rb +93 -0
- data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
- data/lib/graphql/execution/interpreter/arguments.rb +88 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
- data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
- data/lib/graphql/execution/interpreter/resolve.rb +77 -0
- data/lib/graphql/execution/interpreter/runtime.rb +994 -0
- data/lib/graphql/execution/interpreter.rb +226 -0
- data/lib/graphql/execution/lazy/lazy_method_map.rb +98 -0
- data/lib/graphql/execution/lazy.rb +75 -0
- data/lib/graphql/execution/lookahead.rb +311 -0
- data/lib/graphql/execution/multiplex.rb +45 -0
- data/lib/graphql/execution.rb +18 -0
- data/lib/graphql/execution_error.rb +34 -1
- data/lib/graphql/filter.rb +53 -0
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +36 -0
- data/lib/graphql/introspection/base_object.rb +13 -0
- data/lib/graphql/introspection/directive_location_enum.rb +12 -5
- data/lib/graphql/introspection/directive_type.rb +30 -10
- data/lib/graphql/introspection/dynamic_fields.rb +12 -0
- data/lib/graphql/introspection/entry_points.rb +22 -0
- data/lib/graphql/introspection/enum_value_type.rb +21 -8
- data/lib/graphql/introspection/field_type.rb +26 -10
- data/lib/graphql/introspection/input_value_type.rb +64 -14
- data/lib/graphql/introspection/introspection_query.rb +7 -76
- data/lib/graphql/introspection/schema_type.rb +42 -17
- data/lib/graphql/introspection/type_kind_enum.rb +11 -5
- data/lib/graphql/introspection/type_type.rb +104 -16
- data/lib/graphql/introspection.rb +104 -13
- data/lib/graphql/invalid_name_error.rb +11 -0
- data/lib/graphql/invalid_null_error.rb +36 -8
- data/lib/graphql/language/block_string.rb +99 -0
- data/lib/graphql/language/cache.rb +37 -0
- data/lib/graphql/language/definition_slice.rb +41 -0
- data/lib/graphql/language/document_from_schema_definition.rb +335 -0
- data/lib/graphql/language/generation.rb +16 -86
- data/lib/graphql/language/lexer.rb +1436 -705
- data/lib/graphql/language/lexer.rl +172 -64
- data/lib/graphql/language/nodes.rb +617 -105
- data/lib/graphql/language/parser.rb +1524 -430
- data/lib/graphql/language/parser.y +348 -73
- data/lib/graphql/language/printer.rb +386 -0
- data/lib/graphql/language/sanitized_printer.rb +222 -0
- data/lib/graphql/language/token.rb +16 -3
- data/lib/graphql/language/visitor.rb +169 -25
- data/lib/graphql/language.rb +30 -0
- data/lib/graphql/load_application_object_failed_error.rb +22 -0
- data/lib/graphql/name_validator.rb +11 -0
- data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
- data/lib/graphql/pagination/array_connection.rb +79 -0
- data/lib/graphql/pagination/connection.rb +253 -0
- data/lib/graphql/pagination/connections.rb +135 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +228 -0
- data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
- data/lib/graphql/pagination.rb +6 -0
- data/lib/graphql/parse_error.rb +24 -0
- data/lib/graphql/query/context.rb +266 -12
- data/lib/graphql/query/fingerprint.rb +26 -0
- data/lib/graphql/query/input_validation_result.rb +34 -7
- data/lib/graphql/query/null_context.rb +52 -0
- data/lib/graphql/query/result.rb +63 -0
- data/lib/graphql/query/validation_pipeline.rb +114 -0
- data/lib/graphql/query/variable_validation_error.rb +27 -3
- data/lib/graphql/query/variables.rb +75 -24
- data/lib/graphql/query.rb +359 -92
- data/lib/graphql/railtie.rb +13 -0
- data/lib/graphql/rake_task/validate.rb +63 -0
- data/lib/graphql/rake_task.rb +146 -0
- data/lib/graphql/relay/range_add.rb +52 -0
- data/lib/graphql/relay.rb +3 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/runtime_type_error.rb +5 -0
- data/lib/graphql/schema/addition.rb +245 -0
- data/lib/graphql/schema/argument.rb +395 -0
- data/lib/graphql/schema/base_64_bp.rb +26 -0
- data/lib/graphql/schema/base_64_encoder.rb +21 -0
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +47 -0
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +78 -0
- data/lib/graphql/schema/build_from_definition.rb +492 -0
- data/lib/graphql/schema/built_in_types.rb +12 -0
- data/lib/graphql/schema/directive/deprecated.rb +18 -0
- data/lib/graphql/schema/directive/feature.rb +66 -0
- data/lib/graphql/schema/directive/flagged.rb +57 -0
- data/lib/graphql/schema/directive/include.rb +25 -0
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/skip.rb +25 -0
- data/lib/graphql/schema/directive/transform.rb +60 -0
- data/lib/graphql/schema/directive.rb +212 -0
- data/lib/graphql/schema/enum.rb +176 -0
- data/lib/graphql/schema/enum_value.rb +77 -0
- data/lib/graphql/schema/field/connection_extension.rb +80 -0
- data/lib/graphql/schema/field/scope_extension.rb +22 -0
- data/lib/graphql/schema/field.rb +862 -0
- data/lib/graphql/schema/field_extension.rb +156 -0
- data/lib/graphql/schema/find_inherited_value.rb +36 -0
- data/lib/graphql/schema/finder.rb +155 -0
- data/lib/graphql/schema/input_object.rb +258 -0
- data/lib/graphql/schema/interface.rb +113 -0
- data/lib/graphql/schema/introspection_system.rb +164 -0
- data/lib/graphql/schema/invalid_type_error.rb +1 -0
- data/lib/graphql/schema/late_bound_type.rb +37 -0
- data/lib/graphql/schema/list.rb +86 -0
- data/lib/graphql/schema/loader.rb +228 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +124 -0
- data/lib/graphql/schema/member/build_type.rb +178 -0
- data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
- data/lib/graphql/schema/member/has_arguments.rb +376 -0
- data/lib/graphql/schema/member/has_ast_node.rb +20 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
- data/lib/graphql/schema/member/has_directives.rb +113 -0
- data/lib/graphql/schema/member/has_fields.rb +163 -0
- data/lib/graphql/schema/member/has_interfaces.rb +88 -0
- data/lib/graphql/schema/member/has_path.rb +25 -0
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
- data/lib/graphql/schema/member/has_validators.rb +31 -0
- data/lib/graphql/schema/member/relay_shortcuts.rb +73 -0
- data/lib/graphql/schema/member/scoped.rb +21 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +38 -0
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/member.rb +39 -0
- data/lib/graphql/schema/mutation.rb +85 -0
- data/lib/graphql/schema/non_null.rb +67 -0
- data/lib/graphql/schema/null_mask.rb +11 -0
- data/lib/graphql/schema/object.rb +117 -0
- data/lib/graphql/schema/printer.rb +72 -128
- data/lib/graphql/schema/relay_classic_mutation.rb +179 -0
- data/lib/graphql/schema/resolver/has_payload_type.rb +106 -0
- data/lib/graphql/schema/resolver.rb +402 -0
- data/lib/graphql/schema/scalar.rb +68 -0
- data/lib/graphql/schema/subscription.rb +148 -0
- data/lib/graphql/schema/timeout.rb +123 -0
- data/lib/graphql/schema/type_expression.rb +29 -5
- data/lib/graphql/schema/type_membership.rb +51 -0
- data/lib/graphql/schema/union.rb +81 -0
- data/lib/graphql/schema/unique_within_type.rb +34 -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 +33 -0
- data/lib/graphql/schema/validator/format_validator.rb +48 -0
- data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
- data/lib/graphql/schema/validator/length_validator.rb +59 -0
- data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
- data/lib/graphql/schema/validator/required_validator.rb +82 -0
- data/lib/graphql/schema/validator.rb +171 -0
- data/lib/graphql/schema/warden.rb +413 -0
- data/lib/graphql/schema/wrapper.rb +24 -0
- data/lib/graphql/schema.rb +1179 -104
- data/lib/graphql/static_validation/all_rules.rb +14 -0
- data/lib/graphql/static_validation/base_visitor.rb +200 -0
- data/lib/graphql/static_validation/definition_dependencies.rb +198 -0
- data/lib/graphql/static_validation/error.rb +46 -0
- data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
- data/lib/graphql/static_validation/literal_validator.rb +113 -22
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +59 -11
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +48 -0
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +31 -0
- data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +62 -8
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +37 -0
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +20 -13
- data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +32 -26
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +21 -23
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +55 -18
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +390 -70
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +53 -0
- data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +54 -37
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +26 -16
- data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +13 -19
- data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +16 -0
- data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +25 -20
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +22 -33
- data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +41 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
- data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +36 -0
- data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -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 +22 -21
- data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +59 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +56 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +36 -18
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +24 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +103 -39
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +22 -14
- data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +92 -70
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
- data/lib/graphql/static_validation/type_stack.rb +85 -24
- data/lib/graphql/static_validation/validation_context.rb +25 -46
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +46 -15
- data/lib/graphql/static_validation.rb +6 -3
- data/lib/graphql/string_encoding_error.rb +20 -0
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +247 -0
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
- data/lib/graphql/subscriptions/event.rb +144 -0
- data/lib/graphql/subscriptions/instrumentation.rb +28 -0
- data/lib/graphql/subscriptions/serialize.rb +158 -0
- data/lib/graphql/subscriptions.rb +306 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +21 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +51 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +100 -0
- data/lib/graphql/tracing/instrumentation_tracing.rb +83 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +51 -0
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_tracing.rb +122 -0
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +32 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +67 -0
- data/lib/graphql/tracing/scout_tracing.rb +54 -0
- data/lib/graphql/tracing/statsd_tracing.rb +42 -0
- data/lib/graphql/tracing.rb +94 -0
- data/lib/graphql/type_kinds.rb +50 -22
- data/lib/graphql/types/big_int.rb +23 -0
- data/lib/graphql/types/boolean.rb +18 -0
- data/lib/graphql/types/float.rb +19 -0
- data/lib/graphql/types/id.rb +24 -0
- data/lib/graphql/types/int.rb +36 -0
- data/lib/graphql/types/iso_8601_date.rb +45 -0
- data/lib/graphql/types/iso_8601_date_time.rb +76 -0
- data/lib/graphql/types/json.rb +25 -0
- data/lib/graphql/types/relay/base_connection.rb +49 -0
- data/lib/graphql/types/relay/base_edge.rb +29 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +154 -0
- data/lib/graphql/types/relay/default_relay.rb +21 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
- data/lib/graphql/types/relay/has_node_field.rb +41 -0
- data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
- data/lib/graphql/types/relay/node.rb +15 -0
- data/lib/graphql/types/relay/node_behaviors.rb +19 -0
- data/lib/graphql/types/relay/page_info.rb +11 -0
- data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
- data/lib/graphql/types/relay.rb +39 -0
- data/lib/graphql/types/string.rb +29 -0
- data/lib/graphql/types.rb +11 -0
- data/lib/graphql/unauthorized_error.rb +29 -0
- data/lib/graphql/unauthorized_field_error.rb +23 -0
- data/lib/graphql/unresolved_type_error.rb +35 -0
- data/lib/graphql/version.rb +2 -1
- data/lib/graphql.rb +86 -41
- data/readme.md +15 -101
- metadata +394 -279
- data/lib/graphql/analysis/analyze_query.rb +0 -73
- data/lib/graphql/analysis/max_query_complexity.rb +0 -25
- data/lib/graphql/analysis/max_query_depth.rb +0 -25
- data/lib/graphql/analysis/query_complexity.rb +0 -122
- data/lib/graphql/analysis/query_depth.rb +0 -54
- data/lib/graphql/argument.rb +0 -25
- data/lib/graphql/base_type.rb +0 -115
- data/lib/graphql/boolean_type.rb +0 -9
- data/lib/graphql/define/assign_argument.rb +0 -20
- data/lib/graphql/define/assign_enum_value.rb +0 -16
- data/lib/graphql/define/assign_object_field.rb +0 -21
- data/lib/graphql/define/assignment_dictionary.rb +0 -26
- data/lib/graphql/define/defined_object_proxy.rb +0 -32
- data/lib/graphql/define/instance_definable.rb +0 -79
- data/lib/graphql/define/non_null_with_bang.rb +0 -15
- data/lib/graphql/define/type_definer.rb +0 -30
- data/lib/graphql/define.rb +0 -8
- data/lib/graphql/directive/include_directive.rb +0 -10
- data/lib/graphql/directive/skip_directive.rb +0 -11
- data/lib/graphql/directive.rb +0 -49
- data/lib/graphql/enum_type.rb +0 -95
- data/lib/graphql/field.rb +0 -131
- data/lib/graphql/float_type.rb +0 -5
- data/lib/graphql/id_type.rb +0 -12
- data/lib/graphql/input_object_type.rb +0 -71
- data/lib/graphql/int_type.rb +0 -5
- data/lib/graphql/interface_type.rb +0 -38
- data/lib/graphql/internal_representation/node.rb +0 -81
- data/lib/graphql/internal_representation/rewrite.rb +0 -177
- data/lib/graphql/internal_representation.rb +0 -2
- data/lib/graphql/introspection/arguments_field.rb +0 -5
- data/lib/graphql/introspection/enum_values_field.rb +0 -13
- data/lib/graphql/introspection/fields_field.rb +0 -13
- data/lib/graphql/introspection/input_fields_field.rb +0 -12
- data/lib/graphql/introspection/interfaces_field.rb +0 -5
- data/lib/graphql/introspection/of_type_field.rb +0 -6
- data/lib/graphql/introspection/possible_types_field.rb +0 -11
- data/lib/graphql/introspection/schema_field.rb +0 -15
- data/lib/graphql/introspection/type_by_name_field.rb +0 -16
- data/lib/graphql/introspection/typename_field.rb +0 -15
- data/lib/graphql/list_type.rb +0 -46
- data/lib/graphql/non_null_type.rb +0 -43
- data/lib/graphql/object_type.rb +0 -93
- data/lib/graphql/query/arguments.rb +0 -76
- data/lib/graphql/query/directive_resolution.rb +0 -16
- data/lib/graphql/query/executor.rb +0 -45
- data/lib/graphql/query/literal_input.rb +0 -90
- data/lib/graphql/query/serial_execution/execution_context.rb +0 -31
- data/lib/graphql/query/serial_execution/field_resolution.rb +0 -82
- data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -27
- data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -42
- data/lib/graphql/query/serial_execution/value_resolution.rb +0 -107
- data/lib/graphql/query/serial_execution.rb +0 -41
- data/lib/graphql/query/type_resolver.rb +0 -25
- data/lib/graphql/scalar_type.rb +0 -53
- data/lib/graphql/schema/catchall_middleware.rb +0 -34
- data/lib/graphql/schema/middleware_chain.rb +0 -28
- data/lib/graphql/schema/possible_types.rb +0 -34
- data/lib/graphql/schema/reduce_types.rb +0 -68
- data/lib/graphql/schema/rescue_middleware.rb +0 -53
- data/lib/graphql/schema/timeout_middleware.rb +0 -67
- data/lib/graphql/schema/type_map.rb +0 -30
- data/lib/graphql/schema/validation.rb +0 -164
- data/lib/graphql/static_validation/arguments_validator.rb +0 -48
- data/lib/graphql/static_validation/message.rb +0 -36
- data/lib/graphql/string_type.rb +0 -5
- data/lib/graphql/union_type.rb +0 -38
- data/spec/graphql/analysis/analyze_query_spec.rb +0 -50
- data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -62
- data/spec/graphql/analysis/max_query_depth_spec.rb +0 -100
- data/spec/graphql/analysis/query_complexity_spec.rb +0 -235
- data/spec/graphql/analysis/query_depth_spec.rb +0 -80
- data/spec/graphql/argument_spec.rb +0 -20
- data/spec/graphql/base_type_spec.rb +0 -24
- data/spec/graphql/boolean_type_spec.rb +0 -20
- data/spec/graphql/define/instance_definable_spec.rb +0 -55
- data/spec/graphql/directive_spec.rb +0 -77
- data/spec/graphql/enum_type_spec.rb +0 -31
- data/spec/graphql/execution_error_spec.rb +0 -61
- data/spec/graphql/field_spec.rb +0 -92
- data/spec/graphql/float_type_spec.rb +0 -15
- data/spec/graphql/id_type_spec.rb +0 -32
- data/spec/graphql/input_object_type_spec.rb +0 -162
- data/spec/graphql/int_type_spec.rb +0 -15
- data/spec/graphql/interface_type_spec.rb +0 -56
- data/spec/graphql/internal_representation/rewrite_spec.rb +0 -120
- data/spec/graphql/introspection/directive_type_spec.rb +0 -50
- data/spec/graphql/introspection/input_value_type_spec.rb +0 -42
- data/spec/graphql/introspection/introspection_query_spec.rb +0 -10
- data/spec/graphql/introspection/schema_type_spec.rb +0 -45
- data/spec/graphql/introspection/type_type_spec.rb +0 -122
- data/spec/graphql/language/generation_spec.rb +0 -42
- data/spec/graphql/language/parser_spec.rb +0 -442
- data/spec/graphql/language/visitor_spec.rb +0 -49
- data/spec/graphql/list_type_spec.rb +0 -32
- data/spec/graphql/non_null_type_spec.rb +0 -31
- data/spec/graphql/object_type_spec.rb +0 -42
- data/spec/graphql/query/arguments_spec.rb +0 -25
- data/spec/graphql/query/context_spec.rb +0 -83
- data/spec/graphql/query/executor_spec.rb +0 -273
- data/spec/graphql/query/serial_execution/execution_context_spec.rb +0 -53
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -66
- data/spec/graphql/query/type_resolver_spec.rb +0 -8
- data/spec/graphql/query/variables_spec.rb +0 -28
- data/spec/graphql/query_spec.rb +0 -363
- data/spec/graphql/scalar_type_spec.rb +0 -61
- data/spec/graphql/schema/catchall_middleware_spec.rb +0 -32
- data/spec/graphql/schema/middleware_chain_spec.rb +0 -42
- data/spec/graphql/schema/printer_spec.rb +0 -190
- data/spec/graphql/schema/reduce_types_spec.rb +0 -102
- data/spec/graphql/schema/rescue_middleware_spec.rb +0 -33
- data/spec/graphql/schema/timeout_middleware_spec.rb +0 -180
- data/spec/graphql/schema/type_expression_spec.rb +0 -38
- data/spec/graphql/schema/validation_spec.rb +0 -219
- data/spec/graphql/schema_spec.rb +0 -23
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -63
- data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -48
- data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -34
- data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -39
- data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -60
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -31
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -48
- data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -47
- data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -39
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -44
- data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -49
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -25
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -42
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -44
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -63
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -37
- data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -53
- data/spec/graphql/static_validation/type_stack_spec.rb +0 -37
- data/spec/graphql/static_validation/validator_spec.rb +0 -69
- data/spec/graphql/string_type_spec.rb +0 -15
- data/spec/graphql/union_type_spec.rb +0 -31
- data/spec/spec_helper.rb +0 -18
- data/spec/support/dairy_app.rb +0 -309
- data/spec/support/dairy_data.rb +0 -23
- data/spec/support/minimum_input_object.rb +0 -16
- data/spec/support/star_wars_data.rb +0 -71
- data/spec/support/star_wars_schema.rb +0 -76
@@ -0,0 +1,311 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Execution
|
4
|
+
# Lookahead creates a uniform interface to inspect the forthcoming selections.
|
5
|
+
#
|
6
|
+
# It assumes that the AST it's working with is valid. (So, it's safe to use
|
7
|
+
# during execution, but if you're using it directly, be sure to validate first.)
|
8
|
+
#
|
9
|
+
# A field may get access to its lookahead by adding `extras: [:lookahead]`
|
10
|
+
# to its configuration.
|
11
|
+
#
|
12
|
+
# @example looking ahead in a field
|
13
|
+
# field :articles, [Types::Article], null: false,
|
14
|
+
# extras: [:lookahead]
|
15
|
+
#
|
16
|
+
# # For example, imagine a faster database call
|
17
|
+
# # may be issued when only some fields are requested.
|
18
|
+
# #
|
19
|
+
# # Imagine that _full_ fetch must be made to satisfy `fullContent`,
|
20
|
+
# # we can look ahead to see if we need that field. If we do,
|
21
|
+
# # we make the expensive database call instead of the cheap one.
|
22
|
+
# def articles(lookahead:)
|
23
|
+
# if lookahead.selects?(:full_content)
|
24
|
+
# fetch_full_articles(object)
|
25
|
+
# else
|
26
|
+
# fetch_preview_articles(object)
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
class Lookahead
|
30
|
+
# @param query [GraphQL::Query]
|
31
|
+
# @param ast_nodes [Array<GraphQL::Language::Nodes::Field>, Array<GraphQL::Language::Nodes::OperationDefinition>]
|
32
|
+
# @param field [GraphQL::Schema::Field] if `ast_nodes` are fields, this is the field definition matching those nodes
|
33
|
+
# @param root_type [Class] if `ast_nodes` are operation definition, this is the root type for that operation
|
34
|
+
def initialize(query:, ast_nodes:, field: nil, root_type: nil, owner_type: nil)
|
35
|
+
@ast_nodes = ast_nodes.freeze
|
36
|
+
@field = field
|
37
|
+
@root_type = root_type
|
38
|
+
@query = query
|
39
|
+
@selected_type = @field ? @field.type.unwrap : root_type
|
40
|
+
@owner_type = owner_type
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Array<GraphQL::Language::Nodes::Field>]
|
44
|
+
attr_reader :ast_nodes
|
45
|
+
|
46
|
+
# @return [GraphQL::Schema::Field]
|
47
|
+
attr_reader :field
|
48
|
+
|
49
|
+
# @return [GraphQL::Schema::Object, GraphQL::Schema::Union, GraphQL::Schema::Interface]
|
50
|
+
attr_reader :owner_type
|
51
|
+
|
52
|
+
# @return [Hash<Symbol, Object>]
|
53
|
+
def arguments
|
54
|
+
if defined?(@arguments)
|
55
|
+
@arguments
|
56
|
+
else
|
57
|
+
@arguments = if @field
|
58
|
+
@query.schema.after_lazy(@query.arguments_for(@ast_nodes.first, @field)) do |args|
|
59
|
+
args.is_a?(Execution::Interpreter::Arguments) ? args.keyword_arguments : args
|
60
|
+
end
|
61
|
+
else
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# True if this node has a selection on `field_name`.
|
68
|
+
# If `field_name` is a String, it is treated as a GraphQL-style (camelized)
|
69
|
+
# field name and used verbatim. If `field_name` is a Symbol, it is
|
70
|
+
# treated as a Ruby-style (underscored) name and camelized before comparing.
|
71
|
+
#
|
72
|
+
# If `arguments:` is provided, each provided key/value will be matched
|
73
|
+
# against the arguments in the next selection. This method will return false
|
74
|
+
# if any of the given `arguments:` are not present and matching in the next selection.
|
75
|
+
# (But, the next selection may contain _more_ than the given arguments.)
|
76
|
+
# @param field_name [String, Symbol]
|
77
|
+
# @param arguments [Hash] Arguments which must match in the selection
|
78
|
+
# @return [Boolean]
|
79
|
+
def selects?(field_name, selected_type: @selected_type, arguments: nil)
|
80
|
+
selection(field_name, selected_type: selected_type, arguments: arguments).selected?
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [Boolean] True if this lookahead represents a field that was requested
|
84
|
+
def selected?
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
# Like {#selects?}, but can be used for chaining.
|
89
|
+
# It returns a null object (check with {#selected?})
|
90
|
+
# @param field_name [String, Symbol]
|
91
|
+
# @return [GraphQL::Execution::Lookahead]
|
92
|
+
def selection(field_name, selected_type: @selected_type, arguments: nil)
|
93
|
+
next_field_defn = case field_name
|
94
|
+
when String
|
95
|
+
@query.get_field(selected_type, field_name)
|
96
|
+
when Symbol
|
97
|
+
# Try to avoid the `.to_s` below, if possible
|
98
|
+
all_fields = if selected_type.kind.fields?
|
99
|
+
@query.warden.fields(selected_type)
|
100
|
+
else
|
101
|
+
# Handle unions by checking possible
|
102
|
+
@query.warden
|
103
|
+
.possible_types(selected_type)
|
104
|
+
.map { |t| @query.warden.fields(t) }
|
105
|
+
.flatten
|
106
|
+
end
|
107
|
+
|
108
|
+
if (match_by_orig_name = all_fields.find { |f| f.original_name == field_name })
|
109
|
+
match_by_orig_name
|
110
|
+
else
|
111
|
+
# Symbol#name is only present on 3.0+
|
112
|
+
sym_s = field_name.respond_to?(:name) ? field_name.name : field_name.to_s
|
113
|
+
guessed_name = Schema::Member::BuildType.camelize(sym_s)
|
114
|
+
@query.get_field(selected_type, guessed_name)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
if next_field_defn
|
119
|
+
next_nodes = []
|
120
|
+
@ast_nodes.each do |ast_node|
|
121
|
+
ast_node.selections.each do |selection|
|
122
|
+
find_selected_nodes(selection, next_field_defn, arguments: arguments, matches: next_nodes)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
if next_nodes.any?
|
127
|
+
Lookahead.new(query: @query, ast_nodes: next_nodes, field: next_field_defn, owner_type: selected_type)
|
128
|
+
else
|
129
|
+
NULL_LOOKAHEAD
|
130
|
+
end
|
131
|
+
else
|
132
|
+
NULL_LOOKAHEAD
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Like {#selection}, but for all nodes.
|
137
|
+
# It returns a list of Lookaheads for all Selections
|
138
|
+
#
|
139
|
+
# If `arguments:` is provided, each provided key/value will be matched
|
140
|
+
# against the arguments in each selection. This method will filter the selections
|
141
|
+
# if any of the given `arguments:` do not match the given selection.
|
142
|
+
#
|
143
|
+
# @example getting the name of a selection
|
144
|
+
# def articles(lookahead:)
|
145
|
+
# next_lookaheads = lookahead.selections # => [#<GraphQL::Execution::Lookahead ...>, ...]
|
146
|
+
# next_lookaheads.map(&:name) #=> [:full_content, :title]
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# @param arguments [Hash] Arguments which must match in the selection
|
150
|
+
# @return [Array<GraphQL::Execution::Lookahead>]
|
151
|
+
def selections(arguments: nil)
|
152
|
+
subselections_by_type = {}
|
153
|
+
subselections_on_type = subselections_by_type[@selected_type] = {}
|
154
|
+
|
155
|
+
@ast_nodes.each do |node|
|
156
|
+
find_selections(subselections_by_type, subselections_on_type, @selected_type, node.selections, arguments)
|
157
|
+
end
|
158
|
+
|
159
|
+
subselections = []
|
160
|
+
|
161
|
+
subselections_by_type.each do |type, ast_nodes_by_response_key|
|
162
|
+
ast_nodes_by_response_key.each do |response_key, ast_nodes|
|
163
|
+
field_defn = @query.get_field(type, ast_nodes.first.name)
|
164
|
+
lookahead = Lookahead.new(query: @query, ast_nodes: ast_nodes, field: field_defn, owner_type: type)
|
165
|
+
subselections.push(lookahead)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
subselections
|
170
|
+
end
|
171
|
+
|
172
|
+
# The method name of the field.
|
173
|
+
# It returns the method_sym of the Lookahead's field.
|
174
|
+
#
|
175
|
+
# @example getting the name of a selection
|
176
|
+
# def articles(lookahead:)
|
177
|
+
# article.selection(:full_content).name # => :full_content
|
178
|
+
# # ...
|
179
|
+
# end
|
180
|
+
#
|
181
|
+
# @return [Symbol]
|
182
|
+
def name
|
183
|
+
@field && @field.original_name
|
184
|
+
end
|
185
|
+
|
186
|
+
def inspect
|
187
|
+
"#<GraphQL::Execution::Lookahead #{@field ? "@field=#{@field.path.inspect}": "@root_type=#{@root_type}"} @ast_nodes.size=#{@ast_nodes.size}>"
|
188
|
+
end
|
189
|
+
|
190
|
+
# This is returned for {Lookahead#selection} when a non-existent field is passed
|
191
|
+
class NullLookahead < Lookahead
|
192
|
+
# No inputs required here.
|
193
|
+
def initialize
|
194
|
+
end
|
195
|
+
|
196
|
+
def selected?
|
197
|
+
false
|
198
|
+
end
|
199
|
+
|
200
|
+
def selects?(*)
|
201
|
+
false
|
202
|
+
end
|
203
|
+
|
204
|
+
def selection(*)
|
205
|
+
NULL_LOOKAHEAD
|
206
|
+
end
|
207
|
+
|
208
|
+
def selections(*)
|
209
|
+
[]
|
210
|
+
end
|
211
|
+
|
212
|
+
def inspect
|
213
|
+
"#<GraphQL::Execution::Lookahead::NullLookahead>"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# A singleton, so that misses don't come with overhead.
|
218
|
+
NULL_LOOKAHEAD = NullLookahead.new
|
219
|
+
|
220
|
+
private
|
221
|
+
|
222
|
+
def skipped_by_directive?(ast_selection)
|
223
|
+
ast_selection.directives.each do |directive|
|
224
|
+
dir_defn = @query.schema.directives.fetch(directive.name)
|
225
|
+
directive_class = dir_defn
|
226
|
+
if directive_class
|
227
|
+
dir_args = @query.arguments_for(directive, dir_defn)
|
228
|
+
return true unless directive_class.static_include?(dir_args, @query.context)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
false
|
232
|
+
end
|
233
|
+
|
234
|
+
def find_selections(subselections_by_type, selections_on_type, selected_type, ast_selections, arguments)
|
235
|
+
ast_selections.each do |ast_selection|
|
236
|
+
next if skipped_by_directive?(ast_selection)
|
237
|
+
|
238
|
+
case ast_selection
|
239
|
+
when GraphQL::Language::Nodes::Field
|
240
|
+
response_key = ast_selection.alias || ast_selection.name
|
241
|
+
if selections_on_type.key?(response_key)
|
242
|
+
selections_on_type[response_key] << ast_selection
|
243
|
+
elsif arguments.nil? || arguments.empty?
|
244
|
+
selections_on_type[response_key] = [ast_selection]
|
245
|
+
else
|
246
|
+
field_defn = @query.get_field(selected_type, ast_selection.name)
|
247
|
+
if arguments_match?(arguments, field_defn, ast_selection)
|
248
|
+
selections_on_type[response_key] = [ast_selection]
|
249
|
+
end
|
250
|
+
end
|
251
|
+
when GraphQL::Language::Nodes::InlineFragment
|
252
|
+
on_type = selected_type
|
253
|
+
subselections_on_type = selections_on_type
|
254
|
+
if (t = ast_selection.type)
|
255
|
+
# Assuming this is valid, that `t` will be found.
|
256
|
+
on_type = @query.get_type(t.name)
|
257
|
+
subselections_on_type = subselections_by_type[on_type] ||= {}
|
258
|
+
end
|
259
|
+
find_selections(subselections_by_type, subselections_on_type, on_type, ast_selection.selections, arguments)
|
260
|
+
when GraphQL::Language::Nodes::FragmentSpread
|
261
|
+
frag_defn = @query.fragments[ast_selection.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{ast_selection.name} (found: #{@query.fragments.keys})")
|
262
|
+
# Again, assuming a valid AST
|
263
|
+
on_type = @query.get_type(frag_defn.type.name)
|
264
|
+
subselections_on_type = subselections_by_type[on_type] ||= {}
|
265
|
+
find_selections(subselections_by_type, subselections_on_type, on_type, frag_defn.selections, arguments)
|
266
|
+
else
|
267
|
+
raise "Invariant: Unexpected selection type: #{ast_selection.class}"
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
# If a selection on `node` matches `field_name` (which is backed by `field_defn`)
|
273
|
+
# and matches the `arguments:` constraints, then add that node to `matches`
|
274
|
+
def find_selected_nodes(node, field_defn, arguments:, matches:)
|
275
|
+
return if skipped_by_directive?(node)
|
276
|
+
case node
|
277
|
+
when GraphQL::Language::Nodes::Field
|
278
|
+
if node.name == field_defn.graphql_name
|
279
|
+
if arguments.nil? || arguments.empty?
|
280
|
+
# No constraint applied
|
281
|
+
matches << node
|
282
|
+
elsif arguments_match?(arguments, field_defn, node)
|
283
|
+
matches << node
|
284
|
+
end
|
285
|
+
end
|
286
|
+
when GraphQL::Language::Nodes::InlineFragment
|
287
|
+
node.selections.each { |s| find_selected_nodes(s, field_defn, arguments: arguments, matches: matches) }
|
288
|
+
when GraphQL::Language::Nodes::FragmentSpread
|
289
|
+
frag_defn = @query.fragments[node.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{node.name} (found: #{@query.fragments.keys})")
|
290
|
+
frag_defn.selections.each { |s| find_selected_nodes(s, field_defn, arguments: arguments, matches: matches) }
|
291
|
+
else
|
292
|
+
raise "Unexpected selection comparison on #{node.class.name} (#{node})"
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def arguments_match?(arguments, field_defn, field_node)
|
297
|
+
query_kwargs = @query.arguments_for(field_node, field_defn)
|
298
|
+
arguments.all? do |arg_name, arg_value|
|
299
|
+
arg_name_sym = if arg_name.is_a?(String)
|
300
|
+
Schema::Member::BuildType.underscore(arg_name).to_sym
|
301
|
+
else
|
302
|
+
arg_name
|
303
|
+
end
|
304
|
+
|
305
|
+
# Make sure the constraint is present with a matching value
|
306
|
+
query_kwargs.key?(arg_name_sym) && query_kwargs[arg_name_sym] == arg_value
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Execution
|
4
|
+
# Execute multiple queries under the same multiplex "umbrella".
|
5
|
+
# They can share a batching context and reduce redundant database hits.
|
6
|
+
#
|
7
|
+
# The flow is:
|
8
|
+
#
|
9
|
+
# - Multiplex instrumentation setup
|
10
|
+
# - Query instrumentation setup
|
11
|
+
# - Analyze the multiplex + each query
|
12
|
+
# - Begin each query
|
13
|
+
# - Resolve lazy values, breadth-first across all queries
|
14
|
+
# - Finish each query (eg, get errors)
|
15
|
+
# - Query instrumentation teardown
|
16
|
+
# - Multiplex instrumentation teardown
|
17
|
+
#
|
18
|
+
# If one query raises an application error, all queries will be in undefined states.
|
19
|
+
#
|
20
|
+
# Validation errors and {GraphQL::ExecutionError}s are handled in isolation:
|
21
|
+
# one of these errors in one query will not affect the other queries.
|
22
|
+
#
|
23
|
+
# @see {Schema#multiplex} for public API
|
24
|
+
# @api private
|
25
|
+
class Multiplex
|
26
|
+
include Tracing::Traceable
|
27
|
+
|
28
|
+
attr_reader :context, :queries, :schema, :max_complexity, :dataloader
|
29
|
+
|
30
|
+
def initialize(schema:, queries:, context:, max_complexity:)
|
31
|
+
@schema = schema
|
32
|
+
@queries = queries
|
33
|
+
@queries.each { |q| q.multiplex = self }
|
34
|
+
@context = context
|
35
|
+
@dataloader = @context[:dataloader] ||= @schema.dataloader_class.new
|
36
|
+
@tracers = schema.tracers + (context[:tracers] || [])
|
37
|
+
# Support `context: {backtrace: true}`
|
38
|
+
if context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
39
|
+
@tracers << GraphQL::Backtrace::Tracer
|
40
|
+
end
|
41
|
+
@max_complexity = max_complexity
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "graphql/execution/directive_checks"
|
3
|
+
require "graphql/execution/interpreter"
|
4
|
+
require "graphql/execution/lazy"
|
5
|
+
require "graphql/execution/lookahead"
|
6
|
+
require "graphql/execution/multiplex"
|
7
|
+
require "graphql/execution/errors"
|
8
|
+
|
9
|
+
module GraphQL
|
10
|
+
module Execution
|
11
|
+
# @api private
|
12
|
+
class Skip < GraphQL::Error; end
|
13
|
+
|
14
|
+
# Just a singleton for implementing {Query::Context#skip}
|
15
|
+
# @api private
|
16
|
+
SKIP = Skip.new
|
17
|
+
end
|
18
|
+
end
|
@@ -1,11 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module GraphQL
|
2
3
|
# If a field's resolve function returns a {ExecutionError},
|
3
4
|
# the error will be inserted into the response's `"errors"` key
|
4
5
|
# and the field will resolve to `nil`.
|
5
6
|
class ExecutionError < GraphQL::Error
|
6
|
-
# @return [GraphQL::Language::Nodes::Field] the field where the error
|
7
|
+
# @return [GraphQL::Language::Nodes::Field] the field where the error occurred
|
7
8
|
attr_accessor :ast_node
|
8
9
|
|
10
|
+
# @return [String] an array describing the JSON-path into the execution
|
11
|
+
# response which corresponds to this error.
|
12
|
+
attr_accessor :path
|
13
|
+
|
14
|
+
# @return [Hash] Optional data for error objects
|
15
|
+
# @deprecated Use `extensions` instead of `options`. The GraphQL spec
|
16
|
+
# recommends that any custom entries in an error be under the
|
17
|
+
# `extensions` key.
|
18
|
+
attr_accessor :options
|
19
|
+
|
20
|
+
# @return [Hash] Optional custom data for error objects which will be added
|
21
|
+
# under the `extensions` key.
|
22
|
+
attr_accessor :extensions
|
23
|
+
|
24
|
+
def initialize(message, ast_node: nil, options: nil, extensions: nil)
|
25
|
+
@ast_node = ast_node
|
26
|
+
@options = options
|
27
|
+
@extensions = extensions
|
28
|
+
super(message)
|
29
|
+
end
|
30
|
+
|
9
31
|
# @return [Hash] An entry for the response's "errors" key
|
10
32
|
def to_h
|
11
33
|
hash = {
|
@@ -19,6 +41,17 @@ module GraphQL
|
|
19
41
|
}
|
20
42
|
]
|
21
43
|
end
|
44
|
+
if path
|
45
|
+
hash["path"] = path
|
46
|
+
end
|
47
|
+
if options
|
48
|
+
hash.merge!(options)
|
49
|
+
end
|
50
|
+
if extensions
|
51
|
+
hash["extensions"] = extensions.each_with_object({}) { |(key, value), ext|
|
52
|
+
ext[key.to_s] = value
|
53
|
+
}
|
54
|
+
end
|
22
55
|
hash
|
23
56
|
end
|
24
57
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
# @api private
|
4
|
+
class Filter
|
5
|
+
def initialize(only: nil, except: nil)
|
6
|
+
@only = only
|
7
|
+
@except = except
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns true if `member, ctx` passes this filter
|
11
|
+
def call(member, ctx)
|
12
|
+
(@only ? @only.call(member, ctx) : true) &&
|
13
|
+
(@except ? !@except.call(member, ctx) : true)
|
14
|
+
end
|
15
|
+
|
16
|
+
def merge(only: nil, except: nil)
|
17
|
+
onlies = [self].concat(Array(only))
|
18
|
+
merged_only = MergedOnly.build(onlies)
|
19
|
+
merged_except = MergedExcept.build(Array(except))
|
20
|
+
self.class.new(only: merged_only, except: merged_except)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
class MergedOnly
|
26
|
+
def initialize(first, second)
|
27
|
+
@first = first
|
28
|
+
@second = second
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(member, ctx)
|
32
|
+
@first.call(member, ctx) && @second.call(member, ctx)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.build(onlies)
|
36
|
+
case onlies.size
|
37
|
+
when 0
|
38
|
+
nil
|
39
|
+
when 1
|
40
|
+
onlies[0]
|
41
|
+
else
|
42
|
+
onlies.reduce { |memo, only| self.new(memo, only) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class MergedExcept < MergedOnly
|
48
|
+
def call(member, ctx)
|
49
|
+
@first.call(member, ctx) || @second.call(member, ctx)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
# This error is raised when `Types::Int` is given an input value outside of 32-bit integer range.
|
4
|
+
#
|
5
|
+
# For really big integer values, consider `GraphQL::Types::BigInt`
|
6
|
+
#
|
7
|
+
# @see GraphQL::Types::Int which raises this error
|
8
|
+
class IntegerDecodingError < GraphQL::RuntimeTypeError
|
9
|
+
# The value which couldn't be decoded
|
10
|
+
attr_reader :integer_value
|
11
|
+
|
12
|
+
def initialize(value)
|
13
|
+
@integer_value = value
|
14
|
+
super("Integer out of bounds: #{value}. \nConsider using GraphQL::Types::BigInt instead.")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
# This error is raised when `Types::Int` is asked to return a value outside of 32-bit integer range.
|
4
|
+
#
|
5
|
+
# For values outside that range, consider:
|
6
|
+
#
|
7
|
+
# - `ID` for database primary keys or other identifiers
|
8
|
+
# - `GraphQL::Types::BigInt` for really big integer values
|
9
|
+
#
|
10
|
+
# @see GraphQL::Types::Int which raises this error
|
11
|
+
class IntegerEncodingError < GraphQL::RuntimeTypeError
|
12
|
+
# The value which couldn't be encoded
|
13
|
+
attr_reader :integer_value
|
14
|
+
|
15
|
+
# @return [GraphQL::Schema::Field] The field that returned a too-big integer
|
16
|
+
attr_reader :field
|
17
|
+
|
18
|
+
# @return [Array<String, Integer>] Where the field appeared in the GraphQL response
|
19
|
+
attr_reader :path
|
20
|
+
|
21
|
+
def initialize(value, context:)
|
22
|
+
@integer_value = value
|
23
|
+
@field = context[:current_field]
|
24
|
+
@path = context[:current_path]
|
25
|
+
message = "Integer out of bounds: #{value}".dup
|
26
|
+
if @path
|
27
|
+
message << " @ #{@path.join(".")}"
|
28
|
+
end
|
29
|
+
if @field
|
30
|
+
message << " (#{@field.path})"
|
31
|
+
end
|
32
|
+
message << ". Consider using ID or GraphQL::Types::BigInt instead."
|
33
|
+
super(message)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Introspection
|
4
|
+
class BaseObject < GraphQL::Schema::Object
|
5
|
+
introspection(true)
|
6
|
+
|
7
|
+
def self.field(*args, **kwargs, &block)
|
8
|
+
kwargs[:introspection] = true
|
9
|
+
super(*args, **kwargs, &block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,8 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Introspection
|
4
|
+
class DirectiveLocationEnum < GraphQL::Schema::Enum
|
5
|
+
graphql_name "__DirectiveLocation"
|
6
|
+
description "A Directive can be adjacent to many parts of the GraphQL language, "\
|
7
|
+
"a __DirectiveLocation describes one such possible adjacencies."
|
4
8
|
|
5
|
-
|
6
|
-
|
9
|
+
GraphQL::Schema::Directive::LOCATIONS.each do |location|
|
10
|
+
value(location.to_s, GraphQL::Schema::Directive::LOCATION_DESCRIPTIONS[location], value: location)
|
11
|
+
end
|
12
|
+
introspection true
|
13
|
+
end
|
7
14
|
end
|
8
15
|
end
|
@@ -1,11 +1,31 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Introspection
|
4
|
+
class DirectiveType < Introspection::BaseObject
|
5
|
+
graphql_name "__Directive"
|
6
|
+
description "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document."\
|
7
|
+
"\n\n"\
|
8
|
+
"In some cases, you need to provide options to alter GraphQL's execution behavior "\
|
9
|
+
"in ways field arguments will not suffice, such as conditionally including or "\
|
10
|
+
"skipping a field. Directives provide this by describing additional information "\
|
11
|
+
"to the executor."
|
12
|
+
field :name, String, null: false, method: :graphql_name
|
13
|
+
field :description, String
|
14
|
+
field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
|
15
|
+
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
|
16
|
+
argument :include_deprecated, Boolean, required: false, default_value: false
|
17
|
+
end
|
18
|
+
field :on_operation, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_operation?
|
19
|
+
field :on_fragment, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_fragment?
|
20
|
+
field :on_field, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_field?
|
21
|
+
|
22
|
+
field :is_repeatable, Boolean, method: :repeatable?
|
23
|
+
|
24
|
+
def args(include_deprecated:)
|
25
|
+
args = @context.warden.arguments(@object)
|
26
|
+
args = args.reject(&:deprecation_reason) unless include_deprecated
|
27
|
+
args
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
11
31
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Introspection
|
4
|
+
class DynamicFields < Introspection::BaseObject
|
5
|
+
field :__typename, String, "The name of this type", null: false
|
6
|
+
|
7
|
+
def __typename
|
8
|
+
object.class.graphql_name
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Introspection
|
4
|
+
class EntryPoints < Introspection::BaseObject
|
5
|
+
field :__schema, GraphQL::Schema::LateBoundType.new("__Schema"), "This GraphQL schema", null: false
|
6
|
+
field :__type, GraphQL::Schema::LateBoundType.new("__Type"), "A type in the GraphQL system" do
|
7
|
+
argument :name, String
|
8
|
+
end
|
9
|
+
|
10
|
+
def __schema
|
11
|
+
# Apply wrapping manually since this field isn't wrapped by instrumentation
|
12
|
+
schema = @context.query.schema
|
13
|
+
schema_type = schema.introspection_system.types["__Schema"]
|
14
|
+
schema_type.authorized_new(schema, @context)
|
15
|
+
end
|
16
|
+
|
17
|
+
def __type(name:)
|
18
|
+
context.warden.reachable_type?(name) ? context.warden.get_type(name) : nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|