Composing public GraphQL APIs
Problem
A more relevant question now as of yesterday ;-) So with Github or any other of what I'm assuming is the coming avalanche of public GraphQL APIs, it'd often be really handy if you could compose all or parts of a public schema with your private one. For example, what if all of your users had a connected Github account and you could write queries like: [code block] Or if there was a Wikipedia GraphQL API (PLEEAASSEEE someone build this!): [code block] Ideally there'd be some helper code that'd consume the introspection query and auto-construct the schema locally + provide helpers for bridging between schemas. Then there'd need to be some sort of AST slicer to pull out the part of the query that's for the remote API and then send it there to be resolved. Thoughts? Doable? Someone already explored this further than I have? NPM package I missed ;-)? /cc @taion who helped develop some of these ideas.
Unverified for your environment
Select your OS to check compatibility.
1 Fix
Implement Schema Composition for Public GraphQL APIs
The challenge arises from the need to integrate multiple GraphQL schemas (public and private) into a single cohesive API. This requires introspection of the public schemas and a mechanism to resolve queries that span both schemas, which is not natively supported in GraphQL.
Awaiting Verification
Be the first to verify this fix
- 1
Install Required Packages
Begin by installing necessary packages for GraphQL schema composition and introspection. Use Apollo Server for handling GraphQL queries and `graphql-tools` for schema merging.
bashnpm install apollo-server graphql graphql-tools - 2
Fetch Public Schema Introspection
Create a function to fetch the introspection query from the public GraphQL API. This will allow you to retrieve the schema definition and construct it locally.
javascriptconst fetchSchema = async (url) => { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: '{ __schema { types { name } } }' }) }); const { data } = await response.json(); return data; }; - 3
Construct Local Schema
Use the fetched introspection data to construct the local schema using `makeExecutableSchema` from `graphql-tools`. This allows you to merge your private schema with the public one.
javascriptconst { makeExecutableSchema } = require('graphql-tools'); const publicSchema = makeExecutableSchema({ typeDefs: publicTypeDefs, resolvers: publicResolvers }); const privateSchema = makeExecutableSchema({ typeDefs: privateTypeDefs, resolvers: privateResolvers }); const mergedSchema = mergeSchemas({ schemas: [publicSchema, privateSchema] }); - 4
Implement AST Slicing for Remote Queries
Develop a utility to slice the AST of incoming queries. This utility will identify which parts of the query need to be sent to the public API and which can be resolved locally.
javascriptconst { visit } = require('graphql'); const sliceAST = (query) => { const remoteParts = []; visit(query, { Field(node) { if (isRemoteField(node.name.value)) { remoteParts.push(node); } } }); return remoteParts; }; - 5
Set Up Apollo Server
Finally, set up the Apollo Server to handle incoming queries, utilizing the merged schema and the AST slicing utility to resolve queries appropriately.
javascriptconst { ApolloServer } = require('apollo-server'); const server = new ApolloServer({ schema: mergedSchema, context: ({ req }) => ({ token: req.headers.authorization }) }); server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); });
Validation
To confirm the fix, execute a query that includes fields from both the public and private schemas. Ensure that the server responds correctly with data from both sources. Additionally, check the logs for any errors related to schema resolution.
Sign in to verify this fix
Environment
Submitted by
Alex Chen
2450 rep