In this tutorial, we will see how to create a GraphQL Server With NodeJS Express, also will see a folder structure to maintain our code, in this lesson we will use the following packages to make our app run.
Topics
Before installing the dependencies lets initiate the project first by just regular command.
npm init
Install Dependencies
Now let’s begin installing dependencies which were mention above
npm install express graphql express-graphql cors
and to watch over the files changes we will use the nodemon as a dev dependency.
npm install --save-dev nodemon
{
"name": "dummy-app",
"version": "1.0.0",
"description": "Dummy Application Build On NodeJS and GraphQL",
"main": "index.js",
"scripts": {
"test": "",
"dev": "PORT=3000 nodemon index.js"
},
"keywords": [],
"author": "geekstrick",
"license": "MIT",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.0",
"express-graphql": "^0.8.0",
"graphql": "^14.3.0",
},
"devDependencies": {
"nodemon": "^1.19.0"
}
}
"dev": "PORT=3000 nodemon index.js"
will set the enviroment variable
Serve App Using Express
now will create the main index.js files i.e the entry point of our project and will import the required dependencies to run us an app.
touch index.js
using express js will use the app.use()
to send some message and also to run our application.
const express = require('express');
const app = express();
const graphQl = require('./graphql/index'); // will cover in further part
// will use graphQl on path http://127.0.0.1:3000/graphql
app.use('/graphql', cors(), (req, res) => {
return graphQl(req, res);
});
// will serve applocation on http://127.0.0.1:3000
app.listen(process.env.PORT, () => {
console.log('Server is runnnig on port ' + process.env.PORT); //PORT mention in package.json
});
Folder Structure Will Follow Is:
|---index.js
|
|---graphql
| |---index.js // Exports graphql Method
|
| |---mutations
| | |---allMutations.js // exports all mutations
| |
| |---queries
| | |---allQueries.js // exports all Queries
| |
| |---types
| | |---users // Distribute module for type by folder
| | | |---users.js
| | |---index.js // exports all types
| |
| |---resolvers
| | |---users // Distribute module for resolvers by folder
| | | |---getAllUsers.js
| | | |---adduser.js
| | | |---index.js // module index file which will export all module resolvers
| | |---index.js // exports all resolvers
GraphQL index.js
in this, the module will have to return the graphql method which we have imported in our main index.js file. It will run the graphql playground to make GET and POST request.
so let’s get into it.
const express_graphql = require('express-graphql');
const { buildSchema } = require('graphql');
const allTypes = require('./types/index'); // All Exported Types
const allQueries = require('./queries/allQueries'); // All Exported Queries
const allMutation = require('./mutations/allMutations'); // All Exported Mutations
const resolvers = require('./resolvers/index'); // All Exported Resolvers
// this will build all the schema
const schema = buildSchema(`${allQueries} ${allMutation} ${allTypes}`);
// graphQl method
const express_graphiql = (req, res) => {
return express_graphql({
schema: schema, // Build schema
rootValue: resolvers, // Resolvers
graphiql: true,
})(req, res);
};
module.exports = express_graphiql; //Exporting graphQl method
All the queries and mutations and types will be included in buildschema()
object which will build all the types mutations and query also you can see we have passed the request and response as arguments which will be used in resolvers to get the request params in case.
and at the end, we have created a graphql method which will be exported with all goodies.
GraphQL -Types
In this types folder, we will declare our types which is basically a model which defines the data type to the particular response of mutation or a query or else it can be the input type to send data to request body.
// The response data from Resolvers will match this model
const userData = `
type userData {
id: Int
username: String
email: String
mobile: String
role: String
isActive: String
}`;
module.exports = userData;
Similarly, we will create a new input type which accepts the params form the client side.
// The request data in mutation will match this model
const userInputData = `
input userInputData {
authorName: String!
authorSlug: String!
authorPic: String!
authorTitle: String!
}`;
module.exports = `${userData} ${userInputData}`; //combining Both types (there are many approach to be done to combine types)
String!
Means it is a required fieldGraphQL -Queries
let’s define the queries which we have to use, as for now will just define a single query which will be getAllUsers
which will give us an array of userList.
const allQueries = `
type Query {
getAllUsers: [userData]
}
`;
module.exports = allQueries;
type Query {}
will contain all our queries so we have to define all the different queries in a single type Query {}
object.
[userData]
means its an array. In case if you get userById and there must be one output you can simply define getAllUsers: userData
which will return an objectGraphQL -Mutations
let’s define the mutation which we have to use, as for now will just define a single mutation which will be addUser
which will add user data wherever we want.
const allMutations = `
type Mutation {
addUser(inputs:userInputData!): userData
}
`;
module.exports = allMutations;
type Mutation {}
will contain all our Mutation so we have to define all the different Mutation in a single type Mutation {}
object.
userInputData
means its an object inputs. In case if you want to add multiple records in single go so basically you will pass an array and that can be done by addUser(inputs:[userInputData!]): [userData]
which will return an objectGraphQL -Resolvers
lets began with the last part which will make our queries and mutation into action.
First of all, we will make a resolver method for getAllUsers basically which will return all the user data.
let getAllUsers = (root, args, context, info) => {
return new Promise(resolve => {
// any Data that come form DB
const data = [{
id: 1,
username: 'geekstrick',
email: '[email protected]',
mobile: '9893XX-XXXX',
role: 'Admin',
isActive: '0',
},
{
id: 2,
username: 'geekstrick-dummy',
email: '[email protected]',
mobile: '9893XX-XXXX',
role: 'Non-Admin',
isActive: '1',
}]
resolve(data);
});
};
module.exports = getAllUsers;
Similarly, for mutation, we will define a method that can add data.
assuming adding a single set of user data
let addUser = (root, args, context, info) => { // root contains all the input params
return new Promise(resolve => {
const AddedData = {
username: root.username,
email: root.email,
mobile: root.mobile,
role: root.role,
} ]
resolve(AddedData); // Added Data in Response
});
};
module.exports = addUser;
root
: Contains all the input params pass as variablesargs
: Contains the header properties of request
Now the final part in which we will assign the resolvers method to the respective query and mutation.
const getAllUsers = require('./users/getAllUsers'),
addUser = require('./users/addUser');
// root resolvers
var resolvers = {
getAllUsers: getAllUsers,
addUser: addUser,
};
module.exports = resolvers;
now hit the http://127.0.0.1:3000/graphql and make a request to a graphql server