Skip to content

Commit

Permalink
Supergraph Handler (#5744)
Browse files Browse the repository at this point in the history
* Go

* chore(dependencies): updated changesets for modified dependencies

* Cleanup

* Go

* Do not do batching for a single subschema

* Go

* Trigger

* Fix dependenceis

* chore(dependencies): updated changesets for modified dependencies

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
ardatan and github-actions[bot] authored Jul 31, 2023
1 parent 8844268 commit 7cdc69e
Show file tree
Hide file tree
Showing 35 changed files with 1,150 additions and 593 deletions.
6 changes: 6 additions & 0 deletions .changeset/@graphql-mesh_graphql-5744-dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@graphql-mesh/graphql": patch
---
dependencies updates:
- Added dependency [`@graphql-tools/federation@^1.1.0` ↗︎](https://www.npmjs.com/package/@graphql-tools/federation/v/1.1.0) (to `dependencies`)
- Removed dependency [`@graphql-tools/wrap@^10.0.0` ↗︎](https://www.npmjs.com/package/@graphql-tools/wrap/v/10.0.0) (from `dependencies`)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@graphql-mesh/merger-stitching": patch
---
dependencies updates:
- Removed dependency [`@graphql-tools/stitching-directives@^3.0.0` ↗︎](https://www.npmjs.com/package/@graphql-tools/stitching-directives/v/3.0.0) (from `dependencies`)
5 changes: 5 additions & 0 deletions .changeset/@graphql-mesh_runtime-5744-dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@graphql-mesh/runtime": patch
---
dependencies updates:
- Removed dependency [`@graphql-tools/batch-execute@^9.0.0` ↗︎](https://www.npmjs.com/package/@graphql-tools/batch-execute/v/9.0.0) (from `dependencies`)
6 changes: 6 additions & 0 deletions .changeset/ninety-llamas-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@graphql-mesh/merger-stitching': patch
'@graphql-mesh/graphql': patch
---

New strategy to handle Federation
6 changes: 6 additions & 0 deletions .changeset/three-toes-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@graphql-mesh/supergraph': patch
'@graphql-mesh/types': patch
---

New Supergraph handler
11 changes: 11 additions & 0 deletions examples/federation-example/gateway-supergraph/.meshrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
sources:
- name: Supergraph
handler:
supergraph:
source: ./supergraph.graphql

documents:
- example-query.graphql

serve:
playground: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
fragment User on User {
id
username
name
}

fragment Review on Review {
id
body
}

fragment Product on Product {
inStock
name
price
shippingEstimate
upc
weight
}

query TestQuery {
users {
...User
reviews {
...Review
product {
...Product
reviews {
...Review
author {
...User
reviews {
...Review
product {
...Product
}
}
}
}
}
}
}
topProducts {
...Product
reviews {
...Review
author {
...User
reviews {
...Review
product {
...Product
}
}
}
}
}
}
11 changes: 11 additions & 0 deletions examples/federation-example/gateway-supergraph/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "federation-supergraph-gateway",
"version": "0.0.0",
"license": "MIT",
"private": true,
"dependencies": {
"@graphql-mesh/cli": "0.86.0",
"@graphql-mesh/supergraph": "0.0.0",
"graphql": "16.7.1"
}
}
78 changes: 78 additions & 0 deletions examples/federation-example/gateway-supergraph/supergraph.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
schema
@core(feature: "https://specs.apollo.dev/core/v0.2")
@core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION) {
query: Query
}

directive @core(as: String, feature: String!, for: core__Purpose) repeatable on SCHEMA

directive @join__field(
graph: join__Graph
provides: join__FieldSet
requires: join__FieldSet
) on FIELD_DEFINITION

directive @join__graph(name: String!, url: String!) on ENUM_VALUE

directive @join__owner(graph: join__Graph!) on INTERFACE | OBJECT

directive @join__type(graph: join__Graph!, key: join__FieldSet) repeatable on INTERFACE | OBJECT

type Product
@join__owner(graph: PRODUCTS)
@join__type(graph: PRODUCTS, key: "upc")
@join__type(graph: INVENTORY, key: "upc")
@join__type(graph: REVIEWS, key: "upc") {
inStock: Boolean @join__field(graph: INVENTORY)
name: String @join__field(graph: PRODUCTS)
price: Int @join__field(graph: PRODUCTS)
reviews: [Review] @join__field(graph: REVIEWS)
shippingEstimate: Int @join__field(graph: INVENTORY, requires: "price weight")
upc: String! @join__field(graph: PRODUCTS)
weight: Int @join__field(graph: PRODUCTS)
}

type Query {
me: User @join__field(graph: ACCOUNTS)
topProducts(first: Int = 5): [Product] @join__field(graph: PRODUCTS)
user(id: ID!): User @join__field(graph: ACCOUNTS)
users: [User] @join__field(graph: ACCOUNTS)
}

type Review @join__owner(graph: REVIEWS) @join__type(graph: REVIEWS, key: "id") {
author: User @join__field(graph: REVIEWS, provides: "username")
body: String @join__field(graph: REVIEWS)
id: ID! @join__field(graph: REVIEWS)
product: Product @join__field(graph: REVIEWS)
}

type User
@join__owner(graph: ACCOUNTS)
@join__type(graph: ACCOUNTS, key: "id")
@join__type(graph: REVIEWS, key: "id") {
id: ID! @join__field(graph: ACCOUNTS)
name: String @join__field(graph: ACCOUNTS)
reviews: [Review] @join__field(graph: REVIEWS)
username: String @join__field(graph: ACCOUNTS)
}

enum core__Purpose {
"""
`EXECUTION` features provide metadata necessary to for operation execution.
"""
EXECUTION

"""
`SECURITY` features provide metadata necessary to securely resolve fields.
"""
SECURITY
}

scalar join__FieldSet

enum join__Graph {
ACCOUNTS @join__graph(name: "accounts", url: "http://localhost:9880/graphql")
INVENTORY @join__graph(name: "inventory", url: "http://localhost:9872/graphql")
PRODUCTS @join__graph(name: "products", url: "http://localhost:9873/graphql")
REVIEWS @join__graph(name: "reviews", url: "http://localhost:9874/graphql")
}
17 changes: 17 additions & 0 deletions examples/federation-example/gateway-supergraph/supergraph.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
subgraphs:
accounts:
routing_url: http://localhost:9880/graphql
schema:
file: ../services/accounts-subgraph/typeDefs.graphql
reviews:
routing_url: http://localhost:9874/graphql
schema:
file: ../services/reviews/typeDefs.graphql
products:
routing_url: http://localhost:9873/graphql
schema:
file: ../services/products/typeDefs.graphql
inventory:
routing_url: http://localhost:9872/graphql
schema:
file: ../services/inventory/typeDefs.graphql
1 change: 1 addition & 0 deletions examples/federation-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"start-gateway": "mesh dev --dir gateway",
"start-gateway-delayed": "delay 1 && npm run start-gateway",
"start-service-accounts": "ts-node services/accounts/index.ts",
"start-service-accounts-subgraph": "ts-node services/accounts-subgraph/index.ts",
"start-service-inventory": "ts-node services/inventory/index.ts",
"start-service-products": "ts-node services/products/index.ts",
"start-service-reviews": "ts-node services/reviews/index.ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { accountsSubgraphServer } from './server';

accountsSubgraphServer().catch(error => {
console.error(error);
process.exit(1);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "accounts-subgraph",
"version": "0.0.0",
"license": "MIT",
"private": true,
"scripts": {
"start": "ts-node index.ts"
},
"dependencies": {
"@apollo/subgraph": "2.5.1",
"apollo-server": "3.12.0",
"graphql": "16.7.1",
"ts-node": "10.9.1",
"typescript": "5.1.6"
}
}
71 changes: 71 additions & 0 deletions examples/federation-example/services/accounts-subgraph/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { ApolloServer, gql } from 'apollo-server';
import { buildSubgraphSchema } from '@apollo/subgraph';

const typeDefs = gql`
extend type Query {
me: User
user(id: ID!): User
users: [User]
}
type User @key(fields: "id") {
id: ID!
name: String
username: String
}
`;

const resolvers = {
User: {
__resolveReference(object, context) {
return {
...object,
...context.users.find(user => user.id === object.id),
};
},
},
Query: {
me(_root, _args, context) {
return context.users[0];
},
users(_root, _args, context) {
return context.users;
},
user(_root, args, context) {
return context.users.find(user => user.id === args.id);
},
},
};

const server = new ApolloServer({
schema: buildSubgraphSchema([
{
typeDefs,
resolvers,
},
]),
context: {
users: [
{
id: '1',
name: 'Ada Lovelace',
birthDate: '1815-12-10',
username: '@ada',
},
{
id: '2',
name: 'Alan Turing',
birthDate: '1912-06-23',
username: '@complete',
},
],
},
});

export const accountsSubgraphServer = () =>
server.listen({ port: 9880 }).then(({ url }) => {
if (!process.env.CI) {
console.log(`🚀 Server ready at ${url}`);
}
return server;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
extend type Query {
me: User
user(id: ID!): User
users: [User]
}

type User @key(fields: "id") {
id: ID!
name: String
username: String
}
4 changes: 4 additions & 0 deletions examples/federation-example/services/inventory/server.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { inspect } from 'node:util';
import { ApolloServer, gql } from 'apollo-server';
import { buildSubgraphSchema } from '@apollo/subgraph';

Expand All @@ -20,6 +21,9 @@ const resolvers = {
};
},
shippingEstimate(object) {
if (object.price == null || object.weight == null) {
throw new Error(`${inspect(object)} doesn't have required fields; "price" and "weight".`);
}
// free for expensive items
if (object.price > 1000) return 0;
// estimate is based on weight
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
extend type Product @key(fields: "upc") {
upc: String! @external
weight: Int @external
price: Int @external
inStock: Boolean
shippingEstimate: Int @requires(fields: "price weight")
}
10 changes: 10 additions & 0 deletions examples/federation-example/services/products/typeDefs.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extend type Query {
topProducts(first: Int = 5): [Product]
}

type Product @key(fields: "upc") {
upc: String!
name: String
price: Int
weight: Int
}
17 changes: 17 additions & 0 deletions examples/federation-example/services/reviews/typeDefs.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
type Review @key(fields: "id") {
id: ID!
body: String
author: User @provides(fields: "username")
product: Product
}

extend type User @key(fields: "id") {
id: ID! @external
username: String @external
reviews: [Review]
}

extend type Product @key(fields: "upc") {
upc: String! @external
reviews: [Review]
}
Loading

0 comments on commit 7cdc69e

Please sign in to comment.