chore(examples): misc improvements to the draft preview example (#10876)
There were a number of things wrong or could have been improved with the [Draft Preview Example](https://github.com/payloadcms/payload/tree/main/examples/draft-preview), namely: - The package.json was missing `"type": "modue"` which would throw ESM related import errors on startup - The preview secret was missing entirely, with pointless logic was written to throw an error if it missing in the search params as opposed to not matching the environment secret - The `/next/exit-preview` route was duplicated twice - The preview endpoint was unnecessarily querying the database for a matching document as opposed to letting the underlying page itself 404 as needed, and it was also throwing an inaccurate error message Some less critical changes were: - The page query was missing the `depth` and `limit` parameters which is best practice to optimize performance - The logic to format search params in the preview URL was unnecessarily complex - Utilities like `generatePreviewPath` and `getGlobals` were unnecessarily obfuscating simple functions - The `/preview` and `/exit-preview` routes were unecessarily nested within a `/next` page segment - Payload types weren't aliased
This commit is contained in:
@@ -61,17 +61,17 @@ preview: (doc, { req }) => `${req.protocol}//${req.host}/${doc.slug}` // highlig
|
|||||||
|
|
||||||
## Draft Preview
|
## Draft Preview
|
||||||
|
|
||||||
The Preview feature can be used to achieve "Draft Preview", where you enter into a "draft mode" after clicking the preview button. While in "draft mode", you can adjust your page's query to include the `draft: true` in its params. Payload will read this param on the request, and when present, send back a draft document as opposed to a published one based on the document's `_status` field.
|
The Preview feature can be used to achieve "Draft Preview". After clicking the preview button from the Admin Panel, you can enter into "draft mode" within your front-end application. This will allow you to adjust your page queries to include the `draft: true` param. When this param is present on the request, Payload will send back a draft document as opposed to a published one based on the document's `_status` field.
|
||||||
|
|
||||||
To enter draft mode, the URL provided to the `preview` function can point to a custom endpoint in your front-end application that sets a cookie or session variable to indicate that you are in "draft mode". This is framework specific, so the mechanisms here very from framework to framework although the underlying concept is the same.
|
To enter draft mode, the URL provided to the `preview` function can point to a custom endpoint in your front-end application that sets a cookie or session variable to indicate that draft mode is enabled. This is framework specific, so the mechanisms here very from framework to framework although the underlying concept is the same.
|
||||||
|
|
||||||
### Next.js
|
### Next.js
|
||||||
|
|
||||||
If you're using Next.js, you can do the following code to enter draft mode.
|
If you're using Next.js, you can do the following code to enter [Draft Mode](https://nextjs.org/docs/app/building-your-application/configuring/draft-mode).
|
||||||
|
|
||||||
#### Step 1: Create an API Route
|
#### Step 1: Format the Preview URL
|
||||||
|
|
||||||
First, format your `preview` function to point to a custom endpoint that you'll open on your front-end. This URL will include a few key query search params:
|
First, format your `admin.preview` function to point to a custom endpoint that you'll open on your front-end. This URL should include a few key query search params:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { CollectionConfig } from 'payload'
|
import type { CollectionConfig } from 'payload'
|
||||||
@@ -79,17 +79,15 @@ import type { CollectionConfig } from 'payload'
|
|||||||
export const Pages: CollectionConfig = {
|
export const Pages: CollectionConfig = {
|
||||||
slug: 'pages',
|
slug: 'pages',
|
||||||
admin: {
|
admin: {
|
||||||
preview: ({ slug }, { req }) => {
|
preview: ({ slug, collection }) => {
|
||||||
const path = `/${slug}`
|
|
||||||
|
|
||||||
const encodedParams = new URLSearchParams({
|
const encodedParams = new URLSearchParams({
|
||||||
slug,
|
slug,
|
||||||
collection,
|
collection,
|
||||||
path,
|
path: `/${slug}`,
|
||||||
previewSecret: process.env.PREVIEW_SECRET
|
previewSecret: process.env.PREVIEW_SECRET || ''
|
||||||
})
|
})
|
||||||
|
|
||||||
return `/next/preview?${encodedParams.toString()}` // highlight-line
|
return `/preview?${encodedParams.toString()}` // highlight-line
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fields: [
|
fields: [
|
||||||
@@ -105,18 +103,17 @@ export const Pages: CollectionConfig = {
|
|||||||
|
|
||||||
Then, create an API route that verifies the preview secret, authenticates the user, and enters draft mode:
|
Then, create an API route that verifies the preview secret, authenticates the user, and enters draft mode:
|
||||||
|
|
||||||
`/preview/route.ts`
|
`/app/preview/route.ts`
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { CollectionSlug, PayloadRequest, getPayload } from 'payload'
|
import type { CollectionSlug, PayloadRequest } from 'payload'
|
||||||
|
import { getPayload } from 'payload'
|
||||||
|
|
||||||
import { draftMode } from 'next/headers'
|
import { draftMode } from 'next/headers'
|
||||||
import { redirect } from 'next/navigation'
|
import { redirect } from 'next/navigation'
|
||||||
|
|
||||||
import configPromise from '@payload-config'
|
import configPromise from '@payload-config'
|
||||||
|
|
||||||
const payloadToken = 'payload-token'
|
|
||||||
|
|
||||||
export async function GET(
|
export async function GET(
|
||||||
req: {
|
req: {
|
||||||
cookies: {
|
cookies: {
|
||||||
@@ -161,12 +158,13 @@ export async function GET(
|
|||||||
|
|
||||||
const draft = await draftMode()
|
const draft = await draftMode()
|
||||||
|
|
||||||
// You can add additional checks here to see if the user is allowed to preview this page
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
draft.disable()
|
draft.disable()
|
||||||
return new Response('You are not allowed to preview this page', { status: 403 })
|
return new Response('You are not allowed to preview this page', { status: 403 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// You can add additional checks here to see if the user is allowed to preview this page
|
||||||
|
|
||||||
draft.enable()
|
draft.enable()
|
||||||
|
|
||||||
redirect(path)
|
redirect(path)
|
||||||
@@ -177,7 +175,7 @@ export async function GET(
|
|||||||
|
|
||||||
Finally, in your front-end application, you can detect draft mode and adjust your queries to include drafts:
|
Finally, in your front-end application, you can detect draft mode and adjust your queries to include drafts:
|
||||||
|
|
||||||
`/pages/[slug].tsx`
|
`/app/[slug]/page.tsx`
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
export default async function Page({ params: paramsPromise }) {
|
export default async function Page({ params: paramsPromise }) {
|
||||||
|
|||||||
@@ -6,3 +6,6 @@ PAYLOAD_SECRET=YOUR_SECRET_HERE
|
|||||||
|
|
||||||
# Used to configure CORS, format links and more. No trailing slash
|
# Used to configure CORS, format links and more. No trailing slash
|
||||||
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
|
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
|
||||||
|
|
||||||
|
# Used to validate the preview request
|
||||||
|
PREVIEW_SECRET=YOUR_SECRET_HERE
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Payload Draft Preview Example
|
# Payload Draft Preview Example
|
||||||
|
|
||||||
The [Payload Draft Preview Example](https://github.com/payloadcms/payload/tree/main/examples/draft-preview/payload) demonstrates how to implement draft preview in [Payload](https://github.com/payloadcms/payload) using [Versions](https://payloadcms.com/docs/versions/overview) and [Drafts](https://payloadcms.com/docs/versions/drafts). Draft preview allows you to see content on your front-end before it is published.
|
The [Payload Draft Preview Example](https://github.com/payloadcms/payload/tree/main/examples/draft-preview/payload) demonstrates how to implement [Draft Preview](https://payloadcms.com/docs/admin/preview#draft-preview) in [Payload](https://github.com/payloadcms/payload) using [Versions](https://payloadcms.com/docs/versions/overview) and [Drafts](https://payloadcms.com/docs/versions/drafts). With Draft Preview, you can navigate to your front-end application and enter "draft mode", where your queries are modified to fetch draft content instead of published content. This is useful for seeing how your content will look before being published.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
|||||||
2
examples/draft-preview/next-env.d.ts
vendored
2
examples/draft-preview/next-env.d.ts
vendored
@@ -2,4 +2,4 @@
|
|||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Payload preview example.",
|
"description": "Payload preview example.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"type": "module",
|
||||||
"main": "dist/server.js",
|
"main": "dist/server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
|
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
|
||||||
|
|||||||
2326
examples/draft-preview/pnpm-lock.yaml
generated
2326
examples/draft-preview/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ import { notFound } from 'next/navigation'
|
|||||||
import { getPayload } from 'payload'
|
import { getPayload } from 'payload'
|
||||||
import React, { cache, Fragment } from 'react'
|
import React, { cache, Fragment } from 'react'
|
||||||
|
|
||||||
import type { Page as PageType } from '../../../payload-types'
|
import type { Page as PageType } from '@payload-types'
|
||||||
|
|
||||||
import { Gutter } from '../../../components/Gutter'
|
import { Gutter } from '../../../components/Gutter'
|
||||||
import RichText from '../../../components/RichText'
|
import RichText from '../../../components/RichText'
|
||||||
@@ -13,6 +13,7 @@ import classes from './index.module.scss'
|
|||||||
|
|
||||||
export async function generateStaticParams() {
|
export async function generateStaticParams() {
|
||||||
const payload = await getPayload({ config })
|
const payload = await getPayload({ config })
|
||||||
|
|
||||||
const pages = await payload.find({
|
const pages = await payload.find({
|
||||||
collection: 'pages',
|
collection: 'pages',
|
||||||
draft: false,
|
draft: false,
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
import { draftMode } from 'next/headers'
|
|
||||||
|
|
||||||
export async function GET(): Promise<Response> {
|
|
||||||
const draft = await draftMode()
|
|
||||||
draft.disable()
|
|
||||||
return new Response('Draft mode is disabled')
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
import type { CollectionSlug, PayloadRequest } from 'payload'
|
|
||||||
|
|
||||||
import { draftMode } from 'next/headers'
|
|
||||||
import { redirect } from 'next/navigation'
|
|
||||||
import { getPayload } from 'payload'
|
|
||||||
|
|
||||||
import configPromise from '../../../../payload.config'
|
|
||||||
|
|
||||||
const payloadToken = 'payload-token'
|
|
||||||
|
|
||||||
export async function GET(
|
|
||||||
req: {
|
|
||||||
cookies: {
|
|
||||||
get: (name: string) => {
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} & Request,
|
|
||||||
): Promise<Response> {
|
|
||||||
const payload = await getPayload({ config: configPromise })
|
|
||||||
const token = req.cookies.get(payloadToken)?.value
|
|
||||||
const { searchParams } = new URL(req.url)
|
|
||||||
const path = searchParams.get('path')
|
|
||||||
const collection = searchParams.get('collection') as CollectionSlug
|
|
||||||
const slug = searchParams.get('slug')
|
|
||||||
|
|
||||||
const previewSecret = searchParams.get('previewSecret')
|
|
||||||
|
|
||||||
if (previewSecret) {
|
|
||||||
return new Response('You are not allowed to preview this page', { status: 403 })
|
|
||||||
} else {
|
|
||||||
if (!path) {
|
|
||||||
return new Response('No path provided', { status: 404 })
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!collection) {
|
|
||||||
return new Response('No path provided', { status: 404 })
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!slug) {
|
|
||||||
return new Response('No path provided', { status: 404 })
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!path.startsWith('/')) {
|
|
||||||
return new Response('This endpoint can only be used for internal previews', { status: 500 })
|
|
||||||
}
|
|
||||||
|
|
||||||
let user
|
|
||||||
|
|
||||||
try {
|
|
||||||
user = await payload.auth({
|
|
||||||
req: req as unknown as PayloadRequest,
|
|
||||||
headers: req.headers,
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
payload.logger.error({ err: error }, 'Error verifying token for live preview')
|
|
||||||
return new Response('You are not allowed to preview this page', { status: 403 })
|
|
||||||
}
|
|
||||||
|
|
||||||
const draft = await draftMode()
|
|
||||||
|
|
||||||
// You can add additional checks here to see if the user is allowed to preview this page
|
|
||||||
if (!user) {
|
|
||||||
draft.disable()
|
|
||||||
return new Response('You are not allowed to preview this page', { status: 403 })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the given slug exists
|
|
||||||
try {
|
|
||||||
const docs = await payload.find({
|
|
||||||
collection,
|
|
||||||
draft: true,
|
|
||||||
where: {
|
|
||||||
slug: {
|
|
||||||
equals: slug,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!docs.docs.length) {
|
|
||||||
return new Response('Document not found', { status: 404 })
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
payload.logger.error({
|
|
||||||
err: error,
|
|
||||||
msg: 'Error verifying token for live preview:',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
draft.enable()
|
|
||||||
|
|
||||||
redirect(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
63
examples/draft-preview/src/app/(app)/preview/route.ts
Normal file
63
examples/draft-preview/src/app/(app)/preview/route.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import type { CollectionSlug, PayloadRequest } from 'payload'
|
||||||
|
import { getPayload } from 'payload'
|
||||||
|
|
||||||
|
import { draftMode } from 'next/headers'
|
||||||
|
import { redirect } from 'next/navigation'
|
||||||
|
|
||||||
|
import configPromise from '@payload-config'
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
req: {
|
||||||
|
cookies: {
|
||||||
|
get: (name: string) => {
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} & Request,
|
||||||
|
): Promise<Response> {
|
||||||
|
const payload = await getPayload({ config: configPromise })
|
||||||
|
|
||||||
|
const { searchParams } = new URL(req.url)
|
||||||
|
|
||||||
|
const path = searchParams.get('path')
|
||||||
|
const collection = searchParams.get('collection') as CollectionSlug
|
||||||
|
const slug = searchParams.get('slug')
|
||||||
|
const previewSecret = searchParams.get('previewSecret')
|
||||||
|
|
||||||
|
if (previewSecret !== process.env.PREVIEW_SECRET) {
|
||||||
|
return new Response('You are not allowed to preview this page', { status: 403 })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!path || !collection || !slug) {
|
||||||
|
return new Response('Insufficient search params', { status: 404 })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!path.startsWith('/')) {
|
||||||
|
return new Response('This endpoint can only be used for relative previews', { status: 500 })
|
||||||
|
}
|
||||||
|
|
||||||
|
let user
|
||||||
|
|
||||||
|
try {
|
||||||
|
user = await payload.auth({
|
||||||
|
req: req as unknown as PayloadRequest,
|
||||||
|
headers: req.headers,
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
payload.logger.error({ err: error }, 'Error verifying token for live preview')
|
||||||
|
return new Response('You are not allowed to preview this page', { status: 403 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const draft = await draftMode()
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
draft.disable()
|
||||||
|
return new Response('You are not allowed to preview this page', { status: 403 })
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can add additional checks here to see if the user is allowed to preview this page
|
||||||
|
|
||||||
|
draft.enable()
|
||||||
|
|
||||||
|
redirect(path)
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ import type { CollectionAfterChangeHook } from 'payload'
|
|||||||
|
|
||||||
import { revalidatePath } from 'next/cache'
|
import { revalidatePath } from 'next/cache'
|
||||||
|
|
||||||
import type { Page } from '../../../payload-types'
|
import type { Page } from '@payload-types'
|
||||||
|
|
||||||
export const revalidatePage: CollectionAfterChangeHook<Page> = ({ doc, previousDoc, req }) => {
|
export const revalidatePage: CollectionAfterChangeHook<Page> = ({ doc, previousDoc, req }) => {
|
||||||
if (req.context.skipRevalidate) {
|
if (req.context.skipRevalidate) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { CollectionConfig } from 'payload'
|
import type { CollectionConfig, CollectionSlug } from 'payload'
|
||||||
|
|
||||||
import richText from '../../fields/richText'
|
import richText from '../../fields/richText'
|
||||||
import { generatePreviewPath } from '../../utilities/generatePreviewPath'
|
|
||||||
import { loggedIn } from './access/loggedIn'
|
import { loggedIn } from './access/loggedIn'
|
||||||
import { publishedOrLoggedIn } from './access/publishedOrLoggedIn'
|
import { publishedOrLoggedIn } from './access/publishedOrLoggedIn'
|
||||||
import { formatSlug } from './hooks/formatSlug'
|
import { formatSlug } from './hooks/formatSlug'
|
||||||
@@ -17,12 +16,15 @@ export const Pages: CollectionConfig = {
|
|||||||
},
|
},
|
||||||
admin: {
|
admin: {
|
||||||
defaultColumns: ['title', 'slug', 'updatedAt'],
|
defaultColumns: ['title', 'slug', 'updatedAt'],
|
||||||
preview: (doc) => {
|
preview: ({ slug, collection }: { slug: string; collection: CollectionSlug }) => {
|
||||||
const path = generatePreviewPath({
|
const encodedParams = new URLSearchParams({
|
||||||
slug: typeof doc?.slug === 'string' ? doc.slug : '',
|
slug,
|
||||||
collection: 'pages',
|
collection,
|
||||||
|
path: `/${slug}`,
|
||||||
|
previewSecret: process.env.PREVIEW_SECRET || '',
|
||||||
})
|
})
|
||||||
return `${process.env.NEXT_PUBLIC_SERVER_URL}${path}`
|
|
||||||
|
return `${process.env.NEXT_PUBLIC_SERVER_URL}/preview?${encodedParams.toString()}`
|
||||||
},
|
},
|
||||||
useAsTitle: 'title',
|
useAsTitle: 'title',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import type { Page } from '../../payload-types'
|
import type { Page } from '@payload-types'
|
||||||
|
|
||||||
import { Button } from '../Button'
|
import { Button } from '../Button'
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { getPayload } from 'payload'
|
||||||
|
import configPromise from '@payload-config'
|
||||||
|
|
||||||
import type { MainMenu } from '../../payload-types'
|
import type { MainMenu } from '@payload-types'
|
||||||
|
|
||||||
import { getCachedGlobal } from '../../utilities/getGlobals'
|
|
||||||
import { CMSLink } from '../CMSLink'
|
import { CMSLink } from '../CMSLink'
|
||||||
import { Gutter } from '../Gutter'
|
import { Gutter } from '../Gutter'
|
||||||
import classes from './index.module.scss'
|
import classes from './index.module.scss'
|
||||||
|
|
||||||
export async function Header() {
|
export async function Header() {
|
||||||
const header: MainMenu = await getCachedGlobal('main-menu', 1)()
|
const payload = await getPayload({ config: configPromise })
|
||||||
|
|
||||||
|
const header: MainMenu = await payload.findGlobal({
|
||||||
|
slug: 'main-menu',
|
||||||
|
depth: 1,
|
||||||
|
})
|
||||||
|
|
||||||
const navItems = header?.navItems || []
|
const navItems = header?.navItems || []
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Page } from '../payload-types'
|
import type { Page } from '@payload-types'
|
||||||
|
|
||||||
// Used for pre-seeded content so that the homepage is not empty
|
// Used for pre-seeded content so that the homepage is not empty
|
||||||
// @ts-expect-error: Page type is not fully compatible with the provided object structure
|
// @ts-expect-error: Page type is not fully compatible with the provided object structure
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Page } from '../payload-types'
|
import type { Page } from '@payload-types'
|
||||||
|
|
||||||
export const examplePage: Partial<Page> = {
|
export const examplePage: Partial<Page> = {
|
||||||
slug: 'example-page',
|
slug: 'example-page',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Page } from '../payload-types'
|
import type { Page } from '@payload-types'
|
||||||
|
|
||||||
export const examplePageDraft: Partial<Page> = {
|
export const examplePageDraft: Partial<Page> = {
|
||||||
richText: [
|
richText: [
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
import type { CollectionSlug } from 'payload'
|
|
||||||
|
|
||||||
const collectionPrefixMap: Partial<Record<CollectionSlug, string>> = {
|
|
||||||
pages: '',
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
collection: keyof typeof collectionPrefixMap
|
|
||||||
slug: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const generatePreviewPath = ({ slug, collection }: Props) => {
|
|
||||||
const path = `${collectionPrefixMap[collection]}/${slug}`
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
slug,
|
|
||||||
collection,
|
|
||||||
path,
|
|
||||||
}
|
|
||||||
|
|
||||||
const encodedParams = new URLSearchParams()
|
|
||||||
|
|
||||||
Object.entries(params).forEach(([key, value]) => {
|
|
||||||
encodedParams.append(key, value)
|
|
||||||
})
|
|
||||||
|
|
||||||
return `/next/preview?${encodedParams.toString()}`
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import type { Config } from 'src/payload-types'
|
|
||||||
|
|
||||||
import { unstable_cache } from 'next/cache'
|
|
||||||
import { getPayload } from 'payload'
|
|
||||||
|
|
||||||
import configPromise from '../payload.config'
|
|
||||||
|
|
||||||
type Global = keyof Config['globals']
|
|
||||||
|
|
||||||
async function getGlobal(slug: Global, depth = 0) {
|
|
||||||
const payload = await getPayload({ config: configPromise })
|
|
||||||
|
|
||||||
const global = await payload.findGlobal({
|
|
||||||
slug,
|
|
||||||
depth,
|
|
||||||
})
|
|
||||||
|
|
||||||
return global
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a unstable_cache function mapped with the cache tag for the slug
|
|
||||||
*/
|
|
||||||
export const getCachedGlobal = (slug: Global, depth = 0) =>
|
|
||||||
unstable_cache(async () => getGlobal(slug, depth), [slug], {
|
|
||||||
tags: [`global_${slug}`],
|
|
||||||
})
|
|
||||||
@@ -30,6 +30,9 @@
|
|||||||
"@payload-config": [
|
"@payload-config": [
|
||||||
"./src/payload.config.ts"
|
"./src/payload.config.ts"
|
||||||
],
|
],
|
||||||
|
"@payload-types": [
|
||||||
|
"./src/payload-types.ts"
|
||||||
|
],
|
||||||
"react": [
|
"react": [
|
||||||
"./node_modules/@types/react"
|
"./node_modules/@types/react"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@payload-config": ["./test/versions/config.ts"],
|
"@payload-config": ["./test/_community/config.ts"],
|
||||||
"@payloadcms/live-preview": ["./packages/live-preview/src"],
|
"@payloadcms/live-preview": ["./packages/live-preview/src"],
|
||||||
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],
|
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],
|
||||||
"@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],
|
"@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],
|
||||||
|
|||||||
Reference in New Issue
Block a user