graphql 1.7.14 → 1.8.0.pre1
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 +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'
|