@@ -6,7 +6,7 @@ import { escapePostgrestSearchValue } from "@/lib/security/sanitize";
66
77// eslint-disable-next-line @typescript-eslint/no-explicit-any
88type AnySupabase = any ;
9- import { validateOfferInput } from "@/lib/affiliates/validation" ;
9+ import { validateOfferInput , type OfferInput } from "@/lib/affiliates/validation" ;
1010
1111function parsePaginationParam (
1212 value : string | null ,
@@ -28,6 +28,18 @@ function slugify(text: string): string {
2828 return slug || "offer" ;
2929}
3030
31+ async function readJsonObject ( request : NextRequest ) {
32+ try {
33+ const body = await request . json ( ) ;
34+ if ( ! body || typeof body !== "object" || Array . isArray ( body ) ) {
35+ return null ;
36+ }
37+ return body as Record < string , unknown > ;
38+ } catch {
39+ return null ;
40+ }
41+ }
42+
3143/**
3244 * GET /api/affiliates/offers - List affiliate offers (public marketplace)
3345 */
@@ -148,8 +160,11 @@ export async function POST(request: NextRequest) {
148160 const rl = checkRateLimit ( getRateLimitIdentifier ( request , auth . user . id ) , "write" ) ;
149161 if ( ! rl . allowed ) return rateLimitExceeded ( rl ) ;
150162
151- const body = await request . json ( ) ;
152- const validation = validateOfferInput ( body ) ;
163+ const body = await readJsonObject ( request ) ;
164+ if ( ! body ) {
165+ return NextResponse . json ( { error : "Invalid JSON body" } , { status : 400 } ) ;
166+ }
167+ const validation = validateOfferInput ( body as unknown as OfferInput ) ;
153168
154169 if ( ! validation . ok ) {
155170 return NextResponse . json ( { error : validation . errors . join ( "; " ) } , { status : 400 } ) ;
0 commit comments