Criar uma API não deveria começar com meia hora de configuração.
Se a ideia é experimentar uma tecnologia, criar um MVP, desenvolver um backend para um frontend ou simplesmente colocar uma ideia no ar, o primeiro objetivo deveria ser chegar rapidamente ao ponto em que podemos escrever código de negócio.
Imagine que você acabou de ter uma ideia para uma API.
Pode ser:
- uma API para um projeto pessoal;
- um backend para React, Vue ou Next.js;
- um microserviço;
- um MVP;
- uma API para estudos;
- um projeto para experimentar uma biblioteca;
- ou simplesmente aquela ideia que você quer tirar do papel.
Porém, o processo muitas vezes acaba sendo, não a complexidade, mas a repetição.
É exatamente aí que entra um gerador bootstrap.
A ideia central
Um bootstrap não precisa resolver todos os problemas de uma aplicação. Ele precisa eliminar o trabalho repetitivo que acontece antes de a aplicação realmente começar.
Bootstraps
Em tecnologia, bootstrap é o processo de iniciar um sistema a partir de uma estrutura mínima que permite sua evolução.
No desenvolvimento de software, o termo também é usado para descrever ferramentas que automatizam a criação dessa estrutura inicial, como arquivos, configurações, dependências e convenções.
A ideia é simples: reduzir o trabalho necessário para sair do zero e chegar rapidamente a um projeto funcional.
Um exemplo para projetos backend é o Spring Initializr, do ecossistema Spring. Ele permite definir características como linguagem, sistema de build e dependências, e então gera a estrutura inicial do projeto.
No frontend, esse conceito já é bastante familiar através do uso de CLI’s.
CLI (Command-Line Interface)
Interface de Linha de Comando, é uma forma de interagir com um programa através de comandos digitados no terminal, em vez de utilizar uma interface gráfica.
Em vez de criar manualmente toda a estrutura de uma aplicação, configurar TypeScript, ferramentas de build, dependências e uma série de outras peças, utilizamos ferramentas de inicialização.
npm create alguma-coisa
Ou:
npx alguma-cli
A CLI pergunta algumas coisas, cria os arquivos e entrega um projeto pronto para desenvolver.
Entretanto, diferente das CLIs práticas e minimalistas dos frameworks frontend, a curva de aprendizagem dos frameworks (.NET ou Spring) e linguagens backend mais usados no mercado, e até a experiência de implantação desses sistemas, tornam isso uma experiência bem menos proveitosa.
Mas uma solução para esse problema não precisaria exatamente de uma aplicação enterprise com dezenas de abstrações ou sequer um framework novo.
Apenas um bom ponto de partida.
fastify-initializr-ts
O fastify-initializr-ts é uma ferramenta open source que gera um boilerplate moderno de API utilizando:
- Fastify;
- TypeScript;
- Zod;
- OpenAPI/Swagger;
- fastify-type-provider-zod;
- rate limiting;
- Prisma opcional;
- suporte a múltiplos bancos de dados.
Faça uma Única vez a instalação global:
npm install -g fastify-initializr-ts
Comece a criar novos projetos backend com um único comando:
npx fastify-initializr-ts
Depois disso, a CLI conduz o desenvolvedor pelo processo de criação.
Experiência desejada
A CLI foi pensada para transformar a criação inicial do backend em um pequeno wizard: algumas decisões, alguns arquivos gerados e, finalmente, uma API pronta para ser desenvolvida.
Por que Fastify?
O Fastify é um framework HTTP para Node.js focado em baixo overhead, performance e experiência de desenvolvimento. Rápido desenvolvimento implantação prática.
Uma estrutura extremamente básica do Fastify para uma API se pareceria com isto:
import Fastify from "fastify";
const app = Fastify();
app.get("/hello", async () => {
return {
message: "Hello World",
};
});
app.listen({
port: 3000,
});
Simples, certo?
Vamos ver como podemos organizar de maneira mais consistente para adaptar essa estrutura num eventual crescimento de projeto mais a frente.
Um dos aspectos mais interessantes do Fastify para esse projeto é sua arquitetura baseada em plugins.
Plugins podem encapsular funcionalidades e manter responsabilidades separadas, algo que combina muito bem com a proposta de um boilerplate.
Zod: Validando tipos e definindo schemas
Zod é utilizado para validação de dados em runtime e definição de schemas.
O Zod é uma biblioteca de validação orientada a TypeScript.
A ideia é definir um schema que descreve os dados esperados.
import { z } from "zod";
const SignupSchema = z.object({
name: z.string(),
email: z.email(),
password: z.string().min(8),
});
Podemos então validar dados externos:
app.post("/signup", {
schema: {
body: SignupSchema,
},
}, async (request, reply) => {
return reply.status(201).send({
message: "User created",
});
});
A vantagem é que o schema participa tanto da validação quanto da modelagem dos dados.
No fastify-initializr-ts, essa integração é complementada pelo fastify-type-provider-zod.
Uma consequência interessante
Quando schema, validação e tipagem estão próximos, reduzimos a quantidade de contratos duplicados espalhados pela aplicação.
Swagger e OpenAPI: Documentando a API
Aqui aparece outro problema bastante comum.
A aplicação cresce. As rotas aumentam. Entram parâmetros, headers e diferentes respostas.
E, depois de algum tempo, alguém pergunta:
Como essa API funciona mesmo?
Se não existe documentação, começamos uma pequena sessão de arqueologia no código.
É preciso procurar a rota, descobrir o método HTTP, descobrir os parâmetros, descobrir o body, descobrir as respostas possíveis e então testar manualmente.
O projeto tenta resolver isso desde o primeiro minuto.
O template utiliza:
@fastify/swagger
@fastify/swagger-ui
O @fastify/swagger integra a geração da especificação OpenAPI ao Fastify.
Já o @fastify/swagger-ui fornece uma interface visual para explorar a documentação.
Depois de iniciar a aplicação, a documentação fica disponível em:
http://localhost:3000/docs
Enquanto a API roda em:
http://localhost:3000
Isso muda bastante a experiência de desenvolvimento.
Em vez de depender imediatamente de Postman, Insomnia ou comandos curl, temos uma interface visual para descobrir e testar os endpoints.
Prisma: Conectando aos bancos de dados.
O Prisma foi escolhido como ORM opcional.
A proposta é particularmente interessante para aplicações TypeScript porque oferece acesso tipado ao banco, migrations e ferramentas para trabalhar com o modelo de dados.
Banco sob demanda
A escolha do banco acontece durante a criação do projeto. Isso permite manter aplicações simples realmente simples, enquanto projetos que precisam de persistência já recebem a estrutura necessária.
Durante a criação do projeto, a CLI pergunta se queremos configurar um banco.
Atualmente a CLI oferece suporte aos providers definidos pelo projeto.
| Provider | Exemplos |
|---|---|
| PostgreSQL | Supabase, Neon ou instalação própria |
| MySQL | Instalações MySQL compatíveis |
| SQLite | Ambiente local e projetos menores |
| MongoDB | MongoDB |
| SQL Server | Microsoft SQL Server |
| CockroachDB | CockroachDB |
A partir da escolha, a CLI adapta a infraestrutura do projeto.
fastify-ts/
├── lib/
│ └── prisma.ts
├── prisma/
├── prisma.config.ts
├── src/
│ ├── controllers/
│ ├── plugins/
│ ├── types/
│ └── server.ts
└── package.json
Rate limiting
Outra integração presente no template é o rate limiting através do plugin do ecossistema Fastify.
Isso adiciona uma camada básica para limitar a quantidade de requisições processadas.
Rate limiting não é segurança completa
Rate limiting é apenas uma camada de proteção. Ele não substitui autenticação, autorização, validação, proteção contra abuso, configuração adequada de infraestrutura ou outras medidas de segurança.
Deploy
Para implantação dessa aplicação pode ser feito o uso de serviços gratuitos comuns para aplicações baseadas em Javascript e NodeJS como a Vercel, Netlify e Cloudflare Pages.
