graphlient 0.7.0 → 0.9.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/ISSUE_TEMPLATE/bug_report.md +38 -38
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
- data/.github/workflows/ci.yml +33 -29
- data/.github/workflows/danger-comment.yml +10 -0
- data/.github/workflows/danger.yml +13 -22
- data/.github/workflows/rubocop.yml +19 -19
- data/.gitignore +59 -52
- data/.rspec +1 -1
- data/.rubocop.yml +26 -28
- data/.rubocop_todo.yml +72 -48
- data/CHANGELOG.md +128 -107
- data/CONTRIBUTING.md +125 -125
- data/Dangerfile +24 -24
- data/Gemfile +35 -27
- data/LICENSE +21 -21
- data/README.md +800 -508
- data/RELEASING.md +63 -63
- data/Rakefile +15 -15
- data/UPGRADING.md +23 -23
- data/graphlient.gemspec +19 -19
- data/lib/graphlient/adapters/http/adapter.rb +41 -41
- data/lib/graphlient/adapters/http/faraday_adapter.rb +79 -45
- data/lib/graphlient/adapters/http/http_adapter.rb +40 -39
- data/lib/graphlient/adapters/http.rb +3 -3
- data/lib/graphlient/adapters.rb +1 -1
- data/lib/graphlient/client.rb +98 -73
- data/lib/graphlient/errors/client_error.rb +6 -6
- data/lib/graphlient/errors/connection_failed_error.rb +6 -6
- data/lib/graphlient/errors/error.rb +13 -12
- data/lib/graphlient/errors/execution_error.rb +29 -29
- data/lib/graphlient/errors/faraday_server_error.rb +12 -12
- data/lib/graphlient/errors/graphql_error.rb +53 -52
- data/lib/graphlient/errors/http_options_error.rb +6 -6
- data/lib/graphlient/errors/http_server_error.rb +13 -13
- data/lib/graphlient/errors/server_error.rb +7 -7
- data/lib/graphlient/errors/timeout_error.rb +6 -6
- data/lib/graphlient/errors.rb +10 -10
- data/lib/graphlient/extensions/query.rb +15 -15
- data/lib/graphlient/extensions.rb +1 -1
- data/lib/graphlient/query/directive.rb +47 -0
- data/lib/graphlient/query/serializer/arguments.rb +67 -0
- data/lib/graphlient/query/serializer/directives.rb +17 -0
- data/lib/graphlient/query/serializer/evaluator.rb +15 -0
- data/lib/graphlient/query/serializer/fragments.rb +28 -0
- data/lib/graphlient/query/serializer/scalars.rb +63 -0
- data/lib/graphlient/query/serializer.rb +153 -0
- data/lib/graphlient/query.rb +29 -128
- data/lib/graphlient/schema.rb +27 -26
- data/lib/graphlient/version.rb +3 -3
- data/lib/graphlient.rb +8 -8
- data/spec/graphlient/adapters/http/faraday_adapter_spec.rb +172 -112
- data/spec/graphlient/adapters/http/http_adapter_spec.rb +60 -60
- data/spec/graphlient/client_dsl_spec.rb +153 -0
- data/spec/graphlient/client_query_spec.rb +369 -346
- data/spec/graphlient/client_schema_spec.rb +75 -55
- data/spec/graphlient/extensions/query_spec.rb +16 -16
- data/spec/graphlient/github_query_spec.rb +32 -32
- data/spec/graphlient/query_dsl_spec.rb +231 -0
- data/spec/graphlient/query_spec.rb +105 -105
- data/spec/graphlient/schema_spec.rb +56 -56
- data/spec/graphlient/static_client_query_spec.rb +75 -68
- data/spec/graphlient/webmock_client_query_spec.rb +41 -41
- data/spec/spec_helper.rb +26 -14
- data/spec/support/context/dummy_client.rb +33 -26
- data/spec/support/context/github_client.rb +18 -18
- data/spec/support/dummy_app.rb +21 -19
- data/spec/support/dummy_schema.rb +17 -17
- data/spec/support/fixtures/github/schema.yml +14282 -14282
- data/spec/support/fixtures/github/user.yml +76 -76
- data/spec/support/fixtures/github/viewer.yml +76 -76
- data/spec/support/fixtures/invoice_api.json +1288 -1288
- data/spec/support/mutations/create_invoice.rb +18 -18
- data/spec/support/queries/query.rb +48 -47
- data/spec/support/schema/github.json +44479 -44479
- data/spec/support/types/invoice_type.rb +13 -13
- data/spec/support/types/mutation_type.rb +5 -5
- data/spec/support/vcr.rb +9 -9
- metadata +13 -8
- data/Gemfile.danger +0 -5
data/lib/graphlient/client.rb
CHANGED
|
@@ -1,73 +1,98 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
class Client
|
|
3
|
-
attr_accessor :uri, :options
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def
|
|
54
|
-
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
1
|
+
module Graphlient
|
|
2
|
+
class Client
|
|
3
|
+
attr_accessor :uri, :options
|
|
4
|
+
|
|
5
|
+
class InvalidConfigurationError < StandardError; end
|
|
6
|
+
|
|
7
|
+
def initialize(url, options = {}, &_block)
|
|
8
|
+
@url = url
|
|
9
|
+
@options = options.dup
|
|
10
|
+
raise_error_if_invalid_configuration!
|
|
11
|
+
yield self if block_given?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def parse(query_str = nil, &block)
|
|
15
|
+
query_str ||= Graphlient::Query.new do
|
|
16
|
+
instance_eval(&block)
|
|
17
|
+
end
|
|
18
|
+
client.parse(query_str.to_s)
|
|
19
|
+
rescue GraphQL::Client::Error => e
|
|
20
|
+
raise Graphlient::Errors::ClientError, e.message
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_query_string(**_kargs, &block)
|
|
24
|
+
Graphlient::Query.new do
|
|
25
|
+
instance_eval(&block)
|
|
26
|
+
end.to_s
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def execute(query, variables = nil)
|
|
30
|
+
query_params = {}
|
|
31
|
+
query_params[:context] = @options if @options
|
|
32
|
+
query_params[:variables] = variables if variables
|
|
33
|
+
query = client.parse(query) if query.is_a?(String)
|
|
34
|
+
rc = client.query(query, **query_params)
|
|
35
|
+
raise Graphlient::Errors::GraphQLError, rc if rc.errors.any?
|
|
36
|
+
# see https://github.com/github-community-projects/graphql-client/pull/132
|
|
37
|
+
# see https://github.com/exAspArk/graphql-errors/issues/2
|
|
38
|
+
raise Graphlient::Errors::ExecutionError, rc if errors_in_result?(rc)
|
|
39
|
+
|
|
40
|
+
rc
|
|
41
|
+
rescue GraphQL::Client::Error => e
|
|
42
|
+
raise Graphlient::Errors::ClientError, e.message
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def query(query_or_variables = nil, variables = nil, &block)
|
|
46
|
+
if block_given?
|
|
47
|
+
execute(parse(&block), query_or_variables)
|
|
48
|
+
else
|
|
49
|
+
execute(query_or_variables, variables)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def http_adapter_class
|
|
54
|
+
options[:http] || Adapters::HTTP::FaradayAdapter
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def http(&block)
|
|
58
|
+
adapter_options = { headers: @options[:headers], http_options: @options[:http_options] }
|
|
59
|
+
|
|
60
|
+
@http ||= http_adapter_class.new(@url, adapter_options, &block)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Register a custom scalar type for use in variable declarations.
|
|
64
|
+
# Call inside the client initialiser block:
|
|
65
|
+
# client = Graphlient::Client.new(url) do |c|
|
|
66
|
+
# c.scalar :date, 'Date'
|
|
67
|
+
# c.scalar :uuid, 'UUID'
|
|
68
|
+
# c.scalar :decimal, 'Decimal'
|
|
69
|
+
# end
|
|
70
|
+
def scalar(sym, graphql_type)
|
|
71
|
+
Query.scalar(sym, graphql_type)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def schema
|
|
75
|
+
@schema ||= options[:schema] || Graphlient::Schema.new(http, schema_path)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def raise_error_if_invalid_configuration!
|
|
81
|
+
raise InvalidConfigurationError, 'schema_path and schema cannot both be provided' if options.key?(:schema_path) && options.key?(:schema)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def schema_path
|
|
85
|
+
options[:schema_path].to_s if options[:schema_path]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def client
|
|
89
|
+
@client ||= GraphQL::Client.new(schema: schema.graphql_schema, execute: http).tap do |client|
|
|
90
|
+
client.allow_dynamic_queries = @options.key?(:allow_dynamic_queries) ? options[:allow_dynamic_queries] : true
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def errors_in_result?(response)
|
|
95
|
+
response.data && response.data.errors && response.data.errors.all.any?
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Errors
|
|
3
|
-
class ClientError < Error
|
|
4
|
-
end
|
|
5
|
-
end
|
|
6
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Errors
|
|
3
|
+
class ClientError < Error
|
|
4
|
+
end
|
|
5
|
+
end
|
|
6
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Errors
|
|
3
|
-
class ConnectionFailedError < ServerError
|
|
4
|
-
end
|
|
5
|
-
end
|
|
6
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Errors
|
|
3
|
+
class ConnectionFailedError < ServerError
|
|
4
|
+
end
|
|
5
|
+
end
|
|
6
|
+
end
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Errors
|
|
3
|
-
class Error < StandardError
|
|
4
|
-
attr_reader :inner_exception
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Errors
|
|
3
|
+
class Error < StandardError
|
|
4
|
+
attr_reader :inner_exception
|
|
5
|
+
|
|
6
|
+
def initialize(message, inner_exception = nil)
|
|
7
|
+
super(message)
|
|
8
|
+
|
|
9
|
+
@inner_exception = inner_exception
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Errors
|
|
3
|
-
class ExecutionError < Error
|
|
4
|
-
attr_reader :response
|
|
5
|
-
|
|
6
|
-
def initialize(response)
|
|
7
|
-
super('the server responded with a GraphQL execution error')
|
|
8
|
-
@response = response
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def errors
|
|
12
|
-
response.data.errors
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def to_s
|
|
16
|
-
errors.details.map do |key, details|
|
|
17
|
-
details = create_details(details).join("\n")
|
|
18
|
-
[key, details].compact.join(': ')
|
|
19
|
-
end.join("\n")
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
def create_details(details)
|
|
25
|
-
details.map { |detail| detail['message'] }
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Errors
|
|
3
|
+
class ExecutionError < Error
|
|
4
|
+
attr_reader :response
|
|
5
|
+
|
|
6
|
+
def initialize(response)
|
|
7
|
+
super('the server responded with a GraphQL execution error')
|
|
8
|
+
@response = response
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def errors
|
|
12
|
+
response.data.errors
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_s
|
|
16
|
+
errors.details.map do |key, details|
|
|
17
|
+
details = create_details(details).join("\n")
|
|
18
|
+
[key, details].compact.join(': ')
|
|
19
|
+
end.join("\n")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def create_details(details)
|
|
25
|
+
details.map { |detail| detail['message'] }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Errors
|
|
3
|
-
class FaradayServerError < ServerError
|
|
4
|
-
def initialize(inner_exception)
|
|
5
|
-
super(inner_exception.message, inner_exception)
|
|
6
|
-
@inner_exception = inner_exception
|
|
7
|
-
@response = inner_exception.response[:body]
|
|
8
|
-
@status_code = inner_exception.response[:status]
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Errors
|
|
3
|
+
class FaradayServerError < ServerError
|
|
4
|
+
def initialize(inner_exception)
|
|
5
|
+
super(inner_exception.message, inner_exception)
|
|
6
|
+
@inner_exception = inner_exception
|
|
7
|
+
@response = inner_exception.response[:body]
|
|
8
|
+
@status_code = inner_exception.response[:status]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -1,52 +1,53 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Errors
|
|
3
|
-
class GraphQLError < Error
|
|
4
|
-
attr_reader :response
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Errors
|
|
3
|
+
class GraphQLError < Error
|
|
4
|
+
attr_reader :response
|
|
5
|
+
|
|
6
|
+
def initialize(response)
|
|
7
|
+
super('the server responded with a GraphQL error')
|
|
8
|
+
@response = response
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def errors
|
|
12
|
+
@response.errors
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_s
|
|
16
|
+
errors.details.map do |key, details|
|
|
17
|
+
details = create_details(details).join("\n")
|
|
18
|
+
[key == 'data' ? nil : key, details].compact.join(': ')
|
|
19
|
+
end.join("\n")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def create_details(details)
|
|
25
|
+
details.map { |detail| create_detail(detail) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# Generates human readable error explanation from a GraphQL error message
|
|
30
|
+
# It first tries `problem` attribute of the error response
|
|
31
|
+
# then checks for error root level `path` and tries to generate error from that
|
|
32
|
+
# and if none exist, it fallbacks to just return error message
|
|
33
|
+
def create_detail(detail)
|
|
34
|
+
if detail.key?('problems')
|
|
35
|
+
[detail['message'], create_problems(detail['problems']).compact.join("\n ")].join("\n ")
|
|
36
|
+
elsif detail.key?('path')
|
|
37
|
+
[detail['path'].compact.join(' '), detail['message']].join(': ')
|
|
38
|
+
else
|
|
39
|
+
detail['message']
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def create_problems(problems)
|
|
44
|
+
problems.map { |problem| create_problem(problem) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def create_problem(problem)
|
|
48
|
+
paths = problem.key?('path') && !problem['path'].empty? ? "#{problem['path'].join(', ')}: " : ''
|
|
49
|
+
[paths, problem['explanation']].compact.join
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Errors
|
|
3
|
-
class HttpOptionsError < Error
|
|
4
|
-
end
|
|
5
|
-
end
|
|
6
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Errors
|
|
3
|
+
class HttpOptionsError < Error
|
|
4
|
+
end
|
|
5
|
+
end
|
|
6
|
+
end
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Errors
|
|
3
|
-
class HttpServerError < Error
|
|
4
|
-
attr_reader :status_code, :response
|
|
5
|
-
|
|
6
|
-
def initialize(message, response)
|
|
7
|
-
super(message, response)
|
|
8
|
-
@status_code = response.code
|
|
9
|
-
@response = response.body
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Errors
|
|
3
|
+
class HttpServerError < Error
|
|
4
|
+
attr_reader :status_code, :response
|
|
5
|
+
|
|
6
|
+
def initialize(message, response)
|
|
7
|
+
super(message, response)
|
|
8
|
+
@status_code = response.code
|
|
9
|
+
@response = response.body
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Errors
|
|
3
|
-
class ServerError < Error
|
|
4
|
-
attr_reader :status_code, :response
|
|
5
|
-
end
|
|
6
|
-
end
|
|
7
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Errors
|
|
3
|
+
class ServerError < Error
|
|
4
|
+
attr_reader :status_code, :response
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Errors
|
|
3
|
-
class TimeoutError < Error
|
|
4
|
-
end
|
|
5
|
-
end
|
|
6
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Errors
|
|
3
|
+
class TimeoutError < Error
|
|
4
|
+
end
|
|
5
|
+
end
|
|
6
|
+
end
|
data/lib/graphlient/errors.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
require_relative 'errors/error'
|
|
2
|
-
require_relative 'errors/client_error'
|
|
3
|
-
require_relative 'errors/server_error'
|
|
4
|
-
require_relative 'errors/graphql_error'
|
|
5
|
-
require_relative 'errors/execution_error'
|
|
6
|
-
require_relative 'errors/faraday_server_error'
|
|
7
|
-
require_relative 'errors/http_options_error'
|
|
8
|
-
require_relative 'errors/http_server_error'
|
|
9
|
-
require_relative 'errors/connection_failed_error'
|
|
10
|
-
require_relative 'errors/timeout_error'
|
|
1
|
+
require_relative 'errors/error'
|
|
2
|
+
require_relative 'errors/client_error'
|
|
3
|
+
require_relative 'errors/server_error'
|
|
4
|
+
require_relative 'errors/graphql_error'
|
|
5
|
+
require_relative 'errors/execution_error'
|
|
6
|
+
require_relative 'errors/faraday_server_error'
|
|
7
|
+
require_relative 'errors/http_options_error'
|
|
8
|
+
require_relative 'errors/http_server_error'
|
|
9
|
+
require_relative 'errors/connection_failed_error'
|
|
10
|
+
require_relative 'errors/timeout_error'
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
module Graphlient
|
|
2
|
-
module Extensions
|
|
3
|
-
module Query
|
|
4
|
-
def method_missing(method_name, *args, &block)
|
|
5
|
-
Graphlient::Query.new do
|
|
6
|
-
send(method_name, *args, &block)
|
|
7
|
-
end
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def respond_to_missing?(method_name, include_private = false)
|
|
11
|
-
super
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
1
|
+
module Graphlient
|
|
2
|
+
module Extensions
|
|
3
|
+
module Query
|
|
4
|
+
def method_missing(method_name, *args, &block)
|
|
5
|
+
Graphlient::Query.new do
|
|
6
|
+
send(method_name, *args, &block)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
require_relative 'extensions/query'
|
|
1
|
+
require_relative 'extensions/query'
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Graphlient
|
|
2
|
+
class Query
|
|
3
|
+
# Value object returned by `_directive_name(args)` in the DSL.
|
|
4
|
+
#
|
|
5
|
+
# Rather than writing directly to the query string (which would produce
|
|
6
|
+
# the wrong position -- before the field name), _skip / _include etc.
|
|
7
|
+
# return a Directive instance. append_node / spread / on detect Directive
|
|
8
|
+
# objects in their argument list and place them AFTER the field name,
|
|
9
|
+
# producing correct GraphQL output:
|
|
10
|
+
#
|
|
11
|
+
# feeInCents _skip(if: :skip_fee)
|
|
12
|
+
# -> feeInCents @skip(if: $skip_fee)
|
|
13
|
+
#
|
|
14
|
+
# spread :InvoiceFields, _skip(if: :x)
|
|
15
|
+
# -> ...InvoiceFields @skip(if: $x)
|
|
16
|
+
#
|
|
17
|
+
# spread(_skip(if: :x), on: :DraftInvoice) { draft_id }
|
|
18
|
+
# -> ... on DraftInvoice @skip(if: $x) { draftId }
|
|
19
|
+
class Directive
|
|
20
|
+
attr_reader :name, :args
|
|
21
|
+
|
|
22
|
+
def initialize(name, args = {})
|
|
23
|
+
@name = name.to_s.delete_prefix('_').freeze
|
|
24
|
+
@args = args
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_s
|
|
28
|
+
return "@#{name}" if args.empty?
|
|
29
|
+
|
|
30
|
+
formatted = args.map { |k, v| "#{k}: #{format_value(v)}" }.join(', ')
|
|
31
|
+
"@#{name}(#{formatted})"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
# Symbols become variable references ($name); everything else is literal.
|
|
37
|
+
def format_value(value)
|
|
38
|
+
case value
|
|
39
|
+
when Symbol then "$#{value}"
|
|
40
|
+
when String then "\"#{value}\""
|
|
41
|
+
when Numeric, TrueClass, FalseClass then value.to_s
|
|
42
|
+
else value.to_s
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module Graphlient
|
|
2
|
+
class Query
|
|
3
|
+
class Serializer
|
|
4
|
+
module Arguments
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def variable_processor
|
|
8
|
+
@variable_processor ||= ->(k, v) { "$#{k}: #{variable_string(v)}" }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Translate a DSL variable type symbol to its GraphQL type string.
|
|
12
|
+
# :id/:id! -> ID/ID! :int -> Int :date -> Date (if registered) [:int] -> [Int]
|
|
13
|
+
def variable_string(val)
|
|
14
|
+
case val
|
|
15
|
+
when :id, :id!
|
|
16
|
+
val.to_s.upcase
|
|
17
|
+
when ->(v) { scalar?(v) }
|
|
18
|
+
scalar_type(val)
|
|
19
|
+
when Array
|
|
20
|
+
"[#{variable_string(val.first)}]"
|
|
21
|
+
else
|
|
22
|
+
val.to_s
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Separate Directive objects from regular field arguments.
|
|
27
|
+
def field_args(args)
|
|
28
|
+
args.reject { |a| a.is_a?(Directive) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def directive_args(args)
|
|
32
|
+
args.select { |a| a.is_a?(Directive) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def hash_arg(args)
|
|
36
|
+
args.detect { |arg| arg.is_a?(Hash) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def args_str(hash_args, arg_processor: nil)
|
|
40
|
+
hash_args.map do |k, v|
|
|
41
|
+
arg_processor ? arg_processor.call(k, v) : argument_string(k, v)
|
|
42
|
+
end.join(', ')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def argument_string(key, val)
|
|
46
|
+
"#{key}: #{argument_value_string(val)}"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def argument_value_string(value)
|
|
50
|
+
case value
|
|
51
|
+
when String then "\"#{value}\""
|
|
52
|
+
when Numeric then value.to_s
|
|
53
|
+
when Array then "[#{value.map { |v| argument_value_string(v) }.join(', ')}]"
|
|
54
|
+
when Hash then "{ #{value.map { |k, v| "#{k}: #{argument_value_string(v)}" }.join(', ')} }"
|
|
55
|
+
when Symbol then symbol_argument_value(value)
|
|
56
|
+
else
|
|
57
|
+
value
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def symbol_argument_value(value)
|
|
62
|
+
@variables.respond_to?(:key?) && @variables.key?(value) ? "$#{value}" : value.to_s.camelize(:lower)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|