# frozen_string_literal: truerequire"bigdecimal"require"date"require"set"require"zeitwerk"require"concurrent/map"require"dry/core"require"dry/logic"require"dry/types/constraints"require"dry/types/errors"require"dry/types/version"# This must be required explicitly as it may conflict with dry-inflectorrequire"dry/types/inflector"require"dry/types/module"moduleDry# Main library namespace## @api publicmoduleTypesextend::Dry::Core::Extensionsextend::Dry::Core::ClassAttributesextend::Dry::Core::Deprecations[:"dry-types"]include::Dry::Core::ConstantsTYPE_SPEC_REGEX=/(.+)<(.+)>/defself.loader@loader||=::Zeitwerk::Loader.new.tapdo|loader|root=::File.expand_path("..",__dir__)loader.tag="dry-types"loader.inflector=::Zeitwerk::GemInflector.new("#{root}/dry-types.rb")loader.inflector.inflect("json"=>"JSON")loader.push_dir(root)loader.ignore("#{root}/dry-types.rb","#{root}/dry/types/extensions","#{root}/dry/types/printer","#{root}/dry/types/spec/types.rb","#{root}/dry/types/{#{%w[compatconstraintscoreerrorsextensionsinflectormodulejsonparamsprinterversion].join(",")}}.rb")endendloader.setup# @see Dry.Typesdefself.module(*namespaces,default: :nominal,**aliases)::Module.new(container,*namespaces,default: default,**aliases)enddeprecate_class_method:module,message: <<~DEPRECATION
Use Dry.Types() instead. Beware, it exports strict types by default, for old behavior use Dry.Types(default: :nominal). See more options in the changelog
DEPRECATION# @api privatedefself.included(*)raise"Import Dry.Types, not Dry::Types"end# Return container with registered built-in type objects## @return [Container{String => Nominal}]## @api privatedefself.container@container||=Container.newend# Check if a give type is registered## @return [Boolean]## @api privatedefself.registered?(class_or_identifier)container.key?(identifier(class_or_identifier))end# Register a new built-in type## @param [String] name# @param [Type] type# @param [#call,nil] block## @return [Container{String => Nominal}]## @api privatedefself.register(name,type=nil,&block)container.register(name,type||block.call)end# Get a built-in type by its name## @param [String,Class] name## @return [Type,Class]## @api publicdefself.[](name)type_map.fetch_or_store(name)docasenamewhen::Stringresult=name.match(TYPE_SPEC_REGEX)ifresulttype_id,member_id=result[1..2]container[type_id].of(self[member_id])elsecontainer[name]endwhen::Classwarn(<<~DEPRECATION)
Using Dry::Types.[] with a class is deprecated, please use string identifiers: Dry::Types[Integer] -> Dry::Types['integer'].
If you're using dry-struct this means changing `attribute :counter, Integer` to `attribute :counter, Dry::Types['integer']` or to `attribute :counter, 'integer'`.
DEPRECATIONtype_name=identifier(name)ifcontainer.key?(type_name)self[type_name]elsenameendendendend# Infer a type identifier from the provided class## @param [#to_s] klass## @return [String]defself.identifier(klass)Types::Inflector.underscore(klass).tr("/",".")end# Cached type map## @return [Concurrent::Map]## @api privatedefself.type_map@type_map||=::Concurrent::Map.newend# @api privatedefself.const_missing(const)underscored=Types::Inflector.underscore(const)ifcontainer.keys.any?{|key|key.split(".")[0]==underscored}raise::NameError,"dry-types does not define constants for default types. "\"You can access the predefined types with [], e.g. Dry::Types['integer'] "\"or generate a module with types using Dry.Types()"elsesuperendend# Add a new type builder method. This is a public API for defining custom# type constructors## @example simple custom type constructor# Dry::Types.define_builder(:or_nil) do |type|# type.optional.fallback(nil)# end## Dry::Types["integer"].or_nil.("foo") # => nil## @example fallback alias# Dry::Types.define_builder(:or) do |type, fallback|# type.fallback(fallback)# end## Dry::Types["integer"].or(100).("foo") # => 100## @param [Symbol] method# @param [#call] block## @api publicdefself.define_builder(method,&block)Builder.define_method(method)do|*args|block.(self,*args)endendend# Export registered types as a module with constants## @example no options## module Types# # imports all types as constants, uses modules for namespaces# include Dry.Types()# end# # strict types are exported by default# Types::Integer# # => #<Dry::Types[Constrained<Nominal<Integer> rule=[type?(Integer)]>]># Types::Nominal::Integer# # => #<Dry::Types[Nominal<Integer>]>## @example changing default types## module Types# include Dry.Types(default: :nominal)# end# Types::Integer# # => #<Dry::Types[Nominal<Integer>]>## @example cherry-picking namespaces## module Types# include Dry.Types(:strict, :coercible)# end# # cherry-picking discards default types,# # provide the :default option along with the list of# # namespaces if you want the to be exported# Types.constants # => [:Coercible, :Strict]## @example custom names# module Types# include Dry.Types(coercible: :Kernel)# end# Types::Kernel::Integer# # => #<Dry::Types[Constructor<Nominal<Integer> fn=Kernel.Integer>]>## @param [Array<Symbol>] namespaces List of type namespaces to export# @param [Symbol] default Default namespace to export# @param [Hash{Symbol => Symbol}] aliases Optional renamings, like strict: :Draconian## @return [Dry::Types::Module]## @see Dry::Types::Module## @api public#defself.Types(*namespaces,default: Types::Undefined,**aliases)Types::Module.new(Types.container,*namespaces,default: default,**aliases)endendrequire"dry/types/core"# load built-in typesrequire"dry/types/extensions"require"dry/types/printer"