mega-sharp-sys 0.0.1
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.
- checksums.yaml +7 -0
- data/dry-schema-1.16.0/CHANGELOG.md +901 -0
- data/dry-schema-1.16.0/LICENSE +20 -0
- data/dry-schema-1.16.0/README.md +17 -0
- data/dry-schema-1.16.0/config/errors.yml +127 -0
- data/dry-schema-1.16.0/dry-schema.gemspec +50 -0
- data/dry-schema-1.16.0/lib/dry/schema/compiler.rb +51 -0
- data/dry-schema-1.16.0/lib/dry/schema/config.rb +83 -0
- data/dry-schema-1.16.0/lib/dry/schema/constants.rb +47 -0
- data/dry-schema-1.16.0/lib/dry/schema/dsl.rb +517 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/hints/compiler_methods.rb +19 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/hints/message_compiler_methods.rb +89 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/hints/message_set_methods.rb +44 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/hints/result_methods.rb +47 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/hints.rb +65 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/info/schema_compiler.rb +123 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/info.rb +27 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/json_schema/schema_compiler.rb +314 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/json_schema.rb +29 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/monads.rb +32 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions/struct.rb +62 -0
- data/dry-schema-1.16.0/lib/dry/schema/extensions.rb +21 -0
- data/dry-schema-1.16.0/lib/dry/schema/json.rb +17 -0
- data/dry-schema-1.16.0/lib/dry/schema/key.rb +184 -0
- data/dry-schema-1.16.0/lib/dry/schema/key_coercer.rb +41 -0
- data/dry-schema-1.16.0/lib/dry/schema/key_map.rb +136 -0
- data/dry-schema-1.16.0/lib/dry/schema/key_validator.rb +117 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/array.rb +54 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/core.rb +55 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/dsl.rb +282 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/each.rb +31 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/filled.rb +58 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/hash.rb +36 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/key.rb +50 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/maybe.rb +38 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/optional.rb +22 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/required.rb +17 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/schema.rb +103 -0
- data/dry-schema-1.16.0/lib/dry/schema/macros/value.rb +125 -0
- data/dry-schema-1.16.0/lib/dry/schema/message/or/abstract.rb +28 -0
- data/dry-schema-1.16.0/lib/dry/schema/message/or/multi_path.rb +100 -0
- data/dry-schema-1.16.0/lib/dry/schema/message/or/single_path.rb +72 -0
- data/dry-schema-1.16.0/lib/dry/schema/message/or.rb +30 -0
- data/dry-schema-1.16.0/lib/dry/schema/message.rb +116 -0
- data/dry-schema-1.16.0/lib/dry/schema/message_compiler/visitor_opts.rb +56 -0
- data/dry-schema-1.16.0/lib/dry/schema/message_compiler.rb +234 -0
- data/dry-schema-1.16.0/lib/dry/schema/message_set.rb +144 -0
- data/dry-schema-1.16.0/lib/dry/schema/messages/abstract.rb +202 -0
- data/dry-schema-1.16.0/lib/dry/schema/messages/i18n.rb +139 -0
- data/dry-schema-1.16.0/lib/dry/schema/messages/namespaced.rb +93 -0
- data/dry-schema-1.16.0/lib/dry/schema/messages/template.rb +43 -0
- data/dry-schema-1.16.0/lib/dry/schema/messages/yaml.rb +209 -0
- data/dry-schema-1.16.0/lib/dry/schema/messages.rb +32 -0
- data/dry-schema-1.16.0/lib/dry/schema/namespaced_rule.rb +38 -0
- data/dry-schema-1.16.0/lib/dry/schema/params.rb +17 -0
- data/dry-schema-1.16.0/lib/dry/schema/path.rb +107 -0
- data/dry-schema-1.16.0/lib/dry/schema/predicate.rb +102 -0
- data/dry-schema-1.16.0/lib/dry/schema/predicate_inferrer.rb +25 -0
- data/dry-schema-1.16.0/lib/dry/schema/predicate_registry.rb +22 -0
- data/dry-schema-1.16.0/lib/dry/schema/primitive_inferrer.rb +22 -0
- data/dry-schema-1.16.0/lib/dry/schema/processor.rb +213 -0
- data/dry-schema-1.16.0/lib/dry/schema/processor_steps.rb +141 -0
- data/dry-schema-1.16.0/lib/dry/schema/result.rb +203 -0
- data/dry-schema-1.16.0/lib/dry/schema/rule_applier.rb +47 -0
- data/dry-schema-1.16.0/lib/dry/schema/step.rb +59 -0
- data/dry-schema-1.16.0/lib/dry/schema/trace.rb +114 -0
- data/dry-schema-1.16.0/lib/dry/schema/type_container.rb +27 -0
- data/dry-schema-1.16.0/lib/dry/schema/type_registry.rb +44 -0
- data/dry-schema-1.16.0/lib/dry/schema/types.rb +14 -0
- data/dry-schema-1.16.0/lib/dry/schema/types_merger.rb +139 -0
- data/dry-schema-1.16.0/lib/dry/schema/value_coercer.rb +36 -0
- data/dry-schema-1.16.0/lib/dry/schema/version.rb +7 -0
- data/dry-schema-1.16.0/lib/dry/schema.rb +114 -0
- data/dry-schema-1.16.0/lib/dry-schema.rb +3 -0
- data/mega-sharp-sys.gemspec +11 -0
- metadata +114 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
module Schema
|
|
5
|
+
module Macros
|
|
6
|
+
# Macro specialization used within the DSL
|
|
7
|
+
#
|
|
8
|
+
# @api public
|
|
9
|
+
class DSL < Core
|
|
10
|
+
include ::Dry::Logic::Operators
|
|
11
|
+
|
|
12
|
+
undef :eql?
|
|
13
|
+
undef :nil?
|
|
14
|
+
undef :respond_to?
|
|
15
|
+
|
|
16
|
+
# @!attribute [r] chain
|
|
17
|
+
# Indicate if the macro should append its rules to the provided trace
|
|
18
|
+
# @return [Boolean]
|
|
19
|
+
# @api private
|
|
20
|
+
option :chain, default: -> { true }
|
|
21
|
+
|
|
22
|
+
# @!attribute [r] predicate_inferrer
|
|
23
|
+
# PredicateInferrer is used to infer predicate type-check from a type spec
|
|
24
|
+
# @return [PredicateInferrer]
|
|
25
|
+
# @api private
|
|
26
|
+
option :predicate_inferrer, default: proc { PredicateInferrer.new(compiler.predicates) }
|
|
27
|
+
|
|
28
|
+
# @!attribute [r] primitive_inferrer
|
|
29
|
+
# PrimitiveInferrer used to get a list of primitive classes from configured type
|
|
30
|
+
# @return [PrimitiveInferrer]
|
|
31
|
+
# @api private
|
|
32
|
+
option :primitive_inferrer, default: proc { PrimitiveInferrer.new }
|
|
33
|
+
|
|
34
|
+
# @overload value(*predicates, **predicate_opts)
|
|
35
|
+
# Set predicates without and with arguments
|
|
36
|
+
#
|
|
37
|
+
# @param [Array<Symbol>] predicates
|
|
38
|
+
# @param [Hash] predicate_opts
|
|
39
|
+
#
|
|
40
|
+
# @example with a predicate
|
|
41
|
+
# required(:name).value(:filled?)
|
|
42
|
+
#
|
|
43
|
+
# @example with a predicate with arguments
|
|
44
|
+
# required(:name).value(min_size?: 2)
|
|
45
|
+
#
|
|
46
|
+
# @example with a predicate with and without arguments
|
|
47
|
+
# required(:name).value(:filled?, min_size?: 2)
|
|
48
|
+
#
|
|
49
|
+
# @example with a block
|
|
50
|
+
# required(:name).value { filled? & min_size?(2) }
|
|
51
|
+
#
|
|
52
|
+
# @return [Macros::Core]
|
|
53
|
+
#
|
|
54
|
+
# @api public
|
|
55
|
+
def value(*args, **opts, &block)
|
|
56
|
+
if (type_spec_from_opts = opts[:type_spec])
|
|
57
|
+
append_macro(Macros::Value) do |macro|
|
|
58
|
+
macro.call(*args, type_spec: type_spec_from_opts, **opts, &block)
|
|
59
|
+
end
|
|
60
|
+
else
|
|
61
|
+
extract_type_spec(args) do |*predicates, type_spec:, type_rule:|
|
|
62
|
+
append_macro(Macros::Value) do |macro|
|
|
63
|
+
macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Prepends `:filled?` predicate
|
|
70
|
+
#
|
|
71
|
+
# @example with a type spec
|
|
72
|
+
# required(:name).filled(:string)
|
|
73
|
+
#
|
|
74
|
+
# @example with a type spec and a predicate
|
|
75
|
+
# required(:name).filled(:string, format?: /\w+/)
|
|
76
|
+
#
|
|
77
|
+
# @return [Macros::Core]
|
|
78
|
+
#
|
|
79
|
+
# @api public
|
|
80
|
+
def filled(*args, **opts, &block)
|
|
81
|
+
extract_type_spec(args) do |*predicates, type_spec:, type_rule:|
|
|
82
|
+
append_macro(Macros::Filled) do |macro|
|
|
83
|
+
macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Set type specification and predicates for a maybe value
|
|
89
|
+
#
|
|
90
|
+
# @example
|
|
91
|
+
# required(:name).maybe(:string)
|
|
92
|
+
#
|
|
93
|
+
# @see Macros::Key#value
|
|
94
|
+
#
|
|
95
|
+
# @return [Macros::Key]
|
|
96
|
+
#
|
|
97
|
+
# @api public
|
|
98
|
+
def maybe(*args, **opts, &block)
|
|
99
|
+
extract_type_spec(args, nullable: true) do |*predicates, type_spec:, type_rule:|
|
|
100
|
+
append_macro(Macros::Maybe) do |macro|
|
|
101
|
+
macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Specify a nested hash without enforced `hash?` type-check
|
|
107
|
+
#
|
|
108
|
+
# This is a simpler building block than `hash` macro, use it
|
|
109
|
+
# when you want to provide `hash?` type-check with other rules
|
|
110
|
+
# manually.
|
|
111
|
+
#
|
|
112
|
+
# @example
|
|
113
|
+
# required(:tags).value(:hash, min_size?: 1).schema do
|
|
114
|
+
# required(:name).value(:string)
|
|
115
|
+
# end
|
|
116
|
+
#
|
|
117
|
+
# @return [Macros::Core]
|
|
118
|
+
#
|
|
119
|
+
# @api public
|
|
120
|
+
def schema(...)
|
|
121
|
+
append_macro(Macros::Schema) do |macro|
|
|
122
|
+
macro.call(...)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Specify a nested hash with enforced `hash?` type-check
|
|
127
|
+
#
|
|
128
|
+
# @example
|
|
129
|
+
# required(:tags).hash do
|
|
130
|
+
# required(:name).value(:string)
|
|
131
|
+
# end
|
|
132
|
+
#
|
|
133
|
+
# @api public
|
|
134
|
+
def hash(...)
|
|
135
|
+
append_macro(Macros::Hash) do |macro|
|
|
136
|
+
macro.call(...)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Specify predicates that should be applied to each element of an array
|
|
141
|
+
#
|
|
142
|
+
# This is a simpler building block than `array` macro, use it
|
|
143
|
+
# when you want to provide `array?` type-check with other rules
|
|
144
|
+
# manually.
|
|
145
|
+
#
|
|
146
|
+
# @example a list of strings
|
|
147
|
+
# required(:tags).value(:array, min_size?: 2).each(:str?)
|
|
148
|
+
#
|
|
149
|
+
# @example a list of hashes
|
|
150
|
+
# required(:tags).value(:array, min_size?: 2).each(:hash) do
|
|
151
|
+
# required(:name).filled(:string)
|
|
152
|
+
# end
|
|
153
|
+
#
|
|
154
|
+
# @return [Macros::Core]
|
|
155
|
+
#
|
|
156
|
+
# @api public
|
|
157
|
+
def each(...)
|
|
158
|
+
append_macro(Macros::Each) do |macro|
|
|
159
|
+
macro.value(...)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Like `each` but sets `array?` type-check
|
|
164
|
+
#
|
|
165
|
+
# @example a list of strings
|
|
166
|
+
# required(:tags).array(:str?)
|
|
167
|
+
#
|
|
168
|
+
# @example a list of hashes
|
|
169
|
+
# required(:tags).array(:hash) do
|
|
170
|
+
# required(:name).filled(:string)
|
|
171
|
+
# end
|
|
172
|
+
#
|
|
173
|
+
# @return [Macros::Core]
|
|
174
|
+
#
|
|
175
|
+
# @api public
|
|
176
|
+
def array(...)
|
|
177
|
+
append_macro(Macros::Array) do |macro|
|
|
178
|
+
macro.value(...)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Set type spec
|
|
183
|
+
#
|
|
184
|
+
# @example
|
|
185
|
+
# required(:name).type(:string).value(min_size?: 2)
|
|
186
|
+
#
|
|
187
|
+
# @param [Symbol, Array, Dry::Types::Type] spec
|
|
188
|
+
#
|
|
189
|
+
# @return [Macros::Key]
|
|
190
|
+
#
|
|
191
|
+
# @api public
|
|
192
|
+
def type(spec)
|
|
193
|
+
schema_dsl.set_type(name, spec)
|
|
194
|
+
self
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# @api private
|
|
198
|
+
def custom_type?
|
|
199
|
+
schema_dsl.custom_type?(name)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
private
|
|
203
|
+
|
|
204
|
+
# @api private
|
|
205
|
+
def append_macro(macro_type)
|
|
206
|
+
macro = macro_type.new(schema_dsl: schema_dsl, name: name)
|
|
207
|
+
|
|
208
|
+
yield(macro)
|
|
209
|
+
|
|
210
|
+
if chain
|
|
211
|
+
trace << macro
|
|
212
|
+
self
|
|
213
|
+
else
|
|
214
|
+
macro
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# @api private
|
|
219
|
+
# rubocop: disable Metrics/AbcSize
|
|
220
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
|
221
|
+
# rubocop: disable Metrics/PerceivedComplexity
|
|
222
|
+
def extract_type_spec(args, nullable: false, set_type: true)
|
|
223
|
+
type_spec = args[0] unless schema_or_predicate?(args[0])
|
|
224
|
+
|
|
225
|
+
predicates = Array(type_spec ? args[1..] : args)
|
|
226
|
+
type_rule = nil
|
|
227
|
+
|
|
228
|
+
if type_spec
|
|
229
|
+
resolved_type = resolve_type(type_spec, nullable)
|
|
230
|
+
|
|
231
|
+
if type_spec.is_a?(::Array)
|
|
232
|
+
type_rule = type_spec.map { |ts| new(chain: false).value(ts) }.reduce(:|)
|
|
233
|
+
elsif type_spec.is_a?(Dry::Types::Sum) && set_type
|
|
234
|
+
type_rule = [type_spec.left, type_spec.right].map { |ts|
|
|
235
|
+
new(klass: Core, chain: false).value(ts)
|
|
236
|
+
}.reduce(:|)
|
|
237
|
+
elsif type_spec.is_a?(Dry::Types::Intersection) && set_type
|
|
238
|
+
type_rule = [type_spec.left, type_spec.right].map { |ts|
|
|
239
|
+
new(klass: Core, chain: false).value(ts)
|
|
240
|
+
}.reduce(:&)
|
|
241
|
+
else
|
|
242
|
+
type_predicates = predicate_inferrer[resolved_type]
|
|
243
|
+
|
|
244
|
+
predicates.replace(type_predicates + predicates) unless type_predicates.empty?
|
|
245
|
+
|
|
246
|
+
return self if predicates.empty?
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
type(resolved_type) if set_type && resolved_type
|
|
251
|
+
|
|
252
|
+
if type_rule
|
|
253
|
+
yield(*predicates, type_spec: nil, type_rule: type_rule)
|
|
254
|
+
else
|
|
255
|
+
yield(*predicates, type_spec: type_spec, type_rule: nil)
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
# rubocop: enable Metrics/AbcSize
|
|
259
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
|
260
|
+
# rubocop: enable Metrics/PerceivedComplexity
|
|
261
|
+
|
|
262
|
+
# @api private
|
|
263
|
+
def resolve_type(type_spec, nullable)
|
|
264
|
+
resolved = schema_dsl.resolve_type(type_spec)
|
|
265
|
+
|
|
266
|
+
if type_spec.is_a?(::Array) || !nullable || resolved.optional?
|
|
267
|
+
resolved
|
|
268
|
+
else
|
|
269
|
+
schema_dsl.resolve_type([:nil, resolved])
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# @api private
|
|
274
|
+
def schema_or_predicate?(arg)
|
|
275
|
+
arg.is_a?(Dry::Schema::Processor) ||
|
|
276
|
+
(arg.is_a?(Symbol) &&
|
|
277
|
+
arg.to_s.end_with?(QUESTION_MARK))
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
module Schema
|
|
5
|
+
module Macros
|
|
6
|
+
# Macro used to specify predicates for each element of an array
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
class Each < DSL
|
|
10
|
+
# @api private
|
|
11
|
+
def value(*args, **opts, &block)
|
|
12
|
+
extract_type_spec(args, set_type: false) do |*predicates, type_spec:, type_rule:|
|
|
13
|
+
if type_spec && !type_spec.is_a?(Dry::Types::Type)
|
|
14
|
+
type(schema_dsl.array[type_spec])
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
append_macro(Macros::Value) do |macro|
|
|
18
|
+
macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @api private
|
|
24
|
+
def to_ast(*)
|
|
25
|
+
[:each, trace.to_ast]
|
|
26
|
+
end
|
|
27
|
+
alias_method :ast, :to_ast
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
module Schema
|
|
5
|
+
module Macros
|
|
6
|
+
# Macro used to prepend `:filled?` predicate
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
class Filled < Value
|
|
10
|
+
# @api private
|
|
11
|
+
def call(*predicates, **opts, &block)
|
|
12
|
+
ensure_valid_predicates(predicates)
|
|
13
|
+
|
|
14
|
+
append_macro(Macros::Value) do |macro|
|
|
15
|
+
if opts[:type_spec] && !filter_empty_string?
|
|
16
|
+
macro.call(predicates[0], :filled?, *predicates.drop(1), **opts, &block)
|
|
17
|
+
elsif opts[:type_rule]
|
|
18
|
+
macro.call(:filled?).value(*predicates, **opts, &block)
|
|
19
|
+
else
|
|
20
|
+
macro.call(:filled?, *predicates, **opts, &block)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @api private
|
|
26
|
+
def ensure_valid_predicates(predicates)
|
|
27
|
+
if predicates.include?(:empty?)
|
|
28
|
+
raise ::Dry::Schema::InvalidSchemaError, "Using filled with empty? predicate is invalid"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if predicates.include?(:filled?)
|
|
32
|
+
raise ::Dry::Schema::InvalidSchemaError, "Using filled with filled? is redundant"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @api private
|
|
37
|
+
def filter_empty_string?
|
|
38
|
+
!expected_primitives.include?(NilClass) && processor_config.filter_empty_string
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @api private
|
|
42
|
+
def processor_config
|
|
43
|
+
schema_dsl.processor_type.config
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @api private
|
|
47
|
+
def expected_primitives
|
|
48
|
+
primitive_inferrer[schema_type]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @api private
|
|
52
|
+
def schema_type
|
|
53
|
+
schema_dsl.types[name]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
module Schema
|
|
5
|
+
module Macros
|
|
6
|
+
# Macro used to specify a nested schema
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
class Hash < Schema
|
|
10
|
+
# @api private
|
|
11
|
+
def call(*args, &block)
|
|
12
|
+
if args.size >= 1 && args[0].respond_to?(:keys)
|
|
13
|
+
hash_type = args[0]
|
|
14
|
+
type_predicates = predicate_inferrer[hash_type]
|
|
15
|
+
all_predicats = type_predicates + args.drop(1)
|
|
16
|
+
|
|
17
|
+
super(*all_predicats) do
|
|
18
|
+
hash_type.each do |key|
|
|
19
|
+
if key.required?
|
|
20
|
+
required(key.name).value(key.type)
|
|
21
|
+
else
|
|
22
|
+
optional(key.name).value(key.type)
|
|
23
|
+
end
|
|
24
|
+
instance_exec(&block) if block_given?
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
else
|
|
28
|
+
trace << hash?
|
|
29
|
+
|
|
30
|
+
super
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
module Schema
|
|
5
|
+
module Macros
|
|
6
|
+
# Base macro for specifying rules applied to a value found under a key
|
|
7
|
+
#
|
|
8
|
+
# @api public
|
|
9
|
+
class Key < DSL
|
|
10
|
+
# @!attribute [r] filter_schema_dsl
|
|
11
|
+
# @return [Schema::DSL]
|
|
12
|
+
# @api private
|
|
13
|
+
option :filter_schema_dsl, default: proc { schema_dsl&.filter_schema_dsl }
|
|
14
|
+
|
|
15
|
+
# Specify predicates that should be applied before coercion
|
|
16
|
+
#
|
|
17
|
+
# @example check format before coercing to a date
|
|
18
|
+
# required(:publish_date).filter(format?: /\d{4}-\d{2}-\d{2}).value(:date)
|
|
19
|
+
#
|
|
20
|
+
# @see Macros::Key#value
|
|
21
|
+
#
|
|
22
|
+
# @return [Macros::Key]
|
|
23
|
+
#
|
|
24
|
+
# @api public
|
|
25
|
+
def filter(...)
|
|
26
|
+
(filter_schema_dsl[name] || filter_schema_dsl.optional(name)).value(...)
|
|
27
|
+
self
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Coerce macro to a rule
|
|
31
|
+
#
|
|
32
|
+
# @return [Dry::Logic::Rule]
|
|
33
|
+
#
|
|
34
|
+
# @api private
|
|
35
|
+
def to_rule
|
|
36
|
+
if trace.captures.empty?
|
|
37
|
+
super
|
|
38
|
+
else
|
|
39
|
+
[super, trace.to_rule(name)].reduce(operation)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @api private
|
|
44
|
+
def to_ast
|
|
45
|
+
[:predicate, [:key?, [[:name, name], [:input, Undefined]]]]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
module Schema
|
|
5
|
+
module Macros
|
|
6
|
+
# Macro used to specify predicates for a value that can be `nil`
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
class Maybe < DSL
|
|
10
|
+
# @api private
|
|
11
|
+
def call(*args, **opts, &block)
|
|
12
|
+
if args.include?(:empty?)
|
|
13
|
+
raise ::Dry::Schema::InvalidSchemaError, "Using maybe with empty? predicate is invalid"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if args.include?(:nil?)
|
|
17
|
+
raise ::Dry::Schema::InvalidSchemaError, "Using maybe with nil? predicate is redundant"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
append_macro(Macros::Value) do |macro|
|
|
21
|
+
macro.call(*args, **opts, &block)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @api private
|
|
28
|
+
def to_ast
|
|
29
|
+
[:implication,
|
|
30
|
+
[
|
|
31
|
+
[:not, [:predicate, [:nil?, [[:input, Undefined]]]]],
|
|
32
|
+
trace.to_rule.to_ast
|
|
33
|
+
]]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
module Schema
|
|
5
|
+
module Macros
|
|
6
|
+
# A Key specialization used for keys that can be skipped
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
class Optional < Key
|
|
10
|
+
# @api private
|
|
11
|
+
def operation
|
|
12
|
+
:then
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @api private
|
|
16
|
+
def to_rule
|
|
17
|
+
super unless trace.captures.empty?
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
module Schema
|
|
5
|
+
module Macros
|
|
6
|
+
# A Key specialization used for keys that must be present
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
class Required < Key
|
|
10
|
+
# @api private
|
|
11
|
+
def operation
|
|
12
|
+
:and
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
module Schema
|
|
5
|
+
module Macros
|
|
6
|
+
# Macro used to specify a nested schema
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
class Schema < Value
|
|
10
|
+
# @api private
|
|
11
|
+
def call(*args, &block)
|
|
12
|
+
super(*args, &nil) unless args.empty?
|
|
13
|
+
|
|
14
|
+
if args.size.equal?(1) && (op = args.first).is_a?(::Dry::Logic::Operations::Abstract)
|
|
15
|
+
process_operation(op)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if block
|
|
19
|
+
schema = define(*args, &block)
|
|
20
|
+
import_steps(schema)
|
|
21
|
+
trace << schema.to_rule
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
# @api private
|
|
30
|
+
def process_operation(op)
|
|
31
|
+
type(hash_type.schema(merge_operation_types(op)))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @api private
|
|
35
|
+
def hash_type
|
|
36
|
+
schema_dsl.resolve_type(:hash)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @api private
|
|
40
|
+
def merge_operation_types(op)
|
|
41
|
+
op.rules.reduce({}) do |acc, rule|
|
|
42
|
+
types =
|
|
43
|
+
case rule
|
|
44
|
+
when Dry::Logic::Operations::Abstract
|
|
45
|
+
merge_operation_types(rule)
|
|
46
|
+
when Processor
|
|
47
|
+
rule.types
|
|
48
|
+
else
|
|
49
|
+
EMPTY_HASH.dup
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
schema_dsl.merge_types(op.class, acc, types)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @api private
|
|
57
|
+
# rubocop: disable Metrics/AbcSize
|
|
58
|
+
def define(*args, &)
|
|
59
|
+
definition = schema_dsl.new(path: schema_dsl.path, &)
|
|
60
|
+
schema = definition.call
|
|
61
|
+
type_schema =
|
|
62
|
+
if array_type?(parent_type)
|
|
63
|
+
build_array_type(parent_type, definition.strict_type_schema)
|
|
64
|
+
elsif redefined_schema?(args)
|
|
65
|
+
parent_type.schema(definition.types)
|
|
66
|
+
else
|
|
67
|
+
definition.strict_type_schema
|
|
68
|
+
end
|
|
69
|
+
final_type = optional? ? type_schema.optional : type_schema
|
|
70
|
+
|
|
71
|
+
type(final_type)
|
|
72
|
+
|
|
73
|
+
if schema.filter_rules?
|
|
74
|
+
schema_dsl[name].filter { hash?.then(schema(schema.filter_schema)) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
schema
|
|
78
|
+
end
|
|
79
|
+
# rubocop: enable Metrics/AbcSize
|
|
80
|
+
|
|
81
|
+
# @api private
|
|
82
|
+
def parent_type
|
|
83
|
+
schema_dsl.types[name]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# @api private
|
|
87
|
+
def optional?
|
|
88
|
+
parent_type.optional?
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# @api private
|
|
92
|
+
def schema?
|
|
93
|
+
parent_type.respond_to?(:schema)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# @api private
|
|
97
|
+
def redefined_schema?(args)
|
|
98
|
+
schema? && args.first.is_a?(Processor)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|