Neste artigo, abordamos como utilizar o estilo RPC com ZenStack, Fastify e Prisma para expor e consumir endpoints RESTful baseados em operações como findMany, findUnique, create, update, delete e outros. O objetivo é criar uma API robusta, escalável, segura e que siga os padrões modernos de desenvolvimento full-stack com validação, ACL e serialização avançada.
1. Entendendo o estilo RPC com ZenStack
RPC (Remote Procedure Call) no ZenStack transforma automaticamente as operações do Prisma em rotas HTTP públicas, expostas no formato /api/model/Model/operation. Cada método como findMany, create, update, entre outros, pode ser acessado diretamente via requisições HTTP padrão, permitindo acesso completo ao CRUD com filtros, ordenações, paginação e controle de acesso baseado em ACL (Access Control List).
2. Estrutura das rotas RPC
| Operação | Método HTTP | Rota | Parâmetros |
|---|---|---|---|
| findMany | GET | /api/model/modelName/findMany | Query q com filtros |
| findUnique | GET | /api/model/modelName/findUnique | Query q com chave única |
| findFirst | GET | /api/model/modelName/findFirst | Query q com condições |
| count | GET | /api/model/modelName/count | Query q com filtros |
| aggregate | GET | /api/model/modelName/aggregate | Query q com aggregações |
| groupBy | GET | /api/model/modelName/groupBy | Query q com colunas e filtros |
| create | POST | /api/model/modelName/create | Body com objeto data |
| update | PATCH | /api/model/modelName/update | Body com where e data |
| delete | DELETE | /api/model/modelName/delete | Body com filtro where |
| upsert | POST | /api/model/modelName/upsert | Body com where, update, create |
| deleteMany | DELETE | /api/model/modelName/deleteMany | Body com where |
| updateMany | PATCH | /api/model/modelName/updateMany | Body com where e data |
Esses endpoints seguem a estrutura de resposta { data: resultado } e são gerados automaticamente quando o plugin ZenStackFastifyPlugin está registrado com Fastify.
3. Exemplos práticos de uso
Busca com filtros usando where
GET /api/model/post/findMany?q={"where":{"published":true,"authorId":"abc"}}
Retorna todos os posts publicados de um autor específico. Também é possível incluir relações usando include.
GET /api/model/post/findMany?q={"include":{"author":true}}
Buscar um único registro com findUnique
GET /api/model/post/findUnique?q={"where":{"id":"postId"}}
Ou com findFirst para buscar o primeiro resultado que satisfaz uma condição parcial:
GET /api/model/post/findFirst?q={"where":{"title":{"contains":"ZenStack"}}}
Criar novo registro com create
POST /api/model/post/create
Content-Type: application/json
{
"data": {
"title": "Novo post",
"content": "Conteúdo original",
"author": { "connect": { "id": "abc" } }
}
}
Atualizar registros com update
PATCH /api/model/post/update
Content-Type: application/json
{
"where": { "id": "postId" },
"data": { "title": "Título atualizado" }
}
Ambos os campos where e data são obrigatórios para updates com segurança e precisão.
Upsert: create ou update automático
POST /api/model/post/upsert
Content-Type: application/json
{
"where": { "id": "postId" },
"update": { "title": "Atualizado" },
"create": {
"title": "Post alternativo",
"author": { "connect": { "id": "abc" } }
}
}
Ideal para casos em que não se sabe se o recurso já existe.
Excluir registros com delete
DELETE /api/model/post/delete
Content-Type: application/json
{ "where": { "id": "postId" } }
Para deletar múltiplos registros, utilize deleteMany.
4. Filtros avançados
ZenStack permite utilizar filtros Prisma como AND, OR, startsWith, contains, in, entre outros.
GET /api/model/user/findMany?q={"where":{"OR":[{"email":{"contains":"@gmail.com"}},{"name":{"startsWith":"A"}}]}}
Também é possível usar select, orderBy, cursor, take e skip para paginação e refinamento.
5. Serialização automática com SuperJSON
ZenStack utiliza SuperJSON para serializar tipos não triviais como DateTime, BigInt, Decimal e Bytes. As queries GET passam os filtros no parâmetro q como string JSON codificada. Já nos métodos POST/PATCH os dados são enviados no body, como em qualquer API REST tradicional. Se estiver usando front-end com React Query e hooks gerados, isso é tratado automaticamente.
6. Tratamento de respostas e erros
ZenStack padroniza respostas para facilitar debugging e integração com front-end.
Códigos de sucesso:
- 200 para operações comuns
- 201 para
createecreateMany
Códigos de erro:
- 403: acesso negado pelas políticas de segurança
- 422: falha de validação de schema
- 400: erro no corpo da requisição
- 500: erro interno no servidor
Formato de erro:
{
"prisma": true,
"rejectedByPolicy": true,
"code": "P2002",
"message": "Erro de unicidade",
"reason": "email já existe"
}
7. Testes com curl
curl "http://localhost:3000/api/model/post/findMany?q=$(jq -c '{"where":{"published":true}}')"
curl -X POST http://localhost:3000/api/model/post/create \
-H "Content-Type: application/json" \
-d '{"data":{"title":"Exemplo RPC","author":{"connect":{"id":"abc"}}}}'
Conclusão
O estilo RPC do ZenStack com Prisma oferece uma API altamente automatizada, segura e escalável, ideal para aplicações full-stack modernas. Com suporte embutido para validação de dados, controle de acesso, serialização avançada e integração com ferramentas de front-end, ele elimina grande parte da complexidade do backend tradicional. Entender e dominar os comandos where, find, create, update e delete é essencial para extrair o máximo dessa abordagem declarativa e poderosa.