diff --git a/docs/configuration/overview.mdx b/docs/configuration/overview.mdx index b60ab4f8e..1c50bff5a 100644 --- a/docs/configuration/overview.mdx +++ b/docs/configuration/overview.mdx @@ -36,7 +36,6 @@ Here is one of the simplest possible Payload configs: ```ts import { buildConfig } from 'payload' import { mongooseAdapter } from '@payloadcms/db-mongodb' -// import { postgresAdapter } from '@payloadcms/db-postgres' export default buildConfig({ secret: process.env.PAYLOAD_SECRET, diff --git a/docs/database/postgres.mdx b/docs/database/postgres.mdx index 09da6d2e6..c7d010718 100644 --- a/docs/database/postgres.mdx +++ b/docs/database/postgres.mdx @@ -8,18 +8,20 @@ keywords: Postgres, documentation, typescript, Content Management System, cms, h To use Payload with Postgres, install the package `@payloadcms/db-postgres`. It leverages Drizzle ORM and `node-postgres` to interact with a Postgres database that you provide. +Alternatively, the `@payloadcms/db-vercel-postgres` package is also available and is optimized for use with Vercel. + It automatically manages changes to your database for you in development mode, and exposes a full suite of migration controls for you to leverage in order to keep other database environments in sync with your schema. DDL transformations are automatically generated. To configure Payload to use Postgres, pass the `postgresAdapter` to your Payload Config as follows: +### Usage + +`@payloadcms/db-postgres`: + ```ts import { postgresAdapter } from '@payloadcms/db-postgres' export default buildConfig({ - // Your config goes here - collections: [ - // Collections go here - ], // Configure the Postgres adapter here db: postgresAdapter({ // Postgres-specific arguments go here. @@ -31,11 +33,28 @@ export default buildConfig({ }) ``` +`@payloadcms/db-vercel-postgres`: + +```ts +import { vercelPostgresAdapter } from '@payloadcms/db-vercel-postgres' + +export default buildConfig({ + // Automatically uses proces.env.POSTGRES_URL if no options are provided. + db: vercelPostgresAdapter(), + // Optionally, can accept the same options as the @vercel/postgres package. + db: vercelPostgresAdapter({ + pool: { + connectionString: process.env.DATABASE_URL + }, + }), +}) +``` + ## Options | Option | Description | -|-----------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `pool` \* | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres`. | +| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `pool` \* | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres` or to `@vercel/postgres` | | `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. | | `migrationDir` | Customize the directory that migrations are stored. | | `logger` | The instance of the logger to be passed to drizzle. By default Payload's will be used. | diff --git a/docs/getting-started/concepts.mdx b/docs/getting-started/concepts.mdx index b853cd8e1..a13e1dfdb 100644 --- a/docs/getting-started/concepts.mdx +++ b/docs/getting-started/concepts.mdx @@ -162,7 +162,7 @@ All of Payload's GraphQL functionality is abstracted into a separate package. Pa This is the UI library that Payload's Admin Panel uses. All components are exported from this package and can be re-used as you build extensions to the Payload admin UI, or want to use Payload components in your own React apps. Some exports are server components and some are client components. -`@payloadcms/db-postgres`, `@payloadcms/db-mongodb` +`@payloadcms/db-postgres`, `@payloadcms/db-vercel-postgres`, `@payloadcms/db-mongodb` You can choose which Database Adapter you'd like to use for your project, and no matter which you choose, the entire data layer for Payload is contained within these packages. You can only use one at a time for any given project. diff --git a/packages/create-payload-app/src/lib/replacements.ts b/packages/create-payload-app/src/lib/replacements.ts index 319d94d18..1d4496361 100644 --- a/packages/create-payload-app/src/lib/replacements.ts +++ b/packages/create-payload-app/src/lib/replacements.ts @@ -29,6 +29,18 @@ const postgresReplacement: DbAdapterReplacement = { packageName: '@payloadcms/db-postgres', } +const vercelPostgresReplacement: DbAdapterReplacement = { + configReplacement: (envName = 'POSTGRES_URL') => [ + ' db: vercelPostgresAdapter({', + ' pool: {', + ` connectionString: process.env.${envName} || '',`, + ' },', + ' }),', + ], + importReplacement: "import { vercelPostgresAdapter } from '@payloadcms/db-vercel-postgres'", + packageName: '@payloadcms/db-vercel-postgres', +} + const sqliteReplacement: DbAdapterReplacement = { configReplacement: (envName = 'DATABASE_URI') => [ ' db: sqliteAdapter({', @@ -45,6 +57,7 @@ export const dbReplacements: Record = { mongodb: mongodbReplacement, postgres: postgresReplacement, sqlite: sqliteReplacement, + vercelPostgres: vercelPostgresReplacement, } type StorageAdapterReplacement = { diff --git a/packages/create-payload-app/src/lib/select-db.ts b/packages/create-payload-app/src/lib/select-db.ts index f9c826870..a1a0e8995 100644 --- a/packages/create-payload-app/src/lib/select-db.ts +++ b/packages/create-payload-app/src/lib/select-db.ts @@ -27,6 +27,11 @@ const dbChoiceRecord: Record = { title: 'SQLite (beta)', value: 'sqlite', }, + vercelPostgres: { + dbConnectionPrefix: 'postgres://postgres:@127.0.0.1:5432/', + title: 'Vercel Postgres (beta)', + value: 'vercelPostgres', + }, } export async function selectDb(args: CliArgs, projectName: string): Promise { diff --git a/packages/create-payload-app/src/lib/write-env-file.ts b/packages/create-payload-app/src/lib/write-env-file.ts index 1388321b6..e804e25c5 100644 --- a/packages/create-payload-app/src/lib/write-env-file.ts +++ b/packages/create-payload-app/src/lib/write-env-file.ts @@ -42,7 +42,12 @@ export async function writeEnvFile(args: { const key = split[0] let value = split[1] - if (key === 'MONGODB_URI' || key === 'MONGO_URL' || key === 'DATABASE_URI') { + if ( + key === 'MONGODB_URI' || + key === 'MONGO_URL' || + key === 'DATABASE_URI' || + key === 'POSTGRES_URL' + ) { value = databaseUri } if (key === 'PAYLOAD_SECRET' || key === 'PAYLOAD_SECRET_KEY') { diff --git a/packages/create-payload-app/src/types.ts b/packages/create-payload-app/src/types.ts index d5f4fecba..39c4b21dd 100644 --- a/packages/create-payload-app/src/types.ts +++ b/packages/create-payload-app/src/types.ts @@ -57,7 +57,7 @@ interface Template { export type PackageManager = 'bun' | 'npm' | 'pnpm' | 'yarn' -export type DbType = 'mongodb' | 'postgres' | 'sqlite' +export type DbType = 'mongodb' | 'postgres' | 'sqlite' | 'vercelPostgres' export type DbDetails = { dbUri: string diff --git a/scripts/generate-template-variations.ts b/scripts/generate-template-variations.ts index e975e0476..e30ff2cb7 100644 --- a/scripts/generate-template-variations.ts +++ b/scripts/generate-template-variations.ts @@ -11,6 +11,7 @@ import type { DbType, StorageAdapterType } from 'packages/create-payload-app/src/types.js' +import chalk from 'chalk' import { execSync } from 'child_process' import { configurePayloadConfig } from 'create-payload-app/lib/configure-payload-config.js' import { copyRecursiveSync } from 'create-payload-app/utils/copy-recursive-sync.js' @@ -51,7 +52,7 @@ async function main() { { name: 'payload-vercel-postgres-template', dirname: 'with-vercel-postgres', - db: 'postgres', + db: 'vercelPostgres', storage: 'vercelBlobStorage', sharp: false, vercelDeployButtonLink: @@ -68,6 +69,13 @@ async function main() { dbUri: 'POSTGRES_URL', }, }, + { + name: 'payload-postgres-template', + dirname: 'with-postgres', + db: 'postgres', + storage: 'localDisk', + sharp: true, + }, { name: 'payload-vercel-mongodb-template', dirname: 'with-vercel-mongodb', @@ -94,8 +102,8 @@ async function main() { db: 'mongodb', storage: 'localDisk', sharp: true, - // The blank template will later be used by CPA as a base. That's when we want to - // configure the config - not here + // 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, }, { @@ -117,13 +125,13 @@ async function main() { sharp, configureConfig, } of variations) { - console.log(`Generating ${name}...`) + header(`Generating ${name}...`) const destDir = path.join(templatesDir, dirname) copyRecursiveSync(path.join(templatesDir, '_template'), destDir) - console.log(`Generated ${name} in ${destDir}`) + log(`Copied to ${destDir}`) if (configureConfig !== false) { - // Configure payload config + log('Configuring payload.config.ts') await configurePayloadConfig({ dbType: db, packageJsonName: name, @@ -132,6 +140,13 @@ async function main() { sharp, envNames, }) + + log('Configuring .env.example') + // Replace DATABASE_URI with the correct env name if set + await writeEnvExample({ + destDir, + envNames, + }) } await generateReadme({ @@ -153,7 +168,7 @@ async function main() { if ((await fs.stat(migrationDestDir).catch(() => null)) === null) { await fs.mkdir(migrationDestDir, { recursive: true }) } - console.log(`Copying migrations from ${migrationSrcDir} to ${migrationDestDir}`) + log(`Copying migrations from ${migrationSrcDir} to ${migrationDestDir}`) copyRecursiveSync(migrationSrcDir, migrationDestDir) } @@ -161,13 +176,13 @@ async function main() { // TODO: Sharp? - console.log(`Done configuring payload config for ${destDir}/src/payload.config.ts`) + log(`Done configuring payload config for ${destDir}/src/payload.config.ts`) } // TODO: Run prettier manually on the generated files, husky blows up - console.log('Running prettier on generated files...') + log('Running prettier on generated files...') execSync(`pnpm prettier --write templates "*.{js,jsx,ts,tsx}"`) - console.log('Template generation complete!') + log('Template generation complete!') } async function generateReadme({ @@ -199,5 +214,35 @@ ${description} const readmePath = path.join(destDir, 'README.md') await fs.writeFile(readmePath, readmeContent) - console.log(`Generated README.md in ${readmePath}`) + log('Generated README.md') +} + +async function writeEnvExample({ + destDir, + envNames, +}: { + destDir: string + envNames?: TemplateVariations['envNames'] +}) { + const envExamplePath = path.join(destDir, '.env.example') + const envFileContents = await fs.readFile(envExamplePath, 'utf8') + const fileContents = envFileContents + .split('\n') + .filter((e) => e) + .map((l) => + envNames?.dbUri && l.startsWith('DATABASE_URI') + ? l.replace('DATABASE_URI', envNames.dbUri) + : l, + ) + .join('\n') + + await fs.writeFile(envExamplePath, fileContents) +} + +function header(message: string) { + console.log(chalk.bold.green(`\n${message}\n`)) +} + +function log(message: string) { + console.log(chalk.dim(message)) } diff --git a/templates/with-payload-cloud/.env.example b/templates/with-payload-cloud/.env.example index 441b33e68..0cb45aaa6 100644 --- a/templates/with-payload-cloud/.env.example +++ b/templates/with-payload-cloud/.env.example @@ -1,2 +1,2 @@ DATABASE_URI=mongodb://127.0.0.1/payload-template-blank-3-0 -PAYLOAD_SECRET=YOUR_SECRET_HERE +PAYLOAD_SECRET=YOUR_SECRET_HERE \ No newline at end of file diff --git a/templates/with-postgres/.env.example b/templates/with-postgres/.env.example new file mode 100644 index 000000000..0cb45aaa6 --- /dev/null +++ b/templates/with-postgres/.env.example @@ -0,0 +1,2 @@ +DATABASE_URI=mongodb://127.0.0.1/payload-template-blank-3-0 +PAYLOAD_SECRET=YOUR_SECRET_HERE \ No newline at end of file diff --git a/templates/with-postgres/.eslintrc.cjs b/templates/with-postgres/.eslintrc.cjs new file mode 100644 index 000000000..27ce17c15 --- /dev/null +++ b/templates/with-postgres/.eslintrc.cjs @@ -0,0 +1,8 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + extends: ['next/core-web-vitals'], + parserOptions: { + project: ['./tsconfig.json'], + tsconfigRootDir: __dirname, + }, +} diff --git a/templates/with-postgres/.gitignore b/templates/with-postgres/.gitignore new file mode 100644 index 000000000..3d53a40bc --- /dev/null +++ b/templates/with-postgres/.gitignore @@ -0,0 +1,43 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +/.idea/* +!/.idea/runConfigurations + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +.env + +/media diff --git a/templates/with-postgres/.prettierrc.json b/templates/with-postgres/.prettierrc.json new file mode 100644 index 000000000..cb8ee2671 --- /dev/null +++ b/templates/with-postgres/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 100, + "semi": false +} diff --git a/templates/with-postgres/.yarnrc b/templates/with-postgres/.yarnrc new file mode 100644 index 000000000..5e7a4dd33 --- /dev/null +++ b/templates/with-postgres/.yarnrc @@ -0,0 +1 @@ +--install.ignore-engines true diff --git a/templates/with-postgres/Dockerfile b/templates/with-postgres/Dockerfile new file mode 100644 index 000000000..607f608d2 --- /dev/null +++ b/templates/with-postgres/Dockerfile @@ -0,0 +1,69 @@ +# From https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile + +FROM node:18-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# Install dependencies based on the preferred package manager +COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ +RUN \ + if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ + elif [ -f package-lock.json ]; then npm ci; \ + elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \ + else echo "Lockfile not found." && exit 1; \ + fi + + +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Next.js collects completely anonymous telemetry data about general usage. +# Learn more here: https://nextjs.org/telemetry +# Uncomment the following line in case you want to disable telemetry during the build. +# ENV NEXT_TELEMETRY_DISABLED 1 + +RUN \ + if [ -f yarn.lock ]; then yarn run build; \ + elif [ -f package-lock.json ]; then npm run build; \ + elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \ + else echo "Lockfile not found." && exit 1; \ + fi + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV production +# Uncomment the following line in case you want to disable telemetry during runtime. +# ENV NEXT_TELEMETRY_DISABLED 1 + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public + +# Set the correct permission for prerender cache +RUN mkdir .next +RUN chown nextjs:nodejs .next + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +ENV PORT 3000 + +# server.js is created by next build from the standalone output +# https://nextjs.org/docs/pages/api-reference/next-config-js/output +CMD HOSTNAME="0.0.0.0" node server.js diff --git a/templates/with-postgres/README.md b/templates/with-postgres/README.md new file mode 100644 index 000000000..c342c4aea --- /dev/null +++ b/templates/with-postgres/README.md @@ -0,0 +1,8 @@ +# payload-postgres-template + +payload-postgres-template + +## Attributes + +- **Database**: postgres +- **Storage Adapter**: localDisk diff --git a/templates/with-postgres/docker-compose.yml b/templates/with-postgres/docker-compose.yml new file mode 100644 index 000000000..3aba7cc7e --- /dev/null +++ b/templates/with-postgres/docker-compose.yml @@ -0,0 +1,43 @@ +version: '3' + +services: + payload: + image: node:18-alpine + ports: + - '3000:3000' + volumes: + - .:/home/node/app + - node_modules:/home/node/app/node_modules + working_dir: /home/node/app/ + command: sh -c "corepack enable && corepack prepare pnpm@latest --activate && pnpm install && pnpm dev" + depends_on: + - mongo + # - postgres + env_file: + - .env + + # Ensure your DATABASE_URI uses 'mongo' as the hostname ie. mongodb://mongo/my-db-name + mongo: + image: mongo:latest + ports: + - '27017:27017' + command: + - --storageEngine=wiredTiger + volumes: + - data:/data/db + logging: + driver: none + + # Uncomment the following to use postgres + # postgres: + # restart: always + # image: postgres:latest + # volumes: + # - pgdata:/var/lib/postgresql/data + # ports: + # - "5432:5432" + +volumes: + data: + # pgdata: + node_modules: diff --git a/templates/with-postgres/next.config.mjs b/templates/with-postgres/next.config.mjs new file mode 100644 index 000000000..7ec4bd836 --- /dev/null +++ b/templates/with-postgres/next.config.mjs @@ -0,0 +1,8 @@ +import { withPayload } from '@payloadcms/next/withPayload' + +/** @type {import('next').NextConfig} */ +const nextConfig = { + // Your Next.js config here +} + +export default withPayload(nextConfig) diff --git a/templates/with-postgres/package.json b/templates/with-postgres/package.json new file mode 100644 index 000000000..c58f460ac --- /dev/null +++ b/templates/with-postgres/package.json @@ -0,0 +1,51 @@ +{ + "name": "payload-postgres-template", + "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", + "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" + }, + "dependencies": { + "@payloadcms/db-postgres": "beta", + "@payloadcms/next": "beta", + "@payloadcms/plugin-cloud": "beta", + "@payloadcms/richtext-lexical": "beta", + "cross-env": "^7.0.3", + "graphql": "^16.8.1", + "next": "15.0.0-canary.104", + "payload": "beta", + "react": "19.0.0-rc-06d0b89e-20240801", + "react-dom": "19.0.0-rc-06d0b89e-20240801", + "sharp": "0.32.6" + }, + "devDependencies": { + "@types/node": "^20.14.9", + "@types/react": "npm:types-react@19.0.0-rc.0", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.0", + "eslint": "^8", + "eslint-config-next": "15.0.0-canary.104", + "typescript": "5.5.4" + }, + "engines": { + "node": "^18.20.2 || >=20.9.0" + }, + "pnpm": { + "overrides": { + "@types/react": "npm:types-react@19.0.0-rc.0", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.0" + } + }, + "overrides": { + "@types/react": "npm:types-react@19.0.0-rc.0", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.0" + } +} diff --git a/templates/with-postgres/src/app/(payload)/admin/[[...segments]]/not-found.tsx b/templates/with-postgres/src/app/(payload)/admin/[[...segments]]/not-found.tsx new file mode 100644 index 000000000..d5e3c923e --- /dev/null +++ b/templates/with-postgres/src/app/(payload)/admin/[[...segments]]/not-found.tsx @@ -0,0 +1,24 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +import type { Metadata } from 'next' + +import config from '@payload-config' +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views' +import { importMap } from '../importMap' + +type Args = { + params: { + segments: string[] + } + searchParams: { + [key: string]: string | string[] + } +} + +export const generateMetadata = ({ params, searchParams }: Args): Promise => + generatePageMetadata({ config, params, searchParams }) + +const NotFound = ({ params, searchParams }: Args) => + NotFoundPage({ config, params, searchParams, importMap }) + +export default NotFound diff --git a/templates/with-postgres/src/app/(payload)/admin/[[...segments]]/page.tsx b/templates/with-postgres/src/app/(payload)/admin/[[...segments]]/page.tsx new file mode 100644 index 000000000..4d5bbfd27 --- /dev/null +++ b/templates/with-postgres/src/app/(payload)/admin/[[...segments]]/page.tsx @@ -0,0 +1,24 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +import type { Metadata } from 'next' + +import config from '@payload-config' +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import { RootPage, generatePageMetadata } from '@payloadcms/next/views' +import { importMap } from '../importMap' + +type Args = { + params: { + segments: string[] + } + searchParams: { + [key: string]: string | string[] + } +} + +export const generateMetadata = ({ params, searchParams }: Args): Promise => + generatePageMetadata({ config, params, searchParams }) + +const Page = ({ params, searchParams }: Args) => + RootPage({ config, params, searchParams, importMap }) + +export default Page diff --git a/templates/with-postgres/src/app/(payload)/admin/importMap.js b/templates/with-postgres/src/app/(payload)/admin/importMap.js new file mode 100644 index 000000000..8ef702138 --- /dev/null +++ b/templates/with-postgres/src/app/(payload)/admin/importMap.js @@ -0,0 +1 @@ +export const importMap = {} diff --git a/templates/with-postgres/src/app/(payload)/api/[...slug]/route.ts b/templates/with-postgres/src/app/(payload)/api/[...slug]/route.ts new file mode 100644 index 000000000..52caec96a --- /dev/null +++ b/templates/with-postgres/src/app/(payload)/api/[...slug]/route.ts @@ -0,0 +1,10 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY it because it could be re-written at any time. */ +import config from '@payload-config' +import { REST_DELETE, REST_GET, REST_OPTIONS, REST_PATCH, REST_POST } from '@payloadcms/next/routes' + +export const GET = REST_GET(config) +export const POST = REST_POST(config) +export const DELETE = REST_DELETE(config) +export const PATCH = REST_PATCH(config) +export const OPTIONS = REST_OPTIONS(config) diff --git a/templates/with-postgres/src/app/(payload)/api/graphql-playground/route.ts b/templates/with-postgres/src/app/(payload)/api/graphql-playground/route.ts new file mode 100644 index 000000000..7b7f27998 --- /dev/null +++ b/templates/with-postgres/src/app/(payload)/api/graphql-playground/route.ts @@ -0,0 +1,6 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY it because it could be re-written at any time. */ +import config from '@payload-config' +import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes' + +export const GET = GRAPHQL_PLAYGROUND_GET(config) diff --git a/templates/with-postgres/src/app/(payload)/api/graphql/route.ts b/templates/with-postgres/src/app/(payload)/api/graphql/route.ts new file mode 100644 index 000000000..c2723e439 --- /dev/null +++ b/templates/with-postgres/src/app/(payload)/api/graphql/route.ts @@ -0,0 +1,6 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY it because it could be re-written at any time. */ +import config from '@payload-config' +import { GRAPHQL_POST } from '@payloadcms/next/routes' + +export const POST = GRAPHQL_POST(config) diff --git a/templates/with-postgres/src/app/(payload)/custom.scss b/templates/with-postgres/src/app/(payload)/custom.scss new file mode 100644 index 000000000..e69de29bb diff --git a/templates/with-postgres/src/app/(payload)/layout.tsx b/templates/with-postgres/src/app/(payload)/layout.tsx new file mode 100644 index 000000000..b2fefffa3 --- /dev/null +++ b/templates/with-postgres/src/app/(payload)/layout.tsx @@ -0,0 +1,21 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +import configPromise from '@payload-config' +import '@payloadcms/next/css' +import { RootLayout } from '@payloadcms/next/layouts' +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import React from 'react' + +import './custom.scss' +import { importMap } from './admin/importMap' + +type Args = { + children: React.ReactNode +} + +const Layout = ({ children }: Args) => ( + + {children} + +) + +export default Layout diff --git a/templates/with-postgres/src/app/my-route/route.ts b/templates/with-postgres/src/app/my-route/route.ts new file mode 100644 index 000000000..a6422f373 --- /dev/null +++ b/templates/with-postgres/src/app/my-route/route.ts @@ -0,0 +1,14 @@ +import configPromise from '@payload-config' +import { getPayload } from 'payload' + +export const GET = async () => { + const payload = await getPayload({ + config: configPromise, + }) + + const data = await payload.find({ + collection: 'users', + }) + + return Response.json(data) +} diff --git a/templates/with-postgres/src/collections/Media.ts b/templates/with-postgres/src/collections/Media.ts new file mode 100644 index 000000000..568cf4265 --- /dev/null +++ b/templates/with-postgres/src/collections/Media.ts @@ -0,0 +1,16 @@ +import type { CollectionConfig } from 'payload' + +export const Media: CollectionConfig = { + slug: 'media', + access: { + read: () => true, + }, + fields: [ + { + name: 'alt', + type: 'text', + required: true, + }, + ], + upload: true, +} diff --git a/templates/with-postgres/src/collections/Users.ts b/templates/with-postgres/src/collections/Users.ts new file mode 100644 index 000000000..c683d0e2d --- /dev/null +++ b/templates/with-postgres/src/collections/Users.ts @@ -0,0 +1,13 @@ +import type { CollectionConfig } from 'payload' + +export const Users: CollectionConfig = { + slug: 'users', + admin: { + useAsTitle: 'email', + }, + auth: true, + fields: [ + // Email added by default + // Add more fields as needed + ], +} diff --git a/templates/with-postgres/src/migrations/initial.json b/templates/with-postgres/src/migrations/initial.json new file mode 100644 index 000000000..c9d7eee22 --- /dev/null +++ b/templates/with-postgres/src/migrations/initial.json @@ -0,0 +1,375 @@ +{ + "id": "8146d795-d1a9-49be-857d-4320898b38fb", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "5", + "dialect": "pg", + "tables": { + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "email": { + "name": "email", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "reset_password_token": { + "name": "reset_password_token", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "reset_password_expiration": { + "name": "reset_password_expiration", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": false + }, + "salt": { + "name": "salt", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "hash": { + "name": "hash", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "login_attempts": { + "name": "login_attempts", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "lock_until": { + "name": "lock_until", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "users_created_at_idx": { + "name": "users_created_at_idx", + "columns": ["created_at"], + "isUnique": false + }, + "users_email_idx": { + "name": "users_email_idx", + "columns": ["email"], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "media": { + "name": "media", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "alt": { + "name": "alt", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "url": { + "name": "url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "thumbnail_u_r_l": { + "name": "thumbnail_u_r_l", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "filename": { + "name": "filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "mime_type": { + "name": "mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "filesize": { + "name": "filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "width": { + "name": "width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "height": { + "name": "height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "focal_x": { + "name": "focal_x", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "focal_y": { + "name": "focal_y", + "type": "numeric", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "media_created_at_idx": { + "name": "media_created_at_idx", + "columns": ["created_at"], + "isUnique": false + }, + "media_filename_idx": { + "name": "media_filename_idx", + "columns": ["filename"], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "payload_preferences": { + "name": "payload_preferences", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "payload_preferences_key_idx": { + "name": "payload_preferences_key_idx", + "columns": ["key"], + "isUnique": false + }, + "payload_preferences_created_at_idx": { + "name": "payload_preferences_created_at_idx", + "columns": ["created_at"], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "payload_preferences_rels": { + "name": "payload_preferences_rels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "users_id": { + "name": "users_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "payload_preferences_rels_order_idx": { + "name": "payload_preferences_rels_order_idx", + "columns": ["order"], + "isUnique": false + }, + "payload_preferences_rels_parent_idx": { + "name": "payload_preferences_rels_parent_idx", + "columns": ["parent_id"], + "isUnique": false + }, + "payload_preferences_rels_path_idx": { + "name": "payload_preferences_rels_path_idx", + "columns": ["path"], + "isUnique": false + } + }, + "foreignKeys": { + "payload_preferences_rels_parent_fk": { + "name": "payload_preferences_rels_parent_fk", + "tableFrom": "payload_preferences_rels", + "tableTo": "payload_preferences", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_preferences_rels_users_fk": { + "name": "payload_preferences_rels_users_fk", + "tableFrom": "payload_preferences_rels", + "tableTo": "users", + "columnsFrom": ["users_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "payload_migrations": { + "name": "payload_migrations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "batch": { + "name": "batch", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "payload_migrations_created_at_idx": { + "name": "payload_migrations_created_at_idx", + "columns": ["created_at"], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} diff --git a/templates/with-postgres/src/migrations/initial.ts b/templates/with-postgres/src/migrations/initial.ts new file mode 100644 index 000000000..24731cbb6 --- /dev/null +++ b/templates/with-postgres/src/migrations/initial.ts @@ -0,0 +1,93 @@ +import type { MigrateDownArgs, MigrateUpArgs } from '@payloadcms/db-postgres' + +import { sql } from '@payloadcms/db-postgres' + +export async function up({ payload }: MigrateUpArgs): Promise { + await payload.db.drizzle.execute(sql` + +CREATE TABLE IF NOT EXISTS "users" ( + "id" serial PRIMARY KEY NOT NULL, + "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, + "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL, + "email" varchar NOT NULL, + "reset_password_token" varchar, + "reset_password_expiration" timestamp(3) with time zone, + "salt" varchar, + "hash" varchar, + "login_attempts" numeric, + "lock_until" timestamp(3) with time zone +); + +CREATE TABLE IF NOT EXISTS "media" ( + "id" serial PRIMARY KEY NOT NULL, + "alt" varchar NOT NULL, + "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, + "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL, + "url" varchar, + "thumbnail_u_r_l" varchar, + "filename" varchar, + "mime_type" varchar, + "filesize" numeric, + "width" numeric, + "height" numeric, + "focal_x" numeric, + "focal_y" numeric +); + +CREATE TABLE IF NOT EXISTS "payload_preferences" ( + "id" serial PRIMARY KEY NOT NULL, + "key" varchar, + "value" jsonb, + "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, + "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL +); + +CREATE TABLE IF NOT EXISTS "payload_preferences_rels" ( + "id" serial PRIMARY KEY NOT NULL, + "order" integer, + "parent_id" integer NOT NULL, + "path" varchar NOT NULL, + "users_id" integer +); + +CREATE TABLE IF NOT EXISTS "payload_migrations" ( + "id" serial PRIMARY KEY NOT NULL, + "name" varchar, + "batch" numeric, + "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, + "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL +); + +CREATE INDEX IF NOT EXISTS "users_created_at_idx" ON "users" ("created_at"); +CREATE UNIQUE INDEX IF NOT EXISTS "users_email_idx" ON "users" ("email"); +CREATE INDEX IF NOT EXISTS "media_created_at_idx" ON "media" ("created_at"); +CREATE UNIQUE INDEX IF NOT EXISTS "media_filename_idx" ON "media" ("filename"); +CREATE INDEX IF NOT EXISTS "payload_preferences_key_idx" ON "payload_preferences" ("key"); +CREATE INDEX IF NOT EXISTS "payload_preferences_created_at_idx" ON "payload_preferences" ("created_at"); +CREATE INDEX IF NOT EXISTS "payload_preferences_rels_order_idx" ON "payload_preferences_rels" ("order"); +CREATE INDEX IF NOT EXISTS "payload_preferences_rels_parent_idx" ON "payload_preferences_rels" ("parent_id"); +CREATE INDEX IF NOT EXISTS "payload_preferences_rels_path_idx" ON "payload_preferences_rels" ("path"); +CREATE INDEX IF NOT EXISTS "payload_migrations_created_at_idx" ON "payload_migrations" ("created_at"); +DO $$ BEGIN + ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "payload_preferences"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +DO $$ BEGIN + ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_users_fk" FOREIGN KEY ("users_id") REFERENCES "users"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +`) +} + +export async function down({ payload }: MigrateDownArgs): Promise { + await payload.db.drizzle.execute(sql` + +DROP TABLE "users"; +DROP TABLE "media"; +DROP TABLE "payload_preferences"; +DROP TABLE "payload_preferences_rels"; +DROP TABLE "payload_migrations";`) +} diff --git a/templates/with-postgres/src/payload-types.ts b/templates/with-postgres/src/payload-types.ts new file mode 100644 index 000000000..d98da0d04 --- /dev/null +++ b/templates/with-postgres/src/payload-types.ts @@ -0,0 +1,127 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * This file was automatically generated by Payload. + * DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config, + * and re-run `payload generate:types` to regenerate this file. + */ + +export interface Config { + auth: { + users: UserAuthOperations; + }; + collections: { + users: User; + media: Media; + 'payload-preferences': PayloadPreference; + 'payload-migrations': PayloadMigration; + }; + db: { + defaultIDType: string; + }; + globals: {}; + locale: null; + user: User & { + collection: 'users'; + }; +} +export interface UserAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "users". + */ +export interface User { + id: string; + updatedAt: string; + createdAt: string; + email: string; + resetPasswordToken?: string | null; + resetPasswordExpiration?: string | null; + salt?: string | null; + hash?: string | null; + loginAttempts?: number | null; + lockUntil?: string | null; + password?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media". + */ +export interface Media { + id: string; + alt: string; + updatedAt: string; + createdAt: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-preferences". + */ +export interface PayloadPreference { + id: string; + user: { + relationTo: 'users'; + value: string | User; + }; + key?: string | null; + value?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-migrations". + */ +export interface PayloadMigration { + id: string; + name?: string | null; + batch?: number | null; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "auth". + */ +export interface Auth { + [k: string]: unknown; +} + + +declare module 'payload' { + export interface GeneratedTypes extends Config {} +} \ No newline at end of file diff --git a/templates/with-postgres/src/payload.config.ts b/templates/with-postgres/src/payload.config.ts new file mode 100644 index 000000000..961f9c40c --- /dev/null +++ b/templates/with-postgres/src/payload.config.ts @@ -0,0 +1,34 @@ +import { postgresAdapter } from '@payloadcms/db-postgres' +import { lexicalEditor } from '@payloadcms/richtext-lexical' +import path from 'path' +import { buildConfig } from 'payload' +import { fileURLToPath } from 'url' +import sharp from 'sharp' + +import { Users } from './collections/Users' +import { Media } from './collections/Media' + +const filename = fileURLToPath(import.meta.url) +const dirname = path.dirname(filename) + +export default buildConfig({ + admin: { + user: Users.slug, + importMap: { + baseDir: path.resolve(dirname), + }, + }, + collections: [Users, Media], + editor: lexicalEditor(), + secret: process.env.PAYLOAD_SECRET || '', + typescript: { + outputFile: path.resolve(dirname, 'payload-types.ts'), + }, + db: postgresAdapter({ + pool: { + connectionString: process.env.DATABASE_URI || '', + }, + }), + sharp, + plugins: [], +}) diff --git a/templates/with-postgres/tsconfig.json b/templates/with-postgres/tsconfig.json new file mode 100644 index 000000000..c724da8b9 --- /dev/null +++ b/templates/with-postgres/tsconfig.json @@ -0,0 +1,44 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": [ + "./src/*" + ], + "@payload-config": [ + "./src/payload.config.ts" + ] + }, + "target": "ES2017" + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/templates/with-vercel-mongodb/.env.example b/templates/with-vercel-mongodb/.env.example index 441b33e68..22203c5da 100644 --- a/templates/with-vercel-mongodb/.env.example +++ b/templates/with-vercel-mongodb/.env.example @@ -1,2 +1,2 @@ -DATABASE_URI=mongodb://127.0.0.1/payload-template-blank-3-0 -PAYLOAD_SECRET=YOUR_SECRET_HERE +MONGODB_URI=mongodb://127.0.0.1/payload-template-blank-3-0 +PAYLOAD_SECRET=YOUR_SECRET_HERE \ No newline at end of file diff --git a/templates/with-vercel-postgres/.env.example b/templates/with-vercel-postgres/.env.example index 441b33e68..88f8d544a 100644 --- a/templates/with-vercel-postgres/.env.example +++ b/templates/with-vercel-postgres/.env.example @@ -1,2 +1,2 @@ -DATABASE_URI=mongodb://127.0.0.1/payload-template-blank-3-0 -PAYLOAD_SECRET=YOUR_SECRET_HERE +POSTGRES_URL=mongodb://127.0.0.1/payload-template-blank-3-0 +PAYLOAD_SECRET=YOUR_SECRET_HERE \ No newline at end of file diff --git a/templates/with-vercel-postgres/README.md b/templates/with-vercel-postgres/README.md index 3586971a9..ba2f7bf29 100644 --- a/templates/with-vercel-postgres/README.md +++ b/templates/with-vercel-postgres/README.md @@ -6,5 +6,5 @@ payload-vercel-postgres-template ## Attributes -- **Database**: postgres +- **Database**: vercelPostgres - **Storage Adapter**: vercelBlobStorage diff --git a/templates/with-vercel-postgres/package.json b/templates/with-vercel-postgres/package.json index 7300f5367..106928a2b 100644 --- a/templates/with-vercel-postgres/package.json +++ b/templates/with-vercel-postgres/package.json @@ -15,7 +15,7 @@ "start": "cross-env NODE_OPTIONS=--no-deprecation next start" }, "dependencies": { - "@payloadcms/db-postgres": "beta", + "@payloadcms/db-vercel-postgres": "beta", "@payloadcms/next": "beta", "@payloadcms/plugin-cloud": "beta", "@payloadcms/richtext-lexical": "beta", diff --git a/templates/with-vercel-postgres/src/payload.config.ts b/templates/with-vercel-postgres/src/payload.config.ts index ad4219358..cb394a626 100644 --- a/templates/with-vercel-postgres/src/payload.config.ts +++ b/templates/with-vercel-postgres/src/payload.config.ts @@ -1,5 +1,5 @@ import { vercelBlobStorage } from '@payloadcms/storage-vercel-blob' -import { postgresAdapter } from '@payloadcms/db-postgres' +import { vercelPostgresAdapter } from '@payloadcms/db-vercel-postgres' import { lexicalEditor } from '@payloadcms/richtext-lexical' import path from 'path' import { buildConfig } from 'payload' @@ -24,7 +24,7 @@ export default buildConfig({ typescript: { outputFile: path.resolve(dirname, 'payload-types.ts'), }, - db: postgresAdapter({ + db: vercelPostgresAdapter({ pool: { connectionString: process.env.POSTGRES_URL || '', }, diff --git a/tsconfig.json b/tsconfig.json index fdef1fc52..ae27597fb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,7 +37,7 @@ ], "paths": { "@payload-config": [ - "./test/admin/config.ts" + "./test/_community/config.ts" ], "@payloadcms/live-preview": [ "./packages/live-preview/src"