graphql 0.18.15 → 0.19.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/lib/graphql/define/assign_global_id_field.rb +1 -2
- data/lib/graphql/directive.rb +41 -7
- data/lib/graphql/directive/deprecated_directive.rb +11 -0
- data/lib/graphql/directive/include_directive.rb +2 -2
- data/lib/graphql/directive/skip_directive.rb +2 -2
- data/lib/graphql/input_object_type.rb +14 -0
- data/lib/graphql/internal_representation/node.rb +8 -4
- data/lib/graphql/introspection/arguments_field.rb +0 -1
- data/lib/graphql/introspection/directive_location_enum.rb +3 -2
- data/lib/graphql/introspection/directive_type.rb +12 -7
- data/lib/graphql/introspection/enum_value_type.rb +4 -2
- data/lib/graphql/introspection/enum_values_field.rb +0 -1
- data/lib/graphql/introspection/field_type.rb +8 -7
- data/lib/graphql/introspection/fields_field.rb +0 -1
- data/lib/graphql/introspection/input_fields_field.rb +0 -1
- data/lib/graphql/introspection/input_value_type.rb +8 -10
- data/lib/graphql/introspection/interfaces_field.rb +0 -1
- data/lib/graphql/introspection/of_type_field.rb +0 -1
- data/lib/graphql/introspection/possible_types_field.rb +0 -1
- data/lib/graphql/introspection/schema_type.rb +11 -9
- data/lib/graphql/introspection/type_kind_enum.rb +3 -3
- data/lib/graphql/introspection/type_type.rb +9 -6
- data/lib/graphql/language/generation.rb +4 -1
- data/lib/graphql/language/lexer.rb +353 -316
- data/lib/graphql/language/lexer.rl +8 -6
- data/lib/graphql/language/nodes.rb +12 -0
- data/lib/graphql/language/parser.rb +553 -501
- data/lib/graphql/language/parser.y +26 -16
- data/lib/graphql/language/parser_tests.rb +20 -1
- data/lib/graphql/list_type.rb +5 -1
- data/lib/graphql/non_null_type.rb +4 -0
- data/lib/graphql/object_type.rb +1 -1
- data/lib/graphql/query/literal_input.rb +1 -1
- data/lib/graphql/relay.rb +1 -1
- data/lib/graphql/relay/global_id_resolve.rb +3 -5
- data/lib/graphql/relay/node.rb +34 -0
- data/lib/graphql/scalar_type.rb +1 -1
- data/lib/graphql/schema.rb +43 -15
- data/lib/graphql/schema/loader.rb +2 -2
- data/lib/graphql/schema/printer.rb +50 -8
- data/lib/graphql/schema/unique_within_type.rb +28 -0
- data/lib/graphql/schema/validation.rb +10 -3
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +9 -1
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +8 -2
- data/lib/graphql/type_kinds.rb +12 -12
- data/lib/graphql/version.rb +1 -1
- data/readme.md +6 -5
- data/spec/graphql/argument_spec.rb +1 -1
- data/spec/graphql/execution_error_spec.rb +53 -0
- data/spec/graphql/introspection/directive_type_spec.rb +10 -0
- data/spec/graphql/introspection/input_value_type_spec.rb +23 -0
- data/spec/graphql/language/generation_spec.rb +4 -0
- data/spec/graphql/query/executor_spec.rb +2 -2
- data/spec/graphql/relay/mutation_spec.rb +1 -1
- data/spec/graphql/relay/node_spec.rb +87 -0
- data/spec/graphql/schema/catchall_middleware_spec.rb +1 -1
- data/spec/graphql/schema/loader_spec.rb +37 -4
- data/spec/graphql/schema/printer_spec.rb +30 -7
- data/spec/graphql/schema/unique_within_type_spec.rb +27 -0
- data/spec/graphql/schema/validation_spec.rb +7 -11
- data/spec/graphql/schema_spec.rb +32 -2
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +14 -15
- data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +10 -10
- data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +1 -5
- data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +3 -5
- data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +7 -11
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +1 -4
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +10 -13
- data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +3 -5
- data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +2 -4
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +4 -6
- data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +2 -4
- data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +7 -7
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -4
- data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +2 -4
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +3 -6
- data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +2 -4
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +12 -14
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +7 -9
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +20 -22
- data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +27 -23
- data/spec/spec_helper.rb +1 -0
- data/spec/support/dairy_app.rb +2 -2
- data/spec/support/star_wars_schema.rb +15 -18
- data/spec/support/static_validation_helpers.rb +27 -0
- metadata +25 -5
- data/lib/graphql/relay/global_node_identification.rb +0 -138
- data/spec/graphql/relay/global_node_identification_spec.rb +0 -153
@@ -46,7 +46,7 @@ rule
|
|
46
46
|
|
47
47
|
variable_definitions_opt:
|
48
48
|
/* none */ { return [] }
|
49
|
-
|
|
49
|
+
| LPAREN variable_definitions_list RPAREN { return val[1] }
|
50
50
|
|
51
51
|
variable_definitions_list:
|
52
52
|
variable_definition { return [val[0]] }
|
@@ -65,15 +65,15 @@ rule
|
|
65
65
|
type:
|
66
66
|
name { return make_node(:TypeName, name: val[0])}
|
67
67
|
| type BANG { return make_node(:NonNullType, of_type: val[0]) }
|
68
|
-
|
|
68
|
+
| LBRACKET type RBRACKET { return make_node(:ListType, of_type: val[1]) }
|
69
69
|
|
70
70
|
default_value_opt:
|
71
71
|
/* none */ { return nil }
|
72
72
|
| EQUALS input_value { return val[1] }
|
73
73
|
|
74
74
|
selection_set:
|
75
|
-
RCURLY
|
76
|
-
|
|
75
|
+
LCURLY RCURLY { return [] }
|
76
|
+
| LCURLY selection_list RCURLY { return val[1] }
|
77
77
|
|
78
78
|
selection_set_opt:
|
79
79
|
/* none */ { return [] }
|
@@ -155,8 +155,8 @@ rule
|
|
155
155
|
|
156
156
|
arguments_opt:
|
157
157
|
/* none */ { return [] }
|
158
|
-
| RPAREN
|
159
|
-
|
|
158
|
+
| LPAREN RPAREN { return [] }
|
159
|
+
| LPAREN arguments_list RPAREN { return val[1] }
|
160
160
|
|
161
161
|
arguments_list:
|
162
162
|
argument { return [val[0]] }
|
@@ -179,16 +179,16 @@ rule
|
|
179
179
|
variable: VAR_SIGN name { return make_node(:VariableIdentifier, name: val[1], position_source: val[0]) }
|
180
180
|
|
181
181
|
list_value:
|
182
|
-
RBRACKET
|
183
|
-
|
|
182
|
+
LBRACKET RBRACKET { return [] }
|
183
|
+
| LBRACKET list_value_list RBRACKET { return val[1] }
|
184
184
|
|
185
185
|
list_value_list:
|
186
186
|
input_value { return [val[0]] }
|
187
187
|
| list_value_list input_value { val[0] << val[1] }
|
188
188
|
|
189
189
|
object_value:
|
190
|
-
RCURLY
|
191
|
-
|
|
190
|
+
LCURLY RCURLY { return make_node(:InputObject, arguments: [], position_source: val[0])}
|
191
|
+
| LCURLY object_value_list RCURLY { return make_node(:InputObject, arguments: val[1], position_source: val[0])}
|
192
192
|
|
193
193
|
object_value_list:
|
194
194
|
object_value_field { return [val[0]] }
|
@@ -249,9 +249,10 @@ rule
|
|
249
249
|
type_system_definition:
|
250
250
|
schema_definition
|
251
251
|
| type_definition
|
252
|
+
| directive_definition
|
252
253
|
|
253
254
|
schema_definition:
|
254
|
-
SCHEMA
|
255
|
+
SCHEMA LCURLY operation_type_definition_list RCURLY { return make_node(:SchemaDefinition, val[2]) }
|
255
256
|
|
256
257
|
operation_type_definition_list:
|
257
258
|
operation_type_definition
|
@@ -271,7 +272,7 @@ rule
|
|
271
272
|
scalar_type_definition: SCALAR name directives_list_opt { return make_node(:ScalarTypeDefinition, name: val[1], directives: val[2]) }
|
272
273
|
|
273
274
|
object_type_definition:
|
274
|
-
TYPE name implements_opt directives_list_opt
|
275
|
+
TYPE name implements_opt directives_list_opt LCURLY field_definition_list RCURLY {
|
275
276
|
return make_node(:ObjectTypeDefinition, name: val[1], interfaces: val[2], directives: val[3], fields: val[5])
|
276
277
|
}
|
277
278
|
|
@@ -290,7 +291,7 @@ rule
|
|
290
291
|
|
291
292
|
arguments_definitions_opt:
|
292
293
|
/* none */ { return [] }
|
293
|
-
|
|
294
|
+
| LPAREN input_value_definition_list RPAREN { return val[1] }
|
294
295
|
|
295
296
|
field_definition:
|
296
297
|
name arguments_definitions_opt COLON type directives_list_opt {
|
@@ -302,7 +303,7 @@ rule
|
|
302
303
|
| field_definition_list field_definition { val[0] << val[1] }
|
303
304
|
|
304
305
|
interface_type_definition:
|
305
|
-
INTERFACE name directives_list_opt
|
306
|
+
INTERFACE name directives_list_opt LCURLY field_definition_list RCURLY {
|
306
307
|
return make_node(:InterfaceTypeDefinition, name: val[1], directives: val[2], fields: val[4])
|
307
308
|
}
|
308
309
|
|
@@ -316,14 +317,23 @@ rule
|
|
316
317
|
}
|
317
318
|
|
318
319
|
enum_type_definition:
|
319
|
-
ENUM name directives_list_opt
|
320
|
+
ENUM name directives_list_opt LCURLY enum_value_definitions RCURLY {
|
320
321
|
return make_node(:EnumTypeDefinition, name: val[1], directives: val[2], values: val[4])
|
321
322
|
}
|
322
323
|
|
323
324
|
input_object_type_definition:
|
324
|
-
INPUT name directives_list_opt
|
325
|
+
INPUT name directives_list_opt LCURLY input_value_definition_list RCURLY {
|
325
326
|
return make_node(:InputObjectTypeDefinition, name: val[1], directives: val[2], fields: val[4])
|
326
327
|
}
|
328
|
+
|
329
|
+
directive_definition:
|
330
|
+
DIRECTIVE DIR_SIGN name arguments_definitions_opt ON directive_locations {
|
331
|
+
return make_node(:DirectiveDefinition, name: val[2], arguments: val[3], locations: val[5])
|
332
|
+
}
|
333
|
+
|
334
|
+
directive_locations:
|
335
|
+
name { return [val[0].to_s] }
|
336
|
+
| directive_locations PIPE name { val[0] << val[2].to_s }
|
327
337
|
end
|
328
338
|
|
329
339
|
---- header ----
|
@@ -380,6 +380,25 @@ module GraphQL
|
|
380
380
|
assert_equal 'No longer supported', deprecated_directive.arguments[0].value
|
381
381
|
end
|
382
382
|
|
383
|
+
it "parses directive definition" do
|
384
|
+
document = subject.parse('
|
385
|
+
directive @include(if: Boolean!)
|
386
|
+
on FIELD
|
387
|
+
| FRAGMENT_SPREAD
|
388
|
+
| INLINE_FRAGMENT
|
389
|
+
')
|
390
|
+
|
391
|
+
type = document.definitions.first
|
392
|
+
assert_equal GraphQL::Language::Nodes::DirectiveDefinition, type.class
|
393
|
+
assert_equal 'include', type.name
|
394
|
+
|
395
|
+
assert_equal 1, type.arguments.length
|
396
|
+
assert_equal 'if', type.arguments[0].name
|
397
|
+
assert_equal 'Boolean', type.arguments[0].type.of_type.name
|
398
|
+
|
399
|
+
assert_equal ['FIELD', 'FRAGMENT_SPREAD', 'INLINE_FRAGMENT'], type.locations
|
400
|
+
end
|
401
|
+
|
383
402
|
it "parses scalar types" do
|
384
403
|
document = subject.parse('scalar DateTime')
|
385
404
|
|
@@ -535,7 +554,7 @@ module GraphQL
|
|
535
554
|
")
|
536
555
|
end
|
537
556
|
assert_includes(e.message, '"{"')
|
538
|
-
assert_includes(e.message, "
|
557
|
+
assert_includes(e.message, "LCURLY")
|
539
558
|
assert_equal(3, e.line)
|
540
559
|
assert_equal(33, e.col)
|
541
560
|
end
|
data/lib/graphql/list_type.rb
CHANGED
@@ -53,7 +53,11 @@ module GraphQL
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def coerce_non_null_input(value)
|
56
|
-
ensure_array(value).map{ |item| of_type.coerce_input(item) }
|
56
|
+
ensure_array(value).map { |item| of_type.coerce_input(item) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def coerce_result(value)
|
60
|
+
ensure_array(value).map { |item| item.nil? ? nil : of_type.coerce_result(item) }
|
57
61
|
end
|
58
62
|
|
59
63
|
private
|
data/lib/graphql/object_type.rb
CHANGED
@@ -11,7 +11,7 @@ module GraphQL
|
|
11
11
|
# field :director, PersonType
|
12
12
|
# field :cast, CastType
|
13
13
|
# field :starring, types[PersonType] do
|
14
|
-
#
|
14
|
+
# argument :limit, types.Int
|
15
15
|
# resolve -> (object, args, ctx) {
|
16
16
|
# stars = object.cast.stars
|
17
17
|
# args[:limit] && stars = stars.limit(args[:limit])
|
@@ -16,7 +16,7 @@ module GraphQL
|
|
16
16
|
values_hash = {}
|
17
17
|
argument_defns.each do |arg_name, arg_defn|
|
18
18
|
ast_arg = ast_arguments.find { |ast_arg| ast_arg.name == arg_name }
|
19
|
-
arg_default_value = arg_defn.
|
19
|
+
arg_default_value = arg_defn.default_value
|
20
20
|
if ast_arg.nil? && arg_default_value.nil?
|
21
21
|
# If it wasn't in the document,
|
22
22
|
# and there's no provided default,
|
data/lib/graphql/relay.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'base64'
|
2
2
|
|
3
|
-
require 'graphql/relay/global_node_identification'
|
4
3
|
require 'graphql/relay/page_info'
|
5
4
|
require 'graphql/relay/edge'
|
6
5
|
require 'graphql/relay/edge_type'
|
@@ -9,6 +8,7 @@ require 'graphql/relay/array_connection'
|
|
9
8
|
require 'graphql/relay/relation_connection'
|
10
9
|
require 'graphql/relay/global_id_resolve'
|
11
10
|
require 'graphql/relay/mutation'
|
11
|
+
require 'graphql/relay/node'
|
12
12
|
require 'graphql/relay/connection_field'
|
13
13
|
require 'graphql/relay/connection_resolve'
|
14
14
|
require 'graphql/relay/connection_type'
|
@@ -1,14 +1,12 @@
|
|
1
1
|
module GraphQL
|
2
2
|
module Relay
|
3
3
|
class GlobalIdResolve
|
4
|
-
def initialize(
|
5
|
-
@
|
6
|
-
@type_name = type_name
|
4
|
+
def initialize(type:)
|
5
|
+
@type = type
|
7
6
|
end
|
8
7
|
|
9
8
|
def call(obj, args, ctx)
|
10
|
-
|
11
|
-
ctx.query.schema.node_identification.to_global_id(@type_name, id_value)
|
9
|
+
ctx.query.schema.id_from_object(obj, @type, ctx)
|
12
10
|
end
|
13
11
|
end
|
14
12
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module GraphQL
|
2
|
+
module Relay
|
3
|
+
# Helpers for working with Relay-specific Node objects.
|
4
|
+
module Node
|
5
|
+
# @return [GraphQL::Field] a field for finding objects by their global ID.
|
6
|
+
def self.field
|
7
|
+
# We have to define it fresh each time because
|
8
|
+
# its name will be modified and its description
|
9
|
+
# _may_ be modified.
|
10
|
+
GraphQL::Field.define do
|
11
|
+
type(GraphQL::Relay::Node.interface)
|
12
|
+
description("Fetches an object given its ID")
|
13
|
+
argument(:id, !types.ID, "ID of the object")
|
14
|
+
resolve(GraphQL::Relay::Node::FindNode)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [GraphQL::InterfaceType] The interface which all Relay types must implement
|
19
|
+
def self.interface
|
20
|
+
@interface ||= GraphQL::InterfaceType.define do
|
21
|
+
name "Node"
|
22
|
+
field :id, !types.ID
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# A field resolve for finding an object by ID
|
27
|
+
module FindNode
|
28
|
+
def self.call(obj, args, ctx)
|
29
|
+
ctx.query.schema.object_from_id(args[:id], ctx )
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/graphql/scalar_type.rb
CHANGED
data/lib/graphql/schema.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require "graphql/schema/catchall_middleware"
|
2
2
|
require "graphql/schema/invalid_type_error"
|
3
3
|
require "graphql/schema/middleware_chain"
|
4
|
-
require "graphql/schema/rescue_middleware"
|
5
4
|
require "graphql/schema/possible_types"
|
5
|
+
require "graphql/schema/rescue_middleware"
|
6
6
|
require "graphql/schema/reduce_types"
|
7
7
|
require "graphql/schema/timeout_middleware"
|
8
8
|
require "graphql/schema/type_expression"
|
9
9
|
require "graphql/schema/type_map"
|
10
|
+
require "graphql/schema/unique_within_type"
|
10
11
|
require "graphql/schema/validation"
|
11
12
|
|
12
13
|
module GraphQL
|
@@ -47,8 +48,8 @@ module GraphQL
|
|
47
48
|
:query, :mutation, :subscription,
|
48
49
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
49
50
|
:max_depth, :max_complexity,
|
50
|
-
:node_identification,
|
51
51
|
:orphan_types, :resolve_type,
|
52
|
+
:object_from_id, :id_from_object,
|
52
53
|
query_analyzer: -> (schema, analyzer) { schema.query_analyzers << analyzer },
|
53
54
|
middleware: -> (schema, middleware) { schema.middleware << middleware },
|
54
55
|
rescue_from: -> (schema, err_class, &block) { schema.rescue_from(err_class, &block)}
|
@@ -57,23 +58,16 @@ module GraphQL
|
|
57
58
|
:query, :mutation, :subscription,
|
58
59
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
59
60
|
:max_depth, :max_complexity,
|
60
|
-
:orphan_types,
|
61
|
+
:orphan_types,
|
61
62
|
:query_analyzers, :middleware
|
62
63
|
|
63
|
-
|
64
|
-
DIRECTIVES = [GraphQL::Directive::SkipDirective, GraphQL::Directive::IncludeDirective]
|
64
|
+
DIRECTIVES = [GraphQL::Directive::SkipDirective, GraphQL::Directive::IncludeDirective, GraphQL::Directive::DeprecatedDirective]
|
65
65
|
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
|
66
|
-
RESOLVE_TYPE_PROC_REQUIRED = -> (obj, ctx) { raise("Schema.resolve_type is undefined, can't resolve type for #{obj.inspect}") }
|
66
|
+
RESOLVE_TYPE_PROC_REQUIRED = -> (obj, ctx) { raise(NotImplementedError, "Schema.resolve_type is undefined, can't resolve type for #{obj.inspect}") }
|
67
|
+
OBJECT_FROM_ID_PROC_REQUIRED = -> (id, ctx) { raise(NotImplementedError, "Schema.object_from_id is undefined, can't fetch object for #{id.inspect}") }
|
68
|
+
ID_FROM_OBJECT_PROC_REQUIRED = -> (obj, type, ctx) { raise(NotImplementedError, "Schema.id_from_object is undefined, can't return an ID for #{obj.inspect}") }
|
67
69
|
|
68
|
-
attr_reader :directives, :static_validator
|
69
|
-
|
70
|
-
# @!attribute node_identification
|
71
|
-
# @return [GraphQL::Relay::GlobalNodeIdentification] the node identification instance for this schema, when using Relay
|
72
|
-
|
73
|
-
def node_identification=(new_node_ident)
|
74
|
-
new_node_ident.schema = self
|
75
|
-
@node_identification = new_node_ident
|
76
|
-
end
|
70
|
+
attr_reader :directives, :static_validator, :object_from_id_proc, :id_from_object_proc
|
77
71
|
|
78
72
|
# @!attribute [r] middleware
|
79
73
|
# @return [Array<#call>] Middlewares suitable for MiddlewareChain, applied to fields during execution
|
@@ -99,6 +93,8 @@ module GraphQL
|
|
99
93
|
@middleware = [@rescue_middleware]
|
100
94
|
@query_analyzers = []
|
101
95
|
@resolve_type_proc = RESOLVE_TYPE_PROC_REQUIRED
|
96
|
+
@object_from_id_proc = OBJECT_FROM_ID_PROC_REQUIRED
|
97
|
+
@id_from_object_proc = ID_FROM_OBJECT_PROC_REQUIRED
|
102
98
|
# Default to the built-in execution strategy:
|
103
99
|
@query_execution_strategy = GraphQL::Query::SerialExecution
|
104
100
|
@mutation_execution_strategy = GraphQL::Query::SerialExecution
|
@@ -192,6 +188,8 @@ module GraphQL
|
|
192
188
|
|
193
189
|
# Determine the GraphQL type for a given object.
|
194
190
|
# This is required for unions and interfaces (include Relay's node interface)
|
191
|
+
# @param object [Any] An application object which GraphQL is currently resolving on
|
192
|
+
# @param ctx [GraphQL::Query::Context] The context for the current query
|
195
193
|
# @return [GraphQL::ObjectType] The type for exposing `object` in GraphQL
|
196
194
|
def resolve_type(object, ctx)
|
197
195
|
ensure_defined
|
@@ -210,5 +208,35 @@ module GraphQL
|
|
210
208
|
ensure_defined
|
211
209
|
@resolve_type_proc = new_resolve_type_proc
|
212
210
|
end
|
211
|
+
|
212
|
+
# Fetch an application object by its unique id
|
213
|
+
# @param id [String] A unique identifier, provided previously by this GraphQL schema
|
214
|
+
# @param ctx [GraphQL::Query::Context] The context for the current query
|
215
|
+
# @return [Any] The application object identified by `id`
|
216
|
+
def object_from_id(id, ctx)
|
217
|
+
ensure_defined
|
218
|
+
@object_from_id_proc.call(id, ctx)
|
219
|
+
end
|
220
|
+
|
221
|
+
# @param new_proc [#call] A new callable for fetching objects by ID
|
222
|
+
def object_from_id=(new_proc)
|
223
|
+
ensure_defined
|
224
|
+
@object_from_id_proc = new_proc
|
225
|
+
end
|
226
|
+
|
227
|
+
# Get a unique identifier from this object
|
228
|
+
# @param object [Any] An application object
|
229
|
+
# @param ctx [GraphQL::Query::Context] the context for the current query
|
230
|
+
# @return [String] a unique identifier for `object` which clients can use to refetch it
|
231
|
+
def id_from_object(type, object, ctx)
|
232
|
+
ensure_defined
|
233
|
+
@id_from_object_proc.call(type, object, ctx)
|
234
|
+
end
|
235
|
+
|
236
|
+
# @param new_proc [#call] A new callable for generating unique IDs
|
237
|
+
def id_from_object=(new_proc)
|
238
|
+
ensure_defined
|
239
|
+
@id_from_object_proc = new_proc
|
240
|
+
end
|
213
241
|
end
|
214
242
|
end
|
@@ -58,7 +58,7 @@ module GraphQL
|
|
58
58
|
name: enum["name"],
|
59
59
|
description: enum["description"],
|
60
60
|
deprecation_reason: enum["deprecationReason"],
|
61
|
-
value: enum["
|
61
|
+
value: enum["name"]
|
62
62
|
)
|
63
63
|
})
|
64
64
|
when "INTERFACE"
|
@@ -102,7 +102,7 @@ module GraphQL
|
|
102
102
|
name: type["name"],
|
103
103
|
type: type_resolver.call(type["type"]),
|
104
104
|
description: type["description"],
|
105
|
-
default_value: type["defaultValue"]
|
105
|
+
default_value: type["defaultValue"] ? JSON.parse(type["defaultValue"], quirks_mode: true) : nil
|
106
106
|
)
|
107
107
|
when "SCALAR"
|
108
108
|
case type.fetch("name")
|
@@ -12,7 +12,7 @@ module GraphQL
|
|
12
12
|
# Return a GraphQL schema string for the defined types in the schema
|
13
13
|
# @param schema [GraphQL::Schema]
|
14
14
|
def print_schema(schema)
|
15
|
-
print_filtered_schema(schema, method(:is_defined_type))
|
15
|
+
print_filtered_schema(schema, lambda { |n| !is_spec_directive(n) }, method(:is_defined_type))
|
16
16
|
end
|
17
17
|
|
18
18
|
# Return the GraphQL schema string for the introspection type system
|
@@ -21,16 +21,20 @@ module GraphQL
|
|
21
21
|
name "Query"
|
22
22
|
end
|
23
23
|
schema = GraphQL::Schema.define(query: query_root)
|
24
|
-
print_filtered_schema(schema, method(:is_introspection_type))
|
24
|
+
print_filtered_schema(schema, method(:is_spec_directive), method(:is_introspection_type))
|
25
25
|
end
|
26
26
|
|
27
27
|
private
|
28
28
|
|
29
|
-
def print_filtered_schema(schema, type_filter)
|
29
|
+
def print_filtered_schema(schema, directive_filter, type_filter)
|
30
|
+
directives = schema.directives.values.select{ |directive| directive_filter.call(directive) }
|
31
|
+
directive_definitions = directives.map{ |directive| print_directive(directive) }
|
32
|
+
|
30
33
|
types = schema.types.values.select{ |type| type_filter.call(type) }.sort_by(&:name)
|
31
34
|
type_definitions = types.map{ |type| print_type(type) }
|
32
35
|
|
33
|
-
[print_schema_definition(schema)].concat(
|
36
|
+
[print_schema_definition(schema)].concat(directive_definitions)
|
37
|
+
.concat(type_definitions).join("\n\n")
|
34
38
|
end
|
35
39
|
|
36
40
|
def print_schema_definition(schema)
|
@@ -44,6 +48,10 @@ module GraphQL
|
|
44
48
|
BUILTIN_SCALARS = Set.new(["String", "Boolean", "Int", "Float", "ID"])
|
45
49
|
private_constant :BUILTIN_SCALARS
|
46
50
|
|
51
|
+
def is_spec_directive(directive)
|
52
|
+
['skip', 'include', 'deprecated'].include?(directive.name)
|
53
|
+
end
|
54
|
+
|
47
55
|
def is_introspection_type(type)
|
48
56
|
type.name.start_with?("__")
|
49
57
|
end
|
@@ -56,12 +64,27 @@ module GraphQL
|
|
56
64
|
TypeKindPrinters::STRATEGIES.fetch(type.kind).print(type)
|
57
65
|
end
|
58
66
|
|
67
|
+
def print_directive(directive)
|
68
|
+
TypeKindPrinters::DirectivePrinter.print(directive)
|
69
|
+
end
|
70
|
+
|
59
71
|
module TypeKindPrinters
|
60
|
-
module
|
61
|
-
def
|
62
|
-
|
72
|
+
module DeprecatedPrinter
|
73
|
+
def print_deprecated(field_or_enum_value)
|
74
|
+
return unless field_or_enum_value.deprecation_reason
|
75
|
+
|
76
|
+
case field_or_enum_value.deprecation_reason
|
77
|
+
when nil
|
78
|
+
''
|
79
|
+
when '', GraphQL::Directive::DEFAULT_DEPRECATION_REASON
|
80
|
+
' @deprecated'
|
81
|
+
else
|
82
|
+
" @deprecated(reason: #{field_or_enum_value.deprecation_reason.to_s.inspect})"
|
83
|
+
end
|
63
84
|
end
|
85
|
+
end
|
64
86
|
|
87
|
+
module ArgsPrinter
|
65
88
|
def print_args(field)
|
66
89
|
return if field.arguments.empty?
|
67
90
|
"(#{field.arguments.values.map{ |arg| print_input_value(arg) }.join(", ")})"
|
@@ -105,6 +128,24 @@ module GraphQL
|
|
105
128
|
end
|
106
129
|
end
|
107
130
|
|
131
|
+
module FieldPrinter
|
132
|
+
include DeprecatedPrinter
|
133
|
+
include ArgsPrinter
|
134
|
+
def print_fields(type)
|
135
|
+
type.all_fields.map{ |field|
|
136
|
+
" #{field.name}#{print_args(field)}: #{field.type}#{print_deprecated(field)}"
|
137
|
+
}.join("\n")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class DirectivePrinter
|
142
|
+
extend ArgsPrinter
|
143
|
+
def self.print(directive)
|
144
|
+
"directive @#{directive.name}#{print_args(directive)} "\
|
145
|
+
"on #{directive.locations.join(' | ')}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
108
149
|
class ScalarPrinter
|
109
150
|
def self.print(type)
|
110
151
|
"scalar #{type.name}"
|
@@ -137,8 +178,9 @@ module GraphQL
|
|
137
178
|
end
|
138
179
|
|
139
180
|
class EnumPrinter
|
181
|
+
extend DeprecatedPrinter
|
140
182
|
def self.print(type)
|
141
|
-
values = type.values.values.map{ |v| " #{v.name}" }.join("\n")
|
183
|
+
values = type.values.values.map{ |v| " #{v.name}#{print_deprecated(v)}" }.join("\n")
|
142
184
|
"enum #{type.name} {\n#{values}\n}"
|
143
185
|
end
|
144
186
|
end
|