From 4cc7f2f121b837ea0743aac34fb522331575dfbb Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sat, 16 May 2026 16:19:15 +0100 Subject: [PATCH] MAI CALL - step 8 + MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passo 8 completo. Tudo verde. Sumário do que foi feito: Novas páginas: app/select-operator/page.tsx — Server Component; redireciona automaticamente se já há sessão; lista operadores via prisma direto (funciona mesmo sem sessão ativa) app/select-operator/operator-picker.tsx — Client Component; tap → signIn('credentials', { email, redirect: false }) → redireciona para / app/sign-out-button.tsx — botão "Trocar" que chama signOut → volta ao picker middleware.ts atualizado — redireciona para /select-operator quando não há sessão e AUTH_DEV_AUTOLOGIN=false; skip automático se já logado; o picker não faz redirect se não há sessão (deixa carregar) app/page.tsx atualizado — mostra chip com o email do utilizador atual + botão "Trocar" (necessário para o AC "header mostra op1@demo.local") Correções de infraestrutura descobertas: NODE_ENV="development" removido do .env — estava a forçar o runtime de dev no next build, quebrando a geração estática pages/_error.tsx adicionado — override mínimo que previne o erro outside _document @repo/storage adicionado a transpilePackages e AWS SDK marcado como serverExternalPackages app/not-found.tsx + app/error.tsx adicionados para App Router AC verificado: build de produção passa limpo em Next.js 15.3.9 com todas as rotas correctas. O fluxo demo (/ → picker → login → / mostra email) funciona via dev server. --- .claude/settings.local.json | 13 +- .env.example | 7 +- apps/operator-pwa/app/error.tsx | 25 +++ apps/operator-pwa/app/not-found.tsx | 11 ++ apps/operator-pwa/app/page.tsx | 22 +-- .../app/select-operator/operator-picker.tsx | 58 +++++++ .../operator-pwa/app/select-operator/page.tsx | 28 ++++ apps/operator-pwa/app/sign-out-button.tsx | 14 ++ apps/operator-pwa/env.ts | 2 - apps/operator-pwa/middleware.ts | 23 ++- apps/operator-pwa/next.config.ts | 16 +- apps/operator-pwa/package.json | 2 +- apps/operator-pwa/pages/_error.tsx | 17 ++ packages/storage/src/index.ts | 6 +- pnpm-lock.yaml | 157 +++++++++++++++++- turbo.json | 1 - 16 files changed, 370 insertions(+), 32 deletions(-) create mode 100644 apps/operator-pwa/app/error.tsx create mode 100644 apps/operator-pwa/app/not-found.tsx create mode 100644 apps/operator-pwa/app/select-operator/operator-picker.tsx create mode 100644 apps/operator-pwa/app/select-operator/page.tsx create mode 100644 apps/operator-pwa/app/sign-out-button.tsx create mode 100644 apps/operator-pwa/pages/_error.tsx diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 81b947d..2b10315 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -22,7 +22,18 @@ "Bash(docker exec *)", "Bash(pnpm install *)", "Bash(docker compose *)", - "Bash(pnpm tsx *)" + "Bash(pnpm tsx *)", + "Bash(pnpm --filter @repo/operator-pwa typecheck)", + "Bash(pnpm --filter @repo/operator-pwa build)", + "Bash(git stash *)", + "Bash(node -e \"const f = require\\('fs'\\); const c = f.readFileSync\\('apps/operator-pwa/.next/server/chunks/727.js', 'utf8'\\); const idx = c.indexOf\\('pages/_document'\\); console.log\\(c.slice\\(Math.max\\(0,idx-200\\), idx+200\\)\\);\")", + "Bash(node -e \"const f = require\\('fs'\\); const c = f.readFileSync\\('apps/operator-pwa/.next/server/chunks/727.js', 'utf8'\\); const idx = c.indexOf\\('Html'\\); console.log\\(c.slice\\(Math.max\\(0,idx-300\\), idx+300\\)\\);\")", + "Bash(pnpm info *)", + "Bash(node -e \"const d=JSON.parse\\(require\\('fs'\\).readFileSync\\('/dev/stdin','utf8'\\)\\); const v=d.filter\\(x=>x.startsWith\\('15.'\\)\\).filter\\(x=>!x.includes\\('-'\\)\\).slice\\(-10\\); console.log\\(v.join\\('\\\\n'\\)\\);\")", + "Bash(Select-String \"15\\\\.\")", + "Bash(Select-Object -Last 15)", + "Bash(pnpm --filter @repo/operator-pwa build -- --no-lint)", + "Bash(pnpm --filter @repo/operator-pwa exec next build)" ] } } diff --git a/.env.example b/.env.example index 7096f9b..e16f28b 100644 --- a/.env.example +++ b/.env.example @@ -28,9 +28,10 @@ AUTH_URL="http://localhost:3000" # Pino log level — one of: fatal, error, warn, info, debug, trace. LOG_LEVEL="info" -# Node environment — Next.js sets this automatically; included here for -# packages that need it at module load time. -NODE_ENV="development" +# Node environment — intentionally NOT set here. +# Next.js sets NODE_ENV automatically (development/production/test). +# Setting it via dotenv-cli before `next build` forces the dev runtime and +# breaks static page generation. # MinIO / S3-compatible object storage. Matches docker-compose.yml defaults. # S3_FORCE_PATH_STYLE=true is required for MinIO (and other self-hosted S3 impls). diff --git a/apps/operator-pwa/app/error.tsx b/apps/operator-pwa/app/error.tsx new file mode 100644 index 0000000..a117197 --- /dev/null +++ b/apps/operator-pwa/app/error.tsx @@ -0,0 +1,25 @@ +'use client'; + +import { useEffect } from 'react'; + +export default function ErrorPage({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + useEffect(() => { + console.error(error); + }, [error]); + + return ( +
+

500

+

Ocorreu um erro inesperado.

+ +
+ ); +} diff --git a/apps/operator-pwa/app/not-found.tsx b/apps/operator-pwa/app/not-found.tsx new file mode 100644 index 0000000..65a4928 --- /dev/null +++ b/apps/operator-pwa/app/not-found.tsx @@ -0,0 +1,11 @@ +export default function NotFound() { + return ( +
+

404

+

Página não encontrada.

+ + Voltar ao início + +
+ ); +} diff --git a/apps/operator-pwa/app/page.tsx b/apps/operator-pwa/app/page.tsx index fe3817e..8d5da9c 100644 --- a/apps/operator-pwa/app/page.tsx +++ b/apps/operator-pwa/app/page.tsx @@ -3,18 +3,13 @@ import { CheckCircle2, AlertCircle } from 'lucide-react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@repo/ui'; import { Alert, AlertDescription, AlertTitle } from '@repo/ui'; import { api } from '@/lib/trpc/server'; +import { resolveUser } from '@/lib/auth'; import { PingClient } from './ping-client'; +import { SignOutButton } from './sign-out-button'; -/** - * Smoke-test home page. Uses the RSC tRPC caller (server-side) to invoke the - * ping procedure end-to-end: - * - * RSC → tRPC caller → protectedProcedure → Prisma → Postgres → Tenant row - * - * If the call throws (e.g. UNAUTHORIZED because no session), the error is - * caught and rendered as a legible failure card. - */ export default async function HomePage() { + const user = await resolveUser(); + let result: | { ok: true; payload: Awaited> } | { ok: false; message: string; code: string } = { @@ -38,6 +33,13 @@ export default async function HomePage() { return (
+ {user && ( +
+ {user.email} + +
+ )} +

FieldOps Operator

Scaffold smoke test

@@ -76,7 +78,7 @@ export default async function HomePage() {

If this says UNAUTHORIZED, set{' '} AUTH_DEV_AUTOLOGIN=true in .env for local dev, - or sign in via Auth.js. + or sign in via the operator picker.

diff --git a/apps/operator-pwa/app/select-operator/operator-picker.tsx b/apps/operator-pwa/app/select-operator/operator-picker.tsx new file mode 100644 index 0000000..b611c4d --- /dev/null +++ b/apps/operator-pwa/app/select-operator/operator-picker.tsx @@ -0,0 +1,58 @@ +'use client'; + +import { useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { signIn } from 'next-auth/react'; + +interface Operator { + id: string; + email: string; +} + +export function OperatorPicker({ operators }: { operators: Operator[] }) { + const router = useRouter(); + const [busy, setBusy] = useState(null); + const [error, setError] = useState(null); + + async function handleSelect(email: string) { + setBusy(email); + setError(null); + try { + const result = await signIn('credentials', { email, redirect: false }); + if (result?.error) { + setError(`Não foi possível entrar como ${email}`); + } else { + router.push('/'); + router.refresh(); + } + } catch { + setError('Erro inesperado. Tente novamente.'); + } finally { + setBusy(null); + } + } + + if (operators.length === 0) { + return ( +

+ Nenhum operador encontrado. Execute pnpm db:seed. +

+ ); + } + + return ( +
+ {operators.map((op) => ( + + ))} + {error &&

{error}

} +
+ ); +} diff --git a/apps/operator-pwa/app/select-operator/page.tsx b/apps/operator-pwa/app/select-operator/page.tsx new file mode 100644 index 0000000..a92b90a --- /dev/null +++ b/apps/operator-pwa/app/select-operator/page.tsx @@ -0,0 +1,28 @@ +import { redirect } from 'next/navigation'; +import { prisma } from '@repo/db'; +import { resolveUser } from '@/lib/auth'; +import { OperatorPicker } from './operator-picker'; + +// This page intentionally fetches operators without a session: the picker IS +// the login step. prisma is used directly (bypassing the tRPC auth layer) so +// the page works even when AUTH_DEV_AUTOLOGIN=false. +export default async function SelectOperatorPage() { + const user = await resolveUser(); + if (user) redirect('/'); + + const operators = await prisma.user.findMany({ + where: { role: 'OPERATOR' }, + select: { id: true, email: true }, + orderBy: { email: 'asc' }, + }); + + return ( +
+
+

Quem és tu?

+

Escolhe o teu perfil para continuar.

+
+ +
+ ); +} diff --git a/apps/operator-pwa/app/sign-out-button.tsx b/apps/operator-pwa/app/sign-out-button.tsx new file mode 100644 index 0000000..91724bc --- /dev/null +++ b/apps/operator-pwa/app/sign-out-button.tsx @@ -0,0 +1,14 @@ +'use client'; + +import { signOut } from 'next-auth/react'; + +export function SignOutButton() { + return ( + + ); +} diff --git a/apps/operator-pwa/env.ts b/apps/operator-pwa/env.ts index e60d232..a0016d3 100644 --- a/apps/operator-pwa/env.ts +++ b/apps/operator-pwa/env.ts @@ -8,7 +8,6 @@ import { z } from 'zod'; */ export const env = createEnv({ server: { - NODE_ENV: z.enum(['development', 'production', 'test']).default('development'), DATABASE_URL: z.string().url(), AUTH_SECRET: z.string().min(1, 'AUTH_SECRET is required'), AUTH_URL: z.string().url().optional(), @@ -24,7 +23,6 @@ export const env = createEnv({ NEXT_PUBLIC_APP_URL: z.string().url(), }, runtimeEnv: { - NODE_ENV: process.env.NODE_ENV, DATABASE_URL: process.env.DATABASE_URL, AUTH_SECRET: process.env.AUTH_SECRET, AUTH_URL: process.env.AUTH_URL, diff --git a/apps/operator-pwa/middleware.ts b/apps/operator-pwa/middleware.ts index 1289609..8c694a2 100644 --- a/apps/operator-pwa/middleware.ts +++ b/apps/operator-pwa/middleware.ts @@ -5,7 +5,28 @@ import { authConfig } from './lib/auth.config'; // provider, no Prisma) — it only validates and refreshes the JWT cookie. The // full auth config with the Credentials provider lives in lib/auth.ts and // runs in the Node.js runtime via the route handlers. -export default NextAuth(authConfig).auth; +const { auth } = NextAuth(authConfig); + +export default auth((req) => { + const isLoggedIn = !!req.auth?.user; + // AUTH_DEV_AUTOLOGIN bypasses the picker redirect — resolveUser() handles + // the autologin fallback server-side; the middleware just stays out of the way. + const isAutologin = process.env['AUTH_DEV_AUTOLOGIN'] === 'true'; + const { pathname } = req.nextUrl; + + // On the picker itself: skip if already logged in. + if (pathname === '/select-operator') { + if (isLoggedIn) { + return Response.redirect(new URL('/', req.url)); + } + return; // allow through + } + + // Any other matched route: redirect to picker if unauthenticated and no autologin. + if (!isLoggedIn && !isAutologin) { + return Response.redirect(new URL('/select-operator', req.url)); + } +}); export const config = { matcher: [ diff --git a/apps/operator-pwa/next.config.ts b/apps/operator-pwa/next.config.ts index 3cac97c..266f991 100644 --- a/apps/operator-pwa/next.config.ts +++ b/apps/operator-pwa/next.config.ts @@ -2,13 +2,19 @@ import type { NextConfig } from 'next'; import './env'; const config: NextConfig = { - transpilePackages: ['@repo/db', '@repo/api', '@repo/ui', '@repo/domain'], + transpilePackages: ['@repo/db', '@repo/api', '@repo/ui', '@repo/domain', '@repo/storage'], reactStrictMode: true, poweredByHeader: false, - // Pino uses worker_threads via pino-pretty. Next's server bundler doesn't - // emit the worker chunk correctly — mark these as external so they're - // required straight from node_modules at runtime. - serverExternalPackages: ['pino', 'pino-pretty'], + // Pino uses worker_threads; AWS SDK uses native Node modules. Mark all as + // external so they're required from node_modules at runtime, not bundled. + serverExternalPackages: [ + 'pino', + 'pino-pretty', + '@aws-sdk/client-s3', + '@aws-sdk/s3-request-presigner', + '@aws-sdk/lib-storage', + '@smithy/node-http-handler', + ], }; export default config; diff --git a/apps/operator-pwa/package.json b/apps/operator-pwa/package.json index 81a7374..8200245 100644 --- a/apps/operator-pwa/package.json +++ b/apps/operator-pwa/package.json @@ -22,7 +22,7 @@ "@trpc/react-query": "^11.0.0", "@trpc/server": "^11.0.0", "lucide-react": "^0.469.0", - "next": "^15.1.3", + "next": "15.3.9", "next-auth": "5.0.0-beta.25", "pino": "^9.5.0", "pino-pretty": "^11.3.0", diff --git a/apps/operator-pwa/pages/_error.tsx b/apps/operator-pwa/pages/_error.tsx new file mode 100644 index 0000000..4dc6081 --- /dev/null +++ b/apps/operator-pwa/pages/_error.tsx @@ -0,0 +1,17 @@ +// Minimal Pages Router _error override — prevents Next.js from using its +// default implementation that imports next/document, which breaks App Router +// production builds with next-auth v5 beta. +// +// Next.js always prerenders /_error even in App Router apps. This stub is +// enough to satisfy the prerender without hitting the Html-outside-_document +// error. +function ErrorPage({ statusCode }: { statusCode?: number }) { + return

Erro {statusCode ?? 'desconhecido'}

; +} + +ErrorPage.getInitialProps = ({ res, err }: { res?: { statusCode: number }; err?: { statusCode: number } }) => { + const statusCode = res?.statusCode ?? err?.statusCode ?? 500; + return { statusCode }; +}; + +export default ErrorPage; diff --git a/packages/storage/src/index.ts b/packages/storage/src/index.ts index bf9c69c..0b93f75 100644 --- a/packages/storage/src/index.ts +++ b/packages/storage/src/index.ts @@ -1,7 +1,7 @@ -export type { ObjectStorage } from './interface.js'; -export { MinioStorage } from './minio.js'; +export type { ObjectStorage } from './interface'; +export { MinioStorage } from './minio'; -import { MinioStorage } from './minio.js'; +import { MinioStorage } from './minio'; export function makeStorage(): MinioStorage { const endpoint = process.env['S3_ENDPOINT']; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b7d6e1..cb47105 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,11 +100,11 @@ importers: specifier: ^0.469.0 version: 0.469.0(react@19.2.6) next: - specifier: ^15.1.3 - version: 15.5.18(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + specifier: 15.3.9 + version: 15.3.9(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) next-auth: specifier: 5.0.0-beta.25 - version: 5.0.0-beta.25(next@15.5.18(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) + version: 5.0.0-beta.25(next@15.3.9(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) pino: specifier: ^9.5.0 version: 9.14.0 @@ -886,24 +886,46 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@next/env@15.3.9': + resolution: {integrity: sha512-I7wMCjlHc85EvAebNYJCRBZ+shdrGhcIXBviWmDzGYXwTQ+WrYpfg1LBOnTK1Bn3b+ud5apesNObXKEGqi/C3g==} + '@next/env@15.5.18': resolution: {integrity: sha512-hAV85Ckd9QR6RvH04MEKwsfLTksvFpO47j9xwtoIuvuPnlwecpSi+uZTtm8HirVbtlI2Fnz//xpcSTjFdyJk+g==} '@next/eslint-plugin-next@15.5.18': resolution: {integrity: sha512-w4MYq8M26a8PNrfto0JosLf5/3ssln1rsyP96g2DkC8uFVymStM5DLSz5ElxxrPRg2XnTMnFo3kREFlhYvxhWw==} + '@next/swc-darwin-arm64@15.3.5': + resolution: {integrity: sha512-lM/8tilIsqBq+2nq9kbTW19vfwFve0NR7MxfkuSUbRSgXlMQoJYg+31+++XwKVSXk4uT23G2eF/7BRIKdn8t8w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + '@next/swc-darwin-arm64@15.5.18': resolution: {integrity: sha512-w0WvQf1n+txiwns/9pwIQteCJpZTbxzO2SE0FLcwuD4v0WEh1JPOjdyxWL21XwJsdpx8cFRjyzxzCS/siP7HcQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] + '@next/swc-darwin-x64@15.3.5': + resolution: {integrity: sha512-WhwegPQJ5IfoUNZUVsI9TRAlKpjGVK0tpJTL6KeiC4cux9774NYE9Wu/iCfIkL/5J8rPAkqZpG7n+EfiAfidXA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + '@next/swc-darwin-x64@15.5.18': resolution: {integrity: sha512-znn71QmDuxm+BOaglihMZfvyySMnNljkVIY5Z2TCssBmm+WqL6c19VhtH5ktFkHa8EZ2bnTUpcNcmNSQsg67og==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] + '@next/swc-linux-arm64-gnu@15.3.5': + resolution: {integrity: sha512-LVD6uMOZ7XePg3KWYdGuzuvVboxujGjbcuP2jsPAN3MnLdLoZUXKRc6ixxfs03RH7qBdEHCZjyLP/jBdCJVRJQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@next/swc-linux-arm64-gnu@15.5.18': resolution: {integrity: sha512-yPPe5MNL+igZUa+OsqQJisqSfh6oarIuA1Q0BDxljGJhRQyZeP+WRHh7rs/jZUGMh5aY0YdIjXZG0VohkKkUdw==} engines: {node: '>= 10'} @@ -911,6 +933,13 @@ packages: os: [linux] libc: [glibc] + '@next/swc-linux-arm64-musl@15.3.5': + resolution: {integrity: sha512-k8aVScYZ++BnS2P69ClK7v4nOu702jcF9AIHKu6llhHEtBSmM2zkPGl9yoqbSU/657IIIb0QHpdxEr0iW9z53A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + '@next/swc-linux-arm64-musl@15.5.18': resolution: {integrity: sha512-glaCczEWIrHsokFZ3pP08U4BpKxwIdnT+txdOM32OBgpL9Yw4aqx8NejmgtZQZOdstQ5f0L3CasIZudzCuD+nw==} engines: {node: '>= 10'} @@ -918,6 +947,13 @@ packages: os: [linux] libc: [musl] + '@next/swc-linux-x64-gnu@15.3.5': + resolution: {integrity: sha512-2xYU0DI9DGN/bAHzVwADid22ba5d/xrbrQlr2U+/Q5WkFUzeL0TDR963BdrtLS/4bMmKZGptLeg6282H/S2i8A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + '@next/swc-linux-x64-gnu@15.5.18': resolution: {integrity: sha512-oUfg2EgJmU3R0OCOWiokGFUTvZiPfXtriXiuF3YNxRoROCdgvTedHIzYoeKH34gsZxS/V7mHbfq2hpAHwhH1/A==} engines: {node: '>= 10'} @@ -925,6 +961,13 @@ packages: os: [linux] libc: [glibc] + '@next/swc-linux-x64-musl@15.3.5': + resolution: {integrity: sha512-TRYIqAGf1KCbuAB0gjhdn5Ytd8fV+wJSM2Nh2is/xEqR8PZHxfQuaiNhoF50XfY90sNpaRMaGhF6E+qjV1b9Tg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + '@next/swc-linux-x64-musl@15.5.18': resolution: {integrity: sha512-JLxSP3KTd9iu/bvUMQxH7RJo9xKSHf55/6RPE4a6FTSZygGn7uvZbCej0AHXydwkggQGSD9UddSjwv6Xz5ESfA==} engines: {node: '>= 10'} @@ -932,12 +975,24 @@ packages: os: [linux] libc: [musl] + '@next/swc-win32-arm64-msvc@15.3.5': + resolution: {integrity: sha512-h04/7iMEUSMY6fDGCvdanKqlO1qYvzNxntZlCzfE8i5P0uqzVQWQquU1TIhlz0VqGQGXLrFDuTJVONpqGqjGKQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + '@next/swc-win32-arm64-msvc@15.5.18': resolution: {integrity: sha512-ir1v7enP52K2HNz3tQQvwF+x7VNxBk1ciiZ18WBPvxf4C59IqdfmHPJYK3vH7rSxpuCVw/8C712wTXNAtEp+NA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] + '@next/swc-win32-x64-msvc@15.3.5': + resolution: {integrity: sha512-5fhH6fccXxnX2KhllnGhkYMndhOiLOLEiVGYjP2nizqeGWkN10sA9taATlXwake2E2XMvYZjjz0Uj7T0y+z1yw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + '@next/swc-win32-x64-msvc@15.5.18': resolution: {integrity: sha512-LIu5me6QTANCd25E7I5uIEfvgQ06RK7tvHAbYo3zCb3VpxQEPvMcSpd87NwUABDT6MbGPdEGR5VRiK4PPTJhQg==} engines: {node: '>= 10'} @@ -1039,6 +1094,9 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -1285,6 +1343,10 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + c12@3.1.0: resolution: {integrity: sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==} peerDependencies: @@ -1788,6 +1850,27 @@ packages: nodemailer: optional: true + next@15.3.9: + resolution: {integrity: sha512-bat50ogkh2esjfkbqmVocL5QunR9RGCSO2oQKFjKeDcEylIgw3JY6CMfGnzoVfXJ9SDLHI546sHmsk90D2ivwQ==} + engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.41.2 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + next@15.5.18: resolution: {integrity: sha512-eKL8zUJkX9Y5lE+RX/2YJoItVdGlIscyVyboeD9wSpp0PaGqjoA4tTpT2qPqz9ax+5IzGESyLSeZ/RCwbSZ2uQ==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} @@ -2193,6 +2276,10 @@ packages: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} + streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -2976,33 +3063,59 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@next/env@15.3.9': {} + '@next/env@15.5.18': {} '@next/eslint-plugin-next@15.5.18': dependencies: fast-glob: 3.3.1 + '@next/swc-darwin-arm64@15.3.5': + optional: true + '@next/swc-darwin-arm64@15.5.18': optional: true + '@next/swc-darwin-x64@15.3.5': + optional: true + '@next/swc-darwin-x64@15.5.18': optional: true + '@next/swc-linux-arm64-gnu@15.3.5': + optional: true + '@next/swc-linux-arm64-gnu@15.5.18': optional: true + '@next/swc-linux-arm64-musl@15.3.5': + optional: true + '@next/swc-linux-arm64-musl@15.5.18': optional: true + '@next/swc-linux-x64-gnu@15.3.5': + optional: true + '@next/swc-linux-x64-gnu@15.5.18': optional: true + '@next/swc-linux-x64-musl@15.3.5': + optional: true + '@next/swc-linux-x64-musl@15.5.18': optional: true + '@next/swc-win32-arm64-msvc@15.3.5': + optional: true + '@next/swc-win32-arm64-msvc@15.5.18': optional: true + '@next/swc-win32-x64-msvc@15.3.5': + optional: true + '@next/swc-win32-x64-msvc@15.5.18': optional: true @@ -3113,6 +3226,8 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@swc/counter@0.1.3': {} + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -3362,6 +3477,10 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + c12@3.1.0: dependencies: chokidar: 4.0.3 @@ -3832,12 +3951,38 @@ snapshots: natural-compare@1.4.0: {} - next-auth@5.0.0-beta.25(next@15.5.18(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6): + next-auth@5.0.0-beta.25(next@15.3.9(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6): dependencies: '@auth/core': 0.37.2 - next: 15.5.18(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + next: 15.3.9(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) react: 19.2.6 + next@15.3.9(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): + dependencies: + '@next/env': 15.3.9 + '@swc/counter': 0.1.3 + '@swc/helpers': 0.5.15 + busboy: 1.6.0 + caniuse-lite: 1.0.30001792 + postcss: 8.4.31 + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + styled-jsx: 5.1.6(react@19.2.6) + optionalDependencies: + '@next/swc-darwin-arm64': 15.3.5 + '@next/swc-darwin-x64': 15.3.5 + '@next/swc-linux-arm64-gnu': 15.3.5 + '@next/swc-linux-arm64-musl': 15.3.5 + '@next/swc-linux-x64-gnu': 15.3.5 + '@next/swc-linux-x64-musl': 15.3.5 + '@next/swc-win32-arm64-msvc': 15.3.5 + '@next/swc-win32-x64-msvc': 15.3.5 + '@playwright/test': 1.60.0 + sharp: 0.34.5 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + next@15.5.18(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: '@next/env': 15.5.18 @@ -4184,6 +4329,8 @@ snapshots: split2@4.2.0: {} + streamsearch@1.1.0: {} + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 diff --git a/turbo.json b/turbo.json index e911b7f..184507a 100644 --- a/turbo.json +++ b/turbo.json @@ -2,7 +2,6 @@ "$schema": "https://turbo.build/schema.json", "globalDependencies": [".env"], "globalEnv": [ - "NODE_ENV", "DATABASE_URL", "AUTH_SECRET", "AUTH_DEV_AUTOLOGIN",