feat(cpa): rework all prompts to use @clack/prompts
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
"bin"
|
||||
],
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^0.7.0",
|
||||
"@sindresorhus/slugify": "^1.1.0",
|
||||
"arg": "^5.0.0",
|
||||
"chalk": "^4.1.0",
|
||||
@@ -33,9 +34,6 @@
|
||||
"figures": "^3.2.0",
|
||||
"fs-extra": "^9.0.1",
|
||||
"globby": "11.1.0",
|
||||
"handlebars": "^4.7.7",
|
||||
"ora": "^5.1.0",
|
||||
"prompts": "^2.4.2",
|
||||
"terminal-link": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -44,8 +42,7 @@
|
||||
"@types/esprima": "^4.0.6",
|
||||
"@types/fs-extra": "^9.0.12",
|
||||
"@types/jest": "^27.0.3",
|
||||
"@types/node": "^16.6.2",
|
||||
"@types/prompts": "^2.4.1"
|
||||
"@types/node": "^16.6.2"
|
||||
},
|
||||
"exports": {
|
||||
"./commands": {
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import * as p from '@clack/prompts'
|
||||
import chalk from 'chalk'
|
||||
import degit from 'degit'
|
||||
import execa from 'execa'
|
||||
import fse from 'fs-extra'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import ora from 'ora'
|
||||
import path from 'path'
|
||||
|
||||
import type { CliArgs, DbDetails, PackageManager, ProjectTemplate } from '../types.js'
|
||||
|
||||
import { log } from '../utils/log.js'
|
||||
import { debug, error, success, warning } from '../utils/log.js'
|
||||
import { debug, error, warning } from '../utils/log.js'
|
||||
import { configurePayloadConfig } from './configure-payload-config.js'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
@@ -61,14 +60,12 @@ export async function createProject(args: {
|
||||
const { cliArgs, dbDetails, packageManager, projectDir, projectName, template } = args
|
||||
|
||||
if (cliArgs['--dry-run']) {
|
||||
log(`\n Dry run: Creating project in ${chalk.green(projectDir)}\n`)
|
||||
debug(`Dry run: Creating project in ${chalk.green(projectDir)}`)
|
||||
return
|
||||
}
|
||||
|
||||
await createOrFindProjectDir(projectDir)
|
||||
|
||||
log(`\n Creating project in ${chalk.green(projectDir)}\n`)
|
||||
|
||||
if (cliArgs['--local-template']) {
|
||||
// Copy template from local path. For development purposes.
|
||||
const localTemplate = path.resolve(
|
||||
@@ -87,9 +84,11 @@ export async function createProject(args: {
|
||||
await emitter.clone(projectDir)
|
||||
}
|
||||
|
||||
const spinner = ora('Checking latest Payload version...').start()
|
||||
const spinner = p.spinner()
|
||||
spinner.start('Checking latest Payload version...')
|
||||
|
||||
await updatePackageJSON({ projectDir, projectName })
|
||||
spinner.message('Configuring Payload...')
|
||||
await configurePayloadConfig({ dbDetails, projectDirOrConfigPath: { projectDir } })
|
||||
|
||||
// Remove yarn.lock file. This is only desired in Payload Cloud.
|
||||
@@ -99,18 +98,16 @@ export async function createProject(args: {
|
||||
}
|
||||
|
||||
if (!cliArgs['--no-deps']) {
|
||||
spinner.text = 'Installing dependencies...'
|
||||
spinner.message('Installing dependencies...')
|
||||
const result = await installDeps({ cliArgs, packageManager, projectDir })
|
||||
spinner.stop()
|
||||
spinner.clear()
|
||||
if (result) {
|
||||
success('Dependencies installed')
|
||||
spinner.stop('Dependencies installed')
|
||||
} else {
|
||||
error('Error installing dependencies')
|
||||
spinner.stop('Error installing dependencies', 1)
|
||||
}
|
||||
} else {
|
||||
spinner.stop()
|
||||
spinner.clear()
|
||||
spinner.stop('Dependency installation skipped')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { CompilerOptions } from 'typescript'
|
||||
|
||||
import * as p from '@clack/prompts'
|
||||
import { parse, stringify } from 'comment-json'
|
||||
import execa from 'execa'
|
||||
import fs from 'fs'
|
||||
@@ -7,7 +8,6 @@ import globby from 'globby'
|
||||
import path from 'path'
|
||||
import { promisify } from 'util'
|
||||
|
||||
import { log } from '../utils/log.js'
|
||||
const readFile = promisify(fs.readFile)
|
||||
const writeFile = promisify(fs.writeFile)
|
||||
|
||||
@@ -16,14 +16,15 @@ const dirname = path.dirname(filename)
|
||||
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import type { CliArgs, PackageManager } from '../types.js'
|
||||
import type { CliArgs, DbType, PackageManager } from '../types.js'
|
||||
|
||||
import { copyRecursiveSync } from '../utils/copy-recursive-sync.js'
|
||||
import { error, info, debug as origDebug, success, warning } from '../utils/log.js'
|
||||
import { debug as origDebug, warning } from '../utils/log.js'
|
||||
import { moveMessage } from '../utils/messages.js'
|
||||
import { wrapNextConfig } from './wrap-next-config.js'
|
||||
|
||||
type InitNextArgs = Pick<CliArgs, '--debug'> & {
|
||||
dbType: DbType
|
||||
nextConfigPath: string
|
||||
packageManager: PackageManager
|
||||
projectDir: string
|
||||
@@ -40,7 +41,7 @@ type InitNextResult =
|
||||
| { isSrcDir: boolean; nextAppDir?: string; reason: string; success: false }
|
||||
|
||||
export async function initNext(args: InitNextArgs): Promise<InitNextResult> {
|
||||
const { packageManager, projectDir } = args
|
||||
const { dbType: dbType, packageManager, projectDir } = args
|
||||
|
||||
const isSrcDir = fs.existsSync(path.resolve(projectDir, 'src'))
|
||||
|
||||
@@ -61,7 +62,7 @@ export async function initNext(args: InitNextArgs): Promise<InitNextResult> {
|
||||
const layoutPath = path.resolve(nextAppDir, 'layout.tsx')
|
||||
if (fs.existsSync(layoutPath)) {
|
||||
// Output directions for user to move all files from app to top-level directory named `(app)`
|
||||
log(moveMessage({ nextAppDir, projectDir }))
|
||||
p.log.warn(moveMessage({ nextAppDir, projectDir }))
|
||||
return {
|
||||
isSrcDir,
|
||||
nextAppDir,
|
||||
@@ -70,6 +71,9 @@ export async function initNext(args: InitNextArgs): Promise<InitNextResult> {
|
||||
}
|
||||
}
|
||||
|
||||
const installSpinner = p.spinner()
|
||||
installSpinner.start('Installing Payload and dependencies...')
|
||||
|
||||
const configurationResult = installAndConfigurePayload({
|
||||
...args,
|
||||
isSrcDir,
|
||||
@@ -78,11 +82,13 @@ export async function initNext(args: InitNextArgs): Promise<InitNextResult> {
|
||||
})
|
||||
|
||||
if (configurationResult.success === false) {
|
||||
installSpinner.stop(configurationResult.reason, 1)
|
||||
return { ...configurationResult, isSrcDir, success: false }
|
||||
}
|
||||
|
||||
const { success: installSuccess } = await installDeps(projectDir, packageManager)
|
||||
const { success: installSuccess } = await installDeps(projectDir, packageManager, dbType)
|
||||
if (!installSuccess) {
|
||||
installSpinner.stop('Failed to install dependencies', 1)
|
||||
return {
|
||||
...configurationResult,
|
||||
isSrcDir,
|
||||
@@ -93,7 +99,7 @@ export async function initNext(args: InitNextArgs): Promise<InitNextResult> {
|
||||
|
||||
// Add `@payload-config` to tsconfig.json `paths`
|
||||
await addPayloadConfigToTsConfig(projectDir, isSrcDir)
|
||||
|
||||
installSpinner.stop('Successfully installed Payload and dependencies')
|
||||
return { ...configurationResult, isSrcDir, nextAppDir, success: true }
|
||||
}
|
||||
|
||||
@@ -119,14 +125,15 @@ async function addPayloadConfigToTsConfig(projectDir: string, isSrcDir: boolean)
|
||||
}
|
||||
|
||||
function installAndConfigurePayload(
|
||||
args: InitNextArgs & { isSrcDir: boolean; nextAppDir: string },
|
||||
args: InitNextArgs & {
|
||||
isSrcDir: boolean
|
||||
nextAppDir: string
|
||||
},
|
||||
):
|
||||
| { payloadConfigPath: string; success: true }
|
||||
| { payloadConfigPath?: string; reason: string; success: false } {
|
||||
const { '--debug': debug, isSrcDir, nextAppDir, nextConfigPath, projectDir, useDistFiles } = args
|
||||
|
||||
info('Initializing Payload app in Next.js project', 1)
|
||||
|
||||
const logDebug = (message: string) => {
|
||||
if (debug) origDebug(message)
|
||||
}
|
||||
@@ -174,21 +181,18 @@ function installAndConfigurePayload(
|
||||
// Wrap next.config.js with withPayload
|
||||
wrapNextConfig({ nextConfigPath })
|
||||
|
||||
success('Successfully initialized.')
|
||||
return {
|
||||
payloadConfigPath: path.resolve(nextAppDir, '../payload.config.ts'),
|
||||
success: true,
|
||||
}
|
||||
}
|
||||
|
||||
async function installDeps(projectDir: string, packageManager: PackageManager) {
|
||||
info(`Installing dependencies with ${packageManager}`, 1)
|
||||
const packagesToInstall = [
|
||||
'payload',
|
||||
'@payloadcms/db-mongodb',
|
||||
'@payloadcms/next',
|
||||
'@payloadcms/richtext-lexical',
|
||||
].map((pkg) => `${pkg}@alpha`)
|
||||
async function installDeps(projectDir: string, packageManager: PackageManager, dbType: DbType) {
|
||||
const packagesToInstall = ['payload', '@payloadcms/next', '@payloadcms/richtext-lexical'].map(
|
||||
(pkg) => `${pkg}@alpha`,
|
||||
)
|
||||
|
||||
packagesToInstall.push(`@payloadcms/db-${dbType}@alpha`)
|
||||
|
||||
let exitCode = 0
|
||||
switch (packageManager) {
|
||||
@@ -212,10 +216,5 @@ async function installDeps(projectDir: string, packageManager: PackageManager) {
|
||||
}
|
||||
}
|
||||
|
||||
if (exitCode !== 0) {
|
||||
error(`Failed to install dependencies with ${packageManager}`)
|
||||
} else {
|
||||
success(`Successfully installed dependencies`)
|
||||
}
|
||||
return { success: exitCode === 0 }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import prompts from 'prompts'
|
||||
import * as p from '@clack/prompts'
|
||||
|
||||
import type { CliArgs } from '../types.js'
|
||||
|
||||
@@ -6,19 +6,14 @@ export async function parseProjectName(args: CliArgs): Promise<string> {
|
||||
if (args['--name']) return args['--name']
|
||||
if (args._[0]) return args._[0]
|
||||
|
||||
const response = await prompts(
|
||||
{
|
||||
name: 'value',
|
||||
type: 'text',
|
||||
const projectName = await p.text({
|
||||
message: 'Project name?',
|
||||
validate: (value: string) => !!value.length,
|
||||
validate: (value) => {
|
||||
if (!value) return 'Please enter a project name.'
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
})
|
||||
if (p.isCancel(projectName)) {
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
return response.value
|
||||
}
|
||||
return projectName
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import prompts from 'prompts'
|
||||
import * as p from '@clack/prompts'
|
||||
|
||||
import type { CliArgs, ProjectTemplate } from '../types.js'
|
||||
|
||||
export async function parseTemplate(
|
||||
args: CliArgs,
|
||||
validTemplates: ProjectTemplate[],
|
||||
): Promise<ProjectTemplate> {
|
||||
): Promise<ProjectTemplate | undefined> {
|
||||
if (args['--template']) {
|
||||
const templateName = args['--template']
|
||||
const template = validTemplates.find((t) => t.name === templateName)
|
||||
@@ -13,29 +13,20 @@ export async function parseTemplate(
|
||||
return template
|
||||
}
|
||||
|
||||
const response = await prompts(
|
||||
{
|
||||
name: 'value',
|
||||
type: 'select',
|
||||
choices: validTemplates.map((p) => {
|
||||
const response = await p.select<{ label: string; value: string }[], string>({
|
||||
message: 'Choose project template',
|
||||
options: validTemplates.map((p) => {
|
||||
return {
|
||||
description: p.description,
|
||||
title: p.name,
|
||||
label: p.name,
|
||||
value: p.name,
|
||||
}
|
||||
}),
|
||||
message: 'Choose project template',
|
||||
validate: (value: string) => !!value.length,
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
})
|
||||
if (p.isCancel(response)) {
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
const template = validTemplates.find((t) => t.name === response.value)
|
||||
if (!template) throw new Error('Template is undefined')
|
||||
const template = validTemplates.find((t) => t.name === response)
|
||||
|
||||
return template
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as p from '@clack/prompts'
|
||||
import slugify from '@sindresorhus/slugify'
|
||||
import prompts from 'prompts'
|
||||
|
||||
import type { CliArgs, DbDetails, DbType } from '../types.js'
|
||||
|
||||
@@ -23,7 +23,7 @@ const dbChoiceRecord: Record<DbType, DbChoice> = {
|
||||
}
|
||||
|
||||
export async function selectDb(args: CliArgs, projectName: string): Promise<DbDetails> {
|
||||
let dbType: DbType | undefined = undefined
|
||||
let dbType: DbType | symbol | undefined = undefined
|
||||
if (args['--db']) {
|
||||
if (!Object.values(dbChoiceRecord).some((dbChoice) => dbChoice.value === args['--db'])) {
|
||||
throw new Error(
|
||||
@@ -34,31 +34,20 @@ export async function selectDb(args: CliArgs, projectName: string): Promise<DbDe
|
||||
}
|
||||
dbType = args['--db'] as DbType
|
||||
} else {
|
||||
const dbTypeRes = await prompts(
|
||||
{
|
||||
name: 'value',
|
||||
type: 'select',
|
||||
choices: Object.values(dbChoiceRecord).map((dbChoice) => {
|
||||
return {
|
||||
title: dbChoice.title,
|
||||
value: dbChoice.value,
|
||||
}
|
||||
}),
|
||||
message: 'Select a database',
|
||||
validate: (value: string) => !!value.length,
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
dbType = dbTypeRes.value
|
||||
dbType = await p.select<{ label: string; value: DbType }[], DbType>({
|
||||
initialValue: 'mongodb',
|
||||
message: `Select a database`,
|
||||
options: [
|
||||
{ label: 'MongoDB', value: 'mongodb' },
|
||||
{ label: 'Postgres', value: 'postgres' },
|
||||
],
|
||||
})
|
||||
if (p.isCancel(dbType)) process.exit(0)
|
||||
}
|
||||
|
||||
const dbChoice = dbChoiceRecord[dbType]
|
||||
|
||||
let dbUri: string | undefined = undefined
|
||||
let dbUri: string | symbol | undefined = undefined
|
||||
const initialDbUri = `${dbChoice.dbConnectionPrefix}${
|
||||
projectName === '.' ? `payload-${getRandomDigitSuffix()}` : slugify(projectName)
|
||||
}`
|
||||
@@ -68,21 +57,11 @@ export async function selectDb(args: CliArgs, projectName: string): Promise<DbDe
|
||||
} else if (args['--db-connection-string']) {
|
||||
dbUri = args['--db-connection-string']
|
||||
} else {
|
||||
const dbUriRes = await prompts(
|
||||
{
|
||||
name: 'value',
|
||||
type: 'text',
|
||||
initial: initialDbUri,
|
||||
dbUri = await p.text({
|
||||
initialValue: initialDbUri,
|
||||
message: `Enter ${dbChoice.title.split(' ')[0]} connection string`, // strip beta from title
|
||||
validate: (value: string) => !!value.length,
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
dbUri = dbUriRes.value
|
||||
})
|
||||
if (p.isCancel(dbUri)) process.exit(0)
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
|
||||
import type { CliArgs, ProjectTemplate } from '../types.js'
|
||||
|
||||
import { error, success } from '../utils/log.js'
|
||||
import { debug, error } from '../utils/log.js'
|
||||
|
||||
/** Parse and swap .env.example values and write .env */
|
||||
export async function writeEnvFile(args: {
|
||||
@@ -17,7 +16,7 @@ export async function writeEnvFile(args: {
|
||||
const { cliArgs, databaseUri, payloadSecret, projectDir, template } = args
|
||||
|
||||
if (cliArgs['--dry-run']) {
|
||||
success(`DRY RUN: .env file created`)
|
||||
debug(`DRY RUN: .env file created`)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -51,8 +50,6 @@ export async function writeEnvFile(args: {
|
||||
const content = `MONGODB_URI=${databaseUri}\nPAYLOAD_SECRET=${payloadSecret}`
|
||||
await fs.outputFile(`${projectDir}/.env`, content)
|
||||
}
|
||||
|
||||
success('.env file created')
|
||||
} catch (err: unknown) {
|
||||
error('Unable to write .env file')
|
||||
if (err instanceof Error) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import * as p from '@clack/prompts'
|
||||
import slugify from '@sindresorhus/slugify'
|
||||
import arg from 'arg'
|
||||
import chalk from 'chalk'
|
||||
import { detect } from 'detect-package-manager'
|
||||
import globby from 'globby'
|
||||
import path from 'path'
|
||||
@@ -15,13 +17,8 @@ import { parseTemplate } from './lib/parse-template.js'
|
||||
import { selectDb } from './lib/select-db.js'
|
||||
import { getValidTemplates, validateTemplate } from './lib/templates.js'
|
||||
import { writeEnvFile } from './lib/write-env-file.js'
|
||||
import { error, log, success } from './utils/log.js'
|
||||
import {
|
||||
helpMessage,
|
||||
successMessage,
|
||||
successfulNextInit,
|
||||
welcomeMessage,
|
||||
} from './utils/messages.js'
|
||||
import { error, info } from './utils/log.js'
|
||||
import { feedbackOutro, helpMessage, successMessage, successfulNextInit } from './utils/messages.js'
|
||||
|
||||
export class Main {
|
||||
args: CliArgs
|
||||
@@ -73,21 +70,20 @@ export class Main {
|
||||
|
||||
try {
|
||||
if (this.args['--help']) {
|
||||
log(helpMessage())
|
||||
helpMessage()
|
||||
process.exit(0)
|
||||
}
|
||||
log(welcomeMessage)
|
||||
|
||||
// Detect if inside Next.js project
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('\n')
|
||||
p.intro(chalk.bgCyan(chalk.black(' create-payload-app ')))
|
||||
p.log.message("Welcome to Payload. Let's create a project!")
|
||||
// Detect if inside Next.js projeckpt
|
||||
const nextConfigPath = (
|
||||
await globby('next.config.*js', { absolute: true, cwd: process.cwd() })
|
||||
)?.[0]
|
||||
initContext.nextConfigPath = nextConfigPath
|
||||
|
||||
success('Next.js app detected.')
|
||||
|
||||
// TODO: Prompt to continue
|
||||
|
||||
if (initContext.nextConfigPath) {
|
||||
this.args['--name'] = slugify(path.basename(path.dirname(initContext.nextConfigPath)))
|
||||
}
|
||||
@@ -100,20 +96,30 @@ export class Main {
|
||||
const packageManager = await getPackageManager(this.args, projectDir)
|
||||
|
||||
if (nextConfigPath) {
|
||||
// p.note('Detected existing Next.js project.')
|
||||
p.log.step(chalk.bold('Detected existing Next.js project.'))
|
||||
const proceed = await p.confirm({
|
||||
initialValue: true,
|
||||
message: 'Install Payload in this project?',
|
||||
})
|
||||
if (p.isCancel(proceed) || !proceed) {
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const dbDetails = await selectDb(this.args, projectName)
|
||||
|
||||
const result = await initNext({
|
||||
...this.args,
|
||||
dbType: dbDetails.type,
|
||||
nextConfigPath,
|
||||
packageManager,
|
||||
projectDir,
|
||||
})
|
||||
|
||||
if (result.success === false) {
|
||||
error(result.reason)
|
||||
process.exit(1)
|
||||
} else {
|
||||
success('Payload app successfully initialized in Next.js project')
|
||||
}
|
||||
|
||||
const dbDetails = await selectDb(this.args, projectName)
|
||||
await configurePayloadConfig({
|
||||
dbDetails,
|
||||
projectDirOrConfigPath: {
|
||||
@@ -121,9 +127,9 @@ export class Main {
|
||||
},
|
||||
})
|
||||
|
||||
// TODO: This should continue the normal prompt flow
|
||||
success('Payload project successfully created')
|
||||
log(successfulNextInit())
|
||||
info('Payload project successfully created!')
|
||||
p.note(successfulNextInit(), chalk.bgGreen(chalk.black(' Documentation ')))
|
||||
p.outro(feedbackOutro())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -131,13 +137,17 @@ export class Main {
|
||||
if (templateArg) {
|
||||
const valid = validateTemplate(templateArg)
|
||||
if (!valid) {
|
||||
log(helpMessage())
|
||||
helpMessage()
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
const validTemplates = getValidTemplates()
|
||||
const template = await parseTemplate(this.args, validTemplates)
|
||||
if (!template) {
|
||||
p.log.error('Invalid template given')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
switch (template.type) {
|
||||
case 'starter': {
|
||||
@@ -172,8 +182,9 @@ export class Main {
|
||||
}
|
||||
}
|
||||
|
||||
success('Payload project successfully created')
|
||||
log(successMessage(projectDir, packageManager))
|
||||
info('Payload project successfully created!')
|
||||
p.note(successMessage(projectDir, packageManager), chalk.bgGreen(chalk.black(' Next Steps ')))
|
||||
p.outro(feedbackOutro())
|
||||
} catch (err: unknown) {
|
||||
error(err instanceof Error ? err.message : 'An error occurred')
|
||||
}
|
||||
|
||||
@@ -1,34 +1,23 @@
|
||||
/* eslint-disable no-console */
|
||||
import * as p from '@clack/prompts'
|
||||
import chalk from 'chalk'
|
||||
import figures from 'figures'
|
||||
|
||||
export const success = (message: string): void => {
|
||||
console.log(`${chalk.green(figures.tick)} ${chalk.bold(message)}`)
|
||||
}
|
||||
|
||||
export const warning = (message: string): void => {
|
||||
console.log(chalk.yellow('? ') + chalk.bold(message))
|
||||
p.log.warn(chalk.yellow('? ') + chalk.bold(message))
|
||||
}
|
||||
|
||||
export const info = (message: string, paddingTop?: number): void => {
|
||||
console.log(
|
||||
`${'\n'.repeat(paddingTop || 0)}${chalk.green(figures.pointerSmall)} ${chalk.bold(message)}`,
|
||||
)
|
||||
export const info = (message: string): void => {
|
||||
p.log.step(chalk.bold(message))
|
||||
}
|
||||
|
||||
export const error = (message: string): void => {
|
||||
console.log(`${chalk.red(figures.cross)} ${chalk.bold(message)}`)
|
||||
p.log.error(chalk.bold(message))
|
||||
}
|
||||
|
||||
export const debug = (message: string): void => {
|
||||
console.log(
|
||||
`${chalk.gray(figures.pointerSmall)} ${chalk.bgGray('[DEBUG]')} ${chalk.gray(message)}`,
|
||||
)
|
||||
p.log.step(`${chalk.bgGray('[DEBUG]')} ${chalk.gray(message)}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* console.log passthrough
|
||||
*/
|
||||
export const log = (message: string): void => {
|
||||
console.log(message)
|
||||
p.log.message(message)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
/* eslint-disable no-console */
|
||||
import chalk from 'chalk'
|
||||
import figures from 'figures'
|
||||
import path from 'path'
|
||||
import terminalLink from 'terminal-link'
|
||||
|
||||
import type { ProjectTemplate } from '../types.js'
|
||||
import type { PackageManager } from '../types.js'
|
||||
|
||||
import { getValidTemplates } from '../lib/templates.js'
|
||||
|
||||
const header = (message: string): string => `${chalk.yellow(figures.star)} ${chalk.bold(message)}`
|
||||
const header = (message: string): string => chalk.bold(message)
|
||||
|
||||
export const welcomeMessage = chalk`
|
||||
{green Welcome to Payload. Let's create a project! }
|
||||
@@ -15,14 +16,14 @@ export const welcomeMessage = chalk`
|
||||
|
||||
const spacer = ' '.repeat(8)
|
||||
|
||||
export function helpMessage(): string {
|
||||
export function helpMessage(): void {
|
||||
const validTemplates = getValidTemplates()
|
||||
return chalk`
|
||||
console.log(chalk`
|
||||
{bold USAGE}
|
||||
|
||||
{dim $} {bold npx create-payload-app}
|
||||
{dim $} {bold npx create-payload-app} my-project
|
||||
{dim $} {bold npx create-payload-app} -n my-project -t blog
|
||||
{dim $} {bold npx create-payload-app} -n my-project -t template-name
|
||||
|
||||
{bold OPTIONS}
|
||||
|
||||
@@ -36,7 +37,7 @@ export function helpMessage(): string {
|
||||
--use-pnpm Use pnpm to install dependencies
|
||||
--no-deps Do not install any dependencies
|
||||
-h Show help
|
||||
`
|
||||
`)
|
||||
}
|
||||
|
||||
function formatTemplates(templates: ProjectTemplate[]) {
|
||||
@@ -45,19 +46,20 @@ function formatTemplates(templates: ProjectTemplate[]) {
|
||||
.join(`\n${spacer}`)}`
|
||||
}
|
||||
|
||||
export function successMessage(projectDir: string, packageManager: string): string {
|
||||
export function successMessage(projectDir: string, packageManager: PackageManager): string {
|
||||
const relativePath = path.relative(process.cwd(), projectDir)
|
||||
return `
|
||||
${header('Launch Application:')}
|
||||
${header('Launch Application:')}
|
||||
|
||||
- cd ${projectDir}
|
||||
- cd ./${relativePath}
|
||||
- ${
|
||||
packageManager === 'yarn' ? 'yarn' : 'npm run'
|
||||
packageManager === 'npm' ? 'npm run' : packageManager
|
||||
} dev or follow directions in ${createTerminalLink(
|
||||
'README.md',
|
||||
`file://${path.resolve(projectDir, 'README.md')}`,
|
||||
)}
|
||||
|
||||
${header('Documentation:')}
|
||||
${header('Documentation:')}
|
||||
|
||||
- ${createTerminalLink(
|
||||
'Getting Started',
|
||||
@@ -69,35 +71,33 @@ export function successMessage(projectDir: string, packageManager: string): stri
|
||||
}
|
||||
|
||||
export function successfulNextInit(): string {
|
||||
return `
|
||||
${header('Successful Payload Installation!')}
|
||||
|
||||
${header('Documentation:')}
|
||||
|
||||
- ${createTerminalLink(
|
||||
return `- ${createTerminalLink(
|
||||
'Getting Started',
|
||||
'https://payloadcms.com/docs/getting-started/what-is-payload',
|
||||
)}
|
||||
- ${createTerminalLink('Configuration', 'https://payloadcms.com/docs/configuration/overview')}
|
||||
- ${createTerminalLink('Configuration', 'https://payloadcms.com/docs/configuration/overview')}
|
||||
`
|
||||
}
|
||||
|
||||
export function moveMessage(args: { nextAppDir: string; projectDir: string }): string {
|
||||
const relativePath = path.relative(process.cwd(), args.nextAppDir)
|
||||
return `
|
||||
${header('Next Steps:')}
|
||||
${header('Next Steps:')}
|
||||
|
||||
Payload does not support a top-level layout.tsx file in your Next.js app directory.
|
||||
Payload does not support a top-level layout.tsx file in your Next.js app directory.
|
||||
|
||||
${chalk.bold('To continue:')}
|
||||
${chalk.bold('To continue:')}
|
||||
|
||||
- Move all files from ${args.nextAppDir} to a top-level directory named ${chalk.bold(
|
||||
'(app)',
|
||||
)} or similar.
|
||||
Move all files from ./${relativePath} to a named directory such as ${chalk.bold('(app)')}
|
||||
|
||||
Once moved, rerun the create-payload-app command again.
|
||||
Once moved, rerun the create-payload-app command again.
|
||||
`
|
||||
}
|
||||
|
||||
export function feedbackOutro(): string {
|
||||
return `${chalk.bgCyan(chalk.black(' Have feedback? '))} Visit ${createTerminalLink('GitHub', 'https://github.com/payloadcms/payload')}`
|
||||
}
|
||||
|
||||
// Create terminalLink with fallback for unsupported terminals
|
||||
function createTerminalLink(text: string, url: string) {
|
||||
return terminalLink(text, url, {
|
||||
|
||||
46
pnpm-lock.yaml
generated
46
pnpm-lock.yaml
generated
@@ -295,6 +295,9 @@ importers:
|
||||
|
||||
packages/create-payload-app:
|
||||
dependencies:
|
||||
'@clack/prompts':
|
||||
specifier: ^0.7.0
|
||||
version: 0.7.0
|
||||
'@sindresorhus/slugify':
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.2
|
||||
@@ -331,15 +334,6 @@ importers:
|
||||
globby:
|
||||
specifier: 11.1.0
|
||||
version: 11.1.0
|
||||
handlebars:
|
||||
specifier: ^4.7.7
|
||||
version: 4.7.8
|
||||
ora:
|
||||
specifier: ^5.1.0
|
||||
version: 5.4.1
|
||||
prompts:
|
||||
specifier: ^2.4.2
|
||||
version: 2.4.2
|
||||
terminal-link:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
@@ -362,9 +356,6 @@ importers:
|
||||
'@types/node':
|
||||
specifier: ^16.6.2
|
||||
version: 16.18.85
|
||||
'@types/prompts':
|
||||
specifier: ^2.4.1
|
||||
version: 2.4.9
|
||||
|
||||
packages/db-mongodb:
|
||||
dependencies:
|
||||
@@ -2745,6 +2736,23 @@ packages:
|
||||
/@bcoe/v8-coverage@0.2.3:
|
||||
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
|
||||
|
||||
/@clack/core@0.3.4:
|
||||
resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==}
|
||||
dependencies:
|
||||
picocolors: 1.0.0
|
||||
sisteransi: 1.0.5
|
||||
dev: false
|
||||
|
||||
/@clack/prompts@0.7.0:
|
||||
resolution: {integrity: sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==}
|
||||
dependencies:
|
||||
'@clack/core': 0.3.4
|
||||
picocolors: 1.0.0
|
||||
sisteransi: 1.0.5
|
||||
dev: false
|
||||
bundledDependencies:
|
||||
- is-unicode-supported
|
||||
|
||||
/@cspotcode/source-map-support@0.8.1:
|
||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -7451,6 +7459,7 @@ packages:
|
||||
buffer: 5.7.1
|
||||
inherits: 2.0.4
|
||||
readable-stream: 3.6.2
|
||||
dev: true
|
||||
|
||||
/body-parser@1.20.1:
|
||||
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
|
||||
@@ -7790,6 +7799,7 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
restore-cursor: 3.1.0
|
||||
dev: true
|
||||
|
||||
/cli-cursor@4.0.0:
|
||||
resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
|
||||
@@ -7801,6 +7811,7 @@ packages:
|
||||
/cli-spinners@2.9.2:
|
||||
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/cli-truncate@3.1.0:
|
||||
resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==}
|
||||
@@ -7852,6 +7863,7 @@ packages:
|
||||
/clone@1.0.4:
|
||||
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
|
||||
engines: {node: '>=0.8'}
|
||||
dev: true
|
||||
|
||||
/clsx@1.2.1:
|
||||
resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==}
|
||||
@@ -8738,6 +8750,7 @@ packages:
|
||||
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
|
||||
dependencies:
|
||||
clone: 1.0.4
|
||||
dev: true
|
||||
|
||||
/defer-to-connect@2.0.1:
|
||||
resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==}
|
||||
@@ -10725,6 +10738,7 @@ packages:
|
||||
wordwrap: 1.0.0
|
||||
optionalDependencies:
|
||||
uglify-js: 3.17.4
|
||||
dev: true
|
||||
|
||||
/hanji@0.0.5:
|
||||
resolution: {integrity: sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw==}
|
||||
@@ -11234,6 +11248,7 @@ packages:
|
||||
/is-interactive@1.0.0:
|
||||
resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/is-interactive@2.0.0:
|
||||
resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==}
|
||||
@@ -11366,6 +11381,7 @@ packages:
|
||||
/is-unicode-supported@0.1.0:
|
||||
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/is-unicode-supported@1.3.0:
|
||||
resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==}
|
||||
@@ -12595,6 +12611,7 @@ packages:
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
is-unicode-supported: 0.1.0
|
||||
dev: true
|
||||
|
||||
/log-symbols@6.0.0:
|
||||
resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
|
||||
@@ -13060,6 +13077,7 @@ packages:
|
||||
|
||||
/neo-async@2.6.2:
|
||||
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
|
||||
dev: true
|
||||
|
||||
/netmask@2.0.2:
|
||||
resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==}
|
||||
@@ -13489,6 +13507,7 @@ packages:
|
||||
log-symbols: 4.1.0
|
||||
strip-ansi: 6.0.1
|
||||
wcwidth: 1.0.1
|
||||
dev: true
|
||||
|
||||
/ora@8.0.1:
|
||||
resolution: {integrity: sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==}
|
||||
@@ -15472,6 +15491,7 @@ packages:
|
||||
dependencies:
|
||||
onetime: 5.1.2
|
||||
signal-exit: 3.0.7
|
||||
dev: true
|
||||
|
||||
/restore-cursor@4.0.0:
|
||||
resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
|
||||
@@ -17014,6 +17034,7 @@ packages:
|
||||
engines: {node: '>=0.8.0'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/unbox-primitive@1.0.2:
|
||||
@@ -17242,6 +17263,7 @@ packages:
|
||||
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
|
||||
dependencies:
|
||||
defaults: 1.0.4
|
||||
dev: true
|
||||
|
||||
/web-streams-polyfill@3.3.3:
|
||||
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
|
||||
|
||||
Reference in New Issue
Block a user