chore(create-payload-app): migrate to esm, adjust init-next tests

This commit is contained in:
Elliot DeNolf
2024-03-14 11:12:01 -04:00
parent e3e0f056a9
commit 53a09f4989
19 changed files with 179 additions and 90 deletions

View File

@@ -9,3 +9,4 @@
**/node_modules
**/temp
playwright.config.ts
jest.config.js

View File

@@ -1,10 +1,4 @@
// const nextJest = require('next/jest.js')
// const createJestConfig = nextJest({
// // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
// dir: './',
// })
/** @type {import('@jest/types').Config} */
const customJestConfig = {
extensionsToTreatAsEsm: ['.ts', '.tsx'],
globalSetup: './test/jest.setup.ts',
@@ -23,5 +17,4 @@ const customJestConfig = {
verbose: true,
}
// module.exports = createJestConfig(customJestConfig)
export default customJestConfig

View File

@@ -142,6 +142,7 @@
"slate": "0.91.4",
"swc-plugin-transform-remove-imports": "^1.12.1",
"tempfile": "^3.0.0",
"tempy": "^1.0.1",
"ts-node": "10.9.1",
"tsx": "^4.7.1",
"turbo": "^1.12.5",

View File

@@ -1,9 +1,11 @@
module.exports = {
testEnvironment: 'node',
import baseConfig from '../../jest.config.js'
/** @type {import('@jest/types').Config} */
const customJestConfig = {
...baseConfig,
globalSetup: null,
testMatch: ['**/src/**/?(*.)+(spec|test|it-test).[tj]s?(x)'],
testTimeout: 10000,
transform: {
'^.+\\.(ts|tsx)?$': 'ts-jest',
},
verbose: true,
testTimeout: 20000,
}
export default customJestConfig

View File

@@ -2,6 +2,7 @@
"name": "create-payload-app",
"version": "1.0.0",
"license": "MIT",
"type": "module",
"bin": {
"create-payload-app": "bin/cli.js"
},
@@ -41,7 +42,6 @@
"@types/fs-extra": "^9.0.12",
"@types/jest": "^27.0.3",
"@types/node": "^16.6.2",
"@types/prompts": "^2.4.1",
"ts-jest": "^29.1.0"
"@types/prompts": "^2.4.1"
}
}

View File

@@ -1,5 +1,5 @@
import { Main } from './main'
import { error } from './utils/log'
import { Main } from './main.js'
import { error } from './utils/log.js'
async function main(): Promise<void> {
await new Main().init()

View File

@@ -1,10 +1,10 @@
import fse from 'fs-extra'
import path from 'path'
import type { DbDetails } from '../types'
import type { DbDetails } from '../types.js'
import { warning } from '../utils/log'
import { bundlerPackages, dbPackages, editorPackages } from './packages'
import { warning } from '../utils/log.js'
import { bundlerPackages, dbPackages, editorPackages } from './packages.js'
/** Update payload config with necessary imports and adapters */
export async function configurePayloadConfig(args: {

View File

@@ -1,10 +1,10 @@
import fse from 'fs-extra'
import path from 'path'
import type { BundlerType, CliArgs, DbType, ProjectTemplate } from '../types'
import { createProject } from './create-project'
import { bundlerPackages, dbPackages, editorPackages } from './packages'
import type { BundlerType, CliArgs, DbType, ProjectTemplate } from '../types.js'
import { createProject } from './create-project.js'
import { bundlerPackages, dbPackages, editorPackages } from './packages.js'
import exp from 'constants'
import { getValidTemplates } from './templates'
import { getValidTemplates } from './templates.js'
const projectDir = path.resolve(__dirname, './tmp')
describe('createProject', () => {

View File

@@ -5,10 +5,10 @@ import fse from 'fs-extra'
import ora from 'ora'
import path from 'path'
import type { CliArgs, DbDetails, PackageManager, ProjectTemplate } from '../types'
import type { CliArgs, DbDetails, PackageManager, ProjectTemplate } from '../types.js'
import { error, success, warning } from '../utils/log'
import { configurePayloadConfig } from './configure-payload-config'
import { error, success, warning } from '../utils/log.js'
import { configurePayloadConfig } from './configure-payload-config.js'
async function createOrFindProjectDir(projectDir: string): Promise<void> {
const pathExists = await fse.pathExists(projectDir)

View File

@@ -1,18 +1,26 @@
import type { CompilerOptions } from 'typescript'
import chalk from 'chalk'
import * as CommentJson from 'comment-json'
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'
import globby from 'globby'
import path from 'path'
import { promisify } from 'util'
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
import type { CliArgs } from '../types'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
import { copyRecursiveSync } from '../utils/copy-recursive-sync'
import { error, info, debug as origDebug, success, warning } from '../utils/log'
import { fileURLToPath } from 'node:url'
import type { CliArgs } from '../types.js'
import { copyRecursiveSync } from '../utils/copy-recursive-sync.js'
import { error, info, debug as origDebug, success, warning } from '../utils/log.js'
type InitNextArgs = Pick<CliArgs, '--debug'> & {
projectDir?: string
@@ -45,13 +53,13 @@ export async function initNext(args: InitNextArgs): Promise<InitNextResult> {
${chalk.bold(`Wrap your existing next.config.js with the withPayload function. Here is an example:`)}
const { withPayload } = require("@payloadcms/next");
import withPayload from '@payloadcms/next/withPayload'
const nextConfig = {
// Your Next.js config
};
// Your Next.js config here
}
module.exports = withPayload(nextConfig);
export default withPayload(nextConfig)
`
@@ -62,10 +70,10 @@ export async function initNext(args: InitNextArgs): Promise<InitNextResult> {
async function addPayloadConfigToTsConfig(projectDir: string) {
const tsConfigPath = path.resolve(projectDir, 'tsconfig.json')
const userTsConfigContent = await fse.readFile(tsConfigPath, {
const userTsConfigContent = await readFile(tsConfigPath, {
encoding: 'utf8',
})
const userTsConfig = CommentJson.parse(userTsConfigContent) as {
const userTsConfig = parse(userTsConfigContent) as {
compilerOptions?: CompilerOptions
}
if (!userTsConfig.compilerOptions && !('extends' in userTsConfig)) {
@@ -77,7 +85,7 @@ async function addPayloadConfigToTsConfig(projectDir: string) {
...(userTsConfig.compilerOptions.paths || {}),
'@payload-config': ['./payload.config.ts'],
}
await fse.writeFile(tsConfigPath, CommentJson.stringify(userTsConfig, null, 2))
await writeFile(tsConfigPath, stringify(userTsConfig, null, 2), { encoding: 'utf8' })
}
}
@@ -96,6 +104,11 @@ 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]
if (!foundConfig) {
throw new Error(`No next.config.js found at ${projectDir}`)
}
const nextConfigPath = path.resolve(projectDir, foundConfig)
if (!fs.existsSync(nextConfigPath)) {
return {
@@ -107,9 +120,9 @@ async function applyPayloadTemplateFiles(args: InitNextArgs): Promise<InitNextRe
}
const templateFilesPath =
__dirname.endsWith('dist') || useDistFiles
? path.resolve(__dirname, '../..', 'dist/app')
: path.resolve(__dirname, '../../../../app')
dirname.endsWith('dist') || useDistFiles
? path.resolve(dirname, '../..', 'dist/app')
: path.resolve(dirname, '../../../../app')
if (debug) logDebug(`Using template files from: ${templateFilesPath}`)
@@ -152,7 +165,6 @@ async function installDeps(projectDir: string) {
'@payloadcms/db-mongodb',
'@payloadcms/next',
'@payloadcms/richtext-slate',
'@payloadcms/ui',
].map((pkg) => `${pkg}@alpha`)
let exitCode = 0

View File

@@ -1,4 +1,4 @@
import type { BundlerType, DbType, EditorType } from '../types'
import type { BundlerType, DbType, EditorType } from '../types.js'
type DbAdapterReplacement = {
configReplacement: string[]

View File

@@ -1,6 +1,6 @@
import prompts from 'prompts'
import type { CliArgs } from '../types'
import type { CliArgs } from '../types.js'
export async function parseProjectName(args: CliArgs): Promise<string> {
if (args['--name']) return args['--name']
@@ -9,8 +9,8 @@ export async function parseProjectName(args: CliArgs): Promise<string> {
const response = await prompts(
{
name: 'value',
message: 'Project name?',
type: 'text',
message: 'Project name?',
validate: (value: string) => !!value.length,
},
{

View File

@@ -1,6 +1,6 @@
import prompts from 'prompts'
import type { CliArgs, ProjectTemplate } from '../types'
import type { CliArgs, ProjectTemplate } from '../types.js'
export async function parseTemplate(
args: CliArgs,
@@ -16,6 +16,7 @@ export async function parseTemplate(
const response = await prompts(
{
name: 'value',
type: 'select',
choices: validTemplates.map((p) => {
return {
description: p.description,
@@ -24,7 +25,6 @@ export async function parseTemplate(
}
}),
message: 'Choose project template',
type: 'select',
validate: (value: string) => !!value.length,
},
{

View File

@@ -1,7 +1,7 @@
import slugify from '@sindresorhus/slugify'
import prompts from 'prompts'
import type { CliArgs, DbDetails, DbType } from '../types'
import type { CliArgs, DbDetails, DbType } from '../types.js'
type DbChoice = {
dbConnectionPrefix: `${string}/`
@@ -37,6 +37,7 @@ export async function selectDb(args: CliArgs, projectName: string): Promise<DbDe
const dbTypeRes = await prompts(
{
name: 'value',
type: 'select',
choices: Object.values(dbChoiceRecord).map((dbChoice) => {
return {
title: dbChoice.title,
@@ -44,7 +45,6 @@ export async function selectDb(args: CliArgs, projectName: string): Promise<DbDe
}
}),
message: 'Select a database',
type: 'select',
validate: (value: string) => !!value.length,
},
{
@@ -61,11 +61,11 @@ export async function selectDb(args: CliArgs, projectName: string): Promise<DbDe
const dbUriRes = await prompts(
{
name: 'value',
type: 'text',
initial: `${dbChoice.dbConnectionPrefix}${
projectName === '.' ? `payload-${getRandomDigitSuffix()}` : slugify(projectName)
}`,
message: `Enter ${dbChoice.title.split(' ')[0]} connection string`, // strip beta from title
type: 'text',
validate: (value: string) => !!value.length,
},
{
@@ -76,8 +76,8 @@ export async function selectDb(args: CliArgs, projectName: string): Promise<DbDe
)
return {
dbUri: dbUriRes.value,
type: dbChoice.value,
dbUri: dbUriRes.value,
}
}

View File

@@ -1,6 +1,6 @@
import type { ProjectTemplate } from '../types'
import type { ProjectTemplate } from '../types.js'
import { error, info } from '../utils/log'
import { error, info } from '../utils/log.js'
export function validateTemplate(templateName: string): boolean {
const validTemplates = getValidTemplates()
@@ -16,38 +16,38 @@ export function getValidTemplates(): ProjectTemplate[] {
return [
{
name: 'blank',
description: 'Blank Template',
type: 'starter',
description: 'Blank Template',
url: 'https://github.com/payloadcms/payload/templates/blank',
},
{
name: 'website',
description: 'Website Template',
type: 'starter',
description: 'Website Template',
url: 'https://github.com/payloadcms/payload/templates/website',
},
{
name: 'ecommerce',
description: 'E-commerce Template',
type: 'starter',
description: 'E-commerce Template',
url: 'https://github.com/payloadcms/payload/templates/ecommerce',
},
{
name: 'plugin',
description: 'Template for creating a Payload plugin',
type: 'plugin',
description: 'Template for creating a Payload plugin',
url: 'https://github.com/payloadcms/payload-plugin-template',
},
{
name: 'payload-demo',
description: 'Payload demo site at https://demo.payloadcms.com',
type: 'starter',
description: 'Payload demo site at https://demo.payloadcms.com',
url: 'https://github.com/payloadcms/public-demo',
},
{
name: 'payload-website',
description: 'Payload website CMS at https://payloadcms.com',
type: 'starter',
description: 'Payload website CMS at https://payloadcms.com',
url: 'https://github.com/payloadcms/website-cms',
},
]

View File

@@ -1,9 +1,9 @@
import fs from 'fs-extra'
import path from 'path'
import type { ProjectTemplate } from '../types'
import type { ProjectTemplate } from '../types.js'
import { error, success } from '../utils/log'
import { error, success } from '../utils/log.js'
/** Parse and swap .env.example values and write .env */
export async function writeEnvFile(args: {

View File

@@ -2,18 +2,18 @@ import slugify from '@sindresorhus/slugify'
import arg from 'arg'
import commandExists from 'command-exists'
import type { CliArgs, PackageManager } from './types'
import type { CliArgs, PackageManager } from './types.js'
import { createProject } from './lib/create-project'
import { generateSecret } from './lib/generate-secret'
import { initNext } from './lib/init-next'
import { parseProjectName } from './lib/parse-project-name'
import { parseTemplate } from './lib/parse-template'
import { selectDb } from './lib/select-db'
import { getValidTemplates, validateTemplate } from './lib/templates'
import { writeEnvFile } from './lib/write-env-file'
import { error, success } from './utils/log'
import { helpMessage, successMessage, welcomeMessage } from './utils/messages'
import { createProject } from './lib/create-project.js'
import { generateSecret } from './lib/generate-secret.js'
import { initNext } from './lib/init-next.js'
import { parseProjectName } from './lib/parse-project-name.js'
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, success } from './utils/log.js'
import { helpMessage, successMessage, welcomeMessage } from './utils/messages.js'
export class Main {
args: CliArgs

77
pnpm-lock.yaml generated
View File

@@ -256,6 +256,9 @@ importers:
tempfile:
specifier: ^3.0.0
version: 3.0.0
tempy:
specifier: ^1.0.1
version: 1.0.1
ts-node:
specifier: 10.9.1
version: 10.9.1(@swc/core@1.4.2)(@types/node@20.5.7)(typescript@5.2.2)
@@ -341,9 +344,6 @@ importers:
'@types/prompts':
specifier: ^2.4.1
version: 2.4.9
ts-jest:
specifier: ^29.1.0
version: 29.1.2(@babel/core@7.24.0)(esbuild@0.19.12)(jest@29.7.0)(typescript@5.2.2)
packages/db-mongodb:
dependencies:
@@ -6769,6 +6769,14 @@ packages:
- supports-color
dev: true
/aggregate-error@3.1.0:
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
engines: {node: '>=8'}
dependencies:
clean-stack: 2.2.0
indent-string: 4.0.0
dev: true
/ajv-formats@2.1.1(ajv@8.12.0):
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies:
@@ -6944,7 +6952,6 @@ packages:
/array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
dev: false
/array.prototype.filter@1.0.3:
resolution: {integrity: sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==}
@@ -7594,6 +7601,11 @@ packages:
resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
dev: false
/clean-stack@2.2.0:
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
engines: {node: '>=6'}
dev: true
/cli-boxes@3.0.0:
resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
engines: {node: '>=10'}
@@ -8160,6 +8172,11 @@ packages:
resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==}
dev: false
/crypto-random-string@2.0.0:
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
engines: {node: '>=8'}
dev: true
/crypto-random-string@4.0.0:
resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==}
engines: {node: '>=12'}
@@ -8630,6 +8647,20 @@ packages:
hasBin: true
dev: false
/del@6.1.1:
resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==}
engines: {node: '>=10'}
dependencies:
globby: 11.1.0
graceful-fs: 4.2.11
is-glob: 4.0.3
is-path-cwd: 2.2.0
is-path-inside: 3.0.3
p-map: 4.0.0
rimraf: 3.0.2
slash: 3.0.0
dev: true
/delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
@@ -8703,7 +8734,6 @@ packages:
engines: {node: '>=8'}
dependencies:
path-type: 4.0.0
dev: false
/direction@1.0.4:
resolution: {integrity: sha512-GYqKi1aH7PJXxdhTeZBFrg8vUBeKXi+cNprXsC1kpJcbcVnV9wBsrOu1cQEdG0WeQwlfHiy3XvnKfIrJ2R0NzQ==}
@@ -10476,7 +10506,6 @@ packages:
ignore: 5.3.1
merge2: 1.4.1
slash: 3.0.0
dev: false
/globby@14.0.1:
resolution: {integrity: sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==}
@@ -11196,6 +11225,11 @@ packages:
resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
engines: {node: '>=8'}
/is-path-cwd@2.2.0:
resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==}
engines: {node: '>=6'}
dev: true
/is-path-inside@3.0.3:
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
engines: {node: '>=8'}
@@ -13573,6 +13607,13 @@ packages:
p-limit: 4.0.0
dev: true
/p-map@4.0.0:
resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
engines: {node: '>=10'}
dependencies:
aggregate-error: 3.1.0
dev: true
/p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
@@ -13737,7 +13778,6 @@ packages:
/path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
dev: false
/path-type@5.0.0:
resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==}
@@ -16449,6 +16489,17 @@ packages:
uuid: 3.4.0
dev: true
/tempy@1.0.1:
resolution: {integrity: sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==}
engines: {node: '>=10'}
dependencies:
del: 6.1.1
is-stream: 2.0.1
temp-dir: 2.0.0
type-fest: 0.16.0
unique-string: 2.0.0
dev: true
/terminal-link@2.1.1:
resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==}
engines: {node: '>=8'}
@@ -16890,6 +16941,11 @@ packages:
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
engines: {node: '>=4'}
/type-fest@0.16.0:
resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==}
engines: {node: '>=10'}
dev: true
/type-fest@0.20.2:
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
engines: {node: '>=10'}
@@ -17024,6 +17080,13 @@ packages:
engines: {node: '>=18'}
dev: true
/unique-string@2.0.0:
resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==}
engines: {node: '>=8'}
dependencies:
crypto-random-string: 2.0.0
dev: true
/unique-string@3.0.0:
resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==}
engines: {node: '>=12'}

View File

@@ -1,9 +1,11 @@
import type { CompilerOptions } from 'typescript'
import * as CommentJson from 'comment-json'
import execa from 'execa'
import fs from 'fs'
import path from 'path'
import shelljs from 'shelljs'
import tempy from 'tempy'
import { fileURLToPath } from 'url'
import { promisify } from 'util'
@@ -12,12 +14,13 @@ const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
const commonNextCreateParams = '--typescript --eslint --no-tailwind --app --import-alias="@/*"'
const nextCreateCommands: Partial<Record<'noSrcDir' | 'srcDir', string>> = {
srcDir:
'pnpm create next-app@latest . --typescript --eslint --no-tailwind --app --import-alias="@/*" --src-dir',
noSrcDir:
'pnpm create next-app@latest . --typescript --eslint --no-tailwind --app --import-alias="@/*" --no-src-dir',
noSrcDir: `pnpm create next-app@latest . ${commonNextCreateParams} --no-src-dir`,
srcDir: `pnpm create next-app@latest . ${commonNextCreateParams} --src-dir`,
}
describe('create-payload-app', () => {
@@ -34,9 +37,8 @@ describe('create-payload-app', () => {
})
describe.each(Object.keys(nextCreateCommands))(`--init-next with %s`, (nextCmdKey) => {
const projectDir = path.resolve(dirname, 'test-app')
beforeEach(() => {
const projectDir = tempy.directory()
beforeEach(async () => {
if (fs.existsSync(projectDir)) {
fs.rmdirSync(projectDir, { recursive: true })
}
@@ -47,7 +49,20 @@ describe('create-payload-app', () => {
}
// Create a new Next.js project with default options
shelljs.exec(nextCreateCommands[nextCmdKey], { cwd: projectDir })
console.log(`Running: ${nextCreateCommands[nextCmdKey]} in ${projectDir}`)
const [cmd, ...args] = nextCreateCommands[nextCmdKey].split(' ')
const { exitCode, stderr } = await execa(cmd, [...args], { cwd: projectDir })
if (exitCode !== 0) {
console.error({ exitCode, stderr })
}
// WARNING: Big WTF here. Replace improper path string inside tsconfig.json.
// For some reason two double quotes are used for the src path when executed in the test environment.
// This is likely ESM-related
const tsConfigPath = path.resolve(projectDir, 'tsconfig.json')
let userTsConfigContent = await readFile(tsConfigPath, { encoding: 'utf8' })
userTsConfigContent = userTsConfigContent.replace('""@/*""', '"@/*"')
await writeFile(tsConfigPath, userTsConfigContent, { encoding: 'utf8' })
})
afterEach(() => {
@@ -78,9 +93,11 @@ describe('create-payload-app', () => {
const userTsConfig = CommentJson.parse(userTsConfigContent) as {
compilerOptions?: CompilerOptions
}
expect(userTsConfig.compilerOptions.paths?.['@payload-config']).toEqual([
expect(userTsConfig.compilerOptions.paths?.['@payload-config']).toStrictEqual([
'./payload.config.ts',
])
// TODO: Start the Next.js app and check if it runs
})
})
})