DEV Community

Cover image for A Simple Crud App With Prisma, Express, and PostgreSQL
FredAbod
FredAbod

Posted on

A Simple Crud App With Prisma, Express, and PostgreSQL

Building a Simple Blog App with Express, Prisma, and PostgreSQL

In this tutorial, I will take you step by step to building a simple(CRUD) blog application. The app will support creating, retrieving, updating, and deleting blog posts.

Prerequisites

Make sure you have Node.js and npm installed on your machine, and you have PostgreSQL set up with a database.

I hope you know how to setup a Postgres databaseπŸ˜‰πŸ˜‰πŸ˜‰. If you don't You have to😎,

Let's Dive Right in

Diving

Step 1: Project Setup

Create a new directory for your project and initialize it with npm:

mkdir prisma-express-blog-app
cd prisma-express-blog-app
npm init -y
Enter fullscreen mode Exit fullscreen mode

Step 2: We'll Install Our Project Dependencies

npm install express @prisma/client dotenv
Enter fullscreen mode Exit fullscreen mode

Step 3: We'll Set Up Prisma

npx prisma init
Enter fullscreen mode Exit fullscreen mode

This would install the necessary files and folders for prisma

Step 4: We'll configure our prisma schema to look like this

// prisma/schema.prisma

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

// Post model represents individual blog posts
model Post {
  id        Int       @id @default(autoincrement())
  title     String
  content   String
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
}
Enter fullscreen mode Exit fullscreen mode

Step 5: We'll Configure our .env file to contain our postgres database URL. Mine looks like this

DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
Enter fullscreen mode Exit fullscreen mode

I'll edit that and add my postgresDb URL

DATABASE_URL="postgresql://postgres:qwer@localhost:5432/mydb?schema=public"
Enter fullscreen mode Exit fullscreen mode

You'll change your password and database name

Step 6: We'll Create A Database Migration

npx prisma migrate dev
Enter fullscreen mode Exit fullscreen mode

This would create a migration for you and add the folder, when you open the folder you see your migration.sql file which looks exactly like your schema

-- CreateTable
CREATE TABLE "Post" (
    "id" SERIAL NOT NULL,
    "title" TEXT NOT NULL,
    "content" TEXT NOT NULL,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

    CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
);
Enter fullscreen mode Exit fullscreen mode

Step 7: Now we'll create our main entry file and call it app.js.

We'll initialize express, dotenv our middleware and also listen to our port

const express = require("express");
require("dotenv").config();

const app = express();
app.use(express.json());
const port = process.env.PORT || 3000;

app.get("/", (req, res) => {
res.send("Welcome Tou Prisma, Express And PSQL Tutorial");
});

app.listen(port, () => {
console.log(Server listening on ${port});
});

## Step 8: Now lets import prismaClient and configure it, add this lines of code to your `app.js` file
```javascript
const { PrismaClient } = require('@prisma/client')
const prisma = new PrismaClient();
Enter fullscreen mode Exit fullscreen mode

Step 9: Now we add our first route, which would be to add a blog

This route would look like this:

app.post("/post", async (req, res) => {
  try {
    const { title, content } = req.body;
    if (!title || !content) {
      return res
        .status(400)
        .json({ message: "Please input Title Anc Content" });
    }
const blog = await prisma.post.create({
  data: { title, content },
});

return res
  .status(201)
  .json({ message: "Blog created successfully", data: blog });
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
return res.status(500).json({ message: "Error creating blog" });
}
});

After adding this to your `app.js` file we should test that route before moving on, my route looks like this `http://localhost:4500/post` 
> I got my response after testing

![Create Post](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vju5s5b93fi961a5ypzb.png)
> Add as much Blogs as Possible

## Step 10: Stretch Your Fingers 😁😁

![Stretch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ftkqox4dpbtnaihd0o4g.gif)

## Step 11: Now we'll add a Route to get all Blogs and tell us the number of blogs available
```javascript
app.get("/posts", async (req, res) => {
  try {
    const blogs = await prisma.post.findMany();
    return res.status(201).json({ data: blogs.length, blogs });
  } catch (error) {
    return res.status(500).json({ message: "Error fetching blogs" });
  }
});
Enter fullscreen mode Exit fullscreen mode

after testing:

Get All

Step 12: We'll add a route to get a single blog by title

app.get("/get", async (req, res) => {
    const { title } = req.query;
    try {
      const blog = await prisma.post.findFirst({
        where: { title }
      });
      if (blog) {
        return res.status(200).json(blog);
      } else {
        return res.status(404).json({ message: "Blog not found" });
      }
    } catch (error) {
      console.log(error);
      return res.status(500).json({ message: "Error fetching blog" });
    }
  });
Enter fullscreen mode Exit fullscreen mode

Step 13: I'll add some more routes, you can add and test for yourself

Now I finally have this:

const express = require("express");
const { PrismaClient } = require("@prisma/client");
require("dotenv").config();

const prisma = new PrismaClient();

const app = express();
app.use(express.json());
const port = process.env.PORT || 3000;

app.get("/", (req, res) => {
res.send("Welcome to Prisma, Express, and PSQL Tutorial");
});

// Create a blog
app.post("/post", async (req, res) => {
try {
const { title, content } = req.body;
if (!title || !content) {
return res
.status(400)
.json({ message: "Please input Title and Content" });
}

const blog = await prisma.post.create({
  data: { title, content },
});

return res
  .status(201)
  .json({ message: "Blog created successfully", data: blog });
Enter fullscreen mode Exit fullscreen mode

} catch (error) {
return res.status(500).json({ message: "Error creating blog" });
}
});

// Get all blogs
app.get("/posts", async (req, res) => {
try {
const blogs = await prisma.post.findMany();
return res.status(201).json({ data: blogs.length, blogs });
} catch (error) {
return res.status(500).json({ message: "Error fetching blogs" });
}
});

// Get a single blog by title
app.get("/get", async (req, res) => {
const { title } = req.query;
try {
const blog = await prisma.post.findFirst({
where: { title }
});
if (blog) {
return res.status(200).json(blog);
} else {
return res.status(404).json({ message: "Blog not found" });
}
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Error fetching blog" });
}
});

// Update a blog by id
app.put("/post/:id", async (req, res) => {
const { id } = req.params;
const { title, content } = req.body;
try {
const updatedBlog = await prisma.post.update({
where: { id: parseInt(id) },
data: { title, content },
});
return res.json({
message: "Blog updated successfully",
data: updatedBlog,
});
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Error updating blog" });
}
});

// Delete a blog by id
app.delete("/post/:id", async (req, res) => {
const { id } = req.params;
try {
await prisma.post.delete({
where: { id: parseInt(id) },
});
return res.json({ message: "Blog deleted successfully" });
} catch (error) {
return res.status(500).json({ message: "Error deleting blog" });
}
});

app.listen(port, () => {
console.log(Server listening on ${port});
});

> And that is a comprehensive CRUD app using Prisma, PSQL, and express
[Link to Github Repo Containing The Code](https://github.com/FredAbod/Prisma-Tutorial)
## Thank you for taking the time to read πŸ₯°πŸ₯°, I hope this was helpful, Don't Forget to drop a like and followπŸ˜‹πŸ˜‹. See You on the Next OneπŸ€—

![Bow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2go8l3113h2kw6enp2d5.gif)
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
lachiamine profile image
Lachi Amine (0xapma)

good job just easy way to read