diff --git a/src/app/api/compare/route.ts b/src/app/api/compare/route.ts index 9d4328a..3001256 100644 --- a/src/app/api/compare/route.ts +++ b/src/app/api/compare/route.ts @@ -18,6 +18,10 @@ function slugify(text: string): string { .slice(0, 200); } +// TODO: Implement rate limiting per IP/user +// Example: Use Upstash Ratelimit or a simple in-memory counter +// const ratelimit = new Ratelimit({ redis, limiter: slidingWindow(5, "1m") }) + export async function POST(request: Request) { const body: { query?: string; items?: string[]; dimensions?: string[] } = await request.json(); @@ -25,7 +29,21 @@ export async function POST(request: Request) { if (!items || items.length < 2) { return Response.json( - { error: "At least 2 items are required" }, + { error: "At least 2 items are required for comparison" }, + { status: 400 } + ); + } + + if (items.length > 10) { + return Response.json( + { error: "Maximum 10 items allowed per comparison" }, + { status: 400 } + ); + } + + if (items.some((item) => item.trim().length === 0)) { + return Response.json( + { error: "Item names cannot be empty" }, { status: 400 } ); } @@ -70,6 +88,20 @@ export async function POST(request: Request) { ); } + if (progress.stage === "searching") { + controller.enqueue( + encoder.encode( + serializeSSE("progress", { + status: "researching", + message: `Searching the web for ${progress.item}... (${progress.results} results found)`, + itemsCompleted, + totalItems: items.length, + currentStep: `Searching ${progress.item}`, + }) + ) + ); + } + if (progress.stage === "researching") { itemsCompleted++; controller.enqueue( @@ -102,7 +134,17 @@ export async function POST(request: Request) { if (progress.stage === "complete") { const result = progress.result; - const comparisonData: Omit = { + const comparisonData: Omit< + ComparisonData, + | "id" + | "userId" + | "slug" + | "tags" + | "isPublic" + | "viewCount" + | "createdAt" + | "updatedAt" + > = { title, query: query || "", status: "completed", @@ -177,7 +219,7 @@ export async function POST(request: Request) { encoder.encode( serializeSSE("progress", { status: "failed", - message: progress.error, + message: `Comparison failed: ${progress.error}`, itemsCompleted, totalItems: items.length, currentStep: "Failed", @@ -192,11 +234,16 @@ export async function POST(request: Request) { .set({ status: "failed", updatedAt: new Date() }) .where(eq(comparisons.id, id)); + const message = + error instanceof Error + ? error.message + : "An unexpected error occurred during research"; + controller.enqueue( encoder.encode( serializeSSE("progress", { status: "failed", - message: error instanceof Error ? error.message : "Unknown error", + message: `Comparison failed: ${message}`, itemsCompleted, totalItems: items.length, currentStep: "Failed",