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,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 3 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 4 
     | 
    
         
            +
                class Scalar < GraphQL::Schema::Member
         
     | 
| 
      
 5 
     | 
    
         
            +
                  extend GraphQL::Schema::Member::ValidatesInput
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                    def coerce_input(val, ctx)
         
     | 
| 
      
 9 
     | 
    
         
            +
                      val
         
     | 
| 
      
 10 
     | 
    
         
            +
                    end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    def coerce_result(val, ctx)
         
     | 
| 
      
 13 
     | 
    
         
            +
                      val
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    def kind
         
     | 
| 
      
 17 
     | 
    
         
            +
                      GraphQL::TypeKinds::SCALAR
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    def specified_by_url(new_url = nil)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      if new_url
         
     | 
| 
      
 22 
     | 
    
         
            +
                        @specified_by_url = new_url
         
     | 
| 
      
 23 
     | 
    
         
            +
                      elsif defined?(@specified_by_url)
         
     | 
| 
      
 24 
     | 
    
         
            +
                        @specified_by_url
         
     | 
| 
      
 25 
     | 
    
         
            +
                      elsif superclass.respond_to?(:specified_by_url)
         
     | 
| 
      
 26 
     | 
    
         
            +
                        superclass.specified_by_url
         
     | 
| 
      
 27 
     | 
    
         
            +
                      else
         
     | 
| 
      
 28 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 29 
     | 
    
         
            +
                      end
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    def default_scalar(is_default = nil)
         
     | 
| 
      
 33 
     | 
    
         
            +
                      if !is_default.nil?
         
     | 
| 
      
 34 
     | 
    
         
            +
                        @default_scalar = is_default
         
     | 
| 
      
 35 
     | 
    
         
            +
                      end
         
     | 
| 
      
 36 
     | 
    
         
            +
                      @default_scalar
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    def default_scalar?
         
     | 
| 
      
 40 
     | 
    
         
            +
                      @default_scalar ||= false
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    def validate_non_null_input(value, ctx, max_errors: nil)
         
     | 
| 
      
 44 
     | 
    
         
            +
                      coerced_result = begin
         
     | 
| 
      
 45 
     | 
    
         
            +
                        coerce_input(value, ctx)
         
     | 
| 
      
 46 
     | 
    
         
            +
                      rescue GraphQL::CoercionError => err
         
     | 
| 
      
 47 
     | 
    
         
            +
                        err
         
     | 
| 
      
 48 
     | 
    
         
            +
                      rescue StandardError => err
         
     | 
| 
      
 49 
     | 
    
         
            +
                        ctx.query.handle_or_reraise(err)
         
     | 
| 
      
 50 
     | 
    
         
            +
                      end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                      if coerced_result.nil?
         
     | 
| 
      
 53 
     | 
    
         
            +
                        str_value = if value == Float::INFINITY
         
     | 
| 
      
 54 
     | 
    
         
            +
                          ""
         
     | 
| 
      
 55 
     | 
    
         
            +
                        else
         
     | 
| 
      
 56 
     | 
    
         
            +
                          " #{GraphQL::Language.serialize(value)}"
         
     | 
| 
      
 57 
     | 
    
         
            +
                        end
         
     | 
| 
      
 58 
     | 
    
         
            +
                        Query::InputValidationResult.from_problem("Could not coerce value#{str_value} to #{graphql_name}")
         
     | 
| 
      
 59 
     | 
    
         
            +
                      elsif coerced_result.is_a?(GraphQL::CoercionError)
         
     | 
| 
      
 60 
     | 
    
         
            +
                        Query::InputValidationResult.from_problem(coerced_result.message, message: coerced_result.message, extensions: coerced_result.extensions)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      else
         
     | 
| 
      
 62 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 63 
     | 
    
         
            +
                      end
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,148 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 5 
     | 
    
         
            +
                # This class can be extended to create fields on your subscription root.
         
     | 
| 
      
 6 
     | 
    
         
            +
                #
         
     | 
| 
      
 7 
     | 
    
         
            +
                # It provides hooks for the different parts of the subscription lifecycle:
         
     | 
| 
      
 8 
     | 
    
         
            +
                #
         
     | 
| 
      
 9 
     | 
    
         
            +
                # - `#authorized?`: called before initial subscription and subsequent updates
         
     | 
| 
      
 10 
     | 
    
         
            +
                # - `#subscribe`: called for the initial subscription
         
     | 
| 
      
 11 
     | 
    
         
            +
                # - `#update`: called for subsequent update
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                # Also, `#unsubscribe` terminates the subscription.
         
     | 
| 
      
 14 
     | 
    
         
            +
                class Subscription < GraphQL::Schema::Resolver
         
     | 
| 
      
 15 
     | 
    
         
            +
                  extend GraphQL::Schema::Resolver::HasPayloadType
         
     | 
| 
      
 16 
     | 
    
         
            +
                  extend GraphQL::Schema::Member::HasFields
         
     | 
| 
      
 17 
     | 
    
         
            +
                  NO_UPDATE = :no_update
         
     | 
| 
      
 18 
     | 
    
         
            +
                  # The generated payload type is required; If there's no payload,
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # propagate null.
         
     | 
| 
      
 20 
     | 
    
         
            +
                  null false
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def initialize(object:, context:, field:)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    super
         
     | 
| 
      
 24 
     | 
    
         
            +
                    # Figure out whether this is an update or an initial subscription
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @mode = context.query.subscription_update? ? :update : :subscribe
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def resolve_with_support(**args)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    result = nil
         
     | 
| 
      
 30 
     | 
    
         
            +
                    unsubscribed = true
         
     | 
| 
      
 31 
     | 
    
         
            +
                    catch :graphql_subscription_unsubscribed do
         
     | 
| 
      
 32 
     | 
    
         
            +
                      result = super
         
     | 
| 
      
 33 
     | 
    
         
            +
                      unsubscribed = false
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    if unsubscribed
         
     | 
| 
      
 38 
     | 
    
         
            +
                      context.skip
         
     | 
| 
      
 39 
     | 
    
         
            +
                    else
         
     | 
| 
      
 40 
     | 
    
         
            +
                      result
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  # Implement the {Resolve} API
         
     | 
| 
      
 45 
     | 
    
         
            +
                  def resolve(**args)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    # Dispatch based on `@mode`, which will raise a `NoMethodError` if we ever
         
     | 
| 
      
 47 
     | 
    
         
            +
                    # have an unexpected `@mode`
         
     | 
| 
      
 48 
     | 
    
         
            +
                    public_send("resolve_#{@mode}", **args)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  # Wrap the user-defined `#subscribe` hook
         
     | 
| 
      
 52 
     | 
    
         
            +
                  def resolve_subscribe(**args)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    ret_val = args.any? ? subscribe(**args) : subscribe
         
     | 
| 
      
 54 
     | 
    
         
            +
                    if ret_val == :no_response
         
     | 
| 
      
 55 
     | 
    
         
            +
                      context.skip
         
     | 
| 
      
 56 
     | 
    
         
            +
                    else
         
     | 
| 
      
 57 
     | 
    
         
            +
                      ret_val
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  # The default implementation returns nothing on subscribe.
         
     | 
| 
      
 62 
     | 
    
         
            +
                  # Override it to return an object or
         
     | 
| 
      
 63 
     | 
    
         
            +
                  # `:no_response` to (explicitly) return nothing.
         
     | 
| 
      
 64 
     | 
    
         
            +
                  def subscribe(args = {})
         
     | 
| 
      
 65 
     | 
    
         
            +
                    :no_response
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  # Wrap the user-provided `#update` hook
         
     | 
| 
      
 69 
     | 
    
         
            +
                  def resolve_update(**args)
         
     | 
| 
      
 70 
     | 
    
         
            +
                    ret_val = args.any? ? update(**args) : update
         
     | 
| 
      
 71 
     | 
    
         
            +
                    if ret_val == NO_UPDATE
         
     | 
| 
      
 72 
     | 
    
         
            +
                      context.namespace(:subscriptions)[:no_update] = true
         
     | 
| 
      
 73 
     | 
    
         
            +
                      context.skip
         
     | 
| 
      
 74 
     | 
    
         
            +
                    else
         
     | 
| 
      
 75 
     | 
    
         
            +
                      ret_val
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  # The default implementation returns the root object.
         
     | 
| 
      
 80 
     | 
    
         
            +
                  # Override it to return {NO_UPDATE} if you want to
         
     | 
| 
      
 81 
     | 
    
         
            +
                  # skip updates sometimes. Or override it to return a different object.
         
     | 
| 
      
 82 
     | 
    
         
            +
                  def update(args = {})
         
     | 
| 
      
 83 
     | 
    
         
            +
                    object
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  # If an argument is flagged with `loads:` and no object is found for it,
         
     | 
| 
      
 87 
     | 
    
         
            +
                  # remove this subscription (assuming that the object was deleted in the meantime,
         
     | 
| 
      
 88 
     | 
    
         
            +
                  # or that it became inaccessible).
         
     | 
| 
      
 89 
     | 
    
         
            +
                  def load_application_object_failed(err)
         
     | 
| 
      
 90 
     | 
    
         
            +
                    if @mode == :update
         
     | 
| 
      
 91 
     | 
    
         
            +
                      unsubscribe
         
     | 
| 
      
 92 
     | 
    
         
            +
                    end
         
     | 
| 
      
 93 
     | 
    
         
            +
                    super
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                  # Call this to halt execution and remove this subscription from the system
         
     | 
| 
      
 97 
     | 
    
         
            +
                  def unsubscribe
         
     | 
| 
      
 98 
     | 
    
         
            +
                    context.namespace(:subscriptions)[:unsubscribed] = true
         
     | 
| 
      
 99 
     | 
    
         
            +
                    throw :graphql_subscription_unsubscribed
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                  READING_SCOPE = ::Object.new
         
     | 
| 
      
 103 
     | 
    
         
            +
                  # Call this method to provide a new subscription_scope; OR
         
     | 
| 
      
 104 
     | 
    
         
            +
                  # call it without an argument to get the subscription_scope
         
     | 
| 
      
 105 
     | 
    
         
            +
                  # @param new_scope [Symbol]
         
     | 
| 
      
 106 
     | 
    
         
            +
                  # @param optional [Boolean] If true, then don't require `scope:` to be provided to updates to this subscription.
         
     | 
| 
      
 107 
     | 
    
         
            +
                  # @return [Symbol]
         
     | 
| 
      
 108 
     | 
    
         
            +
                  def self.subscription_scope(new_scope = READING_SCOPE, optional: false)
         
     | 
| 
      
 109 
     | 
    
         
            +
                    if new_scope != READING_SCOPE
         
     | 
| 
      
 110 
     | 
    
         
            +
                      @subscription_scope = new_scope
         
     | 
| 
      
 111 
     | 
    
         
            +
                      @subscription_scope_optional = optional
         
     | 
| 
      
 112 
     | 
    
         
            +
                    elsif defined?(@subscription_scope)
         
     | 
| 
      
 113 
     | 
    
         
            +
                      @subscription_scope
         
     | 
| 
      
 114 
     | 
    
         
            +
                    else
         
     | 
| 
      
 115 
     | 
    
         
            +
                      find_inherited_value(:subscription_scope)
         
     | 
| 
      
 116 
     | 
    
         
            +
                    end
         
     | 
| 
      
 117 
     | 
    
         
            +
                  end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                  def self.subscription_scope_optional?
         
     | 
| 
      
 120 
     | 
    
         
            +
                    if defined?(@subscription_scope_optional)
         
     | 
| 
      
 121 
     | 
    
         
            +
                      @subscription_scope_optional
         
     | 
| 
      
 122 
     | 
    
         
            +
                    else
         
     | 
| 
      
 123 
     | 
    
         
            +
                      find_inherited_value(:subscription_scope_optional, false)
         
     | 
| 
      
 124 
     | 
    
         
            +
                    end
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                  # This is called during initial subscription to get a "name" for this subscription.
         
     | 
| 
      
 128 
     | 
    
         
            +
                  # Later, when `.trigger` is called, this will be called again to build another "name".
         
     | 
| 
      
 129 
     | 
    
         
            +
                  # Any subscribers with matching topic will begin the update flow.
         
     | 
| 
      
 130 
     | 
    
         
            +
                  #
         
     | 
| 
      
 131 
     | 
    
         
            +
                  # The default implementation creates a string using the field name, subscription scope, and argument keys and values.
         
     | 
| 
      
 132 
     | 
    
         
            +
                  # In that implementation, only `.trigger` calls with _exact matches_ result in updates to subscribers.
         
     | 
| 
      
 133 
     | 
    
         
            +
                  #
         
     | 
| 
      
 134 
     | 
    
         
            +
                  # To implement a filtered stream-type subscription flow, override this method to return a string with field name and subscription scope.
         
     | 
| 
      
 135 
     | 
    
         
            +
                  # Then, implement {#update} to compare its arguments to the current `object` and return {NO_UPDATE} when an
         
     | 
| 
      
 136 
     | 
    
         
            +
                  # update should be filtered out.
         
     | 
| 
      
 137 
     | 
    
         
            +
                  #
         
     | 
| 
      
 138 
     | 
    
         
            +
                  # @see {#update} for how to skip updates when an event comes with a matching topic.
         
     | 
| 
      
 139 
     | 
    
         
            +
                  # @param arguments [Hash<String => Object>] The arguments for this topic, in GraphQL-style (camelized strings)
         
     | 
| 
      
 140 
     | 
    
         
            +
                  # @param field [GraphQL::Schema::Field]
         
     | 
| 
      
 141 
     | 
    
         
            +
                  # @param scope [Object, nil] A value corresponding to `.trigger(... scope:)` (for updates) or the `subscription_scope` found in `context` (for initial subscriptions).
         
     | 
| 
      
 142 
     | 
    
         
            +
                  # @return [String] An identifier corresponding to a stream of updates
         
     | 
| 
      
 143 
     | 
    
         
            +
                  def self.topic_for(arguments:, field:, scope:)
         
     | 
| 
      
 144 
     | 
    
         
            +
                    Subscriptions::Serialize.dump_recursive([scope, field.graphql_name, arguments])
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,123 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 5 
     | 
    
         
            +
                # This plugin will stop resolving new fields after `max_seconds` have elapsed.
         
     | 
| 
      
 6 
     | 
    
         
            +
                # After the time has passed, any remaining fields will be `nil`, with errors added
         
     | 
| 
      
 7 
     | 
    
         
            +
                # to the `errors` key. Any already-resolved fields will be in the `data` key, so
         
     | 
| 
      
 8 
     | 
    
         
            +
                # you'll get a partial response.
         
     | 
| 
      
 9 
     | 
    
         
            +
                #
         
     | 
| 
      
 10 
     | 
    
         
            +
                # You can subclass `GraphQL::Schema::Timeout` and override `max_seconds` and/or `handle_timeout`
         
     | 
| 
      
 11 
     | 
    
         
            +
                # to provide custom logic when a timeout error occurs.
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                # Note that this will stop a query _in between_ field resolutions, but
         
     | 
| 
      
 14 
     | 
    
         
            +
                # it doesn't interrupt long-running `resolve` functions. Be sure to use
         
     | 
| 
      
 15 
     | 
    
         
            +
                # timeout options for external connections. For more info, see
         
     | 
| 
      
 16 
     | 
    
         
            +
                # www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/
         
     | 
| 
      
 17 
     | 
    
         
            +
                #
         
     | 
| 
      
 18 
     | 
    
         
            +
                # @example Stop resolving fields after 2 seconds
         
     | 
| 
      
 19 
     | 
    
         
            +
                #   class MySchema < GraphQL::Schema
         
     | 
| 
      
 20 
     | 
    
         
            +
                #     use GraphQL::Schema::Timeout, max_seconds: 2
         
     | 
| 
      
 21 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 22 
     | 
    
         
            +
                #
         
     | 
| 
      
 23 
     | 
    
         
            +
                # @example Notifying Bugsnag and logging a timeout
         
     | 
| 
      
 24 
     | 
    
         
            +
                #   class MyTimeout < GraphQL::Schema::Timeout
         
     | 
| 
      
 25 
     | 
    
         
            +
                #     def handle_timeout(error, query)
         
     | 
| 
      
 26 
     | 
    
         
            +
                #        Rails.logger.warn("GraphQL Timeout: #{error.message}: #{query.query_string}")
         
     | 
| 
      
 27 
     | 
    
         
            +
                #        Bugsnag.notify(error, {query_string: query.query_string})
         
     | 
| 
      
 28 
     | 
    
         
            +
                #     end
         
     | 
| 
      
 29 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 30 
     | 
    
         
            +
                #
         
     | 
| 
      
 31 
     | 
    
         
            +
                #   class MySchema < GraphQL::Schema
         
     | 
| 
      
 32 
     | 
    
         
            +
                #     use MyTimeout, max_seconds: 2
         
     | 
| 
      
 33 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 34 
     | 
    
         
            +
                #
         
     | 
| 
      
 35 
     | 
    
         
            +
                class Timeout
         
     | 
| 
      
 36 
     | 
    
         
            +
                  def self.use(schema, **options)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    tracer = new(**options)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    schema.tracer(tracer)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  # @param max_seconds [Numeric] how many seconds the query should be allowed to resolve new fields
         
     | 
| 
      
 42 
     | 
    
         
            +
                  def initialize(max_seconds:)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @max_seconds = max_seconds
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  def trace(key, data)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    case key
         
     | 
| 
      
 48 
     | 
    
         
            +
                    when 'execute_multiplex'
         
     | 
| 
      
 49 
     | 
    
         
            +
                      data.fetch(:multiplex).queries.each do |query|
         
     | 
| 
      
 50 
     | 
    
         
            +
                        timeout_duration_s = max_seconds(query)
         
     | 
| 
      
 51 
     | 
    
         
            +
                        timeout_state = if timeout_duration_s == false
         
     | 
| 
      
 52 
     | 
    
         
            +
                          # if the method returns `false`, don't apply a timeout
         
     | 
| 
      
 53 
     | 
    
         
            +
                          false
         
     | 
| 
      
 54 
     | 
    
         
            +
                        else
         
     | 
| 
      
 55 
     | 
    
         
            +
                          now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
         
     | 
| 
      
 56 
     | 
    
         
            +
                          timeout_at = now + (max_seconds(query) * 1000)
         
     | 
| 
      
 57 
     | 
    
         
            +
                          {
         
     | 
| 
      
 58 
     | 
    
         
            +
                            timeout_at: timeout_at,
         
     | 
| 
      
 59 
     | 
    
         
            +
                            timed_out: false
         
     | 
| 
      
 60 
     | 
    
         
            +
                          }
         
     | 
| 
      
 61 
     | 
    
         
            +
                        end
         
     | 
| 
      
 62 
     | 
    
         
            +
                        query.context.namespace(self.class)[:state] = timeout_state
         
     | 
| 
      
 63 
     | 
    
         
            +
                      end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                      yield
         
     | 
| 
      
 66 
     | 
    
         
            +
                    when 'execute_field', 'execute_field_lazy'
         
     | 
| 
      
 67 
     | 
    
         
            +
                      query_context = data[:context] || data[:query].context
         
     | 
| 
      
 68 
     | 
    
         
            +
                      timeout_state = query_context.namespace(self.class).fetch(:state)
         
     | 
| 
      
 69 
     | 
    
         
            +
                      # If the `:state` is `false`, then `max_seconds(query)` opted out of timeout for this query.
         
     | 
| 
      
 70 
     | 
    
         
            +
                      if timeout_state != false && Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) > timeout_state.fetch(:timeout_at)
         
     | 
| 
      
 71 
     | 
    
         
            +
                        error = if data[:context]
         
     | 
| 
      
 72 
     | 
    
         
            +
                          GraphQL::Schema::Timeout::TimeoutError.new(query_context.parent_type, query_context.field)
         
     | 
| 
      
 73 
     | 
    
         
            +
                        else
         
     | 
| 
      
 74 
     | 
    
         
            +
                          field = data.fetch(:field)
         
     | 
| 
      
 75 
     | 
    
         
            +
                          GraphQL::Schema::Timeout::TimeoutError.new(field.owner, field)
         
     | 
| 
      
 76 
     | 
    
         
            +
                        end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                        # Only invoke the timeout callback for the first timeout
         
     | 
| 
      
 79 
     | 
    
         
            +
                        if !timeout_state[:timed_out]
         
     | 
| 
      
 80 
     | 
    
         
            +
                          timeout_state[:timed_out] = true
         
     | 
| 
      
 81 
     | 
    
         
            +
                          handle_timeout(error, query_context.query)
         
     | 
| 
      
 82 
     | 
    
         
            +
                        end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                        error
         
     | 
| 
      
 85 
     | 
    
         
            +
                      else
         
     | 
| 
      
 86 
     | 
    
         
            +
                        yield
         
     | 
| 
      
 87 
     | 
    
         
            +
                      end
         
     | 
| 
      
 88 
     | 
    
         
            +
                    else
         
     | 
| 
      
 89 
     | 
    
         
            +
                      yield
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  # Called at the start of each query.
         
     | 
| 
      
 94 
     | 
    
         
            +
                  # The default implementation returns the `max_seconds:` value from installing this plugin.
         
     | 
| 
      
 95 
     | 
    
         
            +
                  #
         
     | 
| 
      
 96 
     | 
    
         
            +
                  # @param query [GraphQL::Query] The query that's about to run
         
     | 
| 
      
 97 
     | 
    
         
            +
                  # @return [Integer, false] The number of seconds after which to interrupt query execution and call {#handle_error}, or `false` to bypass the timeout.
         
     | 
| 
      
 98 
     | 
    
         
            +
                  def max_seconds(query)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    @max_seconds
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                  # Invoked when a query times out.
         
     | 
| 
      
 103 
     | 
    
         
            +
                  # @param error [GraphQL::Schema::Timeout::TimeoutError]
         
     | 
| 
      
 104 
     | 
    
         
            +
                  # @param query [GraphQL::Error]
         
     | 
| 
      
 105 
     | 
    
         
            +
                  def handle_timeout(error, query)
         
     | 
| 
      
 106 
     | 
    
         
            +
                    # override to do something interesting
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  # This error is raised when a query exceeds `max_seconds`.
         
     | 
| 
      
 110 
     | 
    
         
            +
                  # Since it's a child of {GraphQL::ExecutionError},
         
     | 
| 
      
 111 
     | 
    
         
            +
                  # its message will be added to the response's `errors` key.
         
     | 
| 
      
 112 
     | 
    
         
            +
                  #
         
     | 
| 
      
 113 
     | 
    
         
            +
                  # To raise an error that will stop query resolution, use a custom block
         
     | 
| 
      
 114 
     | 
    
         
            +
                  # to take this error and raise a new one which _doesn't_ descend from {GraphQL::ExecutionError},
         
     | 
| 
      
 115 
     | 
    
         
            +
                  # such as `RuntimeError`.
         
     | 
| 
      
 116 
     | 
    
         
            +
                  class TimeoutError < GraphQL::ExecutionError
         
     | 
| 
      
 117 
     | 
    
         
            +
                    def initialize(parent_type, field)
         
     | 
| 
      
 118 
     | 
    
         
            +
                      super("Timeout on #{parent_type.graphql_name}.#{field.graphql_name}")
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
              end
         
     | 
| 
      
 123 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,17 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
       1 
2 
     | 
    
         
             
            module GraphQL
         
     | 
| 
       2 
3 
     | 
    
         
             
              class Schema
         
     | 
| 
      
 4 
     | 
    
         
            +
                # @api private
         
     | 
| 
       3 
5 
     | 
    
         
             
                module TypeExpression
         
     | 
| 
       4 
     | 
    
         
            -
                   
     | 
| 
      
 6 
     | 
    
         
            +
                  # Fetch a type from a type map by its AST specification.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # Return `nil` if not found.
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @param type_owner [#get_type] A thing for looking up types by name
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # @param ast_node [GraphQL::Language::Nodes::AbstractNode]
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # @return [Class, GraphQL::Schema::NonNull, GraphQL::Schema:List]
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def self.build_type(type_owner, ast_node)
         
     | 
| 
       5 
12 
     | 
    
         
             
                    case ast_node
         
     | 
| 
       6 
13 
     | 
    
         
             
                    when GraphQL::Language::Nodes::TypeName
         
     | 
| 
       7 
     | 
    
         
            -
                       
     | 
| 
       8 
     | 
    
         
            -
                      schema.types[type_name]
         
     | 
| 
      
 14 
     | 
    
         
            +
                      type_owner.get_type(ast_node.name) # rubocop:disable Development/ContextIsPassedCop -- this is a `context` or `warden`, it's already query-aware
         
     | 
| 
       9 
15 
     | 
    
         
             
                    when GraphQL::Language::Nodes::NonNullType
         
     | 
| 
       10 
16 
     | 
    
         
             
                      ast_inner_type = ast_node.of_type
         
     | 
| 
       11 
     | 
    
         
            -
                      build_type( 
     | 
| 
      
 17 
     | 
    
         
            +
                      inner_type = build_type(type_owner, ast_inner_type)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      wrap_type(inner_type, :to_non_null_type)
         
     | 
| 
       12 
19 
     | 
    
         
             
                    when GraphQL::Language::Nodes::ListType
         
     | 
| 
       13 
20 
     | 
    
         
             
                      ast_inner_type = ast_node.of_type
         
     | 
| 
       14 
     | 
    
         
            -
                      build_type( 
     | 
| 
      
 21 
     | 
    
         
            +
                      inner_type = build_type(type_owner, ast_inner_type)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      wrap_type(inner_type, :to_list_type)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    else
         
     | 
| 
      
 24 
     | 
    
         
            +
                      raise "Invariant: unexpected type from ast: #{ast_node.inspect}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 29 
     | 
    
         
            +
                    private
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    def wrap_type(type, wrapper_method)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      if type.nil?
         
     | 
| 
      
 33 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 34 
     | 
    
         
            +
                      elsif wrapper_method == :to_list_type || wrapper_method == :to_non_null_type
         
     | 
| 
      
 35 
     | 
    
         
            +
                        type.public_send(wrapper_method)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      else
         
     | 
| 
      
 37 
     | 
    
         
            +
                        raise ArgumentError, "Unexpected wrapper method: #{wrapper_method.inspect}"
         
     | 
| 
      
 38 
     | 
    
         
            +
                      end
         
     | 
| 
       15 
39 
     | 
    
         
             
                    end
         
     | 
| 
       16 
40 
     | 
    
         
             
                  end
         
     | 
| 
       17 
41 
     | 
    
         
             
                end
         
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 5 
     | 
    
         
            +
                # This class joins an object type to an abstract type (interface or union) of which
         
     | 
| 
      
 6 
     | 
    
         
            +
                # it is a member.
         
     | 
| 
      
 7 
     | 
    
         
            +
                class TypeMembership
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @return [Class<GraphQL::Schema::Object>]
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_accessor :object_type
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  # @return [Class<GraphQL::Schema::Union>, Module<GraphQL::Schema::Interface>]
         
     | 
| 
      
 12 
     | 
    
         
            +
                  attr_reader :abstract_type
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  # @return [Hash]
         
     | 
| 
      
 15 
     | 
    
         
            +
                  attr_reader :options
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  # Called when an object is hooked up to an abstract type, such as {Schema::Union.possible_types}
         
     | 
| 
      
 18 
     | 
    
         
            +
                  # or {Schema::Object.implements} (for interfaces).
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # @param abstract_type [Class<GraphQL::Schema::Union>, Module<GraphQL::Schema::Interface>]
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # @param object_type [Class<GraphQL::Schema::Object>]
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # @param options [Hash] Any options passed to `.possible_types` or `.implements`
         
     | 
| 
      
 23 
     | 
    
         
            +
                  def initialize(abstract_type, object_type, **options)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @abstract_type = abstract_type
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @object_type = object_type
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @options = options
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  # @return [Boolean] if false, {#object_type} will be treated as _not_ a member of {#abstract_type}
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def visible?(ctx)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    warden = Warden.from_context(ctx)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    (@object_type.respond_to?(:visible?) ? warden.visible_type?(@object_type, ctx) : true) &&
         
     | 
| 
      
 33 
     | 
    
         
            +
                      (@abstract_type.respond_to?(:visible?) ? warden.visible_type?(@abstract_type, ctx) : true)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def graphql_name
         
     | 
| 
      
 37 
     | 
    
         
            +
                    "#{@object_type.graphql_name}.#{@abstract_type.kind.interface? ? "implements" : "belongsTo" }.#{@abstract_type.graphql_name}"
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  def path
         
     | 
| 
      
 41 
     | 
    
         
            +
                    graphql_name
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  def inspect
         
     | 
| 
      
 45 
     | 
    
         
            +
                    "#<#{self.class} #{@object_type.inspect} => #{@abstract_type.inspect}>"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  alias :type_class :itself
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,81 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 3 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 4 
     | 
    
         
            +
                class Union < GraphQL::Schema::Member
         
     | 
| 
      
 5 
     | 
    
         
            +
                  extend GraphQL::Schema::Member::HasUnresolvedTypeError
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                    def inherited(child_class)
         
     | 
| 
      
 9 
     | 
    
         
            +
                      add_unresolved_type_error(child_class)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      super
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    def possible_types(*types, context: GraphQL::Query::NullContext, **options)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      if types.any?
         
     | 
| 
      
 15 
     | 
    
         
            +
                        types.each do |t|
         
     | 
| 
      
 16 
     | 
    
         
            +
                          assert_valid_union_member(t)
         
     | 
| 
      
 17 
     | 
    
         
            +
                          type_memberships << type_membership_class.new(self, t, **options)
         
     | 
| 
      
 18 
     | 
    
         
            +
                        end
         
     | 
| 
      
 19 
     | 
    
         
            +
                      else
         
     | 
| 
      
 20 
     | 
    
         
            +
                        visible_types = []
         
     | 
| 
      
 21 
     | 
    
         
            +
                        warden = Warden.from_context(context)
         
     | 
| 
      
 22 
     | 
    
         
            +
                        type_memberships.each do |type_membership|
         
     | 
| 
      
 23 
     | 
    
         
            +
                          if warden.visible_type_membership?(type_membership, context)
         
     | 
| 
      
 24 
     | 
    
         
            +
                            visible_types << type_membership.object_type
         
     | 
| 
      
 25 
     | 
    
         
            +
                          end
         
     | 
| 
      
 26 
     | 
    
         
            +
                        end
         
     | 
| 
      
 27 
     | 
    
         
            +
                        visible_types
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    def all_possible_types
         
     | 
| 
      
 32 
     | 
    
         
            +
                      type_memberships.map(&:object_type)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    def type_membership_class(membership_class = nil)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      if membership_class
         
     | 
| 
      
 37 
     | 
    
         
            +
                        @type_membership_class = membership_class
         
     | 
| 
      
 38 
     | 
    
         
            +
                      else
         
     | 
| 
      
 39 
     | 
    
         
            +
                        @type_membership_class || find_inherited_value(:type_membership_class, GraphQL::Schema::TypeMembership)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      end
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    def kind
         
     | 
| 
      
 44 
     | 
    
         
            +
                      GraphQL::TypeKinds::UNION
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    def type_memberships
         
     | 
| 
      
 48 
     | 
    
         
            +
                      @type_memberships ||= []
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    # Update a type membership whose `.object_type` is a string or late-bound type
         
     | 
| 
      
 52 
     | 
    
         
            +
                    # so that the type membership's `.object_type` is the given `object_type`.
         
     | 
| 
      
 53 
     | 
    
         
            +
                    # (This is used for updating the union after the schema as lazily loaded the union member.)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    # @api private
         
     | 
| 
      
 55 
     | 
    
         
            +
                    def assign_type_membership_object_type(object_type)
         
     | 
| 
      
 56 
     | 
    
         
            +
                      assert_valid_union_member(object_type)
         
     | 
| 
      
 57 
     | 
    
         
            +
                      type_memberships.each { |tm|
         
     | 
| 
      
 58 
     | 
    
         
            +
                        possible_type = tm.object_type
         
     | 
| 
      
 59 
     | 
    
         
            +
                        if possible_type.is_a?(String) && (possible_type == object_type.name)
         
     | 
| 
      
 60 
     | 
    
         
            +
                          # This is a match of Ruby class names, not graphql names,
         
     | 
| 
      
 61 
     | 
    
         
            +
                          # since strings are used to refer to constants.
         
     | 
| 
      
 62 
     | 
    
         
            +
                          tm.object_type = object_type
         
     | 
| 
      
 63 
     | 
    
         
            +
                        elsif possible_type.is_a?(LateBoundType) && possible_type.graphql_name == object_type.graphql_name
         
     | 
| 
      
 64 
     | 
    
         
            +
                          tm.object_type = object_type
         
     | 
| 
      
 65 
     | 
    
         
            +
                        end
         
     | 
| 
      
 66 
     | 
    
         
            +
                      }
         
     | 
| 
      
 67 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    private
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                    def assert_valid_union_member(type_defn)
         
     | 
| 
      
 73 
     | 
    
         
            +
                      if type_defn.is_a?(Module) && !type_defn.is_a?(Class)
         
     | 
| 
      
 74 
     | 
    
         
            +
                        # it's an interface type, defined as a module
         
     | 
| 
      
 75 
     | 
    
         
            +
                        raise ArgumentError, "Union possible_types can only be object types (not interface types), remove #{type_defn.graphql_name} (#{type_defn.inspect})"
         
     | 
| 
      
 76 
     | 
    
         
            +
                      end
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
              end
         
     | 
| 
      
 81 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'graphql/schema/base_64_bp'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 6 
     | 
    
         
            +
                module UniqueWithinType
         
     | 
| 
      
 7 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                    attr_accessor :default_id_separator
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
                  self.default_id_separator = "-"
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  module_function
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  # @param type_name [String]
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # @param object_value [Any]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # @return [String] a unique, opaque ID generated as a function of the two inputs
         
     | 
| 
      
 17 
     | 
    
         
            +
                  def encode(type_name, object_value, separator: self.default_id_separator)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    object_value_str = object_value.to_s
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    if type_name.include?(separator)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      raise "encode(#{type_name}, #{object_value_str}) contains reserved characters `#{separator}` in the type name"
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    Base64.strict_encode64([type_name, object_value_str].join(separator))
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  # @param node_id [String] A unique ID generated by {.encode}
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # @return [Array<(String, String)>] The type name & value passed to {.encode}
         
     | 
| 
      
 29 
     | 
    
         
            +
                  def decode(node_id, separator: self.default_id_separator)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    GraphQL::Schema::Base64Encoder.decode(node_id).split(separator, 2)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Validator
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Use this to specifically reject values that respond to `.blank?` and respond truthy for that method.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @example Require a non-empty string for an argument
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #   argument :name, String, required: true, validate: { allow_blank: false }
         
     | 
| 
      
 10 
     | 
    
         
            +
                  class AllowBlankValidator < Validator
         
     | 
| 
      
 11 
     | 
    
         
            +
                    def initialize(allow_blank_positional, allow_blank: nil, message: "%{validated} can't be blank", **default_options)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      @message = message
         
     | 
| 
      
 13 
     | 
    
         
            +
                      super(**default_options)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      @allow_blank = allow_blank.nil? ? allow_blank_positional : allow_blank
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    def validate(_object, _context, value)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      if value.respond_to?(:blank?) && value.blank?
         
     | 
| 
      
 19 
     | 
    
         
            +
                        if (value.nil? && @allow_null) || @allow_blank
         
     | 
| 
      
 20 
     | 
    
         
            +
                          # pass
         
     | 
| 
      
 21 
     | 
    
         
            +
                        else
         
     | 
| 
      
 22 
     | 
    
         
            +
                          @message
         
     | 
| 
      
 23 
     | 
    
         
            +
                        end
         
     | 
| 
      
 24 
     | 
    
         
            +
                      end
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Validator
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Use this to specifically reject or permit `nil` values (given as `null` from GraphQL).
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @example require a non-null value for an argument if it is provided
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #   argument :name, String, required: false, validates: { allow_null: false }
         
     | 
| 
      
 10 
     | 
    
         
            +
                  class AllowNullValidator < Validator
         
     | 
| 
      
 11 
     | 
    
         
            +
                    MESSAGE = "%{validated} can't be null"
         
     | 
| 
      
 12 
     | 
    
         
            +
                    def initialize(allow_null_positional, allow_null: nil, message: MESSAGE, **default_options)
         
     | 
| 
      
 13 
     | 
    
         
            +
                      @message = message
         
     | 
| 
      
 14 
     | 
    
         
            +
                      super(**default_options)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      @allow_null = allow_null.nil? ? allow_null_positional : allow_null
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    def validate(_object, _context, value)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      if value.nil? && !@allow_null
         
     | 
| 
      
 20 
     | 
    
         
            +
                        @message
         
     | 
| 
      
 21 
     | 
    
         
            +
                      end
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Validator
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Use this to specifically reject values from an argument.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @example disallow certain values
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #   argument :favorite_non_prime, Integer, required: true,
         
     | 
| 
      
 11 
     | 
    
         
            +
                  #     validates: { exclusion: { in: [2, 3, 5, 7, ... ]} }
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #
         
     | 
| 
      
 13 
     | 
    
         
            +
                  class ExclusionValidator < Validator
         
     | 
| 
      
 14 
     | 
    
         
            +
                    # @param message [String]
         
     | 
| 
      
 15 
     | 
    
         
            +
                    # @param in [Array] The values to reject
         
     | 
| 
      
 16 
     | 
    
         
            +
                    def initialize(message: "%{validated} is reserved", in:, **default_options)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      # `in` is a reserved word, so work around that
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @in_list = binding.local_variable_get(:in)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @message = message
         
     | 
| 
      
 20 
     | 
    
         
            +
                      super(**default_options)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    def validate(_object, _context, value)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      if permitted_empty_value?(value)
         
     | 
| 
      
 25 
     | 
    
         
            +
                        # pass
         
     | 
| 
      
 26 
     | 
    
         
            +
                      elsif @in_list.include?(value)
         
     | 
| 
      
 27 
     | 
    
         
            +
                        @message
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,48 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Validator
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Use this to assert that string values match (or don't match) the given RegExp.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @example requiring input to match a pattern
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #   argument :handle, String, required: true,
         
     | 
| 
      
 11 
     | 
    
         
            +
                  #     validates: { format: { with: /\A[a-z0-9_]+\Z/ } }
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # @example reject inputs that match a pattern
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #   argument :word_that_doesnt_begin_with_a_vowel, String, required: true,
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #     validates: { format: { without: /\A[aeiou]/ } }
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #   # It's pretty hard to come up with a legitimate use case for `without:`
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #
         
     | 
| 
      
 20 
     | 
    
         
            +
                  class FormatValidator < Validator
         
     | 
| 
      
 21 
     | 
    
         
            +
                    # @param with [RegExp, nil]
         
     | 
| 
      
 22 
     | 
    
         
            +
                    # @param without [Regexp, nil]
         
     | 
| 
      
 23 
     | 
    
         
            +
                    # @param message [String]
         
     | 
| 
      
 24 
     | 
    
         
            +
                    def initialize(
         
     | 
| 
      
 25 
     | 
    
         
            +
                      with: nil,
         
     | 
| 
      
 26 
     | 
    
         
            +
                      without: nil,
         
     | 
| 
      
 27 
     | 
    
         
            +
                      message: "%{validated} is invalid",
         
     | 
| 
      
 28 
     | 
    
         
            +
                      **default_options
         
     | 
| 
      
 29 
     | 
    
         
            +
                    )
         
     | 
| 
      
 30 
     | 
    
         
            +
                      @with_pattern = with
         
     | 
| 
      
 31 
     | 
    
         
            +
                      @without_pattern = without
         
     | 
| 
      
 32 
     | 
    
         
            +
                      @message = message
         
     | 
| 
      
 33 
     | 
    
         
            +
                      super(**default_options)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    def validate(_object, _context, value)
         
     | 
| 
      
 37 
     | 
    
         
            +
                      if permitted_empty_value?(value)
         
     | 
| 
      
 38 
     | 
    
         
            +
                        # Do nothing
         
     | 
| 
      
 39 
     | 
    
         
            +
                      elsif value.nil? ||
         
     | 
| 
      
 40 
     | 
    
         
            +
                          (@with_pattern && !value.match?(@with_pattern)) ||
         
     | 
| 
      
 41 
     | 
    
         
            +
                          (@without_pattern && value.match?(@without_pattern))
         
     | 
| 
      
 42 
     | 
    
         
            +
                        @message
         
     | 
| 
      
 43 
     | 
    
         
            +
                      end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
            end
         
     |