fix: align next config with next 15.5.5
This commit is contained in:
parent
0cf1892256
commit
91d0608838
8 changed files with 642 additions and 510 deletions
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
## Stack atual (16/10/2025)
|
## Stack atual (16/10/2025)
|
||||||
- **Next.js**: `15.5.5` (Turbopack em produção + cache de filesystem em DEV).
|
- **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`.
|
- **React / React DOM**: `18.2.0`.
|
||||||
- **Trilha de testes**: Vitest (`pnpm test`) sem modo watch por padrão (`--run --passWithNoTests`).
|
- **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.
|
- **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.
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ Este documento consolida o estado atual do ambiente de desenvolvimento, descreve
|
||||||
## Resumo rápido
|
## 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`).
|
- **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.
|
- **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.
|
- **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.
|
- **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.
|
- 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.).
|
- **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`.
|
- **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**: `server.allowedHosts` + middleware em `middleware.ts` garantem que apenas os domínios Traefik/localhost sejam aceitos.
|
- **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
|
## Comandos de qualidade
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,9 @@
|
||||||
import type { NextConfig } from "next"
|
import type { NextConfig } from "next"
|
||||||
import { ALLOWED_HOSTS } from "./src/config/allowed-hosts"
|
|
||||||
|
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
experimental: {
|
experimental: {
|
||||||
|
// @ts-expect-error Flag documentada mas ainda não declarada nos tipos públicos estáveis.
|
||||||
turbopackFileSystemCacheForDev: true,
|
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
|
} satisfies NextConfig
|
||||||
|
|
||||||
export default nextConfig
|
export default nextConfig
|
||||||
|
|
|
||||||
1120
pnpm-lock.yaml
generated
1120
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -63,9 +63,11 @@ export async function POST(request: Request) {
|
||||||
const items = (report.items ?? []) as HoursByClientItem[]
|
const items = (report.items ?? []) as HoursByClientItem[]
|
||||||
const alerts = items.filter((i) => i.contractedHoursPerMonth != null && (i.totalMs / 3600000) / (i.contractedHoursPerMonth || 1) * 100 >= threshold)
|
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) {
|
for (const item of alerts) {
|
||||||
// Find managers of the company in Prisma
|
// Find managers of the company in Prisma
|
||||||
const managers = await prisma.user.findMany({
|
const managers: ManagerUser[] = await prisma.user.findMany({
|
||||||
where: {
|
where: {
|
||||||
tenantId,
|
tenantId,
|
||||||
companyId: item.companyId,
|
companyId: item.companyId,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { NextResponse } from "next/server"
|
import { NextResponse } from "next/server"
|
||||||
|
|
||||||
import { Prisma } from "@prisma/client"
|
|
||||||
import { prisma } from "@/lib/prisma"
|
import { prisma } from "@/lib/prisma"
|
||||||
import { assertStaffSession } from "@/lib/auth-server"
|
import { assertStaffSession } from "@/lib/auth-server"
|
||||||
import { isAdmin } from "@/lib/authz"
|
import { isAdmin } from "@/lib/authz"
|
||||||
|
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library"
|
||||||
|
|
||||||
export const runtime = "nodejs"
|
export const runtime = "nodejs"
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ export async function PATCH(request: Request, { params }: { params: Promise<{ id
|
||||||
return NextResponse.json({ company })
|
return NextResponse.json({ company })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to update company", 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: "Já existe uma empresa com este slug." }, { status: 409 })
|
||||||
}
|
}
|
||||||
return NextResponse.json({ error: "Falha ao atualizar empresa" }, { status: 500 })
|
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 } })
|
await prisma.company.delete({ where: { id: company.id } })
|
||||||
return NextResponse.json({ ok: true })
|
return NextResponse.json({ ok: true })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2003") {
|
if (error instanceof PrismaClientKnownRequestError && error.code === "P2003") {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "Não é possível remover esta empresa pois existem registros vinculados." },
|
{ error: "Não é possível remover esta empresa pois existem registros vinculados." },
|
||||||
{ status: 409 }
|
{ status: 409 }
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ import { NextResponse } from "next/server"
|
||||||
import { randomBytes } from "crypto"
|
import { randomBytes } from "crypto"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma"
|
import { prisma } from "@/lib/prisma"
|
||||||
import { Prisma } from "@prisma/client"
|
|
||||||
import { assertStaffSession } from "@/lib/auth-server"
|
import { assertStaffSession } from "@/lib/auth-server"
|
||||||
import { isAdmin } from "@/lib/authz"
|
import { isAdmin } from "@/lib/authz"
|
||||||
|
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library"
|
||||||
|
|
||||||
export const runtime = "nodejs"
|
export const runtime = "nodejs"
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ export async function POST(request: Request) {
|
||||||
return NextResponse.json({ company })
|
return NextResponse.json({ company })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to create company", 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
|
// Duplicidade de slug por tenant ou provisioningCode único
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "Já existe uma empresa com este slug ou código de provisionamento." },
|
{ error: "Já existe uma empresa com este slug ou código de provisionamento." },
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "preserve",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue