apollo-federation 1.0.0 → 1.1.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.
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