Pular para o conteúdo
My Blog
Voltar

fastify-initializr-ts: Construindo uma CLI bootstrap para API's Typescript

-

Gustavo Lobo

Editar página

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:

Porém, o processo muitas vezes acaba sendo, não a complexidade, mas a repetição.

É exatamente aí que entra um gerador bootstrap.

Tip

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:

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.

Tip

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?

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

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.

Prisma

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.

ProviderExemplos
PostgreSQLSupabase, Neon ou instalação própria
MySQLInstalações MySQL compatíveis
SQLiteAmbiente local e projetos menores
MongoDBMongoDB
SQL ServerMicrosoft SQL Server
CockroachDBCockroachDB

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.


Editar página
Compartilhar este post: