graphql 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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