elasticgraph-apollo 0.18.0.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 (36) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +63 -0
  4. data/apollo_tests_implementation/Dockerfile +66 -0
  5. data/apollo_tests_implementation/Gemfile +27 -0
  6. data/apollo_tests_implementation/Rakefile +22 -0
  7. data/apollo_tests_implementation/config/products_schema.rb +173 -0
  8. data/apollo_tests_implementation/config/settings.yaml +34 -0
  9. data/apollo_tests_implementation/config.ru +122 -0
  10. data/apollo_tests_implementation/docker-compose.yaml +18 -0
  11. data/apollo_tests_implementation/lib/test_implementation_extension.rb +58 -0
  12. data/apollo_tests_implementation/wait_for_datastore.sh +17 -0
  13. data/elasticgraph-apollo.gemspec +27 -0
  14. data/lib/elastic_graph/apollo/graphql/engine_extension.rb +52 -0
  15. data/lib/elastic_graph/apollo/graphql/entities_field_resolver.rb +305 -0
  16. data/lib/elastic_graph/apollo/graphql/http_endpoint_extension.rb +45 -0
  17. data/lib/elastic_graph/apollo/graphql/service_field_resolver.rb +30 -0
  18. data/lib/elastic_graph/apollo/schema_definition/api_extension.rb +385 -0
  19. data/lib/elastic_graph/apollo/schema_definition/apollo_directives.rb +119 -0
  20. data/lib/elastic_graph/apollo/schema_definition/argument_extension.rb +20 -0
  21. data/lib/elastic_graph/apollo/schema_definition/entity_type_extension.rb +30 -0
  22. data/lib/elastic_graph/apollo/schema_definition/enum_type_extension.rb +23 -0
  23. data/lib/elastic_graph/apollo/schema_definition/enum_value_extension.rb +20 -0
  24. data/lib/elastic_graph/apollo/schema_definition/factory_extension.rb +104 -0
  25. data/lib/elastic_graph/apollo/schema_definition/field_extension.rb +59 -0
  26. data/lib/elastic_graph/apollo/schema_definition/graphql_sdl_enumerator_extension.rb +69 -0
  27. data/lib/elastic_graph/apollo/schema_definition/input_type_extension.rb +20 -0
  28. data/lib/elastic_graph/apollo/schema_definition/interface_type_extension.rb +25 -0
  29. data/lib/elastic_graph/apollo/schema_definition/object_type_extension.rb +28 -0
  30. data/lib/elastic_graph/apollo/schema_definition/scalar_type_extension.rb +23 -0
  31. data/lib/elastic_graph/apollo/schema_definition/state_extension.rb +23 -0
  32. data/lib/elastic_graph/apollo/schema_definition/union_type_extension.rb +20 -0
  33. data/script/boot_eg_apollo_implementation +22 -0
  34. data/script/export_docker_env_vars.sh +15 -0
  35. data/script/test_compatibility +54 -0
  36. metadata +472 -0
@@ -0,0 +1,385 @@
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/error"
10
+ require "elastic_graph/version"
11
+ require "elastic_graph/apollo/graphql/engine_extension"
12
+ require "elastic_graph/apollo/schema_definition/entity_type_extension"
13
+ require "elastic_graph/apollo/schema_definition/factory_extension"
14
+ require "elastic_graph/apollo/schema_definition/state_extension"
15
+
16
+ module ElasticGraph
17
+ module Apollo
18
+ module SchemaDefinition
19
+ # Module designed to be extended onto an `ElasticGraph::SchemaDefinition::API` instance
20
+ # to customize the schema artifacts based on the Apollo Federation subgraph spec:
21
+ #
22
+ # https://www.apollographql.com/docs/federation/subgraph-spec/
23
+ #
24
+ # Note that at this time we do not yet support extending a type owned by another
25
+ # subgraph (which the `@requires`, `@provides`, `@extends`, and `@external`
26
+ # directives are used for).
27
+ module APIExtension
28
+ def results
29
+ register_graphql_extension GraphQL::EngineExtension, defined_at: "elastic_graph/apollo/graphql/engine_extension"
30
+ define_apollo_schema_elements
31
+
32
+ super
33
+ end
34
+
35
+ # Called from the public API, as:
36
+ # schema.tag_built_in_types_with "tag-name", except: ["IntAggregatedValues", ...]
37
+ def tag_built_in_types_with(name, except: [])
38
+ except_set = except.to_set
39
+ on_built_in_types do |type|
40
+ type.directive("tag", name: name) unless except_set.include?(type.name)
41
+ end
42
+ end
43
+
44
+ # Picks which version of Apollo federation to target. By default, the latest supported version is
45
+ # targeted, but you can call this to pick an earlier version, which may be necessary if your
46
+ # organization is running an old version of Apollo studio.
47
+ def target_apollo_federation_version(version)
48
+ # Allow the version to have the `v` prefix, but don't require it.
49
+ version = version.delete_prefix("v")
50
+
51
+ state.apollo_directive_definitions = DIRECTIVE_DEFINITIONS_BY_FEDERATION_VERSION.fetch(version) do
52
+ supported_version_descriptions = DIRECTIVE_DEFINITIONS_BY_FEDERATION_VERSION.keys.map do |version_number|
53
+ "v#{version_number}"
54
+ end.join(", ")
55
+
56
+ raise SchemaError, "elasticgraph-apollo v#{ElasticGraph::VERSION} does not support Apollo federation v#{version}. " \
57
+ "Pick one of the supported versions (#{supported_version_descriptions}) instead."
58
+ end
59
+ end
60
+
61
+ def self.extended(api)
62
+ api.factory.extend FactoryExtension
63
+ api.state.extend StateExtension
64
+
65
+ latest_federation_version = DIRECTIVE_DEFINITIONS_BY_FEDERATION_VERSION
66
+ .keys
67
+ .max_by { |v| v.split(".").map(&:to_i) } # : ::String
68
+
69
+ api.target_apollo_federation_version latest_federation_version
70
+
71
+ api.on_built_in_types do |type|
72
+ # Built-in types like `PageInfo` need to be tagged with `@shareable` on Federation V2 since other subgraphs may
73
+ # have them and they aren't entity types. `Query`, as the root, is a special case that must be skipped.
74
+ (_ = type).apollo_shareable if type.respond_to?(:apollo_shareable) && type.name != "Query"
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ # These directive definitions come straight from the Apollo federation spec:
81
+ # https://github.com/apollographql/federation/blob/25beb382fff253ac38ef6d7a5454af60da0addbb/docs/source/subgraph-spec.mdx#L57-L70
82
+ # https://github.com/apollographql/apollo-federation-subgraph-compatibility/blob/2.0.0/COMPATIBILITY.md#products-schema-to-be-implemented-by-library-maintainers
83
+ #
84
+ # I've updated them here to match the "canonical form" that the GraphQL
85
+ # gem dumps for directives (e.g. it sorts the `on` clauses alphabetically) so that
86
+ # we can use this from our tests to assert the resulting GraphQL SDL.
87
+ directives_for_fed_v2_6 = [
88
+ <<~EOS.strip,
89
+ extend schema
90
+ @link(import: ["@authenticated", "@composeDirective", "@extends", "@external", "@inaccessible", "@interfaceObject", "@key", "@override", "@policy", "@provides", "@requires", "@requiresScopes", "@shareable", "@tag", "FieldSet"], url: "https://specs.apollo.dev/federation/v2.6")
91
+ EOS
92
+ "directive @authenticated on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR",
93
+ "directive @composeDirective(name: String!) repeatable on SCHEMA",
94
+ "directive @extends on INTERFACE | OBJECT",
95
+ "directive @external on FIELD_DEFINITION | OBJECT",
96
+ "directive @inaccessible on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION",
97
+ "directive @interfaceObject on OBJECT",
98
+ "directive @key(fields: FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT",
99
+ "directive @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA",
100
+ "directive @override(from: String!) on FIELD_DEFINITION",
101
+ "directive @policy(policies: [[federation__Policy!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR",
102
+ "directive @provides(fields: FieldSet!) on FIELD_DEFINITION",
103
+ "directive @requires(fields: FieldSet!) on FIELD_DEFINITION",
104
+ "directive @requiresScopes(scopes: [[federation__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR",
105
+ "directive @shareable on FIELD_DEFINITION | OBJECT",
106
+ "directive @tag(name: String!) repeatable on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION"
107
+ ]
108
+
109
+ # Differences between federation v2.5 and v2.6
110
+ #
111
+ # - v2.5 has no @policy directive (v2.6 has this).
112
+ # - The link URL reflects the version
113
+ directives_for_fed_v2_5 = directives_for_fed_v2_6.filter_map do |directive|
114
+ if directive.include?("extend schema")
115
+ directive
116
+ .sub(', "@policy"', "")
117
+ .sub("v2.6", "v2.5")
118
+ elsif directive.include?("directive @policy")
119
+ nil
120
+ else
121
+ directive
122
+ end
123
+ end
124
+
125
+ # Differences between federation v2.3 and v2.5
126
+ #
127
+ # - v2.3 has no @authenticated directive (v2.5 has this).
128
+ # - v2.3 has no @requiresScopes directive (v2.5 has this).
129
+ # - The link URL reflects the version
130
+ directives_for_fed_v2_3 = directives_for_fed_v2_5.filter_map do |directive|
131
+ if directive.include?("extend schema")
132
+ directive
133
+ .sub('"@authenticated", ', "")
134
+ .sub(', "@requiresScopes"', "")
135
+ .sub("v2.5", "v2.3")
136
+ elsif directive.include?("directive @authenticated") || directive.include?("directive @requiresScopes")
137
+ nil
138
+ else
139
+ directive
140
+ end
141
+ end
142
+
143
+ # Differences between federation v2.0 and v2.3
144
+ #
145
+ # - v2.0 has no @composeDirective directive (v2.3 has this).
146
+ # - v2.0 has no @interfaceObject directive (v2.3 has this).
147
+ # - The link URL reflects the version
148
+ directives_for_fed_v2_0 = directives_for_fed_v2_3.filter_map do |directive|
149
+ if directive.include?("extend schema")
150
+ directive
151
+ .sub('"@composeDirective", ', "")
152
+ .sub(', "@interfaceObject"', "")
153
+ .sub("v2.3", "v2.0")
154
+ elsif directive.include?("directive @interfaceObject") || directive.include?("directive @composeDirective")
155
+ nil
156
+ else
157
+ directive
158
+ end
159
+ end
160
+
161
+ DIRECTIVE_DEFINITIONS_BY_FEDERATION_VERSION = {
162
+ "2.6" => directives_for_fed_v2_6,
163
+ "2.5" => directives_for_fed_v2_5,
164
+ "2.3" => directives_for_fed_v2_3,
165
+ "2.0" => directives_for_fed_v2_0
166
+ }
167
+
168
+ def define_apollo_schema_elements
169
+ state.apollo_directive_definitions.each { |directive| raw_sdl directive }
170
+
171
+ apollo_scalar_type "link__Import" do |t|
172
+ t.documentation "Scalar type used by the `@link` directive required for Apollo Federation V2."
173
+ # `scalar_type` requires we set these but this scalar type is only in GraphQL.
174
+ t.mapping type: nil
175
+ t.json_schema type: "null"
176
+ end
177
+
178
+ apollo_scalar_type "federation__Scope" do |t|
179
+ t.documentation "Scalar type used by the `@requiresScopes` directive required for Apollo Federation V2.5+."
180
+ # `scalar_type` requires we set these but this scalar type is only in GraphQL.
181
+ t.mapping type: nil
182
+ t.json_schema type: "null"
183
+ end
184
+
185
+ apollo_scalar_type "federation__Policy" do |t|
186
+ t.documentation "Scalar type used by the `@policy` directive required for Apollo Federation V2.6+."
187
+ # `scalar_type` requires we set these but this scalar type is only in GraphQL.
188
+ t.mapping type: nil
189
+ t.json_schema type: "null"
190
+ end
191
+
192
+ # Copied from https://github.com/apollographql/federation/blob/b3a3cb84d8d67d1d6e817dc85b9ae0ecdd9908d1/docs/source/subgraph-spec.mdx#subgraph-schema-additions
193
+ apollo_enum_type "link__Purpose" do |t|
194
+ t.documentation "Enum type used by the `@link` directive required for Apollo Federation V2."
195
+
196
+ t.value "SECURITY" do |v|
197
+ v.documentation "`SECURITY` features provide metadata necessary to securely resolve fields."
198
+ end
199
+
200
+ t.value "EXECUTION" do |v|
201
+ v.documentation "`EXECUTION` features provide metadata necessary for operation execution."
202
+ end
203
+ end
204
+
205
+ apollo_scalar_type "FieldSet" do |t|
206
+ t.documentation <<~EOS
207
+ A custom scalar type required by the [Apollo Federation subgraph
208
+ spec](https://www.apollographql.com/docs/federation/subgraph-spec/#scalar-fieldset):
209
+
210
+ > This string-serialized scalar represents a set of fields that's passed to a federated directive,
211
+ > such as `@key`, `@requires`, or `@provides`.
212
+ >
213
+ > Grammatically, a `FieldSet` is a [selection set](http://spec.graphql.org/draft/#sec-Selection-Sets)
214
+ > minus the outermost curly braces. It can represent a single field (`"upc"`), multiple fields
215
+ > (`"id countryCode"`), and even nested selection sets (`"id organization { id }"`).
216
+
217
+ Not intended for use by clients other than Apollo.
218
+ EOS
219
+
220
+ # `scalar_type` requires we set these but this scalar type is only in GraphQL.
221
+ t.mapping type: nil
222
+ t.json_schema type: "null"
223
+ end
224
+
225
+ apollo_scalar_type "_Any" do |t|
226
+ t.documentation <<~EOS
227
+ A custom scalar type required by the [Apollo Federation subgraph
228
+ spec](https://www.apollographql.com/docs/federation/subgraph-spec/#scalar-_any):
229
+
230
+ > This scalar is the type used for entity **representations** that the graph router
231
+ > passes to the `Query._entities` field. An `_Any` scalar is validated by matching
232
+ > its `__typename` and `@key` fields against entities defined in the subgraph schema.
233
+ >
234
+ > An `_Any` is serialized as a JSON object, like so:
235
+ >
236
+ > ```
237
+ > {
238
+ > "__typename": "Product",
239
+ > "upc": "abc123"
240
+ > }
241
+ > ```
242
+
243
+ Not intended for use by clients other than Apollo.
244
+ EOS
245
+
246
+ # `scalar_type` requires we set these but this scalar type is only in GraphQL.
247
+ t.mapping type: nil
248
+ t.json_schema type: "null"
249
+ end
250
+
251
+ apollo_object_type "_Service" do |t|
252
+ t.documentation <<~EOS
253
+ An object type required by the [Apollo Federation subgraph
254
+ spec](https://www.apollographql.com/docs/federation/subgraph-spec/#type-_service):
255
+
256
+ > This object type must have an `sdl: String!` field, which returns the SDL of the subgraph schema as a string.
257
+ >
258
+ > - The returned schema string _must_ include all uses of federation-specific directives (`@key`, `@requires`, etc.).
259
+ > - **If supporting Federation 1,** the schema _must not_ include any definitions from [Subgraph schema additions](https://www.apollographql.com/docs/federation/subgraph-spec/#subgraph-schema-additions).
260
+ >
261
+ > For details, see [Enhanced introspection with `Query._service`](https://www.apollographql.com/docs/federation/subgraph-spec/#enhanced-introspection-with-query_service).
262
+
263
+ Not intended for use by clients other than Apollo.
264
+ EOS
265
+
266
+ t.field "sdl", "String", graphql_only: true do |f|
267
+ f.documentation <<~EOS
268
+ A field required by the [Apollo Federation subgraph
269
+ spec](https://www.apollographql.com/docs/federation/subgraph-spec/#required-resolvers-for-introspection):
270
+
271
+ > The returned `sdl` string has the following requirements:
272
+ >
273
+ > - It must **include** all uses of all federation-specific directives, such as `@key`.
274
+ > - All of these directives are shown in [Subgraph schema additions](https://www.apollographql.com/docs/federation/subgraph-spec/#subgraph-schema-additions).
275
+ > - **If supporting Federation 1,** `sdl` must **omit** all automatically added definitions from
276
+ > [Subgraph schema additions](https://www.apollographql.com/docs/federation/subgraph-spec/#subgraph-schema-additions),
277
+ > such as `Query._service` and `_Service.sdl`!
278
+ > - If your library is _only_ supporting Federation 2, `sdl` can include these definitions.
279
+
280
+ Not intended for use by clients other than Apollo.
281
+ EOS
282
+ end
283
+ end
284
+
285
+ entity_types = state.object_types_by_name.values.select do |object_type|
286
+ object_type.directives.any? do |directive|
287
+ directive.name == "key" && directive.arguments[:resolvable]
288
+ end
289
+ end
290
+
291
+ validate_entity_types_can_all_be_resolved(entity_types)
292
+
293
+ entity_type_names = entity_types
294
+ # As per the GraphQL spec[1], only object types can be in a union, and interface
295
+ # types cannot be in a union. The GraphQL gem has validation[2] for this and will raise
296
+ # an error if we violate it, so we must filter to only object types here.
297
+ #
298
+ # [1] https://spec.graphql.org/October2021/#sec-Unions.Type-Validation
299
+ # [2] https://github.com/rmosolgo/graphql-ruby/pull/3024
300
+ .grep(ElasticGraph::SchemaDefinition::SchemaElements::ObjectType)
301
+ .map(&:name)
302
+
303
+ unless entity_type_names.empty?
304
+ apollo_union_type "_Entity" do |t|
305
+ t.extend EntityTypeExtension
306
+ t.documentation <<~EOS
307
+ A union type required by the [Apollo Federation subgraph
308
+ spec](https://www.apollographql.com/docs/federation/subgraph-spec/#union-_entity):
309
+
310
+ > **⚠️ This union type is generated dynamically based on the input subgraph schema!**
311
+ >
312
+ > This union's possible types must include all entities that the subgraph defines.
313
+ > It's the return type of the `Query._entities` field, which the graph router uses
314
+ > to directly access a subgraph's entity fields.
315
+ >
316
+ > For details, see [Defining the `_Entity` union](https://www.apollographql.com/docs/federation/subgraph-spec/#defining-the-_entity-union).
317
+
318
+ In an ElasticGraph schema, this is a union of all indexed types.
319
+
320
+ Not intended for use by clients other than Apollo.
321
+ EOS
322
+
323
+ t.subtypes(*entity_type_names)
324
+ end
325
+ end
326
+ end
327
+
328
+ def apollo_object_type(name, &block)
329
+ object_type name do |type|
330
+ type.graphql_only true
331
+ yield type
332
+ end
333
+ end
334
+
335
+ def apollo_union_type(name, &block)
336
+ union_type name do |type|
337
+ type.graphql_only true
338
+ yield type
339
+ end
340
+ end
341
+
342
+ def apollo_scalar_type(name, &block)
343
+ scalar_type name do |type|
344
+ type.graphql_only true
345
+ yield type
346
+ end
347
+ end
348
+
349
+ def apollo_enum_type(name, &block)
350
+ enum_type name do |type|
351
+ type.graphql_only true
352
+ yield type
353
+ end
354
+ end
355
+
356
+ # state comes from object we extend with this module.
357
+ # @dynamic state
358
+
359
+ def validate_entity_types_can_all_be_resolved(entity_types)
360
+ entity_types.reject(&:indexed?).each do |object_type|
361
+ key_field_names = object_type.directives
362
+ .select { |dir| dir.name == "key" }
363
+ # https://rubular.com/r/JEuYKzqnyR712A
364
+ .flat_map { |dir| dir.arguments[:fields].to_s.gsub(/{.*}/, "").split(" ") }
365
+ .to_set
366
+ unresolvable_fields = object_type.graphql_fields_by_name.values.reject do |field|
367
+ key_field_names.include?(field.name) ||
368
+ field.relationship ||
369
+ field.directives.any? { |directive| directive.name == "external" }
370
+ end
371
+ if unresolvable_fields.any?
372
+ raise SchemaError, <<~EOS
373
+ `#{object_type.name}` has fields that ElasticGraph will be unable to resolve when Apollo requests it as an entity:
374
+ #{unresolvable_fields.map { |field| " * `#{field.name}`" }.join("\n")}
375
+ On a non-indexed entity type like this, ElasticGraph can only resolve `@key` fields and `relates_to_(one|many)` fields.
376
+ To fix this, add these fields to the `apollo_key`, redefine them as a relationship, use `field.apollo_external` so Apollo
377
+ knows how to treat them, or remove them.
378
+ EOS
379
+ end
380
+ end
381
+ end
382
+ end
383
+ end
384
+ end
385
+ end
@@ -0,0 +1,119 @@
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
+ module ElasticGraph
10
+ module Apollo
11
+ module SchemaDefinition
12
+ module ApolloDirectives
13
+ module Authenticated
14
+ # Extension method designed to support Apollo's authenticated directive:
15
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#authenticated
16
+ def apollo_authenticated
17
+ directive "authenticated"
18
+ end
19
+ end
20
+
21
+ module Extends
22
+ # Extension method designed to support Apollo's extends directive:
23
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#extends
24
+ def apollo_extends
25
+ directive "extends"
26
+ end
27
+ end
28
+
29
+ module External
30
+ # Extension method designed to support Apollo's external directive:
31
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#external
32
+ def apollo_external
33
+ directive "external"
34
+ end
35
+ end
36
+
37
+ module Inaccessible
38
+ # Extension method designed to support Apollo's inaccessible directive:
39
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#inaccessible
40
+ def apollo_inaccessible
41
+ directive "inaccessible"
42
+ end
43
+ end
44
+
45
+ module InterfaceObject
46
+ # Extension method designed to support Apollo's interfaceObject directive:
47
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#interfaceObject
48
+ def apollo_interface_object
49
+ directive "interfaceObject"
50
+ end
51
+ end
52
+
53
+ module Key
54
+ # Extension method designed to support Apollo's key directive:
55
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#key
56
+ def apollo_key(fields:, resolvable: true)
57
+ directive "key", fields: fields, resolvable: resolvable
58
+ end
59
+ end
60
+
61
+ module Override
62
+ # Extension method designed to support Apollo's override directive:
63
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#override
64
+ def apollo_override(from:)
65
+ directive "override", from: from
66
+ end
67
+ end
68
+
69
+ module Policy
70
+ # Extension method designed to support Apollo's policy directive:
71
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#policy
72
+ def apollo_policy(policies:)
73
+ directive "policy", policies: policies
74
+ end
75
+ end
76
+
77
+ module Provides
78
+ # Extension method designed to support Apollo's provides directive:
79
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#provides
80
+ def apollo_provides(fields:)
81
+ directive "provides", fields: fields
82
+ end
83
+ end
84
+
85
+ module Requires
86
+ # Extension method designed to support Apollo's requires directive:
87
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#requires
88
+ def apollo_requires(fields:)
89
+ directive "requires", fields: fields
90
+ end
91
+ end
92
+
93
+ module RequiresScopes
94
+ # Extension method designed to support Apollo's requiresScopes directive:
95
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#requiresscopes
96
+ def apollo_requires_scopes(scopes:)
97
+ directive "requiresScopes", scopes: scopes
98
+ end
99
+ end
100
+
101
+ module Shareable
102
+ # Extension method designed to support Apollo's shareable directive:
103
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#shareable
104
+ def apollo_shareable
105
+ directive "shareable"
106
+ end
107
+ end
108
+
109
+ module Tag
110
+ # Extension method designed to support Apollo's tag directive:
111
+ # https://www.apollographql.com/docs/federation/federated-types/federated-directives/#tag
112
+ def apollo_tag(name:)
113
+ directive "tag", name: name
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,20 @@
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/apollo/schema_definition/apollo_directives"
10
+
11
+ module ElasticGraph
12
+ module Apollo
13
+ module SchemaDefinition
14
+ module ArgumentExtension
15
+ include ApolloDirectives::Inaccessible
16
+ include ApolloDirectives::Tag
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
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
+ module ElasticGraph
10
+ module Apollo
11
+ module SchemaDefinition
12
+ # The Apollo `_Entity` type is a type union of _all_ entity subtypes in an ElasticGraph schema.
13
+ # However, unlike a normal union type:
14
+ #
15
+ # - `_Entity` is never an indexed type, and should not be treated as one (even though its subtypes are all indexed, which would
16
+ # usually cause it to be treated as indexed!).
17
+ # - A merged set of `graphql_fields_by_name` cannot be safely computed. That method raises errors if a field with the same name
18
+ # has conflicting definitions on different subtypes, but we must allow that on `_Entity` subtypes.
19
+ module EntityTypeExtension
20
+ def graphql_fields_by_name
21
+ {}
22
+ end
23
+
24
+ def indexed?
25
+ false
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
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/apollo/schema_definition/apollo_directives"
10
+
11
+ module ElasticGraph
12
+ module Apollo
13
+ module SchemaDefinition
14
+ module EnumTypeExtension
15
+ include ApolloDirectives::Authenticated
16
+ include ApolloDirectives::Inaccessible
17
+ include ApolloDirectives::Policy
18
+ include ApolloDirectives::RequiresScopes
19
+ include ApolloDirectives::Tag
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
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/apollo/schema_definition/apollo_directives"
10
+
11
+ module ElasticGraph
12
+ module Apollo
13
+ module SchemaDefinition
14
+ module EnumValueExtension
15
+ include ApolloDirectives::Inaccessible
16
+ include ApolloDirectives::Tag
17
+ end
18
+ end
19
+ end
20
+ end