feat(cpa): create project from example using --example CLI arg (#10172)
Adds the ability to create a project using an existing in the Payload repo example through `create-payload-app`: For example: `pnpx create-payload-app --example custom-server` - creates a project from the [custom-server](https://github.com/payloadcms/payload/tree/main/examples/custom-server) example. This is much easier and faster then downloading the whole repo and copying the example to another folder. Note that we don't configure the payload config with the storage / DB adapter there because examples can be very specific.
This commit is contained in:
@@ -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.
|
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:
|
You can see more examples at:
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
- [Tests](https://github.com/payloadcms/payload/tree/main/examples/testing)
|
||||||
- [White-label Admin UI](https://github.com/payloadcms/payload/tree/main/examples/whitelabel)
|
- [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.
|
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.
|
||||||
|
|||||||
@@ -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:
|
To spin up this example locally, follow the steps below:
|
||||||
|
|
||||||
1. Clone this repo
|
1. Run the following command to create a project from the example:
|
||||||
1. Navigate into the project directory and install dependencies using your preferred package manager:
|
|
||||||
|
|
||||||
- `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.
|
2. Start the server:
|
||||||
|
|
||||||
1. Start the server:
|
|
||||||
- Depending on your package manager, run `pnpm dev`, `yarn dev` or `npm run dev`
|
- 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
|
- 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 your browser and navigate to `http://localhost:3000` to access the homepage.
|
||||||
- Open `http://localhost:3000/admin` to access the admin panel.
|
- Open `http://localhost:3000/admin` to access the admin panel.
|
||||||
1. Login:
|
4. Login:
|
||||||
|
|
||||||
- Use the following credentials to log into the admin panel:
|
- Use the following credentials to log into the admin panel:
|
||||||
> `Email: demo@payloadcms.com` > `Password: demo`
|
> `Email: demo@payloadcms.com` > `Password: demo`
|
||||||
|
|||||||
@@ -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:
|
To spin up this example locally, follow the steps below:
|
||||||
|
|
||||||
1. Clone this repo
|
1. Run the following command to create a project from the example:
|
||||||
1. Navigate into the project directory and install dependencies using your preferred package manager:
|
|
||||||
|
|
||||||
- `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.
|
2. Start the server:
|
||||||
|
|
||||||
1. Start the server:
|
|
||||||
- Depending on your package manager, run `pnpm dev`, `yarn dev` or `npm run dev`
|
- 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
|
- 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 your browser and navigate to `http://localhost:3000` to access the homepage.
|
||||||
- Open `http://localhost:3000/admin` to access the admin panel.
|
- Open `http://localhost:3000/admin` to access the admin panel.
|
||||||
1. Login:
|
4. Login:
|
||||||
|
|
||||||
- Use the following credentials to log into the admin panel:
|
- Use the following credentials to log into the admin panel:
|
||||||
> `Email: demo@payloadcms.com` > `Password: demo`
|
> `Email: demo@payloadcms.com` > `Password: demo`
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# Payload 3 with Custom Server
|
# 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.
|
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.
|
Made from official [examples/custom-server](https://github.com/vercel/next.js/tree/canary/examples/custom-server) from Next.js repository.
|
||||||
|
|||||||
@@ -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:
|
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:
|
||||||
2. `cd` into this directory and run `pnpm i --ignore-workspace`\*, `yarn`, or `npm install`
|
|
||||||
|
|
||||||
> \*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
|
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
|
||||||
5. `open http://localhost:3000/admin` to access the admin panel
|
4. `open http://localhost:3000/admin` to access the admin panel
|
||||||
6. Login with email `demo@payloadcms.com` and password `demo`
|
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.
|
That's it! Changes made in `./src` will be reflected in your app. See the [Development](#development) section for more details.
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ This example demonstrates how to integrate email functionality into Payload.
|
|||||||
|
|
||||||
To spin up this example locally, follow these steps:
|
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
|
2. `cp .env.example .env` to copy the example environment variables
|
||||||
3. `pnpm install && pnpm dev` to install dependencies and start the dev server
|
3. `pnpm install && pnpm dev` to install dependencies and start the dev server
|
||||||
4. open `http://localhost:3000/admin` to access the admin panel
|
4. open `http://localhost:3000/admin` to access the admin panel
|
||||||
|
|||||||
@@ -6,17 +6,16 @@ The [Payload Form Builder Example](https://github.com/payloadcms/payload/tree/ma
|
|||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
1. Clone this repo
|
1. Run the following command to create a project from the example:
|
||||||
2. `cd` into this directory and run `pnpm i --ignore-workspace`\*, `yarn`, or `npm install`
|
|
||||||
|
|
||||||
> \*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
|
- Press `y` when prompted to seed the database
|
||||||
5. `open http://localhost:3000` to access the home page
|
4. `open http://localhost:3000` to access the home page
|
||||||
6. `open http://localhost:3000/admin` to access the admin panel
|
5. `open http://localhost:3000/admin` to access the admin panel
|
||||||
- Login with email `demo@payloadcms.com` and password `demo`
|
- Login with email `demo@payloadcms.com` and password `demo`
|
||||||
|
|
||||||
That's it! Changes made in `./src` will be
|
That's it! Changes made in `./src` will be
|
||||||
|
|||||||
@@ -6,17 +6,16 @@ The [Payload Live Preview Example](https://github.com/payloadcms/payload/tree/ma
|
|||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
1. Clone this repo
|
1. Run the following command to create a project from the example:
|
||||||
2. `cd` into this directory and run `pnpm i --ignore-workspace`\*, `yarn`, or `npm install`
|
|
||||||
|
|
||||||
> \*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
|
- Press `y` when prompted to seed the database
|
||||||
5. `open http://localhost:3000` to access the home page
|
4. `open http://localhost:3000` to access the home page
|
||||||
6. `open http://localhost:3000/admin` to access the admin panel
|
5. `open http://localhost:3000/admin` to access the admin panel
|
||||||
- Login with email `demo@payloadcms.com` and password `demo`
|
- 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.
|
That's it! Changes made in `./src` will be reflected in your app. See the [Development](#development) section for more details.
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ To facilitate the localization process, this example uses the next-intl library.
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. `cp .env.example .env` (copy the .env.example file to .env)
|
1. Run the following command to create a project from the example:
|
||||||
2. `pnpm install` (`pnpm i --ignore-workspaces` if you are running from the monorepo)
|
|
||||||
3. `pnpm run dev`
|
- `npx create-payload-app --example localization`
|
||||||
4. Seed your database in the admin panel (see below)
|
|
||||||
|
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
|
## Seed
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
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:
|
||||||
1. `cd` into this directory and run `pnpm i --ignore-workspace`\*, `yarn`, or `npm install`
|
|
||||||
|
|
||||||
> \*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
|
- Press `y` when prompted to seed the database
|
||||||
1. `open http://localhost:3000` to access the home page
|
3. `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/admin` to access the admin panel
|
||||||
- Login with email `demo@payloadcms.com` and password `demo`
|
- Login with email `demo@payloadcms.com` and password `demo`
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|||||||
@@ -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:
|
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:
|
||||||
1. `cd` into this directory and run `pnpm i --ignore-workspace`\*, or `npm install`
|
|
||||||
|
|
||||||
> \*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.
|
> 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
|
- Press `y` when prompted to seed the database
|
||||||
1. `open http://localhost:3000` to access the home page
|
4. `open http://localhost:3000` to access the home page
|
||||||
1. `open http://localhost:3000/admin` to access the admin panel
|
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.
|
That's it! Changes made in `./src` will be reflected in your app. See the [Development](#development) section for more details.
|
||||||
|
|||||||
@@ -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.
|
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
|
## Add testing to your existing Payload project
|
||||||
|
|
||||||
1. Initial setup:
|
1. Initial setup:
|
||||||
|
|||||||
@@ -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:
|
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
|
2. `cp .env.example .env` to copy the example environment variables
|
||||||
3. `pnpm install && pnpm dev` to install dependencies and start the dev server
|
3. `pnpm install && pnpm dev` to install dependencies and start the dev server
|
||||||
4. `open http://localhost:3000/admin` to access the admin panel
|
4. `open http://localhost:3000/admin` to access the admin panel
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import globby from 'globby'
|
|||||||
import * as os from 'node:os'
|
import * as os from 'node:os'
|
||||||
import path from 'path'
|
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 { createProject } from './create-project.js'
|
||||||
import { dbReplacements } from './replacements.js'
|
import { dbReplacements } from './replacements.js'
|
||||||
@@ -62,6 +62,32 @@ describe('createProject', () => {
|
|||||||
expect(packageJson.name).toStrictEqual(projectName)
|
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', () => {
|
describe('creates project from template', () => {
|
||||||
const templates = getValidTemplates()
|
const templates = getValidTemplates()
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,19 @@ import fse from 'fs-extra'
|
|||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
import path from 'path'
|
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 { tryInitRepoAndCommit } from '../utils/git.js'
|
||||||
import { debug, error, info, warning } from '../utils/log.js'
|
import { debug, error, info, warning } from '../utils/log.js'
|
||||||
import { configurePayloadConfig } from './configure-payload-config.js'
|
import { configurePayloadConfig } from './configure-payload-config.js'
|
||||||
import { configurePluginProject } from './configure-plugin-project.js'
|
import { configurePluginProject } from './configure-plugin-project.js'
|
||||||
|
import { downloadExample } from './download-example.js'
|
||||||
import { downloadTemplate } from './download-template.js'
|
import { downloadTemplate } from './download-template.js'
|
||||||
|
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
@@ -53,15 +60,24 @@ async function installDeps(args: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createProject(args: {
|
type TemplateOrExample =
|
||||||
cliArgs: CliArgs
|
| {
|
||||||
dbDetails?: DbDetails
|
example: ProjectExample
|
||||||
packageManager: PackageManager
|
}
|
||||||
projectDir: string
|
| {
|
||||||
projectName: string
|
template: ProjectTemplate
|
||||||
template: ProjectTemplate
|
}
|
||||||
}): Promise<void> {
|
|
||||||
const { cliArgs, dbDetails, packageManager, projectDir, projectName, template } = args
|
export async function createProject(
|
||||||
|
args: {
|
||||||
|
cliArgs: CliArgs
|
||||||
|
dbDetails?: DbDetails
|
||||||
|
packageManager: PackageManager
|
||||||
|
projectDir: string
|
||||||
|
projectName: string
|
||||||
|
} & TemplateOrExample,
|
||||||
|
): Promise<void> {
|
||||||
|
const { cliArgs, dbDetails, packageManager, projectDir, projectName } = args
|
||||||
|
|
||||||
if (cliArgs['--dry-run']) {
|
if (cliArgs['--dry-run']) {
|
||||||
debug(`Dry run: Creating project in ${chalk.green(projectDir)}`)
|
debug(`Dry run: Creating project in ${chalk.green(projectDir)}`)
|
||||||
@@ -70,6 +86,12 @@ export async function createProject(args: {
|
|||||||
|
|
||||||
await createOrFindProjectDir(projectDir)
|
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']) {
|
if (cliArgs['--local-template']) {
|
||||||
// Copy template from local path. For development purposes.
|
// Copy template from local path. For development purposes.
|
||||||
const localTemplate = path.resolve(
|
const localTemplate = path.resolve(
|
||||||
@@ -78,9 +100,10 @@ export async function createProject(args: {
|
|||||||
cliArgs['--local-template'],
|
cliArgs['--local-template'],
|
||||||
)
|
)
|
||||||
await fse.copy(localTemplate, projectDir)
|
await fse.copy(localTemplate, projectDir)
|
||||||
} else if ('url' in template) {
|
} else if ('template' in args && 'url' in args.template) {
|
||||||
if (cliArgs['--template-branch']) {
|
const { template } = args
|
||||||
template.url = `${template.url.split('#')?.[0]}#${cliArgs['--template-branch']}`
|
if (cliArgs['--branch']) {
|
||||||
|
template.url = `${template.url.split('#')?.[0]}#${cliArgs['--branch']}`
|
||||||
}
|
}
|
||||||
|
|
||||||
await downloadTemplate({
|
await downloadTemplate({
|
||||||
@@ -88,6 +111,17 @@ export async function createProject(args: {
|
|||||||
projectDir,
|
projectDir,
|
||||||
template,
|
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()
|
const spinner = p.spinner()
|
||||||
@@ -95,15 +129,17 @@ export async function createProject(args: {
|
|||||||
|
|
||||||
await updatePackageJSON({ projectDir, projectName })
|
await updatePackageJSON({ projectDir, projectName })
|
||||||
|
|
||||||
if (template.type === 'plugin') {
|
if ('template' in args) {
|
||||||
spinner.message('Configuring Plugin...')
|
if (args.template.type === 'plugin') {
|
||||||
configurePluginProject({ projectDirPath: projectDir, projectName })
|
spinner.message('Configuring Plugin...')
|
||||||
} else {
|
configurePluginProject({ projectDirPath: projectDir, projectName })
|
||||||
spinner.message('Configuring Payload...')
|
} else {
|
||||||
await configurePayloadConfig({
|
spinner.message('Configuring Payload...')
|
||||||
dbType: dbDetails?.type,
|
await configurePayloadConfig({
|
||||||
projectDirOrConfigPath: { projectDir },
|
dbType: dbDetails?.type,
|
||||||
})
|
projectDirOrConfigPath: { projectDir },
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove yarn.lock file. This is only desired in Payload Cloud.
|
// Remove yarn.lock file. This is only desired in Payload Cloud.
|
||||||
|
|||||||
46
packages/create-payload-app/src/lib/download-example.ts
Normal file
46
packages/create-payload-app/src/lib/download-example.ts
Normal file
@@ -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)
|
||||||
|
}
|
||||||
38
packages/create-payload-app/src/lib/examples.ts
Normal file
38
packages/create-payload-app/src/lib/examples.ts
Normal file
@@ -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<ProjectExample[]> {
|
||||||
|
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<false | ProjectExample> {
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import type { CliArgs } from './types.js'
|
|||||||
import { configurePayloadConfig } from './lib/configure-payload-config.js'
|
import { configurePayloadConfig } from './lib/configure-payload-config.js'
|
||||||
import { PACKAGE_VERSION } from './lib/constants.js'
|
import { PACKAGE_VERSION } from './lib/constants.js'
|
||||||
import { createProject } from './lib/create-project.js'
|
import { createProject } from './lib/create-project.js'
|
||||||
|
import { parseExample } from './lib/examples.js'
|
||||||
import { generateSecret } from './lib/generate-secret.js'
|
import { generateSecret } from './lib/generate-secret.js'
|
||||||
import { getPackageManager } from './lib/get-package-manager.js'
|
import { getPackageManager } from './lib/get-package-manager.js'
|
||||||
import { getNextAppDetails, initNext } from './lib/init-next.js'
|
import { getNextAppDetails, initNext } from './lib/init-next.js'
|
||||||
@@ -35,15 +36,16 @@ export class Main {
|
|||||||
// @ts-expect-error bad typings
|
// @ts-expect-error bad typings
|
||||||
this.args = arg(
|
this.args = arg(
|
||||||
{
|
{
|
||||||
|
'--branch': String,
|
||||||
'--db': String,
|
'--db': String,
|
||||||
'--db-accept-recommended': Boolean,
|
'--db-accept-recommended': Boolean,
|
||||||
'--db-connection-string': String,
|
'--db-connection-string': String,
|
||||||
|
'--example': String,
|
||||||
'--help': Boolean,
|
'--help': Boolean,
|
||||||
'--local-template': String,
|
'--local-template': String,
|
||||||
'--name': String,
|
'--name': String,
|
||||||
'--secret': String,
|
'--secret': String,
|
||||||
'--template': String,
|
'--template': String,
|
||||||
'--template-branch': String,
|
|
||||||
|
|
||||||
// Next.js
|
// Next.js
|
||||||
'--init-next': Boolean, // TODO: Is this needed if we detect if inside Next.js project?
|
'--init-next': Boolean, // TODO: Is this needed if we detect if inside Next.js project?
|
||||||
@@ -65,6 +67,7 @@ export class Main {
|
|||||||
|
|
||||||
// Aliases
|
// Aliases
|
||||||
'-d': '--db',
|
'-d': '--db',
|
||||||
|
'-e': '--example',
|
||||||
'-h': '--help',
|
'-h': '--help',
|
||||||
'-n': '--name',
|
'-n': '--name',
|
||||||
'-t': '--template',
|
'-t': '--template',
|
||||||
@@ -204,52 +207,76 @@ export class Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debugFlag) {
|
const exampleArg = this.args['--example']
|
||||||
debug(`Using templates from git tag: v${PACKAGE_VERSION}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const validTemplates = getValidTemplates()
|
if (exampleArg) {
|
||||||
const template = await parseTemplate(this.args, validTemplates)
|
const example = await parseExample({
|
||||||
if (!template) {
|
name: exampleArg,
|
||||||
p.log.error('Invalid template given')
|
branch: this.args['--branch'] ?? 'main',
|
||||||
p.outro(feedbackOutro())
|
})
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (template.type) {
|
if (!example) {
|
||||||
case 'plugin': {
|
helpMessage()
|
||||||
await createProject({
|
process.exit(1)
|
||||||
cliArgs: this.args,
|
|
||||||
packageManager,
|
|
||||||
projectDir,
|
|
||||||
projectName,
|
|
||||||
template,
|
|
||||||
})
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
case 'starter': {
|
|
||||||
const dbDetails = await selectDb(this.args, projectName)
|
|
||||||
const payloadSecret = generateSecret()
|
|
||||||
|
|
||||||
await createProject({
|
await createProject({
|
||||||
cliArgs: this.args,
|
cliArgs: this.args,
|
||||||
dbDetails,
|
example,
|
||||||
packageManager,
|
packageManager,
|
||||||
projectDir,
|
projectDir,
|
||||||
projectName,
|
projectName,
|
||||||
template,
|
})
|
||||||
})
|
}
|
||||||
|
|
||||||
await manageEnvFiles({
|
if (debugFlag) {
|
||||||
cliArgs: this.args,
|
debug(`Using ${exampleArg ? 'examples' : 'templates'} from git tag: v${PACKAGE_VERSION}`)
|
||||||
databaseType: dbDetails.type,
|
}
|
||||||
databaseUri: dbDetails.dbUri,
|
|
||||||
payloadSecret,
|
|
||||||
projectDir,
|
|
||||||
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,20 +2,23 @@ import type arg from 'arg'
|
|||||||
|
|
||||||
export interface Args extends arg.Spec {
|
export interface Args extends arg.Spec {
|
||||||
'--beta': BooleanConstructor
|
'--beta': BooleanConstructor
|
||||||
|
'--branch': StringConstructor
|
||||||
'--db': StringConstructor
|
'--db': StringConstructor
|
||||||
'--db-accept-recommended': BooleanConstructor
|
'--db-accept-recommended': BooleanConstructor
|
||||||
'--db-connection-string': StringConstructor
|
'--db-connection-string': StringConstructor
|
||||||
'--debug': BooleanConstructor
|
'--debug': BooleanConstructor
|
||||||
'--dry-run': BooleanConstructor
|
'--dry-run': BooleanConstructor
|
||||||
|
|
||||||
|
'--example': StringConstructor
|
||||||
'--help': BooleanConstructor
|
'--help': BooleanConstructor
|
||||||
'--init-next': BooleanConstructor
|
'--init-next': BooleanConstructor
|
||||||
|
'--local-example': StringConstructor
|
||||||
'--local-template': StringConstructor
|
'--local-template': StringConstructor
|
||||||
'--name': StringConstructor
|
'--name': StringConstructor
|
||||||
'--no-deps': BooleanConstructor
|
'--no-deps': BooleanConstructor
|
||||||
'--no-git': BooleanConstructor
|
'--no-git': BooleanConstructor
|
||||||
'--secret': StringConstructor
|
'--secret': StringConstructor
|
||||||
'--template': StringConstructor
|
'--template': StringConstructor
|
||||||
'--template-branch': StringConstructor
|
|
||||||
'--use-bun': BooleanConstructor
|
'--use-bun': BooleanConstructor
|
||||||
'--use-npm': BooleanConstructor
|
'--use-npm': BooleanConstructor
|
||||||
'--use-pnpm': BooleanConstructor
|
'--use-pnpm': BooleanConstructor
|
||||||
@@ -23,6 +26,7 @@ export interface Args extends arg.Spec {
|
|||||||
|
|
||||||
// Aliases
|
// Aliases
|
||||||
|
|
||||||
|
'-e': string
|
||||||
'-h': string
|
'-h': string
|
||||||
'-n': string
|
'-n': string
|
||||||
'-t': string
|
'-t': string
|
||||||
@@ -32,6 +36,11 @@ export type CliArgs = arg.Result<Args>
|
|||||||
|
|
||||||
export type ProjectTemplate = GitTemplate | PluginTemplate
|
export type ProjectTemplate = GitTemplate | PluginTemplate
|
||||||
|
|
||||||
|
export type ProjectExample = {
|
||||||
|
name: string
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template that is cloned verbatim from a git repo
|
* Template that is cloned verbatim from a git repo
|
||||||
* Performs .env manipulation based upon input
|
* Performs .env manipulation based upon input
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export function helpMessage(): void {
|
|||||||
|
|
||||||
-n {underline my-payload-app} Set project name
|
-n {underline my-payload-app} Set project name
|
||||||
-t {underline template_name} Choose specific template
|
-t {underline template_name} Choose specific template
|
||||||
|
-e {underline example_name} Choose specific exmaple
|
||||||
|
|
||||||
{dim Available templates: ${formatTemplates(validTemplates)}}
|
{dim Available templates: ${formatTemplates(validTemplates)}}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@payload-config": ["./test/access-control/config.ts"],
|
"@payload-config": ["./test/_community/config.ts"],
|
||||||
"@payloadcms/live-preview": ["./packages/live-preview/src"],
|
"@payloadcms/live-preview": ["./packages/live-preview/src"],
|
||||||
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],
|
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],
|
||||||
"@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],
|
"@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],
|
||||||
|
|||||||
Reference in New Issue
Block a user