plumb 0.0.3 → 0.0.5
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/README.md +609 -57
- data/bench/compare_parametric_schema.rb +102 -0
- data/bench/compare_parametric_struct.rb +68 -0
- data/bench/parametric_schema.rb +229 -0
- data/bench/plumb_hash.rb +109 -0
- data/examples/concurrent_downloads.rb +3 -3
- data/examples/env_config.rb +2 -2
- data/examples/event_registry.rb +127 -0
- data/examples/weekdays.rb +1 -1
- data/lib/plumb/and.rb +4 -3
- data/lib/plumb/any_class.rb +4 -4
- data/lib/plumb/array_class.rb +8 -5
- data/lib/plumb/attributes.rb +268 -0
- data/lib/plumb/build.rb +4 -3
- data/lib/plumb/composable.rb +381 -0
- data/lib/plumb/decorator.rb +57 -0
- data/lib/plumb/deferred.rb +1 -1
- data/lib/plumb/hash_class.rb +19 -8
- data/lib/plumb/hash_map.rb +8 -6
- data/lib/plumb/interface_class.rb +6 -2
- data/lib/plumb/json_schema_visitor.rb +59 -32
- data/lib/plumb/match_class.rb +5 -4
- data/lib/plumb/metadata.rb +5 -1
- data/lib/plumb/metadata_visitor.rb +13 -42
- data/lib/plumb/not.rb +4 -3
- data/lib/plumb/or.rb +10 -4
- data/lib/plumb/pipeline.rb +27 -7
- data/lib/plumb/policy.rb +10 -3
- data/lib/plumb/schema.rb +11 -10
- data/lib/plumb/static_class.rb +4 -3
- data/lib/plumb/step.rb +4 -3
- data/lib/plumb/stream_class.rb +8 -7
- data/lib/plumb/tagged_hash.rb +11 -11
- data/lib/plumb/transform.rb +4 -3
- data/lib/plumb/tuple_class.rb +8 -8
- data/lib/plumb/type_registry.rb +5 -2
- data/lib/plumb/types.rb +30 -1
- data/lib/plumb/value_class.rb +4 -3
- data/lib/plumb/version.rb +1 -1
- data/lib/plumb/visitor_handlers.rb +6 -0
- data/lib/plumb.rb +11 -5
- metadata +10 -3
- data/lib/plumb/steppable.rb +0 -229
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'date'
|
3
4
|
require 'plumb/visitor_handlers'
|
4
5
|
|
5
6
|
module Plumb
|
@@ -23,11 +24,16 @@ module Plumb
|
|
23
24
|
MAX_ITEMS = 'maxItems'
|
24
25
|
MIN_LENGTH = 'minLength'
|
25
26
|
MAX_LENGTH = 'maxLength'
|
27
|
+
FORMAT = 'format'
|
28
|
+
ENVELOPE = {
|
29
|
+
'$schema' => 'https://json-schema.org/draft-08/schema#'
|
30
|
+
}.freeze
|
26
31
|
|
27
|
-
def self.call(node)
|
28
|
-
|
29
|
-
|
30
|
-
|
32
|
+
def self.call(node, root: true)
|
33
|
+
data = new.visit(node)
|
34
|
+
return data unless root
|
35
|
+
|
36
|
+
ENVELOPE.merge(data)
|
31
37
|
end
|
32
38
|
|
33
39
|
private def stringify_keys(hash) = hash.transform_keys(&:to_s)
|
@@ -37,7 +43,7 @@ module Plumb
|
|
37
43
|
end
|
38
44
|
|
39
45
|
on(:pipeline) do |node, props|
|
40
|
-
|
46
|
+
visit_children(node, props)
|
41
47
|
end
|
42
48
|
|
43
49
|
on(:step) do |node, props|
|
@@ -58,9 +64,12 @@ module Plumb
|
|
58
64
|
)
|
59
65
|
end
|
60
66
|
|
67
|
+
on(:data) do |node, props|
|
68
|
+
visit_name :hash, node._schema, props
|
69
|
+
end
|
70
|
+
|
61
71
|
on(:and) do |node, props|
|
62
|
-
left = visit(
|
63
|
-
right = visit(node.right)
|
72
|
+
left, right = node.children.map { |c| visit(c) }
|
64
73
|
type = right[TYPE] || left[TYPE]
|
65
74
|
props = props.merge(left).merge(right)
|
66
75
|
props = props.merge(TYPE => type) if type
|
@@ -69,11 +78,10 @@ module Plumb
|
|
69
78
|
|
70
79
|
# A "default" value is usually an "or" of expected_value | (undefined >> static_value)
|
71
80
|
on(:or) do |node, props|
|
72
|
-
left = visit(
|
73
|
-
|
74
|
-
any_of = [left, right].uniq
|
81
|
+
left, right = node.children.map { |c| visit(c) }
|
82
|
+
any_of = [left, right].uniq.filter(&:any?)
|
75
83
|
if any_of.size == 1
|
76
|
-
props.merge(
|
84
|
+
props.merge(any_of.first)
|
77
85
|
elsif any_of.size == 2 && (defidx = any_of.index { |p| p.key?(DEFAULT) })
|
78
86
|
val = any_of[defidx.zero? ? 1 : 0]
|
79
87
|
props.merge(val).merge(DEFAULT => any_of[defidx][DEFAULT])
|
@@ -83,22 +91,23 @@ module Plumb
|
|
83
91
|
end
|
84
92
|
|
85
93
|
on(:not) do |node, props|
|
86
|
-
props.merge(NOT =>
|
94
|
+
props.merge(NOT => visit_children(node))
|
87
95
|
end
|
88
96
|
|
89
97
|
on(:value) do |node, props|
|
90
|
-
|
98
|
+
value = node.children.first
|
99
|
+
props = case value
|
91
100
|
when ::String, ::Symbol, ::Numeric
|
92
|
-
props.merge(CONST =>
|
101
|
+
props.merge(CONST => value)
|
93
102
|
else
|
94
103
|
props
|
95
104
|
end
|
96
105
|
|
97
|
-
visit(
|
106
|
+
visit(value, props)
|
98
107
|
end
|
99
108
|
|
100
109
|
on(:transform) do |node, props|
|
101
|
-
|
110
|
+
visit_children(node, props)
|
102
111
|
end
|
103
112
|
|
104
113
|
on(:undefined) do |_node, props|
|
@@ -108,18 +117,19 @@ module Plumb
|
|
108
117
|
on(:static) do |node, props|
|
109
118
|
# Set const AND default
|
110
119
|
# to emulate static values
|
111
|
-
|
120
|
+
value = node.children.first
|
121
|
+
props = case value
|
112
122
|
when ::String, ::Symbol, ::Numeric
|
113
|
-
props.merge(CONST =>
|
123
|
+
props.merge(CONST => value, DEFAULT => value)
|
114
124
|
else
|
115
125
|
props
|
116
126
|
end
|
117
127
|
|
118
|
-
visit(
|
128
|
+
visit(value, props)
|
119
129
|
end
|
120
130
|
|
121
131
|
on(:policy) do |node, props|
|
122
|
-
props =
|
132
|
+
props = visit_children(node, props)
|
123
133
|
method_name = :"visit_#{node.policy_name}_policy"
|
124
134
|
if respond_to?(method_name)
|
125
135
|
send(method_name, node, props)
|
@@ -168,20 +178,29 @@ module Plumb
|
|
168
178
|
|
169
179
|
on(:match) do |node, props|
|
170
180
|
# Set const if primitive
|
171
|
-
|
181
|
+
matcher = node.children.first
|
182
|
+
props = case matcher
|
172
183
|
when ::String, ::Symbol, ::Numeric
|
173
|
-
props.merge(CONST =>
|
184
|
+
props.merge(CONST => matcher)
|
174
185
|
else
|
175
186
|
props
|
176
187
|
end
|
177
188
|
|
178
|
-
visit(
|
189
|
+
visit(matcher, props)
|
179
190
|
end
|
180
191
|
|
181
192
|
on(:boolean) do |_node, props|
|
182
193
|
props.merge(TYPE => 'boolean')
|
183
194
|
end
|
184
195
|
|
196
|
+
on(:uuid) do |_node, props|
|
197
|
+
props.merge(TYPE => 'string', FORMAT => 'uuid')
|
198
|
+
end
|
199
|
+
|
200
|
+
on(:email) do |_node, props|
|
201
|
+
props.merge(TYPE => 'string', FORMAT => 'email')
|
202
|
+
end
|
203
|
+
|
185
204
|
on(::String) do |_node, props|
|
186
205
|
props.merge(TYPE => 'string')
|
187
206
|
end
|
@@ -228,6 +247,14 @@ module Plumb
|
|
228
247
|
props.merge(opts)
|
229
248
|
end
|
230
249
|
|
250
|
+
on(::Time) do |_node, props|
|
251
|
+
props.merge(TYPE => 'string', FORMAT => 'date-time')
|
252
|
+
end
|
253
|
+
|
254
|
+
on(::Date) do |_node, props|
|
255
|
+
props.merge(TYPE => 'string', FORMAT => 'date')
|
256
|
+
end
|
257
|
+
|
231
258
|
on(::Hash) do |_node, props|
|
232
259
|
props.merge(TYPE => 'object')
|
233
260
|
end
|
@@ -245,7 +272,7 @@ module Plumb
|
|
245
272
|
{
|
246
273
|
TYPE => 'object',
|
247
274
|
'patternProperties' => {
|
248
|
-
'.*' => visit(node.
|
275
|
+
'.*' => visit(node.children[1])
|
249
276
|
}
|
250
277
|
}
|
251
278
|
end
|
@@ -254,27 +281,27 @@ module Plumb
|
|
254
281
|
{
|
255
282
|
TYPE => 'object',
|
256
283
|
'patternProperties' => {
|
257
|
-
'.*' => visit(node.
|
284
|
+
'.*' => visit(node.children[1])
|
258
285
|
}
|
259
286
|
}
|
260
287
|
end
|
261
288
|
|
262
289
|
on(:build) do |node, props|
|
263
|
-
|
290
|
+
visit_children(node, props)
|
264
291
|
end
|
265
292
|
|
266
293
|
on(:array) do |node, _props|
|
267
|
-
|
268
|
-
{ TYPE => 'array', ITEMS =>
|
294
|
+
items_props = visit_children(node)
|
295
|
+
{ TYPE => 'array', ITEMS => items_props }
|
269
296
|
end
|
270
297
|
|
271
298
|
on(:stream) do |node, _props|
|
272
|
-
|
273
|
-
{ TYPE => 'array', ITEMS =>
|
299
|
+
items_props = visit_children(node)
|
300
|
+
{ TYPE => 'array', ITEMS => items_props }
|
274
301
|
end
|
275
302
|
|
276
303
|
on(:tuple) do |node, _props|
|
277
|
-
items = node.
|
304
|
+
items = node.children.map { |t| visit(t) }
|
278
305
|
{ TYPE => 'array', 'prefixItems' => items }
|
279
306
|
end
|
280
307
|
|
@@ -286,7 +313,7 @@ module Plumb
|
|
286
313
|
}
|
287
314
|
|
288
315
|
key = node.key.to_s
|
289
|
-
children = node.
|
316
|
+
children = node.children.map { |c| visit(c) }
|
290
317
|
key_enum = children.map { |c| c[PROPERTIES][key][CONST] }
|
291
318
|
key_type = children.map { |c| c[PROPERTIES][key][TYPE] }
|
292
319
|
required << key
|
data/lib/plumb/match_class.rb
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'plumb/
|
3
|
+
require 'plumb/composable'
|
4
4
|
|
5
5
|
module Plumb
|
6
6
|
class MatchClass
|
7
|
-
include
|
7
|
+
include Composable
|
8
8
|
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :children
|
10
10
|
|
11
11
|
def initialize(matcher = Undefined, error: nil, label: nil)
|
12
|
-
raise
|
12
|
+
raise ParseError 'matcher must respond to #===' unless matcher.respond_to?(:===)
|
13
13
|
|
14
14
|
@matcher = matcher
|
15
15
|
@error = error.nil? ? build_error(matcher) : (error % matcher)
|
16
16
|
@label = matcher.is_a?(Class) ? matcher.inspect : "Match(#{label || @matcher.inspect})"
|
17
|
+
@children = [matcher].freeze
|
17
18
|
freeze
|
18
19
|
end
|
19
20
|
|
data/lib/plumb/metadata.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Plumb
|
4
4
|
class Metadata
|
5
|
-
include
|
5
|
+
include Composable
|
6
6
|
|
7
7
|
attr_reader :metadata
|
8
8
|
|
@@ -11,6 +11,10 @@ module Plumb
|
|
11
11
|
freeze
|
12
12
|
end
|
13
13
|
|
14
|
+
def ==(other)
|
15
|
+
other.is_a?(self.class) && @metadata == other.metadata
|
16
|
+
end
|
17
|
+
|
14
18
|
def call(result) = result
|
15
19
|
|
16
20
|
private def _inspect = "Metadata[#{@metadata.inspect}]"
|
@@ -10,23 +10,14 @@ module Plumb
|
|
10
10
|
new.visit(node)
|
11
11
|
end
|
12
12
|
|
13
|
-
def on_missing_handler(node, props,
|
13
|
+
def on_missing_handler(node, props, _method_name)
|
14
14
|
return props.merge(type: node) if node.instance_of?(Class)
|
15
15
|
|
16
|
-
|
17
|
-
props
|
18
|
-
end
|
19
|
-
|
20
|
-
on(:undefined) do |_node, props|
|
21
|
-
props
|
22
|
-
end
|
16
|
+
return props unless node.respond_to?(:children)
|
23
17
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
on(:pipeline) do |node, props|
|
29
|
-
visit(node.type, props)
|
18
|
+
node.children.reduce(props) do |acc, child|
|
19
|
+
visit(child, acc)
|
20
|
+
end
|
30
21
|
end
|
31
22
|
|
32
23
|
on(:step) do |node, props|
|
@@ -42,17 +33,12 @@ module Plumb
|
|
42
33
|
props.merge(match: node, type:)
|
43
34
|
end
|
44
35
|
|
45
|
-
on(:match) do |node, props|
|
46
|
-
visit(node.matcher, props)
|
47
|
-
end
|
48
|
-
|
49
36
|
on(:hash) do |_node, props|
|
50
37
|
props.merge(type: Hash)
|
51
38
|
end
|
52
39
|
|
53
40
|
on(:and) do |node, props|
|
54
|
-
left = visit(
|
55
|
-
right = visit(node.right)
|
41
|
+
left, right = node.children.map { |child| visit(child) }
|
56
42
|
type = right[:type] || left[:type]
|
57
43
|
props = props.merge(left).merge(right)
|
58
44
|
props = props.merge(type:) if type
|
@@ -60,7 +46,7 @@ module Plumb
|
|
60
46
|
end
|
61
47
|
|
62
48
|
on(:or) do |node, props|
|
63
|
-
child_metas =
|
49
|
+
child_metas = node.children.map { |child| visit(child) }
|
64
50
|
types = child_metas.map { |child| child[:type] }.flatten.compact
|
65
51
|
types = types.first if types.size == 1
|
66
52
|
child_metas.reduce(props) do |acc, child|
|
@@ -68,27 +54,16 @@ module Plumb
|
|
68
54
|
end.merge(type: types)
|
69
55
|
end
|
70
56
|
|
71
|
-
on(:value) do |node, props|
|
72
|
-
visit(node.value, props)
|
73
|
-
end
|
74
|
-
|
75
|
-
on(:transform) do |node, props|
|
76
|
-
props.merge(type: node.target_type)
|
77
|
-
end
|
78
|
-
|
79
57
|
on(:static) do |node, props|
|
80
|
-
|
81
|
-
|
58
|
+
value = node.children[0]
|
59
|
+
type = value.is_a?(Class) ? value : value.class
|
60
|
+
props.merge(static: value, type:)
|
82
61
|
end
|
83
62
|
|
84
63
|
on(:policy) do |node, props|
|
85
|
-
visit(node.
|
86
|
-
|
87
|
-
|
88
|
-
on(:rules) do |node, props|
|
89
|
-
node.rules.reduce(props) do |acc, rule|
|
90
|
-
acc.merge(rule.name => rule.arg_value)
|
91
|
-
end
|
64
|
+
props = visit(node.children[0], props)
|
65
|
+
props = props.merge(node.policy_name => node.arg) unless node.arg == Plumb::Undefined
|
66
|
+
props
|
92
67
|
end
|
93
68
|
|
94
69
|
on(:boolean) do |_node, props|
|
@@ -103,10 +78,6 @@ module Plumb
|
|
103
78
|
props.merge(type: Hash)
|
104
79
|
end
|
105
80
|
|
106
|
-
on(:build) do |node, props|
|
107
|
-
visit(node.type, props)
|
108
|
-
end
|
109
|
-
|
110
81
|
on(:array) do |_node, props|
|
111
82
|
props.merge(type: Array)
|
112
83
|
end
|
data/lib/plumb/not.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'plumb/
|
3
|
+
require 'plumb/composable'
|
4
4
|
|
5
5
|
module Plumb
|
6
6
|
class Not
|
7
|
-
include
|
7
|
+
include Composable
|
8
8
|
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :children, :errors
|
10
10
|
|
11
11
|
def initialize(step, errors: nil)
|
12
12
|
@step = step
|
13
13
|
@errors = errors
|
14
|
+
@children = [step].freeze
|
14
15
|
freeze
|
15
16
|
end
|
16
17
|
|
data/lib/plumb/or.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'plumb/
|
3
|
+
require 'plumb/composable'
|
4
4
|
|
5
5
|
module Plumb
|
6
6
|
class Or
|
7
|
-
include
|
7
|
+
include Composable
|
8
8
|
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :children
|
10
10
|
|
11
11
|
def initialize(left, right)
|
12
12
|
@left = left
|
13
13
|
@right = right
|
14
|
+
@children = [left, right].freeze
|
14
15
|
freeze
|
15
16
|
end
|
16
17
|
|
@@ -23,7 +24,12 @@ module Plumb
|
|
23
24
|
return left_result if left_result.valid?
|
24
25
|
|
25
26
|
right_result = @right.call(result)
|
26
|
-
right_result.valid?
|
27
|
+
if right_result.valid?
|
28
|
+
right_result
|
29
|
+
else
|
30
|
+
right_result.invalid(errors: [left_result.errors,
|
31
|
+
right_result.errors].flatten)
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
data/lib/plumb/pipeline.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'plumb/
|
3
|
+
require 'plumb/composable'
|
4
4
|
|
5
5
|
module Plumb
|
6
6
|
class Pipeline
|
7
|
-
include
|
7
|
+
include Composable
|
8
8
|
|
9
9
|
class AroundStep
|
10
|
-
include
|
10
|
+
include Composable
|
11
11
|
|
12
12
|
def initialize(step, block)
|
13
13
|
@step = step
|
@@ -19,11 +19,28 @@ module Plumb
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
class << self
|
23
|
+
def around_blocks
|
24
|
+
@around_blocks ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
def around(callable = nil, &block)
|
28
|
+
around_blocks << (callable || block)
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def inherited(subclass)
|
33
|
+
around_blocks.each { |block| subclass.around(block) }
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_reader :children
|
23
39
|
|
24
40
|
def initialize(type = Types::Any, &setup)
|
25
41
|
@type = type
|
26
|
-
@
|
42
|
+
@children = [type].freeze
|
43
|
+
@around_blocks = self.class.around_blocks.dup
|
27
44
|
return unless block_given?
|
28
45
|
|
29
46
|
configure(&setup)
|
@@ -38,10 +55,11 @@ module Plumb
|
|
38
55
|
callable ||= block
|
39
56
|
unless is_a_step?(callable)
|
40
57
|
raise ArgumentError,
|
41
|
-
|
58
|
+
"#step expects an interface #call(Result) Result, but got #{callable.inspect}"
|
42
59
|
end
|
43
60
|
|
44
|
-
callable =
|
61
|
+
callable = prepare_step(callable)
|
62
|
+
callable = @around_blocks.reverse.reduce(callable) { |cl, bl| AroundStep.new(cl, bl) } if @around_blocks.any?
|
45
63
|
@type >>= callable
|
46
64
|
self
|
47
65
|
end
|
@@ -69,5 +87,7 @@ module Plumb
|
|
69
87
|
|
70
88
|
true
|
71
89
|
end
|
90
|
+
|
91
|
+
def prepare_step(callable) = callable
|
72
92
|
end
|
73
93
|
end
|
data/lib/plumb/policy.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'plumb/
|
3
|
+
require 'plumb/composable'
|
4
4
|
|
5
5
|
module Plumb
|
6
6
|
# Wrap a policy composition ("step") in a Policy object.
|
7
7
|
# So that visitors such as JSONSchema and Metadata visitors
|
8
8
|
# can define dedicated handlers for policies, if they need to.
|
9
9
|
class Policy
|
10
|
-
include
|
10
|
+
include Composable
|
11
11
|
|
12
|
-
attr_reader :policy_name, :arg, :
|
12
|
+
attr_reader :policy_name, :arg, :children
|
13
13
|
|
14
14
|
# @param policy_name [Symbol]
|
15
15
|
# @param arg [Object, nil] the argument to the policy, if any.
|
@@ -18,9 +18,16 @@ module Plumb
|
|
18
18
|
@policy_name = policy_name
|
19
19
|
@arg = arg
|
20
20
|
@step = step
|
21
|
+
@children = [step].freeze
|
21
22
|
freeze
|
22
23
|
end
|
23
24
|
|
25
|
+
def ==(other)
|
26
|
+
other.is_a?(self.class) &&
|
27
|
+
policy_name == other.policy_name &&
|
28
|
+
arg == other.arg
|
29
|
+
end
|
30
|
+
|
24
31
|
# The standard Step interface.
|
25
32
|
# @param result [Result::Valid]
|
26
33
|
# @return [Result::Valid, Result::Invalid]
|
data/lib/plumb/schema.rb
CHANGED
@@ -5,13 +5,13 @@ require 'plumb/json_schema_visitor'
|
|
5
5
|
|
6
6
|
module Plumb
|
7
7
|
class Schema
|
8
|
-
include
|
8
|
+
include Composable
|
9
9
|
|
10
10
|
def self.wrap(sch = nil, &block)
|
11
11
|
raise ArgumentError, 'expected a block or a schema' if sch.nil? && !block_given?
|
12
12
|
|
13
13
|
if sch
|
14
|
-
raise ArgumentError, 'expected a
|
14
|
+
raise ArgumentError, 'expected a Composable' unless sch.is_a?(Composable)
|
15
15
|
|
16
16
|
return sch
|
17
17
|
end
|
@@ -49,8 +49,8 @@ module Plumb
|
|
49
49
|
self
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
53
|
-
|
52
|
+
def to_json_schema
|
53
|
+
_hash.to_json_schema(root: true)
|
54
54
|
end
|
55
55
|
|
56
56
|
def call(result)
|
@@ -120,7 +120,7 @@ module Plumb
|
|
120
120
|
block_given? ? ArrayClass.new(element_type: Schema.new(&block)) : type
|
121
121
|
when nil
|
122
122
|
block_given? ? Schema.new(&block) : Types::Any
|
123
|
-
when
|
123
|
+
when Composable
|
124
124
|
type
|
125
125
|
when Class
|
126
126
|
if type == Array && block_given?
|
@@ -140,13 +140,14 @@ module Plumb
|
|
140
140
|
self
|
141
141
|
end
|
142
142
|
|
143
|
-
def
|
144
|
-
|
145
|
-
|
143
|
+
def metadata(data = Undefined)
|
144
|
+
if data == Undefined
|
145
|
+
@_type.metadata
|
146
|
+
else
|
147
|
+
@_type = @_type.metadata(data)
|
148
|
+
end
|
146
149
|
end
|
147
150
|
|
148
|
-
def metadata = @_type.metadata
|
149
|
-
|
150
151
|
def options(opts)
|
151
152
|
@_type = @_type.options(opts)
|
152
153
|
self
|
data/lib/plumb/static_class.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'plumb/
|
3
|
+
require 'plumb/composable'
|
4
4
|
|
5
5
|
module Plumb
|
6
6
|
class StaticClass
|
7
|
-
include
|
7
|
+
include Composable
|
8
8
|
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :children
|
10
10
|
|
11
11
|
def initialize(value = Undefined)
|
12
12
|
raise ArgumentError, 'value must be frozen' unless value.frozen?
|
13
13
|
|
14
14
|
@value = value
|
15
|
+
@children = [value].freeze
|
15
16
|
freeze
|
16
17
|
end
|
17
18
|
|
data/lib/plumb/step.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'plumb/
|
3
|
+
require 'plumb/composable'
|
4
4
|
|
5
5
|
module Plumb
|
6
6
|
class Step
|
7
|
-
include
|
7
|
+
include Composable
|
8
8
|
|
9
|
-
attr_reader :_metadata
|
9
|
+
attr_reader :_metadata, :children
|
10
10
|
|
11
11
|
def initialize(callable = nil, inspect = nil, &block)
|
12
12
|
@_metadata = callable.respond_to?(:metadata) ? callable.metadata : BLANK_HASH
|
13
13
|
@callable = callable || block
|
14
|
+
@children = [@callable].freeze
|
14
15
|
@inspect = inspect || @callable.inspect
|
15
16
|
freeze
|
16
17
|
end
|
data/lib/plumb/stream_class.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'thread'
|
4
|
-
require 'plumb/
|
4
|
+
require 'plumb/composable'
|
5
5
|
|
6
6
|
module Plumb
|
7
7
|
# A stream that validates each element.
|
@@ -15,18 +15,19 @@ module Plumb
|
|
15
15
|
# result.value # => ['name', 10]
|
16
16
|
# end
|
17
17
|
class StreamClass
|
18
|
-
include
|
18
|
+
include Composable
|
19
19
|
|
20
|
-
attr_reader :
|
20
|
+
attr_reader :children
|
21
21
|
|
22
|
-
# @option element_type [
|
22
|
+
# @option element_type [Composable] the type of the elements in the stream
|
23
23
|
def initialize(element_type: Types::Any)
|
24
|
-
@element_type =
|
24
|
+
@element_type = Composable.wrap(element_type)
|
25
|
+
@children = [@element_type].freeze
|
25
26
|
freeze
|
26
27
|
end
|
27
28
|
|
28
29
|
# return a new Stream definition.
|
29
|
-
# @param element_type [
|
30
|
+
# @param element_type [Composable] the type of the elements in the stream
|
30
31
|
def [](element_type)
|
31
32
|
self.class.new(element_type:)
|
32
33
|
end
|
@@ -39,7 +40,7 @@ module Plumb
|
|
39
40
|
|
40
41
|
enum = Enumerator.new do |y|
|
41
42
|
result.value.each do |e|
|
42
|
-
y << element_type.resolve(e)
|
43
|
+
y << @element_type.resolve(e)
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|