perf(api,web,db): refactor and optimize for enterprise readiness

- Add missing @@index([userId]) on Account and Session models (auth query perf)
- Batch holiday-auto-import to eliminate N+1 query pattern (O(n) → O(1))
- Reduce SessionProvider refetchInterval from 5min to 15min
- Fix Cache-Control catch-all to stop blocking static asset caching
- Decompose assistant-tools.ts (2,562 → 809 lines) into callers, helpers, access-control modules
- Add @next/bundle-analyzer for data-driven bundle optimization
- Add @react-pdf/renderer to optimizePackageImports
- Add safety caps (take limits) on unbounded findMany queries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-11 22:34:41 +02:00
parent b3da8817dc
commit dd2c9c0f88
12 changed files with 2273 additions and 1920 deletions
+15 -3
View File
@@ -7,7 +7,13 @@ const nextConfig: NextConfig = {
outputFileTracingRoot: path.resolve(__dirname, "../.."),
devIndicators: false,
experimental: {
optimizePackageImports: ["recharts", "date-fns", "framer-motion", "@capakraken/shared"],
optimizePackageImports: [
"recharts",
"date-fns",
"framer-motion",
"@capakraken/shared",
"@react-pdf/renderer",
],
},
transpilePackages: [
"@capakraken/api",
@@ -60,8 +66,8 @@ const nextConfig: NextConfig = {
],
},
{
// Catch-all for error pages and any remaining routes
source: "/:path*",
// Catch-all for error pages and remaining routes (exclude static assets)
source: "/((?!_next/static|_next/image|favicon.ico).*)",
headers: [
{ key: "Cache-Control", value: "no-store, no-cache, must-revalidate" },
{ key: "Pragma", value: "no-cache" },
@@ -88,7 +94,13 @@ const nextConfig: NextConfig = {
// Only wrap with Sentry in production — the worker.js crash in dev mode
// (vendor-chunks/lib/worker.js MODULE_NOT_FOUND) makes the dev server unstable
// Sentry only in production — dynamic import avoids side effects in dev
// Bundle analyzer — run with ANALYZE=true to inspect client/server chunks
let exportedConfig: NextConfig = nextConfig;
if (process.env.ANALYZE === "true") {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const withBundleAnalyzer = require("@next/bundle-analyzer")({ enabled: true });
exportedConfig = withBundleAnalyzer(exportedConfig);
}
if (process.env.NODE_ENV === "production") {
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports