diff --git a/package.json b/package.json index 37990302b5..a1c71959ac 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "dev:generate-types": "pnpm runts ./test/generateTypes.ts", "dev:postgres": "cross-env PAYLOAD_DATABASE=postgres pnpm runts ./test/dev.ts", "dev:prod": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/dev.ts --prod", + "dev:prod:memorydb": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/dev.ts --prod --start-memory-db", "dev:vercel-postgres": "cross-env PAYLOAD_DATABASE=vercel-postgres pnpm runts ./test/dev.ts", "devsafe": "node ./scripts/delete-recursively.js '**/.next' && pnpm dev", "docker:restart": "pnpm docker:stop --remove-orphans && pnpm docker:start", diff --git a/packages/payload/src/bin/generateImportMap/index.ts b/packages/payload/src/bin/generateImportMap/index.ts index 05d451f1da..850ce084b0 100644 --- a/packages/payload/src/bin/generateImportMap/index.ts +++ b/packages/payload/src/bin/generateImportMap/index.ts @@ -64,12 +64,23 @@ export function addPayloadComponentToImportMap({ // then path needs to be /test/fields/components/Field.tsx NOT /users/username/project/test/fields/components/Field.tsx // so we need to append baseDir to componentPath - imports[importIdentifier] = { - path: - componentPath.startsWith('.') || componentPath.startsWith('/') - ? path.posix.join(baseDir.replace(/\\/g, '/'), componentPath.slice(1)) - : componentPath, - specifier: exportName, + if (componentPath.startsWith('.') || componentPath.startsWith('/')) { + const normalizedBaseDir = baseDir.replace(/\\/g, '/') + + const finalPath = normalizedBaseDir.startsWith('/../') + ? `${normalizedBaseDir}${componentPath.slice(1)}` + : path.posix.join(normalizedBaseDir, componentPath.slice(1)) + + imports[importIdentifier] = { + path: + componentPath.startsWith('.') || componentPath.startsWith('/') ? finalPath : componentPath, + specifier: exportName, + } + } else { + imports[importIdentifier] = { + path: componentPath, + specifier: exportName, + } } importMap[componentPath + '#' + exportName] = importIdentifier } @@ -109,7 +120,29 @@ export async function generateImportMap( // rootDir: / // componentsBaseDir = / - const componentsBaseDir = path.relative(rootDir, config.admin.importMap.baseDir) + // E.g.: + // config.admin.importMap.baseDir = /test/fields/ + // rootDir: /test/fields/prod + // componentsBaseDir = ../ + + // Check if rootDir is a subdirectory of baseDir + const baseDir = config.admin.importMap.baseDir + const isSubdirectory = path.relative(baseDir, rootDir).startsWith('..') + + let componentsBaseDir + + if (isSubdirectory) { + // Get the relative path from rootDir to baseDir + componentsBaseDir = path.relative(rootDir, baseDir) + } else { + // If rootDir is not a subdirectory, just return baseDir relative to rootDir + componentsBaseDir = `/${path.relative(rootDir, baseDir)}` + } + + // Ensure result has a trailing slash + if (!componentsBaseDir.endsWith('/')) { + componentsBaseDir += '/' + } const addToImportMap: AddToImportMap = (payloadComponent) => { if (!payloadComponent) { diff --git a/test/generateImportMap.ts b/test/generateImportMap.ts index 31e2929997..51fce17230 100644 --- a/test/generateImportMap.ts +++ b/test/generateImportMap.ts @@ -4,6 +4,7 @@ const [testConfigDir] = process.argv.slice(2) import type { SanitizedConfig } from 'payload' +import fs from 'fs' import { generateImportMap } from 'payload' import { fileURLToPath } from 'url' @@ -21,11 +22,24 @@ async function run() { const config: SanitizedConfig = await (await import(pathWithConfig)).default - process.env.ROOT_DIR = - testConfigDir === 'live-preview' || testConfigDir === 'admin-root' - ? testDir - : path.resolve(dirname, '..') + let rootDir = '' + if (testConfigDir === 'live-preview' || testConfigDir === 'admin-root') { + rootDir = testDir + if (process.env.PAYLOAD_TEST_PROD === 'true') { + // If in prod mode, there may be a testSuite/prod folder. If so, use that as the rootDir + const prodDir = path.resolve(testDir, 'prod') + try { + fs.accessSync(prodDir, fs.constants.F_OK) + rootDir = prodDir + } catch (err) { + // Swallow err - no prod folder + } + } + } else { + rootDir = path.resolve(dirname, '..') + } + process.env.ROOT_DIR = rootDir await generateImportMap(config, { log: true, force: true }) } } diff --git a/test/helpers.ts b/test/helpers.ts index 5e44c03750..46c4401494 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -348,7 +348,8 @@ export function initPageConsoleErrorCatch(page: Page) { !msg.text().includes('Error: NEXT_REDIRECT') && !msg.text().includes('Error getting document data') && !msg.text().includes('Failed trying to load default language strings') && - !msg.text().includes('TypeError: Failed to fetch') // This happens when server actions are aborted + !msg.text().includes('TypeError: Failed to fetch') && // This happens when server actions are aborted + !msg.text().includes('der-radius: 2px Server Error: Error getting do') // This is a weird error that happens in the console ) { // "Failed to fetch RSC payload for" happens seemingly randomly. There are lots of issues in the next.js repository for this. Causes e2e tests to fail and flake. Will ignore for now // the the server responded with a status of error happens frequently. Will ignore it for now. diff --git a/test/helpers/getNextRootDir.ts b/test/helpers/getNextRootDir.ts index 81f1de753f..0fb0e449d4 100644 --- a/test/helpers/getNextRootDir.ts +++ b/test/helpers/getNextRootDir.ts @@ -33,8 +33,19 @@ export function getNextRootDir(testSuite?: string) { } if (hasNextConfig) { + let rootDir = testSuiteDir + if (process.env.PAYLOAD_TEST_PROD === 'true') { + // If in prod mode, there may be a testSuite/prod folder. If so, use that as the rootDir + const prodDir = resolve(testSuiteDir, 'prod') + try { + fs.accessSync(prodDir, fs.constants.F_OK) + rootDir = prodDir + } catch (err) { + // Swallow err - no prod folder + } + } return { - rootDir: testSuiteDir, + rootDir, adminRoute, } } diff --git a/test/live-preview/e2e.spec.ts b/test/live-preview/e2e.spec.ts index 147d8a617b..0f08d8f6ca 100644 --- a/test/live-preview/e2e.spec.ts +++ b/test/live-preview/e2e.spec.ts @@ -32,6 +32,7 @@ import { ssrAutosavePagesSlug, ssrPagesSlug, } from './shared.js' +import { wait } from 'payload/shared' const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) @@ -178,8 +179,12 @@ describe('Live Preview', () => { await expect(frame.locator(renderedPageTitleLocator)).toHaveText('For Testing: SSR Home') const newTitleValue = 'SSR Home (Edited)' + await wait(1000) - await titleField.fill(newTitleValue) + await titleField.clear() + await titleField.pressSequentially(newTitleValue) + + await wait(1000) await waitForAutoSaveToRunAndComplete(page) diff --git a/test/live-preview/prod/app/(payload)/admin/[[...segments]]/not-found.tsx b/test/live-preview/prod/app/(payload)/admin/[[...segments]]/not-found.tsx new file mode 100644 index 0000000000..180e6f81cd --- /dev/null +++ b/test/live-preview/prod/app/(payload)/admin/[[...segments]]/not-found.tsx @@ -0,0 +1,25 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import type { Metadata } from 'next' + +import config from '@payload-config' +import { generatePageMetadata, NotFoundPage } from '@payloadcms/next/views' + +import { importMap } from '../importMap.js' + +type Args = { + params: Promise<{ + segments: string[] + }> + searchParams: Promise<{ + [key: string]: string | string[] + }> +} + +export const generateMetadata = ({ params, searchParams }: Args): Promise => + generatePageMetadata({ config, params, searchParams }) + +const NotFound = ({ params, searchParams }: Args) => + NotFoundPage({ config, importMap, params, searchParams }) + +export default NotFound diff --git a/test/live-preview/prod/app/(payload)/admin/[[...segments]]/page.tsx b/test/live-preview/prod/app/(payload)/admin/[[...segments]]/page.tsx new file mode 100644 index 0000000000..e59b2d3a84 --- /dev/null +++ b/test/live-preview/prod/app/(payload)/admin/[[...segments]]/page.tsx @@ -0,0 +1,25 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import type { Metadata } from 'next' + +import config from '@payload-config' +import { generatePageMetadata, RootPage } from '@payloadcms/next/views' + +import { importMap } from '../importMap.js' + +type Args = { + params: Promise<{ + segments: string[] + }> + searchParams: Promise<{ + [key: string]: string | string[] + }> +} + +export const generateMetadata = ({ params, searchParams }: Args): Promise => + generatePageMetadata({ config, params, searchParams }) + +const Page = ({ params, searchParams }: Args) => + RootPage({ config, importMap, params, searchParams }) + +export default Page diff --git a/test/live-preview/prod/app/(payload)/admin/importMap.js b/test/live-preview/prod/app/(payload)/admin/importMap.js new file mode 100644 index 0000000000..d34a2c99bd --- /dev/null +++ b/test/live-preview/prod/app/(payload)/admin/importMap.js @@ -0,0 +1,141 @@ +import { RscEntrySlateCell as RscEntrySlateCell_0e78253914a550fdacd75626f1dabe17 } from '@payloadcms/richtext-slate/rsc' +import { RscEntrySlateField as RscEntrySlateField_0e78253914a550fdacd75626f1dabe17 } from '@payloadcms/richtext-slate/rsc' +import { BoldLeafButton as BoldLeafButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { BoldLeaf as BoldLeaf_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { CodeLeafButton as CodeLeafButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { CodeLeaf as CodeLeaf_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { ItalicLeafButton as ItalicLeafButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { ItalicLeaf as ItalicLeaf_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { StrikethroughLeafButton as StrikethroughLeafButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { StrikethroughLeaf as StrikethroughLeaf_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { UnderlineLeafButton as UnderlineLeafButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { UnderlineLeaf as UnderlineLeaf_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { BlockquoteElementButton as BlockquoteElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { BlockquoteElement as BlockquoteElement_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { H1ElementButton as H1ElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { Heading1Element as Heading1Element_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { H2ElementButton as H2ElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { Heading2Element as Heading2Element_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { H3ElementButton as H3ElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { Heading3Element as Heading3Element_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { H4ElementButton as H4ElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { Heading4Element as Heading4Element_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { H5ElementButton as H5ElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { Heading5Element as Heading5Element_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { H6ElementButton as H6ElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { Heading6Element as Heading6Element_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { IndentButton as IndentButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { IndentElement as IndentElement_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { ListItemElement as ListItemElement_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { LinkButton as LinkButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { LinkElement as LinkElement_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { WithLinks as WithLinks_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { OLElementButton as OLElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { OrderedListElement as OrderedListElement_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { RelationshipButton as RelationshipButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { RelationshipElement as RelationshipElement_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { WithRelationship as WithRelationship_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { TextAlignElementButton as TextAlignElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { ULElementButton as ULElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { UnorderedListElement as UnorderedListElement_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { UploadElementButton as UploadElementButton_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { UploadElement as UploadElement_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { WithUpload as WithUpload_0b388c087d9de8c4f011dd323a130cfb } from '@payloadcms/richtext-slate/client' +import { RscEntryLexicalCell as RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e } from '@payloadcms/richtext-lexical/rsc' +import { RscEntryLexicalField as RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e } from '@payloadcms/richtext-lexical/rsc' +import { InlineToolbarFeatureClient as InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { HorizontalRuleFeatureClient as HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { UploadFeatureClient as UploadFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { BlockquoteFeatureClient as BlockquoteFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { RelationshipFeatureClient as RelationshipFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { LinkFeatureClient as LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { ChecklistFeatureClient as ChecklistFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { OrderedListFeatureClient as OrderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { UnorderedListFeatureClient as UnorderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { IndentFeatureClient as IndentFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { AlignFeatureClient as AlignFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { HeadingFeatureClient as HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { ParagraphFeatureClient as ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { InlineCodeFeatureClient as InlineCodeFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { SuperscriptFeatureClient as SuperscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { SubscriptFeatureClient as SubscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { StrikethroughFeatureClient as StrikethroughFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { UnderlineFeatureClient as UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { BoldFeatureClient as BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { ItalicFeatureClient as ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { BlocksFeatureClient as BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { TreeViewFeatureClient as TreeViewFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { CollectionLivePreviewButton as CollectionLivePreviewButton_cdf8c2f401206aec7d2609afbb1e2f40 } from '/../components/CollectionLivePreviewButton/index.js' +import { GlobalLivePreviewButton as GlobalLivePreviewButton_cef560d649f896ba95825fe38ff5f91f } from '/../components/GlobalLivePreviewButton/index.js' + +export const importMap = { + "@payloadcms/richtext-slate/rsc#RscEntrySlateCell": RscEntrySlateCell_0e78253914a550fdacd75626f1dabe17, + "@payloadcms/richtext-slate/rsc#RscEntrySlateField": RscEntrySlateField_0e78253914a550fdacd75626f1dabe17, + "@payloadcms/richtext-slate/client#BoldLeafButton": BoldLeafButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#BoldLeaf": BoldLeaf_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#CodeLeafButton": CodeLeafButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#CodeLeaf": CodeLeaf_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#ItalicLeafButton": ItalicLeafButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#ItalicLeaf": ItalicLeaf_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#StrikethroughLeafButton": StrikethroughLeafButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#StrikethroughLeaf": StrikethroughLeaf_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#UnderlineLeafButton": UnderlineLeafButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#UnderlineLeaf": UnderlineLeaf_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#BlockquoteElementButton": BlockquoteElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#BlockquoteElement": BlockquoteElement_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#H1ElementButton": H1ElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#Heading1Element": Heading1Element_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#H2ElementButton": H2ElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#Heading2Element": Heading2Element_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#H3ElementButton": H3ElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#Heading3Element": Heading3Element_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#H4ElementButton": H4ElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#Heading4Element": Heading4Element_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#H5ElementButton": H5ElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#Heading5Element": Heading5Element_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#H6ElementButton": H6ElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#Heading6Element": Heading6Element_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#IndentButton": IndentButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#IndentElement": IndentElement_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#ListItemElement": ListItemElement_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#LinkButton": LinkButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#LinkElement": LinkElement_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#WithLinks": WithLinks_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#OLElementButton": OLElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#OrderedListElement": OrderedListElement_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#RelationshipButton": RelationshipButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#RelationshipElement": RelationshipElement_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#WithRelationship": WithRelationship_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#TextAlignElementButton": TextAlignElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#ULElementButton": ULElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#UnorderedListElement": UnorderedListElement_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#UploadElementButton": UploadElementButton_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#UploadElement": UploadElement_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-slate/client#WithUpload": WithUpload_0b388c087d9de8c4f011dd323a130cfb, + "@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell": RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e, + "@payloadcms/richtext-lexical/rsc#RscEntryLexicalField": RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e, + "@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#UploadFeatureClient": UploadFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#BlockquoteFeatureClient": BlockquoteFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#RelationshipFeatureClient": RelationshipFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#ChecklistFeatureClient": ChecklistFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#OrderedListFeatureClient": OrderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#UnorderedListFeatureClient": UnorderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#IndentFeatureClient": IndentFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#AlignFeatureClient": AlignFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#ParagraphFeatureClient": ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#InlineCodeFeatureClient": InlineCodeFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#SuperscriptFeatureClient": SuperscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#SubscriptFeatureClient": SubscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#StrikethroughFeatureClient": StrikethroughFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#TreeViewFeatureClient": TreeViewFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "/components/CollectionLivePreviewButton/index.js#CollectionLivePreviewButton": CollectionLivePreviewButton_cdf8c2f401206aec7d2609afbb1e2f40, + "/components/GlobalLivePreviewButton/index.js#GlobalLivePreviewButton": GlobalLivePreviewButton_cef560d649f896ba95825fe38ff5f91f +} diff --git a/test/live-preview/prod/app/(payload)/api/[...slug]/route.ts b/test/live-preview/prod/app/(payload)/api/[...slug]/route.ts new file mode 100644 index 0000000000..183cf457f6 --- /dev/null +++ b/test/live-preview/prod/app/(payload)/api/[...slug]/route.ts @@ -0,0 +1,10 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import config from '@payload-config' +import { REST_DELETE, REST_GET, REST_OPTIONS, REST_PATCH, REST_POST } from '@payloadcms/next/routes' + +export const GET = REST_GET(config) +export const POST = REST_POST(config) +export const DELETE = REST_DELETE(config) +export const PATCH = REST_PATCH(config) +export const OPTIONS = REST_OPTIONS(config) diff --git a/test/live-preview/prod/app/(payload)/api/graphql-playground/route.ts b/test/live-preview/prod/app/(payload)/api/graphql-playground/route.ts new file mode 100644 index 0000000000..dffacb345f --- /dev/null +++ b/test/live-preview/prod/app/(payload)/api/graphql-playground/route.ts @@ -0,0 +1,6 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import config from '@payload-config' +import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes/index.js' + +export const GET = GRAPHQL_PLAYGROUND_GET(config) diff --git a/test/live-preview/prod/app/(payload)/api/graphql/route.ts b/test/live-preview/prod/app/(payload)/api/graphql/route.ts new file mode 100644 index 0000000000..2069ff86b0 --- /dev/null +++ b/test/live-preview/prod/app/(payload)/api/graphql/route.ts @@ -0,0 +1,8 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import config from '@payload-config' +import { GRAPHQL_POST, REST_OPTIONS } from '@payloadcms/next/routes' + +export const POST = GRAPHQL_POST(config) + +export const OPTIONS = REST_OPTIONS(config) diff --git a/test/live-preview/prod/app/(payload)/custom.scss b/test/live-preview/prod/app/(payload)/custom.scss new file mode 100644 index 0000000000..f557cd4277 --- /dev/null +++ b/test/live-preview/prod/app/(payload)/custom.scss @@ -0,0 +1,7 @@ +#custom-css { + font-family: monospace; +} + +#custom-css::after { + content: 'custom-css'; +} diff --git a/test/live-preview/prod/app/(payload)/layout.tsx b/test/live-preview/prod/app/(payload)/layout.tsx new file mode 100644 index 0000000000..f5f86c762a --- /dev/null +++ b/test/live-preview/prod/app/(payload)/layout.tsx @@ -0,0 +1,32 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import type { ServerFunctionClient } from 'payload' + +import config from '@payload-config' +import '@payloadcms/next/css' +import { handleServerFunctions, RootLayout } from '@payloadcms/next/layouts' +import React from 'react' + +import { importMap } from './admin/importMap.js' +import './custom.scss' + +type Args = { + children: React.ReactNode +} + +const serverFunction: ServerFunctionClient = async function (args) { + 'use server' + return handleServerFunctions({ + ...args, + config, + importMap, + }) +} + +const Layout = ({ children }: Args) => ( + + {children} + +) + +export default Layout diff --git a/test/live-preview/prod/app/live-preview/(pages)/[slug]/page.client.tsx b/test/live-preview/prod/app/live-preview/(pages)/[slug]/page.client.tsx new file mode 100644 index 0000000000..d06ac41e74 --- /dev/null +++ b/test/live-preview/prod/app/live-preview/(pages)/[slug]/page.client.tsx @@ -0,0 +1,44 @@ +'use client' + +import { useLivePreview } from '@payloadcms/live-preview-react' +import React from 'react' + +import type { Page as PageType } from '../../../../../payload-types.js' + +import { renderedPageTitleID } from '../../../../../shared.js' +import { PAYLOAD_SERVER_URL } from '../../_api/serverURL.js' +import { Blocks } from '../../_components/Blocks/index.js' +import { Gutter } from '../../_components/Gutter/index.js' +import { Hero } from '../../_components/Hero/index.js' + +export const PageClient: React.FC<{ + page: PageType +}> = ({ page: initialPage }) => { + const { data } = useLivePreview({ + depth: 2, + initialData: initialPage, + serverURL: PAYLOAD_SERVER_URL, + }) + + return ( + + + + +
{`For Testing: ${data.title}`}
+
+
+ ) +} diff --git a/test/live-preview/prod/app/live-preview/(pages)/[slug]/page.tsx b/test/live-preview/prod/app/live-preview/(pages)/[slug]/page.tsx new file mode 100644 index 0000000000..69d394d4d1 --- /dev/null +++ b/test/live-preview/prod/app/live-preview/(pages)/[slug]/page.tsx @@ -0,0 +1,41 @@ +import { notFound } from 'next/navigation.js' +import React from 'react' + +import type { Page } from '../../../../../payload-types.js' + +import { getDoc } from '../../_api/getDoc.js' +import { getDocs } from '../../_api/getDocs.js' +import { PageClient } from './page.client.js' + +type Args = { + params: Promise<{ slug?: string }> +} +export default async function Page({ params: paramsPromise }: Args) { + const { slug = 'home' } = await paramsPromise + let page: null | Page = null + + try { + page = await getDoc({ + slug, + collection: 'pages', + }) + } catch (error) { + console.error(error) // eslint-disable-line no-console + } + + if (!page) { + return notFound() + } + + return +} + +export async function generateStaticParams() { + process.env.PAYLOAD_DROP_DATABASE = 'false' + try { + const pages = await getDocs('pages') + return pages?.map(({ slug }) => slug) + } catch (error) { + return [] + } +} diff --git a/test/live-preview/prod/app/live-preview/(pages)/posts/[slug]/page.client.tsx b/test/live-preview/prod/app/live-preview/(pages)/posts/[slug]/page.client.tsx new file mode 100644 index 0000000000..7da2cc14da --- /dev/null +++ b/test/live-preview/prod/app/live-preview/(pages)/posts/[slug]/page.client.tsx @@ -0,0 +1,73 @@ +'use client' + +import { useLivePreview } from '@payloadcms/live-preview-react' +import { Gutter } from '@payloadcms/ui' +import React from 'react' + +import type { Post as PostType } from '../../../../../../payload-types.js' + +import { postsSlug, renderedPageTitleID } from '../../../../../../shared.js' +import { PAYLOAD_SERVER_URL } from '../../../_api/serverURL.js' +import { Blocks } from '../../../_components/Blocks/index.js' +import { PostHero } from '../../../_heros/PostHero/index.js' + +export const PostClient: React.FC<{ + post: PostType +}> = ({ post: initialPost }) => { + const { data } = useLivePreview({ + depth: 2, + initialData: initialPost, + serverURL: PAYLOAD_SERVER_URL, + }) + + return ( + + + + + +
{`For Testing: ${data.title}`}
+
+
+ ) +} diff --git a/test/live-preview/prod/app/live-preview/(pages)/posts/[slug]/page.tsx b/test/live-preview/prod/app/live-preview/(pages)/posts/[slug]/page.tsx new file mode 100644 index 0000000000..4066ef226e --- /dev/null +++ b/test/live-preview/prod/app/live-preview/(pages)/posts/[slug]/page.tsx @@ -0,0 +1,45 @@ +import { notFound } from 'next/navigation.js' +import React from 'react' + +import type { Post } from '../../../../../../payload-types.js' + +import { postsSlug } from '../../../../../../shared.js' +import { getDoc } from '../../../_api/getDoc.js' +import { getDocs } from '../../../_api/getDocs.js' +import { PostClient } from './page.client.js' + +type Args = { + params: Promise<{ + slug?: string + }> +} + +export default async function Post({ params: paramsPromise }: Args) { + const { slug = '' } = await paramsPromise + let post: null | Post = null + + try { + post = await getDoc({ + slug, + collection: postsSlug, + }) + } catch (error) { + console.error(error) // eslint-disable-line no-console + } + + if (!post) { + notFound() + } + + return +} + +export async function generateStaticParams() { + process.env.PAYLOAD_DROP_DATABASE = 'false' + try { + const ssrPosts = await getDocs(postsSlug) + return ssrPosts?.map(({ slug }) => slug) + } catch (error) { + return [] + } +} diff --git a/test/live-preview/prod/app/live-preview/(pages)/ssr-autosave/[slug]/RefreshRouteOnSave.tsx b/test/live-preview/prod/app/live-preview/(pages)/ssr-autosave/[slug]/RefreshRouteOnSave.tsx new file mode 100644 index 0000000000..046ec440b4 --- /dev/null +++ b/test/live-preview/prod/app/live-preview/(pages)/ssr-autosave/[slug]/RefreshRouteOnSave.tsx @@ -0,0 +1,12 @@ +'use client' + +import { RefreshRouteOnSave as PayloadLivePreview } from '@payloadcms/live-preview-react' +import { useRouter } from 'next/navigation.js' +import React from 'react' + +import { PAYLOAD_SERVER_URL } from '../../../_api/serverURL.js' + +export const RefreshRouteOnSave: React.FC = () => { + const router = useRouter() + return router.refresh()} serverURL={PAYLOAD_SERVER_URL} /> +} diff --git a/test/live-preview/prod/app/live-preview/(pages)/ssr-autosave/[slug]/page.tsx b/test/live-preview/prod/app/live-preview/(pages)/ssr-autosave/[slug]/page.tsx new file mode 100644 index 0000000000..ab47d80c95 --- /dev/null +++ b/test/live-preview/prod/app/live-preview/(pages)/ssr-autosave/[slug]/page.tsx @@ -0,0 +1,52 @@ +import { Gutter } from '@payloadcms/ui' +import { notFound } from 'next/navigation.js' +import React, { Fragment } from 'react' + +import type { Page } from '../../../../../../payload-types.js' + +import { renderedPageTitleID, ssrAutosavePagesSlug } from '../../../../../../shared.js' +import { getDoc } from '../../../_api/getDoc.js' +import { getDocs } from '../../../_api/getDocs.js' +import { Blocks } from '../../../_components/Blocks/index.js' +import { Hero } from '../../../_components/Hero/index.js' +import { RefreshRouteOnSave } from './RefreshRouteOnSave.js' + +type Args = { + params: Promise<{ + slug?: string + }> +} + +export default async function SSRAutosavePage({ params: paramsPromise }: Args) { + const { slug = '' } = await paramsPromise + const data = await getDoc({ + slug, + collection: ssrAutosavePagesSlug, + draft: true, + }) + + if (!data) { + notFound() + } + + return ( + + + + + +
{`For Testing: ${data.title}`}
+
+
+ ) +} + +export async function generateStaticParams() { + process.env.PAYLOAD_DROP_DATABASE = 'false' + try { + const ssrPages = await getDocs(ssrAutosavePagesSlug) + return ssrPages?.map(({ slug }) => slug) + } catch (error) { + return [] + } +} diff --git a/test/live-preview/prod/app/live-preview/(pages)/ssr/[slug]/RefreshRouteOnSave.tsx b/test/live-preview/prod/app/live-preview/(pages)/ssr/[slug]/RefreshRouteOnSave.tsx new file mode 100644 index 0000000000..046ec440b4 --- /dev/null +++ b/test/live-preview/prod/app/live-preview/(pages)/ssr/[slug]/RefreshRouteOnSave.tsx @@ -0,0 +1,12 @@ +'use client' + +import { RefreshRouteOnSave as PayloadLivePreview } from '@payloadcms/live-preview-react' +import { useRouter } from 'next/navigation.js' +import React from 'react' + +import { PAYLOAD_SERVER_URL } from '../../../_api/serverURL.js' + +export const RefreshRouteOnSave: React.FC = () => { + const router = useRouter() + return router.refresh()} serverURL={PAYLOAD_SERVER_URL} /> +} diff --git a/test/live-preview/prod/app/live-preview/(pages)/ssr/[slug]/page.tsx b/test/live-preview/prod/app/live-preview/(pages)/ssr/[slug]/page.tsx new file mode 100644 index 0000000000..b87055e72c --- /dev/null +++ b/test/live-preview/prod/app/live-preview/(pages)/ssr/[slug]/page.tsx @@ -0,0 +1,52 @@ +import { Gutter } from '@payloadcms/ui' +import { notFound } from 'next/navigation.js' +import React, { Fragment } from 'react' + +import type { Page } from '../../../../../../payload-types.js' + +import { renderedPageTitleID, ssrPagesSlug } from '../../../../../../shared.js' +import { getDoc } from '../../../_api/getDoc.js' +import { getDocs } from '../../../_api/getDocs.js' +import { Blocks } from '../../../_components/Blocks/index.js' +import { Hero } from '../../../_components/Hero/index.js' +import { RefreshRouteOnSave } from './RefreshRouteOnSave.js' + +type Args = { + params: Promise<{ + slug?: string + }> +} + +export default async function SSRPage({ params: paramsPromise }: Args) { + const { slug = ' ' } = await paramsPromise + const data = await getDoc({ + slug, + collection: ssrPagesSlug, + draft: true, + }) + + if (!data) { + notFound() + } + + return ( + + + + + +
{`For Testing: ${data.title}`}
+
+
+ ) +} + +export async function generateStaticParams() { + process.env.PAYLOAD_DROP_DATABASE = 'false' + try { + const ssrPages = await getDocs(ssrPagesSlug) + return ssrPages?.map(({ slug }) => slug) + } catch (error) { + return [] + } +} diff --git a/test/live-preview/prod/app/live-preview/_api/getDoc.ts b/test/live-preview/prod/app/live-preview/_api/getDoc.ts new file mode 100644 index 0000000000..2aee9a8c08 --- /dev/null +++ b/test/live-preview/prod/app/live-preview/_api/getDoc.ts @@ -0,0 +1,37 @@ +import type { CollectionSlug, Where } from 'payload' + +import config from '@payload-config' +import { getPayloadHMR } from '@payloadcms/next/utilities/getPayloadHMR.js' + +export const getDoc = async (args: { + collection: CollectionSlug + depth?: number + draft?: boolean + slug?: string +}): Promise => { + const payload = await getPayloadHMR({ config }) + const { slug, collection, depth = 2, draft } = args || {} + + const where: Where = {} + + if (slug) { + where.slug = { + equals: slug, + } + } + + try { + const { docs } = await payload.find({ + collection, + depth, + where, + draft, + }) + + if (docs[0]) return docs[0] as T + } catch (err) { + console.log('Error getting doc', err) + } + + throw new Error('Error getting doc') +} diff --git a/test/live-preview/prod/app/live-preview/_api/getDocs.ts b/test/live-preview/prod/app/live-preview/_api/getDocs.ts new file mode 100644 index 0000000000..d802e7202d --- /dev/null +++ b/test/live-preview/prod/app/live-preview/_api/getDocs.ts @@ -0,0 +1,20 @@ +import config from '@payload-config' +import { getPayloadHMR } from '@payloadcms/next/utilities/getPayloadHMR.js' + +export const getDocs = async (collection: string): Promise => { + const payload = await getPayloadHMR({ config }) + + try { + const { docs } = await payload.find({ + collection, + depth: 0, + limit: 100, + }) + + return docs as T[] + } catch (err) { + console.error(err) + } + + throw new Error('Error getting docs') +} diff --git a/test/live-preview/prod/app/live-preview/_api/getFooter.ts b/test/live-preview/prod/app/live-preview/_api/getFooter.ts new file mode 100644 index 0000000000..8f4604d056 --- /dev/null +++ b/test/live-preview/prod/app/live-preview/_api/getFooter.ts @@ -0,0 +1,20 @@ +import config from '@payload-config' +import { getPayloadHMR } from '@payloadcms/next/utilities/getPayloadHMR.js' + +import type { Footer } from '../../../../payload-types.js' + +export async function getFooter(): Promise