nxt_schema 1.0.0 → 1.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 +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +80 -38
- data/lib/nxt_schema.rb +17 -17
- data/lib/nxt_schema/dsl.rb +7 -7
- data/lib/nxt_schema/{application.rb → node.rb} +1 -1
- data/lib/nxt_schema/node/any_of.rb +21 -33
- data/lib/nxt_schema/node/base.rb +70 -171
- data/lib/nxt_schema/node/collection.rb +43 -8
- data/lib/nxt_schema/{application → node}/error_store.rb +5 -5
- data/lib/nxt_schema/{application → node}/errors/schema_error.rb +1 -1
- data/lib/nxt_schema/{application → node}/errors/validation_error.rb +1 -1
- data/lib/nxt_schema/node/leaf.rb +7 -5
- data/lib/nxt_schema/node/schema.rb +101 -8
- data/lib/nxt_schema/template/any_of.rb +50 -0
- data/lib/nxt_schema/template/base.rb +218 -0
- data/lib/nxt_schema/template/collection.rb +23 -0
- data/lib/nxt_schema/{node → template}/has_sub_nodes.rb +16 -10
- data/lib/nxt_schema/template/leaf.rb +13 -0
- data/lib/nxt_schema/{node → template}/maybe_evaluator.rb +1 -1
- data/lib/nxt_schema/{node → template}/on_evaluator.rb +1 -1
- data/lib/nxt_schema/template/schema.rb +22 -0
- data/lib/nxt_schema/{node → template}/sub_nodes.rb +1 -1
- data/lib/nxt_schema/{node → template}/type_resolver.rb +2 -2
- data/lib/nxt_schema/{node → template}/type_system_resolver.rb +1 -1
- data/lib/nxt_schema/version.rb +1 -1
- metadata +17 -17
- data/lib/nxt_schema/application/any_of.rb +0 -40
- data/lib/nxt_schema/application/base.rb +0 -116
- data/lib/nxt_schema/application/collection.rb +0 -57
- data/lib/nxt_schema/application/leaf.rb +0 -15
- data/lib/nxt_schema/application/schema.rb +0 -114
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1aba2ccbd135921f48a84de3e51d11b0592522b8d9e9e9fd3a5ff188117ffae
|
4
|
+
data.tar.gz: 1c67ef1beda4a6e6a33bd67bc7a9294c7bfbc14ccf72be3b621748212192c8c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34cd6cdacddb969ac3532dc8f52150dc16e8be80b12bf8ceaec9cd147df93547cc02e655eaff1d05eee359b660e1143187adb704fbac91a3f09d4a18ebd28087
|
7
|
+
data.tar.gz: 5f77d02ed8b601aa255a4b9be082c48f1da0e7fa157561547e7c99a726c8a9d2f34a4c76be78cbd60ec529bce719e0b06e42d6645cbbe18e65facf7de9e7a1fc
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
nxt_schema (1.0.
|
4
|
+
nxt_schema (1.0.1)
|
5
5
|
activesupport
|
6
6
|
dry-types
|
7
7
|
nxt_init
|
@@ -50,7 +50,7 @@ GEM
|
|
50
50
|
minitest (5.14.2)
|
51
51
|
nxt_init (0.1.5)
|
52
52
|
activesupport
|
53
|
-
nxt_registry (0.3.
|
53
|
+
nxt_registry (0.3.3)
|
54
54
|
activesupport
|
55
55
|
pry (0.13.1)
|
56
56
|
coderay (~> 1.1)
|
@@ -72,7 +72,7 @@ GEM
|
|
72
72
|
thread_safe (0.3.6)
|
73
73
|
tzinfo (1.2.8)
|
74
74
|
thread_safe (~> 0.1)
|
75
|
-
zeitwerk (2.4.
|
75
|
+
zeitwerk (2.4.2)
|
76
76
|
|
77
77
|
PLATFORMS
|
78
78
|
ruby
|
data/README.md
CHANGED
@@ -16,10 +16,13 @@ Or install it yourself as:
|
|
16
16
|
|
17
17
|
$ gem install nxt_schema
|
18
18
|
|
19
|
-
## What it
|
19
|
+
## What is it for?
|
20
20
|
|
21
|
-
NxtSchema is a type
|
22
|
-
structures of data.
|
21
|
+
NxtSchema is a type coercion and validation framework that allows you to coerce and validate arbitrary nested
|
22
|
+
structures of data. The original idea is taken from https://dry-rb.org/gems/dry-schema and
|
23
|
+
https://dry-rb.org/gems/dry-validation from the amazing dry.rb eco system. In contrast to dry-schema,
|
24
|
+
NxtSchema aims to be a simpler solution that hopefully is easier to understand and debug.
|
25
|
+
It also ships with some handy features that dry-schema does not implement.
|
23
26
|
|
24
27
|
### Usage
|
25
28
|
|
@@ -31,7 +34,7 @@ PERSON = NxtSchema.schema(:person) do
|
|
31
34
|
end
|
32
35
|
|
33
36
|
input = {
|
34
|
-
first_name: '
|
37
|
+
first_name: 'Ändy',
|
35
38
|
last_name: 'Robecke',
|
36
39
|
email: 'andreas@robecke.de'
|
37
40
|
}
|
@@ -58,9 +61,9 @@ The kind of node dictates how the schema is applied to the input. On the root le
|
|
58
61
|
to create schemas:
|
59
62
|
|
60
63
|
```ruby
|
61
|
-
NxtSchema.schema { ... } # =>
|
62
|
-
NxtSchema.collection { ... } # =>
|
63
|
-
NxtSchema.any_of { ... } # =>
|
64
|
+
NxtSchema.schema { ... } # => Creates a schema node
|
65
|
+
NxtSchema.collection { ... } # => Creates an array of nodes
|
66
|
+
NxtSchema.any_of { ... } # => Creates a collection of allowed schemas
|
64
67
|
```
|
65
68
|
|
66
69
|
#### Node predicate aliases
|
@@ -85,6 +88,8 @@ into a schema you also have to combine the node predicates with default value me
|
|
85
88
|
check out the examples below:
|
86
89
|
|
87
90
|
```ruby
|
91
|
+
# Optional node without default value
|
92
|
+
|
88
93
|
schema = NxtSchema.schema(:person) do
|
89
94
|
optional(:email, :String)
|
90
95
|
end
|
@@ -99,19 +104,24 @@ result.output # => {}
|
|
99
104
|
```
|
100
105
|
|
101
106
|
```ruby
|
107
|
+
# Optional node with default value
|
108
|
+
|
102
109
|
schema = NxtSchema.schema(:person) do
|
103
110
|
optional(:email, :String).default('andreas@robecke.de')
|
104
111
|
end
|
105
112
|
|
106
113
|
result = schema.apply(input: { email: nil })
|
107
114
|
result.errors # => {}
|
115
|
+
result.output # => {:email=>"andreas@robecke.de"}
|
108
116
|
|
109
117
|
result = schema.apply(input: {})
|
110
118
|
result.errors # => {}
|
111
|
-
result.output # => {
|
119
|
+
result.output # => {}
|
112
120
|
```
|
113
121
|
|
114
122
|
```ruby
|
123
|
+
# Omnipresent node without default value
|
124
|
+
|
115
125
|
schema = NxtSchema.schema(:person) do
|
116
126
|
omnipresent(:email, :String)
|
117
127
|
end
|
@@ -122,8 +132,9 @@ result.output # => {:email=>NxtSchema::MissingInput}
|
|
122
132
|
```
|
123
133
|
|
124
134
|
```ruby
|
135
|
+
# Omnipresent node with default value and maybe expression to allow default value to break type contract.
|
136
|
+
|
125
137
|
schema = NxtSchema.schema(:person) do
|
126
|
-
# make sure a node is always present and at least nil even though the type is String
|
127
138
|
omnipresent(:email, :String).default(nil).maybe(:nil?)
|
128
139
|
end
|
129
140
|
|
@@ -131,15 +142,16 @@ result = schema.apply(input: {})
|
|
131
142
|
result.errors # => {}
|
132
143
|
result.output # => {:email=>nil}
|
133
144
|
|
134
|
-
result = schema.apply(input:
|
145
|
+
result = schema.apply(input: { email: 'andreas@robecke.de' })
|
135
146
|
result.errors # => {}
|
136
147
|
result.output # => {:email=>"andreas@robecke.de"}
|
137
148
|
```
|
138
149
|
|
139
150
|
##### Conditionally optional nodes
|
140
151
|
|
141
|
-
You can also pass a proc as the optional option. This
|
142
|
-
|
152
|
+
You can also pass a proc as the optional option. This is a shortcut for adding a validation to the parent node
|
153
|
+
that will result in a validation error in case the optional condition does not apply and the parent node does not
|
154
|
+
contain a sub node with that name (here contact schema not including an email node).
|
143
155
|
|
144
156
|
```ruby
|
145
157
|
schema = NxtSchema.schema(:contact) do
|
@@ -180,10 +192,6 @@ The type system is built with dry-types from the amazing https://dry-rb.org eco
|
|
180
192
|
offers features such as default values for types as well as maybe types, these features are built directly into
|
181
193
|
NxtSchema.
|
182
194
|
|
183
|
-
Please note that Dry.rb also has a gem for schemas: https://dry-rb.org/gems/dry-schema and another one dedicated to
|
184
|
-
validations explicitly https://dry-rb.org/gems/dry-validation. You should probably go and check those out! NxtSchema
|
185
|
-
is trying to implement a simpler solution that is easy to understand yet powerful enough for most tasks.
|
186
|
-
|
187
195
|
In NxtSchema every node has a type and you can either provide a symbol that will be resolved
|
188
196
|
through the type system of the schema or you can directly provide an instance of dry type and thus use your
|
189
197
|
custom types. This means you can basically build any kind of objects such as structs and models from your data and
|
@@ -197,11 +205,11 @@ type system that was specified NxtSchema will always fallback to nominal types.
|
|
197
205
|
a separate type system per node if that's what you need.
|
198
206
|
|
199
207
|
```ruby
|
200
|
-
NxtSchema.
|
208
|
+
NxtSchema.schema do
|
201
209
|
required(:test, :String) # The :String will resolve to NxtSchema::Types::Nominal::String
|
202
210
|
end
|
203
211
|
|
204
|
-
NxtSchema.
|
212
|
+
NxtSchema.schema(type_system: NxtSchema::Types::JSON) do
|
205
213
|
required(:test, :Date) # The :Date will resolve to NxtSchema::Types::JSON::Date
|
206
214
|
# When the type does not exist in the default type system (there is non JSON::String) we fallback to nominal types
|
207
215
|
required(:test, :String)
|
@@ -234,7 +242,7 @@ NxtSchema.register_type(
|
|
234
242
|
|
235
243
|
# once registered you can use the type in your schema
|
236
244
|
|
237
|
-
NxtSchema.
|
245
|
+
NxtSchema.schema(:company) do
|
238
246
|
required(:name, :MyCustomStrippedString)
|
239
247
|
end
|
240
248
|
```
|
@@ -244,21 +252,21 @@ end
|
|
244
252
|
#### Default values
|
245
253
|
|
246
254
|
```ruby
|
247
|
-
# Define default values
|
255
|
+
# Define default values with the default method
|
256
|
+
required(:test, :DateTime).default(nil)
|
248
257
|
required(:test, :DateTime).default(-> { Time.current })
|
249
|
-
required(:test, :String, default: 'Andy')
|
250
258
|
```
|
251
259
|
|
252
260
|
#### Maybe values
|
253
261
|
|
254
|
-
With maybe you can allow your values to
|
255
|
-
will simply be set to the input without coercing the value!**
|
262
|
+
With maybe expressions you can halt coercion and allow your values to break the type contract.
|
263
|
+
**Note: This means that your output will simply be set to the input without coercing the value!**
|
256
264
|
|
257
265
|
```ruby
|
258
266
|
# Define maybe values (values that do not match the type)
|
259
267
|
required(:test, :String).maybe(:nil?)
|
260
268
|
|
261
|
-
nodes(:tests).maybe(:empty?) do # will allow the collection to be empty
|
269
|
+
nodes(:tests).maybe(:empty?) do # will allow the collection to be empty and thus not contain strings
|
262
270
|
required(:test, :String)
|
263
271
|
end
|
264
272
|
|
@@ -272,6 +280,8 @@ based on some condition. When the node is yielded to your validation proc you ha
|
|
272
280
|
`node.input` and `node.index` when the node is within a collection of nodes as well as `node.name`. Furthermore you have
|
273
281
|
access to the context that was passed in when defining the schema or passed to the apply method later.
|
274
282
|
|
283
|
+
**NOTE: Validations only run when no maybe expression applies and the node input could be coerced successfully**
|
284
|
+
|
275
285
|
```ruby
|
276
286
|
# Simple custom validation
|
277
287
|
required(:test, :String).validate(-> (node) { node.add_error("#{node.input} is not valid") if node.input == 'not allowed' })
|
@@ -320,7 +330,7 @@ end
|
|
320
330
|
NxtSchema.register_validator(MyCustomExclusionValidator, :my_custom_exclusion_validator)
|
321
331
|
|
322
332
|
# and then simply reference it with the key you've registered it
|
323
|
-
schema = NxtSchema.
|
333
|
+
schema = NxtSchema.schema(:company) do
|
324
334
|
requires(:name, :String).validate(:my_custom_exclusion_validator, %w[lemonade])
|
325
335
|
end
|
326
336
|
|
@@ -333,25 +343,24 @@ schema.apply(name: 'lemonade').valid? # => false
|
|
333
343
|
- Add translated errors
|
334
344
|
- Interpolate with actual vs. expected
|
335
345
|
|
336
|
-
#### Combining validators
|
346
|
+
#### Combining validators
|
337
347
|
|
338
348
|
`node(:test, String).validate(...)` basically adds a validator to the node. Of course you can add multiple validators.
|
339
|
-
But that means that they will all be executed
|
349
|
+
But that means that they will all be executed. If you want your validator to only run in case
|
340
350
|
another was false, you can use `:validat_with do ... end` in order to combine validators based on custom logic.
|
341
351
|
|
342
352
|
```ruby
|
343
|
-
NxtSchema.
|
353
|
+
NxtSchema.schema do
|
344
354
|
required(:test, :Integer).validate_with do
|
345
355
|
validator(:greater_than, 5) &&
|
346
|
-
validator(:greater_than, 6)
|
356
|
+
validator(:greater_than, 6) ||
|
347
357
|
validator(:greater_than, 7)
|
348
358
|
end
|
349
359
|
end
|
350
360
|
```
|
351
361
|
|
352
|
-
|
353
|
-
|
354
|
-
means that you might not have the full validation errors when combining validations with `:validate_with`
|
362
|
+
Note that this will not run subsequent validators once one was valuated to false and thus might not contain all error
|
363
|
+
messages of all validators that would have failed.
|
355
364
|
|
356
365
|
|
357
366
|
### Schema options
|
@@ -363,17 +372,17 @@ You can change this behaviour by providing a strategy for the `:additional_keys`
|
|
363
372
|
|
364
373
|
```ruby
|
365
374
|
# This will simply ignore any other key except test
|
366
|
-
NxtSchema.
|
375
|
+
NxtSchema.schema(additional_keys: :ignore) do
|
367
376
|
required(:test, :String)
|
368
377
|
end
|
369
378
|
|
370
379
|
# This would give you an error in case you apply anything other than { test: '...' }
|
371
|
-
NxtSchema.
|
380
|
+
NxtSchema.schema(additional_keys: :restrict) do
|
372
381
|
required(:test, :String)
|
373
382
|
end
|
374
383
|
|
375
384
|
# This will merge other keys into your output
|
376
|
-
schema = NxtSchema.
|
385
|
+
schema = NxtSchema.schema(additional_keys: :allow) do
|
377
386
|
required(:test, :String)
|
378
387
|
end
|
379
388
|
|
@@ -388,7 +397,7 @@ You may want to transform the keys from your input. Therefore specify the transf
|
|
388
397
|
when you want your schema to return only symbolized keys for example.
|
389
398
|
|
390
399
|
```ruby
|
391
|
-
schema = NxtSchema.
|
400
|
+
schema = NxtSchema.schema(transform_keys: ->(key) { key.to_sym}) do
|
392
401
|
required(:test, :String)
|
393
402
|
end
|
394
403
|
|
@@ -402,7 +411,7 @@ You want to give nodes an ID or some other meta data? You can use the meta metho
|
|
402
411
|
information onto any node.
|
403
412
|
|
404
413
|
```ruby
|
405
|
-
schema = NxtSchema.
|
414
|
+
schema = NxtSchema.schema do
|
406
415
|
ERROR_MESSAGES = {
|
407
416
|
test: 'This is always broken'
|
408
417
|
}
|
@@ -416,12 +425,43 @@ schema.error # {"root.test"=>["This is always broken"]}
|
|
416
425
|
|
417
426
|
#### Contexts
|
418
427
|
|
419
|
-
|
428
|
+
When defining a schema it is possible to pass in a context option. This can be anything that you would like to access
|
429
|
+
during building your schema. A context could provide custom validators or default values depending of the name of your
|
430
|
+
nodes for instance.
|
420
431
|
|
421
432
|
##### Build time
|
422
433
|
|
434
|
+
```ruby
|
435
|
+
context = OpenStruct.new(email_validator: ->(node) { node.input && node.input.includes?('@') })
|
436
|
+
|
437
|
+
NxtSchema.schema(:developers, context: context) do
|
438
|
+
required(:first_name, :String)
|
439
|
+
required(:last_name, :String)
|
440
|
+
required(:email, :String).validate(context.email_validator)
|
441
|
+
end
|
442
|
+
```
|
443
|
+
|
423
444
|
##### Apply time
|
424
445
|
|
446
|
+
You can also pass in a context at apply time. If you do not pass in a specific
|
447
|
+
context at apply time you can still access the context passed in at build time.
|
448
|
+
Basically passing in a context at apply time will overwrite the context from before. You can access it simply through
|
449
|
+
the node.
|
450
|
+
|
451
|
+
```ruby
|
452
|
+
build_context = OpenStruct.new(email_validator: ->(node) { node.input.includes?('@') })
|
453
|
+
apply_context = OpenStruct.new(default_role: 'BOSS')
|
454
|
+
|
455
|
+
schema = NxtSchema.schema(:developers, context: build_context) do
|
456
|
+
# context at build time
|
457
|
+
required(:email, :String).validate(context.email_validator) #
|
458
|
+
# access the context at apply time through the node
|
459
|
+
required(:role, :String).default { |_, node| node.context.default_role }
|
460
|
+
end
|
461
|
+
|
462
|
+
schema.apply(input: input, context: apply_context)
|
463
|
+
```
|
464
|
+
|
425
465
|
## Development
|
426
466
|
|
427
467
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -438,6 +478,8 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
438
478
|
|
439
479
|
## TODO:
|
440
480
|
|
481
|
+
- Explain node interface
|
482
|
+
- Add apply! method to readme
|
441
483
|
- Allow to disable validation when applying
|
442
484
|
--> Are there attributes that should be moved to apply time?
|
443
485
|
- Should we have a global and a local registry for validators?
|
data/lib/nxt_schema.rb
CHANGED
@@ -7,7 +7,7 @@ require 'yaml'
|
|
7
7
|
|
8
8
|
require_relative 'nxt_schema/types'
|
9
9
|
require_relative 'nxt_schema/callable'
|
10
|
-
require_relative 'nxt_schema/
|
10
|
+
require_relative 'nxt_schema/node'
|
11
11
|
require_relative 'nxt_schema/missing_input'
|
12
12
|
require_relative 'nxt_schema/error'
|
13
13
|
require_relative 'nxt_schema/errors/invalid'
|
@@ -31,26 +31,26 @@ require_relative 'nxt_schema/validators/excluded_in'
|
|
31
31
|
require_relative 'nxt_schema/validators/excludes'
|
32
32
|
require_relative 'nxt_schema/validators/query'
|
33
33
|
|
34
|
-
require_relative 'nxt_schema/
|
35
|
-
require_relative 'nxt_schema/
|
36
|
-
require_relative 'nxt_schema/
|
37
|
-
require_relative 'nxt_schema/
|
34
|
+
require_relative 'nxt_schema/template/on_evaluator'
|
35
|
+
require_relative 'nxt_schema/template/maybe_evaluator'
|
36
|
+
require_relative 'nxt_schema/template/type_resolver'
|
37
|
+
require_relative 'nxt_schema/template/type_system_resolver'
|
38
|
+
require_relative 'nxt_schema/template/base'
|
39
|
+
require_relative 'nxt_schema/template/sub_nodes'
|
40
|
+
require_relative 'nxt_schema/template/has_sub_nodes'
|
41
|
+
require_relative 'nxt_schema/template/any_of'
|
42
|
+
require_relative 'nxt_schema/template/collection'
|
43
|
+
require_relative 'nxt_schema/template/schema'
|
44
|
+
require_relative 'nxt_schema/template/leaf'
|
45
|
+
|
46
|
+
require_relative 'nxt_schema/node/errors/schema_error'
|
47
|
+
require_relative 'nxt_schema/node/errors/validation_error'
|
48
|
+
require_relative 'nxt_schema/node/error_store'
|
38
49
|
require_relative 'nxt_schema/node/base'
|
39
|
-
require_relative 'nxt_schema/node/sub_nodes'
|
40
|
-
require_relative 'nxt_schema/node/has_sub_nodes'
|
41
50
|
require_relative 'nxt_schema/node/any_of'
|
51
|
+
require_relative 'nxt_schema/node/leaf'
|
42
52
|
require_relative 'nxt_schema/node/collection'
|
43
53
|
require_relative 'nxt_schema/node/schema'
|
44
|
-
require_relative 'nxt_schema/node/leaf'
|
45
|
-
|
46
|
-
require_relative 'nxt_schema/application/errors/schema_error'
|
47
|
-
require_relative 'nxt_schema/application/errors/validation_error'
|
48
|
-
require_relative 'nxt_schema/application/error_store'
|
49
|
-
require_relative 'nxt_schema/application/base'
|
50
|
-
require_relative 'nxt_schema/application/any_of'
|
51
|
-
require_relative 'nxt_schema/application/leaf'
|
52
|
-
require_relative 'nxt_schema/application/collection'
|
53
|
-
require_relative 'nxt_schema/application/schema'
|
54
54
|
require_relative 'nxt_schema/dsl'
|
55
55
|
|
56
56
|
module NxtSchema
|
data/lib/nxt_schema/dsl.rb
CHANGED
@@ -2,8 +2,8 @@ module NxtSchema
|
|
2
2
|
module Dsl
|
3
3
|
DEFAULT_OPTIONS = { type_system: NxtSchema::Types }.freeze
|
4
4
|
|
5
|
-
def collection(name = :root, type: NxtSchema::
|
6
|
-
NxtSchema::
|
5
|
+
def collection(name = :root, type: NxtSchema::Template::Collection::DEFAULT_TYPE, **options, &block)
|
6
|
+
NxtSchema::Template::Collection.new(
|
7
7
|
name: name,
|
8
8
|
type: type,
|
9
9
|
parent_node: nil,
|
@@ -14,8 +14,8 @@ module NxtSchema
|
|
14
14
|
|
15
15
|
alias nodes collection
|
16
16
|
|
17
|
-
def schema(name = :roots, type: NxtSchema::
|
18
|
-
NxtSchema::
|
17
|
+
def schema(name = :roots, type: NxtSchema::Template::Schema::DEFAULT_TYPE, **options, &block)
|
18
|
+
NxtSchema::Template::Schema.new(
|
19
19
|
name: name,
|
20
20
|
type: type,
|
21
21
|
parent_node: nil,
|
@@ -25,7 +25,7 @@ module NxtSchema
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def any_of(name = :roots, **options, &block)
|
28
|
-
NxtSchema::
|
28
|
+
NxtSchema::Template::AnyOf.new(
|
29
29
|
name: name,
|
30
30
|
parent_node: nil,
|
31
31
|
**DEFAULT_OPTIONS.merge(options),
|
@@ -35,8 +35,8 @@ module NxtSchema
|
|
35
35
|
|
36
36
|
# schema root with NxtSchema::Types::Params type system
|
37
37
|
|
38
|
-
def params(name = :params, type: NxtSchema::
|
39
|
-
NxtSchema::
|
38
|
+
def params(name = :params, type: NxtSchema::Template::Schema::DEFAULT_TYPE, **options, &block)
|
39
|
+
NxtSchema::Template::Schema.new(
|
40
40
|
name: name,
|
41
41
|
type: type,
|
42
42
|
parent_node: nil,
|
@@ -1,50 +1,38 @@
|
|
1
1
|
module NxtSchema
|
2
2
|
module Node
|
3
|
-
class AnyOf < Base
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(name:, type: nil, parent_node:, **options, &block)
|
7
|
-
super
|
8
|
-
end
|
9
|
-
|
10
|
-
def collection(name = sub_nodes.count, type = NxtSchema::Node::Collection::DEFAULT_TYPE, **options, &block)
|
11
|
-
super
|
3
|
+
class AnyOf < Node::Base
|
4
|
+
def valid?
|
5
|
+
valid_application.present?
|
12
6
|
end
|
13
7
|
|
14
|
-
def
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
def node(name = sub_nodes.count, node_or_type_of_node = nil, **options, &block)
|
19
|
-
super
|
20
|
-
end
|
8
|
+
def call
|
9
|
+
child_applications.map(&:call)
|
21
10
|
|
22
|
-
|
11
|
+
if valid?
|
12
|
+
self.output = valid_application.output
|
13
|
+
else
|
14
|
+
child_applications.each do |application|
|
15
|
+
merge_errors(application)
|
16
|
+
end
|
17
|
+
end
|
23
18
|
|
24
|
-
|
25
|
-
raise NotImplementedError
|
26
|
-
end
|
27
|
-
|
28
|
-
def maybe(*args)
|
29
|
-
raise NotImplementedError
|
19
|
+
self
|
30
20
|
end
|
31
21
|
|
32
22
|
private
|
33
23
|
|
34
|
-
|
35
|
-
nil
|
36
|
-
end
|
24
|
+
delegate :[], to: :child_applications
|
37
25
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
raise InvalidOptions, "The optional option is not available for nodes of type #{self.class.name}"
|
26
|
+
def valid_application
|
27
|
+
child_applications.find(&:valid?)
|
42
28
|
end
|
43
29
|
|
44
|
-
def
|
45
|
-
|
30
|
+
def child_applications
|
31
|
+
@child_applications ||= nodes.map { |node| node.build_application(input: input, context: context, parent: self) }
|
32
|
+
end
|
46
33
|
|
47
|
-
|
34
|
+
def nodes
|
35
|
+
@nodes ||= node.sub_nodes.values
|
48
36
|
end
|
49
37
|
end
|
50
38
|
end
|