graphiti_graphql 0.1.0 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -59,18 +59,14 @@ module GraphitiGraphQL
59
59
  !!config[:remote]
60
60
  end
61
61
 
62
- def fetch_remote_schema!
63
- parts = remote_url.split("/")
64
- parts.pop
65
- url = "#{parts.join("/")}/vandal/schema.json"
66
- response = faraday.get(url)
67
- JSON.parse(response.body).deep_symbolize_keys
68
- end
69
-
70
62
  def name
71
63
  config[:name]
72
64
  end
73
65
 
66
+ def stats
67
+ config[:stats]
68
+ end
69
+
74
70
  def type
75
71
  config[:type]
76
72
  end
@@ -102,16 +98,6 @@ module GraphitiGraphQL
102
98
  def all_attributes
103
99
  attributes.merge(extra_attributes)
104
100
  end
105
-
106
- private
107
-
108
- def faraday
109
- if defined?(Faraday)
110
- Faraday
111
- else
112
- raise "Faraday not defined. Please require the 'faraday' gem to use remote resources"
113
- end
114
- end
115
101
  end
116
102
  end
117
103
  end
@@ -16,21 +16,6 @@ module GraphitiGraphQL
16
16
  def resources
17
17
  schema[:resources].map { |r| get_resource(r[:name]) }
18
18
  end
19
-
20
- # TODO some work here, dupes, refer back, etc
21
- def merge_remotes!
22
- resources.select(&:remote?).each do |resource|
23
- remote_schema = resource.fetch_remote_schema!
24
- remote_schema[:resources].each do |remote_config|
25
- unless resources.map(&:name).include?(remote_config[:name])
26
- remote_config[:name] = resource.name
27
- schema[:resources].reject! { |r| r[:name] == resource.name }
28
- schema[:resources] << remote_config
29
- schema
30
- end
31
- end
32
- end
33
- end
34
19
  end
35
20
  end
36
21
  end
@@ -4,22 +4,28 @@ module GraphitiGraphQL
4
4
  query = GraphQL::Query.new(schema, query_string, variables: variables)
5
5
  definition = query.document.definitions.first
6
6
  selection = definition.selections.first
7
- resource_class = find_entrypoint_resource_class(selection.name)
7
+ is_graphiti = schemas.generated.query_field?(selection.name)
8
8
 
9
- # TODO: instead, keep track of fields we add
9
+ # Wrap *everything* in context, in case of federated request
10
10
  Util.with_gql_context do
11
- if resource_class
11
+ if is_graphiti
12
+ resource_class = schemas.generated
13
+ .resource_for_query_field(selection.name)
12
14
  run_query(schema, resource_class, selection, query)
13
15
  else
14
- Graphiti.graphql_schema.schema.execute query_string,
16
+ schemas.graphql.execute query_string,
15
17
  variables: variables,
16
- context: GraphitiGraphQL.get_context
18
+ context: GraphitiGraphQL.config.get_context
17
19
  end
18
20
  end
19
21
  end
20
22
 
21
23
  private
22
24
 
25
+ def schemas
26
+ GraphitiGraphQL.schemas
27
+ end
28
+
23
29
  def run_query(schema, resource_class, selection, query)
24
30
  if (errors = collect_errors(schema, query)).any?
25
31
  {"errors" => errors.map(&:to_h)}
@@ -32,7 +38,7 @@ module GraphitiGraphQL
32
38
 
33
39
  def render(json, selection_name)
34
40
  payload = if find_one?(selection_name)
35
- {selection_name.to_sym => json.values[0][0]}
41
+ {selection_name.to_sym => json.values[0][:nodes][0]}
36
42
  else
37
43
  json
38
44
  end
@@ -49,20 +55,8 @@ module GraphitiGraphQL
49
55
  query.validation_errors + query.analysis_errors + query.context.errors
50
56
  end
51
57
 
52
- # We can't just constantize the name from the schema
53
- # Because classes can be reopened and modified in tests (or elsewhere, in theory)
54
- def find_entrypoint_resource_class(entrypoint)
55
- Graphiti.resources.find(&matches_entrypoint?(entrypoint))
56
- end
57
-
58
58
  def find_entrypoint_schema_resource(entrypoint)
59
- graphiti_schema.resources.find(&matches_entrypoint?(entrypoint))
60
- end
61
-
62
- def matches_entrypoint?(entrypoint)
63
- lambda do |resource|
64
- resource.graphql_entrypoint.to_s.underscore == entrypoint.pluralize.underscore
65
- end
59
+ schemas.generated.schema_resource_for_query_field(entrypoint)
66
60
  end
67
61
 
68
62
  def introspection_query?(query)
@@ -70,14 +64,10 @@ module GraphitiGraphQL
70
64
  end
71
65
 
72
66
  def find_resource_by_selection_name(name)
73
- graphiti_schema.resources
67
+ schemas.graphiti.resources
74
68
  .find { |r| r.type == name.pluralize.underscore }
75
69
  end
76
70
 
77
- def graphiti_schema
78
- Graphiti.graphql_schema.graphiti_schema
79
- end
80
-
81
71
  def schema_resource_for_selection(selection, parent_resource)
82
72
  if parent_resource
83
73
  parent_resource.related_resource(selection.name.underscore.to_sym)
@@ -118,15 +108,19 @@ module GraphitiGraphQL
118
108
  gather_filters(params, selection, variables_hash, chained_name)
119
109
  gather_sorts(params, selection, variables_hash, chained_name)
120
110
  gather_pages(params, selection, variables_hash, chained_name)
111
+ gather_stats(params, selection, variables_hash, chained_name)
121
112
  end
122
113
 
123
114
  params[:include] ||= []
124
115
  params[:include] << chained_name if chained_name
125
116
 
126
- fragments = selection.selections.select { |s|
117
+ nodes = selection.selections.find { |s| s.respond_to?(:name) && s.name == "nodes" }
118
+ children = nodes ? nodes.children : selection.selections
119
+
120
+ fragments = children.select { |s|
127
121
  s.is_a?(GraphQL::Language::Nodes::InlineFragment)
128
122
  }
129
- non_fragments = selection.selections - fragments
123
+ non_fragments = children - fragments
130
124
 
131
125
  if pbt
132
126
  # Only id/_type possible here
@@ -146,8 +140,8 @@ module GraphitiGraphQL
146
140
  end
147
141
 
148
142
  fragments.each do |fragment|
149
- resource_name = Graphiti.graphql_schema.type_registry[fragment.type.name][:resource]
150
- klass = graphiti_schema.resources.find { |r| r.name == resource_name }
143
+ resource_name = schemas.generated.type_registry[fragment.type.name][:resource]
144
+ klass = schemas.graphiti.resources.find { |r| r.name == resource_name }
151
145
  _, _, fragment_sideload_selections = gather_fields fragment.selections,
152
146
  klass,
153
147
  params,
@@ -233,7 +227,9 @@ module GraphitiGraphQL
233
227
 
234
228
  attr_arg.value.arguments.each do |operator_arg|
235
229
  value = operator_arg.value
236
- if value.respond_to?(:name) # is a variable
230
+ if value.is_a?(GraphQL::Language::Nodes::Enum)
231
+ value = value.name
232
+ elsif value.respond_to?(:name) # is a variable
237
233
  value = variable_hash[operator_arg.value.name]
238
234
  end
239
235
  f[filter_param_name] = {operator_arg.name.underscore => value}
@@ -309,5 +305,22 @@ module GraphitiGraphQL
309
305
  params[:page].merge!(pages)
310
306
  end
311
307
  end
308
+
309
+ def gather_stats(params, selection, variable_hash, chained_name = nil)
310
+ stats = selection.children.find { |c| c.name == "stats" }
311
+ nodes = selection.children.find { |c| c.name == "nodes" }
312
+
313
+ if stats
314
+ stat_param = {}
315
+ stats.children.each do |stat_node|
316
+ stat_name = stat_node.name
317
+ calculations = stat_node.children.map(&:name)
318
+ stat_param[stat_name.to_sym] = calculations.join(",")
319
+ end
320
+ stat_param = {chained_name => stat_param} if chained_name
321
+ params[:stats] = stat_param
322
+ params[:page] = {size: 0} unless nodes
323
+ end
324
+ end
312
325
  end
313
326
  end
@@ -3,6 +3,7 @@ module GraphitiGraphQL
3
3
  GQL_TYPE_MAP = {
4
4
  integer_id: String,
5
5
  string: String,
6
+ uuid: String,
6
7
  integer: Integer,
7
8
  float: Float,
8
9
  boolean: GraphQL::Schema::Member::GraphQLTypeNames::Boolean,
@@ -33,6 +34,7 @@ module GraphitiGraphQL
33
34
  end
34
35
 
35
36
  attr_accessor :type_registry, :schema, :graphiti_schema
37
+ attr_reader :query_fields
36
38
 
37
39
  def self.federation?
38
40
  !!@federation
@@ -53,26 +55,11 @@ module GraphitiGraphQL
53
55
  def self.generate(entrypoint_resources = nil)
54
56
  instance = new
55
57
  schema = Class.new(::GraphitiGraphQL.schema_class || GraphQL::Schema)
56
-
57
- if federation?
58
- schema.send(:include, ApolloFederation::Schema)
59
- end
60
-
61
58
  graphiti_schema = GraphitiGraphQL::GraphitiSchema::Wrapper
62
59
  .new(Graphiti::Schema.generate)
63
- # TODO: if we avoid this on federation, or remove altogether
64
- # Make sure we don't blow up
65
- # graphiti_schema.merge_remotes!
66
-
67
- entries = entrypoint_resources || entrypoints
68
- instance.apply_query(graphiti_schema, schema, entries)
69
-
70
- # NB if we add mutation support, make sure this is applied after
71
- if federation?
72
- schema.use GraphQL::Batch
73
- end
74
- instance.schema = schema
75
60
  instance.graphiti_schema = graphiti_schema
61
+ instance.schema = schema
62
+ instance.apply_query(entrypoint_resources || entrypoints)
76
63
  instance
77
64
  end
78
65
 
@@ -82,147 +69,32 @@ module GraphitiGraphQL
82
69
 
83
70
  def initialize
84
71
  @type_registry = {}
72
+ @query_fields = {}
85
73
  end
86
74
 
87
- # TODO put this in a Federation::Schema module
88
- # Maybe even the External classes themselves?
89
- # TODO assign/assign_each
90
- def apply_federation(graphiti_schema, graphql_schema)
91
- type_registry.each_pair do |name, config|
92
- if config[:resource]
93
- local_type = config[:type]
94
- local_resource = Graphiti.resources
95
- .find { |r| r.name == config[:resource] }
96
- # TODO: maybe turn off the graphiti debug for these?
97
- local_type.define_singleton_method :resolve_reference do |reference, context, lookahead|
98
- Federation::BelongsToLoader
99
- .for(local_resource, lookahead.selections.map(&:name))
100
- .load(reference[:id])
101
- end
102
- end
103
- end
104
-
105
- # NB: test already registered bc 2 things have same relationship
106
- GraphitiGraphQL::Federation.external_resources.each_pair do |klass_name, config|
107
- pre_registered = !!type_registry[klass_name]
108
- external_klass = if pre_registered
109
- type_registry[klass_name][:type]
110
- else
111
- external_klass = Class.new(self.class.base_object)
112
- external_klass.graphql_name klass_name
113
- external_klass
114
- end
115
-
116
- unless pre_registered
117
- external_klass.key(fields: "id")
118
- external_klass.extend_type
119
- external_klass.field :id, String, null: false, external: true
120
- external_klass.class_eval do
121
- def self.resolve_reference(reference, _context, _lookup)
122
- reference
123
- end
124
- end
125
- end
126
-
127
- unless pre_registered
128
- # NB must be registered before processing rels
129
- type_registry[klass_name] = { type: external_klass }
130
- end
131
-
132
- # TODO: only do it if field not already defined
133
- config.relationships.each_pair do |name, relationship|
134
- if relationship.has_many?
135
- define_federated_has_many(graphiti_schema, external_klass, relationship)
136
- elsif relationship.belongs_to?
137
- define_federated_belongs_to(config, relationship)
138
- end
139
- end
140
- end
141
- end
142
-
143
- # TODO: refactor to not constantly pass schemas around
144
- def define_federated_has_many(graphiti_schema, external_klass, relationship)
145
- local_name = GraphitiGraphQL::GraphitiSchema::Resource
146
- .gql_name(relationship.local_resource_class.name)
147
- local_type = type_registry[local_name][:type]
148
- local_resource_name = type_registry[local_name][:resource]
149
- local_resource = Graphiti.resources.find { |r| r.name == local_resource_name }
150
-
151
- local_interface = type_registry["I#{local_name}"]
152
- best_type = local_interface ? local_interface[:type] : local_type
153
-
154
- field = external_klass.field relationship.name,
155
- [best_type],
156
- null: false,
157
- extras: [:lookahead]
158
-
159
- define_arguments_for_sideload_field(field, graphiti_schema.get_resource(local_resource_name))
160
- external_klass.define_method relationship.name do |lookahead:, **arguments|
161
- # TODO test params...do version of sort with array/symbol keys and plain string
162
- params = arguments.as_json
163
- .deep_transform_keys { |key| key.to_s.underscore.to_sym }
164
- selections = lookahead.selections.map(&:name)
165
- selections << relationship.foreign_key
166
- selections << :_type # polymorphism
167
- params[:fields] = { local_resource.type => selections.join(",") }
168
-
169
- if (sort = Util.parse_sort(params[:sort]))
170
- params[:sort] = sort
171
- end
172
-
173
- Federation::HasManyLoader
174
- .for(local_resource, params, relationship.foreign_key)
175
- .load(object[:id])
176
- end
177
- end
178
-
179
- def define_federated_belongs_to(external_resource_config, relationship)
180
- type_name = GraphitiSchema::Resource.gql_name(relationship.local_resource_class.name)
181
- local_type = type_registry[type_name][:type]
182
-
183
- # Todo maybe better way here
184
- interface = type_registry["I#{type_name}"]
185
-
186
- local_type = interface[:type] if interface
187
- local_resource_name = type_registry[type_name][:resource]
188
- local_resource_class = Graphiti.resources.find { |r| r.name == local_resource_name }
189
-
190
- local_types = [local_type]
191
- if interface
192
- local_types |= interface[:implementers]
193
- end
194
-
195
- local_types.each do |local|
196
- local.field relationship.name,
197
- type_registry[external_resource_config.type_name][:type], # todo need to define the type?
198
- null: true
199
- end
200
- end
201
-
202
- def apply_query(graphiti_schema, graphql_schema, entries)
203
- query_type = generate_schema_query(graphql_schema, graphiti_schema, entries)
204
- if self.class.federation?
205
- apply_federation(graphiti_schema, schema)
206
- end
75
+ def apply_query(entries)
76
+ query_type = generate_schema_query(entries)
77
+ Federation::SchemaDecorator.decorate(self) if self.class.federation?
207
78
 
208
79
  # NB - don't call .query here of federation will break things
209
- if graphql_schema.instance_variable_get(:@query_object)
210
- graphql_schema.instance_variable_set(:@query_object, nil)
211
- graphql_schema.instance_variable_set(:@federation_query_object, nil)
80
+ if schema.instance_variable_get(:@query_object)
81
+ schema.instance_variable_set(:@query_object, nil)
82
+ schema.instance_variable_set(:@federation_query_object, nil)
212
83
  end
213
- graphql_schema.orphan_types(orphans(graphql_schema))
214
- graphql_schema.query(query_type)
215
- graphql_schema.query # Actually fires the federation code
84
+ schema.orphan_types(orphans(schema))
85
+ schema.query(query_type)
86
+ schema.query # Actually fires the federation code
216
87
  end
217
88
 
218
- def generate_schema_query(graphql_schema, graphiti_schema, entrypoint_resources = nil)
219
- existing_query = graphql_schema.instance_variable_get(:@query) || graphql_schema.send(:find_inherited_value, :query)
89
+ def generate_schema_query(entrypoint_resources = nil)
90
+ existing_query = schema.instance_variable_get(:@query)
91
+ existing_query ||= schema.send(:find_inherited_value, :query)
220
92
  # NB - don't call graphql_schema.query here of federation will break things
221
93
  query_class = Class.new(existing_query || self.class.base_object)
222
94
  # NB MUST be Query or federation-ruby will break things
223
95
  query_class.graphql_name "Query"
224
96
 
225
- entrypoints(graphiti_schema, entrypoint_resources).each do |resource|
97
+ get_entrypoints(entrypoint_resources).each do |resource|
226
98
  next if resource.remote?
227
99
  generate_type(resource)
228
100
 
@@ -243,28 +115,65 @@ module GraphitiGraphQL
243
115
  end
244
116
  end
245
117
 
118
+ def schema_resource_for_query_field(name)
119
+ @query_fields[name.underscore.to_sym]
120
+ end
121
+
122
+ def query_field?(name)
123
+ @query_fields.include?(name.underscore.to_sym)
124
+ end
125
+
126
+ # We can't just constantize the name from the schema
127
+ # Because classes can be reopened and modified in tests (or elsewhere, in theory)
128
+ def resource_for_query_field(name)
129
+ schema_resource = @query_fields[name.underscore.to_sym]
130
+ Graphiti.resources.find { |r| r.name == schema_resource.name }
131
+ end
132
+
246
133
  private
247
134
 
248
- def add_index(query_class, resource)
249
- field = query_class.field resource.graphql_entrypoint,
250
- [type_registry[resource.graphql_class_name][:type]],
135
+ def generate_connection_type(resource, top_level: true)
136
+ name = "#{resource.graphql_class_name}#{top_level ? "TopLevel" : ""}Connection"
137
+ if registered = type_registry[name]
138
+ return registered[:type]
139
+ end
140
+
141
+ type = type_registry[resource.graphql_class_name][:type]
142
+ klass = Class.new(self.class.base_object)
143
+ klass.graphql_name(name)
144
+ klass.field :nodes,
145
+ [type],
251
146
  "List #{resource.graphql_class_name(false).pluralize}",
252
147
  null: false
148
+ if top_level
149
+ klass.field :stats, generate_stat_class(resource), null: false
150
+ end
151
+ register(name, klass)
152
+ klass
153
+ end
154
+
155
+ def add_index(query_class, resource)
156
+ field_name = resource.graphql_entrypoint.to_s.underscore.to_sym
157
+ field = query_class.field field_name,
158
+ generate_connection_type(resource, top_level: true),
159
+ null: false
160
+ @query_fields[field_name] = resource
253
161
  define_arguments_for_sideload_field(field, resource)
254
162
  end
255
163
 
256
164
  def add_show(query_class, resource)
257
- entrypoint = resource.graphql_entrypoint.to_s.singularize.to_sym
258
- field = query_class.field entrypoint,
165
+ field_name = resource.graphql_entrypoint.to_s.underscore.singularize.to_sym
166
+ field = query_class.field field_name,
259
167
  type_registry[resource.graphql_class_name][:type],
260
168
  "Single #{resource.graphql_class_name(false).singularize}",
261
- null: true
169
+ null: false
170
+ @query_fields[field_name] = resource
262
171
  define_arguments_for_sideload_field field,
263
172
  resource,
264
173
  top_level_single: true
265
174
  end
266
175
 
267
- def entrypoints(graphiti_schema, manually_specified)
176
+ def get_entrypoints(manually_specified)
268
177
  resources = graphiti_schema.resources
269
178
  if manually_specified
270
179
  resources = resources.select { |r|
@@ -308,13 +217,17 @@ module GraphitiGraphQL
308
217
  if top_level_single
309
218
  field.argument(:id, String, required: true)
310
219
  else
311
- sort_type = generate_sort_type(resource)
312
- field.argument :sort, [sort_type], required: false
220
+ unless resource.sorts.empty?
221
+ sort_type = generate_sort_type(resource)
222
+ field.argument :sort, [sort_type], required: false
223
+ end
313
224
  field.argument :page, PageType, required: false
314
225
 
315
- filter_type = generate_filter_type(field, resource)
316
- required = resource.filters.any? { |name, config| !!config[:required] }
317
- field.argument :filter, filter_type, required: required
226
+ unless resource.filters.empty?
227
+ filter_type = generate_filter_type(field, resource)
228
+ required = resource.filters.any? { |name, config| !!config[:required] }
229
+ field.argument :filter, filter_type, required: required
230
+ end
318
231
  end
319
232
  end
320
233
 
@@ -338,17 +251,38 @@ module GraphitiGraphQL
338
251
  # TODO guarded operators or otherwise whatever eq => nil is
339
252
  def generate_filter_attribute_type(type_name, filter_name, filter_config)
340
253
  klass = Class.new(GraphQL::Schema::InputObject)
341
- klass.graphql_name "#{type_name}Filter#{filter_name.to_s.camelize(:lower)}"
254
+ filter_graphql_name = "#{type_name}Filter#{filter_name.to_s.camelize(:lower)}"
255
+ klass.graphql_name(filter_graphql_name)
342
256
  filter_config[:operators].each do |operator|
343
257
  canonical_graphiti_type = Graphiti::Types
344
258
  .name_for(filter_config[:type])
345
259
  type = GQL_TYPE_MAP[canonical_graphiti_type]
346
260
  required = !!filter_config[:required] && operator == "eq"
261
+
262
+ if (allowlist = filter_config[:allow])
263
+ type = define_allowlist_type(filter_graphql_name, allowlist)
264
+ end
265
+
266
+ type = [type] unless !!filter_config[:single]
347
267
  klass.argument operator, type, required: required
348
268
  end
349
269
  klass
350
270
  end
351
271
 
272
+ def define_allowlist_type(filter_graphql_name, allowlist)
273
+ name = "#{filter_graphql_name}Allow"
274
+ if (registered = type_registry[name])
275
+ return registered[:type]
276
+ end
277
+ klass = Class.new(GraphQL::Schema::Enum)
278
+ klass.graphql_name(name)
279
+ allowlist.each do |allowed|
280
+ klass.value(allowed)
281
+ end
282
+ register(name, klass)
283
+ klass
284
+ end
285
+
352
286
  def generate_resource_for_sideload(sideload)
353
287
  if sideload.type == :polymorphic_belongs_to
354
288
  unless registered?(sideload.parent_resource)
@@ -375,7 +309,11 @@ module GraphitiGraphQL
375
309
  type_registry[sideload.graphql_class_name][:type]
376
310
  end
377
311
 
378
- gql_field_type = sideload.to_many? ? [gql_type] : gql_type
312
+ gql_field_type = if sideload.to_many?
313
+ generate_connection_type(sideload.resource, top_level: false)
314
+ else
315
+ gql_type
316
+ end
379
317
  field_name = name.to_s.camelize(:lower)
380
318
  unless type_class.fields[field_name]
381
319
  field = type_class.field field_name.to_sym,
@@ -383,7 +321,6 @@ module GraphitiGraphQL
383
321
  null: !sideload.to_many?
384
322
 
385
323
  # No sort/filter/paginate on belongs_to
386
- # unless sideload.type.to_s.include?('belongs_to')
387
324
  unless sideload.type == :polymorphic_belongs_to
388
325
  define_arguments_for_sideload_field(field, sideload.resource)
389
326
  end
@@ -412,8 +349,9 @@ module GraphitiGraphQL
412
349
  klass = Module.new
413
350
  klass.send(:include, self.class.base_interface)
414
351
  klass.definition_methods do
352
+ # rubocop:disable Lint/NestedMethodDefinition(Standard)
415
353
  def resolve_type(object, context)
416
- Graphiti.graphql_schema.schema.types[object[:__typename]]
354
+ GraphitiGraphQL.schemas.graphql.types[object[:__typename]]
417
355
  end
418
356
  end
419
357
  else
@@ -425,10 +363,6 @@ module GraphitiGraphQL
425
363
  implement(klass, type_registry[implements])
426
364
  end
427
365
 
428
- if self.class.federation?
429
- klass.key fields: "id"
430
- end
431
-
432
366
  klass.field(:_type, String, null: false)
433
367
  resource.all_attributes.each do |name, config|
434
368
  if config[:readable]
@@ -482,8 +416,27 @@ module GraphitiGraphQL
482
416
  klass
483
417
  end
484
418
 
419
+ def generate_stat_class(resource)
420
+ klass = Class.new(self.class.base_object)
421
+ klass.graphql_name "#{resource.graphql_class_name(false)}Stats"
422
+ resource.stats.each_pair do |name, calculations|
423
+ calc_class = generate_calc_class(resource, name, calculations)
424
+ klass.field name, calc_class, null: false
425
+ end
426
+ klass
427
+ end
428
+
429
+ def generate_calc_class(resource, stat_name, calculations)
430
+ klass = Class.new(self.class.base_object)
431
+ klass.graphql_name "#{resource.graphql_class_name(false)}#{stat_name}Calculations"
432
+ calculations.each do |calc|
433
+ klass.field calc, Float, null: false
434
+ end
435
+ klass
436
+ end
437
+
485
438
  def registered?(resource)
486
- name = resource.graphql_class_name(false)
439
+ name = resource.graphql_class_name(true)
487
440
  !!type_registry[name]
488
441
  end
489
442