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
@@ -1,10 +0,0 @@
1
- # Get `delegate` like Rails has
2
- module GraphQL::Forwardable
3
- def delegate(*methods, to:)
4
- methods.each do |method_name|
5
- define_method(method_name) do |*args|
6
- self.public_send(to).public_send(method_name, *args)
7
- end
8
- end
9
- end
10
- end
@@ -1,108 +0,0 @@
1
- # Parser is a [parslet](http://kschiess.github.io/parslet/) parser for parsing queries.
2
- #
3
- # If it failes to parse, a {SyntaxError} is raised.
4
- class GraphQL::Parser < Parslet::Parser
5
- root(:document)
6
- rule(:document) { (
7
- space |
8
- operation_definition |
9
- fragment_definition
10
- ).repeat(1).as(:document_parts)
11
- }
12
-
13
- # TODO: whitespace sensitive regarding `on`, eg `onFood`, see lookahead note in spec
14
- rule(:fragment_definition) {
15
- str("fragment").as(:fragment_keyword) >>
16
- space? >> name.as(:fragment_name) >>
17
- space? >> str("on") >> space? >> name.as(:type_condition) >>
18
- space? >> directives.maybe.as(:optional_directives).as(:directives) >>
19
- space? >> selections.as(:selections)
20
- }
21
-
22
- rule(:fragment_spread) {
23
- spread.as(:fragment_spread_keyword) >> space? >>
24
- name.as(:fragment_spread_name) >> space? >>
25
- directives.maybe.as(:optional_directives).as(:directives)
26
- }
27
- rule(:spread) { str("...") }
28
- # TODO: `on` bug, see spec
29
- rule(:inline_fragment) {
30
- spread.as(:fragment_spread_keyword) >> space? >>
31
- str("on ") >> name.as(:inline_fragment_type) >> space? >>
32
- directives.maybe.as(:optional_directives).as(:directives) >> space? >>
33
- selections.as(:selections)
34
- }
35
-
36
- rule(:operation_definition) { (unnamed_selections | named_operation_definition) }
37
- rule(:unnamed_selections) { selections.as(:unnamed_selections)}
38
- rule(:named_operation_definition) {
39
- operation_type.as(:operation_type) >> space? >>
40
- name.as(:name) >> space? >>
41
- operation_variable_definitions.maybe.as(:optional_variables).as(:variables) >> space? >>
42
- directives.maybe.as(:optional_directives).as(:directives) >> space? >>
43
- selections.as(:selections)
44
- }
45
- rule(:operation_type) { (str("query") | str("mutation")) }
46
- rule(:operation_variable_definitions) { str("(") >> space? >> (operation_variable_definition >> separator?).repeat(1) >> space? >> str(")") }
47
- rule(:operation_variable_definition) {
48
- value_variable.as(:variable_name) >> space? >>
49
- str(":") >> space? >>
50
- type.as(:variable_type) >> space? >>
51
- (str("=") >> space? >> value.as(:variable_default_value)).maybe.as(:variable_optional_default_value)}
52
-
53
- rule(:selection) { (inline_fragment | fragment_spread | field) >> space? >> separator? }
54
- rule(:selections) { str("{") >> space? >> selection.repeat(1) >> space? >> str("}")}
55
-
56
- rule(:field) {
57
- field_alias.maybe.as(:alias) >>
58
- name.as(:field_name) >>
59
- field_arguments.maybe.as(:optional_field_arguments).as(:field_arguments) >> space? >>
60
- directives.maybe.as(:optional_directives).as(:directives) >> space? >>
61
- selections.maybe.as(:optional_selections).as(:selections)
62
- }
63
-
64
- rule(:field_alias) { name.as(:alias_name) >> space? >> str(":") >> space? }
65
- rule(:field_arguments) { str("(") >> field_argument.repeat(1) >> str(")") }
66
- rule(:field_argument) { name.as(:field_argument_name) >> str(":") >> space? >> value.as(:field_argument_value) >> separator? }
67
-
68
- rule(:directives) { (directive >> separator?).repeat(1) }
69
- rule(:directive) {
70
- str("@") >> name.as(:directive_name) >>
71
- directive_arguments.maybe.as(:optional_directive_arguments).as(:directive_arguments)
72
- }
73
- rule(:directive_arguments) { str("(") >> directive_argument.repeat(1) >> str(")") }
74
- rule(:directive_argument) { name.as(:directive_argument_name) >> str(":") >> space? >> value.as(:directive_argument_value) >> separator? }
75
-
76
- rule(:type) { (non_null_type | list_type | type_name)}
77
- rule(:list_type) { str("[") >> type.as(:list_type) >> str("]")}
78
- rule(:non_null_type) { (list_type | type_name).as(:non_null_type) >> str("!") }
79
- rule(:type_name) { name.as(:type_name) }
80
-
81
- rule(:value) {(
82
- value_input_object |
83
- value_float |
84
- value_int |
85
- value_string |
86
- value_boolean |
87
- value_array |
88
- value_variable |
89
- value_enum
90
- )}
91
- rule(:value_sign?) { match('[\-\+]').maybe }
92
- rule(:value_array) { (str("[") >> (value >> separator?).repeat(0) >> str("]")).as(:array) }
93
- rule(:value_boolean) { (str("true") | str("false")).as(:boolean) }
94
- rule(:value_float) { (value_sign? >> match('\d').repeat(1) >> str(".") >> match('\d').repeat(1) >> (match("[eE]") >> value_sign? >> match('\d').repeat(1)).maybe).as(:float) }
95
- rule(:value_input_object) { str("{") >> value_input_object_pair.repeat(1).as(:input_object) >> str("}") }
96
- rule(:value_input_object_pair) { space? >> name.as(:input_object_name) >> space? >> str(":") >> space? >> value.as(:input_object_value) >> separator? }
97
- rule(:value_int) { (value_sign? >> match('\d').repeat(1)).as(:int) }
98
- # TODO: support unicode, escaped chars (match the spec)
99
- rule(:value_string) { str('"') >> match('[^\"]').repeat(1).as(:string) >> str('"')}
100
- rule(:value_enum) { name.as(:enum) }
101
- rule(:value_variable) { str("$") >> name.as(:variable) }
102
-
103
- rule(:separator?) { (space? >> str(",") >> space?).maybe }
104
- rule(:name) { match('[_A-Za-z]') >> match('[_0-9A-Za-z]').repeat(0) }
105
- rule(:comment) { str("#") >> match('[^\r\n]').repeat(0) }
106
- rule(:space) { (match('[\s\n]+') | comment).repeat(1) }
107
- rule(:space?) { space.maybe }
108
- end
@@ -1,87 +0,0 @@
1
- # {Transform} is a [parslet](http://kschiess.github.io/parslet/) transform for for turning the AST into objects in {GraphQL::Nodes} objects.
2
- class GraphQL::Transform < Parslet::Transform
3
- # Get syntax classes by shallow name:
4
- include GraphQL::Nodes
5
-
6
- def self.optional_sequence(name)
7
- rule(name => simple(:val)) { [] }
8
- rule(name => sequence(:val)) { val }
9
- end
10
-
11
- # Document
12
- rule(document_parts: sequence(:p)) { Document.new(parts: p, line: p.first.line, col: p.first.col)}
13
-
14
- # Fragment Definition
15
- rule(
16
- fragment_keyword: simple(:kw),
17
- fragment_name: simple(:name),
18
- type_condition: simple(:type),
19
- directives: sequence(:directives),
20
- selections: sequence(:selections)
21
- ) {FragmentDefinition.new(name: name.to_s, type: type.to_s, directives: directives, selections: selections, position_source: kw)}
22
-
23
- rule(
24
- fragment_spread_keyword: simple(:kw),
25
- fragment_spread_name: simple(:n),
26
- directives: sequence(:d)
27
- ) { FragmentSpread.new(name: n.to_s, directives: d, position_source: kw)}
28
-
29
- rule(
30
- fragment_spread_keyword: simple(:kw),
31
- inline_fragment_type: simple(:n),
32
- directives: sequence(:d),
33
- selections: sequence(:s),
34
- ) { InlineFragment.new(type: n.to_s, directives: d, selections: s, position_source: kw)}
35
-
36
- # Operation Definition
37
- rule(
38
- operation_type: simple(:ot),
39
- name: simple(:n),
40
- variables: sequence(:v),
41
- directives: sequence(:d),
42
- selections: sequence(:s),
43
- ) { OperationDefinition.new(operation_type: ot.to_s, name: n.to_s, variables: v, directives: d, selections: s, position_source: ot) }
44
- optional_sequence(:optional_variables)
45
- rule(variable_name: simple(:n), variable_type: simple(:t), variable_optional_default_value: simple(:v)) { Variable.new(name: n.name, type: t, default_value: v, line: n.line, col: n.col)}
46
- rule(variable_name: simple(:n), variable_type: simple(:t), variable_optional_default_value: sequence(:v)) { Variable.new(name: n.name, type: t, default_value: v, line: n.line, col: n.col)}
47
- rule(variable_default_value: simple(:v) ) { v }
48
- rule(variable_default_value: sequence(:v) ) { v }
49
- # Query short-hand
50
- rule(unnamed_selections: sequence(:s)) { OperationDefinition.new(selections: s, operation_type: "query", name: nil, variables: [], directives: [], line: s.first.line, col: s.first.col)}
51
-
52
- # Field
53
- rule(
54
- alias: simple(:a),
55
- field_name: simple(:name),
56
- field_arguments: sequence(:args),
57
- directives: sequence(:dir),
58
- selections: sequence(:sel)
59
- ) { 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? }) }
60
-
61
- rule(alias_name: simple(:a)) { a }
62
- optional_sequence(:optional_field_arguments)
63
- rule(field_argument_name: simple(:n), field_argument_value: simple(:v)) { Argument.new(name: n.to_s, value: v, position_source: n)}
64
- optional_sequence(:optional_selections)
65
- optional_sequence(:optional_directives)
66
-
67
- # Directive
68
- rule(directive_name: simple(:name), directive_arguments: sequence(:args)) { Directive.new(name: name.to_s, arguments: args, position_source: name ) }
69
- rule(directive_argument_name: simple(:n), directive_argument_value: simple(:v)) { Argument.new(name: n.to_s, value: v, position_source: n)}
70
- optional_sequence(:optional_directive_arguments)
71
-
72
- # Type Defs
73
- rule(type_name: simple(:n)) { TypeName.new(name: n.to_s, position_source: n) }
74
- rule(list_type: simple(:t)) { ListType.new(of_type: t, line: t.line, col: t.col)}
75
- rule(non_null_type: simple(:t)) { NonNullType.new(of_type: t, line: t.line, col: t.col)}
76
-
77
- # Values
78
- rule(array: sequence(:v)) { v }
79
- rule(boolean: simple(:v)) { v == "true" ? true : false }
80
- rule(input_object: sequence(:v)) { InputObject.new(pairs: v, line: v.first.line, col: v.first.col) }
81
- rule(input_object_name: simple(:n), input_object_value: simple(:v)) { Argument.new(name: n.to_s, value: v, position_source: n)}
82
- rule(int: simple(:v)) { v.to_i }
83
- rule(float: simple(:v)) { v.to_f }
84
- rule(string: simple(:v)) { v.to_s }
85
- rule(variable: simple(:v)) { VariableIdentifier.new(name: v.to_s, position_source: v) }
86
- rule(enum: simple(:v)) { Enum.new(name: v.to_s, position_source: v)}
87
- end
@@ -1,5 +0,0 @@
1
- class GraphQL::ScalarType < GraphQL::ObjectType
2
- def kind
3
- GraphQL::TypeKinds::SCALAR
4
- end
5
- end
@@ -1,32 +0,0 @@
1
- class GraphQL::Enum
2
- include GraphQL::NonNullWithBang
3
- extend GraphQL::Definable
4
- attr_definable :name, :description
5
- attr_reader :values
6
- def initialize
7
- @values = {}
8
- yield(self, GraphQL::TypeDefiner.instance, GraphQL::FieldDefiner.instance, GraphQL::ArgumentDefiner.instance)
9
- end
10
-
11
- def value(name, description=nil, deprecation_reason: nil, value: name)
12
- @values[name] = EnumValue.new(name: name, description: description, deprecation_reason: deprecation_reason, value: value)
13
- end
14
-
15
- def kind
16
- GraphQL::TypeKinds::ENUM
17
- end
18
-
19
- def coerce(value_name)
20
- @values[value_name].value
21
- end
22
-
23
- class EnumValue
24
- attr_reader :name, :description, :deprecation_reason, :value
25
- def initialize(name:, description:, deprecation_reason:, value:)
26
- @name = name
27
- @description = description
28
- @deprecation_reason = deprecation_reason
29
- @value = value
30
- end
31
- end
32
- end
@@ -1,14 +0,0 @@
1
- class GraphQL::InputObjectType < GraphQL::ObjectType
2
- attr_definable :input_fields
3
-
4
- def input_fields(new_fields=nil)
5
- if !new_fields.nil?
6
- @new_fields = GraphQL::StringNamedHash.new(new_fields).to_h
7
- end
8
- @new_fields
9
- end
10
-
11
- def kind
12
- GraphQL::TypeKinds::INPUT_OBJECT
13
- end
14
- end
@@ -1,14 +0,0 @@
1
- class GraphQL::Interface < GraphQL::ObjectType
2
- def kind
3
- GraphQL::TypeKinds::INTERFACE
4
- end
5
-
6
- def possible_types
7
- @possible_types ||= []
8
- end
9
-
10
- # Might have to override this in your own interface
11
- def resolve_type(object)
12
- @possible_types.find {|t| t.name == object.class.name }
13
- end
14
- end
@@ -1,66 +0,0 @@
1
- class GraphQL::ObjectType
2
- extend GraphQL::Definable
3
- attr_definable :name, :description, :interfaces, :fields
4
- include GraphQL::NonNullWithBang
5
-
6
- def initialize(&block)
7
- self.fields = []
8
- self.interfaces = []
9
- yield(self, GraphQL::TypeDefiner.instance, GraphQL::FieldDefiner.instance, GraphQL::ArgumentDefiner.instance)
10
- end
11
-
12
- def fields(new_fields=nil)
13
- if !new_fields.nil?
14
- self.fields = new_fields
15
- end
16
- @fields
17
- end
18
-
19
- def fields=(new_fields)
20
- stringified_fields = GraphQL::StringNamedHash.new(new_fields).to_h
21
- # TODO: should this field be exposed during introspection? https://github.com/graphql/graphql-js/issues/73
22
- stringified_fields["__typename"] = GraphQL::Introspection::TypenameField.create(self)
23
- @fields = stringified_fields
24
- end
25
-
26
- def interfaces(new_interfaces=nil)
27
- if !new_interfaces.nil?
28
- # if you define interfaces twice, you're gonna have a bad time :(
29
- # (because it gets registered with that interface, then overriden)
30
- @interfaces = new_interfaces
31
- new_interfaces.each {|i| i.possible_types << self }
32
- end
33
- @interfaces
34
- end
35
-
36
- def kind
37
- GraphQL::TypeKinds::OBJECT
38
- end
39
-
40
- def to_s
41
- Printer.instance.print(self)
42
- end
43
-
44
- alias :inspect :to_s
45
-
46
- def ==(other)
47
- if other.is_a?(GraphQL::ObjectType)
48
- self.to_s == other.to_s
49
- else
50
- super
51
- end
52
- end
53
-
54
- class Printer
55
- include Singleton
56
- def print(type)
57
- if type.kind.non_null?
58
- "#{print(type.of_type)}!"
59
- elsif type.kind.list?
60
- "[#{print(type.of_type)}]"
61
- else
62
- type.name
63
- end
64
- end
65
- end
66
- end