evil-client 0.3.3 → 1.0.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 (180) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +0 -11
  3. data/.gitignore +1 -0
  4. data/.rspec +0 -1
  5. data/.rubocop.yml +22 -19
  6. data/.travis.yml +1 -0
  7. data/CHANGELOG.md +251 -6
  8. data/LICENSE.txt +3 -1
  9. data/README.md +47 -81
  10. data/docs/helpers/body.md +93 -0
  11. data/docs/helpers/connection.md +19 -0
  12. data/docs/helpers/headers.md +72 -0
  13. data/docs/helpers/http_method.md +39 -0
  14. data/docs/helpers/let.md +14 -0
  15. data/docs/helpers/logger.md +24 -0
  16. data/docs/helpers/middleware.md +56 -0
  17. data/docs/helpers/operation.md +103 -0
  18. data/docs/helpers/option.md +50 -0
  19. data/docs/helpers/path.md +37 -0
  20. data/docs/helpers/query.md +59 -0
  21. data/docs/helpers/response.md +40 -0
  22. data/docs/helpers/scope.md +121 -0
  23. data/docs/helpers/security.md +102 -0
  24. data/docs/helpers/validate.md +68 -0
  25. data/docs/index.md +70 -78
  26. data/docs/license.md +5 -1
  27. data/docs/rspec.md +96 -0
  28. data/evil-client.gemspec +10 -8
  29. data/lib/evil/client.rb +126 -72
  30. data/lib/evil/client/builder.rb +47 -0
  31. data/lib/evil/client/builder/operation.rb +40 -0
  32. data/lib/evil/client/builder/scope.rb +31 -0
  33. data/lib/evil/client/chaining.rb +17 -0
  34. data/lib/evil/client/connection.rb +60 -20
  35. data/lib/evil/client/container.rb +66 -0
  36. data/lib/evil/client/container/operation.rb +23 -0
  37. data/lib/evil/client/container/scope.rb +28 -0
  38. data/lib/evil/client/exceptions/definition_error.rb +15 -0
  39. data/lib/evil/client/exceptions/name_error.rb +32 -0
  40. data/lib/evil/client/exceptions/response_error.rb +42 -0
  41. data/lib/evil/client/exceptions/type_error.rb +29 -0
  42. data/lib/evil/client/exceptions/validation_error.rb +27 -0
  43. data/lib/evil/client/formatter.rb +49 -0
  44. data/lib/evil/client/formatter/form.rb +45 -0
  45. data/lib/evil/client/formatter/multipart.rb +33 -0
  46. data/lib/evil/client/formatter/part.rb +66 -0
  47. data/lib/evil/client/formatter/text.rb +21 -0
  48. data/lib/evil/client/resolver.rb +84 -0
  49. data/lib/evil/client/resolver/body.rb +22 -0
  50. data/lib/evil/client/resolver/format.rb +30 -0
  51. data/lib/evil/client/resolver/headers.rb +46 -0
  52. data/lib/evil/client/resolver/http_method.rb +34 -0
  53. data/lib/evil/client/resolver/middleware.rb +36 -0
  54. data/lib/evil/client/resolver/query.rb +39 -0
  55. data/lib/evil/client/resolver/request.rb +96 -0
  56. data/lib/evil/client/resolver/response.rb +26 -0
  57. data/lib/evil/client/resolver/security.rb +113 -0
  58. data/lib/evil/client/resolver/uri.rb +35 -0
  59. data/lib/evil/client/rspec.rb +127 -0
  60. data/lib/evil/client/schema.rb +105 -0
  61. data/lib/evil/client/schema/operation.rb +177 -0
  62. data/lib/evil/client/schema/scope.rb +73 -0
  63. data/lib/evil/client/settings.rb +172 -0
  64. data/lib/evil/client/settings/validator.rb +64 -0
  65. data/mkdocs.yml +21 -15
  66. data/spec/features/custom_connection_spec.rb +17 -0
  67. data/spec/features/operation/middleware_spec.rb +50 -0
  68. data/spec/features/operation/options_spec.rb +71 -0
  69. data/spec/features/operation/request_spec.rb +94 -0
  70. data/spec/features/operation/response_spec.rb +48 -0
  71. data/spec/features/scope/options_spec.rb +52 -0
  72. data/spec/fixtures/locales/en.yml +16 -0
  73. data/spec/fixtures/test_client.rb +76 -0
  74. data/spec/spec_helper.rb +18 -6
  75. data/spec/support/fixtures_helper.rb +7 -0
  76. data/spec/unit/builder/operation_spec.rb +90 -0
  77. data/spec/unit/builder/scope_spec.rb +84 -0
  78. data/spec/unit/client_spec.rb +137 -0
  79. data/spec/unit/connection_spec.rb +78 -0
  80. data/spec/unit/container/operation_spec.rb +81 -0
  81. data/spec/unit/container/scope_spec.rb +61 -0
  82. data/spec/unit/container_spec.rb +107 -0
  83. data/spec/unit/exceptions/definition_error_spec.rb +15 -0
  84. data/spec/unit/exceptions/name_error_spec.rb +77 -0
  85. data/spec/unit/exceptions/response_error_spec.rb +22 -0
  86. data/spec/unit/exceptions/type_error_spec.rb +71 -0
  87. data/spec/unit/exceptions/validation_error_spec.rb +13 -0
  88. data/spec/unit/formatter/form_spec.rb +27 -0
  89. data/spec/unit/formatter/multipart_spec.rb +23 -0
  90. data/spec/unit/formatter/part_spec.rb +49 -0
  91. data/spec/unit/formatter/text_spec.rb +37 -0
  92. data/spec/unit/formatter_spec.rb +46 -0
  93. data/spec/unit/resolver/body_spec.rb +65 -0
  94. data/spec/unit/resolver/format_spec.rb +66 -0
  95. data/spec/unit/resolver/headers_spec.rb +93 -0
  96. data/spec/unit/resolver/http_method_spec.rb +67 -0
  97. data/spec/unit/resolver/middleware_spec.rb +83 -0
  98. data/spec/unit/resolver/query_spec.rb +85 -0
  99. data/spec/unit/resolver/request_spec.rb +121 -0
  100. data/spec/unit/resolver/response_spec.rb +64 -0
  101. data/spec/unit/resolver/security_spec.rb +156 -0
  102. data/spec/unit/resolver/uri_spec.rb +117 -0
  103. data/spec/unit/rspec_spec.rb +342 -0
  104. data/spec/unit/schema/operation_spec.rb +309 -0
  105. data/spec/unit/schema/scope_spec.rb +110 -0
  106. data/spec/unit/schema_spec.rb +157 -0
  107. data/spec/unit/settings/validator_spec.rb +128 -0
  108. data/spec/unit/settings_spec.rb +248 -0
  109. metadata +192 -135
  110. data/docs/base_url.md +0 -38
  111. data/docs/documentation.md +0 -9
  112. data/docs/headers.md +0 -59
  113. data/docs/http_method.md +0 -31
  114. data/docs/model.md +0 -173
  115. data/docs/operation.md +0 -0
  116. data/docs/overview.md +0 -0
  117. data/docs/path.md +0 -48
  118. data/docs/query.md +0 -99
  119. data/docs/responses.md +0 -66
  120. data/docs/security.md +0 -102
  121. data/docs/settings.md +0 -32
  122. data/lib/evil/client/connection/net_http.rb +0 -57
  123. data/lib/evil/client/dsl.rb +0 -127
  124. data/lib/evil/client/dsl/base.rb +0 -26
  125. data/lib/evil/client/dsl/files.rb +0 -37
  126. data/lib/evil/client/dsl/headers.rb +0 -16
  127. data/lib/evil/client/dsl/http_method.rb +0 -24
  128. data/lib/evil/client/dsl/operation.rb +0 -91
  129. data/lib/evil/client/dsl/operations.rb +0 -41
  130. data/lib/evil/client/dsl/path.rb +0 -25
  131. data/lib/evil/client/dsl/query.rb +0 -16
  132. data/lib/evil/client/dsl/response.rb +0 -61
  133. data/lib/evil/client/dsl/responses.rb +0 -29
  134. data/lib/evil/client/dsl/scope.rb +0 -27
  135. data/lib/evil/client/dsl/security.rb +0 -57
  136. data/lib/evil/client/dsl/verifier.rb +0 -35
  137. data/lib/evil/client/middleware.rb +0 -81
  138. data/lib/evil/client/middleware/base.rb +0 -11
  139. data/lib/evil/client/middleware/merge_security.rb +0 -20
  140. data/lib/evil/client/middleware/normalize_headers.rb +0 -17
  141. data/lib/evil/client/middleware/stringify_form.rb +0 -40
  142. data/lib/evil/client/middleware/stringify_json.rb +0 -19
  143. data/lib/evil/client/middleware/stringify_multipart.rb +0 -36
  144. data/lib/evil/client/middleware/stringify_multipart/part.rb +0 -36
  145. data/lib/evil/client/middleware/stringify_query.rb +0 -35
  146. data/lib/evil/client/operation.rb +0 -34
  147. data/lib/evil/client/operation/request.rb +0 -26
  148. data/lib/evil/client/operation/response.rb +0 -39
  149. data/lib/evil/client/operation/response_error.rb +0 -13
  150. data/lib/evil/client/operation/unexpected_response_error.rb +0 -19
  151. data/spec/features/instantiation_spec.rb +0 -68
  152. data/spec/features/middleware_spec.rb +0 -79
  153. data/spec/features/operation_with_documentation_spec.rb +0 -41
  154. data/spec/features/operation_with_files_spec.rb +0 -40
  155. data/spec/features/operation_with_form_body_spec.rb +0 -158
  156. data/spec/features/operation_with_headers_spec.rb +0 -99
  157. data/spec/features/operation_with_http_method_spec.rb +0 -45
  158. data/spec/features/operation_with_json_body_spec.rb +0 -156
  159. data/spec/features/operation_with_nested_responses_spec.rb +0 -95
  160. data/spec/features/operation_with_path_spec.rb +0 -47
  161. data/spec/features/operation_with_query_spec.rb +0 -84
  162. data/spec/features/operation_with_security_spec.rb +0 -228
  163. data/spec/features/scoping_spec.rb +0 -48
  164. data/spec/support/test_client.rb +0 -15
  165. data/spec/unit/evil/client/connection/net_http_spec.rb +0 -38
  166. data/spec/unit/evil/client/dsl/files_spec.rb +0 -37
  167. data/spec/unit/evil/client/dsl/operation_spec.rb +0 -374
  168. data/spec/unit/evil/client/dsl/operations_spec.rb +0 -29
  169. data/spec/unit/evil/client/dsl/scope_spec.rb +0 -32
  170. data/spec/unit/evil/client/dsl/security_spec.rb +0 -135
  171. data/spec/unit/evil/client/middleware/merge_security_spec.rb +0 -32
  172. data/spec/unit/evil/client/middleware/normalize_headers_spec.rb +0 -17
  173. data/spec/unit/evil/client/middleware/stringify_form_spec.rb +0 -63
  174. data/spec/unit/evil/client/middleware/stringify_json_spec.rb +0 -61
  175. data/spec/unit/evil/client/middleware/stringify_multipart/part_spec.rb +0 -59
  176. data/spec/unit/evil/client/middleware/stringify_multipart_spec.rb +0 -62
  177. data/spec/unit/evil/client/middleware/stringify_query_spec.rb +0 -40
  178. data/spec/unit/evil/client/middleware_spec.rb +0 -46
  179. data/spec/unit/evil/client/operation/request_spec.rb +0 -49
  180. data/spec/unit/evil/client/operation/response_spec.rb +0 -63
@@ -1,16 +0,0 @@
1
- module Evil::Client::DSL
2
- class Headers < Base
3
- def call(schema)
4
- merge schema, headers: coercer
5
- end
6
-
7
- private
8
-
9
- attr_reader :model, :block
10
-
11
- def initialize(model: Evil::Struct, &block)
12
- @model = model
13
- @block = block
14
- end
15
- end
16
- end
@@ -1,24 +0,0 @@
1
- module Evil::Client::DSL
2
- class HttpMethod < Base
3
- def call(schema)
4
- merge schema, method: http_method
5
- end
6
-
7
- private
8
-
9
- attr_reader :block, :string
10
-
11
- def initialize(string = nil, &block)
12
- @string = string.to_s.downcase
13
- @block = block
14
- end
15
-
16
- def http_method
17
- if block
18
- ->(opts) { block.call(opts).to_s.downcase }
19
- else
20
- proc { string }
21
- end
22
- end
23
- end
24
- end
@@ -1,91 +0,0 @@
1
- module Evil::Client::DSL
2
- class Operation
3
- attr_reader :schema
4
-
5
- def finalize(settings)
6
- @mutex.synchronize do
7
- @schema = @default.dup
8
- instance_exec(settings, &@block) if @block
9
- @schema[:middleware]&.finalize(settings)
10
- @schema
11
- end
12
- end
13
-
14
- private
15
-
16
- def initialize(key, block)
17
- @mutex = Mutex.new
18
- @block = block
19
- @default = { key: key, responses: {} }
20
- end
21
-
22
- # ==========================================================================
23
- # Helper methods that mutate a @schema
24
- # ==========================================================================
25
-
26
- def documentation(value)
27
- @schema[:doc] = value
28
- end
29
-
30
- def http_method(value = nil, &block)
31
- @schema = HttpMethod[schema, value, &block]
32
- end
33
-
34
- def path(value = nil, &block)
35
- @schema = Path[schema, value, &block]
36
- end
37
-
38
- def security(&block)
39
- @schema[:security] = Security.new(&block)
40
- end
41
-
42
- def files(&block)
43
- @schema[:files] = Files.new(&block)
44
- @schema[:format] = "multipart"
45
- @schema.delete :body
46
- end
47
-
48
- def body(format: "json", **options, &block)
49
- @schema[:body] = __model__(options, &block)
50
- @schema[:format] = __valid_format__(format)
51
- @schema.delete :files
52
- end
53
-
54
- def headers(model: Evil::Struct, &block)
55
- @schema = Headers[schema, model: model, &block]
56
- end
57
-
58
- def query(model: Evil::Struct, &block)
59
- @schema = Query[schema, model: model, &block]
60
- end
61
-
62
- def responses(options = {}, &block)
63
- Responses.new(self, options, &block)
64
- end
65
-
66
- def response(name, status, **options, &block)
67
- @schema[:responses][name] = Response[status, block: block, **options]
68
- end
69
-
70
- # ==========================================================================
71
- # Utilities for helpers TODO: extract to a separate module
72
- # ==========================================================================
73
-
74
- def __valid_format__(format)
75
- formats = %w[json form]
76
- return format.to_s if formats.include? format.to_s
77
- raise ArgumentError.new "Invalid format #{format} for body." \
78
- " Use one of formats: #{formats}"
79
- end
80
-
81
- def __model__(model: nil, **, &block)
82
- if model && block
83
- Class.new(model, &block)
84
- elsif block
85
- Class.new(Evil::Struct, &block)
86
- elsif model
87
- model
88
- end
89
- end
90
- end
91
- end
@@ -1,41 +0,0 @@
1
- module Evil::Client::DSL
2
- # Container for operations definitions
3
- # Applies settings to definitions and returns a final schema
4
- class Operations
5
- # Adds block definition as a named operation
6
- #
7
- # @param [#to_sym] key
8
- # @param [Proc] block
9
- # @return [self]
10
- #
11
- def register(key, &block)
12
- @schema[key] = Operation.new(key, block)
13
- self
14
- end
15
-
16
- # Applies settings to all definitions and returns a final schema
17
- #
18
- # @param [Object] settings
19
- # @return [Hash<Symbol, Object>]
20
- #
21
- def finalize(settings)
22
- default = @schema[nil].finalize(settings)
23
- custom = @schema.select { |key| key }
24
-
25
- schema = custom.each_with_object({}) do |(key, operation), hash|
26
- custom = operation.finalize(settings)
27
- hash[key] = default.merge(custom)
28
- hash[key][:format] ||= "json"
29
- hash[key][:responses] = default[:responses].merge(custom[:responses])
30
- end
31
-
32
- Verifier.call(schema)
33
- end
34
-
35
- private
36
-
37
- def initialize
38
- @schema = { nil => Operation.new(nil, nil) }
39
- end
40
- end
41
- end
@@ -1,25 +0,0 @@
1
- module Evil::Client::DSL
2
- # Adds path settings to the operation's schema
3
- class Path < Base
4
- def call(schema)
5
- merge schema, path: path
6
- end
7
-
8
- private
9
-
10
- SLASHES = %r{\A/+|/+\z}
11
-
12
- attr_reader :block, :value
13
-
14
- def initialize(value = nil, &block)
15
- @value = value.to_s.gsub(SLASHES, "")
16
- @block = block
17
- end
18
-
19
- def path
20
- if block then ->(opts) { block.call(opts).to_s.gsub(SLASHES, "") }
21
- else ->(_) { value }
22
- end
23
- end
24
- end
25
- end
@@ -1,16 +0,0 @@
1
- module Evil::Client::DSL
2
- class Query < Base
3
- def call(schema)
4
- merge schema, query: coercer
5
- end
6
-
7
- private
8
-
9
- attr_reader :model, :block
10
-
11
- def initialize(model: nil, &block)
12
- @model = model
13
- @block = block
14
- end
15
- end
16
- end
@@ -1,61 +0,0 @@
1
- module Evil::Client::DSL
2
- # Builds a schema for response processor
3
- class Response
4
- extend Dry::Initializer::Mixin
5
- param :status
6
- option :raise, default: proc { false }
7
- option :format, default: proc {}
8
- option :model, default: proc { nil }
9
- option :block, default: proc { nil }
10
-
11
- def self.[](*args)
12
- new(*args).to_h
13
- end
14
-
15
- def to_h
16
- { status: status.to_i, coercer: coercer, raise: raise }
17
- end
18
-
19
- private
20
-
21
- def json?
22
- format.to_s == "json"
23
- end
24
-
25
- def arity
26
- block&.arity
27
- end
28
-
29
- def coercer
30
- handlers = [parser, processor, wrapper, finalizer].compact
31
- proc { |body| handlers.inject(body) { |obj, handler| handler.call(obj) } }
32
- end
33
-
34
- def parser
35
- proc { |body| JSON.parse(body) } if json?
36
- end
37
-
38
- def wrapper
39
- return unless json?
40
- proc { |data| data.is_a?(Hash) ? data : { data: data } }
41
- end
42
-
43
- def processor
44
- return unless block&.arity == 1
45
- block
46
- end
47
-
48
- def addon
49
- return unless arity == 0
50
- proc { |klass| klass.instance_eval(&block) }
51
- end
52
-
53
- def finalizer
54
- case [model.nil?, addon.nil?]
55
- when [false, true] then model
56
- when [false, false] then Class.new(model).tap(&addon)
57
- when [true, false] then Class.new(Evil::Struct).tap(&addon)
58
- end
59
- end
60
- end
61
- end
@@ -1,29 +0,0 @@
1
- class Evil::Client::DSL::Responses
2
- # Add settings shared by several responses
3
- #
4
- # @param [#to_sym] name
5
- # @param [#to_i] status
6
- # @param [Hash<Symbol, Object>] options
7
- # @param [Proc] block
8
- #
9
- def response(name, status, **options, &block)
10
- @client.send :response, name, status, @options.merge(options), &block
11
- end
12
-
13
- # Add settings shared by several responses
14
- #
15
- # @param [Hash<Symbol, Object>] options
16
- # @param [Proc] block
17
- #
18
- def responses(**options, &block)
19
- self.class.new(@client, @options.merge(options), &block)
20
- end
21
-
22
- private
23
-
24
- def initialize(client, **options, &block)
25
- @client = client
26
- @options = options
27
- instance_eval(&block)
28
- end
29
- end
@@ -1,27 +0,0 @@
1
- module Evil::Client::DSL
2
- # Provides a namespace for client's top-level DSL
3
- class Scope
4
- extend Dry::Initializer::Mixin
5
- option :__scope__, default: proc {}, reader: :private
6
-
7
- # Declares a method that opens new scope inside the current one
8
- # An instance of new scope has access to methods of its parent
9
- #
10
- # @param [#to_sym] name (:[]) The name of the new scope
11
- # @return [self]
12
- #
13
- def self.scope(name = :[], &block)
14
- klass = Class.new(Scope, &block)
15
- define_method(name) do |*args, **options|
16
- klass.new(*args, __scope__: self, **options)
17
- end
18
- self
19
- end
20
-
21
- private
22
-
23
- def method_missing(name, *args)
24
- __scope__.send(name, *args)
25
- end
26
- end
27
- end
@@ -1,57 +0,0 @@
1
- module Evil::Client::DSL
2
- # Nested definition for a security schemas
3
- class Security
4
- # Builds final security schema dependent on request options
5
- #
6
- # @param [Hash<Symbol, Object>] options
7
- # @return [Hash<Symbol, Object>]
8
- #
9
- def call(**options)
10
- @mutex.synchronize do
11
- @schema = {}
12
- instance_exec(options, &@block)
13
- @schema
14
- end
15
- end
16
-
17
- private
18
-
19
- def initialize(&block)
20
- @mutex = Mutex.new
21
- @block = block
22
- end
23
-
24
- # ==========================================================================
25
- # Helper methods that mutate a security @schema
26
- # ==========================================================================
27
-
28
- # @see [https://tools.ietf.org/html/rfc7617]
29
- def basic_auth(user, password)
30
- token = Base64.encode64("#{user}:#{password}").delete("\n")
31
- token_auth(token, prefix: "Basic")
32
- end
33
-
34
- def token_auth(token, using: :headers, prefix: nil)
35
- if using == :headers
36
- prefixed_token = [prefix&.to_s&.capitalize, token].compact.join(" ")
37
- key_auth("authorization", prefixed_token, using: :headers)
38
- else
39
- key_auth("access_token", token, using: using)
40
- end
41
- end
42
-
43
- def key_auth(key, value, using: :headers)
44
- __validate__ using
45
- @schema[using] ||= {}
46
- @schema[using][key.to_s] = value
47
- end
48
-
49
- # ==========================================================================
50
-
51
- def __validate__(part)
52
- parts = %i[body query headers]
53
- return if parts.include? part
54
- raise ArgumentError.new "Wrong part '#{part}'. Use one of parts: #{parts}"
55
- end
56
- end
57
- end
@@ -1,35 +0,0 @@
1
- module Evil::Client::DSL
2
- SchemaError = Class.new(StandardError)
3
-
4
- # Verifies a final schema
5
- class Verifier
6
- def self.call(schema)
7
- new(schema).call
8
- end
9
-
10
- def call
11
- @schema.each do |key, schema|
12
- check_path(key, schema)
13
- check_method(key, schema)
14
- end
15
- end
16
-
17
- private
18
-
19
- def initialize(schema)
20
- @schema = schema
21
- end
22
-
23
- def check_path(key, schema)
24
- return if schema[:path]
25
- raise SchemaError,
26
- "Path definition is missed for operation :#{key}"
27
- end
28
-
29
- def check_method(key, schema)
30
- return if schema[:method]
31
- raise SchemaError,
32
- "HTTP method definition is missed for operation :#{key}"
33
- end
34
- end
35
- end
@@ -1,81 +0,0 @@
1
- class Evil::Client
2
- # Builds and carries stack of middleware parameterized by settings
3
- #
4
- # @example
5
- # # during client definition
6
- # middleware = Evil::Client::Middleware.new do |settings|
7
- # run CustomMiddleware if settings.version > 1
8
- # end
9
- #
10
- # # during client instantiation
11
- # stack = middleware.finalize(settings)
12
- # conn = stack.wrap(connection)
13
- #
14
- # # during runtime to make a request
15
- # conn.call request
16
- #
17
- class Middleware
18
- class << self
19
- require_relative "middleware/base"
20
- require_relative "middleware/merge_security"
21
- require_relative "middleware/normalize_headers"
22
- require_relative "middleware/stringify_json"
23
- require_relative "middleware/stringify_multipart"
24
- require_relative "middleware/stringify_query"
25
- require_relative "middleware/stringify_form"
26
-
27
- # Middleware to be added on top of full stack (before custom ones)
28
- def prepend
29
- new do
30
- run NormalizeHeaders
31
- run MergeSecurity
32
- end.finalize
33
- end
34
-
35
- # Middleware to be added on bottom of full stack
36
- # (between custom stack and connection)
37
- def append
38
- new do
39
- run StringifyQuery
40
- run StringifyJson
41
- run StringifyForm
42
- run StringifyMultipart
43
- end.finalize
44
- end
45
- end
46
-
47
- # Applies client settings to build stack of middleware
48
- #
49
- # @param [Object] settings
50
- # @return [self]
51
- #
52
- def finalize(settings = nil)
53
- @mutex.synchronize do
54
- @stack = []
55
- instance_exec(settings, &@block) if @block
56
- self
57
- end
58
- end
59
-
60
- # Wraps the connection instance to the current stack of middleware
61
- #
62
- # @param [#call] connection
63
- # @return [#call]
64
- #
65
- def call(other)
66
- @stack.reverse.inject(other) { |a, e| e.new(a) }
67
- end
68
-
69
- private
70
-
71
- def initialize(&block)
72
- @mutex = Mutex.new
73
- @block = block
74
- end
75
-
76
- def run(klass)
77
- @stack << klass
78
- self
79
- end
80
- end
81
- end