diff --git a/lib/create.d.ts b/lib/create.d.ts index e50fb0c..8044f69 100644 --- a/lib/create.d.ts +++ b/lib/create.d.ts @@ -1 +1,2 @@ -export default function create(dirName: string, env: string): Promise; +export declare function create(dirName: string, cmd: any): Promise; +export declare function update(dirName: string, subDirName: string, cmd: any): Promise; diff --git a/lib/create.js b/lib/create.js index 9dca358..1fd0ca4 100644 --- a/lib/create.js +++ b/lib/create.js @@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); +exports.update = exports.create = void 0; const file_handle_1 = require("./file-handle"); const enum_1 = require("./enum"); const config_1 = require("./config"); @@ -29,13 +30,15 @@ const prompt = [ * @name 检查项目名是否已存在 * @param dirName */ -function checkProjectName(dirName) { +function checkProjectName(dirName, exists) { // 项目根路径 const rootPath = process.cwd() + '/' + dirName; const isExists = (0, file_handle_1.checkFileExists)(rootPath); - if (isExists) { - console.error((0, tip_style_1.error)(`Cannot create a project named ${(0, tip_style_1.success)(`"${dirName}"`)} because a path with the same name exists.\n`) + (0, tip_style_1.error)('Please choose a different project name.')); - process.exit(1); + if (isExists && !exists) { + throw new global.Error(`Cannot create a project named ${(0, tip_style_1.success)(`"${dirName}"`)} because a path with the same name exists.\nPlease choose a different project name.`); + } + else if (!isExists && exists) { + throw new global.Error(`${(0, tip_style_1.success)(dirName)} is not a valid project dir.\nPlease choose a different project name.`); } } /** @@ -58,7 +61,28 @@ async function getMiniVersion() { }); return versionsSort[0]['sdkVer']; } -async function create(dirName, env) { +async function createWechatMpBoilplate(dir, isDev, isUpdate) { + // 获取微信小程序稳定基础版本库 + const miniVersion = await getMiniVersion(); + // 获取小程序项目app.json内容 + const appJsonWithWeChatMp = (0, template_1.appJsonContentWithWeChatMp)(isDev); + // 获取小程序项目project.config.json内容 + const projectConfigWithWeChatMp = (0, template_1.projectConfigContentWithWeChatMp)(config_1.USER_CONFIG_FILE_NAME, 'wechatMp', miniVersion); + // 获取小程序项目oak.config.json内容 + const oakConfigWithWeChatMp = (0, template_1.oakConfigContentWithWeChatMp)(); + const appJsonPathWithWeChatMp = (0, path_1.join)(dir, 'src', 'app.json'); + // 小程序项目project.config.json路径 + const projectConfigPathWithWeChatMp = (0, path_1.join)(dir, 'src', 'project.config.json'); + // 小程序项目project.config.json路径 + const oakConfigPathWithWeChatMp = (0, path_1.join)(dir, 'src', config_1.USER_CONFIG_FILE_NAME); + // 创建小程序项目project.config.json + (0, file_handle_1.checkFileExistsAndCreate)(projectConfigPathWithWeChatMp, projectConfigWithWeChatMp, enum_1.checkFileExistsAndCreateType.FILE, isUpdate); + // 创建小程序项目app.json + (0, file_handle_1.checkFileExistsAndCreate)(appJsonPathWithWeChatMp, appJsonWithWeChatMp, enum_1.checkFileExistsAndCreateType.FILE, isUpdate); + // 创建小程序项目oak.config.json + (0, file_handle_1.checkFileExistsAndCreate)(oakConfigPathWithWeChatMp, oakConfigWithWeChatMp, enum_1.checkFileExistsAndCreateType.FILE, isUpdate); +} +async function create(dirName, cmd) { const nameOption = { type: 'input', name: 'name', @@ -66,10 +90,8 @@ async function create(dirName, env) { default: dirName, }; prompt.unshift(nameOption); - const isDev = env === 'dev' || env === 'development'; + const isDev = cmd.dev ? true : false; const { name, version, description } = await inquirer_1.default.prompt(prompt); - // 获取微信小程序稳定基础版本库 - const miniVersion = await getMiniVersion(); // 获取package.json内容 const packageJson = (0, template_1.packageJsonContent)({ name, @@ -81,12 +103,6 @@ async function create(dirName, env) { }); // 获取tsconfig.json内容 const tsconfigJson = (0, template_1.tsConfigJsonContent)(); - // 获取小程序项目app.json内容 - const appJsonWithWeChatMp = (0, template_1.appJsonContentWithWeChatMp)(isDev); - // 获取小程序项目project.config.json内容 - const projectConfigWithWeChatMp = (0, template_1.projectConfigContentWithWeChatMp)(config_1.USER_CONFIG_FILE_NAME, 'wechatMp', miniVersion); - // 获取小程序项目oak.config.json内容 - const oakConfigWithWeChatMp = (0, template_1.oakConfigContentWithWeChatMp)(); // 项目根路径 const rootPath = process.cwd() + '/' + dirName; // package.json路径 @@ -97,13 +113,8 @@ async function create(dirName, env) { const webRootPath = `${rootPath}/web`; // 小程序项目根路径 const weChatMpRootPath = `${rootPath}/wechatMp`; - const appJsonPathWithWeChatMp = `${weChatMpRootPath}/src/app.json`; - // 小程序项目project.config.json路径 - const projectConfigPathWithWeChatMp = `${weChatMpRootPath}/src/project.config.json`; - // 小程序项目project.config.json路径 - const oakConfigPathWithWeChatMp = `${weChatMpRootPath}/src/${config_1.USER_CONFIG_FILE_NAME}`; // 被复制的文件夹路径 - const currentPath = (0, path_1.join)(__dirname, '..') + '/template'; + const currentPath = (0, path_1.join)(__dirname, '..', 'template'); //检查项目名是否存在 checkProjectName(dirName); try { @@ -115,12 +126,7 @@ async function create(dirName, env) { (0, file_handle_1.checkFileExistsAndCreate)(tsconfigJsonPath, tsconfigJson, enum_1.checkFileExistsAndCreateType.FILE); // 复制项目文件 (0, file_handle_1.copyFolder)(currentPath, rootPath); - // 创建小程序项目project.config.json - (0, file_handle_1.checkFileExistsAndCreate)(projectConfigPathWithWeChatMp, projectConfigWithWeChatMp, enum_1.checkFileExistsAndCreateType.FILE); - // 创建小程序项目app.json - (0, file_handle_1.checkFileExistsAndCreate)(appJsonPathWithWeChatMp, appJsonWithWeChatMp, enum_1.checkFileExistsAndCreateType.FILE); - // 创建小程序项目oak.config.json - (0, file_handle_1.checkFileExistsAndCreate)(oakConfigPathWithWeChatMp, oakConfigWithWeChatMp, enum_1.checkFileExistsAndCreateType.FILE); + await createWechatMpBoilplate(weChatMpRootPath, isDev); if (!shelljs_1.default.which('npm')) { (0, tip_style_1.Warn)((0, tip_style_1.warn)('Sorry, this script requires npm! Please install npm!')); shelljs_1.default.exit(1); @@ -144,4 +150,31 @@ async function create(dirName, env) { (0, tip_style_1.Error)((0, tip_style_1.error)(err)); } } -exports.default = create; +exports.create = create; +async function update(dirName, subDirName, cmd) { + const isDev = cmd.dev ? true : false; + try { + // 需要拷贝的路径 + const destPath = (0, path_1.join)(process.cwd(), dirName, subDirName); + const templatePath = (0, path_1.join)(__dirname, '..', 'template'); + //检查项目名是否存在 + checkProjectName(dirName, true); + if (subDirName === 'src') { + const fromPath = (0, path_1.join)(templatePath, subDirName); + (0, file_handle_1.copyFolder)(fromPath, destPath, true); + } + else if (subDirName.startsWith('wechatMp')) { + const fromPath = (0, path_1.join)(templatePath, 'wechatMp'); + (0, file_handle_1.copyFolder)(fromPath, destPath, true); + await createWechatMpBoilplate(destPath, isDev, true); + } + else { + throw new global.Error(`Cannot recoganize ${(0, tip_style_1.success)(`"${subDirName}"`)} for update.\n Please choose src/wechatMp%.`); + } + (0, tip_style_1.Success)(`${(0, tip_style_1.success)(`Successfully update directory ${(0, tip_style_1.primary)(subDirName)} for project ${(0, tip_style_1.primary)(dirName)}}`)}`); + } + catch (err) { + console.error((0, tip_style_1.error)(err.message)); + } +} +exports.update = update; diff --git a/lib/file-handle.d.ts b/lib/file-handle.d.ts index 733ec77..0413e16 100644 --- a/lib/file-handle.d.ts +++ b/lib/file-handle.d.ts @@ -45,7 +45,7 @@ export declare function readFile(path: string | PathLike, options?: { * @param {PathLike} currentDir * @param {PathLike} targetDir */ -export declare function copyFolder(currentDir: PathLike, targetDir: PathLike): void; +export declare function copyFolder(currentDir: PathLike, targetDir: PathLike, overwrite?: boolean): void; /** * @name 检测文件/文件夹是否存在 * @export @@ -60,4 +60,4 @@ export declare function checkFileExists(path: PathLike | string): boolean; * @param {*} [data] * @param {checkFileExistsAndCreateType} [type=checkFileExistsAndCreateType.DIRECTORY] */ -export declare function checkFileExistsAndCreate(path: PathLike | string, data?: any, type?: checkFileExistsAndCreateType): void; +export declare function checkFileExistsAndCreate(path: PathLike | string, data?: any, type?: checkFileExistsAndCreateType, overwrite?: boolean): void; diff --git a/lib/file-handle.js b/lib/file-handle.js index b180e0b..b38eecc 100644 --- a/lib/file-handle.js +++ b/lib/file-handle.js @@ -126,7 +126,7 @@ exports.readFile = readFile; * @param {PathLike} currentDir * @param {PathLike} targetDir */ -function copyFolder(currentDir, targetDir) { +function copyFolder(currentDir, targetDir, overwrite) { function handleFolder(currentDir, targetDir) { const files = (0, fs_1.readdirSync)(currentDir, { withFileTypes: true @@ -138,7 +138,13 @@ function copyFolder(currentDir, targetDir) { // 判断文件是否存在 const readCurrentFile = (0, fs_1.existsSync)(copyCurrentFileInfo); const readTargetFile = (0, fs_1.existsSync)(copyTargetFileInfo); - if (readCurrentFile && !readTargetFile) { + if (!readCurrentFile) { + throw new global.Error(`操作失败,待拷贝的源路径${copyCurrentFileInfo}不存在`); + } + else if (file.isFile() && readTargetFile && !overwrite) { + throw new global.Error(`操作失败,待拷贝的目标文件${copyTargetFileInfo}已经存在`); + } + else { // 判断是否为文件,如果为文件则复制,文件夹则递归 if (file.isFile()) { const readStream = (0, fs_1.createReadStream)(copyCurrentFileInfo); @@ -148,16 +154,14 @@ function copyFolder(currentDir, targetDir) { else { try { (0, fs_1.accessSync)((0, path_1.join)(copyTargetFileInfo, '..'), fs_1.constants.W_OK); - copyFolder(copyCurrentFileInfo, copyTargetFileInfo); + copyFolder(copyCurrentFileInfo, copyTargetFileInfo, overwrite); } catch (error) { (0, tip_style_1.Warn)('权限不足' + error); + throw error; } } } - else { - (0, tip_style_1.Error)((0, tip_style_1.error)('操作失败,target文件夹已存在或current文件夹不存在')); - } } } if ((0, fs_1.existsSync)(currentDir)) { @@ -167,7 +171,7 @@ function copyFolder(currentDir, targetDir) { handleFolder(currentDir, targetDir); } else { - (0, tip_style_1.Warn)((0, tip_style_1.warn)('需要copy的文件夹不存在:' + currentDir)); + throw new global.Error('需要copy的文件夹不存在:' + currentDir); } } exports.copyFolder = copyFolder; @@ -188,8 +192,8 @@ exports.checkFileExists = checkFileExists; * @param {*} [data] * @param {checkFileExistsAndCreateType} [type=checkFileExistsAndCreateType.DIRECTORY] */ -function checkFileExistsAndCreate(path, data, type = enum_1.checkFileExistsAndCreateType.DIRECTORY) { - if (!checkFileExists(path)) { +function checkFileExistsAndCreate(path, data, type = enum_1.checkFileExistsAndCreateType.DIRECTORY, overwrite) { + if (!checkFileExists(path) || overwrite) { switch (type) { case enum_1.checkFileExistsAndCreateType.DIRECTORY: (0, fs_1.mkdirSync)(path); @@ -202,5 +206,8 @@ function checkFileExistsAndCreate(path, data, type = enum_1.checkFileExistsAndCr break; } } + else { + throw new global.Error(`${path} already exists!`); + } } exports.checkFileExistsAndCreate = checkFileExistsAndCreate; diff --git a/lib/index.js b/lib/index.js index 661cd8f..284e499 100755 --- a/lib/index.js +++ b/lib/index.js @@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = __importDefault(require("commander")); -const create_1 = __importDefault(require("./create")); +const create_1 = require("./create"); const build_1 = __importDefault(require("./build")); const make_1 = __importDefault(require("./make")); const config_1 = require("./config"); @@ -56,11 +56,17 @@ commander_1.default .description('build we chat mp of build on demand') .action(build_1.default); commander_1.default - .command('create [env]') + .command('create ') .usage('') - // .option('-e, --env ', 'A env') + .option('-d, --dev', 'dev') .description(`create a new project powered by ${config_1.CLI_NAME}`) - .action(create_1.default); + .action(create_1.create); +commander_1.default + .command('update [subDirName]') + .usage('') + .option('-d, --dev', 'dev') + .description(`update project's template powered by ${config_1.CLI_NAME}`) + .action(create_1.update); // output help information on unknown commands commander_1.default.arguments('').action((cmd) => { commander_1.default.outputHelp(); diff --git a/src/create.ts b/src/create.ts index 373a6b2..8b3c4aa 100644 --- a/src/create.ts +++ b/src/create.ts @@ -57,24 +57,12 @@ function checkProjectName(dirName: string, exists?: true) { const rootPath = process.cwd() + '/' + dirName; const isExists = checkFileExists(rootPath); if (isExists && !exists) { - console.error( - error( - `Cannot create a project named ${success( - `"${dirName}"` - )} because a path with the same name exists.\n` - ) + error('Please choose a different project name.') - ); - process.exit(-1); + throw new global.Error(`Cannot create a project named ${success( + `"${dirName}"` + )} because a path with the same name exists.\nPlease choose a different project name.`); } else if (!isExists && exists) { - console.error( - error( - `${success( - `"${dirName}"` - )} is not a valid project dir.\n` - ) + error('Please choose a different project name.') - ); - process.exit(-1); + throw new global.Error(`${success(dirName)} is not a valid project dir.\nPlease choose a different project name.`) } } @@ -101,9 +89,9 @@ async function getMiniVersion() { } -async function createWechatMpBoilplate(dir: string, isDev: boolean) { +async function createWechatMpBoilplate(dir: string, isDev: boolean, isUpdate?: boolean) { // 获取微信小程序稳定基础版本库 - const miniVersion = await getMiniVersion(); + const miniVersion = await getMiniVersion(); // 获取小程序项目app.json内容 const appJsonWithWeChatMp = appJsonContentWithWeChatMp(isDev); // 获取小程序项目project.config.json内容 @@ -115,7 +103,6 @@ async function createWechatMpBoilplate(dir: string, isDev: boolean) { // 获取小程序项目oak.config.json内容 const oakConfigWithWeChatMp = oakConfigContentWithWeChatMp(); - const appJsonPathWithWeChatMp = join(dir, 'src', 'app.json'); // 小程序项目project.config.json路径 @@ -126,23 +113,26 @@ async function createWechatMpBoilplate(dir: string, isDev: boolean) { checkFileExistsAndCreate( projectConfigPathWithWeChatMp, projectConfigWithWeChatMp, - checkFileExistsAndCreateType.FILE + checkFileExistsAndCreateType.FILE, + isUpdate ); // 创建小程序项目app.json checkFileExistsAndCreate( appJsonPathWithWeChatMp, appJsonWithWeChatMp, - checkFileExistsAndCreateType.FILE + checkFileExistsAndCreateType.FILE, + isUpdate ); // 创建小程序项目oak.config.json checkFileExistsAndCreate( oakConfigPathWithWeChatMp, oakConfigWithWeChatMp, - checkFileExistsAndCreateType.FILE + checkFileExistsAndCreateType.FILE, + isUpdate ); } -export async function create(dirName: string, env: string) { +export async function create(dirName: string, cmd: any) { const nameOption = { type: 'input', name: 'name', @@ -150,8 +140,7 @@ export async function create(dirName: string, env: string) { default: dirName, }; prompt.unshift(nameOption); - - const isDev = env === 'dev' || env === 'development'; + const isDev = cmd.dev ? true : false; const { name, version, description }: PromptInput = await inquirer.prompt( prompt @@ -235,24 +224,41 @@ export async function create(dirName: string, env: string) { } -export async function update(dirName: string, subDirName: string, env: string) { - console.log(dirName, subDirName, env); - /* const isDev = env === 'dev' || env === 'development'; +export async function update(dirName: string, subDirName: string, cmd: any) { + const isDev = cmd.dev ? true : false; - // 需要拷贝的路径 - const destPath = join(process.cwd(), dirName, subDirName); + try { + // 需要拷贝的路径 + const destPath = join(process.cwd(), dirName, subDirName); - const templatePath = join(__dirname, '..', 'template'); - //检查项目名是否存在 - checkProjectName(dirName, true); + const templatePath = join(__dirname, '..', 'template'); + //检查项目名是否存在 + checkProjectName(dirName, true); - if (subDirName === 'src') { - const fromPath = join(templatePath, subDirName); - copyFolder(fromPath, destPath); + if (subDirName === 'src') { + const fromPath = join(templatePath, subDirName); + copyFolder(fromPath, destPath, true); + } + else if (subDirName.startsWith('wechatMp')) { + const fromPath = join(templatePath, 'wechatMp'); + copyFolder(fromPath, destPath, true); + + await createWechatMpBoilplate(destPath, isDev, true); + } + else { + throw new global.Error(`Cannot recoganize ${success( + `"${subDirName}"` + )} for update.\n Please choose src/wechatMp%.`); + } + + Success( + `${success( + `Successfully update directory ${primary(subDirName)} for project ${primary(dirName)}}` + )}` + ); + } + catch (err) { + console.error(error((err as Error).message)); } - else if (subDirName.startsWith('wechatMp')) { - const fromPath = join(templatePath, 'wechatMp'); - copyFolder(fromPath, destPath); - } */ } \ No newline at end of file diff --git a/src/file-handle.ts b/src/file-handle.ts index c930d08..f956172 100644 --- a/src/file-handle.ts +++ b/src/file-handle.ts @@ -119,7 +119,7 @@ export function readFile( * @param {PathLike} currentDir * @param {PathLike} targetDir */ -export function copyFolder(currentDir: PathLike, targetDir: PathLike) { +export function copyFolder(currentDir: PathLike, targetDir: PathLike, overwrite?: boolean) { function handleFolder(currentDir: PathLike, targetDir: PathLike) { const files = readdirSync(currentDir, { @@ -127,29 +127,34 @@ export function copyFolder(currentDir: PathLike, targetDir: PathLike) { }) for (let file of files) { // 拼接文件绝对路径 - const copyCurrentFileInfo = currentDir + '/' + file.name - const copyTargetFileInfo = targetDir + '/' + file.name + const copyCurrentFileInfo = currentDir + '/' + file.name; + const copyTargetFileInfo = targetDir + '/' + file.name; // 判断文件是否存在 - const readCurrentFile = existsSync(copyCurrentFileInfo) - const readTargetFile = existsSync(copyTargetFileInfo) - if (readCurrentFile && !readTargetFile) { + const readCurrentFile = existsSync(copyCurrentFileInfo); + const readTargetFile = existsSync(copyTargetFileInfo); + + if (!readCurrentFile) { + throw new global.Error(`操作失败,待拷贝的源路径${copyCurrentFileInfo}不存在`); + } + else if (file.isFile() && readTargetFile && !overwrite) { + throw new global.Error(`操作失败,待拷贝的目标文件${copyTargetFileInfo}已经存在`); + } + else { // 判断是否为文件,如果为文件则复制,文件夹则递归 if (file.isFile()) { - const readStream = createReadStream(copyCurrentFileInfo) - const writeStream = createWriteStream(copyTargetFileInfo) - readStream.pipe(writeStream) + const readStream = createReadStream(copyCurrentFileInfo); + const writeStream = createWriteStream(copyTargetFileInfo); + readStream.pipe(writeStream); } else { try { - accessSync(join(copyTargetFileInfo, '..'), constants.W_OK) - copyFolder(copyCurrentFileInfo, copyTargetFileInfo) + accessSync(join(copyTargetFileInfo, '..'), constants.W_OK); + copyFolder(copyCurrentFileInfo, copyTargetFileInfo, overwrite); } catch (error) { - Warn('权限不足' + error) + Warn('权限不足' + error); + throw error; } } - } else { - Error(error('操作失败,target文件夹已存在或current文件夹不存在')) } - } } @@ -159,7 +164,7 @@ export function copyFolder(currentDir: PathLike, targetDir: PathLike) { } handleFolder(currentDir, targetDir) } else { - Warn(warn('需要copy的文件夹不存在:' + currentDir)) + throw new global.Error('需要copy的文件夹不存在:' + currentDir); } } @@ -180,8 +185,8 @@ export function checkFileExists(path: PathLike | string) { * @param {*} [data] * @param {checkFileExistsAndCreateType} [type=checkFileExistsAndCreateType.DIRECTORY] */ -export function checkFileExistsAndCreate(path: PathLike | string, data?: any, type: checkFileExistsAndCreateType = checkFileExistsAndCreateType.DIRECTORY): void { - if (!checkFileExists(path)) { +export function checkFileExistsAndCreate(path: PathLike | string, data?: any, type: checkFileExistsAndCreateType = checkFileExistsAndCreateType.DIRECTORY, overwrite?: boolean): void { + if (!checkFileExists(path) || overwrite) { switch (type) { case checkFileExistsAndCreateType.DIRECTORY: mkdirSync(path) @@ -194,4 +199,7 @@ export function checkFileExistsAndCreate(path: PathLike | string, data?: any, ty break; } } + else { + throw new global.Error(`${path} already exists!`); + } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index af4d2d9..ea80c42 100644 --- a/src/index.ts +++ b/src/index.ts @@ -58,14 +58,15 @@ program .description('build we chat mp of build on demand') .action(build); program - .command('create [env]') + .command('create ') .usage('') - // .option('-e, --env ', 'A env') + .option('-d, --dev', 'dev') .description(`create a new project powered by ${CLI_NAME}`) .action(create); program .command('update [subDirName]') .usage('') + .option('-d, --dev', 'dev') .description(`update project's template powered by ${CLI_NAME}`) .action(update); // output help information on unknown commands