import { cookie as prismicCookie, type Client, type LinkResolverFunction } from "@prismicio/client" import type { NextRequestLike } from "./types" export type RedirectToPreviewURLConfig = { /** The Prismic client configured for the preview session's repository. */ // `Pick` is used to use the smallest possible subset of // `prismic.Client`. Doing this reduces the surface area for breaking // type changes. client: Pick /** * The `request` object from a Next.js Route Handler. * * @see Next.js Route Handler docs: \ */ request: NextRequestLike /** * A Link Resolver used to resolve the previewed document's URL. * * @see To learn more about Link Resolver: {@link https://prismic.io/docs/core-concepts/link-resolver-route-resolver} */ linkResolver?: LinkResolverFunction /** * The default redirect URL if a URL cannot be determined for the previewed document. * * **Note**: If you `next.config.js` file contains a `basePath`, the `defaultURL` option must * _not_ include it. Instead, provide the `basePath` property using the `basePath` option. */ defaultURL?: string } export async function redirectToPreviewURL(config: RedirectToPreviewURLConfig): Promise { const { client, request, linkResolver, defaultURL = "/" } = config // Need this to avoid the following Next.js build-time error: // You're importing a component that needs next/headers. That only works // in a Server Component which is not supported in the pages/ directory. const { cookies, draftMode } = await import("next/headers") // Dynamic so Node.js can load this module: the bare specifier (kept by // tsdown.config.ts for Next.js's server alias) is not resolvable by Node.js. const { redirect } = await import("next/navigation") const documentID = request.nextUrl.searchParams.get("documentId") ?? undefined // Set the initial preview cookie. Setting the cookie here is necessary // to support unpublished previews. Without setting it here, the page // will try to render without the preview cookie, leading to a // PrismicNotFound error. const cookieJar = await cookies() const previewToken = request.nextUrl.searchParams.get("token") ?? undefined if (previewToken) { cookieJar.set(prismicCookie.preview, previewToken, { sameSite: "none", secure: true }) } const previewURL = await client.resolvePreviewURL({ documentID, previewToken, defaultURL, linkResolver, }) ;(await draftMode()).enable() // Next.js uses `SameSite=Lax` in development, which cross-site iframes drop. cookieJar.set({ ...cookieJar.get("__prerender_bypass")!, httpOnly: true, sameSite: "none", secure: true, }) return redirect(previewURL) }