Skip to content

Commit

Permalink
fix(federation): Composition propagates @deprecated usages on input t…
Browse files Browse the repository at this point in the history
…ype object fields (#1008)

Update graphql peer dependency, introduce new test scenarios to validate the fix.
  • Loading branch information
trevor-scheer committed Sep 8, 2021
1 parent 8cabe69 commit fa2f2fa
Show file tree
Hide file tree
Showing 18 changed files with 185 additions and 52 deletions.
26 changes: 16 additions & 10 deletions federation-integration-testsuite-js/src/fixtures/reviews.ts
Expand Up @@ -74,8 +74,14 @@ export const typeDefs = gql`
retailPrice: String @requires(fields: "price")
}
input ReviewProduct {
upc: String!
body: String!
stars: Int @deprecated(reason: "Stars are no longer in use")
}
extend type Mutation {
reviewProduct(upc: String!, body: String!): Product
reviewProduct(input: ReviewProduct!): Product
updateReview(review: UpdateReviewInput!): Review
deleteReview(id: ID!): Boolean
}
Expand Down Expand Up @@ -157,7 +163,7 @@ export const resolvers: GraphQLResolverMap<any> = {
},
},
Mutation: {
reviewProduct(_, { upc, body }) {
reviewProduct(_, { input: { upc, body } }) {
const id = `${Number(reviews[reviews.length - 1].id) + 1}`;
reviews.push({
id,
Expand All @@ -168,7 +174,7 @@ export const resolvers: GraphQLResolverMap<any> = {
return { upc, __typename: 'Furniture' };
},
updateReview(_, { review: { id }, review: updatedReview }) {
let review = reviews.find(review => review.id === id);
let review = reviews.find((review) => review.id === id);

if (!review) {
return null;
Expand All @@ -183,7 +189,7 @@ export const resolvers: GraphQLResolverMap<any> = {
},
deleteReview(_, { id }) {
const deleted = reviews.splice(
reviews.findIndex(review => review.id === id),
reviews.findIndex((review) => review.id === id),
1,
);
return Boolean(deleted);
Expand All @@ -196,13 +202,13 @@ export const resolvers: GraphQLResolverMap<any> = {
},
User: {
reviews(user) {
return reviews.filter(review => review.authorID === user.id);
return reviews.filter((review) => review.authorID === user.id);
},
numberOfReviews(user) {
return reviews.filter(review => review.authorID === user.id).length;
return reviews.filter((review) => review.authorID === user.id).length;
},
username(user) {
const found = usernames.find(username => username.id === user.id);
const found = usernames.find((username) => username.id === user.id);
return found ? found.username : null;
},
goodAddress(object) {
Expand All @@ -211,18 +217,18 @@ export const resolvers: GraphQLResolverMap<any> = {
},
Furniture: {
reviews(product) {
return reviews.filter(review => review.product.upc === product.upc);
return reviews.filter((review) => review.product.upc === product.upc);
},
},
Book: {
reviews(product) {
return reviews.filter(review => review.product.isbn === product.isbn);
return reviews.filter((review) => review.product.isbn === product.isbn);
},
relatedReviews(book) {
return book.similarBooks
? book.similarBooks
.map(({ isbn }: any) =>
reviews.filter(review => review.product.isbn === isbn),
reviews.filter((review) => review.product.isbn === isbn),
)
.flat()
: [];
Expand Down
Expand Up @@ -67,8 +67,14 @@ export const typeDefs = gql`
retailPrice: String @requires(fields: "price")
}
input ReviewProduct {
upc: String!
body: String!
stars: Int @deprecated(reason: "Stars are no longer in use")
}
extend type Mutation {
reviewProduct(upc: String!, body: String!): Product
reviewProduct(input: ReviewProduct): Product
updateReview(review: UpdateReviewInput!): Review
deleteReview(id: ID!): Boolean
}
Expand Down
2 changes: 1 addition & 1 deletion federation-js/CHANGELOG.md
Expand Up @@ -4,7 +4,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 appropriate changes within that release will be moved into the new section.
- _Nothing yet! Stay tuned!_
- __BREAKING__: This is a breaking change due to a `peerDependencies` update (`graphql@^15.4.0` -> `graphql@^15.5.3`). This `graphql` version includes a fix which resolves an issue which prevented the correct propagation of `@deprecated` usages on input type object fields into the printed subgraph schema. This can be considered a follow-up to PR #996, which previously attempted to propagate @deprecated on *ALL* input values. [PR #1008](https://github.com/apollographql/federation/pull/1008)

## v0.31.0

Expand Down
2 changes: 1 addition & 1 deletion federation-js/package.json
Expand Up @@ -28,6 +28,6 @@
"lodash.xorby": "^4.7.0"
},
"peerDependencies": {
"graphql": "^15.4.0"
"graphql": "^15.5.3"
}
}
98 changes: 98 additions & 0 deletions federation-js/src/service/__tests__/printSubgraphSchema.test.ts
Expand Up @@ -74,4 +74,102 @@ describe('printSubgraphSchema', () => {
"
`);
});

it('prints reviews subgraph correctly', () => {
const schema = buildSubgraphSchema(fixtures[5].typeDefs);
expect(printSubgraphSchema(schema)).toMatchInlineSnapshot(`
"directive @stream on FIELD
directive @transform(from: String!) on FIELD
type Review @key(fields: \\"id\\") {
id: ID!
body(format: Boolean = false): String
author: User @provides(fields: \\"username\\")
product: Product
metadata: [MetadataOrError]
}
input UpdateReviewInput {
id: ID!
body: String
}
input ReviewProduct {
upc: String!
body: String!
stars: Int @deprecated(reason: \\"Stars are no longer in use\\")
}
type KeyValue {
key: String!
value: String!
}
type Error {
code: Int
message: String
}
union MetadataOrError = KeyValue | Error
extend type Query {
_entities(representations: [_Any!]!): [_Entity]!
_service: _Service!
topReviews(first: Int = 5): [Review]
}
extend type UserMetadata {
address: String @external
}
extend type User @key(fields: \\"id\\") {
id: ID! @external
username: String @external
reviews: [Review]
numberOfReviews: Int!
metadata: [UserMetadata] @external
goodAddress: Boolean @requires(fields: \\"metadata { address }\\")
}
extend interface Product {
reviews: [Review]
}
extend type Furniture implements Product @key(fields: \\"upc\\") {
upc: String! @external
reviews: [Review]
}
extend type Book implements Product @key(fields: \\"isbn\\") {
isbn: String! @external
reviews: [Review]
similarBooks: [Book]! @external
relatedReviews: [Review!]! @requires(fields: \\"similarBooks { isbn }\\")
}
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\\")
}
extend type Mutation {
reviewProduct(input: ReviewProduct!): Product
updateReview(review: UpdateReviewInput!): Review
deleteReview(id: ID!): Boolean
}
"
`);
});
});
16 changes: 14 additions & 2 deletions federation-js/src/service/__tests__/printSupergraphSdl.test.ts
Expand Up @@ -163,7 +163,7 @@ describe('printSupergraphSdl', () => {
type Mutation {
deleteReview(id: ID!): Boolean @join__field(graph: REVIEWS)
login(password: String!, userId: String @deprecated(reason: \\"Use username instead\\"), username: String!): User @join__field(graph: ACCOUNTS)
reviewProduct(body: String!, upc: String!): Product @join__field(graph: REVIEWS)
reviewProduct(input: ReviewProduct!): Product @join__field(graph: REVIEWS)
updateReview(review: UpdateReviewInput!): Review @join__field(graph: REVIEWS)
}
Expand Down Expand Up @@ -234,6 +234,12 @@ describe('printSupergraphSdl', () => {
product: Product @join__field(graph: REVIEWS)
}
input ReviewProduct {
body: String!
stars: Int @deprecated(reason: \\"Stars are no longer in use\\")
upc: String!
}
type SMSAccount
@join__owner(graph: ACCOUNTS)
@join__type(graph: ACCOUNTS, key: \\"number\\")
Expand Down Expand Up @@ -471,7 +477,7 @@ describe('printSupergraphSdl', () => {
type Mutation {
deleteReview(id: ID!): Boolean @join__field(graph: REVIEWS)
login(password: String!, username: String!): User @join__field(graph: ACCOUNTS)
reviewProduct(body: String!, upc: String!): Product @join__field(graph: REVIEWS)
reviewProduct(input: ReviewProduct): Product @join__field(graph: REVIEWS)
updateReview(review: UpdateReviewInput!): Review @join__field(graph: REVIEWS)
}
Expand Down Expand Up @@ -540,6 +546,12 @@ describe('printSupergraphSdl', () => {
product: Product @join__field(graph: REVIEWS)
}
input ReviewProduct {
body: String!
stars: Int @deprecated(reason: \\"Stars are no longer in use\\")
upc: String!
}
type SMSAccount
@join__owner(graph: ACCOUNTS)
@join__type(graph: ACCOUNTS, key: \\"number\\")
Expand Down
6 changes: 0 additions & 6 deletions federation-js/src/service/printSubgraphSchema.ts
Expand Up @@ -39,12 +39,6 @@ import { federationDirectives, gatherDirectives } from '../directives';
*/
export const printSchema = printSubgraphSchema;

/**
* Accepts options as a second argument:
*
* - commentDescriptions:
* Provide true to use preceding comments as the description.
*/
export function printSubgraphSchema(schema: GraphQLSchema): string {
return printFilteredSchema(
schema,
Expand Down
2 changes: 1 addition & 1 deletion gateway-js/CHANGELOG.md
Expand Up @@ -4,7 +4,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 appropriate changes within that release will be moved into the new section.
- _Nothing yet! Stay tuned!_
- __BREAKING__: This is a breaking change due to a `peerDependencies` update (`graphql@^15.4.0` -> `graphql@^15.5.3`). This `graphql` version includes a fix which is being necessarily adopted within the `@apollo/federation` package. See associated CHANGELOG entry in the `federation-js` folder for additional details. [PR #1008](https://github.com/apollographql/federation/pull/1008)

## v0.40.0

Expand Down
2 changes: 1 addition & 1 deletion gateway-js/package.json
Expand Up @@ -42,6 +42,6 @@
"pretty-format": "^26.0.0"
},
"peerDependencies": {
"graphql": "^15.4.0"
"graphql": "^15.5.3"
}
}
12 changes: 6 additions & 6 deletions gateway-js/src/__tests__/build-query-plan.feature
Expand Up @@ -1066,7 +1066,7 @@ Scenario: returning across service boundaries
Given query
"""
mutation Review($upc: String!, $body: String!) {
reviewProduct(upc: $upc, body: $body) {
reviewProduct(input: {upc: $upc, body: $body}) {
... on Furniture {
name
}
Expand All @@ -1087,7 +1087,7 @@ Scenario: returning across service boundaries
"upc",
"body"
],
"operation": "mutation($upc:String!$body:String!){reviewProduct(upc:$upc body:$body){__typename ...on Furniture{__typename upc}}}"
"operation": "mutation($upc:String!$body:String!){reviewProduct(input:{upc:$upc body:$body}){__typename ...on Furniture{__typename upc}}}"
},
{
"kind": "Flatten",
Expand Down Expand Up @@ -1139,7 +1139,7 @@ Scenario: supports multiple root mutations
}
}
}
reviewProduct(upc: $upc, body: $body) {
reviewProduct(input: {upc: $upc, body: $body}) {
... on Furniture {
name
}
Expand Down Expand Up @@ -1228,7 +1228,7 @@ Scenario: supports multiple root mutations
"upc",
"body"
],
"operation": "mutation($upc:String!$body:String!){reviewProduct(upc:$upc body:$body){__typename ...on Furniture{__typename upc}}}"
"operation": "mutation($upc:String!$body:String!){reviewProduct(input:{upc:$upc body:$body}){__typename ...on Furniture{__typename upc}}}"
},
{
"kind": "Flatten",
Expand Down Expand Up @@ -1275,7 +1275,7 @@ Scenario: multiple root mutations with correct service order
$password: String!
$reviewId: ID!
) {
reviewProduct(upc: $upc, body: $body) {
reviewProduct(input: {upc: $upc, body: $body}) {
... on Furniture {
upc
}
Expand Down Expand Up @@ -1309,7 +1309,7 @@ Scenario: multiple root mutations with correct service order
"body",
"updatedReview"
],
"operation": "mutation($upc:String!$body:String!$updatedReview:UpdateReviewInput!){reviewProduct(upc:$upc body:$body){__typename ...on Furniture{upc}}updateReview(review:$updatedReview){id body}}"
"operation": "mutation($upc:String!$body:String!$updatedReview:UpdateReviewInput!){reviewProduct(input:{upc:$upc body:$body}){__typename ...on Furniture{upc}}updateReview(review:$updatedReview){id body}}"
},
{
"kind": "Fetch",
Expand Down
13 changes: 8 additions & 5 deletions gateway-js/src/__tests__/integration/mutations.test.ts
@@ -1,5 +1,8 @@
import { execute } from '../execution-utils';
import { astSerializer, queryPlanSerializer } from 'apollo-federation-integration-testsuite';
import {
astSerializer,
queryPlanSerializer,
} from 'apollo-federation-integration-testsuite';
import { accounts, reviews } from 'apollo-federation-integration-testsuite';

expect.addSnapshotSerializer(astSerializer);
Expand Down Expand Up @@ -47,7 +50,7 @@ it('supports mutations', async () => {
it('returning across service boundaries', async () => {
const query = `#graphql
mutation Review($upc: String!, $body: String!) {
reviewProduct(upc: $upc, body: $body) {
reviewProduct(input: { upc: $upc, body: $body }) {
... on Furniture {
name
}
Expand Down Expand Up @@ -92,7 +95,7 @@ it('multiple root mutations', async () => {
}
}
}
reviewProduct(upc: $upc, body: $body) {
reviewProduct(input: { upc: $upc, body: $body }) {
... on Furniture {
name
}
Expand Down Expand Up @@ -148,7 +151,7 @@ it('multiple root mutations with correct service order', async () => {
$password: String!
$reviewId: ID!
) {
reviewProduct(upc: $upc, body: $body) {
reviewProduct(input: { upc: $upc, body: $body }) {
... on Furniture {
upc
}
Expand Down Expand Up @@ -208,7 +211,7 @@ it('multiple root mutations with correct service order', async () => {
Sequence {
Fetch(service: "reviews") {
{
reviewProduct(upc: $upc, body: $body) {
reviewProduct(input: {upc: $upc, body: $body}) {
__typename
... on Furniture {
upc
Expand Down

0 comments on commit fa2f2fa

Please sign in to comment.