gqli 1.0.0 → 1.1.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/CHANGELOG.md +4 -0
- data/lib/gqli/client.rb +23 -5
- data/lib/gqli/clients/contentful.rb +3 -2
- data/lib/gqli/response.rb +15 -2
- data/lib/gqli/version.rb +1 -1
- data/spec/lib/gqli/client_spec.rb +53 -0
- data/spec/lib/gqli/response_spec.rb +51 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4315f21be8d0b00907f0310acc1a17f300dd9157874bf09c75e577ef3b7fb95
|
4
|
+
data.tar.gz: e51cda712da56a947079aa807610bf0979352d3b2e3c2ed28eba337051df85d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71560b1443fc3487f6de643950683b1a5b635cc35f3431d4af36379a29bee58308f20a19037e484065fc43790071574d62068c38c960268b2a55eb37232b8617
|
7
|
+
data.tar.gz: 2d94bff9408e828967ee3b7e20f980a59dc536f4a579675fa8d909149fd908fa8a55d2f2b7022552afc3e3ac644c5472003bedcb21249b6b959add3b2257269f
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## v1.1.0
|
6
|
+
* Added support for timeout management. [#11](https://github.com/contentful-labs/gqli.rb/pull/11)
|
7
|
+
* Added support for error response handling. [#13](https://github.com/contentful-labs/gqli.rb/pull/13)
|
8
|
+
|
5
9
|
## v1.0.0
|
6
10
|
### Added
|
7
11
|
* Added support for Mutations.
|
data/lib/gqli/client.rb
CHANGED
@@ -9,13 +9,17 @@ require_relative './version'
|
|
9
9
|
module GQLi
|
10
10
|
# GraphQL HTTP Client
|
11
11
|
class Client
|
12
|
-
attr_reader :url, :params, :headers, :validate_query, :schema
|
12
|
+
attr_reader :url, :params, :headers, :validate_query, :schema, :options
|
13
13
|
|
14
|
-
def initialize(url, params: {}, headers: {}, validate_query: true)
|
14
|
+
def initialize(url, params: {}, headers: {}, validate_query: true, options: {})
|
15
15
|
@url = url
|
16
16
|
@params = params
|
17
17
|
@headers = headers
|
18
18
|
@validate_query = validate_query
|
19
|
+
@options = options
|
20
|
+
@options[:read_timeout] ||= 60
|
21
|
+
@options[:write_timeout] ||= 60
|
22
|
+
@options[:connect_timeout] ||= 60
|
19
23
|
|
20
24
|
@schema = Introspection.new(self) if validate_query
|
21
25
|
end
|
@@ -34,13 +38,15 @@ module GQLi
|
|
34
38
|
# Executres a query
|
35
39
|
# Ignores validations
|
36
40
|
def execute!(query)
|
37
|
-
http_response =
|
41
|
+
http_response = request.post(@url, params: @params, json: { query: query.to_gql })
|
38
42
|
|
39
43
|
fail "Error: #{http_response.reason}\nBody: #{http_response.body}" if http_response.status >= 300
|
40
44
|
|
41
|
-
|
45
|
+
parsed_response = JSON.parse(http_response.to_s)
|
46
|
+
data = parsed_response['data']
|
47
|
+
errors = parsed_response['errors']
|
42
48
|
|
43
|
-
Response.new(data, query)
|
49
|
+
Response.new(data, errors, query)
|
44
50
|
end
|
45
51
|
|
46
52
|
# Validates a query against the schema
|
@@ -50,6 +56,10 @@ module GQLi
|
|
50
56
|
schema.valid?(query)
|
51
57
|
end
|
52
58
|
|
59
|
+
def request
|
60
|
+
HTTP.headers(request_headers).timeout(timeout_options)
|
61
|
+
end
|
62
|
+
|
53
63
|
protected
|
54
64
|
|
55
65
|
def validation_error_message(validation)
|
@@ -67,5 +77,13 @@ module GQLi
|
|
67
77
|
user_agent: "gqli.rb/#{VERSION}; http.rb/#{HTTP::VERSION}"
|
68
78
|
}.merge(@headers)
|
69
79
|
end
|
80
|
+
|
81
|
+
def timeout_options
|
82
|
+
{
|
83
|
+
write: options[:write_timeout],
|
84
|
+
connect: options[:connect_timeout],
|
85
|
+
read: options[:read_timeout]
|
86
|
+
}
|
87
|
+
end
|
70
88
|
end
|
71
89
|
end
|
@@ -4,7 +4,7 @@ module GQLi
|
|
4
4
|
# Module for creating a Contentful GraphQL client
|
5
5
|
module Contentful
|
6
6
|
# Creates a Contentful GraphQL client
|
7
|
-
def self.create(space, access_token, environment: nil, validate_query: true)
|
7
|
+
def self.create(space, access_token, environment: nil, validate_query: true, options: {})
|
8
8
|
api_url = "https://graphql.contentful.com/content/v1/spaces/#{space}"
|
9
9
|
api_url += "/environments/#{environment}" unless environment.nil?
|
10
10
|
|
@@ -13,7 +13,8 @@ module GQLi
|
|
13
13
|
headers: {
|
14
14
|
'Authorization' => "Bearer #{access_token}"
|
15
15
|
},
|
16
|
-
validate_query: validate_query
|
16
|
+
validate_query: validate_query,
|
17
|
+
options: options
|
17
18
|
)
|
18
19
|
end
|
19
20
|
end
|
data/lib/gqli/response.rb
CHANGED
@@ -5,11 +5,24 @@ require 'hashie/mash'
|
|
5
5
|
module GQLi
|
6
6
|
# Response object wrapper
|
7
7
|
class Response
|
8
|
-
attr_reader :data, :query
|
8
|
+
attr_reader :data, :errors, :query
|
9
9
|
|
10
|
-
def initialize(data, query)
|
10
|
+
def initialize(data, errors, query)
|
11
11
|
@data = Hashie::Mash.new(data)
|
12
|
+
@errors = parse_errors(errors)
|
12
13
|
@query = query
|
13
14
|
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Accepts Hash or Array of errors and converts them to Hashie::Mash instances.
|
19
|
+
# Recursively calls #parse_errors with items if array.
|
20
|
+
# Returns nil if nil is passed.
|
21
|
+
def parse_errors(errors)
|
22
|
+
return unless errors
|
23
|
+
return errors.map { |e| parse_errors(e) } if errors.is_a?(Array)
|
24
|
+
|
25
|
+
Hashie::Mash.new(errors)
|
26
|
+
end
|
14
27
|
end
|
15
28
|
end
|
data/lib/gqli/version.rb
CHANGED
@@ -3,6 +3,8 @@ require 'spec_helper'
|
|
3
3
|
describe GQLi::Client do
|
4
4
|
let(:space_id) { 'cfexampleapi' }
|
5
5
|
let(:token) { 'b4c0n73n7fu1' }
|
6
|
+
let(:default_timeout) { 60 }
|
7
|
+
let(:timeout) { 10 }
|
6
8
|
|
7
9
|
let(:client) do
|
8
10
|
vcr('client') {
|
@@ -20,6 +22,21 @@ describe GQLi::Client do
|
|
20
22
|
}
|
21
23
|
end
|
22
24
|
|
25
|
+
let(:client_with_timeout) do
|
26
|
+
vcr('client') {
|
27
|
+
GQLi::Contentful.create(
|
28
|
+
space_id,
|
29
|
+
token,
|
30
|
+
validate_query: false,
|
31
|
+
options: {
|
32
|
+
connect_timeout: timeout,
|
33
|
+
read_timeout: timeout,
|
34
|
+
write_timeout: timeout
|
35
|
+
}
|
36
|
+
)
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
23
40
|
let(:dsl) { GQLi::DSL }
|
24
41
|
|
25
42
|
describe 'default clients' do
|
@@ -118,4 +135,40 @@ describe GQLi::Client do
|
|
118
135
|
}
|
119
136
|
end
|
120
137
|
end
|
138
|
+
|
139
|
+
context 'without timeout options' do
|
140
|
+
subject { client }
|
141
|
+
|
142
|
+
it 'upon instantiation sets default timeout value' do
|
143
|
+
expect(subject.options[:read_timeout]).to eq(default_timeout)
|
144
|
+
expect(subject.options[:connect_timeout]).to eq(default_timeout)
|
145
|
+
expect(subject.options[:write_timeout]).to eq(default_timeout)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'when executing a request sets default timeout value' do
|
149
|
+
expect(subject.request.default_options.timeout_options[:read_timeout]).to eq(default_timeout)
|
150
|
+
expect(subject.request.default_options.timeout_options[:connect_timeout]).to eq(default_timeout)
|
151
|
+
expect(subject.request.default_options.timeout_options[:write_timeout]).to eq(default_timeout)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'with timeout options' do
|
156
|
+
subject { client_with_timeout }
|
157
|
+
|
158
|
+
it 'contentful client' do
|
159
|
+
expect(subject).to be_a(GQLi::Client)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'upon instantiation sets provided timeout value' do
|
163
|
+
expect(subject.options[:read_timeout]).to eq(timeout)
|
164
|
+
expect(subject.options[:connect_timeout]).to eq(timeout)
|
165
|
+
expect(subject.options[:write_timeout]).to eq(timeout)
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'when executing a request sets provided timeout value' do
|
169
|
+
expect(subject.request.default_options.timeout_options[:read_timeout]).to eq(timeout)
|
170
|
+
expect(subject.request.default_options.timeout_options[:connect_timeout]).to eq(timeout)
|
171
|
+
expect(subject.request.default_options.timeout_options[:write_timeout]).to eq(timeout)
|
172
|
+
end
|
173
|
+
end
|
121
174
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GQLi::Response do
|
4
|
+
let(:errors) { nil }
|
5
|
+
let(:data) { {"testkey" => "test val"} }
|
6
|
+
let(:query) { double(:query) }
|
7
|
+
subject { described_class.new(data, errors, query) }
|
8
|
+
|
9
|
+
describe "#data" do
|
10
|
+
it "returns correct data Hashie" do
|
11
|
+
expect(subject.data).to be_kind_of(Hashie::Mash)
|
12
|
+
expect(subject.data.testkey).to eq(data["testkey"])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#query" do
|
17
|
+
it "returns correct query" do
|
18
|
+
expect(subject.query).to eq(query)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#errors" do
|
23
|
+
context "array errors" do
|
24
|
+
let(:errors) { [{"message" => "this is an error"}] }
|
25
|
+
|
26
|
+
it "converts errors to correct Hashie instances" do
|
27
|
+
expect(subject.errors).to be_kind_of(Array)
|
28
|
+
expect(subject.errors.length).to eq(1)
|
29
|
+
expect(subject.errors.first).to be_kind_of(Hashie::Mash)
|
30
|
+
expect(subject.errors.first.message).to eq(errors.first["message"])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "hash errors" do
|
35
|
+
let(:errors) { {"message" => "this is an error"} }
|
36
|
+
|
37
|
+
it "converts errors to correct Hashie instances" do
|
38
|
+
expect(subject.errors).to be_kind_of(Hashie::Mash)
|
39
|
+
expect(subject.errors.message).to eq(errors["message"])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "nil errors" do
|
44
|
+
it "does not raise error and returns nil" do
|
45
|
+
expect(subject.errors).to be(nil)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gqli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Contentful GmbH (David Litvak Bruno)
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http
|
@@ -349,6 +349,7 @@ files:
|
|
349
349
|
- spec/lib/gqli/client_spec.rb
|
350
350
|
- spec/lib/gqli/dsl_spec.rb
|
351
351
|
- spec/lib/gqli/introspection_spec.rb
|
352
|
+
- spec/lib/gqli/response_spec.rb
|
352
353
|
- spec/spec_helper.rb
|
353
354
|
- usage.rb
|
354
355
|
- usage_introspection.rb
|
@@ -357,7 +358,7 @@ homepage: https://github.com/contentful-labs/gqli.rb
|
|
357
358
|
licenses:
|
358
359
|
- MIT
|
359
360
|
metadata: {}
|
360
|
-
post_install_message:
|
361
|
+
post_install_message:
|
361
362
|
rdoc_options: []
|
362
363
|
require_paths:
|
363
364
|
- lib
|
@@ -373,7 +374,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
373
374
|
version: '0'
|
374
375
|
requirements: []
|
375
376
|
rubygems_version: 3.0.3
|
376
|
-
signing_key:
|
377
|
+
signing_key:
|
377
378
|
specification_version: 4
|
378
379
|
summary: GraphQL client for humans
|
379
380
|
test_files:
|
@@ -384,4 +385,5 @@ test_files:
|
|
384
385
|
- spec/lib/gqli/client_spec.rb
|
385
386
|
- spec/lib/gqli/dsl_spec.rb
|
386
387
|
- spec/lib/gqli/introspection_spec.rb
|
388
|
+
- spec/lib/gqli/response_spec.rb
|
387
389
|
- spec/spec_helper.rb
|