fix: comprehensive TypeScript/build fixes and modernization

- Update tsconfig to ES2024 target and bundler moduleResolution
- Add dynamic imports for chart.js and recharts (bundle optimization)
- Consolidate 17 useState into useReducer in sessions page
- Fix 18 .js extension imports across lib files
- Add type declarations for @rapideditor/country-coder
- Fix platform user types (PlatformUserRole enum)
- Fix Calendar component prop types
- Centralize next-auth type augmentation
- Add force-dynamic to all API routes (prevent build-time prerender)
- Fix Prisma JSON null handling with Prisma.DbNull
- Fix various type mismatches (SessionMessage, ImportRecord, etc.)
- Export ButtonProps from button component
- Update next-themes import path
- Replace JSX.Element with React.ReactElement
- Remove obsolete debug scripts and pnpm lockfile
- Downgrade eslint to v8 for next compatibility
This commit is contained in:
2026-01-20 07:28:10 +01:00
parent 8b3846539f
commit 5bfd762e55
161 changed files with 14655 additions and 11682 deletions

View File

@@ -2,6 +2,8 @@
import { type NextRequest, NextResponse } from "next/server";
import { checkDatabaseConnection, prisma } from "@/lib/prisma";
export const dynamic = "force-dynamic";
export async function GET(request: NextRequest) {
try {
// Check if user has admin access (you may want to add proper auth here)
@@ -36,7 +38,7 @@ export async function GET(request: NextRequest) {
// Count recent AI requests
prisma.aIProcessingRequest.count({
where: {
createdAt: {
requestedAt: {
gte: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24 hours
},
},

View File

@@ -3,6 +3,8 @@ import { fetchAndParseCsv } from "../../../../lib/csvFetcher";
import { processQueuedImports } from "../../../../lib/importProcessor";
import { prisma } from "../../../../lib/prisma";
export const dynamic = "force-dynamic";
export async function POST(request: NextRequest) {
try {
const body = await request.json();

View File

@@ -4,7 +4,9 @@ import { getServerSession } from "next-auth";
import { authOptions } from "../../../../lib/auth";
import { prisma } from "../../../../lib/prisma";
import { processUnprocessedSessions } from "../../../../lib/processingScheduler";
import { ProcessingStatusManager } from "../../../../lib/processingStatusManager";
import { getSessionsNeedingProcessing } from "../../../../lib/processingStatusManager";
export const dynamic = "force-dynamic";
interface SessionUser {
email: string;
@@ -65,11 +67,10 @@ export async function POST(request: NextRequest) {
: 5;
// Check how many sessions need AI processing using the new status system
const sessionsNeedingAI =
await ProcessingStatusManager.getSessionsNeedingProcessing(
ProcessingStage.AI_ANALYSIS,
1000 // Get count only
);
const sessionsNeedingAI = await getSessionsNeedingProcessing(
ProcessingStage.AI_ANALYSIS,
1000 // Get count only
);
// Filter to sessions for this company
const companySessionsNeedingAI = sessionsNeedingAI.filter(

View File

@@ -1,6 +1,9 @@
import NextAuth from "next-auth";
import { authOptions } from "../../../../lib/auth";
// Prevent static generation - this route needs runtime env vars
export const dynamic = "force-dynamic";
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

View File

@@ -3,6 +3,8 @@ import { getServerSession } from "next-auth";
import { authOptions } from "../../../../lib/auth";
import { prisma } from "../../../../lib/prisma";
export const dynamic = "force-dynamic";
export async function GET(_request: NextRequest) {
const session = await getServerSession(authOptions);
if (!session?.user) {

View File

@@ -5,6 +5,8 @@ import { sessionMetrics } from "../../../../lib/metrics";
import { prisma } from "../../../../lib/prisma";
import type { ChatSession } from "../../../../lib/types";
export const dynamic = "force-dynamic";
interface SessionUser {
email: string;
name?: string;

View File

@@ -3,6 +3,8 @@ import { getServerSession } from "next-auth/next";
import { authOptions } from "../../../../lib/auth";
import { prisma } from "../../../../lib/prisma";
export const dynamic = "force-dynamic";
export async function GET(_request: NextRequest) {
const authSession = await getServerSession(authOptions);

View File

@@ -2,6 +2,8 @@ import { type NextRequest, NextResponse } from "next/server";
import { prisma } from "../../../../../lib/prisma";
import type { ChatSession } from "../../../../../lib/types";
export const dynamic = "force-dynamic";
export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ id: string }> }

View File

@@ -1,10 +1,12 @@
import type { Prisma } from "@prisma/client";
import type { Prisma, SessionCategory } from "@prisma/client";
import { type NextRequest, NextResponse } from "next/server";
import { getServerSession } from "next-auth/next";
import { authOptions } from "../../../../lib/auth";
import { prisma } from "../../../../lib/prisma";
import type { ChatSession } from "../../../../lib/types";
export const dynamic = "force-dynamic";
export async function GET(request: NextRequest) {
const authSession = await getServerSession(authOptions);
@@ -44,7 +46,7 @@ export async function GET(request: NextRequest) {
// Category Filter
if (category && category.trim() !== "") {
// Cast to SessionCategory enum if it's a valid value
whereClause.category = category;
whereClause.category = category as SessionCategory;
}
// Language Filter

View File

@@ -3,6 +3,8 @@ import { getServerSession } from "next-auth";
import { authOptions } from "../../../../lib/auth";
import { prisma } from "../../../../lib/prisma";
export const dynamic = "force-dynamic";
export async function POST(request: NextRequest) {
const session = await getServerSession(authOptions);
if (!session?.user || session.user.role !== "ADMIN") {

View File

@@ -5,6 +5,8 @@ import { getServerSession } from "next-auth";
import { authOptions } from "../../../../lib/auth";
import { prisma } from "../../../../lib/prisma";
export const dynamic = "force-dynamic";
interface UserBasicInfo {
id: string;
email: string;

View File

@@ -4,6 +4,8 @@ import { prisma } from "../../../lib/prisma";
import { sendEmail } from "../../../lib/sendEmail";
import { forgotPasswordSchema, validateInput } from "../../../lib/validation";
export const dynamic = "force-dynamic";
// In-memory rate limiting for password reset requests
const resetAttempts = new Map<string, { count: number; resetTime: number }>();

View File

@@ -4,15 +4,7 @@ import { getServerSession } from "next-auth";
import { platformAuthOptions } from "../../../../../lib/platform-auth";
import { prisma } from "../../../../../lib/prisma";
interface PlatformSession {
user: {
id?: string;
name?: string;
email?: string;
isPlatformUser?: boolean;
platformRole?: string;
};
}
export const dynamic = "force-dynamic";
// GET /api/platform/companies/[id] - Get company details
export async function GET(
@@ -20,9 +12,7 @@ export async function GET(
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = (await getServerSession(
platformAuthOptions
)) as PlatformSession | null;
const session = await getServerSession(platformAuthOptions);
if (!session?.user?.isPlatformUser) {
return NextResponse.json(

View File

@@ -4,6 +4,8 @@ import { getServerSession } from "next-auth";
import { platformAuthOptions } from "../../../../../../lib/platform-auth";
import { prisma } from "../../../../../../lib/prisma";
export const dynamic = "force-dynamic";
// POST /api/platform/companies/[id]/users - Invite user to company
export async function POST(
request: NextRequest,

View File

@@ -4,6 +4,8 @@ import { getServerSession } from "next-auth";
import { platformAuthOptions } from "../../../../lib/platform-auth";
import { prisma } from "../../../../lib/prisma";
export const dynamic = "force-dynamic";
// GET /api/platform/companies - List all companies
export async function GET(request: NextRequest) {
try {

View File

@@ -3,6 +3,8 @@ import { type NextRequest, NextResponse } from "next/server";
import { prisma } from "../../../lib/prisma";
import { registerSchema, validateInput } from "../../../lib/validation";
export const dynamic = "force-dynamic";
// In-memory rate limiting (for production, use Redis or similar)
const registrationAttempts = new Map<
string,
@@ -30,8 +32,7 @@ function checkRateLimit(ip: string): boolean {
export async function POST(request: NextRequest) {
try {
// Rate limiting check
const ip =
request.ip || request.headers.get("x-forwarded-for") || "unknown";
const ip = request.headers.get("x-forwarded-for") || "unknown";
if (!checkRateLimit(ip)) {
return NextResponse.json(
{

View File

@@ -4,6 +4,8 @@ import { type NextRequest, NextResponse } from "next/server";
import { prisma } from "../../../lib/prisma";
import { resetPasswordSchema, validateInput } from "../../../lib/validation";
export const dynamic = "force-dynamic";
export async function POST(request: NextRequest) {
try {
const body = await request.json();