chore: pre-builds in CI (#5690)

This commit is contained in:
James Mikrut
2024-04-06 14:10:25 -04:00
committed by GitHub
120 changed files with 505 additions and 345 deletions

View File

@@ -250,7 +250,7 @@ jobs:
suite:
- _community
- access-control
# - admin
- admin
- auth
- email
- field-error-states

View File

@@ -14,8 +14,8 @@ type Args = {
}
}
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
generatePageMetadata({ config, params, searchParams })
export const generateMetadata = ({ params }: Args): Promise<Metadata> =>
generatePageMetadata({ config, params })
const NotFound = ({ params, searchParams }: Args) => NotFoundPage({ config, params, searchParams })

View File

@@ -1,35 +0,0 @@
import QueryString from 'qs'
import { PAYLOAD_SERVER_URL } from './serverURL.js'
export const fetchDoc = async <T>(args: {
collection: string
depth?: number
id?: string
slug?: string
}): Promise<T> => {
const { id, slug, collection, depth = 2 } = args || {}
const queryString = QueryString.stringify(
{
...(slug ? { 'where[slug][equals]': slug } : {}),
...(depth ? { depth } : {}),
},
{ addQueryPrefix: true },
)
const doc: T = await fetch(`${PAYLOAD_SERVER_URL}/api/${collection}${queryString}`, {
cache: 'no-store',
headers: {
'Content-Type': 'application/json',
},
method: 'GET',
})
?.then((res) => res.json())
?.then((res) => {
if (res.errors) throw new Error(res?.errors?.[0]?.message ?? 'Error fetching doc')
return res?.docs?.[0]
})
return doc
}

View File

@@ -1,19 +0,0 @@
import { PAYLOAD_SERVER_URL } from './serverURL.js'
export const fetchDocs = async <T>(collection: string): Promise<T[]> => {
const docs: T[] = await fetch(`${PAYLOAD_SERVER_URL}/api/${collection}?depth=0&limit=100`, {
cache: 'no-store',
headers: {
'Content-Type': 'application/json',
},
method: 'GET',
})
?.then((res) => res.json())
?.then((res) => {
if (res.errors) throw new Error(res?.errors?.[0]?.message ?? 'Error fetching docs')
return res?.docs
})
return docs
}

View File

@@ -1,25 +0,0 @@
import type { Footer } from '../../../test/live-preview/payload-types.js'
import { PAYLOAD_SERVER_URL } from './serverURL.js'
export async function fetchFooter(): Promise<Footer> {
if (!PAYLOAD_SERVER_URL) throw new Error('PAYLOAD_SERVER_URL not found')
const footer = await fetch(`${PAYLOAD_SERVER_URL}/api/globals/footer`, {
cache: 'no-store',
headers: {
'Content-Type': 'application/json',
},
method: 'GET',
})
.then((res) => {
if (!res.ok) throw new Error('Error fetching doc')
return res.json()
})
?.then((res) => {
if (res?.errors) throw new Error(res?.errors[0]?.message || 'Error fetching footer')
return res
})
return footer
}

View File

@@ -1,25 +0,0 @@
import type { Header } from '../../../test/live-preview/payload-types.js'
import { PAYLOAD_SERVER_URL } from './serverURL.js'
export async function fetchHeader(): Promise<Header> {
if (!PAYLOAD_SERVER_URL) throw new Error('PAYLOAD_SERVER_URL not found')
const header = await fetch(`${PAYLOAD_SERVER_URL}/api/globals/header`, {
cache: 'no-store',
headers: {
'Content-Type': 'application/json',
},
method: 'GET',
})
?.then((res) => {
if (!res.ok) throw new Error('Error fetching doc')
return res.json()
})
?.then((res) => {
if (res?.errors) throw new Error(res?.errors[0]?.message || 'Error fetching header')
return res
})
return header
}

View File

@@ -10,6 +10,12 @@ const withBundleAnalyzer = bundleAnalyzer({
export default withBundleAnalyzer(
withPayload({
reactStrictMode: false,
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
async redirects() {
return [
{

View File

@@ -2,6 +2,7 @@ import type { I18n } from '@payloadcms/translations'
import type { Metadata } from 'next'
import type { SanitizedConfig } from 'payload/types'
import { getNextI18n } from '@payloadcms/next/utilities/getNextI18n.js'
import { HydrateClientUser } from '@payloadcms/ui/elements/HydrateClientUser'
import { DefaultTemplate } from '@payloadcms/ui/templates/Default'
import React, { Fragment } from 'react'
@@ -10,13 +11,18 @@ import { initPage } from '../../utilities/initPage.js'
import { NotFoundClient } from './index.client.js'
export const generatePageMetadata = async ({
i18n,
config: configPromise,
}: {
config: SanitizedConfig
i18n: I18n
config: Promise<SanitizedConfig> | SanitizedConfig
params?: { [key: string]: string | string[] }
//eslint-disable-next-line @typescript-eslint/require-await
}): Promise<Metadata> => {
const config = await configPromise
const i18n = getNextI18n({
config,
})
return {
title: i18n.t('general:notFound'),
}

View File

@@ -49,7 +49,7 @@ export const generatePageMetadata = async ({ config: configPromise, params }: Ar
const isGlobal = segmentOne === 'globals'
const isCollection = segmentOne === 'collections'
const i18n = await getNextI18n({
const i18n = getNextI18n({
config,
})

View File

@@ -12,7 +12,7 @@ if (process.env.DISABLE_SWC !== 'true') {
const dirname = path.dirname(filename)
const url = pathToFileURL(dirname).toString() + '/'
register('./dist/bin/register/index.js', url)
register('./dist/bin/loader/index.js', url)
}
bin()

View File

@@ -61,7 +61,6 @@
"nodemailer": "6.9.10",
"pino": "8.15.0",
"pino-pretty": "10.2.0",
"pirates": "^4.0.6",
"pluralize": "8.0.0",
"probe-image-size": "^7.2.3",
"sanitize-filename": "1.6.3",

View File

@@ -0,0 +1,40 @@
import type * as ts from 'typescript'
import { transform } from '@swc-node/core'
import { SourcemapMap } from '@swc-node/sourcemap-support'
import { tsCompilerOptionsToSwcConfig } from './read-default-tsconfig.js'
const injectInlineSourceMap = ({
code,
filename,
map,
}: {
code: string
filename: string
map: string | undefined
}): string => {
if (map) {
SourcemapMap.set(filename, map)
const base64Map = Buffer.from(map, 'utf8').toString('base64')
const sourceMapContent = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${base64Map}`
return `${code}\n${sourceMapContent}`
}
return code
}
export async function compile(
sourcecode: string,
filename: string,
options: ts.CompilerOptions & { fallbackToTs?: (filename: string) => boolean },
): Promise<string> {
if (filename.endsWith('.d.ts')) {
return ''
}
const swcRegisterConfig = tsCompilerOptionsToSwcConfig(options, filename)
return transform(sourcecode, filename, swcRegisterConfig).then(({ code, map }) => {
return injectInlineSourceMap({ code, filename, map })
})
}

View File

@@ -5,7 +5,7 @@ import ts from 'typescript'
import { fileURLToPath, pathToFileURL } from 'url'
import { CLIENT_EXTENSIONS } from './clientExtensions.js'
import { compile } from './register.js'
import { compile } from './compile.js'
interface ResolveContext {
conditions: string[]
@@ -27,7 +27,13 @@ const locatedConfig = getTsconfig()
const tsconfig = locatedConfig.config.compilerOptions as unknown as ts.CompilerOptions
tsconfig.module = ts.ModuleKind.ESNext
tsconfig.moduleResolution = ts.ModuleResolutionKind.NodeNext
// Specify bundler resolution for Next.js compatibility.
// We will use TS to resolve file paths for most flexibility
tsconfig.moduleResolution = ts.ModuleResolutionKind.Bundler
// Don't resolve d.ts files, because we aren't type-checking
tsconfig.noDtsResolution = true
const moduleResolutionCache = ts.createModuleResolutionCache(
ts.sys.getCurrentDirectory(),
@@ -38,10 +44,15 @@ const host: ts.ModuleResolutionHost = {
fileExists: ts.sys.fileExists,
readFile: ts.sys.readFile,
}
const EXTENSIONS: string[] = [ts.Extension.Ts, ts.Extension.Tsx, ts.Extension.Dts, ts.Extension.Mts]
const TS_EXTENSIONS: string[] = [
ts.Extension.Ts,
ts.Extension.Tsx,
ts.Extension.Dts,
ts.Extension.Mts,
]
export const resolve: ResolveFn = async (specifier, context, nextResolve) => {
const isTS = EXTENSIONS.some((ext) => specifier.endsWith(ext))
const isTS = TS_EXTENSIONS.some((ext) => specifier.endsWith(ext))
const isClient = CLIENT_EXTENSIONS.some((ext) => specifier.endsWith(ext))
if (isClient) {
@@ -78,16 +89,21 @@ export const resolve: ResolveFn = async (specifier, context, nextResolve) => {
)
// import from local project to local project TS file
if (
resolvedModule &&
!resolvedModule.resolvedFileName.includes('/node_modules/') &&
EXTENSIONS.includes(resolvedModule.extension)
) {
return {
format: 'ts',
shortCircuit: true,
url: pathToFileURL(resolvedModule.resolvedFileName).href,
if (resolvedModule) {
const resolvedIsNodeModule = resolvedModule.resolvedFileName.includes('/node_modules/')
const resolvedIsTS = TS_EXTENSIONS.includes(resolvedModule.extension)
if (!resolvedIsNodeModule && resolvedIsTS) {
return {
format: 'ts',
shortCircuit: true,
url: pathToFileURL(resolvedModule.resolvedFileName).href,
}
}
// We want to use TS "Bundler" moduleResolution for just about all files
// so we pass the TS result here
return nextResolve(pathToFileURL(resolvedModule.resolvedFileName).href)
}
// import from local project to either:
@@ -140,7 +156,7 @@ export const load: LoadFn = async (url, context, nextLoad) => {
if (context.format === 'ts') {
const { source } = await nextLoad(url, context)
const code = typeof source === 'string' ? source : Buffer.from(source).toString()
const compiled = await compile(code, fileURLToPath(url), swcOptions, true)
const compiled = await compile(code, fileURLToPath(url), swcOptions)
return {
format: 'module',
shortCircuit: true,

View File

@@ -1,125 +0,0 @@
import type { Options } from '@swc-node/core'
import { transform, transformSync } from '@swc-node/core'
import { SourcemapMap, installSourceMapSupport } from '@swc-node/sourcemap-support'
import { getTsconfig } from 'get-tsconfig'
import { platform } from 'os'
import { resolve } from 'path'
import { addHook } from 'pirates'
import * as ts from 'typescript'
import { tsCompilerOptionsToSwcConfig } from './read-default-tsconfig.js'
const DEFAULT_EXTENSIONS = ['.js', '.jsx', '.es6', '.es', '.mjs', '.ts', '.tsx']
const PLATFORM = platform()
const injectInlineSourceMap = ({
code,
filename,
map,
}: {
code: string
filename: string
map: string | undefined
}): string => {
if (map) {
SourcemapMap.set(filename, map)
const base64Map = Buffer.from(map, 'utf8').toString('base64')
const sourceMapContent = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${base64Map}`
return `${code}\n${sourceMapContent}`
}
return code
}
export function compile(
sourcecode: string,
filename: string,
options: ts.CompilerOptions & { fallbackToTs?: (filename: string) => boolean },
): string
export function compile(
sourcecode: string,
filename: string,
options: ts.CompilerOptions & { fallbackToTs?: (filename: string) => boolean },
async: false,
): string
export function compile(
sourcecode: string,
filename: string,
options: ts.CompilerOptions & { fallbackToTs?: (filename: string) => boolean },
async: true,
): Promise<string>
export function compile(
sourcecode: string,
filename: string,
options: ts.CompilerOptions & { fallbackToTs?: (filename: string) => boolean },
async: boolean,
): Promise<string> | string
export function compile(
sourcecode: string,
filename: string,
options: ts.CompilerOptions & { fallbackToTs?: (filename: string) => boolean },
async = false,
) {
if (filename.endsWith('.d.ts')) {
return ''
}
if (options.files && (options.files as string[]).length) {
if (
PLATFORM === 'win32' &&
(options.files as string[]).every((file) => filename !== resolve(process.cwd(), file))
) {
return sourcecode
}
if (
PLATFORM !== 'win32' &&
(options.files as string[]).every((file) => !filename.endsWith(file))
) {
return sourcecode
}
}
if (options && typeof options.fallbackToTs === 'function' && options.fallbackToTs(filename)) {
delete options.fallbackToTs
const { outputText, sourceMapText } = ts.transpileModule(sourcecode, {
compilerOptions: options,
fileName: filename,
})
return injectInlineSourceMap({ code: outputText, filename, map: sourceMapText })
}
let swcRegisterConfig: Options
if (process.env.SWCRC) {
// when SWCRC environment variable is set to true it will use swcrc file
swcRegisterConfig = {
swc: {
swcrc: true,
},
}
} else {
swcRegisterConfig = tsCompilerOptionsToSwcConfig(options, filename)
}
if (async) {
return transform(sourcecode, filename, swcRegisterConfig).then(({ code, map }) => {
return injectInlineSourceMap({ code, filename, map })
})
} else {
const { code, map } = transformSync(sourcecode, filename, swcRegisterConfig)
return injectInlineSourceMap({ code, filename, map })
}
}
export function register(options: Partial<ts.CompilerOptions> = {}, hookOpts = {}) {
const locatedConfig = getTsconfig()
const tsconfig = locatedConfig.config.compilerOptions as unknown as ts.CompilerOptions
options = tsconfig
// options.module = ts.ModuleKind.CommonJS
installSourceMapSupport()
return addHook((code, filename) => compile(code, filename, options), {
exts: DEFAULT_EXTENSIONS,
...hookOpts,
})
}

View File

@@ -1,44 +0,0 @@
import type pino from 'pino'
import { createRequire } from 'module'
import path from 'path'
import type { SanitizedConfig } from './types.js'
import { CLIENT_EXTENSIONS } from '../bin/register/clientExtensions.js'
import Logger from '../utilities/logger.js'
import { findConfig } from './find.js'
import { validateSchema } from './validate.js'
const require = createRequire(import.meta.url)
const loadConfig = async (logger?: pino.Logger): Promise<SanitizedConfig> => {
const localLogger = logger ?? Logger()
const configPath = findConfig()
CLIENT_EXTENSIONS.forEach((ext) => {
require.extensions[ext] = () => null
})
const configPromise = await import(configPath)
let config = await configPromise
if ('default' in config) config = await config.default
if (process.env.NODE_ENV !== 'production') {
config = validateSchema(config, localLogger)
}
return {
...config,
paths: {
config: configPath,
configDir: path.dirname(configPath),
rawConfig: configPath,
},
}
}
export default loadConfig

View File

@@ -1,7 +1,6 @@
'use client'
// TODO: abstract the `next/navigation` dependency out from this component
import { usePathname, useRouter } from 'next/navigation.js'
import queryString from 'qs'
import { useRouter } from 'next/navigation.js'
import React, { useCallback } from 'react'
export type SortColumnProps = {
@@ -22,9 +21,8 @@ const baseClass = 'sort-column'
export const SortColumn: React.FC<SortColumnProps> = (props) => {
const { name, Label, disable = false, label } = props
const { searchParams } = useSearchParams()
const { searchParams, stringifyParams } = useSearchParams()
const router = useRouter()
const pathname = usePathname()
const { t } = useTranslation()
const { sort } = searchParams
@@ -40,17 +38,16 @@ export const SortColumn: React.FC<SortColumnProps> = (props) => {
const setSort = useCallback(
(newSort) => {
const search = queryString.stringify(
{
...searchParams,
sort: newSort,
},
{ addQueryPrefix: true },
router.replace(
stringifyParams({
params: {
sort: newSort,
},
replace: true,
}),
)
router.replace(`${pathname}?${search}`)
},
[searchParams, pathname, router],
[router, stringifyParams],
)
return (

3
pnpm-lock.yaml generated
View File

@@ -769,9 +769,6 @@ importers:
pino-pretty:
specifier: 10.2.0
version: 10.2.0
pirates:
specifier: ^4.0.6
version: 4.0.6
pluralize:
specifier: 8.0.0
version: 8.0.0

View File

@@ -72,9 +72,16 @@ describe('admin', () => {
let disableDuplicateURL: AdminUrlUtil
let serverURL: string
beforeAll(async ({ browser }) => {
beforeAll(async ({ browser }, testInfo) => {
const prebuild = Boolean(process.env.CI)
if (prebuild) testInfo.setTimeout(testInfo.timeout * 2)
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({ dirname }))
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
dirname,
prebuild,
}))
geoUrl = new AdminUrlUtil(serverURL, geoCollectionSlug)
postsUrl = new AdminUrlUtil(serverURL, postsCollectionSlug)
customViewsURL = new AdminUrlUtil(serverURL, customViews2CollectionSlug)
@@ -1271,10 +1278,14 @@ describe('admin', () => {
const downChevron = page.locator('#heading-number .sort-column__desc')
await upChevron.click()
await page.waitForURL(/sort=number/)
await expect(page.locator('.row-1 .cell-number')).toHaveText('1')
await expect(page.locator('.row-2 .cell-number')).toHaveText('2')
await downChevron.click()
await page.waitForURL(/sort=-number/)
await expect(page.locator('.row-1 .cell-number')).toHaveText('2')
await expect(page.locator('.row-2 .cell-number')).toHaveText('1')
})

View File

@@ -1,15 +1,11 @@
import minimist from 'minimist'
import { MongoMemoryReplSet } from 'mongodb-memory-server'
import { nextDev } from 'next/dist/cli/next-dev.js'
import { dirname, resolve } from 'path'
import { fileURLToPath } from 'url'
import open, { openApp, apps } from 'open'
import open from 'open'
import { getNextJSRootDir } from './helpers/getNextJSRootDir.js'
import { createTestHooks } from './testHooks.js'
const _filename = fileURLToPath(import.meta.url)
const _dirname = dirname(_filename)
process.env.PAYLOAD_DROP_DATABASE = 'true'
const {
@@ -26,7 +22,7 @@ process.env.PAYLOAD_DROP_DATABASE = 'true'
const { afterTest, beforeTest } = await createTestHooks(testSuiteArg)
await beforeTest()
const rootDir = resolve(_dirname, '../')
const rootDir = getNextJSRootDir(testSuiteArg)
// Open the admin if the -o flag is passed
if (args.o) {

View File

@@ -42,9 +42,16 @@ let serverURL: string
// If we want to make this run in parallel: test.describe.configure({ mode: 'parallel' })
describe('fields', () => {
beforeAll(async ({ browser }) => {
beforeAll(async ({ browser }, testInfo) => {
const prebuild = Boolean(process.env.CI)
if (prebuild) testInfo.setTimeout(testInfo.timeout * 3)
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
;({ payload, serverURL } = await initPayloadE2ENoConfig({ dirname }))
;({ payload, serverURL } = await initPayloadE2ENoConfig({
dirname,
prebuild,
}))
const context = await browser.newContext()
page = await context.newPage()
@@ -696,6 +703,8 @@ describe('fields', () => {
'#field-customBlocks input[name="customBlocks.0.block1Title"]',
)
await page.mouse.wheel(0, 1750)
await customBlocks.scrollIntoViewIfNeeded()
await expect(customBlocks).toHaveValue('Block 1: Prefilled Title')
@@ -775,6 +784,7 @@ describe('fields', () => {
const assertText3 = 'array row 3'
const assertGroupText3 = 'text in group in row 3'
await page.goto(url.create)
await page.mouse.wheel(0, 1750)
await page.locator('#field-potentiallyEmptyArray').scrollIntoViewIfNeeded()
await wait(300)

7
test/helpers/build.js Normal file
View File

@@ -0,0 +1,7 @@
import nextBuild from 'next/dist/build/index.js'
const build = async () => {
await nextBuild.default(process.env.NEXTJS_DIR, false, false, false, true, true, false, 'default')
}
build()

View File

@@ -0,0 +1,25 @@
import fs from 'fs'
import { dirname, resolve } from 'path'
import { fileURLToPath } from 'url'
const _filename = fileURLToPath(import.meta.url)
const _dirname = dirname(_filename)
export const getNextJSRootDir = (testSuite) => {
const testSuiteDir = resolve(_dirname, `../${testSuite}`)
let hasNextConfig = false
try {
fs.accessSync(`${testSuiteDir}/next.config.mjs`, fs.constants.F_OK)
hasNextConfig = true
} catch (err) {
// Swallow err - no config found
}
if (hasNextConfig) return testSuiteDir
// If no next config found in test suite,
// return monorepo root dir
return resolve(_dirname, '../../')
}

View File

@@ -1,17 +1,24 @@
import { createServer } from 'http'
import nextImport from 'next'
import path from 'path'
import { spawn } from 'node:child_process'
import { dirname, resolve } from 'path'
import { wait } from 'payload/utilities'
import { parse } from 'url'
import { fileURLToPath } from 'url'
import type { GeneratedTypes } from './sdk/types.js'
import { createTestHooks } from '../testHooks.js'
import { getNextJSRootDir } from './getNextJSRootDir.js'
import { PayloadTestSDK } from './sdk/index.js'
import startMemoryDB from './startMemoryDB.js'
const _filename = fileURLToPath(import.meta.url)
const _dirname = dirname(_filename)
type Args = {
dirname: string
prebuild?: boolean
}
type Result<T extends GeneratedTypes<T>> = {
@@ -21,6 +28,7 @@ type Result<T extends GeneratedTypes<T>> = {
export async function initPayloadE2ENoConfig<T extends GeneratedTypes<T>>({
dirname,
prebuild,
}: Args): Promise<Result<T>> {
const testSuiteName = dirname.split('/').pop()
const { beforeTest } = await createTestHooks(testSuiteName)
@@ -32,12 +40,36 @@ export async function initPayloadE2ENoConfig<T extends GeneratedTypes<T>>({
await startMemoryDB()
const dir = getNextJSRootDir(testSuiteName)
if (prebuild) {
await new Promise<void>((res, rej) => {
const buildArgs = ['--max-old-space-size=8192', resolve(_dirname, 'build.js')]
const childProcess = spawn('node', buildArgs, {
stdio: 'inherit',
env: {
PATH: process.env.PATH,
NODE_ENV: 'production',
NEXTJS_DIR: dir,
},
})
childProcess.on('close', (code) => {
if (code === 0) res()
rej()
})
})
}
process.env.NODE_OPTIONS = '--max-old-space-size=8192'
// @ts-expect-error
const app = nextImport({
dev: true,
dev: !prebuild,
hostname: 'localhost',
port,
dir: path.resolve(dirname, '../../'),
dir,
})
const handle = app.getRequestHandler()

View File

@@ -22,7 +22,5 @@ export default async () => {
global._mongoMemoryServer = db
process.env.MONGODB_MEMORY_SERVER_URI = `${global._mongoMemoryServer.getUri()}&retryWrites=true`
console.log(process.env.MONGODB_MEMORY_SERVER_URI)
}
}

View File

@@ -0,0 +1,22 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
import type { Metadata } from 'next'
import config from '@payload-config'
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
import { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views/NotFound/index.js'
type Args = {
params: {
segments: string[]
}
searchParams: {
[key: string]: string | string[]
}
}
export const generateMetadata = ({ params }: Args): Promise<Metadata> =>
generatePageMetadata({ config, params })
const NotFound = ({ params, searchParams }: Args) => NotFoundPage({ config, params, searchParams })
export default NotFound

View File

@@ -0,0 +1,22 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
import type { Metadata } from 'next'
import config from '@payload-config'
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
import { RootPage, generatePageMetadata } from '@payloadcms/next/views/Root/index.js'
type Args = {
params: {
segments: string[]
}
searchParams: {
[key: string]: string | string[]
}
}
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
generatePageMetadata({ config, params, searchParams })
const Page = ({ params, searchParams }: Args) => RootPage({ config, params, searchParams })
export default Page

View File

@@ -0,0 +1,9 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY it because it could be re-written at any time. */
import config from '@payload-config'
import { REST_DELETE, REST_GET, REST_PATCH, REST_POST } from '@payloadcms/next/routes/index.js'
export const GET = REST_GET(config)
export const POST = REST_POST(config)
export const DELETE = REST_DELETE(config)
export const PATCH = REST_PATCH(config)

View File

@@ -0,0 +1,6 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY it because it could be re-written 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)

View File

@@ -0,0 +1,6 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY it because it could be re-written at any time. */
import config from '@payload-config'
import { GRAPHQL_POST } from '@payloadcms/next/routes/index.js'
export const POST = GRAPHQL_POST(config)

View File

@@ -0,0 +1,8 @@
#custom-css {
font-family: monospace;
background-image: url('/placeholder.png');
}
#custom-css::after {
content: 'custom-css';
}

View File

@@ -0,0 +1,15 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
import configPromise from '@payload-config'
import { RootLayout } from '@payloadcms/next/layouts/Root/index.js'
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
import React from 'react'
import './custom.scss'
type Args = {
children: React.ReactNode
}
const Layout = ({ children }: Args) => <RootLayout config={configPromise}>{children}</RootLayout>
export default Layout

View File

@@ -3,7 +3,7 @@
import { useLivePreview } from '@payloadcms/live-preview-react'
import React from 'react'
import type { Post as PostType } from '../../../../../test/live-preview/payload-types.js'
import type { Post as PostType } from '../../../../../payload-types.js'
import { PAYLOAD_SERVER_URL } from '../../../_api/serverURL.js'
import { Blocks } from '../../../_components/Blocks/index.js'

View File

@@ -1,7 +1,7 @@
import { notFound } from 'next/navigation.js'
import React from 'react'
import type { Post } from '../../../../../test/live-preview/payload-types.js'
import type { Post } from '../../../../../payload-types.js'
import { fetchDoc } from '../../../_api/fetchDoc.js'
import { fetchDocs } from '../../../_api/fetchDocs.js'

View File

@@ -0,0 +1,35 @@
import type { Where } from 'payload/types'
import config from '@payload-config'
import { getPayloadHMR } from '@payloadcms/next/utilities/getPayloadHMR.js'
export const fetchDoc = async <T>(args: {
collection: string
depth?: number
slug?: string
}): Promise<T> => {
const payload = await getPayloadHMR({ config })
const { slug, collection, depth = 2 } = args || {}
const where: Where = {}
if (slug) {
where.slug = {
equals: slug,
}
}
try {
const { docs } = await payload.find({
collection,
depth,
where,
})
if (docs[0]) return docs[0] as T
} catch (err) {
console.log('Error fetching doc', err)
}
throw new Error('Error fetching doc')
}

View File

@@ -0,0 +1,20 @@
import config from '@payload-config'
import { getPayloadHMR } from '@payloadcms/next/utilities/getPayloadHMR.js'
export const fetchDocs = async <T>(collection: string): Promise<T[]> => {
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 fetching docs')
}

View File

@@ -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 fetchFooter(): Promise<Footer> {
const payload = await getPayloadHMR({ config })
try {
const footer = await payload.findGlobal({
slug: 'footer',
})
return footer as Footer
} catch (err) {
console.error(err)
}
throw new Error('Error fetching footer.')
}

View File

@@ -0,0 +1,20 @@
import config from '@payload-config'
import { getPayloadHMR } from '@payloadcms/next/utilities/getPayloadHMR.js'
import type { Header } from '../../../payload-types.js'
export async function fetchHeader(): Promise<Header> {
const payload = await getPayloadHMR({ config })
try {
const header = await payload.findGlobal({
slug: 'header',
})
return header as Header
} catch (err) {
console.error(err)
}
throw new Error('Error fetching header.')
}

View File

@@ -1,4 +1,4 @@
import type { Page } from '../../../../test/live-preview/payload-types.js'
import type { Page } from '../../../../payload-types.js'
export type ArchiveBlockProps = Extract<
Exclude<Page['layout'], undefined>[0],

View File

@@ -1,6 +1,6 @@
import React from 'react'
import type { Page } from '../../../../test/live-preview/payload-types.js'
import type { Page } from '../../../../payload-types.js'
import { Gutter } from '../../_components/Gutter/index.js'
import { CMSLink } from '../../_components/Link/index.js'

View File

@@ -1,6 +1,6 @@
import React, { Fragment } from 'react'
import type { Page } from '../../../../test/live-preview/payload-types.js'
import type { Page } from '../../../../payload-types.js'
import { Gutter } from '../../_components/Gutter/index.js'
import { CMSLink } from '../../_components/Link/index.js'

View File

@@ -2,7 +2,7 @@ import type { StaticImageData } from 'next/image.js'
import React from 'react'
import type { Page } from '../../../../test/live-preview/payload-types.js'
import type { Page } from '../../../../payload-types.js'
import { Gutter } from '../../_components/Gutter/index.js'
import { Media } from '../../_components/Media/index.js'

View File

@@ -1,6 +1,6 @@
import React from 'react'
import type { Post } from '../../../../test/live-preview/payload-types.js'
import type { Post } from '../../../../payload-types.js'
import { Card } from '../../_components/Card/index.js'
import { Gutter } from '../../_components/Gutter/index.js'

View File

@@ -1,6 +1,6 @@
import React, { Fragment } from 'react'
import type { Page } from '../../../../test/live-preview/payload-types.js'
import type { Page } from '../../../../payload-types.js'
import { Gutter } from '../../_components/Gutter/index.js'
import RichText from '../../_components/RichText/index.js'

View File

@@ -1,6 +1,6 @@
import React, { Fragment } from 'react'
import type { Page } from '../../../../test/live-preview/payload-types.js'
import type { Page } from '../../../../payload-types.js'
import type { RelationshipsBlockProps } from '../../_blocks/Relationships/index.js'
import type { VerticalPaddingOptions } from '../VerticalPadding/index.js'

View File

@@ -1,7 +1,7 @@
import LinkWithDefault from 'next/link.js'
import React, { Fragment } from 'react'
import type { Post } from '../../../../test/live-preview/payload-types.js'
import type { Post } from '../../../../payload-types.js'
import { Media } from '../Media/index.js'
import classes from './index.module.scss'

View File

@@ -3,7 +3,7 @@
import qs from 'qs'
import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'
import type { Post } from '../../../../../test/live-preview/payload-types.js'
import type { Post } from '../../../../../payload-types.js'
import type { ArchiveBlockProps } from '../../../_blocks/ArchiveBlock/types.js'
import { PAYLOAD_SERVER_URL } from '../../../_api/serverURL.js'

View File

@@ -1,7 +1,7 @@
import LinkWithDefault from 'next/link.js'
import React from 'react'
import type { Page, Post } from '../../../../test/live-preview/payload-types.js'
import type { Page, Post } from '../../../../payload-types.js'
import type { Props as ButtonProps } from '../Button/index.js'
import { Button } from '../Button/index.js'

View File

@@ -11,7 +11,7 @@ export const Media: React.FC<Props> = (props) => {
const { className, htmlElement = 'div', resource } = props
const isVideo = typeof resource !== 'string' && resource?.mimeType?.includes('video')
const Tag = (htmlElement as ElementType) || Fragment
const Tag = (htmlElement) || Fragment
return (
<Tag

View File

@@ -1,7 +1,7 @@
import type { StaticImageData } from 'next/image'
import type { ElementType, Ref } from 'react'
import type { Media as MediaType } from '../../../payload-types'
import type { Media as MediaType } from '../../../payload-types.js'
export interface Props {
alt?: string

Some files were not shown because too many files have changed in this diff Show More