diff --git a/README.md b/README.md index f3ee249237e..1c755751cc6 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,11 @@ If you want to add contributions to this repository, please follow the instructi The [Examples Directory](./examples) is a great resource for learning how to setup Payload in a variety of different ways, but you can also find great examples in our blog and throughout our social media. -If you'd like to run the examples, you can either copy them to a folder outside this repo or run them directly by (1) navigating to the example's subfolder (`cd examples/your-example-folder`) and (2) using the `--ignore-workspace` flag to bypass workspace restrictions (e.g., `pnpm --ignore-workspace install` or `pnpm --ignore-workspace dev`). +If you'd like to run the examples, you can use `create-payload-app` to create a project from one: + +```sh +npx create-payload-app --example example_name +``` You can see more examples at: diff --git a/docs/examples/overview.mdx b/docs/examples/overview.mdx index 79cbb42ee0e..6b75a673dce 100644 --- a/docs/examples/overview.mdx +++ b/docs/examples/overview.mdx @@ -19,4 +19,10 @@ Payload provides a vast array of examples to help you get started with your proj - [Tests](https://github.com/payloadcms/payload/tree/main/examples/testing) - [White-label Admin UI](https://github.com/payloadcms/payload/tree/main/examples/whitelabel) +If you'd like to run the examples, you can use `create-payload-app` to create a project from one: + +```sh +npx create-payload-app --example example_name +``` + We are adding new examples every day, so if your particular use case is not demonstrated in any existing example, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions) or open a new [PR](https://github.com/payloadcms/payload/pulls) to add it yourself. diff --git a/examples/auth/README.md b/examples/auth/README.md index 30d196f4e4a..797cfbcade4 100644 --- a/examples/auth/README.md +++ b/examples/auth/README.md @@ -6,20 +6,17 @@ This [Payload Auth Example](https://github.com/payloadcms/payload/tree/main/exam To spin up this example locally, follow the steps below: -1. Clone this repo -1. Navigate into the project directory and install dependencies using your preferred package manager: +1. Run the following command to create a project from the example: -- `pnpm i --ignore-workspace`\*, `yarn`, or `npm install` +- `npx create-payload-app --example auth` -> \*NOTE: The --ignore-workspace flag is needed if you are running this example within the Payload monorepo to avoid workspace conflicts. - -1. Start the server: +2. Start the server: - Depending on your package manager, run `pnpm dev`, `yarn dev` or `npm run dev` - When prompted, type `y` then `enter` to seed the database with sample data -1. Access the application: +3. Access the application: - Open your browser and navigate to `http://localhost:3000` to access the homepage. - Open `http://localhost:3000/admin` to access the admin panel. -1. Login: +4. Login: - Use the following credentials to log into the admin panel: > `Email: demo@payloadcms.com` > `Password: demo` diff --git a/examples/custom-components/README.md b/examples/custom-components/README.md index 1cdbc6466cd..959bb50ba76 100644 --- a/examples/custom-components/README.md +++ b/examples/custom-components/README.md @@ -6,20 +6,17 @@ This example demonstrates how to use Custom Components in the [Payload](https:// To spin up this example locally, follow the steps below: -1. Clone this repo -1. Navigate into the project directory and install dependencies using your preferred package manager: +1. Run the following command to create a project from the example: -- `pnpm i --ignore-workspace`\*, `yarn`, or `npm install` +- `npx create-payload-app --example custom-components` -> \*NOTE: The --ignore-workspace flag is needed if you are running this example within the Payload monorepo to avoid workspace conflicts. - -1. Start the server: +2. Start the server: - Depending on your package manager, run `pnpm dev`, `yarn dev` or `npm run dev` - When prompted, type `y` then `enter` to seed the database with sample data -1. Access the application: +3. Access the application: - Open your browser and navigate to `http://localhost:3000` to access the homepage. - Open `http://localhost:3000/admin` to access the admin panel. -1. Login: +4. Login: - Use the following credentials to log into the admin panel: > `Email: demo@payloadcms.com` > `Password: demo` diff --git a/examples/custom-server/README.md b/examples/custom-server/README.md index 4bbe2ae5205..785fd7f9ed2 100644 --- a/examples/custom-server/README.md +++ b/examples/custom-server/README.md @@ -1,5 +1,9 @@ # Payload 3 with Custom Server +Run the following command to create a project from the example: + +- `npx create-payload-app --example custom-server` + Uses a [Next.js Custom Server](https://nextjs.org/docs/pages/building-your-application/configuring/custom-server) with express. Made from official [examples/custom-server](https://github.com/vercel/next.js/tree/canary/examples/custom-server) from Next.js repository. diff --git a/examples/draft-preview/README.md b/examples/draft-preview/README.md index 0025a92a1d8..d9b1305fe99 100644 --- a/examples/draft-preview/README.md +++ b/examples/draft-preview/README.md @@ -6,15 +6,14 @@ The [Payload Draft Preview Example](https://github.com/payloadcms/payload/tree/m To spin up this example locally, follow these steps: -1. Clone this repo -2. `cd` into this directory and run `pnpm i --ignore-workspace`\*, `yarn`, or `npm install` +1. Run the following command to create a project from the example: - > \*If you are running using pnpm within the Payload Monorepo, the `--ignore-workspace` flag is needed so that pnpm generates a lockfile in this example's directory despite the fact that one exists in root. +- `npx create-payload-app --example draft-preview` -3. `cp .env.example .env` to copy the example environment variables -4. `pnpm dev`, `yarn dev` or `npm run dev` to start the server -5. `open http://localhost:3000/admin` to access the admin panel -6. Login with email `demo@payloadcms.com` and password `demo` +2. `cp .env.example .env` to copy the example environment variables +3. `pnpm dev`, `yarn dev` or `npm run dev` to start the server +4. `open http://localhost:3000/admin` to access the admin panel +5. Login with email `demo@payloadcms.com` and password `demo` That's it! Changes made in `./src` will be reflected in your app. See the [Development](#development) section for more details. diff --git a/examples/email/README.md b/examples/email/README.md index 6c3418495a2..45d3a665bab 100644 --- a/examples/email/README.md +++ b/examples/email/README.md @@ -6,7 +6,10 @@ This example demonstrates how to integrate email functionality into Payload. To spin up this example locally, follow these steps: -1. Clone this repo +1. Run the following command to create a project from the example: + +- `npx create-payload-app --example email` + 2. `cp .env.example .env` to copy the example environment variables 3. `pnpm install && pnpm dev` to install dependencies and start the dev server 4. open `http://localhost:3000/admin` to access the admin panel diff --git a/examples/form-builder/README.md b/examples/form-builder/README.md index a89bcf322bc..64540965ab7 100644 --- a/examples/form-builder/README.md +++ b/examples/form-builder/README.md @@ -6,17 +6,16 @@ The [Payload Form Builder Example](https://github.com/payloadcms/payload/tree/ma ## Quick Start -1. Clone this repo -2. `cd` into this directory and run `pnpm i --ignore-workspace`\*, `yarn`, or `npm install` +1. Run the following command to create a project from the example: - > \*If you are running using pnpm within the Payload Monorepo, the `--ignore-workspace` flag is needed so that pnpm generates a lockfile in this example's directory despite the fact that one exists in root. +- `npx create-payload-app --example form-builder` -3. `cp .env.example .env` to copy the example environment variables +2. `cp .env.example .env` to copy the example environment variables -4. `pnpm dev`, `yarn dev` or `npm run dev` to start the server +3. `pnpm dev`, `yarn dev` or `npm run dev` to start the server - Press `y` when prompted to seed the database -5. `open http://localhost:3000` to access the home page -6. `open http://localhost:3000/admin` to access the admin panel +4. `open http://localhost:3000` to access the home page +5. `open http://localhost:3000/admin` to access the admin panel - Login with email `demo@payloadcms.com` and password `demo` That's it! Changes made in `./src` will be diff --git a/examples/live-preview/README.md b/examples/live-preview/README.md index ad0779ae8ff..93c41012a1e 100644 --- a/examples/live-preview/README.md +++ b/examples/live-preview/README.md @@ -6,17 +6,16 @@ The [Payload Live Preview Example](https://github.com/payloadcms/payload/tree/ma ## Quick Start -1. Clone this repo -2. `cd` into this directory and run `pnpm i --ignore-workspace`\*, `yarn`, or `npm install` +1. Run the following command to create a project from the example: - > \*If you are running using pnpm within the Payload Monorepo, the `--ignore-workspace` flag is needed so that pnpm generates a lockfile in this example's directory despite the fact that one exists in root. +- `npx create-payload-app --example live-preview` -3. `cp .env.example .env` to copy the example environment variables +2. `cp .env.example .env` to copy the example environment variables -4. `pnpm dev`, `yarn dev` or `npm run dev` to start the server +3. `pnpm dev`, `yarn dev` or `npm run dev` to start the server - Press `y` when prompted to seed the database -5. `open http://localhost:3000` to access the home page -6. `open http://localhost:3000/admin` to access the admin panel +4. `open http://localhost:3000` to access the home page +5. `open http://localhost:3000/admin` to access the admin panel - Login with email `demo@payloadcms.com` and password `demo` That's it! Changes made in `./src` will be reflected in your app. See the [Development](#development) section for more details. diff --git a/examples/localization/README.md b/examples/localization/README.md index ec36197842d..d27c22b6e9a 100644 --- a/examples/localization/README.md +++ b/examples/localization/README.md @@ -8,10 +8,14 @@ To facilitate the localization process, this example uses the next-intl library. ## Setup -1. `cp .env.example .env` (copy the .env.example file to .env) -2. `pnpm install` (`pnpm i --ignore-workspaces` if you are running from the monorepo) -3. `pnpm run dev` -4. Seed your database in the admin panel (see below) +1. Run the following command to create a project from the example: + +- `npx create-payload-app --example localization` + +2. `cp .env.example .env` (copy the .env.example file to .env) +3. `pnpm install` +4. `pnpm run dev` +5. Seed your database in the admin panel (see below) ## Seed diff --git a/examples/multi-tenant/README.md b/examples/multi-tenant/README.md index 6dafc5b99dd..94539b6a5cf 100644 --- a/examples/multi-tenant/README.md +++ b/examples/multi-tenant/README.md @@ -6,15 +6,14 @@ This example demonstrates how to achieve a multi-tenancy in [Payload](https://gi To spin up this example locally, follow these steps: -1. Clone this repo -1. `cd` into this directory and run `pnpm i --ignore-workspace`\*, `yarn`, or `npm install` +1. Run the following command to create a project from the example: - > \*If you are running using pnpm within the Payload Monorepo, the `--ignore-workspace` flag is needed so that pnpm generates a lockfile in this example's directory despite the fact that one exists in root. +- `npx create-payload-app --example multi-tenant` -1. `pnpm dev`, `yarn dev` or `npm run dev` to start the server +2. `pnpm dev`, `yarn dev` or `npm run dev` to start the server - Press `y` when prompted to seed the database -1. `open http://localhost:3000` to access the home page -1. `open http://localhost:3000/admin` to access the admin panel +3. `open http://localhost:3000` to access the home page +4. `open http://localhost:3000/admin` to access the admin panel - Login with email `demo@payloadcms.com` and password `demo` ## How it works diff --git a/examples/tailwind-shadcn-ui/README.md b/examples/tailwind-shadcn-ui/README.md index f10b08372ab..91ecbfb5b36 100644 --- a/examples/tailwind-shadcn-ui/README.md +++ b/examples/tailwind-shadcn-ui/README.md @@ -8,18 +8,17 @@ Checkout our [tutorial](https://payloadcms.com/blog/how-to-setup-tailwindcss-and To spin up this example locally, follow these steps: -1. Clone this repo -1. `cd` into this directory and run `pnpm i --ignore-workspace`\*, or `npm install` +1. Run the following command to create a project from the example: - > \*If you are running using pnpm within the Payload Monorepo, the `--ignore-workspace` flag is needed so that pnpm generates a lockfile in this example's directory despite the fact that one exists in root. +- `npx create-payload-app --example tailwind-shadcn-ui` -1. `cp .env.example .env` to copy the example environment variables +2. `cp .env.example .env` to copy the example environment variables > Adjust `PAYLOAD_PUBLIC_SITE_URL` in the `.env` if your front-end is running on a separate domain or port. -1. `pnpm dev`, `yarn dev` or `npm run dev` to start the server +3. `pnpm dev`, `yarn dev` or `npm run dev` to start the server - Press `y` when prompted to seed the database -1. `open http://localhost:3000` to access the home page -1. `open http://localhost:3000/admin` to access the admin panel +4. `open http://localhost:3000` to access the home page +5. `open http://localhost:3000/admin` to access the admin panel That's it! Changes made in `./src` will be reflected in your app. See the [Development](#development) section for more details. diff --git a/examples/testing/README.md b/examples/testing/README.md index 69ffa7955a8..08c945652d9 100644 --- a/examples/testing/README.md +++ b/examples/testing/README.md @@ -2,6 +2,12 @@ This example demonstrates how to get started with testing Payload using [Jest](https://jestjs.io/). You can clone this down and use it as a starting point for your own Payload projects, or you can follow the steps below to add testing to your existing Payload project. +## Spin up locally: + +Run the following command to create a project from the example: + +- `npx create-payload-app --example testing` + ## Add testing to your existing Payload project 1. Initial setup: diff --git a/examples/whitelabel/README.md b/examples/whitelabel/README.md index 40373d5933c..a88fea89aa6 100644 --- a/examples/whitelabel/README.md +++ b/examples/whitelabel/README.md @@ -6,7 +6,10 @@ This example demonstrates how to re-brand or white-label the [Payload Admin Pane To spin up this example locally, follow these steps: -1. Clone this repo +1. Run the following command to create a project from the example: + +- `npx create-payload-app --example whitelabel` + 2. `cp .env.example .env` to copy the example environment variables 3. `pnpm install && pnpm dev` to install dependencies and start the dev server 4. `open http://localhost:3000/admin` to access the admin panel diff --git a/packages/create-payload-app/src/lib/create-project.spec.ts b/packages/create-payload-app/src/lib/create-project.spec.ts index dabe49d7e55..93503c1e6f4 100644 --- a/packages/create-payload-app/src/lib/create-project.spec.ts +++ b/packages/create-payload-app/src/lib/create-project.spec.ts @@ -5,7 +5,7 @@ import globby from 'globby' import * as os from 'node:os' import path from 'path' -import type { CliArgs, DbType, ProjectTemplate } from '../types.js' +import type { CliArgs, DbType, ProjectExample, ProjectTemplate } from '../types.js' import { createProject } from './create-project.js' import { dbReplacements } from './replacements.js' @@ -62,6 +62,32 @@ describe('createProject', () => { expect(packageJson.name).toStrictEqual(projectName) }) + it('creates example', async () => { + const projectName = 'custom-server-example' + const example: ProjectExample = { + name: 'custom-server', + url: 'https://github.com/payloadcms/payload/examples/custom-server#main', + } + + await createProject({ + cliArgs: { + ...args, + '--local-template': undefined, + '--local-example': 'custom-server', + } as CliArgs, + packageManager, + projectDir, + projectName, + example, + }) + + const packageJsonPath = path.resolve(projectDir, 'package.json') + const packageJson = fse.readJsonSync(packageJsonPath) + + // Check package name and description + expect(packageJson.name).toStrictEqual(projectName) + }) + describe('creates project from template', () => { const templates = getValidTemplates() diff --git a/packages/create-payload-app/src/lib/create-project.ts b/packages/create-payload-app/src/lib/create-project.ts index 3de9c5d3f4d..54b24179f53 100644 --- a/packages/create-payload-app/src/lib/create-project.ts +++ b/packages/create-payload-app/src/lib/create-project.ts @@ -5,12 +5,19 @@ import fse from 'fs-extra' import { fileURLToPath } from 'node:url' import path from 'path' -import type { CliArgs, DbDetails, PackageManager, ProjectTemplate } from '../types.js' +import type { + CliArgs, + DbDetails, + PackageManager, + ProjectExample, + ProjectTemplate, +} from '../types.js' import { tryInitRepoAndCommit } from '../utils/git.js' import { debug, error, info, warning } from '../utils/log.js' import { configurePayloadConfig } from './configure-payload-config.js' import { configurePluginProject } from './configure-plugin-project.js' +import { downloadExample } from './download-example.js' import { downloadTemplate } from './download-template.js' const filename = fileURLToPath(import.meta.url) @@ -53,15 +60,24 @@ async function installDeps(args: { } } -export async function createProject(args: { - cliArgs: CliArgs - dbDetails?: DbDetails - packageManager: PackageManager - projectDir: string - projectName: string - template: ProjectTemplate -}): Promise { - const { cliArgs, dbDetails, packageManager, projectDir, projectName, template } = args +type TemplateOrExample = + | { + example: ProjectExample + } + | { + template: ProjectTemplate + } + +export async function createProject( + args: { + cliArgs: CliArgs + dbDetails?: DbDetails + packageManager: PackageManager + projectDir: string + projectName: string + } & TemplateOrExample, +): Promise { + const { cliArgs, dbDetails, packageManager, projectDir, projectName } = args if (cliArgs['--dry-run']) { debug(`Dry run: Creating project in ${chalk.green(projectDir)}`) @@ -70,6 +86,12 @@ export async function createProject(args: { await createOrFindProjectDir(projectDir) + if (cliArgs['--local-example']) { + // Copy example from local path. For development purposes. + const localExample = path.resolve(dirname, '../../../../examples/', cliArgs['--local-example']) + await fse.copy(localExample, projectDir) + } + if (cliArgs['--local-template']) { // Copy template from local path. For development purposes. const localTemplate = path.resolve( @@ -78,9 +100,10 @@ export async function createProject(args: { cliArgs['--local-template'], ) await fse.copy(localTemplate, projectDir) - } else if ('url' in template) { - if (cliArgs['--template-branch']) { - template.url = `${template.url.split('#')?.[0]}#${cliArgs['--template-branch']}` + } else if ('template' in args && 'url' in args.template) { + const { template } = args + if (cliArgs['--branch']) { + template.url = `${template.url.split('#')?.[0]}#${cliArgs['--branch']}` } await downloadTemplate({ @@ -88,6 +111,17 @@ export async function createProject(args: { projectDir, template, }) + } else if ('example' in args && 'url' in args.example) { + const { example } = args + if (cliArgs['--branch']) { + example.url = `${example.url.split('#')?.[0]}#${cliArgs['--branch']}` + } + + await downloadExample({ + debug: cliArgs['--debug'], + example, + projectDir, + }) } const spinner = p.spinner() @@ -95,15 +129,17 @@ export async function createProject(args: { await updatePackageJSON({ projectDir, projectName }) - if (template.type === 'plugin') { - spinner.message('Configuring Plugin...') - configurePluginProject({ projectDirPath: projectDir, projectName }) - } else { - spinner.message('Configuring Payload...') - await configurePayloadConfig({ - dbType: dbDetails?.type, - projectDirOrConfigPath: { projectDir }, - }) + if ('template' in args) { + if (args.template.type === 'plugin') { + spinner.message('Configuring Plugin...') + configurePluginProject({ projectDirPath: projectDir, projectName }) + } else { + spinner.message('Configuring Payload...') + await configurePayloadConfig({ + dbType: dbDetails?.type, + projectDirOrConfigPath: { projectDir }, + }) + } } // Remove yarn.lock file. This is only desired in Payload Cloud. diff --git a/packages/create-payload-app/src/lib/download-example.ts b/packages/create-payload-app/src/lib/download-example.ts new file mode 100644 index 00000000000..26e378a30fa --- /dev/null +++ b/packages/create-payload-app/src/lib/download-example.ts @@ -0,0 +1,46 @@ +import { Readable } from 'node:stream' +import { pipeline } from 'node:stream/promises' +import { x } from 'tar' + +import type { ProjectExample } from '../types.js' + +import { debug as debugLog } from '../utils/log.js' + +export async function downloadExample({ + debug, + example, + projectDir, +}: { + debug?: boolean + example: ProjectExample + projectDir: string +}) { + const branchOrTag = example.url.split('#')?.[1] || 'latest' + const url = `https://codeload.github.com/payloadcms/payload/tar.gz/${branchOrTag}` + const filter = `payload-${branchOrTag.replace(/^v/, '')}/examples/${example.name}/` + + if (debug) { + debugLog(`Using example url: ${example.url}`) + debugLog(`Codeload url: ${url}`) + debugLog(`Filter: ${filter}`) + } + + await pipeline( + await downloadTarStream(url), + x({ + cwd: projectDir, + filter: (p) => p.includes(filter), + strip: 2 + example.name.split('/').length, + }), + ) +} + +async function downloadTarStream(url: string) { + const res = await fetch(url) + + if (!res.body) { + throw new Error(`Failed to download: ${url}`) + } + + return Readable.from(res.body as unknown as NodeJS.ReadableStream) +} diff --git a/packages/create-payload-app/src/lib/examples.ts b/packages/create-payload-app/src/lib/examples.ts new file mode 100644 index 00000000000..a0448152202 --- /dev/null +++ b/packages/create-payload-app/src/lib/examples.ts @@ -0,0 +1,38 @@ +import type { ProjectExample } from '../types.js' + +import { error, info } from '../utils/log.js' + +export async function getExamples({ branch }: { branch: string }): Promise { + const url = `https://api.github.com/repos/payloadcms/payload/contents/examples?ref=${branch}` + + const response = await fetch(url) + + const examplesResponseList: { name: string; path: string }[] = await response.json() + + const examples: ProjectExample[] = examplesResponseList.map((example) => ({ + name: example.name, + url: `https://github.com/payloadcms/payload/examples/${example.name}#${branch}`, + })) + + return examples +} + +export async function parseExample({ + name, + branch, +}: { + branch: string + name: string +}): Promise { + const examples = await getExamples({ branch }) + + const example = examples.find((e) => e.name === name) + + if (!example) { + error(`'${name}' is not a valid example name.`) + info(`Valid examples: ${examples.map((e) => e.name).join(', ')}`) + return false + } + + return example +} diff --git a/packages/create-payload-app/src/main.ts b/packages/create-payload-app/src/main.ts index a81cae6c0d6..1f75656a54d 100644 --- a/packages/create-payload-app/src/main.ts +++ b/packages/create-payload-app/src/main.ts @@ -10,6 +10,7 @@ import type { CliArgs } from './types.js' import { configurePayloadConfig } from './lib/configure-payload-config.js' import { PACKAGE_VERSION } from './lib/constants.js' import { createProject } from './lib/create-project.js' +import { parseExample } from './lib/examples.js' import { generateSecret } from './lib/generate-secret.js' import { getPackageManager } from './lib/get-package-manager.js' import { getNextAppDetails, initNext } from './lib/init-next.js' @@ -35,15 +36,16 @@ export class Main { // @ts-expect-error bad typings this.args = arg( { + '--branch': String, '--db': String, '--db-accept-recommended': Boolean, '--db-connection-string': String, + '--example': String, '--help': Boolean, '--local-template': String, '--name': String, '--secret': String, '--template': String, - '--template-branch': String, // Next.js '--init-next': Boolean, // TODO: Is this needed if we detect if inside Next.js project? @@ -65,6 +67,7 @@ export class Main { // Aliases '-d': '--db', + '-e': '--example', '-h': '--help', '-n': '--name', '-t': '--template', @@ -204,52 +207,76 @@ export class Main { } } - if (debugFlag) { - debug(`Using templates from git tag: v${PACKAGE_VERSION}`) + const exampleArg = this.args['--example'] + + if (exampleArg) { + const example = await parseExample({ + name: exampleArg, + branch: this.args['--branch'] ?? 'main', + }) + + if (!example) { + helpMessage() + process.exit(1) + } + + await createProject({ + cliArgs: this.args, + example, + packageManager, + projectDir, + projectName, + }) } - const validTemplates = getValidTemplates() - const template = await parseTemplate(this.args, validTemplates) - if (!template) { - p.log.error('Invalid template given') - p.outro(feedbackOutro()) - process.exit(1) + if (debugFlag) { + debug(`Using ${exampleArg ? 'examples' : 'templates'} from git tag: v${PACKAGE_VERSION}`) } - switch (template.type) { - case 'plugin': { - await createProject({ - cliArgs: this.args, - packageManager, - projectDir, - projectName, - template, - }) - break + if (!exampleArg) { + const validTemplates = getValidTemplates() + const template = await parseTemplate(this.args, validTemplates) + if (!template) { + p.log.error('Invalid template given') + p.outro(feedbackOutro()) + process.exit(1) } - case 'starter': { - const dbDetails = await selectDb(this.args, projectName) - const payloadSecret = generateSecret() - - await createProject({ - cliArgs: this.args, - dbDetails, - packageManager, - projectDir, - projectName, - template, - }) - - await manageEnvFiles({ - cliArgs: this.args, - databaseType: dbDetails.type, - databaseUri: dbDetails.dbUri, - payloadSecret, - projectDir, - template, - }) - - break + + switch (template.type) { + case 'plugin': { + await createProject({ + cliArgs: this.args, + packageManager, + projectDir, + projectName, + template, + }) + break + } + case 'starter': { + const dbDetails = await selectDb(this.args, projectName) + const payloadSecret = generateSecret() + + await createProject({ + cliArgs: this.args, + dbDetails, + packageManager, + projectDir, + projectName, + template, + }) + + await manageEnvFiles({ + cliArgs: this.args, + databaseType: dbDetails.type, + databaseUri: dbDetails.dbUri, + payloadSecret, + projectDir, + template, + }) + + break + } } } diff --git a/packages/create-payload-app/src/types.ts b/packages/create-payload-app/src/types.ts index e8d409cb70b..4eded38ff5d 100644 --- a/packages/create-payload-app/src/types.ts +++ b/packages/create-payload-app/src/types.ts @@ -2,20 +2,23 @@ import type arg from 'arg' export interface Args extends arg.Spec { '--beta': BooleanConstructor + '--branch': StringConstructor '--db': StringConstructor '--db-accept-recommended': BooleanConstructor '--db-connection-string': StringConstructor '--debug': BooleanConstructor '--dry-run': BooleanConstructor + + '--example': StringConstructor '--help': BooleanConstructor '--init-next': BooleanConstructor + '--local-example': StringConstructor '--local-template': StringConstructor '--name': StringConstructor '--no-deps': BooleanConstructor '--no-git': BooleanConstructor '--secret': StringConstructor '--template': StringConstructor - '--template-branch': StringConstructor '--use-bun': BooleanConstructor '--use-npm': BooleanConstructor '--use-pnpm': BooleanConstructor @@ -23,6 +26,7 @@ export interface Args extends arg.Spec { // Aliases + '-e': string '-h': string '-n': string '-t': string @@ -32,6 +36,11 @@ export type CliArgs = arg.Result export type ProjectTemplate = GitTemplate | PluginTemplate +export type ProjectExample = { + name: string + url: string +} + /** * Template that is cloned verbatim from a git repo * Performs .env manipulation based upon input diff --git a/packages/create-payload-app/src/utils/messages.ts b/packages/create-payload-app/src/utils/messages.ts index 93459381025..cd9af2f7540 100644 --- a/packages/create-payload-app/src/utils/messages.ts +++ b/packages/create-payload-app/src/utils/messages.ts @@ -34,6 +34,7 @@ export function helpMessage(): void { -n {underline my-payload-app} Set project name -t {underline template_name} Choose specific template + -e {underline example_name} Choose specific exmaple {dim Available templates: ${formatTemplates(validTemplates)}} diff --git a/tsconfig.base.json b/tsconfig.base.json index d4a67657ff4..01f5644941b 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -28,7 +28,7 @@ } ], "paths": { - "@payload-config": ["./test/access-control/config.ts"], + "@payload-config": ["./test/_community/config.ts"], "@payloadcms/live-preview": ["./packages/live-preview/src"], "@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"], "@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],