@graphql-hive/federation-gateway-audit
Version:
Audit tool for Apollo Federation Gateway
553 lines (530 loc) • 9.99 kB
JavaScript
'use strict';
var testkit = require('./testkit-CAf-AsDy.cjs');
require('@apollo/composition');
require('graphql');
require('fets');
require('@apollo/subgraph');
require('graphql-yoga');
const products = [
{
upc: "p1",
name: "p-name-1",
price: 11,
weight: 1,
category: {
averagePrice: 11
}
},
{
upc: "p2",
name: "p-name-2",
price: 22,
weight: 2,
category: {
averagePrice: 22
}
}
];
const posts = [
{
id: "p1",
body: "p1-body"
},
{
id: "p2",
body: "p2-body"
}
];
const comments = [
{
id: "c1",
postId: "p1",
authorId: "a2",
body: "c1-body"
},
{
id: "c2",
postId: "p1",
authorId: "a2",
body: "c2-body"
},
{
id: "c3",
postId: "p1",
authorId: "a2",
body: "c3-body"
},
{
id: "c4",
postId: "p2",
authorId: "a1",
body: "c4-body"
},
{
id: "c5",
postId: "p2",
authorId: "a1",
body: "c5-body"
},
{
id: "c6",
postId: "p2",
authorId: "a1",
body: "c6-body"
}
];
const authors = [
{
id: "a1",
name: "a1-name"
},
{
id: "a2",
name: "a2-name"
}
];
var a = testkit.createSubgraph("a", {
typeDefs: (
/* GraphQL */
`
extend schema
@link(
url: "https://specs.apollo.dev/federation/v2.3"
import: ["@key", "@external", "@requires"]
)
type Product @key(fields: "upc") {
upc: String!
weight: Int @external
price(currency: String!): Int @external
shippingEstimate: Int
@requires(
fields: """
price(currency: "USD") weight
"""
)
category: Category @external
isExpensiveCategory: Boolean
@requires(
fields: """
category { averagePrice(currency: "USD") }
"""
)
}
type Category @external {
averagePrice(currency: String!): Int
}
`
),
resolvers: {
Product: {
__resolveReference(key) {
const product = products.find((p) => p.upc === key.upc);
if (!product) {
return null;
}
if ("weight" in key && "price" in key) {
return {
upc: product.upc,
weight: key.weight,
price: key.price,
category: product.category
};
}
return {
upc: product.upc,
category: product.category
};
},
shippingEstimate(product) {
return product.price * product.weight * 10;
},
isExpensiveCategory(product) {
return product.category.averagePrice > 11;
}
}
}
});
var b = testkit.createSubgraph("b", {
typeDefs: (
/* GraphQL */
`
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key"])
type Query {
products: [Product]
}
type Product @key(fields: "upc") {
upc: String!
name: String
price(currency: String!): Int
weight: Int
category: Category
}
type Category {
averagePrice(currency: String!): Int
}
`
),
resolvers: {
Query: {
products() {
return products.map((p) => ({
upc: p.upc,
name: p.name,
price: p.price,
weight: p.weight,
category: p.category
}));
}
},
Product: {
__resolveReference(key) {
const product = products.find((p) => p.upc === key.upc);
if (!product) {
return null;
}
return {
upc: product.upc,
name: product.name,
price: product.price,
weight: product.weight,
category: product.category
};
}
}
}
});
var c = testkit.createSubgraph("c", {
typeDefs: (
/* GraphQL */
`
extend schema
@link(
url: "https://specs.apollo.dev/federation/v2.3"
import: ["@key", "@external", "@requires"]
)
type Query {
feed: [Post]
}
type Post @key(fields: "id") {
id: ID!
}
type Comment @key(fields: "id") {
id: ID!
authorId: ID
body: String!
}
`
),
resolvers: {
Query: {
feed() {
return posts.map((post) => ({ id: post.id }));
}
},
Post: {
__resolveReference(key) {
const post = posts.find((post2) => post2.id === key.id);
if (!post) {
return null;
}
return {
id: post.id
};
},
comments(post, { limit }) {
return comments.filter((comment) => comment.postId === post.id).slice(0, limit).map((c) => ({
id: c.id,
authorId: c.authorId,
body: c.body
}));
}
},
Comment: {
__resolveReference(key) {
const comment = comments.find((c) => c.id === key.id);
if (!comment) {
return null;
}
return {
id: comment.id,
authorId: comment.authorId,
body: comment.body
};
}
}
}
});
var d = testkit.createSubgraph("d", {
typeDefs: (
/* GraphQL */
`
extend schema
@link(
url: "https://specs.apollo.dev/federation/v2.3"
import: ["@key", "@external", "@requires"]
)
type Post @key(fields: "id") {
id: ID!
author: Author @requires(fields: "comments(limit: 3) { authorId }")
comments(limit: Int!): [Comment]
}
type Comment @key(fields: "id") {
id: ID!
date: String
authorId: ID @external
}
type Author {
id: ID!
name: String
}
`
),
resolvers: {
Post: {
__resolveReference(key) {
const post = posts.find((p) => p.id === key.id);
if (!post) {
return null;
}
if (key.comments) {
if (key.comments.length !== 3) {
throw new Error("Expected 3 comments");
}
return {
id: post.id,
authorId: key.comments?.[2].authorId
};
}
return {
id: post.id
};
},
author(post) {
if (!post.authorId) {
return null;
}
const author = authors.find((a) => a.id === post.authorId);
if (!author) {
return null;
}
return {
id: author.id,
name: author.name
};
},
comments(post, { limit }) {
const coms = comments.filter((comment) => comment.postId === post.id).slice(0, limit).map((c) => ({
id: c.id
}));
return coms;
}
},
Comment: {
__resolveReference(key) {
const comment = comments.find((c) => c.id === key.id);
if (!comment) {
return null;
}
return {
id: comment.id
};
}
}
}
});
var test = [
testkit.createTest(
/* GraphQL */
`
query {
products {
upc
name
shippingEstimate
isExpensiveCategory
}
}
`,
{
data: {
products: [
{
upc: "p1",
name: "p-name-1",
shippingEstimate: 110,
isExpensiveCategory: false
},
{
upc: "p2",
name: "p-name-2",
shippingEstimate: 440,
isExpensiveCategory: true
}
]
}
}
),
testkit.createTest(
/* GraphQL */
`
{
feed {
author {
id
}
}
}
`,
{
data: {
feed: [
{
author: {
id: "a2"
}
},
{
author: {
id: "a1"
}
}
]
}
}
),
testkit.createTest(
/* GraphQL */
`
query {
feed {
author {
id
}
comments(limit: 1) {
id
}
}
}
`,
{
data: {
feed: [
{
author: {
id: "a2"
},
comments: [
{
id: "c1"
}
]
},
{
author: {
id: "a1"
},
comments: [
{
id: "c4"
}
]
}
]
}
}
),
testkit.createTest(
/* GraphQL */
`
query ($limit: Int = 1) {
feed {
author {
id
}
comments(limit: $limit) {
id
}
}
}
`,
{
data: {
feed: [
{
author: {
id: "a2"
},
comments: [
{
id: "c1"
}
]
},
{
author: {
id: "a1"
},
comments: [
{
id: "c4"
}
]
}
]
}
}
),
testkit.createTest(
/* GraphQL */
`
query ($limit: Int = 1) {
feed {
author {
id
}
...Foo
...Bar
}
}
fragment Foo on Post {
comments(limit: $limit) {
id
}
}
fragment Bar on Post {
comments(limit: $limit) {
id
}
}
`,
{
data: {
feed: [
{
author: {
id: "a2"
},
comments: [
{
id: "c1"
}
]
},
{
author: {
id: "a1"
},
comments: [
{
id: "c4"
}
]
}
]
}
}
)
];
var index = testkit.serve("requires-with-argument", [a, b, c, d], test);
exports.default = index;