Utilizando o Prisma com TypeScript e SQLite: Um Guia Prático
Tags: prisma, typescript, node, sql
Published: 2024-02-14 13:43:00

## Introdução ao Prisma

Prisma é um ORM (Object-Relational Mapping) moderno para Node.js e TypeScript. Ele facilita o trabalho com bancos de dados através de uma API intuitiva e fornece recursos como migrações de banco de dados, consultas fortemente tipadas e um modelo de dados declarativo.

## Benefícios do Prisma

- **Produtividade**: Interface de consulta de alto nível.
- **Tipagem Forte**: Integração perfeita com TypeScript.
- **Migrações Automáticas**: Gerenciamento de esquemas de banco de dados.

## Escolha do SQLite

O SQLite é escolhido para este guia devido à sua simplicidade, já que não requer uma instância de banco de dados separada e funciona com um arquivo local. No entanto, o Prisma suporta vários outros bancos de dados, como PostgreSQL, MySQL e SQL Server.

## Configurando o Ambiente

1. **Crie um Projeto Node.js**:
   - `npm init -y`

2. **Instale o Prisma**:
   - `npm install @prisma/client`
   - `npm install --save-dev prisma`

3. **Inicialize o Prisma**:
   - `npx prisma init`
   - Isso cria um novo diretório `prisma` com um arquivo de esquema `schema.prisma`.

4. **Configure o SQLite**:
   - No arquivo `schema.prisma`, configure o provider para `sqlite` e defina o caminho do banco de dados.

   ```prisma
   datasource db {
     provider = "sqlite"
     url      = "file:./dev.db"
   }
   ```

## Criando Modelos e Migrações

### 1. **Defina Modelos no Esquema**:
   - Por exemplo, um modelo `User`:

   ```prisma
model Post {
  id      Int    @id @default(autoincrement())
  title   String
  content String
  User    User?  @relation(fields: [userId], references: [id])
  userId  Int?
}

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

Os modelos `Post` e `User` definidos em Prisma representam tabelas em um banco de dados com relações entre si. Aqui está uma explicação detalhada:

**Modelo `Post`**:
   - **id**: Uma chave primária autoincrementada que identifica cada post de forma única.
   - **title**: Campo de string para o título do post.
   - **content**: Campo de string para o conteúdo do post.
   - **User**: Define uma relação opcional com o modelo `User`. O `?` indica que um post pode ou não ter um usuário associado.
   - **userId**: Uma chave estrangeira opcional que faz referência à chave primária `id` do modelo `User`.

**Modelo `User`**:
   - **id**: Uma chave primária autoincrementada que identifica cada usuário de forma única.
   - **name**: Campo de string para o nome do usuário.
   - **email**: Campo de string para o email do usuário, marcado como único com `@unique`.
   - **posts**: Um array de posts associados a este usuário, representando uma relação Um-para-Muitos.

Em resumo, esses modelos definem a estrutura e as relações entre usuários e posts no banco de dados, onde um usuário pode ter vários posts, mas um post é opcionalmente associado a um único usuário.

### 2. **Execute Migrações e Generate de types**:
   - `npx prisma migrate dev --name init`
   - Isso cria tabelas no SQLite conforme os modelos.
   - `npx prisma generate`

O comando generate do Prisma é usado para gerar o cliente Prisma em seu projeto. Quando você executa npx prisma generate, ele lê o modelo de dados definido no seu arquivo schema.prisma e gera automaticamente um cliente Prisma que pode ser usado em seu aplicativo para acessar seu banco de dados de maneira programática.

Esse processo inclui a criação de métodos e classes com base nos modelos definidos, permitindo realizar operações de banco de dados (como consultas, inserções, atualizações e exclusões) de forma eficiente e segura em relação ao tipo, aproveitando a tipagem forte do TypeScript (se estiver usando TypeScript).

Por exemplo, se você tiver um modelo `User` no seu arquivo `schema.prisma`, após executar `npx prisma generate`, você pode fazer o seguinte em seu código TypeScript:

```typescript
import { User } from '@prisma/client';

const getUser = async (userId: number): Promise<User | null> => {
    const user = await prisma.user.findUnique({
        where: { id: userId },
    });
    return user;
};
```

Neste exemplo, o tipo `User` é importado do cliente Prisma gerado e usado para definir o tipo de retorno da função `getUser`. Isso garante que o objeto retornado por `getUser` esteja em conformidade com a estrutura do modelo `User` definido em seu esquema Prisma, aproveitando a tipagem forte do TypeScript para maior segurança e previsibilidade do código.


## CRUD Básico com Prisma

### Criar Dados

```typescript
const prisma = new PrismaClient();

async function createUser() {
  const user = await prisma.user.create({
    data: {
      name: 'Alice',
      email: 'alice@example.com',
    },
  });
  console.log(user);

  return user
}
```

### Ler Dados

```typescript
async function getUsers() {
  const users = await prisma.user.findMany();
  console.log(users);
  return users
}
```

### Atualizar Dados

```typescript
async function updateUser(userId: number) {
  const user = await prisma.user.update({
    where: { id: userId },
    data: { name: 'Alice Smith' },
  });
  return user
}
```

### Deletar Dados

```typescript
async function deleteUser(userId: number) {
  const user = await prisma.user.delete({
    where: { id: userId },
  });
  console.log(user);
}
```

## Consultas Aninhadas

Para realizar uma consulta aninhada com Prisma, trazendo todos os posts relacionados a um usuário específico, você pode usar o seguinte código TypeScript:

```typescript
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function getUserWithPosts(userId: number) {
    const userWithPosts = await prisma.user.findUnique({
        where: { id: userId },
        include: { posts: true },
    });

    console.log(userWithPosts);
    return userWithPosts;
}
```

Neste exemplo, a função `getUserWithPosts` busca um usuário específico pelo `id` e inclui todos os seus posts relacionados. O método `findUnique` é usado para buscar um único registro, e a opção `include` com `{ posts: true }` indica que queremos incluir os posts relacionados ao usuário no resultado da consulta.

## Conclusão

O Prisma oferece uma maneira poderosa e eficiente de interagir com bancos de dados em aplicações Node.js/TypeScript. Com sua abordagem de tipo seguro e migrações automáticas, o Prisma simplifica o gerenciamento de dados, tornando o desenvolvimento mais produtivo e menos propenso a erros.