graphql 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graph_ql/directive.rb +9 -5
- data/lib/graph_ql/directives/include_directive.rb +2 -2
- data/lib/graph_ql/directives/skip_directive.rb +2 -2
- data/lib/graph_ql/enum.rb +5 -8
- data/lib/graph_ql/field.rb +50 -0
- data/lib/graph_ql/interface.rb +4 -0
- data/lib/graph_ql/introspection/arguments_field.rb +2 -2
- data/lib/graph_ql/introspection/directive_type.rb +10 -10
- data/lib/graph_ql/introspection/enum_value_type.rb +11 -8
- data/lib/graph_ql/introspection/enum_values_field.rb +5 -5
- data/lib/graph_ql/introspection/field_type.rb +14 -10
- data/lib/graph_ql/introspection/fields_field.rb +4 -4
- data/lib/graph_ql/introspection/input_fields_field.rb +3 -3
- data/lib/graph_ql/introspection/input_value_type.rb +8 -8
- data/lib/graph_ql/introspection/interfaces_field.rb +5 -0
- data/lib/graph_ql/introspection/of_type_field.rb +3 -9
- data/lib/graph_ql/introspection/possible_types_field.rb +3 -10
- data/lib/graph_ql/introspection/schema_type.rb +8 -14
- data/lib/graph_ql/introspection/type_kind_enum.rb +1 -1
- data/lib/graph_ql/introspection/type_type.rb +17 -19
- data/lib/graph_ql/introspection/typename_field.rb +15 -0
- data/lib/graph_ql/parser.rb +9 -0
- data/lib/graph_ql/parser/nodes.rb +17 -7
- data/lib/graph_ql/parser/parser.rb +7 -7
- data/lib/graph_ql/parser/transform.rb +23 -20
- data/lib/graph_ql/parser/visitor.rb +29 -13
- data/lib/graph_ql/query.rb +39 -16
- data/lib/graph_ql/query/field_resolution_strategy.rb +15 -11
- data/lib/graph_ql/query/type_resolver.rb +4 -2
- data/lib/graph_ql/repl.rb +1 -1
- data/lib/graph_ql/schema.rb +19 -7
- data/lib/graph_ql/schema/each_item_validator.rb +12 -0
- data/lib/graph_ql/schema/field_validator.rb +13 -0
- data/lib/graph_ql/schema/implementation_validator.rb +21 -0
- data/lib/graph_ql/schema/schema_validator.rb +10 -0
- data/lib/graph_ql/schema/type_reducer.rb +6 -6
- data/lib/graph_ql/schema/type_validator.rb +47 -0
- data/lib/graph_ql/static_validation.rb +18 -0
- data/lib/graph_ql/static_validation/argument_literals_are_compatible.rb +13 -0
- data/lib/graph_ql/static_validation/arguments_are_defined.rb +10 -0
- data/lib/graph_ql/static_validation/arguments_validator.rb +16 -0
- data/lib/graph_ql/static_validation/directives_are_defined.rb +18 -0
- data/lib/graph_ql/static_validation/fields_are_defined_on_type.rb +29 -0
- data/lib/graph_ql/static_validation/fields_have_appropriate_selections.rb +31 -0
- data/lib/graph_ql/static_validation/fields_will_merge.rb +93 -0
- data/lib/graph_ql/static_validation/fragment_types_exist.rb +24 -0
- data/lib/graph_ql/static_validation/fragments_are_used.rb +30 -0
- data/lib/graph_ql/static_validation/literal_validator.rb +27 -0
- data/lib/graph_ql/static_validation/message.rb +29 -0
- data/lib/graph_ql/static_validation/required_arguments_are_present.rb +13 -0
- data/lib/graph_ql/static_validation/type_stack.rb +87 -0
- data/lib/graph_ql/static_validation/validator.rb +48 -0
- data/lib/graph_ql/type_kinds.rb +50 -12
- data/lib/graph_ql/types/argument_definer.rb +7 -0
- data/lib/graph_ql/types/boolean_type.rb +3 -3
- data/lib/graph_ql/types/field_definer.rb +19 -0
- data/lib/graph_ql/types/float_type.rb +3 -3
- data/lib/graph_ql/types/input_object_type.rb +4 -0
- data/lib/graph_ql/types/input_value.rb +1 -1
- data/lib/graph_ql/types/int_type.rb +4 -4
- data/lib/graph_ql/types/list_type.rb +5 -1
- data/lib/graph_ql/types/non_null_type.rb +4 -0
- data/lib/graph_ql/types/object_type.rb +9 -20
- data/lib/graph_ql/types/scalar_type.rb +4 -0
- data/lib/graph_ql/types/string_type.rb +3 -3
- data/lib/graph_ql/types/type_definer.rb +5 -9
- data/lib/graph_ql/union.rb +6 -17
- data/lib/graph_ql/version.rb +1 -1
- data/lib/graphql.rb +58 -78
- data/readme.md +80 -7
- data/spec/graph_ql/interface_spec.rb +15 -1
- data/spec/graph_ql/introspection/directive_type_spec.rb +2 -2
- data/spec/graph_ql/introspection/schema_type_spec.rb +2 -1
- data/spec/graph_ql/introspection/type_type_spec.rb +16 -1
- data/spec/graph_ql/parser/parser_spec.rb +3 -1
- data/spec/graph_ql/parser/transform_spec.rb +12 -2
- data/spec/graph_ql/parser/visitor_spec.rb +13 -5
- data/spec/graph_ql/query_spec.rb +25 -13
- data/spec/graph_ql/schema/field_validator_spec.rb +21 -0
- data/spec/graph_ql/schema/type_reducer_spec.rb +2 -2
- data/spec/graph_ql/schema/type_validator_spec.rb +54 -0
- data/spec/graph_ql/static_validation/argument_literals_are_compatible_spec.rb +41 -0
- data/spec/graph_ql/static_validation/arguments_are_defined_spec.rb +40 -0
- data/spec/graph_ql/static_validation/directives_are_defined_spec.rb +33 -0
- data/spec/graph_ql/static_validation/fields_are_defined_on_type_spec.rb +59 -0
- data/spec/graph_ql/static_validation/fields_have_appropriate_selections_spec.rb +30 -0
- data/spec/graph_ql/{validations → static_validation}/fields_will_merge_spec.rb +24 -17
- data/spec/graph_ql/static_validation/fragment_types_exist_spec.rb +38 -0
- data/spec/graph_ql/static_validation/fragments_are_used_spec.rb +24 -0
- data/spec/graph_ql/static_validation/required_arguments_are_present_spec.rb +41 -0
- data/spec/graph_ql/static_validation/type_stack_spec.rb +35 -0
- data/spec/graph_ql/static_validation/validator_spec.rb +28 -0
- data/spec/graph_ql/types/object_type_spec.rb +1 -1
- data/spec/graph_ql/union_spec.rb +1 -14
- data/spec/support/dummy_app.rb +75 -53
- metadata +53 -31
- data/lib/graph_ql/fields/abstract_field.rb +0 -37
- data/lib/graph_ql/fields/access_field.rb +0 -24
- data/lib/graph_ql/fields/field.rb +0 -34
- data/lib/graph_ql/types/abstract_type.rb +0 -14
- data/lib/graph_ql/validations/fields_are_defined_on_type.rb +0 -44
- data/lib/graph_ql/validations/fields_will_merge.rb +0 -80
- data/lib/graph_ql/validations/fragments_are_used.rb +0 -24
- data/lib/graph_ql/validator.rb +0 -29
- data/spec/graph_ql/validations/fields_are_defined_on_type_spec.rb +0 -28
- data/spec/graph_ql/validations/fragments_are_used_spec.rb +0 -28
- data/spec/graph_ql/validator_spec.rb +0 -24
@@ -0,0 +1,30 @@
|
|
1
|
+
class GraphQL::StaticValidation::FragmentsAreUsed
|
2
|
+
include GraphQL::StaticValidation::Message::MessageHelper
|
3
|
+
|
4
|
+
def validate(context)
|
5
|
+
v = context.visitor
|
6
|
+
used_fragments = []
|
7
|
+
defined_fragments = []
|
8
|
+
v[GraphQL::Nodes::FragmentSpread] << -> (node, parent) { used_fragments << node }
|
9
|
+
v[GraphQL::Nodes::FragmentDefinition] << -> (node, parent) { defined_fragments << node}
|
10
|
+
v[GraphQL::Nodes::Document].leave << -> (node, parent) { add_errors(context.errors, used_fragments, defined_fragments) }
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def add_errors(errors, used_fragments, defined_fragments)
|
16
|
+
undefined_fragments = find_difference(used_fragments, defined_fragments.map(&:name))
|
17
|
+
undefined_fragments.each do |fragment|
|
18
|
+
errors << message("Fragment #{fragment.name} was used, but not defined", fragment)
|
19
|
+
end
|
20
|
+
|
21
|
+
unused_fragments = find_difference(defined_fragments, used_fragments.map(&:name))
|
22
|
+
unused_fragments.each do |fragment|
|
23
|
+
errors << message("Fragment #{fragment.name} was defined, but not used", fragment)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def find_difference(fragments, allowed_fragment_names)
|
28
|
+
fragments.select {|f| !allowed_fragment_names.include?(f.name) }
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Test whether `ast_value` is a valid input for `type`
|
2
|
+
class GraphQL::StaticValidation::LiteralValidator
|
3
|
+
include GraphQL::StaticValidation::Message::MessageHelper
|
4
|
+
|
5
|
+
attr_reader :errors
|
6
|
+
def validate(ast_value, type)
|
7
|
+
if type.kind.non_null?
|
8
|
+
(!ast_value.nil?) && validate(ast_value, type.of_type)
|
9
|
+
elsif type.kind.list? && ast_value.is_a?(Array)
|
10
|
+
item_type = type.of_type
|
11
|
+
ast_value.all? { |val| validate(val, item_type) }
|
12
|
+
elsif type.kind.scalar?
|
13
|
+
!type.coerce(ast_value).nil?
|
14
|
+
elsif type.kind.enum? && ast_value.is_a?(GraphQL::Nodes::Enum)
|
15
|
+
!type.coerce(ast_value.name).nil?
|
16
|
+
elsif type.kind.input_object? && ast_value.is_a?(GraphQL::Nodes::InputObject)
|
17
|
+
fields = type.input_fields
|
18
|
+
ast_value.pairs.all? do |value|
|
19
|
+
field_type = fields[value.name].type
|
20
|
+
present_if_required = field_type.kind.non_null? ? !value.nil? : true
|
21
|
+
present_if_required && validate(value.value, field_type)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Generates GraphQL-compliant validation message.
|
2
|
+
# Only supports one "location", too bad :(
|
3
|
+
class GraphQL::StaticValidation::Message
|
4
|
+
# Convenience for validators
|
5
|
+
module MessageHelper
|
6
|
+
# Error `message` is located at `node`
|
7
|
+
def message(message, node)
|
8
|
+
GraphQL::StaticValidation::Message.new(message, line: node.line, col: node.col)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
attr_reader :message, :line, :co
|
12
|
+
def initialize(message, line: nil, col: nil)
|
13
|
+
@message = message
|
14
|
+
@line = line
|
15
|
+
@col = col
|
16
|
+
end
|
17
|
+
def to_h
|
18
|
+
{
|
19
|
+
"message" => message,
|
20
|
+
"locations" => locations
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def locations
|
27
|
+
@line.nil? && @col.nil ? [] : [{"line" => @line, "column" => @col}]
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class GraphQL::StaticValidation::RequiredArgumentsArePresent < GraphQL::StaticValidation::ArgumentsValidator
|
2
|
+
def validate_node(node, defn, context)
|
3
|
+
present_argument_names = node.arguments.map(&:name)
|
4
|
+
required_argument_names = defn.arguments.values
|
5
|
+
.select { |a| a.type.kind.non_null? }
|
6
|
+
.map(&:name)
|
7
|
+
|
8
|
+
missing_names = required_argument_names - present_argument_names
|
9
|
+
if missing_names.any?
|
10
|
+
context.errors << message("#{node.class.name.split("::").last} '#{node.name}' is missing required arguments: #{missing_names.join(", ")}", node)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# - Ride along with `GraphQL::Visitor`
|
2
|
+
# - Track type info, expose it to validators
|
3
|
+
class GraphQL::StaticValidation::TypeStack
|
4
|
+
# These are jumping-off points for infering types down the tree
|
5
|
+
TYPE_INFERRENCE_ROOTS = [
|
6
|
+
GraphQL::Nodes::OperationDefinition,
|
7
|
+
GraphQL::Nodes::FragmentDefinition,
|
8
|
+
]
|
9
|
+
|
10
|
+
attr_reader :schema, :object_types, :field_definitions
|
11
|
+
def initialize(schema, visitor)
|
12
|
+
@schema = schema
|
13
|
+
@object_types = []
|
14
|
+
@field_definitions = []
|
15
|
+
visitor.enter << -> (node, parent) { PUSH_STRATEGIES[node.class].push(self, node) }
|
16
|
+
visitor.leave << -> (node, parent) { PUSH_STRATEGIES[node.class].pop(self, node) }
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Look up strategies by name and use singleton instance to push and pop
|
22
|
+
PUSH_STRATEGIES = Hash.new { |hash, key| hash[key] = get_strategy_for_node_class(key) }
|
23
|
+
|
24
|
+
def self.get_strategy_for_node_class(node_class)
|
25
|
+
node_class_name = node_class.name.split("::").last
|
26
|
+
strategy_key = "#{node_class_name}Strategy"
|
27
|
+
const_defined?(strategy_key) ? const_get(strategy_key).new : NullStrategy.new
|
28
|
+
end
|
29
|
+
|
30
|
+
class FragmentWithTypeStrategy
|
31
|
+
def push(stack, node)
|
32
|
+
object_type = stack.schema.types[node.type]
|
33
|
+
if !object_type.nil?
|
34
|
+
object_type = object_type.kind.unwrap(object_type)
|
35
|
+
end
|
36
|
+
stack.object_types.push(object_type)
|
37
|
+
end
|
38
|
+
|
39
|
+
def pop(stack, node)
|
40
|
+
stack.object_types.pop
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class FragmentDefinitionStrategy < FragmentWithTypeStrategy; end
|
45
|
+
class InlineFragmentStrategy < FragmentWithTypeStrategy; end
|
46
|
+
|
47
|
+
class OperationDefinitionStrategy
|
48
|
+
def push(stack, node)
|
49
|
+
# query or mutation
|
50
|
+
object_type = stack.schema.public_send(node.operation_type)
|
51
|
+
stack.object_types.push(object_type)
|
52
|
+
end
|
53
|
+
def pop(stack, node)
|
54
|
+
stack.object_types.pop
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class FieldStrategy
|
59
|
+
def push(stack, node)
|
60
|
+
parent_type = stack.object_types.last
|
61
|
+
parent_type = parent_type.kind.unwrap(parent_type)
|
62
|
+
if parent_type.kind.fields?
|
63
|
+
field_class = parent_type.fields[node.name]
|
64
|
+
stack.field_definitions.push(field_class)
|
65
|
+
if !field_class.nil?
|
66
|
+
next_object_type = field_class.type
|
67
|
+
stack.object_types.push(next_object_type)
|
68
|
+
else
|
69
|
+
stack.object_types.push(nil)
|
70
|
+
end
|
71
|
+
else
|
72
|
+
stack.field_definitions.push(nil)
|
73
|
+
stack.object_types.push(parent_type)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def pop(stack, node)
|
78
|
+
stack.field_definitions.pop
|
79
|
+
stack.object_types.pop
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class NullStrategy
|
84
|
+
def push(stack, node); end
|
85
|
+
def pop(stack, node); end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class GraphQL::StaticValidation::Validator
|
2
|
+
VALIDATORS = [
|
3
|
+
GraphQL::StaticValidation::DirectivesAreDefined,
|
4
|
+
GraphQL::StaticValidation::ArgumentsAreDefined,
|
5
|
+
GraphQL::StaticValidation::RequiredArgumentsArePresent,
|
6
|
+
GraphQL::StaticValidation::ArgumentLiteralsAreCompatible,
|
7
|
+
GraphQL::StaticValidation::FragmentTypesExist,
|
8
|
+
GraphQL::StaticValidation::FragmentsAreUsed,
|
9
|
+
GraphQL::StaticValidation::FieldsAreDefinedOnType,
|
10
|
+
GraphQL::StaticValidation::FieldsWillMerge,
|
11
|
+
GraphQL::StaticValidation::FieldsHaveAppropriateSelections,
|
12
|
+
]
|
13
|
+
|
14
|
+
def initialize(schema:, validators: VALIDATORS)
|
15
|
+
@schema = schema
|
16
|
+
@validators = validators
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate(document)
|
20
|
+
context = Context.new(@schema, document)
|
21
|
+
@validators.each do |validator|
|
22
|
+
validator.new.validate(context)
|
23
|
+
end
|
24
|
+
context.visitor.visit(document)
|
25
|
+
context.errors.map(&:to_h)
|
26
|
+
end
|
27
|
+
|
28
|
+
class Context
|
29
|
+
attr_reader :schema, :document, :errors, :visitor, :fragments
|
30
|
+
def initialize(schema, document)
|
31
|
+
@schema = schema
|
32
|
+
@document = document
|
33
|
+
@fragments = {}
|
34
|
+
@errors = []
|
35
|
+
@visitor = GraphQL::Visitor.new
|
36
|
+
@visitor[GraphQL::Nodes::FragmentDefinition] << -> (node, parent) { @fragments[node.name] = node }
|
37
|
+
@type_stack = GraphQL::StaticValidation::TypeStack.new(schema, visitor)
|
38
|
+
end
|
39
|
+
|
40
|
+
def object_types
|
41
|
+
@type_stack.object_types
|
42
|
+
end
|
43
|
+
|
44
|
+
def field_definition
|
45
|
+
@type_stack.field_definitions.last
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/graph_ql/type_kinds.rb
CHANGED
@@ -1,15 +1,53 @@
|
|
1
1
|
module GraphQL::TypeKinds
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
2
|
+
class TypeKind
|
3
|
+
attr_reader :name
|
4
|
+
def initialize(name, resolves: false, fields: false, wraps: false)
|
5
|
+
@name = name
|
6
|
+
@resolves = resolves
|
7
|
+
@fields = fields
|
8
|
+
@wraps = wraps
|
9
|
+
end
|
10
|
+
|
11
|
+
def resolves?; @resolves; end
|
12
|
+
def fields?; @fields; end
|
13
|
+
def wraps?; @wraps; end
|
14
|
+
def to_s; @name; end
|
15
|
+
|
16
|
+
def resolve(type, value)
|
17
|
+
if resolves?
|
18
|
+
type.resolve_type(value)
|
19
|
+
else
|
20
|
+
type
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def unwrap(type)
|
25
|
+
if wraps?
|
26
|
+
wrapped_type = type.of_type
|
27
|
+
wrapped_type.kind.unwrap(wrapped_type)
|
28
|
+
else
|
29
|
+
type
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
TYPE_KINDS = [
|
35
|
+
SCALAR = TypeKind.new("SCALAR"),
|
36
|
+
OBJECT = TypeKind.new("OBJECT", fields: true),
|
37
|
+
INTERFACE = TypeKind.new("INTERFACE", resolves: true, fields: true),
|
38
|
+
UNION = TypeKind.new("UNION", resolves: true),
|
39
|
+
ENUM = TypeKind.new("ENUM"),
|
40
|
+
INPUT_OBJECT = TypeKind.new("INPUT_OBJECT"),
|
41
|
+
LIST = TypeKind.new("LIST", wraps: true),
|
42
|
+
NON_NULL = TypeKind.new("NON_NULL", wraps: true),
|
43
|
+
]
|
44
|
+
|
45
|
+
KIND_NAMES = TYPE_KINDS.map(&:name)
|
46
|
+
class TypeKind
|
47
|
+
KIND_NAMES.each do |kind_name|
|
48
|
+
define_method("#{kind_name.downcase}?") do
|
49
|
+
self.name == kind_name
|
50
|
+
end
|
51
|
+
end
|
14
52
|
end
|
15
53
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class GraphQL::FieldDefiner
|
2
|
+
include Singleton
|
3
|
+
|
4
|
+
def build(type:, args: {}, property: nil, desc: "", deprecation_reason: nil)
|
5
|
+
resolve = if property.nil?
|
6
|
+
-> (o, a, c) { GraphQL::Query::DEFAULT_RESOLVE }
|
7
|
+
else
|
8
|
+
-> (object, a, c) { object.send(property) }
|
9
|
+
end
|
10
|
+
|
11
|
+
GraphQL::Field.new do |f|
|
12
|
+
f.type(type)
|
13
|
+
f.arguments(args)
|
14
|
+
f.description(desc)
|
15
|
+
f.resolve(resolve)
|
16
|
+
f.deprecation_reason(deprecation_reason)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class GraphQL::InputValue
|
2
2
|
attr_reader :type, :description, :default_value
|
3
3
|
attr_accessor :name
|
4
|
-
def initialize(type:, description
|
4
|
+
def initialize(type:, description: nil, default_value: nil, name: nil)
|
5
5
|
@type = type
|
6
6
|
@description = description,
|
7
7
|
@default_value = default_value
|
@@ -1,10 +1,14 @@
|
|
1
1
|
class GraphQL::ListType < GraphQL::ObjectType
|
2
2
|
attr_reader :of_type
|
3
3
|
def initialize(of_type:)
|
4
|
+
@name = "List"
|
4
5
|
@of_type = of_type
|
5
6
|
end
|
6
|
-
|
7
7
|
def kind
|
8
8
|
GraphQL::TypeKinds::LIST
|
9
9
|
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"<GraphQL::ListType(#{of_type.name})>"
|
13
|
+
end
|
10
14
|
end
|
@@ -6,7 +6,7 @@ class GraphQL::ObjectType
|
|
6
6
|
def initialize(&block)
|
7
7
|
self.fields = []
|
8
8
|
self.interfaces = []
|
9
|
-
|
9
|
+
yield(self, GraphQL::TypeDefiner.instance, GraphQL::FieldDefiner.instance, GraphQL::ArgumentDefiner.instance)
|
10
10
|
end
|
11
11
|
|
12
12
|
def fields(new_fields=nil)
|
@@ -22,31 +22,16 @@ class GraphQL::ObjectType
|
|
22
22
|
.reduce({}) { |memo, (key, value)| memo[key.to_s] = value; memo }
|
23
23
|
# Set the name from its context on this type:
|
24
24
|
stringified_fields.each {|k, v| v.respond_to?("name=") && v.name = k }
|
25
|
-
stringified_fields["__typename"] = GraphQL::
|
26
|
-
f.name "__typename"
|
27
|
-
f.description "The name of this type"
|
28
|
-
f.type -> { !GraphQL::STRING_TYPE }
|
29
|
-
f.resolve -> (o, a, c) { self.name }
|
30
|
-
end
|
25
|
+
stringified_fields["__typename"] = GraphQL::Introspection::TypenameField.create(self)
|
31
26
|
@fields = stringified_fields
|
32
27
|
end
|
33
28
|
|
34
|
-
def field(type:, args: {}, property: nil, desc: "", deprecation_reason: nil)
|
35
|
-
GraphQL::AccessField.new(type: type, arguments: args, property: property, description: desc, deprecation_reason: deprecation_reason)
|
36
|
-
end
|
37
|
-
|
38
|
-
def arg(type:, desc: "", default_value: nil)
|
39
|
-
GraphQL::InputValue.new(type: type, description: desc, default_value: default_value)
|
40
|
-
end
|
41
|
-
|
42
|
-
def type
|
43
|
-
@type ||= GraphQL::TypeDefiner.new
|
44
|
-
end
|
45
|
-
|
46
29
|
def interfaces(new_interfaces=nil)
|
47
30
|
if new_interfaces.nil?
|
48
31
|
@interfaces
|
49
32
|
else
|
33
|
+
# if you define interfaces twice, you're gonna have a bad time :(
|
34
|
+
# (because it gets registered with that interface, then overriden)
|
50
35
|
@interfaces = new_interfaces
|
51
36
|
new_interfaces.each {|i| i.possible_types << self }
|
52
37
|
end
|
@@ -57,6 +42,10 @@ class GraphQL::ObjectType
|
|
57
42
|
end
|
58
43
|
|
59
44
|
def to_s
|
60
|
-
name
|
45
|
+
"<GraphQL::ObjectType #{name}>"
|
46
|
+
end
|
47
|
+
|
48
|
+
def inspect
|
49
|
+
to_s
|
61
50
|
end
|
62
51
|
end
|