feat(templates): added int and e2e tests to blank and website templates (#12866)
This PR adds int tests with vitest and e2e tests with playwright directly into our templates. The following are also updated: - bumps core turbo to 2.5.4 in monorepo - blank and website templates moved up to be part of the monorepo workspace - this means we now have thes templates filtered out in pnpm commands in package.json - they will now by default use workspace packages which we can use for manual testing and int and e2e tests - note that turbo doesnt work with these for dev in monorepo context - CPA script will fetch latest version and then replace `workspace:*` or the pinned version in the package.json before installation - blank template no longer uses _template as a base, this is to simplify management for workspace - updated the generate template variations script
This commit is contained in:
51
.github/workflows/main.yml
vendored
51
.github/workflows/main.yml
vendored
@@ -523,24 +523,30 @@ jobs:
|
|||||||
# report-tag: ${{ matrix.suite }}
|
# report-tag: ${{ matrix.suite }}
|
||||||
# job-summary: true
|
# job-summary: true
|
||||||
|
|
||||||
# Build listed templates with packed local packages
|
# Build listed templates with packed local packages and then runs their int and e2e tests
|
||||||
build-templates:
|
build-and-test-templates:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: build
|
needs: build
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- template: blank
|
- template: blank
|
||||||
database: mongodb
|
database: mongodb
|
||||||
|
|
||||||
- template: website
|
- template: website
|
||||||
database: mongodb
|
database: mongodb
|
||||||
|
|
||||||
- template: with-payload-cloud
|
- template: with-payload-cloud
|
||||||
database: mongodb
|
database: mongodb
|
||||||
|
|
||||||
- template: with-vercel-mongodb
|
- template: with-vercel-mongodb
|
||||||
database: mongodb
|
database: mongodb
|
||||||
|
|
||||||
# Postgres
|
# Postgres
|
||||||
- template: with-postgres
|
- template: with-postgres
|
||||||
database: postgres
|
database: postgres
|
||||||
|
|
||||||
- template: with-vercel-postgres
|
- template: with-vercel-postgres
|
||||||
database: postgres
|
database: postgres
|
||||||
|
|
||||||
@@ -615,6 +621,45 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
NODE_OPTIONS: --max-old-space-size=8096
|
NODE_OPTIONS: --max-old-space-size=8096
|
||||||
|
|
||||||
|
- name: Store Playwright's Version
|
||||||
|
run: |
|
||||||
|
# Extract the version number using a more targeted regex pattern with awk
|
||||||
|
PLAYWRIGHT_VERSION=$(pnpm ls @playwright/test --depth=0 | awk '/@playwright\/test/ {print $2}')
|
||||||
|
echo "Playwright's Version: $PLAYWRIGHT_VERSION"
|
||||||
|
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Cache Playwright Browsers for Playwright's Version
|
||||||
|
id: cache-playwright-browsers
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.cache/ms-playwright
|
||||||
|
key: playwright-browsers-${{ env.PLAYWRIGHT_VERSION }}
|
||||||
|
|
||||||
|
- name: Setup Playwright - Browsers and Dependencies
|
||||||
|
if: steps.cache-playwright-browsers.outputs.cache-hit != 'true'
|
||||||
|
run: pnpm exec playwright install --with-deps chromium
|
||||||
|
|
||||||
|
- name: Setup Playwright - Dependencies-only
|
||||||
|
if: steps.cache-playwright-browsers.outputs.cache-hit == 'true'
|
||||||
|
run: pnpm exec playwright install-deps chromium
|
||||||
|
|
||||||
|
- name: Runs Template Int Tests
|
||||||
|
run: pnpm --filter ${{ matrix.template }} run test:int
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: --max-old-space-size=8096
|
||||||
|
PAYLOAD_DATABASE: ${{ matrix.database }}
|
||||||
|
POSTGRES_URL: ${{ env.POSTGRES_URL }}
|
||||||
|
MONGODB_URL: mongodb://localhost:27017/payloadtests
|
||||||
|
|
||||||
|
- name: Runs Template E2E Tests
|
||||||
|
run: PLAYWRIGHT_JSON_OUTPUT_NAME=results_${{ matrix.template }}.json pnpm --filter ${{ matrix.template }} test:e2e
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: --max-old-space-size=8096
|
||||||
|
PAYLOAD_DATABASE: ${{ matrix.database }}
|
||||||
|
POSTGRES_URL: ${{ env.POSTGRES_URL }}
|
||||||
|
MONGODB_URL: mongodb://localhost:27017/payloadtests
|
||||||
|
NEXT_TELEMETRY_DISABLED: 1
|
||||||
|
|
||||||
tests-type-generation:
|
tests-type-generation:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: [changes, build]
|
needs: [changes, build]
|
||||||
@@ -650,7 +695,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- lint
|
- lint
|
||||||
- build
|
- build
|
||||||
- build-templates
|
- build-and-test-templates
|
||||||
- tests-unit
|
- tests-unit
|
||||||
- tests-int
|
- tests-int
|
||||||
- tests-e2e
|
- tests-e2e
|
||||||
|
|||||||
@@ -75,9 +75,7 @@ import * as Sentry from '@sentry/nextjs'
|
|||||||
const config = buildConfig({
|
const config = buildConfig({
|
||||||
collections: [Pages, Media],
|
collections: [Pages, Media],
|
||||||
plugins: [
|
plugins: [
|
||||||
sentryPlugin({
|
sentryPlugin({ Sentry })
|
||||||
Sentry,
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -101,7 +99,7 @@ export default buildConfig({
|
|||||||
pg, // Inject the patched pg driver for Sentry instrumentation
|
pg, // Inject the patched pg driver for Sentry instrumentation
|
||||||
}),
|
}),
|
||||||
plugins: [
|
plugins: [
|
||||||
sentryPlugin({ Sentry }),
|
sentryPlugin({ Sentry })
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "website",
|
"name": "astro-website",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -11,11 +11,11 @@
|
|||||||
"bf": "pnpm run build:force",
|
"bf": "pnpm run build:force",
|
||||||
"build": "pnpm run build:core",
|
"build": "pnpm run build:core",
|
||||||
"build:admin-bar": "turbo build --filter \"@payloadcms/admin-bar\"",
|
"build:admin-bar": "turbo build --filter \"@payloadcms/admin-bar\"",
|
||||||
"build:all": "turbo build",
|
"build:all": "turbo build --filter \"!blank\" --filter \"!website\"",
|
||||||
"build:app": "next build",
|
"build:app": "next build",
|
||||||
"build:app:analyze": "cross-env ANALYZE=true next build",
|
"build:app:analyze": "cross-env ANALYZE=true next build",
|
||||||
"build:clean": "pnpm clean:build",
|
"build:clean": "pnpm clean:build",
|
||||||
"build:core": "turbo build --filter \"!@payloadcms/plugin-*\" --filter \"!@payloadcms/storage-*\"",
|
"build:core": "turbo build --filter \"!@payloadcms/plugin-*\" --filter \"!@payloadcms/storage-*\" --filter \"!blank\" --filter \"!website\"",
|
||||||
"build:core:force": "pnpm clean:build && pnpm build:core --no-cache --force",
|
"build:core:force": "pnpm clean:build && pnpm build:core --no-cache --force",
|
||||||
"build:create-payload-app": "turbo build --filter create-payload-app",
|
"build:create-payload-app": "turbo build --filter create-payload-app",
|
||||||
"build:db-mongodb": "turbo build --filter \"@payloadcms/db-mongodb\"",
|
"build:db-mongodb": "turbo build --filter \"@payloadcms/db-mongodb\"",
|
||||||
@@ -79,9 +79,9 @@
|
|||||||
"docker:start": "docker compose -f test/docker-compose.yml up -d",
|
"docker:start": "docker compose -f test/docker-compose.yml up -d",
|
||||||
"docker:stop": "docker compose -f test/docker-compose.yml down",
|
"docker:stop": "docker compose -f test/docker-compose.yml down",
|
||||||
"force:build": "pnpm run build:core:force",
|
"force:build": "pnpm run build:core:force",
|
||||||
"lint": "turbo run lint --log-order=grouped --continue",
|
"lint": "turbo run lint --log-order=grouped --continue --filter \"!blank\" --filter \"!website\"",
|
||||||
"lint-staged": "lint-staged",
|
"lint-staged": "lint-staged",
|
||||||
"lint:fix": "turbo run lint:fix --log-order=grouped --continue",
|
"lint:fix": "turbo run lint:fix --log-order=grouped --continue --filter \"!blank\" --filter \"!website\"",
|
||||||
"obliterate-playwright-cache-macos": "rm -rf ~/Library/Caches/ms-playwright && find /System/Volumes/Data/private/var/folders -type d -name 'playwright*' -exec rm -rf {} +",
|
"obliterate-playwright-cache-macos": "rm -rf ~/Library/Caches/ms-playwright && find /System/Volumes/Data/private/var/folders -type d -name 'playwright*' -exec rm -rf {} +",
|
||||||
"prepare": "husky",
|
"prepare": "husky",
|
||||||
"prepare-run-test-against-prod": "pnpm bf && rm -rf test/packed && rm -rf test/node_modules && rm -rf app && rm -f test/pnpm-lock.yaml && pnpm run script:pack --all --no-build --dest test/packed && pnpm runts test/setupProd.ts && cd test && pnpm i --ignore-workspace && cd ..",
|
"prepare-run-test-against-prod": "pnpm bf && rm -rf test/packed && rm -rf test/node_modules && rm -rf app && rm -f test/pnpm-lock.yaml && pnpm run script:pack --all --no-build --dest test/packed && pnpm runts test/setupProd.ts && cd test && pnpm i --ignore-workspace && cd ..",
|
||||||
@@ -181,7 +181,7 @@
|
|||||||
"tempy": "1.0.1",
|
"tempy": "1.0.1",
|
||||||
"tstyche": "^3.1.1",
|
"tstyche": "^3.1.1",
|
||||||
"tsx": "4.19.2",
|
"tsx": "4.19.2",
|
||||||
"turbo": "^2.3.3",
|
"turbo": "^2.5.4",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.7.1",
|
"packageManager": "pnpm@9.7.1",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import path from 'path'
|
|||||||
|
|
||||||
import type { CliArgs, DbType, ProjectExample, ProjectTemplate } from '../types.js'
|
import type { CliArgs, DbType, ProjectExample, ProjectTemplate } from '../types.js'
|
||||||
|
|
||||||
import { createProject } from './create-project.js'
|
import { createProject, updatePackageJSONDependencies } from './create-project.js'
|
||||||
import { dbReplacements } from './replacements.js'
|
import { dbReplacements } from './replacements.js'
|
||||||
import { getValidTemplates } from './templates.js'
|
import { getValidTemplates } from './templates.js'
|
||||||
|
|
||||||
@@ -179,5 +179,37 @@ describe('createProject', () => {
|
|||||||
expect(content).toContain(dbReplacement.configReplacement().join('\n'))
|
expect(content).toContain(dbReplacement.configReplacement().join('\n'))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('updates package.json', () => {
|
||||||
|
it('updates package name and bumps workspace versions', async () => {
|
||||||
|
const latestVersion = '3.0.0'
|
||||||
|
const initialJSON = {
|
||||||
|
name: 'test-project',
|
||||||
|
version: '1.0.0',
|
||||||
|
dependencies: {
|
||||||
|
'@payloadcms/db-mongodb': 'workspace:*',
|
||||||
|
payload: 'workspace:*',
|
||||||
|
'@payloadcms/ui': 'workspace:*',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const correctlyModifiedJSON = {
|
||||||
|
name: 'test-project',
|
||||||
|
version: '1.0.0',
|
||||||
|
dependencies: {
|
||||||
|
'@payloadcms/db-mongodb': `${latestVersion}`,
|
||||||
|
payload: `${latestVersion}`,
|
||||||
|
'@payloadcms/ui': `${latestVersion}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePackageJSONDependencies({
|
||||||
|
latestVersion,
|
||||||
|
packageJson: initialJSON,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(initialJSON).toEqual(correctlyModifiedJSON)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -129,7 +129,11 @@ export async function createProject(
|
|||||||
const spinner = p.spinner()
|
const spinner = p.spinner()
|
||||||
spinner.start('Checking latest Payload version...')
|
spinner.start('Checking latest Payload version...')
|
||||||
|
|
||||||
await updatePackageJSON({ projectDir, projectName })
|
const payloadVersion = await getLatestPackageVersion({ packageName: 'payload' })
|
||||||
|
|
||||||
|
spinner.stop(`Found latest version of Payload ${payloadVersion}`)
|
||||||
|
|
||||||
|
await updatePackageJSON({ latestVersion: payloadVersion, projectDir, projectName })
|
||||||
|
|
||||||
if ('template' in args) {
|
if ('template' in args) {
|
||||||
if (args.template.type === 'plugin') {
|
if (args.template.type === 'plugin') {
|
||||||
@@ -177,17 +181,105 @@ export async function createProject(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the package.json file into an object and then does the following:
|
||||||
|
* - Sets the `name` property to the provided `projectName`.
|
||||||
|
* - Bumps the payload packages from workspace:* to the latest version.
|
||||||
|
* - Writes the updated object back to the package.json file.
|
||||||
|
*/
|
||||||
export async function updatePackageJSON(args: {
|
export async function updatePackageJSON(args: {
|
||||||
|
/**
|
||||||
|
* The latest version of Payload to use in the package.json.
|
||||||
|
*/
|
||||||
|
latestVersion: string
|
||||||
projectDir: string
|
projectDir: string
|
||||||
|
/**
|
||||||
|
* The name of the project to set in package.json.
|
||||||
|
*/
|
||||||
projectName: string
|
projectName: string
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
const { projectDir, projectName } = args
|
const { latestVersion, projectDir, projectName } = args
|
||||||
const packageJsonPath = path.resolve(projectDir, 'package.json')
|
const packageJsonPath = path.resolve(projectDir, 'package.json')
|
||||||
try {
|
try {
|
||||||
const packageObj = await fse.readJson(packageJsonPath)
|
const packageObj = await fse.readJson(packageJsonPath)
|
||||||
packageObj.name = projectName
|
packageObj.name = projectName
|
||||||
|
|
||||||
|
updatePackageJSONDependencies({
|
||||||
|
latestVersion,
|
||||||
|
packageJson: packageObj,
|
||||||
|
})
|
||||||
|
|
||||||
await fse.writeJson(packageJsonPath, packageObj, { spaces: 2 })
|
await fse.writeJson(packageJsonPath, packageObj, { spaces: 2 })
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
warning(`Unable to update name in package.json. ${err instanceof Error ? err.message : ''}`)
|
warning(`Unable to update name in package.json. ${err instanceof Error ? err.message : ''}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively updates a JSON object to replace all instances of `workspace:` with the latest version pinned.
|
||||||
|
*
|
||||||
|
* Does not return and instead modifies the `packageJson` object in place.
|
||||||
|
*/
|
||||||
|
export function updatePackageJSONDependencies(args: {
|
||||||
|
latestVersion: string
|
||||||
|
packageJson: Record<string, unknown>
|
||||||
|
}): void {
|
||||||
|
const { latestVersion, packageJson } = args
|
||||||
|
|
||||||
|
const updatedDependencies = Object.entries(packageJson.dependencies || {}).reduce(
|
||||||
|
(acc, [key, value]) => {
|
||||||
|
if (typeof value === 'string' && value.startsWith('workspace:')) {
|
||||||
|
acc[key] = `${latestVersion}`
|
||||||
|
} else if (key === 'payload' || key.startsWith('@payloadcms')) {
|
||||||
|
acc[key] = `${latestVersion}`
|
||||||
|
} else {
|
||||||
|
acc[key] = value
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
},
|
||||||
|
{} as Record<string, string>,
|
||||||
|
)
|
||||||
|
packageJson.dependencies = updatedDependencies
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the latest version of a package from the NPM registry.
|
||||||
|
*
|
||||||
|
* Used in determining the latest version of Payload to use in the generated templates.
|
||||||
|
*/
|
||||||
|
async function getLatestPackageVersion({
|
||||||
|
packageName = 'payload',
|
||||||
|
}: {
|
||||||
|
/**
|
||||||
|
* Package name to fetch the latest version for based on the NPM registry URL
|
||||||
|
*
|
||||||
|
* Eg. for `'payload'`, it will fetch the version from `https://registry.npmjs.org/payload`
|
||||||
|
*
|
||||||
|
* @default 'payload'
|
||||||
|
*/
|
||||||
|
packageName?: string
|
||||||
|
}): Promise<string> {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`https://registry.npmjs.org/-/package/${packageName}/dist-tags`)
|
||||||
|
const data = await response.json()
|
||||||
|
|
||||||
|
// Monster chaining for type safety just checking for data.latest
|
||||||
|
const latestVersion =
|
||||||
|
data &&
|
||||||
|
typeof data === 'object' &&
|
||||||
|
'latest' in data &&
|
||||||
|
data.latest &&
|
||||||
|
typeof data.latest === 'string'
|
||||||
|
? data.latest
|
||||||
|
: null
|
||||||
|
|
||||||
|
if (!latestVersion) {
|
||||||
|
throw new Error(`No latest version found for package: ${packageName}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return latestVersion
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching Payload version:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export async function downloadTemplate({
|
|||||||
}) {
|
}) {
|
||||||
const branchOrTag = template.url.split('#')?.[1] || 'latest'
|
const branchOrTag = template.url.split('#')?.[1] || 'latest'
|
||||||
const url = `https://codeload.github.com/payloadcms/payload/tar.gz/${branchOrTag}`
|
const url = `https://codeload.github.com/payloadcms/payload/tar.gz/${branchOrTag}`
|
||||||
const filter = `payload-${branchOrTag.replace(/^v/, '')}/templates/${template.name}/`
|
const filter = `payload-${branchOrTag.replace(/^v/, '').replaceAll('/', '-')}/templates/${template.name}/`
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
debugLog(`Using template url: ${template.url}`)
|
debugLog(`Using template url: ${template.url}`)
|
||||||
|
|||||||
@@ -22,6 +22,10 @@
|
|||||||
],
|
],
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
"./css": {
|
||||||
|
"import": "./src/dummy.css",
|
||||||
|
"default": "./src/dummy.css"
|
||||||
|
},
|
||||||
".": {
|
".": {
|
||||||
"import": "./src/index.js",
|
"import": "./src/index.js",
|
||||||
"types": "./src/index.js",
|
"types": "./src/index.js",
|
||||||
|
|||||||
0
packages/next/src/dummy.css
Normal file
0
packages/next/src/dummy.css
Normal file
@@ -36,6 +36,16 @@
|
|||||||
"import": "./src/scss/styles.scss",
|
"import": "./src/scss/styles.scss",
|
||||||
"default": "./src/scss/styles.scss"
|
"default": "./src/scss/styles.scss"
|
||||||
},
|
},
|
||||||
|
"./icons/*": {
|
||||||
|
"import": "./src/icons/*/index.tsx",
|
||||||
|
"types": "./src/icons/*/index.tsx",
|
||||||
|
"default": "./src/icons/*/index.tsx"
|
||||||
|
},
|
||||||
|
"./elements/*": {
|
||||||
|
"import": "./src/elements/*/index.tsx",
|
||||||
|
"types": "./src/elements/*/index.tsx",
|
||||||
|
"default": "./src/elements/*/index.tsx"
|
||||||
|
},
|
||||||
"./elements/RenderServerComponent": {
|
"./elements/RenderServerComponent": {
|
||||||
"import": "./src/elements/RenderServerComponent/index.tsx",
|
"import": "./src/elements/RenderServerComponent/index.tsx",
|
||||||
"types": "./src/elements/RenderServerComponent/index.tsx",
|
"types": "./src/elements/RenderServerComponent/index.tsx",
|
||||||
|
|||||||
4286
pnpm-lock.yaml
generated
4286
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -3,5 +3,7 @@ packages:
|
|||||||
- 'packages/*'
|
- 'packages/*'
|
||||||
- 'tools/*'
|
- 'tools/*'
|
||||||
- 'test'
|
- 'test'
|
||||||
|
- 'templates/blank'
|
||||||
|
- 'templates/website'
|
||||||
# exclude packages that are inside test directories
|
# exclude packages that are inside test directories
|
||||||
# - '!**/test/**'
|
# - '!**/test/**'
|
||||||
|
|||||||
7
templates/_template/.gitignore
vendored
7
templates/_template/.gitignore
vendored
@@ -41,3 +41,10 @@ next-env.d.ts
|
|||||||
.env
|
.env
|
||||||
|
|
||||||
/media
|
/media
|
||||||
|
|
||||||
|
# Playwright
|
||||||
|
node_modules/
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/blob-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
|||||||
@@ -3,6 +3,15 @@ import { withPayload } from '@payloadcms/next/withPayload'
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
// Your Next.js config here
|
// Your Next.js config here
|
||||||
|
webpack: (webpackConfig) => {
|
||||||
|
webpackConfig.resolve.extensionAlias = {
|
||||||
|
'.cjs': ['.cts', '.cjs'],
|
||||||
|
'.js': ['.ts', '.tsx', '.js', '.jsx'],
|
||||||
|
'.mjs': ['.mts', '.mjs'],
|
||||||
|
}
|
||||||
|
|
||||||
|
return webpackConfig
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
||||||
|
|||||||
@@ -12,7 +12,10 @@
|
|||||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
"start": "cross-env NODE_OPTIONS=--no-deprecation next start",
|
||||||
|
"test": "pnpm run test:int && pnpm run test:e2e",
|
||||||
|
"test:e2e": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" pnpm exec playwright test",
|
||||||
|
"test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@payloadcms/db-mongodb": "latest",
|
"@payloadcms/db-mongodb": "latest",
|
||||||
@@ -30,13 +33,21 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
|
"@playwright/test": "1.50.0",
|
||||||
|
"@testing-library/react": "16.3.0",
|
||||||
"@types/node": "^22.5.4",
|
"@types/node": "^22.5.4",
|
||||||
"@types/react": "19.1.0",
|
"@types/react": "19.1.0",
|
||||||
"@types/react-dom": "19.1.2",
|
"@types/react-dom": "19.1.2",
|
||||||
|
"@vitejs/plugin-react": "4.5.2",
|
||||||
"eslint": "^9.16.0",
|
"eslint": "^9.16.0",
|
||||||
"eslint-config-next": "15.3.0",
|
"eslint-config-next": "15.3.0",
|
||||||
|
"jsdom": "26.1.0",
|
||||||
|
"playwright": "1.50.0",
|
||||||
|
"playwright-core": "1.50.0",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3",
|
||||||
|
"vite-tsconfig-paths": "5.1.4",
|
||||||
|
"vitest": "3.2.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.20.2 || >=20.9.0",
|
"node": "^18.20.2 || >=20.9.0",
|
||||||
|
|||||||
41
templates/_template/playwright.config.ts
Normal file
41
templates/_template/playwright.config.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read environment variables from file.
|
||||||
|
* https://github.com/motdotla/dotenv
|
||||||
|
*/
|
||||||
|
import 'dotenv/config'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests/e2e',
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: 'html',
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
|
// baseURL: 'http://localhost:3000',
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: { ...devices['Desktop Chrome'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
webServer: {
|
||||||
|
command: 'pnpm dev',
|
||||||
|
reuseExistingServer: true,
|
||||||
|
url: 'http://localhost:3000',
|
||||||
|
},
|
||||||
|
})
|
||||||
1
templates/_template/test.env
Normal file
1
templates/_template/test.env
Normal file
@@ -0,0 +1 @@
|
|||||||
|
NODE_OPTIONS="--no-deprecation --no-experimental-strip-types"
|
||||||
20
templates/_template/tests/e2e/frontend.e2e.spec.ts
Normal file
20
templates/_template/tests/e2e/frontend.e2e.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { test, expect, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
test.describe('Frontend', () => {
|
||||||
|
let page: Page
|
||||||
|
|
||||||
|
test.beforeAll(async ({ browser }, testInfo) => {
|
||||||
|
const context = await browser.newContext()
|
||||||
|
page = await context.newPage()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('can go on homepage', async ({ page }) => {
|
||||||
|
await page.goto('http://localhost:3000')
|
||||||
|
|
||||||
|
await expect(page).toHaveTitle(/Payload Blank Template/)
|
||||||
|
|
||||||
|
const headging = page.locator('h1').first()
|
||||||
|
|
||||||
|
await expect(headging).toHaveText('Welcome to your new project.')
|
||||||
|
})
|
||||||
|
})
|
||||||
20
templates/_template/tests/int/api.int.spec.ts
Normal file
20
templates/_template/tests/int/api.int.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { getPayload, Payload } from 'payload'
|
||||||
|
import config from '@/payload.config'
|
||||||
|
|
||||||
|
import { describe, it, beforeAll, expect } from 'vitest'
|
||||||
|
|
||||||
|
let payload: Payload
|
||||||
|
|
||||||
|
describe('API', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
const payloadConfig = await config
|
||||||
|
payload = await getPayload({ config: payloadConfig })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fetches users', async () => {
|
||||||
|
const users = await payload.find({
|
||||||
|
collection: 'users',
|
||||||
|
})
|
||||||
|
expect(users).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
12
templates/_template/vitest.config.mts
Normal file
12
templates/_template/vitest.config.mts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [tsconfigPaths(), react()],
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: ['./vitest.setup.ts'],
|
||||||
|
include: ['tests/int/**/*.int.spec.ts'],
|
||||||
|
},
|
||||||
|
})
|
||||||
4
templates/_template/vitest.setup.ts
Normal file
4
templates/_template/vitest.setup.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Any setup scripts you might need go here
|
||||||
|
|
||||||
|
// Load .env files
|
||||||
|
import 'dotenv/config'
|
||||||
7
templates/blank/.gitignore
vendored
7
templates/blank/.gitignore
vendored
@@ -41,3 +41,10 @@ next-env.d.ts
|
|||||||
.env
|
.env
|
||||||
|
|
||||||
/media
|
/media
|
||||||
|
|
||||||
|
# Playwright
|
||||||
|
node_modules/
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/blob-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
|||||||
@@ -3,6 +3,15 @@ import { withPayload } from '@payloadcms/next/withPayload'
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
// Your Next.js config here
|
// Your Next.js config here
|
||||||
|
webpack: (webpackConfig) => {
|
||||||
|
webpackConfig.resolve.extensionAlias = {
|
||||||
|
'.cjs': ['.cts', '.cjs'],
|
||||||
|
'.js': ['.ts', '.tsx', '.js', '.jsx'],
|
||||||
|
'.mjs': ['.mts', '.mjs'],
|
||||||
|
}
|
||||||
|
|
||||||
|
return webpackConfig
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
||||||
|
|||||||
@@ -1,42 +1,52 @@
|
|||||||
{
|
{
|
||||||
"name": "template-blank-3.0",
|
"name": "blank",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "A blank template to get started with Payload 3.0",
|
"description": "A blank template to get started with Payload 3.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
|
"build": "cross-env NODE_OPTIONS=\"--no-deprecation --max-old-space-size=8000\" next build",
|
||||||
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
|
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||||
"devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
|
"devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||||
"generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",
|
"generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",
|
||||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
"start": "cross-env NODE_OPTIONS=--no-deprecation next start",
|
||||||
|
"test": "pnpm run test:int && pnpm run test:e2e",
|
||||||
|
"test:e2e": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" pnpm exec playwright test",
|
||||||
|
"test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@payloadcms/db-mongodb": "3.43.0",
|
"@payloadcms/db-mongodb": "workspace:*",
|
||||||
"@payloadcms/next": "3.43.0",
|
"@payloadcms/next": "workspace:*",
|
||||||
"@payloadcms/payload-cloud": "3.43.0",
|
"@payloadcms/payload-cloud": "workspace:*",
|
||||||
"@payloadcms/richtext-lexical": "3.43.0",
|
"@payloadcms/richtext-lexical": "workspace:*",
|
||||||
"@payloadcms/ui": "3.43.0",
|
"@payloadcms/ui": "workspace:*",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
"dotenv": "16.4.7",
|
||||||
"graphql": "^16.8.1",
|
"graphql": "^16.8.1",
|
||||||
"next": "15.3.0",
|
"next": "15.3.2",
|
||||||
"payload": "3.43.0",
|
"payload": "workspace:*",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.1.0",
|
|
||||||
"sharp": "0.32.6"
|
"sharp": "0.32.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@playwright/test": "1.50.0",
|
||||||
|
"@testing-library/react": "16.3.0",
|
||||||
"@types/node": "^22.5.4",
|
"@types/node": "^22.5.4",
|
||||||
"@types/react": "19.1.0",
|
"@types/react": "19.1.0",
|
||||||
"@types/react-dom": "19.1.2",
|
"@types/react-dom": "19.1.2",
|
||||||
|
"@vitejs/plugin-react": "4.5.2",
|
||||||
"eslint": "^9.16.0",
|
"eslint": "^9.16.0",
|
||||||
"eslint-config-next": "15.3.0",
|
"eslint-config-next": "15.3.0",
|
||||||
|
"jsdom": "26.1.0",
|
||||||
|
"playwright": "1.50.0",
|
||||||
|
"playwright-core": "1.50.0",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3",
|
||||||
|
"vite-tsconfig-paths": "5.1.4",
|
||||||
|
"vitest": "3.2.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.20.2 || >=20.9.0",
|
"node": "^18.20.2 || >=20.9.0",
|
||||||
|
|||||||
41
templates/blank/playwright.config.ts
Normal file
41
templates/blank/playwright.config.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read environment variables from file.
|
||||||
|
* https://github.com/motdotla/dotenv
|
||||||
|
*/
|
||||||
|
import 'dotenv/config'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests/e2e',
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: 'html',
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
|
// baseURL: 'http://localhost:3000',
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: { ...devices['Desktop Chrome'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
webServer: {
|
||||||
|
command: 'pnpm dev',
|
||||||
|
reuseExistingServer: true,
|
||||||
|
url: 'http://localhost:3000',
|
||||||
|
},
|
||||||
|
})
|
||||||
2298
templates/blank/pnpm-lock.yaml
generated
2298
templates/blank/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -6,24 +6,94 @@
|
|||||||
* and re-run `payload generate:types` to regenerate this file.
|
* and re-run `payload generate:types` to regenerate this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported timezones in IANA format.
|
||||||
|
*
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "supportedTimezones".
|
||||||
|
*/
|
||||||
|
export type SupportedTimezones =
|
||||||
|
| 'Pacific/Midway'
|
||||||
|
| 'Pacific/Niue'
|
||||||
|
| 'Pacific/Honolulu'
|
||||||
|
| 'Pacific/Rarotonga'
|
||||||
|
| 'America/Anchorage'
|
||||||
|
| 'Pacific/Gambier'
|
||||||
|
| 'America/Los_Angeles'
|
||||||
|
| 'America/Tijuana'
|
||||||
|
| 'America/Denver'
|
||||||
|
| 'America/Phoenix'
|
||||||
|
| 'America/Chicago'
|
||||||
|
| 'America/Guatemala'
|
||||||
|
| 'America/New_York'
|
||||||
|
| 'America/Bogota'
|
||||||
|
| 'America/Caracas'
|
||||||
|
| 'America/Santiago'
|
||||||
|
| 'America/Buenos_Aires'
|
||||||
|
| 'America/Sao_Paulo'
|
||||||
|
| 'Atlantic/South_Georgia'
|
||||||
|
| 'Atlantic/Azores'
|
||||||
|
| 'Atlantic/Cape_Verde'
|
||||||
|
| 'Europe/London'
|
||||||
|
| 'Europe/Berlin'
|
||||||
|
| 'Africa/Lagos'
|
||||||
|
| 'Europe/Athens'
|
||||||
|
| 'Africa/Cairo'
|
||||||
|
| 'Europe/Moscow'
|
||||||
|
| 'Asia/Riyadh'
|
||||||
|
| 'Asia/Dubai'
|
||||||
|
| 'Asia/Baku'
|
||||||
|
| 'Asia/Karachi'
|
||||||
|
| 'Asia/Tashkent'
|
||||||
|
| 'Asia/Calcutta'
|
||||||
|
| 'Asia/Dhaka'
|
||||||
|
| 'Asia/Almaty'
|
||||||
|
| 'Asia/Jakarta'
|
||||||
|
| 'Asia/Bangkok'
|
||||||
|
| 'Asia/Shanghai'
|
||||||
|
| 'Asia/Singapore'
|
||||||
|
| 'Asia/Tokyo'
|
||||||
|
| 'Asia/Seoul'
|
||||||
|
| 'Australia/Brisbane'
|
||||||
|
| 'Australia/Sydney'
|
||||||
|
| 'Pacific/Guam'
|
||||||
|
| 'Pacific/Noumea'
|
||||||
|
| 'Pacific/Auckland'
|
||||||
|
| 'Pacific/Fiji';
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
auth: {
|
auth: {
|
||||||
users: UserAuthOperations;
|
users: UserAuthOperations;
|
||||||
};
|
};
|
||||||
|
blocks: {};
|
||||||
collections: {
|
collections: {
|
||||||
users: User;
|
users: User;
|
||||||
media: Media;
|
media: Media;
|
||||||
|
'payload-locked-documents': PayloadLockedDocument;
|
||||||
'payload-preferences': PayloadPreference;
|
'payload-preferences': PayloadPreference;
|
||||||
'payload-migrations': PayloadMigration;
|
'payload-migrations': PayloadMigration;
|
||||||
};
|
};
|
||||||
|
collectionsJoins: {};
|
||||||
|
collectionsSelect: {
|
||||||
|
users: UsersSelect<false> | UsersSelect<true>;
|
||||||
|
media: MediaSelect<false> | MediaSelect<true>;
|
||||||
|
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
||||||
|
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
||||||
|
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
|
||||||
|
};
|
||||||
db: {
|
db: {
|
||||||
defaultIDType: string;
|
defaultIDType: string;
|
||||||
};
|
};
|
||||||
globals: {};
|
globals: {};
|
||||||
|
globalsSelect: {};
|
||||||
locale: null;
|
locale: null;
|
||||||
user: User & {
|
user: User & {
|
||||||
collection: 'users';
|
collection: 'users';
|
||||||
};
|
};
|
||||||
|
jobs: {
|
||||||
|
tasks: unknown;
|
||||||
|
workflows: unknown;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
export interface UserAuthOperations {
|
export interface UserAuthOperations {
|
||||||
forgotPassword: {
|
forgotPassword: {
|
||||||
@@ -79,6 +149,29 @@ export interface Media {
|
|||||||
focalX?: number | null;
|
focalX?: number | null;
|
||||||
focalY?: number | null;
|
focalY?: number | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-locked-documents".
|
||||||
|
*/
|
||||||
|
export interface PayloadLockedDocument {
|
||||||
|
id: string;
|
||||||
|
document?:
|
||||||
|
| ({
|
||||||
|
relationTo: 'users';
|
||||||
|
value: string | User;
|
||||||
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'media';
|
||||||
|
value: string | Media;
|
||||||
|
} | null);
|
||||||
|
globalSlug?: string | null;
|
||||||
|
user: {
|
||||||
|
relationTo: 'users';
|
||||||
|
value: string | User;
|
||||||
|
};
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-preferences".
|
* via the `definition` "payload-preferences".
|
||||||
@@ -113,6 +206,71 @@ export interface PayloadMigration {
|
|||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "users_select".
|
||||||
|
*/
|
||||||
|
export interface UsersSelect<T extends boolean = true> {
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
email?: T;
|
||||||
|
resetPasswordToken?: T;
|
||||||
|
resetPasswordExpiration?: T;
|
||||||
|
salt?: T;
|
||||||
|
hash?: T;
|
||||||
|
loginAttempts?: T;
|
||||||
|
lockUntil?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "media_select".
|
||||||
|
*/
|
||||||
|
export interface MediaSelect<T extends boolean = true> {
|
||||||
|
alt?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
url?: T;
|
||||||
|
thumbnailURL?: T;
|
||||||
|
filename?: T;
|
||||||
|
mimeType?: T;
|
||||||
|
filesize?: T;
|
||||||
|
width?: T;
|
||||||
|
height?: T;
|
||||||
|
focalX?: T;
|
||||||
|
focalY?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-locked-documents_select".
|
||||||
|
*/
|
||||||
|
export interface PayloadLockedDocumentsSelect<T extends boolean = true> {
|
||||||
|
document?: T;
|
||||||
|
globalSlug?: T;
|
||||||
|
user?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-preferences_select".
|
||||||
|
*/
|
||||||
|
export interface PayloadPreferencesSelect<T extends boolean = true> {
|
||||||
|
user?: T;
|
||||||
|
key?: T;
|
||||||
|
value?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-migrations_select".
|
||||||
|
*/
|
||||||
|
export interface PayloadMigrationsSelect<T extends boolean = true> {
|
||||||
|
name?: T;
|
||||||
|
batch?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "auth".
|
* via the `definition` "auth".
|
||||||
|
|||||||
1
templates/blank/test.env
Normal file
1
templates/blank/test.env
Normal file
@@ -0,0 +1 @@
|
|||||||
|
NODE_OPTIONS="--no-deprecation --no-experimental-strip-types"
|
||||||
20
templates/blank/tests/e2e/frontend.e2e.spec.ts
Normal file
20
templates/blank/tests/e2e/frontend.e2e.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { test, expect, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
test.describe('Frontend', () => {
|
||||||
|
let page: Page
|
||||||
|
|
||||||
|
test.beforeAll(async ({ browser }, testInfo) => {
|
||||||
|
const context = await browser.newContext()
|
||||||
|
page = await context.newPage()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('can go on homepage', async ({ page }) => {
|
||||||
|
await page.goto('http://localhost:3000')
|
||||||
|
|
||||||
|
await expect(page).toHaveTitle(/Payload Blank Template/)
|
||||||
|
|
||||||
|
const headging = page.locator('h1').first()
|
||||||
|
|
||||||
|
await expect(headging).toHaveText('Welcome to your new project.')
|
||||||
|
})
|
||||||
|
})
|
||||||
20
templates/blank/tests/int/api.int.spec.ts
Normal file
20
templates/blank/tests/int/api.int.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { getPayload, Payload } from 'payload'
|
||||||
|
import config from '@/payload.config'
|
||||||
|
|
||||||
|
import { describe, it, beforeAll, expect } from 'vitest'
|
||||||
|
|
||||||
|
let payload: Payload
|
||||||
|
|
||||||
|
describe('API', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
const payloadConfig = await config
|
||||||
|
payload = await getPayload({ config: payloadConfig })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fetches users', async () => {
|
||||||
|
const users = await payload.find({
|
||||||
|
collection: 'users',
|
||||||
|
})
|
||||||
|
expect(users).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -40,5 +40,5 @@
|
|||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
12
templates/blank/vitest.config.mts
Normal file
12
templates/blank/vitest.config.mts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [tsconfigPaths(), react()],
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: ['./vitest.setup.ts'],
|
||||||
|
include: ['tests/int/**/*.int.spec.ts'],
|
||||||
|
},
|
||||||
|
})
|
||||||
4
templates/blank/vitest.setup.ts
Normal file
4
templates/blank/vitest.setup.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Any setup scripts you might need go here
|
||||||
|
|
||||||
|
// Load .env files
|
||||||
|
import 'dotenv/config'
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "plugin-package-name-placeholder",
|
"name": "plugin",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "A blank template to get started with Payload 3.0",
|
"description": "A blank template to get started with Payload 3.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
8
templates/website/.gitignore
vendored
8
templates/website/.gitignore
vendored
@@ -11,3 +11,11 @@ public/media/
|
|||||||
|
|
||||||
public/robots.txt
|
public/robots.txt
|
||||||
public/sitemap*.xml
|
public/sitemap*.xml
|
||||||
|
|
||||||
|
|
||||||
|
# Playwright
|
||||||
|
node_modules/
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/blob-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
|||||||
@@ -20,6 +20,15 @@ const nextConfig = {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
webpack: (webpackConfig) => {
|
||||||
|
webpackConfig.resolve.extensionAlias = {
|
||||||
|
'.cjs': ['.cts', '.cjs'],
|
||||||
|
'.js': ['.ts', '.tsx', '.js', '.jsx'],
|
||||||
|
'.mjs': ['.mts', '.mjs'],
|
||||||
|
}
|
||||||
|
|
||||||
|
return webpackConfig
|
||||||
|
},
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
redirects,
|
redirects,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@payloadcms/template-website",
|
"name": "website",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Website template for Payload",
|
"description": "Website template for Payload",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -16,21 +16,24 @@
|
|||||||
"lint:fix": "cross-env NODE_OPTIONS=--no-deprecation next lint --fix",
|
"lint:fix": "cross-env NODE_OPTIONS=--no-deprecation next lint --fix",
|
||||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||||
"reinstall": "cross-env NODE_OPTIONS=--no-deprecation rm -rf node_modules && rm pnpm-lock.yaml && pnpm --ignore-workspace install",
|
"reinstall": "cross-env NODE_OPTIONS=--no-deprecation rm -rf node_modules && rm pnpm-lock.yaml && pnpm --ignore-workspace install",
|
||||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
"start": "cross-env NODE_OPTIONS=--no-deprecation next start",
|
||||||
|
"test": "pnpm run test:int && pnpm run test:e2e",
|
||||||
|
"test:e2e": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" pnpm exec playwright test --config=playwright.config.ts",
|
||||||
|
"test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@payloadcms/admin-bar": "3.43.0",
|
"@payloadcms/admin-bar": "workspace:*",
|
||||||
"@payloadcms/db-mongodb": "3.43.0",
|
"@payloadcms/db-mongodb": "workspace:*",
|
||||||
"@payloadcms/live-preview-react": "3.43.0",
|
"@payloadcms/live-preview-react": "workspace:*",
|
||||||
"@payloadcms/next": "3.43.0",
|
"@payloadcms/next": "workspace:*",
|
||||||
"@payloadcms/payload-cloud": "3.43.0",
|
"@payloadcms/payload-cloud": "workspace:*",
|
||||||
"@payloadcms/plugin-form-builder": "3.43.0",
|
"@payloadcms/plugin-form-builder": "workspace:*",
|
||||||
"@payloadcms/plugin-nested-docs": "3.43.0",
|
"@payloadcms/plugin-nested-docs": "workspace:*",
|
||||||
"@payloadcms/plugin-redirects": "3.43.0",
|
"@payloadcms/plugin-redirects": "workspace:*",
|
||||||
"@payloadcms/plugin-search": "3.43.0",
|
"@payloadcms/plugin-search": "workspace:*",
|
||||||
"@payloadcms/plugin-seo": "3.43.0",
|
"@payloadcms/plugin-seo": "workspace:*",
|
||||||
"@payloadcms/richtext-lexical": "3.43.0",
|
"@payloadcms/richtext-lexical": "workspace:*",
|
||||||
"@payloadcms/ui": "3.43.0",
|
"@payloadcms/ui": "workspace:*",
|
||||||
"@radix-ui/react-checkbox": "^1.0.4",
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-label": "^2.0.2",
|
"@radix-ui/react-label": "^2.0.2",
|
||||||
"@radix-ui/react-select": "^2.0.0",
|
"@radix-ui/react-select": "^2.0.0",
|
||||||
@@ -38,12 +41,13 @@
|
|||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
"dotenv": "16.4.7",
|
||||||
"geist": "^1.3.0",
|
"geist": "^1.3.0",
|
||||||
"graphql": "^16.8.2",
|
"graphql": "^16.8.2",
|
||||||
"lucide-react": "^0.378.0",
|
"lucide-react": "^0.378.0",
|
||||||
"next": "15.3.0",
|
"next": "15.3.3",
|
||||||
"next-sitemap": "^4.2.3",
|
"next-sitemap": "^4.2.3",
|
||||||
"payload": "3.43.0",
|
"payload": "workspace:*",
|
||||||
"prism-react-renderer": "^2.3.1",
|
"prism-react-renderer": "^2.3.1",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.1.0",
|
"react-dom": "19.1.0",
|
||||||
@@ -66,6 +70,14 @@
|
|||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
|
"@playwright/test": "1.50.0",
|
||||||
|
"jsdom": "26.1.0",
|
||||||
|
"@testing-library/react": "16.3.0",
|
||||||
|
"@vitejs/plugin-react": "4.5.2",
|
||||||
|
"playwright": "1.50.0",
|
||||||
|
"playwright-core": "1.50.0",
|
||||||
|
"vite-tsconfig-paths": "5.1.4",
|
||||||
|
"vitest": "3.2.3",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
41
templates/website/playwright.config.ts
Normal file
41
templates/website/playwright.config.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read environment variables from file.
|
||||||
|
* https://github.com/motdotla/dotenv
|
||||||
|
*/
|
||||||
|
import 'dotenv/config'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests/e2e',
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: 'html',
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
|
// baseURL: 'http://localhost:3000',
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: { ...devices['Desktop Chrome'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
webServer: {
|
||||||
|
command: 'pnpm dev',
|
||||||
|
reuseExistingServer: true,
|
||||||
|
url: 'http://localhost:3000',
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -25,47 +25,29 @@ import { default as default_1a7510af427896d367a49dbf838d2de6 } from '@/component
|
|||||||
import { default as default_8a7ab0eb7ab5c511aba12e68480bfe5e } from '@/components/BeforeLogin'
|
import { default as default_8a7ab0eb7ab5c511aba12e68480bfe5e } from '@/components/BeforeLogin'
|
||||||
|
|
||||||
export const importMap = {
|
export const importMap = {
|
||||||
'@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell':
|
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell": RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||||
RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e,
|
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalField": RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||||
'@payloadcms/richtext-lexical/rsc#RscEntryLexicalField':
|
"@payloadcms/richtext-lexical/rsc#LexicalDiffComponent": LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||||
RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e,
|
"@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
'@payloadcms/richtext-lexical/rsc#LexicalDiffComponent':
|
"@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient": FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e,
|
"@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
'@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient':
|
"@payloadcms/richtext-lexical/client#ParagraphFeatureClient": ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
'@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient':
|
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
'@payloadcms/richtext-lexical/client#HeadingFeatureClient':
|
"@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
"@payloadcms/plugin-seo/client#OverviewComponent": OverviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||||
'@payloadcms/richtext-lexical/client#ParagraphFeatureClient':
|
"@payloadcms/plugin-seo/client#MetaTitleComponent": MetaTitleComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||||
ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
"@payloadcms/plugin-seo/client#MetaImageComponent": MetaImageComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||||
'@payloadcms/richtext-lexical/client#UnderlineFeatureClient':
|
"@payloadcms/plugin-seo/client#MetaDescriptionComponent": MetaDescriptionComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||||
UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
"@payloadcms/plugin-seo/client#PreviewComponent": PreviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||||
'@payloadcms/richtext-lexical/client#BoldFeatureClient':
|
"@/fields/slug/SlugComponent#SlugComponent": SlugComponent_92cc057d0a2abb4f6cf0307edf59f986,
|
||||||
BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
'@payloadcms/richtext-lexical/client#ItalicFeatureClient':
|
"@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
"@payloadcms/plugin-search/client#LinkToDoc": LinkToDoc_aead06e4cbf6b2620c5c51c9ab283634,
|
||||||
'@payloadcms/richtext-lexical/client#LinkFeatureClient':
|
"@payloadcms/plugin-search/client#ReindexButton": ReindexButton_aead06e4cbf6b2620c5c51c9ab283634,
|
||||||
LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
"@/Header/RowLabel#RowLabel": RowLabel_ec255a65fa6fa8d1faeb09cf35284224,
|
||||||
'@payloadcms/plugin-seo/client#OverviewComponent':
|
"@/Footer/RowLabel#RowLabel": RowLabel_1f6ff6ff633e3695d348f4f3c58f1466,
|
||||||
OverviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
"@/components/BeforeDashboard#default": default_1a7510af427896d367a49dbf838d2de6,
|
||||||
'@payloadcms/plugin-seo/client#MetaTitleComponent':
|
"@/components/BeforeLogin#default": default_8a7ab0eb7ab5c511aba12e68480bfe5e
|
||||||
MetaTitleComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
|
||||||
'@payloadcms/plugin-seo/client#MetaImageComponent':
|
|
||||||
MetaImageComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
|
||||||
'@payloadcms/plugin-seo/client#MetaDescriptionComponent':
|
|
||||||
MetaDescriptionComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
|
||||||
'@payloadcms/plugin-seo/client#PreviewComponent':
|
|
||||||
PreviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
|
||||||
'@/fields/slug/SlugComponent#SlugComponent': SlugComponent_92cc057d0a2abb4f6cf0307edf59f986,
|
|
||||||
'@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient':
|
|
||||||
HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
|
||||||
'@payloadcms/richtext-lexical/client#BlocksFeatureClient':
|
|
||||||
BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
|
||||||
'@payloadcms/plugin-search/client#LinkToDoc': LinkToDoc_aead06e4cbf6b2620c5c51c9ab283634,
|
|
||||||
'@payloadcms/plugin-search/client#ReindexButton': ReindexButton_aead06e4cbf6b2620c5c51c9ab283634,
|
|
||||||
'@/Header/RowLabel#RowLabel': RowLabel_ec255a65fa6fa8d1faeb09cf35284224,
|
|
||||||
'@/Footer/RowLabel#RowLabel': RowLabel_1f6ff6ff633e3695d348f4f3c58f1466,
|
|
||||||
'@/components/BeforeDashboard#default': default_1a7510af427896d367a49dbf838d2de6,
|
|
||||||
'@/components/BeforeLogin#default': default_8a7ab0eb7ab5c511aba12e68480bfe5e,
|
|
||||||
}
|
}
|
||||||
|
|||||||
1
templates/website/test.env
Normal file
1
templates/website/test.env
Normal file
@@ -0,0 +1 @@
|
|||||||
|
NODE_OPTIONS="--no-deprecation --no-experimental-strip-types"
|
||||||
20
templates/website/tests/e2e/frontend.e2e.spec.ts
Normal file
20
templates/website/tests/e2e/frontend.e2e.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { test, expect, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
test.describe('Frontend', () => {
|
||||||
|
let page: Page
|
||||||
|
|
||||||
|
test.beforeAll(async ({ browser }, testInfo) => {
|
||||||
|
const context = await browser.newContext()
|
||||||
|
page = await context.newPage()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('can go on homepage', async ({ page }) => {
|
||||||
|
await page.goto('http://localhost:3000')
|
||||||
|
|
||||||
|
await expect(page).toHaveTitle(/Payload Website Template/)
|
||||||
|
|
||||||
|
const headging = page.locator('h1').first()
|
||||||
|
|
||||||
|
await expect(headging).toHaveText('Payload Website Template')
|
||||||
|
})
|
||||||
|
})
|
||||||
20
templates/website/tests/int/api.int.spec.ts
Normal file
20
templates/website/tests/int/api.int.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { getPayload, Payload } from 'payload'
|
||||||
|
import config from '@/payload.config'
|
||||||
|
|
||||||
|
import { describe, it, beforeAll, expect } from 'vitest'
|
||||||
|
|
||||||
|
let payload: Payload
|
||||||
|
|
||||||
|
describe('API', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
const payloadConfig = await config
|
||||||
|
payload = await getPayload({ config: payloadConfig })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fetches users', async () => {
|
||||||
|
const users = await payload.find({
|
||||||
|
collection: 'users',
|
||||||
|
})
|
||||||
|
expect(users).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,10 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Strictness */
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noUncheckedIndexedAccess": true,
|
|
||||||
"noImplicitOverride": true,
|
|
||||||
|
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
@@ -15,8 +11,6 @@
|
|||||||
],
|
],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strictNullChecks": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
@@ -47,10 +41,11 @@
|
|||||||
"**/*.tsx",
|
"**/*.tsx",
|
||||||
".next/types/**/*.ts",
|
".next/types/**/*.ts",
|
||||||
"redirects.js",
|
"redirects.js",
|
||||||
|
"next-env.d.ts",
|
||||||
"next.config.js",
|
"next.config.js",
|
||||||
"next-sitemap.config.cjs"
|
"next-sitemap.config.cjs"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
12
templates/website/vitest.config.mts
Normal file
12
templates/website/vitest.config.mts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [tsconfigPaths(), react()],
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: ['./vitest.setup.ts'],
|
||||||
|
include: ['tests/int/**/*.int.spec.ts'],
|
||||||
|
},
|
||||||
|
})
|
||||||
4
templates/website/vitest.setup.ts
Normal file
4
templates/website/vitest.setup.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Any setup scripts you might need go here
|
||||||
|
|
||||||
|
// Load .env files
|
||||||
|
import 'dotenv/config'
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "payload-cloud-mongodb-template",
|
"name": "with-payload-cloud",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "A blank template to get started with Payload 3.0",
|
"description": "A blank template to get started with Payload 3.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
7
templates/with-postgres/.gitignore
vendored
7
templates/with-postgres/.gitignore
vendored
@@ -41,3 +41,10 @@ next-env.d.ts
|
|||||||
.env
|
.env
|
||||||
|
|
||||||
/media
|
/media
|
||||||
|
|
||||||
|
# Playwright
|
||||||
|
node_modules/
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/blob-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# payload-postgres-template
|
# with-postgres
|
||||||
|
|
||||||
payload-postgres-template
|
with-postgres
|
||||||
|
|
||||||
## Attributes
|
## Attributes
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,15 @@ import { withPayload } from '@payloadcms/next/withPayload'
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
// Your Next.js config here
|
// Your Next.js config here
|
||||||
|
webpack: (webpackConfig) => {
|
||||||
|
webpackConfig.resolve.extensionAlias = {
|
||||||
|
'.cjs': ['.cts', '.cjs'],
|
||||||
|
'.js': ['.ts', '.tsx', '.js', '.jsx'],
|
||||||
|
'.mjs': ['.mts', '.mjs'],
|
||||||
|
}
|
||||||
|
|
||||||
|
return webpackConfig
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "payload-postgres-template",
|
"name": "with-postgres",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "A blank template to get started with Payload 3.0",
|
"description": "A blank template to get started with Payload 3.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -13,7 +13,10 @@
|
|||||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
"start": "cross-env NODE_OPTIONS=--no-deprecation next start",
|
||||||
|
"test": "pnpm run test:int && pnpm run test:e2e",
|
||||||
|
"test:e2e": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" pnpm exec playwright test",
|
||||||
|
"test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@payloadcms/db-postgres": "3.43.0",
|
"@payloadcms/db-postgres": "3.43.0",
|
||||||
@@ -31,13 +34,21 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
|
"@playwright/test": "1.50.0",
|
||||||
|
"@testing-library/react": "16.3.0",
|
||||||
"@types/node": "^22.5.4",
|
"@types/node": "^22.5.4",
|
||||||
"@types/react": "19.1.0",
|
"@types/react": "19.1.0",
|
||||||
"@types/react-dom": "19.1.2",
|
"@types/react-dom": "19.1.2",
|
||||||
|
"@vitejs/plugin-react": "4.5.2",
|
||||||
"eslint": "^9.16.0",
|
"eslint": "^9.16.0",
|
||||||
"eslint-config-next": "15.3.0",
|
"eslint-config-next": "15.3.0",
|
||||||
|
"jsdom": "26.1.0",
|
||||||
|
"playwright": "1.50.0",
|
||||||
|
"playwright-core": "1.50.0",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3",
|
||||||
|
"vite-tsconfig-paths": "5.1.4",
|
||||||
|
"vitest": "3.2.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.20.2 || >=20.9.0",
|
"node": "^18.20.2 || >=20.9.0",
|
||||||
|
|||||||
41
templates/with-postgres/playwright.config.ts
Normal file
41
templates/with-postgres/playwright.config.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read environment variables from file.
|
||||||
|
* https://github.com/motdotla/dotenv
|
||||||
|
*/
|
||||||
|
import 'dotenv/config'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests/e2e',
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: 'html',
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
|
// baseURL: 'http://localhost:3000',
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: { ...devices['Desktop Chrome'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
webServer: {
|
||||||
|
command: 'pnpm dev',
|
||||||
|
reuseExistingServer: true,
|
||||||
|
url: 'http://localhost:3000',
|
||||||
|
},
|
||||||
|
})
|
||||||
20
templates/with-postgres/tests/e2e/frontend.e2e.spec.ts
Normal file
20
templates/with-postgres/tests/e2e/frontend.e2e.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { test, expect, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
test.describe('Frontend', () => {
|
||||||
|
let page: Page
|
||||||
|
|
||||||
|
test.beforeAll(async ({ browser }, testInfo) => {
|
||||||
|
const context = await browser.newContext()
|
||||||
|
page = await context.newPage()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('can go on homepage', async ({ page }) => {
|
||||||
|
await page.goto('http://localhost:3000')
|
||||||
|
|
||||||
|
await expect(page).toHaveTitle(/Payload Blank Template/)
|
||||||
|
|
||||||
|
const headging = page.locator('h1').first()
|
||||||
|
|
||||||
|
await expect(headging).toHaveText('Welcome to your new project.')
|
||||||
|
})
|
||||||
|
})
|
||||||
20
templates/with-postgres/tests/int/api.int.spec.ts
Normal file
20
templates/with-postgres/tests/int/api.int.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { getPayload, Payload } from 'payload'
|
||||||
|
import config from '@/payload.config'
|
||||||
|
|
||||||
|
import { describe, it, beforeAll, expect } from 'vitest'
|
||||||
|
|
||||||
|
let payload: Payload
|
||||||
|
|
||||||
|
describe('API', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
const payloadConfig = await config
|
||||||
|
payload = await getPayload({ config: payloadConfig })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fetches users', async () => {
|
||||||
|
const users = await payload.find({
|
||||||
|
collection: 'users',
|
||||||
|
})
|
||||||
|
expect(users).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
12
templates/with-postgres/vitest.config.mts
Normal file
12
templates/with-postgres/vitest.config.mts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [tsconfigPaths(), react()],
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: ['./vitest.setup.ts'],
|
||||||
|
include: ['tests/int/**/*.int.spec.ts'],
|
||||||
|
},
|
||||||
|
})
|
||||||
4
templates/with-postgres/vitest.setup.ts
Normal file
4
templates/with-postgres/vitest.setup.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Any setup scripts you might need go here
|
||||||
|
|
||||||
|
// Load .env files
|
||||||
|
import 'dotenv/config'
|
||||||
7
templates/with-vercel-mongodb/.gitignore
vendored
7
templates/with-vercel-mongodb/.gitignore
vendored
@@ -41,3 +41,10 @@ next-env.d.ts
|
|||||||
.env
|
.env
|
||||||
|
|
||||||
/media
|
/media
|
||||||
|
|
||||||
|
# Playwright
|
||||||
|
node_modules/
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/blob-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
|||||||
@@ -3,6 +3,15 @@ import { withPayload } from '@payloadcms/next/withPayload'
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
// Your Next.js config here
|
// Your Next.js config here
|
||||||
|
webpack: (webpackConfig) => {
|
||||||
|
webpackConfig.resolve.extensionAlias = {
|
||||||
|
'.cjs': ['.cts', '.cjs'],
|
||||||
|
'.js': ['.ts', '.tsx', '.js', '.jsx'],
|
||||||
|
'.mjs': ['.mts', '.mjs'],
|
||||||
|
}
|
||||||
|
|
||||||
|
return webpackConfig
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "payload-vercel-mongodb-template",
|
"name": "with-vercel-mongodb",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "A blank template to get started with Payload 3.0",
|
"description": "A blank template to get started with Payload 3.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -12,7 +12,10 @@
|
|||||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
"start": "cross-env NODE_OPTIONS=--no-deprecation next start",
|
||||||
|
"test": "pnpm run test:int && pnpm run test:e2e",
|
||||||
|
"test:e2e": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" pnpm exec playwright test",
|
||||||
|
"test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@payloadcms/db-mongodb": "3.43.0",
|
"@payloadcms/db-mongodb": "3.43.0",
|
||||||
@@ -30,15 +33,23 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
|
"@playwright/test": "1.50.0",
|
||||||
|
"@testing-library/react": "16.3.0",
|
||||||
"@types/node": "^22.5.4",
|
"@types/node": "^22.5.4",
|
||||||
"@types/react": "19.1.0",
|
"@types/react": "19.1.0",
|
||||||
"@types/react-dom": "19.1.2",
|
"@types/react-dom": "19.1.2",
|
||||||
|
"@vitejs/plugin-react": "4.5.2",
|
||||||
"eslint": "^9.16.0",
|
"eslint": "^9.16.0",
|
||||||
"eslint-config-next": "15.3.0",
|
"eslint-config-next": "15.3.0",
|
||||||
|
"jsdom": "26.1.0",
|
||||||
|
"playwright": "1.50.0",
|
||||||
|
"playwright-core": "1.50.0",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3",
|
||||||
|
"vite-tsconfig-paths": "5.1.4",
|
||||||
|
"vitest": "3.2.3"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.12.1",
|
"packageManager": "pnpm@10.12.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.20.2 || >=20.9.0"
|
"node": "^18.20.2 || >=20.9.0"
|
||||||
},
|
},
|
||||||
|
|||||||
41
templates/with-vercel-mongodb/playwright.config.ts
Normal file
41
templates/with-vercel-mongodb/playwright.config.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read environment variables from file.
|
||||||
|
* https://github.com/motdotla/dotenv
|
||||||
|
*/
|
||||||
|
import 'dotenv/config'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests/e2e',
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: 'html',
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
|
// baseURL: 'http://localhost:3000',
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: { ...devices['Desktop Chrome'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
webServer: {
|
||||||
|
command: 'pnpm dev',
|
||||||
|
reuseExistingServer: true,
|
||||||
|
url: 'http://localhost:3000',
|
||||||
|
},
|
||||||
|
})
|
||||||
20
templates/with-vercel-mongodb/tests/e2e/frontend.e2e.spec.ts
Normal file
20
templates/with-vercel-mongodb/tests/e2e/frontend.e2e.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { test, expect, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
test.describe('Frontend', () => {
|
||||||
|
let page: Page
|
||||||
|
|
||||||
|
test.beforeAll(async ({ browser }, testInfo) => {
|
||||||
|
const context = await browser.newContext()
|
||||||
|
page = await context.newPage()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('can go on homepage', async ({ page }) => {
|
||||||
|
await page.goto('http://localhost:3000')
|
||||||
|
|
||||||
|
await expect(page).toHaveTitle(/Payload Blank Template/)
|
||||||
|
|
||||||
|
const headging = page.locator('h1').first()
|
||||||
|
|
||||||
|
await expect(headging).toHaveText('Welcome to your new project.')
|
||||||
|
})
|
||||||
|
})
|
||||||
20
templates/with-vercel-mongodb/tests/int/api.int.spec.ts
Normal file
20
templates/with-vercel-mongodb/tests/int/api.int.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { getPayload, Payload } from 'payload'
|
||||||
|
import config from '@/payload.config'
|
||||||
|
|
||||||
|
import { describe, it, beforeAll, expect } from 'vitest'
|
||||||
|
|
||||||
|
let payload: Payload
|
||||||
|
|
||||||
|
describe('API', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
const payloadConfig = await config
|
||||||
|
payload = await getPayload({ config: payloadConfig })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fetches users', async () => {
|
||||||
|
const users = await payload.find({
|
||||||
|
collection: 'users',
|
||||||
|
})
|
||||||
|
expect(users).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
12
templates/with-vercel-mongodb/vitest.config.mts
Normal file
12
templates/with-vercel-mongodb/vitest.config.mts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [tsconfigPaths(), react()],
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: ['./vitest.setup.ts'],
|
||||||
|
include: ['tests/int/**/*.int.spec.ts'],
|
||||||
|
},
|
||||||
|
})
|
||||||
4
templates/with-vercel-mongodb/vitest.setup.ts
Normal file
4
templates/with-vercel-mongodb/vitest.setup.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Any setup scripts you might need go here
|
||||||
|
|
||||||
|
// Load .env files
|
||||||
|
import 'dotenv/config'
|
||||||
7
templates/with-vercel-postgres/.gitignore
vendored
7
templates/with-vercel-postgres/.gitignore
vendored
@@ -41,3 +41,10 @@ next-env.d.ts
|
|||||||
.env
|
.env
|
||||||
|
|
||||||
/media
|
/media
|
||||||
|
|
||||||
|
# Playwright
|
||||||
|
node_modules/
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/blob-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
|||||||
@@ -3,6 +3,15 @@ import { withPayload } from '@payloadcms/next/withPayload'
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
// Your Next.js config here
|
// Your Next.js config here
|
||||||
|
webpack: (webpackConfig) => {
|
||||||
|
webpackConfig.resolve.extensionAlias = {
|
||||||
|
'.cjs': ['.cts', '.cjs'],
|
||||||
|
'.js': ['.ts', '.tsx', '.js', '.jsx'],
|
||||||
|
'.mjs': ['.mts', '.mjs'],
|
||||||
|
}
|
||||||
|
|
||||||
|
return webpackConfig
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "payload-vercel-postgres-template",
|
"name": "with-vercel-postgres",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "A blank template to get started with Payload 3.0",
|
"description": "A blank template to get started with Payload 3.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -13,7 +13,10 @@
|
|||||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
"start": "cross-env NODE_OPTIONS=--no-deprecation next start",
|
||||||
|
"test": "pnpm run test:int && pnpm run test:e2e",
|
||||||
|
"test:e2e": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" pnpm exec playwright test",
|
||||||
|
"test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@payloadcms/db-vercel-postgres": "3.43.0",
|
"@payloadcms/db-vercel-postgres": "3.43.0",
|
||||||
@@ -31,15 +34,23 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
|
"@playwright/test": "1.50.0",
|
||||||
|
"@testing-library/react": "16.3.0",
|
||||||
"@types/node": "^22.5.4",
|
"@types/node": "^22.5.4",
|
||||||
"@types/react": "19.1.0",
|
"@types/react": "19.1.0",
|
||||||
"@types/react-dom": "19.1.2",
|
"@types/react-dom": "19.1.2",
|
||||||
|
"@vitejs/plugin-react": "4.5.2",
|
||||||
"eslint": "^9.16.0",
|
"eslint": "^9.16.0",
|
||||||
"eslint-config-next": "15.3.0",
|
"eslint-config-next": "15.3.0",
|
||||||
|
"jsdom": "26.1.0",
|
||||||
|
"playwright": "1.50.0",
|
||||||
|
"playwright-core": "1.50.0",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3",
|
||||||
|
"vite-tsconfig-paths": "5.1.4",
|
||||||
|
"vitest": "3.2.3"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.12.1",
|
"packageManager": "pnpm@10.12.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.20.2 || >=20.9.0"
|
"node": "^18.20.2 || >=20.9.0"
|
||||||
},
|
},
|
||||||
|
|||||||
41
templates/with-vercel-postgres/playwright.config.ts
Normal file
41
templates/with-vercel-postgres/playwright.config.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read environment variables from file.
|
||||||
|
* https://github.com/motdotla/dotenv
|
||||||
|
*/
|
||||||
|
import 'dotenv/config'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests/e2e',
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: 'html',
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
|
// baseURL: 'http://localhost:3000',
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: { ...devices['Desktop Chrome'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
webServer: {
|
||||||
|
command: 'pnpm dev',
|
||||||
|
reuseExistingServer: true,
|
||||||
|
url: 'http://localhost:3000',
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"id": "80b6c48b-dc29-46a6-93d9-4c7ffb28e4d1",
|
"id": "64c3b19c-9d51-4e55-9c9c-333d9b73bc28",
|
||||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import * as migration_20250616_201653_initial from './20250616_201653_initial'
|
import * as migration_20250624_171210_initial from './20250624_171210_initial'
|
||||||
|
|
||||||
export const migrations = [
|
export const migrations = [
|
||||||
{
|
{
|
||||||
up: migration_20250616_201653_initial.up,
|
up: migration_20250624_171210_initial.up,
|
||||||
down: migration_20250616_201653_initial.down,
|
down: migration_20250624_171210_initial.down,
|
||||||
name: '20250616_201653_initial',
|
name: '20250624_171210_initial',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { test, expect, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
test.describe('Frontend', () => {
|
||||||
|
let page: Page
|
||||||
|
|
||||||
|
test.beforeAll(async ({ browser }, testInfo) => {
|
||||||
|
const context = await browser.newContext()
|
||||||
|
page = await context.newPage()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('can go on homepage', async ({ page }) => {
|
||||||
|
await page.goto('http://localhost:3000')
|
||||||
|
|
||||||
|
await expect(page).toHaveTitle(/Payload Blank Template/)
|
||||||
|
|
||||||
|
const headging = page.locator('h1').first()
|
||||||
|
|
||||||
|
await expect(headging).toHaveText('Welcome to your new project.')
|
||||||
|
})
|
||||||
|
})
|
||||||
20
templates/with-vercel-postgres/tests/int/api.int.spec.ts
Normal file
20
templates/with-vercel-postgres/tests/int/api.int.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { getPayload, Payload } from 'payload'
|
||||||
|
import config from '@/payload.config'
|
||||||
|
|
||||||
|
import { describe, it, beforeAll, expect } from 'vitest'
|
||||||
|
|
||||||
|
let payload: Payload
|
||||||
|
|
||||||
|
describe('API', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
const payloadConfig = await config
|
||||||
|
payload = await getPayload({ config: payloadConfig })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fetches users', async () => {
|
||||||
|
const users = await payload.find({
|
||||||
|
collection: 'users',
|
||||||
|
})
|
||||||
|
expect(users).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
12
templates/with-vercel-postgres/vitest.config.mts
Normal file
12
templates/with-vercel-postgres/vitest.config.mts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [tsconfigPaths(), react()],
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: ['./vitest.setup.ts'],
|
||||||
|
include: ['tests/int/**/*.int.spec.ts'],
|
||||||
|
},
|
||||||
|
})
|
||||||
4
templates/with-vercel-postgres/vitest.setup.ts
Normal file
4
templates/with-vercel-postgres/vitest.setup.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Any setup scripts you might need go here
|
||||||
|
|
||||||
|
// Load .env files
|
||||||
|
import 'dotenv/config'
|
||||||
8
templates/with-vercel-website/.gitignore
vendored
8
templates/with-vercel-website/.gitignore
vendored
@@ -11,3 +11,11 @@ public/media/
|
|||||||
|
|
||||||
public/robots.txt
|
public/robots.txt
|
||||||
public/sitemap*.xml
|
public/sitemap*.xml
|
||||||
|
|
||||||
|
|
||||||
|
# Playwright
|
||||||
|
node_modules/
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/blob-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
|||||||
@@ -20,6 +20,15 @@ const nextConfig = {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
webpack: (webpackConfig) => {
|
||||||
|
webpackConfig.resolve.extensionAlias = {
|
||||||
|
'.cjs': ['.cts', '.cjs'],
|
||||||
|
'.js': ['.ts', '.tsx', '.js', '.jsx'],
|
||||||
|
'.mjs': ['.mts', '.mjs'],
|
||||||
|
}
|
||||||
|
|
||||||
|
return webpackConfig
|
||||||
|
},
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
redirects,
|
redirects,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "payload-vercel-website-template",
|
"name": "with-vercel-website",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Website template for Payload",
|
"description": "Website template for Payload",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -17,7 +17,10 @@
|
|||||||
"lint:fix": "cross-env NODE_OPTIONS=--no-deprecation next lint --fix",
|
"lint:fix": "cross-env NODE_OPTIONS=--no-deprecation next lint --fix",
|
||||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||||
"reinstall": "cross-env NODE_OPTIONS=--no-deprecation rm -rf node_modules && rm pnpm-lock.yaml && pnpm --ignore-workspace install",
|
"reinstall": "cross-env NODE_OPTIONS=--no-deprecation rm -rf node_modules && rm pnpm-lock.yaml && pnpm --ignore-workspace install",
|
||||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
"start": "cross-env NODE_OPTIONS=--no-deprecation next start",
|
||||||
|
"test": "pnpm run test:int && pnpm run test:e2e",
|
||||||
|
"test:e2e": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" pnpm exec playwright test --config=playwright.config.ts",
|
||||||
|
"test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@payloadcms/admin-bar": "3.43.0",
|
"@payloadcms/admin-bar": "3.43.0",
|
||||||
@@ -40,10 +43,11 @@
|
|||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
"dotenv": "16.4.7",
|
||||||
"geist": "^1.3.0",
|
"geist": "^1.3.0",
|
||||||
"graphql": "^16.8.2",
|
"graphql": "^16.8.2",
|
||||||
"lucide-react": "^0.378.0",
|
"lucide-react": "^0.378.0",
|
||||||
"next": "15.3.0",
|
"next": "15.3.3",
|
||||||
"next-sitemap": "^4.2.3",
|
"next-sitemap": "^4.2.3",
|
||||||
"payload": "3.43.0",
|
"payload": "3.43.0",
|
||||||
"prism-react-renderer": "^2.3.1",
|
"prism-react-renderer": "^2.3.1",
|
||||||
@@ -56,21 +60,29 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
|
"@playwright/test": "1.50.0",
|
||||||
"@tailwindcss/typography": "^0.5.13",
|
"@tailwindcss/typography": "^0.5.13",
|
||||||
|
"@testing-library/react": "16.3.0",
|
||||||
"@types/escape-html": "^1.0.2",
|
"@types/escape-html": "^1.0.2",
|
||||||
"@types/node": "22.5.4",
|
"@types/node": "22.5.4",
|
||||||
"@types/react": "19.1.0",
|
"@types/react": "19.1.0",
|
||||||
"@types/react-dom": "19.1.2",
|
"@types/react-dom": "19.1.2",
|
||||||
|
"@vitejs/plugin-react": "4.5.2",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"eslint": "^9.16.0",
|
"eslint": "^9.16.0",
|
||||||
"eslint-config-next": "15.3.0",
|
"eslint-config-next": "15.3.0",
|
||||||
|
"jsdom": "26.1.0",
|
||||||
|
"playwright": "1.50.0",
|
||||||
|
"playwright-core": "1.50.0",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3",
|
||||||
|
"vite-tsconfig-paths": "5.1.4",
|
||||||
|
"vitest": "3.2.3"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.12.1",
|
"packageManager": "pnpm@10.12.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.20.2 || >=20.9.0"
|
"node": "^18.20.2 || >=20.9.0"
|
||||||
},
|
},
|
||||||
|
|||||||
41
templates/with-vercel-website/playwright.config.ts
Normal file
41
templates/with-vercel-website/playwright.config.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read environment variables from file.
|
||||||
|
* https://github.com/motdotla/dotenv
|
||||||
|
*/
|
||||||
|
import 'dotenv/config'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests/e2e',
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: 'html',
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
|
// baseURL: 'http://localhost:3000',
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: { ...devices['Desktop Chrome'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
webServer: {
|
||||||
|
command: 'pnpm dev',
|
||||||
|
reuseExistingServer: true,
|
||||||
|
url: 'http://localhost:3000',
|
||||||
|
},
|
||||||
|
})
|
||||||
20
templates/with-vercel-website/tests/e2e/frontend.e2e.spec.ts
Normal file
20
templates/with-vercel-website/tests/e2e/frontend.e2e.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { test, expect, Page } from '@playwright/test'
|
||||||
|
|
||||||
|
test.describe('Frontend', () => {
|
||||||
|
let page: Page
|
||||||
|
|
||||||
|
test.beforeAll(async ({ browser }, testInfo) => {
|
||||||
|
const context = await browser.newContext()
|
||||||
|
page = await context.newPage()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('can go on homepage', async ({ page }) => {
|
||||||
|
await page.goto('http://localhost:3000')
|
||||||
|
|
||||||
|
await expect(page).toHaveTitle(/Payload Website Template/)
|
||||||
|
|
||||||
|
const headging = page.locator('h1').first()
|
||||||
|
|
||||||
|
await expect(headging).toHaveText('Payload Website Template')
|
||||||
|
})
|
||||||
|
})
|
||||||
20
templates/with-vercel-website/tests/int/api.int.spec.ts
Normal file
20
templates/with-vercel-website/tests/int/api.int.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { getPayload, Payload } from 'payload'
|
||||||
|
import config from '@/payload.config'
|
||||||
|
|
||||||
|
import { describe, it, beforeAll, expect } from 'vitest'
|
||||||
|
|
||||||
|
let payload: Payload
|
||||||
|
|
||||||
|
describe('API', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
const payloadConfig = await config
|
||||||
|
payload = await getPayload({ config: payloadConfig })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fetches users', async () => {
|
||||||
|
const users = await payload.find({
|
||||||
|
collection: 'users',
|
||||||
|
})
|
||||||
|
expect(users).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,10 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Strictness */
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noUncheckedIndexedAccess": true,
|
|
||||||
"noImplicitOverride": true,
|
|
||||||
|
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
@@ -15,8 +11,6 @@
|
|||||||
],
|
],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strictNullChecks": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
@@ -47,10 +41,11 @@
|
|||||||
"**/*.tsx",
|
"**/*.tsx",
|
||||||
".next/types/**/*.ts",
|
".next/types/**/*.ts",
|
||||||
"redirects.js",
|
"redirects.js",
|
||||||
|
"next-env.d.ts",
|
||||||
"next.config.js",
|
"next.config.js",
|
||||||
"next-sitemap.config.cjs"
|
"next-sitemap.config.cjs"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
12
templates/with-vercel-website/vitest.config.mts
Normal file
12
templates/with-vercel-website/vitest.config.mts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [tsconfigPaths(), react()],
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: ['./vitest.setup.ts'],
|
||||||
|
include: ['tests/int/**/*.int.spec.ts'],
|
||||||
|
},
|
||||||
|
})
|
||||||
4
templates/with-vercel-website/vitest.setup.ts
Normal file
4
templates/with-vercel-website/vitest.setup.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Any setup scripts you might need go here
|
||||||
|
|
||||||
|
// Load .env files
|
||||||
|
import 'dotenv/config'
|
||||||
@@ -37,10 +37,22 @@ async function main() {
|
|||||||
allTgzs,
|
allTgzs,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// remove node_modules
|
||||||
|
await fs.rm(path.join(templatePath, 'node_modules'), { recursive: true, force: true })
|
||||||
|
// replace workspace:* from package.json with a real version so that it can be installed with pnpm
|
||||||
|
// without this step, even though the packages are built locally as tars
|
||||||
|
// it will error as it cannot contain workspace dependencies when installing with --ignore-workspace
|
||||||
|
const packageJsonPath = path.join(templatePath, 'package.json')
|
||||||
|
const initialPackageJson = await fs.readFile(packageJsonPath, 'utf-8')
|
||||||
|
const initialPackageJsonObj = JSON.parse(initialPackageJson)
|
||||||
|
|
||||||
|
updatePackageJSONDependencies({ latestVersion: '3.42.0', packageJson: initialPackageJsonObj })
|
||||||
|
|
||||||
|
await fs.writeFile(packageJsonPath, JSON.stringify(initialPackageJsonObj, null, 2))
|
||||||
|
|
||||||
execSync('pnpm add ./*.tgz --ignore-workspace', execOpts)
|
execSync('pnpm add ./*.tgz --ignore-workspace', execOpts)
|
||||||
execSync('pnpm install --ignore-workspace', execOpts)
|
execSync('pnpm install --ignore-workspace', execOpts)
|
||||||
|
|
||||||
const packageJsonPath = path.join(templatePath, 'package.json')
|
|
||||||
const packageJson = await fs.readFile(packageJsonPath, 'utf-8')
|
const packageJson = await fs.readFile(packageJsonPath, 'utf-8')
|
||||||
const packageJsonObj = JSON.parse(packageJson) as {
|
const packageJsonObj = JSON.parse(packageJson) as {
|
||||||
dependencies: Record<string, string>
|
dependencies: Record<string, string>
|
||||||
@@ -64,7 +76,7 @@ async function main() {
|
|||||||
packageJsonObj.pnpm = { overrides }
|
packageJsonObj.pnpm = { overrides }
|
||||||
await fs.writeFile(packageJsonPath, JSON.stringify(packageJsonObj, null, 2))
|
await fs.writeFile(packageJsonPath, JSON.stringify(packageJsonObj, null, 2))
|
||||||
|
|
||||||
execSync('pnpm install --ignore-workspace --no-frozen-lockfile', execOpts)
|
execSync('pnpm install --no-frozen-lockfile --ignore-workspace', execOpts)
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
path.resolve(templatePath, '.env'),
|
path.resolve(templatePath, '.env'),
|
||||||
// Populate POSTGRES_URL just in case it's needed
|
// Populate POSTGRES_URL just in case it's needed
|
||||||
@@ -81,3 +93,28 @@ BLOB_READ_WRITE_TOKEN=vercel_blob_rw_TEST_asdf`,
|
|||||||
function header(message: string, opts?: { enable?: boolean }) {
|
function header(message: string, opts?: { enable?: boolean }) {
|
||||||
console.log(chalk.bold.green(`${message}\n`))
|
console.log(chalk.bold.green(`${message}\n`))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively updates a JSON object to replace all instances of `workspace:` with the latest version pinned.
|
||||||
|
*
|
||||||
|
* Does not return and instead modifies the `packageJson` object in place.
|
||||||
|
*/
|
||||||
|
export function updatePackageJSONDependencies(args: {
|
||||||
|
latestVersion: string
|
||||||
|
packageJson: Record<string, unknown>
|
||||||
|
}): void {
|
||||||
|
const { latestVersion, packageJson } = args
|
||||||
|
|
||||||
|
const updatedDependencies = Object.entries(packageJson.dependencies || {}).reduce(
|
||||||
|
(acc, [key, value]) => {
|
||||||
|
if (typeof value === 'string' && value.startsWith('workspace:')) {
|
||||||
|
acc[key] = `${latestVersion}`
|
||||||
|
} else {
|
||||||
|
acc[key] = value
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
},
|
||||||
|
{} as Record<string, string>,
|
||||||
|
)
|
||||||
|
packageJson.dependencies = updatedDependencies
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ type TemplateVariation = {
|
|||||||
envNames?: {
|
envNames?: {
|
||||||
dbUri: string
|
dbUri: string
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* If the template is part of the workspace, then do not replace the package.json versions
|
||||||
|
*/
|
||||||
|
workspace?: boolean
|
||||||
generateLockfile?: boolean
|
generateLockfile?: boolean
|
||||||
/** package.json name */
|
/** package.json name */
|
||||||
name: string
|
name: string
|
||||||
@@ -69,7 +73,7 @@ async function main() {
|
|||||||
|
|
||||||
let variations: TemplateVariation[] = [
|
let variations: TemplateVariation[] = [
|
||||||
{
|
{
|
||||||
name: 'payload-vercel-postgres-template',
|
name: 'with-vercel-postgres',
|
||||||
db: 'vercel-postgres',
|
db: 'vercel-postgres',
|
||||||
dirname: 'with-vercel-postgres',
|
dirname: 'with-vercel-postgres',
|
||||||
envNames: {
|
envNames: {
|
||||||
@@ -92,7 +96,7 @@ async function main() {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'payload-vercel-website-template',
|
name: 'with-vercel-website',
|
||||||
base: 'website', // This is the base template to copy from
|
base: 'website', // This is the base template to copy from
|
||||||
db: 'vercel-postgres',
|
db: 'vercel-postgres',
|
||||||
dirname: 'with-vercel-website',
|
dirname: 'with-vercel-website',
|
||||||
@@ -116,7 +120,7 @@ async function main() {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'payload-postgres-template',
|
name: 'with-postgres',
|
||||||
db: 'postgres',
|
db: 'postgres',
|
||||||
dirname: 'with-postgres',
|
dirname: 'with-postgres',
|
||||||
sharp: true,
|
sharp: true,
|
||||||
@@ -124,7 +128,7 @@ async function main() {
|
|||||||
storage: 'localDisk',
|
storage: 'localDisk',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'payload-vercel-mongodb-template',
|
name: 'with-vercel-mongodb',
|
||||||
db: 'mongodb',
|
db: 'mongodb',
|
||||||
dirname: 'with-vercel-mongodb',
|
dirname: 'with-vercel-mongodb',
|
||||||
envNames: {
|
envNames: {
|
||||||
@@ -157,6 +161,8 @@ async function main() {
|
|||||||
// The blank template is used as a base for create-payload-app functionality,
|
// The blank template is used as a base for create-payload-app functionality,
|
||||||
// so we do not configure the payload.config.ts file, which leaves the placeholder comments.
|
// so we do not configure the payload.config.ts file, which leaves the placeholder comments.
|
||||||
configureConfig: false,
|
configureConfig: false,
|
||||||
|
workspace: true,
|
||||||
|
base: 'none', // Do not copy from the base _template directory
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'website',
|
name: 'website',
|
||||||
@@ -172,6 +178,7 @@ async function main() {
|
|||||||
base: 'none',
|
base: 'none',
|
||||||
skipDockerCompose: true,
|
skipDockerCompose: true,
|
||||||
skipReadme: true,
|
skipReadme: true,
|
||||||
|
workspace: true,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -200,6 +207,7 @@ async function main() {
|
|||||||
storage,
|
storage,
|
||||||
vercelDeployButtonLink,
|
vercelDeployButtonLink,
|
||||||
targetDeployment = 'default',
|
targetDeployment = 'default',
|
||||||
|
workspace = false,
|
||||||
} = variation
|
} = variation
|
||||||
|
|
||||||
header(`Generating ${name}...`)
|
header(`Generating ${name}...`)
|
||||||
@@ -229,6 +237,7 @@ async function main() {
|
|||||||
sharp,
|
sharp,
|
||||||
storageAdapter: storage,
|
storageAdapter: storage,
|
||||||
}
|
}
|
||||||
|
|
||||||
await configurePayloadConfig(configureArgs)
|
await configurePayloadConfig(configureArgs)
|
||||||
|
|
||||||
log('Configuring .env.example')
|
log('Configuring .env.example')
|
||||||
@@ -255,18 +264,25 @@ async function main() {
|
|||||||
// Fetch latest npm version of payload package:
|
// Fetch latest npm version of payload package:
|
||||||
const payloadVersion = await getLatestPackageVersion({ packageName: 'payload' })
|
const payloadVersion = await getLatestPackageVersion({ packageName: 'payload' })
|
||||||
|
|
||||||
// Bump package.json versions
|
// Bump package.json versions only in non-workspace templates such as Vercel variants
|
||||||
|
// Workspace templates should always continue to point to `workspace:*` version of payload packages
|
||||||
|
if (!workspace) {
|
||||||
await bumpPackageJson({
|
await bumpPackageJson({
|
||||||
templateDir: destDir,
|
templateDir: destDir,
|
||||||
latestVersion: payloadVersion,
|
latestVersion: payloadVersion,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (generateLockfile) {
|
if (generateLockfile) {
|
||||||
log('Generating pnpm-lock.yaml')
|
log('Generating pnpm-lock.yaml')
|
||||||
execSyncSafe(`pnpm install --ignore-workspace --no-frozen-lockfile`, { cwd: destDir })
|
execSyncSafe(`pnpm install ${workspace ? '' : '--ignore-workspace'} --no-frozen-lockfile`, {
|
||||||
|
cwd: destDir,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
log('Installing dependencies without generating lockfile')
|
log('Installing dependencies without generating lockfile')
|
||||||
execSyncSafe(`pnpm install --ignore-workspace --no-frozen-lockfile`, { cwd: destDir })
|
execSyncSafe(`pnpm install ${workspace ? '' : '--ignore-workspace'} --no-frozen-lockfile`, {
|
||||||
|
cwd: destDir,
|
||||||
|
})
|
||||||
await fs.rm(`${destDir}/pnpm-lock.yaml`, { force: true })
|
await fs.rm(`${destDir}/pnpm-lock.yaml`, { force: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,11 +323,13 @@ async function main() {
|
|||||||
|
|
||||||
// Generate importmap
|
// Generate importmap
|
||||||
log('Generating import map')
|
log('Generating import map')
|
||||||
execSyncSafe(`pnpm --ignore-workspace generate:importmap`, { cwd: destDir })
|
execSyncSafe(`pnpm ${workspace ? '' : '--ignore-workspace'} generate:importmap`, {
|
||||||
|
cwd: destDir,
|
||||||
|
})
|
||||||
|
|
||||||
if (shouldBuild) {
|
if (shouldBuild) {
|
||||||
log('Building...')
|
log('Building...')
|
||||||
execSyncSafe(`pnpm --ignore-workspace build`, { cwd: destDir })
|
execSyncSafe(`pnpm ${workspace ? '' : '--ignore-workspace'} build`, { cwd: destDir })
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Email?
|
// TODO: Email?
|
||||||
@@ -514,9 +532,18 @@ async function getLatestPackageVersion({
|
|||||||
packageName?: string
|
packageName?: string
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`https://registry.npmjs.org/${packageName}`)
|
const response = await fetch(`https://registry.npmjs.org/-/package/${packageName}/dist-tags`)
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
const latestVersion = data['dist-tags'].latest
|
|
||||||
|
// Monster chaining for type safety just checking for data.latest
|
||||||
|
const latestVersion =
|
||||||
|
data &&
|
||||||
|
typeof data === 'object' &&
|
||||||
|
'latest' in data &&
|
||||||
|
data.latest &&
|
||||||
|
typeof data.latest === 'string'
|
||||||
|
? data.latest
|
||||||
|
: null
|
||||||
|
|
||||||
log(`Found latest version of ${packageName}: ${latestVersion}`)
|
log(`Found latest version of ${packageName}: ${latestVersion}`)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user