Skip to content

Commit

Permalink
Merge pull request #3582 from apollographql/jbaxleyiii/reduce-interfa…
Browse files Browse the repository at this point in the history
…ce-expansion

Reduce interface expansion for types contained to a single service
  • Loading branch information
trevor-scheer committed Jan 21, 2020
2 parents 26e7b91 + 19250dc commit 604e98b
Show file tree
Hide file tree
Showing 6 changed files with 767 additions and 5 deletions.
1 change: 1 addition & 0 deletions packages/apollo-gateway/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
> The changes noted within this `vNEXT` section have not been released yet. New PRs and commits which introduce changes should include an entry in this `vNEXT` section as part of their development. When a release is being prepared, a new header will be (manually) created below and the the appropriate changes within that release will be moved into the new section.
* Fix onSchemaChange callbacks for unmanaged configs [#3605](https://github.com/apollographql/apollo-server/pull/3605)
* Reduce interface expansion for types contained to a single service [#3582](https://github.com/apollographql/apollo-server/pull/3582)

# v0.11.4

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const typeDefs = gql`
extend type Query {
product(upc: String!): Product
vehicle(id: String!): Vehicle
topProducts(first: Int = 5): [Product]
topCars(first: Int = 5): [Car]
}
Expand Down Expand Up @@ -65,11 +66,32 @@ export const typeDefs = gql`
details: ProductDetailsBook
}
type Car @key(fields: "id") {
interface Vehicle {
id: String!
description: String
price: String
}
type Car implements Vehicle @key(fields: "id") {
id: String!
description: String
price: String
}
type Van implements Vehicle @key(fields: "id") {
id: String!
description: String
price: String
}
union Thing = Car | Ikea
extend type User @key(fields: "id") {
id: ID! @external
vehicle: Vehicle
thing: Thing
}
# Value type
type KeyValue {
key: String!
Expand Down Expand Up @@ -131,17 +153,25 @@ const products = [
{ __typename: 'Book', isbn: '0987654321', price: 29 },
];

const cars = [
const vehicles = [
{
__typename: 'Car',
id: '1',
description: 'Humble Toyota',
price: 9990,
},
{
__typename: 'Car',
id: '2',
description: 'Awesome Tesla',
price: 12990,
},
{
__typename: 'Van',
id: '3',
description: 'Just a van...',
price: 15990,
},
];

export const resolvers: GraphQLResolverMap<any> = {
Expand Down Expand Up @@ -176,13 +206,34 @@ export const resolvers: GraphQLResolverMap<any> = {
},
Car: {
__resolveReference(object) {
return cars.find(car => car.id === object.id);
return vehicles.find(vehicles => vehicles.id === object.id);
},
},
Van: {
__resolveReference(object) {
return vehicles.find(vehicles => vehicles.id === object.id);
},
},
Thing: {
__resolveType(object) {
return 'id' in object ? 'Car' : 'Ikea';
},
},
User: {
vehicle(user) {
return vehicles.find(vehicles => vehicles.id === user.id);
},
thing(user) {
return vehicles.find(vehicles => vehicles.id === user.id);
},
},
Query: {
product(_, args) {
return products.find(product => product.upc === args.upc);
},
vehicle(_, args) {
return vehicles.find(vehicles => vehicles.id === args.id);
},
topProducts(_, args) {
return products.slice(0, args.first);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,17 @@ export const typeDefs = gql`
relatedReviews: [Review!]! @requires(fields: "similarBooks { isbn }")
}
extend type Car @key(fields: "id") {
extend interface Vehicle {
retailPrice: String
}
extend type Car implements Vehicle @key(fields: "id") {
id: String! @external
price: String @external
retailPrice: String @requires(fields: "price")
}
extend type Van implements Vehicle @key(fields: "id") {
id: String! @external
price: String @external
retailPrice: String @requires(fields: "price")
Expand Down Expand Up @@ -217,6 +227,11 @@ export const resolvers: GraphQLResolverMap<any> = {
return car.price;
},
},
Van: {
retailPrice(van) {
return van.price;
},
},
MetadataOrError: {
__resolveType(object) {
return 'key' in object ? 'KeyValue' : 'Error';
Expand Down
117 changes: 117 additions & 0 deletions packages/apollo-gateway/src/__tests__/executeQueryPlan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import { buildQueryPlan, buildOperationContext } from '../buildQueryPlan';
import { executeQueryPlan } from '../executeQueryPlan';
import { LocalGraphQLDataSource } from '../datasources/LocalGraphQLDataSource';

import { astSerializer, queryPlanSerializer } from '../snapshotSerializers';
expect.addSnapshotSerializer(astSerializer);
expect.addSnapshotSerializer(queryPlanSerializer);

function buildLocalService(modules: GraphQLSchemaModule[]) {
const schema = buildFederatedSchema(modules);
return new LocalGraphQLDataSource(schema);
Expand Down Expand Up @@ -434,6 +438,119 @@ describe('executeQueryPlan', () => {
expect(response.errors).toBeUndefined();
});

it(`can execute queries on interface types`, async () => {
const query = gql`
query {
vehicle(id: "1") {
description
price
retailPrice
}
}
`;

const operationContext = buildOperationContext(schema, query);
const queryPlan = buildQueryPlan(operationContext);

const response = await executeQueryPlan(
queryPlan,
serviceMap,
buildRequestContext(),
operationContext,
);

expect(response.data).toMatchInlineSnapshot(`
Object {
"vehicle": Object {
"description": "Humble Toyota",
"price": "9990",
"retailPrice": "9990",
},
}
`);
});

it(`can execute queries whose fields are interface types`, async () => {
const query = gql`
query {
user(id: "1") {
name
vehicle {
description
price
retailPrice
}
}
}
`;

const operationContext = buildOperationContext(schema, query);
const queryPlan = buildQueryPlan(operationContext);

const response = await executeQueryPlan(
queryPlan,
serviceMap,
buildRequestContext(),
operationContext,
);

expect(response.data).toMatchInlineSnapshot(`
Object {
"user": Object {
"name": "Ada Lovelace",
"vehicle": Object {
"description": "Humble Toyota",
"price": "9990",
"retailPrice": "9990",
},
},
}
`);
});

it(`can execute queries whose fields are union types`, async () => {
const query = gql`
query {
user(id: "1") {
name
thing {
... on Vehicle {
description
price
retailPrice
}
... on Ikea {
asile
}
}
}
}
`;

const operationContext = buildOperationContext(schema, query);
const queryPlan = buildQueryPlan(operationContext);

const response = await executeQueryPlan(
queryPlan,
serviceMap,
buildRequestContext(),
operationContext,
);

expect(response.data).toMatchInlineSnapshot(`
Object {
"user": Object {
"name": "Ada Lovelace",
"thing": Object {
"description": "Humble Toyota",
"price": "9990",
"retailPrice": "9990",
},
},
}
`);
});

it('can execute queries with falsey @requires (except undefined)', async () => {
const query = gql`
query {
Expand Down

0 comments on commit 604e98b

Please sign in to comment.