Rocky_Mountain_Vending/app/api/ebay/search/route.ts

120 lines
3 KiB
TypeScript

import { NextResponse } from "next/server"
import { fetchQuery } from "convex/nextjs"
import { api } from "@/convex/_generated/api"
import { hasConvexUrl } from "@/lib/convex-config"
import {
filterTrustedEbayListings,
rankListingsForQuery,
type CachedEbayListing,
type EbayCacheState,
} from "@/lib/ebay-parts-match"
type CacheSource = "convex" | "fallback"
function getDisabledCacheState(message: string): EbayCacheState {
return {
key: "manual-parts",
status: "disabled",
lastSuccessfulAt: null,
lastAttemptAt: null,
nextEligibleAt: null,
lastError: message,
consecutiveFailures: 0,
queryCount: 0,
itemCount: 0,
sourceQueries: [],
freshnessMs: null,
isStale: true,
listingCount: 0,
activeListingCount: 0,
message,
}
}
function getErrorCacheState(message: string): EbayCacheState {
const now = Date.now()
return {
key: "manual-parts",
status: "error",
lastSuccessfulAt: null,
lastAttemptAt: now,
nextEligibleAt: null,
lastError: message,
consecutiveFailures: 1,
queryCount: 0,
itemCount: 0,
sourceQueries: [],
freshnessMs: null,
isStale: true,
listingCount: 0,
activeListingCount: 0,
message,
}
}
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const keywords = searchParams.get("keywords")?.trim() || ""
const maxResults = Math.min(
Math.max(Number.parseInt(searchParams.get("maxResults") || "6", 10) || 6, 1),
20
)
if (!keywords) {
return NextResponse.json(
{ error: "Keywords parameter is required" },
{ status: 400 }
)
}
if (!hasConvexUrl()) {
const message =
"Cached eBay backend is disabled because NEXT_PUBLIC_CONVEX_URL is not configured."
return NextResponse.json({
query: keywords,
results: [],
cache: getDisabledCacheState(message),
cacheSource: "fallback" satisfies CacheSource,
error: message,
})
}
try {
const [overview, listings] = await Promise.all([
fetchQuery(api.ebay.getCacheOverview, {}),
fetchQuery(api.ebay.listCachedListings, { limit: 200 }),
])
const trustedListings = filterTrustedEbayListings(
listings as CachedEbayListing[]
)
const ranked = rankListingsForQuery(
keywords,
trustedListings,
maxResults
)
return NextResponse.json({
query: keywords,
results: ranked,
cache: overview,
cacheSource: "convex" satisfies CacheSource,
})
} catch (error) {
console.error("Failed to load cached eBay listings:", error)
const message =
error instanceof Error
? `Cached eBay listings are unavailable: ${error.message}`
: "Cached eBay listings are unavailable."
return NextResponse.json(
{
query: keywords,
results: [],
cache: getErrorCacheState(message),
cacheSource: "fallback" satisfies CacheSource,
error: message,
},
{ status: 200 }
)
}
}