apollo-federation 1.0.0 → 1.1.0

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: 1c9617a66dc6c2f6494bffedd691cc4058c9f3caddb3ebb597eb2379baeb0849
4
- data.tar.gz: 53e28fe56d42405030a674d7d4f27bc0360fd7768e2f635d57eb27923cc1f94a
3
+ metadata.gz: c06244e9136f28d4a4c15906ab176c9d4d83ea685c1b2a73bcac91d6f1ac8e65
4
+ data.tar.gz: f9f9eec152182226fe35fc07f97f7e4a787a7ba2cd45442f2725f8c7a593a28e
5
5
  SHA512:
6
- metadata.gz: 7163ef5206d0d86cbf97830b965561bb6d9d5e3b35a1370053fda2d4285a95c45d5fd9eb820c258a2f0f7caabcd4ad63e4884ecf346e68a94f971a3c034741a9
7
- data.tar.gz: 782dcece3899ee1edce74aa137cd1ccddd0778acc6a548a3b090d89deba1ca67f7a6adaba7344c100fd83d7f36250ef303457db2fc7f797c62eba51e3667b372
6
+ metadata.gz: 451f1e7582fcbe3a85061755ef537678c819532879994584243c9ce9424883496d4ae9db79926dd25a7b5baab374395438d670e0c1967735ca31cf07519c5058
7
+ data.tar.gz: b118eda2b44fb44499745b4161cb75fc75dc59b59e29158d434b8152e23ce772b1b51c47820a8e4c9fb5c0275262b0a02d826dc1bfeda56ad3d4fac697fb3ab7
@@ -1,3 +1,38 @@
1
+ # [1.1.0](https://github.com/Gusto/apollo-federation-ruby/compare/v1.0.4...v1.1.0) (2020-05-27)
2
+
3
+
4
+ ### Features
5
+
6
+ * 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))
7
+
8
+ ## [1.0.4](https://github.com/Gusto/apollo-federation-ruby/compare/v1.0.3...v1.0.4) (2020-04-06)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * 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))
14
+
15
+ ## [1.0.3](https://github.com/Gusto/apollo-federation-ruby/compare/v1.0.2...v1.0.3) (2020-03-25)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * 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))
21
+
22
+ ## [1.0.2](https://github.com/Gusto/apollo-federation-ruby/compare/v1.0.1...v1.0.2) (2020-02-19)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * service field context ([#50](https://github.com/Gusto/apollo-federation-ruby/issues/50)) ([6dd1fe7](https://github.com/Gusto/apollo-federation-ruby/commit/6dd1fe7))
28
+
29
+ ## [1.0.1](https://github.com/Gusto/apollo-federation-ruby/compare/v1.0.0...v1.0.1) (2020-01-29)
30
+
31
+
32
+ ### Bug Fixes
33
+
34
+ * Send context to SDL generation / don't cache ([#45](https://github.com/Gusto/apollo-federation-ruby/issues/45)) ([9a29be1](https://github.com/Gusto/apollo-federation-ruby/commit/9a29be1))
35
+
1
36
  # [1.0.0](https://github.com/Gusto/apollo-federation-ruby/compare/v0.5.1...v1.0.0) (2019-12-09)
2
37
 
3
38
 
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # apollo-federation
2
2
 
3
+ [![CircleCI](https://circleci.com/gh/Gusto/apollo-federation-ruby/tree/master.svg?style=svg)](https://circleci.com/gh/Gusto/apollo-federation-ruby/tree/master)
4
+
3
5
  This gem extends the [GraphQL Ruby](http://graphql-ruby.org/) gem to add support for creating an [Apollo Federation](https://www.apollographql.com/docs/apollo-server/federation/introduction/) schema.
4
6
 
5
7
  ## DISCLAIMER
@@ -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
@@ -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,49 +8,93 @@ 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
+ 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
44
+ end
45
+ end
46
+
47
+ # TODO: Remove these once we drop support for graphql 1.9
48
+ module OneNineMethods
49
+ include CommonMethods
50
+
51
+ def to_graphql
52
+ orig_defn = super
53
+ @query_object = federation_query(query)
30
54
 
31
55
  possible_entities = orig_defn.types.values.select do |type|
32
56
  !type.introspection? && !type.default_scalar? && type.is_a?(GraphQL::ObjectType) &&
33
57
  type.metadata[:federation_directives]&.any? { |directive| directive[:name] == 'key' }
34
58
  end
59
+ @query_object.define_entities_field(possible_entities)
35
60
 
36
- if !possible_entities.empty?
37
- entity_type = Class.new(Entity) do
38
- possible_types(*possible_entities)
61
+ super
62
+ end
63
+ end
64
+
65
+ module OneTenMethods
66
+ include CommonMethods
67
+
68
+ def query(new_query_object = nil)
69
+ if new_query_object
70
+ @orig_query_object = new_query_object
71
+ else
72
+ if !@federation_query_object
73
+ @federation_query_object = federation_query(@orig_query_object)
74
+ @federation_query_object.define_entities_field(schema_entities)
75
+
76
+ super(@federation_query_object)
39
77
  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)
78
+
79
+ super
43
80
  end
81
+ end
44
82
 
45
- query(federation_query)
83
+ private
46
84
 
47
- super
48
- end
85
+ def schema_entities
86
+ # Create a temporary schema that inherits from this one to extract the types
87
+ types_schema = Class.new(self)
88
+ # Add the original query objects to the types. We have to use orphan_types here to avoid
89
+ # infinite recursion
90
+ types_schema.orphan_types(@orig_query_object)
49
91
 
50
- def federation_sdl
51
- @federation_sdl ||= begin
52
- document_from_schema = FederatedDocumentFromSchemaDefinition.new(self)
53
- GraphQL::Language::Printer.new.print(document_from_schema.document)
92
+ # Walk through all of the types and determine which ones are entities (any type with a
93
+ # "key" directive)
94
+ types_schema.types.values.select do |type|
95
+ # TODO: Interfaces can have a key...
96
+ !type.introspection? && type.include?(ApolloFederation::Object) &&
97
+ type.federation_directives&.any? { |directive| directive[:name] == 'key' }
54
98
  end
55
99
  end
56
100
  end
@@ -10,7 +10,8 @@ module ApolloFederation
10
10
  field(:_service, Service, null: false)
11
11
 
12
12
  def _service
13
- { sdl: context.schema.class.federation_sdl }
13
+ schema_class = context.schema.is_a?(GraphQL::Schema) ? context.schema.class : context.schema
14
+ { sdl: schema_class.federation_sdl(context: context) }
14
15
  end
15
16
  end
16
17
  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.0'
4
+ VERSION = '1.1.0'
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.0
4
+ version: 1.1.0
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: 2019-12-09 00:00:00.000000000 Z
12
+ date: 2020-05-27 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