graphql.js

import { ApolloServer } from 'apollo-server-koa';

import Server from 'treehouse/server';

/**
 * Extends <code>Server</code> and integrates an <code>ApolloServer</code>
 * (a GraphQL handler) into the server.
 * Accepts the standard input that <code>Server</code> does, as well as an
 * additional <code>schema</code> parameter, which is used to populate
 * <code>ApolloServer</code>.
 *
 * <code>ApolloServer</code> integrates itself into the server by adding an
 * additional <code>router</code> to the <code>Koa</code> app. This
 * <code>router</code> handles requests to <code>config.graphql.url</code>.
 *
 * @class
 * @extends Server
 * @see {@link Server}
 * @see {@link https://www.apollographql.com/docs/apollo-server/v2/whats-new.html|ApolloServer}
 */
export default class GraphqQLServer extends Server {
  graphql: Object;

  /**
   * Instantiates the base <code>Server</code> and intializes the GraphQL
   * Server capabilities.
   *
   * <code>schema</code> should be the resulting object from combining your
   * <code>typedefs</code> and your <code>resolvers</code> using something like
   * <code>makeExecutableSchema</code> from <code>graphql-tools</code> or
   * <code>apollo-server-koa</code>.
   *
   * @constructor
   * @param {Object} config     The application configuration object
   * @param {Object} schema     The graphql schema object
   */
  constructor(config: Object, schema: Object) {
    super(config);

    this.initializeGraphQl(this.app, schema, config);
  }

  /**
   * Initializes <code>ApolloServer</code> with the provided
   * <code>schema</code>, then applies the
   * <code>ApolloServer</code> router and handlers to the server application.
   *
   * @param {Object} config     The application configuration object
   * @param {Object} schema     The graphql schema object
   * @return {void}
   */
  initializeGraphQl(app, schema, config) {
    this.graphql = new ApolloServer({
      schema,
      introspection: config.graphql.introspection,
    });

    // Attach the graphql router to the app
    this.graphql.applyMiddleware({
      app,
      gui: config.graphql.gui,
      path: config.graphql.url,
    });
  }
}