Files
portfolio/app/api/revalidate/route.ts
T

46 lines
1.4 KiB
TypeScript
Raw Normal View History

import { revalidateTag } from 'next/cache';
import { type NextRequest, NextResponse } from 'next/server';
/**
* POST /api/revalidate
*
* Webhook endpoint for on-demand ISR. PocketBase (or any external
* caller) sends this request after mutating CMS content so the
* relevant tag is purged from the Next.js data cache.
*
* Expected body: `{ "tag": "<collection-name>" }`
* Required header: `x-revalidate-secret: <REVALIDATE_SECRET>`
*/
export async function POST(request: NextRequest): Promise<NextResponse> {
const secret = request.headers.get('x-revalidate-secret');
if (secret !== process.env.REVALIDATE_SECRET) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
let body: unknown;
try {
body = await request.json();
} catch {
return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 });
}
if (
typeof body !== 'object' ||
body === null ||
!('tag' in body) ||
typeof (body as Record<string, unknown>).tag !== 'string'
) {
return NextResponse.json({ error: 'Missing or invalid "tag" field' }, { status: 400 });
}
const tag = (body as { tag: string }).tag;
/* Second arg is required by the Next.js 15 type signature;
* "max" means the purge propagates indefinitely — correct for
* an on-demand webhook that has no TTL of its own. */
revalidateTag(tag, 'max');
return NextResponse.json({ revalidated: true, tag }, { status: 200 });
}