# frozen_string_literal: truemoduleGraphQLclassSchemaclassValidator# The thing being validated# @return [GraphQL::Schema::Argument, GraphQL::Schema::Field, GraphQL::Schema::Resolver, Class<GraphQL::Schema::InputObject>]attr_reader:validated# @param validated [GraphQL::Schema::Argument, GraphQL::Schema::Field, GraphQL::Schema::Resolver, Class<GraphQL::Schema::InputObject>] The argument or argument owner this validator is attached to# @param allow_blank [Boolean] if `true`, then objects that respond to `.blank?` and return true for `.blank?` will skip this validation# @param allow_null [Boolean] if `true`, then incoming `null`s will skip this validationdefinitialize(validated:,allow_blank: false,allow_null: false)@validated=validated@allow_blank=allow_blank@allow_null=allow_nullend# @param object [Object] The application object that this argument's field is being resolved for# @param context [GraphQL::Query::Context]# @param value [Object] The client-provided value for this argument (after parsing and coercing by the input type)# @return [nil, Array<String>, String] Error message or messages to adddefvalidate(object,context,value)raiseGraphQL::RequiredImplementationMissingError,"Validator classes should implement #validate"end# This is like `String#%`, but it supports the case that only some of `string`'s# values are present in `substitutions`defpartial_format(string,substitutions)substitutions.eachdo|key,value|sub_v=value.is_a?(String)?value:value.to_sstring=string.gsub("%{#{key}}",sub_v)endstringend# @return [Boolean] `true` if `value` is `nil` and this validator has `allow_null: true` or if value is `.blank?` and this validator has `allow_blank: true`defpermitted_empty_value?(value)(value.nil?&&@allow_null)||(@allow_blank&&value.respond_to?(:blank?)&&value.blank?)end# @param schema_member [GraphQL::Schema::Field, GraphQL::Schema::Argument, Class<GraphQL::Schema::InputObject>]# @param validates_hash [Hash{Symbol => Hash}, Hash{Class => Hash} nil] A configuration passed as `validates:`# @return [Array<Validator>]defself.from_config(schema_member,validates_hash)ifvalidates_hash.nil?||validates_hash.empty?EMPTY_ARRAYelsevalidates_hash=validates_hash.dupdefault_options={}ifvalidates_hash[:allow_null]default_options[:allow_null]=validates_hash.delete(:allow_null)endifvalidates_hash[:allow_blank]default_options[:allow_blank]=validates_hash.delete(:allow_blank)end# allow_nil or allow_blank are the _only_ validations:ifvalidates_hash.empty?validates_hash=default_optionsendvalidates_hash.mapdo|validator_name,options|validator_class=casevalidator_namewhenClassvalidator_nameelseall_validators[validator_name]||raise(ArgumentError,"unknown validation: #{validator_name.inspect}")endifoptions.is_a?(Hash)validator_class.new(validated: schema_member,**(default_options.merge(options)))elsevalidator_class.new(options,validated: schema_member,**default_options)endendendend# Add `validator_class` to be initialized when `validates:` is given `name`.# (It's initialized with whatever options are given by the key `name`).# @param name [Symbol]# @param validator_class [Class]# @return [void]defself.install(name,validator_class)all_validators[name]=validator_classnilend# Remove whatever validator class is {.install}ed at `name`, if there is one# @param name [Symbol]# @return [void]defself.uninstall(name)all_validators.delete(name)nilendclass<<selfattr_accessor:all_validatorsendself.all_validators={}includeSchema::FindInheritedValue::EmptyObjectsclassValidationFailedError<GraphQL::ExecutionErrorattr_reader:errorsdefinitialize(errors:)@errors=errorssuper(errors.join(", "))endend# @param validators [Array<Validator>]# @param object [Object]# @param context [Query::Context]# @param value [Object]# @return [void]# @raises [ValidationFailedError]defself.validate!(validators,object,context,value,as: nil)# Assuming the default case is no errors, reduce allocations in that case.# This will be replaced with a mutable array if we actually get any errors.all_errors=EMPTY_ARRAYvalidators.eachdo|validator|validated=as||validator.validatederrors=validator.validate(object,context,value)iferrors&&(errors.is_a?(Array)&&errors!=EMPTY_ARRAY)||(errors.is_a?(String))ifall_errors.frozen?# It's emptyall_errors=[]endinterpolation_vars={validated: validated.graphql_name}iferrors.is_a?(String)all_errors<<(errors%interpolation_vars)elseerrors=errors.map{|e|e%interpolation_vars}all_errors.concat(errors)endendendifall_errors.any?raiseValidationFailedError.new(errors: all_errors)endnilendendendendrequire"graphql/schema/validator/length_validator"GraphQL::Schema::Validator.install(:length,GraphQL::Schema::Validator::LengthValidator)require"graphql/schema/validator/numericality_validator"GraphQL::Schema::Validator.install(:numericality,GraphQL::Schema::Validator::NumericalityValidator)require"graphql/schema/validator/format_validator"GraphQL::Schema::Validator.install(:format,GraphQL::Schema::Validator::FormatValidator)require"graphql/schema/validator/inclusion_validator"GraphQL::Schema::Validator.install(:inclusion,GraphQL::Schema::Validator::InclusionValidator)require"graphql/schema/validator/exclusion_validator"GraphQL::Schema::Validator.install(:exclusion,GraphQL::Schema::Validator::ExclusionValidator)require"graphql/schema/validator/required_validator"GraphQL::Schema::Validator.install(:required,GraphQL::Schema::Validator::RequiredValidator)require"graphql/schema/validator/allow_null_validator"GraphQL::Schema::Validator.install(:allow_null,GraphQL::Schema::Validator::AllowNullValidator)require"graphql/schema/validator/allow_blank_validator"GraphQL::Schema::Validator.install(:allow_blank,GraphQL::Schema::Validator::AllowBlankValidator)