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,179 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "graphql/types/string"
|
3
|
+
|
4
|
+
module GraphQL
|
5
|
+
class Schema
|
6
|
+
# Mutations that extend this base class get some conventions added for free:
|
7
|
+
#
|
8
|
+
# - An argument called `clientMutationId` is _always_ added, but it's not passed
|
9
|
+
# to the resolve method. The value is re-inserted to the response. (It's for
|
10
|
+
# client libraries to manage optimistic updates.)
|
11
|
+
# - The returned object type always has a field called `clientMutationId` to support that.
|
12
|
+
# - The mutation accepts one argument called `input`, `argument`s defined in the mutation
|
13
|
+
# class are added to that input object, which is generated by the mutation.
|
14
|
+
#
|
15
|
+
# These conventions were first specified by Relay Classic, but they come in handy:
|
16
|
+
#
|
17
|
+
# - `clientMutationId` supports optimistic updates and cache rollbacks on the client
|
18
|
+
# - using a single `input:` argument makes it easy to post whole JSON objects to the mutation
|
19
|
+
# using one GraphQL variable (`$input`) instead of making a separate variable for each argument.
|
20
|
+
#
|
21
|
+
# @see {GraphQL::Schema::Mutation} for an example, it's basically the same.
|
22
|
+
#
|
23
|
+
class RelayClassicMutation < GraphQL::Schema::Mutation
|
24
|
+
# The payload should always include this field
|
25
|
+
field(:client_mutation_id, String, "A unique identifier for the client performing the mutation.")
|
26
|
+
# Relay classic default:
|
27
|
+
null(true)
|
28
|
+
|
29
|
+
# Override {GraphQL::Schema::Resolver#resolve_with_support} to
|
30
|
+
# delete `client_mutation_id` from the kwargs.
|
31
|
+
def resolve_with_support(**inputs)
|
32
|
+
input = inputs[:input].to_kwargs
|
33
|
+
|
34
|
+
new_extras = field ? field.extras : []
|
35
|
+
all_extras = self.class.extras + new_extras
|
36
|
+
|
37
|
+
# Transfer these from the top-level hash to the
|
38
|
+
# shortcutted `input:` object
|
39
|
+
all_extras.each do |ext|
|
40
|
+
# It's possible that the `extra` was not passed along by this point,
|
41
|
+
# don't re-add it if it wasn't given here.
|
42
|
+
if inputs.key?(ext)
|
43
|
+
input[ext] = inputs[ext]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
if input
|
48
|
+
# This is handled by Relay::Mutation::Resolve, a bit hacky, but here we are.
|
49
|
+
input_kwargs = input.to_h
|
50
|
+
client_mutation_id = input_kwargs.delete(:client_mutation_id)
|
51
|
+
else
|
52
|
+
# Relay Classic Mutations with no `argument`s
|
53
|
+
# don't require `input:`
|
54
|
+
input_kwargs = {}
|
55
|
+
end
|
56
|
+
|
57
|
+
return_value = if input_kwargs.any?
|
58
|
+
super(**input_kwargs)
|
59
|
+
else
|
60
|
+
super()
|
61
|
+
end
|
62
|
+
|
63
|
+
context.schema.after_lazy(return_value) do |return_hash|
|
64
|
+
# It might be an error
|
65
|
+
if return_hash.is_a?(Hash)
|
66
|
+
return_hash[:client_mutation_id] = client_mutation_id
|
67
|
+
end
|
68
|
+
return_hash
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class << self
|
73
|
+
def dummy
|
74
|
+
@dummy ||= begin
|
75
|
+
d = Class.new(GraphQL::Schema::Resolver)
|
76
|
+
d.argument_class(self.argument_class)
|
77
|
+
# TODO make this lazier?
|
78
|
+
d.argument(:input, input_type, description: "Parameters for #{self.graphql_name}")
|
79
|
+
d
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def field_arguments(context = GraphQL::Query::NullContext)
|
84
|
+
dummy.arguments(context)
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_field_argument(name, context = GraphQL::Query::NullContext)
|
88
|
+
dummy.get_argument(name, context)
|
89
|
+
end
|
90
|
+
|
91
|
+
def own_field_arguments
|
92
|
+
dummy.own_arguments
|
93
|
+
end
|
94
|
+
|
95
|
+
def all_field_argument_definitions
|
96
|
+
dummy.all_argument_definitions
|
97
|
+
end
|
98
|
+
|
99
|
+
# Also apply this argument to the input type:
|
100
|
+
def argument(*args, own_argument: false, **kwargs, &block)
|
101
|
+
it = input_type # make sure any inherited arguments are already added to it
|
102
|
+
arg = super(*args, **kwargs, &block)
|
103
|
+
|
104
|
+
# This definition might be overriding something inherited;
|
105
|
+
# if it is, remove the inherited definition so it's not confused at runtime as having multiple definitions
|
106
|
+
prev_args = it.own_arguments[arg.graphql_name]
|
107
|
+
case prev_args
|
108
|
+
when GraphQL::Schema::Argument
|
109
|
+
if prev_args.owner != self
|
110
|
+
it.own_arguments.delete(arg.graphql_name)
|
111
|
+
end
|
112
|
+
when Array
|
113
|
+
prev_args.reject! { |a| a.owner != self }
|
114
|
+
if prev_args.empty?
|
115
|
+
it.own_arguments.delete(arg.graphql_name)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it.add_argument(arg)
|
120
|
+
arg
|
121
|
+
end
|
122
|
+
|
123
|
+
# The base class for generated input object types
|
124
|
+
# @param new_class [Class] The base class to use for generating input object definitions
|
125
|
+
# @return [Class] The base class for this mutation's generated input object (default is {GraphQL::Schema::InputObject})
|
126
|
+
def input_object_class(new_class = nil)
|
127
|
+
if new_class
|
128
|
+
@input_object_class = new_class
|
129
|
+
end
|
130
|
+
@input_object_class || (superclass.respond_to?(:input_object_class) ? superclass.input_object_class : GraphQL::Schema::InputObject)
|
131
|
+
end
|
132
|
+
|
133
|
+
# @param new_input_type [Class, nil] If provided, it configures this mutation to accept `new_input_type` instead of generating an input type
|
134
|
+
# @return [Class] The generated {Schema::InputObject} class for this mutation's `input`
|
135
|
+
def input_type(new_input_type = nil)
|
136
|
+
if new_input_type
|
137
|
+
@input_type = new_input_type
|
138
|
+
end
|
139
|
+
@input_type ||= generate_input_type
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# Generate the input type for the `input:` argument
|
145
|
+
# To customize how input objects are generated, override this method
|
146
|
+
# @return [Class] a subclass of {.input_object_class}
|
147
|
+
def generate_input_type
|
148
|
+
mutation_args = all_argument_definitions
|
149
|
+
mutation_class = self
|
150
|
+
Class.new(input_object_class) do
|
151
|
+
class << self
|
152
|
+
def default_graphql_name
|
153
|
+
"#{self.mutation.graphql_name}Input"
|
154
|
+
end
|
155
|
+
|
156
|
+
def description(new_desc = nil)
|
157
|
+
super || "Autogenerated input type of #{self.mutation.graphql_name}"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
mutation(mutation_class)
|
161
|
+
# these might be inherited:
|
162
|
+
mutation_args.each do |arg|
|
163
|
+
add_argument(arg)
|
164
|
+
end
|
165
|
+
argument :client_mutation_id, String, "A unique identifier for the client performing the mutation.", required: false
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
def authorize_arguments(args, values)
|
173
|
+
# remove the `input` wrapper to match values
|
174
|
+
input_args = args["input"].type.unwrap.arguments(context)
|
175
|
+
super(input_args, values)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Resolver
|
6
|
+
# Adds `field(...)` helper to resolvers so that they can
|
7
|
+
# generate payload types.
|
8
|
+
#
|
9
|
+
# Or, an already-defined one can be attached with `payload_type(...)`.
|
10
|
+
module HasPayloadType
|
11
|
+
# Call this method to get the derived return type of the mutation,
|
12
|
+
# or use it as a configuration method to assign a return type
|
13
|
+
# instead of generating one.
|
14
|
+
# @param new_payload_type [Class, nil] If a type definition class is provided, it will be used as the return type of the mutation field
|
15
|
+
# @return [Class] The object type which this mutation returns.
|
16
|
+
def payload_type(new_payload_type = nil)
|
17
|
+
if new_payload_type
|
18
|
+
@payload_type = new_payload_type
|
19
|
+
end
|
20
|
+
@payload_type ||= generate_payload_type
|
21
|
+
end
|
22
|
+
|
23
|
+
def type(new_type = nil, null: nil)
|
24
|
+
if new_type
|
25
|
+
payload_type(new_type)
|
26
|
+
if !null.nil?
|
27
|
+
self.null(null)
|
28
|
+
end
|
29
|
+
else
|
30
|
+
super()
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :type_expr :payload_type
|
35
|
+
|
36
|
+
def field_class(new_class = nil)
|
37
|
+
if new_class
|
38
|
+
@field_class = new_class
|
39
|
+
elsif defined?(@field_class) && @field_class
|
40
|
+
@field_class
|
41
|
+
else
|
42
|
+
find_inherited_value(:field_class, GraphQL::Schema::Field)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# An object class to use for deriving return types
|
47
|
+
# @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
|
48
|
+
# @return [Class]
|
49
|
+
def object_class(new_class = nil)
|
50
|
+
if new_class
|
51
|
+
if defined?(@payload_type)
|
52
|
+
raise "Can't configure `object_class(...)` after the payload type has already been initialized. Move this configuration higher up the class definition."
|
53
|
+
end
|
54
|
+
@object_class = new_class
|
55
|
+
else
|
56
|
+
@object_class || find_inherited_value(:object_class, GraphQL::Schema::Object)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
NO_INTERFACES = [].freeze
|
61
|
+
|
62
|
+
def field(*args, **kwargs, &block)
|
63
|
+
pt = payload_type # make sure it's initialized with any inherited fields
|
64
|
+
field_defn = super
|
65
|
+
|
66
|
+
# Remove any inherited fields to avoid false conflicts at runtime
|
67
|
+
prev_fields = pt.own_fields[field_defn.graphql_name]
|
68
|
+
case prev_fields
|
69
|
+
when GraphQL::Schema::Field
|
70
|
+
if prev_fields.owner != self
|
71
|
+
pt.own_fields.delete(field_defn.graphql_name)
|
72
|
+
end
|
73
|
+
when Array
|
74
|
+
prev_fields.reject! { |f| f.owner != self }
|
75
|
+
if prev_fields.empty?
|
76
|
+
pt.own_fields.delete(field_defn.graphql_name)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
pt.add_field(field_defn, method_conflict_warning: false)
|
81
|
+
field_defn
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# Build a subclass of {.object_class} based on `self`.
|
87
|
+
# This value will be cached as `{.payload_type}`.
|
88
|
+
# Override this hook to customize return type generation.
|
89
|
+
def generate_payload_type
|
90
|
+
resolver_name = graphql_name
|
91
|
+
resolver_fields = all_field_definitions
|
92
|
+
Class.new(object_class) do
|
93
|
+
graphql_name("#{resolver_name}Payload")
|
94
|
+
description("Autogenerated return type of #{resolver_name}.")
|
95
|
+
resolver_fields.each do |f|
|
96
|
+
# Reattach the already-defined field here
|
97
|
+
# (The field's `.owner` will still point to the mutation, not the object type, I think)
|
98
|
+
# Don't re-warn about a method conflict. Since this type is generated, it should be fixed in the resolver instead.
|
99
|
+
add_field(f, method_conflict_warning: false)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,402 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "graphql/schema/resolver/has_payload_type"
|
3
|
+
|
4
|
+
module GraphQL
|
5
|
+
class Schema
|
6
|
+
# A class-based container for field configuration and resolution logic. It supports:
|
7
|
+
#
|
8
|
+
# - Arguments, via `.argument(...)` helper, which will be applied to the field.
|
9
|
+
# - Return type, via `.type(..., null: ...)`, which will be applied to the field.
|
10
|
+
# - Description, via `.description(...)`, which will be applied to the field
|
11
|
+
# - Resolution, via `#resolve(**args)` method, which will be called to resolve the field.
|
12
|
+
# - `#object` and `#context` accessors for use during `#resolve`.
|
13
|
+
#
|
14
|
+
# Resolvers can be attached with the `resolver:` option in a `field(...)` call.
|
15
|
+
#
|
16
|
+
# A resolver's configuration may be overridden with other keywords in the `field(...)` call.
|
17
|
+
#
|
18
|
+
# @see {GraphQL::Schema::Mutation} for a concrete subclass of `Resolver`.
|
19
|
+
# @see {GraphQL::Function} `Resolver` is a replacement for `GraphQL::Function`
|
20
|
+
class Resolver
|
21
|
+
include Schema::Member::GraphQLTypeNames
|
22
|
+
# Really we only need description from here, but:
|
23
|
+
extend Schema::Member::BaseDSLMethods
|
24
|
+
extend GraphQL::Schema::Member::HasArguments
|
25
|
+
extend GraphQL::Schema::Member::HasValidators
|
26
|
+
include Schema::Member::HasPath
|
27
|
+
extend Schema::Member::HasPath
|
28
|
+
|
29
|
+
# @param object [Object] The application object that this field is being resolved on
|
30
|
+
# @param context [GraphQL::Query::Context]
|
31
|
+
# @param field [GraphQL::Schema::Field]
|
32
|
+
def initialize(object:, context:, field:)
|
33
|
+
@object = object
|
34
|
+
@context = context
|
35
|
+
@field = field
|
36
|
+
# Since this hash is constantly rebuilt, cache it for this call
|
37
|
+
@arguments_by_keyword = {}
|
38
|
+
self.class.arguments(context).each do |name, arg|
|
39
|
+
@arguments_by_keyword[arg.keyword] = arg
|
40
|
+
end
|
41
|
+
@prepared_arguments = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Object] The application object this field is being resolved on
|
45
|
+
attr_reader :object
|
46
|
+
|
47
|
+
# @return [GraphQL::Query::Context]
|
48
|
+
attr_reader :context
|
49
|
+
|
50
|
+
# @return [GraphQL::Dataloader]
|
51
|
+
def dataloader
|
52
|
+
context.dataloader
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [GraphQL::Schema::Field]
|
56
|
+
attr_reader :field
|
57
|
+
|
58
|
+
def arguments
|
59
|
+
@prepared_arguments || raise("Arguments have not been prepared yet, still waiting for #load_arguments to resolve. (Call `.arguments` later in the code.)")
|
60
|
+
end
|
61
|
+
|
62
|
+
# This method is _actually_ called by the runtime,
|
63
|
+
# it does some preparation and then eventually calls
|
64
|
+
# the user-defined `#resolve` method.
|
65
|
+
# @api private
|
66
|
+
def resolve_with_support(**args)
|
67
|
+
# First call the ready? hook which may raise
|
68
|
+
ready_val = if args.any?
|
69
|
+
ready?(**args)
|
70
|
+
else
|
71
|
+
ready?
|
72
|
+
end
|
73
|
+
context.schema.after_lazy(ready_val) do |is_ready, ready_early_return|
|
74
|
+
if ready_early_return
|
75
|
+
if is_ready != false
|
76
|
+
raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{is_ready.inspect}, #{ready_early_return.inspect}]"
|
77
|
+
else
|
78
|
+
ready_early_return
|
79
|
+
end
|
80
|
+
elsif is_ready
|
81
|
+
# Then call each prepare hook, which may return a different value
|
82
|
+
# for that argument, or may return a lazy object
|
83
|
+
load_arguments_val = load_arguments(args)
|
84
|
+
context.schema.after_lazy(load_arguments_val) do |loaded_args|
|
85
|
+
@prepared_arguments = loaded_args
|
86
|
+
Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
|
87
|
+
# Then call `authorized?`, which may raise or may return a lazy object
|
88
|
+
authorized_val = if loaded_args.any?
|
89
|
+
authorized?(**loaded_args)
|
90
|
+
else
|
91
|
+
authorized?
|
92
|
+
end
|
93
|
+
context.schema.after_lazy(authorized_val) do |(authorized_result, early_return)|
|
94
|
+
# If the `authorized?` returned two values, `false, early_return`,
|
95
|
+
# then use the early return value instead of continuing
|
96
|
+
if early_return
|
97
|
+
if authorized_result == false
|
98
|
+
early_return
|
99
|
+
else
|
100
|
+
raise "Unexpected result from #authorized? (expected `true`, `false` or `[false, {...}]`): [#{authorized_result.inspect}, #{early_return.inspect}]"
|
101
|
+
end
|
102
|
+
elsif authorized_result
|
103
|
+
# Finally, all the hooks have passed, so resolve it
|
104
|
+
if loaded_args.any?
|
105
|
+
public_send(self.class.resolve_method, **loaded_args)
|
106
|
+
else
|
107
|
+
public_send(self.class.resolve_method)
|
108
|
+
end
|
109
|
+
else
|
110
|
+
raise GraphQL::UnauthorizedFieldError.new(context: context, object: object, type: field.owner, field: field)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Do the work. Everything happens here.
|
119
|
+
# @return [Object] An object corresponding to the return type
|
120
|
+
def resolve(**args)
|
121
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.class.name}#resolve should execute the field's logic"
|
122
|
+
end
|
123
|
+
|
124
|
+
# Called before arguments are prepared.
|
125
|
+
# Implement this hook to make checks before doing any work.
|
126
|
+
#
|
127
|
+
# If it returns a lazy object (like a promise), it will be synced by GraphQL
|
128
|
+
# (but the resulting value won't be used).
|
129
|
+
#
|
130
|
+
# @param args [Hash] The input arguments, if there are any
|
131
|
+
# @raise [GraphQL::ExecutionError] To add an error to the response
|
132
|
+
# @raise [GraphQL::UnauthorizedError] To signal an authorization failure
|
133
|
+
# @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
|
134
|
+
def ready?(**args)
|
135
|
+
true
|
136
|
+
end
|
137
|
+
|
138
|
+
# Called after arguments are loaded, but before resolving.
|
139
|
+
#
|
140
|
+
# Override it to check everything before calling the mutation.
|
141
|
+
# @param inputs [Hash] The input arguments
|
142
|
+
# @raise [GraphQL::ExecutionError] To add an error to the response
|
143
|
+
# @raise [GraphQL::UnauthorizedError] To signal an authorization failure
|
144
|
+
# @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
|
145
|
+
def authorized?(**inputs)
|
146
|
+
arg_owner = @field # || self.class
|
147
|
+
args = arg_owner.arguments(context)
|
148
|
+
authorize_arguments(args, inputs)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Called when an object loaded by `loads:` fails the `.authorized?` check for its resolved GraphQL object type.
|
152
|
+
#
|
153
|
+
# By default, the error is re-raised and passed along to {{Schema.unauthorized_object}}.
|
154
|
+
#
|
155
|
+
# Any value returned here will be used _instead of_ of the loaded object.
|
156
|
+
# @param err [GraphQL::UnauthorizedError]
|
157
|
+
def unauthorized_object(err)
|
158
|
+
raise err
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
def authorize_arguments(args, inputs)
|
164
|
+
args.each_value do |argument|
|
165
|
+
arg_keyword = argument.keyword
|
166
|
+
if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
|
167
|
+
arg_auth, err = argument.authorized?(self, arg_value, context)
|
168
|
+
if !arg_auth
|
169
|
+
return arg_auth, err
|
170
|
+
else
|
171
|
+
true
|
172
|
+
end
|
173
|
+
else
|
174
|
+
true
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def load_arguments(args)
|
180
|
+
prepared_args = {}
|
181
|
+
prepare_lazies = []
|
182
|
+
|
183
|
+
args.each do |key, value|
|
184
|
+
arg_defn = @arguments_by_keyword[key]
|
185
|
+
if arg_defn
|
186
|
+
prepped_value = prepared_args[key] = arg_defn.load_and_authorize_value(self, value, context)
|
187
|
+
if context.schema.lazy?(prepped_value)
|
188
|
+
prepare_lazies << context.schema.after_lazy(prepped_value) do |finished_prepped_value|
|
189
|
+
prepared_args[key] = finished_prepped_value
|
190
|
+
end
|
191
|
+
end
|
192
|
+
else
|
193
|
+
# these are `extras:`
|
194
|
+
prepared_args[key] = value
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Avoid returning a lazy if none are needed
|
199
|
+
if prepare_lazies.any?
|
200
|
+
GraphQL::Execution::Lazy.all(prepare_lazies).then { prepared_args }
|
201
|
+
else
|
202
|
+
prepared_args
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def get_argument(name, context = GraphQL::Query::NullContext)
|
207
|
+
self.class.get_argument(name, context)
|
208
|
+
end
|
209
|
+
|
210
|
+
class << self
|
211
|
+
def field_arguments(context = GraphQL::Query::NullContext)
|
212
|
+
arguments(context)
|
213
|
+
end
|
214
|
+
|
215
|
+
def get_field_argument(name, context = GraphQL::Query::NullContext)
|
216
|
+
get_argument(name, context)
|
217
|
+
end
|
218
|
+
|
219
|
+
def all_field_argument_definitions
|
220
|
+
all_argument_definitions
|
221
|
+
end
|
222
|
+
|
223
|
+
# Default `:resolve` set below.
|
224
|
+
# @return [Symbol] The method to call on instances of this object to resolve the field
|
225
|
+
def resolve_method(new_method = nil)
|
226
|
+
if new_method
|
227
|
+
@resolve_method = new_method
|
228
|
+
end
|
229
|
+
@resolve_method || (superclass.respond_to?(:resolve_method) ? superclass.resolve_method : :resolve)
|
230
|
+
end
|
231
|
+
|
232
|
+
# Additional info injected into {#resolve}
|
233
|
+
# @see {GraphQL::Schema::Field#extras}
|
234
|
+
def extras(new_extras = nil)
|
235
|
+
if new_extras
|
236
|
+
@own_extras = new_extras
|
237
|
+
end
|
238
|
+
own_extras = @own_extras || []
|
239
|
+
own_extras + (superclass.respond_to?(:extras) ? superclass.extras : [])
|
240
|
+
end
|
241
|
+
|
242
|
+
# If `true` (default), then the return type for this resolver will be nullable.
|
243
|
+
# If `false`, then the return type is non-null.
|
244
|
+
#
|
245
|
+
# @see #type which sets the return type of this field and accepts a `null:` option
|
246
|
+
# @param allow_null [Boolean] Whether or not the response can be null
|
247
|
+
def null(allow_null = nil)
|
248
|
+
if !allow_null.nil?
|
249
|
+
@null = allow_null
|
250
|
+
end
|
251
|
+
|
252
|
+
@null.nil? ? (superclass.respond_to?(:null) ? superclass.null : true) : @null
|
253
|
+
end
|
254
|
+
|
255
|
+
def resolver_method(new_method_name = nil)
|
256
|
+
if new_method_name
|
257
|
+
@resolver_method = new_method_name
|
258
|
+
else
|
259
|
+
@resolver_method || :resolve_with_support
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# Call this method to get the return type of the field,
|
264
|
+
# or use it as a configuration method to assign a return type
|
265
|
+
# instead of generating one.
|
266
|
+
# TODO unify with {#null}
|
267
|
+
# @param new_type [Class, Array<Class>, nil] If a type definition class is provided, it will be used as the return type of the field
|
268
|
+
# @param null [true, false] Whether or not the field may return `nil`
|
269
|
+
# @return [Class] The type which this field returns.
|
270
|
+
def type(new_type = nil, null: nil)
|
271
|
+
if new_type
|
272
|
+
if null.nil?
|
273
|
+
raise ArgumentError, "required argument `null:` is missing"
|
274
|
+
end
|
275
|
+
@type_expr = new_type
|
276
|
+
@null = null
|
277
|
+
else
|
278
|
+
if type_expr
|
279
|
+
GraphQL::Schema::Member::BuildType.parse_type(type_expr, null: self.null)
|
280
|
+
elsif superclass.respond_to?(:type)
|
281
|
+
superclass.type
|
282
|
+
else
|
283
|
+
nil
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
# Specifies the complexity of the field. Defaults to `1`
|
289
|
+
# @return [Integer, Proc]
|
290
|
+
def complexity(new_complexity = nil)
|
291
|
+
if new_complexity
|
292
|
+
@complexity = new_complexity
|
293
|
+
end
|
294
|
+
@complexity || (superclass.respond_to?(:complexity) ? superclass.complexity : 1)
|
295
|
+
end
|
296
|
+
|
297
|
+
def broadcastable(new_broadcastable)
|
298
|
+
@broadcastable = new_broadcastable
|
299
|
+
end
|
300
|
+
|
301
|
+
# @return [Boolean, nil]
|
302
|
+
def broadcastable?
|
303
|
+
if defined?(@broadcastable)
|
304
|
+
@broadcastable
|
305
|
+
else
|
306
|
+
(superclass.respond_to?(:broadcastable?) ? superclass.broadcastable? : nil)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
# Get or set the `max_page_size:` which will be configured for fields using this resolver
|
311
|
+
# (`nil` means "unlimited max page size".)
|
312
|
+
# @param max_page_size [Integer, nil] Set a new value
|
313
|
+
# @return [Integer, nil] The `max_page_size` assigned to fields that use this resolver
|
314
|
+
def max_page_size(new_max_page_size = :not_given)
|
315
|
+
if new_max_page_size != :not_given
|
316
|
+
@max_page_size = new_max_page_size
|
317
|
+
elsif defined?(@max_page_size)
|
318
|
+
@max_page_size
|
319
|
+
elsif superclass.respond_to?(:max_page_size)
|
320
|
+
superclass.max_page_size
|
321
|
+
else
|
322
|
+
nil
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
# @return [Boolean] `true` if this resolver or a superclass has an assigned `max_page_size`
|
327
|
+
def has_max_page_size?
|
328
|
+
(!!defined?(@max_page_size)) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
|
329
|
+
end
|
330
|
+
|
331
|
+
# Get or set the `default_page_size:` which will be configured for fields using this resolver
|
332
|
+
# (`nil` means "unlimited default page size".)
|
333
|
+
# @param default_page_size [Integer, nil] Set a new value
|
334
|
+
# @return [Integer, nil] The `default_page_size` assigned to fields that use this resolver
|
335
|
+
def default_page_size(new_default_page_size = :not_given)
|
336
|
+
if new_default_page_size != :not_given
|
337
|
+
@default_page_size = new_default_page_size
|
338
|
+
elsif defined?(@default_page_size)
|
339
|
+
@default_page_size
|
340
|
+
elsif superclass.respond_to?(:default_page_size)
|
341
|
+
superclass.default_page_size
|
342
|
+
else
|
343
|
+
nil
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
# @return [Boolean] `true` if this resolver or a superclass has an assigned `default_page_size`
|
348
|
+
def has_default_page_size?
|
349
|
+
(!!defined?(@default_page_size)) || (superclass.respond_to?(:has_default_page_size?) && superclass.has_default_page_size?)
|
350
|
+
end
|
351
|
+
|
352
|
+
# A non-normalized type configuration, without `null` applied
|
353
|
+
def type_expr
|
354
|
+
@type_expr || (superclass.respond_to?(:type_expr) ? superclass.type_expr : nil)
|
355
|
+
end
|
356
|
+
|
357
|
+
# Add an argument to this field's signature, but
|
358
|
+
# also add some preparation hook methods which will be used for this argument
|
359
|
+
# @see {GraphQL::Schema::Argument#initialize} for the signature
|
360
|
+
def argument(*args, **kwargs, &block)
|
361
|
+
# Use `from_resolver: true` to short-circuit the InputObject's own `loads:` implementation
|
362
|
+
# so that we can support `#load_{x}` methods below.
|
363
|
+
super(*args, from_resolver: true, **kwargs)
|
364
|
+
end
|
365
|
+
|
366
|
+
# Registers new extension
|
367
|
+
# @param extension [Class] Extension class
|
368
|
+
# @param options [Hash] Optional extension options
|
369
|
+
def extension(extension, **options)
|
370
|
+
@own_extensions ||= []
|
371
|
+
@own_extensions << {extension => options}
|
372
|
+
end
|
373
|
+
|
374
|
+
# @api private
|
375
|
+
def extensions
|
376
|
+
own_exts = @own_extensions
|
377
|
+
# Jump through some hoops to avoid creating arrays when we don't actually need them
|
378
|
+
if superclass.respond_to?(:extensions)
|
379
|
+
s_exts = superclass.extensions
|
380
|
+
if own_exts
|
381
|
+
if s_exts.any?
|
382
|
+
own_exts + s_exts
|
383
|
+
else
|
384
|
+
own_exts
|
385
|
+
end
|
386
|
+
else
|
387
|
+
s_exts
|
388
|
+
end
|
389
|
+
else
|
390
|
+
own_exts || EMPTY_ARRAY
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
private
|
395
|
+
|
396
|
+
def own_extensions
|
397
|
+
@own_extensions
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|