Building a simple REST API using Nodejs, Expressjs, Prisma, and SQL - Part 02

Setting up a Express server - CRUD with Prisma

Building a simple REST API using Nodejs, Expressjs, Prisma, and SQL - Part 02

In the previous article, we had our files set up and more importantly, we worked on setting up a database project on PlanetScale. And creating and pushing the schema to our database.

Now we will work on building an express server to work along prisma to interact with the database.

In the index.js file, we will start by importing the packages we had installed. We will be using ES6 modules. So in the package.json, add a variable "type" and set its value to "module".

While we are in the package.json, also install nodemon with the flag --save-dev, to have it installed as dev dependency.

npm install nodemon --save-dev

We will use nodemon to have our server restart when we make changes and save our files. In production we will run the server by calling node index.js. To use nodemon in the package.json file, add a dev script.

scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nodemon index.js",
    "start": "node index.js"
  },

Now to run the server we will use the following command in the terminal

npm run dev

import dotenv from 'dotenv'
import express from 'express'
import { PrismaClient } from '@prisma/client'

Now let's initialize dotenv, prisma, and express.

dotenv.config()

const prisma = new PrismaClient()

const app = express()

const router = express.Router()

app.use(express.json({ limit: '100mmb' }))

app.use('/api/v1', router)

In the app.use() middleware we are initializing express.json to be able to parse the JSON body we will receive in the post requests. Also, we are prefixing the route with /api/v1.

That's with all the initializations, now we will go ahead and write some routes.

We will start by creating routes for doing CRUD operations on the User.

// route to get all the users
router.get('/users', async (req, res) => {
  try {
    const users = await prisma.user.findMany()
    res.status(200).json(users)
  } catch (err) {
    res.status(404).json('Items not found')
  }
})

// route to get a user by id
router.get('/users/:id', async (req, res) => {
  try {
    const { id } = req.params
    const user = await prisma.user.findUnique({
      where: { id }
    })
    res.status(200).json(user)
  } catch (error) {
    res.status(404).json('Item not found')
  }
})

// route to create a new user
router.post('/users', async (req, res) => {
  try {
    console.log(req.body)
    const newUser = await prisma.user.create({ data: req.body })
    res.status(201).json(newUser)
  } catch {
    res.status(400).json('Bad request')
  }
})

// route to update a user by id
router.put('/users/:id', async (req, res) => {
  try {
    console.log(req.params, 'params')
    const { id } = req.params
    const user = await prisma.user.update({
      where: { id },
      data: req.body
    })
    res.status(200).json(user)
  } catch (error) {
    res.status(404).json('Item not found')
  }
})

// route to delete a user based on id
router.delete('/users/:id', async (req, res) => {
  const { id } = req.params
  console.log(id, 'id')
  const user = await prisma.user.delete({
    where: { id }
  })
  res.status(200).json(user)
})

Now that we have the routes set for doing CRUD operations on User, we will proceed by making the server listen on a port of our choice.

In the .env file, I will add another variable called port, and I will pass in my port there.

So now the .env file will look like this

DATABASE_URL=<url-copied-from-planet-scale-db>
PORT=3000

Okay, we have the .env set, now will write the code for the API server to start listening in port 3000.

app.listen(process.env.PORT, () => console.log(`Server running on port ${process.env.PORT}`))

Done. Now restart your server by running the command:

npm run dev

And you now have your server running on port 3000. Now open a rest API client like Postman or Thunder Client. I am using Thunder Client VS Code extension.

Create a request to the URL: localhost:3000/api/v1/users
on clicking send you will receive a Status of 200 OK and an empty array. Because we don't have any data in the database.

So now let's add a new user, change the Method from GET to POST, click on Body, paste in the following JSON, and click send.

{
    "username": "Steve Jobs"
}

Your Thunder Client or REST Client should now look like this

And that's it you created your first user. You can see the ID and createdAt fields added. Now add a few more users. And do the GET request again.

So now we can see both the GET route and POST route working.

Let's try fetching a single user by ID. Copy the ID of one of the users, and paste it into the URL path after putting a slash after users.

http://localhost:3000/api/v1/users/5bfe918e-deb8-4bcd-beca-d178bf6508ce

Now do a GET request, and you will receive data of the individual user.

To update the data, maybe for changing the username from Elon to Elon Musk. Change the Method from GET to PUT. And in the body, JSON - edit the username.

{
    "username": "Elon Musk"
}

Now click that send button, and you will receive the following result.

To delete the user, change the method to DELETE and press Send. You will receive a response of 200 status if the user is deleted. Try getting all the users, and see if the user was successfully deleted or not.

You now have a server API running on port 3000, listening for CRUD operations for the User entity through users resource.

In the terminal, if you type in

npx prisma studio

A database explorer will open where you can view the Users collection which currently has the entries we have added using our Express REST API.