graphql_cody 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +5 -0
- data/MIT-LICENSE +20 -0
- data/lib/generators/graphql/core.rb +74 -0
- data/lib/generators/graphql/enum_generator.rb +33 -0
- data/lib/generators/graphql/install_generator.rb +190 -0
- data/lib/generators/graphql/interface_generator.rb +27 -0
- data/lib/generators/graphql/loader_generator.rb +21 -0
- data/lib/generators/graphql/mutation_generator.rb +55 -0
- data/lib/generators/graphql/object_generator.rb +79 -0
- data/lib/generators/graphql/relay.rb +63 -0
- data/lib/generators/graphql/relay_generator.rb +21 -0
- data/lib/generators/graphql/scalar_generator.rb +20 -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_mutation.erb +10 -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 +7 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +52 -0
- data/lib/generators/graphql/templates/interface.erb +8 -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_type.erb +12 -0
- data/lib/generators/graphql/templates/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +8 -0
- data/lib/generators/graphql/templates/query_type.erb +15 -0
- data/lib/generators/graphql/templates/scalar.erb +15 -0
- data/lib/generators/graphql/templates/schema.erb +27 -0
- data/lib/generators/graphql/templates/union.erb +7 -0
- data/lib/generators/graphql/type_generator.rb +98 -0
- data/lib/generators/graphql/union_generator.rb +33 -0
- data/lib/graphql/analysis/analyze_query.rb +98 -0
- data/lib/graphql/analysis/ast/analyzer.rb +84 -0
- data/lib/graphql/analysis/ast/field_usage.rb +51 -0
- data/lib/graphql/analysis/ast/max_query_complexity.rb +23 -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 +56 -0
- data/lib/graphql/analysis/ast/visitor.rb +268 -0
- data/lib/graphql/analysis/ast.rb +91 -0
- data/lib/graphql/analysis/field_usage.rb +45 -0
- data/lib/graphql/analysis/max_query_complexity.rb +26 -0
- data/lib/graphql/analysis/max_query_depth.rb +26 -0
- data/lib/graphql/analysis/query_complexity.rb +88 -0
- data/lib/graphql/analysis/query_depth.rb +43 -0
- data/lib/graphql/analysis/reducer_state.rb +48 -0
- data/lib/graphql/analysis.rb +9 -0
- data/lib/graphql/analysis_error.rb +5 -0
- data/lib/graphql/argument.rb +131 -0
- data/lib/graphql/authorization.rb +82 -0
- data/lib/graphql/backtrace/inspect_result.rb +50 -0
- data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
- data/lib/graphql/backtrace/table.rb +159 -0
- data/lib/graphql/backtrace/traced_error.rb +54 -0
- data/lib/graphql/backtrace/tracer.rb +81 -0
- data/lib/graphql/backtrace.rb +64 -0
- data/lib/graphql/backwards_compatibility.rb +61 -0
- data/lib/graphql/base_type.rb +230 -0
- data/lib/graphql/boolean_type.rb +2 -0
- data/lib/graphql/coercion_error.rb +13 -0
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +53 -0
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +200 -0
- data/lib/graphql/compatibility/execution_specification.rb +436 -0
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +111 -0
- data/lib/graphql/compatibility/lazy_execution_specification.rb +215 -0
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +87 -0
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +79 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +266 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +682 -0
- data/lib/graphql/compatibility.rb +5 -0
- data/lib/graphql/dataloader/null_dataloader.rb +22 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +155 -0
- data/lib/graphql/dataloader.rb +308 -0
- data/lib/graphql/define/assign_argument.rb +12 -0
- data/lib/graphql/define/assign_connection.rb +13 -0
- data/lib/graphql/define/assign_enum_value.rb +18 -0
- data/lib/graphql/define/assign_global_id_field.rb +11 -0
- data/lib/graphql/define/assign_mutation_function.rb +34 -0
- data/lib/graphql/define/assign_object_field.rb +42 -0
- data/lib/graphql/define/defined_object_proxy.rb +53 -0
- data/lib/graphql/define/instance_definable.rb +240 -0
- data/lib/graphql/define/no_definition_error.rb +7 -0
- data/lib/graphql/define/non_null_with_bang.rb +16 -0
- data/lib/graphql/define/type_definer.rb +31 -0
- data/lib/graphql/define.rb +31 -0
- data/lib/graphql/deprecated_dsl.rb +55 -0
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/dig.rb +19 -0
- data/lib/graphql/directive/deprecated_directive.rb +2 -0
- data/lib/graphql/directive/include_directive.rb +2 -0
- data/lib/graphql/directive/skip_directive.rb +2 -0
- data/lib/graphql/directive.rb +107 -0
- data/lib/graphql/enum_type.rb +133 -0
- data/lib/graphql/execution/directive_checks.rb +37 -0
- data/lib/graphql/execution/errors.rb +163 -0
- data/lib/graphql/execution/execute.rb +333 -0
- data/lib/graphql/execution/flatten.rb +40 -0
- data/lib/graphql/execution/instrumentation.rb +92 -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 +103 -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 +70 -0
- data/lib/graphql/execution/interpreter/runtime.rb +949 -0
- data/lib/graphql/execution/interpreter.rb +122 -0
- data/lib/graphql/execution/lazy/lazy_method_map.rb +98 -0
- data/lib/graphql/execution/lazy/resolve.rb +91 -0
- data/lib/graphql/execution/lazy.rb +83 -0
- data/lib/graphql/execution/lookahead.rb +307 -0
- data/lib/graphql/execution/multiplex.rb +214 -0
- data/lib/graphql/execution/typecast.rb +50 -0
- data/lib/graphql/execution.rb +11 -0
- data/lib/graphql/execution_error.rb +58 -0
- data/lib/graphql/field/resolve.rb +59 -0
- data/lib/graphql/field.rb +226 -0
- data/lib/graphql/filter.rb +53 -0
- data/lib/graphql/float_type.rb +2 -0
- data/lib/graphql/function.rb +128 -0
- data/lib/graphql/id_type.rb +2 -0
- data/lib/graphql/input_object_type.rb +138 -0
- data/lib/graphql/int_type.rb +2 -0
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +36 -0
- data/lib/graphql/interface_type.rb +72 -0
- data/lib/graphql/internal_representation/document.rb +27 -0
- data/lib/graphql/internal_representation/node.rb +206 -0
- data/lib/graphql/internal_representation/print.rb +51 -0
- data/lib/graphql/internal_representation/rewrite.rb +184 -0
- data/lib/graphql/internal_representation/scope.rb +88 -0
- data/lib/graphql/internal_representation/visit.rb +36 -0
- data/lib/graphql/internal_representation.rb +7 -0
- data/lib/graphql/introspection/base_object.rb +13 -0
- data/lib/graphql/introspection/directive_location_enum.rb +15 -0
- data/lib/graphql/introspection/directive_type.rb +29 -0
- data/lib/graphql/introspection/dynamic_fields.rb +17 -0
- data/lib/graphql/introspection/entry_points.rb +35 -0
- data/lib/graphql/introspection/enum_value_type.rb +23 -0
- data/lib/graphql/introspection/field_type.rb +28 -0
- data/lib/graphql/introspection/input_value_type.rb +67 -0
- data/lib/graphql/introspection/introspection_query.rb +7 -0
- data/lib/graphql/introspection/schema_type.rb +44 -0
- data/lib/graphql/introspection/type_kind_enum.rb +13 -0
- data/lib/graphql/introspection/type_type.rb +95 -0
- data/lib/graphql/introspection.rb +114 -0
- data/lib/graphql/invalid_name_error.rb +11 -0
- data/lib/graphql/invalid_null_error.rb +50 -0
- 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 +347 -0
- data/lib/graphql/language/generation.rb +24 -0
- data/lib/graphql/language/lexer.rb +1467 -0
- data/lib/graphql/language/lexer.rl +258 -0
- data/lib/graphql/language/nodes.rb +707 -0
- data/lib/graphql/language/parser.rb +1974 -0
- data/lib/graphql/language/parser.y +544 -0
- data/lib/graphql/language/printer.rb +366 -0
- data/lib/graphql/language/sanitized_printer.rb +222 -0
- data/lib/graphql/language/token.rb +34 -0
- data/lib/graphql/language/visitor.rb +242 -0
- data/lib/graphql/language.rb +36 -0
- data/lib/graphql/list_type.rb +80 -0
- data/lib/graphql/load_application_object_failed_error.rb +22 -0
- data/lib/graphql/name_validator.rb +11 -0
- data/lib/graphql/non_null_type.rb +71 -0
- data/lib/graphql/object_type.rb +130 -0
- data/lib/graphql/pagination/active_record_relation_connection.rb +48 -0
- data/lib/graphql/pagination/array_connection.rb +77 -0
- data/lib/graphql/pagination/connection.rb +226 -0
- data/lib/graphql/pagination/connections.rb +160 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +196 -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/arguments.rb +189 -0
- data/lib/graphql/query/arguments_cache.rb +24 -0
- data/lib/graphql/query/context.rb +371 -0
- data/lib/graphql/query/executor.rb +52 -0
- data/lib/graphql/query/fingerprint.rb +26 -0
- data/lib/graphql/query/input_validation_result.rb +43 -0
- data/lib/graphql/query/literal_input.rb +136 -0
- data/lib/graphql/query/null_context.rb +55 -0
- data/lib/graphql/query/result.rb +63 -0
- data/lib/graphql/query/serial_execution/field_resolution.rb +92 -0
- data/lib/graphql/query/serial_execution/operation_resolution.rb +19 -0
- data/lib/graphql/query/serial_execution/selection_resolution.rb +23 -0
- data/lib/graphql/query/serial_execution/value_resolution.rb +87 -0
- data/lib/graphql/query/serial_execution.rb +40 -0
- data/lib/graphql/query/validation_pipeline.rb +139 -0
- data/lib/graphql/query/variable_validation_error.rb +44 -0
- data/lib/graphql/query/variables.rb +78 -0
- data/lib/graphql/query.rb +454 -0
- data/lib/graphql/railtie.rb +117 -0
- data/lib/graphql/rake_task/validate.rb +63 -0
- data/lib/graphql/rake_task.rb +145 -0
- data/lib/graphql/relay/array_connection.rb +83 -0
- data/lib/graphql/relay/base_connection.rb +189 -0
- data/lib/graphql/relay/connection_instrumentation.rb +54 -0
- data/lib/graphql/relay/connection_resolve.rb +43 -0
- data/lib/graphql/relay/connection_type.rb +41 -0
- data/lib/graphql/relay/edge.rb +27 -0
- data/lib/graphql/relay/edge_type.rb +19 -0
- data/lib/graphql/relay/edges_instrumentation.rb +39 -0
- data/lib/graphql/relay/global_id_resolve.rb +18 -0
- data/lib/graphql/relay/mongo_relation_connection.rb +50 -0
- data/lib/graphql/relay/mutation/instrumentation.rb +23 -0
- data/lib/graphql/relay/mutation/resolve.rb +56 -0
- data/lib/graphql/relay/mutation/result.rb +38 -0
- data/lib/graphql/relay/mutation.rb +106 -0
- data/lib/graphql/relay/node.rb +39 -0
- data/lib/graphql/relay/page_info.rb +7 -0
- data/lib/graphql/relay/range_add.rb +59 -0
- data/lib/graphql/relay/relation_connection.rb +188 -0
- data/lib/graphql/relay/type_extensions.rb +32 -0
- data/lib/graphql/relay.rb +18 -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/scalar_type.rb +91 -0
- data/lib/graphql/schema/addition.rb +247 -0
- data/lib/graphql/schema/argument.rb +383 -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 +477 -0
- data/lib/graphql/schema/built_in_types.rb +12 -0
- data/lib/graphql/schema/catchall_middleware.rb +35 -0
- data/lib/graphql/schema/default_parse_error.rb +10 -0
- data/lib/graphql/schema/default_type_error.rb +17 -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/skip.rb +25 -0
- data/lib/graphql/schema/directive/transform.rb +60 -0
- data/lib/graphql/schema/directive.rb +210 -0
- data/lib/graphql/schema/enum.rb +193 -0
- data/lib/graphql/schema/enum_value.rb +97 -0
- data/lib/graphql/schema/field/connection_extension.rb +76 -0
- data/lib/graphql/schema/field/scope_extension.rb +22 -0
- data/lib/graphql/schema/field.rb +880 -0
- data/lib/graphql/schema/field_extension.rb +69 -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 +253 -0
- data/lib/graphql/schema/interface.rb +136 -0
- data/lib/graphql/schema/introspection_system.rb +169 -0
- data/lib/graphql/schema/invalid_type_error.rb +7 -0
- data/lib/graphql/schema/late_bound_type.rb +33 -0
- data/lib/graphql/schema/list.rb +75 -0
- data/lib/graphql/schema/loader.rb +226 -0
- data/lib/graphql/schema/member/accepts_definition.rb +159 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +129 -0
- data/lib/graphql/schema/member/build_type.rb +180 -0
- data/lib/graphql/schema/member/cached_graphql_definition.rb +31 -0
- data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
- data/lib/graphql/schema/member/has_arguments.rb +332 -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 +98 -0
- data/lib/graphql/schema/member/has_fields.rb +163 -0
- data/lib/graphql/schema/member/has_interfaces.rb +90 -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/instrumentation.rb +131 -0
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -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 +161 -0
- data/lib/graphql/schema/middleware_chain.rb +82 -0
- data/lib/graphql/schema/mutation.rb +94 -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 +150 -0
- data/lib/graphql/schema/possible_types.rb +44 -0
- data/lib/graphql/schema/printer.rb +100 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +160 -0
- data/lib/graphql/schema/rescue_middleware.rb +60 -0
- data/lib/graphql/schema/resolver/has_payload_type.rb +96 -0
- data/lib/graphql/schema/resolver.rb +397 -0
- data/lib/graphql/schema/scalar.rb +69 -0
- data/lib/graphql/schema/subscription.rb +155 -0
- data/lib/graphql/schema/timeout.rb +123 -0
- data/lib/graphql/schema/timeout_middleware.rb +88 -0
- data/lib/graphql/schema/traversal.rb +228 -0
- data/lib/graphql/schema/type_expression.rb +43 -0
- data/lib/graphql/schema/type_membership.rb +48 -0
- data/lib/graphql/schema/union.rb +95 -0
- data/lib/graphql/schema/unique_within_type.rb +34 -0
- data/lib/graphql/schema/validation.rb +313 -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 +68 -0
- data/lib/graphql/schema/validator.rb +174 -0
- data/lib/graphql/schema/warden.rb +409 -0
- data/lib/graphql/schema/wrapper.rb +29 -0
- data/lib/graphql/schema.rb +1945 -0
- data/lib/graphql/static_validation/all_rules.rb +40 -0
- data/lib/graphql/static_validation/base_visitor.rb +217 -0
- data/lib/graphql/static_validation/default_visitor.rb +15 -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 +139 -0
- data/lib/graphql/static_validation/no_validate_visitor.rb +10 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +66 -0
- 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 +71 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +37 -0
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +23 -0
- 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 +65 -0
- 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 +30 -0
- 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 +73 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +418 -0
- 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 +73 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +39 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +21 -0
- 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 +37 -0
- 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 +32 -0
- 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/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/required_arguments_are_present.rb +37 -0
- 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 +50 -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 +46 -0
- 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 +153 -0
- 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 +39 -0
- 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 +155 -0
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
- data/lib/graphql/static_validation/type_stack.rb +216 -0
- data/lib/graphql/static_validation/validation_context.rb +49 -0
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +96 -0
- data/lib/graphql/static_validation.rb +19 -0
- data/lib/graphql/string_encoding_error.rb +20 -0
- data/lib/graphql/string_type.rb +2 -0
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +245 -0
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
- data/lib/graphql/subscriptions/event.rb +144 -0
- data/lib/graphql/subscriptions/instrumentation.rb +79 -0
- data/lib/graphql/subscriptions/serialize.rb +138 -0
- data/lib/graphql/subscriptions/subscription_root.rb +76 -0
- data/lib/graphql/subscriptions.rb +299 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +35 -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 +76 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +51 -0
- data/lib/graphql/tracing/platform_tracing.rb +139 -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/skylight_tracing.rb +70 -0
- data/lib/graphql/tracing/statsd_tracing.rb +42 -0
- data/lib/graphql/tracing.rb +95 -0
- data/lib/graphql/type_kinds.rb +77 -0
- 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 +34 -0
- data/lib/graphql/types/iso_8601_date_time.rb +65 -0
- data/lib/graphql/types/json.rb +25 -0
- data/lib/graphql/types/relay/base_connection.rb +39 -0
- data/lib/graphql/types/relay/base_edge.rb +29 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +156 -0
- data/lib/graphql/types/relay/default_relay.rb +27 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +53 -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 +15 -0
- data/lib/graphql/types/relay/node_field.rb +25 -0
- data/lib/graphql/types/relay/nodes_field.rb +27 -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 +41 -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/union_type.rb +115 -0
- data/lib/graphql/unresolved_type_error.rb +35 -0
- data/lib/graphql/upgrader/member.rb +937 -0
- data/lib/graphql/upgrader/schema.rb +38 -0
- data/lib/graphql/version.rb +4 -0
- data/lib/graphql.rb +168 -0
- data/readme.md +49 -0
- metadata +714 -0
@@ -0,0 +1,313 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
# This module provides a function for validating GraphQL types.
|
5
|
+
#
|
6
|
+
# Its {RULES} contain objects that respond to `#call(type)`. Rules are
|
7
|
+
# looked up for given types (by class ancestry), then applied to
|
8
|
+
# the object until an error is returned.
|
9
|
+
#
|
10
|
+
# Remove this in GraphQL-Ruby 2.0 when schema instances are removed.
|
11
|
+
class Validation
|
12
|
+
# Lookup the rules for `object` based on its class,
|
13
|
+
# Then returns an error message or `nil`
|
14
|
+
# @param object [Object] something to be validated
|
15
|
+
# @return [String, Nil] error message, if there was one
|
16
|
+
def self.validate(object)
|
17
|
+
RULES.each do |parent_class, validations|
|
18
|
+
if object.is_a?(parent_class)
|
19
|
+
validations.each do |rule|
|
20
|
+
if error = rule.call(object)
|
21
|
+
return error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
module Rules
|
30
|
+
# @param property_name [Symbol] The method to validate
|
31
|
+
# @param allowed_classes [Class] Classes which the return value may be an instance of
|
32
|
+
# @return [Proc] A proc which will validate the input by calling `property_name` and asserting it is an instance of one of `allowed_classes`
|
33
|
+
def self.assert_property(property_name, *allowed_classes)
|
34
|
+
# Hide LateBoundType from user-facing errors
|
35
|
+
allowed_classes_message = allowed_classes.map(&:name).reject {|n| n.include?("LateBoundType") }.join(" or ")
|
36
|
+
->(obj) {
|
37
|
+
property_value = obj.public_send(property_name)
|
38
|
+
is_valid_value = allowed_classes.any? { |allowed_class| property_value.is_a?(allowed_class) }
|
39
|
+
is_valid_value ? nil : "#{property_name} must return #{allowed_classes_message}, not #{property_value.class.name} (#{property_value.inspect})"
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param property_name [Symbol] The method whose return value will be validated
|
44
|
+
# @param from_class [Class] The class for keys in the return value
|
45
|
+
# @param to_class [Class] The class for values in the return value
|
46
|
+
# @return [Proc] A proc to validate that validates the input by calling `property_name` and asserting that the return value is a Hash of `{from_class => to_class}` pairs
|
47
|
+
def self.assert_property_mapping(property_name, from_class, to_class)
|
48
|
+
->(obj) {
|
49
|
+
property_value = obj.public_send(property_name)
|
50
|
+
if !property_value.is_a?(Hash)
|
51
|
+
"#{property_name} must be a hash of {#{from_class.name} => #{to_class.name}}, not a #{property_value.class.name} (#{property_value.inspect})"
|
52
|
+
else
|
53
|
+
invalid_key, invalid_value = property_value.find { |key, value| !key.is_a?(from_class) || !value.is_a?(to_class) }
|
54
|
+
if invalid_key
|
55
|
+
"#{property_name} must map #{from_class} => #{to_class}, not #{invalid_key.class.name} => #{invalid_value.class.name} (#{invalid_key.inspect} => #{invalid_value.inspect})"
|
56
|
+
else
|
57
|
+
nil # OK
|
58
|
+
end
|
59
|
+
end
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param property_name [Symbol] The method whose return value will be validated
|
64
|
+
# @param list_member_class [Class] The class which each member of the returned array should be an instance of
|
65
|
+
# @return [Proc] A proc to validate the input by calling `property_name` and asserting that the return is an Array of `list_member_class` instances
|
66
|
+
def self.assert_property_list_of(property_name, list_member_class)
|
67
|
+
->(obj) {
|
68
|
+
property_value = obj.public_send(property_name)
|
69
|
+
if !property_value.is_a?(Array)
|
70
|
+
"#{property_name} must be an Array of #{list_member_class.name}, not a #{property_value.class.name} (#{property_value.inspect})"
|
71
|
+
else
|
72
|
+
invalid_member = property_value.find { |value| !value.is_a?(list_member_class) }
|
73
|
+
if invalid_member
|
74
|
+
"#{property_name} must contain #{list_member_class.name}, not #{invalid_member.class.name} (#{invalid_member.inspect})"
|
75
|
+
else
|
76
|
+
nil # OK
|
77
|
+
end
|
78
|
+
end
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.count_at_least(item_name, minimum_count, get_items_proc)
|
83
|
+
->(type) {
|
84
|
+
items = get_items_proc.call(type)
|
85
|
+
|
86
|
+
if items.size < minimum_count
|
87
|
+
"#{type.name} must define at least #{minimum_count} #{item_name}. #{items.size} defined."
|
88
|
+
else
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.assert_named_items_are_valid(item_name, get_items_proc)
|
95
|
+
->(type) {
|
96
|
+
items = get_items_proc.call(type)
|
97
|
+
error_message = nil
|
98
|
+
items.each do |item|
|
99
|
+
item_message = GraphQL::Schema::Validation.validate(item)
|
100
|
+
if item_message
|
101
|
+
error_message = "#{item_name} #{item.name.inspect} #{item_message}"
|
102
|
+
break
|
103
|
+
end
|
104
|
+
end
|
105
|
+
error_message
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
HAS_AT_LEAST_ONE_FIELD = Rules.count_at_least("field", 1, ->(type) { type.all_fields })
|
110
|
+
FIELDS_ARE_VALID = Rules.assert_named_items_are_valid("field", ->(type) { type.all_fields })
|
111
|
+
HAS_AT_LEAST_ONE_ARGUMENT = Rules.count_at_least("argument", 1, ->(type) { type.arguments })
|
112
|
+
|
113
|
+
HAS_ONE_OR_MORE_POSSIBLE_TYPES = ->(type) {
|
114
|
+
type.possible_types.length >= 1 ? nil : "must have at least one possible type"
|
115
|
+
}
|
116
|
+
|
117
|
+
NAME_IS_STRING = Rules.assert_property(:name, String)
|
118
|
+
DESCRIPTION_IS_STRING_OR_NIL = Rules.assert_property(:description, String, NilClass)
|
119
|
+
ARGUMENTS_ARE_STRING_TO_ARGUMENT = Rules.assert_property_mapping(:arguments, String, GraphQL::Argument)
|
120
|
+
ARGUMENTS_ARE_VALID = Rules.assert_named_items_are_valid("argument", ->(type) { type.arguments.values })
|
121
|
+
|
122
|
+
DEFAULT_VALUE_IS_VALID_FOR_TYPE = ->(type) {
|
123
|
+
if !type.default_value.nil?
|
124
|
+
coerced_value = begin
|
125
|
+
type.type.coerce_isolated_result(type.default_value)
|
126
|
+
rescue => ex
|
127
|
+
ex
|
128
|
+
end
|
129
|
+
|
130
|
+
if coerced_value.nil? || coerced_value.is_a?(StandardError)
|
131
|
+
msg = "default value #{type.default_value.inspect} is not valid for type #{type.type}"
|
132
|
+
msg += " (#{coerced_value})" if coerced_value.is_a?(StandardError)
|
133
|
+
msg
|
134
|
+
end
|
135
|
+
end
|
136
|
+
}
|
137
|
+
|
138
|
+
DEPRECATED_ARGUMENTS_ARE_OPTIONAL = ->(argument) {
|
139
|
+
if argument.deprecation_reason && argument.type.non_null?
|
140
|
+
"must be optional because it's deprecated"
|
141
|
+
end
|
142
|
+
}
|
143
|
+
|
144
|
+
TYPE_IS_VALID_INPUT_TYPE = ->(type) {
|
145
|
+
outer_type = type.type
|
146
|
+
inner_type = outer_type.respond_to?(:unwrap) ? outer_type.unwrap : nil
|
147
|
+
|
148
|
+
case inner_type
|
149
|
+
when GraphQL::ScalarType, GraphQL::InputObjectType, GraphQL::EnumType
|
150
|
+
# OK
|
151
|
+
else
|
152
|
+
"type must be a valid input type (Scalar or InputObject), not #{outer_type.class} (#{outer_type})"
|
153
|
+
end
|
154
|
+
}
|
155
|
+
|
156
|
+
SCHEMA_CAN_RESOLVE_TYPES = ->(schema) {
|
157
|
+
if schema.types.values.any? { |type| type.kind.abstract? } && schema.resolve_type_proc.nil?
|
158
|
+
"schema contains Interfaces or Unions, so you must define a `resolve_type -> (obj, ctx) { ... }` function"
|
159
|
+
else
|
160
|
+
# :+1:
|
161
|
+
end
|
162
|
+
}
|
163
|
+
|
164
|
+
SCHEMA_CAN_FETCH_IDS = ->(schema) {
|
165
|
+
has_node_field = schema.query && schema.query.fields.each_value.any?(&:relay_node_field)
|
166
|
+
if has_node_field && schema.object_from_id_proc.nil?
|
167
|
+
"schema contains `node(id:...)` field, so you must define a `object_from_id -> (id, ctx) { ... }` function"
|
168
|
+
else
|
169
|
+
# :rocket:
|
170
|
+
end
|
171
|
+
}
|
172
|
+
|
173
|
+
SCHEMA_CAN_GENERATE_IDS = ->(schema) {
|
174
|
+
has_id_field = schema.types.values.any? { |t| t.kind.fields? && t.all_fields.any? { |f| f.resolve_proc.is_a?(GraphQL::Relay::GlobalIdResolve) } }
|
175
|
+
if has_id_field && schema.id_from_object_proc.nil?
|
176
|
+
"schema contains `global_id_field`, so you must define a `id_from_object -> (obj, type, ctx) { ... }` function"
|
177
|
+
else
|
178
|
+
# :ok_hand:
|
179
|
+
end
|
180
|
+
}
|
181
|
+
|
182
|
+
SCHEMA_INSTRUMENTERS_ARE_VALID = ->(schema) {
|
183
|
+
errs = []
|
184
|
+
schema.instrumenters[:query].each do |inst|
|
185
|
+
if !inst.respond_to?(:before_query) || !inst.respond_to?(:after_query)
|
186
|
+
errs << "`instrument(:query, #{inst})` is invalid: must respond to `before_query(query)` and `after_query(query)` "
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
schema.instrumenters[:field].each do |inst|
|
191
|
+
if !inst.respond_to?(:instrument)
|
192
|
+
errs << "`instrument(:field, #{inst})` is invalid: must respond to `instrument(type, field)`"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
if errs.any?
|
197
|
+
errs.join("Invalid instrumenters:\n" + errs.join("\n"))
|
198
|
+
else
|
199
|
+
nil
|
200
|
+
end
|
201
|
+
}
|
202
|
+
|
203
|
+
RESERVED_TYPE_NAME = ->(type) {
|
204
|
+
if type.name.start_with?('__') && !type.introspection?
|
205
|
+
# TODO: make this a hard failure in a later version
|
206
|
+
GraphQL::Deprecation.warn("Name #{type.name.inspect} must not begin with \"__\", which is reserved by GraphQL introspection.")
|
207
|
+
nil
|
208
|
+
else
|
209
|
+
# ok name
|
210
|
+
end
|
211
|
+
}
|
212
|
+
|
213
|
+
RESERVED_NAME = ->(named_thing) {
|
214
|
+
if named_thing.name.start_with?('__')
|
215
|
+
# TODO: make this a hard failure in a later version
|
216
|
+
GraphQL::Deprecation.warn("Name #{named_thing.name.inspect} must not begin with \"__\", which is reserved by GraphQL introspection.")
|
217
|
+
nil
|
218
|
+
else
|
219
|
+
# no worries
|
220
|
+
end
|
221
|
+
}
|
222
|
+
|
223
|
+
INTERFACES_ARE_IMPLEMENTED = ->(obj_type) {
|
224
|
+
field_errors = []
|
225
|
+
obj_type.interfaces.each do |interface_type|
|
226
|
+
interface_type.fields.each do |field_name, field_defn|
|
227
|
+
object_field = obj_type.get_field(field_name)
|
228
|
+
if object_field.nil?
|
229
|
+
field_errors << %|"#{field_name}" is required by #{interface_type.name} but not implemented by #{obj_type.name}|
|
230
|
+
elsif !GraphQL::Execution::Typecast.subtype?(field_defn.type, object_field.type)
|
231
|
+
field_errors << %|"#{field_name}" is required by #{interface_type.name} to return #{field_defn.type} but #{obj_type.name}.#{field_name} returns #{object_field.type}|
|
232
|
+
else
|
233
|
+
field_defn.arguments.each do |arg_name, arg_defn|
|
234
|
+
object_field_arg = object_field.arguments[arg_name]
|
235
|
+
if object_field_arg.nil?
|
236
|
+
field_errors << %|"#{arg_name}" argument is required by #{interface_type.name}.#{field_name} but not accepted by #{obj_type.name}.#{field_name}|
|
237
|
+
elsif arg_defn.type != object_field_arg.type
|
238
|
+
field_errors << %|"#{arg_name}" is required by #{interface_type.name}.#{field_defn.name} to accept #{arg_defn.type} but #{obj_type.name}.#{field_name} accepts #{object_field_arg.type} for "#{arg_name}"|
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
object_field.arguments.each do |arg_name, arg_defn|
|
243
|
+
if field_defn.arguments[arg_name].nil? && arg_defn.type.is_a?(GraphQL::NonNullType)
|
244
|
+
field_errors << %|"#{arg_name}" is not accepted by #{interface_type.name}.#{field_name} but required by #{obj_type.name}.#{field_name}|
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
if field_errors.any?
|
251
|
+
"#{obj_type.name} failed to implement some interfaces: #{field_errors.join(", ")}"
|
252
|
+
else
|
253
|
+
nil
|
254
|
+
end
|
255
|
+
}
|
256
|
+
end
|
257
|
+
|
258
|
+
# A mapping of `{Class => [Proc, Proc...]}` pairs.
|
259
|
+
# To validate an instance, find entries where `object.is_a?(key)` is true.
|
260
|
+
# Then apply each rule from the matching values.
|
261
|
+
RULES = {
|
262
|
+
GraphQL::Field => [
|
263
|
+
Rules::NAME_IS_STRING,
|
264
|
+
Rules::RESERVED_NAME,
|
265
|
+
Rules::DESCRIPTION_IS_STRING_OR_NIL,
|
266
|
+
Rules.assert_property(:deprecation_reason, String, NilClass),
|
267
|
+
Rules.assert_property(:type, GraphQL::BaseType, GraphQL::Schema::LateBoundType),
|
268
|
+
Rules.assert_property(:property, Symbol, NilClass),
|
269
|
+
Rules::ARGUMENTS_ARE_STRING_TO_ARGUMENT,
|
270
|
+
Rules::ARGUMENTS_ARE_VALID,
|
271
|
+
],
|
272
|
+
GraphQL::Argument => [
|
273
|
+
Rules::NAME_IS_STRING,
|
274
|
+
Rules::RESERVED_NAME,
|
275
|
+
Rules::DESCRIPTION_IS_STRING_OR_NIL,
|
276
|
+
Rules.assert_property(:deprecation_reason, String, NilClass),
|
277
|
+
Rules::TYPE_IS_VALID_INPUT_TYPE,
|
278
|
+
Rules::DEFAULT_VALUE_IS_VALID_FOR_TYPE,
|
279
|
+
Rules::DEPRECATED_ARGUMENTS_ARE_OPTIONAL,
|
280
|
+
],
|
281
|
+
GraphQL::BaseType => [
|
282
|
+
Rules::NAME_IS_STRING,
|
283
|
+
Rules::RESERVED_TYPE_NAME,
|
284
|
+
Rules::DESCRIPTION_IS_STRING_OR_NIL,
|
285
|
+
],
|
286
|
+
GraphQL::ObjectType => [
|
287
|
+
Rules::HAS_AT_LEAST_ONE_FIELD,
|
288
|
+
Rules.assert_property_list_of(:interfaces, GraphQL::InterfaceType),
|
289
|
+
Rules::FIELDS_ARE_VALID,
|
290
|
+
Rules::INTERFACES_ARE_IMPLEMENTED,
|
291
|
+
],
|
292
|
+
GraphQL::InputObjectType => [
|
293
|
+
Rules::HAS_AT_LEAST_ONE_ARGUMENT,
|
294
|
+
Rules::ARGUMENTS_ARE_STRING_TO_ARGUMENT,
|
295
|
+
Rules::ARGUMENTS_ARE_VALID,
|
296
|
+
],
|
297
|
+
GraphQL::UnionType => [
|
298
|
+
Rules.assert_property_list_of(:possible_types, GraphQL::ObjectType),
|
299
|
+
Rules::HAS_ONE_OR_MORE_POSSIBLE_TYPES,
|
300
|
+
],
|
301
|
+
GraphQL::InterfaceType => [
|
302
|
+
Rules::FIELDS_ARE_VALID,
|
303
|
+
],
|
304
|
+
GraphQL::Schema => [
|
305
|
+
Rules::SCHEMA_INSTRUMENTERS_ARE_VALID,
|
306
|
+
Rules::SCHEMA_CAN_RESOLVE_TYPES,
|
307
|
+
Rules::SCHEMA_CAN_FETCH_IDS,
|
308
|
+
Rules::SCHEMA_CAN_GENERATE_IDS,
|
309
|
+
],
|
310
|
+
}
|
311
|
+
end
|
312
|
+
end
|
313
|
+
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
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Validator
|
6
|
+
# You can use this to allow certain values for an argument.
|
7
|
+
#
|
8
|
+
# Usually, a {GraphQL::Schema::Enum} is better for this, because it's self-documenting.
|
9
|
+
#
|
10
|
+
# @example only allow certain values for an argument
|
11
|
+
#
|
12
|
+
# argument :favorite_prime, Integer, required: true,
|
13
|
+
# validates: { inclusion: { in: [2, 3, 5, 7, 11, ... ] } }
|
14
|
+
#
|
15
|
+
class InclusionValidator < Validator
|
16
|
+
# @param message [String]
|
17
|
+
# @param in [Array] The values to allow
|
18
|
+
def initialize(in:, message: "%{validated} is not included in the list", **default_options)
|
19
|
+
# `in` is a reserved word, so work around that
|
20
|
+
@in_list = binding.local_variable_get(:in)
|
21
|
+
@message = message
|
22
|
+
super(**default_options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate(_object, _context, value)
|
26
|
+
if permitted_empty_value?(value)
|
27
|
+
# pass
|
28
|
+
elsif !@in_list.include?(value)
|
29
|
+
@message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Validator
|
6
|
+
# Use this to enforce a `.length` restriction on incoming values. It works for both Strings and Lists.
|
7
|
+
#
|
8
|
+
# @example Allow no more than 10 IDs
|
9
|
+
#
|
10
|
+
# argument :ids, [ID], required: true, validates: { length: { maximum: 10 } }
|
11
|
+
#
|
12
|
+
# @example Require three selections
|
13
|
+
#
|
14
|
+
# argument :ice_cream_preferences, [ICE_CREAM_FLAVOR], required: true, validates: { length: { is: 3 } }
|
15
|
+
#
|
16
|
+
class LengthValidator < Validator
|
17
|
+
# @param maximum [Integer]
|
18
|
+
# @param too_long [String] Used when `maximum` is exceeded or value is greater than `within`
|
19
|
+
# @param minimum [Integer]
|
20
|
+
# @param too_short [String] Used with value is less than `minimum` or less than `within`
|
21
|
+
# @param is [Integer] Exact length requirement
|
22
|
+
# @param wrong_length [String] Used when value doesn't match `is`
|
23
|
+
# @param within [Range] An allowed range (becomes `minimum:` and `maximum:` under the hood)
|
24
|
+
# @param message [String]
|
25
|
+
def initialize(
|
26
|
+
maximum: nil, too_long: "%{validated} is too long (maximum is %{count})",
|
27
|
+
minimum: nil, too_short: "%{validated} is too short (minimum is %{count})",
|
28
|
+
is: nil, within: nil, wrong_length: "%{validated} is the wrong length (should be %{count})",
|
29
|
+
message: nil,
|
30
|
+
**default_options
|
31
|
+
)
|
32
|
+
if within && (minimum || maximum)
|
33
|
+
raise ArgumentError, "`length: { ... }` may include `within:` _or_ `minimum:`/`maximum:`, but not both"
|
34
|
+
end
|
35
|
+
# Under the hood, `within` is decomposed into `minimum` and `maximum`
|
36
|
+
@maximum = maximum || (within && within.max)
|
37
|
+
@too_long = message || too_long
|
38
|
+
@minimum = minimum || (within && within.min)
|
39
|
+
@too_short = message || too_short
|
40
|
+
@is = is
|
41
|
+
@wrong_length = message || wrong_length
|
42
|
+
super(**default_options)
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate(_object, _context, value)
|
46
|
+
return if permitted_empty_value?(value) # pass in this case
|
47
|
+
length = value.nil? ? 0 : value.length
|
48
|
+
if @maximum && length > @maximum
|
49
|
+
partial_format(@too_long, { count: @maximum })
|
50
|
+
elsif @minimum && length < @minimum
|
51
|
+
partial_format(@too_short, { count: @minimum })
|
52
|
+
elsif @is && length != @is
|
53
|
+
partial_format(@wrong_length, { count: @is })
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class Validator
|
5
|
+
# Use this to assert numerical comparisons hold true for inputs.
|
6
|
+
#
|
7
|
+
# @example Require a number between 0 and 1
|
8
|
+
#
|
9
|
+
# argument :batting_average, Float, required: true, validates: { numericality: { within: 0..1 } }
|
10
|
+
#
|
11
|
+
# @example Require the number 42
|
12
|
+
#
|
13
|
+
# argument :the_answer, Integer, required: true, validates: { numericality: { equal_to: 42 } }
|
14
|
+
#
|
15
|
+
# @example Require a real number
|
16
|
+
#
|
17
|
+
# argument :items_count, Integer, required: true, validates: { numericality: { greater_than_or_equal_to: 0 } }
|
18
|
+
#
|
19
|
+
class NumericalityValidator < Validator
|
20
|
+
# @param greater_than [Integer]
|
21
|
+
# @param greater_than_or_equal_to [Integer]
|
22
|
+
# @param less_than [Integer]
|
23
|
+
# @param less_than_or_equal_to [Integer]
|
24
|
+
# @param equal_to [Integer]
|
25
|
+
# @param other_than [Integer]
|
26
|
+
# @param odd [Boolean]
|
27
|
+
# @param even [Boolean]
|
28
|
+
# @param within [Range]
|
29
|
+
# @param message [String] used for all validation failures
|
30
|
+
def initialize(
|
31
|
+
greater_than: nil, greater_than_or_equal_to: nil,
|
32
|
+
less_than: nil, less_than_or_equal_to: nil,
|
33
|
+
equal_to: nil, other_than: nil,
|
34
|
+
odd: nil, even: nil, within: nil,
|
35
|
+
message: "%{validated} must be %{comparison} %{target}",
|
36
|
+
null_message: Validator::AllowNullValidator::MESSAGE,
|
37
|
+
**default_options
|
38
|
+
)
|
39
|
+
|
40
|
+
@greater_than = greater_than
|
41
|
+
@greater_than_or_equal_to = greater_than_or_equal_to
|
42
|
+
@less_than = less_than
|
43
|
+
@less_than_or_equal_to = less_than_or_equal_to
|
44
|
+
@equal_to = equal_to
|
45
|
+
@other_than = other_than
|
46
|
+
@odd = odd
|
47
|
+
@even = even
|
48
|
+
@within = within
|
49
|
+
@message = message
|
50
|
+
@null_message = null_message
|
51
|
+
super(**default_options)
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate(object, context, value)
|
55
|
+
if permitted_empty_value?(value)
|
56
|
+
# pass in this case
|
57
|
+
elsif value.nil? # @allow_null is handled in the parent class
|
58
|
+
@null_message
|
59
|
+
elsif @greater_than && value <= @greater_than
|
60
|
+
partial_format(@message, { comparison: "greater than", target: @greater_than })
|
61
|
+
elsif @greater_than_or_equal_to && value < @greater_than_or_equal_to
|
62
|
+
partial_format(@message, { comparison: "greater than or equal to", target: @greater_than_or_equal_to })
|
63
|
+
elsif @less_than && value >= @less_than
|
64
|
+
partial_format(@message, { comparison: "less than", target: @less_than })
|
65
|
+
elsif @less_than_or_equal_to && value > @less_than_or_equal_to
|
66
|
+
partial_format(@message, { comparison: "less than or equal to", target: @less_than_or_equal_to })
|
67
|
+
elsif @equal_to && value != @equal_to
|
68
|
+
partial_format(@message, { comparison: "equal to", target: @equal_to })
|
69
|
+
elsif @other_than && value == @other_than
|
70
|
+
partial_format(@message, { comparison: "something other than", target: @other_than })
|
71
|
+
elsif @even && !value.even?
|
72
|
+
(partial_format(@message, { comparison: "even", target: "" })).strip
|
73
|
+
elsif @odd && !value.odd?
|
74
|
+
(partial_format(@message, { comparison: "odd", target: "" })).strip
|
75
|
+
elsif @within && !@within.include?(value)
|
76
|
+
partial_format(@message, { comparison: "within", target: @within })
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|