Skip to content

Prisma ORM + Express + Typescript (API REST)

En esta guía práctica aprenderemos a trabajar con Prisma ORM en un proyecto de Node.js con Express y TypeScript. Construiremos una API REST que nos permitirá interactuar con una base de datos SQLite utilizando Prisma como ORM. A lo largo de la guía, veremos cómo configurar Prisma en nuestro proyecto, definir los modelos de la base de datos, crear migraciones, y realizar consultas a la base de datos utilizando Prisma y Express.

Tutorial en video 👇👇👇

¿Qué es Prisma?

Prisma es una herramienta de código abierto que nos permite interactuar con nuestra base de datos de una forma más sencilla y segura. Con Prisma, podemos escribir consultas en TypeScript y obtener un autocompletado de las tablas y campos de nuestra base de datos. Además, Prisma nos facilita la creación de migraciones y nos permite definir las relaciones entre las tablas de una forma sencilla y segura.

Recursos

Extensiones VSCode (opcional):

  1. Material Icon Theme Personaliza los íconos de tus archivos y carpetas con este tema de íconos visualmente atractivo. Ideal para mejorar la navegación y organización de proyectos.
  2. Moonlight Un tema oscuro inspirado en colores suaves y relajantes, perfecto para sesiones de programación prolongadas.
  3. Pretty TypeScript Errors Transforma los errores de TypeScript en mensajes más claros y fáciles de entender, optimizando el proceso de depuración.
  4. Prisma Soporte oficial para trabajar con Prisma, un ORM que facilita la manipulación de bases de datos en proyectos TypeScript y JavaScript.
  5. SQLite Viewer Una herramienta para explorar bases de datos SQLite directamente desde Visual Studio Code, con una interfaz fácil de usar.
  6. Thunder Client Una alternativa ligera y rápida a Postman, diseñada para realizar pruebas de API directamente en el editor.

Instalación

sh
npm init -y
npm i -D typescript tsx @types/node

tsconfig.json

sh
npx tsc --init

Prisma

sh
npm i -D prisma

Configurar Prisma ORM con SQLite

sh
npx prisma init --datasource-provider sqlite

Los modelos en el esquema Prisma tienen dos propósitos principales:

  • Definir la estructura de la base de datos
  • Definir las relaciones entre las tablas

prisma/schema.prisma

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

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

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  posts Post[]
}

model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String?
  published Boolean @default(false)
  author    User    @relation(fields: [authorId], references: [id])
  authorId  Int
}

Migraciones

sh
npx prisma migrate dev --name init

Este comando hizo tres cosas:

  1. Se creó un nuevo archivo de migración SQL para esta migración en el prisma/migrationsdirectorio.
  2. Ejecutó el archivo de migración SQL contra la base de datos.
  3. Se ejecutó prisma generatebajo el capó (que instaló el @prisma/clientpaquete y generó una API de cliente Prisma personalizada en función de sus modelos).

Express y Prisma

package.json

json
{
  "name": "01-prisma",
  "version": "1.0.0",
  "scripts": {
    "dev": "tsx --watch src/server.ts"
  },
  "devDependencies": {
    "@types/express": "^5.0.0",
    "@types/node": "^22.10.2",
    "prisma": "^6.0.1",
    "tsx": "^4.19.2",
    "typescript": "^5.7.2"
  },
  "dependencies": {
    "@prisma/client": "^6.0.1",
    "express": "^4.21.2"
  }
}
sh
npm i express

src/config/prisma.ts

ts
import { PrismaClient } from "@prisma/client";

export const prisma = new PrismaClient();

src/server.ts

ts
import express from "express";

import postRouter from "./routes/post.route";
import userRouter from "./routes/user.route";

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

app.use(express.json());

app.use("/api/v1/users", userRouter);
app.use("/api/v1/posts", postRouter);

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

src/routes/user.route.ts

ts
import { Router } from "express";

import { prisma } from "../config/prisma";

const userRouter = Router();

// /api/v1/users

userRouter.get("/", async (req, res) => {
  try {
    const users = await prisma.user.findMany();
    res.json({ users });
  } catch (error) {
    console.log(error);
    res.status(500).json({ message: "Internal server error" });
  }
});

userRouter.post("/", async (req, res) => {
  try {
    const { name, email } = req.body;
    const user = await prisma.user.create({
      data: {
        name,
        email,
      },
    });
    res.json({ user });
  } catch (error) {
    console.log(error);
    res.status(500).json({ message: "Internal server error" });
  }
});

export default userRouter;
ts
import { Router } from "express";

import { prisma } from "../config/prisma";

const postRouter = Router();

// /api/v1/posts

postRouter.get("/", async (req, res) => {
  try {
    const posts = await prisma.post.findMany();
    res.json({ posts });
  } catch (error) {
    console.log(error);
    res.status(500).json({ message: "Internal server error" });
  }
});

postRouter.post("/", async (req, res) => {
  try {
    const { title, content, authorEmail } = req.body;
    const post = await prisma.post.create({
      data: {
        title,
        content,
        author: {
          connect: { email: authorEmail },
        },
      },
    });
    res.json({ post });
  } catch (error) {
    console.log(error);
    res.status(500).json({ message: "Internal server error" });
  }
});

export default postRouter;

Conclusiones

Prisma es una herramienta muy útil para trabajar con bases de datos en proyectos de Node.js. Nos permite escribir consultas en TypeScript y nos ofrece un autocompletado de las tablas y campos de nuestra base de datos. Además, Prisma nos facilita la creación de migraciones y nos permite definir las relaciones entre las tablas de una forma sencilla y segura. Sin duda, Prisma es una excelente opción para trabajar con bases de datos en proyectos de Node.js.