graphql 0.2.0 → 0.3.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/{types → definition_helpers}/argument_definer.rb +0 -0
- data/lib/graph_ql/definition_helpers/definable.rb +18 -0
- data/lib/graph_ql/{types → definition_helpers}/field_definer.rb +0 -0
- data/lib/graph_ql/definition_helpers/forwardable.rb +10 -0
- data/lib/graph_ql/definition_helpers/non_null_with_bang.rb +9 -0
- data/lib/graph_ql/definition_helpers/string_named_hash.rb +12 -0
- data/lib/graph_ql/{types → definition_helpers}/type_definer.rb +1 -0
- data/lib/graph_ql/directive.rb +9 -5
- data/lib/graph_ql/directives/directive_chain.rb +1 -1
- data/lib/graph_ql/field.rb +1 -5
- data/lib/graph_ql/parser/transform.rb +1 -3
- data/lib/graph_ql/query.rb +14 -3
- data/lib/graph_ql/query/arguments.rb +6 -5
- data/lib/graph_ql/query/field_resolution_strategy.rb +3 -3
- data/lib/graph_ql/{types → scalars}/boolean_type.rb +0 -0
- data/lib/graph_ql/{types → scalars}/float_type.rb +1 -1
- data/lib/graph_ql/scalars/id_type.rb +6 -0
- data/lib/graph_ql/{types → scalars}/int_type.rb +0 -0
- data/lib/graph_ql/{types → scalars}/scalar_type.rb +0 -4
- data/lib/graph_ql/{types → scalars}/string_type.rb +0 -0
- data/lib/graph_ql/static_validation.rb +7 -10
- data/lib/graph_ql/static_validation/all_rules.rb +23 -0
- data/lib/graph_ql/static_validation/literal_validator.rb +0 -3
- data/lib/graph_ql/static_validation/{argument_literals_are_compatible.rb → rules/argument_literals_are_compatible.rb} +0 -0
- data/lib/graph_ql/static_validation/{arguments_are_defined.rb → rules/arguments_are_defined.rb} +5 -0
- data/lib/graph_ql/static_validation/{directives_are_defined.rb → rules/directives_are_defined.rb} +0 -0
- data/lib/graph_ql/static_validation/{fields_are_defined_on_type.rb → rules/fields_are_defined_on_type.rb} +0 -0
- data/lib/graph_ql/static_validation/{fields_have_appropriate_selections.rb → rules/fields_have_appropriate_selections.rb} +0 -0
- data/lib/graph_ql/static_validation/{fields_will_merge.rb → rules/fields_will_merge.rb} +13 -5
- data/lib/graph_ql/static_validation/rules/fragment_spreads_are_possible.rb +50 -0
- data/lib/graph_ql/static_validation/{fragment_types_exist.rb → rules/fragment_types_exist.rb} +0 -0
- data/lib/graph_ql/static_validation/rules/fragments_are_finite.rb +23 -0
- data/lib/graph_ql/static_validation/rules/fragments_are_on_composite_types.rb +27 -0
- data/lib/graph_ql/static_validation/{fragments_are_used.rb → rules/fragments_are_used.rb} +0 -0
- data/lib/graph_ql/static_validation/{required_arguments_are_present.rb → rules/required_arguments_are_present.rb} +0 -0
- data/lib/graph_ql/static_validation/rules/variable_default_values_are_correctly_typed.rb +24 -0
- data/lib/graph_ql/static_validation/rules/variable_usages_are_allowed.rb +47 -0
- data/lib/graph_ql/static_validation/rules/variables_are_input_types.rb +27 -0
- data/lib/graph_ql/static_validation/rules/variables_are_used_and_defined.rb +31 -0
- data/lib/graph_ql/static_validation/type_stack.rb +13 -1
- data/lib/graph_ql/static_validation/validator.rb +14 -18
- data/lib/graph_ql/type_kinds.rb +8 -4
- data/lib/graph_ql/{enum.rb → types/enum.rb} +7 -6
- data/lib/graph_ql/types/input_object_type.rb +3 -10
- data/lib/graph_ql/{interface.rb → types/interface.rb} +0 -4
- data/lib/graph_ql/types/list_type.rb +0 -4
- data/lib/graph_ql/types/non_null_type.rb +0 -4
- data/lib/graph_ql/types/object_type.rb +28 -13
- data/lib/graph_ql/{union.rb → types/union.rb} +0 -4
- data/lib/graph_ql/version.rb +1 -1
- data/lib/graphql.rb +9 -40
- data/readme.md +26 -20
- data/spec/graph_ql/directive_spec.rb +4 -4
- data/spec/graph_ql/introspection/directive_type_spec.rb +2 -2
- data/spec/graph_ql/introspection/schema_type_spec.rb +3 -2
- data/spec/graph_ql/introspection/type_type_spec.rb +7 -7
- data/spec/graph_ql/parser/parser_spec.rb +6 -2
- data/spec/graph_ql/query_spec.rb +26 -8
- data/spec/graph_ql/scalars/id_type_spec.rb +24 -0
- data/spec/graph_ql/schema/type_reducer_spec.rb +1 -0
- data/spec/graph_ql/schema/type_validator_spec.rb +1 -1
- data/spec/graph_ql/static_validation/{argument_literals_are_compatible_spec.rb → rules/argument_literals_are_compatible_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{arguments_are_defined_spec.rb → rules/arguments_are_defined_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{directives_are_defined_spec.rb → rules/directives_are_defined_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{fields_are_defined_on_type_spec.rb → rules/fields_are_defined_on_type_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{fields_have_appropriate_selections_spec.rb → rules/fields_have_appropriate_selections_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{fields_will_merge_spec.rb → rules/fields_will_merge_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/rules/fragment_spreads_are_possible_spec.rb +46 -0
- data/spec/graph_ql/static_validation/{fragment_types_exist_spec.rb → rules/fragment_types_exist_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/rules/fragments_are_finite_spec.rb +43 -0
- data/spec/graph_ql/static_validation/rules/fragments_are_on_composite_types_spec.rb +48 -0
- data/spec/graph_ql/static_validation/{fragments_are_used_spec.rb → rules/fragments_are_used_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{required_arguments_are_present_spec.rb → rules/required_arguments_are_present_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +43 -0
- data/spec/graph_ql/static_validation/rules/variable_usages_are_allowed_spec.rb +45 -0
- data/spec/graph_ql/static_validation/rules/variables_are_input_types_spec.rb +36 -0
- data/spec/graph_ql/static_validation/rules/variables_are_used_and_defined_spec.rb +44 -0
- data/spec/graph_ql/static_validation/type_stack_spec.rb +2 -2
- data/spec/graph_ql/static_validation/validator_spec.rb +44 -5
- data/spec/graph_ql/types/enum_spec.rb +10 -0
- data/spec/graph_ql/{interface_spec.rb → types/interface_spec.rb} +1 -1
- data/spec/graph_ql/types/object_type_spec.rb +13 -0
- data/spec/graph_ql/{union_spec.rb → types/union_spec.rb} +0 -0
- data/spec/support/dummy_app.rb +7 -6
- data/spec/support/dummy_data.rb +3 -3
- metadata +74 -46
- data/lib/graph_ql/types/non_null_with_bang.rb +0 -5
- data/spec/graph_ql/enum_spec.rb +0 -5
data/lib/graph_ql/static_validation/{fragment_types_exist.rb → rules/fragment_types_exist.rb}
RENAMED
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class GraphQL::StaticValidation::FragmentsAreFinite
|
2
|
+
include GraphQL::StaticValidation::Message::MessageHelper
|
3
|
+
|
4
|
+
def validate(context)
|
5
|
+
context.visitor[GraphQL::Nodes::FragmentDefinition] << -> (node, parent) {
|
6
|
+
if has_nested_spread(node, [], context)
|
7
|
+
context.errors << message("Fragment #{node.name} contains an infinite loop", node)
|
8
|
+
end
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def has_nested_spread(fragment_def, parent_fragment_names, context)
|
15
|
+
nested_spreads = fragment_def.selections
|
16
|
+
.select {|f| f.is_a?(GraphQL::Nodes::FragmentSpread)}
|
17
|
+
|
18
|
+
nested_spreads.any? do |spread|
|
19
|
+
nested_def = context.fragments[spread.name]
|
20
|
+
parent_fragment_names.include?(spread.name) || has_nested_spread(nested_def, parent_fragment_names + [fragment_def.name], context)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class GraphQL::StaticValidation::FragmentsAreOnCompositeTypes
|
2
|
+
include GraphQL::StaticValidation::Message::MessageHelper
|
3
|
+
|
4
|
+
HAS_TYPE_CONDITION = [
|
5
|
+
GraphQL::Nodes::FragmentDefinition,
|
6
|
+
GraphQL::Nodes::InlineFragment,
|
7
|
+
]
|
8
|
+
|
9
|
+
def validate(context)
|
10
|
+
HAS_TYPE_CONDITION.each do |node_class|
|
11
|
+
context.visitor[node_class] << -> (node, parent) {
|
12
|
+
validate_type_is_composite(node, context)
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def validate_type_is_composite(node, context)
|
20
|
+
type_name = node.type
|
21
|
+
type_def = context.schema.types[type_name]
|
22
|
+
if type_def.nil? || !type_def.kind.composite?
|
23
|
+
context.errors << message("Invalid fragment on type #{type_name} (must be Union, Interface or Object)", node)
|
24
|
+
GraphQL::Visitor::SKIP
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped
|
2
|
+
include GraphQL::StaticValidation::Message::MessageHelper
|
3
|
+
|
4
|
+
def validate(context)
|
5
|
+
literal_validator = GraphQL::StaticValidation::LiteralValidator.new
|
6
|
+
context.visitor[GraphQL::Nodes::Variable] << -> (node, parent) {
|
7
|
+
if !node.default_value.nil?
|
8
|
+
validate_default_value(node, literal_validator, context)
|
9
|
+
end
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate_default_value(node, literal_validator, context)
|
14
|
+
value = node.default_value
|
15
|
+
if node.type.is_a?(GraphQL::Nodes::NonNullType)
|
16
|
+
context.errors << message("Non-null variable $#{node.name} can't have a default value", node)
|
17
|
+
else
|
18
|
+
type = context.schema.types[node.type.name]
|
19
|
+
if !literal_validator.validate(value, type)
|
20
|
+
context.errors << message("Default value for $#{node.name} doesn't match type #{node.type.name}", node)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class GraphQL::StaticValidation::VariableUsagesAreAllowed
|
2
|
+
include GraphQL::StaticValidation::Message::MessageHelper
|
3
|
+
|
4
|
+
def validate(context)
|
5
|
+
# holds { name => ast_node } pairs
|
6
|
+
declared_variables = {}
|
7
|
+
|
8
|
+
context.visitor[GraphQL::Nodes::OperationDefinition] << -> (node, parent) {
|
9
|
+
declared_variables = node.variables.each_with_object({}) { |var, memo| memo[var.name] = var }
|
10
|
+
}
|
11
|
+
|
12
|
+
context.visitor[GraphQL::Nodes::Argument] << -> (node, parent) {
|
13
|
+
return if !node.value.is_a?(GraphQL::Nodes::VariableIdentifier)
|
14
|
+
if parent.is_a?(GraphQL::Nodes::Field)
|
15
|
+
arguments = context.field_definition.arguments
|
16
|
+
elsif parent.is_a?(GraphQL::Nodes::Directive)
|
17
|
+
arguments = context.directive_definition.arguments
|
18
|
+
end
|
19
|
+
var_defn_ast = declared_variables[node.value.name]
|
20
|
+
validate_usage(arguments, node, var_defn_ast, context)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def validate_usage(arguments, arg_node, ast_var, context)
|
27
|
+
var_type = to_query_type(ast_var.type, context.schema.types)
|
28
|
+
if !ast_var.default_value.nil?
|
29
|
+
var_type = GraphQL::NonNullType.new(of_type: var_type)
|
30
|
+
end
|
31
|
+
|
32
|
+
arg_defn = arguments[arg_node.name]
|
33
|
+
if var_type != arg_defn.type
|
34
|
+
context.errors << message("Type mismatch on variable $#{ast_var.name} and argument #{arg_node.name} (#{var_type.to_s} / #{arg_defn.type.to_s})", arg_node)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_query_type(ast_type, types)
|
39
|
+
if ast_type.is_a?(GraphQL::Nodes::NonNullType)
|
40
|
+
GraphQL::NonNullType.new(of_type: to_query_type(ast_type.of_type, types))
|
41
|
+
elsif ast_type.is_a?(GraphQL::Nodes::ListType)
|
42
|
+
GraphQL::ListType.new(of_type: to_query_type(ast_type.of_type, types))
|
43
|
+
else
|
44
|
+
types[ast_type.name]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class GraphQL::StaticValidation::VariablesAreInputTypes
|
2
|
+
include GraphQL::StaticValidation::Message::MessageHelper
|
3
|
+
|
4
|
+
def validate(context)
|
5
|
+
context.visitor[GraphQL::Nodes::Variable] << -> (node, parent) {
|
6
|
+
validate_is_input_type(node, context)
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def validate_is_input_type(node, context)
|
13
|
+
type_name = get_type_name(node.type)
|
14
|
+
type = context.schema.types[type_name]
|
15
|
+
if !type.kind.input?
|
16
|
+
context.errors << message("#{type.name} isn't a valid input type (on $#{node.name})", node)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_type_name(ast_type)
|
21
|
+
if ast_type.respond_to?(:of_type)
|
22
|
+
get_type_name(ast_type.of_type)
|
23
|
+
else
|
24
|
+
ast_type.name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class GraphQL::StaticValidation::VariablesAreUsedAndDefined
|
2
|
+
include GraphQL::StaticValidation::Message::MessageHelper
|
3
|
+
|
4
|
+
def validate(context)
|
5
|
+
# holds { name => used? } pairs
|
6
|
+
declared_variables = {}
|
7
|
+
|
8
|
+
context.visitor[GraphQL::Nodes::OperationDefinition] << -> (node, parent) {
|
9
|
+
declared_variables = node.variables.each_with_object({}) { |var, memo| memo[var.name] = false }
|
10
|
+
}
|
11
|
+
|
12
|
+
context.visitor[GraphQL::Nodes::VariableIdentifier] << -> (node, parent) {
|
13
|
+
if declared_variables.key?(node.name)
|
14
|
+
declared_variables[node.name] = true
|
15
|
+
else
|
16
|
+
context.errors << message("Variable $#{node.name} is used but not declared", node)
|
17
|
+
GraphQL::Visitor::SKIP
|
18
|
+
end
|
19
|
+
}
|
20
|
+
|
21
|
+
context.visitor[GraphQL::Nodes::OperationDefinition].leave << -> (node, parent) {
|
22
|
+
unused_variables = declared_variables
|
23
|
+
.select { |name, used| !used }
|
24
|
+
.keys
|
25
|
+
|
26
|
+
unused_variables.each do |var_name|
|
27
|
+
context.errors << message("Variable $#{var_name} is declared but not used", node)
|
28
|
+
end
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
@@ -7,11 +7,12 @@ class GraphQL::StaticValidation::TypeStack
|
|
7
7
|
GraphQL::Nodes::FragmentDefinition,
|
8
8
|
]
|
9
9
|
|
10
|
-
attr_reader :schema, :object_types, :field_definitions
|
10
|
+
attr_reader :schema, :object_types, :field_definitions, :directive_definitions
|
11
11
|
def initialize(schema, visitor)
|
12
12
|
@schema = schema
|
13
13
|
@object_types = []
|
14
14
|
@field_definitions = []
|
15
|
+
@directive_definitions = []
|
15
16
|
visitor.enter << -> (node, parent) { PUSH_STRATEGIES[node.class].push(self, node) }
|
16
17
|
visitor.leave << -> (node, parent) { PUSH_STRATEGIES[node.class].pop(self, node) }
|
17
18
|
end
|
@@ -80,6 +81,17 @@ class GraphQL::StaticValidation::TypeStack
|
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
84
|
+
class DirectiveStrategy
|
85
|
+
def push(stack, node)
|
86
|
+
directive_defn = stack.schema.directives[node.name]
|
87
|
+
stack.directive_definitions.push(directive_defn)
|
88
|
+
end
|
89
|
+
|
90
|
+
def pop(stack, node)
|
91
|
+
stack.directive_definitions.pop
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
83
95
|
class NullStrategy
|
84
96
|
def push(stack, node); end
|
85
97
|
def pop(stack, node); end
|
@@ -1,25 +1,16 @@
|
|
1
|
+
# Initialized with a {GraphQL::Schema}, then it can validate {GraphQL::Nodes::Documents}s based on that schema.
|
2
|
+
#
|
3
|
+
# By default, it's used by {GraphQL::Query}
|
1
4
|
class GraphQL::StaticValidation::Validator
|
2
|
-
|
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)
|
5
|
+
def initialize(schema:, rules: GraphQL::StaticValidation::ALL_RULES)
|
15
6
|
@schema = schema
|
16
|
-
@
|
7
|
+
@rules = rules
|
17
8
|
end
|
18
9
|
|
19
10
|
def validate(document)
|
20
11
|
context = Context.new(@schema, document)
|
21
|
-
@
|
22
|
-
|
12
|
+
@rules.each do |rules|
|
13
|
+
rules.new.validate(context)
|
23
14
|
end
|
24
15
|
context.visitor.visit(document)
|
25
16
|
context.errors.map(&:to_h)
|
@@ -30,10 +21,11 @@ class GraphQL::StaticValidation::Validator
|
|
30
21
|
def initialize(schema, document)
|
31
22
|
@schema = schema
|
32
23
|
@document = document
|
33
|
-
@fragments = {}
|
24
|
+
@fragments = document.parts.each_with_object({}) do |part, memo|
|
25
|
+
part.is_a?(GraphQL::Nodes::FragmentDefinition) && memo[part.name] = part
|
26
|
+
end
|
34
27
|
@errors = []
|
35
28
|
@visitor = GraphQL::Visitor.new
|
36
|
-
@visitor[GraphQL::Nodes::FragmentDefinition] << -> (node, parent) { @fragments[node.name] = node }
|
37
29
|
@type_stack = GraphQL::StaticValidation::TypeStack.new(schema, visitor)
|
38
30
|
end
|
39
31
|
|
@@ -44,5 +36,9 @@ class GraphQL::StaticValidation::Validator
|
|
44
36
|
def field_definition
|
45
37
|
@type_stack.field_definitions.last
|
46
38
|
end
|
39
|
+
|
40
|
+
def directive_definition
|
41
|
+
@type_stack.directive_definitions.last
|
42
|
+
end
|
47
43
|
end
|
48
44
|
end
|
data/lib/graph_ql/type_kinds.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
module GraphQL::TypeKinds
|
2
2
|
class TypeKind
|
3
3
|
attr_reader :name
|
4
|
-
def initialize(name, resolves: false, fields: false, wraps: false)
|
4
|
+
def initialize(name, resolves: false, fields: false, wraps: false, input: false)
|
5
5
|
@name = name
|
6
6
|
@resolves = resolves
|
7
7
|
@fields = fields
|
8
8
|
@wraps = wraps
|
9
|
+
@input = input
|
10
|
+
@composite = fields? || resolves?
|
9
11
|
end
|
10
12
|
|
11
13
|
def resolves?; @resolves; end
|
12
14
|
def fields?; @fields; end
|
13
15
|
def wraps?; @wraps; end
|
16
|
+
def input?; @input; end
|
14
17
|
def to_s; @name; end
|
18
|
+
def composite?; @composite; end
|
15
19
|
|
16
20
|
def resolve(type, value)
|
17
21
|
if resolves?
|
@@ -32,12 +36,12 @@ module GraphQL::TypeKinds
|
|
32
36
|
end
|
33
37
|
|
34
38
|
TYPE_KINDS = [
|
35
|
-
SCALAR = TypeKind.new("SCALAR"),
|
39
|
+
SCALAR = TypeKind.new("SCALAR", input: true),
|
36
40
|
OBJECT = TypeKind.new("OBJECT", fields: true),
|
37
41
|
INTERFACE = TypeKind.new("INTERFACE", resolves: true, fields: true),
|
38
42
|
UNION = TypeKind.new("UNION", resolves: true),
|
39
|
-
ENUM = TypeKind.new("ENUM"),
|
40
|
-
INPUT_OBJECT = TypeKind.new("INPUT_OBJECT"),
|
43
|
+
ENUM = TypeKind.new("ENUM", input: true),
|
44
|
+
INPUT_OBJECT = TypeKind.new("INPUT_OBJECT", input: true),
|
41
45
|
LIST = TypeKind.new("LIST", wraps: true),
|
42
46
|
NON_NULL = TypeKind.new("NON_NULL", wraps: true),
|
43
47
|
]
|
@@ -8,24 +8,25 @@ class GraphQL::Enum
|
|
8
8
|
yield(self, GraphQL::TypeDefiner.instance, GraphQL::FieldDefiner.instance, GraphQL::ArgumentDefiner.instance)
|
9
9
|
end
|
10
10
|
|
11
|
-
def value(name, description=nil, deprecation_reason: nil)
|
12
|
-
@values[name] = EnumValue.new(name: name, description: description, deprecation_reason: deprecation_reason)
|
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
13
|
end
|
14
14
|
|
15
15
|
def kind
|
16
16
|
GraphQL::TypeKinds::ENUM
|
17
17
|
end
|
18
18
|
|
19
|
-
def coerce(
|
20
|
-
@values[value
|
19
|
+
def coerce(value_name)
|
20
|
+
@values[value_name].value
|
21
21
|
end
|
22
22
|
|
23
23
|
class EnumValue
|
24
|
-
attr_reader :name, :description, :deprecation_reason
|
25
|
-
def initialize(name:, description:, deprecation_reason:)
|
24
|
+
attr_reader :name, :description, :deprecation_reason, :value
|
25
|
+
def initialize(name:, description:, deprecation_reason:, value:)
|
26
26
|
@name = name
|
27
27
|
@description = description
|
28
28
|
@deprecation_reason = deprecation_reason
|
29
|
+
@value = value
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
@@ -2,20 +2,13 @@ class GraphQL::InputObjectType < GraphQL::ObjectType
|
|
2
2
|
attr_definable :input_fields
|
3
3
|
|
4
4
|
def input_fields(new_fields=nil)
|
5
|
-
if new_fields.nil?
|
6
|
-
@new_fields
|
7
|
-
else
|
8
|
-
@new_fields = new_fields
|
9
|
-
.reduce({}) {|memo, (k, v)| memo[k.to_s] = v; memo}
|
10
|
-
.each { |k, v| v.respond_to?("name=") && v.name = k}
|
5
|
+
if !new_fields.nil?
|
6
|
+
@new_fields = GraphQL::StringNamedHash.new(new_fields).to_h
|
11
7
|
end
|
8
|
+
@new_fields
|
12
9
|
end
|
13
10
|
|
14
11
|
def kind
|
15
12
|
GraphQL::TypeKinds::INPUT_OBJECT
|
16
13
|
end
|
17
|
-
|
18
|
-
def to_s
|
19
|
-
"<GraphQL::InputObjectType #{name}>"
|
20
|
-
end
|
21
14
|
end
|
@@ -10,31 +10,27 @@ class GraphQL::ObjectType
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def fields(new_fields=nil)
|
13
|
-
if new_fields
|
13
|
+
if !new_fields.nil?
|
14
14
|
self.fields = new_fields
|
15
|
-
else
|
16
|
-
@fields
|
17
15
|
end
|
16
|
+
@fields
|
18
17
|
end
|
19
18
|
|
20
19
|
def fields=(new_fields)
|
21
|
-
stringified_fields = new_fields
|
22
|
-
|
23
|
-
# Set the name from its context on this type:
|
24
|
-
stringified_fields.each {|k, v| v.respond_to?("name=") && v.name = k }
|
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
|
25
22
|
stringified_fields["__typename"] = GraphQL::Introspection::TypenameField.create(self)
|
26
23
|
@fields = stringified_fields
|
27
24
|
end
|
28
25
|
|
29
26
|
def interfaces(new_interfaces=nil)
|
30
|
-
if new_interfaces.nil?
|
31
|
-
@interfaces
|
32
|
-
else
|
27
|
+
if !new_interfaces.nil?
|
33
28
|
# if you define interfaces twice, you're gonna have a bad time :(
|
34
29
|
# (because it gets registered with that interface, then overriden)
|
35
30
|
@interfaces = new_interfaces
|
36
31
|
new_interfaces.each {|i| i.possible_types << self }
|
37
32
|
end
|
33
|
+
@interfaces
|
38
34
|
end
|
39
35
|
|
40
36
|
def kind
|
@@ -42,10 +38,29 @@ class GraphQL::ObjectType
|
|
42
38
|
end
|
43
39
|
|
44
40
|
def to_s
|
45
|
-
|
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
|
46
52
|
end
|
47
53
|
|
48
|
-
|
49
|
-
|
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
|
50
65
|
end
|
51
66
|
end
|