graphql 1.7.14 → 1.8.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/generators/graphql/function_generator.rb +1 -1
- data/lib/generators/graphql/loader_generator.rb +1 -1
- data/lib/generators/graphql/mutation_generator.rb +1 -6
- data/lib/generators/graphql/templates/function.erb +2 -2
- data/lib/generators/graphql/templates/loader.erb +2 -2
- data/lib/graphql.rb +2 -0
- data/lib/graphql/argument.rb +0 -1
- data/lib/graphql/backwards_compatibility.rb +2 -3
- data/lib/graphql/base_type.rb +18 -16
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -117
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -14
- data/lib/graphql/define/assign_object_field.rb +5 -12
- data/lib/graphql/deprecated_dsl.rb +28 -0
- data/lib/graphql/directive.rb +0 -1
- data/lib/graphql/enum_type.rb +1 -3
- data/lib/graphql/execution.rb +0 -1
- data/lib/graphql/execution/multiplex.rb +29 -12
- data/lib/graphql/field.rb +5 -20
- data/lib/graphql/function.rb +12 -0
- data/lib/graphql/input_object_type.rb +1 -3
- data/lib/graphql/internal_representation/node.rb +14 -26
- data/lib/graphql/internal_representation/visit.rb +6 -3
- data/lib/graphql/introspection/arguments_field.rb +0 -1
- data/lib/graphql/introspection/enum_values_field.rb +0 -1
- data/lib/graphql/introspection/fields_field.rb +0 -1
- data/lib/graphql/introspection/input_fields_field.rb +0 -1
- 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_field.rb +0 -1
- data/lib/graphql/introspection/type_by_name_field.rb +0 -1
- data/lib/graphql/introspection/typename_field.rb +0 -1
- data/lib/graphql/language.rb +0 -3
- data/lib/graphql/language/generation.rb +182 -3
- data/lib/graphql/language/lexer.rb +69 -144
- data/lib/graphql/language/lexer.rl +4 -15
- data/lib/graphql/language/nodes.rb +76 -136
- data/lib/graphql/language/parser.rb +621 -668
- data/lib/graphql/language/parser.y +11 -17
- data/lib/graphql/language/token.rb +3 -10
- data/lib/graphql/object_type.rb +6 -1
- data/lib/graphql/query.rb +13 -8
- data/lib/graphql/query/arguments.rb +33 -48
- data/lib/graphql/query/context.rb +1 -0
- data/lib/graphql/query/literal_input.rb +1 -4
- data/lib/graphql/relay/connection_resolve.rb +3 -0
- data/lib/graphql/relay/global_id_resolve.rb +5 -1
- data/lib/graphql/relay/relation_connection.rb +19 -14
- data/lib/graphql/schema.rb +219 -12
- data/lib/graphql/schema/argument.rb +33 -0
- data/lib/graphql/schema/build_from_definition.rb +18 -64
- data/lib/graphql/schema/enum.rb +76 -0
- data/lib/graphql/schema/field.rb +127 -0
- data/lib/graphql/schema/field/dynamic_resolve.rb +63 -0
- data/lib/graphql/schema/field/unwrapped_resolve.rb +20 -0
- data/lib/graphql/schema/input_object.rb +61 -0
- data/lib/graphql/schema/interface.rb +32 -0
- data/lib/graphql/schema/loader.rb +2 -2
- data/lib/graphql/schema/member.rb +97 -0
- data/lib/graphql/schema/member/build_type.rb +106 -0
- data/lib/graphql/schema/member/has_fields.rb +56 -0
- data/lib/graphql/schema/member/instrumentation.rb +113 -0
- data/lib/graphql/schema/member/list_type_proxy.rb +21 -0
- data/lib/graphql/schema/member/non_null_type_proxy.rb +21 -0
- data/lib/graphql/schema/object.rb +65 -0
- data/lib/graphql/schema/printer.rb +266 -33
- data/lib/graphql/schema/scalar.rb +25 -0
- data/lib/graphql/schema/traversal.rb +26 -17
- data/lib/graphql/schema/union.rb +48 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +8 -15
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -11
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +5 -7
- data/lib/graphql/tracing.rb +0 -1
- data/lib/graphql/tracing/platform_tracing.rb +7 -20
- data/lib/graphql/tracing/scout_tracing.rb +2 -2
- data/lib/graphql/unresolved_type_error.rb +2 -3
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/dummy/app/channels/graphql_channel.rb +1 -22
- data/spec/dummy/log/development.log +0 -239
- data/spec/dummy/log/test.log +0 -204
- data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -4
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/generators/graphql/function_generator_spec.rb +0 -26
- data/spec/generators/graphql/loader_generator_spec.rb +0 -24
- data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
- data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
- data/spec/graphql/backtrace_spec.rb +0 -10
- data/spec/graphql/base_type_spec.rb +5 -19
- data/spec/graphql/boolean_type_spec.rb +3 -3
- data/spec/graphql/directive_spec.rb +1 -3
- data/spec/graphql/enum_type_spec.rb +5 -18
- data/spec/graphql/execution/execute_spec.rb +1 -1
- data/spec/graphql/execution/multiplex_spec.rb +2 -2
- data/spec/graphql/float_type_spec.rb +2 -2
- data/spec/graphql/id_type_spec.rb +1 -1
- data/spec/graphql/input_object_type_spec.rb +2 -15
- data/spec/graphql/int_type_spec.rb +2 -2
- data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
- data/spec/graphql/introspection/schema_type_spec.rb +0 -1
- data/spec/graphql/language/generation_spec.rb +186 -21
- data/spec/graphql/language/lexer_spec.rb +1 -21
- data/spec/graphql/language/nodes_spec.rb +12 -21
- data/spec/graphql/language/parser_spec.rb +1 -1
- data/spec/graphql/query/arguments_spec.rb +15 -37
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -2
- data/spec/graphql/query/variables_spec.rb +1 -1
- data/spec/graphql/query_spec.rb +5 -31
- data/spec/graphql/rake_task_spec.rb +1 -3
- data/spec/graphql/relay/base_connection_spec.rb +1 -1
- data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
- data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
- data/spec/graphql/relay/connection_type_spec.rb +1 -1
- data/spec/graphql/relay/mutation_spec.rb +3 -3
- data/spec/graphql/relay/relation_connection_spec.rb +1 -65
- data/spec/graphql/schema/build_from_definition_spec.rb +4 -86
- data/spec/graphql/schema/enum_spec.rb +60 -0
- data/spec/graphql/schema/field_spec.rb +14 -0
- data/spec/graphql/schema/input_object_spec.rb +43 -0
- data/spec/graphql/schema/interface_spec.rb +98 -0
- data/spec/graphql/schema/object_spec.rb +119 -0
- data/spec/graphql/schema/printer_spec.rb +15 -92
- data/spec/graphql/schema/scalar_spec.rb +40 -0
- data/spec/graphql/schema/union_spec.rb +35 -0
- data/spec/graphql/schema/validation_spec.rb +1 -1
- data/spec/graphql/schema/warden_spec.rb +11 -11
- data/spec/graphql/schema_spec.rb +25 -23
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +2 -10
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
- data/spec/graphql/string_type_spec.rb +3 -3
- data/spec/graphql/subscriptions_spec.rb +1 -1
- data/spec/graphql/tracing/platform_tracing_spec.rb +1 -60
- data/spec/support/dummy/schema.rb +25 -39
- data/spec/support/jazz.rb +334 -0
- data/spec/support/lazy_helpers.rb +21 -23
- data/spec/support/star_wars/data.rb +7 -6
- data/spec/support/star_wars/schema.rb +109 -142
- metadata +39 -33
- data/lib/graphql/execution/instrumentation.rb +0 -82
- data/lib/graphql/language/block_string.rb +0 -47
- data/lib/graphql/language/document_from_schema_definition.rb +0 -277
- data/lib/graphql/language/printer.rb +0 -351
- data/lib/graphql/tracing/data_dog_tracing.rb +0 -49
- data/spec/graphql/execution/instrumentation_spec.rb +0 -165
- data/spec/graphql/language/block_string_spec.rb +0 -70
- data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
- data/spec/graphql/language/printer_spec.rb +0 -203
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
# Extend this class to define GraphQL enums in your schema.
|
5
|
+
#
|
6
|
+
# By default, GraphQL enum values are translated into Ruby strings.
|
7
|
+
# You can provide a custom value with the `value:` keyword.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # equivalent to
|
11
|
+
# # enum PizzaTopping {
|
12
|
+
# # MUSHROOMS
|
13
|
+
# # ONIONS
|
14
|
+
# # PEPPERS
|
15
|
+
# # }
|
16
|
+
# class PizzaTopping < GraphQL::Enum
|
17
|
+
# value :MUSHROOMS
|
18
|
+
# value :ONIONS
|
19
|
+
# value :PEPPERS
|
20
|
+
# end
|
21
|
+
class Schema
|
22
|
+
class Enum < GraphQL::Schema::Member
|
23
|
+
# @api private
|
24
|
+
Value = Struct.new(:name, :description, :value, :deprecation_reason)
|
25
|
+
|
26
|
+
class << self
|
27
|
+
# Define a value for this enum
|
28
|
+
# @param graphql_name [String, Symbol] the GraphQL value for this, usually `SCREAMING_CASE`
|
29
|
+
# @param description [String], the GraphQL description for this value, present in documentation
|
30
|
+
# @param value [Object], the translated Ruby value for this object (defaults to `graphql_name`)
|
31
|
+
# @param deprecation_reason [String] if this object is deprecated, include a message here
|
32
|
+
# @return [void]
|
33
|
+
def value(graphql_name, description = nil, value: nil, deprecation_reason: nil)
|
34
|
+
graphql_name = graphql_name.to_s
|
35
|
+
value ||= graphql_name
|
36
|
+
own_values << Value.new(graphql_name, description, value, deprecation_reason)
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Array<GraphQL::Schema::Enum::Value>]
|
41
|
+
def values
|
42
|
+
all_values = own_values
|
43
|
+
inherited_values = superclass <= GraphQL::Schema::Enum ? superclass.values : []
|
44
|
+
inherited_values.each do |inherited_v|
|
45
|
+
if all_values.none? { |v| v.name == inherited_v.name }
|
46
|
+
all_values << inherited_v
|
47
|
+
end
|
48
|
+
end
|
49
|
+
all_values
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [GraphQL::EnumType]
|
53
|
+
def to_graphql
|
54
|
+
enum_type = GraphQL::EnumType.new
|
55
|
+
enum_type.name = graphql_name
|
56
|
+
enum_type.description = description
|
57
|
+
values.each do |val|
|
58
|
+
enum_value = GraphQL::EnumType::EnumValue.new
|
59
|
+
enum_value.name = val.name
|
60
|
+
enum_value.description = val.description
|
61
|
+
enum_value.value = val.value
|
62
|
+
enum_value.deprecation_reason = val.deprecation_reason
|
63
|
+
enum_type.add_value(enum_value)
|
64
|
+
end
|
65
|
+
enum_type
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def own_values
|
71
|
+
@own_values ||= []
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# test_via: ../object.rb
|
3
|
+
require "graphql/schema/field/dynamic_resolve"
|
4
|
+
require "graphql/schema/field/unwrapped_resolve"
|
5
|
+
module GraphQL
|
6
|
+
class Schema
|
7
|
+
class Field
|
8
|
+
include GraphQL::Schema::Member::CachedGraphQLDefinition
|
9
|
+
|
10
|
+
# @return [String]
|
11
|
+
attr_reader :name
|
12
|
+
|
13
|
+
# @return [String]
|
14
|
+
attr_reader :description
|
15
|
+
|
16
|
+
def initialize(name, return_type_expr = nil, desc = nil, null: nil, field: nil, function: nil, deprecation_reason: nil, method: nil, connection: nil, max_page_size: nil, resolve: nil, &args_block)
|
17
|
+
if !(field || function)
|
18
|
+
if return_type_expr.nil?
|
19
|
+
raise ArgumentError "missing possitional argument `type`"
|
20
|
+
end
|
21
|
+
if null.nil?
|
22
|
+
raise ArgumentError, "missing keyword argument null:"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
@name = name.to_s
|
26
|
+
@description = desc
|
27
|
+
@field = field
|
28
|
+
@function = function
|
29
|
+
@resolve = resolve
|
30
|
+
@deprecation_reason = deprecation_reason
|
31
|
+
@method = method
|
32
|
+
@return_type_expr = return_type_expr
|
33
|
+
@return_type_null = null
|
34
|
+
@args_block = args_block
|
35
|
+
@connection = connection
|
36
|
+
@max_page_size = max_page_size
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [GraphQL::Field]
|
40
|
+
def to_graphql
|
41
|
+
method_name = @method || Member::BuildType.underscore(@name)
|
42
|
+
|
43
|
+
field_defn = if @field
|
44
|
+
@field.dup
|
45
|
+
elsif @function
|
46
|
+
GraphQL::Function.build_field(@function)
|
47
|
+
else
|
48
|
+
GraphQL::Field.new
|
49
|
+
end
|
50
|
+
field_defn.name = @name
|
51
|
+
|
52
|
+
if @return_type_expr
|
53
|
+
return_type_name = Member::BuildType.to_type_name(@return_type_expr)
|
54
|
+
connection = @connection.nil? ? return_type_name.end_with?("Connection") : @connection
|
55
|
+
field_defn.type = -> {
|
56
|
+
Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
|
57
|
+
}
|
58
|
+
elsif @connection.nil? && (@field || @function)
|
59
|
+
return_type_name = Member::BuildType.to_type_name(field_defn.type)
|
60
|
+
connection = return_type_name.end_with?("Connection")
|
61
|
+
else
|
62
|
+
connection = @connection
|
63
|
+
end
|
64
|
+
|
65
|
+
if @description
|
66
|
+
field_defn.description = @description
|
67
|
+
end
|
68
|
+
|
69
|
+
if @deprecation_reason
|
70
|
+
field_defn.deprecation_reason = @deprecation_reason
|
71
|
+
end
|
72
|
+
|
73
|
+
field_defn.resolve = if @resolve || @function || @field
|
74
|
+
prev_resolve = @resolve || field_defn.resolve_proc
|
75
|
+
UnwrappedResolve.new(inner_resolve: prev_resolve)
|
76
|
+
else
|
77
|
+
DynamicResolve.new(method_name: method_name, connection: connection)
|
78
|
+
end
|
79
|
+
|
80
|
+
field_defn.connection = connection
|
81
|
+
field_defn.connection_max_page_size = @max_page_size
|
82
|
+
|
83
|
+
field_proxy = FieldProxy.new(field_defn, argument_class: self.class.argument_class)
|
84
|
+
# apply this first, so it can be overriden below
|
85
|
+
if connection
|
86
|
+
field_proxy.argument :after, "String", "Returns the elements in the list that come after the specified global ID.", required: false
|
87
|
+
field_proxy.argument :before, "String", "Returns the elements in the list that come before the specified global ID.", required: false
|
88
|
+
field_proxy.argument :first, "Int", "Returns the first _n_ elements from the list.", required: false
|
89
|
+
field_proxy.argument :last, "Int", "Returns the last _n_ elements from the list.", required: false
|
90
|
+
end
|
91
|
+
|
92
|
+
if @args_block
|
93
|
+
field_proxy.instance_eval(&@args_block)
|
94
|
+
end
|
95
|
+
|
96
|
+
field_defn
|
97
|
+
end
|
98
|
+
|
99
|
+
class << self
|
100
|
+
def argument_class(new_arg_class = nil)
|
101
|
+
if new_arg_class
|
102
|
+
@argument_class = new_arg_class
|
103
|
+
else
|
104
|
+
@argument_class || GraphQL::Schema::Argument
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# This object exists only to be `instance_eval`'d
|
111
|
+
# when the `field(...)` method is called with a block.
|
112
|
+
# This object receives that block.
|
113
|
+
class FieldProxy
|
114
|
+
def initialize(field, argument_class:)
|
115
|
+
@field = field
|
116
|
+
@argument_class = argument_class
|
117
|
+
end
|
118
|
+
|
119
|
+
# This is the `argument(...)` DSL for class-based field definitons
|
120
|
+
def argument(*args)
|
121
|
+
arg = @argument_class.new(*args)
|
122
|
+
@field.arguments[arg.name] = arg.graphql_definition
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Field
|
6
|
+
class DynamicResolve
|
7
|
+
def initialize(method_name:, connection:)
|
8
|
+
@method_name = method_name
|
9
|
+
@connection = connection
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(obj, args, ctx)
|
13
|
+
if obj.respond_to?(@method_name)
|
14
|
+
public_send_field(obj, @method_name, args)
|
15
|
+
elsif obj.object.respond_to?(@method_name)
|
16
|
+
public_send_field(obj.object, @method_name, args)
|
17
|
+
elsif obj.is_a?(Hash)
|
18
|
+
obj[@method_name]
|
19
|
+
else
|
20
|
+
raise <<-ERR
|
21
|
+
Failed to implement #{ctx.irep_node.owner_type.name}.#{ctx.field.name}, tried:
|
22
|
+
|
23
|
+
- `#{obj.class}##{@method_name}`, which did not exist
|
24
|
+
- `#{obj.object.class}##{@method_name}`, which did not exist
|
25
|
+
- Looking up hash key `#{@method_name.inspect}` on `#{obj}`, but it wasn't a Hash
|
26
|
+
|
27
|
+
To implement this field, define one of the methods above (and check for typos)
|
28
|
+
ERR
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def public_send_field(obj, method_name, graphql_args)
|
35
|
+
if graphql_args.any?
|
36
|
+
# Splat the GraphQL::Arguments to Ruby keyword arguments
|
37
|
+
ruby_kwargs = {}
|
38
|
+
|
39
|
+
graphql_args.keys.each do |key|
|
40
|
+
ruby_kwargs[Schema::Member::BuildType.underscore(key).to_sym] = graphql_args[key]
|
41
|
+
end
|
42
|
+
|
43
|
+
if @connection
|
44
|
+
# Remove pagination args before passing it to a user method
|
45
|
+
ruby_kwargs.delete(:first)
|
46
|
+
ruby_kwargs.delete(:last)
|
47
|
+
ruby_kwargs.delete(:before)
|
48
|
+
ruby_kwargs.delete(:after)
|
49
|
+
end
|
50
|
+
|
51
|
+
if ruby_kwargs.any?
|
52
|
+
obj.public_send(method_name, ruby_kwargs)
|
53
|
+
else
|
54
|
+
obj.public_send(method_name)
|
55
|
+
end
|
56
|
+
else
|
57
|
+
obj.public_send(method_name)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class Field
|
5
|
+
# This object is backed by an `Object`, but the resolve isn't expecting
|
6
|
+
# that wrapper, so unwrap it before calling the inner resolver
|
7
|
+
class UnwrappedResolve
|
8
|
+
def initialize(inner_resolve:)
|
9
|
+
@inner_resolve = inner_resolve
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(obj, args, ctx)
|
13
|
+
# Might be nil, still want to call the func in that case
|
14
|
+
inner_obj = obj && obj.object
|
15
|
+
@inner_resolve.call(inner_obj, args, ctx)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class InputObject < GraphQL::Schema::Member
|
5
|
+
extend GraphQL::Delegate
|
6
|
+
|
7
|
+
def initialize(values, context:)
|
8
|
+
@arguments = self.class.arguments_class.new(values, context: context)
|
9
|
+
@context = context
|
10
|
+
end
|
11
|
+
|
12
|
+
# A lot of methods work just like GraphQL::Arguments
|
13
|
+
def_delegators :@arguments, :[], :key?, :to_h
|
14
|
+
def_delegators :to_h, :keys, :values, :each, :any?
|
15
|
+
|
16
|
+
class << self
|
17
|
+
# @return [Class<GraphQL::Arguments>]
|
18
|
+
attr_accessor :arguments_class
|
19
|
+
|
20
|
+
def argument(*args)
|
21
|
+
argument = GraphQL::Schema::Argument.new(*args)
|
22
|
+
own_arguments << argument
|
23
|
+
arg_name = argument.name
|
24
|
+
# Add a method access
|
25
|
+
define_method(Member::BuildType.underscore(arg_name)) do
|
26
|
+
@arguments.public_send(arg_name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def arguments
|
31
|
+
all_arguments = own_arguments
|
32
|
+
inherited_arguments = (superclass <= GraphQL::Schema::InputObject ? superclass.arguments : [])
|
33
|
+
inherited_arguments.each do |inherited_a|
|
34
|
+
if all_arguments.none? { |a| a.name == inherited_a.name }
|
35
|
+
all_arguments << inherited_a
|
36
|
+
end
|
37
|
+
end
|
38
|
+
all_arguments
|
39
|
+
end
|
40
|
+
|
41
|
+
def own_arguments
|
42
|
+
@own_arguments ||= []
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_graphql
|
46
|
+
type_defn = GraphQL::InputObjectType.new
|
47
|
+
type_defn.name = graphql_name
|
48
|
+
type_defn.description = description
|
49
|
+
arguments.each do |arg|
|
50
|
+
type_defn.arguments[arg.name] = arg.graphql_definition
|
51
|
+
end
|
52
|
+
# Make a reference to a classic-style Arguments class
|
53
|
+
self.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(type_defn)
|
54
|
+
# But use this InputObject class at runtime
|
55
|
+
type_defn.arguments_class = self
|
56
|
+
type_defn
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class Interface < GraphQL::Schema::Member
|
5
|
+
extend GraphQL::Schema::Member::HasFields
|
6
|
+
field_class GraphQL::Schema::Field
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# When this interface is added to a `GraphQL::Schema::Object`,
|
11
|
+
# it calls this method. We add methods to the object by convention,
|
12
|
+
# a nested module named `Implementation`
|
13
|
+
def apply_implemented(object_class)
|
14
|
+
if defined?(self::Implementation)
|
15
|
+
object_class.include(self::Implementation)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_graphql
|
20
|
+
type_defn = GraphQL::InterfaceType.new
|
21
|
+
type_defn.name = graphql_name
|
22
|
+
type_defn.description = description
|
23
|
+
fields.each do |field_inst|
|
24
|
+
field_defn = field_inst.graphql_definition
|
25
|
+
type_defn.fields[field_defn.name] = field_defn
|
26
|
+
end
|
27
|
+
type_defn
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -97,7 +97,7 @@ module GraphQL
|
|
97
97
|
}]
|
98
98
|
)
|
99
99
|
when "FIELD"
|
100
|
-
Field.define(
|
100
|
+
GraphQL::Field.define(
|
101
101
|
name: type["name"],
|
102
102
|
type: type_resolver.call(type["type"]),
|
103
103
|
description: type["description"],
|
@@ -138,7 +138,7 @@ module GraphQL
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
|
-
Argument.define(
|
141
|
+
GraphQL::Argument.define(
|
142
142
|
name: type["name"],
|
143
143
|
type: type_resolver.call(type["type"]),
|
144
144
|
description: type["description"],
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
# The base class for things that make up the schema,
|
4
|
+
# eg objects, enums, scalars.
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
class Schema
|
8
|
+
class Member
|
9
|
+
# Adds a layer of caching over user-supplied `.to_graphql` methods.
|
10
|
+
# Users override `.to_graphql`, but all runtime code should use `.graphql_definition`.
|
11
|
+
module CachedGraphQLDefinition
|
12
|
+
# A cached result of {.to_graphql}.
|
13
|
+
# It's cached here so that user-overridden {.to_graphql} implementations
|
14
|
+
# are also cached
|
15
|
+
def graphql_definition
|
16
|
+
@graphql_definition ||= to_graphql
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# These constants are interpreted as GraphQL types
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# field :isDraft, Boolean, null: false
|
24
|
+
# field :id, ID, null: false
|
25
|
+
module GraphQLTypeNames
|
26
|
+
Boolean = "Boolean"
|
27
|
+
ID = "ID"
|
28
|
+
end
|
29
|
+
|
30
|
+
include GraphQLTypeNames
|
31
|
+
class << self
|
32
|
+
include CachedGraphQLDefinition
|
33
|
+
|
34
|
+
# Delegate to the derived type definition if possible.
|
35
|
+
# This is tricky because missing methods cause the definition to be built & cached.
|
36
|
+
def method_missing(method_name, *args, &block)
|
37
|
+
if graphql_definition.respond_to?(method_name)
|
38
|
+
graphql_definition.public_send(method_name, *args, &block)
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Check if the derived type definition responds to the method
|
45
|
+
# @return [Boolean]
|
46
|
+
def respond_to_missing?(method_name, incl_private = false)
|
47
|
+
graphql_definition.respond_to?(method_name, incl_private) || super
|
48
|
+
end
|
49
|
+
|
50
|
+
# Call this with a new name to override the default name for this schema member; OR
|
51
|
+
# call it without an argument to get the name of this schema member
|
52
|
+
#
|
53
|
+
# The default name is the Ruby constant name,
|
54
|
+
# without any namespaces and with any `-Type` suffix removed
|
55
|
+
# @param new_name [String]
|
56
|
+
# @return [String]
|
57
|
+
def graphql_name(new_name = nil)
|
58
|
+
if new_name
|
59
|
+
@graphql_name = new_name
|
60
|
+
else
|
61
|
+
@graphql_name || self.name.split("::").last.sub(/Type\Z/, "")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Call this method to provide a new description; OR
|
66
|
+
# call it without an argument to get the description
|
67
|
+
# @param new_description [String]
|
68
|
+
# @return [String]
|
69
|
+
def description(new_description = nil)
|
70
|
+
if new_description
|
71
|
+
@description = new_description
|
72
|
+
else
|
73
|
+
@description || (superclass <= GraphQL::Schema::Member ? superclass.description : nil)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_graphql
|
78
|
+
raise NotImplementedError
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_list_type
|
82
|
+
ListTypeProxy.new(self)
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_non_null_type
|
86
|
+
NonNullTypeProxy.new(self)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
require 'graphql/schema/member/list_type_proxy'
|
94
|
+
require 'graphql/schema/member/non_null_type_proxy'
|
95
|
+
require 'graphql/schema/member/has_fields'
|
96
|
+
require 'graphql/schema/member/instrumentation'
|
97
|
+
require 'graphql/schema/member/build_type'
|