Skip to content

Commit

Permalink
Rename federation resolver configuration to representations. (#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
gmac authored Jun 2, 2024
1 parent 61775c0 commit 5aca51a
Show file tree
Hide file tree
Showing 11 changed files with 44 additions and 30 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ type Query {
The `@stitch` directive can be added to class-based schemas with a directive class:

```ruby
class StitchField < GraphQL::Schema::Directive
class StitchingResolver < GraphQL::Schema::Directive
graphql_name "stitch"
locations FIELD_DEFINITION
repeatable true
Expand All @@ -274,7 +274,7 @@ end

class Query < GraphQL::Schema::Object
field :product, Product, null: false do
directive StitchField, key: "id"
directive StitchingResolver, key: "id"
argument :id, ID, required: true
end
end
Expand All @@ -284,7 +284,7 @@ The `@stitch` directive can be exported from a class-based schema to an SDL stri

#### SDL-based schemas

A clean SDL string may also have stitching directives applied via static configuration by passing a `stitch` array in [location settings](./docs/composer.md#performing-composition):
A clean schema may also have stitching directives applied via static configuration by passing a `stitch` array in [location settings](./docs/composer.md#performing-composition):

```ruby
sdl_string = <<~GRAPHQL
Expand Down Expand Up @@ -316,7 +316,7 @@ supergraph = GraphQL::Stitching::Composer.new.perform({
The library is configured to use a `@stitch` directive by default. You may customize this by setting a new name during initialization:

```ruby
GraphQL::Stitching.stitch_directive = "merge"
GraphQL::Stitching.stitch_directive = "resolver"
```

## Executables
Expand Down
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ Major components include:

Additional topics:

- [Stitching mechanics](./mechanics.md) - learn more about building for stitching.
- [Stitching mechanics](./mechanics.md) - more about building for stitching and how it operates.
- [Federation entities](./federation_entities.md) - more about Apollo Federation compatibility.
2 changes: 1 addition & 1 deletion lib/graphql/stitching/composer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ def extract_resolvers(type_name, types_by_location)
field: field_candidate.name,
arg: argument_name,
list: resolver_structure.first.list?,
federation: config.federation,
representations: config.representations,
)
end
end
Expand Down
10 changes: 5 additions & 5 deletions lib/graphql/stitching/composer/resolver_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def extract_federation_entities(schema, location)
memo[field_path] << new(
key: key,
type_name: entity_type.graphql_name,
federation: true,
representations: true,
)
end
end
Expand All @@ -48,7 +48,7 @@ def from_kwargs(kwargs)
new(
key: kwargs[:key],
type_name: kwargs[:type_name] || kwargs[:typeName],
federation: kwargs[:federation] || false,
representations: kwargs[:representations] || false,
)
end

Expand All @@ -61,12 +61,12 @@ def federation_entities_schema?(schema)
end
end

attr_reader :key, :type_name, :federation
attr_reader :key, :type_name, :representations

def initialize(key:, type_name:, federation: false)
def initialize(key:, type_name:, representations: false)
@key = key
@type_name = type_name
@federation = federation
@representations = representations
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/graphql/stitching/executor/resolver_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ def build_document(origin_sets_by_operation, operation_name = nil, operation_dir
if resolver.list?
input = origin_set.each_with_index.reduce(String.new) do |memo, (origin_obj, index)|
memo << "," if index > 0
memo << build_key(resolver.key, origin_obj, federation: resolver.federation)
memo << build_key(resolver.key, origin_obj, as_representation: resolver.representations?)
memo
end

"_#{batch_index}_result: #{resolver.field}(#{resolver.arg}:[#{input}]) #{op.selections}"
else
origin_set.map.with_index do |origin_obj, index|
input = build_key(resolver.key, origin_obj, federation: resolver.federation?)
input = build_key(resolver.key, origin_obj, as_representation: resolver.representations?)
"_#{batch_index}_#{index}_result: #{resolver.field}(#{resolver.arg}:#{input}) #{op.selections}"
end
end
Expand Down Expand Up @@ -93,9 +93,9 @@ def build_document(origin_sets_by_operation, operation_name = nil, operation_dir
return doc, variable_defs.keys
end

def build_key(key, origin_obj, federation: false)
def build_key(key, origin_obj, as_representation: false)
key_value = JSON.generate(origin_obj[ExportSelection.key(key)])
if federation
if as_representation
"{ __typename: \"#{origin_obj[ExportSelection.typename_node.alias]}\", #{key}: #{key_value} }"
else
key_value
Expand Down
19 changes: 16 additions & 3 deletions lib/graphql/stitching/resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,30 @@ module GraphQL
module Stitching
# Defines a root resolver query that provides direct access to an entity type.
Resolver = Struct.new(
# location name providing the resolver query.
:location,

# name of merged type fulfilled through this resolver.
:type_name,

# a key field to select from prior locations, sent as resolver argument.
:key,

# name of the root field to query.
:field,

# name of the root field argument used to send the key.
:arg,

# specifies when the resolver is a list query.
:list,
:federation,

# specifies that keys should be sent as JSON representations with __typename and key.
:representations,
keyword_init: true
) do
alias_method :list?, :list
alias_method :federation?, :federation
alias_method :representations?, :representations

def as_json
{
Expand All @@ -24,7 +37,7 @@ def as_json
field: field,
arg: arg,
list: list,
federation: federation,
representations: representations,
}.tap(&:compact!)
end
end
Expand Down
6 changes: 3 additions & 3 deletions lib/graphql/stitching/supergraph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def from_definition(schema, executables:)
field: kwargs[:field],
arg: kwargs[:arg],
list: kwargs[:list] || false,
federation: kwargs[:federation] || false,
representations: kwargs[:representations] || false,
)
end

Expand Down Expand Up @@ -130,7 +130,7 @@ def to_definition
kwargs[:field] == resolver.field &&
kwargs[:arg] == resolver.arg &&
kwargs.fetch(:list, false) == resolver.list &&
kwargs.fetch(:federation, false) == resolver.federation
kwargs.fetch(:representations, false) == resolver.representations
end

type.directive(ResolverDirective, **{
Expand All @@ -140,7 +140,7 @@ def to_definition
field: resolver.field,
arg: resolver.arg,
list: resolver.list || nil,
federation: resolver.federation || nil,
representations: resolver.representations || nil,
}.tap(&:compact!)) if existing.nil?
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/graphql/stitching/supergraph/resolver_directive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class ResolverDirective < GraphQL::Schema::Directive
argument :field, String, required: true
argument :arg, String, required: true
argument :list, Boolean, required: false
argument :federation, Boolean, required: false
argument :representations, Boolean, required: false
repeatable true
end
end
Expand Down
4 changes: 2 additions & 2 deletions test/graphql/stitching/composer/configuration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def test_perform_with_static_resolver_config
key: "id",
arg: "id",
list: false,
federation: false,
representations: false,
),
GraphQL::Stitching::Resolver.new(
location: "bravo",
Expand All @@ -60,7 +60,7 @@ def test_perform_with_static_resolver_config
key: "id",
arg: "key",
list: false,
federation: false,
representations: false,
),
]
}
Expand Down
10 changes: 5 additions & 5 deletions test/graphql/stitching/composer/merge_resolvers_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def test_creates_resolver_map
field: "a",
arg: "id",
list: false,
federation: false,
representations: false,
type_name: "Test"
),
GraphQL::Stitching::Resolver.new(
Expand All @@ -25,7 +25,7 @@ def test_creates_resolver_map
field: "b",
arg: "ids",
list: true,
federation: false,
representations: false,
type_name: "Test"
),
],
Expand Down Expand Up @@ -130,7 +130,7 @@ def test_builds_union_resolvers_for_select_typenames
type Query {
fruitA(id:ID!):Fruit
@stitch(key: "id", typeName: "Apple")
@stitch(key: "id", typeName: "Banana", federation: true)
@stitch(key: "id", typeName: "Banana", representations: true)
coconut(id: ID!): Coconut
@stitch(key: "id")
}
Expand All @@ -151,8 +151,8 @@ def test_builds_union_resolvers_for_select_typenames
assert_equal ["coconut", "fruitB"], supergraph.resolvers["Coconut"].map(&:field).sort
assert_equal ["fruitB"], supergraph.resolvers["Fruit"].map(&:field).sort

assert_equal false, supergraph.resolvers["Apple"].find { _1.location == "a" }.federation
assert_equal true, supergraph.resolvers["Banana"].find { _1.location == "a" }.federation
assert_equal false, supergraph.resolvers["Apple"].find { _1.location == "a" }.representations?
assert_equal true, supergraph.resolvers["Banana"].find { _1.location == "a" }.representations?
end

def test_raises_when_given_typename_is_not_a_possible_type
Expand Down
2 changes: 1 addition & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

ComposerError = GraphQL::Stitching::Composer::ComposerError
ValidationError = GraphQL::Stitching::Composer::ValidationError
STITCH_DEFINITION = "directive @stitch(key: String!, typeName: String, federation: Boolean=false) repeatable on FIELD_DEFINITION\n"
STITCH_DEFINITION = "directive @stitch(key: String!, typeName: String, representations: Boolean=false) repeatable on FIELD_DEFINITION\n"

def squish_string(str)
str.gsub(/\s+/, " ").strip
Expand Down

0 comments on commit 5aca51a

Please sign in to comment.