@crystallize/koa-middleware-apollo v0.2.0
koa-middleware-apollo
Apollo server implementation that uses the traditional koa middleware pattern. Heavily inspired by apollo-server-koa.
This package is a work in progress and currently does not support file uploads or GraphQL subscriptions.
Motivation
While the official implementation of the Apollo GraphQL server for koa, the apollo-server-koa package mentioned above, provides an easy way to get a GraphQL server up and running, it does not work the same way that other koa middleware does. Rather than adding a middleware function to the koa stack (via app.use()), apollo-server-koa exposes an applyMiddleware function on an instance of the ApolloServer class (see package documentation for further details). This can be problematic if you, for instance, want to use path parameters for your GraphQL endpoint (e.g. /graph/:clientId).
@crystallize/koa-middleware-apollo exports middleware functions that integrate seamlessly into any koa middleware stack, thus providing better interoperability and allowing for greater customizability.
Batteries not Included
Since our aim is to integrate as seamlessly as possible into any middleware stack, we make as few assumptions as reasonably possible. Therefore, @crystallize/koa-middleware-apollo does not include a bodyparser, a router or anything other than the basic tools to run a GraphQL server. Contrary to apollo-server-koa, it also does not export graphql-tools or apollo-server-core, which means you will have to add that to your dependencies manually if you intend to use functionality provided by these packages (e.g. makeExecutableSchema or gql respectively).
Installation
yarn add @crystallize/koa-middleware-apolloBasic GraphQL Server
basicGraphqlServer(options[, dependencies]) -> Function
Returns middleware for a basic GraphQL server (implemented using ApolloServerBase from the apollo-server-core package).
options: Configuration object that will be passed to theApolloServerBaseconstructordependencies(optional): Allows for deeper customization of middleware behavior using dependency injection for various functions (default implementations shown here):getMethod:ctx => ctx.request.methodgetQuery:ctx => ctx.request.bodyrunQuery:runHttpQuery(fromapollo-server-core)getOptions:ctx => apollo.graphQLServerOptions({ ctx })(fromapollo-server-core)getRequest:ctx => convertNodeHttpToRequest(ctx.req)
Example
const { basicGraphqlServer } = require('@crystallize/koa-middleware-apollo')
const app = require('./app')
const schema = require('./schema')
const middleware = basicGraphqlServer({
schema,
debug: true,
context: ({ ctx }) => {
const { user } = ctx.state
return { user }
}
})
app.use(middleware)graphqlServer(apollo[, dependencies]) -> Function
Returns middleware for a custom GraphQL server instance.
apollo: Instance of anApolloServerclassdependencies(optional): See above
GraphQL Playground
playground(options[, dependencies]) -> Function
Returns middleware for rendering a GraphQL playground via the @apollographql/graphql-playground-html package.
options: Configuration object that will be passed directly to the playground render function. See docs for available optionsdependencies(optional):getEndpoint: Returns the GraphQL server endpoint. Will receive koactxas its only parameter. Defaults tooptions.endpoint.
Full Example
This is a close to real life example implementation of a basic GraphQL server at an endpoint that makes use of a path parameter.
const Koa = require('koa')
const Router = require('koa-router')
const bodyParser = require('koa-bodyparser')
const {
basicGraphqlServer,
playground
} = require('@crystallize/koa-middleware-apollo')
const schema = require('./schema')
const router = new Router()
router.post(
'/graph/:clientId',
basicGraphqlServer({
schema,
context: ({ ctx }) => {
const { clientId } = ctx.params
return { clientId }
}
})
)
router.get(
'/graph/:clientId',
playground(
{
settings: {
'editor.theme': 'light'
}
},
{
getEndpoint: ctx => `/graph/${ctx.params.clientId}`
}
)
)
const app = new Koa()
app
.use(bodyParser())
.use(router.routes())
app.listen(process.env.PORT || 3000)Author
Michael Smesnik at crystallize
License
MIT