graphql 0.3.0 → 0.4.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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graph_ql/{types/input_value.rb → argument.rb} +4 -1
  3. data/lib/graph_ql/{scalars/boolean_type.rb → boolean_type.rb} +0 -0
  4. data/lib/graph_ql/definition_helpers.rb +10 -0
  5. data/lib/graph_ql/definition_helpers/argument_definer.rb +5 -2
  6. data/lib/graph_ql/definition_helpers/definable.rb +1 -1
  7. data/lib/graph_ql/definition_helpers/field_definer.rb +4 -1
  8. data/lib/graph_ql/definition_helpers/non_null_with_bang.rb +3 -1
  9. data/lib/graph_ql/definition_helpers/string_named_hash.rb +7 -1
  10. data/lib/graph_ql/definition_helpers/type_definer.rb +13 -1
  11. data/lib/graph_ql/directive.rb +14 -6
  12. data/lib/graph_ql/{directives → directive}/include_directive.rb +1 -1
  13. data/lib/graph_ql/{directives → directive}/skip_directive.rb +1 -1
  14. data/lib/graph_ql/enum_type.rb +66 -0
  15. data/lib/graph_ql/field.rb +49 -13
  16. data/lib/graph_ql/{scalars/float_type.rb → float_type.rb} +0 -0
  17. data/lib/graph_ql/{scalars/id_type.rb → id_type.rb} +0 -0
  18. data/lib/graph_ql/input_object_type.rb +33 -0
  19. data/lib/graph_ql/{scalars/int_type.rb → int_type.rb} +0 -0
  20. data/lib/graph_ql/interface_type.rb +33 -0
  21. data/lib/graph_ql/introspection/field_type.rb +1 -0
  22. data/lib/graph_ql/introspection/fields_field.rb +1 -0
  23. data/lib/graph_ql/introspection/input_value_type.rb +1 -1
  24. data/lib/graph_ql/introspection/introspection_query.rb +77 -0
  25. data/lib/graph_ql/introspection/schema_field.rb +13 -0
  26. data/lib/graph_ql/introspection/type_by_name_field.rb +14 -0
  27. data/lib/graph_ql/introspection/type_kind_enum.rb +1 -1
  28. data/lib/graph_ql/{types/list_type.rb → list_type.rb} +3 -0
  29. data/lib/graph_ql/{parser/nodes.rb → nodes.rb} +8 -1
  30. data/lib/graph_ql/{types/non_null_type.rb → non_null_type.rb} +3 -0
  31. data/lib/graph_ql/object_type.rb +92 -0
  32. data/lib/graph_ql/parser.rb +107 -6
  33. data/lib/graph_ql/query.rb +8 -0
  34. data/lib/graph_ql/query/arguments.rb +13 -4
  35. data/lib/graph_ql/{directives → query}/directive_chain.rb +2 -2
  36. data/lib/graph_ql/query/field_resolution_strategy.rb +2 -2
  37. data/lib/graph_ql/query/operation_resolver.rb +3 -3
  38. data/lib/graph_ql/query/selection_resolver.rb +1 -1
  39. data/lib/graph_ql/scalar_type.rb +9 -0
  40. data/lib/graph_ql/schema.rb +26 -17
  41. data/lib/graph_ql/schema/type_reducer.rb +7 -0
  42. data/lib/graph_ql/static_validation/arguments_validator.rb +1 -0
  43. data/lib/graph_ql/static_validation/message.rb +4 -1
  44. data/lib/graph_ql/static_validation/rules/fields_are_defined_on_type.rb +1 -0
  45. data/lib/graph_ql/static_validation/rules/fields_have_appropriate_selections.rb +1 -0
  46. data/lib/graph_ql/static_validation/type_stack.rb +24 -4
  47. data/lib/graph_ql/static_validation/validator.rb +27 -0
  48. data/lib/graph_ql/{scalars/string_type.rb → string_type.rb} +0 -0
  49. data/lib/graph_ql/transform.rb +87 -0
  50. data/lib/graph_ql/type_kinds.rb +9 -0
  51. data/lib/graph_ql/{types/union.rb → union_type.rb} +8 -4
  52. data/lib/graph_ql/version.rb +1 -1
  53. data/lib/graph_ql/{parser/visitor.rb → visitor.rb} +29 -4
  54. data/lib/graphql.rb +28 -11
  55. data/readme.md +11 -1
  56. data/spec/graph_ql/{types/enum_spec.rb → enum_type_spec.rb} +1 -1
  57. data/spec/graph_ql/{fields/field_spec.rb → field_spec.rb} +0 -0
  58. data/spec/graph_ql/{scalars/id_type_spec.rb → id_type_spec.rb} +0 -0
  59. data/spec/graph_ql/{types/input_object_type_spec.rb → input_object_type_spec.rb} +0 -0
  60. data/spec/graph_ql/{types/interface_spec.rb → interface_type_spec.rb} +1 -1
  61. data/spec/graph_ql/introspection/introspection_query_spec.rb +10 -0
  62. data/spec/graph_ql/introspection/schema_type_spec.rb +0 -4
  63. data/spec/graph_ql/introspection/type_type_spec.rb +1 -5
  64. data/spec/graph_ql/{types/object_type_spec.rb → object_type_spec.rb} +0 -0
  65. data/spec/graph_ql/{parser/parser_spec.rb → parser_spec.rb} +0 -0
  66. data/spec/graph_ql/query/operation_resolver_spec.rb +1 -1
  67. data/spec/graph_ql/query_spec.rb +6 -2
  68. data/spec/graph_ql/schema/type_validator_spec.rb +1 -1
  69. data/spec/graph_ql/{parser/transform_spec.rb → transform_spec.rb} +0 -0
  70. data/spec/graph_ql/{types/union_spec.rb → union_type_spec.rb} +2 -2
  71. data/spec/graph_ql/{parser/visitor_spec.rb → visitor_spec.rb} +0 -0
  72. data/spec/support/{dummy_app.rb → dairy_app.rb} +8 -8
  73. data/spec/support/{dummy_data.rb → dairy_data.rb} +0 -0
  74. data/spec/support/star_wars_data.rb +71 -0
  75. data/spec/support/star_wars_schema.rb +87 -0
  76. metadata +59 -50
  77. data/lib/graph_ql/definition_helpers/forwardable.rb +0 -10
  78. data/lib/graph_ql/parser/parser.rb +0 -108
  79. data/lib/graph_ql/parser/transform.rb +0 -87
  80. data/lib/graph_ql/scalars/scalar_type.rb +0 -5
  81. data/lib/graph_ql/types/enum.rb +0 -32
  82. data/lib/graph_ql/types/input_object_type.rb +0 -14
  83. data/lib/graph_ql/types/interface.rb +0 -14
  84. data/lib/graph_ql/types/object_type.rb +0 -66
@@ -13,6 +13,13 @@ class GraphQL::Schema::TypeReducer
13
13
  end
14
14
  end
15
15
 
16
+ # Reduce all of `types` and return the combined result
17
+ def self.find_all(types)
18
+ types.reduce({}) do |memo, type|
19
+ self.new(type, memo).result
20
+ end
21
+ end
22
+
16
23
  private
17
24
 
18
25
  def find_types(type, type_hash)
@@ -5,6 +5,7 @@ class GraphQL::StaticValidation::ArgumentsValidator
5
5
  def validate(context)
6
6
  visitor = context.visitor
7
7
  visitor[GraphQL::Nodes::Field] << -> (node, parent) {
8
+ return if context.skip_field?(node.name)
8
9
  field_defn = context.field_definition
9
10
  validate_node(node, field_defn, context)
10
11
  }
@@ -8,12 +8,15 @@ class GraphQL::StaticValidation::Message
8
8
  GraphQL::StaticValidation::Message.new(message, line: node.line, col: node.col)
9
9
  end
10
10
  end
11
- attr_reader :message, :line, :co
11
+ attr_reader :message, :line, :col
12
+
12
13
  def initialize(message, line: nil, col: nil)
13
14
  @message = message
14
15
  @line = line
15
16
  @col = col
16
17
  end
18
+
19
+ # A hash representation of this Message
17
20
  def to_h
18
21
  {
19
22
  "message" => message,
@@ -6,6 +6,7 @@ class GraphQL::StaticValidation::FieldsAreDefinedOnType
6
6
  def validate(context)
7
7
  visitor = context.visitor
8
8
  visitor[GraphQL::Nodes::Field] << -> (node, parent) {
9
+ return if context.skip_field?(node.name)
9
10
  parent_type = context.object_types[-2]
10
11
  parent_type = parent_type.kind.unwrap(parent_type)
11
12
  validate_field(context.errors, node, parent_type, parent)
@@ -5,6 +5,7 @@ class GraphQL::StaticValidation::FieldsHaveAppropriateSelections
5
5
 
6
6
  def validate(context)
7
7
  context.visitor[GraphQL::Nodes::Field] << -> (node, parent) {
8
+ return if context.skip_field?(node.name)
8
9
  field_defn = context.field_definition
9
10
  validate_field_selections(node, field_defn, context.errors)
10
11
  }
@@ -7,7 +7,25 @@ class GraphQL::StaticValidation::TypeStack
7
7
  GraphQL::Nodes::FragmentDefinition,
8
8
  ]
9
9
 
10
- attr_reader :schema, :object_types, :field_definitions, :directive_definitions
10
+ # @return [GraphQL::Schema] the schema whose types are present in this document
11
+ attr_reader :schema
12
+
13
+ # When it enters an object (starting with query or mutation root), it's pushed on this stack.
14
+ # When it exits, it's popped off.
15
+ # @return [Array<GraphQL::ObjectType, GraphQL::Union, GraphQL::Interface>]
16
+ attr_reader :object_types
17
+
18
+ # When it enters a field, it's pushed on this stack (useful for nested fields, args).
19
+ # When it exits, it's popped off.
20
+ # @return [Array<GraphQL::Field>] fields which have been entered
21
+ attr_reader :field_definitions
22
+
23
+ # Directives are pushed on, then popped off while traversing the tree
24
+ # @return [Array<GraphQL::Node::Directive>] directives which have been entered
25
+ attr_reader :directive_definitions
26
+
27
+ # @param schema [GraphQL::Schema] the schema whose types to use when climbing this document
28
+ # @param visitor [GraphQL::Visitor] a visitor to follow & watch the types
11
29
  def initialize(schema, visitor)
12
30
  @schema = schema
13
31
  @object_types = []
@@ -61,7 +79,7 @@ class GraphQL::StaticValidation::TypeStack
61
79
  parent_type = stack.object_types.last
62
80
  parent_type = parent_type.kind.unwrap(parent_type)
63
81
  if parent_type.kind.fields?
64
- field_class = parent_type.fields[node.name]
82
+ field_class = stack.schema.get_field(parent_type, node.name)
65
83
  stack.field_definitions.push(field_class)
66
84
  if !field_class.nil?
67
85
  next_object_type = field_class.type
@@ -92,8 +110,10 @@ class GraphQL::StaticValidation::TypeStack
92
110
  end
93
111
  end
94
112
 
113
+ # A no-op strategy (don't handle this node)
95
114
  class NullStrategy
96
- def push(stack, node); end
97
- def pop(stack, node); end
115
+ def self.new; self; end
116
+ def self.push(stack, node); end
117
+ def self.pop(stack, node); end
98
118
  end
99
119
  end
@@ -1,12 +1,23 @@
1
1
  # Initialized with a {GraphQL::Schema}, then it can validate {GraphQL::Nodes::Documents}s based on that schema.
2
2
  #
3
3
  # By default, it's used by {GraphQL::Query}
4
+ #
5
+ # @example Validate a query
6
+ # validator = GraphQL::StaticValidation::Validator.new(schema: MySchema)
7
+ # document = GraphQL.parse(query_string)
8
+ # errors = validator.validate(document)
9
+ #
4
10
  class GraphQL::StaticValidation::Validator
11
+ # @param schema [GraphQL::Schema]
12
+ # @param rule [Array<#validate(context)>] a list of rules to use when validating
5
13
  def initialize(schema:, rules: GraphQL::StaticValidation::ALL_RULES)
6
14
  @schema = schema
7
15
  @rules = rules
8
16
  end
9
17
 
18
+ # Validate `document` against the schema. Returns an array of message hashes.
19
+ # @param document [GraphQL::Nodes::Document]
20
+ # @return [Array<Hash>]
10
21
  def validate(document)
11
22
  context = Context.new(@schema, document)
12
23
  @rules.each do |rules|
@@ -16,6 +27,16 @@ class GraphQL::StaticValidation::Validator
16
27
  context.errors.map(&:to_h)
17
28
  end
18
29
 
30
+ # The validation context gets passed to each validator.
31
+ #
32
+ # It exposes a {GraphQL::Visitor} where validators may add hooks. ({Visitor#visit} is called in {Validator#validate})
33
+ #
34
+ # It provides access to the schema & fragments which validators may read from.
35
+ #
36
+ # It holds a list of errors which each validator may add to.
37
+ #
38
+ # It also provides limited access to the {TypeStack} instance,
39
+ # which tracks state as you climb in and out of different fields.
19
40
  class Context
20
41
  attr_reader :schema, :document, :errors, :visitor, :fragments
21
42
  def initialize(schema, document)
@@ -40,5 +61,11 @@ class GraphQL::StaticValidation::Validator
40
61
  def directive_definition
41
62
  @type_stack.directive_definitions.last
42
63
  end
64
+
65
+ # Don't try to validate dynamic fields
66
+ # since they aren't defined by the type system
67
+ def skip_field?(field_name)
68
+ GraphQL::Schema::DYNAMIC_FIELDS.include?(field_name)
69
+ end
43
70
  end
44
71
  end
@@ -0,0 +1,87 @@
1
+ module GraphQL
2
+ # {Transform} is a [parslet](http://kschiess.github.io/parslet/) transform for for turning the AST into objects in {GraphQL::Nodes} objects.
3
+ class Transform < Parslet::Transform
4
+ def self.optional_sequence(name)
5
+ rule(name => simple(:val)) { [] }
6
+ rule(name => sequence(:val)) { val }
7
+ end
8
+
9
+ # Document
10
+ rule(document_parts: sequence(:p)) { Nodes::Document.new(parts: p, line: p.first.line, col: p.first.col)}
11
+
12
+ # Fragment Definition
13
+ rule(
14
+ fragment_keyword: simple(:kw),
15
+ fragment_name: simple(:name),
16
+ type_condition: simple(:type),
17
+ directives: sequence(:directives),
18
+ selections: sequence(:selections)
19
+ ) { Nodes::FragmentDefinition.new(name: name.to_s, type: type.to_s, directives: directives, selections: selections, position_source: kw)}
20
+
21
+ rule(
22
+ fragment_spread_keyword: simple(:kw),
23
+ fragment_spread_name: simple(:n),
24
+ directives: sequence(:d)
25
+ ) { Nodes::FragmentSpread.new(name: n.to_s, directives: d, position_source: kw)}
26
+
27
+ rule(
28
+ fragment_spread_keyword: simple(:kw),
29
+ inline_fragment_type: simple(:n),
30
+ directives: sequence(:d),
31
+ selections: sequence(:s),
32
+ ) { Nodes::InlineFragment.new(type: n.to_s, directives: d, selections: s, position_source: kw)}
33
+
34
+ # Operation Definition
35
+ rule(
36
+ operation_type: simple(:ot),
37
+ name: simple(:n),
38
+ variables: sequence(:v),
39
+ directives: sequence(:d),
40
+ selections: sequence(:s),
41
+ ) { Nodes::OperationDefinition.new(operation_type: ot.to_s, name: n.to_s, variables: v, directives: d, selections: s, position_source: ot) }
42
+ optional_sequence(:optional_variables)
43
+ rule(variable_name: simple(:n), variable_type: simple(:t), variable_optional_default_value: simple(:v)) { Nodes::Variable.new(name: n.name, type: t, default_value: v, line: n.line, col: n.col)}
44
+ rule(variable_name: simple(:n), variable_type: simple(:t), variable_optional_default_value: sequence(:v)) { Nodes::Variable.new(name: n.name, type: t, default_value: v, line: n.line, col: n.col)}
45
+ rule(variable_default_value: simple(:v) ) { v }
46
+ rule(variable_default_value: sequence(:v) ) { v }
47
+ # Query short-hand
48
+ rule(unnamed_selections: sequence(:s)) { Nodes::OperationDefinition.new(selections: s, operation_type: "query", name: nil, variables: [], directives: [], line: s.first.line, col: s.first.col)}
49
+
50
+ # Field
51
+ rule(
52
+ alias: simple(:a),
53
+ field_name: simple(:name),
54
+ field_arguments: sequence(:args),
55
+ directives: sequence(:dir),
56
+ selections: sequence(:sel)
57
+ ) { Nodes::Field.new(alias: a && a.to_s, name: name.to_s, arguments: args, directives: dir, selections: sel, position_source: [a, name].find { |part| !part.nil? }) }
58
+
59
+ rule(alias_name: simple(:a)) { a }
60
+ optional_sequence(:optional_field_arguments)
61
+ rule(field_argument_name: simple(:n), field_argument_value: simple(:v)) { Nodes::Argument.new(name: n.to_s, value: v, position_source: n)}
62
+ optional_sequence(:optional_selections)
63
+ optional_sequence(:optional_directives)
64
+
65
+ # Directive
66
+ rule(directive_name: simple(:name), directive_arguments: sequence(:args)) { Nodes::Directive.new(name: name.to_s, arguments: args, position_source: name ) }
67
+ rule(directive_argument_name: simple(:n), directive_argument_value: simple(:v)) { Nodes::Argument.new(name: n.to_s, value: v, position_source: n)}
68
+ optional_sequence(:optional_directive_arguments)
69
+
70
+ # Type Defs
71
+ rule(type_name: simple(:n)) { Nodes::TypeName.new(name: n.to_s, position_source: n) }
72
+ rule(list_type: simple(:t)) { Nodes::ListType.new(of_type: t, line: t.line, col: t.col)}
73
+ rule(non_null_type: simple(:t)) { Nodes::NonNullType.new(of_type: t, line: t.line, col: t.col)}
74
+
75
+ # Values
76
+ rule(array: sequence(:v)) { v }
77
+ rule(boolean: simple(:v)) { v == "true" ? true : false }
78
+ rule(input_object: sequence(:v)) { Nodes::InputObject.new(pairs: v, line: v.first.line, col: v.first.col) }
79
+ rule(input_object_name: simple(:n), input_object_value: simple(:v)) { Nodes::Argument.new(name: n.to_s, value: v, position_source: n)}
80
+ rule(int: simple(:v)) { v.to_i }
81
+ rule(float: simple(:v)) { v.to_f }
82
+ rule(string: simple(:v)) { v.to_s }
83
+ rule(variable: simple(:v)) { Nodes::VariableIdentifier.new(name: v.to_s, position_source: v) }
84
+ rule(enum: simple(:v)) { Nodes::Enum.new(name: v.to_s, position_source: v)}
85
+ end
86
+ TRANSFORM = GraphQL::Transform.new
87
+ end
@@ -1,4 +1,6 @@
1
+ # Type kinds are the basic categories which a type may belong to (`Object`, `Scalar`, `Union`...)
1
2
  module GraphQL::TypeKinds
3
+ # These objects are singletons, eg `GraphQL::TypeKinds::UNION`, `GraphQL::TypeKinds::SCALAR`.
2
4
  class TypeKind
3
5
  attr_reader :name
4
6
  def initialize(name, resolves: false, fields: false, wraps: false, input: false)
@@ -10,13 +12,19 @@ module GraphQL::TypeKinds
10
12
  @composite = fields? || resolves?
11
13
  end
12
14
 
15
+ # Does this TypeKind have multiple possible implementors?
13
16
  def resolves?; @resolves; end
17
+ # Does this TypeKind have queryable fields?
14
18
  def fields?; @fields; end
19
+ # Does this TypeKind modify another type?
15
20
  def wraps?; @wraps; end
21
+ # Is this TypeKind a valid query input?
16
22
  def input?; @input; end
17
23
  def to_s; @name; end
24
+ # Is this TypeKind composed of many values?
18
25
  def composite?; @composite; end
19
26
 
27
+ # Get the implementing type for `value` from `type` (no-op for TypeKinds which don't `resolves?`)
20
28
  def resolve(type, value)
21
29
  if resolves?
22
30
  type.resolve_type(value)
@@ -25,6 +33,7 @@ module GraphQL::TypeKinds
25
33
  end
26
34
  end
27
35
 
36
+ # Get the modified type for `type` (no-op for TypeKinds which don't `wraps?`)
28
37
  def unwrap(type)
29
38
  if wraps?
30
39
  wrapped_type = type.of_type
@@ -1,5 +1,10 @@
1
- class GraphQL::Union
2
- include GraphQL::NonNullWithBang
1
+ # A collection of {ObjectType}s
2
+ #
3
+ # @example a union of types
4
+ # PetUnion = GraphQL::UnionType.new("Pet", "House pets", [DogType, CatType])
5
+ #
6
+ class GraphQL::UnionType
7
+ include GraphQL::DefinitionHelpers::NonNullWithBang
3
8
  attr_reader :name, :description, :possible_types
4
9
  def initialize(name, desc, types)
5
10
  @name = name
@@ -11,8 +16,7 @@ class GraphQL::Union
11
16
  GraphQL::TypeKinds::UNION
12
17
  end
13
18
 
14
- # Find a type in this union for a given object.
15
- # Reimplement if needed
19
+ # @see {InterfaceType#resolve_type}
16
20
  def resolve_type(object)
17
21
  type_name = object.class.name
18
22
  possible_types.find {|t| t.name == type_name}
@@ -1,3 +1,3 @@
1
1
  module GraphQL
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -1,28 +1,44 @@
1
1
  # Depth-first traversal through the tree, calling hooks at each stop.
2
2
  #
3
- # @example: Create a visitor, add hooks, then search a document
3
+ # @example Create a visitor, add hooks, then search a document
4
4
  # total_field_count = 0
5
5
  # visitor = GraphQL::Visitor.new
6
+ # # Whenever you find a field, increment the field count:
6
7
  # visitor[GraphQL::Nodes::Field] << -> (node) { total_field_count += 1 }
8
+ # # When we finish, print the field count:
7
9
  # visitor[GraphQL::Nodes::Document].leave << -> (node) { p total_field_count }
8
10
  # visitor.visit(document)
9
11
  # # => 6
10
12
  #
11
13
  class GraphQL::Visitor
14
+ # If any hook returns this value, the {Visitor} stops visiting this
15
+ # node right away
12
16
  SKIP = :_skip
13
17
 
14
- attr_reader :enter, :leave
18
+ # @return [Array<Proc>] Hooks to call when entering _any_ node
19
+ attr_reader :enter
20
+ # @return [Array<Proc>] Hooks to call when leaving _any_ node
21
+ attr_reader :leave
22
+
15
23
  def initialize
16
24
  @visitors = {}
17
25
  @enter = []
18
26
  @leave = []
19
27
  end
20
28
 
29
+ # Get a {NodeVisitor} for `node_class`
30
+ # @param node_class [Class] The node class that you want to listen to
31
+ # @return [NodeVisitor]
32
+ #
33
+ # @example Run a hook whenever you enter a new Field
34
+ # visitor[GraphQL::Nodes::Field] << -> (node, parent) { p "Here's a field" }
21
35
  def [](node_class)
22
36
  @visitors[node_class] ||= NodeVisitor.new
23
37
  end
24
38
 
25
- # Apply built-up vistors to `document`
39
+ # Visit `root` and all children, applying hooks as you go
40
+ # @param root [GraphQL::Nodes::AbstractNode] some node to start parsing on
41
+ # @return [void]
26
42
  def visit(root, parent=nil)
27
43
  begin_visit(root, parent) &&
28
44
  root.children.reduce(true) { |memo, child| memo && visit(child, root) }
@@ -49,13 +65,22 @@ class GraphQL::Visitor
49
65
  hooks.reduce(true) { |memo, proc| memo && (proc.call(node, parent) != SKIP) }
50
66
  end
51
67
 
68
+ # Collect `enter` and `leave` hooks for classes in {GraphQL::Nodes}
69
+ #
70
+ # Access {NodeVisitor}s via {GraphQL::Visitor#[]}
52
71
  class NodeVisitor
53
- attr_reader :enter, :leave
72
+ # @return [Array<Proc>] Hooks to call when entering a node of this type
73
+ attr_reader :enter
74
+ # @return [Array<Proc>] Hooks to call when leaving a node of this type
75
+ attr_reader :leave
76
+
54
77
  def initialize
55
78
  @enter = []
56
79
  @leave = []
57
80
  end
58
81
 
82
+ # Shorthand to add a hook to the {#enter} array
83
+ # @param hook [Proc] A hook to add
59
84
  def <<(hook)
60
85
  enter << hook
61
86
  end
data/lib/graphql.rb CHANGED
@@ -3,6 +3,10 @@ require "parslet"
3
3
  require "singleton"
4
4
 
5
5
  module GraphQL
6
+ # Turn a query string into an AST
7
+ # @param string [String] a GraphQL query string
8
+ # @param as [Symbol] If you want to use this to parse some _piece_ of a document, pass the rule name (from {GraphQL::Parser::Parser})
9
+ # @return [GraphQL::Nodes::Document]
6
10
  def self.parse(string, as: nil)
7
11
  parser = as ? GraphQL::PARSER.send(as) : GraphQL::PARSER
8
12
  tree = parser.parse(string)
@@ -12,26 +16,33 @@ module GraphQL
12
16
  raise [line, col, string].join(", ")
13
17
  end
14
18
 
19
+ # Types & Fields that support GraphQL introspection queries
15
20
  module Introspection; end
16
21
  end
17
22
 
18
- def require_dir(dir)
19
- Dir.glob(File.expand_path("../graph_ql/#{dir}/*.rb", __FILE__)).each do |file|
20
- require file
21
- end
22
- end
23
23
  # Order matters for these:
24
24
 
25
- require_dir('definition_helpers')
26
- require 'graph_ql/types/object_type'
27
- require_dir('types')
25
+ require 'graph_ql/definition_helpers'
26
+ require 'graph_ql/object_type'
27
+
28
+ require 'graph_ql/enum_type'
29
+ require 'graph_ql/input_object_type'
30
+ require 'graph_ql/interface_type'
31
+ require 'graph_ql/list_type'
32
+ require 'graph_ql/non_null_type'
33
+ require 'graph_ql/union_type'
28
34
 
35
+ require 'graph_ql/argument'
29
36
  require 'graph_ql/field'
30
37
  require 'graph_ql/type_kinds'
31
38
  require 'graph_ql/introspection/typename_field'
32
39
 
33
- require 'graph_ql/scalars/scalar_type'
34
- require_dir('scalars')
40
+ require 'graph_ql/scalar_type'
41
+ require 'graph_ql/boolean_type'
42
+ require 'graph_ql/float_type'
43
+ require 'graph_ql/id_type'
44
+ require 'graph_ql/int_type'
45
+ require 'graph_ql/string_type'
35
46
 
36
47
  require 'graph_ql/introspection/input_value_type'
37
48
  require 'graph_ql/introspection/enum_value_type'
@@ -45,13 +56,19 @@ require 'graph_ql/introspection/enum_values_field'
45
56
  require 'graph_ql/introspection/interfaces_field'
46
57
 
47
58
  require 'graph_ql/introspection/type_type'
59
+ require 'graph_ql/introspection/arguments_field'
48
60
  require 'graph_ql/introspection/field_type'
49
61
 
50
- require 'graph_ql/introspection/arguments_field'
51
62
  require 'graph_ql/introspection/directive_type'
52
63
  require 'graph_ql/introspection/schema_type'
64
+ require 'graph_ql/introspection/schema_field'
65
+ require 'graph_ql/introspection/type_by_name_field'
66
+ require 'graph_ql/introspection/introspection_query'
53
67
 
68
+ require 'graph_ql/nodes'
54
69
  require 'graph_ql/parser'
70
+ require 'graph_ql/transform'
71
+ require 'graph_ql/visitor'
55
72
  require 'graph_ql/directive'
56
73
  require 'graph_ql/schema'
57
74