web_pipe 0.3.0 → 0.4.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 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