add cli
This commit is contained in:
107
packages/dooringx-cli/src/createPlugin.ts
Normal file
107
packages/dooringx-cli/src/createPlugin.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2022-01-13 16:16:53
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2022-01-14 09:16:58
|
||||
* @FilePath: \dooringx-cli\src\createPlugin.ts
|
||||
*/
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
import inquirer from 'inquirer';
|
||||
import path from 'path';
|
||||
import modifyTemplate from './modifyTemplate';
|
||||
import { deleteFolder, doAction } from './utils';
|
||||
|
||||
export async function createPlugin(name: string, option: string) {
|
||||
createApp(name, option);
|
||||
}
|
||||
async function createApp(projectName: string, option: string) {
|
||||
let root = path.resolve(projectName);
|
||||
|
||||
const isExist = fs.existsSync(root);
|
||||
|
||||
if (isExist) {
|
||||
const choices = ['y', 'n'];
|
||||
let sign = 'y';
|
||||
const result = await inquirer.prompt({
|
||||
name: 'sign',
|
||||
type: 'list',
|
||||
message: `${projectName} already exists , continue ?`,
|
||||
choices,
|
||||
});
|
||||
sign = result.sign;
|
||||
if (sign === 'n') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fs.ensureDirSync(projectName); // 没有则创建文件夹
|
||||
console.log(`create a new app in ${chalk.green(root)}`);
|
||||
const packageJson = {
|
||||
name: projectName,
|
||||
version: '0.0.1',
|
||||
private: true,
|
||||
};
|
||||
// 写入package.json
|
||||
fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(packageJson, null, 2));
|
||||
process.chdir(root);
|
||||
// 复制项目模板,安装项目依赖等
|
||||
await run(root, projectName, option);
|
||||
}
|
||||
|
||||
async function run(root: string, projectName: string, _option: string) {
|
||||
const template = 'dooringx-plugin-template';
|
||||
const templateName = template;
|
||||
const allDependencies = [templateName];
|
||||
console.log('Installing packages. This might take a couple of minutes');
|
||||
console.log(`Installing ${chalk.cyan(templateName)} ...`);
|
||||
try {
|
||||
await doAction(root, allDependencies);
|
||||
} catch (e) {
|
||||
console.log(`Installing ${chalk.red(templateName)} failed ...`, e);
|
||||
}
|
||||
console.log(`Installing ${chalk.cyan(templateName)} succeed!`);
|
||||
|
||||
const templatePath = path.dirname(
|
||||
require.resolve(`${templateName}/package.json`, { paths: [root] })
|
||||
);
|
||||
// 复制文件到项目目录
|
||||
|
||||
const tempDir = path.join(root, 'temp');
|
||||
const templateDir = path.join(templatePath, `template`);
|
||||
|
||||
if (fs.existsSync(templatePath)) {
|
||||
await modifyTemplate(templateDir, 'temp', {
|
||||
projectName: projectName,
|
||||
basicProject: template,
|
||||
});
|
||||
|
||||
fs.copySync(tempDir, root);
|
||||
deleteFolder(tempDir);
|
||||
} else {
|
||||
console.error(`Could not locate supplied template: ${chalk.green(templatePath)}`);
|
||||
return;
|
||||
}
|
||||
let tempPkg = fs.readFileSync(root + '/template.json').toString();
|
||||
let pkg = fs.readFileSync(root + '/package.json').toString();
|
||||
|
||||
const tempPkgJson = JSON.parse(tempPkg);
|
||||
let pkgJson = JSON.parse(pkg);
|
||||
pkgJson = { ...pkgJson };
|
||||
pkgJson.main = tempPkgJson?.main;
|
||||
pkgJson.scripts = tempPkgJson?.scripts;
|
||||
pkgJson.dependencies = {
|
||||
...tempPkgJson?.dependencies,
|
||||
};
|
||||
pkgJson.devDependencies = {
|
||||
...tempPkgJson?.devDependencies,
|
||||
};
|
||||
fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(pkgJson, null, 2));
|
||||
fs.unlinkSync(path.join(root, 'template.json'));
|
||||
fs.unlinkSync(path.join(root, 'package-lock.json'));
|
||||
console.log(`🎉 Successfully created project ${projectName}.`);
|
||||
console.log('👉 Get started with the following commands:');
|
||||
console.log(`${chalk.cyan(`cd ${projectName}`)}`);
|
||||
console.log(`${chalk.cyan('npm install')}`);
|
||||
process.exit(0);
|
||||
}
|
28
packages/dooringx-cli/src/index.ts
Normal file
28
packages/dooringx-cli/src/index.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-06-10 20:45:06
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2022-01-13 17:07:39
|
||||
* @FilePath: \dooringx-cli\src\index.ts
|
||||
*/
|
||||
import { Command } from 'commander';
|
||||
import { createPlugin } from './createPlugin';
|
||||
const packageJson = require('../package.json');
|
||||
let program = new Command();
|
||||
|
||||
program
|
||||
.command('create <project-name>')
|
||||
.description('create project')
|
||||
.alias('c')
|
||||
.action(() => {
|
||||
console.log('in progress');
|
||||
});
|
||||
program
|
||||
.command('plugin <project-name>')
|
||||
.description('create plugin project')
|
||||
.alias('p')
|
||||
.action((name, options) => {
|
||||
createPlugin(name, options);
|
||||
});
|
||||
|
||||
program.version(packageJson.version).parse(process.argv);
|
63
packages/dooringx-cli/src/modifyTemplate.ts
Normal file
63
packages/dooringx-cli/src/modifyTemplate.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import MetalSmith from 'metalsmith';
|
||||
import { ejs } from 'consolidate';
|
||||
import { promisify } from 'util';
|
||||
import * as path from 'path';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} fromPath 源路径
|
||||
* @param {*} toPath 目标路径
|
||||
*/
|
||||
async function handleTemplate(fromPath: string, toPath: string, config: any) {
|
||||
await new Promise((resovle, reject) => {
|
||||
MetalSmith(__dirname)
|
||||
.source(fromPath)
|
||||
.destination(path.join(path.resolve(), toPath))
|
||||
.use(async (_files, metal, done) => {
|
||||
let result = {
|
||||
license: 'MIT',
|
||||
version: '0.0.1',
|
||||
...config,
|
||||
};
|
||||
const data = metal.metadata();
|
||||
Object.assign(data, result);
|
||||
//@ts-ignore
|
||||
done();
|
||||
})
|
||||
.use((files, metal, done) => {
|
||||
Object.keys(files).forEach(async (file) => {
|
||||
let content = files[file].contents.toString();
|
||||
if (
|
||||
file.includes('.js') ||
|
||||
file.includes('.json') ||
|
||||
file.includes('.txt') ||
|
||||
file.includes('.md')
|
||||
) {
|
||||
if (content.includes('<%')) {
|
||||
let { render } = ejs;
|
||||
//@ts-ignore
|
||||
render = promisify(render);
|
||||
try {
|
||||
content = await render(content, metal.metadata());
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
files[file].contents = Buffer.from(content);
|
||||
}
|
||||
}
|
||||
});
|
||||
//@ts-ignore
|
||||
done();
|
||||
})
|
||||
.build((err) => {
|
||||
if (!err) {
|
||||
resovle(true);
|
||||
} else {
|
||||
console.log(err);
|
||||
reject(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default handleTemplate;
|
84
packages/dooringx-cli/src/utils.ts
Normal file
84
packages/dooringx-cli/src/utils.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-06-10 20:45:06
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2022-01-14 09:15:23
|
||||
* @FilePath: \dooringx-cli\src\utils.ts
|
||||
*/
|
||||
import spawn from 'cross-spawn';
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
/**
|
||||
* 使用npm安装或卸载项目依赖
|
||||
* @param {*} root 项目路径
|
||||
* @param {*} allDependencies 项目依赖
|
||||
* @param {*} action npm install 或 npm uninstall
|
||||
*/
|
||||
export async function doAction(
|
||||
root: string,
|
||||
allDependencies: string | string[],
|
||||
action = 'install'
|
||||
) {
|
||||
typeof allDependencies === 'string' ? (allDependencies = [allDependencies]) : null;
|
||||
return new Promise((resolve) => {
|
||||
const command = 'npm';
|
||||
const args = [
|
||||
action,
|
||||
'--save',
|
||||
'--save-exact',
|
||||
'--loglevel',
|
||||
'error',
|
||||
...allDependencies,
|
||||
'--cwd',
|
||||
root,
|
||||
];
|
||||
const child = spawn(command, args, { stdio: 'inherit' });
|
||||
child.on('close', resolve);
|
||||
});
|
||||
}
|
||||
|
||||
export async function buildAction(
|
||||
root: string,
|
||||
script: string,
|
||||
cwd: string,
|
||||
isLerna: boolean,
|
||||
name: string
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
if (isLerna) {
|
||||
const command = `lerna exec npm run `;
|
||||
const args = [script, `--scope=${name}`, '--loglevel', 'error'];
|
||||
const child = spawn(command, args, { stdio: 'inherit', cwd: cwd });
|
||||
child.on('close', resolve);
|
||||
} else {
|
||||
const command = 'npm run ';
|
||||
const args = [script, '--loglevel', 'error'];
|
||||
const child = spawn(command, args, { stdio: 'inherit', cwd: root });
|
||||
child.on('close', resolve);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function copyFolder(workPath: string, targetPath: string) {
|
||||
return fs.copy(workPath, targetPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件、文件夹
|
||||
* @param {*} path 要删除资源的路径
|
||||
*/
|
||||
export function deleteFolder(path: string) {
|
||||
let files = [];
|
||||
if (fs.existsSync(path)) {
|
||||
if (!fs.statSync(path).isDirectory()) {
|
||||
fs.unlinkSync(path);
|
||||
} else {
|
||||
files = fs.readdirSync(path);
|
||||
files.forEach(function (file) {
|
||||
let curPath = path + '/' + file;
|
||||
deleteFolder(curPath);
|
||||
});
|
||||
fs.rmdirSync(path);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user