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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -1
- data/CHANGELOG.md +29 -0
- data/Gemfile +2 -2
- data/README.md +18 -11
- data/docs/building_a_rack_application.md +1 -1
- data/docs/composing_applications.md +4 -4
- data/docs/connection_struct/configuring_the_connection_struct.md +4 -4
- data/docs/connection_struct/halting_the_pipe.md +17 -19
- data/docs/connection_struct/sharing_data_downstream.md +9 -8
- data/docs/connection_struct.md +22 -19
- data/docs/design_model.md +10 -9
- data/docs/dsl_free_usage.md +85 -14
- data/docs/extensions/container.md +9 -10
- data/docs/extensions/cookies.md +4 -2
- data/docs/extensions/dry_schema.md +5 -4
- data/docs/extensions/flash.md +9 -11
- data/docs/extensions/{dry_view.md → hanami_view.md} +20 -22
- data/docs/extensions/not_found.md +40 -0
- data/docs/extensions/params.md +6 -4
- data/docs/extensions/rails.md +31 -38
- data/docs/extensions/redirect.md +5 -4
- data/docs/extensions/router_params.md +5 -5
- data/docs/extensions/session.md +4 -4
- data/docs/extensions/url.md +6 -6
- data/docs/extensions.md +5 -6
- data/docs/introduction.md +7 -7
- data/docs/plugging_operations/composing_operations.md +3 -3
- data/docs/plugging_operations/injecting_operations.md +4 -4
- data/docs/plugging_operations/inspecting_operations.md +24 -0
- data/docs/plugging_operations/resolving_operations.md +3 -3
- data/docs/plugging_operations.md +3 -3
- data/docs/plugs/config.md +1 -1
- data/docs/plugs/content_type.md +2 -1
- data/docs/plugs.md +6 -7
- data/docs/recipes/hanami_2_and_dry_rb_integration.md +12 -0
- data/docs/recipes/hanami_router_integration.md +3 -1
- data/docs/recipes/using_all_restful_methods.md +6 -5
- data/docs/testing.md +64 -0
- data/docs/using_rack_middlewares/composing_middlewares.md +2 -3
- data/docs/using_rack_middlewares/injecting_middlewares.md +6 -6
- data/docs/using_rack_middlewares/inspecting_middlewares.md +35 -0
- data/docs/using_rack_middlewares.md +6 -6
- data/lib/web_pipe/app.rb +22 -25
- data/lib/web_pipe/conn.rb +0 -1
- data/lib/web_pipe/conn_support/builder.rb +0 -7
- data/lib/web_pipe/conn_support/composition.rb +3 -26
- data/lib/web_pipe/conn_support/errors.rb +5 -5
- data/lib/web_pipe/conn_support/headers.rb +1 -50
- data/lib/web_pipe/conn_support/types.rb +3 -3
- data/lib/web_pipe/dsl/builder.rb +10 -19
- data/lib/web_pipe/dsl/class_context.rb +15 -40
- data/lib/web_pipe/dsl/instance_context.rb +53 -0
- data/lib/web_pipe/extensions/container/container.rb +2 -15
- data/lib/web_pipe/extensions/cookies/cookies.rb +2 -31
- data/lib/web_pipe/extensions/dry_schema/dry_schema.rb +2 -56
- data/lib/web_pipe/extensions/flash/flash.rb +2 -32
- data/lib/web_pipe/extensions/hanami_view/hanami_view.rb +67 -0
- data/lib/web_pipe/extensions/not_found/not_found.rb +26 -0
- data/lib/web_pipe/extensions/params/params.rb +2 -63
- data/lib/web_pipe/extensions/rails/rails.rb +2 -123
- data/lib/web_pipe/extensions/redirect/redirect.rb +2 -20
- data/lib/web_pipe/extensions/router_params/router_params.rb +1 -39
- data/lib/web_pipe/extensions/session/session.rb +2 -25
- data/lib/web_pipe/extensions/url/url.rb +2 -5
- data/lib/web_pipe/pipe.rb +229 -0
- data/lib/web_pipe/plug.rb +31 -65
- data/lib/web_pipe/plugs/config.rb +0 -2
- data/lib/web_pipe/plugs/content_type.rb +0 -2
- data/lib/web_pipe/rack_support/app_with_middlewares.rb +3 -26
- data/lib/web_pipe/rack_support/middleware.rb +2 -2
- data/lib/web_pipe/rack_support/middleware_specification.rb +19 -48
- data/lib/web_pipe/test_support.rb +28 -0
- data/lib/web_pipe/types.rb +1 -3
- data/lib/web_pipe/version.rb +1 -1
- data/lib/web_pipe.rb +77 -17
- data/web_pipe.gemspec +1 -2
- metadata +16 -9
- data/docs/recipes/dry_rb_integration.md +0 -18
- data/lib/web_pipe/dsl/dsl_context.rb +0 -85
- data/lib/web_pipe/dsl/instance_methods.rb +0 -114
- data/lib/web_pipe/extensions/dry_view/dry_view.rb +0 -158
data/lib/web_pipe.rb
CHANGED
@@ -1,23 +1,83 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'dry/core/extensions'
|
3
4
|
require 'web_pipe/dsl/builder'
|
4
5
|
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# Entry-point for the DSL layer.
|
7
|
+
#
|
8
|
+
# Including this module into your class adds to it a DSL layer which makes it
|
9
|
+
# convenient to interact with an instance of {WebPipe::Pipe} transparently. It
|
10
|
+
# means that the DSL is actually an optional layer, and you can achieve
|
11
|
+
# everything by using {WebPipe::Pipe} instances.
|
12
|
+
#
|
13
|
+
# Your class gets access to {WebPipe::DSL::ClassContext::DSL_METHODS} at the
|
14
|
+
# class level, while {WebPipe::DSL::InstanceContext::PIPE_METHODS} are available
|
15
|
+
# for every instance of it. Both groups of methods are delegating to
|
16
|
+
# {WebPipe::Pipe}, so you can look there for documentation.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# class HelloWorld
|
20
|
+
# include WebPipe
|
21
|
+
#
|
22
|
+
# use :runtime, Rack::Runtime
|
23
|
+
#
|
24
|
+
# plug :content_type do |conn|
|
25
|
+
# conn.add_response_header('Content-Type', 'plain/text')
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# plug :render do |conn|
|
29
|
+
# conn.set_response_body('Hello, World!')
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# The instance of your class is itself the final rack application. When you
|
34
|
+
# initialize it, you have the chance to inject different plugs or middlewares
|
35
|
+
# from those defined at the class level.
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# HelloWorld.new(
|
39
|
+
# middlewares: {
|
40
|
+
# runtime: [Class.new do
|
41
|
+
# def initialize(app)
|
42
|
+
# @app = app
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# def call(env)
|
46
|
+
# status, headers, body = @app.call(env)
|
47
|
+
# [status, headers.merge('Injected' => '1'), body]
|
48
|
+
# end
|
49
|
+
# end]
|
50
|
+
# },
|
51
|
+
# plugs: {
|
52
|
+
# render: ->(conn) { conn.set_response_body('Injected!') }
|
53
|
+
# }
|
54
|
+
# )
|
8
55
|
module WebPipe
|
9
56
|
extend Dry::Core::Extensions
|
10
57
|
|
11
|
-
#
|
12
|
-
#
|
58
|
+
# Called via {Module#include}, makes available web_pipe's DSL.
|
59
|
+
#
|
60
|
+
# Includes an instance of `Builder`. That means that `Builder#included` is
|
61
|
+
# eventually called.
|
13
62
|
def self.included(klass)
|
14
63
|
klass.include(call)
|
15
64
|
end
|
16
65
|
|
66
|
+
# Chained to {Module#include} to make the DSL available and provide options.
|
67
|
+
#
|
68
|
+
# @param container [#[]] Container from where resolve operations. See
|
69
|
+
# {WebPipe::Plug}.
|
70
|
+
#
|
71
|
+
# @example
|
72
|
+
# include WebPipe.call(container: Container)
|
17
73
|
def self.call(**opts)
|
18
74
|
DSL::Builder.new(**opts)
|
19
75
|
end
|
20
76
|
|
77
|
+
register_extension :container do
|
78
|
+
require 'web_pipe/extensions/container/container'
|
79
|
+
end
|
80
|
+
|
21
81
|
register_extension :cookies do
|
22
82
|
require 'web_pipe/extensions/cookies/cookies'
|
23
83
|
end
|
@@ -27,24 +87,16 @@ module WebPipe
|
|
27
87
|
require 'web_pipe/extensions/dry_schema/plugs/sanitize_params'
|
28
88
|
end
|
29
89
|
|
30
|
-
register_extension :dry_view do
|
31
|
-
require 'web_pipe/extensions/dry_view/dry_view'
|
32
|
-
end
|
33
|
-
|
34
|
-
register_extension :container do
|
35
|
-
require 'web_pipe/extensions/container/container'
|
36
|
-
end
|
37
|
-
|
38
90
|
register_extension :flash do
|
39
91
|
require 'web_pipe/extensions/flash/flash'
|
40
92
|
end
|
41
93
|
|
42
|
-
register_extension :
|
43
|
-
require 'web_pipe/extensions/
|
94
|
+
register_extension :hanami_view do
|
95
|
+
require 'web_pipe/extensions/hanami_view/hanami_view'
|
44
96
|
end
|
45
97
|
|
46
|
-
register_extension :
|
47
|
-
require 'web_pipe/extensions/
|
98
|
+
register_extension :not_found do
|
99
|
+
require 'web_pipe/extensions/not_found/not_found'
|
48
100
|
end
|
49
101
|
|
50
102
|
register_extension :params do
|
@@ -55,6 +107,14 @@ module WebPipe
|
|
55
107
|
require 'web_pipe/extensions/rails/rails'
|
56
108
|
end
|
57
109
|
|
110
|
+
register_extension :redirect do
|
111
|
+
require 'web_pipe/extensions/redirect/redirect'
|
112
|
+
end
|
113
|
+
|
114
|
+
register_extension :router_params do
|
115
|
+
require 'web_pipe/extensions/router_params/router_params'
|
116
|
+
end
|
117
|
+
|
58
118
|
register_extension :session do
|
59
119
|
require 'web_pipe/extensions/session/session'
|
60
120
|
end
|
data/web_pipe.gemspec
CHANGED
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
|
13
13
|
spec.summary = 'Rack application builder through a pipe of operations on an immutable struct.'
|
14
14
|
spec.homepage = 'https://github.com/waiting-for-dev/web_pipe'
|
15
|
+
spec.licenses = ['MIT']
|
15
16
|
|
16
17
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
18
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
@@ -43,8 +44,6 @@ Gem::Specification.new do |spec|
|
|
43
44
|
spec.add_development_dependency 'bundler'
|
44
45
|
spec.add_development_dependency 'dry-schema', '~> 1.0'
|
45
46
|
spec.add_development_dependency 'dry-transformer', '~> 0.1'
|
46
|
-
# TODO: Readd when dry-rb 0.8 is released (ruby 3.0 support)
|
47
|
-
# spec.add_development_dependency 'dry-view', '~> 0.8'
|
48
47
|
spec.add_development_dependency 'pry-byebug'
|
49
48
|
spec.add_development_dependency 'rack-flash3', '~> 1.0'
|
50
49
|
spec.add_development_dependency 'rack-test', '~> 1.1'
|
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.16.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: 2021-
|
11
|
+
date: 2021-11-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-monads
|
@@ -277,8 +277,9 @@ files:
|
|
277
277
|
- docs/extensions/container.md
|
278
278
|
- docs/extensions/cookies.md
|
279
279
|
- docs/extensions/dry_schema.md
|
280
|
-
- docs/extensions/dry_view.md
|
281
280
|
- docs/extensions/flash.md
|
281
|
+
- docs/extensions/hanami_view.md
|
282
|
+
- docs/extensions/not_found.md
|
282
283
|
- docs/extensions/params.md
|
283
284
|
- docs/extensions/rails.md
|
284
285
|
- docs/extensions/redirect.md
|
@@ -289,16 +290,19 @@ files:
|
|
289
290
|
- docs/plugging_operations.md
|
290
291
|
- docs/plugging_operations/composing_operations.md
|
291
292
|
- docs/plugging_operations/injecting_operations.md
|
293
|
+
- docs/plugging_operations/inspecting_operations.md
|
292
294
|
- docs/plugging_operations/resolving_operations.md
|
293
295
|
- docs/plugs.md
|
294
296
|
- docs/plugs/config.md
|
295
297
|
- docs/plugs/content_type.md
|
296
|
-
- docs/recipes/
|
298
|
+
- docs/recipes/hanami_2_and_dry_rb_integration.md
|
297
299
|
- docs/recipes/hanami_router_integration.md
|
298
300
|
- docs/recipes/using_all_restful_methods.md
|
301
|
+
- docs/testing.md
|
299
302
|
- docs/using_rack_middlewares.md
|
300
303
|
- docs/using_rack_middlewares/composing_middlewares.md
|
301
304
|
- docs/using_rack_middlewares/injecting_middlewares.md
|
305
|
+
- docs/using_rack_middlewares/inspecting_middlewares.md
|
302
306
|
- lib/web_pipe.rb
|
303
307
|
- lib/web_pipe/app.rb
|
304
308
|
- lib/web_pipe/conn.rb
|
@@ -309,14 +313,14 @@ files:
|
|
309
313
|
- lib/web_pipe/conn_support/types.rb
|
310
314
|
- lib/web_pipe/dsl/builder.rb
|
311
315
|
- lib/web_pipe/dsl/class_context.rb
|
312
|
-
- lib/web_pipe/dsl/
|
313
|
-
- lib/web_pipe/dsl/instance_methods.rb
|
316
|
+
- lib/web_pipe/dsl/instance_context.rb
|
314
317
|
- lib/web_pipe/extensions/container/container.rb
|
315
318
|
- lib/web_pipe/extensions/cookies/cookies.rb
|
316
319
|
- lib/web_pipe/extensions/dry_schema/dry_schema.rb
|
317
320
|
- lib/web_pipe/extensions/dry_schema/plugs/sanitize_params.rb
|
318
|
-
- lib/web_pipe/extensions/dry_view/dry_view.rb
|
319
321
|
- lib/web_pipe/extensions/flash/flash.rb
|
322
|
+
- lib/web_pipe/extensions/hanami_view/hanami_view.rb
|
323
|
+
- lib/web_pipe/extensions/not_found/not_found.rb
|
320
324
|
- lib/web_pipe/extensions/params/params.rb
|
321
325
|
- lib/web_pipe/extensions/params/params/transf.rb
|
322
326
|
- lib/web_pipe/extensions/rails/rails.rb
|
@@ -324,6 +328,7 @@ files:
|
|
324
328
|
- lib/web_pipe/extensions/router_params/router_params.rb
|
325
329
|
- lib/web_pipe/extensions/session/session.rb
|
326
330
|
- lib/web_pipe/extensions/url/url.rb
|
331
|
+
- lib/web_pipe/pipe.rb
|
327
332
|
- lib/web_pipe/plug.rb
|
328
333
|
- lib/web_pipe/plugs.rb
|
329
334
|
- lib/web_pipe/plugs/config.rb
|
@@ -331,11 +336,13 @@ files:
|
|
331
336
|
- lib/web_pipe/rack_support/app_with_middlewares.rb
|
332
337
|
- lib/web_pipe/rack_support/middleware.rb
|
333
338
|
- lib/web_pipe/rack_support/middleware_specification.rb
|
339
|
+
- lib/web_pipe/test_support.rb
|
334
340
|
- lib/web_pipe/types.rb
|
335
341
|
- lib/web_pipe/version.rb
|
336
342
|
- web_pipe.gemspec
|
337
343
|
homepage: https://github.com/waiting-for-dev/web_pipe
|
338
|
-
licenses:
|
344
|
+
licenses:
|
345
|
+
- MIT
|
339
346
|
metadata:
|
340
347
|
allowed_push_host: https://rubygems.org
|
341
348
|
homepage_uri: https://github.com/waiting-for-dev/web_pipe
|
@@ -356,7 +363,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
356
363
|
- !ruby/object:Gem::Version
|
357
364
|
version: '0'
|
358
365
|
requirements: []
|
359
|
-
rubygems_version: 3.2
|
366
|
+
rubygems_version: 3.1.2
|
360
367
|
signing_key:
|
361
368
|
specification_version: 4
|
362
369
|
summary: Rack application builder through a pipe of operations on an immutable struct.
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# dry-rb integration
|
2
|
-
|
3
|
-
`web_pipe` has been designed to integrate smoothly with
|
4
|
-
[dry-rb](https://dry-rb.org/) ecosystem. It shares same design
|
5
|
-
principles and it ships with some extensions which even make this
|
6
|
-
integration tighter (like
|
7
|
-
[`:dry-view`](../extensions/dry_view.md) or
|
8
|
-
[`:dry-schema`](../extensions/dry_schema.md) extensions).
|
9
|
-
|
10
|
-
If you want to use `web_pipe` with the rest of dry-rb libraries,
|
11
|
-
your best bet is to use
|
12
|
-
[`dry-web-web_pipe`](https://github.com/waiting-for-dev/dry-web-web_pipe)
|
13
|
-
skeleton generator. It is a fork of
|
14
|
-
[`dry-web-roda`](https://github.com/dry-rb/dry-web-roda) with
|
15
|
-
`roda` dependency switched to a combination of `web_pipe` and
|
16
|
-
[`hanami-router`](https://github.com/hanami/router).
|
17
|
-
|
18
|
-
Look at `dry-web-web_pipe` README for more details.
|
@@ -1,85 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'web_pipe'
|
4
|
-
require 'web_pipe/types'
|
5
|
-
require 'web_pipe/plug'
|
6
|
-
require 'web_pipe/rack_support/middleware_specification'
|
7
|
-
|
8
|
-
module WebPipe
|
9
|
-
module DSL
|
10
|
-
# Defines the DSL for the pipe class and keeps it state.
|
11
|
-
#
|
12
|
-
# This allows adding rack middlewares and plugs at the class
|
13
|
-
# definition level.
|
14
|
-
#
|
15
|
-
# @api private
|
16
|
-
class DSLContext
|
17
|
-
# @!attribute middleware_specifications
|
18
|
-
# @return [Array<RackSupport::MiddlewareSpecifications>]
|
19
|
-
attr_reader :middleware_specifications
|
20
|
-
|
21
|
-
# @!attribute plugs
|
22
|
-
# @return [Array<Plug>]
|
23
|
-
attr_reader :plugs
|
24
|
-
|
25
|
-
def initialize(middleware_specifications, plugs)
|
26
|
-
@middleware_specifications = Types.Array(
|
27
|
-
RackSupport::MiddlewareSpecification
|
28
|
-
)[middleware_specifications]
|
29
|
-
@plugs = Types.Array(Plug::Instance)[plugs]
|
30
|
-
end
|
31
|
-
|
32
|
-
# Creates and add rack middleware specifications to the stack.
|
33
|
-
#
|
34
|
-
# The spec can be given in two forms:
|
35
|
-
#
|
36
|
-
# - As one or two arguments, first one being a
|
37
|
-
# rack middleware class and second one optionally its
|
38
|
-
# initialization options.
|
39
|
-
# - As a {WebPipe} class instance, in which case all its rack
|
40
|
-
# middlewares will be considered.
|
41
|
-
#
|
42
|
-
# @param name [RackSupport::MiddlewareSpecification::Name[]]
|
43
|
-
# @param spec [RackSupport::MiddlewareSpecification::Spec[]]
|
44
|
-
#
|
45
|
-
# @return [Array<RackSupport::Middleware>]
|
46
|
-
def use(name, *spec)
|
47
|
-
middleware_specifications << RackSupport::MiddlewareSpecification.new(name: name, spec: spec)
|
48
|
-
end
|
49
|
-
|
50
|
-
# Creates and adds a plug to the stack.
|
51
|
-
#
|
52
|
-
# The spec can be given as a {Plug::Spec}, as a block (which
|
53
|
-
# is captured into a {Proc}, one of the options for a
|
54
|
-
# {Plug::Spec} or as a {WebPipe} (in which case all its plugs
|
55
|
-
# will be composed).
|
56
|
-
#
|
57
|
-
# @param name [Plug::Name[]]
|
58
|
-
# @param spec [Plug::Spec[], WebPipe]
|
59
|
-
# @param block_spec [Proc]
|
60
|
-
#
|
61
|
-
# @return [Array<Plug>]
|
62
|
-
def plug(name, spec = nil, &block_spec)
|
63
|
-
plug_spec = if spec.is_a?(WebPipe)
|
64
|
-
spec.to_proc
|
65
|
-
elsif spec
|
66
|
-
spec
|
67
|
-
else
|
68
|
-
block_spec
|
69
|
-
end
|
70
|
-
|
71
|
-
plugs << Plug.new(name: name, spec: plug_spec)
|
72
|
-
end
|
73
|
-
|
74
|
-
# Adds middlewares and plugs from a WebPipe to respective
|
75
|
-
# stacks.
|
76
|
-
#
|
77
|
-
# @param name [Plug::Name[], Middleware::Name[]]
|
78
|
-
# @param spec [WebPipe]
|
79
|
-
def compose(name, spec)
|
80
|
-
use(name, spec)
|
81
|
-
plug(name, spec)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
@@ -1,114 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'web_pipe/types'
|
4
|
-
require 'web_pipe/conn'
|
5
|
-
require 'web_pipe/app'
|
6
|
-
require 'web_pipe/plug'
|
7
|
-
require 'web_pipe/rack_support/app_with_middlewares'
|
8
|
-
require 'web_pipe/rack_support/middleware_specification'
|
9
|
-
require 'web_pipe/conn_support/composition'
|
10
|
-
|
11
|
-
module WebPipe
|
12
|
-
module DSL
|
13
|
-
# Instance methods for the pipe.
|
14
|
-
#
|
15
|
-
# It is from here that you get the rack application you can route
|
16
|
-
# to. The initialization phase gives you the chance to inject any
|
17
|
-
# of the plugs or middlewares, while the instance you get has the
|
18
|
-
# `#call` method expected by rack.
|
19
|
-
#
|
20
|
-
# The pipe state can be accessed through the pipe class, which
|
21
|
-
# has been configured through {ClassContext}.
|
22
|
-
#
|
23
|
-
# @api private
|
24
|
-
module InstanceMethods
|
25
|
-
# No injections at all.
|
26
|
-
EMPTY_INJECTIONS = {
|
27
|
-
plugs: Types::EMPTY_HASH,
|
28
|
-
middlewares: Types::EMPTY_HASH
|
29
|
-
}.freeze
|
30
|
-
|
31
|
-
# Type for how plugs and middlewares should be injected.
|
32
|
-
Injections = Types::Strict::Hash.schema(
|
33
|
-
plugs: Plug::Injections,
|
34
|
-
middlewares: RackSupport::MiddlewareSpecification::Injections
|
35
|
-
)
|
36
|
-
|
37
|
-
# @!attribute [r] injections [Injections[]]
|
38
|
-
# Injected plugs and middlewares that allow overriding what
|
39
|
-
# has been configured.
|
40
|
-
attr_reader :injections
|
41
|
-
|
42
|
-
# @return [RackSupport::AppWithMiddlewares[]]
|
43
|
-
attr_reader :rack_app
|
44
|
-
|
45
|
-
# @return [ConnSupport::Composition::Operation[]]
|
46
|
-
attr_reader :operations
|
47
|
-
|
48
|
-
# @return [Array<RackSupport::Middlewares>]
|
49
|
-
attr_reader :middlewares
|
50
|
-
|
51
|
-
# rubocop:disable Metrics/AbcSize
|
52
|
-
def initialize(injects = EMPTY_INJECTIONS)
|
53
|
-
@injections = Injections[injects]
|
54
|
-
container = self.class.container
|
55
|
-
@middlewares = RackSupport::MiddlewareSpecification.inject_and_resolve(
|
56
|
-
self.class.middleware_specifications, injections[:middlewares]
|
57
|
-
)
|
58
|
-
@operations = Plug.inject_and_resolve(
|
59
|
-
self.class.plugs, injections[:plugs], container, self
|
60
|
-
)
|
61
|
-
app = App.new(operations)
|
62
|
-
@rack_app = RackSupport::AppWithMiddlewares.new(middlewares, app)
|
63
|
-
end
|
64
|
-
# rubocop:enable Metrics/AbcSize
|
65
|
-
|
66
|
-
# Expected interface for rack.
|
67
|
-
#
|
68
|
-
# @param env [Hash] Rack env
|
69
|
-
#
|
70
|
-
# @return [Array] Rack response
|
71
|
-
def call(env)
|
72
|
-
rack_app.call(env)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Proc for the composition of all operations.
|
76
|
-
#
|
77
|
-
# This can be used to plug a {WebPipe} itself as an operation.
|
78
|
-
#
|
79
|
-
# @example
|
80
|
-
# class HtmlApp
|
81
|
-
# include WebPipe
|
82
|
-
#
|
83
|
-
# plug :html
|
84
|
-
#
|
85
|
-
# private
|
86
|
-
#
|
87
|
-
# def html(conn)
|
88
|
-
# conn.add_response_header('Content-Type', 'text/html')
|
89
|
-
# end
|
90
|
-
# end
|
91
|
-
#
|
92
|
-
# class App
|
93
|
-
# include WebPipe
|
94
|
-
#
|
95
|
-
# plug :html, &HtmlApp.new
|
96
|
-
# plug :body
|
97
|
-
#
|
98
|
-
# private
|
99
|
-
#
|
100
|
-
# def body(conn)
|
101
|
-
# conn.set_response_body('Hello, world!')
|
102
|
-
# end
|
103
|
-
# end
|
104
|
-
#
|
105
|
-
# @see ConnSupport::Composition
|
106
|
-
def to_proc
|
107
|
-
ConnSupport::Composition
|
108
|
-
.new(operations)
|
109
|
-
.method(:call)
|
110
|
-
.to_proc
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
@@ -1,158 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'web_pipe/types'
|
4
|
-
require 'web_pipe/conn'
|
5
|
-
require 'dry/view'
|
6
|
-
|
7
|
-
#:nodoc:
|
8
|
-
module WebPipe
|
9
|
-
# Integration with `dry-view` rendering system.
|
10
|
-
#
|
11
|
-
# This extensions adds a {#view} method to {WebPipe::Conn} which
|
12
|
-
# sets the string output of a `dry-view` view as response body.
|
13
|
-
#
|
14
|
-
# @example
|
15
|
-
# WebPipe.load_extensions(:dry_view)
|
16
|
-
#
|
17
|
-
# class SayHelloView < Dry::View
|
18
|
-
# config.paths = [File.join(__dir__, '..', 'templates')]
|
19
|
-
# config.template = 'say_hello'
|
20
|
-
#
|
21
|
-
# expose :name
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# class App
|
25
|
-
# include WebPipe
|
26
|
-
#
|
27
|
-
# plug :render
|
28
|
-
#
|
29
|
-
# def render(conn)
|
30
|
-
# conn.view(SayHello.new, name: 'Joe')
|
31
|
-
# end
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# If there is a `:container` configured (in {Conn#config}), the view
|
35
|
-
# instance can be resolved from it.
|
36
|
-
#
|
37
|
-
# @example
|
38
|
-
# WebPipe.load_extensions(:dry_view, :container)
|
39
|
-
#
|
40
|
-
# class App
|
41
|
-
# include WebPipe
|
42
|
-
#
|
43
|
-
# Container = { 'views.say_hello' => SayHelloView.new }.freeze
|
44
|
-
#
|
45
|
-
# plug :config_container, ->(conn) { conn.add_config(:container, Container) }
|
46
|
-
# plug :render
|
47
|
-
#
|
48
|
-
# def render(conn)
|
49
|
-
# conn.view('views.say_hello', name: 'Joe')
|
50
|
-
# end
|
51
|
-
# end
|
52
|
-
#
|
53
|
-
# Context ({Dry::View::Context}) for the view can be set explicetly
|
54
|
-
# through the `context:` argument, as in a standard call to
|
55
|
-
# {Dry::View#call}. However, it is possible to leverage configured
|
56
|
-
# default context while still being able to inject request specific
|
57
|
-
# context. For that to work, `:view_context` should be present in
|
58
|
-
# {WebPipe::Conn#config}. Its value must be a lambda accepting the
|
59
|
-
# {Conn} instance and returning a hash, which will be passed to
|
60
|
-
# {Dry::View::Context#with} to create the final context at the
|
61
|
-
# moment {#view} is called.
|
62
|
-
#
|
63
|
-
# @example
|
64
|
-
# class MyContext < Dry::View::Context
|
65
|
-
# attr_reader :current_path
|
66
|
-
#
|
67
|
-
# def initialize(current_path: nil, **options)
|
68
|
-
# @current_path = current_path
|
69
|
-
# super
|
70
|
-
# end
|
71
|
-
# end
|
72
|
-
#
|
73
|
-
# class SayHelloView < Dry::View
|
74
|
-
# config.paths = [File.join(__dir__, '..', 'templates')]
|
75
|
-
# config.template = 'say_hello'
|
76
|
-
# config.default_context = MyContext.new
|
77
|
-
#
|
78
|
-
# expose :name
|
79
|
-
# end
|
80
|
-
#
|
81
|
-
# WebPipe.load_extensions(:url)
|
82
|
-
#
|
83
|
-
# class App
|
84
|
-
# include WebPipe
|
85
|
-
#
|
86
|
-
# plug :config_view_context
|
87
|
-
# plug :render
|
88
|
-
#
|
89
|
-
# def config_view_context(conn)
|
90
|
-
# conn.add_config(:view_context, ->(conn) { { current_path: conn.full_path } })
|
91
|
-
# end
|
92
|
-
#
|
93
|
-
# def render(conn)
|
94
|
-
# conn.view(SayHelloView.new, name: 'Joe') # `current_path`
|
95
|
-
# # will be available in the view scope
|
96
|
-
# end
|
97
|
-
# end
|
98
|
-
#
|
99
|
-
# @see https://dry-rb.org/gems/dry-view/
|
100
|
-
# @see WebPipe::Container
|
101
|
-
module DryView
|
102
|
-
# Where to find in {#config} request's view context generator.
|
103
|
-
VIEW_CONTEXT_KEY = :view_context
|
104
|
-
|
105
|
-
# Default request's view context
|
106
|
-
DEFAULT_VIEW_CONTEXT = ->(_conn) { Types::EMPTY_HASH }
|
107
|
-
|
108
|
-
# Sets string output of a view as response body.
|
109
|
-
#
|
110
|
-
# If the view is not a {Dry::View} instance, it is resolved from
|
111
|
-
# the configured container.
|
112
|
-
#
|
113
|
-
# `kwargs` is used as the input for the view (the arguments that
|
114
|
-
# {Dry::View#call} receives). If they doesn't contain an explicit
|
115
|
-
# `context:` key, it can be added through the injection of the
|
116
|
-
# result of a lambda present in context's `:view_context`.(see
|
117
|
-
# {Dry::View::Context#with}).
|
118
|
-
#
|
119
|
-
# @param view_spec [Dry::View, Any]
|
120
|
-
# @param kwargs [Hash] Arguments to pass along to `Dry::View#call`
|
121
|
-
#
|
122
|
-
# @return WebPipe::Conn
|
123
|
-
def view(view_spec, **kwargs)
|
124
|
-
view_instance = view_instance(view_spec)
|
125
|
-
view_input = view_input(kwargs, view_instance)
|
126
|
-
|
127
|
-
set_response_body(
|
128
|
-
view_instance.call(
|
129
|
-
**view_input
|
130
|
-
).to_str
|
131
|
-
)
|
132
|
-
end
|
133
|
-
|
134
|
-
private
|
135
|
-
|
136
|
-
def view_instance(view_spec)
|
137
|
-
return view_spec if view_spec.is_a?(Dry::View)
|
138
|
-
|
139
|
-
fetch_config(:container)[view_spec]
|
140
|
-
end
|
141
|
-
|
142
|
-
def view_input(kwargs, view_instance)
|
143
|
-
return kwargs if kwargs.key?(:context)
|
144
|
-
|
145
|
-
context = view_instance
|
146
|
-
.config
|
147
|
-
.default_context
|
148
|
-
.with(
|
149
|
-
**fetch_config(
|
150
|
-
VIEW_CONTEXT_KEY, DEFAULT_VIEW_CONTEXT
|
151
|
-
).call(self)
|
152
|
-
)
|
153
|
-
kwargs.merge(context: context)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
Conn.include(DryView)
|
158
|
-
end
|