graphlient 0.7.0 → 0.8.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/.github/workflows/ci.yml +2 -1
- data/.github/workflows/danger.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/README.md +27 -2
- data/lib/graphlient/adapters/http/faraday_adapter.rb +35 -1
- data/lib/graphlient/client.rb +8 -1
- data/lib/graphlient/version.rb +1 -1
- data/spec/graphlient/adapters/http/faraday_adapter_spec.rb +55 -0
- data/spec/graphlient/client_schema_spec.rb +20 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed5f47ad98345af440481f9dca800767524807bc667eace999d7ba36826e59fa
|
4
|
+
data.tar.gz: 22ec20f5b725b3bb85bc9c8e8371693824f7fd85b2db43336ce7f6a6be31543f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c5ddbaafe24dfbdd6e99535bedb7a021eba55a956b4b716661c9c8778018a96118afc5a6def029aad14da883de8d47a747b4a85ead2cee0868d5ddcfb298359
|
7
|
+
data.tar.gz: 3fd8b40976687fd83b00b865f62d514a87571de0bf68015486328d526a2d9cc76a8c4454a5d78f86acba6480860ac1abde3ff2edda1e92c26b03c58f60b067e2
|
data/.github/workflows/ci.yml
CHANGED
@@ -14,8 +14,9 @@ jobs:
|
|
14
14
|
- { ruby: 2.7.2 }
|
15
15
|
- { ruby: 3.0.0 }
|
16
16
|
- { ruby: 3.1.2 }
|
17
|
+
- { ruby: 3.2.2 }
|
17
18
|
- { ruby: "ruby-head", ignore: true }
|
18
|
-
- { ruby: "jruby-9.
|
19
|
+
- { ruby: "jruby-9.3.9.0", ignore: true }
|
19
20
|
- { ruby: "jruby-head", ignore: true }
|
20
21
|
steps:
|
21
22
|
- uses: actions/checkout@v3
|
@@ -18,5 +18,5 @@ jobs:
|
|
18
18
|
bundler-cache: true
|
19
19
|
- run: |
|
20
20
|
# the personal token is public, this is ok, base64 encode to avoid tripping Github
|
21
|
-
TOKEN=$(echo -n
|
21
|
+
TOKEN=$(echo -n Z2hwX0xNQ3VmanBFeTBvYkZVTWh6NVNqVFFBOEUxU25abzBqRUVuaAo= | base64 --decode)
|
22
22
|
DANGER_GITHUB_API_TOKEN=$TOKEN bundle exec danger --verbose
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
### (Next)
|
2
2
|
* Your contribution here.
|
3
3
|
|
4
|
+
### 0.8.0 (2024/01/06)
|
5
|
+
* [#110](https://github.com/ashkan18/graphlient/pull/110): Ensure correct Faraday JSON response body parsing with invalid response header - [@taylorthurlow](https://github.com/taylorthurlow).
|
6
|
+
* [#107](https://github.com/ashkan18/graphlient/pull/107): Pass in initialized schema as an option - [@kbaum](https://github.com/kbaum).
|
7
|
+
* [#106](https://github.com/ashkan18/graphlient/pull/106): Add 3.2 to the list of ruby ci versions - [@igor-drozdov](https://github.com/igor-drozdov).
|
8
|
+
* [#102](https://github.com/ashkan18/graphlient/pull/102): Update ci to test latest jruby - [@ashkan18](https://github.com/ashkan18).
|
9
|
+
|
4
10
|
### 0.7.0 (2022/10/11)
|
5
11
|
* [#98](https://github.com/ashkan18/graphlient/pull/98): Bring back danger checks and improve them - [@ashkan18](https://github.com/ashkan18).
|
6
12
|
* [#94](https://github.com/ashkan18/graphlient/pull/94): Enabled fragments - [@rellampec](https://github.com/rellampec).
|
data/README.md
CHANGED
@@ -9,7 +9,8 @@ A friendlier Ruby client for consuming GraphQL-based APIs. Built on top of your
|
|
9
9
|
|
10
10
|
- [Installation](#installation)
|
11
11
|
- [Usage](#usage)
|
12
|
-
- [Schema
|
12
|
+
- [Schema Storing and Loading on Disk](#schema-storing-and-loading-on-disk)
|
13
|
+
- [Preloading Schema Once](#preloading-schema-once)
|
13
14
|
- [Error Handling](#error-handling)
|
14
15
|
- [Executing Parameterized Queries and Mutations](#executing-parameterized-queries-and-mutations)
|
15
16
|
- [Parse and Execute Queries Separately](#parse-and-execute-queries-separately)
|
@@ -140,6 +141,30 @@ client = Client.new(url, schema_path: 'config/your_graphql_schema.json')
|
|
140
141
|
client.schema.dump! # you only need to call this when graphql schema changes
|
141
142
|
```
|
142
143
|
|
144
|
+
### Preloading Schema Once
|
145
|
+
|
146
|
+
Even if caching the schema on disk, instantiating `Graphlient::Client` often can be both time and memory intensive due to loading the schema for each instance. This is especially true if the schema is a large file. To get around these performance issues, instantiate your schema once and pass it in as a configuration option.
|
147
|
+
|
148
|
+
One time in an initializer
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
schema = Graphlient::Schema.new(
|
152
|
+
'https://graphql.foo.com/graphql', 'lib/graphql_schema_foo.json'
|
153
|
+
)
|
154
|
+
```
|
155
|
+
|
156
|
+
Pass in each time you initialize a client
|
157
|
+
|
158
|
+
```
|
159
|
+
client = Graphlient::Client.new(
|
160
|
+
'https://graphql.foo.com/graphql',
|
161
|
+
schema: schema,
|
162
|
+
headers: {
|
163
|
+
'Authorization' => 'Bearer 123',
|
164
|
+
}
|
165
|
+
)
|
166
|
+
```
|
167
|
+
|
143
168
|
### Error Handling
|
144
169
|
|
145
170
|
Unlike graphql-client, Graphlient will always raise an exception unless the query has succeeded.
|
@@ -341,7 +366,7 @@ invoice_query = client.parse do
|
|
341
366
|
query do
|
342
367
|
invoice(id: 10) do
|
343
368
|
id
|
344
|
-
|
369
|
+
___Fragments__Invoice
|
345
370
|
end
|
346
371
|
end
|
347
372
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'faraday'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
module Graphlient
|
4
5
|
module Adapters
|
@@ -13,7 +14,8 @@ module Graphlient
|
|
13
14
|
variables: variables
|
14
15
|
}.to_json
|
15
16
|
end
|
16
|
-
|
17
|
+
|
18
|
+
parse_body(response.body)
|
17
19
|
rescue Faraday::ConnectionFailed => e
|
18
20
|
raise Graphlient::Errors::ConnectionFailedError, e
|
19
21
|
rescue Faraday::TimeoutError => e
|
@@ -39,6 +41,38 @@ module Graphlient
|
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Faraday 2.x's JSON response middleware will only parse a JSON
|
48
|
+
# response body into a Hash (or Array) object if the response headers
|
49
|
+
# match a specific content type regex. See Faraday's response JSON
|
50
|
+
# middleware definition for specifics on what the datatype of the
|
51
|
+
# response body will be. This method will handle the situation where
|
52
|
+
# the response header is not set appropriately, but contains JSON
|
53
|
+
# anyways. If the body cannot be parsed as JSON, an exception will be
|
54
|
+
# raised.
|
55
|
+
def parse_body(body)
|
56
|
+
case body
|
57
|
+
when Hash, Array
|
58
|
+
body
|
59
|
+
when String
|
60
|
+
begin
|
61
|
+
JSON.parse(body)
|
62
|
+
rescue JSON::ParserError
|
63
|
+
raise Graphlient::Errors::ServerError, 'Failed to parse response body as JSON'
|
64
|
+
end
|
65
|
+
else
|
66
|
+
inner_exception = StandardError.new <<~ERR.strip.tr("\n", ' ')
|
67
|
+
Unexpected response body type '#{body.class}'. Graphlient doesn't
|
68
|
+
know how to handle a response body of this type, but Faraday is
|
69
|
+
returning it. Please open an issue, particularly if the response
|
70
|
+
body does actually contain valid JSON.
|
71
|
+
ERR
|
72
|
+
|
73
|
+
raise Graphlient::Errors::ClientError, inner_exception
|
74
|
+
end
|
75
|
+
end
|
42
76
|
end
|
43
77
|
end
|
44
78
|
end
|
data/lib/graphlient/client.rb
CHANGED
@@ -2,9 +2,12 @@ module Graphlient
|
|
2
2
|
class Client
|
3
3
|
attr_accessor :uri, :options
|
4
4
|
|
5
|
+
class InvalidConfigurationError < StandardError; end
|
6
|
+
|
5
7
|
def initialize(url, options = {}, &_block)
|
6
8
|
@url = url
|
7
9
|
@options = options.dup
|
10
|
+
raise_error_if_invalid_configuration!
|
8
11
|
yield self if block_given?
|
9
12
|
end
|
10
13
|
|
@@ -51,11 +54,15 @@ module Graphlient
|
|
51
54
|
end
|
52
55
|
|
53
56
|
def schema
|
54
|
-
@schema ||= Graphlient::Schema.new(http, schema_path)
|
57
|
+
@schema ||= options[:schema] || Graphlient::Schema.new(http, schema_path)
|
55
58
|
end
|
56
59
|
|
57
60
|
private
|
58
61
|
|
62
|
+
def raise_error_if_invalid_configuration!
|
63
|
+
raise InvalidConfigurationError, 'schema_path and schema cannot both be provided' if options.key?(:schema_path) && options.key?(:schema)
|
64
|
+
end
|
65
|
+
|
59
66
|
def schema_path
|
60
67
|
return options[:schema_path].to_s if options[:schema_path]
|
61
68
|
end
|
data/lib/graphlient/version.rb
CHANGED
@@ -75,6 +75,61 @@ describe Graphlient::Adapters::HTTP::FaradayAdapter do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
context 'a non-error response without an appropriate JSON header' do
|
79
|
+
let(:url) { 'http://example.com/graphql' }
|
80
|
+
let(:headers) { { 'Content-Type' => 'application/notjson' } }
|
81
|
+
let(:client) { Graphlient::Client.new(url) }
|
82
|
+
let(:response_headers) { { 'Content-Type' => 'application/notjson' } }
|
83
|
+
|
84
|
+
context 'when the response body is valid JSON' do
|
85
|
+
before do
|
86
|
+
stub_request(:post, url).to_return(
|
87
|
+
status: 200,
|
88
|
+
headers: response_headers,
|
89
|
+
body: DummySchema.execute(GraphQL::Introspection::INTROSPECTION_QUERY).to_json
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'retrieves schema' do
|
94
|
+
expect(client.schema).to be_a Graphlient::Schema
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'when the response body is not valid JSON' do
|
99
|
+
before do
|
100
|
+
stub_request(:post, url).to_return(
|
101
|
+
status: 200,
|
102
|
+
headers: response_headers,
|
103
|
+
body: ''
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'raises Graphlient::Errors::ServerError' do
|
108
|
+
expect { client.schema }.to raise_error(Graphlient::Errors::ServerError) { |error|
|
109
|
+
expect(error.message).to include('Failed to parse response body as JSON')
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'when the Faraday response body object is not a type we expect from Faraday' do
|
115
|
+
before do
|
116
|
+
stub_request(:post, url).to_return(
|
117
|
+
status: 200,
|
118
|
+
headers: response_headers
|
119
|
+
)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'raises Graphlient::Errors::ClientError' do
|
123
|
+
mock_response = double('response', body: nil)
|
124
|
+
allow(client.http.connection).to receive(:post).and_return(mock_response)
|
125
|
+
|
126
|
+
expect { client.schema }.to raise_error(Graphlient::Errors::ClientError) { |error|
|
127
|
+
expect(error.message).to include "Unexpected response body type 'NilClass'"
|
128
|
+
}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
78
133
|
context 'Failed to open TCP connection error' do
|
79
134
|
let(:url) { 'http://example.com/graphql' }
|
80
135
|
let(:client) { Graphlient::Client.new(url) }
|
@@ -51,5 +51,25 @@ describe Graphlient::Client do
|
|
51
51
|
expect(client.schema.path).to eq 'config/schema.json'
|
52
52
|
end
|
53
53
|
end
|
54
|
+
|
55
|
+
context 'when preloaded schema is provided' do
|
56
|
+
let(:schema) { Graphlient::Schema.new(url, 'spec/support/fixtures/invoice_api.json') }
|
57
|
+
let(:client) { described_class.new(url, schema: schema) }
|
58
|
+
|
59
|
+
it 'returns the passed in schema' do
|
60
|
+
expect(client.schema).not_to be_nil
|
61
|
+
expect(client.schema).to eq(schema)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when and a schema and a schema path are provided' do
|
66
|
+
let(:schema) { Graphlient::Schema.new(url, 'spec/support/fixtures/invoice_api.json') }
|
67
|
+
let(:client) { described_class.new(url, schema: schema, schema_path: 'spec/support/fixtures/invoice_api.json') }
|
68
|
+
|
69
|
+
it 'raises an invalid configuration error' do
|
70
|
+
expect { client }.to raise_error(Graphlient::Client::InvalidConfigurationError,
|
71
|
+
/schema_path and schema cannot both be provided/)
|
72
|
+
end
|
73
|
+
end
|
54
74
|
end
|
55
75
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphlient
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ashkan Nasseri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -131,7 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
131
|
- !ruby/object:Gem::Version
|
132
132
|
version: 1.3.6
|
133
133
|
requirements: []
|
134
|
-
rubygems_version: 3.
|
134
|
+
rubygems_version: 3.3.7
|
135
135
|
signing_key:
|
136
136
|
specification_version: 4
|
137
137
|
summary: A friendlier Ruby client for consuming GraphQL-based APIs.
|