The newest buzzword in API development is GraphQL. Although RESTful APIs are the most widely used method of exposing data from apps, they have a number of drawbacks that they seek to address.
A query language developed by Facebook called GraphQL was made open-source in 2015. It offers a simple and adaptable syntax for describing and interacting with data in an API.
The creation of a GraphQL node.js project will be covered in this tutorial. A Todo application will be created using GraphQL and the Express.js web framework for Node.
What is GraphQL?
GraphQL is a query language for APIs and a runtime for executing such queries with your current data, according to their official documentation. By allowing you to query only the information you need, it simplifies API evolution and provides a comprehensive, intelligible description of your data.
GraphQL operates as a server-side runtime, executing queries based on a defined type system. It is independent of storage engines or databases, relying instead on existing code and data stores. For a thorough comparison with RESTful APIs, see our GraphQL vs. RESTful API article.
To set up a GraphQL service, define schema types and fields, then implement resolvers for each field and type to handle client-side requests.
GraphQL glossary
The GraphQL type system defines how to describe and manipulate data. This system is the core of GraphQL. Let’s explore the techniques for working with data in GraphQL.
type
GraphQL object types feature strongly typed fields. Your data models should align directly with these GraphQL types.
type User {
id: ID! # The "!" means required
firstname: String
lastname: String
email: String
username: String
todos: [Todo] # Todo is another GraphQL type
}
questions
All of the queries that a client can issue using the GraphQL API are defined by a graphical query. You should specify the root query, which should contain all open inquiries by the conference.
Below we define and map queries to the corresponding RESTful APIs:
type RootQuery {
user(id: ID): User # Corresponds to GET /api/users/:id
users: [User] # Corresponds to GET /api/users
todo(id: ID!): Todo # Corresponds to GET /api/todos/:id
todos: [Todo] # Corresponds to GET /api/todos
}
mutation
If GraphQL queries receive requests that modify the GraphQL API, such as Post, Put, patch, and delete requests.
we will put all the mutations in one root mutation To display:
type RootMutation {
createUser(input: UserInput!): User # Corresponds to POST /api/users
updateUser(id: ID!, input: UserInput!): User # Corresponds to PATCH /api/users
removeUser(id: ID!): User # Corresponds to DELETE /api/users
createTodo(input: TodoInput!): Todo
updateTodo(id: ID!, input: TodoInput!): Todo
removeTodo(id: ID!): Todo
}
Have you noticed the use of -Input type for mutation, such as user input and todo input? It is great practice to designate input types when building and updating your resources.
you can define the Input type like below:
input UserInput {
firstname: String!
lastname: String
email: String!
username: String!
}
conciliator
Resolvers tell GraphQL what to do when each query or mutation is requested. It’s a basic function that does the hard work of hitting the database layer to perform CRUD (Create, Read, Update, Delete) operations, hit an internal RESTful API endpoint, or satisfy a client request. Calls a microservice.
you can make a new resolver.js file and add the following code:
import sequelize from '../models';
export default function resolvers () {
const models = sequelize.models;
return {
// Resolvers for Queries
RootQuery: {
user (root, { id }, context) {
return models.User.findById(id, context);
},
users (root, args, context) {
return models.User.findAll({}, context);
}
},
User: {
todos (user) {
return user.getTodos();
}
},
}
// Resolvers for Mutations
RootMutation: {
createUser (root, { input }, context) {
return models.User.create(input, context);
},
updateUser (root, { id, input }, context) {
return models.User.update(input, { ...context, where: { id } });
},
removeUser (root, { id }, context) {
return models.User.destroy(input, { ...context, where: { id } });
},
// ... Resolvers for Todos go here
}
};
}
plan
The GraphQL schema is what GraphQL exposes to the world. Therefore, types, queries, and mutations will be included inside the schema to be exposed to the world.
Below is how to expose types, queries, and mutations to the world:
schema {
query: RootQuery
mutation: RootMutation
}
In the above script, we included root query And root mutation We were created first to appear before the world.
How graphql works with nodejs and expressjs
GraphQL implements all major programming languages, and Node.js is no exception. But Official GraphQL Website-there is a section for Javascript support and also, and there are other implementations of GraphQL to simplify writing and coding in GraphQL.
GraphQL Apollo provides implementations for Node.js and Express.js and makes it easy to get started with GraphQL.
The next section will teach you how to create and develop your first GraphQL application.
Setting up GraphQL with Express.js
Building a GraphQL API server with Express.js is straightforward to get started. In this section, we will figure out how to build a graphical server.
initialize the project with the express
First, you’ll need to install and set up a new Express.js project.
Create a folder for your project and install Express.js using this command:
cd <project-name> && npm init -y
npm install express
The previous operation generates a fresh package. Install the Express.js library and a JSON file in your project.
The structure of our project will then be as indicated in the image below. Separate modules for the project’s characteristics, such as users and to-dos, would be included.
Sign up for newsletter
Want to know how we grew our traffic by over 1000%?
initialize graphically
Let’s start by installing the GraphQL Express.js dependencies. Run the following command to install:
npm install apollo-server-express graphql @graphql-tools/schema --save
create schema and types
Next, we’re going to make an index.js file inside the modules folder and add the following code snippet:
const { gql } = require('apollo-server-express');
const users = require('./users');
const todos = require('./todos');
const { GraphQLScalarType } = require('graphql');
const { makeExecutableSchema } = require('@graphql-tools/schema');
const typeDefs = gql`
scalar Time
type Query {
getVersion: String!
}
type Mutation {
version: String!
}
`;
const timeScalar = new GraphQLScalarType({
name: 'Time',
description: 'Time custom scalar type',
serialize: (value) => value,
});
const resolvers = {
Time: timeScalar,
Query: {
getVersion: () => `v1`,
},
};
const schema = makeExecutableSchema({
typeDefs: [typeDefs, users.typeDefs, todos.typeDefs],
resolvers: [resolvers, users.resolvers, todos.resolvers],
});
module.exports = schema;
code walkthrough
Let’s work through the code snippet and break it down:
Phase 1
We constructed the default query and mutation types before importing the necessary libraries. For the time being, the query and mutation just set the GraphQL API version. But as we advance, we’ll add more schemas to the list of queries and modifications.
step 2:
Then we created a new scalar type for time and our first resolver for the query and mutation created above. In addition, we also generated a schema using the makeExecutableSchema function.
The generated schema includes all other schemas we’ve imported and will include more schemas as we create and import them.
From the code excerpt above, we see that we imported several schemas into the makeExecutableEchema method. This approach allows us to manage the complexity of the application effectively. By doing this, we create the Todo and User schemas.
create todo schema
The todo schema displays basic CRUD actions that application users can execute. The schema for the Todo CRUD operation is shown below.
const { gql } = require('apollo-server-express');
const createTodo = require('./mutations/create-todo');
const updateTodo = require('./mutations/update-todo');
const removeTodo = require('./mutations/delete-todo');
const todo = require('./queries/todo');
const todos = require('./queries/todos');
const typeDefs = gql`
type Todo {
id: ID!
title: String
description: String
user: User
}
input CreateTodoInput {
title: String!
description: String
isCompleted: Boolean
}
input UpdateTodoInput {
title: String
description: String
isCompleted: Boolean
}
extend type Query {
todo(id: ID): Todo!
todos: [Todo!]
}
extend type Mutation {
createTodo(input: CreateTodoInput!): Todo
updateTodo(id: ID!, input: UpdateTodoInput!): Todo
removeTodo(id: ID!): Todo
}
`;
// Provide resolver functions for your schema fields
const resolvers = {
// Resolvers for Queries
Query: {
todo,
todos,
},
// Resolvers for Mutations
Mutation: {
createTodo,
updateTodo,
removeTodo,
},
};
module.exports = { typeDefs, resolvers };
code walkthrough
Let’s work through the code snippet and break it down:
Phase 1:
First, we created a schema for our todos using GraphQL type, InputAnd Detailed, Detailed Keywords are used to inherit and add new queries and mutations to existing root queries and mutations we create.
step 2:
Next, we created a resolver, which is used to retrieve the correct data when a particular query or mutation is called.
With the resolver function, we can create separate methods for business logic and database manipulation as shown in the create-todo.js example.
make create-user.js ./mutations
File in a folder and add business logic to create a new to-do in your database.
const models = require('../../../models');
module.exports = async (root, { input }, context) => {
return models.todos.push({ ...input });
};
The above code snippet is a simple way to create a new todo in our database using Sequelize ORM. you can learn more about Sequelize and how to set it up with Node.js,
You can follow the same steps to create multiple schemas depending on your application or you can Clone the complete project from GitHub,
Next, we are going to set up the server with Express.js and run the newly created Todo application with GraphQL and Node.js
installation and run server
Last but not least, we’ll configure our server with apollo-server-express. The library is first installed, then configured.
apollo-server-express Apollo Server is a straightforward Express.js wrapper that is suggested because it was created to work with Express.js’s development.
Let’s configure the Express.js server to work with the recently installed server apollo-server-express using the samples covered above.
Add the following code to the server.js file in the root directory:
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const schema = require('./modules');
const app = express();
async function startServer() {
const server = new ApolloServer({ schema });
await server.start();
server.applyMiddleware({ app });
}
startServer();
app.listen({ port: 3000 }, () =>
console.log(`Server ready at
);
In the code above, you have successfully created your first CRUD GraphQL server for Todos and Users. You can start your development server and use playground http://localhost:3000/graphql, If everything is successful, you should be presented with the screen below:
summary
Facebook supports GraphQL, a cutting-edge technology that makes it easier to construct complex APIs using the RESTful architectural pattern.
This tutorial has introduced GraphQL and demonstrated how to use Express JS to create your first GraphQL API.
Tell us what you create with GraphQL.
I am an experienced writer and technology enthusiast contributing to Hostao Blogs. With a degree in Computer Science and a background in web hosting, I simplify complex tech topics for all readers. My articles cover web development, cybersecurity, and emerging digital trends. I'm dedicated to making technical subjects accessible and providing valuable insights. Beyond writing, I'm an avid tech explorer and outdoor enthusiast, always at the forefront of digital advancements.