DEV Community

loading...

Create a simple GraphQL API with Node JS

zoun profile image Sonia ・5 min read

I used for the first time GraphQL a few days ago and i wanted to share with you what i learned.

In this project, we are going to use GraphQL for one of my favorite Tv Shows : Friends !

11103892_f57d05a21e.jpg

Let's get started

Create a new project

mkdir mygraphQlApi
cd mygraphQlApi
npm init
Enter fullscreen mode Exit fullscreen mode

We are going to use :

  • Koa
npm install koa --save
Enter fullscreen mode Exit fullscreen mode
npm install koa-bodyparser koa-helmet koa-router --save
Enter fullscreen mode Exit fullscreen mode
  • Knex and Knex CLI
npm install knex -g
Enter fullscreen mode Exit fullscreen mode
npm install knex@0.13.0 -g
Enter fullscreen mode Exit fullscreen mode
  • Postgres
npm install pg --save
Enter fullscreen mode Exit fullscreen mode
  • GraphQL
npm install graphql graphql-tools apollo-server-koa --save
Enter fullscreen mode Exit fullscreen mode

 Create the Database

We are going to connect to Postgres

sudo -u postgres psql postgres
Enter fullscreen mode Exit fullscreen mode

Then create the database

postgres=# CREATE DATABASE friends;

Enter fullscreen mode Exit fullscreen mode

List your databases to see your new DB just created

postgres=# \list

Enter fullscreen mode Exit fullscreen mode
                                   List of databases
    Name     |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-------------+----------+----------+-------------+-------------+-----------------------
 friends     | postgres | UTF8     | fr_FR.UTF-8 | fr_FR.UTF-8 | 
 postgres    | postgres | UTF8     | fr_FR.UTF-8 | fr_FR.UTF-8 | 
 template0   | postgres | UTF8     | fr_FR.UTF-8 | fr_FR.UTF-8 | =c/postgres          +
             |          |          |             |             | postgres=CTc/postgres
 template1   | postgres | UTF8     | fr_FR.UTF-8 | fr_FR.UTF-8 | =c/postgres          +
             |          |          |             |             | postgres=CTc/postgres

Enter fullscreen mode Exit fullscreen mode

Finally create a user with a password

CREATE USER myusername WITH PASSWORD 'password';
Enter fullscreen mode Exit fullscreen mode

Connect to your DB

psql -h localhost -d friends -U myusername
Password for user myusername: 


friends=> 

Enter fullscreen mode Exit fullscreen mode

Everything is fine !

Type \q to quit.

Back to the project

We are going to create a folder called knex and some subfolders for our seeds, migrations and queries.

mkdir knex
mkdir knex/migrations
mkdir knex/seeds
mkdir knex/queries
Enter fullscreen mode Exit fullscreen mode

Then, to store some data, we are goind to create a folder called data, with a cast.js file inside that folder.

mkdir data
cd data
touch cast.js
Enter fullscreen mode Exit fullscreen mode

Initiate the project

knex init
Enter fullscreen mode Exit fullscreen mode

This command will create a file called knex.js

Let's modify the file like this :

module.exports = {
 development: {
  client: 'pg',
  connection: 'postgres://username:password@localhost:5432/database',
  migrations: {
      directory: __dirname + '/knex/migrations',
    },
    seeds: {
      directory: __dirname + '/knex/seeds'
    }
 }
};
Enter fullscreen mode Exit fullscreen mode

NB : Replace the username, password and database value with the right ones.

Now your project should look like this

Capture d'écran 2021-02-07 18:46:02.png

The Database is empty !

For now, you have a database, but with no data ! Let's fix that !

First , let's create a table on the DB.

knex migrate:make cast
Using environment: development
Created Migration: /path/of/your/project/knex/migrations/20210207185018_cast.js

Enter fullscreen mode Exit fullscreen mode

This command is going to create a migration file, let's modify it like this

exports.up = (knex) => Promise.all([
    knex.schema.createTable('cast', function(table) {
        table.increments();
        table.string('firstName').notNullable();
        table.string('lastName').notNullable();
        table.string('Food').notNullable();
    })
]);

exports.down = (knex) => {
return knex.schema.dropTable('cast');
};
Enter fullscreen mode Exit fullscreen mode

Now let's "run" the migration

knex migrate:latest --env development
Using environment: development
Batch 1 run: 1 migrations

Enter fullscreen mode Exit fullscreen mode

Now that we have a table, let's fill it with some data.
We are going to "seed" the table.

knex seed:make cast_seed
Using environment: development
Created seed file:/path/of/your/project/knex/seeds/cast_seed.js

Enter fullscreen mode Exit fullscreen mode

In the data folder, go to your cast.js file and complete it like this :

module.exports = [
    {
      "firstName": "Chandler",
      "lastName": "Bing",
      "Food": "Cheesecake"
    },
    {
        "firstName": "Monica",
        "lastName": "Geller",
        "Food": "Mint Cookies"
    },
    {
        "firstName": "Joey",
        "lastName": "Tribiani",
        "Food": "Pizza"
    }
];

Enter fullscreen mode Exit fullscreen mode

Complete your seed file like this to seed the DB with the data from your file.

const castData = require('../../data/cast');

exports.seed = function(knex) {
  // Deletes ALL existing entries
  return knex('cast').del()
    .then(function () {
      // Inserts seed entries
      return knex('cast').insert(castData);
    });
};
Enter fullscreen mode Exit fullscreen mode

Let's now run this command

knex seed:run --env development
Using environment: development
Ran 1 seed files

Enter fullscreen mode Exit fullscreen mode

Let's connect to the DB, to see our data

psql -h localhost -d friends -U myusername
Password for user myusername: 

friends=> SELECT * FROM public.cast;
 id | firstName | lastName |    Food     
----+-----------+----------+-------------
  1 | Chandler  | Bing     | Cheesecake
  2 | Monica    | Geller   | MintCookies
  3 | Joey      | Tribiani | Pizza
(3 rows)

Enter fullscreen mode Exit fullscreen mode

Congrats, you have now a DB, with a table called cast, and some data in that table!

Next step, the GraphQL part !

GraphQL part

Now let's make the GraphQL part.

Let's create a file called index.js

touch index.js
Enter fullscreen mode Exit fullscreen mode

It should look like this

const Koa = require('koa');
const { ApolloServer, gql } = require('apollo-server-koa');
const queries = require('./knex/queries/queries.js');

const typeDefs = gql`
  type Cast {
    firstName: String
    lastName: String
    Food: String
  }
  type Query {
    cast(firstName: String, lastName: String, Food: String): [Cast]
  }
`;

const schema = {
  typeDefs,
  resolvers: {
    // Prototypes for GET 
    Query: {
      cast: (_, filters) => queries.getCast(filters),
    }
  }
}

const server = new ApolloServer(schema);

const app = new Koa();
server.applyMiddleware({ app });

app.listen({ port: 3000 }, () =>
  console.log(`🚀 Server ready at http://localhost:3000${server.graphqlPath}`),
);
Enter fullscreen mode Exit fullscreen mode

As you can see line 3, we are using queries , let's create them :

In the knex folder, we created a folder called queries. Let's create a file called queries.js

cd knex/queries
touch queries.js
Enter fullscreen mode Exit fullscreen mode
const knex = require('../connect');

function getCast(filters) {
  return knex('cast')
  .select('*')
  .where(filters);
}

module.exports = {
  getCast
};
Enter fullscreen mode Exit fullscreen mode

Let create the connect file used on the first line

cd ../
touch connect.js
Enter fullscreen mode Exit fullscreen mode
const environment = process.env.NODE_ENV || 'development';
const config = require('../knexfile.js')[environment];

module.exports = require('knex')(config);
Enter fullscreen mode Exit fullscreen mode

Now, let's start our server

node index.js
🚀 Server ready at http://localhost:3000/graphql

Enter fullscreen mode Exit fullscreen mode

You should see something like this

Capture d'écran 2021-02-13 19:10:00.png

Query some data

Let's try to query some data

# Write your query or mutation here
query Everyone {
  cast {
    firstName
  }
}
Enter fullscreen mode Exit fullscreen mode

Click on the Play button

{
  "data": {
    "cast": [
      {
        "firstName": "Chandler"
      },
      {
        "firstName": "Monica"
      },
      {
        "firstName": "Joey"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Tadaaaam ! You have made your first query with GraphQL !

Let's add some characters

But wait a minute ... where is Ross ? and Rachel ? And Phoebe ?

We need to add them to our database.

Let's use Mutations for that.

In your index.js file, let's update the schema to add Mutations

# index.js
const typeDefs = gql`
  type Cast {
    firstName: String
    lastName: String
    Food: String
  }
  type Query {
    cast(firstName: String, lastName: String, Food: String): [Cast]
  }
  type Mutation {
  addSomeone(firstName: String, lastName: String, Food: String): [Cast]
}
`;

const schema = {
  typeDefs,
  resolvers: {
    // Prototypes for GET 
    Query: {
      cast: (_, filters) => queries.getCast(filters),
    },
    // Prototypes for PUT
    Mutation: {
        addSomeone: async (_, cast) => {
          const newOne = await queries.addSomeone(cast);

          return newOne;
        }
      }
  }
}
Enter fullscreen mode Exit fullscreen mode

Then in the queries.js file, let's create the actual queries for those mutations.

# queries.js

const knex = require('../connect');

function getCast(filters) {
  return knex('cast')
  .select('*')
  .where(filters);
}

function addSomeone(cast) {
    return knex('cast')
    .insert({
      firstName: cast.firstName,
      lastName: cast.lastName,
      Food: cast.Food
    })
    .returning('*');
}

module.exports = {
  getCast,
  addSomeone
};
Enter fullscreen mode Exit fullscreen mode

Restart our server and write a Mutation to add Ross

mutation addRoss{
  addSomeone(firstName: "Ross", lastName: "Geller", Food: "Turkey Sandwich") {
    firstName
  }
}
Enter fullscreen mode Exit fullscreen mode

Hit the play button

{
  "data": {
    "addSomeone": [
      {
        "firstName": "Ross"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Let's query all the cast once again

# Write your query or mutation here
query Everyone {
  cast {
    firstName
  }
}
Enter fullscreen mode Exit fullscreen mode

Click on play ... and cross fingers

{
  "data": {
    "cast": [
      {
        "firstName": "Chandler"
      },
      {
        "firstName": "Monica"
      },
      {
        "firstName": "Joey"
      },
      {
        "firstName": "Ross"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Yeaaaah ! Now you can add all the others !

Conclusion

I just started learning GraphQL so i probably made some mistakes, i am still figuring out how to make everything work but i wanted to share this first milestone with you !

If you have some tips or resources to help me keep digging the subject, drop them on the comments !

The full code is here on GIthub : Code

Discussion (0)

pic
Editor guide