Skip to content

GraphQL Server Framework implemented as Express middlewares

License

Notifications You must be signed in to change notification settings

supergraphql/supergraph

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SuperGraph

npm CircleCI Codecov

SuperGraph is a GraphQL Server Framework. It is inspired by Koa, built on Apollo Server, and turns your GraphQL endpoint into a Koa-like application, with support for context, middleware, and many other features.

It is great for setting up an API Gateway on top of existing GraphQL endpoint, applying concepts like remote schemas and schema stitching. But it also makes it very easy to set up a GraphQL Server from scratch.

SuperGraph is implemented as a set of Express middlewares, so you can build a GraphQL Server as easily as a regular web server!

Concepts

SuperGraph bridges the gap between commonly used patterns for HTTP middleware frameworks like Koa and Express, and GraphQL endpoints. A GraphQL server is composed of three components:

  • GraphQL schemas
  • Resolvers
  • Context

SuperGraph uses these same three components:

  • GraphQL schemas define the routes of our server
  • Resolvers define the implementation of these routes
  • Application middleware is used to construct the context passed to every resolver, and router middleware is used to add common functionality to the resolvers

Installation

SuperGraph requires node v7.6.0 or higher for ES2015 and async function support. Following common practice, it has apollo-link and graphql specified as peer dependencies, so make sure you install those too.

$ yarn add supergraph apollo-link graphql

Examples

Set up your first GraphQL Server in minutes using Express and SuperGraph.

SuperGraph makes it easy to set up a GraphQL Server from scratch. But this example really takes it to the next level by combining two existing GraphQL endpoints, link them together, and apply some middleware on top.

Documentation

Express Request

SuperGraph add a supergraph object to the Express Request context, with the following structure. For normal use cases, you never have to modify anything directly.

  • req.supergraph.context.schemas will contain all GraphQL schemas
  • req.supergraph.context.resolvers will contain all GraphQL resolver functions
  • req.supergraph.context.middlewares will contain all GraphQL middleware functions
  • req.supergraph.context.mergedSchema will contain the final schema used for your endpoint

schema({name?: string, schema: GraphQLSchema | string}) or

schema(schema: GraphQLSchema | string)

Adds a GraphQL schema to the SuperGraph application. This can either be a full GraphQLSchema or a Type definition string. Optionally you can specify a name for the schema, so you can reference it anywhere using context.schemas.schemaName. This is actually a convenient shorthand for the schema SuperGraph middleware function: use(schema(...))

remoteSchema({
  name?: string,
  uri?: string,
  introspectionSchema?: GraphQLSchema,
  authenticationToken?: (context) => string},
  forwardHeaders?: boolean | Array<string>
})
remoteSchema({ name?: string, link?: ApolloLink, introspectionSchema?: GraphQLSchema, authenticationToken?: (context) => string}, forwardHeaders?: boolean | Array })

Adds a schema for a remote GraphQL endpoint to the SuperGraph Application. You can either specify a URL for the endpoint, or pass in an existing ApolloLink. You can optionally pass in an introspectionSchema. If you don't, SuperGraph will run the introspection query against your endpoint to retrieve the schema. You can also optionally pass in a function that retrieves the authenticationToken from the GraphQL context. It will be added as Bearer token to the Authorization header for this remote endpoint. For more complex scenarios, use the possibility to pass in your own ApolloLink definition.

use(path: '...', fn: async (event, next) => {...})

Specify a router middleware for a certain GraphQL path. You can specify multiple middlewares for the same path, and each middleware can specify actions before and after the next middleware or resolver runs (like Koa). The basic syntax is:

(event, next) => {
  // Do something before
  const result = await next()
  // Do something after
  return result
}

The event object contains the following properties:

  • parent, args, context and info. These are the common resolver parameters.
  • addFields. Helper method to add fields to the resolver (see below).

resolve(path: string, fn: async (event) => {...}

Specify a regular resolver for a GraphQL path. This type of resolver is used for fields that are not part of a remote schema. You can only specify one resolver per GraphQL path. The event object contains the same properties as above, and also:

resolve(path: string, resolver: {
  fragment?: string
  resolve: async (event) => {...}
  __resolveType?: async (event) => {...}
})

Specify a merge (schema stitching) resolver for a GraphQL path. You can only specify one resolver per GraphQL path. The event object contains the same properties as above, and also:

  • addTypenameField(). Helper method. See below
  • delegate(). Helper method to delegate execution to an existing query or mutation (useful for schema stitching). See below
  • delegateQuery(). Helper method to execute a custom query or mutation against your underlying schema (useful for schema stitching). See below

await serve({serverOptions})

This method exposes the Express middleware for your SuperGraph application. You add it to your GraphQL Express route (/graphql). It accepts the following Apollo Server serverOptions, that it will pass through to Apollo Server:

  • rootValue: the value passed to the first resolve function
  • formatError: a function to apply to every error before sending the response to clients
  • validationRules: additional GraphQL validation rules to be applied to client-specified queries
  • formatParams: a function applied for each query in a batch to format parameters before execution
  • formatResponse: a function applied to each response after execution
  • tracing: when set to true, collect and expose trace data in the Apollo Tracing format

Helper methods

SuperGraph comes with a number of helper methods that you can use inside your resolvers:

addFields(fields: [FieldNode | string] | FieldNode | string)

Helper method to add one or more fields to your query. This is useful when you need a specific field to be part of the query result for further processing, even if the user doesn't specify it in their query.

addTypenameField()

Helper method to add the __typename field to your query fields. This is useful for resolvers for interface and union fields, that require the __typename field for Type resolving. This is an explicit shorthand for addFields('__typename'). It is a separate function because it is to be expected that graphql-tools will support this out of the box soon, so you don't have to specify this field manually anymore.

delegate(operationType: 'query' | 'mutation', operationName: '...', args?: {...})

This is a helper method for mergeInfo.delegate, and one of the most used methods when defining resolvers for schema stitching. It delegates the execution to the query or mutation with the specified operationName. Optionally, you can specify query arguments. If you don't specify arguments, the resolver arguments will be injected automatically.

delegateQuery(query: string, args?: {...})

This is a helper method that works like mergeInfo.delegate, but instead of specifying an operationName, you can define a custom query. This is very useful for executing a query that is unrelated to the resolver (for example, retrieve user data). As with delegate, arguments are optional, and will be injected automatically.

Support for other server frameworks

Support for other server frameworks (Hapi, Koa, Restify, Lambda, Micro and Azure Functions) will be released soon!

Additional middlewares

Additional useful SuperGraph application and router middlewares (for logging, authentication, mocking, etc.) will be released soon as a separate package!

Contributing

If you run into any issue using SuperGraph, or if you have a feature request, please open an issue.

Releases

No releases published

Packages

No packages published