graphlient 0.3.3 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 7ed6aeee8ae9bf6da765d8142a11387f17bfff3f
4
- data.tar.gz: 084a33299652bb41bd08b83dd752a9703f0d7c58
2
+ SHA256:
3
+ metadata.gz: c049e978a0c48e45fe84d49470bc890ae3b6ea86b86aab8158322616c62968dd
4
+ data.tar.gz: c7307c2b5c6ac6ac2b55ee4d416bbfffee1e29ed0826916254077add10370ee9
5
5
  SHA512:
6
- metadata.gz: af15ee7373138bea76bf1d01beacdafa28ad50240974539c1fd33b3513a571253ce3df7b8739f4fbbd1ff3cbbe776af51c5c719c7ac68bc46e011d72cd97a3b1
7
- data.tar.gz: 4711176bd83a7d24d13ee8bef46ab8eaf54473d03da06912a00a1c4bb544057285801765e753ea5225e073f3e9bbcaf8f1769c75efc203767525f6a120354c44
6
+ metadata.gz: 627d0d04d5ecea5e4c33ea0e59b15ac46fc458f76f179ac624d3519036865ad29267f629b1b3fda7592a50c846ea2cf06cc58a8f188a06caee44715268c18d07
7
+ data.tar.gz: 9742adef6879fbd08b00350674dced4b4886e476b45388d6d1a1afaaebba440153632e878649ff68beb223b158f365dd180b6db76e8463a13dbbeb4cdf8aa88d
@@ -1,9 +1,18 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ Lint/SplatKeywordArguments:
5
+ Enabled: false
6
+
1
7
  Style/FrozenStringLiteralComment:
2
8
  Enabled: false
3
9
 
4
10
  Style/Documentation:
5
11
  Enabled: false
6
12
 
13
+ Style/SafeNavigation:
14
+ Enabled: false
15
+
7
16
  Metrics/LineLength:
8
17
  Enabled: false
9
18
 
@@ -3,9 +3,9 @@ language: ruby
3
3
  cache: bundler
4
4
 
5
5
  rvm:
6
- - 2.3.6
7
- - 2.4.3
8
6
  - 2.5.0
7
+ - 2.7.2
8
+ - 3.0.0
9
9
  - ruby-head
10
10
  - jruby-9.1.16.0
11
11
  - jruby-head
@@ -15,7 +15,7 @@ before_install:
15
15
 
16
16
  matrix:
17
17
  include:
18
- - rvm: 2.3.6
18
+ - rvm: 2.7.2
19
19
  script:
20
20
  - bundle exec danger
21
21
  allow_failures:
@@ -1,6 +1,34 @@
1
- ### 0.3.3 (Next)
2
-
1
+ ### 0.6.0 (Next)
3
2
  * Your contribution here.
3
+
4
+ ### 0.5.0 (12/28/2020)
5
+
6
+ * [#81](https://github.com/ashkan18/graphlient/pull/81): Make graphlient run on ruby 3.0 - [@Burgestrand](https://github.com/Burgestrand).
7
+ * [#79](https://github.com/ashkan18/graphlient/pull/79): Added client testing docs - [@GabrielDzul](https://github.com/GabrielDzul).
8
+
9
+ ### 0.4.0 (5/22/2020)
10
+
11
+ * [#72](https://github.com/ashkan18/graphlient/pull/72): Add http_options - [@neroleung](https://github.com/neroleung).
12
+ * [#71](https://github.com/ashkan18/graphlient/issues/70): Add `Graphlient::Errors::TimeoutError` - [@BenDrozdoff](https://github.com/BenDrozdoff).
13
+ * [#75](https://github.com/ashkan18/graphlient/pull/75): Support Faraday 1.x - [@jfhinchcliffe](https://github.com/jfhinchcliffe).
14
+ * [#78](https://github.com/ashkan18/graphlient/pull/78): Add description of timeout values - [@sap1enza](https://github.com/sap1enza).
15
+
16
+ ### 0.3.7 (11/14/2019)
17
+
18
+ * [#68](https://github.com/ashkan18/graphlient/pull/68): Add `Graphlient::Errors::ConnectionFailedError` - [@neroleung](https://github.com/neroleung).
19
+
20
+ ### 0.3.6 (07/23/2019)
21
+
22
+ * [#63](https://github.com/ashkan18/graphlient/pull/63): Remove unused method for attribute with typo - [@ashkan18](https://github.com/ashkan18).
23
+ * [#62](https://github.com/ashkan18/graphlient/pull/62): Fix typo preventing access to response object on error - [@jmondo](https://github.com/jmondo).
24
+
25
+ ### 0.3.4 (01/31/2019)
26
+
27
+ * [#56](https://github.com/ashkan18/graphlient/pull/56): Remove safe navigation usage to retain support for Ruby 2.2 - [@avinoth](https://github.com/avinoth).
28
+ * [#57](https://github.com/ashkan18/graphlient/pull/57): Add support for parsing queries from a String - [@ateamlunchbox](https://github.com/ateamlunchbox).
29
+
30
+ ### 0.3.3 (09/23/2018)
31
+
4
32
  * [#50](https://github.com/ashkan18/graphlient/pull/50): More detailed error responses - [@ashkan18](https://github.com/ashkan18).
5
33
 
6
34
  ### 0.3.2 (07/03/2018)
data/Gemfile CHANGED
@@ -4,6 +4,10 @@ gemspec
4
4
 
5
5
  gem 'rake'
6
6
 
7
+ group :development, :test do
8
+ gem 'activesupport', '< 6'
9
+ end
10
+
7
11
  group :development do
8
12
  gem 'byebug', platform: :ruby
9
13
  gem 'danger-changelog', '~> 0.2.1'
@@ -11,7 +15,7 @@ group :development do
11
15
  end
12
16
 
13
17
  group :test do
14
- gem 'graphql'
18
+ gem 'graphql', '~> 1.9'
15
19
  gem 'graphql-errors'
16
20
  gem 'rack-parser'
17
21
  gem 'rack-test'
data/README.md CHANGED
@@ -15,16 +15,25 @@ gem 'graphlient'
15
15
 
16
16
  ## Usage
17
17
 
18
- Create a new instance of `Graphlient::Client` with a URL and optional headers.
18
+ Create a new instance of `Graphlient::Client` with a URL and optional headers/http_options.
19
19
 
20
20
  ```ruby
21
21
  client = Graphlient::Client.new('https://test-graphql.biz/graphql',
22
22
  headers: {
23
23
  'Authorization' => 'Bearer 123'
24
+ },
25
+ http_options: {
26
+ read_timeout: 20,
27
+ write_timeout: 30
24
28
  }
25
29
  )
26
30
  ```
27
31
 
32
+ | http_options | default | type |
33
+ |---------------|---------|---------|
34
+ | read_timeout | nil | seconds |
35
+ | write_timeout | nil | seconds |
36
+
28
37
  The schema is available automatically via `.schema`.
29
38
 
30
39
  ```ruby
@@ -126,6 +135,9 @@ Unlike graphql-client, Graphlient will always raise an exception unless the quer
126
135
  * [Graphlient::Errors::ServerError](lib/graphlient/errors/server_error.rb): all transport errors raised by HTTP Adapters. You can access `inner_exception`, `status_code` and `response` on these errors to get more details on what went wrong
127
136
  * [Graphlient::Errors::FaradayServerError](lib/graphlient/errors/faraday_server_error.rb): this inherits from `ServerError` ☝️, we recommend using `ServerError` to rescue these
128
137
  * [Graphlient::Errors::HttpServerError](lib/graphlient/errors/http_server_error.rb): this inherits from `ServerError` ☝️, we recommend using `ServerError` to rescue these
138
+ * [Graphlient::Errors::ConnectionFailedError](lib/graphlient/errors/connection_failed_error.rb): this inherits from `ServerError` ☝️, we recommend using `ServerError` to rescue these
139
+ * [Graphlient::Errors::TimeoutError](lib/graphlient/errors/timeout_error.rb): this inherits from `ServerError` ☝️, we recommend using `ServerError` to rescue these
140
+ * [Graphlient::Errors::HttpOptionsError](lib/graphlient/errors/http_options_error.rb): all NoMethodError raised by HTTP Adapters when given options in `http_options` are invalid
129
141
 
130
142
 
131
143
  All errors inherit from `Graphlient::Errors::Error` if you need to handle them in bulk.
@@ -208,6 +220,23 @@ end
208
220
  client.execute query, ids: [42]
209
221
  ```
210
222
 
223
+ Or pass in a string instead of a block:
224
+
225
+ ```ruby
226
+ # parse a query, returns a GraphQL::Client::OperationDefinition
227
+ query = client.parse <<~GRAPHQL
228
+ query($some_id: Int) {
229
+ invoice(id: $some_id) {
230
+ id
231
+ feeInCents
232
+ }
233
+ }
234
+ GRAPHQL
235
+
236
+ # execute a query, returns a GraphQL::Client::Response
237
+ client.execute query, ids: [42]
238
+ ```
239
+
211
240
  ### Dynamic vs. Static Queries
212
241
 
213
242
  Graphlient uses [graphql-client](https://github.com/github/graphql-client), which [recommends](https://github.com/github/graphql-client/blob/master/guides/dynamic-query-error.md) building queries as static module members along with dynamic variables during execution. This can be accomplished with graphlient the same way.
@@ -316,7 +345,7 @@ describe App do
316
345
  Graphlient::Client.new('http://test-graphql.biz/graphql') do |client|
317
346
  client.http do |h|
318
347
  h.connection do |c|
319
- c.use Faraday::Adapter::Rack, app
348
+ c.adapter Faraday::Adapter::Rack, app
320
349
  end
321
350
  end
322
351
  end
@@ -360,6 +389,49 @@ describe App do
360
389
  end
361
390
  ```
362
391
 
392
+ In order to stub the response to actual queries, [dump the schema into a JSON file](#schema-storing-and-loading-on-disk) and specify it via schema_path as follows.
393
+
394
+ ```ruby
395
+ describe App do
396
+ let(:url) { 'http://graph.biz/graphql' }
397
+ let(:client) { Graphlient::Client.new(url, schema_path: 'spec/support/fixtures/invoice_api.json') }
398
+ let(:query) do
399
+ <<~GRAPHQL
400
+ query{
401
+ invoice(id: 42) {
402
+ id
403
+ feeInCents
404
+ }
405
+ }
406
+ GRAPHQL
407
+ end
408
+ let(:json_response) do
409
+ {
410
+ 'data' => {
411
+ 'invoice' => {
412
+ 'id' => '42',
413
+ 'feeInCents' => 2000
414
+ }
415
+ }
416
+ }.to_json
417
+ end
418
+
419
+ before do
420
+ stub_request(:post, url).to_return(
421
+ status: 200,
422
+ body: json_response
423
+ )
424
+ end
425
+
426
+ it 'returns invoice fees' do
427
+ response = client.query(query)
428
+ expect(response.data).to be_truthy
429
+ expect(response.data.invoice.id).to eq('42')
430
+ expect(response.data.invoice.fee_in_cents).to eq(2000)
431
+ end
432
+ end
433
+ ```
434
+
363
435
  ## License
364
436
 
365
437
  MIT License, see [LICENSE](LICENSE)
@@ -21,6 +21,8 @@ Change next release in [CHANGELOG.md](CHANGELOG.md) to the new version.
21
21
 
22
22
  Remove the line with "Your contribution here.", since there will be no more contributions to this release.
23
23
 
24
+ Update the version in `lib/graphlient/version.rb`.
25
+
24
26
  Commit your changes.
25
27
 
26
28
  ```
@@ -0,0 +1,23 @@
1
+ Upgrading Graphlient
2
+ ===========================
3
+
4
+ ### Upgrading to >= 0.4.0
5
+
6
+ #### Requires Faraday >= 1.0
7
+
8
+ See [#75](https://github.com/ashkan18/graphlient/pull/75).
9
+
10
+ #### Changes in error handling of connection refused error
11
+
12
+ When the GraphQL request was failing, we were receiving a `Faraday::ServerError`. After 0.4.0, Graphlient
13
+ will return `Graphlient::Errors::FaradayServerError` instead.
14
+
15
+ ### Upgrading to >= 0.3.7
16
+
17
+ #### Changes in error handling of connection refused error
18
+
19
+ Prior to 0.3.7, Graphlient would return `NoMethodError: undefined method []' for nil:NilClass` error if connection is
20
+ refused/failed when connecting to a remote host. After 0.3.7, Graphlient will return a new
21
+ `Graphlient::Errors::ConnectionFailedError` instead.
22
+
23
+ See [#68](https://github.com/ashkan18/graphlient/pull/68) for more information.
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
14
14
  s.homepage = 'http://github.com/ashkan18/graphlient'
15
15
  s.licenses = ['MIT']
16
16
  s.summary = 'A friendlier Ruby client for consuming GraphQL-based APIs.'
17
- s.add_dependency 'faraday'
17
+ s.add_dependency 'faraday', '>= 1.0'
18
18
  s.add_dependency 'faraday_middleware'
19
19
  s.add_dependency 'graphql-client'
20
20
  end
@@ -14,9 +14,27 @@ module Graphlient
14
14
  options[:headers] if options
15
15
  end
16
16
 
17
+ def http_options
18
+ return {} unless options
19
+
20
+ options[:http_options] || {}
21
+ end
22
+
17
23
  def execute(*)
18
24
  raise NotImplementedError
19
25
  end
26
+
27
+ private
28
+
29
+ def configure_http_options(client_options)
30
+ http_options.each do |k, v|
31
+ begin
32
+ client_options.send("#{k}=", v)
33
+ rescue NoMethodError => e
34
+ raise Graphlient::Errors::HttpOptionsError, e.message
35
+ end
36
+ end
37
+ end
20
38
  end
21
39
  end
22
40
  end
@@ -15,8 +15,14 @@ module Graphlient
15
15
  }.to_json
16
16
  end
17
17
  response.body
18
+ rescue Faraday::ConnectionFailed => e
19
+ raise Graphlient::Errors::ConnectionFailedError, e
20
+ rescue Faraday::TimeoutError => e
21
+ raise Graphlient::Errors::TimeoutError, e
18
22
  rescue Faraday::ClientError => e
19
23
  raise Graphlient::Errors::FaradayServerError, e
24
+ rescue Faraday::ServerError => e
25
+ raise Graphlient::Errors::FaradayServerError, e
20
26
  end
21
27
 
22
28
  def connection
@@ -24,10 +30,13 @@ module Graphlient
24
30
  c.use Faraday::Response::RaiseError
25
31
  c.request :json
26
32
  c.response :json
33
+
34
+ configure_http_options(c.options)
35
+
27
36
  if block_given?
28
37
  yield c
29
38
  else
30
- c.use Faraday::Adapter::NetHttp
39
+ c.adapter Faraday::Adapter::NetHttp
31
40
  end
32
41
  end
33
42
  end
@@ -9,7 +9,7 @@ module Graphlient
9
9
 
10
10
  request['Accept'] = 'application/json'
11
11
  request['Content-Type'] = 'application/json'
12
- headers&.each { |name, value| request[name] = value }
12
+ headers && headers.each { |name, value| request[name] = value }
13
13
 
14
14
  body = {}
15
15
  body['query'] = document.to_query_string
@@ -29,6 +29,8 @@ module Graphlient
29
29
  def connection
30
30
  Net::HTTP.new(uri.host, uri.port).tap do |client|
31
31
  client.use_ssl = uri.scheme == 'https'
32
+
33
+ configure_http_options(client)
32
34
  end
33
35
  end
34
36
  end
@@ -8,8 +8,8 @@ module Graphlient
8
8
  yield self if block_given?
9
9
  end
10
10
 
11
- def parse(&block)
12
- query_str = Graphlient::Query.new do
11
+ def parse(query_str = nil, &block)
12
+ query_str ||= Graphlient::Query.new do
13
13
  instance_eval(&block)
14
14
  end
15
15
  client.parse(query_str.to_s)
@@ -22,11 +22,11 @@ module Graphlient
22
22
  query_params[:context] = @options if @options
23
23
  query_params[:variables] = variables if variables
24
24
  query = client.parse(query) if query.is_a?(String)
25
- rc = client.query(query, query_params)
25
+ rc = client.query(query, **query_params)
26
26
  raise Graphlient::Errors::GraphQLError, rc if rc.errors.any?
27
27
  # see https://github.com/github/graphql-client/pull/132
28
28
  # see https://github.com/exAspArk/graphql-errors/issues/2
29
- raise Graphlient::Errors::ExecutionError, rc if rc.data&.errors && rc.data.errors.any?
29
+ raise Graphlient::Errors::ExecutionError, rc if errors_in_result?(rc)
30
30
  rc
31
31
  rescue GraphQL::Client::Error => e
32
32
  raise Graphlient::Errors::ClientError, e.message
@@ -45,7 +45,9 @@ module Graphlient
45
45
  end
46
46
 
47
47
  def http(&block)
48
- @http ||= http_adapter_class.new(@url, headers: @options[:headers], &block)
48
+ adapter_options = { headers: @options[:headers], http_options: @options[:http_options] }
49
+
50
+ @http ||= http_adapter_class.new(@url, adapter_options, &block)
49
51
  end
50
52
 
51
53
  def schema
@@ -63,5 +65,9 @@ module Graphlient
63
65
  client.allow_dynamic_queries = @options.key?(:allow_dynamic_queries) ? options[:allow_dynamic_queries] : true
64
66
  end
65
67
  end
68
+
69
+ def errors_in_result?(response)
70
+ response.data && response.data.errors && response.data.errors.any?
71
+ end
66
72
  end
67
73
  end
@@ -4,4 +4,7 @@ require_relative 'errors/server_error'
4
4
  require_relative 'errors/graphql_error'
5
5
  require_relative 'errors/execution_error'
6
6
  require_relative 'errors/faraday_server_error'
7
+ require_relative 'errors/http_options_error'
7
8
  require_relative 'errors/http_server_error'
9
+ require_relative 'errors/connection_failed_error'
10
+ require_relative 'errors/timeout_error'
@@ -0,0 +1,6 @@
1
+ module Graphlient
2
+ module Errors
3
+ class ConnectionFailedError < ServerError
4
+ end
5
+ end
6
+ end
@@ -1,7 +1,7 @@
1
1
  module Graphlient
2
2
  module Errors
3
3
  class GraphQLError < Error
4
- attr_reader :responsee
4
+ attr_reader :response
5
5
  def initialize(response)
6
6
  super('the server responded with a GraphQL error')
7
7
  @response = response
@@ -0,0 +1,6 @@
1
+ module Graphlient
2
+ module Errors
3
+ class HttpOptionsError < Error
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Graphlient
2
+ module Errors
3
+ class TimeoutError < Error
4
+ end
5
+ end
6
+ end
@@ -1,3 +1,3 @@
1
1
  module Graphlient
2
- VERSION = '0.3.3'.freeze
2
+ VERSION = '0.5.0'.freeze
3
3
  end
@@ -8,29 +8,32 @@ describe Graphlient::Adapters::HTTP::FaradayAdapter do
8
8
  Graphlient::Client.new('http://example.com/graphql') do |client|
9
9
  client.http do |h|
10
10
  h.connection do |c|
11
- c.use Faraday::Adapter::Rack, app
11
+ c.adapter Faraday::Adapter::Rack, app
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
16
 
17
17
  it 'inserts a middleware into the connection' do
18
+ expect(client.http.connection.adapter).to eq Faraday::Adapter::Rack
18
19
  expect(client.http.connection.builder.handlers).to eq(
19
20
  [
20
21
  Faraday::Response::RaiseError,
21
22
  FaradayMiddleware::EncodeJson,
22
- FaradayMiddleware::ParseJson,
23
- Faraday::Adapter::Rack
23
+ FaradayMiddleware::ParseJson
24
24
  ]
25
25
  )
26
26
  end
27
27
  end
28
28
 
29
- context 'with custom url and headers' do
29
+ context 'with custom url, headers and http_options' do
30
30
  let(:url) { 'http://example.com/graphql' }
31
31
  let(:headers) { { 'Foo' => 'bar' } }
32
+ let(:http_options) { { timeout: timeout, write_timeout: write_timeout } }
33
+ let(:timeout) { 123 }
34
+ let(:write_timeout) { 234 }
32
35
  let(:client) do
33
- Graphlient::Client.new(url, headers: headers)
36
+ Graphlient::Client.new(url, headers: headers, http_options: http_options)
34
37
  end
35
38
 
36
39
  it 'sets url' do
@@ -40,6 +43,19 @@ describe Graphlient::Adapters::HTTP::FaradayAdapter do
40
43
  it 'sets headers' do
41
44
  expect(client.http.headers).to eq headers
42
45
  end
46
+
47
+ it 'sets http_options' do
48
+ expect(client.http.connection.options.timeout).to eq(timeout)
49
+ expect(client.http.connection.options.write_timeout).to eq(write_timeout)
50
+ end
51
+
52
+ context 'when http_options contains invalid option' do
53
+ let(:http_options) { { an_invalid_option: 'an invalid option' } }
54
+
55
+ it 'raises Graphlient::Errors::HttpOptionsError' do
56
+ expect { client.http.connection }.to raise_error(Graphlient::Errors::HttpOptionsError)
57
+ end
58
+ end
43
59
  end
44
60
 
45
61
  context 'default' do
@@ -57,4 +73,40 @@ describe Graphlient::Adapters::HTTP::FaradayAdapter do
57
73
  expect(client.schema).to be_a Graphlient::Schema
58
74
  end
59
75
  end
76
+
77
+ context 'Failed to open TCP connection error' do
78
+ let(:url) { 'http://example.com/graphql' }
79
+ let(:client) { Graphlient::Client.new(url) }
80
+ let(:error_message) do
81
+ 'Failed to open TCP connection to localhost:3000 (Connection refused - connect(2) for "localhost" port 3000)'
82
+ end
83
+
84
+ before do
85
+ wrapped_error = Errno::ECONNREFUSED.new(error_message)
86
+ error = Faraday::ConnectionFailed.new(wrapped_error)
87
+
88
+ stub_request(:post, url).to_raise(error)
89
+ end
90
+
91
+ specify do
92
+ expected_error_message = "Connection refused - #{error_message}"
93
+
94
+ expect { client.schema }.to raise_error(Graphlient::Errors::ConnectionFailedError, expected_error_message)
95
+ end
96
+ end
97
+
98
+ context 'Faraday Timeout Error' do
99
+ let(:url) { 'http://example.com/graphql' }
100
+ let(:client) { Graphlient::Client.new(url) }
101
+ let(:error_message) { 'Failed to Connect' }
102
+
103
+ before do
104
+ stub_request(:post, url).to_raise(Faraday::TimeoutError.new(Net::ReadTimeout.new(error_message)))
105
+ end
106
+ it 'raises a Graphlient Timeout' do
107
+ expect { client.schema }.to raise_error(Graphlient::Errors::TimeoutError) { |error|
108
+ expect(error.message).to include(error_message)
109
+ }
110
+ end
111
+ end
60
112
  end