Member preview

Running our first GraphQL Mutation — Part 1

User management system — Register

Graphql Typescript Server Boilerplate Serie :

In this part we will register a User by calling a Graphql Mutation.

So What is a GraphQL Mutation ?

Most discussions of GraphQL focus on data fetching, but any complete data platform needs a way to modify server-side data as well.

In REST, any request might end up causing some side-effects on the server, but by convention it’s suggested that one doesn’t use GETrequests to modify data. GraphQL is similar - technically any query could be implemented to cause a data write. However, it's useful to establish a convention that any operations that cause writes should be sent explicitly via a mutation.

Just like in queries, if the mutation field returns an object type, you can ask for nested fields. This can be useful for fetching the new state of an object after an update. Let’s look at a simple example mutation:

Let’s Start

We’ll be dealing with some security awarness when adding our users informations into a database , so we’ll Install uuid & bcryptjs packages by running :

yarn add uuid bcryptjs

We’ll use uuid/v4 to generate a randon userId , and bcryptjs to hash our userpassword information . We’ll also need some typing settings on our dev environment :

yarn add -D @types/uuid @types/bcryptjs 

We’ll also need to install nodemon package to enable hotReloading and make coding easier :

yarn add -D nodemon 

Let’s begin by making some changes on our User Entity in src/entity/User.ts

import {
Entity,
Column,
PrimaryColumn,
BeforeInsert,
BaseEntity
} from "typeorm";
import * as uuidv4 from "uuid/v4";
@Entity("users")
export class User extends BaseEntity {
@PrimaryColumn("uuid") id: string;
  @Column("varchar", { length: 255 })
email: string;
  @Column("text") password: string;
  @BeforeInsert()
addId() {
this.id = uuidv4();
}
}

Now we’ll make some code refractoring to make it more visible and well structured , so we’ll create two files schema.graphql& resolvers.ts :

You can guess that the schema.graphql should contain this:

type Query {
hello(name: String): String!
}
type Mutation {
register(email: String!, password: String!): Boolean
}
We add a simple register Mutation that takes two parameters : email & password & return a Boolean value .
String! : means it’s a string and cannot be null

Create a new file src/types/graphql-utils.ts and paste this into it

export interface ResolverMap {
[key: string]: {
[key: string]: (parent: any, args: any, context: {}, info: any) => any;
};
}

And the resolvers.ts should contain this:

import * as bcrypt from "bcryptjs";
import { ResolverMap } from "./types/graphql-utils";
import { User } from "./entity/User";
export const resolvers: ResolverMap = {
Query: {
hello: (_: any, { name }: any) =>
`Well done dear ${name ||
"Follower"} , follow me for more : https://medium.com/@siddik.mehdi`
},
Mutation: {
register: async (_ : any, { email, password } : any) => {
const hashedPassword = await bcrypt.hash(password,10)
const user = User.create({
email,
password : hashedPassword
})
await user.save()
return true
}
}
};
export default resolvers;

As you can see we specify type “any” for our resolver’s arguments , so to type out this arguments based on our schema.graphql we’ll install a libary called gql2ts ( Graphql to Typescript ) as a dev dependency locally into our project :

yarn add -D gql2ts cross-env

To use it , we have to add a script to our package.json :

{
"name": "gql-server-boilerplate",
"version": "0.0.1",
"description": "Awesome project developed with TypeORM.",
"devDependencies": {
"@types/bcryptjs": "^2.4.2",
"@types/node": "^10.12.3",
"@types/uuid": "^3.4.4",
"gql2ts": "^1.10.1",
"nodemon": "^1.18.6",
"ts-node": "6.0.0",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.15.0",
"typescript": "3.1.6"
},
"dependencies": {
"bcryptjs": "^2.4.3",
"graphql-import": "^0.7.1",
"graphql-yoga": "^1.16.7",
"path": "^0.12.7",
"pg": "^7.6.1",
"reflect-metadata": "^0.1.12",
"typeorm": "0.2.8",
"uuid": "^3.3.2"
},
"scripts": {
"start": " nodemon --exec ts-node src/index.ts",
"gen-schema-types": "gql2ts src/schema.graphql -o src/types/schema.d.ts"
}
}

I called the script “gen-schema-types” , it convert the graphql Schema ( src/schema.graphql ) and convert it to typescript types definitions 
( src/types/schema.d.ts ) . Run the script via :

yarn gen-schema-types

So now , we’ll have a control over all our types , and our resolvers.ts should look like this :

import * as bcrypt from "bcryptjs";
import { ResolverMap } from "./types/graphql-utils";
import { User } from "./entity/User";
export const resolvers: ResolverMap = {
Query: {
hello: (_, { name }: GQL.IHelloOnQueryArguments) => `Well done dear ${name ||
"Follower"} , follow me for more : https://medium.com/@siddik.mehdi`
},
Mutation: {
register: async (
_,
{ email, password }: GQL.IRegisterOnMutationArguments
) => {
const hashedPassword = await bcrypt.hash(password, 10);
const user = User.create({
email,
password: hashedPassword
});
      await user.save();
return true;
}
}
};

Now we’ll need to Install graphql-import & path packages by running :

yarn add graphql-import path

And make thesrc/index.ts look like this :

import 'reflect-metadata'
import { GraphQLServer }  from 'graphql-yoga'
import { resolvers } from './resolvers';
import { importSchema } from "graphql-import";
import * as path from 'path'
import { createConnection } from 'typeorm';
const typeDefs = importSchema(path.join(__dirname , "schema.graphql"));
const server = new GraphQLServer({ typeDefs , resolvers })
createConnection().then(() => {
server.start(() => console.log("Server is running on localhost:4000"));
});

Let’s test all that stuff now :

Register Mutation Result

And what’s going on our postgresql database ?


P.S. If you like this, make sure to subscribe, follow me on twitter, 
follow me on
Instagram, support me on patreon, and share this
with your friends 😀


Graphql Typescript Server Boilerplate Serie :