standard-procedure-plumbing 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 717c30b41fce6d982c4f3f9d5a0c8ac5abb8187e7bf03b13151fee49f42a3955
4
- data.tar.gz: e0857d6739d95a5861a66871168a9be8154d1854a03fd59534f939b4be06896c
3
+ metadata.gz: a0bfd8678cd958f92a30d6c1879e664ac790637b400a2fd73302a7ed60a3b450
4
+ data.tar.gz: f06824216f1d2da14fa645b0f246106180e6e8e69f8fa7d5526e8a343ac77923
5
5
  SHA512:
6
- metadata.gz: 9de7d23847f7776acb4c4c8d6585451d26a565e3c2982afdf6ebff45293d9977fc27ad79b9996eb192b5f80de713afae7cb725641682d21577beeac4ec76530a
7
- data.tar.gz: eecd88c9eba77690548c56ce683aec310d76955bf3e9d0c85a2f9a7f700a5df7e43206647cbedc18e1cd73530141c881570ee9451787bdca0e5cb4f2e9db7e43
6
+ metadata.gz: ac2e9872aba1ecb6c4f2831ee6da3689afdcf1162c5bc0b65eaa2298ae1a00f4d698fb7909c34e10daa6b14cd10bcd8ab54cd92839fab7a1107cd93de831c2c5
7
+ data.tar.gz: 64f585e329a112504b692b788d6b6c9562bc188eb9c621a33001f2aed69d92c6260909c8a3df174436bfeda345791b7ca370afb09fdad2d281d466efcb0784fc
data/.rubocop.yml ADDED
@@ -0,0 +1,24 @@
1
+ # We want Exclude directives from different
2
+ # config files to get merged, not overwritten
3
+ inherit_mode:
4
+ merge:
5
+ - Exclude
6
+
7
+ require:
8
+ # Standard's config uses custom cops,
9
+ # so it must be loaded along with custom Standard gems
10
+ - standard
11
+ - standard-custom
12
+ - standard-performance
13
+ # rubocop-performance is required when using Performance cops
14
+ - rubocop-performance
15
+
16
+ inherit_gem:
17
+ standard: config/base.yml
18
+ standard-performance: config/base.yml
19
+ standard-custom: config/base.yml
20
+
21
+ # Global options, like Ruby version
22
+ AllCops:
23
+ SuggestExtensions: false
24
+ TargetRubyVersion: 3.2
data/.solargraph.yml ADDED
@@ -0,0 +1,32 @@
1
+ ---
2
+ include:
3
+ - "**/*.rb"
4
+ exclude:
5
+ - spec/**/*
6
+ - test/**/*
7
+ - vendor/**/*
8
+ - ".bundle/**/*"
9
+ require:
10
+ - actioncable
11
+ - actionmailer
12
+ - actionpack
13
+ - actionview
14
+ - activejob
15
+ - activemodel
16
+ - activerecord
17
+ - activestorage
18
+ - activesupport
19
+ domains: []
20
+ reporters:
21
+ - rubocop
22
+ - require_not_found
23
+ formatter:
24
+ rubocop:
25
+ cops: safe
26
+ except: []
27
+ only: []
28
+ extra_args: []
29
+ require_paths: []
30
+ plugins:
31
+ - solargraph-rails
32
+ max_files: 5000
data/.standard.yml CHANGED
@@ -1,3 +1,9 @@
1
- # For available configuration options, see:
2
- # https://github.com/standardrb/standard
3
- ruby_version: 3.0
1
+ fix: true
2
+ parallel: true
3
+ format: progress
4
+ default_ignores: true
5
+
6
+ ignore:
7
+ - 'vendor/**/*'
8
+ - 'Gemfile.lock'
9
+
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
- ## [Unreleased]
1
+ ## [0.1.2] - 2024-08-14
2
+
3
+ - Removed dependencies
4
+ - Removed Ractor-based concurrent pipe (as I don't trust it yet)
5
+
6
+ ## [0.1.1] - 2024-08-14
7
+
8
+ - Tidied up the code
9
+ - Added Plumbing::Chain
2
10
 
3
11
  ## [0.1.0] - 2024-04-13
4
12
 
5
13
  - Initial release
14
+
15
+ ## [Unreleased]
16
+
data/README.md CHANGED
@@ -1,50 +1,163 @@
1
1
  # Plumbing
2
2
 
3
- Composable Observer
3
+ ## Plumbing::Pipe - a composable observer
4
4
 
5
5
  [Observers](https://ruby-doc.org/3.3.0/stdlibs/observer/Observable.html) in Ruby are a pattern where objects (observers) register their interest in another object (the observable). This pattern is common throughout programming languages (event listeners in Javascript, the dependency protocol in [Smalltalk](https://en.wikipedia.org/wiki/Smalltalk)).
6
6
 
7
- Unlike ruby's in-built observers, this gem makes observers "composable". Instead of simply registering for notifications from the observable, we observe a stream of notifications, which could be produced by multiple observables, all being sent through the same pipe. We can then chain observers together, composing a "pipeline" of operations from a single source of events.
7
+ [Plumbing::Pipe](lib/plumbing/pipe.rb) makes observers "composable". Instead of simply registering for notifications from the observable, we observe a stream of notifications, which could be produced by multiple observables, all being sent through the same pipe. We can then chain observers together, composing a "pipeline" of operations from a single source of events.
8
8
 
9
- For example, in a social-networking application, you may push all events associated with a user through a single pipe. But one module within the application is only interested in follow requests, another module in comments. So the "followers" module would attach a "filter pipe" to the "users" pipe, filtering out everything except follow requests. Then the code within that module observes this "filter pipe" so only gets notified about follow requests. And similarly, the "comments" module attaches a "filter pipe" to the "users" pipe, filtering out everything except "comments".
9
+ ### Usage
10
10
 
11
- However, the pipeline can do much more than simple filtering.
11
+ A simple observer:
12
+ ```ruby
13
+ require "plumbing"
12
14
 
13
- In a search engine application, it is important to keep a record of what has been searched for, but more importantly, which of those search results resulted in a click - as you can then use this data to improve your search results in future. We could implement a chain of observers, from the pipe that records all search related events, a filter that looks at the events from a single user, to another observer that maintains a log of every search result for a given user from the last 30 minutes and then matches any clicks to those results - sending those matches to an analytics service.
15
+ @source = Plumbing::Pipe.start
14
16
 
15
- The key fact is that each element in the chain of observers is only aware of the stream of events from the element just before it. And when it outputs its own events, any observers to that stream are only aware of the element they have subscribed to. This means that the chain works in a similar manner to unix pipes.
17
+ @observer = @source.add_observer do |event|
18
+ puts event.type
19
+ end
16
20
 
17
- In unix, you can use `cat logfile | grep -o "some text" | ec -l` to easily count the number of times "some text" occurs in your logfile. Each individual command in that pipeline is extremely simple and optimised for its one task. But piping them together gives you incredible flexibility and power.
21
+ @source.notify "something_happened", message: "But what was it?"
22
+ # => "something_happened"
23
+ ```
18
24
 
19
- The same is true when you compose a pipeline of observers, each of which watches the events in a stream. You can attach observers which buffer the incoming events, so the receivers aren't swamped. You can attach observers which manipulate the incoming data (see the inline emoji writer in the examples folder), or de-duplicate or merge events (which is very useful if you want to prevent flicker and unnecessary redraws in your user-interface). And observers can republish events to different streams - we could take events on one stream and send those same events, or a subset, to a web-socket.
25
+ Simple filtering:
26
+ ```ruby
27
+ require "plumbing"
20
28
 
29
+ @source = Plumbing::Pipe.start
21
30
 
22
- ## Installation
23
-
24
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
31
+ @filter = Plumbing::Filter.start source: @source, accepts: %w[important urgent]
25
32
 
26
- Install the gem and add to the application's Gemfile by executing:
33
+ @observer = @filter.add_observer do |event|
34
+ puts event.type
35
+ end
27
36
 
28
- $ bundle add standard-procedure-plumbing
37
+ @source.notify "important", message: "ALERT! ALERT!"
38
+ # => "important"
29
39
 
30
- ## Usage
40
+ @source.notify "unimportant", message: "Nothing to see here"
41
+ # => <no output>
42
+ ```
31
43
 
32
- Create a pipe, chain pipes together, add observers and push events
44
+ Custom filtering:
45
+ ```ruby
46
+ require "plumbing"
33
47
 
34
- require 'plumbing'
48
+ class EveryThirdEvent < Plumbing::CustomFilter
49
+ def initialize source:
50
+ super source: source
51
+ @events = []
52
+ end
35
53
 
36
- @pipe = Plumbing::Pipe.start
37
- @filter = Plumbing::Filter.start source: @pipe, accepts: %w[important urgent]
38
- @observer = @filter.add_observer do |event|
39
- puts event.type
54
+ def received event
55
+ @events << event
56
+ # if we've already stored 2 events in the buffer then broadcast the newest event and clear the buffer
57
+ if @events.count >= 2
58
+ @events.clear
59
+ self << event
40
60
  end
61
+ end
62
+ end
63
+
64
+ @source = Plumbing::Pipe.start
65
+ @filter = EveryThirdEvent.new(source: @source)
66
+
67
+ @observer = @filter.add_observer do |event|
68
+ puts event.type
69
+ end
70
+
71
+ 1.upto 10 do |i|
72
+ @source.notify i.to_s
73
+ end
74
+ # => "3"
75
+ # => "6"
76
+ # => "9"
77
+ ```
78
+
79
+ Joining multiple sources
80
+ ```ruby
81
+ require "plumbing"
82
+
83
+ @first_source = Plumbing::Pipe.start
84
+ @second_source = Plumbing::Pipe.start
85
+
86
+ @join = Plumbing::Junction.start @first_source, @second_source
87
+
88
+ @observer = @join.add_observer do |event|
89
+ puts event.type
90
+ end
91
+
92
+ @first_source.notify "one"
93
+ # => "one"
94
+ @second_source.notify "two"
95
+ # => "two"
96
+ ```
97
+
98
+ ## Plumbing::Chain - a chain of operations that occur in sequence
99
+
100
+ Define a sequence of operations that proceed in order, passing their output from one operation as the input to another.
101
+
102
+ You can define pre-conditions (which validate the inputs supplied) or post-conditions (which validate the output).
103
+
104
+ ### Usage:
105
+
106
+ ```ruby
107
+ require "plumbing"
108
+ class BuildSequence < Plumbing::Chain
109
+ pre_condition :must_be_an_array do |input|
110
+ input.is_a? Array
111
+ end
112
+
113
+ post_condition :must_have_three_elements do |output|
114
+ # yes, this is a stupid post-condition but it shows how you can ensure your outputs are valid
115
+ output.length == 3
116
+ end
117
+
118
+ perform :add_first
119
+ perform :add_second
120
+ perform :add_third
121
+
122
+ private
123
+
124
+ def add_first input
125
+ input << "first"
126
+ end
127
+
128
+ def add_second input
129
+ input << "second"
130
+ end
131
+
132
+ def add_third input
133
+ input << "third"
134
+ end
135
+ end
136
+
137
+ BuildSequence.new.call []
138
+ # => ["first", "second", "third"]
139
+
140
+ BuildSequence.new.call 1
141
+ # => Plumbing::PreconditionError("must_be_an_array")
142
+
143
+ BuildSequence.new.call ["extra element"]
144
+ # => Plumbing::PostconditionError("must_have_three_elements")
145
+ ```
146
+
147
+ ## Installation
148
+
149
+ Install the gem and add to the application's Gemfile by executing:
150
+
151
+ ```sh
152
+ bundle add standard-procedure-plumbing
153
+ ```
154
+
155
+ Then:
41
156
 
42
- @pipe << Event.new(type: "unimportant", data: { some: "data"})
43
- # => no output
44
- @pipe << Event.new(type: "important", data: { some: "data"})
45
- # => "important"
157
+ ```ruby
158
+ require 'plumbing'
159
+ ```
46
160
 
47
- @filter.remove_observer @observer
48
161
 
49
162
  ## Development
50
163
 
@@ -0,0 +1 @@
1
+ 30cc1d4b434b322269e0100acd3a42088d93359e0d34b7a947ac272c55b2e82788ab6f0926f2cc95552d746b71791470412a7cdfa34605d4b20309df0de97a33
@@ -0,0 +1 @@
1
+ 18d6d3138d2879c1672ab60b1534a6bc382e99a67adb4f8eff9c60ffb96b78b148bffac54ff1f7e78a2da1fc36d000041806b3a73993416c62279ef3ca09beba
@@ -0,0 +1,105 @@
1
+ require_relative "error"
2
+ require_relative "event"
3
+
4
+ module Plumbing
5
+ # The "plumbing" for a Pipe.
6
+ # This class is "blocked", in that it won't push any events to registered observers.
7
+ # Instead, this is the basis for subclasses like [Plumbing::Pipe] which actually allow events to flow through them.
8
+ class BlockedPipe
9
+ # Create a new BlockedPipe
10
+ # Subclasses should call `super()` to ensure the pipe is initialised corrected
11
+ def initialize
12
+ @observers = []
13
+ end
14
+
15
+ # Push an event into the pipe
16
+ # @param event [Plumbing::Event] the event to push into the pipe
17
+ # Subclasses should implement this method
18
+ def << event
19
+ raise Plumbing::PipeIsBlocked
20
+ end
21
+
22
+ # A shortcut to creating and then pushing an event
23
+ # @param event_type [String] representing the type of event this is
24
+ # @param data [Hash] representing the event-specific data to be passed to the observers
25
+ def notify event_type, data = nil
26
+ Event.new(type: event_type, data: data).tap do |event|
27
+ self << event
28
+ end
29
+ end
30
+
31
+ # Add an observer to this pipe
32
+ # @param callable [Proc] (optional)
33
+ # @param &block [Block] (optional)
34
+ # @return an object representing this observer (dependent upon the implementation of the pipe itself)
35
+ # Either a `callable` or a `block` must be supplied. If the latter, it is converted to a [Proc]
36
+ def add_observer observer = nil, &block
37
+ observer ||= block.to_proc
38
+ raise Plumbing::InvalidObserver.new "observer_does_not_respond_to_call" unless observer.respond_to? :call
39
+ @observers << observer
40
+ end
41
+
42
+ # Remove an observer from this pipe
43
+ # @param observer
44
+ # This removes the given observer from this pipe. The observer should have previously been returned by #add_observer and is implementation-specific
45
+ def remove_observer observer
46
+ @observers.delete observer
47
+ end
48
+
49
+ # Test whether the given observer is observing this pipe
50
+ # @param observer
51
+ # @return [boolean]
52
+ def is_observer? observer
53
+ @observers.include? observer
54
+ end
55
+
56
+ # Close this pipe and perform any cleanup.
57
+ # Subclasses should override this to perform their own shutdown routines and call `super` to ensure everything is tidied up
58
+ def shutdown
59
+ # clean up and release any observers, just in case
60
+ @observers = []
61
+ end
62
+
63
+ # Start this pipe
64
+ # Subclasses may override this method to add any implementation specific details.
65
+ # By default any supplied parameters are called to the subclass' `initialize` method
66
+ def self.start(**params)
67
+ new(**params)
68
+ end
69
+
70
+ protected
71
+
72
+ # Get the next event from the queue
73
+ # @return [Plumbing::Event]
74
+ # Subclasses should implement this method
75
+ def get_next_event
76
+ raise Plumbing::PipeIsBlocked
77
+ end
78
+
79
+ # Start the event loop
80
+ # This loop keeps running until `shutdown` is called
81
+ # Some subclasses may need to replace this method to deal with their own specific implementations
82
+ # @param initial_event [Plumbing::Event] optional; the first event in the queue
83
+ def start_run_loop initial_event = nil
84
+ loop do
85
+ event = initial_event || get_next_event
86
+ break if event == :shutdown
87
+ dispatch event
88
+ initial_event = nil
89
+ end
90
+ end
91
+
92
+ # Dispatch an event to all observers
93
+ # @param event [Plumbing::Event]
94
+ # Enumerates all observers and `calls` them with this event
95
+ # Discards any errors raised by the observer so that all observers will be successfully notified
96
+ def dispatch event
97
+ @observers.collect do |observer|
98
+ observer.call event
99
+ rescue => ex
100
+ puts ex
101
+ ex
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,59 @@
1
+ module Plumbing
2
+ # A chain of operations that are executed in sequence
3
+ class Chain
4
+ def call params
5
+ self.class._call params, self
6
+ end
7
+
8
+ class << self
9
+ def pre_condition name, &validator
10
+ pre_conditions[name.to_sym] = validator
11
+ end
12
+
13
+ def perform method, &implementation
14
+ implementation ||= ->(params, instance) { instance.send(method, params) }
15
+ operations << implementation
16
+ end
17
+
18
+ def post_condition name, &validator
19
+ post_conditions[name.to_sym] = validator
20
+ end
21
+
22
+ def _call params, instance
23
+ validate_preconditions_for params
24
+ result = params
25
+ operations.each do |operation|
26
+ result = operation.call(result, instance)
27
+ end
28
+ validate_postconditions_for result
29
+ result
30
+ end
31
+
32
+ private
33
+
34
+ def operations
35
+ @operations ||= []
36
+ end
37
+
38
+ def pre_conditions
39
+ @pre_conditions ||= {}
40
+ end
41
+
42
+ def post_conditions
43
+ @post_conditions ||= {}
44
+ end
45
+
46
+ def validate_preconditions_for input
47
+ failed_preconditions = pre_conditions.select { |name, validator| !validator.call(input) }
48
+ raise PreConditionError, failed_preconditions.keys.join(", ") if failed_preconditions.any?
49
+ input
50
+ end
51
+
52
+ def validate_postconditions_for output
53
+ failed_postconditions = post_conditions.select { |name, validator| !validator.call(output) }
54
+ raise PostConditionError, failed_postconditions.keys.join(", ") if failed_postconditions.any?
55
+ output
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,19 @@
1
+ module Plumbing
2
+ # Base error class for all Plumbing errors
3
+ class Error < StandardError; end
4
+
5
+ # Error raised because a pre-condition failed
6
+ class PreConditionError < Error; end
7
+
8
+ # Error raised because a post-condition failed
9
+ class PostConditionError < Error; end
10
+
11
+ # Error raised because an invalid [Event] object was pushed into the pipe
12
+ class InvalidEvent < Error; end
13
+
14
+ # Error raised because an invalid observer was registered
15
+ class InvalidObserver < Error; end
16
+
17
+ # Error raised because a BlockedPipe was used instead of an actual implementation of a Pipe
18
+ class PipeIsBlocked < Plumbing::Error; end
19
+ end
@@ -1,16 +1,5 @@
1
- require "dry/types"
2
- require "dry/struct"
3
-
4
1
  module Plumbing
5
- class Event < Dry::Struct
6
- module Types
7
- include Dry::Types()
8
- SequenceNumber = Strict::Integer
9
- EventType = Strict::String
10
- EventData = Strict::Hash.default({}.freeze)
11
- end
12
-
13
- attribute :type, Types::EventType
14
- attribute :data, Types::EventData
2
+ # An immutable data structure representing an Event
3
+ Event = Data.define :type, :data do
15
4
  end
16
5
  end
@@ -1,19 +1,21 @@
1
- require "dry/types"
2
- require_relative "pipe"
1
+ require_relative "blocked_pipe"
3
2
 
4
3
  module Plumbing
5
- class Filter < Pipe
6
- module Types
7
- include Dry::Types()
8
- Source = Instance(Plumbing::Pipe)
9
- EventTypes = Array.of(Plumbing::Event::Types::EventType)
10
- end
4
+ # A pipe that filters events from a source pipe
5
+ class Filter < BlockedPipe
6
+ class InvalidFilter < Error; end
11
7
 
8
+ # Chain this pipe to the source pipe
9
+ # @param source [Plumbing::BlockedPipe]
10
+ # @param accepts [Array[String]] event types that this filter will allow through (or pass [] to allow all)
11
+ # @param rejects [Array[String]] event types that this filter will not allow through
12
12
  def initialize source:, accepts: [], rejects: []
13
13
  super()
14
- @accepted_event_types = Types::EventTypes[accepts]
15
- @rejected_event_types = Types::EventTypes[rejects]
16
- Types::Source[source].add_observer do |event|
14
+ raise InvalidFilter.new "source must be a Plumbing::BlockedPipe descendant" unless source.is_a? Plumbing::BlockedPipe
15
+ raise InvalidFilter.new "accepts and rejects must be arrays" unless accepts.is_a?(Array) && rejects.is_a?(Array)
16
+ @accepted_event_types = accepts
17
+ @rejected_event_types = rejects
18
+ source.add_observer do |event|
17
19
  filter_and_republish(event)
18
20
  end
19
21
  end
@@ -21,9 +23,10 @@ module Plumbing
21
23
  private
22
24
 
23
25
  def filter_and_republish event
26
+ raise InvalidEvent.new "event is not a Plumbing::Event" unless event.is_a? Plumbing::Event
24
27
  return nil if @accepted_event_types.any? && !@accepted_event_types.include?(event.type)
25
28
  return nil if @rejected_event_types.include? event.type
26
- self << event
29
+ dispatch event
27
30
  end
28
31
  end
29
32
  end
data/lib/plumbing/pipe.rb CHANGED
@@ -1,55 +1,29 @@
1
- require "dry/types"
2
- require_relative "event"
1
+ require_relative "blocked_pipe"
3
2
 
4
3
  module Plumbing
5
- InvalidEvent = Dry::Types::ConstraintError
6
- InvalidObserver = Dry::Types::ConstraintError
7
-
8
- class Pipe
9
- module Types
10
- include Dry::Types()
11
- Event = Instance(Plumbing::Event)
12
- Observer = Interface(:call)
13
- end
14
-
4
+ # An implementation of a pipe that uses Fibers
5
+ class Pipe < BlockedPipe
15
6
  def initialize
16
- @observers = []
17
- @fiber = Fiber.new do |event|
18
- loop do
19
- break if event == :shutdown
20
- @observers.each do |observer|
21
- observer.call event
22
- rescue
23
- nil
24
- end
25
- event = Fiber.yield
26
- end
27
- # clean up and release any observers, just in case
28
- @observers = []
7
+ super
8
+ @fiber = Fiber.new do |initial_event|
9
+ start_run_loop initial_event
29
10
  end
30
11
  end
31
12
 
32
13
  def << event
33
- @fiber.resume Types::Event[event]
34
- end
35
-
36
- def add_observer callable = nil, &block
37
- callable ||= block.to_proc
38
- Types::Observer[callable].tap do |observer|
39
- @observers << observer
40
- end
41
- end
42
-
43
- def remove_observer callable
44
- @observers.delete callable
14
+ raise Plumbing::InvalidEvent.new "event is not a Plumbing::Event" unless event.is_a? Plumbing::Event
15
+ @fiber.resume event
45
16
  end
46
17
 
47
18
  def shutdown
19
+ super
48
20
  @fiber.resume :shutdown
49
21
  end
50
22
 
51
- def self.start(**params)
52
- new(**params)
23
+ protected
24
+
25
+ def get_next_event
26
+ Fiber.yield
53
27
  end
54
28
  end
55
29
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plumbing
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/plumbing.rb CHANGED
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/types"
4
3
  module Plumbing
5
- class Error < StandardError; end
6
-
7
4
  require_relative "plumbing/version"
8
5
 
6
+ require_relative "plumbing/error"
9
7
  require_relative "plumbing/event"
10
8
  require_relative "plumbing/pipe"
9
+ require_relative "plumbing/chain"
11
10
  end
metadata CHANGED
@@ -1,44 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard-procedure-plumbing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rahoul Baruah
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-14 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: dry-types
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: dry-struct
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- description: An event pipeline
11
+ date: 2024-08-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A composable event pipeline and sequential pipelines of operations
42
14
  email:
43
15
  - rahoulb@echodek.co
44
16
  executables: []
@@ -46,15 +18,20 @@ extensions: []
46
18
  extra_rdoc_files: []
47
19
  files:
48
20
  - ".rspec"
21
+ - ".rubocop.yml"
22
+ - ".solargraph.yml"
49
23
  - ".standard.yml"
50
24
  - CHANGELOG.md
51
25
  - CODE_OF_CONDUCT.md
52
- - Guardfile
53
26
  - LICENSE
54
27
  - README.md
55
28
  - Rakefile
29
+ - checksums/standard-procedure-plumbing-0.1.1.gem.sha512
30
+ - checksums/standard-procedure-plumbing-0.1.2.gem.sha512
56
31
  - lib/plumbing.rb
57
- - lib/plumbing/.DS_Store
32
+ - lib/plumbing/blocked_pipe.rb
33
+ - lib/plumbing/chain.rb
34
+ - lib/plumbing/error.rb
58
35
  - lib/plumbing/event.rb
59
36
  - lib/plumbing/filter.rb
60
37
  - lib/plumbing/pipe.rb
@@ -65,8 +42,8 @@ licenses: []
65
42
  metadata:
66
43
  allowed_push_host: https://rubygems.org
67
44
  homepage_uri: https://theartandscienceofruby.com
68
- source_code_uri: https://github.com
69
- changelog_uri: https://github.com
45
+ source_code_uri: https://github.com/standard-procedure/plumbing
46
+ changelog_uri: https://github.com/standard-procedure/plumbing/blob/main/CHANGELOG.md
70
47
  post_install_message:
71
48
  rdoc_options: []
72
49
  require_paths:
@@ -82,8 +59,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
59
  - !ruby/object:Gem::Version
83
60
  version: '0'
84
61
  requirements: []
85
- rubygems_version: 3.5.6
62
+ rubygems_version: 3.5.9
86
63
  signing_key:
87
64
  specification_version: 4
88
- summary: An event pipeline
65
+ summary: Plumbing - various pipelines for your ruby application
89
66
  test_files: []
data/Guardfile DELETED
@@ -1,32 +0,0 @@
1
- ignore(/bin/, /log/, /public/, /storage/, /tmp/)
2
-
3
- group :formatting do
4
- guard :standardrb, fix: true, all_on_start: true, progress: true do
5
- watch(/.+\.rb$/)
6
- watch(/.+\.thor$/)
7
- watch(/.+\.rake$/)
8
- watch(/Guardfile$/)
9
- watch(/Rakefile$/)
10
- watch(/Gemfile$/)
11
- end
12
- end
13
-
14
- group :development do
15
- guard :rspec, cmd: "bundle exec rspec" do
16
- watch("spec/.+_helper.rb") { "spec" }
17
- watch(%r{^spec/.+_spec\.rb$})
18
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
19
- end
20
-
21
- guard :bundler do
22
- require "guard/bundler"
23
- require "guard/bundler/verify"
24
- helper = Guard::Bundler::Verify.new
25
-
26
- files = ["Gemfile"]
27
- files += Dir["*.gemspec"] if files.any? { |f| helper.uses_gemspec?(f) }
28
-
29
- # Assume files are symlinked from somewhere
30
- files.each { |file| watch(helper.real_path(file)) }
31
- end
32
- end
Binary file