web_pipe 0.2.0 → 0.3.0
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/CHANGELOG.md +65 -1
- data/Gemfile.lock +1 -1
- data/README.md +52 -7
- data/lib/web_pipe/app.rb +9 -47
- data/lib/web_pipe/conn_support/composition.rb +89 -0
- data/lib/web_pipe/dsl/class_context.rb +2 -2
- data/lib/web_pipe/dsl/dsl_context.rb +22 -11
- data/lib/web_pipe/dsl/instance_methods.rb +44 -2
- data/lib/web_pipe/extensions/dry_view/dry_view.rb +1 -1
- data/lib/web_pipe/extensions/dry_view/plugs/view_context.rb +1 -1
- data/lib/web_pipe/plug.rb +12 -8
- data/lib/web_pipe/plugs/container.rb +1 -1
- data/lib/web_pipe/plugs/content_type.rb +1 -1
- data/lib/web_pipe/rack/app_with_middlewares.rb +2 -2
- data/lib/web_pipe/rack/middleware.rb +7 -13
- data/lib/web_pipe/rack/middleware_specification.rb +33 -0
- data/lib/web_pipe/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f0e9b6d0efd9e7280bd1628237d3219f1307a28d63ec0d8f0e63366ce93e166
|
4
|
+
data.tar.gz: 407269e3f023e97a84855fe315ca3558ccf49a2b0cb78674336274fb1ae2c800
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
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
|
184
|
-
|
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,
|
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
|
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,
|
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,
|
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,
|
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 '
|
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(
|
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
|
-
|
78
|
-
ConnSupport::Builder.(env)
|
79
|
-
)
|
57
|
+
ConnSupport::Builder.(env)
|
80
58
|
end
|
81
59
|
|
82
60
|
def apply_operations(conn)
|
83
|
-
operations.
|
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
|
-
|
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
|
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
|
31
|
+
# Creates and add rack middlewares to the stack.
|
31
32
|
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
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(
|
39
|
-
middlewares
|
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
|
55
|
+
# @param spec [Plug::Spec[]]
|
56
|
+
# @param block_spec [Proc]
|
46
57
|
#
|
47
58
|
# @return [Array<Plug>]
|
48
|
-
def plug(name,
|
49
|
-
plugs << Plug.new(name,
|
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
|
@@ -17,7 +17,7 @@ module WebPipe
|
|
17
17
|
#
|
18
18
|
# ViewContext = (conn) -> { { current_path: conn.full_path } }
|
19
19
|
#
|
20
|
-
# plug :view_context,
|
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/
|
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
|
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
|
39
|
-
# {Conn} used by
|
40
|
-
|
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)
|
@@ -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
|
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.
|
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
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
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
|
data/lib/web_pipe/version.rb
CHANGED
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.
|
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-
|
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
|