apollo-federation 1.0.2 → 1.1.2

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: 3bba6484dd50766b5b896bc8ba754d3f2332e6dfc8f62776f45f7378316995a4
4
- data.tar.gz: eef5867e52e8fcaa45727754f25b64ecc6d1daad69baedebe499ba354c37fe72
3
+ metadata.gz: 2363ab0739ef4119e0c16d88151e575f664c33d9a66eb2a3c6aa6756770d759c
4
+ data.tar.gz: 8ed8b3c011adcecdaaed0f5aebe7a159079c56ea2296878c6c18a93a04f257d4
5
5
  SHA512:
6
- metadata.gz: 87870f073d0957e84c6f3618acdd12cb1348cdcb7dbeba97a27f770b85cc2f29a0a241b0f308e19d231fce153bda5189795298ffa9eb980d1833f9c182c48acf
7
- data.tar.gz: d2401b6d42952a41f34fab5657331936dcc415dc06b65d79dd32add7afa26c0a8bba60a3484f033eacaa3ffca87fa76e834c9aed6001311beea645c89cc9d089
6
+ metadata.gz: 5f54f342bb56723f70550b1b0748de3c14191281f3bc1a8d496cc9b893d2c8bbb278bdf58d11f70141fd59ef1710d48d2a8de5b4b98940124edf253d688bf3fa
7
+ data.tar.gz: a762847991cda4b9526ca56686991a752fc24d33a5cbeea1a01f2b863ea2667b823fd2f750ac3c40052627c647b1bc70b9395a1e4dae58a25594b0e7f70233ad
@@ -1,3 +1,38 @@
1
+ ## [1.1.2](https://github.com/Gusto/apollo-federation-ruby/compare/v1.1.1...v1.1.2) (2020-06-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Fix _service field type owner ([#70](https://github.com/Gusto/apollo-federation-ruby/issues/70)) ([364e54f](https://github.com/Gusto/apollo-federation-ruby/commit/364e54fbb333b7cd4fe30f04bf72733b0e18d3f4))
7
+
8
+ ## [1.1.1](https://github.com/Gusto/apollo-federation-ruby/compare/v1.1.0...v1.1.1) (2020-05-29)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **lazy resolve:** Handle problem with sync resolve ([#58](https://github.com/Gusto/apollo-federation-ruby/issues/58)) ([e66c22b](https://github.com/Gusto/apollo-federation-ruby/commit/e66c22ba6fe51a7c282190ee77bd02dbfa514a66))
14
+
15
+ # [1.1.0](https://github.com/Gusto/apollo-federation-ruby/compare/v1.0.4...v1.1.0) (2020-05-27)
16
+
17
+
18
+ ### Features
19
+
20
+ * Add support for interpreter runtime ([#65](https://github.com/Gusto/apollo-federation-ruby/issues/65)) ([1957da0](https://github.com/Gusto/apollo-federation-ruby/commit/1957da0))
21
+
22
+ ## [1.0.4](https://github.com/Gusto/apollo-federation-ruby/compare/v1.0.3...v1.0.4) (2020-04-06)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * Fix spec to account for breaking change to graphql-ruby 1.10.0 ([#62](https://github.com/Gusto/apollo-federation-ruby/issues/62)) ([a631441](https://github.com/Gusto/apollo-federation-ruby/commit/a631441))
28
+
29
+ ## [1.0.3](https://github.com/Gusto/apollo-federation-ruby/compare/v1.0.2...v1.0.3) (2020-03-25)
30
+
31
+
32
+ ### Bug Fixes
33
+
34
+ * Make the tracer work with the new interpreter runtime ([#59](https://github.com/Gusto/apollo-federation-ruby/issues/59)) ([de4caf0](https://github.com/Gusto/apollo-federation-ruby/commit/de4caf0))
35
+
1
36
  ## [1.0.2](https://github.com/Gusto/apollo-federation-ruby/compare/v1.0.1...v1.0.2) (2020-02-19)
2
37
 
3
38
 
@@ -13,7 +13,14 @@ module ApolloFederation
13
13
  module ClassMethods
14
14
  extend GraphQL::Schema::Member::HasFields
15
15
 
16
- def define_entities_field(entity_type)
16
+ def define_entities_field(possible_entities)
17
+ # If there are any "entities", define the Entity union and and the Query._entities field
18
+ return if possible_entities.empty?
19
+
20
+ entity_type = Class.new(Entity) do
21
+ possible_types(*possible_entities)
22
+ end
23
+
17
24
  field(:_entities, [entity_type, null: true], null: false) do
18
25
  argument :representations, [Any], required: true
19
26
  extension(EntityTypeResolutionExtension)
@@ -32,8 +39,8 @@ module ApolloFederation
32
39
  ' but no object type of that name was found in the schema'
33
40
  end
34
41
 
35
- # TODO: Handle non-class types?
36
- type_class = type.metadata[:type_class]
42
+ # TODO: What if the type is an interface?
43
+ type_class = type.is_a?(GraphQL::ObjectType) ? type.metadata[:type_class] : type
37
44
  if type_class.respond_to?(:resolve_reference)
38
45
  result = type_class.resolve_reference(reference, context)
39
46
  else
@@ -2,17 +2,15 @@
2
2
 
3
3
  class EntityTypeResolutionExtension < GraphQL::Schema::FieldExtension
4
4
  def after_resolve(value:, context:, **_rest)
5
- synced_value =
6
- value.map do |type, result|
7
- [type, context.query.schema.sync_lazy(result)]
5
+ value.map do |type, result|
6
+ context.schema.after_lazy(result) do |resolved_value|
7
+ # TODO: This isn't 100% correct: if (for some reason) 2 different resolve_reference calls
8
+ # return the same object, it might not have the right type
9
+ # Right now, apollo-federation just adds a __typename property to the result,
10
+ # but I don't really like the idea of modifying the resolved object
11
+ context[resolved_value] = type
12
+ resolved_value
8
13
  end
9
-
10
- # TODO: This isn't 100% correct: if (for some reason) 2 different resolve_reference calls
11
- # return the same object, it might not have the right type
12
- # Right now, apollo-federation just adds a __typename property to the result,
13
- # but I don't really like the idea of modifying the resolved object
14
- synced_value.each { |type, result| context[result] = type }
15
-
16
- synced_value.map { |_, result| result }
14
+ end
17
15
  end
18
16
  end
@@ -23,17 +23,17 @@ module ApolloFederation
23
23
  end
24
24
  federation_fields.each { |field| object_node = object_node.delete_child(field) }
25
25
  end
26
- merge_directives(object_node, object_type.metadata[:federation_directives])
26
+ merge_directives(object_node, object_type)
27
27
  end
28
28
 
29
29
  def build_interface_type_node(interface_type)
30
30
  field_node = super
31
- merge_directives(field_node, interface_type.metadata[:federation_directives])
31
+ merge_directives(field_node, interface_type)
32
32
  end
33
33
 
34
34
  def build_field_node(field_type)
35
35
  field_node = super
36
- merge_directives(field_node, field_type.metadata[:federation_directives])
36
+ merge_directives(field_node, field_type)
37
37
  end
38
38
 
39
39
  def build_type_definition_nodes(types)
@@ -53,7 +53,15 @@ module ApolloFederation
53
53
  type == warden.root_type_for_operation('query')
54
54
  end
55
55
 
56
- def merge_directives(node, directives)
56
+ def merge_directives(node, type)
57
+ if type.is_a?(ApolloFederation::HasDirectives)
58
+ directives = type.federation_directives
59
+ elsif type.is_a?(GraphQL::Define::InstanceDefinable)
60
+ directives = type.metadata[:federation_directives]
61
+ else
62
+ directives = []
63
+ end
64
+
57
65
  (directives || []).each do |directive|
58
66
  node = node.merge_directive(
59
67
  name: directive[:name],
@@ -2,6 +2,8 @@
2
2
 
3
3
  module ApolloFederation
4
4
  module HasDirectives
5
+ attr_reader :federation_directives
6
+
5
7
  def add_directive(name:, arguments: nil)
6
8
  @federation_directives ||= []
7
9
  @federation_directives << { name: name, arguments: arguments }
@@ -8,48 +8,97 @@ require 'apollo-federation/federated_document_from_schema_definition.rb'
8
8
  module ApolloFederation
9
9
  module Schema
10
10
  def self.included(klass)
11
- klass.extend(ClassMethods)
11
+ if Gem::Version.new(GraphQL::VERSION) >= Gem::Version.new('1.10.0')
12
+ klass.extend(OneTenMethods)
13
+ else
14
+ klass.extend(OneNineMethods)
15
+ end
12
16
  end
13
17
 
14
- module ClassMethods
15
- def to_graphql
16
- orig_defn = super
18
+ module CommonMethods
19
+ def federation_sdl(context: nil)
20
+ document_from_schema = FederatedDocumentFromSchemaDefinition.new(self, context: context)
21
+ GraphQL::Language::Printer.new.print(document_from_schema.document)
22
+ end
23
+
24
+ private
17
25
 
18
- if query.nil?
26
+ def federation_query(query_obj)
27
+ # Build the new query object with the '_service' field
28
+ if query_obj.nil?
19
29
  base = GraphQL::Schema::Object
30
+ elsif Gem::Version.new(GraphQL::VERSION) >= Gem::Version.new('1.10.0')
31
+ base = query_obj
20
32
  else
21
- base = query.metadata[:type_class]
33
+ base = query_obj.metadata[:type_class]
22
34
  end
23
35
 
24
- federation_query = Class.new(base) do
36
+ klass = Class.new(base) do
37
+ # TODO: Maybe the name should inherit from the original Query name
38
+ # Or MAYBE we should just modify the original class?
25
39
  graphql_name 'Query'
26
40
 
27
41
  include EntitiesField
28
42
  include ServiceField
29
43
  end
30
44
 
45
+ klass.define_service_field
46
+ klass
47
+ end
48
+ end
49
+
50
+ # TODO: Remove these once we drop support for graphql 1.9
51
+ module OneNineMethods
52
+ include CommonMethods
53
+
54
+ def to_graphql
55
+ orig_defn = super
56
+ @query_object = federation_query(query)
57
+
31
58
  possible_entities = orig_defn.types.values.select do |type|
32
59
  !type.introspection? && !type.default_scalar? && type.is_a?(GraphQL::ObjectType) &&
33
60
  type.metadata[:federation_directives]&.any? { |directive| directive[:name] == 'key' }
34
61
  end
62
+ @query_object.define_entities_field(possible_entities)
35
63
 
36
- if !possible_entities.empty?
37
- entity_type = Class.new(Entity) do
38
- possible_types(*possible_entities)
64
+ super
65
+ end
66
+ end
67
+
68
+ module OneTenMethods
69
+ include CommonMethods
70
+
71
+ def query(new_query_object = nil)
72
+ if new_query_object
73
+ @orig_query_object = new_query_object
74
+ else
75
+ if !@federation_query_object
76
+ @federation_query_object = federation_query(@orig_query_object)
77
+ @federation_query_object.define_entities_field(schema_entities)
78
+
79
+ super(@federation_query_object)
39
80
  end
40
- # TODO: Should/can we encapsulate all of this inside the module? What's the best/most Ruby
41
- # way to split this out?
42
- federation_query.define_entities_field(entity_type)
81
+
82
+ super
43
83
  end
84
+ end
44
85
 
45
- query(federation_query)
86
+ private
46
87
 
47
- super
48
- end
88
+ def schema_entities
89
+ # Create a temporary schema that inherits from this one to extract the types
90
+ types_schema = Class.new(self)
91
+ # Add the original query objects to the types. We have to use orphan_types here to avoid
92
+ # infinite recursion
93
+ types_schema.orphan_types(@orig_query_object)
49
94
 
50
- def federation_sdl(context: nil)
51
- document_from_schema = FederatedDocumentFromSchemaDefinition.new(self, context: context)
52
- GraphQL::Language::Printer.new.print(document_from_schema.document)
95
+ # Walk through all of the types and determine which ones are entities (any type with a
96
+ # "key" directive)
97
+ types_schema.types.values.select do |type|
98
+ # TODO: Interfaces can have a key...
99
+ !type.introspection? && type.include?(ApolloFederation::Object) &&
100
+ type.federation_directives&.any? { |directive| directive[:name] == 'key' }
101
+ end
53
102
  end
54
103
  end
55
104
  end
@@ -5,12 +5,21 @@ require 'apollo-federation/service'
5
5
 
6
6
  module ApolloFederation
7
7
  module ServiceField
8
- extend GraphQL::Schema::Member::HasFields
8
+ def self.included(base)
9
+ base.extend(ClassMethods)
10
+ end
11
+
12
+ module ClassMethods
13
+ extend GraphQL::Schema::Member::HasFields
9
14
 
10
- field(:_service, Service, null: false)
15
+ def define_service_field
16
+ field(:_service, Service, null: false)
17
+ end
18
+ end
11
19
 
12
20
  def _service
13
- { sdl: context.schema.class.federation_sdl(context: context) }
21
+ schema_class = context.schema.is_a?(GraphQL::Schema) ? context.schema.class : context.schema
22
+ { sdl: schema_class.federation_sdl(context: context) }
14
23
  end
15
24
  end
16
25
  end
@@ -103,7 +103,7 @@ module ApolloFederation
103
103
  # because we don't have the error `location` here.
104
104
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
105
105
  def self.execute_field(data, &block)
106
- context = data.fetch(:context) || data.fetch(:query).context
106
+ context = data.fetch(:context, nil) || data.fetch(:query).context
107
107
  return block.call unless context && context[:tracing_enabled]
108
108
 
109
109
  start_time_nanos = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
@@ -116,16 +116,17 @@ module ApolloFederation
116
116
 
117
117
  end_time_nanos = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
118
118
 
119
- # interpreter runtime
119
+ # legacy runtime
120
120
  if data.include?(:context)
121
121
  path = context.path
122
122
  field_name = context.field.graphql_name
123
123
  field_type = context.field.type.to_s
124
124
  parent_type = context.parent_type.graphql_name
125
- else # legacy runtime
125
+ else # interpreter runtime
126
126
  path = data.fetch(:path)
127
- field_name = data.fetch(:field).graphql_name
128
- field_type = data.fetch(:field).type.unwrap.graphql_name
127
+ field = data.fetch(:field)
128
+ field_name = field.graphql_name
129
+ field_type = field.type.to_type_signature
129
130
  parent_type = data.fetch(:owner).graphql_name
130
131
  end
131
132
 
@@ -147,7 +148,7 @@ module ApolloFederation
147
148
  # Optional Step 3:
148
149
  # Overwrite the end times on the trace node if the resolver was lazy.
149
150
  def self.execute_field_lazy(data, &block)
150
- context = data.fetch(:context) || data.fetch(:query).context
151
+ context = data.fetch(:context, nil) || data.fetch(:query).context
151
152
  return block.call unless context && context[:tracing_enabled]
152
153
 
153
154
  begin
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ApolloFederation
4
- VERSION = '1.0.2'
4
+ VERSION = '1.1.2'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apollo-federation
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noa Elad
@@ -9,20 +9,20 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-02-19 00:00:00.000000000 Z
12
+ date: 2020-06-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: graphql
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: 1.9.8
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
27
  version: 1.9.8
28
28
  - !ruby/object:Gem::Dependency