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 }}
|
||||
# job-summary: true
|
||||
|
||||
# Build listed templates with packed local packages
|
||||
build-templates:
|
||||
# Build listed templates with packed local packages and then runs their int and e2e tests
|
||||
build-and-test-templates:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- template: blank
|
||||
database: mongodb
|
||||
|
||||
- template: website
|
||||
database: mongodb
|
||||
|
||||
- template: with-payload-cloud
|
||||
database: mongodb
|
||||
|
||||
- template: with-vercel-mongodb
|
||||
database: mongodb
|
||||
|
||||
# Postgres
|
||||
- template: with-postgres
|
||||
database: postgres
|
||||
|
||||
- template: with-vercel-postgres
|
||||
database: postgres
|
||||
|
||||
@@ -615,6 +621,45 @@ jobs:
|
||||
env:
|
||||
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:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [changes, build]
|
||||
@@ -650,7 +695,7 @@ jobs:
|
||||
needs:
|
||||
- lint
|
||||
- build
|
||||
- build-templates
|
||||
- build-and-test-templates
|
||||
- tests-unit
|
||||
- tests-int
|
||||
- tests-e2e
|
||||
|
||||
@@ -75,9 +75,7 @@ import * as Sentry from '@sentry/nextjs'
|
||||
const config = buildConfig({
|
||||
collections: [Pages, Media],
|
||||
plugins: [
|
||||
sentryPlugin({
|
||||
Sentry,
|
||||
}),
|
||||
sentryPlugin({ Sentry })
|
||||
],
|
||||
})
|
||||
|
||||
@@ -101,7 +99,7 @@ export default buildConfig({
|
||||
pg, // Inject the patched pg driver for Sentry instrumentation
|
||||
}),
|
||||
plugins: [
|
||||
sentryPlugin({ Sentry }),
|
||||
sentryPlugin({ Sentry })
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "website",
|
||||
"name": "astro-website",
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
10
package.json
10
package.json
@@ -11,11 +11,11 @@
|
||||
"bf": "pnpm run build:force",
|
||||
"build": "pnpm run build:core",
|
||||
"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:analyze": "cross-env ANALYZE=true next 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:create-payload-app": "turbo build --filter create-payload-app",
|
||||
"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:stop": "docker compose -f test/docker-compose.yml down",
|
||||
"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: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 {} +",
|
||||
"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 ..",
|
||||
@@ -181,7 +181,7 @@
|
||||
"tempy": "1.0.1",
|
||||
"tstyche": "^3.1.1",
|
||||
"tsx": "4.19.2",
|
||||
"turbo": "^2.3.3",
|
||||
"turbo": "^2.5.4",
|
||||
"typescript": "5.7.3"
|
||||
},
|
||||
"packageManager": "pnpm@9.7.1",
|
||||
|
||||
@@ -7,7 +7,7 @@ import path from 'path'
|
||||
|
||||
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 { getValidTemplates } from './templates.js'
|
||||
|
||||
@@ -179,5 +179,37 @@ describe('createProject', () => {
|
||||
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()
|
||||
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 (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: {
|
||||
/**
|
||||
* The latest version of Payload to use in the package.json.
|
||||
*/
|
||||
latestVersion: string
|
||||
projectDir: string
|
||||
/**
|
||||
* The name of the project to set in package.json.
|
||||
*/
|
||||
projectName: string
|
||||
}): Promise<void> {
|
||||
const { projectDir, projectName } = args
|
||||
const { latestVersion, projectDir, projectName } = args
|
||||
const packageJsonPath = path.resolve(projectDir, 'package.json')
|
||||
try {
|
||||
const packageObj = await fse.readJson(packageJsonPath)
|
||||
packageObj.name = projectName
|
||||
|
||||
updatePackageJSONDependencies({
|
||||
latestVersion,
|
||||
packageJson: packageObj,
|
||||
})
|
||||
|
||||
await fse.writeJson(packageJsonPath, packageObj, { spaces: 2 })
|
||||
} catch (err: unknown) {
|
||||
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 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) {
|
||||
debugLog(`Using template url: ${template.url}`)
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
],
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./css": {
|
||||
"import": "./src/dummy.css",
|
||||
"default": "./src/dummy.css"
|
||||
},
|
||||
".": {
|
||||
"import": "./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",
|
||||
"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": {
|
||||
"import": "./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/*'
|
||||
- 'tools/*'
|
||||
- 'test'
|
||||
- 'templates/blank'
|
||||
- 'templates/website'
|
||||
# exclude packages that are inside test directories
|
||||
# - '!**/test/**'
|
||||
|
||||
7
templates/_template/.gitignore
vendored
7
templates/_template/.gitignore
vendored
@@ -41,3 +41,10 @@ next-env.d.ts
|
||||
.env
|
||||
|
||||
/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} */
|
||||
const nextConfig = {
|
||||
// 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 })
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"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": {
|
||||
"@payloadcms/db-mongodb": "latest",
|
||||
@@ -30,13 +33,21 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@playwright/test": "1.50.0",
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@types/node": "^22.5.4",
|
||||
"@types/react": "19.1.0",
|
||||
"@types/react-dom": "19.1.2",
|
||||
"@vitejs/plugin-react": "4.5.2",
|
||||
"eslint": "^9.16.0",
|
||||
"eslint-config-next": "15.3.0",
|
||||
"jsdom": "26.1.0",
|
||||
"playwright": "1.50.0",
|
||||
"playwright-core": "1.50.0",
|
||||
"prettier": "^3.4.2",
|
||||
"typescript": "5.7.3"
|
||||
"typescript": "5.7.3",
|
||||
"vite-tsconfig-paths": "5.1.4",
|
||||
"vitest": "3.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"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
|
||||
|
||||
/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} */
|
||||
const nextConfig = {
|
||||
// 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 })
|
||||
|
||||
@@ -1,42 +1,52 @@
|
||||
{
|
||||
"name": "template-blank-3.0",
|
||||
"name": "blank",
|
||||
"version": "1.0.0",
|
||||
"description": "A blank template to get started with Payload 3.0",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"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",
|
||||
"devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",
|
||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"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": {
|
||||
"@payloadcms/db-mongodb": "3.43.0",
|
||||
"@payloadcms/next": "3.43.0",
|
||||
"@payloadcms/payload-cloud": "3.43.0",
|
||||
"@payloadcms/richtext-lexical": "3.43.0",
|
||||
"@payloadcms/ui": "3.43.0",
|
||||
"@payloadcms/db-mongodb": "workspace:*",
|
||||
"@payloadcms/next": "workspace:*",
|
||||
"@payloadcms/payload-cloud": "workspace:*",
|
||||
"@payloadcms/richtext-lexical": "workspace:*",
|
||||
"@payloadcms/ui": "workspace:*",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv": "16.4.7",
|
||||
"graphql": "^16.8.1",
|
||||
"next": "15.3.0",
|
||||
"payload": "3.43.0",
|
||||
"next": "15.3.2",
|
||||
"payload": "workspace:*",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"sharp": "0.32.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@playwright/test": "1.50.0",
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@types/node": "^22.5.4",
|
||||
"@types/react": "19.1.0",
|
||||
"@types/react-dom": "19.1.2",
|
||||
"@vitejs/plugin-react": "4.5.2",
|
||||
"eslint": "^9.16.0",
|
||||
"eslint-config-next": "15.3.0",
|
||||
"jsdom": "26.1.0",
|
||||
"playwright": "1.50.0",
|
||||
"playwright-core": "1.50.0",
|
||||
"prettier": "^3.4.2",
|
||||
"typescript": "5.7.3"
|
||||
"typescript": "5.7.3",
|
||||
"vite-tsconfig-paths": "5.1.4",
|
||||
"vitest": "3.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
auth: {
|
||||
users: UserAuthOperations;
|
||||
};
|
||||
blocks: {};
|
||||
collections: {
|
||||
users: User;
|
||||
media: Media;
|
||||
'payload-locked-documents': PayloadLockedDocument;
|
||||
'payload-preferences': PayloadPreference;
|
||||
'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: {
|
||||
defaultIDType: string;
|
||||
};
|
||||
globals: {};
|
||||
globalsSelect: {};
|
||||
locale: null;
|
||||
user: User & {
|
||||
collection: 'users';
|
||||
};
|
||||
jobs: {
|
||||
tasks: unknown;
|
||||
workflows: unknown;
|
||||
};
|
||||
}
|
||||
export interface UserAuthOperations {
|
||||
forgotPassword: {
|
||||
@@ -79,6 +149,29 @@ export interface Media {
|
||||
focalX?: 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
|
||||
* via the `definition` "payload-preferences".
|
||||
@@ -113,6 +206,71 @@ export interface PayloadMigration {
|
||||
updatedAt: 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
|
||||
* 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": [
|
||||
"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",
|
||||
"description": "A blank template to get started with Payload 3.0",
|
||||
"license": "MIT",
|
||||
|
||||
8
templates/website/.gitignore
vendored
8
templates/website/.gitignore
vendored
@@ -11,3 +11,11 @@ public/media/
|
||||
|
||||
public/robots.txt
|
||||
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,
|
||||
redirects,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@payloadcms/template-website",
|
||||
"name": "website",
|
||||
"version": "1.0.0",
|
||||
"description": "Website template for Payload",
|
||||
"license": "MIT",
|
||||
@@ -16,21 +16,24 @@
|
||||
"lint:fix": "cross-env NODE_OPTIONS=--no-deprecation next lint --fix",
|
||||
"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",
|
||||
"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": {
|
||||
"@payloadcms/admin-bar": "3.43.0",
|
||||
"@payloadcms/db-mongodb": "3.43.0",
|
||||
"@payloadcms/live-preview-react": "3.43.0",
|
||||
"@payloadcms/next": "3.43.0",
|
||||
"@payloadcms/payload-cloud": "3.43.0",
|
||||
"@payloadcms/plugin-form-builder": "3.43.0",
|
||||
"@payloadcms/plugin-nested-docs": "3.43.0",
|
||||
"@payloadcms/plugin-redirects": "3.43.0",
|
||||
"@payloadcms/plugin-search": "3.43.0",
|
||||
"@payloadcms/plugin-seo": "3.43.0",
|
||||
"@payloadcms/richtext-lexical": "3.43.0",
|
||||
"@payloadcms/ui": "3.43.0",
|
||||
"@payloadcms/admin-bar": "workspace:*",
|
||||
"@payloadcms/db-mongodb": "workspace:*",
|
||||
"@payloadcms/live-preview-react": "workspace:*",
|
||||
"@payloadcms/next": "workspace:*",
|
||||
"@payloadcms/payload-cloud": "workspace:*",
|
||||
"@payloadcms/plugin-form-builder": "workspace:*",
|
||||
"@payloadcms/plugin-nested-docs": "workspace:*",
|
||||
"@payloadcms/plugin-redirects": "workspace:*",
|
||||
"@payloadcms/plugin-search": "workspace:*",
|
||||
"@payloadcms/plugin-seo": "workspace:*",
|
||||
"@payloadcms/richtext-lexical": "workspace:*",
|
||||
"@payloadcms/ui": "workspace:*",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-select": "^2.0.0",
|
||||
@@ -38,12 +41,13 @@
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv": "16.4.7",
|
||||
"geist": "^1.3.0",
|
||||
"graphql": "^16.8.2",
|
||||
"lucide-react": "^0.378.0",
|
||||
"next": "15.3.0",
|
||||
"next": "15.3.3",
|
||||
"next-sitemap": "^4.2.3",
|
||||
"payload": "3.43.0",
|
||||
"payload": "workspace:*",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
@@ -66,6 +70,14 @@
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.4.2",
|
||||
"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"
|
||||
},
|
||||
"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'
|
||||
|
||||
export const importMap = {
|
||||
'@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell':
|
||||
RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||
'@payloadcms/richtext-lexical/rsc#RscEntryLexicalField':
|
||||
RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||
'@payloadcms/richtext-lexical/rsc#LexicalDiffComponent':
|
||||
LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||
'@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient':
|
||||
InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
'@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient':
|
||||
FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
'@payloadcms/richtext-lexical/client#HeadingFeatureClient':
|
||||
HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
'@payloadcms/richtext-lexical/client#ParagraphFeatureClient':
|
||||
ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
'@payloadcms/richtext-lexical/client#UnderlineFeatureClient':
|
||||
UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
'@payloadcms/richtext-lexical/client#BoldFeatureClient':
|
||||
BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
'@payloadcms/richtext-lexical/client#ItalicFeatureClient':
|
||||
ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
'@payloadcms/richtext-lexical/client#LinkFeatureClient':
|
||||
LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
'@payloadcms/plugin-seo/client#OverviewComponent':
|
||||
OverviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||
'@payloadcms/plugin-seo/client#MetaTitleComponent':
|
||||
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,
|
||||
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell": RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalField": RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||
"@payloadcms/richtext-lexical/rsc#LexicalDiffComponent": LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||
"@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient": FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/richtext-lexical/client#ParagraphFeatureClient": ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/plugin-seo/client#OverviewComponent": OverviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||
"@payloadcms/plugin-seo/client#MetaTitleComponent": 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": {
|
||||
/* Strictness */
|
||||
"strict": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
|
||||
"baseUrl": ".",
|
||||
"esModuleInterop": true,
|
||||
"target": "ES2022",
|
||||
@@ -15,8 +11,6 @@
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
"jsx": "preserve",
|
||||
@@ -47,10 +41,11 @@
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
"redirects.js",
|
||||
"next-env.d.ts",
|
||||
"next.config.js",
|
||||
"next-sitemap.config.cjs"
|
||||
],
|
||||
"exclude": [
|
||||
"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",
|
||||
"description": "A blank template to get started with Payload 3.0",
|
||||
"license": "MIT",
|
||||
|
||||
7
templates/with-postgres/.gitignore
vendored
7
templates/with-postgres/.gitignore
vendored
@@ -41,3 +41,10 @@ next-env.d.ts
|
||||
.env
|
||||
|
||||
/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
|
||||
|
||||
|
||||
@@ -3,6 +3,15 @@ import { withPayload } from '@payloadcms/next/withPayload'
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// 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 })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "payload-postgres-template",
|
||||
"name": "with-postgres",
|
||||
"version": "1.0.0",
|
||||
"description": "A blank template to get started with Payload 3.0",
|
||||
"license": "MIT",
|
||||
@@ -13,7 +13,10 @@
|
||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"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": {
|
||||
"@payloadcms/db-postgres": "3.43.0",
|
||||
@@ -31,13 +34,21 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@playwright/test": "1.50.0",
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@types/node": "^22.5.4",
|
||||
"@types/react": "19.1.0",
|
||||
"@types/react-dom": "19.1.2",
|
||||
"@vitejs/plugin-react": "4.5.2",
|
||||
"eslint": "^9.16.0",
|
||||
"eslint-config-next": "15.3.0",
|
||||
"jsdom": "26.1.0",
|
||||
"playwright": "1.50.0",
|
||||
"playwright-core": "1.50.0",
|
||||
"prettier": "^3.4.2",
|
||||
"typescript": "5.7.3"
|
||||
"typescript": "5.7.3",
|
||||
"vite-tsconfig-paths": "5.1.4",
|
||||
"vitest": "3.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"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
|
||||
|
||||
/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} */
|
||||
const nextConfig = {
|
||||
// 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 })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "payload-vercel-mongodb-template",
|
||||
"name": "with-vercel-mongodb",
|
||||
"version": "1.0.0",
|
||||
"description": "A blank template to get started with Payload 3.0",
|
||||
"license": "MIT",
|
||||
@@ -12,7 +12,10 @@
|
||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"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": {
|
||||
"@payloadcms/db-mongodb": "3.43.0",
|
||||
@@ -30,15 +33,23 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@playwright/test": "1.50.0",
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@types/node": "^22.5.4",
|
||||
"@types/react": "19.1.0",
|
||||
"@types/react-dom": "19.1.2",
|
||||
"@vitejs/plugin-react": "4.5.2",
|
||||
"eslint": "^9.16.0",
|
||||
"eslint-config-next": "15.3.0",
|
||||
"jsdom": "26.1.0",
|
||||
"playwright": "1.50.0",
|
||||
"playwright-core": "1.50.0",
|
||||
"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": {
|
||||
"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
|
||||
|
||||
/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} */
|
||||
const nextConfig = {
|
||||
// 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 })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "payload-vercel-postgres-template",
|
||||
"name": "with-vercel-postgres",
|
||||
"version": "1.0.0",
|
||||
"description": "A blank template to get started with Payload 3.0",
|
||||
"license": "MIT",
|
||||
@@ -13,7 +13,10 @@
|
||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"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": {
|
||||
"@payloadcms/db-vercel-postgres": "3.43.0",
|
||||
@@ -31,15 +34,23 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@playwright/test": "1.50.0",
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@types/node": "^22.5.4",
|
||||
"@types/react": "19.1.0",
|
||||
"@types/react-dom": "19.1.2",
|
||||
"@vitejs/plugin-react": "4.5.2",
|
||||
"eslint": "^9.16.0",
|
||||
"eslint-config-next": "15.3.0",
|
||||
"jsdom": "26.1.0",
|
||||
"playwright": "1.50.0",
|
||||
"playwright-core": "1.50.0",
|
||||
"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": {
|
||||
"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",
|
||||
"version": "7",
|
||||
"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 = [
|
||||
{
|
||||
up: migration_20250616_201653_initial.up,
|
||||
down: migration_20250616_201653_initial.down,
|
||||
name: '20250616_201653_initial',
|
||||
up: migration_20250624_171210_initial.up,
|
||||
down: migration_20250624_171210_initial.down,
|
||||
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/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,
|
||||
redirects,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "payload-vercel-website-template",
|
||||
"name": "with-vercel-website",
|
||||
"version": "1.0.0",
|
||||
"description": "Website template for Payload",
|
||||
"license": "MIT",
|
||||
@@ -17,7 +17,10 @@
|
||||
"lint:fix": "cross-env NODE_OPTIONS=--no-deprecation next lint --fix",
|
||||
"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",
|
||||
"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": {
|
||||
"@payloadcms/admin-bar": "3.43.0",
|
||||
@@ -40,10 +43,11 @@
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv": "16.4.7",
|
||||
"geist": "^1.3.0",
|
||||
"graphql": "^16.8.2",
|
||||
"lucide-react": "^0.378.0",
|
||||
"next": "15.3.0",
|
||||
"next": "15.3.3",
|
||||
"next-sitemap": "^4.2.3",
|
||||
"payload": "3.43.0",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
@@ -56,21 +60,29 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@playwright/test": "1.50.0",
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@types/escape-html": "^1.0.2",
|
||||
"@types/node": "22.5.4",
|
||||
"@types/react": "19.1.0",
|
||||
"@types/react-dom": "19.1.2",
|
||||
"@vitejs/plugin-react": "4.5.2",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"copyfiles": "^2.4.1",
|
||||
"eslint": "^9.16.0",
|
||||
"eslint-config-next": "15.3.0",
|
||||
"jsdom": "26.1.0",
|
||||
"playwright": "1.50.0",
|
||||
"playwright-core": "1.50.0",
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.4.2",
|
||||
"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": {
|
||||
"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": {
|
||||
/* Strictness */
|
||||
"strict": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
|
||||
"baseUrl": ".",
|
||||
"esModuleInterop": true,
|
||||
"target": "ES2022",
|
||||
@@ -15,8 +11,6 @@
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
"jsx": "preserve",
|
||||
@@ -47,10 +41,11 @@
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
"redirects.js",
|
||||
"next-env.d.ts",
|
||||
"next.config.js",
|
||||
"next-sitemap.config.cjs"
|
||||
],
|
||||
"exclude": [
|
||||
"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,
|
||||
})
|
||||
|
||||
// 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 install --ignore-workspace', execOpts)
|
||||
|
||||
const packageJsonPath = path.join(templatePath, 'package.json')
|
||||
const packageJson = await fs.readFile(packageJsonPath, 'utf-8')
|
||||
const packageJsonObj = JSON.parse(packageJson) as {
|
||||
dependencies: Record<string, string>
|
||||
@@ -64,7 +76,7 @@ async function main() {
|
||||
packageJsonObj.pnpm = { overrides }
|
||||
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(
|
||||
path.resolve(templatePath, '.env'),
|
||||
// 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 }) {
|
||||
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?: {
|
||||
dbUri: string
|
||||
}
|
||||
/**
|
||||
* If the template is part of the workspace, then do not replace the package.json versions
|
||||
*/
|
||||
workspace?: boolean
|
||||
generateLockfile?: boolean
|
||||
/** package.json name */
|
||||
name: string
|
||||
@@ -69,7 +73,7 @@ async function main() {
|
||||
|
||||
let variations: TemplateVariation[] = [
|
||||
{
|
||||
name: 'payload-vercel-postgres-template',
|
||||
name: 'with-vercel-postgres',
|
||||
db: 'vercel-postgres',
|
||||
dirname: 'with-vercel-postgres',
|
||||
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
|
||||
db: 'vercel-postgres',
|
||||
dirname: 'with-vercel-website',
|
||||
@@ -116,7 +120,7 @@ async function main() {
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'payload-postgres-template',
|
||||
name: 'with-postgres',
|
||||
db: 'postgres',
|
||||
dirname: 'with-postgres',
|
||||
sharp: true,
|
||||
@@ -124,7 +128,7 @@ async function main() {
|
||||
storage: 'localDisk',
|
||||
},
|
||||
{
|
||||
name: 'payload-vercel-mongodb-template',
|
||||
name: 'with-vercel-mongodb',
|
||||
db: 'mongodb',
|
||||
dirname: 'with-vercel-mongodb',
|
||||
envNames: {
|
||||
@@ -157,6 +161,8 @@ async function main() {
|
||||
// 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.
|
||||
configureConfig: false,
|
||||
workspace: true,
|
||||
base: 'none', // Do not copy from the base _template directory
|
||||
},
|
||||
{
|
||||
name: 'website',
|
||||
@@ -172,6 +178,7 @@ async function main() {
|
||||
base: 'none',
|
||||
skipDockerCompose: true,
|
||||
skipReadme: true,
|
||||
workspace: true,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -200,6 +207,7 @@ async function main() {
|
||||
storage,
|
||||
vercelDeployButtonLink,
|
||||
targetDeployment = 'default',
|
||||
workspace = false,
|
||||
} = variation
|
||||
|
||||
header(`Generating ${name}...`)
|
||||
@@ -229,6 +237,7 @@ async function main() {
|
||||
sharp,
|
||||
storageAdapter: storage,
|
||||
}
|
||||
|
||||
await configurePayloadConfig(configureArgs)
|
||||
|
||||
log('Configuring .env.example')
|
||||
@@ -255,18 +264,25 @@ async function main() {
|
||||
// Fetch latest npm version of payload package:
|
||||
const payloadVersion = await getLatestPackageVersion({ packageName: 'payload' })
|
||||
|
||||
// Bump package.json versions
|
||||
await bumpPackageJson({
|
||||
templateDir: destDir,
|
||||
latestVersion: payloadVersion,
|
||||
})
|
||||
// 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({
|
||||
templateDir: destDir,
|
||||
latestVersion: payloadVersion,
|
||||
})
|
||||
}
|
||||
|
||||
if (generateLockfile) {
|
||||
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 {
|
||||
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 })
|
||||
}
|
||||
|
||||
@@ -307,11 +323,13 @@ async function main() {
|
||||
|
||||
// Generate importmap
|
||||
log('Generating import map')
|
||||
execSyncSafe(`pnpm --ignore-workspace generate:importmap`, { cwd: destDir })
|
||||
execSyncSafe(`pnpm ${workspace ? '' : '--ignore-workspace'} generate:importmap`, {
|
||||
cwd: destDir,
|
||||
})
|
||||
|
||||
if (shouldBuild) {
|
||||
log('Building...')
|
||||
execSyncSafe(`pnpm --ignore-workspace build`, { cwd: destDir })
|
||||
execSyncSafe(`pnpm ${workspace ? '' : '--ignore-workspace'} build`, { cwd: destDir })
|
||||
}
|
||||
|
||||
// TODO: Email?
|
||||
@@ -514,9 +532,18 @@ async function getLatestPackageVersion({
|
||||
packageName?: string
|
||||
}) {
|
||||
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 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}`)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user