TorbatYar/frontend/app/api/crm/[...path]/route.ts
Mortezakoohjani e140908034 Ship enterprise CRM frontend with real API wiring and thin app routes.
Connect all CRM pages to the BFF and CRM service, add module docs, and mark CRM available in the SuperApp catalog.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 20:58:17 +03:30

97 lines
2.4 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
/**
* Same-origin BFF proxy → CRM service.
* Browser calls /api/crm/* so TLS/CORS/DNS issues
* do not block CRUD from the SuperApp origin.
*/
const UPSTREAM =
process.env.CRM_SERVICE_URL ||
process.env.NEXT_PUBLIC_CRM_API_URL ||
"http://localhost:8003";
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: "crm_proxy_error",
message: `پروکسی CRM به ${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);
}