diff --git a/templates/website/src/Footer/hooks/revalidateFooter.ts b/templates/website/src/Footer/hooks/revalidateFooter.ts index f6267c0fd38..df3acec0273 100644 --- a/templates/website/src/Footer/hooks/revalidateFooter.ts +++ b/templates/website/src/Footer/hooks/revalidateFooter.ts @@ -2,10 +2,12 @@ import type { GlobalAfterChangeHook } from 'payload' import { revalidateTag } from 'next/cache' -export const revalidateFooter: GlobalAfterChangeHook = ({ doc, req: { payload } }) => { - payload.logger.info(`Revalidating footer`) +export const revalidateFooter: GlobalAfterChangeHook = ({ doc, req: { payload, context } }) => { + if (!context.disableRevalidate) { + payload.logger.info(`Revalidating footer`) - revalidateTag('global_footer') + revalidateTag('global_footer') + } return doc } diff --git a/templates/website/src/Header/hooks/revalidateHeader.ts b/templates/website/src/Header/hooks/revalidateHeader.ts index 7315cc260d5..efe176aa885 100644 --- a/templates/website/src/Header/hooks/revalidateHeader.ts +++ b/templates/website/src/Header/hooks/revalidateHeader.ts @@ -2,10 +2,12 @@ import type { GlobalAfterChangeHook } from 'payload' import { revalidateTag } from 'next/cache' -export const revalidateHeader: GlobalAfterChangeHook = ({ doc, req: { payload } }) => { - payload.logger.info(`Revalidating header`) +export const revalidateHeader: GlobalAfterChangeHook = ({ doc, req: { payload, context } }) => { + if (!context.disableRevalidate) { + payload.logger.info(`Revalidating header`) - revalidateTag('global_header') + revalidateTag('global_header') + } return doc } diff --git a/templates/website/src/app/(frontend)/next/seed/route.ts b/templates/website/src/app/(frontend)/next/seed/route.ts index 9b42fcbc7cd..0dc91e47e9c 100644 --- a/templates/website/src/app/(frontend)/next/seed/route.ts +++ b/templates/website/src/app/(frontend)/next/seed/route.ts @@ -3,7 +3,6 @@ import { seed } from '@/endpoints/seed' import config from '@payload-config' import { headers } from 'next/headers' -const payloadToken = 'payload-token' export const maxDuration = 60 // This function can run for a maximum of 60 seconds export async function POST( diff --git a/templates/website/src/collections/Pages/hooks/revalidatePage.ts b/templates/website/src/collections/Pages/hooks/revalidatePage.ts index db0a9d3bfc8..2a1980945a0 100644 --- a/templates/website/src/collections/Pages/hooks/revalidatePage.ts +++ b/templates/website/src/collections/Pages/hooks/revalidatePage.ts @@ -7,34 +7,37 @@ import type { Page } from '../../../payload-types' export const revalidatePage: CollectionAfterChangeHook = ({ doc, previousDoc, - req: { payload }, + req: { payload, context }, }) => { - if (doc._status === 'published') { - const path = doc.slug === 'home' ? '/' : `/${doc.slug}` + if (!context.disableRevalidate) { + if (doc._status === 'published') { + const path = doc.slug === 'home' ? '/' : `/${doc.slug}` - payload.logger.info(`Revalidating page at path: ${path}`) + payload.logger.info(`Revalidating page at path: ${path}`) - revalidatePath(path) - revalidateTag('pages-sitemap') - } + revalidatePath(path) + revalidateTag('pages-sitemap') + } - // If the page was previously published, we need to revalidate the old path - if (previousDoc?._status === 'published' && doc._status !== 'published') { - const oldPath = previousDoc.slug === 'home' ? '/' : `/${previousDoc.slug}` + // If the page was previously published, we need to revalidate the old path + if (previousDoc?._status === 'published' && doc._status !== 'published') { + const oldPath = previousDoc.slug === 'home' ? '/' : `/${previousDoc.slug}` - payload.logger.info(`Revalidating old page at path: ${oldPath}`) + payload.logger.info(`Revalidating old page at path: ${oldPath}`) - revalidatePath(oldPath) - revalidateTag('pages-sitemap') + revalidatePath(oldPath) + revalidateTag('pages-sitemap') + } } - return doc } -export const revalidateDelete: CollectionAfterDeleteHook = ({ doc }) => { - const path = doc?.slug === 'home' ? '/' : `/${doc?.slug}` - revalidatePath(path) - revalidateTag('pages-sitemap') +export const revalidateDelete: CollectionAfterDeleteHook = ({ doc, req: { context } }) => { + if (!context.disableRevalidate) { + const path = doc?.slug === 'home' ? '/' : `/${doc?.slug}` + revalidatePath(path) + revalidateTag('pages-sitemap') + } return doc } diff --git a/templates/website/src/collections/Posts/hooks/revalidatePost.ts b/templates/website/src/collections/Posts/hooks/revalidatePost.ts index bbc072979d1..ff43752852e 100644 --- a/templates/website/src/collections/Posts/hooks/revalidatePost.ts +++ b/templates/website/src/collections/Posts/hooks/revalidatePost.ts @@ -7,35 +7,38 @@ import type { Post } from '../../../payload-types' export const revalidatePost: CollectionAfterChangeHook = ({ doc, previousDoc, - req: { payload }, + req: { payload, context }, }) => { - if (doc._status === 'published') { - const path = `/posts/${doc.slug}` + if (!context.disableRevalidate) { + if (doc._status === 'published') { + const path = `/posts/${doc.slug}` - payload.logger.info(`Revalidating post at path: ${path}`) + payload.logger.info(`Revalidating post at path: ${path}`) - revalidatePath(path) - revalidateTag('posts-sitemap') - } + revalidatePath(path) + revalidateTag('posts-sitemap') + } - // If the post was previously published, we need to revalidate the old path - if (previousDoc._status === 'published' && doc._status !== 'published') { - const oldPath = `/posts/${previousDoc.slug}` + // If the post was previously published, we need to revalidate the old path + if (previousDoc._status === 'published' && doc._status !== 'published') { + const oldPath = `/posts/${previousDoc.slug}` - payload.logger.info(`Revalidating old post at path: ${oldPath}`) + payload.logger.info(`Revalidating old post at path: ${oldPath}`) - revalidatePath(oldPath) - revalidateTag('posts-sitemap') + revalidatePath(oldPath) + revalidateTag('posts-sitemap') + } } - return doc } -export const revalidateDelete: CollectionAfterDeleteHook = ({ doc }) => { - const path = `/posts/${doc?.slug}` +export const revalidateDelete: CollectionAfterDeleteHook = ({ doc, req: { context } }) => { + if (!context.disableRevalidate) { + const path = `/posts/${doc?.slug}` - revalidatePath(path) - revalidateTag('posts-sitemap') + revalidatePath(path) + revalidateTag('posts-sitemap') + } return doc } diff --git a/templates/website/src/endpoints/seed/index.ts b/templates/website/src/endpoints/seed/index.ts index ca010c9d9db..50e7c6f9ed0 100644 --- a/templates/website/src/endpoints/seed/index.ts +++ b/templates/website/src/endpoints/seed/index.ts @@ -42,35 +42,52 @@ export const seed = async ({ payload.logger.info(`— Clearing collections and globals...`) // clear the database - for (const global of globals) { - await payload.updateGlobal({ - slug: global, - data: { - navItems: [], - }, - }) - } - - for (const collection of collections) { - await payload.delete({ - collection: collection, - where: { - id: { - exists: true, + await Promise.all( + globals.map((global) => + payload.updateGlobal({ + slug: global, + data: { + navItems: [], }, - }, - }) - } + depth: 0, + context: { + disableRevalidate: true, + }, + }), + ), + ) + + await Promise.all( + collections.map((collection) => + payload.delete({ + collection: collection, + where: { + id: { + exists: true, + }, + }, + depth: 0, + context: { + disableRevalidate: true, + }, + }), + ), + ) const pages = await payload.delete({ collection: 'pages', where: {}, + context: { + disableRevalidate: true, + }, + depth: 0, }) payload.logger.info(`— Seeding demo author and user...`) await payload.delete({ collection: 'users', + depth: 0, where: { email: { equals: 'demo-author@payloadcms.com', @@ -78,17 +95,6 @@ export const seed = async ({ }, }) - const demoAuthor = await payload.create({ - collection: 'users', - data: { - name: 'Demo Author', - email: 'demo-author@payloadcms.com', - password: 'password', - }, - }) - - let demoAuthorID: number | string = demoAuthor.id - payload.logger.info(`— Seeding media...`) const [image1Buffer, image2Buffer, image3Buffer, hero1Buffer] = await Promise.all([ fetchFileByURL( @@ -105,48 +111,67 @@ export const seed = async ({ ), ]) - const image1Doc = await payload.create({ - collection: 'media', - data: image1, - file: image1Buffer, - }) - const image2Doc = await payload.create({ - collection: 'media', - data: image2, - file: image2Buffer, - }) - const image3Doc = await payload.create({ - collection: 'media', - data: image2, - file: image3Buffer, - }) - const imageHomeDoc = await payload.create({ - collection: 'media', - data: image2, - file: hero1Buffer, - }) - - payload.logger.info(`— Seeding categories...`) - const technologyCategory = await payload.create({ - collection: 'categories', - data: { - title: 'Technology', - }, - }) + const [ + demoAuthor, + image1Doc, + image2Doc, + image3Doc, + imageHomeDoc, + technologyCategory, + newsCategory, + financeCategory, + ] = await Promise.all([ + payload.create({ + collection: 'users', + data: { + name: 'Demo Author', + email: 'demo-author@payloadcms.com', + password: 'password', + }, + }), + payload.create({ + collection: 'media', + data: image1, + file: image1Buffer, + }), + payload.create({ + collection: 'media', + data: image2, + file: image2Buffer, + }), + payload.create({ + collection: 'media', + data: image2, + file: image3Buffer, + }), + payload.create({ + collection: 'media', + data: image2, + file: hero1Buffer, + }), + + payload.create({ + collection: 'categories', + data: { + title: 'Technology', + }, + }), - const newsCategory = await payload.create({ - collection: 'categories', - data: { - title: 'News', - }, - }) + payload.create({ + collection: 'categories', + data: { + title: 'News', + }, + }), - const financeCategory = await payload.create({ - collection: 'categories', - data: { - title: 'Finance', - }, - }) + payload.create({ + collection: 'categories', + data: { + title: 'Finance', + }, + }), + ]) + let demoAuthorID: number | string = demoAuthor.id await payload.create({ collection: 'categories', @@ -188,6 +213,11 @@ export const seed = async ({ // This way we can sort them by `createdAt` or `publishedAt` and they will be in the expected order const post1Doc = await payload.create({ collection: 'posts', + depth: 0, + context: { + disableRevalidate: true, + }, + select: { content: false }, data: JSON.parse( JSON.stringify({ ...post1, categories: [technologyCategory.id] }) .replace(/"\{\{IMAGE_1\}\}"/g, String(image1ID)) @@ -198,6 +228,11 @@ export const seed = async ({ const post2Doc = await payload.create({ collection: 'posts', + depth: 0, + context: { + disableRevalidate: true, + }, + select: { content: false }, data: JSON.parse( JSON.stringify({ ...post2, categories: [newsCategory.id] }) .replace(/"\{\{IMAGE_1\}\}"/g, String(image2ID)) @@ -208,6 +243,11 @@ export const seed = async ({ const post3Doc = await payload.create({ collection: 'posts', + depth: 0, + context: { + disableRevalidate: true, + }, + select: { content: false }, data: JSON.parse( JSON.stringify({ ...post3, categories: [financeCategory.id] }) .replace(/"\{\{IMAGE_1\}\}"/g, String(image3ID)) @@ -239,21 +279,12 @@ export const seed = async ({ }, }) - payload.logger.info(`— Seeding home page...`) - - await payload.create({ - collection: 'pages', - data: JSON.parse( - JSON.stringify(home) - .replace(/"\{\{IMAGE_1\}\}"/g, String(imageHomeID)) - .replace(/"\{\{IMAGE_2\}\}"/g, String(image2ID)), - ), - }) - payload.logger.info(`— Seeding contact form...`) const contactForm = await payload.create({ collection: 'forms', + depth: 0, + select: { title: true }, data: JSON.parse(JSON.stringify(contactFormData)), }) @@ -263,74 +294,88 @@ export const seed = async ({ contactFormID = `"${contactFormID}"` } - payload.logger.info(`— Seeding contact page...`) - - const contactPage = await payload.create({ - collection: 'pages', - data: JSON.parse( - JSON.stringify(contactPageData).replace(/"\{\{CONTACT_FORM_ID\}\}"/g, String(contactFormID)), - ), - }) + payload.logger.info(`— Seeding pages...`) + + const [_, contactPage] = await Promise.all([ + payload.create({ + collection: 'pages', + depth: 0, + data: JSON.parse( + JSON.stringify(home) + .replace(/"\{\{IMAGE_1\}\}"/g, String(imageHomeID)) + .replace(/"\{\{IMAGE_2\}\}"/g, String(image2ID)), + ), + }), + payload.create({ + collection: 'pages', + depth: 0, + data: JSON.parse( + JSON.stringify(contactPageData).replace( + /"\{\{CONTACT_FORM_ID\}\}"/g, + String(contactFormID), + ), + ), + }), + ]) - payload.logger.info(`— Seeding header...`) + payload.logger.info(`— Seeding globals...`) - await payload.updateGlobal({ - slug: 'header', - data: { - navItems: [ - { - link: { - type: 'custom', - label: 'Posts', - url: '/posts', + await Promise.all([ + payload.updateGlobal({ + slug: 'header', + data: { + navItems: [ + { + link: { + type: 'custom', + label: 'Posts', + url: '/posts', + }, }, - }, - { - link: { - type: 'reference', - label: 'Contact', - reference: { - relationTo: 'pages', - value: contactPage.id, + { + link: { + type: 'reference', + label: 'Contact', + reference: { + relationTo: 'pages', + value: contactPage.id, + }, }, }, - }, - ], - }, - }) - - payload.logger.info(`— Seeding footer...`) - - await payload.updateGlobal({ - slug: 'footer', - data: { - navItems: [ - { - link: { - type: 'custom', - label: 'Admin', - url: '/admin', + ], + }, + }), + payload.updateGlobal({ + slug: 'footer', + data: { + navItems: [ + { + link: { + type: 'custom', + label: 'Admin', + url: '/admin', + }, }, - }, - { - link: { - type: 'custom', - label: 'Source Code', - newTab: true, - url: 'https://github.com/payloadcms/payload/tree/main/templates/website', + { + link: { + type: 'custom', + label: 'Source Code', + newTab: true, + url: 'https://github.com/payloadcms/payload/tree/main/templates/website', + }, }, - }, - { - link: { - type: 'custom', - label: 'Payload', - newTab: true, - url: 'https://payloadcms.com/', + { + link: { + type: 'custom', + label: 'Payload', + newTab: true, + url: 'https://payloadcms.com/', + }, }, - }, - ], - }, - }) + ], + }, + }), + ]) payload.logger.info('Seeded database successfully!') } diff --git a/templates/website/src/endpoints/seedHandler.ts b/templates/website/src/endpoints/seedHandler.ts deleted file mode 100644 index 1c90a2cb24a..00000000000 --- a/templates/website/src/endpoints/seedHandler.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { type PayloadHandler } from 'payload' - -import { seed as seedScript } from '@/endpoints/seed' - -export const seedHandler: PayloadHandler = async (req): Promise => { - const { payload, user } = req - - if (!user) { - return Response.json({ error: 'Unauthorized' }, { status: 401 }) - } - - try { - await seedScript({ payload, req }) - return Response.json({ success: true }) - } catch (error: unknown) { - const message = error instanceof Error ? error.message : 'Unknown error' - payload.logger.error(message) - return Response.json({ error: message }, { status: 500 }) - } -}