elasticgraph-graphql 0.19.1.1 → 0.19.2.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/lib/elastic_graph/graphql/aggregation/composite_grouping_adapter.rb +1 -1
  4. data/lib/elastic_graph/graphql/aggregation/computation.rb +1 -1
  5. data/lib/elastic_graph/graphql/aggregation/date_histogram_grouping.rb +1 -1
  6. data/lib/elastic_graph/graphql/aggregation/field_path_encoder.rb +1 -1
  7. data/lib/elastic_graph/graphql/aggregation/field_term_grouping.rb +1 -1
  8. data/lib/elastic_graph/graphql/aggregation/key.rb +1 -1
  9. data/lib/elastic_graph/graphql/aggregation/nested_sub_aggregation.rb +1 -1
  10. data/lib/elastic_graph/graphql/aggregation/non_composite_grouping_adapter.rb +2 -2
  11. data/lib/elastic_graph/graphql/aggregation/path_segment.rb +2 -2
  12. data/lib/elastic_graph/graphql/aggregation/query.rb +1 -1
  13. data/lib/elastic_graph/graphql/aggregation/query_adapter.rb +33 -6
  14. data/lib/elastic_graph/graphql/aggregation/query_optimizer.rb +1 -1
  15. data/lib/elastic_graph/graphql/aggregation/resolvers/aggregated_values.rb +2 -6
  16. data/lib/elastic_graph/graphql/aggregation/resolvers/count_detail.rb +1 -1
  17. data/lib/elastic_graph/graphql/aggregation/resolvers/grouped_by.rb +26 -6
  18. data/lib/elastic_graph/graphql/aggregation/resolvers/node.rb +1 -1
  19. data/lib/elastic_graph/graphql/aggregation/resolvers/relay_connection_builder.rb +5 -6
  20. data/lib/elastic_graph/graphql/aggregation/resolvers/sub_aggregations.rb +10 -8
  21. data/lib/elastic_graph/graphql/aggregation/script_term_grouping.rb +1 -1
  22. data/lib/elastic_graph/graphql/aggregation/term_grouping.rb +2 -2
  23. data/lib/elastic_graph/graphql/client.rb +1 -1
  24. data/lib/elastic_graph/graphql/config.rb +21 -6
  25. data/lib/elastic_graph/graphql/datastore_query/document_paginator.rb +10 -5
  26. data/lib/elastic_graph/graphql/datastore_query/index_expression_builder.rb +2 -3
  27. data/lib/elastic_graph/graphql/datastore_query/paginator.rb +1 -1
  28. data/lib/elastic_graph/graphql/datastore_query/routing_picker.rb +2 -3
  29. data/lib/elastic_graph/graphql/datastore_query.rb +66 -74
  30. data/lib/elastic_graph/graphql/datastore_response/document.rb +1 -1
  31. data/lib/elastic_graph/graphql/datastore_response/search_response.rb +83 -9
  32. data/lib/elastic_graph/graphql/datastore_search_router.rb +19 -4
  33. data/lib/elastic_graph/graphql/decoded_cursor.rb +1 -1
  34. data/lib/elastic_graph/graphql/filtering/boolean_query.rb +1 -1
  35. data/lib/elastic_graph/graphql/filtering/field_path.rb +1 -1
  36. data/lib/elastic_graph/graphql/filtering/filter_args_translator.rb +2 -2
  37. data/lib/elastic_graph/graphql/filtering/filter_interpreter.rb +10 -5
  38. data/lib/elastic_graph/graphql/filtering/filter_node_interpreter.rb +2 -2
  39. data/lib/elastic_graph/graphql/filtering/filter_value_set_extractor.rb +17 -2
  40. data/lib/elastic_graph/graphql/filtering/range_query.rb +1 -1
  41. data/lib/elastic_graph/graphql/http_endpoint.rb +2 -2
  42. data/lib/elastic_graph/graphql/monkey_patches/schema_field.rb +1 -1
  43. data/lib/elastic_graph/graphql/monkey_patches/schema_object.rb +1 -1
  44. data/lib/elastic_graph/graphql/query_adapter/filters.rb +1 -1
  45. data/lib/elastic_graph/graphql/query_adapter/pagination.rb +1 -1
  46. data/lib/elastic_graph/graphql/query_adapter/requested_fields.rb +18 -3
  47. data/lib/elastic_graph/graphql/query_adapter/sort.rb +1 -1
  48. data/lib/elastic_graph/graphql/query_details_tracker.rb +13 -4
  49. data/lib/elastic_graph/graphql/query_executor.rb +12 -5
  50. data/lib/elastic_graph/graphql/resolvers/get_record_field_value.rb +6 -12
  51. data/lib/elastic_graph/graphql/resolvers/graphql_adapter_builder.rb +123 -0
  52. data/lib/elastic_graph/graphql/resolvers/list_records.rb +4 -4
  53. data/lib/elastic_graph/graphql/resolvers/nested_relationships.rb +57 -27
  54. data/lib/elastic_graph/graphql/resolvers/nested_relationships_source.rb +324 -0
  55. data/lib/elastic_graph/graphql/resolvers/object.rb +36 -0
  56. data/lib/elastic_graph/graphql/resolvers/query_adapter.rb +2 -2
  57. data/lib/elastic_graph/graphql/resolvers/query_source.rb +6 -3
  58. data/lib/elastic_graph/graphql/resolvers/relay_connection/array_adapter.rb +1 -1
  59. data/lib/elastic_graph/graphql/resolvers/relay_connection/generic_adapter.rb +1 -1
  60. data/lib/elastic_graph/graphql/resolvers/relay_connection/page_info.rb +1 -1
  61. data/lib/elastic_graph/graphql/resolvers/relay_connection/search_response_adapter_builder.rb +1 -1
  62. data/lib/elastic_graph/graphql/resolvers/relay_connection.rb +1 -1
  63. data/lib/elastic_graph/graphql/resolvers/resolvable_value.rb +2 -7
  64. data/lib/elastic_graph/graphql/scalar_coercion_adapters/cursor.rb +1 -1
  65. data/lib/elastic_graph/graphql/scalar_coercion_adapters/date.rb +1 -1
  66. data/lib/elastic_graph/graphql/scalar_coercion_adapters/date_time.rb +1 -1
  67. data/lib/elastic_graph/graphql/scalar_coercion_adapters/local_time.rb +1 -1
  68. data/lib/elastic_graph/graphql/scalar_coercion_adapters/longs.rb +1 -1
  69. data/lib/elastic_graph/graphql/scalar_coercion_adapters/no_op.rb +1 -1
  70. data/lib/elastic_graph/graphql/scalar_coercion_adapters/time_zone.rb +1 -1
  71. data/lib/elastic_graph/graphql/scalar_coercion_adapters/untyped.rb +1 -1
  72. data/lib/elastic_graph/graphql/scalar_coercion_adapters/valid_time_zones.rb +1 -1
  73. data/lib/elastic_graph/graphql/schema/arguments.rb +1 -1
  74. data/lib/elastic_graph/graphql/schema/enum_value.rb +1 -1
  75. data/lib/elastic_graph/graphql/schema/field.rb +12 -27
  76. data/lib/elastic_graph/graphql/schema/relation_join.rb +17 -9
  77. data/lib/elastic_graph/graphql/schema/type.rb +15 -7
  78. data/lib/elastic_graph/graphql/schema.rb +11 -31
  79. data/lib/elastic_graph/graphql.rb +38 -40
  80. data/script/dump_time_zones +1 -1
  81. metadata +25 -27
  82. data/lib/elastic_graph/graphql/resolvers/graphql_adapter.rb +0 -114
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Block, Inc.
1
+ # Copyright 2024 - 2025 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -63,21 +63,25 @@ module ElasticGraph
63
63
 
64
64
  # Normalizes the given documents, ensuring it has the expected cardinality.
65
65
  def normalize_documents(response, &handle_warning)
66
- doc_cardinality.normalize(response, handle_warning: handle_warning, &:id)
66
+ doc_cardinality.normalize(response, handle_warning: handle_warning) { |doc| (_ = doc).id }
67
67
  end
68
68
 
69
69
  private
70
70
 
71
71
  def normalize_ids(id_or_ids, &handle_warning)
72
- id_cardinality.normalize(id_or_ids, handle_warning: handle_warning, &:itself)
72
+ id_cardinality.normalize(id_or_ids, handle_warning: handle_warning) { |id| id }
73
73
  end
74
74
 
75
75
  module Cardinality
76
76
  module Many
77
77
  def self.normalize(list_or_scalar, handle_warning:)
78
- return list_or_scalar if list_or_scalar.is_a?(Enumerable)
79
- handle_warning.call("scalar instead of a list")
80
- Array(list_or_scalar)
78
+ case list_or_scalar
79
+ when ::Enumerable
80
+ list_or_scalar
81
+ else
82
+ handle_warning.call("scalar instead of a list")
83
+ Array(list_or_scalar)
84
+ end
81
85
  end
82
86
 
83
87
  def self.blank_value
@@ -87,9 +91,13 @@ module ElasticGraph
87
91
 
88
92
  module One
89
93
  def self.normalize(list_or_scalar, handle_warning:, &deterministic_comparator)
90
- return list_or_scalar unless list_or_scalar.is_a?(Enumerable)
91
- handle_warning.call("list of more than one item instead of a scalar") if list_or_scalar.size > 1
92
- list_or_scalar.min_by(&deterministic_comparator)
94
+ case list_or_scalar
95
+ when ::Enumerable
96
+ handle_warning.call("list of more than one item instead of a scalar") if (_ = list_or_scalar).size > 1
97
+ list_or_scalar.min_by(&deterministic_comparator)
98
+ else
99
+ list_or_scalar
100
+ end
93
101
  end
94
102
 
95
103
  def self.blank_value
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Block, Inc.
1
+ # Copyright 2024 - 2025 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -24,7 +24,8 @@ module ElasticGraph
24
24
  graphql_type,
25
25
  index_definitions,
26
26
  object_runtime_metadata,
27
- enum_runtime_metadata
27
+ enum_runtime_metadata,
28
+ resolvers_needing_lookahead
28
29
  )
29
30
  @schema = schema
30
31
  @graphql_type = graphql_type
@@ -37,6 +38,7 @@ module ElasticGraph
37
38
  @elasticgraph_category = object_runtime_metadata&.elasticgraph_category
38
39
  @graphql_only_return_type = object_runtime_metadata&.graphql_only_return_type
39
40
  @enum_runtime_metadata = enum_runtime_metadata
41
+ @resolvers_needing_lookahead = resolvers_needing_lookahead
40
42
  @enum_value_names_by_original_name = (enum_runtime_metadata&.values_by_name || {}).to_h do |name, value|
41
43
  [value.alternate_original_name || name, name]
42
44
  end
@@ -45,7 +47,7 @@ module ElasticGraph
45
47
  end
46
48
 
47
49
  def name
48
- @name ||= @graphql_type.to_type_signature.to_sym
50
+ @name ||= @graphql_type.to_type_signature
49
51
  end
50
52
 
51
53
  # List of index definitions that should be searched for this type.
@@ -114,7 +116,7 @@ module ElasticGraph
114
116
  end
115
117
 
116
118
  def field_named(field_name)
117
- @fields_by_name.fetch(field_name.to_s)
119
+ @fields_by_name.fetch(field_name)
118
120
  rescue KeyError => e
119
121
  msg = "No field named #{field_name} (on type #{name}) could be found"
120
122
  msg += "; Possible alternatives: [#{e.corrections.join(", ").delete('"')}]." if e.corrections.any?
@@ -122,7 +124,7 @@ module ElasticGraph
122
124
  end
123
125
 
124
126
  def enum_value_named(enum_value_name)
125
- @enum_values_by_name[enum_value_name.to_s]
127
+ @enum_values_by_name[enum_value_name]
126
128
  end
127
129
 
128
130
  def coerce_result(result)
@@ -226,7 +228,7 @@ module ElasticGraph
226
228
  graphql_enum_value = @graphql_type.values.fetch(enum_value_name)
227
229
 
228
230
  EnumValue.new(
229
- name: graphql_enum_value.graphql_name.to_sym,
231
+ name: graphql_enum_value.graphql_name,
230
232
  type: self,
231
233
  runtime_metadata: @enum_runtime_metadata&.values_by_name&.dig(enum_value_name)
232
234
  )
@@ -250,7 +252,13 @@ module ElasticGraph
250
252
  # Eagerly fan out and instantiate all `Field` objects so that the :extras
251
253
  # get added to each field as require before we execute the first query
252
254
  fields_hash.each_with_object({}) do |(name, field), hash|
253
- hash[name] = Field.new(schema, self, field, @object_runtime_metadata&.graphql_fields_by_name&.dig(name))
255
+ hash[name] = Field.new(
256
+ schema,
257
+ self,
258
+ field,
259
+ @object_runtime_metadata&.graphql_fields_by_name&.dig(name),
260
+ @resolvers_needing_lookahead
261
+ )
254
262
  end
255
263
  end
256
264
 
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Block, Inc.
1
+ # Copyright 2024 - 2025 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -6,16 +6,13 @@
6
6
  #
7
7
  # frozen_string_literal: true
8
8
 
9
- require "digest/md5"
10
- require "forwardable"
11
- require "graphql"
12
9
  require "elastic_graph/constants"
13
10
  require "elastic_graph/errors"
14
11
  require "elastic_graph/graphql/monkey_patches/schema_field"
15
12
  require "elastic_graph/graphql/monkey_patches/schema_object"
16
13
  require "elastic_graph/graphql/schema/field"
17
14
  require "elastic_graph/graphql/schema/type"
18
- require "elastic_graph/support/hash_util"
15
+ require "graphql"
19
16
 
20
17
  module ElasticGraph
21
18
  # Wraps a GraphQL::Schema object in order to provide higher-level, more convenient APIs
@@ -37,11 +34,14 @@ module ElasticGraph
37
34
  runtime_metadata:,
38
35
  index_definitions_by_graphql_type:,
39
36
  graphql_gem_plugins:,
40
- &build_resolver
37
+ graphql_adapter:
41
38
  )
42
39
  @element_names = runtime_metadata.schema_element_names
43
40
  @config = config
44
41
  @runtime_metadata = runtime_metadata
42
+ resolvers_needing_lookahead = runtime_metadata.graphql_resolvers_by_name.filter_map do |name, resolver|
43
+ name if resolver.needs_lookahead
44
+ end.to_set
45
45
 
46
46
  @types_by_graphql_type = Hash.new do |hash, key|
47
47
  hash[key] = Type.new(
@@ -49,19 +49,18 @@ module ElasticGraph
49
49
  key,
50
50
  index_definitions_by_graphql_type[key.graphql_name] || [],
51
51
  runtime_metadata.object_types_by_name[key.graphql_name],
52
- runtime_metadata.enum_types_by_name[key.graphql_name]
52
+ runtime_metadata.enum_types_by_name[key.graphql_name],
53
+ resolvers_needing_lookahead
53
54
  )
54
55
  end
55
56
 
56
- @build_resolver = build_resolver
57
-
58
57
  # Note: as part of loading the schema, the GraphQL gem may use the resolver (such
59
58
  # when a directive has a custom scalar) so we must wait to instantiate the schema
60
59
  # as late as possible here. If we do this before initializing some of the instance
61
60
  # variables above we'll get `NoMethodError` on `nil`.
62
61
  @graphql_schema = ::GraphQL::Schema.from_definition(
63
62
  graphql_schema_string,
64
- default_resolve: LazyResolverAdapter.new(method(:resolver)),
63
+ default_resolve: graphql_adapter,
65
64
  using: graphql_gem_plugins
66
65
  )
67
66
 
@@ -79,7 +78,7 @@ module ElasticGraph
79
78
  # get type objects for wrapped types, but you need to get it from a field object of that
80
79
  # type.
81
80
  def type_named(type_name)
82
- @types_by_name.fetch(type_name.to_s)
81
+ @types_by_name.fetch(type_name)
83
82
  rescue KeyError => e
84
83
  msg = "No type named #{type_name} could be found"
85
84
  msg += "; Possible alternatives: [#{e.corrections.join(", ").delete('"')}]." if e.corrections.any?
@@ -114,31 +113,12 @@ module ElasticGraph
114
113
  end
115
114
 
116
115
  def to_s
117
- "#<#{self.class.name} 0x#{__id__.to_s(16)} indexed_document_types=#{indexed_document_types.map(&:name).sort.to_s.delete(":")}>"
116
+ "#<#{self.class.name} 0x#{__id__.to_s(16)} indexed_document_types=[#{indexed_document_types.map(&:name).sort.join(", ")}]>"
118
117
  end
119
118
  alias_method :inspect, :to_s
120
119
 
121
120
  private
122
121
 
123
- # Adapter class to allow us to lazily load the resolver instance.
124
- #
125
- # Necessary because the resolver must be provided to `GraphQL::Schema.from_definition`,
126
- # but the resolver logic itself depends upon the loaded schema to know how to resolve.
127
- # To work around the circular dependency, we build the schema with this lazy adapter,
128
- # then build the resolver with the schema, and then the lazy resolver lazily loads the resolver.
129
- LazyResolverAdapter = Struct.new(:builder) do
130
- def resolver
131
- @resolver ||= builder.call
132
- end
133
-
134
- extend Forwardable
135
- def_delegators :resolver, :call, :resolve_type, :coerce_input, :coerce_result
136
- end
137
-
138
- def resolver
139
- @resolver ||= @build_resolver.call(self)
140
- end
141
-
142
122
  def build_types_by_name
143
123
  graphql_schema.types.transform_values do |graphql_type|
144
124
  @types_by_graphql_type[graphql_type]
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Block, Inc.
1
+ # Copyright 2024 - 2025 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -79,7 +79,8 @@ module ElasticGraph
79
79
  monotonic_clock: monotonic_clock,
80
80
  logger: logger,
81
81
  slow_query_threshold_ms: @config.slow_query_latency_warning_threshold_in_ms,
82
- datastore_search_router: datastore_search_router
82
+ datastore_search_router: datastore_search_router,
83
+ config: config
83
84
  )
84
85
  end
85
86
  end
@@ -88,26 +89,14 @@ module ElasticGraph
88
89
  def schema
89
90
  @schema ||= begin
90
91
  require "elastic_graph/graphql/schema"
91
-
92
92
  Schema.new(
93
93
  graphql_schema_string: graphql_schema_string,
94
94
  config: config,
95
95
  runtime_metadata: runtime_metadata,
96
96
  index_definitions_by_graphql_type: @datastore_core.index_definitions_by_graphql_type,
97
- graphql_gem_plugins: graphql_gem_plugins
98
- ) do |schema|
99
- @graphql_adapter || begin
100
- @schema = schema # assign this so that `#schema` returns the schema when `datastore_query_adapters` is called below
101
- require "elastic_graph/graphql/resolvers/graphql_adapter"
102
- Resolvers::GraphQLAdapter.new(
103
- schema: schema,
104
- datastore_query_builder: datastore_query_builder,
105
- datastore_query_adapters: datastore_query_adapters,
106
- runtime_metadata: runtime_metadata,
107
- resolvers: graphql_resolvers
108
- )
109
- end
110
- end
97
+ graphql_gem_plugins: graphql_gem_plugins,
98
+ graphql_adapter: graphql_adapter
99
+ )
111
100
  end
112
101
  end
113
102
 
@@ -128,7 +117,7 @@ module ElasticGraph
128
117
  def datastore_query_builder
129
118
  @datastore_query_builder ||= begin
130
119
  require "elastic_graph/graphql/datastore_query"
131
- DatastoreQuery::Builder.with(
120
+ DatastoreQuery::Builder.new(
132
121
  filter_interpreter:,
133
122
  filter_node_interpreter:,
134
123
  runtime_metadata:,
@@ -146,32 +135,42 @@ module ElasticGraph
146
135
  {
147
136
  # We depend on this to avoid N+1 calls to the datastore.
148
137
  ::GraphQL::Dataloader => {},
149
- # This is new in the graphql-ruby 2.4 release, and will be required in the future.
150
- # We pass `preload: true` because the way we handle the schema depends on it being preloaded.
151
- ::GraphQL::Schema::Visibility => {preload: true}
138
+ # Here we opt-in to the old `GraphQL::Schema::Warden` visibility plugin.
139
+ # The new plugin, `GraphQL::Schema::Visibility`, causes a performance regression
140
+ # in ElasticGraph projects, and until that's fixed we want to stick with the old plugin.
141
+ #
142
+ # TODO: switch back to `::GraphQL::Schema::Visibility => {preload: true}` once the perf issue has been fixed.
143
+ ::GraphQL::Schema::Warden => {}
152
144
  }
153
145
  end
154
146
  end
155
147
 
156
- # @private
157
- def graphql_resolvers
158
- @graphql_resolvers ||= begin
159
- require "elastic_graph/graphql/resolvers/get_record_field_value"
160
- require "elastic_graph/graphql/resolvers/list_records"
161
- require "elastic_graph/graphql/resolvers/nested_relationships"
162
-
163
- nested_relationships = Resolvers::NestedRelationships.new(
164
- schema_element_names: runtime_metadata.schema_element_names,
165
- logger: logger
166
- )
167
-
168
- list_records = Resolvers::ListRecords.new
148
+ def graphql_adapter
149
+ @graphql_adapter ||= begin
150
+ require "elastic_graph/graphql/resolvers/graphql_adapter_builder"
151
+ Resolvers::GraphQLAdapterBuilder.new(
152
+ named_resolvers: named_graphql_resolvers,
153
+ query_adapter: resolver_query_adapter,
154
+ runtime_metadata: runtime_metadata
155
+ ).build
156
+ end
157
+ end
169
158
 
170
- get_record_field_value = Resolvers::GetRecordFieldValue.new(
171
- schema_element_names: runtime_metadata.schema_element_names
159
+ def resolver_query_adapter
160
+ @resolver_query_adapter ||= begin
161
+ require "elastic_graph/graphql/resolvers/query_adapter"
162
+ Resolvers::QueryAdapter.new(
163
+ datastore_query_builder: datastore_query_builder,
164
+ datastore_query_adapters: datastore_query_adapters
172
165
  )
166
+ end
167
+ end
173
168
 
174
- [nested_relationships, list_records, get_record_field_value]
169
+ # @private
170
+ def named_graphql_resolvers
171
+ @named_graphql_resolvers ||= runtime_metadata.graphql_resolvers_by_name.transform_values do |resolver|
172
+ ext = resolver.load_resolver
173
+ (_ = ext.extension_class).new(elasticgraph_graphql: self, config: ext.config)
175
174
  end
176
175
  end
177
176
 
@@ -194,14 +193,13 @@ module ElasticGraph
194
193
  filter_node_interpreter: filter_node_interpreter
195
194
  ),
196
195
  GraphQL::QueryAdapter::Sort.new(order_by_arg_name: schema_element_names.order_by),
197
- Aggregation::QueryAdapter.new(
198
- schema: schema,
196
+ Aggregation::QueryAdapter::WithoutSchema.new(
199
197
  config: config,
200
198
  filter_args_translator: filter_args_translator,
201
199
  runtime_metadata: runtime_metadata,
202
200
  sub_aggregation_grouping_adapter: sub_aggregation_grouping_adapter
203
201
  ),
204
- GraphQL::QueryAdapter::RequestedFields.new(schema)
202
+ GraphQL::QueryAdapter::RequestedFields::WithoutSchema.new
205
203
  ]
206
204
  end
207
205
  end
@@ -8,7 +8,7 @@ updated_code_filename = "#{__dir__}/../../tmp/updated_valid_time_zones.rb"
8
8
  java_time_zones = `java --source 11 #{__dir__}/dump_time_zones.java`.split("\n")
9
9
 
10
10
  ::File.write(updated_code_filename, <<~EOS)
11
- # Copyright 2024 Block, Inc.
11
+ # Copyright 2024 - 2025 Block, Inc.
12
12
  #
13
13
  # Use of this source code is governed by an MIT-style
14
14
  # license that can be found in the LICENSE file or at
metadata CHANGED
@@ -1,16 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticgraph-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.1.1
4
+ version: 0.19.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Myron Marston
8
8
  - Ben VandenBos
9
9
  - Block Engineering
10
- autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2025-02-07 00:00:00.000000000 Z
12
+ date: 2025-04-09 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: elasticgraph-datastore_core
@@ -18,113 +17,112 @@ dependencies:
18
17
  requirements:
19
18
  - - '='
20
19
  - !ruby/object:Gem::Version
21
- version: 0.19.1.1
20
+ version: 0.19.2.0
22
21
  type: :runtime
23
22
  prerelease: false
24
23
  version_requirements: !ruby/object:Gem::Requirement
25
24
  requirements:
26
25
  - - '='
27
26
  - !ruby/object:Gem::Version
28
- version: 0.19.1.1
27
+ version: 0.19.2.0
29
28
  - !ruby/object:Gem::Dependency
30
29
  name: elasticgraph-schema_artifacts
31
30
  requirement: !ruby/object:Gem::Requirement
32
31
  requirements:
33
32
  - - '='
34
33
  - !ruby/object:Gem::Version
35
- version: 0.19.1.1
34
+ version: 0.19.2.0
36
35
  type: :runtime
37
36
  prerelease: false
38
37
  version_requirements: !ruby/object:Gem::Requirement
39
38
  requirements:
40
39
  - - '='
41
40
  - !ruby/object:Gem::Version
42
- version: 0.19.1.1
41
+ version: 0.19.2.0
43
42
  - !ruby/object:Gem::Dependency
44
43
  name: graphql
45
44
  requirement: !ruby/object:Gem::Requirement
46
45
  requirements:
47
46
  - - "~>"
48
47
  - !ruby/object:Gem::Version
49
- version: 2.4.8
48
+ version: 2.5.1
50
49
  type: :runtime
51
50
  prerelease: false
52
51
  version_requirements: !ruby/object:Gem::Requirement
53
52
  requirements:
54
53
  - - "~>"
55
54
  - !ruby/object:Gem::Version
56
- version: 2.4.8
55
+ version: 2.5.1
57
56
  - !ruby/object:Gem::Dependency
58
57
  name: elasticgraph-admin
59
58
  requirement: !ruby/object:Gem::Requirement
60
59
  requirements:
61
60
  - - '='
62
61
  - !ruby/object:Gem::Version
63
- version: 0.19.1.1
62
+ version: 0.19.2.0
64
63
  type: :development
65
64
  prerelease: false
66
65
  version_requirements: !ruby/object:Gem::Requirement
67
66
  requirements:
68
67
  - - '='
69
68
  - !ruby/object:Gem::Version
70
- version: 0.19.1.1
69
+ version: 0.19.2.0
71
70
  - !ruby/object:Gem::Dependency
72
71
  name: elasticgraph-elasticsearch
73
72
  requirement: !ruby/object:Gem::Requirement
74
73
  requirements:
75
74
  - - '='
76
75
  - !ruby/object:Gem::Version
77
- version: 0.19.1.1
76
+ version: 0.19.2.0
78
77
  type: :development
79
78
  prerelease: false
80
79
  version_requirements: !ruby/object:Gem::Requirement
81
80
  requirements:
82
81
  - - '='
83
82
  - !ruby/object:Gem::Version
84
- version: 0.19.1.1
83
+ version: 0.19.2.0
85
84
  - !ruby/object:Gem::Dependency
86
85
  name: elasticgraph-opensearch
87
86
  requirement: !ruby/object:Gem::Requirement
88
87
  requirements:
89
88
  - - '='
90
89
  - !ruby/object:Gem::Version
91
- version: 0.19.1.1
90
+ version: 0.19.2.0
92
91
  type: :development
93
92
  prerelease: false
94
93
  version_requirements: !ruby/object:Gem::Requirement
95
94
  requirements:
96
95
  - - '='
97
96
  - !ruby/object:Gem::Version
98
- version: 0.19.1.1
97
+ version: 0.19.2.0
99
98
  - !ruby/object:Gem::Dependency
100
99
  name: elasticgraph-indexer
101
100
  requirement: !ruby/object:Gem::Requirement
102
101
  requirements:
103
102
  - - '='
104
103
  - !ruby/object:Gem::Version
105
- version: 0.19.1.1
104
+ version: 0.19.2.0
106
105
  type: :development
107
106
  prerelease: false
108
107
  version_requirements: !ruby/object:Gem::Requirement
109
108
  requirements:
110
109
  - - '='
111
110
  - !ruby/object:Gem::Version
112
- version: 0.19.1.1
111
+ version: 0.19.2.0
113
112
  - !ruby/object:Gem::Dependency
114
113
  name: elasticgraph-schema_definition
115
114
  requirement: !ruby/object:Gem::Requirement
116
115
  requirements:
117
116
  - - '='
118
117
  - !ruby/object:Gem::Version
119
- version: 0.19.1.1
118
+ version: 0.19.2.0
120
119
  type: :development
121
120
  prerelease: false
122
121
  version_requirements: !ruby/object:Gem::Requirement
123
122
  requirements:
124
123
  - - '='
125
124
  - !ruby/object:Gem::Version
126
- version: 0.19.1.1
127
- description:
125
+ version: 0.19.2.0
128
126
  email:
129
127
  - myron@squareup.com
130
128
  executables: []
@@ -182,9 +180,11 @@ files:
182
180
  - lib/elastic_graph/graphql/query_details_tracker.rb
183
181
  - lib/elastic_graph/graphql/query_executor.rb
184
182
  - lib/elastic_graph/graphql/resolvers/get_record_field_value.rb
185
- - lib/elastic_graph/graphql/resolvers/graphql_adapter.rb
183
+ - lib/elastic_graph/graphql/resolvers/graphql_adapter_builder.rb
186
184
  - lib/elastic_graph/graphql/resolvers/list_records.rb
187
185
  - lib/elastic_graph/graphql/resolvers/nested_relationships.rb
186
+ - lib/elastic_graph/graphql/resolvers/nested_relationships_source.rb
187
+ - lib/elastic_graph/graphql/resolvers/object.rb
188
188
  - lib/elastic_graph/graphql/resolvers/query_adapter.rb
189
189
  - lib/elastic_graph/graphql/resolvers/query_source.rb
190
190
  - lib/elastic_graph/graphql/resolvers/relay_connection.rb
@@ -215,12 +215,11 @@ licenses:
215
215
  - MIT
216
216
  metadata:
217
217
  bug_tracker_uri: https://github.com/block/elasticgraph/issues
218
- changelog_uri: https://github.com/block/elasticgraph/releases/tag/v0.19.1.1
219
- documentation_uri: https://block.github.io/elasticgraph/docs/main/
218
+ changelog_uri: https://github.com/block/elasticgraph/releases/tag/v0.19.2.0
219
+ documentation_uri: https://block.github.io/elasticgraph/api-docs/v0.19.2.0/
220
220
  homepage_uri: https://block.github.io/elasticgraph/
221
- source_code_uri: https://github.com/block/elasticgraph/tree/v0.19.1.1/elasticgraph-graphql
221
+ source_code_uri: https://github.com/block/elasticgraph/tree/v0.19.2.0/elasticgraph-graphql
222
222
  gem_category: core
223
- post_install_message:
224
223
  rdoc_options: []
225
224
  require_paths:
226
225
  - lib
@@ -238,8 +237,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
237
  - !ruby/object:Gem::Version
239
238
  version: '0'
240
239
  requirements: []
241
- rubygems_version: 3.5.22
242
- signing_key:
240
+ rubygems_version: 3.6.2
243
241
  specification_version: 4
244
242
  summary: The ElasticGraph GraphQL query engine.
245
243
  test_files: []
@@ -1,114 +0,0 @@
1
- # Copyright 2024 Block, Inc.
2
- #
3
- # Use of this source code is governed by an MIT-style
4
- # license that can be found in the LICENSE file or at
5
- # https://opensource.org/licenses/MIT.
6
- #
7
- # frozen_string_literal: true
8
-
9
- require "elastic_graph/graphql/resolvers/query_adapter"
10
-
11
- module ElasticGraph
12
- class GraphQL
13
- module Resolvers
14
- # Adapts the GraphQL gem's resolver interface to the interface implemented by
15
- # our resolvers. Responsible for routing a resolution request to the appropriate
16
- # resolver.
17
- class GraphQLAdapter
18
- def initialize(schema:, datastore_query_builder:, datastore_query_adapters:, runtime_metadata:, resolvers:)
19
- @schema = schema
20
- @query_adapter = QueryAdapter.new(
21
- datastore_query_builder: datastore_query_builder,
22
- datastore_query_adapters: datastore_query_adapters
23
- )
24
-
25
- @resolvers = resolvers
26
-
27
- scalar_types_by_name = runtime_metadata.scalar_types_by_name
28
- @coercion_adapters_by_scalar_type_name = ::Hash.new do |hash, name|
29
- scalar_types_by_name.fetch(name).load_coercion_adapter.extension_class
30
- end
31
- end
32
-
33
- # To be a valid resolver, we must implement `call`, accepting the 5 arguments listed here.
34
- #
35
- # See https://graphql-ruby.org/api-doc/1.9.6/GraphQL/Schema.html#from_definition-class_method
36
- # (specifically, the `default_resolve` argument) for the API documentation.
37
- def call(parent_type, field, object, args, context)
38
- schema_field = @schema.field_named(parent_type.graphql_name, field.name)
39
-
40
- # Extract the `:lookahead` extra that we have configured all fields to provide.
41
- # See https://graphql-ruby.org/api-doc/1.10.8/GraphQL/Execution/Lookahead.html for more info.
42
- # It is not a "real" arg in the schema and breaks `args_to_schema_form` when we call that
43
- # so we need to peel it off here.
44
- lookahead = args[:lookahead]
45
- # Convert args to the form they were defined in the schema, undoing the normalization
46
- # the GraphQL gem does to convert them to Ruby keyword args form.
47
- args = schema_field.args_to_schema_form(args.except(:lookahead))
48
-
49
- resolver = resolver_for(schema_field, object) do
50
- raise <<~ERROR
51
- No resolver yet implemented for this case.
52
-
53
- parent_type: #{schema_field.parent_type}
54
-
55
- field: #{schema_field}
56
-
57
- obj: #{object.inspect}
58
-
59
- args: #{args.inspect}
60
-
61
- ctx: #{context.inspect}
62
- ERROR
63
- end
64
-
65
- result = resolver.resolve(field: schema_field, object: object, args: args, context: context, lookahead: lookahead) do
66
- @query_adapter.build_query_from(field: schema_field, args: args, lookahead: lookahead, context: context)
67
- end
68
-
69
- # Give the field a chance to coerce the result before returning it. Initially, this is only used to deal with
70
- # enum value overrides (e.g. so that if `DayOfWeek.MONDAY` has been overridden to `DayOfWeek.MON`, we can coerce
71
- # a `MONDAY` value being returned by a painless script to `MON`), but this is designed to be general purpose
72
- # and we may use it for other coercions in the future.
73
- #
74
- # Note that coercion of scalar values is handled by the `coerce_result` callback below.
75
- schema_field.coerce_result(result)
76
- end
77
-
78
- # In order to support unions and interfaces, we must implement `resolve_type`.
79
- def resolve_type(supertype, object, context)
80
- # If `__typename` is available, use that to resolve. It should be available on any embedded abstract types...
81
- # (See `Inventor` in `config/schema.graphql` for an example of this kind of type union.)
82
- if (typename = object["__typename"])
83
- @schema.graphql_schema.possible_types(supertype).find { |t| t.graphql_name == typename }
84
- else
85
- # ...otherwise infer the type based on what index the object came from. This is the case
86
- # with unions/interfaces of individually indexed types.
87
- # (See `Part` in `config/schema/widgets.rb` for an example of this kind of type union.)
88
- @schema.document_type_stored_in(object.index_definition_name).graphql_type
89
- end
90
- end
91
-
92
- def coerce_input(type, value, ctx)
93
- scalar_coercion_adapter_for(type).coerce_input(value, ctx)
94
- end
95
-
96
- def coerce_result(type, value, ctx)
97
- scalar_coercion_adapter_for(type).coerce_result(value, ctx)
98
- end
99
-
100
- private
101
-
102
- def scalar_coercion_adapter_for(type)
103
- @coercion_adapters_by_scalar_type_name[type.graphql_name]
104
- end
105
-
106
- def resolver_for(field, object)
107
- return object if object.respond_to?(:can_resolve?) && object.can_resolve?(field: field, object: object)
108
- resolver = @resolvers.find { |r| r.can_resolve?(field: field, object: object) }
109
- resolver || yield
110
- end
111
- end
112
- end
113
- end
114
- end