005 — Relatório Técnico · Stack da Aplicação: OpenAPI, Estado, UI e Testes
005 — Relatório Técnico · Stack da Aplicação: OpenAPI, Estado, UI e Testes
Seção intitulada “005 — Relatório Técnico · Stack da Aplicação: OpenAPI, Estado, UI e Testes”Entrega técnica da stack da aplicação. A fundação está na ADR 001.
O que foi construído
Seção intitulada “O que foi construído”Contrato de API (OpenAPI + Scalar)
Seção intitulada “Contrato de API (OpenAPI + Scalar)”app/server/openapi/document.ts—buildOpenApiDocument()mescla domínios e converte schemas Zod comz.toJSONSchema({ target: "draft-2020-12" }). Sem biblioteca intermediária.app/server/openapi/domains/{health,tasks}.ts— cada um exporta{ tag, schemas, paths }.app/server/{health,tasks}/schemas.ts— schemas Zod, fonte única.app/openapi.json/route.ts— serve o spec (force-static).app/reference/route.ts— UI Scalar via@scalar/nextjs-api-reference.app/api/{health,tasks}/route.ts— handlers reais que validam com os mesmos schemas (safeParse/parse).
Tipos e cliente tipado
Seção intitulada “Tipos e cliente tipado”scripts/gen-openapi-types.ts(pnpm openapi) — materializaopenapi.jsone geralib/shared/api-types.ts(openapi-typescript).lib/client/api.ts— clienteopenapi-fetchtipado:api.GET("/api/tasks"),api.POST("/api/tasks", { body }).
Estado (Zustand)
Seção intitulada “Estado (Zustand)”stores/tasks/store.ts+stores/tasks/sync.tsx— padrão inegociável do manifesto.components/tasks-demo.tsx+app/page.tsx— demo consumindo a store e a API.lib/dividida emserver/,client/,shared/(por ambiente de execução).
UI (shadcn/ui)
Seção intitulada “UI (shadcn/ui)”- Todos os componentes em
packages/ui/src/components/; hookuse-mobileempackages/ui/src/hooks/.Toaster(Sonner) montado noapp/layout.tsx.
Testes (Vitest)
Seção intitulada “Testes (Vitest)”vitest.config.ts+vitest.setup.ts(jsdom + Testing Library).app/server/tasks/schemas.test.ts— teste de contrato (schema → teste → implementação).
Banco (PostgreSQL + Prisma)
Seção intitulada “Banco (PostgreSQL + Prisma)”- Prisma 7 com schema multi-arquivo por domínio (
prismaSchemaFolder):apps/web/prisma.config.ts—schema: "prisma"(pasta),datasource.url = env("DATABASE_URL"), seed.apps/web/prisma/schema.prisma— sógenerator(novoprisma-client, outputgenerated/) +datasource(provider, sem url).apps/web/prisma/models/tasks.prismaemodels/users.prisma— um domínio por arquivo, com relaçãoUser 1—N Task.apps/web/lib/server/db.ts—PrismaClientcom@prisma/adapter-pg(singleton).apps/web/app/api/tasks/route.ts— agora persiste via Prisma (não mais em memória).prisma/seed.tsidempotente (cria User + Tasks).postinstall: prisma generate.
docker-compose.yml— Postgres 17 (pnpm db:start).apps/web/.env.example—DATABASE_URL. Scriptsdb:generate/push/migrate/studio/seed.
Validações executadas
Seção intitulada “Validações executadas”| Validação | Resultado |
|---|---|
tsc --noEmit (apps/web) | ✓ sem erros |
vitest run (apps/web) | ✓ 4 testes, 1 arquivo |
next build (apps/web) | ✓ rotas /, /api/health, /api/tasks, /openapi.json, /reference |
pnpm openapi | ✓ spec + tipos gerados (paths: /api/health, /api/tasks) |
prisma generate (multi-domínio) | ✓ client gerado de prisma/models/*.prisma |
| Banco real (Docker) | ✓ db:push + db:seed + POST/GET /api/tasks persistem; relação User↔Task OK |
Arquivos tocados (principais)
Seção intitulada “Arquivos tocados (principais)”apps/web/app/server/**,apps/web/app/api/**,apps/web/app/{openapi.json,reference}/**— OpenAPI.apps/web/stores/**,apps/web/components/tasks-demo.tsx,apps/web/app/page.tsx— estado/UI.apps/web/lib/**— cliente tipado e tipos gerados.apps/web/{vitest.config.ts,vitest.setup.ts},app/server/tasks/schemas.test.ts— testes.apps/web/prisma/**,docker-compose.yml,apps/web/.env.example— banco.packages/ui/**— componentes shadcn/ui.
Decisões técnicas relevantes
Seção intitulada “Decisões técnicas relevantes”- Zod 4 nativo para OpenAPI — sem adaptador, contrato vivo.
- Tipos da API gerados — o front não escreve tipos da API à mão.
- Prisma 7 (última versão) com driver adapter (
@prisma/adapter-pg) e schema multi-arquivo por domínio (prisma/models/*.prisma) — “controle de domínios”.
Criado por Joseph Trupel