From a3135a6918120ff157b4ae47a6289c890a371b14 Mon Sep 17 00:00:00 2001 From: Kenton Duprey Date: Sun, 30 Jun 2024 00:34:57 -0400 Subject: [PATCH] feat: Add API routes for disabling draft mode, enabling draft mode, and revalidating cache This commit adds three new API routes for managing draft mode and cache revalidation. The `disable-draft` route disables draft mode and redirects to the home page. The `draft` route enables draft mode and redirects to the preview URL. The `revalidate` route receives a webhook payload, validates the signature, and revalidates the cache based on the payload type. These changes enhance the functionality of the application and improve the developer experience. --- .../src/app/api/disable-draft/route.ts | 8 ++++ apps/frontend/src/app/api/draft/route.ts | 21 ++++++++++ apps/frontend/src/app/api/revalidate/route.ts | 39 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 apps/frontend/src/app/api/disable-draft/route.ts create mode 100644 apps/frontend/src/app/api/draft/route.ts create mode 100644 apps/frontend/src/app/api/revalidate/route.ts diff --git a/apps/frontend/src/app/api/disable-draft/route.ts b/apps/frontend/src/app/api/disable-draft/route.ts new file mode 100644 index 00000000..68185e6c --- /dev/null +++ b/apps/frontend/src/app/api/disable-draft/route.ts @@ -0,0 +1,8 @@ +import { SERVER_SITE_URL } from "@kduprey/config"; +import { draftMode } from "next/headers"; +import { NextResponse } from "next/server"; + +export function GET() { + draftMode().disable(); + return NextResponse.redirect(new URL("/", SERVER_SITE_URL)); +} diff --git a/apps/frontend/src/app/api/draft/route.ts b/apps/frontend/src/app/api/draft/route.ts new file mode 100644 index 00000000..9208142e --- /dev/null +++ b/apps/frontend/src/app/api/draft/route.ts @@ -0,0 +1,21 @@ +// ./app/api/draft/route.ts + +import { validatePreviewUrl } from "@sanity/preview-url-secret"; +import { draftMode } from "next/headers"; +import { redirect } from "next/navigation"; +import { client, token } from "@/sanity"; + +const clientWithToken = client.withConfig({ token }); + +export async function GET(request: Request) { + const { isValid, redirectTo = "/" } = await validatePreviewUrl( + clientWithToken, + request.url, + ); + + if (!isValid) return new Response("Invalid secret", { status: 401 }); + + draftMode().enable(); + + redirect(redirectTo); +} diff --git a/apps/frontend/src/app/api/revalidate/route.ts b/apps/frontend/src/app/api/revalidate/route.ts new file mode 100644 index 00000000..b81a9e7a --- /dev/null +++ b/apps/frontend/src/app/api/revalidate/route.ts @@ -0,0 +1,39 @@ +import { revalidateTag } from "next/cache"; +import { type NextRequest, NextResponse } from "next/server"; +import { parseBody } from "next-sanity/webhook"; + +interface WebhookPayload { + _type: string; +} + +export async function POST(req: NextRequest) { + try { + const { body, isValidSignature } = await parseBody( + req, + process.env.SANITY_REVALIDATE_SECRET, + ); + + if (!isValidSignature) { + const message = "Invalid signature"; + return new Response(JSON.stringify({ body, isValidSignature, message }), { + status: 401, + }); + } + + if (!body?._type) { + const message = "Bad Request"; + return new Response(JSON.stringify({ body, message }), { status: 400 }); + } + + // If the `_type` is `page`, then all `client.fetch` calls with + // `{next: {tags: ['page']}}` will be revalidated + revalidateTag(body._type); + + return NextResponse.json({ body }); + } catch (err) { + console.error(err); + return new Response(JSON.stringify({ message: "Internal Server Error" }), { + status: 500, + }); + } +}