From 5223e7867cc85e88f07e092c88dafeba5ecf745e Mon Sep 17 00:00:00 2001 From: Dorian Niemiec Date: Sat, 7 Sep 2024 15:49:20 +0200 Subject: [PATCH] feat: add Next.js cache revalidation webhook --- .env.example | 1 + app/api/revalidate/route.ts | 39 +++++++++++++++++++++++++++++++++++++ package-lock.json | 9 +++++++++ package.json | 1 + 4 files changed, 50 insertions(+) create mode 100644 app/api/revalidate/route.ts diff --git a/.env.example b/.env.example index 6b29935..3a53761 100644 --- a/.env.example +++ b/.env.example @@ -18,6 +18,7 @@ EMAIL_CONTACT_ADDRESS= EMAIL_CONTACT_DEST= NEXT_PUBLIC_SANITY_PROJECT_ID= +SANITY_WEBHOOK_SECRET= NEXT_PUBLIC_HCAPTCHA_SITE_KEY= HCAPTCHA_SECRET= diff --git a/app/api/revalidate/route.ts b/app/api/revalidate/route.ts new file mode 100644 index 0000000..306f9bf --- /dev/null +++ b/app/api/revalidate/route.ts @@ -0,0 +1,39 @@ +import { isValidSignature, SIGNATURE_HEADER_NAME } from "@sanity/webhook"; +import { revalidatePath } from "next/cache"; +import { NextRequest, NextResponse } from "next/server"; + +const secret = `${process.env.SANITY_WEBHOOK_SECRET}`; + +export async function POST(req: NextRequest) { + //const { body, isValidSignature } = await parseBody(req, secret); + const body = await req.json(); + const rawBody = JSON.stringify(body); + + if ( + !(await isValidSignature( + rawBody, + req.headers[SIGNATURE_HEADER_NAME], + secret.trim() + )) + ) { + return NextResponse.json({ message: "Invalid signature" }, { status: 401 }); + } + + try { + if (body._type == "blog") { + revalidatePath(`/blog/${body.slug.current}`); + revalidatePath("/blog", "page"); + revalidatePath("/blog/page/[id]", "page"); + return NextResponse.json({ + message: `Revalidated "${body._type}" with slug "${body.slug}"` + }); + } + + return NextResponse.json({ message: "No managed type" }); + } catch (err) { + return NextResponse.json( + { message: "Error revalidating" }, + { status: 500 } + ); + } +} diff --git a/package-lock.json b/package-lock.json index 183042f..d098443 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "@sanity/code-input": "^4.1.4", "@sanity/image-url": "^1.0.2", "@sanity/vision": "^3.53.0", + "@sanity/webhook": "^4.0.2-bc", "@tailwindcss/typography": "^0.5.13", "@types/bcrypt": "^5.0.2", "@types/cookie": "^0.6.0", @@ -8696,6 +8697,14 @@ } } }, + "node_modules/@sanity/webhook": { + "version": "4.0.2-bc", + "resolved": "https://registry.npmjs.org/@sanity/webhook/-/webhook-4.0.2-bc.tgz", + "integrity": "sha512-I/Qq+ppPMkdZ2lQ3iHJ1HylBkEy+imn5qCOWEJefdVIyWdYPpNmTAH09exU6K6M1HRMM7Au4oOdijx3kruZEWA==", + "engines": { + "node": ">=18.17" + } + }, "node_modules/@sentry-internal/browser-utils": { "version": "8.24.0", "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.24.0.tgz", diff --git a/package.json b/package.json index 9da7cb5..52036f3 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@sanity/code-input": "^4.1.4", "@sanity/image-url": "^1.0.2", "@sanity/vision": "^3.53.0", + "@sanity/webhook": "^4.0.2-bc", "@tailwindcss/typography": "^0.5.13", "@types/bcrypt": "^5.0.2", "@types/cookie": "^0.6.0",