graphql 1.0.0 → 1.1.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +10 -0
  3. data/lib/graphql/base_type.rb +8 -5
  4. data/lib/graphql/compatibility.rb +3 -0
  5. data/lib/graphql/compatibility/execution_specification.rb +414 -0
  6. data/lib/graphql/compatibility/query_parser_specification.rb +117 -0
  7. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +81 -0
  8. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +78 -0
  9. data/lib/graphql/compatibility/schema_parser_specification.rb +239 -0
  10. data/lib/graphql/define/instance_definable.rb +53 -21
  11. data/lib/graphql/directive.rb +1 -1
  12. data/lib/graphql/enum_type.rb +31 -8
  13. data/lib/graphql/execution/directive_checks.rb +0 -6
  14. data/lib/graphql/input_object_type.rb +6 -4
  15. data/lib/graphql/introspection/arguments_field.rb +3 -1
  16. data/lib/graphql/introspection/enum_values_field.rb +10 -5
  17. data/lib/graphql/introspection/fields_field.rb +1 -1
  18. data/lib/graphql/introspection/input_fields_field.rb +2 -2
  19. data/lib/graphql/introspection/interfaces_field.rb +7 -1
  20. data/lib/graphql/introspection/possible_types_field.rb +1 -1
  21. data/lib/graphql/introspection/schema_type.rb +1 -1
  22. data/lib/graphql/introspection/type_by_name_field.rb +4 -2
  23. data/lib/graphql/introspection/type_type.rb +7 -6
  24. data/lib/graphql/language/lexer.rl +0 -4
  25. data/lib/graphql/language/parser.rb +1 -1
  26. data/lib/graphql/language/parser.y +1 -1
  27. data/lib/graphql/list_type.rb +3 -4
  28. data/lib/graphql/non_null_type.rb +4 -8
  29. data/lib/graphql/object_type.rb +5 -3
  30. data/lib/graphql/query.rb +48 -12
  31. data/lib/graphql/query/context.rb +7 -1
  32. data/lib/graphql/query/serial_execution/execution_context.rb +8 -3
  33. data/lib/graphql/query/serial_execution/field_resolution.rb +8 -5
  34. data/lib/graphql/query/serial_execution/operation_resolution.rb +2 -2
  35. data/lib/graphql/query/serial_execution/selection_resolution.rb +4 -21
  36. data/lib/graphql/query/serial_execution/value_resolution.rb +59 -99
  37. data/lib/graphql/query/variables.rb +7 -2
  38. data/lib/graphql/scalar_type.rb +1 -1
  39. data/lib/graphql/schema.rb +49 -18
  40. data/lib/graphql/schema/build_from_definition.rb +248 -0
  41. data/lib/graphql/schema/instrumented_field_map.rb +23 -0
  42. data/lib/graphql/schema/loader.rb +4 -11
  43. data/lib/graphql/schema/possible_types.rb +4 -2
  44. data/lib/graphql/schema/printer.rb +1 -1
  45. data/lib/graphql/schema/type_expression.rb +4 -4
  46. data/lib/graphql/schema/type_map.rb +1 -1
  47. data/lib/graphql/schema/validation.rb +4 -0
  48. data/lib/graphql/schema/warden.rb +114 -0
  49. data/lib/graphql/static_validation/literal_validator.rb +10 -7
  50. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -3
  51. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
  52. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
  53. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -14
  54. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
  55. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  56. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -4
  57. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +2 -1
  58. data/lib/graphql/static_validation/validation_context.rb +7 -1
  59. data/lib/graphql/union_type.rb +6 -3
  60. data/lib/graphql/unresolved_type_error.rb +1 -2
  61. data/lib/graphql/version.rb +1 -1
  62. data/readme.md +1 -5
  63. data/spec/graphql/compatibility/execution_specification_spec.rb +3 -0
  64. data/spec/graphql/compatibility/query_parser_specification_spec.rb +5 -0
  65. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +5 -0
  66. data/spec/graphql/define/instance_definable_spec.rb +20 -0
  67. data/spec/graphql/directive_spec.rb +11 -0
  68. data/spec/graphql/enum_type_spec.rb +20 -1
  69. data/spec/graphql/input_object_type_spec.rb +9 -9
  70. data/spec/graphql/introspection/directive_type_spec.rb +4 -4
  71. data/spec/graphql/introspection/input_value_type_spec.rb +6 -6
  72. data/spec/graphql/introspection/type_type_spec.rb +28 -26
  73. data/spec/graphql/language/parser_spec.rb +27 -17
  74. data/spec/graphql/list_type_spec.rb +2 -2
  75. data/spec/graphql/query/variables_spec.rb +1 -0
  76. data/spec/graphql/scalar_type_spec.rb +3 -3
  77. data/spec/graphql/schema/build_from_definition_spec.rb +693 -0
  78. data/spec/graphql/schema/type_expression_spec.rb +3 -3
  79. data/spec/graphql/schema/validation_spec.rb +7 -3
  80. data/spec/graphql/schema/warden_spec.rb +510 -0
  81. data/spec/graphql/schema_spec.rb +129 -0
  82. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +1 -1
  83. data/spec/graphql/static_validation/type_stack_spec.rb +3 -3
  84. data/spec/spec_helper.rb +27 -1
  85. data/spec/support/dairy_app.rb +8 -5
  86. metadata +21 -3
  87. data/lib/graphql/language/parser_tests.rb +0 -809
@@ -41,7 +41,7 @@ module GraphQL
41
41
  self.coerce_result = proc
42
42
  end
43
43
 
44
- def validate_non_null_input(value)
44
+ def validate_non_null_input(value, warden)
45
45
  result = Query::InputValidationResult.new
46
46
  if coerce_non_null_input(value).nil?
47
47
  result.add_problem("Could not coerce value #{JSON.generate(value, quirks_mode: true)} to #{name}")
@@ -1,5 +1,6 @@
1
1
  require "graphql/schema/catchall_middleware"
2
2
  require "graphql/schema/invalid_type_error"
3
+ require "graphql/schema/instrumented_field_map"
3
4
  require "graphql/schema/middleware_chain"
4
5
  require "graphql/schema/possible_types"
5
6
  require "graphql/schema/rescue_middleware"
@@ -9,6 +10,8 @@ require "graphql/schema/type_expression"
9
10
  require "graphql/schema/type_map"
10
11
  require "graphql/schema/unique_within_type"
11
12
  require "graphql/schema/validation"
13
+ require "graphql/schema/warden"
14
+ require "graphql/schema/build_from_definition"
12
15
 
13
16
  module GraphQL
14
17
  # A GraphQL schema which may be queried with {GraphQL::Query}.
@@ -43,6 +46,8 @@ module GraphQL
43
46
  # end
44
47
  #
45
48
  class Schema
49
+ include BuildFromDefinition
50
+
46
51
  include GraphQL::Define::InstanceDefinable
47
52
  accepts_definitions \
48
53
  :query, :mutation, :subscription,
@@ -50,6 +55,8 @@ module GraphQL
50
55
  :max_depth, :max_complexity,
51
56
  :orphan_types, :resolve_type,
52
57
  :object_from_id, :id_from_object,
58
+ directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.name] = d; m }},
59
+ instrument: -> (schema, type, instrumenter) { schema.instrumenters[type] << instrumenter },
53
60
  query_analyzer: ->(schema, analyzer) { schema.query_analyzers << analyzer },
54
61
  middleware: ->(schema, middleware) { schema.middleware << middleware },
55
62
  rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block)}
@@ -58,13 +65,14 @@ module GraphQL
58
65
  :query, :mutation, :subscription,
59
66
  :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
60
67
  :max_depth, :max_complexity,
61
- :orphan_types,
62
- :query_analyzers, :middleware
68
+ :orphan_types, :directives,
69
+ :query_analyzers, :middleware, :instrumenters
63
70
 
71
+ BUILT_IN_TYPES = Hash[[INT_TYPE, STRING_TYPE, FLOAT_TYPE, BOOLEAN_TYPE, ID_TYPE].map{ |type| [type.name, type] }]
64
72
  DIRECTIVES = [GraphQL::Directive::IncludeDirective, GraphQL::Directive::SkipDirective, GraphQL::Directive::DeprecatedDirective]
65
73
  DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
66
74
 
67
- attr_reader :directives, :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
75
+ attr_reader :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
68
76
 
69
77
  # @!attribute [r] middleware
70
78
  # @return [Array<#call>] Middlewares suitable for MiddlewareChain, applied to fields during execution
@@ -83,6 +91,7 @@ module GraphQL
83
91
  @resolve_type_proc = nil
84
92
  @object_from_id_proc = nil
85
93
  @id_from_object_proc = nil
94
+ @instrumenters = Hash.new { |h, k| h[k] = [] }
86
95
  # Default to the built-in execution strategy:
87
96
  @query_execution_strategy = GraphQL::Query::SerialExecution
88
97
  @mutation_execution_strategy = GraphQL::Query::SerialExecution
@@ -101,21 +110,33 @@ module GraphQL
101
110
 
102
111
  def define(**kwargs, &block)
103
112
  super
104
- types
113
+ all_types = orphan_types + [query, mutation, subscription, GraphQL::Introspection::SchemaType]
114
+ @types = GraphQL::Schema::ReduceTypes.reduce(all_types.compact)
115
+
116
+ @instrumented_field_map = InstrumentedFieldMap.new(self)
117
+ field_instrumenters = @instrumenters[:field]
118
+ types.each do |type_name, type|
119
+ if type.kind.fields?
120
+ type.all_fields.each do |field_defn|
121
+
122
+ instrumented_field_defn = field_instrumenters.reduce(field_defn) do |defn, inst|
123
+ inst.instrument(type, defn)
124
+ end
125
+
126
+ @instrumented_field_map.set(type.name, field_defn.name, instrumented_field_defn)
127
+ end
128
+ end
129
+ end
105
130
  # Assert that all necessary configs are present:
106
131
  validation_error = Validation.validate(self)
107
132
  validation_error && raise(NotImplementedError, validation_error)
108
133
  nil
109
134
  end
110
135
 
136
+
137
+ # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
111
138
  # @return [GraphQL::Schema::TypeMap] `{ name => type }` pairs of types in this schema
112
- def types
113
- @types ||= begin
114
- ensure_defined
115
- all_types = orphan_types + [query, mutation, subscription, GraphQL::Introspection::SchemaType]
116
- GraphQL::Schema::ReduceTypes.reduce(all_types.compact)
117
- end
118
- end
139
+ attr_reader :types
119
140
 
120
141
  # Execute a query on itself.
121
142
  # See {Query#initialize} for arguments.
@@ -127,9 +148,11 @@ module GraphQL
127
148
 
128
149
  # Resolve field named `field_name` for type `parent_type`.
129
150
  # Handles dynamic fields `__typename`, `__type` and `__schema`, too
151
+ # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
152
+ # @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
130
153
  def get_field(parent_type, field_name)
131
154
  ensure_defined
132
- defined_field = parent_type.get_field(field_name)
155
+ defined_field = @instrumented_field_map.get(parent_type.name, field_name)
133
156
  if defined_field
134
157
  defined_field
135
158
  elsif field_name == "__typename"
@@ -137,7 +160,7 @@ module GraphQL
137
160
  elsif field_name == "__schema" && parent_type == query
138
161
  GraphQL::Introspection::SchemaField.create(self)
139
162
  elsif field_name == "__type" && parent_type == query
140
- GraphQL::Introspection::TypeByNameField.create(self.types)
163
+ GraphQL::Introspection::TypeByNameField.create(self)
141
164
  else
142
165
  nil
143
166
  end
@@ -145,16 +168,16 @@ module GraphQL
145
168
 
146
169
  def type_from_ast(ast_node)
147
170
  ensure_defined
148
- GraphQL::Schema::TypeExpression.build_type(self, ast_node)
171
+ GraphQL::Schema::TypeExpression.build_type(self.types, ast_node)
149
172
  end
150
173
 
151
- # TODO: when `resolve_type` is schema level, can this be removed?
174
+ # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
152
175
  # @param type_defn [GraphQL::InterfaceType, GraphQL::UnionType] the type whose members you want to retrieve
153
176
  # @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
154
177
  def possible_types(type_defn)
155
178
  ensure_defined
156
- @interface_possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
157
- @interface_possible_types.possible_types(type_defn)
179
+ @possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
180
+ @possible_types.possible_types(type_defn)
158
181
  end
159
182
 
160
183
  def root_type_for_operation(operation)
@@ -184,7 +207,8 @@ module GraphQL
184
207
  end
185
208
 
186
209
  # Determine the GraphQL type for a given object.
187
- # This is required for unions and interfaces (include Relay's node interface)
210
+ # This is required for unions and interfaces (including Relay's `Node` interface)
211
+ # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
188
212
  # @param object [Any] An application object which GraphQL is currently resolving on
189
213
  # @param ctx [GraphQL::Query::Context] The context for the current query
190
214
  # @return [GraphQL::ObjectType] The type for exposing `object` in GraphQL
@@ -250,6 +274,13 @@ module GraphQL
250
274
  @id_from_object_proc = new_proc
251
275
  end
252
276
 
277
+ # Create schema with the result of an introspection query.
278
+ # @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
279
+ # @return [GraphQL::Schema] the schema described by `input`
280
+ def self.from_introspection(introspection_result)
281
+ GraphQL::Schema::Loader.load(introspection_result)
282
+ end
283
+
253
284
  private
254
285
 
255
286
  # Lazily create a middleware and add it to the schema
@@ -0,0 +1,248 @@
1
+ module GraphQL
2
+ class Schema
3
+ module BuildFromDefinition
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ class InvalidDocumentError < Error; end;
9
+
10
+ module ClassMethods
11
+ # Create schema from an IDL schema.
12
+ # @param definition_string String A schema definition string
13
+ # @return [GraphQL::Schema] the schema described by `document`
14
+ def from_definition(definition_string)
15
+ document = GraphQL::parse(definition_string)
16
+ Builder.build(document)
17
+ end
18
+ end
19
+
20
+ module Builder
21
+ extend self
22
+
23
+ def build(document)
24
+ raise InvalidDocumentError.new('Must provide a document ast.') if !document || !document.is_a?(GraphQL::Language::Nodes::Document)
25
+
26
+ schema_definition = nil
27
+ types = {}
28
+ types.merge!(GraphQL::Schema::BUILT_IN_TYPES)
29
+ directives = {}
30
+ type_resolver = -> (type) { -> { resolve_type(types, type) } }
31
+
32
+ document.definitions.each do |definition|
33
+ case definition
34
+ when GraphQL::Language::Nodes::SchemaDefinition
35
+ raise InvalidDocumentError.new('Must provide only one schema definition.') if schema_definition
36
+ schema_definition = definition
37
+ when GraphQL::Language::Nodes::EnumTypeDefinition
38
+ types[definition.name] = build_enum_type(definition, type_resolver)
39
+ when GraphQL::Language::Nodes::ObjectTypeDefinition
40
+ types[definition.name] = build_object_type(definition, type_resolver)
41
+ when GraphQL::Language::Nodes::InterfaceTypeDefinition
42
+ types[definition.name] = build_interface_type(definition, type_resolver)
43
+ when GraphQL::Language::Nodes::UnionTypeDefinition
44
+ types[definition.name] = build_union_type(definition, type_resolver)
45
+ when GraphQL::Language::Nodes::ScalarTypeDefinition
46
+ types[definition.name] = build_scalar_type(definition, type_resolver)
47
+ when GraphQL::Language::Nodes::InputObjectTypeDefinition
48
+ types[definition.name] = build_input_object_type(definition, type_resolver)
49
+ when GraphQL::Language::Nodes::DirectiveDefinition
50
+ directives[definition.name] = build_directive(definition, type_resolver)
51
+ end
52
+ end
53
+
54
+ GraphQL::Schema::DIRECTIVES.each do |built_in_directive|
55
+ directives[built_in_directive.name] = built_in_directive unless directives[built_in_directive.name]
56
+ end
57
+
58
+ if schema_definition
59
+ if schema_definition.query
60
+ raise InvalidDocumentError.new("Specified query type \"#{schema_definition.query}\" not found in document.") unless types[schema_definition.query]
61
+ query_root_type = types[schema_definition.query]
62
+ end
63
+
64
+ if schema_definition.mutation
65
+ raise InvalidDocumentError.new("Specified mutation type \"#{schema_definition.mutation}\" not found in document.") unless types[schema_definition.mutation]
66
+ mutation_root_type = types[schema_definition.mutation]
67
+ end
68
+
69
+ if schema_definition.subscription
70
+ raise InvalidDocumentError.new("Specified subscription type \"#{schema_definition.subscription}\" not found in document.") unless types[schema_definition.subscription]
71
+ subscription_root_type = types[schema_definition.subscription]
72
+ end
73
+ else
74
+ query_root_type = types['Query']
75
+ mutation_root_type = types['Mutation']
76
+ subscription_root_type = types['Subscription']
77
+ end
78
+
79
+ raise InvalidDocumentError.new('Must provide schema definition with query type or a type named Query.') unless query_root_type
80
+
81
+ Schema.define do
82
+ query query_root_type
83
+ mutation mutation_root_type
84
+ subscription subscription_root_type
85
+ orphan_types types.values
86
+ resolve_type NullResolveType
87
+
88
+ directives directives.values
89
+ end
90
+ end
91
+
92
+ NullResolveType = -> (obj, ctx) {
93
+ raise(NotImplementedError, "Generated Schema cannot use Interface or Union types for execution.")
94
+ }
95
+
96
+ def build_enum_type(enum_type_definition, type_resolver)
97
+ GraphQL::EnumType.define(
98
+ name: enum_type_definition.name,
99
+ description: enum_type_definition.description,
100
+ values: enum_type_definition.values.map do |enum_value_definition|
101
+ EnumType::EnumValue.define(
102
+ name: enum_value_definition.name,
103
+ value: enum_value_definition.name,
104
+ deprecation_reason: build_deprecation_reason(enum_value_definition.directives),
105
+ description: enum_value_definition.description,
106
+ )
107
+ end
108
+ )
109
+ end
110
+
111
+ def build_deprecation_reason(directives)
112
+ deprecated_directive = directives.find{ |d| d.name == 'deprecated' }
113
+ return unless deprecated_directive
114
+
115
+ reason = deprecated_directive.arguments.find{ |a| a.name == 'reason' }
116
+ return GraphQL::Directive::DEFAULT_DEPRECATION_REASON unless reason
117
+
118
+ reason.value
119
+ end
120
+
121
+ def build_scalar_type(scalar_type_definition, type_resolver)
122
+ GraphQL::ScalarType.define(
123
+ name: scalar_type_definition.name,
124
+ description: scalar_type_definition.description,
125
+ )
126
+ end
127
+
128
+ def build_union_type(union_type_definition, type_resolver)
129
+ GraphQL::UnionType.define(
130
+ name: union_type_definition.name,
131
+ description: union_type_definition.description,
132
+ possible_types: union_type_definition.types.map{ |type_name| type_resolver.call(type_name) },
133
+ )
134
+ end
135
+
136
+ def build_object_type(object_type_definition, type_resolver)
137
+ GraphQL::ObjectType.define(
138
+ name: object_type_definition.name,
139
+ description: object_type_definition.description,
140
+ fields: Hash[build_fields(object_type_definition.fields, type_resolver)],
141
+ interfaces: object_type_definition.interfaces.map{ |interface_name| type_resolver.call(interface_name) },
142
+ )
143
+ end
144
+
145
+ def build_input_object_type(input_object_type_definition, type_resolver)
146
+ GraphQL::InputObjectType.define(
147
+ name: input_object_type_definition.name,
148
+ description: input_object_type_definition.description,
149
+ arguments: Hash[build_input_arguments(input_object_type_definition, type_resolver)],
150
+ )
151
+ end
152
+
153
+ def build_input_arguments(input_object_type_definition, type_resolver)
154
+ input_object_type_definition.fields.map do |input_argument|
155
+ default_value = case input_argument.default_value
156
+ when GraphQL::Language::Nodes::Enum
157
+ input_argument.default_value.name
158
+ else
159
+ input_argument.default_value
160
+ end
161
+
162
+ [
163
+ input_argument.name,
164
+ GraphQL::Argument.define(
165
+ name: input_argument.name,
166
+ type: type_resolver.call(input_argument.type),
167
+ description: input_argument.description,
168
+ default_value: default_value,
169
+ )
170
+ ]
171
+ end
172
+ end
173
+
174
+ def build_directive(directive_definition, type_resolver)
175
+ GraphQL::Directive.define(
176
+ name: directive_definition.name,
177
+ description: directive_definition.description,
178
+ arguments: Hash[build_directive_arguments(directive_definition, type_resolver)],
179
+ locations: directive_definition.locations.map(&:to_sym),
180
+ )
181
+ end
182
+
183
+ def build_directive_arguments(directive_definition, type_resolver)
184
+ directive_definition.arguments.map do |directive_argument|
185
+ [
186
+ directive_argument.name,
187
+ GraphQL::Argument.define(
188
+ name: directive_argument.name,
189
+ type: type_resolver.call(directive_argument.type),
190
+ description: directive_argument.description,
191
+ default_value: directive_argument.default_value,
192
+ )
193
+ ]
194
+ end
195
+ end
196
+
197
+ def build_interface_type(interface_type_definition, type_resolver)
198
+ GraphQL::InterfaceType.define(
199
+ name: interface_type_definition.name,
200
+ description: interface_type_definition.description,
201
+ fields: Hash[build_fields(interface_type_definition.fields, type_resolver)],
202
+ )
203
+ end
204
+
205
+ def build_fields(field_definitions, type_resolver)
206
+ field_definitions.map do |field_definition|
207
+ field_arguments = Hash[field_definition.arguments.map do |argument|
208
+ default_value = case argument.default_value
209
+ when GraphQL::Language::Nodes::Enum
210
+ argument.default_value.name
211
+ else
212
+ argument.default_value
213
+ end
214
+
215
+ arg = GraphQL::Argument.define(
216
+ name: argument.name,
217
+ description: argument.description,
218
+ type: type_resolver.call(argument.type),
219
+ default_value: default_value,
220
+ )
221
+
222
+ [argument.name, arg]
223
+ end]
224
+
225
+ [
226
+ field_definition.name,
227
+ GraphQL::Field.define(
228
+ name: field_definition.name,
229
+ description: field_definition.description,
230
+ type: type_resolver.call(field_definition.type),
231
+ arguments: field_arguments,
232
+ deprecation_reason: build_deprecation_reason(field_definition.directives),
233
+ )
234
+ ]
235
+ end
236
+ end
237
+
238
+ def resolve_type(types, ast_node)
239
+ type = GraphQL::Schema::TypeExpression.build_type(types, ast_node)
240
+ raise InvalidDocumentError.new("Type \"#{ast_node.name}\" not found in document.") unless type
241
+ type
242
+ end
243
+ end
244
+
245
+ private_constant :Builder
246
+ end
247
+ end
248
+ end
@@ -0,0 +1,23 @@
1
+ module GraphQL
2
+ class Schema
3
+ # A two-level map with fields as the last values.
4
+ # The first level is type names, which point to a second map.
5
+ # The second level is field names, which point to fields.
6
+ #
7
+ # The catch is, the fields in this map _may_ have been modified by being instrumented.
8
+ class InstrumentedFieldMap
9
+ def initialize(schema)
10
+ @storage = Hash.new { |h, k| h[k] = {} }
11
+ end
12
+
13
+ def set(type_name, field_name, field)
14
+ @storage[type_name][field_name] = field
15
+ end
16
+
17
+ def get(type_name, field_name)
18
+ type = @storage[type_name]
19
+ type && type[field_name]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -10,6 +10,7 @@ module GraphQL
10
10
  # Create schema with the result of an introspection query.
11
11
  # @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
12
12
  # @return [GraphQL::Schema] the schema described by `input`
13
+ # @deprecated Use {GraphQL::Schema.from_introspection} instead
13
14
  def load(introspection_result)
14
15
  schema = introspection_result.fetch("data").fetch("__schema")
15
16
 
@@ -109,17 +110,9 @@ module GraphQL
109
110
  default_value: type["defaultValue"] ? JSON.parse(type["defaultValue"], quirks_mode: true) : nil
110
111
  )
111
112
  when "SCALAR"
112
- case type.fetch("name")
113
- when "Int"
114
- INT_TYPE
115
- when "String"
116
- STRING_TYPE
117
- when "Float"
118
- FLOAT_TYPE
119
- when "Boolean"
120
- BOOLEAN_TYPE
121
- when "ID"
122
- ID_TYPE
113
+ type_name = type.fetch("name")
114
+ if GraphQL::Schema::BUILT_IN_TYPES[type_name]
115
+ GraphQL::Schema::BUILT_IN_TYPES[type_name]
123
116
  else
124
117
  ScalarType.define(
125
118
  name: type["name"],