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
data/lib/graphql/schema.rb
CHANGED
@@ -1,127 +1,1202 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "graphql/schema/addition"
|
3
|
+
require "graphql/schema/base_64_encoder"
|
4
|
+
require "graphql/schema/find_inherited_value"
|
5
|
+
require "graphql/schema/finder"
|
2
6
|
require "graphql/schema/invalid_type_error"
|
3
|
-
require "graphql/schema/
|
4
|
-
require "graphql/schema/
|
5
|
-
require "graphql/schema/
|
6
|
-
require "graphql/schema/
|
7
|
-
require "graphql/schema/timeout_middleware"
|
7
|
+
require "graphql/schema/introspection_system"
|
8
|
+
require "graphql/schema/late_bound_type"
|
9
|
+
require "graphql/schema/null_mask"
|
10
|
+
require "graphql/schema/timeout"
|
8
11
|
require "graphql/schema/type_expression"
|
9
|
-
require "graphql/schema/
|
10
|
-
require "graphql/schema/
|
12
|
+
require "graphql/schema/unique_within_type"
|
13
|
+
require "graphql/schema/warden"
|
14
|
+
require "graphql/schema/build_from_definition"
|
15
|
+
|
16
|
+
require "graphql/schema/validator"
|
17
|
+
require "graphql/schema/member"
|
18
|
+
require "graphql/schema/wrapper"
|
19
|
+
require "graphql/schema/list"
|
20
|
+
require "graphql/schema/non_null"
|
21
|
+
require "graphql/schema/argument"
|
22
|
+
require "graphql/schema/enum_value"
|
23
|
+
require "graphql/schema/enum"
|
24
|
+
require "graphql/schema/field_extension"
|
25
|
+
require "graphql/schema/field"
|
26
|
+
require "graphql/schema/input_object"
|
27
|
+
require "graphql/schema/interface"
|
28
|
+
require "graphql/schema/scalar"
|
29
|
+
require "graphql/schema/object"
|
30
|
+
require "graphql/schema/union"
|
31
|
+
require "graphql/schema/directive"
|
32
|
+
require "graphql/schema/directive/deprecated"
|
33
|
+
require "graphql/schema/directive/include"
|
34
|
+
require "graphql/schema/directive/one_of"
|
35
|
+
require "graphql/schema/directive/skip"
|
36
|
+
require "graphql/schema/directive/feature"
|
37
|
+
require "graphql/schema/directive/flagged"
|
38
|
+
require "graphql/schema/directive/transform"
|
39
|
+
require "graphql/schema/type_membership"
|
40
|
+
|
41
|
+
require "graphql/schema/resolver"
|
42
|
+
require "graphql/schema/mutation"
|
43
|
+
require "graphql/schema/relay_classic_mutation"
|
44
|
+
require "graphql/schema/subscription"
|
11
45
|
|
12
46
|
module GraphQL
|
13
47
|
# A GraphQL schema which may be queried with {GraphQL::Query}.
|
48
|
+
#
|
49
|
+
# The {Schema} contains:
|
50
|
+
#
|
51
|
+
# - types for exposing your application
|
52
|
+
# - query analyzers for assessing incoming queries (including max depth & max complexity restrictions)
|
53
|
+
# - execution strategies for running incoming queries
|
54
|
+
#
|
55
|
+
# Schemas start with root types, {Schema#query}, {Schema#mutation} and {Schema#subscription}.
|
56
|
+
# The schema will traverse the tree of fields & types, using those as starting points.
|
57
|
+
# Any undiscoverable types may be provided with the `types` configuration.
|
58
|
+
#
|
59
|
+
# Schemas can restrict large incoming queries with `max_depth` and `max_complexity` configurations.
|
60
|
+
# (These configurations can be overridden by specific calls to {Schema#execute})
|
61
|
+
#
|
62
|
+
# Schemas can specify how queries should be executed against them.
|
63
|
+
# `query_execution_strategy`, `mutation_execution_strategy` and `subscription_execution_strategy`
|
64
|
+
# each apply to corresponding root types.
|
65
|
+
# #
|
66
|
+
# @example defining a schema
|
67
|
+
# class MySchema < GraphQL::Schema
|
68
|
+
# query QueryType
|
69
|
+
# # If types are only connected by way of interfaces, they must be added here
|
70
|
+
# orphan_types ImageType, AudioType
|
71
|
+
# end
|
72
|
+
#
|
14
73
|
class Schema
|
15
|
-
extend
|
16
|
-
|
17
|
-
DIRECTIVES = [GraphQL::Directive::SkipDirective, GraphQL::Directive::IncludeDirective]
|
18
|
-
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
|
19
|
-
|
20
|
-
attr_reader :query, :mutation, :subscription, :directives, :static_validator, :query_analyzers
|
21
|
-
attr_accessor :max_depth
|
22
|
-
attr_accessor :max_complexity
|
23
|
-
|
24
|
-
# Override these if you don't want the default executor:
|
25
|
-
attr_accessor :query_execution_strategy,
|
26
|
-
:mutation_execution_strategy,
|
27
|
-
:subscription_execution_strategy
|
28
|
-
|
29
|
-
# @return [Array<#call>] Middlewares suitable for MiddlewareChain, applied to fields during execution
|
30
|
-
attr_reader :middleware
|
31
|
-
|
32
|
-
# @param query [GraphQL::ObjectType] the query root for the schema
|
33
|
-
# @param mutation [GraphQL::ObjectType] the mutation root for the schema
|
34
|
-
# @param subscription [GraphQL::ObjectType] the subscription root for the schema
|
35
|
-
# @param max_depth [Integer] maximum query nesting (if it's greater, raise an error)
|
36
|
-
# @param types [Array<GraphQL::BaseType>] additional types to include in this schema
|
37
|
-
def initialize(query:, mutation: nil, subscription: nil, max_depth: nil, max_complexity: nil, types: [])
|
38
|
-
@query = query
|
39
|
-
@mutation = mutation
|
40
|
-
@subscription = subscription
|
41
|
-
@max_depth = max_depth
|
42
|
-
@max_complexity = max_complexity
|
43
|
-
@orphan_types = types
|
44
|
-
@directives = DIRECTIVES.reduce({}) { |m, d| m[d.name] = d; m }
|
45
|
-
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
46
|
-
@rescue_middleware = GraphQL::Schema::RescueMiddleware.new
|
47
|
-
@middleware = [@rescue_middleware]
|
48
|
-
@query_analyzers = []
|
49
|
-
# Default to the built-in execution strategy:
|
50
|
-
self.query_execution_strategy = GraphQL::Query::SerialExecution
|
51
|
-
self.mutation_execution_strategy = GraphQL::Query::SerialExecution
|
52
|
-
self.subscription_execution_strategy = GraphQL::Query::SerialExecution
|
53
|
-
end
|
54
|
-
|
55
|
-
def_delegators :@rescue_middleware, :rescue_from, :remove_handler
|
74
|
+
extend GraphQL::Schema::Member::HasAstNode
|
75
|
+
extend GraphQL::Schema::FindInheritedValue
|
56
76
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
77
|
+
class DuplicateNamesError < GraphQL::Error
|
78
|
+
attr_reader :duplicated_name
|
79
|
+
def initialize(duplicated_name:, duplicated_definition_1:, duplicated_definition_2:)
|
80
|
+
@duplicated_name = duplicated_name
|
81
|
+
super(
|
82
|
+
"Found two visible definitions for `#{duplicated_name}`: #{duplicated_definition_1}, #{duplicated_definition_2}"
|
83
|
+
)
|
62
84
|
end
|
63
85
|
end
|
64
86
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
87
|
+
class UnresolvedLateBoundTypeError < GraphQL::Error
|
88
|
+
attr_reader :type
|
89
|
+
def initialize(type:)
|
90
|
+
@type = type
|
91
|
+
super("Late bound type was never found: #{type.inspect}")
|
92
|
+
end
|
71
93
|
end
|
72
94
|
|
73
|
-
#
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
95
|
+
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
96
|
+
class InvalidDocumentError < Error; end;
|
97
|
+
|
98
|
+
class << self
|
99
|
+
# Create schema with the result of an introspection query.
|
100
|
+
# @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
|
101
|
+
# @return [Class<GraphQL::Schema>] the schema described by `input`
|
102
|
+
def from_introspection(introspection_result)
|
103
|
+
GraphQL::Schema::Loader.load(introspection_result)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Create schema from an IDL schema or file containing an IDL definition.
|
107
|
+
# @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
|
108
|
+
# @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
|
109
|
+
# @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
|
110
|
+
# @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
|
111
|
+
# @return [Class] the schema described by `document`
|
112
|
+
def from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
|
113
|
+
# If the file ends in `.graphql` or `.graphqls`, treat it like a filepath
|
114
|
+
if definition_or_path.end_with?(".graphql") || definition_or_path.end_with?(".graphqls")
|
115
|
+
GraphQL::Schema::BuildFromDefinition.from_definition_path(
|
116
|
+
self,
|
117
|
+
definition_or_path,
|
118
|
+
default_resolve: default_resolve,
|
119
|
+
parser: parser,
|
120
|
+
using: using,
|
121
|
+
)
|
122
|
+
else
|
123
|
+
GraphQL::Schema::BuildFromDefinition.from_definition(
|
124
|
+
self,
|
125
|
+
definition_or_path,
|
126
|
+
default_resolve: default_resolve,
|
127
|
+
parser: parser,
|
128
|
+
using: using,
|
129
|
+
)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def deprecated_graphql_definition
|
134
|
+
graphql_definition(silence_deprecation_warning: true)
|
135
|
+
end
|
136
|
+
|
137
|
+
# @return [GraphQL::Subscriptions]
|
138
|
+
def subscriptions(inherited: true)
|
139
|
+
defined?(@subscriptions) ? @subscriptions : (inherited ? find_inherited_value(:subscriptions, nil) : nil)
|
140
|
+
end
|
141
|
+
|
142
|
+
def subscriptions=(new_implementation)
|
143
|
+
@subscriptions = new_implementation
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
147
|
+
# @see {#as_json}
|
148
|
+
# @return [String]
|
149
|
+
def to_json(**args)
|
150
|
+
JSON.pretty_generate(as_json(**args))
|
151
|
+
end
|
152
|
+
|
153
|
+
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
154
|
+
# @param context [Hash]
|
155
|
+
# @param only [<#call(member, ctx)>]
|
156
|
+
# @param except [<#call(member, ctx)>]
|
157
|
+
# @return [Hash] GraphQL result
|
158
|
+
def as_json(only: nil, except: nil, context: {})
|
159
|
+
execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
|
160
|
+
end
|
161
|
+
|
162
|
+
# Return the GraphQL IDL for the schema
|
163
|
+
# @param context [Hash]
|
164
|
+
# @param only [<#call(member, ctx)>]
|
165
|
+
# @param except [<#call(member, ctx)>]
|
166
|
+
# @return [String]
|
167
|
+
def to_definition(only: nil, except: nil, context: {})
|
168
|
+
GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
|
169
|
+
end
|
170
|
+
|
171
|
+
# Return the GraphQL::Language::Document IDL AST for the schema
|
172
|
+
# @return [GraphQL::Language::Document]
|
173
|
+
def to_document
|
174
|
+
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
175
|
+
end
|
176
|
+
|
177
|
+
# @return [String, nil]
|
178
|
+
def description(new_description = nil)
|
179
|
+
if new_description
|
180
|
+
@description = new_description
|
181
|
+
elsif defined?(@description)
|
182
|
+
@description
|
183
|
+
else
|
184
|
+
find_inherited_value(:description, nil)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def find(path)
|
189
|
+
if !@finder
|
190
|
+
@find_cache = {}
|
191
|
+
@finder ||= GraphQL::Schema::Finder.new(self)
|
192
|
+
end
|
193
|
+
@find_cache[path] ||= @finder.find(path)
|
194
|
+
end
|
195
|
+
|
196
|
+
def default_filter
|
197
|
+
GraphQL::Filter.new(except: default_mask)
|
198
|
+
end
|
199
|
+
|
200
|
+
def default_mask(new_mask = nil)
|
201
|
+
if new_mask
|
202
|
+
@own_default_mask = new_mask
|
203
|
+
else
|
204
|
+
@own_default_mask || find_inherited_value(:default_mask, Schema::NullMask)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def static_validator
|
209
|
+
GraphQL::StaticValidation::Validator.new(schema: self)
|
210
|
+
end
|
211
|
+
|
212
|
+
def use(plugin, **kwargs)
|
213
|
+
if kwargs.any?
|
214
|
+
plugin.use(self, **kwargs)
|
215
|
+
else
|
216
|
+
plugin.use(self)
|
217
|
+
end
|
218
|
+
own_plugins << [plugin, kwargs]
|
219
|
+
end
|
220
|
+
|
221
|
+
def plugins
|
222
|
+
find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
|
223
|
+
end
|
224
|
+
|
225
|
+
# Build a map of `{ name => type }` and return it
|
226
|
+
# @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
|
227
|
+
# @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
|
228
|
+
def types(context = GraphQL::Query::NullContext)
|
229
|
+
all_types = non_introspection_types.merge(introspection_system.types)
|
230
|
+
visible_types = {}
|
231
|
+
all_types.each do |k, v|
|
232
|
+
visible_types[k] =if v.is_a?(Array)
|
233
|
+
visible_t = nil
|
234
|
+
v.each do |t|
|
235
|
+
if t.visible?(context)
|
236
|
+
if visible_t.nil?
|
237
|
+
visible_t = t
|
238
|
+
else
|
239
|
+
raise DuplicateNamesError.new(
|
240
|
+
duplicated_name: k, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
241
|
+
)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
visible_t
|
246
|
+
else
|
247
|
+
v
|
248
|
+
end
|
249
|
+
end
|
250
|
+
visible_types
|
251
|
+
end
|
252
|
+
|
253
|
+
# @param type_name [String]
|
254
|
+
# @return [Module, nil] A type, or nil if there's no type called `type_name`
|
255
|
+
def get_type(type_name, context = GraphQL::Query::NullContext)
|
256
|
+
local_entry = own_types[type_name]
|
257
|
+
type_defn = case local_entry
|
258
|
+
when nil
|
259
|
+
nil
|
260
|
+
when Array
|
261
|
+
visible_t = nil
|
262
|
+
warden = Warden.from_context(context)
|
263
|
+
local_entry.each do |t|
|
264
|
+
if warden.visible_type?(t, context)
|
265
|
+
if visible_t.nil?
|
266
|
+
visible_t = t
|
267
|
+
else
|
268
|
+
raise DuplicateNamesError.new(
|
269
|
+
duplicated_name: type_name, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
270
|
+
)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
visible_t
|
275
|
+
when Module
|
276
|
+
local_entry
|
277
|
+
else
|
278
|
+
raise "Invariant: unexpected own_types[#{type_name.inspect}]: #{local_entry.inspect}"
|
279
|
+
end
|
280
|
+
|
281
|
+
type_defn ||
|
282
|
+
introspection_system.types[type_name] || # todo context-specific introspection?
|
283
|
+
(superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
|
284
|
+
end
|
285
|
+
|
286
|
+
# @api private
|
287
|
+
attr_writer :connections
|
288
|
+
|
289
|
+
# @return [GraphQL::Pagination::Connections] if installed
|
290
|
+
def connections
|
291
|
+
if defined?(@connections)
|
292
|
+
@connections
|
293
|
+
else
|
294
|
+
inherited_connections = find_inherited_value(:connections, nil)
|
295
|
+
# This schema is part of an inheritance chain which is using new connections,
|
296
|
+
# make a new instance, so we don't pollute the upstream one.
|
297
|
+
if inherited_connections
|
298
|
+
@connections = Pagination::Connections.new(schema: self)
|
299
|
+
else
|
300
|
+
nil
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def new_connections?
|
306
|
+
!!connections
|
307
|
+
end
|
308
|
+
|
309
|
+
def query(new_query_object = nil)
|
310
|
+
if new_query_object
|
311
|
+
if @query_object
|
312
|
+
raise GraphQL::Error, "Second definition of `query(...)` (#{new_query_object.inspect}) is invalid, already configured with #{@query_object.inspect}"
|
313
|
+
else
|
314
|
+
@query_object = new_query_object
|
315
|
+
add_type_and_traverse(new_query_object, root: true)
|
316
|
+
nil
|
317
|
+
end
|
318
|
+
else
|
319
|
+
@query_object || find_inherited_value(:query)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def mutation(new_mutation_object = nil)
|
324
|
+
if new_mutation_object
|
325
|
+
if @mutation_object
|
326
|
+
raise GraphQL::Error, "Second definition of `mutation(...)` (#{new_mutation_object.inspect}) is invalid, already configured with #{@mutation_object.inspect}"
|
327
|
+
else
|
328
|
+
@mutation_object = new_mutation_object
|
329
|
+
add_type_and_traverse(new_mutation_object, root: true)
|
330
|
+
nil
|
331
|
+
end
|
332
|
+
else
|
333
|
+
@mutation_object || find_inherited_value(:mutation)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def subscription(new_subscription_object = nil)
|
338
|
+
if new_subscription_object
|
339
|
+
if @subscription_object
|
340
|
+
raise GraphQL::Error, "Second definition of `subscription(...)` (#{new_subscription_object.inspect}) is invalid, already configured with #{@subscription_object.inspect}"
|
341
|
+
else
|
342
|
+
@subscription_object = new_subscription_object
|
343
|
+
add_subscription_extension_if_necessary
|
344
|
+
add_type_and_traverse(new_subscription_object, root: true)
|
345
|
+
nil
|
346
|
+
end
|
347
|
+
else
|
348
|
+
@subscription_object || find_inherited_value(:subscription)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
# @see [GraphQL::Schema::Warden] Restricted access to root types
|
353
|
+
# @return [GraphQL::ObjectType, nil]
|
354
|
+
def root_type_for_operation(operation)
|
355
|
+
case operation
|
356
|
+
when "query"
|
357
|
+
query
|
358
|
+
when "mutation"
|
359
|
+
mutation
|
360
|
+
when "subscription"
|
361
|
+
subscription
|
362
|
+
else
|
363
|
+
raise ArgumentError, "unknown operation type: #{operation}"
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
def root_types
|
368
|
+
@root_types
|
369
|
+
end
|
370
|
+
|
371
|
+
# @param type [Module] The type definition whose possible types you want to see
|
372
|
+
# @return [Hash<String, Module>] All possible types, if no `type` is given.
|
373
|
+
# @return [Array<Module>] Possible types for `type`, if it's given.
|
374
|
+
def possible_types(type = nil, context = GraphQL::Query::NullContext)
|
375
|
+
if type
|
376
|
+
# TODO duck-typing `.possible_types` would probably be nicer here
|
377
|
+
if type.kind.union?
|
378
|
+
type.possible_types(context: context)
|
379
|
+
else
|
380
|
+
stored_possible_types = own_possible_types[type.graphql_name]
|
381
|
+
visible_possible_types = if stored_possible_types && type.kind.interface?
|
382
|
+
stored_possible_types.select do |possible_type|
|
383
|
+
possible_type.interfaces(context).include?(type)
|
384
|
+
end
|
385
|
+
else
|
386
|
+
stored_possible_types
|
387
|
+
end
|
388
|
+
visible_possible_types ||
|
389
|
+
introspection_system.possible_types[type.graphql_name] ||
|
390
|
+
(
|
391
|
+
superclass.respond_to?(:possible_types) ?
|
392
|
+
superclass.possible_types(type, context) :
|
393
|
+
EMPTY_ARRAY
|
394
|
+
)
|
395
|
+
end
|
396
|
+
else
|
397
|
+
find_inherited_value(:possible_types, EMPTY_HASH)
|
398
|
+
.merge(own_possible_types)
|
399
|
+
.merge(introspection_system.possible_types)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
def union_memberships(type = nil)
|
404
|
+
if type
|
405
|
+
own_um = own_union_memberships.fetch(type.graphql_name, EMPTY_ARRAY)
|
406
|
+
inherited_um = find_inherited_value(:union_memberships, EMPTY_HASH).fetch(type.graphql_name, EMPTY_ARRAY)
|
407
|
+
own_um + inherited_um
|
408
|
+
else
|
409
|
+
joined_um = own_union_memberships.dup
|
410
|
+
find_inherited_value(:union_memberhips, EMPTY_HASH).each do |k, v|
|
411
|
+
um = joined_um[k] ||= []
|
412
|
+
um.concat(v)
|
413
|
+
end
|
414
|
+
joined_um
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
# @api private
|
419
|
+
# @see GraphQL::Dataloader
|
420
|
+
def dataloader_class
|
421
|
+
@dataloader_class || GraphQL::Dataloader::NullDataloader
|
422
|
+
end
|
423
|
+
|
424
|
+
attr_writer :dataloader_class
|
425
|
+
|
426
|
+
def references_to(to_type = nil, from: nil)
|
427
|
+
@own_references_to ||= Hash.new { |h, k| h[k] = [] }
|
428
|
+
if to_type
|
429
|
+
if !to_type.is_a?(String)
|
430
|
+
to_type = to_type.graphql_name
|
431
|
+
end
|
432
|
+
|
433
|
+
if from
|
434
|
+
@own_references_to[to_type] << from
|
435
|
+
else
|
436
|
+
own_refs = @own_references_to[to_type]
|
437
|
+
inherited_refs = find_inherited_value(:references_to, EMPTY_HASH)[to_type] || EMPTY_ARRAY
|
438
|
+
own_refs + inherited_refs
|
439
|
+
end
|
440
|
+
else
|
441
|
+
# `@own_references_to` can be quite large for big schemas,
|
442
|
+
# and generally speaking, we won't inherit any values.
|
443
|
+
# So optimize the most common case -- don't create a duplicate Hash.
|
444
|
+
inherited_value = find_inherited_value(:references_to, EMPTY_HASH)
|
445
|
+
if inherited_value.any?
|
446
|
+
inherited_value.merge(@own_references_to)
|
447
|
+
else
|
448
|
+
@own_references_to
|
449
|
+
end
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
def type_from_ast(ast_node, context: nil)
|
454
|
+
type_owner = context ? context.warden : self
|
455
|
+
GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
|
456
|
+
end
|
457
|
+
|
458
|
+
def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext)
|
459
|
+
parent_type = case type_or_name
|
460
|
+
when LateBoundType
|
461
|
+
get_type(type_or_name.name, context)
|
462
|
+
when String
|
463
|
+
get_type(type_or_name, context)
|
464
|
+
when Module
|
465
|
+
type_or_name
|
466
|
+
else
|
467
|
+
raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
|
468
|
+
end
|
469
|
+
|
470
|
+
if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
|
471
|
+
field
|
472
|
+
elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
|
473
|
+
entry_point_field
|
474
|
+
elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
|
475
|
+
dynamic_field
|
476
|
+
else
|
477
|
+
nil
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
def get_fields(type, context = GraphQL::Query::NullContext)
|
482
|
+
type.fields(context)
|
483
|
+
end
|
484
|
+
|
485
|
+
def introspection(new_introspection_namespace = nil)
|
486
|
+
if new_introspection_namespace
|
487
|
+
@introspection = new_introspection_namespace
|
488
|
+
# reset this cached value:
|
489
|
+
@introspection_system = nil
|
490
|
+
else
|
491
|
+
@introspection || find_inherited_value(:introspection)
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
def introspection_system
|
496
|
+
if !@introspection_system
|
497
|
+
@introspection_system = Schema::IntrospectionSystem.new(self)
|
498
|
+
@introspection_system.resolve_late_bindings
|
499
|
+
end
|
500
|
+
@introspection_system
|
501
|
+
end
|
502
|
+
|
503
|
+
def cursor_encoder(new_encoder = nil)
|
504
|
+
if new_encoder
|
505
|
+
@cursor_encoder = new_encoder
|
506
|
+
end
|
507
|
+
@cursor_encoder || find_inherited_value(:cursor_encoder, Base64Encoder)
|
508
|
+
end
|
509
|
+
|
510
|
+
def default_max_page_size(new_default_max_page_size = nil)
|
511
|
+
if new_default_max_page_size
|
512
|
+
@default_max_page_size = new_default_max_page_size
|
513
|
+
else
|
514
|
+
@default_max_page_size || find_inherited_value(:default_max_page_size)
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
def default_page_size(new_default_page_size = nil)
|
519
|
+
if new_default_page_size
|
520
|
+
@default_page_size = new_default_page_size
|
521
|
+
else
|
522
|
+
@default_page_size || find_inherited_value(:default_page_size)
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
def query_execution_strategy(new_query_execution_strategy = nil)
|
527
|
+
if new_query_execution_strategy
|
528
|
+
@query_execution_strategy = new_query_execution_strategy
|
529
|
+
else
|
530
|
+
@query_execution_strategy || find_inherited_value(:query_execution_strategy, self.default_execution_strategy)
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
def mutation_execution_strategy(new_mutation_execution_strategy = nil)
|
535
|
+
if new_mutation_execution_strategy
|
536
|
+
@mutation_execution_strategy = new_mutation_execution_strategy
|
537
|
+
else
|
538
|
+
@mutation_execution_strategy || find_inherited_value(:mutation_execution_strategy, self.default_execution_strategy)
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
def subscription_execution_strategy(new_subscription_execution_strategy = nil)
|
543
|
+
if new_subscription_execution_strategy
|
544
|
+
@subscription_execution_strategy = new_subscription_execution_strategy
|
545
|
+
else
|
546
|
+
@subscription_execution_strategy || find_inherited_value(:subscription_execution_strategy, self.default_execution_strategy)
|
547
|
+
end
|
548
|
+
end
|
549
|
+
|
550
|
+
attr_writer :validate_timeout
|
551
|
+
|
552
|
+
def validate_timeout(new_validate_timeout = nil)
|
553
|
+
if new_validate_timeout
|
554
|
+
@validate_timeout = new_validate_timeout
|
555
|
+
elsif defined?(@validate_timeout)
|
556
|
+
@validate_timeout
|
557
|
+
else
|
558
|
+
find_inherited_value(:validate_timeout)
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
# Validate a query string according to this schema.
|
563
|
+
# @param string_or_document [String, GraphQL::Language::Nodes::Document]
|
564
|
+
# @return [Array<GraphQL::StaticValidation::Error >]
|
565
|
+
def validate(string_or_document, rules: nil, context: nil)
|
566
|
+
doc = if string_or_document.is_a?(String)
|
567
|
+
GraphQL.parse(string_or_document)
|
568
|
+
else
|
569
|
+
string_or_document
|
570
|
+
end
|
571
|
+
query = GraphQL::Query.new(self, document: doc, context: context)
|
572
|
+
validator_opts = { schema: self }
|
573
|
+
rules && (validator_opts[:rules] = rules)
|
574
|
+
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
575
|
+
res = validator.validate(query, timeout: validate_timeout, max_errors: validate_max_errors)
|
576
|
+
res[:errors]
|
577
|
+
end
|
578
|
+
|
579
|
+
attr_writer :validate_max_errors
|
580
|
+
|
581
|
+
def validate_max_errors(new_validate_max_errors = nil)
|
582
|
+
if new_validate_max_errors
|
583
|
+
@validate_max_errors = new_validate_max_errors
|
584
|
+
elsif defined?(@validate_max_errors)
|
585
|
+
@validate_max_errors
|
586
|
+
else
|
587
|
+
find_inherited_value(:validate_max_errors)
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
attr_writer :max_complexity
|
592
|
+
|
593
|
+
def max_complexity(max_complexity = nil)
|
594
|
+
if max_complexity
|
595
|
+
@max_complexity = max_complexity
|
596
|
+
elsif defined?(@max_complexity)
|
597
|
+
@max_complexity
|
598
|
+
else
|
599
|
+
find_inherited_value(:max_complexity)
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
603
|
+
attr_writer :analysis_engine
|
604
|
+
|
605
|
+
def analysis_engine
|
606
|
+
@analysis_engine || find_inherited_value(:analysis_engine, self.default_analysis_engine)
|
607
|
+
end
|
608
|
+
|
609
|
+
def using_ast_analysis?
|
610
|
+
true
|
611
|
+
end
|
612
|
+
|
613
|
+
def interpreter?
|
614
|
+
true
|
615
|
+
end
|
616
|
+
|
617
|
+
attr_writer :interpreter
|
618
|
+
|
619
|
+
def error_bubbling(new_error_bubbling = nil)
|
620
|
+
if !new_error_bubbling.nil?
|
621
|
+
@error_bubbling = new_error_bubbling
|
622
|
+
else
|
623
|
+
@error_bubbling.nil? ? find_inherited_value(:error_bubbling) : @error_bubbling
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
627
|
+
attr_writer :error_bubbling
|
628
|
+
|
629
|
+
attr_writer :max_depth
|
630
|
+
|
631
|
+
def max_depth(new_max_depth = nil)
|
632
|
+
if new_max_depth
|
633
|
+
@max_depth = new_max_depth
|
634
|
+
elsif defined?(@max_depth)
|
635
|
+
@max_depth
|
636
|
+
else
|
637
|
+
find_inherited_value(:max_depth)
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
641
|
+
def disable_introspection_entry_points
|
642
|
+
@disable_introspection_entry_points = true
|
643
|
+
# TODO: this clears the cache made in `def types`. But this is not a great solution.
|
644
|
+
@introspection_system = nil
|
645
|
+
end
|
646
|
+
|
647
|
+
def disable_schema_introspection_entry_point
|
648
|
+
@disable_schema_introspection_entry_point = true
|
649
|
+
# TODO: this clears the cache made in `def types`. But this is not a great solution.
|
650
|
+
@introspection_system = nil
|
651
|
+
end
|
652
|
+
|
653
|
+
def disable_type_introspection_entry_point
|
654
|
+
@disable_type_introspection_entry_point = true
|
655
|
+
# TODO: this clears the cache made in `def types`. But this is not a great solution.
|
656
|
+
@introspection_system = nil
|
657
|
+
end
|
658
|
+
|
659
|
+
def disable_introspection_entry_points?
|
660
|
+
if instance_variable_defined?(:@disable_introspection_entry_points)
|
661
|
+
@disable_introspection_entry_points
|
662
|
+
else
|
663
|
+
find_inherited_value(:disable_introspection_entry_points?, false)
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
def disable_schema_introspection_entry_point?
|
668
|
+
if instance_variable_defined?(:@disable_schema_introspection_entry_point)
|
669
|
+
@disable_schema_introspection_entry_point
|
670
|
+
else
|
671
|
+
find_inherited_value(:disable_schema_introspection_entry_point?, false)
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
def disable_type_introspection_entry_point?
|
676
|
+
if instance_variable_defined?(:@disable_type_introspection_entry_point)
|
677
|
+
@disable_type_introspection_entry_point
|
678
|
+
else
|
679
|
+
find_inherited_value(:disable_type_introspection_entry_point?, false)
|
680
|
+
end
|
681
|
+
end
|
682
|
+
|
683
|
+
def orphan_types(*new_orphan_types)
|
684
|
+
if new_orphan_types.any?
|
685
|
+
new_orphan_types = new_orphan_types.flatten
|
686
|
+
add_type_and_traverse(new_orphan_types, root: false)
|
687
|
+
own_orphan_types.concat(new_orphan_types.flatten)
|
688
|
+
end
|
689
|
+
|
690
|
+
find_inherited_value(:orphan_types, EMPTY_ARRAY) + own_orphan_types
|
691
|
+
end
|
692
|
+
|
693
|
+
def default_execution_strategy
|
694
|
+
if superclass <= GraphQL::Schema
|
695
|
+
superclass.default_execution_strategy
|
696
|
+
else
|
697
|
+
@default_execution_strategy ||= GraphQL::Execution::Interpreter
|
698
|
+
end
|
699
|
+
end
|
700
|
+
|
701
|
+
def default_analysis_engine
|
702
|
+
if superclass <= GraphQL::Schema
|
703
|
+
superclass.default_analysis_engine
|
704
|
+
else
|
705
|
+
@default_analysis_engine ||= GraphQL::Analysis::AST
|
706
|
+
end
|
707
|
+
end
|
708
|
+
|
709
|
+
def context_class(new_context_class = nil)
|
710
|
+
if new_context_class
|
711
|
+
@context_class = new_context_class
|
712
|
+
else
|
713
|
+
@context_class || find_inherited_value(:context_class, GraphQL::Query::Context)
|
714
|
+
end
|
715
|
+
end
|
716
|
+
|
717
|
+
def rescue_from(*err_classes, &handler_block)
|
718
|
+
err_classes.each do |err_class|
|
719
|
+
Execution::Errors.register_rescue_from(err_class, error_handlers[:subclass_handlers], handler_block)
|
720
|
+
end
|
721
|
+
end
|
722
|
+
|
723
|
+
NEW_HANDLER_HASH = ->(h, k) {
|
724
|
+
h[k] = {
|
725
|
+
class: k,
|
726
|
+
handler: nil,
|
727
|
+
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
728
|
+
}
|
729
|
+
}
|
730
|
+
|
731
|
+
def error_handlers
|
732
|
+
@error_handlers ||= {
|
733
|
+
class: nil,
|
734
|
+
handler: nil,
|
735
|
+
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
736
|
+
}
|
737
|
+
end
|
738
|
+
|
739
|
+
# @api private
|
740
|
+
def handle_or_reraise(context, err)
|
741
|
+
handler = Execution::Errors.find_handler_for(self, err.class)
|
742
|
+
if handler
|
743
|
+
obj = context[:current_object]
|
744
|
+
args = context[:current_arguments]
|
745
|
+
args = args && args.keyword_arguments
|
746
|
+
field = context[:current_field]
|
747
|
+
if obj.is_a?(GraphQL::Schema::Object)
|
748
|
+
obj = obj.object
|
749
|
+
end
|
750
|
+
handler[:handler].call(err, obj, args, context, field)
|
751
|
+
else
|
752
|
+
raise err
|
753
|
+
end
|
754
|
+
end
|
755
|
+
|
756
|
+
# rubocop:disable Lint/DuplicateMethods
|
757
|
+
module ResolveTypeWithType
|
758
|
+
def resolve_type(type, obj, ctx)
|
759
|
+
maybe_lazy_resolve_type_result = if type.is_a?(Module) && type.respond_to?(:resolve_type)
|
760
|
+
type.resolve_type(obj, ctx)
|
761
|
+
else
|
762
|
+
super
|
763
|
+
end
|
764
|
+
|
765
|
+
after_lazy(maybe_lazy_resolve_type_result) do |resolve_type_result|
|
766
|
+
if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
|
767
|
+
resolved_type = resolve_type_result[0]
|
768
|
+
resolved_value = resolve_type_result[1]
|
769
|
+
else
|
770
|
+
resolved_type = resolve_type_result
|
771
|
+
resolved_value = obj
|
772
|
+
end
|
773
|
+
|
774
|
+
if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind))
|
775
|
+
if resolved_value
|
776
|
+
[resolved_type, resolved_value]
|
777
|
+
else
|
778
|
+
resolved_type
|
779
|
+
end
|
780
|
+
else
|
781
|
+
raise ".resolve_type should return a type definition, but got #{resolved_type.inspect} (#{resolved_type.class}) from `resolve_type(#{type}, #{obj}, #{ctx})`"
|
782
|
+
end
|
783
|
+
end
|
784
|
+
end
|
785
|
+
end
|
786
|
+
|
787
|
+
def resolve_type(type, obj, ctx)
|
788
|
+
if type.kind.object?
|
789
|
+
type
|
790
|
+
else
|
791
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
|
792
|
+
end
|
793
|
+
end
|
794
|
+
# rubocop:enable Lint/DuplicateMethods
|
795
|
+
|
796
|
+
def inherited(child_class)
|
797
|
+
if self == GraphQL::Schema
|
798
|
+
child_class.directives(default_directives.values)
|
799
|
+
end
|
800
|
+
child_class.singleton_class.prepend(ResolveTypeWithType)
|
801
|
+
super
|
802
|
+
end
|
803
|
+
|
804
|
+
def object_from_id(node_id, ctx)
|
805
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to load by ID (tried to load from id `#{node_id}`)"
|
806
|
+
end
|
807
|
+
|
808
|
+
def id_from_object(object, type, ctx)
|
809
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.id_from_object(object, type, ctx) must be implemented to create global ids (tried to create an id for `#{object.inspect}`)"
|
810
|
+
end
|
811
|
+
|
812
|
+
def visible?(member, ctx)
|
813
|
+
member.visible?(ctx)
|
814
|
+
end
|
815
|
+
|
816
|
+
def accessible?(member, ctx)
|
817
|
+
member.accessible?(ctx)
|
818
|
+
end
|
819
|
+
|
820
|
+
def schema_directive(dir_class, **options)
|
821
|
+
@own_schema_directives ||= []
|
822
|
+
Member::HasDirectives.add_directive(self, @own_schema_directives, dir_class, options)
|
823
|
+
end
|
824
|
+
|
825
|
+
def schema_directives
|
826
|
+
Member::HasDirectives.get_directives(self, @own_schema_directives, :schema_directives)
|
827
|
+
end
|
828
|
+
|
829
|
+
# This hook is called when a client tries to access one or more
|
830
|
+
# fields that fail the `accessible?` check.
|
831
|
+
#
|
832
|
+
# By default, an error is added to the response. Override this hook to
|
833
|
+
# track metrics or return a different error to the client.
|
834
|
+
#
|
835
|
+
# @param error [InaccessibleFieldsError] The analysis error for this check
|
836
|
+
# @return [AnalysisError, nil] Return an error to skip the query
|
837
|
+
def inaccessible_fields(error)
|
838
|
+
error
|
839
|
+
end
|
840
|
+
|
841
|
+
# This hook is called when an object fails an `authorized?` check.
|
842
|
+
# You might report to your bug tracker here, so you can correct
|
843
|
+
# the field resolvers not to return unauthorized objects.
|
844
|
+
#
|
845
|
+
# By default, this hook just replaces the unauthorized object with `nil`.
|
846
|
+
#
|
847
|
+
# Whatever value is returned from this method will be used instead of the
|
848
|
+
# unauthorized object (accessible as `unauthorized_error.object`). If an
|
849
|
+
# error is raised, then `nil` will be used.
|
850
|
+
#
|
851
|
+
# If you want to add an error to the `"errors"` key, raise a {GraphQL::ExecutionError}
|
852
|
+
# in this hook.
|
853
|
+
#
|
854
|
+
# @param unauthorized_error [GraphQL::UnauthorizedError]
|
855
|
+
# @return [Object] The returned object will be put in the GraphQL response
|
856
|
+
def unauthorized_object(unauthorized_error)
|
86
857
|
nil
|
87
858
|
end
|
88
|
-
end
|
89
859
|
|
90
|
-
|
91
|
-
|
92
|
-
|
860
|
+
# This hook is called when a field fails an `authorized?` check.
|
861
|
+
#
|
862
|
+
# By default, this hook implements the same behavior as unauthorized_object.
|
863
|
+
#
|
864
|
+
# Whatever value is returned from this method will be used instead of the
|
865
|
+
# unauthorized field . If an error is raised, then `nil` will be used.
|
866
|
+
#
|
867
|
+
# If you want to add an error to the `"errors"` key, raise a {GraphQL::ExecutionError}
|
868
|
+
# in this hook.
|
869
|
+
#
|
870
|
+
# @param unauthorized_error [GraphQL::UnauthorizedFieldError]
|
871
|
+
# @return [Field] The returned field will be put in the GraphQL response
|
872
|
+
def unauthorized_field(unauthorized_error)
|
873
|
+
unauthorized_object(unauthorized_error)
|
874
|
+
end
|
93
875
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
876
|
+
def type_error(type_error, ctx)
|
877
|
+
case type_error
|
878
|
+
when GraphQL::InvalidNullError
|
879
|
+
ctx.errors << type_error
|
880
|
+
when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
|
881
|
+
raise type_error
|
882
|
+
when GraphQL::IntegerDecodingError
|
883
|
+
nil
|
884
|
+
end
|
885
|
+
end
|
100
886
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
887
|
+
# A function to call when {#execute} receives an invalid query string
|
888
|
+
#
|
889
|
+
# The default is to add the error to `context.errors`
|
890
|
+
# @param err [GraphQL::ParseError] The error encountered during parsing
|
891
|
+
# @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
|
892
|
+
# @return void
|
893
|
+
def parse_error(parse_err, ctx)
|
894
|
+
ctx.errors.push(parse_err)
|
895
|
+
end
|
896
|
+
|
897
|
+
def lazy_resolve(lazy_class, value_method)
|
898
|
+
lazy_methods.set(lazy_class, value_method)
|
899
|
+
end
|
900
|
+
|
901
|
+
def instrument(instrument_step, instrumenter, options = {})
|
902
|
+
own_instrumenters[instrument_step] << instrumenter
|
903
|
+
end
|
904
|
+
|
905
|
+
# Add several directives at once
|
906
|
+
# @param new_directives [Class]
|
907
|
+
def directives(*new_directives)
|
908
|
+
if new_directives.any?
|
909
|
+
new_directives.flatten.each { |d| directive(d) }
|
910
|
+
end
|
911
|
+
|
912
|
+
find_inherited_value(:directives, default_directives).merge(own_directives)
|
913
|
+
end
|
914
|
+
|
915
|
+
# Attach a single directive to this schema
|
916
|
+
# @param new_directive [Class]
|
917
|
+
# @return void
|
918
|
+
def directive(new_directive)
|
919
|
+
add_type_and_traverse(new_directive, root: false)
|
920
|
+
end
|
921
|
+
|
922
|
+
def default_directives
|
923
|
+
@default_directives ||= {
|
924
|
+
"include" => GraphQL::Schema::Directive::Include,
|
925
|
+
"skip" => GraphQL::Schema::Directive::Skip,
|
926
|
+
"deprecated" => GraphQL::Schema::Directive::Deprecated,
|
927
|
+
"oneOf" => GraphQL::Schema::Directive::OneOf,
|
928
|
+
}.freeze
|
929
|
+
end
|
930
|
+
|
931
|
+
def tracer(new_tracer)
|
932
|
+
own_tracers << new_tracer
|
933
|
+
end
|
934
|
+
|
935
|
+
def tracers
|
936
|
+
find_inherited_value(:tracers, EMPTY_ARRAY) + own_tracers
|
937
|
+
end
|
938
|
+
|
939
|
+
def query_analyzer(new_analyzer)
|
940
|
+
own_query_analyzers << new_analyzer
|
941
|
+
end
|
942
|
+
|
943
|
+
def query_analyzers
|
944
|
+
find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
|
945
|
+
end
|
946
|
+
|
947
|
+
def multiplex_analyzer(new_analyzer)
|
948
|
+
own_multiplex_analyzers << new_analyzer
|
949
|
+
end
|
950
|
+
|
951
|
+
def multiplex_analyzers
|
952
|
+
find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
|
953
|
+
end
|
954
|
+
|
955
|
+
def sanitized_printer(new_sanitized_printer = nil)
|
956
|
+
if new_sanitized_printer
|
957
|
+
@own_sanitized_printer = new_sanitized_printer
|
958
|
+
else
|
959
|
+
@own_sanitized_printer || GraphQL::Language::SanitizedPrinter
|
960
|
+
end
|
961
|
+
end
|
962
|
+
|
963
|
+
# Execute a query on itself.
|
964
|
+
# @see {Query#initialize} for arguments.
|
965
|
+
# @return [Hash] query result, ready to be serialized as JSON
|
966
|
+
def execute(query_str = nil, **kwargs)
|
967
|
+
if query_str
|
968
|
+
kwargs[:query] = query_str
|
969
|
+
end
|
970
|
+
# Some of the query context _should_ be passed to the multiplex, too
|
971
|
+
multiplex_context = if (ctx = kwargs[:context])
|
972
|
+
{
|
973
|
+
backtrace: ctx[:backtrace],
|
974
|
+
tracers: ctx[:tracers],
|
975
|
+
dataloader: ctx[:dataloader],
|
976
|
+
}
|
977
|
+
else
|
978
|
+
{}
|
979
|
+
end
|
980
|
+
# Since we're running one query, don't run a multiplex-level complexity analyzer
|
981
|
+
all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
|
982
|
+
all_results[0]
|
983
|
+
end
|
984
|
+
|
985
|
+
# Execute several queries on itself, concurrently.
|
986
|
+
#
|
987
|
+
# @example Run several queries at once
|
988
|
+
# context = { ... }
|
989
|
+
# queries = [
|
990
|
+
# { query: params[:query_1], variables: params[:variables_1], context: context },
|
991
|
+
# { query: params[:query_2], variables: params[:variables_2], context: context },
|
992
|
+
# ]
|
993
|
+
# results = MySchema.multiplex(queries)
|
994
|
+
# render json: {
|
995
|
+
# result_1: results[0],
|
996
|
+
# result_2: results[1],
|
997
|
+
# }
|
998
|
+
#
|
999
|
+
# @see {Query#initialize} for query keyword arguments
|
1000
|
+
# @see {Execution::Multiplex#run_all} for multiplex keyword arguments
|
1001
|
+
# @param queries [Array<Hash>] Keyword arguments for each query
|
1002
|
+
# @param context [Hash] Multiplex-level context
|
1003
|
+
# @return [Array<Hash>] One result for each query in the input
|
1004
|
+
def multiplex(queries, **kwargs)
|
1005
|
+
GraphQL::Execution::Interpreter.run_all(self, queries, **kwargs)
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
def instrumenters
|
1009
|
+
inherited_instrumenters = find_inherited_value(:instrumenters) || Hash.new { |h,k| h[k] = [] }
|
1010
|
+
inherited_instrumenters.merge(own_instrumenters) do |_step, inherited, own|
|
1011
|
+
inherited + own
|
1012
|
+
end
|
1013
|
+
end
|
1014
|
+
|
1015
|
+
# @api private
|
1016
|
+
def add_subscription_extension_if_necessary
|
1017
|
+
if !defined?(@subscription_extension_added) && subscription && self.subscriptions
|
1018
|
+
@subscription_extension_added = true
|
1019
|
+
subscription.all_field_definitions.each do |field|
|
1020
|
+
if !field.extensions.any? { |ext| ext.is_a?(Subscriptions::DefaultSubscriptionResolveExtension) }
|
1021
|
+
field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
|
1022
|
+
end
|
1023
|
+
end
|
1024
|
+
end
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
def query_stack_error(query, err)
|
1028
|
+
query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
|
1029
|
+
end
|
1030
|
+
|
1031
|
+
# Call the given block at the right time, either:
|
1032
|
+
# - Right away, if `value` is not registered with `lazy_resolve`
|
1033
|
+
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
1034
|
+
# @api private
|
1035
|
+
def after_lazy(value, &block)
|
1036
|
+
if lazy?(value)
|
1037
|
+
GraphQL::Execution::Lazy.new do
|
1038
|
+
result = sync_lazy(value)
|
1039
|
+
# The returned result might also be lazy, so check it, too
|
1040
|
+
after_lazy(result, &block)
|
1041
|
+
end
|
1042
|
+
else
|
1043
|
+
yield(value) if block_given?
|
1044
|
+
end
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
# Override this method to handle lazy objects in a custom way.
|
1048
|
+
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
1049
|
+
# @return [Object] A GraphQL-ready (non-lazy) object
|
1050
|
+
# @api private
|
1051
|
+
def sync_lazy(value)
|
1052
|
+
lazy_method = lazy_method_name(value)
|
1053
|
+
if lazy_method
|
1054
|
+
synced_value = value.public_send(lazy_method)
|
1055
|
+
sync_lazy(synced_value)
|
1056
|
+
else
|
1057
|
+
value
|
1058
|
+
end
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
|
1062
|
+
def lazy_method_name(obj)
|
1063
|
+
lazy_methods.get(obj)
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
# @return [Boolean] True if this object should be lazily resolved
|
1067
|
+
def lazy?(obj)
|
1068
|
+
!!lazy_method_name(obj)
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
# Return a lazy if any of `maybe_lazies` are lazy,
|
1072
|
+
# otherwise, call the block eagerly and return the result.
|
1073
|
+
# @param maybe_lazies [Array]
|
1074
|
+
# @api private
|
1075
|
+
def after_any_lazies(maybe_lazies)
|
1076
|
+
if maybe_lazies.any? { |l| lazy?(l) }
|
1077
|
+
GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
|
1078
|
+
yield result
|
1079
|
+
end
|
1080
|
+
else
|
1081
|
+
yield maybe_lazies
|
1082
|
+
end
|
111
1083
|
end
|
112
|
-
end
|
113
1084
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
1085
|
+
private
|
1086
|
+
|
1087
|
+
# @param t [Module, Array<Module>]
|
1088
|
+
# @return [void]
|
1089
|
+
def add_type_and_traverse(t, root:)
|
1090
|
+
if root
|
1091
|
+
@root_types ||= []
|
1092
|
+
@root_types << t
|
1093
|
+
end
|
1094
|
+
new_types = Array(t)
|
1095
|
+
addition = Schema::Addition.new(schema: self, own_types: own_types, new_types: new_types)
|
1096
|
+
addition.types.each do |name, types_entry| # rubocop:disable Development/ContextIsPassedCop -- build-time, not query-time
|
1097
|
+
if (prev_entry = own_types[name])
|
1098
|
+
prev_entries = case prev_entry
|
1099
|
+
when Array
|
1100
|
+
prev_entry
|
1101
|
+
when Module
|
1102
|
+
own_types[name] = [prev_entry]
|
1103
|
+
else
|
1104
|
+
raise "Invariant: unexpected prev_entry at #{name.inspect} when adding #{t.inspect}"
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
case types_entry
|
1108
|
+
when Array
|
1109
|
+
prev_entries.concat(types_entry)
|
1110
|
+
prev_entries.uniq! # in case any are being re-visited
|
1111
|
+
when Module
|
1112
|
+
if !prev_entries.include?(types_entry)
|
1113
|
+
prev_entries << types_entry
|
1114
|
+
end
|
1115
|
+
else
|
1116
|
+
raise "Invariant: unexpected types_entry at #{name} when adding #{t.inspect}"
|
1117
|
+
end
|
1118
|
+
else
|
1119
|
+
if types_entry.is_a?(Array)
|
1120
|
+
types_entry.uniq!
|
1121
|
+
end
|
1122
|
+
own_types[name] = types_entry
|
1123
|
+
end
|
1124
|
+
end
|
1125
|
+
|
1126
|
+
own_possible_types.merge!(addition.possible_types) { |key, old_val, new_val| old_val + new_val }
|
1127
|
+
own_union_memberships.merge!(addition.union_memberships)
|
1128
|
+
|
1129
|
+
addition.references.each { |thing, pointers|
|
1130
|
+
pointers.each { |pointer| references_to(thing, from: pointer) }
|
1131
|
+
}
|
1132
|
+
|
1133
|
+
addition.directives.each { |dir_class| own_directives[dir_class.graphql_name] = dir_class }
|
1134
|
+
|
1135
|
+
addition.arguments_with_default_values.each do |arg|
|
1136
|
+
arg.validate_default_value
|
1137
|
+
end
|
1138
|
+
end
|
1139
|
+
|
1140
|
+
def lazy_methods
|
1141
|
+
if !defined?(@lazy_methods)
|
1142
|
+
if inherited_map = find_inherited_value(:lazy_methods)
|
1143
|
+
# this isn't _completely_ inherited :S (Things added after `dup` won't work)
|
1144
|
+
@lazy_methods = inherited_map.dup
|
1145
|
+
else
|
1146
|
+
@lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
|
1147
|
+
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
1148
|
+
@lazy_methods.set(GraphQL::Dataloader::Request, :load)
|
1149
|
+
end
|
1150
|
+
end
|
1151
|
+
@lazy_methods
|
1152
|
+
end
|
1153
|
+
|
1154
|
+
def own_types
|
1155
|
+
@own_types ||= {}
|
1156
|
+
end
|
1157
|
+
|
1158
|
+
def non_introspection_types
|
1159
|
+
find_inherited_value(:non_introspection_types, EMPTY_HASH).merge(own_types)
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
def own_plugins
|
1163
|
+
@own_plugins ||= []
|
1164
|
+
end
|
1165
|
+
|
1166
|
+
def own_orphan_types
|
1167
|
+
@own_orphan_types ||= []
|
1168
|
+
end
|
1169
|
+
|
1170
|
+
def own_possible_types
|
1171
|
+
@own_possible_types ||= {}
|
1172
|
+
end
|
1173
|
+
|
1174
|
+
def own_union_memberships
|
1175
|
+
@own_union_memberships ||= {}
|
1176
|
+
end
|
1177
|
+
|
1178
|
+
def own_directives
|
1179
|
+
@own_directives ||= {}
|
1180
|
+
end
|
1181
|
+
|
1182
|
+
def own_instrumenters
|
1183
|
+
@own_instrumenters ||= Hash.new { |h,k| h[k] = [] }
|
1184
|
+
end
|
1185
|
+
|
1186
|
+
def own_tracers
|
1187
|
+
@own_tracers ||= []
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
def own_query_analyzers
|
1191
|
+
@defined_query_analyzers ||= []
|
1192
|
+
end
|
1193
|
+
|
1194
|
+
def own_multiplex_analyzers
|
1195
|
+
@own_multiplex_analyzers ||= []
|
124
1196
|
end
|
125
1197
|
end
|
1198
|
+
|
1199
|
+
# Install these here so that subclasses will also install it.
|
1200
|
+
self.connections = GraphQL::Pagination::Connections.new(schema: self)
|
126
1201
|
end
|
127
1202
|
end
|