Repository URL to install this package:
|
Version:
0.14.1 ▾
|
require 'dry/types/hash/schema_builder'
module Dry
module Types
class Hash < Definition
SCHEMA_BUILDER = SchemaBuilder.new.freeze
# @param [{Symbol => Definition}] type_map
# @param [Symbol] constructor
# @return [Schema]
def schema(type_map, constructor = nil)
member_types = transform_types(type_map)
if constructor.nil?
Schema.new(primitive, member_types: member_types, **options, meta: meta)
else
SCHEMA_BUILDER.(
primitive,
**options,
member_types: member_types,
meta: meta,
hash_type: constructor
)
end
end
# Build a map type
#
# @param [Type] key_type
# @param [Type] value_type
# @return [Map]
def map(key_type, value_type)
Map.new(
primitive,
key_type: resolve_type(key_type),
value_type: resolve_type(value_type),
meta: meta
)
end
# @param [{Symbol => Definition}] type_map
# @return [Schema]
def weak(type_map)
schema(type_map, :weak)
end
# @param [{Symbol => Definition}] type_map
# @return [Schema]
def permissive(type_map)
schema(type_map, :permissive)
end
# @param [{Symbol => Definition}] type_map
# @return [Schema]
def strict(type_map)
schema(type_map, :strict)
end
# @param [{Symbol => Definition}] type_map
# @return [Schema]
def strict_with_defaults(type_map)
schema(type_map, :strict_with_defaults)
end
# @param [{Symbol => Definition}] type_map
# @return [Schema]
def symbolized(type_map)
schema(type_map, :symbolized)
end
# Build a schema from an AST
# @api private
# @param [{Symbol => Definition}] member_types
# @return [Schema]
def instantiate(member_types)
SCHEMA_BUILDER.instantiate(primitive, **options, member_types: member_types)
end
# Injects a type transformation function for building schemas
# @param [#call,nil] proc
# @param [#call,nil] block
# @return [Hash]
def with_type_transform(proc = nil, &block)
fn = proc || block
if fn.nil?
raise ArgumentError, "a block or callable argument is required"
end
handle = Dry::Types::FnContainer.register(fn)
meta(type_transform_fn: handle)
end
private
# @api private
def transform_types(type_map)
type_fn = meta.fetch(:type_transform_fn, Schema::NO_TRANSFORM)
type_transform = Dry::Types::FnContainer[type_fn]
type_map.each_with_object({}) { |(name, type), result|
result[name] = type_transform.(
resolve_type(type),
name
)
}
end
# @api private
def resolve_type(type)
case type
when String, Class then Types[type]
else type
end
end
end
end
end