If you search the interwebs you will find more than a few people that tell you GraphQL is not a suitable replacement for your REST API implementation. We won't get too much into a comparison here, but they are almost 100% wrong. There are some times where REST is just easier, but I don't think thats a very good reason to choose a solution. I am however going to get you running with GraphQL and KOA as quickly as possible to help you know if it's right for you.

While this post is specifically leveraging KOA which is my personal favorite, it is very transferable to their other implementations.

Basic needs

npm install --save \
    koa \
    koa-bodyparser \
    koa-router \
    apollo-server-koa \
    graphql-tools 

server.js
Lets quickly stand up a KOA server with a basic hello world to get us started. This example is a relatively decent example of something you could actually use.

import http from 'http';
import Koa from 'koa';

function Server() {
    const app = new Koa();
    const server = http.createServer(app.callback());

    app
        .use(() => {
            this.body = 'Hello world!';
        })

    app.on('error', err => {
        console.error(err);
    });

    async function listen(port = 3000) {
        return server.listen(port, () => {
            console.log(`Listening on ${server.address().port}`);
        });
    }

    async function close() {
        server.close();
    }

    return Object.freeze({
        listen,
        close
    });
}

export default Server().listen(3000);

The code samples are definitely positioned to be an example of something you could steer more towards production / real life code than most intros purposefully.

server/graphql/status/index.js
We're going to setup schema that will allow us to get a status and an instance ID. In the real world I would suggest your functionality actually be sitting out in a separate file, but I wanted to make the inner working a little more obvious here.

// Lets pretend we're doing something to actually get server status here
function status() {
    return { okay: true, message: 'All is right' };
}

// Lets pretend we're actually getting instance ID or something
function status() {
    return 'f355a9c53311';
}

// This sets up the type strict interface for graphQL
const typeDefs = `
    type Status {
        okay: Boolean,
        message: String
    }

    type Query {
        status: Status
        instance: String
    }
`;

// These resolvers map to the above type defs
const resolvers = {
    Query: {
        status
        instance
    }
};

// Returning in the raw will make sense shortly
export default {
    typeDefs,
    resolvers
}

Important note / update: The below file has some code that just doesn't scale well for makeExecutableSchema. Please checkout my other blog post on schema stitching to see better information in detail.

server/graphql/index.js
We will now use our above definition to create our graphQL Schema. I'm using this approach because it makes it very easy to expand and grow the code base as you would in the real world. I still feel like there is another iteration of optimization or improved organization here, but I think it will take some growth and heartache to find that next step.

import Router from 'koa-router';
import { graphqlKoa } from 'apollo-server-koa';
import { makeExecutableSchema } from 'graphql-tools';

// Import our config for the status "endpoint"
import statusDefs from 'status';
/*
** This is where additional schemas would be
** imported in the future.
*/

// Create a new KOA router
const router = new Router({});

// makeExecutableSchema allows you to config in multile ways.
// I prefer this below method to load multiple config options
export const schema = makeExecutableSchema({
  typeDefs: [securityDefs.typeDefs],
  resolvers: [securityDefs.resolvers],
});

/*
** Honest Note:
** These two lines gets you going, but I'm pretty sure this is 
** not production ready. I'll be doing some more research and 
** will update this code later when I find a better way
*/
router.post('/api', graphqlKoa({ schema }));
router.get('/api', graphqlKoa({ schema }));

export default router;

server.js
Now lets pop back to server.js and add in the cool bits to make your graphQL work

// Add imports
import koaBody from 'koa-bodyparser';
import router from './graphql';

...

function Server() {
    ...
    
    app
        .use(koaBody())
        .use(router.routes())
        .use(router.allowedMethods());

    ...
}

server/graphql/index.js
Lets just take this one step further and setup GraphiQL so that you can quickly test and play with your new endpoint. We'll go back to the graphql/index.js and make just a couple line adjustments

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

/*
** Add this line after the other router lines and in the future
** make sure that it's only turned on in development mode
*/
router.get('/graphiql', graphiqlKoa({ endpointURL: '/api' }));

You'll now have GraphiQL available in your browser at http://localhost:3000/graphiql and you'll be able to run a query like the following.
Screenshot-2018-06-11-09.02.55