TorbatYar/frontend/app/api/accounting/[...path]/route.ts
Mortezakoohjani 7d66932da8 Complete Accounting sidebar modules with ops CRUD, BFF proxy, and treasury APIs.
Wire nested nav pages for phases 5.1-5.11 to real list/create endpoints, fix COA import connectivity via same-origin proxy, and add operational migration.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 16:10:06 +03:30

97 lines
2.5 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
/**
* Same-origin BFF proxy → accounting service.
* Browser calls /api/accounting/* so TLS/CORS/DNS issues to accounting.torbatyar.ir
* do not block setup / CRUD from the SuperApp origin.
*/
const UPSTREAM =
process.env.ACCOUNTING_SERVICE_URL ||
process.env.NEXT_PUBLIC_ACCOUNTING_API_URL ||
"http://localhost:8002";
async function proxy(req: NextRequest, pathSegments: string[]) {
const path = pathSegments.join("/");
const url = new URL(req.url);
const target = `${UPSTREAM.replace(/\/$/, "")}/${path}${url.search}`;
const headers = new Headers();
const pass = ["authorization", "content-type", "x-tenant-id", "accept"];
for (const h of pass) {
const v = req.headers.get(h);
if (v) headers.set(h, v);
}
let body: ArrayBuffer | undefined;
if (req.method !== "GET" && req.method !== "HEAD") {
body = await req.arrayBuffer();
}
try {
const res = await fetch(target, {
method: req.method,
headers,
body,
cache: "no-store",
});
const outHeaders = new Headers();
const ct = res.headers.get("content-type");
if (ct) outHeaders.set("content-type", ct);
return new NextResponse(await res.arrayBuffer(), {
status: res.status,
headers: outHeaders,
});
} catch (err) {
const detail = err instanceof Error ? err.message : "upstream_unreachable";
return NextResponse.json(
{
error: {
code: "accounting_proxy_error",
message: `پروکسی حسابداری به ${UPSTREAM} وصل نشد — ${detail}`,
},
},
{ status: 502 }
);
}
}
export async function GET(
req: NextRequest,
ctx: { params: Promise<{ path: string[] }> }
) {
const { path } = await ctx.params;
return proxy(req, path);
}
export async function POST(
req: NextRequest,
ctx: { params: Promise<{ path: string[] }> }
) {
const { path } = await ctx.params;
return proxy(req, path);
}
export async function PATCH(
req: NextRequest,
ctx: { params: Promise<{ path: string[] }> }
) {
const { path } = await ctx.params;
return proxy(req, path);
}
export async function PUT(
req: NextRequest,
ctx: { params: Promise<{ path: string[] }> }
) {
const { path } = await ctx.params;
return proxy(req, path);
}
export async function DELETE(
req: NextRequest,
ctx: { params: Promise<{ path: string[] }> }
) {
const { path } = await ctx.params;
return proxy(req, path);
}