58 lines
2 KiB
TypeScript
58 lines
2 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { createCart, getCart } from "@/lib/medusa";
|
|
import { headers } from "next/headers";
|
|
import { createRateLimiter, getClientIp } from "@/lib/rateLimit";
|
|
import { isNonEmptyString, checkCsrf, isValidMedusaId, badRequest } from "@/lib/apiUtils";
|
|
import { getAuthToken } from "@/lib/auth";
|
|
|
|
// 10 cart creations per IP per 15 minutes
|
|
const limiter = createRateLimiter({ windowMs: 15 * 60 * 1000, maxRequests: 10 });
|
|
|
|
// POST /api/cart — create a new cart
|
|
export async function POST() {
|
|
const csrfError = await checkCsrf();
|
|
if (csrfError) return csrfError;
|
|
|
|
const hdrs = await headers();
|
|
const ip = getClientIp(hdrs);
|
|
const limit = limiter.check(`cart:${ip}`);
|
|
if (!limit.allowed) {
|
|
return NextResponse.json(
|
|
{ error: "Too many requests. Please try again later." },
|
|
{ status: 429, headers: { "Retry-After": String(Math.ceil(limit.retryAfterMs / 1000)) } },
|
|
);
|
|
}
|
|
|
|
// Pass auth token so Medusa associates the cart with the logged-in customer
|
|
const authToken = (await getAuthToken()) ?? undefined;
|
|
|
|
try {
|
|
const cart = await createCart(authToken);
|
|
return NextResponse.json(cart);
|
|
} catch (e) {
|
|
console.error("[cart:create]", (e as Error).message);
|
|
return NextResponse.json({ error: "Failed to create cart" }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
// GET /api/cart?id=cart_xxx — fetch an existing cart
|
|
export async function GET(request: Request) {
|
|
const { searchParams } = new URL(request.url);
|
|
const id = searchParams.get("id");
|
|
if (!isNonEmptyString(id)) {
|
|
return badRequest("Missing cart id");
|
|
}
|
|
if (!isValidMedusaId(id)) {
|
|
return badRequest("Invalid cart ID format");
|
|
}
|
|
try {
|
|
const cart = await getCart(id);
|
|
if (!cart) {
|
|
return NextResponse.json({ error: "Cart not found" }, { status: 404 });
|
|
}
|
|
return NextResponse.json(cart);
|
|
} catch (e) {
|
|
console.error("[cart:get]", (e as Error).message);
|
|
return NextResponse.json({ error: "Failed to fetch cart" }, { status: 500 });
|
|
}
|
|
}
|