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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +0 -11
- data/.gitignore +1 -0
- data/.rspec +0 -1
- data/.rubocop.yml +22 -19
- data/.travis.yml +1 -0
- data/CHANGELOG.md +251 -6
- data/LICENSE.txt +3 -1
- data/README.md +47 -81
- data/docs/helpers/body.md +93 -0
- data/docs/helpers/connection.md +19 -0
- data/docs/helpers/headers.md +72 -0
- data/docs/helpers/http_method.md +39 -0
- data/docs/helpers/let.md +14 -0
- data/docs/helpers/logger.md +24 -0
- data/docs/helpers/middleware.md +56 -0
- data/docs/helpers/operation.md +103 -0
- data/docs/helpers/option.md +50 -0
- data/docs/helpers/path.md +37 -0
- data/docs/helpers/query.md +59 -0
- data/docs/helpers/response.md +40 -0
- data/docs/helpers/scope.md +121 -0
- data/docs/helpers/security.md +102 -0
- data/docs/helpers/validate.md +68 -0
- data/docs/index.md +70 -78
- data/docs/license.md +5 -1
- data/docs/rspec.md +96 -0
- data/evil-client.gemspec +10 -8
- data/lib/evil/client.rb +126 -72
- data/lib/evil/client/builder.rb +47 -0
- data/lib/evil/client/builder/operation.rb +40 -0
- data/lib/evil/client/builder/scope.rb +31 -0
- data/lib/evil/client/chaining.rb +17 -0
- data/lib/evil/client/connection.rb +60 -20
- data/lib/evil/client/container.rb +66 -0
- data/lib/evil/client/container/operation.rb +23 -0
- data/lib/evil/client/container/scope.rb +28 -0
- data/lib/evil/client/exceptions/definition_error.rb +15 -0
- data/lib/evil/client/exceptions/name_error.rb +32 -0
- data/lib/evil/client/exceptions/response_error.rb +42 -0
- data/lib/evil/client/exceptions/type_error.rb +29 -0
- data/lib/evil/client/exceptions/validation_error.rb +27 -0
- data/lib/evil/client/formatter.rb +49 -0
- data/lib/evil/client/formatter/form.rb +45 -0
- data/lib/evil/client/formatter/multipart.rb +33 -0
- data/lib/evil/client/formatter/part.rb +66 -0
- data/lib/evil/client/formatter/text.rb +21 -0
- data/lib/evil/client/resolver.rb +84 -0
- data/lib/evil/client/resolver/body.rb +22 -0
- data/lib/evil/client/resolver/format.rb +30 -0
- data/lib/evil/client/resolver/headers.rb +46 -0
- data/lib/evil/client/resolver/http_method.rb +34 -0
- data/lib/evil/client/resolver/middleware.rb +36 -0
- data/lib/evil/client/resolver/query.rb +39 -0
- data/lib/evil/client/resolver/request.rb +96 -0
- data/lib/evil/client/resolver/response.rb +26 -0
- data/lib/evil/client/resolver/security.rb +113 -0
- data/lib/evil/client/resolver/uri.rb +35 -0
- data/lib/evil/client/rspec.rb +127 -0
- data/lib/evil/client/schema.rb +105 -0
- data/lib/evil/client/schema/operation.rb +177 -0
- data/lib/evil/client/schema/scope.rb +73 -0
- data/lib/evil/client/settings.rb +172 -0
- data/lib/evil/client/settings/validator.rb +64 -0
- data/mkdocs.yml +21 -15
- data/spec/features/custom_connection_spec.rb +17 -0
- data/spec/features/operation/middleware_spec.rb +50 -0
- data/spec/features/operation/options_spec.rb +71 -0
- data/spec/features/operation/request_spec.rb +94 -0
- data/spec/features/operation/response_spec.rb +48 -0
- data/spec/features/scope/options_spec.rb +52 -0
- data/spec/fixtures/locales/en.yml +16 -0
- data/spec/fixtures/test_client.rb +76 -0
- data/spec/spec_helper.rb +18 -6
- data/spec/support/fixtures_helper.rb +7 -0
- data/spec/unit/builder/operation_spec.rb +90 -0
- data/spec/unit/builder/scope_spec.rb +84 -0
- data/spec/unit/client_spec.rb +137 -0
- data/spec/unit/connection_spec.rb +78 -0
- data/spec/unit/container/operation_spec.rb +81 -0
- data/spec/unit/container/scope_spec.rb +61 -0
- data/spec/unit/container_spec.rb +107 -0
- data/spec/unit/exceptions/definition_error_spec.rb +15 -0
- data/spec/unit/exceptions/name_error_spec.rb +77 -0
- data/spec/unit/exceptions/response_error_spec.rb +22 -0
- data/spec/unit/exceptions/type_error_spec.rb +71 -0
- data/spec/unit/exceptions/validation_error_spec.rb +13 -0
- data/spec/unit/formatter/form_spec.rb +27 -0
- data/spec/unit/formatter/multipart_spec.rb +23 -0
- data/spec/unit/formatter/part_spec.rb +49 -0
- data/spec/unit/formatter/text_spec.rb +37 -0
- data/spec/unit/formatter_spec.rb +46 -0
- data/spec/unit/resolver/body_spec.rb +65 -0
- data/spec/unit/resolver/format_spec.rb +66 -0
- data/spec/unit/resolver/headers_spec.rb +93 -0
- data/spec/unit/resolver/http_method_spec.rb +67 -0
- data/spec/unit/resolver/middleware_spec.rb +83 -0
- data/spec/unit/resolver/query_spec.rb +85 -0
- data/spec/unit/resolver/request_spec.rb +121 -0
- data/spec/unit/resolver/response_spec.rb +64 -0
- data/spec/unit/resolver/security_spec.rb +156 -0
- data/spec/unit/resolver/uri_spec.rb +117 -0
- data/spec/unit/rspec_spec.rb +342 -0
- data/spec/unit/schema/operation_spec.rb +309 -0
- data/spec/unit/schema/scope_spec.rb +110 -0
- data/spec/unit/schema_spec.rb +157 -0
- data/spec/unit/settings/validator_spec.rb +128 -0
- data/spec/unit/settings_spec.rb +248 -0
- metadata +192 -135
- data/docs/base_url.md +0 -38
- data/docs/documentation.md +0 -9
- data/docs/headers.md +0 -59
- data/docs/http_method.md +0 -31
- data/docs/model.md +0 -173
- data/docs/operation.md +0 -0
- data/docs/overview.md +0 -0
- data/docs/path.md +0 -48
- data/docs/query.md +0 -99
- data/docs/responses.md +0 -66
- data/docs/security.md +0 -102
- data/docs/settings.md +0 -32
- data/lib/evil/client/connection/net_http.rb +0 -57
- data/lib/evil/client/dsl.rb +0 -127
- data/lib/evil/client/dsl/base.rb +0 -26
- data/lib/evil/client/dsl/files.rb +0 -37
- data/lib/evil/client/dsl/headers.rb +0 -16
- data/lib/evil/client/dsl/http_method.rb +0 -24
- data/lib/evil/client/dsl/operation.rb +0 -91
- data/lib/evil/client/dsl/operations.rb +0 -41
- data/lib/evil/client/dsl/path.rb +0 -25
- data/lib/evil/client/dsl/query.rb +0 -16
- data/lib/evil/client/dsl/response.rb +0 -61
- data/lib/evil/client/dsl/responses.rb +0 -29
- data/lib/evil/client/dsl/scope.rb +0 -27
- data/lib/evil/client/dsl/security.rb +0 -57
- data/lib/evil/client/dsl/verifier.rb +0 -35
- data/lib/evil/client/middleware.rb +0 -81
- data/lib/evil/client/middleware/base.rb +0 -11
- data/lib/evil/client/middleware/merge_security.rb +0 -20
- data/lib/evil/client/middleware/normalize_headers.rb +0 -17
- data/lib/evil/client/middleware/stringify_form.rb +0 -40
- data/lib/evil/client/middleware/stringify_json.rb +0 -19
- data/lib/evil/client/middleware/stringify_multipart.rb +0 -36
- data/lib/evil/client/middleware/stringify_multipart/part.rb +0 -36
- data/lib/evil/client/middleware/stringify_query.rb +0 -35
- data/lib/evil/client/operation.rb +0 -34
- data/lib/evil/client/operation/request.rb +0 -26
- data/lib/evil/client/operation/response.rb +0 -39
- data/lib/evil/client/operation/response_error.rb +0 -13
- data/lib/evil/client/operation/unexpected_response_error.rb +0 -19
- data/spec/features/instantiation_spec.rb +0 -68
- data/spec/features/middleware_spec.rb +0 -79
- data/spec/features/operation_with_documentation_spec.rb +0 -41
- data/spec/features/operation_with_files_spec.rb +0 -40
- data/spec/features/operation_with_form_body_spec.rb +0 -158
- data/spec/features/operation_with_headers_spec.rb +0 -99
- data/spec/features/operation_with_http_method_spec.rb +0 -45
- data/spec/features/operation_with_json_body_spec.rb +0 -156
- data/spec/features/operation_with_nested_responses_spec.rb +0 -95
- data/spec/features/operation_with_path_spec.rb +0 -47
- data/spec/features/operation_with_query_spec.rb +0 -84
- data/spec/features/operation_with_security_spec.rb +0 -228
- data/spec/features/scoping_spec.rb +0 -48
- data/spec/support/test_client.rb +0 -15
- data/spec/unit/evil/client/connection/net_http_spec.rb +0 -38
- data/spec/unit/evil/client/dsl/files_spec.rb +0 -37
- data/spec/unit/evil/client/dsl/operation_spec.rb +0 -374
- data/spec/unit/evil/client/dsl/operations_spec.rb +0 -29
- data/spec/unit/evil/client/dsl/scope_spec.rb +0 -32
- data/spec/unit/evil/client/dsl/security_spec.rb +0 -135
- data/spec/unit/evil/client/middleware/merge_security_spec.rb +0 -32
- data/spec/unit/evil/client/middleware/normalize_headers_spec.rb +0 -17
- data/spec/unit/evil/client/middleware/stringify_form_spec.rb +0 -63
- data/spec/unit/evil/client/middleware/stringify_json_spec.rb +0 -61
- data/spec/unit/evil/client/middleware/stringify_multipart/part_spec.rb +0 -59
- data/spec/unit/evil/client/middleware/stringify_multipart_spec.rb +0 -62
- data/spec/unit/evil/client/middleware/stringify_query_spec.rb +0 -40
- data/spec/unit/evil/client/middleware_spec.rb +0 -46
- data/spec/unit/evil/client/operation/request_spec.rb +0 -49
- data/spec/unit/evil/client/operation/response_spec.rb +0 -63
data/docs/responses.md
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
For every operation you have to describe all expected responses and how they should be processed.
|
2
|
-
|
3
|
-
Use the `response` method with anexpected http response status(es):
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
operation :find_cat do
|
7
|
-
# ...
|
8
|
-
response 200, 201
|
9
|
-
end
|
10
|
-
```
|
11
|
-
|
12
|
-
This definition tells a client to accept responses with given statuses, and to return an instance of `Rack::Response`.
|
13
|
-
|
14
|
-
```ruby
|
15
|
-
client.operations[:find_cat].call
|
16
|
-
# => #<Rack::Response @code=200 ...>
|
17
|
-
```
|
18
|
-
|
19
|
-
## Data Coersion
|
20
|
-
|
21
|
-
Instead of returning a raw rack response, you can coerce it using a block. The block will take 3 options, namely the response, its body and headers:
|
22
|
-
|
23
|
-
```ruby
|
24
|
-
operation :find_cat do |settings| # remember that you have access to settings
|
25
|
-
# ...
|
26
|
-
response 200 do |response:, body:, headers:|
|
27
|
-
JSON.parse(body) if settings.format == "json"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# later at a runtime
|
32
|
-
client.operations[:find_cat].call
|
33
|
-
# => { name: "Bastet", age: 10 }
|
34
|
-
```
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
## Raising Exceptions
|
39
|
-
|
40
|
-
When processing responces with error statuses you may need to raise an exception instead of returning values. Do this using option `raise: true`
|
41
|
-
|
42
|
-
```ruby
|
43
|
-
operation :find_cat do
|
44
|
-
# ...
|
45
|
-
response 422, raise: true
|
46
|
-
end
|
47
|
-
```
|
48
|
-
|
49
|
-
This time the operation will raise a `Evil::Client::ResponseError` (inherited from the `RuntimeError`). The exception carries a rack response:
|
50
|
-
|
51
|
-
```ruby
|
52
|
-
begin
|
53
|
-
client.operations[:find_cat].call
|
54
|
-
rescue Evil::Client::ResponseError => error
|
55
|
-
error.response
|
56
|
-
# => #<Rack::Response @code=422 ...>
|
57
|
-
end
|
58
|
-
```
|
59
|
-
|
60
|
-
Like before, you can add a block to handle the response. In this case an exception will carry a result of the block.
|
61
|
-
|
62
|
-
## Unexpected Responses
|
63
|
-
|
64
|
-
In case the server responded with undefined status, the operation raises `Evil::Client::UnexpectedResponseError` (inherited from the `RuntimeError`) that carries a rack response just like the `Evil::Client::ResponseError` before.
|
65
|
-
|
66
|
-
Notice that you can declare default responses using anonymous `operation {}` syntax. Only those responces that are declared neither by default, nor for a specific operation, will cause unexpected response behaviour.
|
data/docs/security.md
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
Use `security` declaration for the authorization schema. Inside the block you have access to 3 methods:
|
2
|
-
* `basic_auth`
|
3
|
-
* `token_auth`
|
4
|
-
* `key_auth`
|
5
|
-
|
6
|
-
## Basic Authentication
|
7
|
-
|
8
|
-
Use `basic_auth(login, password)` to define [basic authentication following RFC-7617][basic_auth]:
|
9
|
-
|
10
|
-
```ruby
|
11
|
-
operation :find_cat do |settings|
|
12
|
-
security do
|
13
|
-
basic_auth settings.login, settings.password
|
14
|
-
end
|
15
|
-
end
|
16
|
-
```
|
17
|
-
|
18
|
-
This declaration with add a header `"Authentication" => "Basic {encoded token}"` to every request. The header is added independenlty of declaration for other [headers][headers].
|
19
|
-
|
20
|
-
## Token Authentication
|
21
|
-
|
22
|
-
The command `token_auth(token, **options)` allows you to insert a customizable token to any part of the request. Unlike `basic_auth`, you need to provide the token (build, encrypt etc.) by hand.
|
23
|
-
|
24
|
-
```ruby
|
25
|
-
operation :find_cat do |settings|
|
26
|
-
security do
|
27
|
-
token_auth settings.token
|
28
|
-
end
|
29
|
-
end
|
30
|
-
```
|
31
|
-
|
32
|
-
By default the token is added to `"Authentication" => {token}` header of the request. You can prepend it with a necessary prefix. For example, you can define a [Bearer token authentication following RFC-6750][bearer]:
|
33
|
-
|
34
|
-
```ruby
|
35
|
-
operation :find_cat do |settings|
|
36
|
-
security do
|
37
|
-
token_auth settings.token, prefix: "Bearer"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
```
|
41
|
-
|
42
|
-
Instead of headers, you can send a token in either request body, or a query. In this case the token will be sent under `access_key` ignoring a prefix:
|
43
|
-
|
44
|
-
```ruby
|
45
|
-
operation :find_cat do |settings|
|
46
|
-
path { "/cats" }
|
47
|
-
security do
|
48
|
-
token_auth settings.token, using: :query
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# will send a request to "../cats?access_key={token}"
|
53
|
-
```
|
54
|
-
|
55
|
-
## Authentication Using Arbitrary Key
|
56
|
-
|
57
|
-
The most customizeable option is to authenticate requests with an arbitrary key. This time key-value pair will be added to the selected part (`headers`, `body`, or `query`) of the request:
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
operation :find_cat do |settings|
|
61
|
-
path { "/cats" }
|
62
|
-
security do
|
63
|
-
key_auth :accss_key, settings.token, using: :query
|
64
|
-
end
|
65
|
-
end
|
66
|
-
```
|
67
|
-
|
68
|
-
## Authentication Using Several Schemes
|
69
|
-
|
70
|
-
You can define several schemes for the same request. All of them will be applied at once:
|
71
|
-
|
72
|
-
```ruby
|
73
|
-
operation :find_cat do |settings|
|
74
|
-
security do
|
75
|
-
basic_auth settings.login, settings.password
|
76
|
-
token_auth settings.token, using: :query
|
77
|
-
end
|
78
|
-
end
|
79
|
-
```
|
80
|
-
|
81
|
-
Moreover, you can declare shared authentication by default, and either update, or reload it for a specific operation:
|
82
|
-
|
83
|
-
```ruby
|
84
|
-
operation do |settings|
|
85
|
-
security { basic_auth settings.login, settings.password }
|
86
|
-
end
|
87
|
-
|
88
|
-
operation :find_cat do |settings|
|
89
|
-
security { token_auth settings.token, using: :query } # added to default security
|
90
|
-
end
|
91
|
-
|
92
|
-
operation :find_cats do |settings|
|
93
|
-
security { token_auth settings.token } # reloads default "Authentication" header
|
94
|
-
end
|
95
|
-
```
|
96
|
-
|
97
|
-
|
98
|
-
[basic_auth]: https://tools.ietf.org/html/rfc7617
|
99
|
-
[bearer]: https://tools.ietf.org/html/rfc6750
|
100
|
-
[headers]:
|
101
|
-
[body]:
|
102
|
-
[query]:
|
data/docs/settings.md
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
Use `settings` to parameterize an instance of the client.
|
2
|
-
|
3
|
-
Inside the block you can define both `param`s and `option`s for a client constructor. See [dry-initializer docs][dry-initializer] for detailed description of the methods' syntax.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
require "evil-client"
|
7
|
-
require "dry-types"
|
8
|
-
|
9
|
-
class CatsClient < Evil::Client
|
10
|
-
settings do
|
11
|
-
param :roor_url
|
12
|
-
option :version, type: Dry::Types["coercible.int"], default: proc { 1 }
|
13
|
-
option :login, type: Dry::Types["strict.string"] # required
|
14
|
-
option :password, type: Dry::Types["strict.string"] # required
|
15
|
-
end
|
16
|
-
end
|
17
|
-
```
|
18
|
-
|
19
|
-
Now you can initialize a client:
|
20
|
-
|
21
|
-
```ruby
|
22
|
-
client = CatsClient.new "https://cats.example.com",
|
23
|
-
login: "cats_lover",
|
24
|
-
password: "purr"
|
25
|
-
```
|
26
|
-
|
27
|
-
A container with assigned settings will be passed to blocks declaring [base_url][base_url], [connection][connection], and [operations][operation].
|
28
|
-
|
29
|
-
[base_url]:
|
30
|
-
[connection]:
|
31
|
-
[operation]:
|
32
|
-
[dry-initializer]: http://dry-rb.org/gems/dry-initializer
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require "net/http"
|
2
|
-
require "net/https"
|
3
|
-
|
4
|
-
class Evil::Client
|
5
|
-
class Connection
|
6
|
-
# Net::HTTP based implementation of [Evil::Client::Connection]
|
7
|
-
class NetHTTP < Connection
|
8
|
-
# Sends a request to the remote uri,
|
9
|
-
# and returns rack-compatible response
|
10
|
-
#
|
11
|
-
# @param [Hash] env Middleware environment with keys:
|
12
|
-
# :http_method, :path, :query_string, :body_string, :headers
|
13
|
-
# @return [Array] Rack-compatible response [status, body, headers]
|
14
|
-
#
|
15
|
-
def call(env, *)
|
16
|
-
request = build_request(env)
|
17
|
-
Net::HTTP.start base_uri.host, base_uri.port, opts do |http|
|
18
|
-
handle http.request(request)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def opts
|
25
|
-
@opts ||= {}.tap { |hash| hash[:use_ssl] = base_uri.scheme == "https" }
|
26
|
-
end
|
27
|
-
|
28
|
-
def build_request(env)
|
29
|
-
type, path, query, body, headers = parse_env(env)
|
30
|
-
|
31
|
-
sender = build_sender(type)
|
32
|
-
uri = build_uri(path, query)
|
33
|
-
|
34
|
-
sender.new(uri).tap do |request|
|
35
|
-
request.body = body
|
36
|
-
headers.each { |key, value| request[key] = value }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def parse_env(env)
|
41
|
-
env.values_at :http_method, :path, :query_string, :body_string, :headers
|
42
|
-
end
|
43
|
-
|
44
|
-
def build_sender(type)
|
45
|
-
Net::HTTP.const_get type.capitalize
|
46
|
-
end
|
47
|
-
|
48
|
-
def build_uri(path, query)
|
49
|
-
base_uri.merge(URI.encode(path)).tap { |uri| uri.query = query }
|
50
|
-
end
|
51
|
-
|
52
|
-
def handle(response)
|
53
|
-
[response.code.to_i, Hash(response.header), Array(response.body)]
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/evil/client/dsl.rb
DELETED
@@ -1,127 +0,0 @@
|
|
1
|
-
class Evil::Client
|
2
|
-
# Defines a DSL to customize class-level settings of the specific client
|
3
|
-
module DSL
|
4
|
-
require_relative "dsl/base"
|
5
|
-
require_relative "dsl/files"
|
6
|
-
require_relative "dsl/headers"
|
7
|
-
require_relative "dsl/http_method"
|
8
|
-
require_relative "dsl/path"
|
9
|
-
require_relative "dsl/query"
|
10
|
-
require_relative "dsl/response"
|
11
|
-
require_relative "dsl/responses"
|
12
|
-
require_relative "dsl/security"
|
13
|
-
require_relative "dsl/verifier"
|
14
|
-
require_relative "dsl/operation"
|
15
|
-
require_relative "dsl/operations"
|
16
|
-
require_relative "dsl/scope"
|
17
|
-
|
18
|
-
# Adds [#operations] to a specific client's instances
|
19
|
-
def self.extended(klass)
|
20
|
-
klass.include Dry::Initializer.define -> do
|
21
|
-
param :settings
|
22
|
-
param :base_url
|
23
|
-
param :operations
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# Helper to define params and options a for a client's constructor
|
28
|
-
#
|
29
|
-
# @example
|
30
|
-
# class MyClient < Evil::Client
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# MyClient.new "https://foo.com", user: "bar", token: "baz"
|
34
|
-
#
|
35
|
-
# @param [Proc] block
|
36
|
-
# @return [self]
|
37
|
-
#
|
38
|
-
def settings(&block)
|
39
|
-
return self unless block
|
40
|
-
schema[:settings] = Class.new { include Dry::Initializer.define(&block) }
|
41
|
-
self
|
42
|
-
end
|
43
|
-
|
44
|
-
# Helper to define base url of the server
|
45
|
-
#
|
46
|
-
# @param [#to_s] value
|
47
|
-
# @return [self]
|
48
|
-
#
|
49
|
-
def base_url(&block)
|
50
|
-
return self unless block
|
51
|
-
schema[:base_url] = block
|
52
|
-
self
|
53
|
-
end
|
54
|
-
|
55
|
-
# Helper specify a connection to be used by a client
|
56
|
-
#
|
57
|
-
# @param [#to_sym] type (nil)
|
58
|
-
# The specific type of connection. Uses NetHTTP by default.
|
59
|
-
# @return [self]
|
60
|
-
#
|
61
|
-
def connection(type = nil, &block)
|
62
|
-
schema[:connection] = Connection[type]
|
63
|
-
schema[:middleware] = Middleware.new(&block)
|
64
|
-
self
|
65
|
-
end
|
66
|
-
|
67
|
-
# Helper to declare operation, either default or specific
|
68
|
-
#
|
69
|
-
# @param [#to_sym] name (nil)
|
70
|
-
# @param [Proc] block
|
71
|
-
# @return [self]
|
72
|
-
#
|
73
|
-
def operation(name = nil, &block)
|
74
|
-
schema[:operations].register(name, &block)
|
75
|
-
self
|
76
|
-
end
|
77
|
-
|
78
|
-
# Helper to define scopes of the client's top-level DSL
|
79
|
-
#
|
80
|
-
# @param [#to_sym] name (:[])
|
81
|
-
# @param [Proc] block
|
82
|
-
# @return [self]
|
83
|
-
#
|
84
|
-
def scope(name = :[], &block)
|
85
|
-
klass = Class.new(Scope, &block)
|
86
|
-
define_method(name) do |*args, **options|
|
87
|
-
klass.new(*args, __scope__: self, **options)
|
88
|
-
end
|
89
|
-
self
|
90
|
-
end
|
91
|
-
|
92
|
-
# Takes constructor arguments and builds a final schema for an instance
|
93
|
-
# (All the instantiation magics goes here)
|
94
|
-
#
|
95
|
-
# @param [Object] *args
|
96
|
-
# @return [Hash<Symbol, Object>]
|
97
|
-
#
|
98
|
-
def new(*args)
|
99
|
-
settings = schema[:settings].new(*args)
|
100
|
-
base_url = schema[:base_url].call(settings)
|
101
|
-
middleware = schema[:middleware].finalize(settings)
|
102
|
-
operations = schema[:operations].finalize(settings)
|
103
|
-
client = schema[:connection].new URI(base_url)
|
104
|
-
connection = Middleware.prepend.(middleware.(Middleware.append.(client)))
|
105
|
-
|
106
|
-
data = operations.each_with_object({}) do |(key, schema), hash|
|
107
|
-
hash[key] = Evil::Client::Operation.new schema, connection
|
108
|
-
end
|
109
|
-
|
110
|
-
super(settings, base_url, data)
|
111
|
-
end
|
112
|
-
|
113
|
-
private
|
114
|
-
|
115
|
-
BASE_URL = proc { raise NotImplementedError.new "Base url is not defined" }
|
116
|
-
|
117
|
-
def schema
|
118
|
-
@schema ||= {
|
119
|
-
settings: Class.new,
|
120
|
-
base_url: BASE_URL,
|
121
|
-
connection: Connection[nil],
|
122
|
-
middleware: Middleware.new,
|
123
|
-
operations: Operations.new
|
124
|
-
}
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
data/lib/evil/client/dsl/base.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
module Evil::Client::DSL
|
2
|
-
class Base
|
3
|
-
def self.[](schema, *args, &block)
|
4
|
-
new(*args, &block).call(schema)
|
5
|
-
end
|
6
|
-
|
7
|
-
def call(schema)
|
8
|
-
schema
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def merge(source, target)
|
14
|
-
target.inject(source) do |obj, (key, val)|
|
15
|
-
obj.merge key => (Hash === val ? merge(obj.fetch(key, {}), val) : val)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def coercer
|
20
|
-
@coercer ||= if @model && @block then Class.new(@model, &@block)
|
21
|
-
elsif @block then Class.new(Evil::Struct, &@block)
|
22
|
-
elsif @model then @model
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module Evil::Client::DSL
|
2
|
-
# Nested definition for attached files
|
3
|
-
class Files
|
4
|
-
# Builds a final upload schema from 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 files @schema
|
26
|
-
# ==========================================================================
|
27
|
-
|
28
|
-
def add(data, type: "text/plain", charset: "utf-8", filename: nil, **)
|
29
|
-
@schema << {
|
30
|
-
file: data.respond_to?(:read) ? data : StringIO.new(data),
|
31
|
-
type: MIME::Types[type].first,
|
32
|
-
charset: charset,
|
33
|
-
filename: filename
|
34
|
-
}
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|