// app/api/users/[id]/route.ts import { NextResponse } from "next/server"; const BE_BASE_URL = process.env.BE_BASE_URL || "http://localhost:5000"; const COOKIE_NAME = "auth_token"; // Field mapping: snake_case input -> { snake_case for data, PascalCase for fields } // Matches API metadata field_names.users mapping const FIELD_MAPPING: Record = { id: { dataKey: "id", fieldName: "ID" }, email: { dataKey: "email", fieldName: "Email" }, first_name: { dataKey: "first_name", fieldName: "FirstName" }, last_name: { dataKey: "last_name", fieldName: "LastName" }, username: { dataKey: "username", fieldName: "Username" }, phone: { dataKey: "phone", fieldName: "Phone" }, job_title: { dataKey: "job_title", fieldName: "JobTitle" }, password: { dataKey: "password", fieldName: "Password" }, temp_link: { dataKey: "temp_link", fieldName: "TempLink" }, temp_password: { dataKey: "temp_password", fieldName: "TempPassword" }, temp_expiry: { dataKey: "temp_expiry", fieldName: "TempExpiry" }, groups: { dataKey: "groups", fieldName: "Groups" }, merchants: { dataKey: "merchants", fieldName: "Merchants" }, enabled: { dataKey: "enabled", fieldName: "Enabled" }, }; /** * Transforms frontend snake_case data to backend format * with data (snake_case) and fields (PascalCase) arrays */ function transformUserUpdateData(updates: Record): { data: Record; fields: string[]; } { const data: Record = {}; const fields: string[] = []; for (const [key, value] of Object.entries(updates)) { // Skip undefined/null values if (value === undefined || value === null) { continue; } const mapping = FIELD_MAPPING[key]; if (mapping) { // Use the dataKey for the data object (snake_case) data[mapping.dataKey] = value; // Use the fieldName for the fields array (PascalCase) fields.push(mapping.fieldName); } else { // If no mapping exists, use the key as-is (for backwards compatibility) data[key] = value; // Convert snake_case to PascalCase for fields const pascalCase = key .split("_") .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(""); fields.push(pascalCase); } } return { data, fields }; } export async function PUT( request: Request, context: { params: Promise<{ id: string }> } ) { try { const { id } = await context.params; const body = await request.json(); // Transform the request body to match backend format const transformedBody = transformUserUpdateData(body); // Get the auth token from cookies const { cookies } = await import("next/headers"); const cookieStore = await cookies(); const token = cookieStore.get(COOKIE_NAME)?.value; if (!token) { return NextResponse.json( { message: "Missing Authorization header" }, { status: 401 } ); } // According to swagger: /api/v1/users/{id} const response = await fetch(`${BE_BASE_URL}/api/v1/users/${id}`, { method: "PUT", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify(transformedBody), }); const data = await response.json(); return NextResponse.json(data, { status: response.status }); } catch (err: unknown) { const errorMessage = err instanceof Error ? err.message : "Unknown error occurred"; return NextResponse.json( { message: "Internal server error", error: errorMessage }, { status: 500 } ); } } export async function DELETE( _request: Request, context: { params: Promise<{ id: string }> } ) { try { const { id } = await context.params; const { cookies } = await import("next/headers"); const cookieStore = await cookies(); const token = cookieStore.get(COOKIE_NAME)?.value; if (!token) { return NextResponse.json( { message: "Missing Authorization header" }, { status: 401 } ); } // According to swagger: /api/v1/users/{id} const response = await fetch(`${BE_BASE_URL}/api/v1/users/${id}`, { method: "DELETE", headers: { Authorization: `Bearer ${token}`, }, }); // Some backends return empty body for DELETE; handle safely let data: unknown = null; try { data = await response.json(); } catch { data = { success: response.ok }; } return NextResponse.json(data ?? { success: response.ok }, { status: response.status, }); } catch (err: unknown) { console.error("Proxy DELETE /api/v1/users/{id} error:", err); const errorMessage = err instanceof Error ? err.message : "Unknown error occurred"; return NextResponse.json( { message: "Internal server error", error: errorMessage }, { status: 500 } ); } }