dry-schema 0.1.0 → 1.0.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +166 -0
  3. data/LICENSE +1 -1
  4. data/README.md +13 -4
  5. data/config/errors.yml +59 -54
  6. data/lib/dry/schema/compiler.rb +24 -0
  7. data/lib/dry/schema/config.rb +23 -27
  8. data/lib/dry/schema/constants.rb +27 -3
  9. data/lib/dry/schema/dsl.rb +36 -49
  10. data/lib/dry/schema/extensions/hints/compiler_methods.rb +19 -0
  11. data/lib/dry/schema/extensions/hints/message_compiler_methods.rb +84 -0
  12. data/lib/dry/schema/extensions/hints/message_set_methods.rb +44 -0
  13. data/lib/dry/schema/extensions/hints/result_methods.rb +47 -0
  14. data/lib/dry/schema/extensions/hints.rb +56 -0
  15. data/lib/dry/schema/extensions/monads.rb +15 -4
  16. data/lib/dry/schema/extensions.rb +6 -0
  17. data/lib/dry/schema/json.rb +4 -2
  18. data/lib/dry/schema/key.rb +8 -10
  19. data/lib/dry/schema/key_coercer.rb +6 -2
  20. data/lib/dry/schema/key_map.rb +5 -4
  21. data/lib/dry/schema/macros/array.rb +39 -0
  22. data/lib/dry/schema/macros/core.rb +2 -0
  23. data/lib/dry/schema/macros/dsl.rb +149 -4
  24. data/lib/dry/schema/macros/each.rb +12 -1
  25. data/lib/dry/schema/macros/filled.rb +14 -7
  26. data/lib/dry/schema/macros/hash.rb +6 -32
  27. data/lib/dry/schema/macros/key.rb +38 -60
  28. data/lib/dry/schema/macros/maybe.rb +5 -3
  29. data/lib/dry/schema/macros/optional.rb +8 -1
  30. data/lib/dry/schema/macros/required.rb +3 -1
  31. data/lib/dry/schema/macros/schema.rb +46 -0
  32. data/lib/dry/schema/macros/value.rb +18 -2
  33. data/lib/dry/schema/macros.rb +4 -0
  34. data/lib/dry/schema/message/or.rb +54 -0
  35. data/lib/dry/schema/message.rb +56 -72
  36. data/lib/dry/schema/message_compiler/visitor_opts.rb +28 -1
  37. data/lib/dry/schema/message_compiler.rb +85 -74
  38. data/lib/dry/schema/message_set.rb +82 -50
  39. data/lib/dry/schema/messages/abstract.rb +84 -44
  40. data/lib/dry/schema/messages/i18n.rb +45 -9
  41. data/lib/dry/schema/messages/namespaced.rb +22 -5
  42. data/lib/dry/schema/messages/template.rb +68 -0
  43. data/lib/dry/schema/messages/yaml.rb +76 -22
  44. data/lib/dry/schema/messages.rb +19 -24
  45. data/lib/dry/schema/namespaced_rule.rb +37 -0
  46. data/lib/dry/schema/params.rb +4 -2
  47. data/lib/dry/schema/path.rb +102 -0
  48. data/lib/dry/schema/predicate.rb +15 -0
  49. data/lib/dry/schema/predicate_inferrer.rb +116 -23
  50. data/lib/dry/schema/predicate_registry.rb +2 -0
  51. data/lib/dry/schema/processor.rb +70 -39
  52. data/lib/dry/schema/result.rb +16 -31
  53. data/lib/dry/schema/rule_applier.rb +10 -3
  54. data/lib/dry/schema/trace.rb +16 -3
  55. data/lib/dry/schema/type_registry.rb +5 -3
  56. data/lib/dry/schema/types.rb +3 -1
  57. data/lib/dry/schema/value_coercer.rb +10 -4
  58. data/lib/dry/schema/version.rb +3 -1
  59. data/lib/dry/schema.rb +39 -13
  60. data/lib/dry-schema.rb +2 -0
  61. metadata +43 -47
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dry/initializer'
2
4
 
3
5
  require 'dry/schema/constants'
@@ -50,29 +52,23 @@ module Dry
50
52
 
51
53
  include ::Dry::Equalizer(:options)
52
54
 
53
- # @!attribute [r] compiler
54
- # @return [Compiler] The rule compiler object
55
+ # @return [Compiler] The rule compiler object
55
56
  option :compiler, default: -> { Compiler.new }
56
57
 
57
- # @!attribute [r] processor_type
58
- # @return [Compiler] The type of the processor (Params, JSON, or a custom sub-class)
58
+ # @return [Compiler] The type of the processor (Params, JSON, or a custom sub-class)
59
59
  option :processor_type, default: -> { Processor }
60
60
 
61
- # @!attribute [r] macros
62
- # @return [Array] An array with macros defined within the DSL
61
+ # @return [Array] An array with macros defined within the DSL
63
62
  option :macros, default: -> { EMPTY_ARRAY.dup }
64
63
 
65
- # @!attribute [r] types
66
- # @return [Compiler] A key=>type map defined within the DSL
64
+ # @return [Compiler] A key=>type map defined within the DSL
67
65
  option :types, default: -> { EMPTY_HASH.dup }
68
66
 
69
- # @!attribute [r] parent
70
- # @return [DSL] An optional parent DSL object that will be used to merge keys and rules
67
+ # @return [DSL] An optional parent DSL object that will be used to merge keys and rules
71
68
  option :parent, optional: true
72
69
 
73
- # @!attribute [r] config
74
- # @return [Config] Configuration object exposed via `#configure` method
75
- option :config, optional: true, default: -> { Config.new }
70
+ # @return [Config] Configuration object exposed via `#configure` method
71
+ option :config, optional: true, default: proc { parent ? parent.config.dup : Config.new }
76
72
 
77
73
  # Build a new DSL object and evaluate provided block
78
74
  #
@@ -90,7 +86,7 @@ module Dry
90
86
  # @return [DSL]
91
87
  #
92
88
  # @api public
93
- def self.new(options = EMPTY_HASH, &block)
89
+ def self.new(**options, &block)
94
90
  dsl = super
95
91
  dsl.instance_eval(&block) if block
96
92
  dsl
@@ -101,7 +97,7 @@ module Dry
101
97
  # @example
102
98
  # Dry::Schema.define do
103
99
  # configure do |config|
104
- # config.messages = :i18n
100
+ # config.messages.backend = :i18n
105
101
  # end
106
102
  # end
107
103
  #
@@ -160,6 +156,8 @@ module Dry
160
156
  #
161
157
  # @api public
162
158
  def key(name, macro:, &block)
159
+ raise ArgumentError, "Key +#{name}+ is not a symbol" unless name.is_a?(::Symbol)
160
+
163
161
  set_type(name, Types::Any)
164
162
 
165
163
  macro = macro.new(
@@ -203,7 +201,7 @@ module Dry
203
201
  #
204
202
  # @api public
205
203
  def array
206
- -> member_type { type_registry["array"].of(resolve_type(member_type)) }
204
+ -> member_type { type_registry['array'].of(resolve_type(member_type)) }
207
205
  end
208
206
 
209
207
  # Return type schema used by the value coercer
@@ -212,7 +210,11 @@ module Dry
212
210
  #
213
211
  # @api private
214
212
  def type_schema
215
- type_registry["hash"].schema(types.merge(parent_types)).safe
213
+ if parent
214
+ parent.type_schema.schema(types)
215
+ else
216
+ type_registry['hash'].schema(types).lax
217
+ end
216
218
  end
217
219
 
218
220
  # Return a new DSL instance using the same processor type
@@ -234,16 +236,25 @@ module Dry
234
236
  # @api private
235
237
  def set_type(name, spec)
236
238
  type = resolve_type(spec)
237
- meta = { omittable: true, maybe: maybe?(type) }
239
+ meta = { required: false, maybe: type.optional? }
238
240
 
239
241
  types[name] = type.meta(meta)
240
242
  end
241
243
 
242
- # Check if the given type is a maybe sum
244
+ # Resolve type object from the provided spec
245
+ #
246
+ # @param [Symbol, Array<Symbol>, Dry::Types::Type] spec
247
+ #
248
+ # @return [Dry::Types::Type]
243
249
  #
244
250
  # @api private
245
- def maybe?(type)
246
- type.is_a?(Dry::Types::Sum) && type.left.primitive.equal?(NilClass)
251
+ def resolve_type(spec)
252
+ case spec
253
+ when ::Dry::Types::Type then spec
254
+ when ::Array then spec.map { |s| resolve_type(s) }.reduce(:|)
255
+ else
256
+ type_registry[spec]
257
+ end
247
258
  end
248
259
 
249
260
  protected
@@ -263,16 +274,14 @@ module Dry
263
274
  #
264
275
  # @api protected
265
276
  def rules
266
- macros.map { |m| [m.name, m.to_rule] }.to_h.merge(parent_rules)
277
+ parent_rules.merge(macros.map { |m| [m.name, m.to_rule] }.to_h.compact)
267
278
  end
268
279
 
269
280
  # Build a key map from defined types
270
281
  #
271
282
  # @api protected
272
283
  def key_map(types = self.types)
273
- keys = types.keys.each_with_object([]) { |key_name, arr|
274
- arr << key_spec(key_name, types[key_name])
275
- }
284
+ keys = types.map { |key, type| key_spec(key, type) }
276
285
  km = KeyMap.new(keys)
277
286
 
278
287
  if key_map_type
@@ -336,8 +345,8 @@ module Dry
336
345
  #
337
346
  # @api private
338
347
  def key_spec(name, type)
339
- if type.respond_to?(:member_types)
340
- { name => key_map(type.member_types) }
348
+ if type.respond_to?(:keys)
349
+ { name => key_map(type.name_key_map) }
341
350
  elsif type.respond_to?(:member)
342
351
  kv = key_spec(name, type.member)
343
352
  kv.equal?(name) ? name : kv.flatten(1)
@@ -346,33 +355,11 @@ module Dry
346
355
  end
347
356
  end
348
357
 
349
- # Resolve type object from the provided spec
350
- #
351
- # @param [Symbol, Array<Symbol>, Dry::Types::Type]
352
- #
353
- # @return [Dry::Types::Type]
354
- #
355
- # @api private
356
- def resolve_type(spec)
357
- case spec
358
- when ::Dry::Types::Type then spec
359
- when ::Array then spec.map { |s| resolve_type(s) }.reduce(:|)
360
- else
361
- type_registry[spec]
362
- end
363
- end
364
-
365
358
  # @api private
366
359
  def parent_rules
367
360
  parent&.rules || EMPTY_HASH
368
361
  end
369
362
 
370
- # @api private
371
- def parent_types
372
- # TODO: this is awful, it'd be nice if we had `Dry::Types::Hash::Schema#merge`
373
- parent&.type_schema&.member_types || EMPTY_HASH
374
- end
375
-
376
363
  # @api private
377
364
  def parent_key_map
378
365
  parent&.key_map || EMPTY_ARRAY
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Schema
5
+ module Extensions
6
+ module Hints
7
+ # Tweaks AND visitor to enable :hints
8
+ #
9
+ # @api private
10
+ module CompilerMethods
11
+ # @api private
12
+ def visit_and(node)
13
+ super.with(hints: true)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Schema
5
+ module Extensions
6
+ module Hints
7
+ # Adds support for processing [:hint, ...] nodes produced by dry-logic
8
+ #
9
+ # @api private
10
+ module MessageCompilerMethods
11
+ HINT_TYPE_EXCLUSION = %i[
12
+ key? nil? bool? str? int? float? decimal?
13
+ date? date_time? time? hash? array?
14
+ ].freeze
15
+
16
+ HINT_OTHER_EXCLUSION = %i[format? filled?].freeze
17
+
18
+ # @api private
19
+ attr_reader :hints
20
+
21
+ # @api private
22
+ def initialize(*args)
23
+ super
24
+ @hints = @options.fetch(:hints, true)
25
+ end
26
+
27
+ # @api private
28
+ def hints?
29
+ hints.equal?(true)
30
+ end
31
+
32
+ # @api private
33
+ def filter(messages, opts)
34
+ Array(messages).flatten.map { |msg| msg unless exclude?(msg, opts) }.compact.uniq
35
+ end
36
+
37
+ # @api private
38
+ def exclude?(messages, opts)
39
+ Array(messages).all? do |msg|
40
+ hints = opts
41
+ .hints
42
+ .reject { |hint| msg == hint }
43
+ .reject { |hint| hint.predicate == :filled? }
44
+
45
+ key_failure = opts.key_failure?(msg.path)
46
+ predicate = msg.predicate
47
+
48
+ (HINT_TYPE_EXCLUSION.include?(predicate) && !key_failure) ||
49
+ (msg.predicate == :filled? && key_failure) ||
50
+ (!key_failure && HINT_TYPE_EXCLUSION.include?(predicate) &&
51
+ !hints.empty? && hints.any? { |hint| hint.path == msg.path }) ||
52
+ HINT_OTHER_EXCLUSION.include?(predicate)
53
+ end
54
+ end
55
+
56
+ # @api private
57
+ def message_type(options)
58
+ options[:message_type].equal?(:hint) ? Hint : Message
59
+ end
60
+
61
+ # @api private
62
+ def visit_hint(node, opts)
63
+ if hints?
64
+ filter(visit(node, opts.(message_type: :hint)), opts)
65
+ end
66
+ end
67
+
68
+ # @api private
69
+ def visit_predicate(node, opts)
70
+ message = super
71
+ opts.current_messages << message
72
+ message
73
+ end
74
+
75
+ # @api private
76
+ def visit_each(node, opts)
77
+ # TODO: we can still generate a hint for elements here!
78
+ []
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Schema
5
+ module Extensions
6
+ module Hints
7
+ # Hint extensions for MessageSet
8
+ #
9
+ # @api public
10
+ module MessageSetMethods
11
+ # Filtered message hints from all messages
12
+ #
13
+ # @return [Array<Message::Hint>]
14
+ attr_reader :hints
15
+
16
+ # Configuration option to enable/disable showing errors
17
+ #
18
+ # @return [Boolean]
19
+ attr_reader :failures
20
+
21
+ # @api private
22
+ def initialize(messages, options = EMPTY_HASH)
23
+ super
24
+ @hints = messages.select(&:hint?)
25
+ @failures = options.fetch(:failures, true)
26
+ end
27
+
28
+ # Dump message set to a hash with either all messages or just hints
29
+ #
30
+ # @see MessageSet#to_h
31
+ # @see ResultMethods#hints
32
+ #
33
+ # @return [Hash<Symbol=>Array<String>>]
34
+ #
35
+ # @api public
36
+ def to_h
37
+ @to_h ||= failures ? messages_map : messages_map(hints)
38
+ end
39
+ alias_method :to_hash, :to_h
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Schema
5
+ module Extensions
6
+ module Hints
7
+ # Get errors exclusively without hints
8
+ #
9
+ # @api public
10
+ module ResultMethods
11
+ # Return error messages exclusively
12
+ #
13
+ # @see Result#errors
14
+ #
15
+ # @return [MessageSet]
16
+ #
17
+ # @api public
18
+ def errors(options = EMPTY_HASH)
19
+ message_set(options.merge(hints: false))
20
+ end
21
+
22
+ # Get all messages including hints
23
+ #
24
+ # @see #message_set
25
+ #
26
+ # @return [MessageSet]
27
+ #
28
+ # @api public
29
+ def messages(options = EMPTY_HASH)
30
+ message_set(options)
31
+ end
32
+
33
+ # Get hints exclusively without errors
34
+ #
35
+ # @see #message_set
36
+ #
37
+ # @return [MessageSet]
38
+ #
39
+ # @api public
40
+ def hints(options = EMPTY_HASH)
41
+ message_set(options.merge(failures: false))
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/schema/compiler'
4
+ require 'dry/schema/message'
5
+ require 'dry/schema/message_compiler'
6
+
7
+ require 'dry/schema/extensions/hints/compiler_methods'
8
+ require 'dry/schema/extensions/hints/message_compiler_methods'
9
+ require 'dry/schema/extensions/hints/message_set_methods'
10
+ require 'dry/schema/extensions/hints/result_methods'
11
+
12
+ module Dry
13
+ module Schema
14
+ # Hint-specific Message extensions
15
+ #
16
+ # @see Message
17
+ #
18
+ # @api public
19
+ class Message
20
+ # Hints extension for Or messages
21
+ #
22
+ # @see Message::Or
23
+ #
24
+ # @api public
25
+ class Or
26
+ # @api private
27
+ def hint?
28
+ false
29
+ end
30
+ end
31
+
32
+ # @api private
33
+ def hint?
34
+ false
35
+ end
36
+ end
37
+
38
+ # A hint message sub-type
39
+ #
40
+ # @api private
41
+ class Hint < Message
42
+ # @api private
43
+ def hint?
44
+ true
45
+ end
46
+ end
47
+
48
+ # Hints extensions
49
+ module Extensions
50
+ Compiler.prepend(Hints::CompilerMethods)
51
+ MessageCompiler.prepend(Hints::MessageCompilerMethods)
52
+ MessageSet.prepend(Hints::MessageSetMethods)
53
+ Result.prepend(Hints::ResultMethods)
54
+ end
55
+ end
56
+ end
@@ -1,18 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dry/monads/result'
2
4
 
3
5
  module Dry
4
6
  module Schema
7
+ # Monad extension for Result
8
+ #
9
+ # @api public
5
10
  class Result
6
11
  include Dry::Monads::Result::Mixin
7
12
 
8
- def to_monad(options = EMPTY_HASH)
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
9
21
  if success?
10
- Success(output)
22
+ Success(self)
11
23
  else
12
- Failure(messages(options))
24
+ Failure(self)
13
25
  end
14
26
  end
15
- alias_method :to_result, :to_monad
16
27
  end
17
28
  end
18
29
  end
@@ -1,3 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Dry::Schema.register_extension(:monads) do
2
4
  require 'dry/schema/extensions/monads'
3
5
  end
6
+
7
+ Dry::Schema.register_extension(:hints) do
8
+ require 'dry/schema/extensions/hints'
9
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dry/schema/processor'
2
4
 
3
5
  module Dry
@@ -5,7 +7,7 @@ module Dry
5
7
  # JSON schema type
6
8
  #
7
9
  # @see Processor
8
- # @see Schema.JSON
10
+ # @see Schema#JSON
9
11
  #
10
12
  # @api public
11
13
  class JSON < Processor
@@ -13,4 +15,4 @@ module Dry
13
15
  config.type_registry = config.type_registry.namespaced(:json)
14
16
  end
15
17
  end
16
- end
18
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  module Schema
3
5
  # Key objects used by key maps
@@ -10,19 +12,13 @@ module Dry
10
12
 
11
13
  include Dry.Equalizer(:name, :coercer)
12
14
 
13
- # @!attribute[r] id
14
- # @return [Symbol] The key identifier
15
- # @api public
15
+ # @return [Symbol] The key identifier
16
16
  attr_reader :id
17
17
 
18
- # @!attribute[r] name
19
- # @return [Symbol, String, Object] The actual key name expected in an input hash
20
- # @api public
18
+ # @return [Symbol, String, Object] The actual key name expected in an input hash
21
19
  attr_reader :name
22
20
 
23
- # @!attribute[r] id
24
- # @return [Proc, #call] A key name coercer function
25
- # @api public
21
+ # @return [Proc, #call] A key name coercer function
26
22
  attr_reader :coercer
27
23
 
28
24
  # @api private
@@ -44,6 +40,8 @@ module Dry
44
40
 
45
41
  # @api private
46
42
  def read(source)
43
+ return unless source.is_a?(::Hash)
44
+
47
45
  if source.key?(name)
48
46
  yield(source[name])
49
47
  elsif source.key?(coerced_name)
@@ -163,4 +161,4 @@ module Dry
163
161
  end
164
162
  end
165
163
  end
166
- end
164
+ end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dry/core/cache'
4
+ require 'dry/equalizer'
2
5
 
3
6
  module Dry
4
7
  module Schema
@@ -7,6 +10,7 @@ module Dry
7
10
  # @api private
8
11
  class KeyCoercer
9
12
  extend Dry::Core::Cache
13
+ include ::Dry::Equalizer(:key_map, :coercer)
10
14
 
11
15
  TO_SYM = :to_sym.to_proc.freeze
12
16
 
@@ -26,10 +30,10 @@ module Dry
26
30
  def initialize(key_map, &coercer)
27
31
  @key_map = key_map.coercible(&coercer)
28
32
  end
29
-
33
+
30
34
  # @api private
31
35
  def call(source)
32
- key_map.write(Hash(source))
36
+ key_map.write(source.to_h)
33
37
  end
34
38
  alias_method :[], :call
35
39
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dry/equalizer'
2
4
  require 'dry/core/cache'
3
5
  require 'dry/schema/constants'
@@ -19,8 +21,7 @@ module Dry
19
21
  include Dry.Equalizer(:keys)
20
22
  include Enumerable
21
23
 
22
- # @!attribute[r] keys
23
- # @return [Array<Key>] A list of defined key objects
24
+ # @return [Array<Key>] A list of defined key objects
24
25
  attr_reader :keys
25
26
 
26
27
  # Coerce a list of key specs into a key map
@@ -39,7 +40,7 @@ module Dry
39
40
 
40
41
  # Build new, or returned a cached instance of a key map
41
42
  #
42
- # @param [Array<Symbol, Array, Hash<Symbol=>Array>>
43
+ # @param [Array<Symbol>, Array, Hash<Symbol=>Array>] args
43
44
  #
44
45
  # @return [KeyMap]
45
46
  def self.new(*args)
@@ -130,4 +131,4 @@ module Dry
130
131
  end
131
132
  end
132
133
  end
133
- end
134
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/schema/macros/dsl'
4
+
5
+ module Dry
6
+ module Schema
7
+ module Macros
8
+ # Macro used to specify predicates for each element of an array
9
+ #
10
+ # @api private
11
+ class Array < DSL
12
+ # @api private
13
+ def value(*args, **opts, &block)
14
+ type(:array)
15
+
16
+ extract_type_spec(*args, set_type: false) do |*predicates, type_spec:|
17
+ type(schema_dsl.array[type_spec]) if type_spec
18
+
19
+ is_hash_block = type_spec.equal?(:hash)
20
+
21
+ if predicates.any? || opts.any? || !is_hash_block
22
+ super(*predicates, type_spec: type_spec, **opts, &(is_hash_block ? nil : block))
23
+ end
24
+
25
+ hash(&block) if is_hash_block
26
+ end
27
+
28
+ self
29
+ end
30
+
31
+ # @api private
32
+ def to_ast(*)
33
+ [:and, [trace.array?.to_ast, [:each, trace.to_ast]]]
34
+ end
35
+ alias_method :ast, :to_ast
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dry/initializer'
2
4
 
3
5
  require 'dry/schema/constants'