graphql 0.1.0 → 0.2.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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graph_ql/directive.rb +9 -5
  3. data/lib/graph_ql/directives/include_directive.rb +2 -2
  4. data/lib/graph_ql/directives/skip_directive.rb +2 -2
  5. data/lib/graph_ql/enum.rb +5 -8
  6. data/lib/graph_ql/field.rb +50 -0
  7. data/lib/graph_ql/interface.rb +4 -0
  8. data/lib/graph_ql/introspection/arguments_field.rb +2 -2
  9. data/lib/graph_ql/introspection/directive_type.rb +10 -10
  10. data/lib/graph_ql/introspection/enum_value_type.rb +11 -8
  11. data/lib/graph_ql/introspection/enum_values_field.rb +5 -5
  12. data/lib/graph_ql/introspection/field_type.rb +14 -10
  13. data/lib/graph_ql/introspection/fields_field.rb +4 -4
  14. data/lib/graph_ql/introspection/input_fields_field.rb +3 -3
  15. data/lib/graph_ql/introspection/input_value_type.rb +8 -8
  16. data/lib/graph_ql/introspection/interfaces_field.rb +5 -0
  17. data/lib/graph_ql/introspection/of_type_field.rb +3 -9
  18. data/lib/graph_ql/introspection/possible_types_field.rb +3 -10
  19. data/lib/graph_ql/introspection/schema_type.rb +8 -14
  20. data/lib/graph_ql/introspection/type_kind_enum.rb +1 -1
  21. data/lib/graph_ql/introspection/type_type.rb +17 -19
  22. data/lib/graph_ql/introspection/typename_field.rb +15 -0
  23. data/lib/graph_ql/parser.rb +9 -0
  24. data/lib/graph_ql/parser/nodes.rb +17 -7
  25. data/lib/graph_ql/parser/parser.rb +7 -7
  26. data/lib/graph_ql/parser/transform.rb +23 -20
  27. data/lib/graph_ql/parser/visitor.rb +29 -13
  28. data/lib/graph_ql/query.rb +39 -16
  29. data/lib/graph_ql/query/field_resolution_strategy.rb +15 -11
  30. data/lib/graph_ql/query/type_resolver.rb +4 -2
  31. data/lib/graph_ql/repl.rb +1 -1
  32. data/lib/graph_ql/schema.rb +19 -7
  33. data/lib/graph_ql/schema/each_item_validator.rb +12 -0
  34. data/lib/graph_ql/schema/field_validator.rb +13 -0
  35. data/lib/graph_ql/schema/implementation_validator.rb +21 -0
  36. data/lib/graph_ql/schema/schema_validator.rb +10 -0
  37. data/lib/graph_ql/schema/type_reducer.rb +6 -6
  38. data/lib/graph_ql/schema/type_validator.rb +47 -0
  39. data/lib/graph_ql/static_validation.rb +18 -0
  40. data/lib/graph_ql/static_validation/argument_literals_are_compatible.rb +13 -0
  41. data/lib/graph_ql/static_validation/arguments_are_defined.rb +10 -0
  42. data/lib/graph_ql/static_validation/arguments_validator.rb +16 -0
  43. data/lib/graph_ql/static_validation/directives_are_defined.rb +18 -0
  44. data/lib/graph_ql/static_validation/fields_are_defined_on_type.rb +29 -0
  45. data/lib/graph_ql/static_validation/fields_have_appropriate_selections.rb +31 -0
  46. data/lib/graph_ql/static_validation/fields_will_merge.rb +93 -0
  47. data/lib/graph_ql/static_validation/fragment_types_exist.rb +24 -0
  48. data/lib/graph_ql/static_validation/fragments_are_used.rb +30 -0
  49. data/lib/graph_ql/static_validation/literal_validator.rb +27 -0
  50. data/lib/graph_ql/static_validation/message.rb +29 -0
  51. data/lib/graph_ql/static_validation/required_arguments_are_present.rb +13 -0
  52. data/lib/graph_ql/static_validation/type_stack.rb +87 -0
  53. data/lib/graph_ql/static_validation/validator.rb +48 -0
  54. data/lib/graph_ql/type_kinds.rb +50 -12
  55. data/lib/graph_ql/types/argument_definer.rb +7 -0
  56. data/lib/graph_ql/types/boolean_type.rb +3 -3
  57. data/lib/graph_ql/types/field_definer.rb +19 -0
  58. data/lib/graph_ql/types/float_type.rb +3 -3
  59. data/lib/graph_ql/types/input_object_type.rb +4 -0
  60. data/lib/graph_ql/types/input_value.rb +1 -1
  61. data/lib/graph_ql/types/int_type.rb +4 -4
  62. data/lib/graph_ql/types/list_type.rb +5 -1
  63. data/lib/graph_ql/types/non_null_type.rb +4 -0
  64. data/lib/graph_ql/types/object_type.rb +9 -20
  65. data/lib/graph_ql/types/scalar_type.rb +4 -0
  66. data/lib/graph_ql/types/string_type.rb +3 -3
  67. data/lib/graph_ql/types/type_definer.rb +5 -9
  68. data/lib/graph_ql/union.rb +6 -17
  69. data/lib/graph_ql/version.rb +1 -1
  70. data/lib/graphql.rb +58 -78
  71. data/readme.md +80 -7
  72. data/spec/graph_ql/interface_spec.rb +15 -1
  73. data/spec/graph_ql/introspection/directive_type_spec.rb +2 -2
  74. data/spec/graph_ql/introspection/schema_type_spec.rb +2 -1
  75. data/spec/graph_ql/introspection/type_type_spec.rb +16 -1
  76. data/spec/graph_ql/parser/parser_spec.rb +3 -1
  77. data/spec/graph_ql/parser/transform_spec.rb +12 -2
  78. data/spec/graph_ql/parser/visitor_spec.rb +13 -5
  79. data/spec/graph_ql/query_spec.rb +25 -13
  80. data/spec/graph_ql/schema/field_validator_spec.rb +21 -0
  81. data/spec/graph_ql/schema/type_reducer_spec.rb +2 -2
  82. data/spec/graph_ql/schema/type_validator_spec.rb +54 -0
  83. data/spec/graph_ql/static_validation/argument_literals_are_compatible_spec.rb +41 -0
  84. data/spec/graph_ql/static_validation/arguments_are_defined_spec.rb +40 -0
  85. data/spec/graph_ql/static_validation/directives_are_defined_spec.rb +33 -0
  86. data/spec/graph_ql/static_validation/fields_are_defined_on_type_spec.rb +59 -0
  87. data/spec/graph_ql/static_validation/fields_have_appropriate_selections_spec.rb +30 -0
  88. data/spec/graph_ql/{validations → static_validation}/fields_will_merge_spec.rb +24 -17
  89. data/spec/graph_ql/static_validation/fragment_types_exist_spec.rb +38 -0
  90. data/spec/graph_ql/static_validation/fragments_are_used_spec.rb +24 -0
  91. data/spec/graph_ql/static_validation/required_arguments_are_present_spec.rb +41 -0
  92. data/spec/graph_ql/static_validation/type_stack_spec.rb +35 -0
  93. data/spec/graph_ql/static_validation/validator_spec.rb +28 -0
  94. data/spec/graph_ql/types/object_type_spec.rb +1 -1
  95. data/spec/graph_ql/union_spec.rb +1 -14
  96. data/spec/support/dummy_app.rb +75 -53
  97. metadata +53 -31
  98. data/lib/graph_ql/fields/abstract_field.rb +0 -37
  99. data/lib/graph_ql/fields/access_field.rb +0 -24
  100. data/lib/graph_ql/fields/field.rb +0 -34
  101. data/lib/graph_ql/types/abstract_type.rb +0 -14
  102. data/lib/graph_ql/validations/fields_are_defined_on_type.rb +0 -44
  103. data/lib/graph_ql/validations/fields_will_merge.rb +0 -80
  104. data/lib/graph_ql/validations/fragments_are_used.rb +0 -24
  105. data/lib/graph_ql/validator.rb +0 -29
  106. data/spec/graph_ql/validations/fields_are_defined_on_type_spec.rb +0 -28
  107. data/spec/graph_ql/validations/fragments_are_used_spec.rb +0 -28
  108. 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
@@ -1,15 +1,53 @@
1
1
  module GraphQL::TypeKinds
2
- KIND_NAMES = %i{
3
- SCALAR
4
- OBJECT
5
- INTERFACE
6
- UNION
7
- ENUM
8
- INPUT_OBJECT
9
- LIST
10
- NON_NULL
11
- }
12
- KIND_NAMES.each do |type_kind|
13
- const_set(type_kind, type_kind)
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,7 @@
1
+ class GraphQL::ArgumentDefiner
2
+ include Singleton
3
+
4
+ def build(type:, desc: "", default_value: nil)
5
+ GraphQL::InputValue.new(type: type, description: desc, default_value: default_value)
6
+ end
7
+ end
@@ -1,6 +1,6 @@
1
- GraphQL::BOOLEAN_TYPE = GraphQL::ScalarType.new do
2
- name "Boolean"
3
- def coerce(value)
1
+ GraphQL::BOOLEAN_TYPE = GraphQL::ScalarType.new do |t|
2
+ t.name "Boolean"
3
+ def t.coerce(value)
4
4
  !!value
5
5
  end
6
6
  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,6 +1,6 @@
1
- GraphQL::FLOAT_TYPE = GraphQL::ScalarType.new do
2
- name "Float"
3
- def coerce(value)
1
+ GraphQL::FLOAT_TYPE = GraphQL::ScalarType.new do |t|
2
+ t.name "Float"
3
+ def t.coerce(value)
4
4
  value.to_f
5
5
  end
6
6
  end
@@ -14,4 +14,8 @@ class GraphQL::InputObjectType < GraphQL::ObjectType
14
14
  def kind
15
15
  GraphQL::TypeKinds::INPUT_OBJECT
16
16
  end
17
+
18
+ def to_s
19
+ "<GraphQL::InputObjectType #{name}>"
20
+ end
17
21
  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:, default_value:, name: nil)
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,6 +1,6 @@
1
- GraphQL::INT_TYPE = GraphQL::ScalarType.new do
2
- name "Int"
3
- def coerce(value)
4
- value.to_i
1
+ GraphQL::INT_TYPE = GraphQL::ScalarType.new do |t|
2
+ t.name "Int"
3
+ def t.coerce(value)
4
+ value.is_a?(Numeric) ? value.to_i : nil
5
5
  end
6
6
  end
@@ -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
@@ -15,4 +15,8 @@ class GraphQL::NonNullType < GraphQL::ObjectType
15
15
  def kind
16
16
  GraphQL::TypeKinds::NON_NULL
17
17
  end
18
+
19
+ def to_s
20
+ "<GraphQL::NonNullType(#{of_type.name})>"
21
+ end
18
22
  end
@@ -6,7 +6,7 @@ class GraphQL::ObjectType
6
6
  def initialize(&block)
7
7
  self.fields = []
8
8
  self.interfaces = []
9
- instance_eval(&block)
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::Field.new do |f|
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