Pular para o conteúdo
Kayro Gomes

API REST com OpenAPI e SDK TypeScript

API REST pública com autenticação JWT, rate limiting por IP/tenant, documentação OpenAPI gerada do código e SDK TypeScript publicado no npm com tipos sincronizados.

  • Hono
  • TypeScript
  • Zod
  • Postgres
  • OpenAPI
  • Bun
Imagem ilustrativa de exemplo usada em posts do blog

Construí essa API para servir de backend público do meu portfólio: o site consome ela para listar projetos, posts, e enviar formulários. A ideia foi tratar a API como produto: documentação viva, SDKs versionados, e rate limiting justo.

Por que Hono

Hono roda em Bun, Vercel Edge, Cloudflare Workers, Deno, Node — o mesmo código. Para uma API pública, isso é enorme: posso mover de host sem reescrever nada. Performance também é o ponto: roteador baseado em radix tree, latência sub-ms no warm path.

1import { Hono } from 'hono'
2import { zValidator } from '@hono/zod-validator'
3import { z } from 'zod'
4
5const app = new Hono()
6
7const CreateProjectSchema = z.object({
8 title: z.string().min(3).max(120),
9 summary: z.string().min(10).max(280),
10 tech: z.array(z.string()).min(1).max(20),
11 liveUrl: z.string().url().optional(),
12 repoUrl: z.string().url().optional(),
13})
14
15app.post('/projects', zValidator('json', CreateProjectSchema), async (c) => {
16 const data = c.req.valid('json')
17
18 // A partir daqui, data é CreateProject tipado.
19 // Sem cast, sem unknown, sem narrow manual.
20 const project = await db.projects.create({ data })
21
22 return c.json({ project }, 201)
23})

OpenAPI gerado do código

Em vez de manter um openapi.yaml à mão, eu gero do código no build. Cada rota exporta seu schema Zod, e o @hono/zod-openapi monta o spec. Resultado: a documentação em /docs está sempre sincronizada com o que o servidor realmente aceita.

1import { OpenAPIHono } from '@hono/zod-openapi'
2
3const app = new OpenAPIHono()
4
5app.openapi(
6 {
7 method: 'post',
8 path: '/projects',
9 request: {
10 body: { content: { 'application/json': { schema: CreateProjectSchema } } },
11 },
12 responses: {
13 201: {
14 description: 'Project created',
15 content: { 'application/json': { schema: ProjectResponseSchema } },
16 },
17 400: { description: 'Validation error' },
18 429: { description: 'Rate limit exceeded' },
19 },
20 },
21 async (c) => {
22 const data = c.req.valid('json')
23 // ...
24 }
25)
26
27// Gera /doc e /openapi.json automaticamente
28app.doc('/openapi.json', { openapi: '3.1.0', info: { title: 'Kayro API', version: '1.0.0' } })
Foto de capa ilustrativa com gradiente azul e roxo — usada no hero da home

Imagem de capa ilustrativa. Substitua no admin em Mídia.

O SDK npm é gerado do mesmo openapi.json via openapi-typescript. O consumidor importa o cliente tipado e o autocomplete do editor mostra os campos, retornos e erros de cada endpoint. Zero código de cola, zero chance de drift entre spec e implementação.