web_pipe 0.2.0 → 0.3.0

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: d89f930070f399bae4f6949b4f62b61d2fcb6f8716e9527baa350cf673daa4a6
4
- data.tar.gz: a7942d96afa3110e68dd55591a56b780d39a61c6e5b22cff5087a628b5997a6e
3
+ metadata.gz: 2f0e9b6d0efd9e7280bd1628237d3219f1307a28d63ec0d8f0e63366ce93e166
4
+ data.tar.gz: 407269e3f023e97a84855fe315ca3558ccf49a2b0cb78674336274fb1ae2c800
5
5
  SHA512:
6
- metadata.gz: 9a5b905649927d6bbba53540583f9429ef862aa0ee764087f037f3b490e32c87d3d24cbd30980267d7a7bd89735d23c9a3965c21938fa50d326f7a794eab6c6b
7
- data.tar.gz: 19c1b7ec4247cfe48cde66b0c74eee6978f905759f943b77d0b93d315e2cc603759a4ae5afc7282945255093d4fd746e4101e62834067b10853aaa9f69e3d254
6
+ metadata.gz: a2bf1652e9c88e4dcd708b95fc573d1daffeea2f3d56fd908598eb447c1819912c2ac53a35eecf0a5315d4e1195b9c412c34e5a58fb70cf3c5cfa36da602aa45
7
+ data.tar.gz: 386e1da635847bc21ab2eee5203babda8020fb89f8a11be51e2718bf844e34405ccdb60f4e537d3d3e7afb3d62264f32add6be94711420f490e2f02c3420c9be
data/CHANGELOG.md CHANGED
@@ -4,6 +4,70 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [0.3.0] - 2019-07-12
8
+ ### Added
9
+ - **BREAKING**: When plugging with `plug:`, the operation is no longer specified through `with:`. Now it is just the second positional argument ([9](https://github.com/waiting-for-dev/web_pipe/pull/9)):
10
+
11
+ ```ruby
12
+ plug :from_container, 'container'
13
+ plug :inline, ->(conn) { conn.set_response_body('Hello world') }
14
+ ```
15
+ - It is possible to plug a block ([9](https://github.com/waiting-for-dev/web_pipe/pull/9)):
16
+ ```ruby
17
+ plug(:content_type) { |conn| conn.add_response_header('Content-Type', 'text/html') }
18
+ ```
19
+
20
+ - WebPipe plug's can be composed. A WebPipe proc representation is the composition of all its operations, which is an operation itself ([9](https://github.com/waiting-for-dev/web_pipe/pull/9)):
21
+
22
+ ```ruby
23
+ class HtmlApp
24
+ include WebPipe
25
+
26
+ plug :content_type
27
+ plug :default_status
28
+
29
+ private
30
+
31
+ def content_type(conn)
32
+ conn.add_response_header('Content-Type', 'text/html')
33
+ end
34
+
35
+ def default_status(conn)
36
+ conn.set_status(404)
37
+ end
38
+ end
39
+
40
+ class App
41
+ include WebPipe
42
+
43
+ plug :html, &HtmlApp.new
44
+ plug :body
45
+
46
+ private
47
+
48
+ def body(conn)
49
+ conn.set_response_body('Hello, world!')
50
+ end
51
+ end
52
+ ```
53
+
54
+ - WebPipe's middlewares can be composed into another WebPipe class, also through `:use`:
55
+
56
+ ```ruby
57
+ class HtmlApp
58
+ include WebPipe
59
+
60
+ use Rack::Session::Cookie, key: 'key', secret: 'top_secret'
61
+ use Rack::MethodOverride
62
+ end
63
+
64
+ class App
65
+ include WebPipe
66
+
67
+ use HtmlApp
68
+ end
69
+ ```
70
+
7
71
  ## [0.2.0] - 2019-07-05
8
72
  ### Added
9
73
  - dry-view integration ([#1](https://github.com/waiting-for-dev/web_pipe/pull/1), [#3](https://github.com/waiting-for-dev/web_pipe/pull/3), [#4](https://github.com/waiting-for-dev/web_pipe/pull/4), [#5](https://github.com/waiting-for-dev/web_pipe/pull/5) and [#6](https://github.com/waiting-for-dev/web_pipe/pull/6))
@@ -15,4 +79,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
15
79
 
16
80
  ## [0.1.0] - 2019-05-07
17
81
  ### Added
18
- - Initial release.
82
+ - Initial release.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- web_pipe (0.1.0)
4
+ web_pipe (0.2.0)
5
5
  dry-initializer (~> 3.0)
6
6
  dry-monads (~> 1.2)
7
7
  dry-struct (~> 1.0)
data/README.md CHANGED
@@ -180,20 +180,52 @@ class App
180
180
 
181
181
  #### Proc (or anything responding to `#call`)
182
182
 
183
- Operations can also be defined inline, through the `with:` keyword, as
184
- anything that responds to `#call`, like a `Proc`:
183
+ Operations can also be defined inline as anything that responds to
184
+ `#call`, like a `Proc`, or also like a block:
185
185
 
186
186
  ```ruby
187
187
  class App
188
188
  include WebPipe
189
189
 
190
- plug :hello, with: ->(conn) { conn }
190
+ plug :hello, ->(conn) { conn }
191
+ plug(:hello2) { |conn| conn }
192
+ end
193
+ ```
194
+
195
+ The representation of a `WebPipe` as a Proc is itself an operation
196
+ accepting a `Conn` and returning a `Conn`: the composition of all its
197
+ plugs. Therefore, it can be plugged to any other `WebPipe`:
198
+
199
+ ```ruby
200
+ class HtmlApp
201
+ include WebPipe
202
+
203
+ plug :html
204
+
205
+ private
206
+
207
+ def html(conn)
208
+ conn.add_response_header('Content-Type', 'text/html')
209
+ end
210
+ end
211
+
212
+ class App
213
+ include WebPipe
214
+
215
+ plug :html, &HtmlApp.new
216
+ plug :body
217
+
218
+ private
219
+
220
+ def body(conn)
221
+ conn.set_response_body('Hello, world!')
222
+ end
191
223
  end
192
224
  ```
193
225
 
194
226
  #### Container
195
227
 
196
- When `with:` is a `String` or a `Symbol`, it can be used as the key to
228
+ When a `String` or a `Symbol` is given, it can be used as the key to
197
229
  resolve an operation from a container. A container is just anything
198
230
  responding to `#[]`.
199
231
 
@@ -207,7 +239,7 @@ class App
207
239
 
208
240
  include WebPipe.(container: Container)
209
241
 
210
- plug :hello, with: 'plugs.hello'
242
+ plug :hello, 'plugs.hello'
211
243
  end
212
244
  ```
213
245
 
@@ -220,7 +252,7 @@ overriding those configured through `plug`:
220
252
  class App
221
253
  include WebPipe
222
254
 
223
- plug :hello, with: ->(conn) { conn.set_response_body('Hello') }
255
+ plug :hello, ->(conn) { conn.set_response_body('Hello') }
224
256
  end
225
257
 
226
258
  run App.new(
@@ -243,7 +275,20 @@ class App
243
275
  use Middleware1
244
276
  use Middleware2, option_1: value_1
245
277
 
246
- plug :hello, with: ->(conn) { conn }
278
+ plug :hello, ->(conn) { conn }
279
+ end
280
+ ```
281
+
282
+ It is also possible to compose all the middlewares from another pipe
283
+ class. Extending from previous example:
284
+
285
+ ```ruby
286
+ class App2
287
+ include WebPipe
288
+
289
+ use App # it will also use Middleware1 and Middleware2
290
+
291
+ plug :hello, ->(conn) { conn }
247
292
  end
248
293
  ```
249
294
 
data/lib/web_pipe/app.rb CHANGED
@@ -1,11 +1,8 @@
1
1
  require 'dry/initializer'
2
- require 'dry/monads/result'
3
2
  require 'web_pipe/types'
4
3
  require 'web_pipe/conn'
5
4
  require 'web_pipe/conn_support/builder'
6
- require 'dry/monads/result/extensions/either'
7
-
8
- Dry::Monads::Result.load_extensions(:either)
5
+ require 'web_pipe/conn_support/composition'
9
6
 
10
7
  module WebPipe
11
8
  # Rack application built around applying a pipe of {Operation} to
@@ -26,41 +23,24 @@ module WebPipe
26
23
  # whenever the stack is emptied or a {Conn::Dirty} is
27
24
  # returned in any of the steps.
28
25
  class App
29
- # Type for an operation.
30
- #
31
- # It should be anything callable expecting a {Conn} and
32
- # returning a {Conn}.
33
- Operation = Types.Interface(:call)
34
-
35
26
  # Type for a rack environment.
36
27
  RackEnv = Types::Strict::Hash
37
28
 
38
- # Error raised when an {Operation} returns something that is not a
39
- # {Conn}.
40
- class InvalidOperationResult < RuntimeError
41
- # @param returned [Any] What was returned from the {Operation}
42
- def initialize(returned)
43
- super(
44
- <<~eos
45
- An operation returned +#{returned.inspect}+. To be valid,
46
- an operation must return whether a
47
- WebPipe::Conn::Clean or a WebPipe::Conn::Dirty.
48
- eos
49
- )
50
- end
51
- end
52
-
53
29
  include Dry::Monads::Result::Mixin
54
30
 
55
31
  include Dry::Initializer.define -> do
56
32
  # @!attribute [r] operations
57
33
  # @return [Array<Operation[]>]
58
- param :operations, type: Types.Array(Operation)
34
+ param :operations, type: Types.Array(
35
+ ConnSupport::Composition::Operation
36
+ )
59
37
  end
60
38
 
61
39
  # @param env [Hash] Rack env
62
40
  #
63
41
  # @return env [Array] Rack response
42
+ # @raise ConnSupport::Composition::InvalidOperationResult when an
43
+ # operation does not return a {Conn}
64
44
  def call(env)
65
45
  extract_rack_response(
66
46
  apply_operations(
@@ -74,33 +54,15 @@ module WebPipe
74
54
  private
75
55
 
76
56
  def conn_from_env(env)
77
- Success(
78
- ConnSupport::Builder.(env)
79
- )
57
+ ConnSupport::Builder.(env)
80
58
  end
81
59
 
82
60
  def apply_operations(conn)
83
- operations.reduce(conn) do |new_conn, operation|
84
- new_conn.bind { |c| apply_operation(c, operation) }
85
- end
86
- end
87
-
88
- def apply_operation(conn, operation)
89
- result = operation.(conn)
90
- case result
91
- when Conn::Clean
92
- Success(result)
93
- when Conn::Dirty
94
- Failure(result)
95
- else
96
- raise InvalidOperationResult.new(result)
97
- end
61
+ ConnSupport::Composition.new(operations).call(conn)
98
62
  end
99
63
 
100
64
  def extract_rack_response(conn)
101
- extract_proc = :rack_response.to_proc
102
-
103
- conn.either(extract_proc, extract_proc)
65
+ conn.rack_response
104
66
  end
105
67
  end
106
68
  end
@@ -0,0 +1,89 @@
1
+ require 'dry/initializer'
2
+ require 'dry/monads/result'
3
+ require 'web_pipe/types'
4
+ require 'web_pipe/conn'
5
+ require 'dry/monads/result/extensions/either'
6
+
7
+ Dry::Monads::Result.load_extensions(:either)
8
+
9
+ module WebPipe
10
+ module ConnSupport
11
+ # Composition of a pipe of {Operation} on a {Conn}.
12
+ #
13
+ # It represents the composition of a series of functions which
14
+ # take a {Conn} as argument and return a {Conn}.
15
+ #
16
+ # However, {Conn} can itself be of two different types (subclasses
17
+ # of it): a {Conn::Clean} or a {Conn::Dirty}. On execution time,
18
+ # the composition is stopped whenever the stack is emptied or a
19
+ # {Conn::Dirty} is returned in any of the steps.
20
+ class Composition
21
+ # Type for an operation.
22
+ #
23
+ # It should be anything callable expecting a {Conn} and
24
+ # returning a {Conn}.
25
+ Operation = Types.Interface(:call)
26
+
27
+ # Error raised when an {Operation} returns something that is not
28
+ # a {Conn}.
29
+ class InvalidOperationResult < RuntimeError
30
+ # @param returned [Any] What was returned from the {Operation}
31
+ def initialize(returned)
32
+ super(
33
+ <<~eos
34
+ An operation returned +#{returned.inspect}+. To be valid,
35
+ an operation must return whether a
36
+ WebPipe::Conn::Clean or a WebPipe::Conn::Dirty.
37
+ eos
38
+ )
39
+ end
40
+ end
41
+
42
+ include Dry::Monads::Result::Mixin
43
+
44
+ include Dry::Initializer.define -> do
45
+ # @!attribute [r] operations
46
+ # @return [Array<Operation[]>]
47
+ param :operations, type: Types.Array(Operation)
48
+ end
49
+
50
+ # @param conn [Conn]
51
+ # @return [Conn]
52
+ # @raise InvalidOperationResult when an operation does not
53
+ # return a {Conn}
54
+ def call(conn)
55
+ extract_result(
56
+ apply_operations(
57
+ conn
58
+ )
59
+ )
60
+ end
61
+
62
+ private
63
+
64
+ def apply_operations(conn)
65
+ operations.reduce(Success(conn)) do |new_conn, operation|
66
+ new_conn.bind { |c| apply_operation(c, operation) }
67
+ end
68
+ end
69
+
70
+ def apply_operation(conn, operation)
71
+ result = operation.(conn)
72
+ case result
73
+ when Conn::Clean
74
+ Success(result)
75
+ when Conn::Dirty
76
+ Failure(result)
77
+ else
78
+ raise InvalidOperationResult.new(result)
79
+ end
80
+ end
81
+
82
+ def extract_result(result)
83
+ extract_proc = :itself.to_proc
84
+
85
+ result.either(extract_proc, extract_proc)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -51,8 +51,8 @@ module WebPipe
51
51
  def define_dsl
52
52
  DSL_METHODS.each do |method|
53
53
  module_exec(dsl_context) do |dsl_context|
54
- define_method(method) do |*args|
55
- dsl_context.method(method).(*args)
54
+ define_method(method) do |*args, &block|
55
+ dsl_context.method(method).(*args, &block)
56
56
  end
57
57
  end
58
58
  end
@@ -2,6 +2,7 @@ require 'dry/initializer'
2
2
  require 'web_pipe/types'
3
3
  require 'web_pipe/plug'
4
4
  require 'web_pipe/rack/middleware'
5
+ require 'web_pipe/rack/middleware_specification'
5
6
 
6
7
  module WebPipe
7
8
  module DSL
@@ -21,32 +22,42 @@ module WebPipe
21
22
 
22
23
  include Dry::Initializer.define -> do
23
24
  param :middlewares,
24
- type: Types.Array(Rack::Middleware::Instance)
25
+ type: Types.Array(Rack::Middleware)
25
26
 
26
27
  param :plugs,
27
28
  type: Types.Array(Plug::Instance)
28
29
  end
29
30
 
30
- # Creates and add a rack middleware to the stack.
31
+ # Creates and add rack middlewares to the stack.
31
32
  #
32
- # @param middleware
33
- # [WebPipe::Rack::Middleware::MiddlewareClass[]] Rack middleware
34
- # @param middleware [WebPipe::Rack::Options[]] Options to
35
- # initialize
33
+ # The spec can be given in two forms:
34
+ #
35
+ # - As one or two arguments, first one being a
36
+ # {::Rack::Middleware} class and second one optionally its
37
+ # initialization options.
38
+ # - As a {WebPipe} class, in which case all its rack middlewares
39
+ # will be added to the stack in order.
40
+ #
41
+ # @param spec [Rack::MiddlewareSpecification::Spec[]]
36
42
  #
37
43
  # @return [Array<Rack::Middleware>]
38
- def use(middleware, *options)
39
- middlewares << Rack::Middleware.new(middleware, options)
44
+ def use(*spec)
45
+ middlewares.push(*Rack::MiddlewareSpecification.call(spec))
40
46
  end
41
47
 
42
48
  # Creates and adds a plug to the stack.
43
49
  #
50
+ # The spec can be given as a {Plug::Spec} or as a block, which
51
+ # is captured into a {Proc} (one of the options for a
52
+ # {Plug::Spec}.
53
+ #
44
54
  # @param name [Plug::Name[]]
45
- # @param with [Plug::Spec[]]
55
+ # @param spec [Plug::Spec[]]
56
+ # @param block_spec [Proc]
46
57
  #
47
58
  # @return [Array<Plug>]
48
- def plug(name, with: nil)
49
- plugs << Plug.new(name, with)
59
+ def plug(name, spec = nil, &block_spec)
60
+ plugs << Plug.new(name, spec || block_spec)
50
61
  end
51
62
  end
52
63
  end
@@ -4,6 +4,7 @@ require 'web_pipe/conn'
4
4
  require 'web_pipe/app'
5
5
  require 'web_pipe/plug'
6
6
  require 'web_pipe/rack/app_with_middlewares'
7
+ require 'web_pipe/conn_support/composition'
7
8
 
8
9
  module WebPipe
9
10
  module DSL
@@ -35,14 +36,17 @@ module WebPipe
35
36
  type: Injections
36
37
  end
37
38
 
38
- # @return [Rack::AppWithMiddlewares]
39
+ # @return [Rack::AppWithMiddlewares[]]
39
40
  attr_reader :rack_app
40
41
 
42
+ # @return [ConnSupport::Composition::Operation[]]
43
+ attr_reader :operations
44
+
41
45
  def initialize(*args)
42
46
  super
43
47
  middlewares = self.class.middlewares
44
48
  container = self.class.container
45
- operations = Plug.inject_and_resolve(self.class.plugs, injections, container, self)
49
+ @operations = Plug.inject_and_resolve(self.class.plugs, injections, container, self)
46
50
  app = App.new(operations)
47
51
  @rack_app = Rack::AppWithMiddlewares.new(middlewares, app)
48
52
  end
@@ -55,6 +59,44 @@ module WebPipe
55
59
  def call(env)
56
60
  rack_app.call(env)
57
61
  end
62
+
63
+ # Proc for the composition of all operations.
64
+ #
65
+ # This can be used to plug a {WebPipe} itself as an operation.
66
+ #
67
+ # @example
68
+ # class HtmlApp
69
+ # include WebPipe
70
+ #
71
+ # plug :html
72
+ #
73
+ # private
74
+ #
75
+ # def html(conn)
76
+ # conn.add_response_header('Content-Type', 'text/html')
77
+ # end
78
+ # end
79
+ #
80
+ # class App
81
+ # include WebPipe
82
+ #
83
+ # plug :html, &HtmlApp.new
84
+ # plug :body
85
+ #
86
+ # private
87
+ #
88
+ # def body(conn)
89
+ # conn.set_response_body('Hello, world!')
90
+ # end
91
+ # end
92
+ #
93
+ # @see ConnSupport::Composition
94
+ def to_proc
95
+ ConnSupport::Composition.
96
+ new(operations).
97
+ method(:call).
98
+ to_proc
99
+ end
58
100
  end
59
101
  end
60
102
  end
@@ -38,7 +38,7 @@ module WebPipe
38
38
  #
39
39
  # Container = { 'views.say_hello' => SayHelloView.new }.freeze
40
40
  #
41
- # plug :container, with: WebPipe::Plugs::Container[Container]
41
+ # plug :container, WebPipe::Plugs::Container[Container]
42
42
  # plug :render
43
43
  #
44
44
  # def render(conn)
@@ -17,7 +17,7 @@ module WebPipe
17
17
  #
18
18
  # ViewContext = (conn) -> { { current_path: conn.full_path } }
19
19
  #
20
- # plug :view_context, with: WebPipe::Plugs::ViewContext[ViewContext]
20
+ # plug :view_context, WebPipe::Plugs::ViewContext[ViewContext]
21
21
  # plug :render
22
22
  #
23
23
  # def render
data/lib/web_pipe/plug.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'dry/initializer'
2
2
  require 'web_pipe/types'
3
- require 'web_pipe/app'
3
+ require 'web_pipe/conn_support/composition'
4
4
 
5
5
  module WebPipe
6
6
  # A plug is a specification to resolve a callable object.
@@ -25,8 +25,8 @@ module WebPipe
25
25
  super(
26
26
  <<~eos
27
27
  Plug with name +#{name}+ is invalid. It must be something
28
- callable, an instance method when `with:` is not given, or
29
- something callable registered in the container."
28
+ callable, an instance method when no operation is given,
29
+ or something callable registered in the container."
30
30
  eos
31
31
  )
32
32
  end
@@ -35,9 +35,13 @@ module WebPipe
35
35
  # Type for the name of a plug.
36
36
  Name = Types::Strict::Symbol.constructor(&:to_sym)
37
37
 
38
- # Type for the spec to resolve and {App::Operation} on a
39
- # {Conn} used by {Plug}.
40
- Spec = App::Operation | Types.Constant(nil) | Types::Strict::String | Types::Strict::Symbol
38
+ # Type for the spec to resolve and
39
+ # {ConnSupport::Composition::Operation} on a {Conn} used by
40
+ # {Plug}.
41
+ Spec = ConnSupport::Composition::Operation |
42
+ Types.Constant(nil) |
43
+ Types::Strict::String |
44
+ Types::Strict::Symbol
41
45
 
42
46
  # Type for an instance of self.
43
47
  Instance = Types.Instance(self)
@@ -68,7 +72,7 @@ module WebPipe
68
72
  # @param container [Types::Container[]]
69
73
  # @param object [Object]
70
74
  #
71
- # @return [Operation[]]
75
+ # @return [ConnSupport::Composition::Operation[]]
72
76
  # @raise [InvalidPlugError] When nothing callable is resolved.
73
77
  def call(container, pipe)
74
78
  if spec.respond_to?(:call)
@@ -89,7 +93,7 @@ module WebPipe
89
93
  # @container container [Types::Container[]]
90
94
  # @object [Object]
91
95
  #
92
- # @return [Array<Operation[]>]
96
+ # @return [Array<ConnSupport::Composition::Operation[]>]
93
97
  def self.inject_and_resolve(plugs, injections, container, object)
94
98
  plugs.map do |plug|
95
99
  if injections.has_key?(plug.name)
@@ -13,7 +13,7 @@ module WebPipe
13
13
  #
14
14
  # Cont = { name: SomeDependency.new }.freeze
15
15
  #
16
- # plug :container, with: WebPipe::Plugs::Container[Cont]
16
+ # plug :container, WebPipe::Plugs::Container[Cont]
17
17
  # plug :resolve
18
18
  #
19
19
  # private
@@ -10,7 +10,7 @@ module WebPipe
10
10
  # class App
11
11
  # include WebPipe
12
12
  #
13
- # plug :html, with: WebPipe::Plugs::ContentType['text/html']
13
+ # plug :html, WebPipe::Plugs::ContentType['text/html']
14
14
  # end
15
15
  module ContentType
16
16
  # Content-Type header
@@ -24,7 +24,7 @@ module WebPipe
24
24
 
25
25
  include Dry::Initializer.define -> do
26
26
  param :rack_middlewares,
27
- type: Types.Array(Middleware::Instance)
27
+ type: Types.Array(Middleware)
28
28
 
29
29
  param :app, type: App
30
30
  end
@@ -51,7 +51,7 @@ module WebPipe
51
51
  def build_rack_app(rack_middlewares, app)
52
52
  ::Rack::Builder.new.tap do |b|
53
53
  rack_middlewares.each do |middleware|
54
- b.use(middleware.middleware, *middleware.middleware_options)
54
+ b.use(middleware.middleware, *middleware.options)
55
55
  end
56
56
  b.run(app)
57
57
  end
@@ -1,14 +1,14 @@
1
1
  require 'dry/initializer'
2
2
  require 'web_pipe/types'
3
+ require 'dry/struct'
3
4
 
4
5
  module WebPipe
5
6
  module Rack
6
7
  # Simple data structure to represent a rack middleware class with
7
8
  # its initialization options.
8
- class Middleware
9
- # Type for an instance of self.
10
- Instance = Types.Instance(self)
11
-
9
+ #
10
+ # @api private
11
+ class Middleware < Dry::Struct
12
12
  # Type for a rack middleware class.
13
13
  MiddlewareClass = Types.Instance(Class)
14
14
 
@@ -17,17 +17,11 @@ module WebPipe
17
17
 
18
18
  # @!attribute [r] middleware
19
19
  # @return [MiddlewareClass[]] Rack middleware
20
+ attribute :middleware, MiddlewareClass
20
21
 
21
22
  # @!attribute [r] options
22
- # @return [Options[]]
23
- # Options to initialize the rack middleware
24
-
25
-
26
- include Dry::Initializer.define -> do
27
- param :middleware, type: MiddlewareClass
28
-
29
- param :middleware_options, type: Options
30
- end
23
+ # @return [Options[]] Options to initialize the rack middleware
24
+ attribute :options, Options
31
25
  end
32
26
  end
33
27
  end
@@ -0,0 +1,33 @@
1
+ require 'web_pipe/rack/middleware'
2
+ require 'web_pipe/types'
3
+
4
+ module WebPipe
5
+ module Rack
6
+ # Specification on how to resolve {Rack::Middleware}'s.
7
+ #
8
+ # Rack middlewares can be specified in two ways:
9
+ #
10
+ # - As an array where fist element is a rack middleware class
11
+ # while the rest of elements are its initialization options.
12
+ # - A single element array where it is a class including
13
+ # {WebPipe}. This specifies all {Rack::Middlewares} configured
14
+ # for that {WebPipe}.
15
+ #
16
+ # @api private
17
+ module MiddlewareSpecification
18
+ # Resolves {Rack::Middlewares} from given specification.
19
+ #
20
+ # @param spec [Array]
21
+ # @return [Array<Rack::Middleware>]
22
+ def self.call(spec)
23
+ klass = spec[0]
24
+ options = spec[1..-1] || Types::EMPTY_ARRAY
25
+ if klass.included_modules.include?(WebPipe)
26
+ klass.middlewares
27
+ elsif klass.is_a?(Class)
28
+ [Middleware.new(middleware: klass, options: options)]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module WebPipe
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: web_pipe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc Busqué
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-05 00:00:00.000000000 Z
11
+ date: 2019-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -221,6 +221,7 @@ files:
221
221
  - lib/web_pipe/app.rb
222
222
  - lib/web_pipe/conn.rb
223
223
  - lib/web_pipe/conn_support/builder.rb
224
+ - lib/web_pipe/conn_support/composition.rb
224
225
  - lib/web_pipe/conn_support/errors.rb
225
226
  - lib/web_pipe/conn_support/headers.rb
226
227
  - lib/web_pipe/conn_support/types.rb
@@ -236,6 +237,7 @@ files:
236
237
  - lib/web_pipe/plugs/content_type.rb
237
238
  - lib/web_pipe/rack/app_with_middlewares.rb
238
239
  - lib/web_pipe/rack/middleware.rb
240
+ - lib/web_pipe/rack/middleware_specification.rb
239
241
  - lib/web_pipe/types.rb
240
242
  - lib/web_pipe/version.rb
241
243
  - web_pipe.gemspec