The last article I have written GraphQL — 101 which was focused to get a brief introduction about GraphQL and its features.
The agenda for this article to get more into the process and discuss the steps involved to get started with GraphQL endpoint for your next RESTful API from scratch in NodeJs using KoaJs, we will also be using koa2-cors
for CORS support along with the mongoose
ORM for MongoDb. So let’s get started.
NodeJS - v6 or later
// Download latest node verison https://nodejs.org/en/download/
// Dependancies
graphql, koa, koa-graphql, koa-mount, koa2-cors, mongoose
// run below command to install all the dependancies at once
npm i -S graphql koa koa-graphql koa-mount koa2-cors mongoose
For this example I have created a directory structure as follows
src /
controller // all controllers
model // all mongoose models
schema // graphql schema
config.js // application config
index.js // koa app
util.js // utilities
.babelrc // to support ES7
The whole idea here is to modularize the application and separate the data and business logic. Directory model will have all the mongoose model acting as data layer and controller will have all the business logics implemented on the data layer. We will be using controllers directory into the schema which will be routing rules for the application.
Application config src/config.js
// Application level config
const app = {
host: '127.0.0.1',
port: 5000
};
// Database config
const database = {
host: '127.0.0.1',
port: 27017,
user: '',
password: '',
name: 'graphql',
replica: false,
};
database.uri = `mongodb://${database.host}/${database.name}`;
if(database.user !== '') database.uri = `mongodb://${database.user}:${encodeURIComponent(database.password)}@${database.host}:${database.port}/${database.name}?authSource=admin`;
export default {
app,
database
}
The entry point of Koa app defined in src/index.js
which initialize the Koa app with CORS and GraphQL configurations.
// Babel Polyfil for ES6/7 support
import 'babel-polyfill';
import Koa from 'koa';
import cors from 'koa2-cors';
import mount from 'koa-mount';
import mongoose from 'mongoose';
import graphQLHTTP from 'koa-graphql';
import config from './config';
import schema from './schema';
// Creating new Koa app
const app = new Koa();
// Initialize the mongoose and connect to the MongoDb database
mongoose.connect(config.database.uri);
mongoose.connection.on('error', console.error);
mongoose.Promise = global.Promise;
app
.use(cors()) // support CORS
.use(mount('/graphql', graphQLHTTP({
schema: schema,
graphiql: true
})));
app.listen(config.app.port, config.app.host, () => {
console.log(`🖥 Server started at //${config.app.host}:${config.app.port}/graphql`);
});
A GraphQL schema which contains Type and Field, a sample user schema is defined in src/schema/user.js
import {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLList
} from 'graphql';
import UserController from '../controller/UserController';
// export Type User
export const UserType = new GraphQLObjectType({
name: "UserType",
description: "Type for user",
fields: () => ({
id: {type: GraphQLString},
first_name: {type: GraphQLString},
last_name: {type: GraphQLString},
email: {type: GraphQLString},
avatar: {type: GraphQLString}
})
});
// export Field User
export const UserField = {
type: new GraphQLList(UserType),
args: {
first_name: {type: GraphQLString},
last_name: {type: GraphQLString}
},
resolve: UserController.all
}
All the business logics for the application will be in controllers, a sample controller is defined in src/controller/UserController.js
import User from '../model/User';
class UserController{
constructor(){
return {
all: this.all.bind(this)
}
}
// root and args from resolve
all(root, args) {
return User.find().exec();
}
}
export default new UserController();
Model is data layer for the application in this app a Mongoose model, a sample model is defined in src/mode/User.js
which is being used in User Controller
import mongoose from 'mongoose';
const UserSchema = mongoose.Schema({
id: String,
first_name: String,
last_name: String,
email: String,
password: String,
avatar: String
});
export default mongoose.model('User', UserSchema);
Every GraphQL requests for this application land to the URL http://127.0.01/graphql on which we have mounted our GraphQL HTTP module.
Then the request will be sent to the corresponding Query or Mutation after GraphQL HTTP verifies the request and the requested Query or Mutation is found for example
// A GraphQL request for user
{
user {
first_name,
last_name
}
}
This request will land to the GraphQL endpoint and them GraphQL HTTP module will pass it to the resolve method of user field defined in user schema. The resolve method is a method from UserController.
The Koa app which we generally use for RESTful API development it contains a Router which route the requests to their corresponding method defined in Controller, in GraphQL there is only one endpoint which have multiple Query or Mutation.
GraphQL HTTP handles the routing between Queries and Mutation being requests by client and pass the Query or Mutation requests to their defined fields.
GraphQL HTTP will also throw error when a request Query or Mutation is defined in the schema.
This is to get started with GraphQL using KoaJS and MongoDb with CORS support using koa2-cors in a native fashion.
The modularity in this KoaJS GraphQL RESTful API application is achieved by separating the individual fields from Query/Mutation schema and pointing their resolve method directly to the corresponding controller.
Hope you enjoy reading this, please share this to spread the awesomeness of GraphQL and KoaJS.
Don’t forget to share your suggestions to improve this and future articles.
Happy coding :)
Google Develover Expert — WebTechnologies and Angular | Principal Architect at Naukri.com | Entrepreneur | TechEnthusiast | Speaker