chore(create-payload-app): remove unneeded 2.0 func, add cli overrides
This commit is contained in:
@@ -7,7 +7,8 @@
|
||||
"create-payload-app": "bin/cli.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm copyfiles && pnpm build:swc",
|
||||
"build": "pnpm copyfiles && pnpm typecheck && pnpm build:swc",
|
||||
"typecheck": "tsc",
|
||||
"copyfiles": "copyfiles -u 2 \"../../app/(payload)/**\" \"dist\"",
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import fse from 'fs-extra'
|
||||
import path from 'path'
|
||||
import globby from 'globby'
|
||||
|
||||
import type { DbDetails } from '../types.js'
|
||||
|
||||
import { warning } from '../utils/log.js'
|
||||
import { bundlerPackages, dbPackages, editorPackages } from './packages.js'
|
||||
import { dbReplacements } from './packages.js'
|
||||
|
||||
/** Update payload config with necessary imports and adapters */
|
||||
export async function configurePayloadConfig(args: {
|
||||
@@ -15,47 +15,10 @@ export async function configurePayloadConfig(args: {
|
||||
return
|
||||
}
|
||||
|
||||
// Update package.json
|
||||
const packageJsonPath = path.resolve(args.projectDir, 'package.json')
|
||||
try {
|
||||
const packageObj = await fse.readJson(packageJsonPath)
|
||||
|
||||
packageObj.dependencies['payload'] = '^2.0.0'
|
||||
|
||||
const dbPackage = dbPackages[args.dbDetails.type]
|
||||
const bundlerPackage = bundlerPackages['webpack']
|
||||
const editorPackage = editorPackages['lexical']
|
||||
|
||||
// Delete all other db adapters
|
||||
Object.values(dbPackages).forEach((p) => {
|
||||
if (p.packageName !== dbPackage.packageName) {
|
||||
delete packageObj.dependencies[p.packageName]
|
||||
}
|
||||
})
|
||||
|
||||
packageObj.dependencies[dbPackage.packageName] = dbPackage.version
|
||||
packageObj.dependencies[bundlerPackage.packageName] = bundlerPackage.version
|
||||
packageObj.dependencies[editorPackage.packageName] = editorPackage.version
|
||||
|
||||
await fse.writeJson(packageJsonPath, packageObj, { spaces: 2 })
|
||||
} catch (err: unknown) {
|
||||
warning(`Unable to configure Payload in package.json`)
|
||||
warning(err instanceof Error ? err.message : '')
|
||||
}
|
||||
|
||||
try {
|
||||
const possiblePaths = [
|
||||
path.resolve(args.projectDir, 'src/payload.config.ts'),
|
||||
path.resolve(args.projectDir, 'src/payload/payload.config.ts'),
|
||||
]
|
||||
|
||||
let payloadConfigPath: string | undefined
|
||||
|
||||
possiblePaths.forEach((p) => {
|
||||
if (fse.pathExistsSync(p) && !payloadConfigPath) {
|
||||
payloadConfigPath = p
|
||||
}
|
||||
})
|
||||
const payloadConfigPath = (
|
||||
await globby('**/payload.config.ts', { absolute: true, cwd: args.projectDir })
|
||||
)?.[0]
|
||||
|
||||
if (!payloadConfigPath) {
|
||||
warning('Unable to update payload.config.ts with plugins')
|
||||
@@ -65,9 +28,7 @@ export async function configurePayloadConfig(args: {
|
||||
const configContent = fse.readFileSync(payloadConfigPath, 'utf-8')
|
||||
const configLines = configContent.split('\n')
|
||||
|
||||
const dbReplacement = dbPackages[args.dbDetails.type]
|
||||
const bundlerReplacement = bundlerPackages['webpack']
|
||||
const editorReplacement = editorPackages['slate']
|
||||
const dbReplacement = dbReplacements[args.dbDetails.type]
|
||||
|
||||
let dbConfigStartLineIndex: number | undefined
|
||||
let dbConfigEndLineIndex: number | undefined
|
||||
@@ -76,21 +37,6 @@ export async function configurePayloadConfig(args: {
|
||||
if (l.includes('// database-adapter-import')) {
|
||||
configLines[i] = dbReplacement.importReplacement
|
||||
}
|
||||
if (l.includes('// bundler-import')) {
|
||||
configLines[i] = bundlerReplacement.importReplacement
|
||||
}
|
||||
|
||||
if (l.includes('// bundler-config')) {
|
||||
configLines[i] = bundlerReplacement.configReplacement
|
||||
}
|
||||
|
||||
if (l.includes('// editor-import')) {
|
||||
configLines[i] = editorReplacement.importReplacement
|
||||
}
|
||||
|
||||
if (l.includes('// editor-config')) {
|
||||
configLines[i] = editorReplacement.configReplacement
|
||||
}
|
||||
|
||||
if (l.includes('// database-adapter-config-start')) {
|
||||
dbConfigStartLineIndex = i
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import fse from 'fs-extra'
|
||||
import path from 'path'
|
||||
import type { BundlerType, CliArgs, DbType, ProjectTemplate } from '../types.js'
|
||||
import type { CliArgs, DbType, ProjectTemplate } from '../types.js'
|
||||
import { createProject } from './create-project.js'
|
||||
import { bundlerPackages, dbPackages, editorPackages } from './packages.js'
|
||||
import { dbReplacements } from './packages.js'
|
||||
import { getValidTemplates } from './templates.js'
|
||||
|
||||
const projectDir = path.resolve(__dirname, './tmp')
|
||||
@@ -104,29 +104,16 @@ describe('createProject', () => {
|
||||
},
|
||||
})
|
||||
|
||||
const dbReplacement = dbPackages[db as DbType]
|
||||
const bundlerReplacement = bundlerPackages[bundler as BundlerType]
|
||||
const editorReplacement = editorPackages['slate']
|
||||
const dbReplacement = dbReplacements[db as DbType]
|
||||
|
||||
const packageJsonPath = path.resolve(projectDir, 'package.json')
|
||||
const packageJson = fse.readJsonSync(packageJsonPath)
|
||||
|
||||
// Check deps
|
||||
expect(packageJson.dependencies['payload']).toEqual('^2.0.0')
|
||||
expect(packageJson.dependencies[dbReplacement.packageName]).toEqual(dbReplacement.version)
|
||||
|
||||
// Should only have one db adapter
|
||||
expect(
|
||||
Object.keys(packageJson.dependencies).filter((n) => n.startsWith('@payloadcms/db-')),
|
||||
).toHaveLength(1)
|
||||
|
||||
expect(packageJson.dependencies[bundlerReplacement.packageName]).toEqual(
|
||||
bundlerReplacement.version,
|
||||
)
|
||||
expect(packageJson.dependencies[editorReplacement.packageName]).toEqual(
|
||||
editorReplacement.version,
|
||||
)
|
||||
|
||||
let payloadConfigPath = path.resolve(projectDir, 'src/payload.config.ts')
|
||||
|
||||
// Website and ecommerce templates have payload.config.ts in src/payload
|
||||
@@ -142,12 +129,6 @@ describe('createProject', () => {
|
||||
expect(content).not.toContain('// database-adapter-config-start')
|
||||
expect(content).not.toContain('// database-adapter-config-end')
|
||||
expect(content).toContain(dbReplacement.configReplacement.join('\n'))
|
||||
|
||||
expect(content).not.toContain('// bundler-config-import')
|
||||
expect(content).toContain(bundlerReplacement.importReplacement)
|
||||
|
||||
expect(content).not.toContain('// bundler-config')
|
||||
expect(content).toContain(bundlerReplacement.configReplacement)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,14 +2,18 @@ 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 { error, success, warning } from '../utils/log.js'
|
||||
import { debug, error, success, warning } from '../utils/log.js'
|
||||
import { configurePayloadConfig } from './configure-payload-config.js'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
async function createOrFindProjectDir(projectDir: string): Promise<void> {
|
||||
const pathExists = await fse.pathExists(projectDir)
|
||||
if (!pathExists) {
|
||||
@@ -40,7 +44,7 @@ async function installDeps(args: {
|
||||
})
|
||||
return true
|
||||
} catch (err: unknown) {
|
||||
console.log({ err })
|
||||
error(`Error installing dependencies${err instanceof Error ? `: ${err.message}` : ''}.`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -48,29 +52,34 @@ async function installDeps(args: {
|
||||
export async function createProject(args: {
|
||||
cliArgs: CliArgs
|
||||
dbDetails?: DbDetails
|
||||
overrides?: {
|
||||
gitBranch?: string
|
||||
}
|
||||
packageManager: PackageManager
|
||||
projectDir: string
|
||||
projectName: string
|
||||
template: ProjectTemplate
|
||||
}): Promise<void> {
|
||||
const { cliArgs, dbDetails, overrides, packageManager, projectDir, projectName, template } = args
|
||||
const { cliArgs, dbDetails, packageManager, projectDir, projectName, template } = args
|
||||
|
||||
if (cliArgs['--dry-run']) {
|
||||
console.log(`\n Dry run: Creating project in ${chalk.green(path.resolve(projectDir))}\n`)
|
||||
console.log(`\n Dry run: Creating project in ${chalk.green(projectDir)}\n`)
|
||||
return
|
||||
}
|
||||
|
||||
await createOrFindProjectDir(projectDir)
|
||||
|
||||
console.log(`\n Creating project in ${chalk.green(path.resolve(projectDir))}\n`)
|
||||
console.log(`\n Creating project in ${chalk.green(projectDir)}\n`)
|
||||
|
||||
if ('url' in template) {
|
||||
if (cliArgs['--local-template']) {
|
||||
// Copy template from local path. For development purposes.
|
||||
const localTemplate = path.resolve(
|
||||
dirname,
|
||||
'../../../../templates/',
|
||||
cliArgs['--local-template'],
|
||||
)
|
||||
await fse.copy(localTemplate, projectDir)
|
||||
} else if ('url' in template) {
|
||||
let templateUrl = template.url
|
||||
if (args.overrides?.gitBranch) {
|
||||
templateUrl = `${template.url}#${overrides?.gitBranch}`
|
||||
if (cliArgs['--template-branch']) {
|
||||
templateUrl = `${template.url}#${cliArgs['--template-branch']}`
|
||||
debug(`Using template url: ${templateUrl}`)
|
||||
}
|
||||
const emitter = degit(templateUrl)
|
||||
@@ -88,6 +97,7 @@ export async function createProject(args: {
|
||||
await fse.remove(lockPath)
|
||||
}
|
||||
|
||||
if (!cliArgs['--no-deps']) {
|
||||
spinner.text = 'Installing dependencies...'
|
||||
const result = await installDeps({ cliArgs, packageManager, projectDir })
|
||||
spinner.stop()
|
||||
@@ -97,6 +107,10 @@ export async function createProject(args: {
|
||||
} else {
|
||||
error('Error installing dependencies')
|
||||
}
|
||||
} else {
|
||||
spinner.stop()
|
||||
spinner.clear()
|
||||
}
|
||||
}
|
||||
|
||||
export async function updatePackageJSON(args: {
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { CompilerOptions } from 'typescript'
|
||||
|
||||
import chalk from 'chalk'
|
||||
import { parse, stringify } from 'comment-json'
|
||||
import { detect } from 'detect-package-manager'
|
||||
import execa from 'execa'
|
||||
import fs from 'fs'
|
||||
import fse from 'fs-extra'
|
||||
@@ -30,7 +29,6 @@ type InitNextArgs = Pick<CliArgs, '--debug'> & {
|
||||
type InitNextResult = { reason?: string; success: boolean; userAppDir?: string }
|
||||
|
||||
export async function initNext(args: InitNextArgs): Promise<InitNextResult> {
|
||||
args.projectDir = args.projectDir || process.cwd()
|
||||
const { packageManager, projectDir } = args
|
||||
const templateResult = await applyPayloadTemplateFiles(args)
|
||||
if (!templateResult.success) return templateResult
|
||||
@@ -104,7 +102,7 @@ async function applyPayloadTemplateFiles(args: InitNextArgs): Promise<InitNextRe
|
||||
}
|
||||
|
||||
// Next.js configs can be next.config.js, next.config.mjs, etc.
|
||||
const foundConfig = (await globby('next.config.*js', { cwd: projectDir }))?.[0]
|
||||
const foundConfig = (await globby('next.config.*js', { absolute: true, cwd: projectDir }))?.[0]
|
||||
|
||||
if (!foundConfig) {
|
||||
throw new Error(`No next.config.js found at ${projectDir}`)
|
||||
@@ -137,11 +135,14 @@ async function applyPayloadTemplateFiles(args: InitNextArgs): Promise<InitNextRe
|
||||
}
|
||||
|
||||
// src/app or app
|
||||
const userAppDirGlob = await globby(['**/app'], {
|
||||
const userAppDir = (
|
||||
await globby(['**/app'], {
|
||||
absolute: true,
|
||||
cwd: projectDir,
|
||||
onlyDirectories: true,
|
||||
})
|
||||
const userAppDir = path.resolve(projectDir, userAppDirGlob?.[0])
|
||||
)?.[0]
|
||||
|
||||
if (!fs.existsSync(userAppDir)) {
|
||||
return { reason: `Could not find user app directory inside ${projectDir}`, success: false }
|
||||
} else {
|
||||
|
||||
@@ -1,24 +1,9 @@
|
||||
import type { BundlerType, DbType, EditorType } from '../types.js'
|
||||
import type { DbType } from '../types.js'
|
||||
|
||||
type DbAdapterReplacement = {
|
||||
configReplacement: string[]
|
||||
importReplacement: string
|
||||
packageName: string
|
||||
version: string
|
||||
}
|
||||
|
||||
type BundlerReplacement = {
|
||||
configReplacement: string
|
||||
importReplacement: string
|
||||
packageName: string
|
||||
version: string
|
||||
}
|
||||
|
||||
type EditorReplacement = {
|
||||
configReplacement: string
|
||||
importReplacement: string
|
||||
packageName: string
|
||||
version: string
|
||||
}
|
||||
|
||||
const mongodbReplacement: DbAdapterReplacement = {
|
||||
@@ -26,7 +11,6 @@ const mongodbReplacement: DbAdapterReplacement = {
|
||||
packageName: '@payloadcms/db-mongodb',
|
||||
// Replacement between `// database-adapter-config-start` and `// database-adapter-config-end`
|
||||
configReplacement: [' db: mongooseAdapter({', ' url: process.env.DATABASE_URI,', ' }),'],
|
||||
version: '^1.0.0',
|
||||
}
|
||||
|
||||
const postgresReplacement: DbAdapterReplacement = {
|
||||
@@ -39,45 +23,9 @@ const postgresReplacement: DbAdapterReplacement = {
|
||||
],
|
||||
importReplacement: "import { postgresAdapter } from '@payloadcms/db-postgres'",
|
||||
packageName: '@payloadcms/db-postgres',
|
||||
version: '^0.x', // up to, not including 1.0.0
|
||||
}
|
||||
|
||||
export const dbPackages: Record<DbType, DbAdapterReplacement> = {
|
||||
export const dbReplacements: Record<DbType, DbAdapterReplacement> = {
|
||||
mongodb: mongodbReplacement,
|
||||
postgres: postgresReplacement,
|
||||
}
|
||||
|
||||
const webpackReplacement: BundlerReplacement = {
|
||||
importReplacement: "import { webpackBundler } from '@payloadcms/bundler-webpack'",
|
||||
packageName: '@payloadcms/bundler-webpack',
|
||||
// Replacement of line containing `// bundler-config`
|
||||
configReplacement: ' bundler: webpackBundler(),',
|
||||
version: '^1.0.0',
|
||||
}
|
||||
|
||||
const viteReplacement: BundlerReplacement = {
|
||||
configReplacement: ' bundler: viteBundler(),',
|
||||
importReplacement: "import { viteBundler } from '@payloadcms/bundler-vite'",
|
||||
packageName: '@payloadcms/bundler-vite',
|
||||
version: '^0.x', // up to, not including 1.0.0
|
||||
}
|
||||
|
||||
export const bundlerPackages: Record<BundlerType, BundlerReplacement> = {
|
||||
vite: viteReplacement,
|
||||
webpack: webpackReplacement,
|
||||
}
|
||||
|
||||
export const editorPackages: Record<EditorType, EditorReplacement> = {
|
||||
lexical: {
|
||||
configReplacement: ' editor: lexicalEditor({}),',
|
||||
importReplacement: "import { lexicalEditor } from '@payloadcms/richtext-lexical'",
|
||||
packageName: '@payloadcms/richtext-lexical',
|
||||
version: '^0.x', // up to, not including 1.0.0
|
||||
},
|
||||
slate: {
|
||||
configReplacement: ' editor: slateEditor({}),',
|
||||
importReplacement: "import { slateEditor } from '@payloadcms/richtext-slate'",
|
||||
packageName: '@payloadcms/richtext-slate',
|
||||
version: '^1.0.0',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -58,13 +58,21 @@ export async function selectDb(args: CliArgs, projectName: string): Promise<DbDe
|
||||
|
||||
const dbChoice = dbChoiceRecord[dbType]
|
||||
|
||||
let dbUri: string | undefined = undefined
|
||||
const initialDbUri = `${dbChoice.dbConnectionPrefix}${
|
||||
projectName === '.' ? `payload-${getRandomDigitSuffix()}` : slugify(projectName)
|
||||
}`
|
||||
|
||||
if (args['--db-accept-recommended']) {
|
||||
dbUri = initialDbUri
|
||||
} else if (args['--db-connection-string']) {
|
||||
dbUri = args['--db-connection-string']
|
||||
} else {
|
||||
const dbUriRes = await prompts(
|
||||
{
|
||||
name: 'value',
|
||||
type: 'text',
|
||||
initial: `${dbChoice.dbConnectionPrefix}${
|
||||
projectName === '.' ? `payload-${getRandomDigitSuffix()}` : slugify(projectName)
|
||||
}`,
|
||||
initial: initialDbUri,
|
||||
message: `Enter ${dbChoice.title.split(' ')[0]} connection string`, // strip beta from title
|
||||
validate: (value: string) => !!value.length,
|
||||
},
|
||||
@@ -74,10 +82,12 @@ export async function selectDb(args: CliArgs, projectName: string): Promise<DbDe
|
||||
},
|
||||
},
|
||||
)
|
||||
dbUri = dbUriRes.value
|
||||
}
|
||||
|
||||
return {
|
||||
type: dbChoice.value,
|
||||
dbUri: dbUriRes.value,
|
||||
dbUri,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { parseAndInsertWithPayload, withPayloadImportStatement } from './wrap-next-config'
|
||||
import { parseAndInsertWithPayload, withPayloadImportStatement } from './wrap-next-config.js'
|
||||
|
||||
const defaultNextConfig = `/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
|
||||
@@ -3,7 +3,7 @@ import fs from 'fs'
|
||||
import globby from 'globby'
|
||||
import path from 'path'
|
||||
|
||||
export const withPayloadImportStatement = `import { withPayload } from '@payloadcms/next/withPayload'\n`
|
||||
export const withPayloadImportStatement = `import { withPayload } from '@payloadcms/next'\n`
|
||||
|
||||
export const wrapNextConfig = async (args: { projectDir: string }): Promise<void> => {
|
||||
const foundConfig = (await globby('next.config.*js', { cwd: args.projectDir }))?.[0]
|
||||
|
||||
@@ -25,7 +25,10 @@ export class Main {
|
||||
this.args = arg(
|
||||
{
|
||||
'--db': String,
|
||||
'--db-accept-recommended': Boolean,
|
||||
'--db-connection-string': String,
|
||||
'--help': Boolean,
|
||||
'--local-template': String,
|
||||
'--name': String,
|
||||
'--secret': String,
|
||||
'--template': String,
|
||||
@@ -63,10 +66,11 @@ export class Main {
|
||||
}
|
||||
|
||||
const projectName = await parseProjectName(this.args)
|
||||
const projectDir =
|
||||
const projectDir = path.resolve(
|
||||
projectName === '.' || this.args['--init-next']
|
||||
? path.basename(process.cwd())
|
||||
: `./${slugify(projectName)}`
|
||||
: `./${slugify(projectName)}`,
|
||||
)
|
||||
|
||||
console.log(welcomeMessage)
|
||||
const packageManager = await getPackageManager(this.args, projectDir)
|
||||
@@ -95,7 +99,6 @@ export class Main {
|
||||
const template = await parseTemplate(this.args, validTemplates)
|
||||
|
||||
switch (template.type) {
|
||||
case 'local':
|
||||
case 'starter': {
|
||||
const dbDetails = await selectDb(this.args, projectName)
|
||||
const payloadSecret = generateSecret()
|
||||
|
||||
@@ -3,10 +3,13 @@ import type arg from 'arg'
|
||||
export interface Args extends arg.Spec {
|
||||
'--beta': BooleanConstructor
|
||||
'--db': StringConstructor
|
||||
'--db-accept-recommended': BooleanConstructor
|
||||
'--db-connection-string': StringConstructor
|
||||
'--debug': BooleanConstructor
|
||||
'--dry-run': BooleanConstructor
|
||||
'--help': BooleanConstructor
|
||||
'--init-next': BooleanConstructor
|
||||
'--local-template': StringConstructor
|
||||
'--name': StringConstructor
|
||||
'--no-deps': BooleanConstructor
|
||||
'--secret': StringConstructor
|
||||
@@ -60,5 +63,4 @@ export type DbDetails = {
|
||||
type: DbType
|
||||
}
|
||||
|
||||
export type BundlerType = 'vite' | 'webpack'
|
||||
export type EditorType = 'lexical' | 'slate'
|
||||
|
||||
@@ -7,17 +7,6 @@
|
||||
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
||||
"rootDir": "./src" /* Specify the root folder within your source files. */
|
||||
},
|
||||
"exclude": [
|
||||
"dist",
|
||||
"build",
|
||||
"tests",
|
||||
"test",
|
||||
"node_modules",
|
||||
".eslintrc.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.spec.jsx",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.spec.tsx"
|
||||
],
|
||||
"exclude": ["dist", "build", "tests", "test", "node_modules", ".eslintrc.js"],
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts", "src/**/*.json"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user