plumb 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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 Steppable
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 Steppable' unless sch.is_a?(Steppable)
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 json_schema
53
- JSONSchemaVisitor.call(_hash).to_h
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 Steppable
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 meta(md = nil)
144
- @_type = @_type.meta(md) if md
145
- self
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
@@ -1,17 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class StaticClass
7
- include Steppable
7
+ include Composable
8
8
 
9
- attr_reader :value
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/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class Step
7
- include Steppable
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
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'thread'
4
- require 'plumb/steppable'
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 Steppable
18
+ include Composable
19
19
 
20
- attr_reader :element_type
20
+ attr_reader :children
21
21
 
22
- # @option element_type [Steppable] the type of the elements in the stream
22
+ # @option element_type [Composable] the type of the elements in the stream
23
23
  def initialize(element_type: Types::Any)
24
- @element_type = Steppable.wrap(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 [Steppable] the type of the elements in the stream
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
 
@@ -1,29 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class TaggedHash
7
- include Steppable
7
+ include Composable
8
8
 
9
- attr_reader :key, :types
9
+ attr_reader :key, :children
10
10
 
11
- def initialize(hash_type, key, types)
11
+ def initialize(hash_type, key, children)
12
12
  @hash_type = hash_type
13
13
  @key = Key.wrap(key)
14
- @types = types
14
+ @children = children
15
15
 
16
- raise ArgumentError, 'all types must be HashClass' if @types.size.zero? || @types.any? do |t|
16
+ raise ArgumentError, 'all types must be HashClass' if @children.size.zero? || @children.any? do |t|
17
17
  !t.is_a?(HashClass)
18
18
  end
19
- raise ArgumentError, "all types must define key #{@key}" unless @types.all? { |t| !!t.at_key(@key) }
19
+ raise ArgumentError, "all types must define key #{@key}" unless @children.all? { |t| !!t.at_key(@key) }
20
20
 
21
21
  # types are assumed to have literal values for the index field :key
22
- @index = @types.each.with_object({}) do |t, memo|
22
+ @index = @children.each.with_object({}) do |t, memo|
23
23
  key_type = t.at_key(@key)
24
24
  raise TypeError, "key type at :#{@key} #{key_type} must be a Match type" unless key_type.is_a?(MatchClass)
25
25
 
26
- memo[key_type.matcher] = t
26
+ memo[key_type.children[0]] = t
27
27
  end
28
28
 
29
29
  freeze
@@ -41,6 +41,6 @@ module Plumb
41
41
 
42
42
  private
43
43
 
44
- def _inspect = "TaggedHash[#{@key.inspect}, #{@types.map(&:inspect).join(', ')}]"
44
+ def _inspect = "TaggedHash[#{@key.inspect}, #{@children.map(&:inspect).join(', ')}]"
45
45
  end
46
46
  end
@@ -1,16 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class Transform
7
- include Steppable
7
+ include Composable
8
8
 
9
- attr_reader :target_type
9
+ attr_reader :children
10
10
 
11
11
  def initialize(target_type, callable)
12
12
  @target_type = target_type
13
13
  @callable = callable || Plumb::NOOP
14
+ @children = [target_type].freeze
14
15
  freeze
15
16
  end
16
17
 
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class TupleClass
7
- include Steppable
7
+ include Composable
8
8
 
9
- attr_reader :types
9
+ attr_reader :children
10
10
 
11
- def initialize(*types)
12
- @types = types.map { |t| Steppable.wrap(t) }
11
+ def initialize(*children)
12
+ @children = children.map { |t| Composable.wrap(t) }.freeze
13
13
  freeze
14
14
  end
15
15
 
@@ -21,10 +21,10 @@ module Plumb
21
21
 
22
22
  def call(result)
23
23
  return result.invalid(errors: 'must be an Array') unless result.value.is_a?(::Array)
24
- return result.invalid(errors: 'must have the same size') unless result.value.size == @types.size
24
+ return result.invalid(errors: 'must have the same size') unless result.value.size == @children.size
25
25
 
26
26
  errors = {}
27
- values = @types.map.with_index do |type, idx|
27
+ values = @children.map.with_index do |type, idx|
28
28
  val = result.value[idx]
29
29
  r = type.resolve(val)
30
30
  errors[idx] = ["expected #{type.inspect}, got #{val.inspect}", r.errors].flatten unless r.valid?
@@ -39,7 +39,7 @@ module Plumb
39
39
  private
40
40
 
41
41
  def _inspect
42
- "Tuple[#{@types.map(&:inspect).join(', ')}]"
42
+ "Tuple[#{@children.map(&:inspect).join(', ')}]"
43
43
  end
44
44
  end
45
45
  end
@@ -7,7 +7,7 @@ module Plumb
7
7
  case obj
8
8
  when Module
9
9
  obj.extend TypeRegistry
10
- when Steppable
10
+ when Composable
11
11
  anc = [name, const_name].join('::')
12
12
  obj.freeze.name.set(anc)
13
13
  end
@@ -17,16 +17,19 @@ module Plumb
17
17
  host.extend TypeRegistry
18
18
  constants(false).each do |const_name|
19
19
  const = const_get(const_name)
20
+
20
21
  anc = [host.name, const_name].join('::')
21
22
  case const
22
23
  when Module
24
+ next if const.is_a?(Class)
25
+
23
26
  child_mod = Module.new
24
27
  child_mod.define_singleton_method(:name) do
25
28
  anc
26
29
  end
27
30
  child_mod.send(:include, const)
28
31
  host.const_set(const_name, child_mod)
29
- when Steppable
32
+ when Composable
30
33
  type = const.dup
31
34
  type.freeze.name.set(anc)
32
35
  host.const_set(const_name, type)
data/lib/plumb/types.rb CHANGED
@@ -101,7 +101,7 @@ module Plumb
101
101
  Types::Static[value]
102
102
  end
103
103
 
104
- type | (Types::Undefined >> val_type)
104
+ (Types::Undefined >> val_type) | type
105
105
  end
106
106
 
107
107
  # Split a string into an array. Default separator is /\s*,\s*/
@@ -146,6 +146,11 @@ module Plumb
146
146
  Hash = HashClass.new
147
147
  Interface = InterfaceClass.new
148
148
 
149
+ class Data
150
+ extend Composable
151
+ include Plumb::Attributes
152
+ end
153
+
149
154
  module Lax
150
155
  NUMBER_EXPR = /^\d{1,3}(?:,\d{3})*(?:\.\d+)?$/
151
156
 
@@ -1,15 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class ValueClass
7
- include Steppable
7
+ include Composable
8
8
 
9
- attr_reader :value
9
+ attr_reader :children
10
10
 
11
11
  def initialize(value = Undefined)
12
12
  @value = value
13
+ @children = [value].freeze
13
14
  freeze
14
15
  end
15
16
 
data/lib/plumb/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plumb
4
- VERSION = '0.0.3'
4
+ VERSION = '0.0.4'
5
5
  end
@@ -39,5 +39,11 @@ module Plumb
39
39
  def on_missing_handler(node, _props, method_name)
40
40
  raise "No handler for #{node.inspect} with :#{method_name}"
41
41
  end
42
+
43
+ def visit_children(node, props = BLANK_HASH)
44
+ node.children.reduce(props) do |acc, child|
45
+ visit(child, acc)
46
+ end
47
+ end
42
48
  end
43
49
  end
data/lib/plumb.rb CHANGED
@@ -10,7 +10,7 @@ module Plumb
10
10
  end
11
11
 
12
12
  # Register a policy with the given name and block.
13
- # Optionally define a method on the Steppable method to call the policy.
13
+ # Optionally define a method on the Composable method to call the policy.
14
14
  # Example:
15
15
  # Plumb.policy(:multiply_by, for_type: Integer, helper: true) do |step, factor, &block|
16
16
  # step.transform(Integer) { |number| number * factor }
@@ -39,11 +39,11 @@ module Plumb
39
39
 
40
40
  return self unless helper
41
41
 
42
- if Steppable.instance_methods.include?(name)
43
- raise Policies::MethodAlreadyDefinedError, "Method #{name} is already defined on Steppable"
42
+ if Composable.instance_methods.include?(name)
43
+ raise Policies::MethodAlreadyDefinedError, "Method #{name} is already defined on Composable"
44
44
  end
45
45
 
46
- Steppable.define_method(name) do |arg = Undefined, &bl|
46
+ Composable.define_method(name) do |arg = Undefined, &bl|
47
47
  if arg == Undefined
48
48
  policy(name, &bl)
49
49
  else
@@ -53,11 +53,15 @@ module Plumb
53
53
 
54
54
  self
55
55
  end
56
+
57
+ def self.decorate(type, &block)
58
+ Decorator.call(type, &block)
59
+ end
56
60
  end
57
61
 
58
62
  require 'plumb/result'
59
63
  require 'plumb/type_registry'
60
- require 'plumb/steppable'
64
+ require 'plumb/composable'
61
65
  require 'plumb/any_class'
62
66
  require 'plumb/step'
63
67
  require 'plumb/and'
@@ -72,6 +76,8 @@ require 'plumb/array_class'
72
76
  require 'plumb/stream_class'
73
77
  require 'plumb/hash_class'
74
78
  require 'plumb/interface_class'
79
+ require 'plumb/attributes'
75
80
  require 'plumb/types'
76
81
  require 'plumb/json_schema_visitor'
77
82
  require 'plumb/schema'
83
+ require 'plumb/decorator'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plumb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismael Celis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-18 00:00:00.000000000 Z
11
+ date: 2024-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bigdecimal
@@ -54,13 +54,17 @@ files:
54
54
  - examples/concurrent_downloads.rb
55
55
  - examples/csv_stream.rb
56
56
  - examples/env_config.rb
57
+ - examples/event_registry.rb
57
58
  - examples/programmers.csv
58
59
  - examples/weekdays.rb
59
60
  - lib/plumb.rb
60
61
  - lib/plumb/and.rb
61
62
  - lib/plumb/any_class.rb
62
63
  - lib/plumb/array_class.rb
64
+ - lib/plumb/attributes.rb
63
65
  - lib/plumb/build.rb
66
+ - lib/plumb/composable.rb
67
+ - lib/plumb/decorator.rb
64
68
  - lib/plumb/deferred.rb
65
69
  - lib/plumb/hash_class.rb
66
70
  - lib/plumb/hash_map.rb
@@ -79,7 +83,6 @@ files:
79
83
  - lib/plumb/schema.rb
80
84
  - lib/plumb/static_class.rb
81
85
  - lib/plumb/step.rb
82
- - lib/plumb/steppable.rb
83
86
  - lib/plumb/stream_class.rb
84
87
  - lib/plumb/tagged_hash.rb
85
88
  - lib/plumb/transform.rb