Skip to content

Commit

Permalink
feat(next-drupal)!: add draft mode to pages router
Browse files Browse the repository at this point in the history
Issue #502

BREAKING CHANGE:
The options to the DrupalClient.preview() method were previously ignored. The
options are now passed to the NextApiResponse.setDraftMode() method and their
TypeScript definition have now changed to match the options parameter of the
setDraftMode method.
  • Loading branch information
JohnAlbin committed Jan 30, 2024
1 parent 0b2f311 commit a4f8d84
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 29 deletions.
74 changes: 52 additions & 22 deletions packages/next-drupal/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import type {
Locale,
PathAlias,
PathPrefix,
PreviewOptions,
} from "./types"

const DEFAULT_API_PREFIX = "/jsonapi"
Expand Down Expand Up @@ -1082,56 +1081,87 @@ export class DrupalClient {
async preview(
request: NextApiRequest,
response: NextApiResponse,
options?: PreviewOptions
options?: Parameters<NextApiResponse["setDraftMode"]>[0]
) {
const { slug, resourceVersion, plugin } = request.query
const { slug, resourceVersion, plugin, secret, scope, ...draftData } =
request.query
const useDraftMode = options?.enable

try {
// Always clear preview data to handle different scopes.
response.clearPreviewData()

// Validate the preview url.
const result = await this.validateDraftUrl(
new URL(request.url).searchParams
new URL(request.url, `http://${request.headers.host}`).searchParams
)

const validationPayload = await result.json()
const previewData = {
resourceVersion,
plugin,
...validationPayload,
}

if (!result.ok) {
this.debug(`Draft url validation error: ${validationPayload.message}`)
response.statusCode = result.status

return response.json(await result.json())
return response.json(validationPayload)
}

const validationPayload = await result.json()
// Optionally turn on draft mode.
if (useDraftMode) {
response.setDraftMode(options)
}

response.setPreviewData({
resourceVersion,
plugin,
...validationPayload,
})
// Turns on preview mode and adds preview data to Next.js' static context.
response.setPreviewData(previewData)

// Fix issue with cookie.
// See https://github.com/vercel/next.js/discussions/32238.
// See https://github.com/vercel/next.js/blob/d895a50abbc8f91726daa2d7ebc22c58f58aabbb/packages/next/server/api-utils/node.ts#L504.
if (this.forceIframeSameSiteCookie) {
const previous = response.getHeader("Set-Cookie") as string[]
previous.forEach((cookie, index) => {
previous[index] = cookie.replace(
"SameSite=Lax",
"SameSite=None;Secure"
)
})
response.setHeader(`Set-Cookie`, previous)
const cookies = (response.getHeader("Set-Cookie") as string[]).map(
(cookie) => cookie.replace("SameSite=Lax", "SameSite=None; Secure")
)
if (useDraftMode) {
// Adds preview data for use in app router pages.
cookies.push(
`${DRAFT_DATA_COOKIE_NAME}=${encodeURIComponent(
JSON.stringify({ slug, resourceVersion, ...draftData })
)}; Path=/; HttpOnly; SameSite=None; Secure`
)
}
response.setHeader("Set-Cookie", cookies)

// We can safely redirect to the slug since this has been validated on the server.
// We can safely redirect to the slug since this has been validated on the
// server.
response.writeHead(307, { Location: slug })

this.debug(`${useDraftMode ? "Draft" : "Preview"} mode enabled.`)

return response.end()
} catch (error) {
this.debug(`Preview failed: ${error.message}`)
return response.status(422).end()
}
}

async previewDisable(request: NextApiRequest, response: NextApiResponse) {
// Disable both preview and draft modes.
response.clearPreviewData()
response.setDraftMode({ enable: false })

// Delete the draft data cookie.
const cookies = response.getHeader("Set-Cookie") as string[]
cookies.push(
`${DRAFT_DATA_COOKIE_NAME}=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; SameSite=None; Secure`
)
response.setHeader("Set-Cookie", cookies)

response.writeHead(307, { Location: "/" })
response.end()
}

async getMenu<T = DrupalMenuLinkContent>(
name: string,
options?: JsonApiWithLocaleOptions &
Expand Down
7 changes: 0 additions & 7 deletions packages/next-drupal/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,13 +410,6 @@ export interface JsonApiResourceWithPath extends JsonApiResource {
path: PathAlias
}

export interface PreviewOptions {
errorMessages?: {
secret?: string
slug?: string
}
}

export type GetResourcePreviewUrlOptions = JsonApiWithLocaleOptions & {
isVersionable?: boolean
}
Expand Down

0 comments on commit a4f8d84

Please sign in to comment.