web_pipe 0.3.0 → 0.4.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: 2f0e9b6d0efd9e7280bd1628237d3219f1307a28d63ec0d8f0e63366ce93e166
4
- data.tar.gz: 407269e3f023e97a84855fe315ca3558ccf49a2b0cb78674336274fb1ae2c800
3
+ metadata.gz: 846bd7956d65605edaad299346280d7ae4b426d8cf4160e47ebac7375135b4e7
4
+ data.tar.gz: 41923761b8227c956f6b554bf8dc49fdc6323dc97e08399b5f8b4bc043552fdf
5
5
  SHA512:
6
- metadata.gz: a2bf1652e9c88e4dcd708b95fc573d1daffeea2f3d56fd908598eb447c1819912c2ac53a35eecf0a5315d4e1195b9c412c34e5a58fb70cf3c5cfa36da602aa45
7
- data.tar.gz: 386e1da635847bc21ab2eee5203babda8020fb89f8a11be51e2718bf844e34405ccdb60f4e537d3d3e7afb3d62264f32add6be94711420f490e2f02c3420c9be
6
+ metadata.gz: b2de9d0a5e7f172e9c42fcf2e97b6ff22046552670c9cf096d270438aab9d572fb4bd915fba282e578f48b39c412ba867d8359881426073b936c9734b3e8a693
7
+ data.tar.gz: b72848b3ad1e98f18dea9da6b8dc19eef99c61ffb3f71115fd041b1fe699b5ca22bf0395f80e4fd16621d1b72ba8970a1555577126f148ffadf4768ed4a417b4
@@ -4,6 +4,57 @@ 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.4.0] - 2019-07-17
8
+ ### Added
9
+ - **BREAKING**: Middlewares have to be named when used ([11](https://github.com/waiting-for-dev/web_pipe/pull/11)):
10
+
11
+ ```ruby
12
+ use :cookies, Rack::Session:Cookie, secret: 'my_secret', key: 'foo'
13
+ ```
14
+
15
+ - **BREAKING**: Middlewares have to be initialized when composed ([11](https://github.com/waiting-for-dev/web_pipe/pull/11)):
16
+
17
+ ```ruby
18
+ use :pipe, PipeWithMiddlewares.new
19
+ ```
20
+
21
+ - **BREAKING**: The array of injected plugs is now scoped within a `plugs:` kwarg ([11](https://github.com/waiting-for-dev/web_pipe/pull/11)):
22
+
23
+ ```ruby
24
+ App.new(plugs: { nothing: ->(conn) { conn } })
25
+ ```
26
+
27
+ - Middlewares can be injected ([11](https://github.com/waiting-for-dev/web_pipe/pull/11)):
28
+
29
+ ```ruby
30
+ App.new(middlewares: { cache: [MyMiddleware, my_options] })
31
+ ```
32
+
33
+ - DSL helper method `compose` to add middlewares and plugs in order and in a single shot ([12](https://github.com/waiting-for-dev/web_pipe/pull/11)):
34
+
35
+ ```ruby
36
+ class App
37
+ include WebPipe.(container: Container)
38
+
39
+ use :first, FirstMiddleware
40
+
41
+ plug :first_plug, 'first_plug'
42
+ end
43
+
44
+ class AnotherApp
45
+ include WebPipe.(container: Container)
46
+
47
+ compose App
48
+ # Equivalent to:
49
+ # use App.new
50
+ # plug &App.new
51
+
52
+ use :second, SecondMiddleware
53
+
54
+ plug :second_plug, 'second_plug'
55
+ end
56
+ ```
57
+
7
58
  ## [0.3.0] - 2019-07-12
8
59
  ### Added
9
60
  - **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)):
@@ -51,7 +102,7 @@ class App
51
102
  end
52
103
  ```
53
104
 
54
- - WebPipe's middlewares can be composed into another WebPipe class, also through `:use`:
105
+ - WebPipe's middlewares can be composed into another WebPipe class, also through `:use` ([10](https://github.com/waiting-for-dev/web_pipe/pull/10)):
55
106
 
56
107
  ```ruby
57
108
  class HtmlApp
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- web_pipe (0.2.0)
4
+ web_pipe (0.3.0)
5
5
  dry-initializer (~> 3.0)
6
6
  dry-monads (~> 1.2)
7
7
  dry-struct (~> 1.0)
data/README.md CHANGED
@@ -255,8 +255,9 @@ class App
255
255
  plug :hello, ->(conn) { conn.set_response_body('Hello') }
256
256
  end
257
257
 
258
- run App.new(
259
- hello: ->(conn) { conn.set_response_body('Injected') }
258
+ run App.new(plugs: {
259
+ hello: ->(conn) { conn.set_response_body('Injected') }
260
+ }
260
261
  )
261
262
  ```
262
263
 
@@ -272,8 +273,8 @@ plugs:
272
273
  class App
273
274
  include WebPipe
274
275
 
275
- use Middleware1
276
- use Middleware2, option_1: value_1
276
+ use :middleware_1, Middleware1
277
+ use :middleware_1, Middleware2, option_1: value_1
277
278
 
278
279
  plug :hello, ->(conn) { conn }
279
280
  end
@@ -286,12 +287,20 @@ class. Extending from previous example:
286
287
  class App2
287
288
  include WebPipe
288
289
 
289
- use App # it will also use Middleware1 and Middleware2
290
+ use :app, App.new # it will also use Middleware1 and Middleware2
290
291
 
291
292
  plug :hello, ->(conn) { conn }
292
293
  end
293
294
  ```
294
295
 
296
+ Middlewares can also be injected on initialization:
297
+
298
+ ```ruby
299
+ App.new(middlewares: {
300
+ middleware_1: [AnotherMiddleware, options]
301
+ })
302
+ ```
303
+
295
304
  ### Standalone usage
296
305
 
297
306
  If you prefer, you can use the application builder without the
@@ -18,7 +18,7 @@ module WebPipe
18
18
  # @api private
19
19
  class ClassContext < Module
20
20
  # Methods to be imported from the {DSLContext}.
21
- DSL_METHODS = %i[middlewares use plugs plug].freeze
21
+ DSL_METHODS = %i[middleware_specifications use plugs plug compose].freeze
22
22
 
23
23
  # @!attribute [r] container
24
24
  # @return [Types::Container[]]
@@ -1,7 +1,6 @@
1
1
  require 'dry/initializer'
2
2
  require 'web_pipe/types'
3
3
  require 'web_pipe/plug'
4
- require 'web_pipe/rack/middleware'
5
4
  require 'web_pipe/rack/middleware_specification'
6
5
 
7
6
  module WebPipe
@@ -13,36 +12,37 @@ module WebPipe
13
12
  #
14
13
  # @api private
15
14
  class DSLContext
16
- # @!attribute middlewares
17
- # @return [Array<Rack::Middleware>]
15
+ # @!attribute middleware_specifications
16
+ # @return [Array<Rack::MiddlewareSpecifications>]
18
17
 
19
18
  # @!attribute plugs
20
19
  # @return [Array<Plug>]
21
20
 
22
21
 
23
22
  include Dry::Initializer.define -> do
24
- param :middlewares,
25
- type: Types.Array(Rack::Middleware)
23
+ param :middleware_specifications,
24
+ type: Types.Array(Rack::MiddlewareSpecification)
26
25
 
27
26
  param :plugs,
28
27
  type: Types.Array(Plug::Instance)
29
28
  end
30
29
 
31
- # Creates and add rack middlewares to the stack.
30
+ # Creates and add rack middleware specifications to the stack.
32
31
  #
33
32
  # The spec can be given in two forms:
34
33
  #
35
34
  # - As one or two arguments, first one being a
36
- # {::Rack::Middleware} class and second one optionally its
35
+ # rack middleware class and second one optionally its
37
36
  # initialization options.
38
- # - As a {WebPipe} class, in which case all its rack middlewares
39
- # will be added to the stack in order.
37
+ # - As a {WebPipe} class instance, in which case all its rack
38
+ # middlewares will be considered.
40
39
  #
40
+ # @param name [Rack::MiddlewareSpecification::Name[]]
41
41
  # @param spec [Rack::MiddlewareSpecification::Spec[]]
42
42
  #
43
43
  # @return [Array<Rack::Middleware>]
44
- def use(*spec)
45
- middlewares.push(*Rack::MiddlewareSpecification.call(spec))
44
+ def use(name, *spec)
45
+ middleware_specifications << Rack::MiddlewareSpecification.new(name, spec)
46
46
  end
47
47
 
48
48
  # Creates and adds a plug to the stack.
@@ -59,6 +59,16 @@ module WebPipe
59
59
  def plug(name, spec = nil, &block_spec)
60
60
  plugs << Plug.new(name, spec || block_spec)
61
61
  end
62
+
63
+ # Adds middlewares and plugs from a WebPipe to respective
64
+ # stacks.
65
+ #
66
+ # @param name [Plug::Name[], Middleware::Name[]]
67
+ # @param spec [WebPipe]
68
+ def compose(name, spec)
69
+ use(name, spec)
70
+ plug(name, &spec)
71
+ end
62
72
  end
63
73
  end
64
74
  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/rack/middleware_specification'
7
8
  require 'web_pipe/conn_support/composition'
8
9
 
9
10
  module WebPipe
@@ -12,8 +13,8 @@ module WebPipe
12
13
  #
13
14
  # It is from here that you get the rack application you can route
14
15
  # to. The initialization phase gives you the chance to inject any
15
- # of the plugs, while the instance you get has the `#call` method
16
- # expected by rack.
16
+ # of the plugs or middlewares, while the instance you get has the
17
+ # `#call` method expected by rack.
17
18
  #
18
19
  # The pipe state can be accessed through the pipe class, which
19
20
  # has been configured through {ClassContext}.
@@ -21,13 +22,20 @@ module WebPipe
21
22
  # @api private
22
23
  module InstanceMethods
23
24
  # No injections at all.
24
- EMPTY_INJECTIONS = Types::EMPTY_HASH
25
+ EMPTY_INJECTIONS = {
26
+ plugs: Types::EMPTY_HASH,
27
+ middlewares: Types::EMPTY_HASH
28
+ }.freeze
25
29
 
26
- # Type for how plugs should be injected.
27
- Injections = Types::Strict::Hash.map(Plug::Name, Plug::Spec)
30
+ # Type for how plugs and middlewares should be injected.
31
+ Injections = Types::Strict::Hash.schema(
32
+ plugs: Plug::Injections,
33
+ middlewares: Rack::MiddlewareSpecification::Injections
34
+ )
28
35
 
29
36
  # @!attribute [r] injections [Injections[]]
30
- # Injected plugs that allow overriding what has been configured.
37
+ # Injected plugs and middlewares that allow overriding what
38
+ # has been configured.
31
39
 
32
40
 
33
41
  include Dry::Initializer.define -> do
@@ -42,11 +50,18 @@ module WebPipe
42
50
  # @return [ConnSupport::Composition::Operation[]]
43
51
  attr_reader :operations
44
52
 
53
+ # @return [Array<Rack::Middlewares>]
54
+ attr_reader :middlewares
55
+
45
56
  def initialize(*args)
46
57
  super
47
- middlewares = self.class.middlewares
48
58
  container = self.class.container
49
- @operations = Plug.inject_and_resolve(self.class.plugs, injections, container, self)
59
+ @middlewares = Rack::MiddlewareSpecification.inject_and_resolve(
60
+ self.class.middleware_specifications, injections[:middlewares]
61
+ )
62
+ @operations = Plug.inject_and_resolve(
63
+ self.class.plugs, injections[:plugs], container, self
64
+ )
50
65
  app = App.new(operations)
51
66
  @rack_app = Rack::AppWithMiddlewares.new(middlewares, app)
52
67
  end
@@ -46,6 +46,13 @@ module WebPipe
46
46
  # Type for an instance of self.
47
47
  Instance = Types.Instance(self)
48
48
 
49
+ # Schema expected to inject plugs.
50
+ #
51
+ # @see #inject_and_resolve
52
+ Injections = Types::Strict::Hash.map(
53
+ Plug::Name, Plug::Spec
54
+ ).default(Types::EMPTY_HASH)
55
+
49
56
  # @!attribute [r] name
50
57
  # @return [Name[]]
51
58
 
@@ -89,7 +96,7 @@ module WebPipe
89
96
  # Change `plugs` spec's present in `injections` and resolves.
90
97
  #
91
98
  # @param plugs [Array<Plug>]
92
- # @param injections [InstanceMethods::Injections[]]
99
+ # @param injections [InstanceMethods::PlugInjections[]]
93
100
  # @container container [Types::Container[]]
94
101
  # @object [Object]
95
102
  #
@@ -9,25 +9,75 @@ module WebPipe
9
9
  #
10
10
  # - As an array where fist element is a rack middleware class
11
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
12
+ # - A single element array where it is an instance of a class
13
+ # including {WebPipe}. This specifies all {Rack::Middlewares}
14
14
  # for that {WebPipe}.
15
15
  #
16
16
  # @api private
17
- module MiddlewareSpecification
17
+ class MiddlewareSpecification
18
+ # Type for the name given to a middleware.
19
+ Name = Types::Strict::Symbol.constructor(&:to_sym)
20
+
21
+ # Poor type for the specification to resolve a rack middleware.
22
+ Spec = Types::Strict::Array
23
+
24
+ # Schema expected to inject middleware specifications.
25
+ #
26
+ # @see #inject_and_resolve
27
+ Injections = Types::Strict::Hash.map(
28
+ Rack::MiddlewareSpecification::Name, Rack::MiddlewareSpecification::Spec
29
+ ).default(Types::EMPTY_HASH)
30
+
31
+ # @!attribute [r] name
32
+ # @return [Name[]]
33
+
34
+ # @!attribute [r] spec
35
+ # @return [Spec[]]
36
+
37
+
38
+ include Dry::Initializer.define -> do
39
+ param :name, Name
40
+
41
+ param :spec, Spec
42
+ end
43
+
44
+ # Change spec's present in `injections` and resolves.
45
+ #
46
+ # @param middleware_specifications [Array<MiddlewareSpecification>]
47
+ # @param injections [Injections[]]
48
+ #
49
+ # @return [Array<Rack::Middleware>]
50
+ def self.inject_and_resolve(middleware_specifications, injections)
51
+ middleware_specifications.map do |spec|
52
+ if injections.has_key?(spec.name)
53
+ spec.with(injections[spec.name])
54
+ else
55
+ spec
56
+ end.()
57
+ end.flatten
58
+ end
59
+
18
60
  # Resolves {Rack::Middlewares} from given specification.
19
61
  #
20
- # @param spec [Array]
21
62
  # @return [Array<Rack::Middleware>]
22
- def self.call(spec)
63
+ def call
23
64
  klass = spec[0]
24
65
  options = spec[1..-1] || Types::EMPTY_ARRAY
25
- if klass.included_modules.include?(WebPipe)
66
+ if klass.is_a?(WebPipe)
26
67
  klass.middlewares
27
68
  elsif klass.is_a?(Class)
28
69
  [Middleware.new(middleware: klass, options: options)]
29
70
  end
30
71
  end
72
+
73
+ # Returns new instance with {#spec} replaced.
74
+ #
75
+ # @param new_spec [Spec[]]
76
+ #
77
+ # @return [MiddlewareSpecification]
78
+ def with(new_spec)
79
+ self.class.new(name, new_spec)
80
+ end
31
81
  end
32
82
  end
33
83
  end
@@ -1,3 +1,3 @@
1
1
  module WebPipe
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.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.3.0
4
+ version: 0.4.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-12 00:00:00.000000000 Z
11
+ date: 2019-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack