Express GraphQL Server

Mutation :

Mutation allows you to do is to create actions on your graphql server .

From the Main query type there is also another built in type which is known as mutation, so one of the typical actions in a CRUD application would be to create a resource.

In this case we could have a function let’s call it addUser , it is called mutation function its actually going to accept an email which has to be a string and it cannot be null , basically saying that this email address is a required field we could also ask for a name which could be optional

When you call that add user action we’re expect to get back a user object or basically an object of the user type in order to actually implement this add user function we’re have to add it in the resolvers object

adduser function is going to expect arguments now one of the arguments is know as the arguments object which basically refers to the arguments that are going to be passed with the query into your graphQL endpoint.

Example 1 : Express Graphql Server – Query, Mutation

Dependencies :

{
  "name": "GraphQL_intro",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "express": "^4.17.1",
    "express-graphql": "^0.9.0",
    "graphql": "^15.1.0"
  },
  "devDependencies": {
    "supervisor": "^0.12.0"
  }
}

Index.js

const express  = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');
const crypto = require('crypto');

app = express();

const db={
    users: [
        { id: '1', email: 'alex@gmail.com', name: 'Alex', avatarUrl: 'https://gravatar.com/...' },
        { id: '2', email: 'max@gmail.com', name: 'Max', avatarUrl: 'https://gravatar.com/...' }
    ],
}

//We should have the definition for Query and Mutation type properties in resolver

const schema = buildSchema(`
    type Query{
        users : [User!]!
        user(id: ID!): User
    }

    type Mutation {
        addUser(email: String!, name: String): User
    }

    type User{
        id: ID!
        email: String!
        name: String
        avatarUrl: String
    }
`)

//In order to return users, we have to have a resolver function
const rootValue = {
    users: () => db.users,
    user: args => db.users.find(user => user.id === args.id),
    addUser: ({email, name})=>{
        const user = {
            id: crypto.randomBytes(10).toString(),
            email,
            name
        }

        db.users.push(user);
        return user
    }
}

app.use('/graphql', graphqlHTTP({
    schema,
    rootValue,
    graphiql:true
}))

app.listen(3000, ()=>{console.log("Server Listening Port 3000")})

OUTPUT :

1. Query User by Id : 
===================
query {
  user(id:"1"){
    id,
    name,
    email
  }
}

{
  "data": {
    "user": {
      "id": "1",
      "name": "Alex",
      "email": "alex@gmail.com"
    }
  }
}

******************
2. Mutation addUser : 
==================
mutation{
  addUser(email:"xyz@abc.com", name:"Praba"){
    id,
    name,
    email
  }
}

{
  "data": {
    "addUser": {
      "id": "qϒ|�\u000e����",
      "name": "Praba",
      "email": "xyz@abc.com"
    }
  }
}

************************
3. Query User by variable : 
========================
query getUser($id:ID!){
  user(id: $id){
    id,
    email,
    name
  }
}

Query Variables : 
{
  "id": "1"
}


{
  "data": {
    "user": {
      "id": "1",
      "email": "alex@gmail.com",
      "name": "Alex"
    }
  }
}

Example 2 : What happen if the users has the reference of the message. The message is another collection

const express  = require('express');
const graphqlHTTP = require('express-graphql');
const {buildSchema} = require('graphql');
const crypto = require('crypto');

app = express();

const db={
    users: [
        { id: '1', email: 'alex@gmail.com', name: 'Alex', avatarUrl: 'https://gravatar.com/...' },
        { id: '2', email: 'max@gmail.com', name: 'Max', avatarUrl: 'https://gravatar.com/...' }
    ],
    messages: [
        {id: '1', userId: '1', body:'Hello', createdAt: Date.now()},
        {id: '2', userId: '2', body:'Hi', createdAt: Date.now()},
        {id: '3', userId: '2', body:'Whats app', createdAt: Date.now()},
    ]
}

class User {
    constructor (user){
        Object.assign(this, user)
    }

    get message(){
        return db.messages.filter(message => message.userId === this.id)
    }
}

//We should have the definition for Query and Mutation type properties in resolver

const schema = buildSchema(`
    type Query{
        users : [User!]!
        user(id: ID!): User
        messages: [Message!]!
    }

    type Mutation {
        addUser(email: String!, name: String): User
    }

    type User{
        id: ID!
        email: String!
        name: String
        avatarUrl: String
        message: [Message!]!
    }

    type Message {
        id: ID!
        body: String!
        createdAt: String
    }
`)

//In order to return users, we have to have a resolver function
const rootValue = {
    //users: () => db.users,
    users: () => db.users.map(user => new User(user)),
    user: args => db.users.find(user => user.id === args.id),
    messages:()=> db.messages,
    addUser: ({email, name})=>{
        const user = {
            id: crypto.randomBytes(10).toString(),
            email,
            name
        }

        db.users.push(user);
        return user
    }
}

app.use('/graphql', graphqlHTTP({
    schema,
    rootValue,
    graphiql:true
}))

app.listen(3000, ()=>{console.log("Server Listening Port 3000")})

OUTPUT 2 :

query {
  users {
    email
    message {
      id
      body
    }
  }
}

{
  "data": {
    "users": [
      {
        "email": "alex@gmail.com",
        "message": [
          {
            "id": "1",
            "body": "Hello"
          }
        ]
      },
      {
        "email": "max@gmail.com",
        "message": [
          {
            "id": "2",
            "body": "Hi"
          },
          {
            "id": "3",
            "body": "Whats app"
          }
        ]
      }
    ]
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *