Pular para o conteúdo principal

Desenvolvimento com Prisma ORM no Cursor: Um Guia Completo

Prisma development in Cursor

Prisma é um ORM TypeScript de nova geração que fornece um cliente de banco de dados type-safe, migrações de schema declarativas e um navegador visual de banco de dados chamado Prisma Studio. Prisma elimina código boilerplate de acesso ao banco de dados e captura erros de consulta em tempo de compilação. O Cursor, com seu assistente de IA integrado e base compatível com VS Code, é um excelente editor para desenvolvimento Prisma -- ele fornece IntelliSense para a linguagem de schema do Prisma, auto-completa consultas do Prisma Client e pode gerar schemas completos a partir de descrições em linguagem natural.

Este guia aborda o fluxo de trabalho completo de desenvolvimento com Prisma no Cursor: instalação e configuração, design de schema, migrações, consultas do Prisma Client, relacionamentos, Prisma Studio e geração de schema com IA.

Instalando e Configurando Prisma no Cursor​

Pré-requisitos​

Prisma funciona com Node.js 18+ e suporta PostgreSQL, MySQL, SQLite, MongoDB e SQL Server. Verifique sua versão do Node.js:

node --version
dica

O terminal integrado do Cursor (Ctrl+`) permanece sincronizado com o painel do Explorer. Você pode executar comandos do Prisma CLI e ver imediatamente os arquivos gerados aparecerem na árvore de arquivos.

Instalando a Extensão Prisma​

O Cursor herda a compatibilidade de extensões do VS Code. Instale a extensão oficial Prisma a partir da view de Extensões (Ctrl+Shift+X):

  1. Pesquise por "Prisma".
  2. Instale a extensão publicada pela Prisma.
  3. Recarregue o Cursor se solicitado.

A extensão fornece:

  • Realce de sintaxe para arquivos de schema .prisma.
  • Formatação automática ao salvar.
  • IntelliSense para campos de modelo, atributos e relacionamentos.
  • Validação inline para erros de schema.
  • Ações de código para correções rápidas.
aviso

Se a extensão Prisma não estiver instalada, o Cursor tratará arquivos .prisma como texto puro. Você perderá realce de sintaxe, autocomplete e detecção de erros. Sempre instale a extensão oficial antes de editar arquivos de schema.

Inicializando Prisma em um Projeto​

Instale o Prisma CLI e inicialize uma nova configuração Prisma:

npm install prisma --save-dev
npm install @prisma/client

npx prisma init

Isso cria:

  • prisma/schema.prisma -- o arquivo de schema principal.
  • .env -- arquivo de ambiente com um placeholder DATABASE_URL.

Defina sua string de conexão com o banco de dados em .env:

# .env
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"
dica

Peça ao Cursor: "Configure Prisma com PostgreSQL no meu projeto. Crie o arquivo de schema com um modelo User e configure a conexão com o banco de dados." O Cursor executará os comandos init, gerará o schema e configurará o arquivo .env.

Design de Schema​

O schema do Prisma é a fonte única de verdade para sua estrutura de banco de dados. Ele define modelos, relacionamentos, enums e configuração de datasource.

Entendendo o Arquivo de Schema​

// prisma/schema.prisma

// Generator: diz ao Prisma como gerar o cliente
generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch", "postgresqlExtensions"]
}

// Datasource: conexão com o banco de dados
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
extensions = [pgcrypto, postgis]
}

// Model: mapeia para uma tabela do banco de dados
model User {
id String @id @default(uuid())
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

model Post {
id String @id @default(uuid())
title String
content String?
published Boolean @default(false)
viewCount Int @default(0)
author User @relation(fields: [authorId], references: [id])
authorId String
categories Category[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@index([authorId])
@@index([published])
}

model Category {
id String @id @default(uuid())
name String @unique
posts Post[]
}

model Profile {
id String @id @default(uuid())
bio String?
user User @relation(fields: [userId], references: [id])
userId String @unique
}

enum Role {
USER
ADMIN
EDITOR
}

Atributos de Campo Comuns​

AtributoDescrição
@idMarca um campo como chave primária
@default(uuid())Gera automaticamente um UUID ao inserir
@default(autoincrement())Inteiro auto-incrementável (MySQL/PostgreSQL)
@uniqueImpõe unicidade no campo
@updatedAtAtualiza automaticamente o timestamp ao atualizar registro
@relationDefine um relacionamento entre modelos
@mapMapeia um campo para uma coluna com nome diferente
@@indexCria um índice de banco de dados no(s) campo(s)
@@uniqueRestrição única composta
@@mapMapeia um modelo para uma tabela com nome diferente
dica

Peça ao Cursor: "Gere um schema Prisma para uma plataforma de e-commerce com modelos User, Product, Order, OrderItem e Category. Inclua relacionamentos apropriados, índices e enums para status de pedido e disponibilidade de produto." O Cursor produzirá um schema completo e validado com sintaxe de relacionamento correta.

Relacionamentos​

Prisma suporta relacionamentos um-para-um, um-para-muitos e muitos-para-muitos.

Relacionamento Um-para-Um:

model User {
id String @id @default(uuid())
profile Profile?
}

model Profile {
id String @id @default(uuid())
user User @relation(fields: [userId], references: [id])
userId String @unique
}

Relacionamento Um-para-Muitos:

model User {
id String @id @default(uuid())
posts Post[]
}

model Post {
id String @id @default(uuid())
author User @relation(fields: [authorId], references: [id])
authorId String
}

Relacionamento Muitos-para-Muitos (implícito):

model Post {
id String @id @default(uuid())
categories Category[]
}

model Category {
id String @id @default(uuid())
posts Post[]
}

Relacionamento Muitos-para-Muitos (explícito, com campos extras na tabela de junção):

model Post {
id String @id @default(uuid())
tags PostTag[]
}

model Tag {
id String @id @default(uuid())
posts PostTag[]
}

model PostTag {
post Post @relation(fields: [postId], references: [id])
postId String
tag Tag @relation(fields: [tagId], references: [id])
tagId String
assignedAt DateTime @default(now())

@@id([postId, tagId])
}
aviso

Ao usar relacionamentos muitos-para-muitos implícitos, o Prisma gera automaticamente uma tabela de junção oculta. Você não pode adicionar campos extras (como assignedAt ou createdBy) a esta tabela oculta. Se você precisa de metadados no relacionamento, use uma tabela de junção explícita como mostrado acima.

Migrações​

Prisma Migrate cria e aplica mudanças de schema de banco de dados de forma versionada e reversível.

Criando Sua Primeira Migração​

Após definir seu schema, crie a migração inicial:

npx prisma migrate dev --name init

Este comando:

  1. Gera um arquivo de migração SQL em prisma/migrations/.
  2. Aplica a migração ao seu banco de dados.
  3. Regenera o Prisma Client.
dica

Use nomes de migração descritivos: npx prisma migrate dev --name add_order_status_enum. Esses nomes aparecem no histórico de migrações e ajudam a rastrear a evolução do schema.

Modificando o Schema​

Quando você muda o schema, cria uma nova migração:

# Após editar schema.prisma
npx prisma migrate dev --name add_post_view_count

Prisma detecta a diferença entre seu schema e o banco de dados, gera uma migração e a aplica.

Workflow de Migração para Produção​

Para bancos de dados de produção, use prisma migrate deploy que aplica migrações pendentes sem redefinir dados:

# Aplicar migrações em produção
npx prisma migrate deploy
aviso

Nunca execute prisma migrate dev contra um banco de dados de produção. O comando dev pode redefinir o banco de dados se detectar desvio de schema. Sempre use migrate deploy em ambientes de produção.

Redefinindo o Banco de Dados​

Durante o desenvolvimento, pode ser necessário redefinir o banco de dados e reaplicar todas as migrações:

npx prisma migrate reset

Isso descarta todos os dados e tabelas, depois reaplica todas as migrações do zero.

Populando o Banco de Dados​

Crie um script de seed para popular seu banco de dados com dados iniciais:

// prisma/seed.ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
// Criar usuários
const alice = await prisma.user.create({
data: {
name: 'Alice Johnson',
role: 'ADMIN',
profile: {
create: {
bio: 'Software engineer and blogger',
},
},
},
});

const bob = await prisma.user.create({
data: {
name: 'Bob Smith',
role: 'USER',
},
});

// Criar posts
const post1 = await prisma.post.create({
data: {
title: 'Getting Started with Prisma',
content: 'Prisma is a type-safe ORM...',
published: true,
author: { connect: { id: alice.id } },
},
});

const post2 = await prisma.post.create({
data: {
title: 'Advanced Prisma Relations',
content: 'Relations in Prisma...',
published: true,
author: { connect: { id: alice.id } },
},
});

console.log('Seed data created successfully');
}

main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});

Configure o comando de seed em package.json:

{
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}

Execute o seed:

npx prisma db seed
dica

Peça ao Cursor: "Crie um script de seed para meu schema Prisma com 5 usuários, 20 posts e 10 categorias. Certifique-se de que alguns posts não estejam publicados e que alguns usuários tenham perfis enquanto outros não." O Cursor gerará um script de seed realista que exercita todos os tipos de relacionamento.

Consultas do Prisma Client​

O Prisma Client é o construtor de consultas type-safe gerado automaticamente que substitui modelos ORM tradicionais e SQL bruto.

Instanciando o Cliente​

Crie uma instância singleton para evitar múltiplas conexões em desenvolvimento:

// lib/prisma.ts
import { PrismaClient } from '@prisma/client';

const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined;
};

export const prisma =
globalForPrisma.prisma ??
new PrismaClient({
log: ['query', 'info', 'warn', 'error'],
});

if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma;
}
aviso

Em desenvolvimento com hot module reloading, criar um novo PrismaClient a cada mudança de arquivo causa esgotamento do pool de conexões. O padrão singleton acima previne isso armazenando a instância em cache no globalThis.

Operações CRUD​

Criar:

// Criar um único registro
const user = await prisma.user.create({
data: {
name: 'Charlie Brown',
profile: {
create: {
bio: 'New user bio',
},
},
},
});

// Criar múltiplos registros
const users = await prisma.user.createMany({
data: [
{ email: '[email protected]', name: 'User One' },
{ email: '[email protected]', name: 'User Two' },
{ email: '[email protected]', name: 'User Three' },
],
});

Ler:

// Encontrar um único registro
const user = await prisma.user.findUnique({
where: { email: '[email protected]' },
include: { profile: true, posts: true },
});

// Encontrar múltiplos registros com filtragem e ordenação
const publishedPosts = await prisma.post.findMany({
where: { published: true },
orderBy: { createdAt: 'desc' },
take: 10,
skip: 0,
include: {
author: {
select: { id: true, name: true, email: true },
},
},
});

// Contar registros
const totalPosts = await prisma.post.count({
where: { published: true },
});

Atualizar:

// Atualizar um único registro
const updatedPost = await prisma.post.update({
where: { id: postId },
data: {
title: 'Updated Title',
viewCount: { increment: 1 },
},
});

// Atualizar múltiplos registros
const result = await prisma.post.updateMany({
where: { published: false, authorId: userId },
data: { published: true },
});

Excluir:

// Excluir um único registro
const deletedUser = await prisma.user.delete({
where: { id: userId },
});

// Excluir múltiplos registros
const result = await prisma.post.deleteMany({
where: { authorId: userId, published: false },
});

Filtragem Avançada​

const posts = await prisma.post.findMany({
where: {
AND: [
{ published: true },
{
OR: [
{ title: { contains: 'prisma', mode: 'insensitive' } },
{ content: { contains: 'orm', mode: 'insensitive' } },
],
},
],
createdAt: {
gte: new Date('2024-01-01'),
lte: new Date('2024-12-31'),
},
author: {
role: { in: ['ADMIN', 'EDITOR'] },
},
},
orderBy: [{ viewCount: 'desc' }, { createdAt: 'desc' }],
});

Transações​

// Transação interativa
const result = await prisma.$transaction(async (tx) => {
const author = await tx.user.create({
data: { email: '[email protected]', name: 'New Author' },
});

const post = await tx.post.create({
data: {
title: 'My First Post',
content: 'Hello world',
authorId: author.id,
},
});

await tx.profile.create({
data: {
bio: 'New author profile',
userId: author.id,
},
});

return { author, post };
});
dica

Peça ao Cursor: "Escreva uma transação Prisma que transfere créditos entre dois usuários. Deduza do remetente, adicione ao destinatário e crie um registro de transferência. Reverta se o remetente tiver saldo insuficiente." O Cursor gerará a transação interativa com tratamento de erros adequado.

Paginação​

// Paginação baseada em offset
const page = 1;
const pageSize = 10;

const [posts, totalCount] = await prisma.$transaction([
prisma.post.findMany({
where: { published: true },
orderBy: { createdAt: 'desc' },
skip: (page - 1) * pageSize,
take: pageSize,
include: { author: true },
}),
prisma.post.count({ where: { published: true } }),
]);

const totalPages = Math.ceil(totalCount / pageSize);

Prisma Studio​

Prisma Studio é um navegador visual de banco de dados que roda no seu navegador. Ele permite visualizar, criar, atualizar e excluir registros sem escrever consultas.

Iniciando o Prisma Studio​

npx prisma studio

Isso abre uma interface no navegador em http://localhost:5555 onde você pode:

  • Navegar por todos os modelos definidos no seu schema.
  • Visualizar registros em uma tabela ordenável e filtrável.
  • Criar novos registros com uma interface de formulário.
  • Editar registros existentes clicando nas células.
  • Excluir registros com um diálogo de confirmação.
  • Filtrar e buscar registros por valores de campo.
dica

Prisma Studio é inestimável para debugging durante o desenvolvimento. Em vez de escrever consultas descartáveis, inicie o Studio, inspecione seus dados e faça edições rápidas. Ele reflete mudanças em tempo real.

aviso

Prisma Studio escreve diretamente no seu banco de dados. Tenha cuidado ao usá-lo contra um banco de dados de produção -- não há desfazer para exclusões ou edições. Sempre faça backup dos seus dados antes de fazer alterações manuais no Studio.

Filtragem no Studio​

Prisma Studio suporta filtragem por:

  • Nome do campo (selecione qualquer coluna).
  • Operador de filtro (igual, diferente, contém, começa com, termina com, etc.).
  • Múltiplos filtros combinados com lógica AND/OR.

Geração de Schema com IA no Cursor​

O assistente de IA do Cursor se destaca em gerar schemas Prisma, consultas e estratégias de migração a partir de descrições em linguagem natural.

Gerando um Schema a partir de uma Descrição​

Abra o Cursor Chat (Ctrl+L) e descreva seu modelo de dados:

Generate a Prisma schema for a project management application with these models:
- User (id, email, name, avatar, role enum: ADMIN/MEMBER/VIEWER)
- Workspace (id, name, slug, ownerId)
- Project (id, name, description, workspaceId, status enum)
- Task (id, title, description, status, priority, assigneeId, projectId, dueDate)
- Comment (id, content, authorId, taskId)
- Label (id, name, color, projectId)
Include all necessary relations, indexes on foreign keys, and timestamps.
Use PostgreSQL with UUID primary keys.

O Cursor gerará um schema completo com todos os modelos, relacionamentos, enums e índices. O schema gerado inclui modelos User, Workspace, Project, Task, Comment e Label com relacionamentos de chave estrangeira adequados, restrições únicas compostas e índices de banco de dados em todas as colunas de chave estrangeira.

dica

Ao pedir ao Cursor para gerar schemas, especifique o provedor de banco de dados (PostgreSQL, MySQL, etc.), o tipo de chave primária (UUID vs. autoincrement) e se você precisa de índices. Isso garante que o schema gerado use recursos específicos do banco de dados corretamente.

Geração de Consultas com IA​

Peça ao Cursor para escrever consultas complexas:

Write a Prisma query to fetch the top 5 most active users in a workspace,
sorted by the number of completed tasks. Include each user's name, email,
avatar, and task count. Only count tasks created in the last 30 days.
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

const topUsers = await prisma.user.findMany({
where: {
assignedTasks: {
some: {
status: 'DONE',
createdAt: { gte: thirtyDaysAgo },
project: { workspaceId },
},
},
},
select: {
id: true,
name: true,
email: true,
avatar: true,
_count: {
select: {
assignedTasks: {
where: {
status: 'DONE',
createdAt: { gte: thirtyDaysAgo },
},
},
},
},
},
orderBy: {
assignedTasks: {
_count: 'desc',
},
},
take: 5,
});
aviso

O _count do Prisma com filtragem aninhada pode gerar consultas SQL caras. Sempre verifique o SQL gerado (ative o log de consultas com new PrismaClient({ log: ['query'] })) e adicione índices de banco de dados apropriados para evitar full table scans.

Conclusão​

Prisma combinado com o Cursor cria uma experiência de desenvolvimento de banco de dados simplificada. O arquivo de schema declarativo serve como fonte única de verdade, as migrações fornecem um caminho seguro para a evolução do schema, o Prisma Client type-safe captura erros de consulta em tempo de compilação e o Prisma Studio oferece uma interface visual para inspeção de dados. O assistente de IA do Cursor acelera cada passo -- desde a geração de schemas completos para modelos de domínio complexos até a escrita de consultas otimizadas com includes aninhados e agregações. Comece instalando a extensão Prisma, defina seus modelos com relacionamentos e índices adequados, use migrate dev durante o desenvolvimento e migrate deploy em produção, e deixe o Cursor gerar o boilerplate repetitivo para que você possa focar na camada de dados da sua aplicação.