web_pipe 0.13.0 → 0.16.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/CHANGELOG.md +29 -0
  4. data/Gemfile +2 -2
  5. data/README.md +18 -11
  6. data/docs/building_a_rack_application.md +1 -1
  7. data/docs/composing_applications.md +4 -4
  8. data/docs/connection_struct/configuring_the_connection_struct.md +4 -4
  9. data/docs/connection_struct/halting_the_pipe.md +17 -19
  10. data/docs/connection_struct/sharing_data_downstream.md +9 -8
  11. data/docs/connection_struct.md +22 -19
  12. data/docs/design_model.md +10 -9
  13. data/docs/dsl_free_usage.md +85 -14
  14. data/docs/extensions/container.md +9 -10
  15. data/docs/extensions/cookies.md +4 -2
  16. data/docs/extensions/dry_schema.md +5 -4
  17. data/docs/extensions/flash.md +9 -11
  18. data/docs/extensions/{dry_view.md → hanami_view.md} +20 -22
  19. data/docs/extensions/not_found.md +40 -0
  20. data/docs/extensions/params.md +6 -4
  21. data/docs/extensions/rails.md +31 -38
  22. data/docs/extensions/redirect.md +5 -4
  23. data/docs/extensions/router_params.md +5 -5
  24. data/docs/extensions/session.md +4 -4
  25. data/docs/extensions/url.md +6 -6
  26. data/docs/extensions.md +5 -6
  27. data/docs/introduction.md +7 -7
  28. data/docs/plugging_operations/composing_operations.md +3 -3
  29. data/docs/plugging_operations/injecting_operations.md +4 -4
  30. data/docs/plugging_operations/inspecting_operations.md +24 -0
  31. data/docs/plugging_operations/resolving_operations.md +3 -3
  32. data/docs/plugging_operations.md +3 -3
  33. data/docs/plugs/config.md +1 -1
  34. data/docs/plugs/content_type.md +2 -1
  35. data/docs/plugs.md +6 -7
  36. data/docs/recipes/hanami_2_and_dry_rb_integration.md +12 -0
  37. data/docs/recipes/hanami_router_integration.md +3 -1
  38. data/docs/recipes/using_all_restful_methods.md +6 -5
  39. data/docs/testing.md +64 -0
  40. data/docs/using_rack_middlewares/composing_middlewares.md +2 -3
  41. data/docs/using_rack_middlewares/injecting_middlewares.md +6 -6
  42. data/docs/using_rack_middlewares/inspecting_middlewares.md +35 -0
  43. data/docs/using_rack_middlewares.md +6 -6
  44. data/lib/web_pipe/app.rb +22 -25
  45. data/lib/web_pipe/conn.rb +0 -1
  46. data/lib/web_pipe/conn_support/builder.rb +0 -7
  47. data/lib/web_pipe/conn_support/composition.rb +3 -26
  48. data/lib/web_pipe/conn_support/errors.rb +5 -5
  49. data/lib/web_pipe/conn_support/headers.rb +1 -50
  50. data/lib/web_pipe/conn_support/types.rb +3 -3
  51. data/lib/web_pipe/dsl/builder.rb +10 -19
  52. data/lib/web_pipe/dsl/class_context.rb +15 -40
  53. data/lib/web_pipe/dsl/instance_context.rb +53 -0
  54. data/lib/web_pipe/extensions/container/container.rb +2 -15
  55. data/lib/web_pipe/extensions/cookies/cookies.rb +2 -31
  56. data/lib/web_pipe/extensions/dry_schema/dry_schema.rb +2 -56
  57. data/lib/web_pipe/extensions/flash/flash.rb +2 -32
  58. data/lib/web_pipe/extensions/hanami_view/hanami_view.rb +67 -0
  59. data/lib/web_pipe/extensions/not_found/not_found.rb +26 -0
  60. data/lib/web_pipe/extensions/params/params.rb +2 -63
  61. data/lib/web_pipe/extensions/rails/rails.rb +2 -123
  62. data/lib/web_pipe/extensions/redirect/redirect.rb +2 -20
  63. data/lib/web_pipe/extensions/router_params/router_params.rb +1 -39
  64. data/lib/web_pipe/extensions/session/session.rb +2 -25
  65. data/lib/web_pipe/extensions/url/url.rb +2 -5
  66. data/lib/web_pipe/pipe.rb +229 -0
  67. data/lib/web_pipe/plug.rb +31 -65
  68. data/lib/web_pipe/plugs/config.rb +0 -2
  69. data/lib/web_pipe/plugs/content_type.rb +0 -2
  70. data/lib/web_pipe/rack_support/app_with_middlewares.rb +3 -26
  71. data/lib/web_pipe/rack_support/middleware.rb +2 -2
  72. data/lib/web_pipe/rack_support/middleware_specification.rb +19 -48
  73. data/lib/web_pipe/test_support.rb +28 -0
  74. data/lib/web_pipe/types.rb +1 -3
  75. data/lib/web_pipe/version.rb +1 -1
  76. data/lib/web_pipe.rb +77 -17
  77. data/web_pipe.gemspec +1 -2
  78. metadata +16 -9
  79. data/docs/recipes/dry_rb_integration.md +0 -18
  80. data/lib/web_pipe/dsl/dsl_context.rb +0 -85
  81. data/lib/web_pipe/dsl/instance_methods.rb +0 -114
  82. data/lib/web_pipe/extensions/dry_view/dry_view.rb +0 -158
@@ -0,0 +1,229 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'web_pipe/conn_support/composition'
4
+ require 'web_pipe/app'
5
+ require 'web_pipe/plug'
6
+ require 'web_pipe/rack_support/middleware_specification'
7
+ require 'web_pipe/rack_support/app_with_middlewares'
8
+ require 'web_pipe/types'
9
+
10
+ module WebPipe
11
+ # Composable rack application builder.
12
+ #
13
+ # An instance of this class helps build rack applications that can compose.
14
+ # Besides the DSL, which only adds a convenience layer, this is the higher
15
+ # abstraction on the library.
16
+ #
17
+ # Applications are built by plugging functions that take and return a
18
+ # {WebPipe::Conn} instance. That's an immutable struct that contains all the
19
+ # request information alongside methods to build the response. See {#plug} for
20
+ # details.
21
+ #
22
+ # Middlewares can also be added to the resulting application thanks to {#use}.
23
+ #
24
+ # Be aware that instances of this class are immutable, so methods return new
25
+ # objects every time.
26
+ #
27
+ # The instance itself is the final rack application.
28
+ #
29
+ # @example
30
+ # # config.ru
31
+ # require 'web_pipe/pipe'
32
+ #
33
+ # app = WebPipe::Pipe.new
34
+ # .use(:runtime, Rack::Runtime)
35
+ # .plug(:content_type) do |conn|
36
+ # conn.add_response_header('Content-Type', 'text/plain')
37
+ # end
38
+ # .plug(:render) do |conn|
39
+ # conn.set_response_body('Hello, World!')
40
+ # end
41
+ #
42
+ # run app
43
+ class Pipe
44
+ # Container that resolves nothing
45
+ EMPTY_CONTAINER = {}.freeze
46
+
47
+ # @!attribute [r] container
48
+ # Container from where resolve operations. See {#plug}.
49
+ attr_reader :container
50
+
51
+ # @!attribute [r] context
52
+ # Object from where resolve operations. See {#plug}.
53
+ attr_reader :context
54
+
55
+ # @api private
56
+ EMPTY_PLUGS = [].freeze
57
+
58
+ # @api private
59
+ EMPTY_MIDDLEWARE_SPECIFICATIONS = [].freeze
60
+
61
+ # @api private
62
+ Container = Types.Interface(:[])
63
+
64
+ # @api private
65
+ attr_reader :plugs
66
+
67
+ # @api private
68
+ attr_reader :middleware_specifications
69
+
70
+ # @param container [#to_h] Container from where resolve plug's operations
71
+ # (see {#plug}).
72
+ # @param context [Any] Object from where resolve plug's operations (see
73
+ # {#plug})
74
+ def initialize(
75
+ container: EMPTY_CONTAINER,
76
+ context: nil,
77
+ plugs: EMPTY_PLUGS,
78
+ middleware_specifications: EMPTY_MIDDLEWARE_SPECIFICATIONS
79
+ )
80
+ @plugs = plugs
81
+ @middleware_specifications = middleware_specifications
82
+ @container = Container[container]
83
+ @context = context
84
+ end
85
+
86
+ # Names and adds a plug operation to the application.
87
+ #
88
+ # The operation can be provided in several ways:
89
+ #
90
+ # - Through the `spec` parameter as:
91
+ # - Anything responding to `#call` (like a {Proc}).
92
+ # - As a string or symbol key for something registered in {#container}.
93
+ # - Anything responding to `#to_proc` (like another {WebPipe::Pipe}
94
+ # instance or an instance of a class including {WebPipe}).
95
+ # - As `nil` (default), meaning that the operation is a method in
96
+ # {#context} matching the `name` parameter.
97
+ # - Through a block, if the `spec` parameter is `nil`.
98
+ #
99
+ # @param name [Symbol]
100
+ # @param spec [#call, #to_proc, String, Symbol, nil]
101
+ # @yieldparam [WebPipe::Conn]
102
+ #
103
+ # @return [WebPipe::Pipe] A fresh new instance with the added plug.
104
+ def plug(name, spec = nil, &block_spec)
105
+ with(
106
+ plugs: [
107
+ *plugs,
108
+ Plug.new(name: name, spec: spec || block_spec)
109
+ ]
110
+ )
111
+ end
112
+
113
+ # Names and adds a rack middleware to the final application.
114
+ #
115
+ # The middleware can be given in three forms:
116
+ #
117
+ # - As one or two arguments, the first one being a
118
+ # rack middleware class, and optionally a second one with its initialization
119
+ # options.
120
+ # - As something responding to `#to_middlewares` with an array of
121
+ # {WebPipe::RackSupport::Middleware} (like another {WebPipe::Pipe} instance
122
+ # or a class including {WebPipe}), case in which all middlewares are used.
123
+ #
124
+ # @overload use(name, middleware_class)
125
+ # @param name [Symbol]
126
+ # @param middleware_class [Class]
127
+ # @overload use(name, middleware_class, middleware_options)
128
+ # @param name [Symbol]
129
+ # @param middleware_class [Class]
130
+ # @param middleware_options [Any]
131
+ # @overload use(name, to_middlewares)
132
+ # @param name [Symbol]
133
+ # @param middleware_class [#to_middlewares]
134
+ #
135
+ # @return [WebPipe::Pipe] A fresh new instance with the added middleware.
136
+ def use(name, *spec)
137
+ with(
138
+ middleware_specifications: [
139
+ *middleware_specifications,
140
+ RackSupport::MiddlewareSpecification.new(name: name, spec: spec)
141
+ ]
142
+ )
143
+ end
144
+
145
+ # Shortcut for {#plug} and {#use} a pipe at once.
146
+ #
147
+ # @param name [#to_sym]
148
+ # @param spec [#to_proc#to_middlewares]
149
+ def compose(name, spec)
150
+ use(name, spec)
151
+ .plug(name, spec)
152
+ end
153
+
154
+ # Operations {#plug}ged to the app, mapped by their names.
155
+ #
156
+ # @return [Hash{Symbol => Proc}]
157
+ def operations
158
+ @operations ||= Hash[
159
+ plugs.map { |plug| [plug.name, plug.call(container, context)] }
160
+ ]
161
+ end
162
+
163
+ # Middlewares {#use}d in the app, mapped by their names.
164
+ #
165
+ # Returns them wrapped within {WebPipe::RackSupport::Middleware} instances,
166
+ # from where you can access their classes and options.
167
+ #
168
+ # @return [Hash{Symbol=>Array<WebPipe::RackSupport::Middleware>}]
169
+ def middlewares
170
+ @middlewares ||= Hash[
171
+ middleware_specifications.map { |mw_spec| [mw_spec.name, mw_spec.call] }
172
+ ]
173
+ end
174
+
175
+ # @api private
176
+ def to_proc
177
+ ConnSupport::Composition
178
+ .new(operations.values)
179
+ .method(:call)
180
+ end
181
+
182
+ # @api private
183
+ def to_middlewares
184
+ middlewares.values.flatten
185
+ end
186
+
187
+ # @api private
188
+ def inject(plugs: {}, middleware_specifications: {})
189
+ res_mw_specs = RackSupport::MiddlewareSpecification.inject(
190
+ self.middleware_specifications, middleware_specifications
191
+ )
192
+ res_plugs = Plug.inject(
193
+ self.plugs, plugs
194
+ )
195
+ with(
196
+ plugs: res_plugs,
197
+ middleware_specifications: res_mw_specs
198
+ )
199
+ end
200
+
201
+ # @api private
202
+ def call(env)
203
+ rack_app.call(env)
204
+ end
205
+
206
+ private
207
+
208
+ def app
209
+ App.new(operations.values).freeze
210
+ end
211
+
212
+ def rack_app
213
+ RackSupport::AppWithMiddlewares.new(
214
+ to_middlewares,
215
+ app
216
+ ).freeze
217
+ end
218
+
219
+ def with(plugs: nil, middleware_specifications: nil)
220
+ self.class.new(
221
+ container: container,
222
+ context: context,
223
+ middleware_specifications: middleware_specifications ||
224
+ self.middleware_specifications,
225
+ plugs: plugs || self.plugs
226
+ )
227
+ end
228
+ end
229
+ end
data/lib/web_pipe/plug.rb CHANGED
@@ -5,106 +5,72 @@ require 'web_pipe/types'
5
5
  require 'web_pipe/conn_support/composition'
6
6
 
7
7
  module WebPipe
8
- # A plug is a specification to resolve a callable object.
9
- #
10
- # It is initialized with a {Name} and a {Spec} and, on resolution
11
- # time, is called with a {Types::Container} and an {Object} to act
12
- # in the following fashion:
13
- #
14
- # - When the spec responds to `#call`, it is returned itself as the
15
- # callable object.
16
- # - When the spec is `nil`, then a {Proc} wrapping a method with the
17
- # plug name in `object` is returned.
18
- # - Otherwise, spec is taken as the key to resolve the operation
19
- # from the `container`.
20
- #
21
8
  # @api private
22
9
  class Plug < Dry::Struct
23
- # Error raised when no operation can be resolved from a {Spec}.
10
+ # Raised when the specification for an operation is invalid.
24
11
  class InvalidPlugError < ArgumentError
25
- # @param name [Any] Name for the plug that can't be resolved
26
12
  def initialize(name)
27
13
  super(
28
14
  <<~MSG
29
- Plug with name +#{name}+ is invalid. It must be something
30
- callable, an instance method when no operation is given,
31
- or something callable registered in the container."
15
+ Plug with name +#{name}+ can't be resolved. You must provide
16
+ something responding to `#call` or `#to_proc`, or a key for
17
+ something registered in the container obeying those exact
18
+ constraints. If nothing is given, it's expected to be a method
19
+ defined in the context object.
32
20
  MSG
33
21
  )
34
22
  end
35
23
  end
36
-
37
- # Type for the name of a plug.
38
24
  Name = Types::Strict::Symbol.constructor(&:to_sym)
39
25
 
40
- # Type for the spec to resolve and
41
- # {ConnSupport::Composition::Operation} on a {Conn} used by
42
- # {Plug}.
43
- Spec = ConnSupport::Composition::Operation |
26
+ Spec = Types.Interface(:call) |
27
+ Types.Interface(:to_proc) |
44
28
  Types.Constant(nil) |
45
29
  Types::Strict::String |
46
30
  Types::Strict::Symbol
47
31
 
48
- # Type for an instance of self.
49
- Instance = Types.Instance(self)
50
-
51
- # Schema expected to inject plugs.
52
- #
53
- # @see #inject_and_resolve
54
32
  Injections = Types::Strict::Hash.map(
55
- Plug::Name, Plug::Spec
33
+ Name, Spec
56
34
  ).default(Types::EMPTY_HASH)
57
35
 
58
- # @!attribute [r] name
59
- # @return [Name[]]
60
36
  attribute :name, Name
61
37
 
62
- # @!attribute [r] spec
63
- # @return [Spec[]]
64
38
  attribute :spec, Spec
65
39
 
66
- # Creates a new instance with given `spec` but keeping `name`.
67
- #
68
- # @param new_spec [Spec[]]
69
- # @return [self]
70
40
  def with(new_spec)
71
41
  new(spec: new_spec)
72
42
  end
73
43
 
74
- # Resolves the operation.
75
- #
76
- # @param container [Types::Container[]]
77
- # @param object [Object]
78
- #
79
- # @return [ConnSupport::Composition::Operation[]]
80
- # @raise [InvalidPlugError] When nothing callable is resolved.
81
- def call(container, pipe)
82
- if spec.respond_to?(:call)
44
+ # rubocop:disable Metrics/MethodLength
45
+ # rubocop:disable Metrics/AbcSize
46
+ def call(container, context)
47
+ if spec.respond_to?(:to_proc) && !spec.is_a?(Symbol)
48
+ spec.to_proc
49
+ elsif spec.respond_to?(:call)
83
50
  spec
84
51
  elsif spec.nil?
85
- pipe.method(name)
86
- elsif container[spec].respond_to?(:call)
87
- container[spec]
52
+ context.method(name)
53
+ elsif container[spec]
54
+ with(container[spec]).call(container, context)
88
55
  else
89
56
  raise InvalidPlugError, name
90
57
  end
91
58
  end
59
+ # rubocop:enable Metrics/MethodLength
60
+ # rubocop:enable Metrics/AbcSize
92
61
 
93
- # Change `plugs` spec's present in `injections` and resolves.
94
- #
95
- # @param plugs [Array<Plug>]
96
- # @param injections [InstanceMethods::PlugInjections[]]
97
- # @container container [Types::Container[]]
98
- # @object [Object]
99
- #
100
- # @return [Array<ConnSupport::Composition::Operation[]>]
101
- def self.inject_and_resolve(plugs, injections, container, object)
62
+ def self.inject(plugs, injections)
102
63
  plugs.map do |plug|
103
- if injections.key?(plug.name)
104
- plug.with(injections[plug.name])
105
- else
106
- plug
107
- end.call(container, object)
64
+ inject_plug(plug, injections)
65
+ end
66
+ end
67
+
68
+ def self.inject_plug(plug, injections)
69
+ name = plug.name
70
+ if injections.key?(name)
71
+ plug.with(injections[name])
72
+ else
73
+ plug
108
74
  end
109
75
  end
110
76
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'web_pipe/types'
4
-
5
3
  module WebPipe
6
4
  module Plugs
7
5
  # Adds given pairs to {Conn#config}.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'web_pipe/types'
4
-
5
3
  module WebPipe
6
4
  module Plugs
7
5
  # Sets `Content-Type` response header.
@@ -1,43 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'web_pipe/types'
4
3
  require 'web_pipe/rack_support/middleware'
5
4
  require 'rack'
6
5
 
7
6
  module WebPipe
8
7
  module RackSupport
9
- # Helper to build and call a rack application with middlewares.
10
- #
11
8
  # @api private
12
9
  class AppWithMiddlewares
13
- # Type for a rack application.
14
- #
15
- # It should be something callable accepting a rack env and
16
- # returning a rack response.
17
- App = Types.Interface(:call)
18
-
19
- # @!attribute [r] rack_middlewares
20
- # @return [Array<RackMiddleware>]
21
- attr_reader :rack_middlewares
22
-
23
- # @!attribute [r] app
24
- # @return [App[]]
25
- attr_reader :app
26
-
27
- # @return [Rack::Builder]
28
- attr_reader :builder
10
+ attr_reader :rack_middlewares, :app, :builder
29
11
 
30
12
  def initialize(rack_middlewares, app)
31
- @rack_middlewares = Types.Array(Middleware)[rack_middlewares]
32
- @app = App[app]
13
+ @rack_middlewares = rack_middlewares
14
+ @app = app
33
15
  @builder = build_rack_app(rack_middlewares, app)
34
16
  end
35
17
 
36
- # Calls rack application.
37
- #
38
- # @param env [Hash] Rack env
39
- #
40
- # @return [Array] Rack resonse
41
18
  def call(env)
42
19
  builder.call(env)
43
20
  end
@@ -5,10 +5,10 @@ require 'dry/struct'
5
5
 
6
6
  module WebPipe
7
7
  module RackSupport
8
+ # Wrapper for a rack middleware.
9
+ #
8
10
  # Simple data structure to represent a rack middleware class with
9
11
  # its initialization options.
10
- #
11
- # @api private
12
12
  class Middleware < Dry::Struct
13
13
  # Type for a rack middleware class.
14
14
  MiddlewareClass = Types.Instance(Class)
@@ -6,74 +6,45 @@ require 'web_pipe/types'
6
6
 
7
7
  module WebPipe
8
8
  module RackSupport
9
- # Specification on how to resolve {Rack::Middleware}'s.
10
- #
11
- # Rack middlewares can be specified in two ways:
12
- #
13
- # - As an array where fist element is a rack middleware class
14
- # while the rest of elements are its initialization options.
15
- # - A single element array where it is an instance of a class
16
- # including {WebPipe}. This specifies all {RackSupport::Middlewares} for
17
- # that {WebPipe}.
18
- #
19
9
  # @api private
20
10
  class MiddlewareSpecification < Dry::Struct
21
- # Type for the name given to a middleware.
22
11
  Name = Types::Strict::Symbol.constructor(&:to_sym)
23
12
 
24
- # Poor type for the specification to resolve a rack middleware.
25
13
  Spec = Types::Strict::Array
26
14
 
27
- # Schema expected to inject middleware specifications.
28
- #
29
- # @see #inject_and_resolve
30
15
  Injections = Types::Strict::Hash.map(
31
- RackSupport::MiddlewareSpecification::Name, RackSupport::MiddlewareSpecification::Spec
16
+ Name, Spec
32
17
  ).default(Types::EMPTY_HASH)
33
18
 
34
- # @!attribute [r] name
35
- # @return [Name[]]
36
19
  attribute :name, Name
37
20
 
38
- # @!attribute [r] spec
39
- # @return [Spec[]]
40
21
  attribute :spec, Spec
41
22
 
42
- # Change spec's present in `injections` and resolves.
43
- #
44
- # @param middleware_specifications [Array<MiddlewareSpecification>]
45
- # @param injections [Injections[]]
46
- #
47
- # @return [Array<RackSupport::Middleware>]
48
- def self.inject_and_resolve(middleware_specifications, injections)
49
- middleware_specifications.map do |spec|
50
- if injections.key?(spec.name)
51
- spec.with(injections[spec.name])
52
- else
53
- spec
54
- end.call
55
- end.flatten
23
+ def self.inject(middleware_specifications, injections)
24
+ middleware_specifications.map do |middleware_spec|
25
+ inject_middleware(middleware_spec, injections)
26
+ end
27
+ end
28
+
29
+ def self.inject_middleware(middleware_spec, injections)
30
+ name = middleware_spec.name
31
+ if injections.key?(name)
32
+ middleware_spec.with(injections[name])
33
+ else
34
+ middleware_spec
35
+ end
56
36
  end
57
37
 
58
- # Resolves {RackSupport::Middlewares} from given specification.
59
- #
60
- # @return [Array<RackSupport::Middleware>]
61
38
  def call
62
- klass = spec[0]
39
+ klass_or_pipe = spec[0]
63
40
  options = spec[1..] || Types::EMPTY_ARRAY
64
- case klass
65
- when WebPipe
66
- klass.middlewares
67
- when Class
68
- [Middleware.new(middleware: klass, options: options)]
41
+ if klass_or_pipe.respond_to?(:to_middlewares)
42
+ klass_or_pipe.to_middlewares
43
+ elsif klass_or_pipe.is_a?(Class)
44
+ [Middleware.new(middleware: klass_or_pipe, options: options)]
69
45
  end
70
46
  end
71
47
 
72
- # Returns new instance with {#spec} replaced.
73
- #
74
- # @param new_spec [Spec[]]
75
- #
76
- # @return [MiddlewareSpecification]
77
48
  def with(new_spec)
78
49
  new(spec: new_spec)
79
50
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'web_pipe/conn_support/builder'
4
+ require 'rack/mock'
5
+
6
+ module WebPipe
7
+ # Test helper methods.
8
+ #
9
+ # This module is meant to be included in a test file to provide helper
10
+ # methods.
11
+ module TestSupport
12
+ # Builds a {WebPipe::Conn}
13
+ #
14
+ # @param uri [String] URI that will be used to populate the request
15
+ # attributes
16
+ # @param attributes [Hash<Symbol, Any>] Manually set attributes for the
17
+ # struct. It overrides what is taken from the `uri` parameter
18
+ # @param env_opts [Hash] Options to be added to the `env` from which the
19
+ # connection struct is created. See {Rack::MockRequest.env_for}.
20
+ # @return [Conn]
21
+ def build_conn(uri = '', attributes: {}, env_opts: {})
22
+ env = Rack::MockRequest.env_for(uri, env_opts)
23
+ ConnSupport::Builder
24
+ .call(env)
25
+ .new(attributes)
26
+ end
27
+ end
28
+ end
@@ -4,11 +4,9 @@ require 'dry/types'
4
4
  require 'dry/core/constants'
5
5
 
6
6
  module WebPipe
7
- # Namespace for generic library types.
7
+ # Namespace for generic types.
8
8
  module Types
9
9
  include Dry.Types()
10
10
  include Dry::Core::Constants
11
-
12
- Container = Interface(:[])
13
11
  end
14
12
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebPipe
4
- VERSION = '0.13.0'
4
+ VERSION = '0.16.0'
5
5
  end