graphql-stitching 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f67a4b892fba612e2e38552ae0a0f681ed0fdc136c04ecef4d2c01692eed9eb8
4
- data.tar.gz: 3db164c53dc67d64b7364ba5a17186e3eb612074993b21df5f9a8b059fca9f89
3
+ metadata.gz: a05f9ff15f40a886a20136cdaf5323cf37a59e7d98de27cc19cf7e600feb48e2
4
+ data.tar.gz: 7727f7394bb99abcb3c3a448f1ebf8b3bd5f9b7a2fd74e9bc741285f401a23cc
5
5
  SHA512:
6
- metadata.gz: 8d687747a19a25a69b1c998910265a183bdb22338fec5e9787412ca5c1cdfc5e0b838bb49ce4942ce41dec0e000e0ddc35bdf07368a7a772751ffc5342b7ee48
7
- data.tar.gz: f4419aa525964b37db62ce2343d11914ac56677825c8f1450c5187465b2f28e3a740acf6779309bdb0a5fbd41829054101aed4c9d0eb764882759c50bbf1b641
6
+ metadata.gz: f8993da51f8bd18ec1e590727a24bcba8690831e006a1a3fc861cfaa83b9794b94f90fb0e458919d7997d67606ae8ece4acfdd8a3a0d6fe669e7971b01232cf3
7
+ data.tar.gz: 1032ed3279a98d1bc52db321a49a0a47d78dfb00cf9a8c922d1e77217ac837f8695c146908767ec398620f42a816f92eefc339d1fde970fe543904a6a30976f5
data/README.md CHANGED
@@ -92,7 +92,7 @@ To facilitate this merging of types, stitching must know how to cross-reference
92
92
  directive @stitch(key: String!) repeatable on FIELD_DEFINITION
93
93
  ```
94
94
 
95
- This directive is applied to root queries where a merged type may be accessed in each location, and a `key` argument specifies a field needed from other locations to be used as a query argument.
95
+ This directive (or [static configuration](#sdl-based-schemas)) is applied to root queries where a merged type may be accessed in each location, and a `key` argument specifies a field needed from other locations to be used as a query argument.
96
96
 
97
97
  ```ruby
98
98
  products_schema = <<~GRAPHQL
@@ -219,7 +219,7 @@ type Query {
219
219
  }
220
220
  ```
221
221
 
222
- The `@stitch` directive is also repeatable (_requires graphql-ruby v2.0.15_), allowing a single query to associate with multiple keys:
222
+ The `@stitch` directive is also repeatable (_requires graphql-ruby >= v2.0.15_), allowing a single query to associate with multiple keys:
223
223
 
224
224
  ```graphql
225
225
  type Product {
@@ -251,6 +251,35 @@ class Query < GraphQL::Schema::Object
251
251
  end
252
252
  ```
253
253
 
254
+ The `@stitch` directive can be exported from a class-based schema to an SDL string by calling `schema.to_definition`.
255
+
256
+ #### SDL-based schemas
257
+
258
+ A clean SDL string may also have stitching directives applied via static configuration using the `GraphQL::Stitching` module to build the SDL into a schema:
259
+
260
+ ```ruby
261
+ sdl_string = <<~GRAPHQL
262
+ type Product {
263
+ id: ID!
264
+ upc: ID!
265
+ }
266
+ type Query {
267
+ productById(id: ID!): Product
268
+ productByUpc(upc: ID!): Product
269
+ }
270
+ GRAPHQL
271
+
272
+ decorated_schema = GraphQL::Stitching.schema_from_definition(sdl_string, stitch_directives: [
273
+ { type_name: "Query", field_name: "productById", key: "id" },
274
+ { type_name: "Query", field_name: "productByUpc", key: "upc" },
275
+ ])
276
+
277
+ supergraph = GraphQL::Stitching::Composer.new(schemas: {
278
+ "products" => decorated_schema,
279
+ # ...
280
+ })
281
+ ```
282
+
254
283
  #### Custom directive names
255
284
 
256
285
  The library is configured to use a `@stitch` directive by default. You may customize this by setting a new name during initialization:
data/docs/supergraph.md CHANGED
@@ -30,7 +30,7 @@ end
30
30
 
31
31
  ### Export and caching
32
32
 
33
- A Supergraph is designed to be composed, cached, and restored. Calling the `export` method will return an SDL (Schema Definition Language) print of the combined graph schema and a deletation mapping hash. These can be persisted in any raw format that suits your stack:
33
+ A Supergraph is designed to be composed, cached, and restored. Calling the `export` method will return an SDL (Schema Definition Language) print of the combined graph schema and a delegation mapping hash. These can be persisted in any raw format that suits your stack:
34
34
 
35
35
  ```ruby
36
36
  supergraph_sdl, delegation_map = supergraph.export
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  end
27
27
  spec.require_paths = ['lib']
28
28
 
29
- spec.add_runtime_dependency 'graphql', '~> 2.0.3'
29
+ spec.add_runtime_dependency 'graphql', '>= 1.13.9'
30
30
 
31
31
  spec.add_development_dependency 'bundler', '~> 2.0'
32
32
  spec.add_development_dependency 'rake', '~> 12.0'
@@ -67,7 +67,17 @@ module GraphQL
67
67
  end
68
68
 
69
69
  def validate_as_shared(ctx, type, subschema_types_by_location)
70
- expected_fields = type.fields.keys.sort
70
+ expected_fields = begin
71
+ type.fields.keys.sort
72
+ rescue StandardError => e
73
+ # bug with inherited interfaces in older versions of GraphQL
74
+ if type.interfaces.any? { _1.is_a?(GraphQL::Schema::LateBoundType) }
75
+ raise Composer::ComposerError, "Merged interface inheritance requires GraphQL >= v2.0.3"
76
+ else
77
+ raise e
78
+ end
79
+ end
80
+
71
81
  subschema_types_by_location.each do |location, subschema_type|
72
82
  if subschema_type.fields.keys.sort != expected_fields
73
83
  raise Composer::ValidationError, "Shared type `#{type.graphql_name}` must have consistent fields across locations,
@@ -96,7 +96,7 @@ module GraphQL
96
96
  end
97
97
  end
98
98
 
99
- # { "Type" => ["location1", "location2", ...] }
99
+ # "Type" => ["location1", "location2", ...]
100
100
  def locations_by_type
101
101
  @locations_by_type ||= @locations_by_type_and_field.each_with_object({}) do |(type_name, fields), memo|
102
102
  memo[type_name] = fields.values.flatten.uniq
@@ -104,7 +104,7 @@ module GraphQL
104
104
  end
105
105
 
106
106
  # collects all possible boundary keys for a given type
107
- # { "Type" => ["id", ...] }
107
+ # ("Type") => ["id", ...]
108
108
  def possible_keys_for_type(type_name)
109
109
  @possible_keys_by_type[type_name] ||= begin
110
110
  keys = @boundaries[type_name].map { _1["selection"] }
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GraphQL
4
4
  module Stitching
5
- VERSION = "0.2.2"
5
+ VERSION = "0.2.3"
6
6
  end
7
7
  end
@@ -19,6 +19,56 @@ module GraphQL
19
19
  def stitching_directive_names
20
20
  [stitch_directive]
21
21
  end
22
+
23
+ def schema_from_definition(sdl, stitch_directives:)
24
+ ast = GraphQL.parse(sdl)
25
+
26
+ if stitch_directives&.any?
27
+ directive_definition = ast.definitions.find do |d|
28
+ d.is_a?(GraphQL::Language::Nodes::DirectiveDefinition) && d.name == stitch_directive
29
+ end
30
+
31
+ if !directive_definition
32
+ directive_sdl = "directive @#{stitch_directive}(key: String!) repeatable on FIELD_DEFINITION"
33
+ directive_definition = GraphQL.parse(directive_sdl).definitions.first
34
+ ast.send(:merge!, { definitions: [directive_definition, *ast.definitions] })
35
+ end
36
+ end
37
+
38
+ stitch_directives.each do |config|
39
+ config[:type_name] ||= "Query"
40
+
41
+ type_node = ast.definitions.find do |d|
42
+ d.is_a?(GraphQL::Language::Nodes::ObjectTypeDefinition) && d.name == config[:type_name]
43
+ end
44
+
45
+ raise StitchingError, "invalid type name `#{config[:type_name]}`." unless type_node
46
+
47
+ field_node = type_node.fields.find do |f|
48
+ f.name == config[:field_name]
49
+ end
50
+
51
+ raise StitchingError, "invalid field name `#{config[:field_name]}`." unless field_node
52
+
53
+ field_node.send(:merge!, {
54
+ directives: [
55
+ *field_node.directives,
56
+ GraphQL::Language::Nodes::Directive.new(
57
+ arguments: [GraphQL::Language::Nodes::Argument.new(name: "key", value: config[:key])],
58
+ name: stitch_directive,
59
+ )
60
+ ]
61
+ })
62
+ end
63
+
64
+ if GraphQL::Schema::BuildFromDefinition.method(:from_document).parameters.first.last == :document
65
+ # GraphQL v1.13.x
66
+ GraphQL::Schema::BuildFromDefinition.from_document(ast, default_resolve: nil)
67
+ else
68
+ # GraphQL v2
69
+ GraphQL::Schema::BuildFromDefinition.from_document(GraphQL::Schema, ast, default_resolve: nil)
70
+ end
71
+ end
22
72
  end
23
73
  end
24
74
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-stitching
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg MacWilliam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-21 00:00:00.000000000 Z
11
+ date: 2023-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 2.0.3
19
+ version: 1.13.9
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 2.0.3
26
+ version: 1.13.9
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement