first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:46:42 +03:00
commit 2a5b661443
202 changed files with 49770 additions and 0 deletions

105
frontend/lib/api-proxy.ts Normal file
View File

@@ -0,0 +1,105 @@
import { NextRequest, NextResponse } from "next/server"
import { optimizeImage } from "./image-optimizer"
import { getToken } from "next-auth/jwt"
const API_URL = (process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080") + "/api/v1"
export async function handleImageProxyRequest(req: NextRequest, targetEndpoint: string) {
try {
const formData = await req.formData()
const newFormData = new FormData()
// Process fields
// We need to iterate twice: first to collect all config fields, then to process files
const configMap = new Map<string, string>()
for (const [key, value] of formData.entries()) {
if (typeof value === "string") {
configMap.set(key, value)
}
}
for (const [key, value] of formData.entries()) {
if (value instanceof File && value.size > 0) {
// Determine configuration for this file
let width = 0
let height = 0
let quality = 80
let format = "avif"
// Heuristic 1: "image" field maps to root "width", "height", etc.
if (key === "image") {
width = Number(configMap.get("width")) || 0
height = Number(configMap.get("height")) || 0
quality = Number(configMap.get("quality")) || 80
format = configMap.get("format") || "avif"
}
// Heuristic 2: "[prefix]_logo" maps to "[prefix]_width", etc.
else if (key.endsWith("_logo")) {
const prefix = key.replace("_logo", "")
width = Number(configMap.get(`${prefix}_width`)) || 0
height = Number(configMap.get(`${prefix}_height`)) || 0
quality = Number(configMap.get(`${prefix}_quality`)) || 80
format = configMap.get(`${prefix}_format`) || "avif"
}
// If any config is found (or defaults for "image"), optimize
if (key === "image" || key.endsWith("_logo")) {
const buffer = Buffer.from(await value.arrayBuffer())
const { buffer: processedBuffer, contentType, filename } = await optimizeImage(buffer, {
width,
height,
quality,
format,
})
// Create Blob from Buffer
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const blob = new Blob([processedBuffer as any], { type: contentType })
newFormData.append(key, blob, filename)
} else {
// Just forward other files as is
newFormData.append(key, value)
}
} else {
newFormData.append(key, value)
}
}
// Get Auth Token (Server-side)
// NextAuth's getSession might not work in API routes depending on setup,
// getToken is more reliable for middleware/API routes.
const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET })
const headers: HeadersInit = {}
if (token && token.accessToken) {
headers["Authorization"] = `Bearer ${token.accessToken}`
}
// Determine method (POST or PUT)
const method = req.method
const targetUrl = `${API_URL}${targetEndpoint}`
const response = await fetch(targetUrl, {
method: method,
headers: headers,
body: newFormData,
})
const data = await response.json()
if (!response.ok) {
return NextResponse.json(data, { status: response.status })
}
return NextResponse.json(data)
} catch (error: unknown) {
console.error("Proxy Error:", error)
const errorMessage = error instanceof Error ? error.message : "Internal Server Error"
return NextResponse.json(
{ error: errorMessage },
{ status: 500 }
)
}
}