fix: align next config with next 15.5.5

This commit is contained in:
Esdras Renan 2025-10-16 21:39:43 -03:00
parent 0cf1892256
commit 91d0608838
8 changed files with 642 additions and 510 deletions

View file

@ -20,7 +20,7 @@
## Stack atual (16/10/2025)
- **Next.js**: `15.5.5` (Turbopack em produção + cache de filesystem em DEV).
- `next.config.ts` mantém `experimental.turbopackFileSystemCacheForDev`; whitelist de domínios em `src/config/allowed-hosts.ts` usada tanto no `server.allowedHosts` quanto no `middleware.ts`.
- `next.config.ts` mantém `experimental.turbopackFileSystemCacheForDev` (flag não tipada oficialmente); whitelist de domínios em `src/config/allowed-hosts.ts` aplicada pelo `middleware.ts`.
- **React / React DOM**: `18.2.0`.
- **Trilha de testes**: Vitest (`pnpm test`) sem modo watch por padrão (`--run --passWithNoTests`).
- **CI**: workflow `Quality Checks` (`.github/workflows/quality-checks.yml`) roda `pnpm install`, `prisma:generate`, `lint`, `test`, `build`. Variáveis críticas (`BETTER_AUTH_SECRET`, `NEXT_PUBLIC_APP_URL`, etc.) são definidas apenas no runner — não afetam a VPS.

View file

@ -5,7 +5,7 @@ Este documento consolida o estado atual do ambiente de desenvolvimento, descreve
## Resumo rápido
- **Node/PNPM**: Node 20.9+ (alinhado ao requisito do Next 15) + pnpm 9 (habilite via `corepack enable && corepack prepare pnpm@9 --activate`).
- **Next.js 15.5.5**: Projeto voltou para a versão estável (`next@15.5.5`) com Turbopack como bundler padrão, cache de filesystem habilitado e whitelist de domínios via `server.allowedHosts` + middleware.
- **Next.js 15.5.5**: Projeto voltou para a versão estável (`next@15.5.5`) com Turbopack como bundler padrão, cache de filesystem habilitado via `experimental.turbopackFileSystemCacheForDev` (flag ainda sem tipagem pública) e whitelist de domínios garantida pelo middleware.
- **Lint/Test/Build**: `pnpm lint`, `pnpm test`, `pnpm build`. O script de testes usa `vitest --run --passWithNoTests`, eliminando o modo watch interativo.
- **Banco DEV**: SQLite em `prisma/prisma/db.dev.sqlite`. Defina `DATABASE_URL="file:./prisma/db.dev.sqlite"` ao chamar CLI do Prisma.
- **Desktop (Tauri)**: fonte em `apps/desktop`. Usa Radix tabs + componentes shadcn-like, integra com os endpoints `/api/machines/*` e suporta atualização automática via GitHub Releases.
@ -35,8 +35,8 @@ Este documento consolida o estado atual do ambiente de desenvolvimento, descreve
- Mantemos o projeto em `next@15.5.5`, priorizando estabilidade enquanto acompanhamos as novidades do 16.
- **React 18.2**: voltamos para a versão suportada oficialmente pelo Next 15. Evite APIs exclusivas do React 19 (`use(...)`, `useActionState`, etc.).
- **Turbopack** segue como bundler padrão. Mantemos `experimental.turbopackFileSystemCacheForDev = true` no `next.config.ts` para acelerar reinicializações do `pnpm dev`.
- **Whitelist de hosts**: `server.allowedHosts` + middleware em `middleware.ts` garantem que apenas os domínios Traefik/localhost sejam aceitos.
- **Turbopack** segue como bundler padrão. Mantemos `experimental.turbopackFileSystemCacheForDev = true` no `next.config.ts` (com `@ts-expect-error`, pois o release estável ainda não exporta o tipo).
- **Whitelist de hosts**: o release estável 15.5 não aceita `server.allowedHosts` (vide [`invalid-next-config`](https://nextjs.org/docs/messages/invalid-next-config)), portanto bloqueamos domínios exclusivamente via `middleware.ts`.
## Comandos de qualidade

View file

@ -1,15 +1,9 @@
import type { NextConfig } from "next"
import { ALLOWED_HOSTS } from "./src/config/allowed-hosts"
const nextConfig = {
experimental: {
// @ts-expect-error Flag documentada mas ainda não declarada nos tipos públicos estáveis.
turbopackFileSystemCacheForDev: true,
},
// No Next 16 specific trustHostHeader flag; we whitelist via classic server.allowedHosts.
// @ts-expect-error server.allowedHosts disponível na linha 15.x
server: {
allowedHosts: [...ALLOWED_HOSTS],
},
} satisfies NextConfig
export default nextConfig

1120
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -63,9 +63,11 @@ export async function POST(request: Request) {
const items = (report.items ?? []) as HoursByClientItem[]
const alerts = items.filter((i) => i.contractedHoursPerMonth != null && (i.totalMs / 3600000) / (i.contractedHoursPerMonth || 1) * 100 >= threshold)
type ManagerUser = { email: string; name: string | null }
for (const item of alerts) {
// Find managers of the company in Prisma
const managers = await prisma.user.findMany({
const managers: ManagerUser[] = await prisma.user.findMany({
where: {
tenantId,
companyId: item.companyId,

View file

@ -1,9 +1,9 @@
import { NextResponse } from "next/server"
import { Prisma } from "@prisma/client"
import { prisma } from "@/lib/prisma"
import { assertStaffSession } from "@/lib/auth-server"
import { isAdmin } from "@/lib/authz"
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library"
export const runtime = "nodejs"
@ -48,7 +48,7 @@ export async function PATCH(request: Request, { params }: { params: Promise<{ id
return NextResponse.json({ company })
} catch (error) {
console.error("Failed to update company", error)
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
if (error instanceof PrismaClientKnownRequestError && error.code === "P2002") {
return NextResponse.json({ error: "Já existe uma empresa com este slug." }, { status: 409 })
}
return NextResponse.json({ error: "Falha ao atualizar empresa" }, { status: 500 })
@ -95,7 +95,7 @@ export async function DELETE(_: Request, { params }: { params: Promise<{ id: str
await prisma.company.delete({ where: { id: company.id } })
return NextResponse.json({ ok: true })
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2003") {
if (error instanceof PrismaClientKnownRequestError && error.code === "P2003") {
return NextResponse.json(
{ error: "Não é possível remover esta empresa pois existem registros vinculados." },
{ status: 409 }

View file

@ -2,9 +2,9 @@ import { NextResponse } from "next/server"
import { randomBytes } from "crypto"
import { prisma } from "@/lib/prisma"
import { Prisma } from "@prisma/client"
import { assertStaffSession } from "@/lib/auth-server"
import { isAdmin } from "@/lib/authz"
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library"
export const runtime = "nodejs"
@ -67,7 +67,7 @@ export async function POST(request: Request) {
return NextResponse.json({ company })
} catch (error) {
console.error("Failed to create company", error)
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
if (error instanceof PrismaClientKnownRequestError && error.code === "P2002") {
// Duplicidade de slug por tenant ou provisioningCode único
return NextResponse.json(
{ error: "Já existe uma empresa com este slug ou código de provisionamento." },

View file

@ -15,7 +15,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"jsx": "preserve",
"incremental": true,
"plugins": [
{