Prisma tal y como lo describen en su sitio web es un ORM de próxima generación para Node.js y TypeScript. Prisma ayuda a desarrollar aplicaciones más rápido y con menos errores con un ORM libre para PostgreSQL, MySQL y SQLite.
Por si os interesa os dejo info de NX y el concepto de monorepos, y un vídeo donde Beeman explica un poco más acerca del stack que usa con Angular, Nest.js, GraphQL, Apollo y Prisma en el mismo monorepo. Y aquí otro tutorial de Prisma.
Primeros pasos
Primero necesitamos el CLI de prisma, yo utilizo yarn pero sientete libre de utilizar npm si lo deseas
yarn add @prisma/cli -D
Después tenemos que inicializar prisma
npx prisma init
Esto va a crear una carpeta en nuestro proyecto con el archivo schema.prisma
Al abrirlo verás esto
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
Añadimos nuestros modelos en el mismo archivo schema.prisma
model User {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
email String @unique
password String
posts Post[]
}
model Post {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
text String
authorId String
author User @relation(fields: [authorId], references: [id])
}
Para poder probar prisma en local vamos a lanzar una instancia de postgres con un archivo docker-compose.yml
version: '3'
services:
postgres:
image: postgres
ports:
- 5432:5432
environment:
POSTGRES_DB: prisma
POSTGRES_USER: prisma
POSTGRES_PASSWORD: prisma
volumes:
- ./tmp/postgres:/var/lib/postgresql/data
Y arrancamos la base de datos en la terminal con el comando
docker-compose up
Es así de simple, visita la documentación de docker si no lo tienes instalado.
Ahora necesitamos cambiar la configuración de conexión con la base de datos en el archivo .env
DATABASE_URL="postgresql://prisma:prisma@localhost:5432/prisma?schema=public"
Hacemos la migración con prisma para crear los modelos en la base de datos.
npx prisma migrate dev --preview-feature
Esto creará un directorio de migraciones dentro de la carpeta prisma. Una vez que tenemos la migración vamos a generar el client de prisma que nos permitirá hacer las querys en la base de datos.
npx prisma generate
Opcional * Si quieres puedes añadir un script en package.json para migrar y generar el cliente cuando haces cambios
"prisma:up": "npx prisma migrate dev --preview-feature && npx prisma generate"
Ahora ya podemos usar el client de prisma
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
Si estás usando NX creamos una librería para gestionar prisma
nx g @nrwl/nest:lib data
Vamos a generar un servicio para realizar las querys al lado de data.module.ts y no olvides añadirlo en la lista de providers.
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class DataService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
constructor() {
super();
}
async onModuleInit() {
await this.$connect();
}
async onModuleDestroy() {
await this.$disconnect();
}
async createUser({ email, password }: { email: string; password: string }) {
const user = await this.user.create({ data: { email, password } });
console.log(user);
}
}
Ahora solo tenemos que importar el DataService en cualquier servicio para empezar a usar las querys de prisma. Aquí os dejo un ejemplo de un CRUD típico.
import { Injectable, NotFoundException } from '@nestjs/common';
import { CreateCategoryInput } from './dto/create.category.input';
import { CreatePostInput } from './dto/create.post.input';
import { UpdateCategoryInput } from './dto/update.category.input';
import { UpdatePostInput } from './dto/update.post.input';
import { Category } from './models/category';
import { Post } from './models/Post';
import { DataService } from '@fubu/data';
@Injectable()
export class CategoryService {
constructor(private readonly data: DataService) {}
public async categories(): Promise<Category[]> {
return await this.data.category.findMany({ include: { posts: true } });
}
public async category(id: string): Promise<Category> {
const found = await this.data.category.findUnique({ where: { id } });
if (!found) throw new NotFoundException();
return found;
}
public async createCategory(input: CreateCategoryInput): Promise<Category> {
return await this.data.category.create({ data: { ...input } });
}
public async updateCategory(id: string, input: UpdateCategoryInput): Promise<Category> {
const category = await this.category(id);
return await this.data.category.update({ where: { id: category.id }, data: { ...input } });
}
public async deleteCategory(id: string): Promise<Category> {
const category = await this.category(id);
return await this.data.category.delete({ where: { id: category.id } });
}
public async post(id: string): Promise<Post> {
const found = await this.data.post.findUnique({ where: { id } });
if (!found) throw new NotFoundException();
return found;
}
public async createPost(categoryId: string, input: CreatePostInput): Promise<Post> {
const category = await this.category(categoryId);
return await this.data.post.create({
data: {
Category: { connect: { id: category.id } },
...input,
},
});
}
public async updatePost(id: string, input: UpdatePostInput): Promise<Post> {
const post = await this.post(id);
return this.data.post.update({ where: { id: post.id }, data: { ...input } });
}
public async deletePost(id: string): Promise<Post> {
const post = await this.post(id);
return this.data.post.delete({ where: { id: post.id } });
}
}
Gracias por leer el post espero que haya sido de ayuda, cualquier duda por favor comentad!! 👇👇👇