feat: improve compare API route with searching stage and validation
This commit is contained in:
@@ -18,6 +18,10 @@ function slugify(text: string): string {
|
|||||||
.slice(0, 200);
|
.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) {
|
export async function POST(request: Request) {
|
||||||
const body: { query?: string; items?: string[]; dimensions?: string[] } =
|
const body: { query?: string; items?: string[]; dimensions?: string[] } =
|
||||||
await request.json();
|
await request.json();
|
||||||
@@ -25,7 +29,21 @@ export async function POST(request: Request) {
|
|||||||
|
|
||||||
if (!items || items.length < 2) {
|
if (!items || items.length < 2) {
|
||||||
return Response.json(
|
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 }
|
{ 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") {
|
if (progress.stage === "researching") {
|
||||||
itemsCompleted++;
|
itemsCompleted++;
|
||||||
controller.enqueue(
|
controller.enqueue(
|
||||||
@@ -102,7 +134,17 @@ export async function POST(request: Request) {
|
|||||||
if (progress.stage === "complete") {
|
if (progress.stage === "complete") {
|
||||||
const result = progress.result;
|
const result = progress.result;
|
||||||
|
|
||||||
const comparisonData: Omit<ComparisonData, "id" | "userId" | "slug" | "tags" | "isPublic" | "viewCount" | "createdAt" | "updatedAt"> = {
|
const comparisonData: Omit<
|
||||||
|
ComparisonData,
|
||||||
|
| "id"
|
||||||
|
| "userId"
|
||||||
|
| "slug"
|
||||||
|
| "tags"
|
||||||
|
| "isPublic"
|
||||||
|
| "viewCount"
|
||||||
|
| "createdAt"
|
||||||
|
| "updatedAt"
|
||||||
|
> = {
|
||||||
title,
|
title,
|
||||||
query: query || "",
|
query: query || "",
|
||||||
status: "completed",
|
status: "completed",
|
||||||
@@ -177,7 +219,7 @@ export async function POST(request: Request) {
|
|||||||
encoder.encode(
|
encoder.encode(
|
||||||
serializeSSE("progress", {
|
serializeSSE("progress", {
|
||||||
status: "failed",
|
status: "failed",
|
||||||
message: progress.error,
|
message: `Comparison failed: ${progress.error}`,
|
||||||
itemsCompleted,
|
itemsCompleted,
|
||||||
totalItems: items.length,
|
totalItems: items.length,
|
||||||
currentStep: "Failed",
|
currentStep: "Failed",
|
||||||
@@ -192,11 +234,16 @@ export async function POST(request: Request) {
|
|||||||
.set({ status: "failed", updatedAt: new Date() })
|
.set({ status: "failed", updatedAt: new Date() })
|
||||||
.where(eq(comparisons.id, id));
|
.where(eq(comparisons.id, id));
|
||||||
|
|
||||||
|
const message =
|
||||||
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "An unexpected error occurred during research";
|
||||||
|
|
||||||
controller.enqueue(
|
controller.enqueue(
|
||||||
encoder.encode(
|
encoder.encode(
|
||||||
serializeSSE("progress", {
|
serializeSSE("progress", {
|
||||||
status: "failed",
|
status: "failed",
|
||||||
message: error instanceof Error ? error.message : "Unknown error",
|
message: `Comparison failed: ${message}`,
|
||||||
itemsCompleted,
|
itemsCompleted,
|
||||||
totalItems: items.length,
|
totalItems: items.length,
|
||||||
currentStep: "Failed",
|
currentStep: "Failed",
|
||||||
|
|||||||
Reference in New Issue
Block a user