From b3cbb72d085f02e24658e0d39c6cc43952509132 Mon Sep 17 00:00:00 2001 From: streakingman Date: Thu, 24 Feb 2022 14:38:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20set-project=20=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- actions/set-project.js | 80 ++++++++++++++++++++++++++++++++++++++ index.js | 49 ++++++++++++----------- package.json | 2 + templates/commitlint.ejs | 9 +++++ templates/editor.ejs | 15 +++++++ templates/eslint.ejs | 19 +++++++++ templates/eslintignore.ejs | 6 +++ templates/lintstaged.ejs | 14 +++++++ templates/prettier.ejs | 12 ++++++ utils/batch-install.js | 16 ++++++++ utils/file-generator.js | 40 +++++++++++++++++++ yarn.lock | 31 ++++++++++++++- 12 files changed, 270 insertions(+), 23 deletions(-) create mode 100644 actions/set-project.js create mode 100644 templates/commitlint.ejs create mode 100644 templates/editor.ejs create mode 100644 templates/eslint.ejs create mode 100644 templates/eslintignore.ejs create mode 100644 templates/lintstaged.ejs create mode 100644 templates/prettier.ejs create mode 100644 utils/batch-install.js create mode 100644 utils/file-generator.js diff --git a/actions/set-project.js b/actions/set-project.js new file mode 100644 index 0000000..5a8c632 --- /dev/null +++ b/actions/set-project.js @@ -0,0 +1,80 @@ +const { execSync } = require('child_process'); +const { batchInstall } = require('../utils/batch-install'); +const { fileGenerator } = require('../utils/file-generator'); +const inquirer = require('inquirer'); + +const setProject = async () => { + const { + hasEslintAndPrettier, + hasCommitlintAndLintstagedAndHusky, + hasStandardVersion, + } = await inquirer.prompt([ + { + type: 'confirm', + name: 'hasEslintAndPrettier', + message: '是否使用eslint+prettier', + default: true, + }, + { + type: 'confirm', + name: 'hasCommitlintAndLintstagedAndHusky', + message: '是否使用commitlint+lintstaged+husky?', + default: true, + }, + { + type: 'confirm', + name: 'hasStandardVersion', + message: '是否使用standard-version管理版本号?', + default: true, + }, + ]); + if (hasEslintAndPrettier) { + batchInstall( + [ + 'eslint', + 'prettier', + 'eslint-config-prettier', + 'eslint-plugin-prettier', + ], + { + dev: true, + } + ); + fileGenerator({ templateName: 'prettier' }); + fileGenerator({ templateName: 'eslint' }); + fileGenerator({ templateName: 'eslintignore' }); + } + if (hasCommitlintAndLintstagedAndHusky) { + batchInstall( + [ + '@commitlint/cli', + '@commitlint/config-conventional', + 'lint-staged', + 'husky', + ], + { dev: true } + ); + // husky安装与钩子配置 + execSync('npx husky install'); + execSync('npm set-script prepare "husky install"'); + execSync('npx husky add .husky/pre-commit "npx lint-staged"'); + execSync( + 'npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"' + ); + fileGenerator({ templateName: 'commitlint' }); + fileGenerator({ templateName: 'lintstaged' }); + } + if (hasStandardVersion) { + batchInstall(['standard-version'], { dev: true }); + execSync( + 'npm set-script release:first "standard-version -- --first-release"' + ); + execSync('npm set-script release "standard-version"'); + } + fileGenerator({ templateName: 'editor' }); + console.log('依赖安装完成,已生成基础配置'); +}; + +module.exports = { + setProject, +}; diff --git a/index.js b/index.js index 4e2d9de..b4a77e2 100644 --- a/index.js +++ b/index.js @@ -1,37 +1,42 @@ #!/usr/bin/env node -const { execSync } = require("child_process"); -const { checkGit } = require("./actions/check-git"); -const { setGit } = require("./actions/set-git"); -const { program } = require("commander"); -const fs = require("fs"); -const path = require("path"); +const { execSync } = require('child_process'); +const { checkGit } = require('./actions/check-git'); +const { setGit } = require('./actions/set-git'); +const { setProject } = require('./actions/set-project'); +const { program } = require('commander'); +const fs = require('fs'); +const path = require('path'); const { version } = JSON.parse( - fs.readFileSync(path.join(__dirname, "./package.json")).toString() + fs.readFileSync(path.join(__dirname, './package.json')).toString() ); -const CLINAME = "skm"; +const CLINAME = 'skm'; // 检查版本 -const latestVersion = execSync("npm view @tuya-fe/www-cli version"); -const [x1, y1, z1] = latestVersion.toString().trim().split("."); -const [x2, y2, z2] = version.split("."); +const latestVersion = execSync('npm view @tuya-fe/www-cli version'); +const [x1, y1, z1] = latestVersion.toString().trim().split('.'); +const [x2, y2, z2] = version.split('.'); if (!(x1 === x2 && y1 === y2 && z1 <= z2)) { - console.log(`发现新版本${CLINAME}@${version},请更新`); + console.log(`发现新版本${CLINAME}@${version},请更新`); } program - .version(`${CLINAME}@${version}`, "-v") - .helpOption("-h", "帮助信息") - .usage(" [options]") - .name(CLINAME); + .version(`${CLINAME}@${version}`, '-v') + .helpOption('-h', '帮助信息') + .usage(' [options]') + .name(CLINAME); program - .command("check-git") - .description("查看当前仓库git配置用户名和邮箱") - .action(checkGit); + .command('check-git') + .description('查看当前仓库git配置用户名和邮箱') + .action(checkGit); program - .command("set-git") - .description("配置当前仓库git配置用户名和邮箱") - .action(setGit); + .command('set-git') + .description('配置当前仓库git配置用户名和邮箱') + .action(setGit); +program + .command('set-project') + .description('安装lint和工程化依赖以及简单配置') + .action(setProject); program.showHelpAfterError(`${CLINAME} -h 查看帮助`); program.addHelpCommand(false); diff --git a/package.json b/package.json index ee4bfe8..7bbc412 100644 --- a/package.json +++ b/package.json @@ -33,9 +33,11 @@ "devDependencies": { "@commitlint/cli": "^16.2.1", "@commitlint/config-conventional": "^16.2.1", + "ejs": "^3.1.6", "eslint": "7", "eslint-config-prettier": "^8.4.0", "eslint-plugin-prettier": "^4.0.0", + "fs-extra": "^10.0.1", "husky": "^7.0.4", "lint-staged": "^12.3.4", "prettier": "^2.5.1", diff --git a/templates/commitlint.ejs b/templates/commitlint.ejs new file mode 100644 index 0000000..ae1ba59 --- /dev/null +++ b/templates/commitlint.ejs @@ -0,0 +1,9 @@ +/** + * commitlint config + * @ref http://commitlint.js.org/ + * @desc generated at <%- generatedAt %> by streakingman-cli@<%- version %> + */ + +module.exports = { + extends: ['@commitlint/config-conventional'], +}; diff --git a/templates/editor.ejs b/templates/editor.ejs new file mode 100644 index 0000000..6e0a93c --- /dev/null +++ b/templates/editor.ejs @@ -0,0 +1,15 @@ +# https://editorconfig.org/ +# generated at <%- generatedAt %> by streakingman-cli@<%- version %> +# 该配置文件是给webstorm使用的 +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/templates/eslint.ejs b/templates/eslint.ejs new file mode 100644 index 0000000..8825fb2 --- /dev/null +++ b/templates/eslint.ejs @@ -0,0 +1,19 @@ +/** +* eslint config +* @ref http://eslint.cn/ +* @desc generated at <%- generatedAt %> by streakingman-cli@<%- version %> +*/ + +module.exports = { + parserOptions: { + ecmaVersion: 11, + }, + env: { + es6: true, + }, + plugins: ['eslint-plugin-prettier'], + extends: ['plugin:prettier/recommended'], + rules: { + 'prettier/prettier': 'error', + }, +}; diff --git a/templates/eslintignore.ejs b/templates/eslintignore.ejs new file mode 100644 index 0000000..99049a2 --- /dev/null +++ b/templates/eslintignore.ejs @@ -0,0 +1,6 @@ +# generated at <%- generatedAt %> by streakingman-cli@<%- version %> + +!.eslintrc.js +!.prettierrc.js +!.commitlintrc.js +!.lintstagedrc.js diff --git a/templates/lintstaged.ejs b/templates/lintstaged.ejs new file mode 100644 index 0000000..0b2a760 --- /dev/null +++ b/templates/lintstaged.ejs @@ -0,0 +1,14 @@ +/** + * lint-staged config + * @ref https://www.npmjs.com/package/lint-staged + * @desc generated at <%- generatedAt %> by streakingman-cli@<%- version %> + */ + +module.exports = { + '*.{[tj]s,[tj]sx,[cm]js}': [ + 'eslint --fix' + ], + '*.json': [ + 'prettier --write' + ] +}; diff --git a/templates/prettier.ejs b/templates/prettier.ejs new file mode 100644 index 0000000..c6f631e --- /dev/null +++ b/templates/prettier.ejs @@ -0,0 +1,12 @@ +/** + * prettier config + * @ref https://prettier.io/ + * @desc generated at <%- generatedAt %> by streakingman-cli@<%- version %> + */ + +module.exports = { + tabWidth: 4, + singleQuote: true, + htmlWhitespaceSensitivity: 'css', + endOfLine: 'lf' +} diff --git a/utils/batch-install.js b/utils/batch-install.js new file mode 100644 index 0000000..d8f5d0f --- /dev/null +++ b/utils/batch-install.js @@ -0,0 +1,16 @@ +const { execSync } = require('child_process'); + +const batchInstall = (deps, { dev }) => { + for (const dep of deps) { + console.log(`🚓 正在安装 ${dep} ...`); + try { + execSync(`yarn add ${dep} ${dev ? '--dev' : ''}`, { stdio: [2] }); + } catch (e) { + console.log(`❌ ${dep} 安装失败:${e}`); + } + } +}; + +module.exports = { + batchInstall, +}; diff --git a/utils/file-generator.js b/utils/file-generator.js new file mode 100644 index 0000000..8bef834 --- /dev/null +++ b/utils/file-generator.js @@ -0,0 +1,40 @@ +const { version } = require('../package.json'); +const { execSync } = require('child_process'); +const fs = require('fs'); +const fse = require('fs-extra'); +const path = require('path'); +const ejs = require('ejs'); + +const generatorTemplateFileMap = { + commitlint: '.commitlintrc.js', + editor: '.editorconfig', + eslint: '.eslintrc.js', + eslintignore: '.eslintignore', + lintstaged: '.lintstagedrc.js', + prettier: '.prettierrc.js', +}; + +const fileGenerator = ({ templateName }) => { + const cwd = process.cwd(); + const file = path.join( + path.join(__dirname, '../templates'), + `${templateName}.ejs` + ); + const template = fs.readFileSync(file, 'utf8'); + const data = { + generatedAt: new Date().toLocaleString(), + version, + }; + const filename = generatorTemplateFileMap[templateName]; + + fse.outputFileSync(path.join(cwd, filename), ejs.render(template, data)); + + // 格式化生成配置文件 + if (filename.endsWith('.js')) { + execSync(`prettier --write ${path.join(cwd, filename)}`); + } +}; + +module.exports = { + fileGenerator, +}; diff --git a/yarn.lock b/yarn.lock index bb0cff6..5f68cf1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -397,6 +397,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +async@0.9.x: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -893,6 +898,13 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== +ejs@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a" + integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw== + dependencies: + jake "^10.6.1" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -1116,6 +1128,13 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +filelist@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b" + integrity sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ== + dependencies: + minimatch "^3.0.4" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -1173,7 +1192,7 @@ fs-access@^1.0.1: dependencies: null-check "^1.0.0" -fs-extra@^10.0.0: +fs-extra@^10.0.0, fs-extra@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.1.tgz#27de43b4320e833f6867cc044bfce29fdf0ef3b8" integrity sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag== @@ -1499,6 +1518,16 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= +jake@^10.6.1: + version "10.8.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" + integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A== + dependencies: + async "0.9.x" + chalk "^2.4.2" + filelist "^1.0.1" + minimatch "^3.0.4" + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"