diff --git a/README.md b/README.md index 58460e88..5dcececd 100644 --- a/README.md +++ b/README.md @@ -113,12 +113,12 @@ products_schema = <<~GRAPHQL } GRAPHQL -shipping_schema = <<~GRAPHQL +catalog_schema = <<~GRAPHQL directive @stitch(key: String!) repeatable on FIELD_DEFINITION type Product { id: ID! - weight: Float! + price: Float! } type Query { @@ -131,7 +131,7 @@ client = GraphQL::Stitching::Client.new(locations: { schema: GraphQL::Schema.from_definition(products_schema), executable: GraphQL::Stitching::HttpExecutable.new(url: "http://localhost:3001"), }, - shipping: { + catalog: { schema: GraphQL::Schema.from_definition(shipping_schema), executable: GraphQL::Stitching::HttpExecutable.new(url: "http://localhost:3002"), }, @@ -151,9 +151,9 @@ type Query { ``` * The `@stitch` directive is applied to a root query where the merged type may be accessed. The merged type identity is inferred from the field return. -* The `key: "id"` parameter indicates that an `{ id }` must be selected from prior locations so it may be submitted as an argument to this query. The query argument used to send the key is inferred when possible (more on arguments later). +* The `key: "id"` parameter indicates that an `{ id }` must be selected from prior locations so it may be submitted as an argument to this query. The query argument used to send the key is inferred when possible ([more on arguments](#multiple-query-arguments) later). -Each location that provides a unique variant of a type must provide one stitching query per key. The exception to this requirement are types that contain only a single key field: +Each location that provides a unique variant of a type must provide at least one stitching query. The exception to this requirement are types that contain only a single key field: ```graphql type Product { @@ -228,7 +228,7 @@ type Query { } ``` -The `@stitch` directive is also repeatable (_requires graphql-ruby >= v2.0.15_), allowing a single query to associate with multiple keys: +The `@stitch` directive is also repeatable, allowing a single query to associate with multiple keys: ```graphql type Product { @@ -311,16 +311,15 @@ The [Apollo Federation specification](https://www.apollographql.com/docs/federat The composer will automatcially detect and stitch schemas with an `_entities` query, for example: ```ruby -accounts_schema = <<~GRAPHQL +products_schema = <<~GRAPHQL directive @key(fields: String!) repeatable on OBJECT - type User @key(fields: "id") { + type Product @key(fields: "id") { id: ID! name: String! - address: String! } - union _Entity = User + union _Entity = Product scalar _Any type Query { @@ -329,15 +328,15 @@ accounts_schema = <<~GRAPHQL } GRAPHQL -comments_schema = <<~GRAPHQL +catalog_schema = <<~GRAPHQL directive @key(fields: String!) repeatable on OBJECT - type User @key(fields: "id") { + type Product @key(fields: "id") { id: ID! - comments: [String!]! + price: Float! } - union _Entity = User + union _Entity = Product scalar _Any type Query { @@ -346,12 +345,12 @@ comments_schema = <<~GRAPHQL GRAPHQL client = GraphQL::Stitching::Client.new(locations: { - accounts: { - schema: GraphQL::Schema.from_definition(accounts_schema), + products: { + schema: GraphQL::Schema.from_definition(products_schema), executable: ..., }, - comments: { - schema: GraphQL::Schema.from_definition(comments_schema), + catalog: { + schema: GraphQL::Schema.from_definition(catalog_schema), executable: ..., }, }) diff --git a/lib/graphql/stitching/client.rb b/lib/graphql/stitching/client.rb index a369bfe3..825f657e 100644 --- a/lib/graphql/stitching/client.rb +++ b/lib/graphql/stitching/client.rb @@ -20,6 +20,10 @@ def initialize(locations: nil, supergraph: nil, composer: nil) composer ||= GraphQL::Stitching::Composer.new composer.perform(locations) end + + @on_cache_read = nil + @on_cache_write = nil + @on_error = nil end def execute(query:, variables: nil, operation_name: nil, context: nil, validate: true) diff --git a/lib/graphql/stitching/composer.rb b/lib/graphql/stitching/composer.rb index 6a721f61..00005423 100644 --- a/lib/graphql/stitching/composer.rb +++ b/lib/graphql/stitching/composer.rb @@ -39,6 +39,12 @@ def initialize( @directive_kwarg_merger = directive_kwarg_merger || BASIC_VALUE_MERGER @root_field_location_selector = root_field_location_selector || BASIC_ROOT_FIELD_LOCATION_SELECTOR @stitch_directives = {} + + @field_map = nil + @boundary_map = nil + @mapped_type_names = nil + @candidate_directives_by_name_and_location = nil + @schema_directives = nil end def perform(locations_input) diff --git a/lib/graphql/stitching/export_selection.rb b/lib/graphql/stitching/export_selection.rb index ccf0b455..9cc3eb65 100644 --- a/lib/graphql/stitching/export_selection.rb +++ b/lib/graphql/stitching/export_selection.rb @@ -8,6 +8,8 @@ class ExportSelection EXPORT_PREFIX = "_export_" class << self + @typename_node = nil + def key?(name) return false unless name diff --git a/lib/graphql/stitching/request.rb b/lib/graphql/stitching/request.rb index 514c38b2..db9e4207 100644 --- a/lib/graphql/stitching/request.rb +++ b/lib/graphql/stitching/request.rb @@ -9,6 +9,15 @@ class Request attr_reader :document, :variables, :operation_name, :context def initialize(document, operation_name: nil, variables: nil, context: nil) + @string = nil + @digest = nil + @normalized_string = nil + @normalized_digest = nil + @operation = nil + @operation_directives = nil + @variable_definitions = nil + @fragment_definitions = nil + @document = if document.is_a?(String) @string = document GraphQL.parse(document) diff --git a/lib/graphql/stitching/shaper.rb b/lib/graphql/stitching/shaper.rb index b0790a23..f5773686 100644 --- a/lib/graphql/stitching/shaper.rb +++ b/lib/graphql/stitching/shaper.rb @@ -9,6 +9,7 @@ class Shaper def initialize(supergraph:, request:) @supergraph = supergraph @request = request + @root_type = nil end def perform!(raw) diff --git a/lib/graphql/stitching/supergraph.rb b/lib/graphql/stitching/supergraph.rb index c23c4924..5879f336 100644 --- a/lib/graphql/stitching/supergraph.rb +++ b/lib/graphql/stitching/supergraph.rb @@ -97,6 +97,10 @@ def initialize(schema:, fields:, boundaries:, executables:) @possible_keys_by_type_and_location = {} @memoized_schema_possible_types = {} @memoized_schema_fields = {} + @memoized_introspection_types = nil + @memoized_schema_types = nil + @fields_by_type_and_location = nil + @locations_by_type = nil # add introspection types into the fields mapping @locations_by_type_and_field = memoized_introspection_types.each_with_object(fields) do |(type_name, type), memo|