next-sanity
Version:
Sanity.io toolkit for Next.js
91 lines (90 loc) • 3.06 kB
JavaScript
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