UNPKG

next-sanity

Version:
91 lines (90 loc) 3.06 kB
import { r as partitionedCookieName } from "../constants.js"; import { validatePreviewUrl } from "@sanity/preview-url-secret"; import { perspectiveCookieName, variantCookieName } from "@sanity/preview-url-secret/constants"; import { cookies, draftMode } from "next/headers"; import { redirect } from "next/navigation"; /** * Sets up an API route for enabling draft mode, can be paired with the `previewUrl.previewMode.enable` in `sanity/presentation`. * Can also be used with `sanity-plugin-iframe-pane`. * * When the preview loads in a cross-site iframe (Presentation Tool), draft-mode * cookies are set with the CHIPS `Partitioned` attribute so Safari 18.4+ stores * them despite third-party cookie blocking. Top-level / same-site requests keep * unpartitioned cookies so `draftMode().disable()` continues to work. * * @see https://github.com/sanity-io/sanity/issues/12806 * * @example * ```ts * // src/app/api/draft-mode/enable/route.ts * * import { defineEnableDraftMode } from "next-sanity/draft-mode"; * import { client } from "@/sanity/lib/client"; * * export const { GET } = defineEnableDraftMode({ * client: client.withConfig({ token: process.env.SANITY_API_READ_TOKEN }), * }); * ``` * * @public */ function defineEnableDraftMode(options) { const { client } = options; return { GET: async (request) => { const { isValid, redirectTo = "/", studioPreviewPerspective, studioPreviewVariant } = await validatePreviewUrl(client, request.url); if (!isValid) return new Response("Invalid secret", { status: 401 }); const draftModeStore = await draftMode(); if (!draftModeStore.isEnabled) draftModeStore.enable(); const isSecure = process.env.NODE_ENV === "production" || (options.secureDevMode ?? false); const partitioned = isSecure && request.headers.get("sec-fetch-dest") === "iframe" && request.headers.get("sec-fetch-site") === "cross-site"; const cookieStore = await cookies(); const cookie = cookieStore.get("__prerender_bypass"); cookieStore.set({ name: "__prerender_bypass", value: cookie?.value, httpOnly: true, path: "/", secure: isSecure, sameSite: isSecure ? "none" : "lax", partitioned }); if (studioPreviewPerspective) cookieStore.set({ name: perspectiveCookieName, value: studioPreviewPerspective, httpOnly: true, path: "/", secure: isSecure, sameSite: isSecure ? "none" : "lax", partitioned }); if (studioPreviewVariant) cookieStore.set({ name: variantCookieName, value: studioPreviewVariant, httpOnly: true, path: "/", secure: isSecure, sameSite: isSecure ? "none" : "lax", partitioned }); else cookieStore.delete({ name: variantCookieName, httpOnly: true, path: "/", secure: isSecure, sameSite: isSecure ? "none" : "lax", partitioned }); if (partitioned) cookieStore.set({ name: partitionedCookieName, value: "1", httpOnly: true, path: "/", secure: true, sameSite: "none", partitioned: true }); return redirect(redirectTo); } }; } export { defineEnableDraftMode }; //# sourceMappingURL=index.js.map