dry-types 0.14.1 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +631 -134
  3. data/LICENSE +17 -17
  4. data/README.md +15 -13
  5. data/dry-types.gemspec +27 -30
  6. data/lib/dry/types/any.rb +32 -12
  7. data/lib/dry/types/array/constructor.rb +32 -0
  8. data/lib/dry/types/array/member.rb +75 -16
  9. data/lib/dry/types/array.rb +19 -6
  10. data/lib/dry/types/builder.rb +131 -15
  11. data/lib/dry/types/builder_methods.rb +49 -20
  12. data/lib/dry/types/coercions/json.rb +43 -7
  13. data/lib/dry/types/coercions/params.rb +118 -31
  14. data/lib/dry/types/coercions.rb +76 -22
  15. data/lib/dry/types/compat.rb +0 -2
  16. data/lib/dry/types/compiler.rb +56 -41
  17. data/lib/dry/types/constrained/coercible.rb +36 -6
  18. data/lib/dry/types/constrained.rb +81 -32
  19. data/lib/dry/types/constraints.rb +18 -4
  20. data/lib/dry/types/constructor/function.rb +216 -0
  21. data/lib/dry/types/constructor/wrapper.rb +94 -0
  22. data/lib/dry/types/constructor.rb +126 -56
  23. data/lib/dry/types/container.rb +7 -0
  24. data/lib/dry/types/core.rb +54 -21
  25. data/lib/dry/types/decorator.rb +38 -17
  26. data/lib/dry/types/default.rb +61 -16
  27. data/lib/dry/types/enum.rb +43 -20
  28. data/lib/dry/types/errors.rb +75 -9
  29. data/lib/dry/types/extensions/maybe.rb +74 -16
  30. data/lib/dry/types/extensions/monads.rb +29 -0
  31. data/lib/dry/types/extensions.rb +7 -1
  32. data/lib/dry/types/fn_container.rb +6 -1
  33. data/lib/dry/types/hash/constructor.rb +33 -0
  34. data/lib/dry/types/hash.rb +86 -67
  35. data/lib/dry/types/inflector.rb +3 -1
  36. data/lib/dry/types/json.rb +18 -16
  37. data/lib/dry/types/lax.rb +75 -0
  38. data/lib/dry/types/map.rb +76 -33
  39. data/lib/dry/types/meta.rb +51 -0
  40. data/lib/dry/types/module.rb +120 -0
  41. data/lib/dry/types/nominal.rb +210 -0
  42. data/lib/dry/types/options.rb +13 -26
  43. data/lib/dry/types/params.rb +39 -25
  44. data/lib/dry/types/predicate_inferrer.rb +238 -0
  45. data/lib/dry/types/predicate_registry.rb +34 -0
  46. data/lib/dry/types/primitive_inferrer.rb +97 -0
  47. data/lib/dry/types/printable.rb +16 -0
  48. data/lib/dry/types/printer.rb +315 -0
  49. data/lib/dry/types/result.rb +29 -3
  50. data/lib/dry/types/schema/key.rb +156 -0
  51. data/lib/dry/types/schema.rb +408 -0
  52. data/lib/dry/types/spec/types.rb +103 -33
  53. data/lib/dry/types/sum.rb +84 -35
  54. data/lib/dry/types/type.rb +49 -0
  55. data/lib/dry/types/version.rb +3 -1
  56. data/lib/dry/types.rb +156 -76
  57. data/lib/dry-types.rb +3 -1
  58. metadata +65 -78
  59. data/.gitignore +0 -10
  60. data/.rspec +0 -2
  61. data/.travis.yml +0 -27
  62. data/.yardopts +0 -5
  63. data/CONTRIBUTING.md +0 -29
  64. data/Gemfile +0 -24
  65. data/Rakefile +0 -20
  66. data/benchmarks/hash_schemas.rb +0 -51
  67. data/lib/dry/types/compat/form_types.rb +0 -27
  68. data/lib/dry/types/compat/int.rb +0 -14
  69. data/lib/dry/types/definition.rb +0 -113
  70. data/lib/dry/types/hash/schema.rb +0 -199
  71. data/lib/dry/types/hash/schema_builder.rb +0 -75
  72. data/lib/dry/types/safe.rb +0 -59
  73. data/log/.gitkeep +0 -0
@@ -1,11 +1,18 @@
1
- require 'dry/types/decorator'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/equalizer"
4
+ require "dry/types/decorator"
2
5
 
3
6
  module Dry
4
7
  module Types
8
+ # Enum types can be used to define an enum on top of an existing type
9
+ #
10
+ # @api public
5
11
  class Enum
6
12
  include Type
7
- include Dry::Equalizer(:type, :options, :mapping)
13
+ include Dry::Equalizer(:type, :mapping, inspect: false, immutable: true)
8
14
  include Decorator
15
+ include Builder
9
16
 
10
17
  # @return [Array]
11
18
  attr_reader :values
@@ -19,7 +26,9 @@ module Dry
19
26
  # @param [Type] type
20
27
  # @param [Hash] options
21
28
  # @option options [Array] :values
22
- def initialize(type, options)
29
+ #
30
+ # @api private
31
+ def initialize(type, **options)
23
32
  super
24
33
  @mapping = options.fetch(:mapping).freeze
25
34
  @values = @mapping.keys.freeze
@@ -27,45 +36,59 @@ module Dry
27
36
  freeze
28
37
  end
29
38
 
30
- # @param [Object] input
31
39
  # @return [Object]
32
- def call(input = Undefined)
33
- type[map_value(input)]
40
+ #
41
+ # @api private
42
+ def call_unsafe(input)
43
+ type.call_unsafe(map_value(input))
44
+ end
45
+
46
+ # @return [Object]
47
+ #
48
+ # @api private
49
+ def call_safe(input, &block)
50
+ type.call_safe(map_value(input), &block)
34
51
  end
35
- alias_method :[], :call
36
52
 
37
- # @param [Object] input
38
- # @yieldparam [Failure] failure
39
- # @yieldreturn [Result]
40
- # @return [Logic::Result]
41
- # @return [Object] if coercion fails and a block is given
53
+ # @see Dry::Types::Constrained#try
54
+ #
55
+ # @api public
42
56
  def try(input)
43
57
  super(map_value(input))
44
58
  end
45
59
 
60
+ # @api private
46
61
  def default(*)
47
- raise '.enum(*values).default(value) is not supported. Call '\
48
- '.default(value).enum(*values) instead'
62
+ raise ".enum(*values).default(value) is not supported. Call "\
63
+ ".default(value).enum(*values) instead"
49
64
  end
50
65
 
51
66
  # Check whether a value is in the enum
52
67
  alias_method :include?, :valid?
53
68
 
54
- # @api public
69
+ # @see Nominal#to_ast
55
70
  #
56
- # @see Definition#to_ast
71
+ # @api public
57
72
  def to_ast(meta: true)
58
- [:enum, [type.to_ast(meta: meta),
59
- mapping,
60
- meta ? self.meta : EMPTY_HASH]]
73
+ [:enum, [type.to_ast(meta: meta), mapping]]
74
+ end
75
+
76
+ # @return [String]
77
+ #
78
+ # @api public
79
+ def to_s
80
+ PRINTER.(self)
61
81
  end
82
+ alias_method :inspect, :to_s
62
83
 
63
84
  private
64
85
 
65
86
  # Maps a value
66
87
  #
67
- # @params [Object]
88
+ # @param [Object] input
89
+ #
68
90
  # @return [Object]
91
+ #
69
92
  # @api private
70
93
  def map_value(input)
71
94
  if input.equal?(Undefined)
@@ -1,14 +1,71 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  module Types
3
- extend Dry::Core::ClassAttributes
5
+ extend ::Dry::Core::ClassAttributes
4
6
 
5
7
  # @!attribute [r] namespace
6
- # @return [Container{String => Definition}]
8
+ # @return [Container{String => Nominal}]
7
9
  defines :namespace
8
10
 
9
11
  namespace self
10
12
 
11
- class SchemaError < TypeError
13
+ # Base class for coercion errors raise by dry-types
14
+ #
15
+ class CoercionError < ::StandardError
16
+ # @api private
17
+ def self.handle(exception, meta: Undefined)
18
+ if block_given?
19
+ yield
20
+ else
21
+ raise new(
22
+ exception.message,
23
+ meta: meta,
24
+ backtrace: exception.backtrace
25
+ )
26
+ end
27
+ end
28
+
29
+ # Metadata associated with the error
30
+ #
31
+ # @return [Object]
32
+ attr_reader :meta
33
+
34
+ # @api private
35
+ def initialize(message, meta: Undefined, backtrace: Undefined)
36
+ unless message.is_a?(::String)
37
+ raise ::ArgumentError, "message must be a string, #{message.class} given"
38
+ end
39
+
40
+ super(message)
41
+ @meta = Undefined.default(meta, nil)
42
+ set_backtrace(backtrace) unless Undefined.equal?(backtrace)
43
+ end
44
+ end
45
+
46
+ # Collection of multiple errors
47
+ #
48
+ class MultipleError < CoercionError
49
+ # @return [Array<CoercionError>]
50
+ attr_reader :errors
51
+
52
+ # @param [Array<CoercionError>] errors
53
+ def initialize(errors)
54
+ @errors = errors
55
+ end
56
+
57
+ # @return string
58
+ def message
59
+ errors.map(&:message).join(", ")
60
+ end
61
+
62
+ # @return [Array]
63
+ def meta
64
+ errors.map(&:meta)
65
+ end
66
+ end
67
+
68
+ class SchemaError < CoercionError
12
69
  # @param [String,Symbol] key
13
70
  # @param [Object] value
14
71
  # @param [String, #to_s] result
@@ -17,26 +74,34 @@ module Dry
17
74
  end
18
75
  end
19
76
 
20
- MapError = Class.new(TypeError)
77
+ MapError = ::Class.new(CoercionError)
21
78
 
22
- SchemaKeyError = Class.new(KeyError)
79
+ SchemaKeyError = ::Class.new(CoercionError)
23
80
  private_constant(:SchemaKeyError)
24
81
 
25
82
  class MissingKeyError < SchemaKeyError
83
+ # @return [Symbol]
84
+ attr_reader :key
85
+
26
86
  # @param [String,Symbol] key
27
87
  def initialize(key)
28
- super(":#{key} is missing in Hash input")
88
+ @key = key
89
+ super("#{key.inspect} is missing in Hash input")
29
90
  end
30
91
  end
31
92
 
32
93
  class UnknownKeysError < SchemaKeyError
94
+ # @return [Array<Symbol>]
95
+ attr_reader :keys
96
+
33
97
  # @param [<String, Symbol>] keys
34
- def initialize(*keys)
98
+ def initialize(keys)
99
+ @keys = keys
35
100
  super("unexpected keys #{keys.inspect} in Hash input")
36
101
  end
37
102
  end
38
103
 
39
- class ConstraintError < TypeError
104
+ class ConstraintError < CoercionError
40
105
  # @return [String, #to_s]
41
106
  attr_reader :result
42
107
  # @return [Object]
@@ -56,9 +121,10 @@ module Dry
56
121
  end
57
122
 
58
123
  # @return [String]
59
- def to_s
124
+ def message
60
125
  "#{input.inspect} violates constraints (#{result} failed)"
61
126
  end
127
+ alias_method :to_s, :message
62
128
  end
63
129
  end
64
130
  end
@@ -1,49 +1,83 @@
1
- require 'dry/monads/maybe'
2
- require 'dry/types/decorator'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/equalizer"
4
+ require "dry/monads/maybe"
5
+ require "dry/types/decorator"
3
6
 
4
7
  module Dry
5
8
  module Types
9
+ # Maybe extension provides Maybe types where values are wrapped using `Either` monad
10
+ #
11
+ # @api public
6
12
  class Maybe
7
13
  include Type
8
- include Dry::Equalizer(:type, :options)
14
+ include ::Dry::Equalizer(:type, :options, inspect: false, immutable: true)
9
15
  include Decorator
10
16
  include Builder
11
- include Dry::Monads::Maybe::Mixin
17
+ include Printable
18
+ include ::Dry::Monads::Maybe::Mixin
19
+
20
+ # @param [Dry::Monads::Maybe, Object] input
21
+ #
22
+ # @return [Dry::Monads::Maybe]
23
+ #
24
+ # @api private
25
+ def call_unsafe(input = Undefined)
26
+ case input
27
+ when ::Dry::Monads::Maybe
28
+ input
29
+ when Undefined
30
+ None()
31
+ else
32
+ Maybe(type.call_unsafe(input))
33
+ end
34
+ end
12
35
 
13
36
  # @param [Dry::Monads::Maybe, Object] input
37
+ #
14
38
  # @return [Dry::Monads::Maybe]
15
- def call(input = Undefined)
39
+ #
40
+ # @api private
41
+ def call_safe(input = Undefined)
16
42
  case input
17
- when Dry::Monads::Maybe
43
+ when ::Dry::Monads::Maybe
18
44
  input
19
45
  when Undefined
20
46
  None()
21
47
  else
22
- Maybe(type[input])
48
+ Maybe(type.call_safe(input) { |output = input| return yield(output) })
23
49
  end
24
50
  end
25
- alias_method :[], :call
26
51
 
27
52
  # @param [Object] input
53
+ #
28
54
  # @return [Result::Success]
55
+ #
56
+ # @api public
29
57
  def try(input = Undefined)
30
- res = if input.equal?(Undefined)
31
- None()
32
- else
33
- Maybe(type[input])
34
- end
58
+ result = type.try(input)
35
59
 
36
- Result::Success.new(res)
60
+ if result.success?
61
+ Result::Success.new(Maybe(result.input))
62
+ else
63
+ result
64
+ end
37
65
  end
38
66
 
39
67
  # @return [true]
68
+ #
69
+ # @api public
40
70
  def default?
41
71
  true
42
72
  end
43
73
 
44
74
  # @param [Object] value
75
+ #
45
76
  # @see Dry::Types::Builder#default
77
+ #
46
78
  # @raise [ArgumentError] if nil provided as default value
79
+ #
80
+ # @api public
47
81
  def default(value)
48
82
  if value.nil?
49
83
  raise ArgumentError, "nil cannot be used as a default of a maybe type"
@@ -54,15 +88,39 @@ module Dry
54
88
  end
55
89
 
56
90
  module Builder
91
+ # Turn a type into a maybe type
92
+ #
57
93
  # @return [Maybe]
94
+ #
95
+ # @api public
96
+ def maybe
97
+ Maybe.new(Types["nil"] | self)
98
+ end
99
+ end
100
+
101
+ # @api private
102
+ class Schema::Key
103
+ # @api private
58
104
  def maybe
59
- Maybe.new(Types['strict.nil'] | self)
105
+ __new__(type.maybe)
106
+ end
107
+ end
108
+
109
+ # @api private
110
+ class Printer
111
+ MAPPING[Maybe] = :visit_maybe
112
+
113
+ # @api private
114
+ def visit_maybe(maybe)
115
+ visit(maybe.type) do |type|
116
+ yield "Maybe<#{type}>"
117
+ end
60
118
  end
61
119
  end
62
120
 
63
121
  # Register non-coercible maybe types
64
122
  NON_NIL.each_key do |name|
65
- register("maybe.strict.#{name}", self["strict.#{name}"].maybe)
123
+ register("maybe.strict.#{name}", self[name.to_s].maybe)
66
124
  end
67
125
 
68
126
  # Register coercible maybe types
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/monads/result"
4
+
5
+ module Dry
6
+ module Types
7
+ # Monad extension for Result
8
+ #
9
+ # @api public
10
+ class Result
11
+ include Dry::Monads::Result::Mixin
12
+
13
+ # Turn result into a monad
14
+ #
15
+ # This makes result objects work with dry-monads (or anything with a compatible interface)
16
+ #
17
+ # @return [Dry::Monads::Success,Dry::Monads::Failure]
18
+ #
19
+ # @api public
20
+ def to_monad
21
+ if success?
22
+ Success(input)
23
+ else
24
+ Failure([error, input])
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Dry::Types.register_extension(:maybe) do
2
- require 'dry/types/extensions/maybe'
4
+ require "dry/types/extensions/maybe"
5
+ end
6
+
7
+ Dry::Types.register_extension(:monads) do
8
+ require "dry/types/extensions/monads"
3
9
  end
@@ -1,7 +1,12 @@
1
- require 'dry/types/container'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/types/container"
2
4
 
3
5
  module Dry
4
6
  module Types
7
+ # Internal container for constructor functions used by the built-in types
8
+ #
9
+ # @api private
5
10
  class FnContainer
6
11
  # @api private
7
12
  def self.container
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/types/constructor"
4
+
5
+ module Dry
6
+ module Types
7
+ # Hash type exposes additional APIs for working with schema hashes
8
+ #
9
+ # @api public
10
+ class Hash < Nominal
11
+ class Constructor < ::Dry::Types::Constructor
12
+ # @api private
13
+ def constructor_type
14
+ ::Dry::Types::Hash::Constructor
15
+ end
16
+
17
+ # @return [Lax]
18
+ #
19
+ # @api public
20
+ def lax
21
+ type.lax.constructor(fn, meta: meta)
22
+ end
23
+
24
+ # @see Dry::Types::Array#of
25
+ #
26
+ # @api public
27
+ def schema(*args)
28
+ type.schema(*args).constructor(fn, meta: meta)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,34 +1,44 @@
1
- require 'dry/types/hash/schema_builder'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/types/hash/constructor"
2
4
 
3
5
  module Dry
4
6
  module Types
5
- class Hash < Definition
6
- SCHEMA_BUILDER = SchemaBuilder.new.freeze
7
-
8
- # @param [{Symbol => Definition}] type_map
9
- # @param [Symbol] constructor
10
- # @return [Schema]
11
- def schema(type_map, constructor = nil)
12
- member_types = transform_types(type_map)
13
-
14
- if constructor.nil?
15
- Schema.new(primitive, member_types: member_types, **options, meta: meta)
7
+ # Hash types can be used to define maps and schemas
8
+ #
9
+ # @api public
10
+ class Hash < Nominal
11
+ NOT_REQUIRED = {required: false}.freeze
12
+
13
+ # @overload schema(type_map, meta = EMPTY_HASH)
14
+ # @param [{Symbol => Dry::Types::Nominal}] type_map
15
+ # @param [Hash] meta
16
+ # @return [Dry::Types::Schema]
17
+ #
18
+ # @overload schema(keys)
19
+ # @param [Array<Dry::Types::Schema::Key>] key List of schema keys
20
+ # @param [Hash] meta
21
+ # @return [Dry::Types::Schema]
22
+ #
23
+ # @api public
24
+ def schema(keys_or_map, meta = EMPTY_HASH)
25
+ if keys_or_map.is_a?(::Array)
26
+ keys = keys_or_map
16
27
  else
17
- SCHEMA_BUILDER.(
18
- primitive,
19
- **options,
20
- member_types: member_types,
21
- meta: meta,
22
- hash_type: constructor
23
- )
28
+ keys = build_keys(keys_or_map)
24
29
  end
30
+
31
+ Schema.new(primitive, keys: keys, **options, meta: self.meta.merge(meta))
25
32
  end
26
33
 
27
34
  # Build a map type
28
35
  #
29
36
  # @param [Type] key_type
30
37
  # @param [Type] value_type
38
+ #
31
39
  # @return [Map]
40
+ #
41
+ # @api public
32
42
  def map(key_type, value_type)
33
43
  Map.new(
34
44
  primitive,
@@ -38,81 +48,90 @@ module Dry
38
48
  )
39
49
  end
40
50
 
41
- # @param [{Symbol => Definition}] type_map
42
- # @return [Schema]
43
- def weak(type_map)
44
- schema(type_map, :weak)
45
- end
46
-
47
- # @param [{Symbol => Definition}] type_map
48
- # @return [Schema]
49
- def permissive(type_map)
50
- schema(type_map, :permissive)
51
- end
52
-
53
- # @param [{Symbol => Definition}] type_map
54
- # @return [Schema]
55
- def strict(type_map)
56
- schema(type_map, :strict)
57
- end
58
-
59
- # @param [{Symbol => Definition}] type_map
60
- # @return [Schema]
61
- def strict_with_defaults(type_map)
62
- schema(type_map, :strict_with_defaults)
63
- end
64
-
65
- # @param [{Symbol => Definition}] type_map
66
- # @return [Schema]
67
- def symbolized(type_map)
68
- schema(type_map, :symbolized)
69
- end
70
-
71
- # Build a schema from an AST
72
51
  # @api private
73
- # @param [{Symbol => Definition}] member_types
74
- # @return [Schema]
75
- def instantiate(member_types)
76
- SCHEMA_BUILDER.instantiate(primitive, **options, member_types: member_types)
52
+ def weak(*)
53
+ raise "Support for old hash schemas was removed, please refer to the CHANGELOG "\
54
+ "on how to proceed with the new API https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md"
77
55
  end
56
+ alias_method :permissive, :weak
57
+ alias_method :strict, :weak
58
+ alias_method :strict_with_defaults, :weak
59
+ alias_method :symbolized, :weak
78
60
 
79
61
  # Injects a type transformation function for building schemas
62
+ #
80
63
  # @param [#call,nil] proc
81
64
  # @param [#call,nil] block
65
+ #
82
66
  # @return [Hash]
67
+ #
68
+ # @api public
83
69
  def with_type_transform(proc = nil, &block)
84
70
  fn = proc || block
85
71
 
86
- if fn.nil?
87
- raise ArgumentError, "a block or callable argument is required"
88
- end
72
+ raise ArgumentError, "a block or callable argument is required" if fn.nil?
89
73
 
90
74
  handle = Dry::Types::FnContainer.register(fn)
91
- meta(type_transform_fn: handle)
75
+ with(type_transform_fn: handle)
76
+ end
77
+
78
+ # @api private
79
+ def constructor_type
80
+ ::Dry::Types::Hash::Constructor
81
+ end
82
+
83
+ # Whether the type transforms types of schemas created by {Dry::Types::Hash#schema}
84
+ #
85
+ # @return [Boolean]
86
+ #
87
+ # @api public
88
+ def transform_types?
89
+ !options[:type_transform_fn].nil?
90
+ end
91
+
92
+ # @param meta [Boolean] Whether to dump the meta to the AST
93
+ #
94
+ # @return [Array] An AST representation
95
+ #
96
+ # @api public
97
+ def to_ast(meta: true)
98
+ [:hash, [options.slice(:type_transform_fn), meta ? self.meta : EMPTY_HASH]]
92
99
  end
93
100
 
94
101
  private
95
102
 
96
103
  # @api private
97
- def transform_types(type_map)
98
- type_fn = meta.fetch(:type_transform_fn, Schema::NO_TRANSFORM)
104
+ def build_keys(type_map)
105
+ type_fn = options.fetch(:type_transform_fn, Schema::NO_TRANSFORM)
99
106
  type_transform = Dry::Types::FnContainer[type_fn]
100
107
 
101
- type_map.each_with_object({}) { |(name, type), result|
102
- result[name] = type_transform.(
103
- resolve_type(type),
104
- name
105
- )
106
- }
108
+ type_map.map do |map_key, type|
109
+ name, options = key_name(map_key)
110
+ key = Schema::Key.new(resolve_type(type), name, **options)
111
+ type_transform.(key)
112
+ end
107
113
  end
108
114
 
109
115
  # @api private
110
116
  def resolve_type(type)
111
117
  case type
112
- when String, Class then Types[type]
118
+ when Type then type
119
+ when ::Class, ::String then Types[type]
113
120
  else type
114
121
  end
115
122
  end
123
+
124
+ # @api private
125
+ def key_name(key)
126
+ if key.to_s.end_with?("?")
127
+ [key.to_s.chop.to_sym, NOT_REQUIRED]
128
+ else
129
+ [key, EMPTY_HASH]
130
+ end
131
+ end
116
132
  end
117
133
  end
118
134
  end
135
+
136
+ require "dry/types/schema/key"
137
+ require "dry/types/schema"
@@ -1,4 +1,6 @@
1
- require 'dry/inflector'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/inflector"
2
4
 
3
5
  module Dry
4
6
  module Types