web_pipe 0.6.1 → 0.7.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: 2e30728a57f73a570c6345efd53dc22d32006a3b6bd6eb666c15b3f079fd3f83
4
- data.tar.gz: e85225c017e8ee7c23a65b7d5cda617cabc403d052c2196087542fc56c3d3636
3
+ metadata.gz: ce3123c1c702c02eaab09f4cb56209b512499d913fddaa55a95307e779748e15
4
+ data.tar.gz: f8fdcce1e652e37b719e3a621b19f9762ec3a47b74ff39ab4695f30f5ea0722c
5
5
  SHA512:
6
- metadata.gz: 6b24b6829b5657403ce5ef161fc4c0fe265a091195fc0de5c878751aaf88041e169ad1628e448fbb6dd27412f3564b50e087cad782fab4c9ad39b6a0acbf4e18
7
- data.tar.gz: a60f0297742a97ea66a2cf0b8629319a05881921c2589b6c493ded751dd27bfb29e64284e1048cb39981ea756a575e5b955a7f8a3efd6965c19ba395c3534353
6
+ metadata.gz: 117619501c7d97297266b8ac7cd89a6a2440c1cca7a1791da00e2b2a1935e790e4cd0d1877ea9ec5c9208cc9bac6ed8e07b981b04708102d67ca2760d1ed95e6
7
+ data.tar.gz: '08a391660d75a830e5e9e0bda97b62a4b299f5f543a86959d5fe86c8dda823b11438640d253400ec8a742a009c2a312cdeeb6a95c7a4cb4af4711589e5075fdd'
@@ -4,6 +4,33 @@ 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.7.0] - 2019-08-27
8
+ ### Added
9
+ - **BREAKING**. `Conn#config` instead of `Conn#bag` for extension configuration.
10
+ [[#29]](https://github.com/waiting-for-dev/web_pipe/pull/29)
11
+
12
+ - **BREAKING**. `:params` extension extracted from `:url` extension.
13
+ [[#30]](https://github.com/waiting-for-dev/web_pipe/pull/30)
14
+
15
+ - **BREAKING**. Router params are extracted as a param transformation.
16
+ [[#30]](https://github.com/waiting-for-dev/web_pipe/pull/30)
17
+
18
+ - **BREAKING**. Plugs now respond to `.call` instead of `.[]`.
19
+ [[#31]](https://github.com/waiting-for-dev/web_pipe/pull/31)
20
+
21
+ - **BREAKING**. `:dry-schema` extension has not a default handler.
22
+ [[#32]](https://github.com/waiting-for-dev/web_pipe/pull/32)
23
+
24
+ - **BREAKING**. `:dry-schema` extension stores output in `#config`.
25
+ [[#32]](https://github.com/waiting-for-dev/web_pipe/pull/32)
26
+
27
+ - Integration with `transproc` gem to provide any number of params
28
+ transformations.
29
+ [[#30]](https://github.com/waiting-for-dev/web_pipe/pull/30)
30
+
31
+ - `:dry-schema` extension automatically loads `:params` extension.
32
+ [[#32]](https://github.com/waiting-for-dev/web_pipe/pull/32)
33
+
7
34
  ## [0.6.1] - 2019-08-02
8
35
  ### Fixed
9
36
  - Fixed support for ruby 2.4.
@@ -0,0 +1 @@
1
+ theme: jekyll-theme-slate
@@ -23,27 +23,32 @@ module WebPipe
23
23
  register_extension :dry_schema do
24
24
  require 'web_pipe/extensions/dry_schema/dry_schema'
25
25
  require 'web_pipe/extensions/dry_schema/plugs/sanitize_params'
26
- require 'web_pipe/extensions/dry_schema/plugs/param_sanitization_handler'
27
26
  end
28
27
 
29
28
  register_extension :dry_view do
30
29
  require 'web_pipe/extensions/dry_view/dry_view'
31
- require 'web_pipe/extensions/dry_view/plugs/view_context'
32
30
  end
33
31
 
34
32
  register_extension :container do
35
33
  require 'web_pipe/extensions/container/container'
36
- require 'web_pipe/extensions/container/plugs/container'
37
34
  end
38
35
 
39
36
  register_extension :flash do
40
37
  require 'web_pipe/extensions/flash/flash'
41
38
  end
42
39
 
40
+ register_extension :router_params do
41
+ require 'web_pipe/extensions/router_params/router_params'
42
+ end
43
+
43
44
  register_extension :redirect do
44
45
  require 'web_pipe/extensions/redirect/redirect'
45
46
  end
46
47
 
48
+ register_extension :params do
49
+ require 'web_pipe/extensions/params/params'
50
+ end
51
+
47
52
  register_extension :session do
48
53
  require 'web_pipe/extensions/session/session'
49
54
  end
@@ -210,6 +210,18 @@ module WebPipe
210
210
  # @return [Bag[]]
211
211
  attribute :bag, Bag
212
212
 
213
+ # @!attribute [r] config
214
+ #
215
+ # Instance level configuration.
216
+ #
217
+ # It is a hash where anything can be stored. Keys must be symbols.
218
+ #
219
+ # The idea of it is for extensions to have somewhere to store user
220
+ # provided values they may need at some point.
221
+ #
222
+ # @return [Bag[]]
223
+ attribute :config, Bag
224
+
213
225
  # Sets response status code.
214
226
  #
215
227
  # @param code [StatusCode]
@@ -320,6 +332,34 @@ module WebPipe
320
332
  )
321
333
  end
322
334
 
335
+ # Reads an item from {#config}.
336
+ #
337
+ # @param key [Symbol]
338
+ #
339
+ # @return [Object]
340
+ #
341
+ # @raise ConnSupport::KeyNotFoundInConfigError when key is not
342
+ # present in {#config}.
343
+ def fetch_config(key, default = Types::Undefined)
344
+ return config.fetch(key, default) unless default == Types::Undefined
345
+
346
+ config.fetch(key) { raise ConnSupport::KeyNotFoundInConfigError.new(key) }
347
+ end
348
+
349
+ # Writes an item to {#config}.
350
+ #
351
+ # If it already exists, it is overwritten.
352
+ #
353
+ # @param key [Symbol]
354
+ # @param value [Object]
355
+ #
356
+ # @return [Conn]
357
+ def add_config(key, value)
358
+ new(
359
+ config: config.merge(key => value)
360
+ )
361
+ end
362
+
323
363
  # Builds response in the way rack expects.
324
364
  #
325
365
  # It is useful to finish a rack application built with a
@@ -1,9 +1,6 @@
1
1
  require 'dry/monads/result'
2
2
  require 'web_pipe/types'
3
3
  require 'web_pipe/conn'
4
- require 'dry/monads/result/extensions/either'
5
-
6
- Dry::Monads::Result.load_extensions(:either)
7
4
 
8
5
  module WebPipe
9
6
  module ConnSupport
@@ -1,7 +1,7 @@
1
1
  module WebPipe
2
2
  module ConnSupport
3
- # Error raised when trying to fetch an entry in {Conn}'s bag for
4
- # an unknown key.
3
+ # Error raised when trying to fetch an entry in {Conn#bag} for an
4
+ # unknown key.
5
5
  class KeyNotFoundInBagError < KeyError
6
6
  # @param key [Any] Key not found in the bag
7
7
  def initialize(key)
@@ -13,6 +13,19 @@ module WebPipe
13
13
  end
14
14
  end
15
15
 
16
+ # Error raised when trying to fetch an entry in {Conn#config} for
17
+ # an unknown key.
18
+ class KeyNotFoundInConfigError < KeyError
19
+ # @param key [Any] Key not found in config
20
+ def initialize(key)
21
+ super(
22
+ <<~eos
23
+ Config does not contain a key with name +#{key}+.
24
+ eos
25
+ )
26
+ end
27
+ end
28
+
16
29
  # Error raised when trying to use a conn's feature which requires
17
30
  # a rack middleware which is not present
18
31
  class MissingMiddlewareError < RuntimeError
@@ -1,10 +1,8 @@
1
1
  require 'web_pipe'
2
2
 
3
3
  module WebPipe
4
- # Extension adding a `#container` method to fetch bag's `:container`
5
- # key.
6
- #
7
- # Usually, the container is set with {WebPipe::Plugs::Container}.
4
+ # Extension adding a `#container` method which returns {Conn#config}
5
+ # `:container` key.
8
6
  #
9
7
  # @example
10
8
  # require 'web_pipe'
@@ -14,15 +12,15 @@ module WebPipe
14
12
  # class App
15
13
  # include WebPipe
16
14
  #
17
- # plug :container, WebPipe::Plugs::Container[MyContainer]
15
+ # plug :container, ->(conn) { conn.add_config(:container, MyContainer) }
18
16
  # plug :render, ->(conn) { conn.set_response_body(conn.container['view']) }
19
17
  # end
20
18
  module Container
21
- # Returns bag `:container` value
19
+ # Returns {Conn#config} `:container` value
22
20
  #
23
21
  # @return [Any]
24
22
  def container
25
- fetch(:container)
23
+ fetch_config(:container)
26
24
  end
27
25
  end
28
26
 
@@ -1,5 +1,7 @@
1
1
  require 'web_pipe'
2
2
 
3
+ WebPipe.load_extensions(:params)
4
+
3
5
  module WebPipe
4
6
  # Integration with `dry-schema` validation library.
5
7
  #
@@ -8,11 +10,12 @@ module WebPipe
8
10
  #
9
11
  # On its own, the library just provides with a
10
12
  # `Conn#sanitized_params` method, which will return what is set into
11
- # bag's `:sanitized_params` key.
13
+ # config's `:sanitized_params` key.
12
14
  #
13
- # This key in the bag is what will be populated by `SanitizeParams`
14
- # plug, which accepts a `dry-validation` schema that will be applied
15
- # to `Conn#params`:
15
+ # This key in config is what will be populated by `SanitizeParams` plug. It
16
+ # takes as arguments the `dry-schema` schema that will be applied to
17
+ # `Conn#params` and an error handler taking `Conn` instance and the validation
18
+ # result:
16
19
  #
17
20
  # @example
18
21
  # require 'web_pipe'
@@ -26,43 +29,32 @@ module WebPipe
26
29
  # required(:name).filled(:string)
27
30
  # end
28
31
  #
29
- # plug :sanitize_params, WebPipe::Plugs::SanitizeParams[Schema]
32
+ # plug :sanitize_params, WebPipe::Plugs::SanitizeParams.(
33
+ # Schema,
34
+ # ->(conn, result) { ... }
35
+ # )
30
36
  # plug(:do_something_with_params) do |conn|
31
37
  # DB.persist(:entity, conn.sanitized_params)
32
38
  # end
33
39
  # end
34
40
  #
35
- # By default, when the result of applying the schema is a failure,
36
- # {Conn} is halted with a 500 as status code. However, you can
37
- # specify your own handler for the unhappy path. It will take the
38
- # {Conn} and {Dry::Schema::Result} instances as arguments:
39
- #
40
- # @example
41
- # plug :sanitize_params, WebPipe::Plugs::SanitizeParams[
42
- # Schema,
43
- # ->(conn, result) { ... }
44
- # ]
45
- #
46
41
  # A common workflow is applying the same handler for all param
47
- # sanitization across your application. This can be achieved setting
48
- # a `:param_sanitization_handler` bag key in a upstream operation
49
- # which can be composed downstream for any number of
50
- # pipes. `SanitizeParams` will used configured handler if none is
51
- # injected as argument. Another plug `ParamSanitizationHandler`
52
- # exists to help with this process:
42
+ # sanitization across your application. This can be achieved configuring
43
+ # a `:param_sanitization_handler` in a upstream operation which can
44
+ # be composed downstream from any number of pipes. `SanitizeParams`
45
+ # will used configured handler if none is injected as
46
+ # argument.
53
47
  #
54
48
  # @example
55
49
  # class App
56
- # plug :sanitization_handler, WebPipe::Plugs::ParamSanitizationHandler[
57
- # ->(conn, result) { ... }
58
- # ]
50
+ # plug :sanitization_handler, ->(conn, result) { ... }
59
51
  # end
60
52
  #
61
53
  # class Subapp
62
54
  # Schema = Dry::Schema.Params { ... }
63
55
  #
64
56
  # plug :app, App.new
65
- # plug :sanitize_params, WebPipe::Plugs::SanitizeParams[Schema]
57
+ # plug :sanitize_params, WebPipe::Plugs::SanitizeParams.call(Schema)
66
58
  # end
67
59
  #
68
60
  # @see https://dry-rb.org/gems/dry-schema/
@@ -70,9 +62,9 @@ module WebPipe
70
62
  SANITIZED_PARAMS_KEY = :sanitized_params
71
63
 
72
64
  def sanitized_params
73
- fetch(SANITIZED_PARAMS_KEY)
65
+ fetch_config(SANITIZED_PARAMS_KEY)
74
66
  end
75
67
  end
76
68
 
77
69
  Conn.include(DrySchema)
78
- end
70
+ end
@@ -1,6 +1,5 @@
1
1
  require 'web_pipe/types'
2
2
  require 'web_pipe/extensions/dry_schema/dry_schema'
3
- require 'web_pipe/extensions/dry_schema/plugs/param_sanitization_handler'
4
3
 
5
4
  module WebPipe
6
5
  module Plugs
@@ -8,25 +7,20 @@ module WebPipe
8
7
  #
9
8
  # @see WebPipe::DrySchema
10
9
  module SanitizeParams
11
- # Default handler if none is configured nor injected.
10
+ # {Conn#config} key to store the handler.
12
11
  #
13
- # @return [ParamSanitizationHandler::Handler[]]
14
- DEFAULT_HANDLER = lambda do |conn, _result|
15
- conn.
16
- set_status(500).
17
- set_response_body('Given params do not conform with the expected schema').
18
- halt
19
- end
12
+ # @return [Symbol]
13
+ PARAM_SANITIZATION_HANDLER_KEY = :param_sanitization_handler
20
14
 
21
15
  # @param schema [Dry::Schema::Processor]
22
16
  # @param handler [ParamSanitizationHandler::Handler[]]
23
17
  #
24
18
  # @return [ConnSupport::Composition::Operation[], Types::Undefined]
25
- def self.[](schema, handler = Types::Undefined)
19
+ def self.call(schema, handler = Types::Undefined)
26
20
  lambda do |conn|
27
21
  result = schema.(conn.params)
28
22
  if result.success?
29
- conn.add(DrySchema::SANITIZED_PARAMS_KEY, result.output)
23
+ conn.add_config(DrySchema::SANITIZED_PARAMS_KEY, result.output)
30
24
  else
31
25
  get_handler(conn, handler).(conn, result)
32
26
  end
@@ -36,11 +30,9 @@ module WebPipe
36
30
  def self.get_handler(conn, handler)
37
31
  return handler unless handler == Types::Undefined
38
32
 
39
- conn.fetch(
40
- Plugs::ParamSanitizationHandler::PARAM_SANITIZATION_HANDLER_KEY, DEFAULT_HANDLER
41
- )
33
+ conn.fetch_config(PARAM_SANITIZATION_HANDLER_KEY)
42
34
  end
43
35
  private_class_method :get_handler
44
36
  end
45
37
  end
46
- end
38
+ end
@@ -28,9 +28,8 @@ module WebPipe
28
28
  # end
29
29
  # end
30
30
  #
31
- # If {WebPipe::Conn#bag} has a `:container` key, the view instance
32
- # can be resolved from it. {WebPipe::Container} extension can be
33
- # used to streamline this integration.
31
+ # If there is a `:container` configured (in {Conn#config}), the view
32
+ # instance can be resolved from it.
34
33
  #
35
34
  # @example
36
35
  # WebPipe.load_extensions(:dry_view, :container)
@@ -40,7 +39,7 @@ module WebPipe
40
39
  #
41
40
  # Container = { 'views.say_hello' => SayHelloView.new }.freeze
42
41
  #
43
- # plug :container, WebPipe::Plugs::Container[Container]
42
+ # plug :config_container, ->(conn) { conn.add_config(:container, Container[Container]) }
44
43
  # plug :render
45
44
  #
46
45
  # def render(conn)
@@ -52,9 +51,11 @@ module WebPipe
52
51
  # through the `context:` argument, as in a standard call to
53
52
  # {Dry::View#call}. However, it is possible to leverage configured
54
53
  # default context while still being able to inject request specific
55
- # context. For that to work, a key `:view_context` should be present
56
- # in {WebPipe::Conn#bag}. It must be equal to a hash which will be
57
- # passed to {Dry::View::Context#with} to create the final context:
54
+ # context. For that to work, `:view_context` should be present in
55
+ # {WebPipe::Conn#config}. Its value must be a lambda accepting the
56
+ # {Conn} instance and returning a hash, which will be passed to
57
+ # {Dry::View::Context#with} to create the final context at the
58
+ # moment {#view} is called.
58
59
  #
59
60
  # @example
60
61
  # class MyContext < Dry::View::Context
@@ -77,11 +78,11 @@ module WebPipe
77
78
  # class App
78
79
  # include WebPipe
79
80
  #
80
- # plug :set_view_context
81
+ # plug :config_view_context
81
82
  # plug :render
82
83
  #
83
- # def set_view_context(conn)
84
- # conn.put(:view_context, { current_path: conn.full_path })
84
+ # def config_view_context(conn)
85
+ # conn.add_config(:view_context, ->(conn) { { current_path: conn.full_path } })
85
86
  # end
86
87
  #
87
88
  # def render(conn)
@@ -90,25 +91,14 @@ module WebPipe
90
91
  # end
91
92
  # end
92
93
  #
93
- # It can be streamline using {WebPipe::Plugs::ViewContext} plug,
94
- # which accepts a callable object which should return the request
95
- # context from given {WebPipe::Conn}:
96
- #
97
- # @example
98
- # # ...
99
- # plug :set_view_context, WebPipe::Plugs::ViewContext[
100
- # ->(conn) { { current_path: conn.full_path } }
101
- # ]
102
- # # ...
103
- #
104
94
  # @see https://dry-rb.org/gems/dry-view/
105
95
  # @see WebPipe::Container
106
96
  module DryView
107
- # Where to find in {#bag} request's view context
97
+ # Where to find in {#config} request's view context generator.
108
98
  VIEW_CONTEXT_KEY = :view_context
109
99
 
110
100
  # Default request's view context
111
- DEFAULT_VIEW_CONTEXT = Types::EMPTY_HASH
101
+ DEFAULT_VIEW_CONTEXT = ->(_conn) { Types::EMPTY_HASH }
112
102
 
113
103
  # Sets string output of a view as response body.
114
104
  #
@@ -117,8 +107,8 @@ module WebPipe
117
107
  #
118
108
  # `kwargs` is used as the input for the view (the arguments that
119
109
  # {Dry::View#call} receives). If they doesn't contain an explicit
120
- # `context:` key, it can be added through the injection injection
121
- # of what is present in bag's `:view_context`.(see
110
+ # `context:` key, it can be added through the injection of the
111
+ # result of a lambda present in context's `:view_context`.(see
122
112
  # {Dry::View::Context#with}).
123
113
  #
124
114
  # @param view_spec [Dry::View, Any]
@@ -141,7 +131,7 @@ module WebPipe
141
131
  def view_instance(view_spec)
142
132
  return view_spec if view_spec.is_a?(Dry::View)
143
133
 
144
- fetch(:container)[view_spec]
134
+ fetch_config(:container)[view_spec]
145
135
  end
146
136
 
147
137
  def view_input(kwargs, view_instance)
@@ -151,7 +141,7 @@ module WebPipe
151
141
  config.
152
142
  default_context.
153
143
  with(
154
- fetch(VIEW_CONTEXT_KEY, DEFAULT_VIEW_CONTEXT)
144
+ fetch_config(VIEW_CONTEXT_KEY, DEFAULT_VIEW_CONTEXT).(self)
155
145
  )
156
146
  kwargs.merge(context: context)
157
147
  end
@@ -0,0 +1,99 @@
1
+ require 'web_pipe/types'
2
+ require 'web_pipe/extensions/params/params/transf'
3
+
4
+ module WebPipe
5
+ # Adds a {Conn#params} method which can perform any number of
6
+ # transformations to the request parameters.
7
+ #
8
+ # When no transformations are given, {#params} just returns request
9
+ # parameters (both GET and POST) as a hash:
10
+ #
11
+ # @example
12
+ # # http://www.example.com?foo=bar
13
+ # conn.params #=> { 'foo' => 'bar' }
14
+ #
15
+ # Further processing can be specified thanks to `transproc` gem (you
16
+ # need to add it yourself to the Gemfile). All hash transformations
17
+ # in `transproc` are available:
18
+ #
19
+ # @example
20
+ # # http://www.example.com?foo=bar
21
+ # conn.params([:deep_symbolize_keys]) #=> { foo: 'bar' }
22
+ #
23
+ # Extra needed arguments can be provided as an array:
24
+ #
25
+ # @example
26
+ # # http://www.example.com?foo=bar&zoo=zoo
27
+ # conn.params([:deep_symbolize_keys, [:reject_keys, [:zoo]]) #=> { foo: 'bar' }
28
+ #
29
+ # Instead of injecting transformations at the moment `#params` is
30
+ # called, you can configure them to be automatically used.
31
+ #
32
+ # @example
33
+ # # http://www.example.com?foo=bar
34
+ # conn.
35
+ # add_config(:param_transformation, [:deep_symbolize_keys]).
36
+ # params #=> { foo: 'bar' }
37
+ #
38
+ # You can register your own transformation functions:
39
+ #
40
+ # @example
41
+ # # http://www.example.com?foo=bar
42
+ # fake = ->(_params) { { fake: :params } }
43
+ # WebPipe::Params::Transf.register(:fake, fake)
44
+ # conn.params([:fake]) #=> { fake: :params }
45
+ #
46
+ # Your own transformation functions can depend on the {Conn}
47
+ # instance at the moment of execution. For that, just place it as the
48
+ # last argument of the function and it will be curried automatically:
49
+ #
50
+ # @example
51
+ # # http://www.example.com?foo=bar
52
+ # add_name = ->(params, conn) { params.merge(name: conn.fetch(:name)) }
53
+ # WebPipe::Params::Transf.register(:add_name, add_name)
54
+ # conn.
55
+ # add(:name, 'Joe').
56
+ # params([:deep_symbolize_keys, :add_name]) #=> { foo: 'bar', name: 'Joe' }
57
+ #
58
+ # Inline transformations can also be provided:
59
+ #
60
+ # @example
61
+ # # http://www.example.com?foo=bar
62
+ # fake = ->(_params) { { fake: :params } }
63
+ # conn.
64
+ # params(fake) #=> { fake: :params }
65
+ #
66
+ # @see https://github.com/solnic/transproc
67
+ module Params
68
+ # Key where configured transformations are set
69
+ PARAM_TRANSFORMATION_KEY = :param_transformations
70
+
71
+ # @param transformation_specs [Array<Symbol, Array>, Types::Undefined]
72
+ # @return [Any]
73
+ def params(transformation_specs = Types::Undefined)
74
+ specs = if transformation_specs == Types::Undefined
75
+ fetch_config(PARAM_TRANSFORMATION_KEY, [])
76
+ else
77
+ transformation_specs
78
+ end
79
+ transformations = specs.reduce(Transf[:id]) do |acc, t|
80
+ acc.>>transformation(t)
81
+ end
82
+
83
+ Transf[transformations].(request.params)
84
+ end
85
+
86
+ private
87
+
88
+ def transformation(spec)
89
+ transformation = Transf[*spec]
90
+ if (transformation.fn.arity - transformation.args.count) == 1
91
+ transformation
92
+ else
93
+ Transf[*[spec, self]]
94
+ end
95
+ end
96
+ end
97
+
98
+ Conn.include(Params)
99
+ end
@@ -0,0 +1,15 @@
1
+ require 'transproc'
2
+
3
+ module WebPipe
4
+ module Params
5
+ module Transf
6
+ extend Transproc::Registry
7
+
8
+ import Transproc::HashTransformations
9
+
10
+ def self.id(params)
11
+ params
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,59 @@
1
+ require 'web_pipe'
2
+ require 'web_pipe/types'
3
+
4
+ WebPipe.load_extensions(:params)
5
+
6
+ module WebPipe
7
+ # Adds a transformation to merge router params into {Conn#params}.
8
+ #
9
+ # This extension gives an opportunity for rack routers to modify
10
+ # {Conn#params} hash. This is useful so that they can provide *route
11
+ # parameters*, which are typically rendered as variables in routes
12
+ # definitions (e.g.: `/user/:id/edit`).
13
+ #
14
+ # It adds a `:router_params` transformation that, when used, will
15
+ # merged env's `router.params` in {Conn#params} hash. Choosing this
16
+ # name automatically integrates with `hanami-router`.
17
+ #
18
+ # When using this extension, `:params` extension is automatically enabled.
19
+ #
20
+ # @example
21
+ # require 'web_pipe'
22
+ #
23
+ # WebPipe.load_extensions(:router_params)
24
+ #
25
+ # class MyApp
26
+ # include WebPipe
27
+ #
28
+ # plug :config
29
+ # plug :get_params
30
+ #
31
+ # private
32
+ #
33
+ # def config(conn)
34
+ # conn.add_config(:param_transformation, [:router_params])
35
+ # end
36
+ #
37
+ # def get_params(conn)
38
+ # # http://example.com/users/1/edit
39
+ # conn.params #=> { id: 1 }
40
+ # conn
41
+ # end
42
+ # end
43
+ #
44
+ # @see WebPipe::Params
45
+ # @see https://github.com/hanami/router#string-matching-with-variables
46
+ module RouterParams
47
+ ROUTER_PARAM_KEY = 'router.params'
48
+
49
+ # @param params [Hash]
50
+ # @param conn [WebPipe::Conn]
51
+ #
52
+ # @return [Hash]
53
+ def self.call(params, conn)
54
+ params.merge(conn.env.fetch(ROUTER_PARAM_KEY, Types::EMPTY_HASH))
55
+ end
56
+
57
+ WebPipe::Params::Transf.register(:router_params, method(:call))
58
+ end
59
+ end
@@ -4,11 +4,6 @@ module WebPipe
4
4
  # This methods are in fact redundant with the information already
5
5
  # present in {Conn} struct but, of course, they are very useful.
6
6
  module Url
7
- # Env's key used to retrieve params set by the router.
8
- #
9
- # @see #router_params
10
- ROUTER_PARAMS_KEY = 'router.params'
11
-
12
7
  # Base part of the URL.
13
8
  #
14
9
  # This is {#scheme} and {#host}, adding {#port} unless it is the
@@ -58,37 +53,6 @@ module WebPipe
58
53
  def url
59
54
  request.url
60
55
  end
61
-
62
- # *Params* in rack env's 'router.params' key.
63
- #
64
- # Routers used to map routes to applications build with
65
- # {WebPipe} have the option to introduce extra params through
66
- # setting env's 'router.params' key. These parameters will be
67
- # merged with GET and POST ones when calling {#params}.
68
- #
69
- # This kind of functionality is usually implemented from the
70
- # router side allowing the addition of variables in the route
71
- # definition, e.g.:
72
- #
73
- # @example
74
- # /user/:id/update
75
- #
76
- # @return [Hash]
77
- def router_params
78
- env.fetch(ROUTER_PARAMS_KEY, Types::EMPTY_HASH)
79
- end
80
-
81
- # GET, POST and {#router_params} merged in a hash.
82
- #
83
- # @return [Params]
84
- #
85
- # @example
86
- # { 'id' => '1', 'name' => 'Joe' }
87
- #
88
- # @return Hash
89
- def params
90
- request.params.merge(router_params)
91
- end
92
56
  end
93
57
 
94
58
  Conn.include(Url)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'web_pipe/types'
4
+
5
+ module WebPipe
6
+ module Plugs
7
+ # Adds given pairs to {Conn#config}.
8
+ #
9
+ # @example
10
+ # class App
11
+ # include WebPipe
12
+ #
13
+ # plug :config, WebPipe::Plugs::Config.(foo: :bar)
14
+ # end
15
+ module Config
16
+ def self.call(pairs)
17
+ lambda do |conn|
18
+ conn.new(
19
+ config: conn.config.merge(pairs)
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -10,13 +10,13 @@ module WebPipe
10
10
  # class App
11
11
  # include WebPipe
12
12
  #
13
- # plug :html, WebPipe::Plugs::ContentType['text/html']
13
+ # plug :html, WebPipe::Plugs::ContentType.call('text/html')
14
14
  # end
15
15
  module ContentType
16
16
  # Content-Type header
17
17
  HEADER = 'Content-Type'
18
18
 
19
- def self.[](content_type)
19
+ def self.call(content_type)
20
20
  ->(conn) { conn.add_response_header(HEADER, content_type) }
21
21
  end
22
22
  end
@@ -1,3 +1,3 @@
1
1
  module WebPipe
2
- VERSION = "0.6.1"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -36,9 +36,10 @@ Gem::Specification.new do |spec|
36
36
  spec.require_paths = ["lib"]
37
37
 
38
38
  spec.add_runtime_dependency "rack", "~> 2.0"
39
- spec.add_runtime_dependency "dry-monads", "~> 1.2"
39
+ spec.add_runtime_dependency "dry-monads", "~> 1.3"
40
40
  spec.add_runtime_dependency "dry-types", "~> 1.1"
41
41
  spec.add_runtime_dependency "dry-struct", "~> 1.0"
42
+ spec.add_runtime_dependency "transproc", "~> 1.1"
42
43
 
43
44
  spec.add_development_dependency "bundler", "~> 1.17"
44
45
  spec.add_development_dependency "rake", "~> 10.0"
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.6.1
4
+ version: 0.7.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-08-02 00:00:00.000000000 Z
11
+ date: 2019-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.2'
33
+ version: '1.3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.2'
40
+ version: '1.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: dry-types
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: transproc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.1'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: bundler
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -227,9 +241,9 @@ files:
227
241
  - Gemfile
228
242
  - README.md
229
243
  - Rakefile
244
+ - _config.yml
230
245
  - bin/console
231
246
  - bin/setup
232
- - lib/dry/monads/result/extensions/either.rb
233
247
  - lib/web_pipe.rb
234
248
  - lib/web_pipe/app.rb
235
249
  - lib/web_pipe/conn.rb
@@ -243,19 +257,20 @@ files:
243
257
  - lib/web_pipe/dsl/dsl_context.rb
244
258
  - lib/web_pipe/dsl/instance_methods.rb
245
259
  - lib/web_pipe/extensions/container/container.rb
246
- - lib/web_pipe/extensions/container/plugs/container.rb
247
260
  - lib/web_pipe/extensions/cookies/cookies.rb
248
261
  - lib/web_pipe/extensions/dry_schema/dry_schema.rb
249
- - lib/web_pipe/extensions/dry_schema/plugs/param_sanitization_handler.rb
250
262
  - lib/web_pipe/extensions/dry_schema/plugs/sanitize_params.rb
251
263
  - lib/web_pipe/extensions/dry_view/dry_view.rb
252
- - lib/web_pipe/extensions/dry_view/plugs/view_context.rb
253
264
  - lib/web_pipe/extensions/flash/flash.rb
265
+ - lib/web_pipe/extensions/params/params.rb
266
+ - lib/web_pipe/extensions/params/params/transf.rb
254
267
  - lib/web_pipe/extensions/redirect/redirect.rb
268
+ - lib/web_pipe/extensions/router_params/router_params.rb
255
269
  - lib/web_pipe/extensions/session/session.rb
256
270
  - lib/web_pipe/extensions/url/url.rb
257
271
  - lib/web_pipe/plug.rb
258
272
  - lib/web_pipe/plugs.rb
273
+ - lib/web_pipe/plugs/config.rb
259
274
  - lib/web_pipe/plugs/content_type.rb
260
275
  - lib/web_pipe/rack/app_with_middlewares.rb
261
276
  - lib/web_pipe/rack/middleware.rb
@@ -1,42 +0,0 @@
1
- require "dry/core/extensions"
2
-
3
- module Dry
4
- module Monads
5
- # This is currently a PR in dry-monads:
6
- #
7
- # https://github.com/dry-rb/dry-monads/pull/84
8
- class Result
9
- extend Dry::Core::Extensions
10
-
11
- register_extension(:either) do
12
- class Success
13
- # Returns result of applying first function to the internal value.
14
- #
15
- # @example
16
- # Dry::Monads.Success(1).either(-> x { x + 1 }, -> x { x + 2 }) # => 2
17
- #
18
- # @param f [#call] Function to apply
19
- # @param g [#call] Ignored
20
- # @return [Any] Return value of `f`
21
- def either(f, _g)
22
- f.(success)
23
- end
24
- end
25
-
26
- class Failure
27
- # Returns result of applying second function to the internal value.
28
- #
29
- # @example
30
- # Dry::Monads.Failure(1).either(-> x { x + 1 }, -> x { x + 2 }) # => 3
31
- #
32
- # @param f [#call] Ignored
33
- # @param g [#call] Function to call
34
- # @return [Any] Return value of `g`
35
- def either(_f, g)
36
- g.(failure)
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,31 +0,0 @@
1
- require 'web_pipe/types'
2
-
3
- module WebPipe
4
- module Plugs
5
- # Sets a container into bag's `:container` key.
6
- #
7
- # Given container is check to respond to `#[]` method, which is
8
- # meant to be used to resolve dependencies.
9
- #
10
- # @example
11
- # class App
12
- # include WebPipe
13
- #
14
- # Cont = { name: SomeDependency.new }.freeze
15
- #
16
- # plug :container, WebPipe::Plugs::Container[Cont]
17
- # plug :resolve
18
- #
19
- # private
20
- #
21
- # def resolve(conn)
22
- # conn.add(:dependency, conn.fetch(:container)[:name])
23
- # end
24
- # end
25
- module Container
26
- def self.[](container)
27
- ->(conn) { conn.add(:container, Types::Container[container]) }
28
- end
29
- end
30
- end
31
- end
@@ -1,27 +0,0 @@
1
- require 'web_pipe/types'
2
-
3
- module WebPipe
4
- module Plugs
5
- # Sets `:param_sanitization_handler` bag key.
6
- #
7
- # @see WebPipe::DrySchema
8
- module ParamSanitizationHandler
9
- # Bag key to store the handler.
10
- #
11
- # @return [Symbol]
12
- PARAM_SANITIZATION_HANDLER_KEY = :param_sanitization_handler
13
-
14
- # Type constructor for the handler.
15
- Handler = Types.Interface(:call)
16
-
17
- # @param handler [Handler[]]
18
- #
19
- # @return [ConnSupport::Composition::Operation[]]
20
- def self.[](handler)
21
- lambda do |conn|
22
- conn.add(PARAM_SANITIZATION_HANDLER_KEY, Handler[handler])
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,38 +0,0 @@
1
- require 'web_pipe/types'
2
- require 'web_pipe/extensions/dry_view/dry_view'
3
-
4
- module WebPipe
5
- module Plugs
6
- # Calls object with conn and add the result into bag's `:view_context`.
7
- #
8
- # This is meant to contain a Proc which will be called with the same
9
- # {WebPipe::Conn} instance of the operation. It must return
10
- # request specific view context as a hash. Ultimately, this will
11
- # be provided to {Dry::View::Context#with} before passing the
12
- # result along to the view instance.
13
- #
14
- # @example
15
- # class App
16
- # include WebPipe
17
- #
18
- # ViewContext = (conn) -> { { current_path: conn.full_path } }
19
- #
20
- # plug :view_context, WebPipe::Plugs::ViewContext[ViewContext]
21
- # plug :render
22
- #
23
- # def render
24
- # view(MyView.new)
25
- # end
26
- # end
27
- #
28
- # @see WebPipe::Conn#view
29
- module ViewContext
30
- def self.[](view_context_proc)
31
- Types.Interface(:call)[view_context_proc]
32
- lambda do |conn|
33
- conn.add(Conn::VIEW_CONTEXT_KEY, view_context_proc.(conn))
34
- end
35
- end
36
- end
37
- end
38
- end