create-ias-lowcode
Version:
134 lines (133 loc) • 5.44 kB
JavaScript
// lib/createApp.ts (核心逻辑)
import path from 'path';
import chalk from 'chalk';
import fs from 'fs-extra';
import inquirer from 'inquirer';
import { execa } from 'execa';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export async function createApp(projectName, options) {
const cwd = process.cwd();
console.log('cwd', cwd);
const targetDir = path.resolve(cwd, projectName);
console.log(chalk.cyan('创建新项目: ') + chalk.green(projectName));
console.log(chalk.cyan('提示: 按回车键确认'));
// 1. 交互式问答
const answers = await inquirer.prompt([
{
type: 'list',
name: 'features',
message: '选择需要的功能:',
choices: [
{ name: '基础开发框架', value: 'base', checked: true },
{ name: '组件', value: 'component' }
],
validate: (input) => {
if (input.length === 0) {
return '请至少选择一个功能 (按空格键选择)';
}
return true;
}
}
]);
console.log('选择的功能:', answers.features);
// 如果选择了基础开发框架,则询问包管理器
if (answers.features.includes('base')) {
console.log('询问包管理器...');
const packageManagerAnswer = await inquirer.prompt([
{
type: 'list',
name: 'packageManager',
message: '选择包管理器:',
choices: ['npm', 'yarn', 'pnpm'],
default: 'npm'
}
]);
answers.packageManager = packageManagerAnswer.packageManager;
console.log('选择的包管理器:', answers.packageManager);
// 询问是否需要安装依赖
const installDepsAnswer = await inquirer.prompt([
{
type: 'confirm',
name: 'installDeps',
message: '是否需要安装依赖?',
default: true
}
]);
answers.installDeps = installDepsAnswer.installDeps;
console.log('是否安装依赖:', answers.installDeps ? '是' : '否');
}
// 2. 处理目标目录
await handleExistingDirectory(targetDir);
// 3. 生成项目结构
const config = {
name: projectName,
features: answers.features,
packageManager: answers.packageManager
};
await generateProjectStructure(targetDir, config);
// 4. 只有在选择了基础开发框架且用户选择安装依赖时才安装依赖
if (answers.features.includes('base') && answers.packageManager && answers.installDeps) {
await installDependencies(targetDir, answers.packageManager);
// 自动切换到项目目录
try {
process.chdir(targetDir);
console.log(chalk.green(`\n✅ 项目创建成功,已自动进入项目目录 ${projectName}!`));
console.log(chalk.cyan(` ${answers.packageManager} run dev`) + ' (启动项目)');
}
catch (err) {
console.error(`❌ 无法切换到项目目录: ${err}`);
console.log(chalk.green(`\n✅ 项目创建成功!执行以下命令启动:`));
console.log(chalk.cyan(` cd ${projectName}`));
console.log(chalk.cyan(` ${answers.packageManager} run dev`));
}
}
else if (answers.features.includes('base') && answers.packageManager) {
console.log(chalk.green(`\n✅ 项目创建成功!执行以下命令启动:`));
console.log(chalk.cyan(` cd ${projectName}`));
console.log(chalk.cyan(` ${answers.packageManager} install`) + ' (安装依赖)');
console.log(chalk.cyan(` ${answers.packageManager} dev`) + ' (启动项目)');
}
else if (answers.features.includes('component')) {
console.log(chalk.green(`\n✅ 组件创建成功!`));
}
}
async function handleExistingDirectory(targetDir) {
if (await fs.pathExists(targetDir)) {
const { action } = await inquirer.prompt({
type: 'list',
name: 'action',
message: `目录 ${chalk.cyan(targetDir)} 已存在,如何处理?`,
choices: [
{ name: '覆盖', value: 'overwrite' },
{ name: '取消', value: 'cancel' }
]
});
if (action === 'cancel')
process.exit(0);
await fs.remove(targetDir);
}
await fs.ensureDir(targetDir);
}
async function generateProjectStructure(targetDir, config) {
// 根据选择的功能复制不同的模板
if (config.features.includes('base')) {
// 复制基础模板
await fs.copy(path.join(__dirname, '../templates/base'), targetDir);
//修改文件npmrc.txt为.npmrc
await fs.rename(path.join(targetDir, 'npmrc.txt'), path.join(targetDir, '.npmrc'));
}
if (config.features.includes('component')) {
// 复制组件模板
await fs.copy(path.join(__dirname, '../templates/component'), targetDir);
}
}
async function installDependencies(targetDir, packageManager) {
console.log(chalk.blue('\n🔧 正在安装依赖...'));
await execa(packageManager, ['install'], {
cwd: targetDir,
stdio: 'inherit'
});
}