@gdjiami/cli
Version:
CLI for build front end project.
257 lines (256 loc) • 11.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
/**
* create project
*/
var path_1 = tslib_1.__importDefault(require("path"));
var chalk_1 = tslib_1.__importDefault(require("chalk"));
var fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
var ignore_1 = tslib_1.__importDefault(require("ignore"));
var validate_npm_package_name_1 = tslib_1.__importDefault(require("validate-npm-package-name"));
var semver_1 = tslib_1.__importDefault(require("semver"));
var child_process_1 = require("child_process");
var pickBy_1 = tslib_1.__importDefault(require("lodash/pickBy"));
var utils_1 = require("../../utils");
var getTemplate_1 = tslib_1.__importDefault(require("./getTemplate"));
var genGitignore_1 = tslib_1.__importDefault(require("./genGitignore"));
var genGlobalDeclaration_1 = tslib_1.__importDefault(require("./genGlobalDeclaration"));
var genVscodeSettings_1 = tslib_1.__importDefault(require("./genVscodeSettings"));
var genESlintConfig_1 = tslib_1.__importDefault(require("./genESlintConfig"));
var genTsConfig_1 = tslib_1.__importDefault(require("./genTsConfig"));
var genPrettier_1 = tslib_1.__importDefault(require("./genPrettier"));
var useYarn = utils_1.shouldUseYarn();
var builinDevDependencies = [
// format
'prettier',
'pretty-quick',
'husky',
'@types/webpack-env',
'@types/react-hot-loader',
];
/**
* 检查是否是合法的npm包名
* @param name
*/
function validatePackageName(name) {
var res = validate_npm_package_name_1.default(name);
if (!res.validForNewPackages) {
utils_1.message.error("Could not create a project called " + chalk_1.default.red(name) + " because of npm naming restrictions:");
printValidationResults(res.errors);
printValidationResults(res.warnings);
process.exit(1);
}
}
function printValidationResults(results) {
if (typeof results !== 'undefined') {
results.forEach(function (error) {
console.error(chalk_1.default.red(" * " + error));
});
}
}
function ensureAppPath(appPath) {
if (fs_extra_1.default.existsSync(appPath)) {
var name = path_1.default.basename(appPath);
utils_1.message.error("Could not create a project called " + name + ", directory existed.");
process.exit(1);
}
fs_extra_1.default.ensureDirSync(appPath);
}
/**
* clone files from templatePath to appPath,
* default it will ignore `node_modules`, `dist` and `yarn.*`, `.git` etc
* Template developer also define `.template-ignore` to add ignore rules
* .gitignore will automatic recognized by npm
* @param templatePath
* @param appPath
*/
function cloneTemplate(templatePath, appPath) {
var ig = ignore_1.default();
var defaultIgnore = ['node_modules', 'dist', 'yarn.*', '.git', '.template-ignore', '.cache-loader'];
ig.add(defaultIgnore);
var templateIgnorePath = path_1.default.join(templatePath, '.template-ignore');
if (fs_extra_1.default.existsSync(templateIgnorePath)) {
ig.add(fs_extra_1.default.readFileSync(templateIgnorePath).toString());
}
fs_extra_1.default.copySync(templatePath, appPath, {
overwrite: false,
errorOnExist: false,
dereference: true,
filter: function (src) {
var relativePath = path_1.default.relative(templatePath, src);
if (relativePath === '') {
return true;
}
return !ig.ignores(relativePath);
},
});
}
function transformDependencies(org) {
return Object.keys(org).map(function (key) {
if (org[key] === '*') {
return key;
}
return key + "@" + org[key];
});
}
function initialPackageJson(appPath, templatePath, ownPath, argv) {
var name = argv.name, binName = argv.binName, cliName = argv.cliName, cliVersion = argv.cliVersion;
var reservedProperties = {
name: name,
version: '0.1.0',
private: true,
dependencies: {},
devDependencies: {},
scripts: {
start: binName + " start",
build: binName + " build",
serve: binName + " serve",
analyze: binName + " analyze",
},
// prettier format
husky: {
hooks: {
'pre-commit': 'pretty-quick --staged',
},
},
};
var optionalProperties = {
jm: {
// proxy config, can use template variable in .env.*
proxy: {},
// for antd, antd-mobile
importPlugin: [],
},
browserslist: 'last 2 versions',
optionalDependencies: {},
};
var pacakgeJson = tslib_1.__assign(tslib_1.__assign({}, reservedProperties), optionalProperties);
var templatePackageJson = path_1.default.join(templatePath, 'package.json');
if (fs_extra_1.default.existsSync(templatePackageJson)) {
var pkg = require(templatePackageJson);
if (pkg.dependencies) {
pacakgeJson.dependencies = tslib_1.__assign(tslib_1.__assign({}, pacakgeJson.dependencies), pkg.dependencies);
}
if (pkg.devDependencies) {
pacakgeJson.devDependencies = tslib_1.__assign(tslib_1.__assign({}, pacakgeJson.devDependencies), pkg.devDependencies);
}
if (pkg.scripts) {
pacakgeJson.scripts = tslib_1.__assign(tslib_1.__assign({}, pacakgeJson.scripts), pkg.scripts);
}
// 合并package.json
var includeFields_1 = pkg.includeFields || [];
var pickedPkg = pickBy_1.default(pkg, function (value, key) { return key in optionalProperties || key.startsWith('jm') || includeFields_1.indexOf(key) !== -1; });
pacakgeJson = tslib_1.__assign(tslib_1.__assign({}, pacakgeJson), pickedPkg);
}
// install cli commands
var packageToInstall = cliName;
cliVersion = cliVersion || pacakgeJson.devDependencies[cliName];
delete pacakgeJson.devDependencies[cliName];
if (cliVersion) {
var validSemver = semver_1.default.valid(cliVersion);
if (validSemver) {
packageToInstall += "@" + validSemver;
}
}
cloneTemplate(templatePath, appPath);
utils_1.writeJSON(path_1.default.join(appPath, 'package.json'), pacakgeJson);
utils_1.message.info("Installing pacakges. This might take a couple of minutes.");
var devdependencies = builinDevDependencies
.filter(function (dep) {
return !(dep in pacakgeJson.dependencies) && !(dep in pacakgeJson.devDependencies);
})
.concat(transformDependencies(pacakgeJson.devDependencies));
var dependencies = transformDependencies(pacakgeJson.dependencies);
devdependencies.push(packageToInstall);
var dependenciesInstallCommand;
var devDependenciesInstallCommand;
if (useYarn) {
var command = 'yarnpkg';
dependenciesInstallCommand = command + " add " + dependencies.join(' ') + " -s";
devDependenciesInstallCommand = command + " add " + devdependencies.join(' ') + " --dev -s";
}
else {
var command = 'npm';
dependenciesInstallCommand = command + " install " + dependencies.join(' ') + " --save";
devDependenciesInstallCommand = command + " install " + devdependencies.join(' ') + " --save-dev";
}
utils_1.message.info(chalk_1.default.cyan("Installing dependencies..."));
child_process_1.execSync(dependenciesInstallCommand, { stdio: 'inherit' });
utils_1.message.info(chalk_1.default.cyan("Installing devdependencies..."));
child_process_1.execSync(devDependenciesInstallCommand, { stdio: 'inherit' });
}
function tryInitialGit(appPath) {
try {
child_process_1.execSync('git init', { stdio: 'ignore' });
return true;
}
catch (e) {
return false;
}
}
function firstCommit() {
try {
child_process_1.execSync('git add -A', { stdio: 'ignore' });
child_process_1.execSync('git commit -m "Initial commit from jm-cli"', {
stdio: 'ignore',
});
}
catch (_a) {
// ignore
}
}
/**
* welcome infomation
*/
function welcome(args) {
var cmd = useYarn ? 'yarn' : 'npm';
console.log("\n\u2728 Success! Created " + chalk_1.default.blue(args.name) + " at " + chalk_1.default.cyan(args.appPath) + "\nInside that directory, you can run several commands:\n\n " + chalk_1.default.green(cmd + " start") + " " + chalk_1.default.gray("# Starts the development server.") + "\n " + chalk_1.default.green(cmd + " build") + " " + chalk_1.default.gray("# Bundles the app into static files for production.") + "\n " + chalk_1.default.green(cmd + " serve") + " " + chalk_1.default.gray("# Serve production bundle in 'dist'") + "\n " + chalk_1.default.green(cmd + " analyze") + " " + chalk_1.default.gray("# Analyze webpack bundle for production") + "\n\nTyping " + chalk_1.default.green("cd " + args.name) + " to start code happily.\n ");
}
/**
* @param cwd 当前工作目录
* @param originalDirname cli项目根目录
* @param argv 命令参数
*/
exports.default = (function (cwd, originalDirname, argv) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var name, version, template, templatePath, appPath, gitInitialed, ownPackageJson, generators;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
utils_1.message.info("Creating a new React Project in " + chalk_1.default.green(cwd) + "\n");
name = argv.name, version = argv.version, template = argv.template;
validatePackageName(name);
return [4 /*yield*/, getTemplate_1.default(!!argv.force, originalDirname, cwd, template)];
case 1:
templatePath = _a.sent();
if (!fs_extra_1.default.existsSync(templatePath)) {
utils_1.message.error("Template path " + templatePath + " not existed.");
process.exit(1);
}
appPath = path_1.default.join(cwd, name);
ensureAppPath(appPath);
process.chdir(appPath);
gitInitialed = tryInitialGit(appPath);
if (gitInitialed) {
utils_1.message.info('Initialized a git repository.');
}
ownPackageJson = require(path_1.default.join(originalDirname, 'package.json'));
initialPackageJson(appPath, templatePath, originalDirname, {
name: name,
cliName: ownPackageJson.name,
cliVersion: version,
binName: Object.keys(ownPackageJson.bin)[0],
});
generators = [genTsConfig_1.default, genESlintConfig_1.default, genVscodeSettings_1.default, genGlobalDeclaration_1.default, genGitignore_1.default, genPrettier_1.default];
generators.forEach(function (g) { return g(appPath, originalDirname, ownPackageJson); });
if (gitInitialed) {
firstCommit();
}
welcome({
name: name,
appPath: appPath,
});
return [2 /*return*/];
}
});
}); });