elasticgraph-apollo 0.19.3.0 → 1.0.0.rc1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9dfc6d3665fbade9f03f4f45fe835c4ed77a136eedc26b0540ee35f2d7e9de49
4
- data.tar.gz: 53356460e361d3c3438b2991f9455507cb7019228caafbffb5f577aa7245cf1f
3
+ metadata.gz: 60fe05fd8a1f0f1419414ab12d49ce2c6f83d3d51a65395a1c337daaf9686504
4
+ data.tar.gz: b69ab2f7e0a55ded216b2f21985cd5a61c0f85f98fda8d821618b493abc7a071
5
5
  SHA512:
6
- metadata.gz: de7a3784bf12bd0bd880e144bbd3022208a1d2f07277700a9b64b67fbd10314b4cdf9daf974661fa478e0ceffead64f6b610db8212a0cb365a529135693b00a8
7
- data.tar.gz: f2e5c81cb0b62c3d51e7c44ad7018e4d9b6b44b9c0b070297dd85c62836fc5b3cb70dd3f47a4612959f786c4837b3db61cbc4e0550a5b2ff6488b170542a9d91
6
+ metadata.gz: '07948b4764320e60d8b006b1191336f85cc8691849e7c8a9b208d4c347eeab1b5c626fc82d1be85a712742c6c1b471ed40b72e3d8f8d8be1593859f6d1cc4778'
7
+ data.tar.gz: ab665204ae619f74c6f19e2da52094cc1f06fc1c484b74f5286d1a554a765f3c9250eea0f911c1e30d792fc8ad3a4aedb919d699b52e20537400a183a20105d8
@@ -48,14 +48,14 @@ module ApolloTestImpl
48
48
  schema.on_root_query_type do |type|
49
49
  type.field "product", "Product" do |f|
50
50
  f.argument "id", "ID!"
51
- f.resolve_with :product
51
+ f.resolver = :product
52
52
  end
53
53
 
54
54
  type.field "deprecatedProduct", "DeprecatedProduct" do |f|
55
55
  f.argument "sku", "String!"
56
56
  f.argument "package", "String!"
57
57
  f.directive "deprecated", reason: "Use product query instead"
58
- f.resolve_with :product
58
+ f.resolver = :product
59
59
  end
60
60
  end
61
61
 
@@ -24,7 +24,7 @@ class ProductResolver
24
24
  query = @datastore_query_builder.new_query(
25
25
  search_index_definitions: [@product_index_def],
26
26
  monotonic_clock_deadline: context[:monotonic_clock_deadline],
27
- filters: [{"id" => {"equalToAnyOf" => [args.fetch("id")]}}],
27
+ client_filters: [{"id" => {"equalToAnyOf" => [args.fetch("id")]}}],
28
28
  individual_docs_needed: true,
29
29
  request_all_fields: true
30
30
  )
@@ -166,7 +166,7 @@ module ElasticGraph
166
166
  query.merge_with(
167
167
  document_pagination: {first: representations.length},
168
168
  requested_fields: additional_requested_fields_for(representations),
169
- filters: [filter]
169
+ internal_filters: [filter]
170
170
  )
171
171
  end
172
172
 
@@ -242,7 +242,7 @@ module ElasticGraph
242
242
  # In the case of representations which don't query Id, we ask for 2 documents so that
243
243
  # if something weird is going on and it matches more than 1, we can detect that and return an error.
244
244
  document_pagination: {first: 2},
245
- filters: [build_filter_for_hash(fields)]
245
+ internal_filters: [build_filter_for_hash(fields)]
246
246
  )
247
247
  end
248
248
 
@@ -8,6 +8,7 @@
8
8
 
9
9
  require "elastic_graph/errors"
10
10
  require "elastic_graph/version"
11
+ require "elastic_graph/apollo/graphql/engine_extension"
11
12
  require "elastic_graph/apollo/schema_definition/entity_type_extension"
12
13
  require "elastic_graph/apollo/schema_definition/factory_extension"
13
14
  require "elastic_graph/apollo/schema_definition/state_extension"
@@ -124,6 +125,7 @@ module ElasticGraph
124
125
  end
125
126
  end
126
127
 
128
+ api.register_graphql_extension GraphQL::EngineExtension, defined_at: "elastic_graph/apollo/graphql/engine_extension"
127
129
  api.state.after_user_definition_complete do
128
130
  api.send(:define_apollo_schema_elements)
129
131
  end
@@ -378,19 +380,11 @@ module ElasticGraph
378
380
  end
379
381
  end
380
382
 
381
- require(require_path = "elastic_graph/apollo/graphql/engine_extension")
382
- register_graphql_extension GraphQL::EngineExtension, defined_at: require_path
383
-
384
383
  require(require_path = "elastic_graph/apollo/graphql/entities_field_resolver")
385
384
  register_graphql_resolver :apollo_entities, GraphQL::EntitiesFieldResolver, defined_at: require_path
386
385
 
387
386
  require(require_path = "elastic_graph/apollo/graphql/service_field_resolver")
388
387
  register_graphql_resolver :apollo_service, GraphQL::ServiceFieldResolver, defined_at: require_path
389
-
390
- require(require_path = "elastic_graph/apollo/graphql/apollo_entity_ref_resolver")
391
- register_graphql_resolver :apollo_entity_ref, GraphQL::ApolloEntityRefResolver::ForSingleId, defined_at: require_path
392
- register_graphql_resolver :apollo_entity_ref_list, GraphQL::ApolloEntityRefResolver::ForIdList, defined_at: require_path
393
- register_graphql_resolver :apollo_entity_ref_paginated, GraphQL::ApolloEntityRefResolver::ForPaginatedList, defined_at: require_path
394
388
  end
395
389
 
396
390
  def apollo_object_type(name, &block)
@@ -493,7 +487,7 @@ module ElasticGraph
493
487
  EOS
494
488
  end
495
489
 
496
- f.resolve_with :apollo_entities
490
+ f.resolver = :apollo_entities
497
491
  end
498
492
  end
499
493
 
@@ -509,7 +503,7 @@ module ElasticGraph
509
503
  Not intended for use by clients other than Apollo.
510
504
  EOS
511
505
 
512
- f.resolve_with :apollo_service
506
+ f.resolver = :apollo_service
513
507
  end
514
508
  end
515
509
  end
@@ -7,7 +7,6 @@
7
7
  # frozen_string_literal: true
8
8
 
9
9
  require "elastic_graph/apollo/schema_definition/apollo_directives"
10
- require "elastic_graph/apollo/schema_definition/object_and_interface_extension"
11
10
 
12
11
  module ElasticGraph
13
12
  module Apollo
@@ -21,7 +20,6 @@ module ElasticGraph
21
20
  include ApolloDirectives::Policy
22
21
  include ApolloDirectives::RequiresScopes
23
22
  include ApolloDirectives::Tag
24
- include ObjectAndInterfaceExtension
25
23
  end
26
24
  end
27
25
  end
@@ -7,7 +7,6 @@
7
7
  # frozen_string_literal: true
8
8
 
9
9
  require "elastic_graph/apollo/schema_definition/apollo_directives"
10
- require "elastic_graph/apollo/schema_definition/object_and_interface_extension"
11
10
 
12
11
  module ElasticGraph
13
12
  module Apollo
@@ -24,7 +23,6 @@ module ElasticGraph
24
23
  include ApolloDirectives::RequiresScopes
25
24
  include ApolloDirectives::Shareable
26
25
  include ApolloDirectives::Tag
27
- include ObjectAndInterfaceExtension
28
26
  end
29
27
  end
30
28
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticgraph-apollo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.3.0
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Myron Marston
@@ -9,7 +9,7 @@ authors:
9
9
  - Block Engineering
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-06-20 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: elasticgraph-graphql
@@ -17,42 +17,42 @@ dependencies:
17
17
  requirements:
18
18
  - - '='
19
19
  - !ruby/object:Gem::Version
20
- version: 0.19.3.0
20
+ version: 1.0.0.rc1
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - '='
26
26
  - !ruby/object:Gem::Version
27
- version: 0.19.3.0
27
+ version: 1.0.0.rc1
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: elasticgraph-support
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - '='
33
33
  - !ruby/object:Gem::Version
34
- version: 0.19.3.0
34
+ version: 1.0.0.rc1
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - '='
40
40
  - !ruby/object:Gem::Version
41
- version: 0.19.3.0
41
+ version: 1.0.0.rc1
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: graphql
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: 2.5.4
48
+ version: 2.5.6
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: 2.5.4
55
+ version: 2.5.6
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: apollo-federation
58
58
  requirement: !ruby/object:Gem::Requirement
@@ -79,70 +79,70 @@ dependencies:
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 0.19.3.0
82
+ version: 1.0.0.rc1
83
83
  type: :development
84
84
  prerelease: false
85
85
  version_requirements: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 0.19.3.0
89
+ version: 1.0.0.rc1
90
90
  - !ruby/object:Gem::Dependency
91
91
  name: elasticgraph-admin
92
92
  requirement: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 0.19.3.0
96
+ version: 1.0.0.rc1
97
97
  type: :development
98
98
  prerelease: false
99
99
  version_requirements: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 0.19.3.0
103
+ version: 1.0.0.rc1
104
104
  - !ruby/object:Gem::Dependency
105
105
  name: elasticgraph-elasticsearch
106
106
  requirement: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 0.19.3.0
110
+ version: 1.0.0.rc1
111
111
  type: :development
112
112
  prerelease: false
113
113
  version_requirements: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: 0.19.3.0
117
+ version: 1.0.0.rc1
118
118
  - !ruby/object:Gem::Dependency
119
119
  name: elasticgraph-opensearch
120
120
  requirement: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
- version: 0.19.3.0
124
+ version: 1.0.0.rc1
125
125
  type: :development
126
126
  prerelease: false
127
127
  version_requirements: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - '='
130
130
  - !ruby/object:Gem::Version
131
- version: 0.19.3.0
131
+ version: 1.0.0.rc1
132
132
  - !ruby/object:Gem::Dependency
133
133
  name: elasticgraph-indexer
134
134
  requirement: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - '='
137
137
  - !ruby/object:Gem::Version
138
- version: 0.19.3.0
138
+ version: 1.0.0.rc1
139
139
  type: :development
140
140
  prerelease: false
141
141
  version_requirements: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - '='
144
144
  - !ruby/object:Gem::Version
145
- version: 0.19.3.0
145
+ version: 1.0.0.rc1
146
146
  email:
147
147
  - myron@squareup.com
148
148
  executables: []
@@ -160,7 +160,6 @@ files:
160
160
  - apollo_tests_implementation/docker-compose.yaml
161
161
  - apollo_tests_implementation/lib/product_resolver.rb
162
162
  - apollo_tests_implementation/wait_for_datastore.sh
163
- - lib/elastic_graph/apollo/graphql/apollo_entity_ref_resolver.rb
164
163
  - lib/elastic_graph/apollo/graphql/engine_extension.rb
165
164
  - lib/elastic_graph/apollo/graphql/entities_field_resolver.rb
166
165
  - lib/elastic_graph/apollo/graphql/http_endpoint_extension.rb
@@ -175,7 +174,6 @@ files:
175
174
  - lib/elastic_graph/apollo/schema_definition/field_extension.rb
176
175
  - lib/elastic_graph/apollo/schema_definition/input_type_extension.rb
177
176
  - lib/elastic_graph/apollo/schema_definition/interface_type_extension.rb
178
- - lib/elastic_graph/apollo/schema_definition/object_and_interface_extension.rb
179
177
  - lib/elastic_graph/apollo/schema_definition/object_type_extension.rb
180
178
  - lib/elastic_graph/apollo/schema_definition/scalar_type_extension.rb
181
179
  - lib/elastic_graph/apollo/schema_definition/state_extension.rb
@@ -188,10 +186,10 @@ licenses:
188
186
  - MIT
189
187
  metadata:
190
188
  bug_tracker_uri: https://github.com/block/elasticgraph/issues
191
- changelog_uri: https://github.com/block/elasticgraph/releases/tag/v0.19.3.0
192
- documentation_uri: https://block.github.io/elasticgraph/api-docs/v0.19.3.0/
189
+ changelog_uri: https://github.com/block/elasticgraph/releases/tag/v1.0.0.rc1
190
+ documentation_uri: https://block.github.io/elasticgraph/api-docs/v1.0.0.rc1/
193
191
  homepage_uri: https://block.github.io/elasticgraph/
194
- source_code_uri: https://github.com/block/elasticgraph/tree/v0.19.3.0/elasticgraph-apollo
192
+ source_code_uri: https://github.com/block/elasticgraph/tree/v1.0.0.rc1/elasticgraph-apollo
195
193
  gem_category: extension
196
194
  rdoc_options: []
197
195
  require_paths:
@@ -200,7 +198,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
200
198
  requirements:
201
199
  - - ">="
202
200
  - !ruby/object:Gem::Version
203
- version: '3.2'
201
+ version: '3.4'
204
202
  - - "<"
205
203
  - !ruby/object:Gem::Version
206
204
  version: '3.5'
@@ -210,7 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
208
  - !ruby/object:Gem::Version
211
209
  version: '0'
212
210
  requirements: []
213
- rubygems_version: 3.6.2
211
+ rubygems_version: 3.6.7
214
212
  specification_version: 4
215
213
  summary: An ElasticGraph extension that implements the Apollo federation spec.
216
214
  test_files: []
@@ -1,72 +0,0 @@
1
- # Copyright 2024 - 2025 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/relay_connection/array_adapter"
10
-
11
- module ElasticGraph
12
- module Apollo
13
- module GraphQL
14
- # Namespace for resolvers which provide Apollo entity references from ids.
15
- #
16
- # @private
17
- module ApolloEntityRefResolver
18
- # GraphQL resolver for fields defined with `apollo_entity_ref_field` that are backed by a single id.
19
- #
20
- # @private
21
- class ForSingleId
22
- def initialize(elasticgraph_graphql:, config:)
23
- @source_id_field = config.fetch(:source_id_field)
24
- @exposed_id_field = config.fetch(:exposed_id_field)
25
- end
26
-
27
- def resolve(field:, object:, args:, context:)
28
- if (id = object.fetch(@source_id_field))
29
- {@exposed_id_field => id}
30
- end
31
- end
32
- end
33
-
34
- # GraphQL resolver for fields defined with `apollo_entity_ref_field` that are backed by an list of ids.
35
- #
36
- # @private
37
- class ForIdList
38
- def initialize(elasticgraph_graphql:, config:)
39
- @source_ids_field = config.fetch(:source_ids_field)
40
- @exposed_id_field = config.fetch(:exposed_id_field)
41
- end
42
-
43
- def resolve(field:, object:, args:, context:)
44
- object
45
- .fetch(@source_ids_field)
46
- .map { |id| {@exposed_id_field => id} }
47
- end
48
- end
49
-
50
- # GraphQL resolver for paginated fields defined with `apollo_entity_ref_paginated_collection_field`.
51
- #
52
- # @private
53
- class ForPaginatedList
54
- def initialize(elasticgraph_graphql:, config:)
55
- @for_id_list = ForIdList.new(elasticgraph_graphql:, config:)
56
- end
57
-
58
- def resolve(field:, object:, args:, context:)
59
- array = @for_id_list.resolve(field:, object:, args:, context:)
60
-
61
- ::ElasticGraph::GraphQL::Resolvers::RelayConnection::ArrayAdapter.build(
62
- array,
63
- args,
64
- context.fetch(:elastic_graph_schema).element_names,
65
- context
66
- )
67
- end
68
- end
69
- end
70
- end
71
- end
72
- end
@@ -1,218 +0,0 @@
1
- # Copyright 2024 - 2025 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/apollo/schema_definition/apollo_directives"
10
-
11
- module ElasticGraph
12
- module Apollo
13
- module SchemaDefinition
14
- # Extends {ElasticGraph::SchemaDefinition::SchemaElements::ObjectType} and
15
- # {ElasticGraph::SchemaDefinition::SchemaElements::InterfaceType} to offer some Apollo-specific APIs.
16
- module ObjectAndInterfaceExtension
17
- # Exposes an Apollo entity reference as a new field, backed by an `ID` field.
18
- #
19
- # When integrating an ElasticGraph project as a subgraph into a larger Apollo supergraph, it's useful to be able
20
- # to reference entities owned by other subgraphs. The most straightforward way to do this is to define an
21
- # _entity reference_ type (e.g. a type containing just the `@key` fields such as `id: ID` and marked as
22
- # `resolvable: false` in the `@key` directive), and then define fields using that type. This approach works
23
- # particularly well when you plan ahead and know which `ID` fields to model with entity reference types.
24
- #
25
- # However, on an existing schema where you've got some raw `ID` fields of external entities, it can be quite
26
- # difficult to replace the `ID` fields with full-blown entity reference types, as doing so would require migrating
27
- # clients and running a full backfill.
28
- #
29
- # This API provides an alternate solution for this situation: it defines a GraphQL-only field which returns an entity
30
- # reference type using a custom GraphQL resolver.
31
- #
32
- # See the [Apollo docs on referencing an entity without contributing
33
- # fields](https://www.apollographql.com/docs/graphos/schema-design/federated-schemas/entities/contribute-fields#referencing-an-entity-without-contributing-fields)
34
- # for more information.
35
- #
36
- # @param name [String] Name of the field
37
- # @param type [String] Name of the entity reference type (which must be defined separately)
38
- # @param id_field_name_in_index [String] Name of the backing ID field in the datastore index
39
- # @return [void]
40
- # @note This can be used for either a singleton or list reference, based on if `type` is a list.
41
- # @note The resulting field will be only be available for clients to request as a return field. It will not support filtering,
42
- # sorting, grouping, aggregated values, or highlights.
43
- # @see #apollo_entity_ref_paginated_collection_field
44
- #
45
- # @example Expose `Review.product` and `Review.comments` entity reference fields
46
- # ElasticGraph.define_schema do |schema|
47
- # schema.object_type "Product" do |t|
48
- # t.field "id", "ID"
49
- # t.apollo_key fields: "id", resolvable: false
50
- # end
51
- #
52
- # schema.object_type "Comment" do |t|
53
- # t.field "id", "ID"
54
- # t.apollo_key fields: "id", resolvable: false
55
- # end
56
- #
57
- # schema.object_type "Review" do |t|
58
- # t.field "id", "ID"
59
- # t.field "score", "Int"
60
- #
61
- # # Fields originally defined in the first version of the schema
62
- # t.field "productId", "ID"
63
- # t.field "commentIds", "[ID!]!"
64
- #
65
- # # New field we're adding to expose the existing `productId` field as a `Product` entity reference.
66
- # t.apollo_entity_ref_field "product", "Product", id_field_name_in_index: "productId"
67
- #
68
- # # New field we're adding to expose the existing `commentIds` field as a list of `Comment` entity references.
69
- # t.apollo_entity_ref_field "comments", "[Comment!]!", id_field_name_in_index: "commentIds"
70
- #
71
- # t.index "reviews"
72
- # end
73
- # end
74
- def apollo_entity_ref_field(name, type, id_field_name_in_index:)
75
- field(
76
- name,
77
- type,
78
- name_in_index: id_field_name_in_index,
79
- **LIMITED_GRAPHQL_ONLY_FIELD_OPTIONS
80
- ) do |f|
81
- validate_entity_ref_options(__method__.to_s, f, id_field_name_in_index, type) do |exposed_id_field|
82
- if f.type.list?
83
- f.resolve_with :apollo_entity_ref_list, source_ids_field: id_field_name_in_index, exposed_id_field: exposed_id_field
84
- else
85
- f.resolve_with :apollo_entity_ref, source_id_field: id_field_name_in_index, exposed_id_field: exposed_id_field
86
- end
87
- end
88
-
89
- yield f if block_given?
90
- end
91
- end
92
-
93
- # Exposes a collection of Apollo entity references as a new paginated field, backed by an `ID` field.
94
- #
95
- # When integrating an ElasticGraph project as a subgraph into a larger Apollo supergraph, it's useful to be able
96
- # to reference entities owned by other subgraphs. The most straightforward way to do this is to define an
97
- # _entity reference_ type (e.g. a type containing just the `@key` fields such as `id: ID` and marked as
98
- # `resolvable: false` in the `@key` directive), and then define fields using that type. This approach works
99
- # particularly well when you plan ahead and know which `ID` fields to model with entity reference types.
100
- #
101
- # However, on an existing schema where you've got some raw `ID` fields of external entities, it can be quite
102
- # difficult to replace the `ID` fields with full-blown entity reference types, as doing so would require migrating
103
- # clients and running a full backfill.
104
- #
105
- # This API provides an alternate solution for this situation: it defines a GraphQL-only field which returns an entity
106
- # reference type using a custom GraphQL resolver. In contrast to {#apollo_entity_ref_field}, this defines a field as
107
- # a [paginated Relay connection](https://relay.dev/graphql/connections.htm) rather than a simple list.
108
- #
109
- # See the [Apollo docs on referencing an entity without contributing
110
- # fields](https://www.apollographql.com/docs/graphos/schema-design/federated-schemas/entities/contribute-fields#referencing-an-entity-without-contributing-fields)
111
- # for more information.
112
- #
113
- # @param name [String] Name of the field
114
- # @param element_type [String] Name of the entity reference type (which must be defined separately)
115
- # @param id_field_name_in_index [String] Name of the backing ID field in the datastore index
116
- # @return [void]
117
- # @note This requires `id_field_name_in_index` to be a list or paginated collection field.
118
- # @note The resulting field will be only be available for clients to request as a return field. It will not support filtering,
119
- # sorting, grouping, aggregated values, or highlights.
120
- # @see #apollo_entity_ref_field
121
- # @see ElasticGraph::SchemaDefinition::SchemaElements::TypeWithSubfields#paginated_collection_field
122
- #
123
- # @example Expose `Review.product` and `Review.comments` entity reference fields
124
- # ElasticGraph.define_schema do |schema|
125
- # schema.object_type "Comment" do |t|
126
- # t.field "id", "ID"
127
- # t.apollo_key fields: "id", resolvable: false
128
- # end
129
- #
130
- # schema.object_type "Review" do |t|
131
- # t.field "id", "ID"
132
- # t.field "score", "Int"
133
- #
134
- # # Field originally defined in the first version of the schema
135
- # t.field "commentIds", "[ID!]!"
136
- #
137
- # # New field we're adding to expose the existing `commentIds` field as a list of `Comment` entity references.
138
- # t.apollo_entity_ref_paginated_collection_field "comments", "Comment", id_field_name_in_index: "commentIds"
139
- #
140
- # t.index "reviews"
141
- # end
142
- # end
143
- def apollo_entity_ref_paginated_collection_field(name, element_type, id_field_name_in_index:)
144
- paginated_collection_field(
145
- name,
146
- element_type,
147
- name_in_index: id_field_name_in_index,
148
- **LIMITED_GRAPHQL_ONLY_PAGINATED_FIELD_OPTIONS
149
- ) do |f|
150
- validate_entity_ref_options(__method__.to_s, f, id_field_name_in_index, element_type) do |exposed_id_field|
151
- backing_indexing_field = f.backing_indexing_field # : ::ElasticGraph::SchemaDefinition::SchemaElements::Field
152
- unless backing_indexing_field.type.list?
153
- raise Errors::SchemaError, "`#{f.parent_type.name}.#{f.name}` is invalid: `id_field_name_in_index` must reference an " \
154
- "id collection field, but the type of `#{id_field_name_in_index}` is `#{backing_indexing_field.type.name}`."
155
- end
156
-
157
- f.resolve_with :apollo_entity_ref_paginated, source_ids_field: id_field_name_in_index, exposed_id_field: exposed_id_field
158
-
159
- yield f if block_given?
160
- end
161
- end
162
- end
163
-
164
- private
165
-
166
- # The set of options for a GraphQL-only field that has all abilities disabled. A field defined with these options
167
- # is available to be returned, but cannot be used for anything else (filtering, grouping, sorting, etc.).
168
- LIMITED_GRAPHQL_ONLY_FIELD_OPTIONS = {
169
- graphql_only: true,
170
- filterable: false,
171
- groupable: false,
172
- aggregatable: false,
173
- sortable: false
174
- }
175
-
176
- # Like {LIMITED_GRAPHQL_ONLY_FIELD_OPTIONS} but for
177
- # {ElasticGraph::SchemaDefinition::SchemaElements::TypeWithSubfields#paginated_collection_field}.
178
- # It does not support the `sortable` option.
179
- LIMITED_GRAPHQL_ONLY_PAGINATED_FIELD_OPTIONS = LIMITED_GRAPHQL_ONLY_FIELD_OPTIONS.except(:sortable)
180
-
181
- def validate_entity_ref_options(method_name, field, id_field_name_in_index, entity_ref_type_name)
182
- # Defer validation since it depends on the definition of the entity ref type, which may be as yet undefined.
183
- schema_def_state.after_user_definition_complete do
184
- backing_indexing_field = field.backing_indexing_field # : ::ElasticGraph::SchemaDefinition::SchemaElements::Field
185
- backing_indexing_field_type = backing_indexing_field.type.fully_unwrapped.name
186
-
187
- unless backing_indexing_field_type == "ID"
188
- raise Errors::SchemaError, "`#{field.parent_type.name}.#{field.name}` is invalid: `id_field_name_in_index` must " \
189
- "reference an `ID` field, but the type of `#{id_field_name_in_index}` is `#{backing_indexing_field_type}`."
190
- end
191
-
192
- entity_ref_type = schema_def_state.type_ref(entity_ref_type_name).fully_unwrapped.as_object_type
193
- unless entity_ref_type
194
- raise Errors::SchemaError, "`#{field.parent_type.name}.#{field.name}` is invalid: the referenced type " \
195
- "(`#{entity_ref_type_name}`) is not an object type as required by `#{method_name}`."
196
- end
197
-
198
- entity_ref_type_fields = entity_ref_type.graphql_fields_by_name.keys
199
-
200
- unless entity_ref_type_fields.size == 1
201
- raise Errors::SchemaError, "`#{field.parent_type.name}.#{field.name}` is invalid: `#{method_name}` can only be used " \
202
- "for types with a single field, but `#{entity_ref_type.name}` has #{entity_ref_type_fields.size} fields."
203
- end
204
-
205
- exposed_id_field = entity_ref_type_fields.first
206
- exposed_id_field_type = entity_ref_type.graphql_fields_by_name.fetch(exposed_id_field).type
207
- unless exposed_id_field_type.unwrap_non_null.name == "ID"
208
- raise Errors::SchemaError, "`#{field.parent_type.name}.#{field.name}` is invalid: `#{method_name}` can only be used for " \
209
- "types with a single `ID` field, but the type of `#{entity_ref_type.name}.#{exposed_id_field}` is `#{exposed_id_field_type.name}`."
210
- end
211
-
212
- yield exposed_id_field
213
- end
214
- end
215
- end
216
- end
217
- end
218
- end