graphql 1.6.3 → 1.6.4
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/lib/generators/graphql/install_generator.rb +31 -5
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -1
- data/lib/graphql/query.rb +5 -0
- data/lib/graphql/query/literal_input.rb +4 -0
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
- data/lib/graphql/query/validation_pipeline.rb +3 -2
- data/lib/graphql/schema/printer.rb +6 -6
- data/lib/graphql/static_validation/validator.rb +9 -5
- data/lib/graphql/version.rb +1 -1
- data/readme.md +2 -0
- data/spec/generators/graphql/install_generator_spec.rb +17 -5
- data/spec/graphql/base_type_spec.rb +1 -1
- data/spec/graphql/query/literal_input_spec.rb +18 -0
- data/spec/graphql/query_spec.rb +21 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +21 -21
- data/spec/graphql/schema/printer_spec.rb +100 -98
- data/spec/graphql/static_validation/validator_spec.rb +10 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 347eef5d121c7ccb7f0c217370e2a02285d36096
|
4
|
+
data.tar.gz: e2b7083f415d77f05dcb888c121075617c93e677
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07a84a28ba76c6b7f0586b1c4e73745ae4d279482cab00b2a1ae6d087e566156359f993d325cc102c7af3ed23b0dc3f381d29635fef85ebe73d71ed103d7e0f2
|
7
|
+
data.tar.gz: d5b0dcfeb682086a666c839ebf4d0dcfd695201682016cc55d16d28d6f487012ac8f82e6360ea58780e3a6874c4eee52b49d0e8f44d37817e0672decdb27753f
|
@@ -68,6 +68,11 @@ module Graphql
|
|
68
68
|
default: false,
|
69
69
|
desc: "Include GraphQL::Batch installation"
|
70
70
|
|
71
|
+
# These two options are taken from Rails' own generators'
|
72
|
+
class_option :api,
|
73
|
+
type: :boolean,
|
74
|
+
desc: "Preconfigure smaller stack for API only apps"
|
75
|
+
|
71
76
|
|
72
77
|
GRAPHIQL_ROUTE = <<-RUBY
|
73
78
|
if Rails.env.development?
|
@@ -83,19 +88,40 @@ RUBY
|
|
83
88
|
template("graphql_controller.erb", "app/controllers/graphql_controller.rb")
|
84
89
|
route('post "/graphql", to: "graphql#execute"')
|
85
90
|
|
86
|
-
if !options[:skip_graphiql]
|
87
|
-
gem("graphiql-rails", group: :development)
|
88
|
-
route(GRAPHIQL_ROUTE)
|
89
|
-
end
|
90
|
-
|
91
91
|
if options[:batch]
|
92
92
|
gem("graphql-batch")
|
93
93
|
create_dir("app/graphql/loaders")
|
94
94
|
end
|
95
|
+
|
96
|
+
if options.api?
|
97
|
+
say("Skipped graphiql, as this rails project is API only")
|
98
|
+
say(" You may wish to use GraphiQL.app for development: https://github.com/skevy/graphiql-app")
|
99
|
+
elsif !options[:skip_graphiql]
|
100
|
+
gem("graphiql-rails", group: :development)
|
101
|
+
|
102
|
+
# This is a little cheat just to get cleaner shell output:
|
103
|
+
log :route, 'graphiql-rails'
|
104
|
+
shell.mute do
|
105
|
+
route(GRAPHIQL_ROUTE)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
if gemfile_modified?
|
110
|
+
say "Gemfile has been modified, make sure you `bundle install`"
|
111
|
+
end
|
95
112
|
end
|
96
113
|
|
97
114
|
private
|
98
115
|
|
116
|
+
def gemfile_modified?
|
117
|
+
@gemfile_modified
|
118
|
+
end
|
119
|
+
|
120
|
+
def gem(*args)
|
121
|
+
@gemfile_modified = true
|
122
|
+
super(*args)
|
123
|
+
end
|
124
|
+
|
99
125
|
def create_dir(dir)
|
100
126
|
empty_directory(dir)
|
101
127
|
if !options[:skip_keeps]
|
@@ -2,11 +2,12 @@ class GraphqlController < ApplicationController
|
|
2
2
|
def execute
|
3
3
|
variables = ensure_hash(params[:variables])
|
4
4
|
query = params[:query]
|
5
|
+
operation_name = params[:operationName]
|
5
6
|
context = {
|
6
7
|
# Query context goes here, for example:
|
7
8
|
# current_user: current_user,
|
8
9
|
}
|
9
|
-
result = <%= schema_name %>.execute(query, variables: variables, context: context)
|
10
|
+
result = <%= schema_name %>.execute(query, variables: variables, context: context, operation_name: operation_name)
|
10
11
|
render json: result
|
11
12
|
end
|
12
13
|
|
data/lib/graphql/query.rb
CHANGED
@@ -29,6 +29,9 @@ module GraphQL
|
|
29
29
|
|
30
30
|
attr_reader :schema, :context, :root_value, :warden, :provided_variables, :operation_name
|
31
31
|
|
32
|
+
# @return [Boolean] if false, static validation is skipped (execution behavior for invalid queries is undefined)
|
33
|
+
attr_accessor :validate
|
34
|
+
|
32
35
|
attr_accessor :query_string
|
33
36
|
|
34
37
|
# @return [GraphQL::Language::Nodes::Document]
|
@@ -59,6 +62,7 @@ module GraphQL
|
|
59
62
|
@root_value = root_value
|
60
63
|
@fragments = nil
|
61
64
|
@operations = nil
|
65
|
+
@validate = validate
|
62
66
|
|
63
67
|
@analysis_errors = []
|
64
68
|
if variables.is_a?(String)
|
@@ -270,6 +274,7 @@ module GraphQL
|
|
270
274
|
|
271
275
|
@validation_pipeline = GraphQL::Query::ValidationPipeline.new(
|
272
276
|
query: self,
|
277
|
+
validate: @validate,
|
273
278
|
parse_error: parse_error,
|
274
279
|
operation_name_error: operation_name_error,
|
275
280
|
max_depth: @max_depth,
|
@@ -77,6 +77,10 @@ module GraphQL
|
|
77
77
|
# `context` isn't present when pre-calculating defaults
|
78
78
|
if context
|
79
79
|
value = arg_defn.prepare(value, context)
|
80
|
+
if value.is_a?(GraphQL::ExecutionError)
|
81
|
+
value.ast_node = ast_arg
|
82
|
+
raise value
|
83
|
+
end
|
80
84
|
end
|
81
85
|
values_hash[arg_name] = value
|
82
86
|
end
|
@@ -24,7 +24,7 @@ module GraphQL
|
|
24
24
|
def result
|
25
25
|
result_name = irep_node.name
|
26
26
|
raw_value = get_raw_value
|
27
|
-
if raw_value
|
27
|
+
if raw_value.is_a?(GraphQL::Execution::Execute::Skip)
|
28
28
|
{}
|
29
29
|
else
|
30
30
|
{ result_name => get_finished_value(raw_value) }
|
@@ -14,10 +14,11 @@ module GraphQL
|
|
14
14
|
#
|
15
15
|
# @api private
|
16
16
|
class ValidationPipeline
|
17
|
-
def initialize(query:, parse_error:, operation_name_error:, max_depth:, max_complexity:)
|
17
|
+
def initialize(query:, validate:, parse_error:, operation_name_error:, max_depth:, max_complexity:)
|
18
18
|
@validation_errors = []
|
19
19
|
@analysis_errors = []
|
20
20
|
@internal_representation = nil
|
21
|
+
@validate = validate
|
21
22
|
@parse_error = parse_error
|
22
23
|
@operation_name_error = operation_name_error
|
23
24
|
@query = query
|
@@ -76,7 +77,7 @@ module GraphQL
|
|
76
77
|
elsif @operation_name_error
|
77
78
|
@validation_errors << @operation_name_error
|
78
79
|
else
|
79
|
-
validation_result = @schema.static_validator.validate(@query)
|
80
|
+
validation_result = @schema.static_validator.validate(@query, validate: @validate)
|
80
81
|
@validation_errors.concat(validation_result[:errors])
|
81
82
|
@internal_representation = validation_result[:irep]
|
82
83
|
|
@@ -186,7 +186,7 @@ module GraphQL
|
|
186
186
|
end
|
187
187
|
|
188
188
|
out = "(\n".dup
|
189
|
-
out << arguments.map.with_index{ |arg, i|
|
189
|
+
out << arguments.sort_by(&:name).map.with_index{ |arg, i|
|
190
190
|
"#{print_description(arg, " #{indentation}", i == 0)} #{indentation}"\
|
191
191
|
"#{print_input_value(arg)}"
|
192
192
|
}.join("\n")
|
@@ -244,7 +244,7 @@ module GraphQL
|
|
244
244
|
include DescriptionPrinter
|
245
245
|
def print_fields(warden, type)
|
246
246
|
fields = warden.fields(type)
|
247
|
-
fields.map.with_index { |field, i|
|
247
|
+
fields.sort_by(&:name).map.with_index { |field, i|
|
248
248
|
"#{print_description(field, ' ', i == 0)}"\
|
249
249
|
" #{field.name}#{print_args(warden, field, ' ')}: #{field.type}#{print_deprecated(field)}"
|
250
250
|
}.join("\n")
|
@@ -275,7 +275,7 @@ module GraphQL
|
|
275
275
|
def self.print(warden, type)
|
276
276
|
interfaces = warden.interfaces(type)
|
277
277
|
if interfaces.any?
|
278
|
-
implementations = " implements #{interfaces.map(&:to_s).join(", ")}"
|
278
|
+
implementations = " implements #{interfaces.sort_by(&:name).map(&:to_s).join(", ")}"
|
279
279
|
else
|
280
280
|
implementations = nil
|
281
281
|
end
|
@@ -301,7 +301,7 @@ module GraphQL
|
|
301
301
|
def self.print(warden, type)
|
302
302
|
possible_types = warden.possible_types(type)
|
303
303
|
"#{print_description(type)}"\
|
304
|
-
"union #{type.name} = #{possible_types.map(&:to_s).join(" | ")}"
|
304
|
+
"union #{type.name} = #{possible_types.sort_by(&:name).map(&:to_s).join(" | ")}"
|
305
305
|
end
|
306
306
|
end
|
307
307
|
|
@@ -311,7 +311,7 @@ module GraphQL
|
|
311
311
|
def self.print(warden, type)
|
312
312
|
enum_values = warden.enum_values(type)
|
313
313
|
|
314
|
-
values = enum_values.map.with_index { |v, i|
|
314
|
+
values = enum_values.sort_by(&:name).map.with_index { |v, i|
|
315
315
|
"#{print_description(v, ' ', i == 0)}"\
|
316
316
|
" #{v.name}#{print_deprecated(v)}"
|
317
317
|
}.join("\n")
|
@@ -326,7 +326,7 @@ module GraphQL
|
|
326
326
|
extend DescriptionPrinter
|
327
327
|
def self.print(warden, type)
|
328
328
|
arguments = warden.arguments(type)
|
329
|
-
fields = arguments.map.with_index{ |field, i|
|
329
|
+
fields = arguments.sort_by(&:name).map.with_index{ |field, i|
|
330
330
|
"#{print_description(field, " ", i == 0)}"\
|
331
331
|
" #{print_input_value(field)}"
|
332
332
|
}.join("\n")
|
@@ -7,8 +7,8 @@ module GraphQL
|
|
7
7
|
#
|
8
8
|
# @example Validate a query
|
9
9
|
# validator = GraphQL::StaticValidation::Validator.new(schema: MySchema)
|
10
|
-
#
|
11
|
-
# errors = validator.validate(
|
10
|
+
# query = GraphQL::Query.new(MySchema, query_string)
|
11
|
+
# errors = validator.validate(query)[:errors]
|
12
12
|
#
|
13
13
|
class Validator
|
14
14
|
# @param schema [GraphQL::Schema]
|
@@ -21,14 +21,18 @@ module GraphQL
|
|
21
21
|
# Validate `query` against the schema. Returns an array of message hashes.
|
22
22
|
# @param query [GraphQL::Query]
|
23
23
|
# @return [Array<Hash>]
|
24
|
-
def validate(query)
|
24
|
+
def validate(query, validate: true)
|
25
25
|
context = GraphQL::StaticValidation::ValidationContext.new(query)
|
26
26
|
rewrite = GraphQL::InternalRepresentation::Rewrite.new
|
27
27
|
|
28
28
|
# Put this first so its enters and exits are always called
|
29
29
|
rewrite.validate(context)
|
30
|
-
|
31
|
-
|
30
|
+
|
31
|
+
# If the caller opted out of validation, don't attach these
|
32
|
+
if validate
|
33
|
+
@rules.each do |rules|
|
34
|
+
rules.new.validate(context)
|
35
|
+
end
|
32
36
|
end
|
33
37
|
|
34
38
|
context.visitor.visit
|
data/lib/graphql/version.rb
CHANGED
data/readme.md
CHANGED
@@ -31,6 +31,8 @@ $ bundle install
|
|
31
31
|
$ rails generate graphql:install
|
32
32
|
```
|
33
33
|
|
34
|
+
After this, you may need to run `bundle install` again, as by default graphiql-rails is added on installation.
|
35
|
+
|
34
36
|
Or, see ["Getting Started"](https://rmosolgo.github.io/graphql-ruby/).
|
35
37
|
|
36
38
|
## Upgrade
|
@@ -3,20 +3,19 @@ require "spec_helper"
|
|
3
3
|
require "generators/graphql/install_generator"
|
4
4
|
|
5
5
|
class GraphQLGeneratorsInstallGeneratorTest < Rails::Generators::TestCase
|
6
|
-
|
7
6
|
tests Graphql::Generators::InstallGenerator
|
8
7
|
destination File.expand_path("../../../tmp/dummy", File.dirname(__FILE__))
|
9
8
|
|
10
9
|
setup do
|
11
10
|
prepare_destination
|
12
|
-
|
13
|
-
|
11
|
+
|
12
|
+
FileUtils.cd(File.join(destination_root, '..')) do
|
14
13
|
`rails new dummy --skip-active-record --skip-test-unit --skip-spring --skip-bundle`
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
18
17
|
test "it generates a folder structure" do
|
19
|
-
run_generator
|
18
|
+
run_generator
|
20
19
|
|
21
20
|
assert_file "app/graphql/types/.keep"
|
22
21
|
assert_file "app/graphql/mutations/.keep"
|
@@ -93,6 +92,18 @@ RUBY
|
|
93
92
|
assert_file "app/graphql/dummy_schema.rb", EXPECTED_RELAY_BATCH_SCHEMA
|
94
93
|
end
|
95
94
|
|
95
|
+
test "it doesn't install graphiql when API Only" do
|
96
|
+
run_generator(['--api'])
|
97
|
+
|
98
|
+
assert_file "Gemfile" do |contents|
|
99
|
+
refute_includes contents, "graphiql-rails"
|
100
|
+
end
|
101
|
+
|
102
|
+
assert_file "config/routes.rb" do |contents|
|
103
|
+
refute_includes contents, "GraphiQL::Rails"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
96
107
|
test "it can skip keeps, skip graphiql and customize schema name" do
|
97
108
|
run_generator(["--skip-keeps", "--skip-graphiql", "--schema=CustomSchema"])
|
98
109
|
assert_no_file "app/graphql/types/.keep"
|
@@ -116,11 +127,12 @@ class GraphqlController < ApplicationController
|
|
116
127
|
def execute
|
117
128
|
variables = ensure_hash(params[:variables])
|
118
129
|
query = params[:query]
|
130
|
+
operation_name = params[:operationName]
|
119
131
|
context = {
|
120
132
|
# Query context goes here, for example:
|
121
133
|
# current_user: current_user,
|
122
134
|
}
|
123
|
-
result = DummySchema.execute(query, variables: variables, context: context)
|
135
|
+
result = DummySchema.execute(query, variables: variables, context: context, operation_name: operation_name)
|
124
136
|
render json: result
|
125
137
|
end
|
126
138
|
|
@@ -20,6 +20,19 @@ describe GraphQL::Query::LiteralInput do
|
|
20
20
|
end
|
21
21
|
resolve ->(t, a, c) { a[:value] }
|
22
22
|
end
|
23
|
+
|
24
|
+
field :fieldWithArgumentThatIsBadByDefault do
|
25
|
+
type types.Int
|
26
|
+
argument :value do
|
27
|
+
type types.Int
|
28
|
+
default_value 7
|
29
|
+
prepare ->(arg, ctx) do
|
30
|
+
GraphQL::ExecutionError.new("Always bad")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
resolve ->(*args) { 42 }
|
35
|
+
end
|
23
36
|
end
|
24
37
|
|
25
38
|
GraphQL::Schema.define(query: query)
|
@@ -35,6 +48,11 @@ describe GraphQL::Query::LiteralInput do
|
|
35
48
|
assert_equal(7, result["data"]["addToArgumentValue"])
|
36
49
|
end
|
37
50
|
|
51
|
+
it "raises an execution error if the default value is bad" do
|
52
|
+
result = schema.execute("{ fieldWithArgumentThatIsBadByDefault }", context: { })
|
53
|
+
assert_equal(result["errors"], [{"message" => "Always bad"}])
|
54
|
+
end
|
55
|
+
|
38
56
|
it "prepares values from variables" do
|
39
57
|
result = schema.execute("query ($value: Int!) { addToArgumentValue(value: $value) }", variables: { "value" => 1}, context: { val: 2 } )
|
40
58
|
assert_equal(result["data"]["addToArgumentValue"], 3)
|
data/spec/graphql/query_spec.rb
CHANGED
@@ -518,6 +518,27 @@ describe GraphQL::Query do
|
|
518
518
|
end
|
519
519
|
end
|
520
520
|
|
521
|
+
describe "validate: false" do
|
522
|
+
it "doesn't validate the query" do
|
523
|
+
invalid_query_string = "{ nonExistantField }"
|
524
|
+
# Can assign attribute
|
525
|
+
query = GraphQL::Query.new(schema, invalid_query_string)
|
526
|
+
query.validate = false
|
527
|
+
assert_equal true, query.valid?
|
528
|
+
assert_equal 0, query.static_errors.length
|
529
|
+
|
530
|
+
# Can pass keyword argument
|
531
|
+
query = GraphQL::Query.new(schema, invalid_query_string, validate: false)
|
532
|
+
assert_equal true, query.valid?
|
533
|
+
assert_equal 0, query.static_errors.length
|
534
|
+
|
535
|
+
# Can pass `true`
|
536
|
+
query = GraphQL::Query.new(schema, invalid_query_string, validate: true)
|
537
|
+
assert_equal false, query.valid?
|
538
|
+
assert_equal 1, query.static_errors.length
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
521
542
|
describe 'NullValue type arguments' do
|
522
543
|
let(:schema_definition) {
|
523
544
|
<<-GRAPHQL
|
@@ -19,11 +19,11 @@ schema {
|
|
19
19
|
}
|
20
20
|
|
21
21
|
type HelloScalars {
|
22
|
-
|
23
|
-
int: Int
|
22
|
+
bool: Boolean
|
24
23
|
float: Float
|
25
24
|
id: ID
|
26
|
-
|
25
|
+
int: Int
|
26
|
+
str: String!
|
27
27
|
}
|
28
28
|
SCHEMA
|
29
29
|
|
@@ -60,11 +60,11 @@ directive @foo(
|
|
60
60
|
|
61
61
|
# With an enum
|
62
62
|
enum Color {
|
63
|
-
|
63
|
+
BLUE
|
64
64
|
|
65
65
|
# Not a creative color
|
66
66
|
GREEN
|
67
|
-
|
67
|
+
RED
|
68
68
|
}
|
69
69
|
|
70
70
|
# What a great type
|
@@ -142,11 +142,11 @@ schema {
|
|
142
142
|
}
|
143
143
|
|
144
144
|
type HelloScalars {
|
145
|
-
nonNullStr: String!
|
146
|
-
listOfStrs: [String]
|
147
145
|
listOfNonNullStrs: [String!]
|
148
|
-
|
146
|
+
listOfStrs: [String]
|
149
147
|
nonNullListOfNonNullStrs: [String!]!
|
148
|
+
nonNullListOfStrs: [String]!
|
149
|
+
nonNullStr: String!
|
150
150
|
}
|
151
151
|
SCHEMA
|
152
152
|
|
@@ -160,8 +160,8 @@ schema {
|
|
160
160
|
}
|
161
161
|
|
162
162
|
type Recurse {
|
163
|
-
str: String
|
164
163
|
recurse: Recurse
|
164
|
+
str: String
|
165
165
|
}
|
166
166
|
SCHEMA
|
167
167
|
|
@@ -195,10 +195,10 @@ schema {
|
|
195
195
|
}
|
196
196
|
|
197
197
|
type Hello {
|
198
|
-
|
198
|
+
booleanToStr(bool: Boolean): String
|
199
199
|
floatToStr(float: Float): String
|
200
200
|
idToStr(id: ID): String
|
201
|
-
|
201
|
+
str(int: Int): String
|
202
202
|
strToStr(bool: String): String
|
203
203
|
}
|
204
204
|
SCHEMA
|
@@ -281,8 +281,8 @@ schema {
|
|
281
281
|
}
|
282
282
|
|
283
283
|
enum Hello {
|
284
|
-
WO
|
285
284
|
RLD
|
285
|
+
WO
|
286
286
|
}
|
287
287
|
|
288
288
|
type OutputEnumRoot {
|
@@ -382,14 +382,14 @@ schema {
|
|
382
382
|
}
|
383
383
|
|
384
384
|
enum Color {
|
385
|
-
RED
|
386
385
|
BLUE
|
386
|
+
RED
|
387
387
|
}
|
388
388
|
|
389
389
|
type Hello {
|
390
|
-
str(int: Int = 2): String
|
391
390
|
hello(color: Color = RED): String
|
392
391
|
nullable(color: Color = null): String
|
392
|
+
str(int: Int = 2): String
|
393
393
|
}
|
394
394
|
SCHEMA
|
395
395
|
|
@@ -404,9 +404,9 @@ schema {
|
|
404
404
|
}
|
405
405
|
|
406
406
|
type HelloScalars {
|
407
|
-
str: String
|
408
|
-
int: Int
|
409
407
|
bool: Boolean
|
408
|
+
int: Int
|
409
|
+
str: String
|
410
410
|
}
|
411
411
|
|
412
412
|
type Mutation {
|
@@ -420,8 +420,8 @@ type Mutation {
|
|
420
420
|
it 'supports simple type with mutation and default values' do
|
421
421
|
schema = <<-SCHEMA
|
422
422
|
enum Color {
|
423
|
-
RED
|
424
423
|
BLUE
|
424
|
+
RED
|
425
425
|
}
|
426
426
|
|
427
427
|
type Mutation {
|
@@ -444,9 +444,9 @@ schema {
|
|
444
444
|
}
|
445
445
|
|
446
446
|
type HelloScalars {
|
447
|
-
str: String
|
448
|
-
int: Int
|
449
447
|
bool: Boolean
|
448
|
+
int: Int
|
449
|
+
str: String
|
450
450
|
}
|
451
451
|
|
452
452
|
type Subscription {
|
@@ -494,15 +494,15 @@ union Union = Concrete
|
|
494
494
|
it 'supports @deprecated' do
|
495
495
|
schema = <<-SCHEMA
|
496
496
|
enum MyEnum {
|
497
|
-
VALUE
|
498
497
|
OLD_VALUE @deprecated
|
499
498
|
OTHER_VALUE @deprecated(reason: "Terrible reasons")
|
499
|
+
VALUE
|
500
500
|
}
|
501
501
|
|
502
502
|
type Query {
|
503
|
+
enum: MyEnum
|
503
504
|
field1: String @deprecated
|
504
505
|
field2: Int @deprecated(reason: "Because I said so")
|
505
|
-
enum: MyEnum
|
506
506
|
}
|
507
507
|
SCHEMA
|
508
508
|
|
@@ -136,13 +136,13 @@ schema {
|
|
136
136
|
query: Root
|
137
137
|
}
|
138
138
|
|
139
|
-
# Directs the executor to include this field or fragment only when the
|
139
|
+
# Directs the executor to include this field or fragment only when the `if` argument is true.
|
140
140
|
directive @include(
|
141
141
|
# Included when true.
|
142
142
|
if: Boolean!
|
143
143
|
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
|
144
144
|
|
145
|
-
# Directs the executor to skip this field or fragment when the
|
145
|
+
# Directs the executor to skip this field or fragment when the `if` argument is true.
|
146
146
|
directive @skip(
|
147
147
|
# Skipped when true.
|
148
148
|
if: Boolean!
|
@@ -163,30 +163,33 @@ directive @deprecated(
|
|
163
163
|
# skipping a field. Directives provide this by describing additional information
|
164
164
|
# to the executor.
|
165
165
|
type __Directive {
|
166
|
-
|
166
|
+
args: [__InputValue!]!
|
167
167
|
description: String
|
168
168
|
locations: [__DirectiveLocation!]!
|
169
|
-
|
170
|
-
|
171
|
-
onFragment: Boolean! @deprecated(reason: "Use
|
172
|
-
|
169
|
+
name: String!
|
170
|
+
onField: Boolean! @deprecated(reason: "Use `locations`.")
|
171
|
+
onFragment: Boolean! @deprecated(reason: "Use `locations`.")
|
172
|
+
onOperation: Boolean! @deprecated(reason: "Use `locations`.")
|
173
173
|
}
|
174
174
|
|
175
175
|
# A Directive can be adjacent to many parts of the GraphQL language, a
|
176
176
|
# __DirectiveLocation describes one such possible adjacencies.
|
177
177
|
enum __DirectiveLocation {
|
178
|
-
# Location adjacent to
|
179
|
-
|
178
|
+
# Location adjacent to an argument definition.
|
179
|
+
ARGUMENT_DEFINITION
|
180
180
|
|
181
|
-
# Location adjacent to
|
182
|
-
|
181
|
+
# Location adjacent to an enum definition.
|
182
|
+
ENUM
|
183
183
|
|
184
|
-
# Location adjacent to
|
185
|
-
|
184
|
+
# Location adjacent to an enum value definition.
|
185
|
+
ENUM_VALUE
|
186
186
|
|
187
187
|
# Location adjacent to a field.
|
188
188
|
FIELD
|
189
189
|
|
190
|
+
# Location adjacent to a field definition.
|
191
|
+
FIELD_DEFINITION
|
192
|
+
|
190
193
|
# Location adjacent to a fragment definition.
|
191
194
|
FRAGMENT_DEFINITION
|
192
195
|
|
@@ -196,95 +199,91 @@ enum __DirectiveLocation {
|
|
196
199
|
# Location adjacent to an inline fragment.
|
197
200
|
INLINE_FRAGMENT
|
198
201
|
|
199
|
-
# Location adjacent to
|
200
|
-
|
202
|
+
# Location adjacent to an input object field definition.
|
203
|
+
INPUT_FIELD_DEFINITION
|
201
204
|
|
202
|
-
# Location adjacent to
|
203
|
-
|
205
|
+
# Location adjacent to an input object type definition.
|
206
|
+
INPUT_OBJECT
|
207
|
+
|
208
|
+
# Location adjacent to an interface definition.
|
209
|
+
INTERFACE
|
210
|
+
|
211
|
+
# Location adjacent to a mutation operation.
|
212
|
+
MUTATION
|
204
213
|
|
205
214
|
# Location adjacent to an object type definition.
|
206
215
|
OBJECT
|
207
216
|
|
208
|
-
# Location adjacent to a
|
209
|
-
|
217
|
+
# Location adjacent to a query operation.
|
218
|
+
QUERY
|
210
219
|
|
211
|
-
# Location adjacent to
|
212
|
-
|
220
|
+
# Location adjacent to a scalar definition.
|
221
|
+
SCALAR
|
213
222
|
|
214
|
-
# Location adjacent to
|
215
|
-
|
223
|
+
# Location adjacent to a schema definition.
|
224
|
+
SCHEMA
|
225
|
+
|
226
|
+
# Location adjacent to a subscription operation.
|
227
|
+
SUBSCRIPTION
|
216
228
|
|
217
229
|
# Location adjacent to a union definition.
|
218
230
|
UNION
|
219
|
-
|
220
|
-
# Location adjacent to an enum definition.
|
221
|
-
ENUM
|
222
|
-
|
223
|
-
# Location adjacent to an enum value definition.
|
224
|
-
ENUM_VALUE
|
225
|
-
|
226
|
-
# Location adjacent to an input object type definition.
|
227
|
-
INPUT_OBJECT
|
228
|
-
|
229
|
-
# Location adjacent to an input object field definition.
|
230
|
-
INPUT_FIELD_DEFINITION
|
231
231
|
}
|
232
232
|
|
233
233
|
# One possible value for a given Enum. Enum values are unique values, not a
|
234
234
|
# placeholder for a string or numeric value. However an Enum value is returned in
|
235
235
|
# a JSON response as a string.
|
236
236
|
type __EnumValue {
|
237
|
-
|
237
|
+
deprecationReason: String
|
238
238
|
description: String
|
239
239
|
isDeprecated: Boolean!
|
240
|
-
|
240
|
+
name: String!
|
241
241
|
}
|
242
242
|
|
243
243
|
# Object and Interface types are described by a list of Fields, each of which has
|
244
244
|
# a name, potentially a list of arguments, and a return type.
|
245
245
|
type __Field {
|
246
|
-
name: String!
|
247
|
-
description: String
|
248
246
|
args: [__InputValue!]!
|
249
|
-
type: __Type!
|
250
|
-
isDeprecated: Boolean!
|
251
247
|
deprecationReason: String
|
248
|
+
description: String
|
249
|
+
isDeprecated: Boolean!
|
250
|
+
name: String!
|
251
|
+
type: __Type!
|
252
252
|
}
|
253
253
|
|
254
254
|
# Arguments provided to Fields or Directives and the input fields of an
|
255
255
|
# InputObject are represented as Input Values which describe their type and
|
256
256
|
# optionally a default value.
|
257
257
|
type __InputValue {
|
258
|
-
name: String!
|
259
|
-
description: String
|
260
|
-
type: __Type!
|
261
|
-
|
262
258
|
# A GraphQL-formatted string representing the default value for this input value.
|
263
259
|
defaultValue: String
|
260
|
+
description: String
|
261
|
+
name: String!
|
262
|
+
type: __Type!
|
264
263
|
}
|
265
264
|
|
266
265
|
# A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all
|
267
266
|
# available types and directives on the server, as well as the entry points for
|
268
267
|
# query, mutation, and subscription operations.
|
269
268
|
type __Schema {
|
270
|
-
# A list of all
|
271
|
-
|
272
|
-
|
273
|
-
# The type that query operations will be rooted at.
|
274
|
-
queryType: __Type!
|
269
|
+
# A list of all directives supported by this server.
|
270
|
+
directives: [__Directive!]!
|
275
271
|
|
276
272
|
# If this server supports mutation, the type that mutation operations will be rooted at.
|
277
273
|
mutationType: __Type
|
278
274
|
|
275
|
+
# The type that query operations will be rooted at.
|
276
|
+
queryType: __Type!
|
277
|
+
|
279
278
|
# If this server support subscription, the type that subscription operations will be rooted at.
|
280
279
|
subscriptionType: __Type
|
281
280
|
|
282
|
-
# A list of all
|
283
|
-
|
281
|
+
# A list of all types supported by this server.
|
282
|
+
types: [__Type!]!
|
284
283
|
}
|
285
284
|
|
286
285
|
# The fundamental unit of any GraphQL Schema is the type. There are many kinds of
|
287
|
-
# types in GraphQL as represented by the
|
286
|
+
# types in GraphQL as represented by the `__TypeKind` enum.
|
288
287
|
#
|
289
288
|
# Depending on the kind of a type, certain fields describe information about that
|
290
289
|
# type. Scalar types provide no information beyond a name and description, while
|
@@ -292,42 +291,42 @@ type __Schema {
|
|
292
291
|
# they describe. Abstract types, Union and Interface, provide the Object types
|
293
292
|
# possible at runtime. List and NonNull types compose other types.
|
294
293
|
type __Type {
|
295
|
-
kind: __TypeKind!
|
296
|
-
name: String
|
297
294
|
description: String
|
298
|
-
fields(includeDeprecated: Boolean = false): [__Field!]
|
299
|
-
interfaces: [__Type!]
|
300
|
-
possibleTypes: [__Type!]
|
301
295
|
enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
|
296
|
+
fields(includeDeprecated: Boolean = false): [__Field!]
|
302
297
|
inputFields: [__InputValue!]
|
298
|
+
interfaces: [__Type!]
|
299
|
+
kind: __TypeKind!
|
300
|
+
name: String
|
303
301
|
ofType: __Type
|
302
|
+
possibleTypes: [__Type!]
|
304
303
|
}
|
305
304
|
|
306
|
-
# An enum describing what kind of type a given
|
305
|
+
# An enum describing what kind of type a given `__Type` is.
|
307
306
|
enum __TypeKind {
|
308
|
-
# Indicates this type is a
|
309
|
-
|
307
|
+
# Indicates this type is an enum. `enumValues` is a valid field.
|
308
|
+
ENUM
|
310
309
|
|
311
|
-
# Indicates this type is an object.
|
312
|
-
|
310
|
+
# Indicates this type is an input object. `inputFields` is a valid field.
|
311
|
+
INPUT_OBJECT
|
313
312
|
|
314
|
-
# Indicates this type is an interface.
|
313
|
+
# Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.
|
315
314
|
INTERFACE
|
316
315
|
|
317
|
-
# Indicates this type is a
|
318
|
-
|
316
|
+
# Indicates this type is a list. `ofType` is a valid field.
|
317
|
+
LIST
|
319
318
|
|
320
|
-
# Indicates this type is
|
321
|
-
|
319
|
+
# Indicates this type is a non-null. `ofType` is a valid field.
|
320
|
+
NON_NULL
|
322
321
|
|
323
|
-
# Indicates this type is an
|
324
|
-
|
322
|
+
# Indicates this type is an object. `fields` and `interfaces` are valid fields.
|
323
|
+
OBJECT
|
325
324
|
|
326
|
-
# Indicates this type is a
|
327
|
-
|
325
|
+
# Indicates this type is a scalar.
|
326
|
+
SCALAR
|
328
327
|
|
329
|
-
# Indicates this type is a
|
330
|
-
|
328
|
+
# Indicates this type is a union. `possibleTypes` is a valid field.
|
329
|
+
UNION
|
331
330
|
}
|
332
331
|
SCHEMA
|
333
332
|
assert_equal expected.chomp, GraphQL::Schema::Printer.print_introspection_schema
|
@@ -384,15 +383,15 @@ SCHEMA
|
|
384
383
|
it "returns the schema as a string for the defined types" do
|
385
384
|
expected = <<SCHEMA
|
386
385
|
type Audio {
|
386
|
+
duration: Int!
|
387
387
|
id: ID!
|
388
388
|
name: String!
|
389
|
-
duration: Int!
|
390
389
|
}
|
391
390
|
|
392
391
|
enum Choice {
|
393
|
-
FOO
|
394
392
|
BAR
|
395
393
|
BAZ @deprecated(reason: "Use \\\"BAR\\\".")
|
394
|
+
FOO
|
396
395
|
WOZ @deprecated
|
397
396
|
}
|
398
397
|
|
@@ -403,10 +402,11 @@ type Comment implements Node {
|
|
403
402
|
|
404
403
|
# Autogenerated input type of CreatePost
|
405
404
|
input CreatePostInput {
|
405
|
+
body: String!
|
406
|
+
|
406
407
|
# A unique identifier for the client performing the mutation.
|
407
408
|
clientMutationId: String
|
408
409
|
title: String!
|
409
|
-
body: String!
|
410
410
|
}
|
411
411
|
|
412
412
|
# Autogenerated return type of CreatePost
|
@@ -417,14 +417,14 @@ type CreatePostPayload {
|
|
417
417
|
}
|
418
418
|
|
419
419
|
type Image {
|
420
|
+
height: Int!
|
420
421
|
id: ID!
|
421
422
|
name: String!
|
422
423
|
width: Int!
|
423
|
-
height: Int!
|
424
424
|
}
|
425
425
|
|
426
426
|
# Media objects
|
427
|
-
union Media =
|
427
|
+
union Media = Audio | Image
|
428
428
|
|
429
429
|
type Mutation {
|
430
430
|
# Create a blog post
|
@@ -437,11 +437,11 @@ interface Node {
|
|
437
437
|
|
438
438
|
# A blog post
|
439
439
|
type Post {
|
440
|
-
id: ID!
|
441
|
-
title: String!
|
442
440
|
body: String!
|
443
441
|
comments: [Comment!]
|
444
|
-
comments_count: Int! @deprecated(reason:
|
442
|
+
comments_count: Int! @deprecated(reason: "Use \\\"comments\\\".")
|
443
|
+
id: ID!
|
444
|
+
title: String!
|
445
445
|
}
|
446
446
|
|
447
447
|
# The query root of this schema
|
@@ -449,7 +449,7 @@ type Query {
|
|
449
449
|
post(
|
450
450
|
# Post ID
|
451
451
|
id: ID!
|
452
|
-
varied: Varied = {id:
|
452
|
+
varied: Varied = {id: "123", int: 234, float: 2.3, enum: FOO, sub: [{string: "str"}]}
|
453
453
|
variedWithNulls: Varied = {id: null, int: null, float: null, enum: null, sub: null}
|
454
454
|
): Post
|
455
455
|
}
|
@@ -457,10 +457,10 @@ type Query {
|
|
457
457
|
# Test
|
458
458
|
input Sub {
|
459
459
|
# Something
|
460
|
-
|
460
|
+
int: Int
|
461
461
|
|
462
462
|
# Something
|
463
|
-
|
463
|
+
string: String
|
464
464
|
}
|
465
465
|
|
466
466
|
type Subscription {
|
@@ -468,14 +468,15 @@ type Subscription {
|
|
468
468
|
}
|
469
469
|
|
470
470
|
input Varied {
|
471
|
-
id: ID
|
472
|
-
int: Int
|
473
|
-
float: Float
|
474
471
|
bool: Boolean
|
475
472
|
enum: Choice = FOO
|
473
|
+
float: Float
|
474
|
+
id: ID
|
475
|
+
int: Int
|
476
476
|
sub: [Sub]
|
477
477
|
}
|
478
478
|
SCHEMA
|
479
|
+
|
479
480
|
assert_equal expected.chomp, GraphQL::Schema::Printer.print_schema(schema)
|
480
481
|
end
|
481
482
|
end
|
@@ -483,8 +484,8 @@ SCHEMA
|
|
483
484
|
it "applies an `only` filter" do
|
484
485
|
expected = <<SCHEMA
|
485
486
|
enum Choice {
|
486
|
-
FOO
|
487
487
|
BAR
|
488
|
+
FOO
|
488
489
|
}
|
489
490
|
|
490
491
|
type Subscription {
|
@@ -492,10 +493,10 @@ type Subscription {
|
|
492
493
|
}
|
493
494
|
|
494
495
|
input Varied {
|
495
|
-
int: Int
|
496
|
-
float: Float
|
497
496
|
bool: Boolean
|
498
497
|
enum: Choice = FOO
|
498
|
+
float: Float
|
499
|
+
int: Int
|
499
500
|
}
|
500
501
|
SCHEMA
|
501
502
|
|
@@ -520,14 +521,14 @@ SCHEMA
|
|
520
521
|
it "applies an `except` filter" do
|
521
522
|
expected = <<SCHEMA
|
522
523
|
type Audio {
|
524
|
+
duration: Int!
|
523
525
|
id: ID!
|
524
526
|
name: String!
|
525
|
-
duration: Int!
|
526
527
|
}
|
527
528
|
|
528
529
|
enum Choice {
|
529
|
-
FOO
|
530
530
|
BAR
|
531
|
+
FOO
|
531
532
|
}
|
532
533
|
|
533
534
|
# A blog comment
|
@@ -537,10 +538,11 @@ type Comment implements Node {
|
|
537
538
|
|
538
539
|
# Autogenerated input type of CreatePost
|
539
540
|
input CreatePostInput {
|
541
|
+
body: String!
|
542
|
+
|
540
543
|
# A unique identifier for the client performing the mutation.
|
541
544
|
clientMutationId: String
|
542
545
|
title: String!
|
543
|
-
body: String!
|
544
546
|
}
|
545
547
|
|
546
548
|
# Autogenerated return type of CreatePost
|
@@ -564,10 +566,10 @@ interface Node {
|
|
564
566
|
|
565
567
|
# A blog post
|
566
568
|
type Post {
|
567
|
-
id: ID!
|
568
|
-
title: String!
|
569
569
|
body: String!
|
570
570
|
comments: [Comment!]
|
571
|
+
id: ID!
|
572
|
+
title: String!
|
571
573
|
}
|
572
574
|
|
573
575
|
# The query root of this schema
|
@@ -596,11 +598,11 @@ SCHEMA
|
|
596
598
|
expected = <<SCHEMA
|
597
599
|
# A blog post
|
598
600
|
type Post {
|
599
|
-
id: ID!
|
600
|
-
title: String!
|
601
601
|
body: String!
|
602
602
|
comments: [Comment!]
|
603
603
|
comments_count: Int! @deprecated(reason: \"Use \\\"comments\\\".\")
|
604
|
+
id: ID!
|
605
|
+
title: String!
|
604
606
|
}
|
605
607
|
SCHEMA
|
606
608
|
assert_equal expected.chomp, GraphQL::Schema::Printer.new(schema).print_type(schema.types['Post'])
|
@@ -4,7 +4,8 @@ require "spec_helper"
|
|
4
4
|
describe GraphQL::StaticValidation::Validator do
|
5
5
|
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: Dummy::Schema) }
|
6
6
|
let(:query) { GraphQL::Query.new(Dummy::Schema, query_string) }
|
7
|
-
let(:
|
7
|
+
let(:validate) { true }
|
8
|
+
let(:errors) { validator.validate(query, validate: validate)[:errors].map(&:to_h) }
|
8
9
|
|
9
10
|
|
10
11
|
describe "validation order" do
|
@@ -30,6 +31,14 @@ describe GraphQL::StaticValidation::Validator do
|
|
30
31
|
# nonsenseField, nonsenseArg, bogusField, bogusArg, undefinedVar
|
31
32
|
assert_equal(5, errors.length)
|
32
33
|
end
|
34
|
+
|
35
|
+
describe "when validate: false" do
|
36
|
+
let(:validate) { false }
|
37
|
+
|
38
|
+
it "skips validation" do
|
39
|
+
assert_equal 0, errors.length
|
40
|
+
end
|
41
|
+
end
|
33
42
|
end
|
34
43
|
|
35
44
|
describe "infinite fragments" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|