@graphql-hive/federation-gateway-audit
Version:
Audit tool for Apollo Federation Gateway
160 lines (142 loc) • 3.96 kB
text/typescript
import { createSubgraph } from "../../subgraph.js";
import { products, reviews } from "./data.js";
const Product = {
__resolveReference(key: { id: string; similar?: { id: string[] } }) {
const product = products.find((product) => product.id === key.id);
return product
? {
__typename: product.__typename,
id: product.id,
similar: key.similar,
}
: null;
},
reviews(product: { id: string }) {
return reviews
.filter((review) => review.productId === product.id)
.map((review) => {
const product = products.find(
(product) => product.id === review.productId,
);
return {
__typename: "Review",
id: review.id,
body: review.body,
product: product
? {
__typename: product.__typename,
id: product.id,
}
: null,
};
});
},
reviewsCount(product: { id: string }) {
return reviews.filter((review) => review.productId === product.id).length;
},
reviewsScore(product: { id: string }) {
const productReviews = reviews.filter(
(review) => review.productId === product.id,
);
if (productReviews.length === 0) {
return 0;
}
const sum = productReviews.reduce((acc, review) => acc + review.score, 0);
return sum / productReviews.length;
},
reviewsOfSimilar(product: { __typename: string; similar: { id: string[] } }) {
const similarProducts = products.filter(
(p) =>
p.__typename === product.__typename &&
product.similar.id.includes(p.id),
);
return similarProducts
.flatMap((p) => reviews.filter((review) => review.productId === p.id))
.map((review) => {
const product = products.find(
(product) => product.id === review.productId,
);
return {
__typename: "Review",
id: review.id,
body: review.body,
product: product
? {
__typename: product.__typename,
id: product.id,
}
: null,
};
});
},
};
export default createSubgraph("reviews", {
typeDefs: /* GraphQL */ `
schema
@link(
url: "https://specs.apollo.dev/federation/v2.3"
import: ["@key", "@shareable", "@requires", "@external"]
) {
query: Query
}
type Book implements Product & Similar @key(fields: "id") {
id: ID!
reviewsCount: Int!
reviewsScore: Float! @shareable
reviews: [Review!]!
similar: [Book] @external
reviewsOfSimilar: [Review!]! @requires(fields: "similar { id }")
}
type Magazine implements Product & Similar @key(fields: "id") {
id: ID!
reviewsCount: Int!
reviewsScore: Float! @shareable
reviews: [Review!]!
similar: [Magazine] @external
reviewsOfSimilar: [Review!]! @requires(fields: "similar { id }")
}
interface Product {
id: ID!
reviewsCount: Int!
reviewsScore: Float!
reviews: [Review!]!
}
interface Similar {
similar: [Product]
}
type Query {
review(id: Int!): Review
}
type Review {
id: Int!
body: String!
product: Product
}
`,
resolvers: {
Query: {
review(_: {}, { id }: { id: number }) {
const review = reviews.find((review) => review.id === id);
if (!review) {
return null;
}
const product = products.find(
(product) => product.id === review.productId,
);
return {
__typename: "Review",
id: review.id,
body: review.body,
product: product
? {
__typename: product.__typename,
id: product.id,
}
: null,
};
},
},
Book: Product,
Magazine: Product,
},
});