Skip to main content

Command Palette

Search for a command to run...

7. GraphQL - Node.js

Published
4 min read

GraphQL is a query language for APis and runtime to execute these queries. Unlike REST (multiple endpoints), GraphQL has a single endpoint where clients specify exactly what they want.

GraphQL vs REST

RESTGraphQL
It have multiple endpoints (/users, /posts, /comments)It have single endpoint (/graphql)
It fetches extra datafetch only that data that client ask for
Uses HTTP verbs (GET, POST, PUT, DELETE)Uses queries, mutations, subscriptions
For real time data fetching it require websockets/extra setupBult in via subscription

👉 REST = server decides response
👉 GraphQL = client decides response

Node.js (Apollo Server) provides GraphQL backend.

Queries (Read data)

  • Purpose: Fetch (read) data.

  • Similar to GET in REST.

  • Queries are read-only → they never modify the server’s state.

Mutations (Create , delete , update data)

  • Purpose: Modify data (create, update, delete).

  • Similar to POST, PUT, DELETE in REST.

  • Mutations change server state and usually return the modified data.

INSTALLATIONS

npm i @apollo/server graphql graphql-tag

Define Schemas in graphQL

Schemas is used to defines types and structure of API.

const { gql } = require('graphql-tag');
//type definations
const typeDefs = gql`  
  type User {
    id: ID!          # ! means required (non-nullable)
    name: String!
    email: String!
  },

  type Query{
   users: [User]    # get all the user
   user(id: ID!):User  # get particular(one) user by id
  },

  type Mutation{
   createUser(  # create user
     name: String!
     email:String!
   ): User      # return our User

   deleteUser(id: ID!):Boolean   # we want to return boolean here

   updateUser(
     id: ID!
     name: String  # this time they are not mandotory
     email: String
   ):User
  }
`;
module.exports= typeDefs

After Schemas define - resolvers


// currently we dont have database so we assume this as a mock data
// We must create Mongoose model not used this mock data in real prjects
let users = [
  { 
    id: "1",
    name: "Ayush", 
    email: "ayush@example.com"
  },
  { 
    id: "2", 
    name: "Vansi", 
    email: "vansi@example.com" 
  },
];
// Now define resolvers here
const resolvers = {
    Query:{
        users:()=>users  // return all users , users: asycn()=> await User.find({}) -> with mongoose model
        user: (_ , {id})=> users.find(item => item.id === id) // find one user with provided id 
    },
    Mutation:{
      createUser:(_ , {name , email})=>{ //// createUser:asycn (_, args)=> {const newUser = await User.create(args) return newUser}
        const newUser = {
          id:String(users.length +1),
          name,
          email
        }
        users.push(newUser) // current we dont have db so push in mock data
        return newUser
      },
      deleteUser:(_, {id})=> {
        const index = users.findIndex(user => user.id === id);
        if(index ===-1) return false

        users.splice(index , 1)
        return true
      },
      updateUser:(_, {id , ...updates})=>{
        const index = users.findIndex(user => user.id === id);
        if(index === -1) return null
        const updatedUser = {
          ...users[index] , ...updates
        }
        users[index]=updatedUser
        return updatedUser
      }
    }
}
module.exports = resolvers

Run server

// server.js
const {ApolloServer} = require('@apollo/server')
const {startStandaloneServer} = require('@apollo/server/standalone')
const typeDefs = require('./graphql/schema')
const resolvers = require('./graphql/resolvers')

async function startServer(){
   // await dbConnect() 
    const server = new ApolloServer({
        typeDefs , resolvers
    });
    const {url} = await startStandaloneServer(server , {
        listen: {port:4000}
    })

    console.log(`Server running at: ${url}`)
}
startServer();

OnCLick on - http://localhost:4000 GraphQL redirect to apollo server UI where we test our graphQL Apis

// query to get all users testing 
query{
  users{
    name
  }
}
// Run above code we get only name field of all the users
{
  "data": {
    "users": [
      {
        "name": "Ayush"
      },
      {
        "name": "Vansi"
      }
    ]
  }
}

// query to get partucular user by id
query{
  user(id:"2"){
    name
  }
}
//output
{
  "data": {
    "user": {
      "name": "Vansi"
    }
  }
}

Mutation testing results:

// pass input : createuser
mutation{
  createUser(
    name:"Simran",
    email:"sim@gmail.com"
  ){
    name   #need only name 
  }
}
//output
{
  "data": {
    "createUser": {
      "name": "Simran",
      "email": "sim@gmail.com"
    }
  }
}

//pass input: delete User
mutation{
  deleteUser(id: "4")
}
//output
{
  "data": {
    "deleteUser": true
  }
}

//pass input: update user
mutation{
  updateUser(id:"3" , name:"SimranUpdated"){
    name
  }
}
//output
{
  "data": {
    "updateUser": {
      "name": "SimranUpdated"
    }
  }
}