DEV Community

Dalibor Belic
Dalibor Belic

Posted on • Originally published at blog.daliborbelic.com on

Building Backend | Node, Postgres, GraphQL

Hi there 👋

Every application, you'll agree, needs a back-end. And there are many languages and tools that can accomplish that. But, in this quick tutorial, I'll show you how to set up the GraphQL backend server with Node, and PostgreSQL- a quite common stack for building robust back-ends that operate with large amounts of data. Be that as it may, I'm assuming you did your research, hence you decided on this tool combination.

Structure and packages

First, let's define the structure of the server.

▶ Paste this into terminal: npm init -y and create the required files and folders

Screenshot 2021-06-07 082444.png

Now, do install all the packages we'll need: npm i apollo-server graphql graphql-tag pg

INDEX.JS

In the index.js, the entry point of our project, we paste this:

const { ApolloServer } = require("apollo-server");
const typeDefs = require("./graphql/typeDefs");
const resolvers = require("./graphql/resolvers");

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req }) => {
    return { req };
  },
});

const PORT = process.env.PORT || 4000;

server.listen({ port: PORT });
console.log("Server up and running on port: " + PORT);

Enter fullscreen mode Exit fullscreen mode

✅ The server is up and running!

Postgres

I'll assume you have Postgres installed. So, open your terminal and log into Postgres. In my case: psql -U postgres + password. After logging in create a new database that we'll use in this tutorial: CREATE DATABASE dogdb

Now in db.js file, we'll prepare the connection to our database. Through pool we'll be communicating with it.

const Pool = require("pg").Pool;

const pool = new Pool({
  user: "postgres",
  password: "postgres",
  host: "localhost",
  port: 5432,
  database: "dogdb",
});

module.exports = pool;

Enter fullscreen mode Exit fullscreen mode

Back in the terminal, we'll create a new table (in tables we store data). But before that, we'll install the 'uuid-ossp' extension that will later generate unique ids for each instance in our db.

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";


CREATE TABLE dog(
    uid UUID NOT NULL PRIMARY KEY,
    name VARCHAR(20) NOT NULL,
    breed VARCHAR(40) NOT NULL
);

Enter fullscreen mode Exit fullscreen mode

✅ DB is ready!

GraphQL

In typeDefs, we define types, queries and mutations. In other words, we describe the data and the manipulations of the data that we'll utilize later.

const gql = require('graphql-tag');

module.exports = gql`
  type Dog{
      uid: ID!
      name: String!
      breed: String!
    }

  type Query {
      getDogs: [Dog]
  }

  type Mutation{
      addDog(name: String!, breed: String!): Dog!
      editDog(name: String!, breed: String!): Dog!
      deleteDog(uid: ID!): String!
  }
`

Enter fullscreen mode Exit fullscreen mode

Now, create a new file in the resolvers folder, next to the index.js, and call it dogs.js. There, in that file, we'll write CRUD operations for type Dog. Before that, let's first import dogs.js to index.js (the entry point for resolvers).

const dogsResolvers = require('./dogs');

module.exports = {
  Query: {
    ...dogsResolvers .Query,
  },
  Mutation: {
    ...dogsResolvers .Mutation,
  },
};

Enter fullscreen mode Exit fullscreen mode

Later, if you decide to have cats (or even badgers). You'll do the same. Create cats.js in the resolvers folder and import it in index.js.

Now, let's do CRUD!

const pool = require('../../db')

module.exports = {
  Query: {
    async getDogs() {
      try {
        const dogs = await pool.query('SELECT * FROM dogs')
        return dogs.rows;
      } catch (error) {
        throw new Error(error);
      }
    },
  },
Mutation: {
    async addDog(_, { name, breed }) {
      try {
        const query = {
          text: 'INSERT INTO dog(uid, name, breed) VALUES(uuid_generate_v4(), $1, $2) 
                   RETURNING *',
          values: [name, breed]
        }
        const dog = await pool.query(query);
        return dog.rows[0];
      } catch (error) {
        throw new Error(error);
      }
    },
    async editDog(_, { uid, name, breed }) {
      try {
        const query = {
          text: 'UPDATE dog SET name=$1, breed=$2 WHERE uid=$3 RETURNING *',
          values: [name, breed, uid]
        }
        const dog = await pool.query(query);
        return dog.rows[0];
      } catch (error) {
        throw new Error(error);
      }
    },
    async deleteDog(_, { uid }) {
      try {
        const query = {
          text: 'DELETE FROM dog WHERE uid=$1',
          values: [uid]
        }
        await pool.query(query)
        return 'Dog deleted'
      } catch (error) {
        throw new Error(error);
      }
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

✅✅✅ Congrats! You build the server!!! 🥳🚀

Let's try it out!

Open your browser and go to this URL: http://localhost:4000/ We'll check if our server works!

addDog

image.png

getDogs

image.png

editDog

image.png

deleteDog

image.png

Amazing, isn't it?

Bravo! You reached the end of this post! Thanks for following through, I hope you found this quick tutorial useful! Your feedback is welcome :)

Till next time,

Dalibor

Discussion (0)