From c1adfc11d145056ffe8cf13f9a420722cbbaff46 Mon Sep 17 00:00:00 2001 From: Aiden-FE Date: Fri, 22 Mar 2024 18:12:25 +0800 Subject: [PATCH] feat: support create prettyquick and commitlint plugins --- package.json | 1 + pnpm-lock.yaml | 131 +++++++++++++++++++++++++++++++- src/commands/plugin.cmd.ts | 41 ++++++++-- src/utils/commitlint.plugin.ts | 75 ++++++++++++++++++ src/utils/githooks.plugin.ts | 10 +-- src/utils/index.ts | 4 +- src/utils/prettier.plugin.ts | 6 +- src/utils/prettyquick.plugin.ts | 80 +++++++++++++++++++ 8 files changed, 330 insertions(+), 18 deletions(-) create mode 100644 src/utils/commitlint.plugin.ts create mode 100644 src/utils/prettyquick.plugin.ts diff --git a/package.json b/package.json index 81f0856..3f8843e 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "dependencies": { "@compass-aiden/helpers": "^0.2.0", "@compass-aiden/telegram": "^2.1.0", + "@inquirer/prompts": "^4.3.0", "axios": "^1.6.7", "chalk": "^5.3.0", "commander": "^12.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 31858c0..31f6e47 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ dependencies: '@compass-aiden/telegram': specifier: ^2.1.0 version: 2.1.0(axios@1.6.7) + '@inquirer/prompts': + specifier: ^4.3.0 + version: 4.3.0 axios: specifier: ^1.6.7 version: 1.6.7 @@ -408,6 +411,121 @@ packages: resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} dev: true + /@inquirer/checkbox@2.2.0: + resolution: {integrity: sha512-L+owhbEm98dnP15XtT/8D1+nNvQecf8HngVFYTJaDR0jlfIeOHFHRbjhLKoVYxks85yY8mLaYXVZQLU46KTkXg==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 7.1.0 + '@inquirer/type': 1.2.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + figures: 3.2.0 + dev: false + + /@inquirer/confirm@3.1.0: + resolution: {integrity: sha512-nH5mxoTEoqk6WpoBz80GMpDSm9jH5V9AF8n+JZAZfMzd9gHeEG9w1o3KawPRR72lfzpP+QxBHLkOKLEApwhDiQ==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 7.1.0 + '@inquirer/type': 1.2.1 + dev: false + + /@inquirer/core@7.1.0: + resolution: {integrity: sha512-FRCiDiU54XHt5B/D8hX4twwZuzSP244ANHbu3R7CAsJfiv1dUOz24ePBgCZjygEjDUi6BWIJuk4eWLKJ7LATUw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/type': 1.2.1 + '@types/mute-stream': 0.0.4 + '@types/node': 20.11.27 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-spinners: 2.9.2 + cli-width: 4.1.0 + figures: 3.2.0 + mute-stream: 1.0.0 + run-async: 3.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: false + + /@inquirer/editor@2.1.0: + resolution: {integrity: sha512-gBxebaZLATrQyjZnuPLcfM2WxjZG6rjEmnzepJb/0bypi1PgWt9rZoH+a/j1uJx/tF+jhYrvSBr8McEOWcyAWg==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 7.1.0 + '@inquirer/type': 1.2.1 + external-editor: 3.1.0 + dev: false + + /@inquirer/expand@2.1.0: + resolution: {integrity: sha512-jQgF7ImxxsX4MM8BUk33ffOvx3YOlaEqNCLTxBk7eZ5KOqOshmUq9FnOMnacUXpu7MJtkV/DJHubFiC/q4NF6g==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 7.1.0 + '@inquirer/type': 1.2.1 + chalk: 4.1.2 + figures: 3.2.0 + dev: false + + /@inquirer/input@2.1.0: + resolution: {integrity: sha512-o57pST+xxZfGww1h4G7ISiX37KlLcajhKgKGG7/h8J6ClWtsyqwMv1el9Ds/4geuYN/HcPj0MyX9gTEO62UpcA==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 7.1.0 + '@inquirer/type': 1.2.1 + dev: false + + /@inquirer/password@2.1.0: + resolution: {integrity: sha512-93x0Rpq75SP9u4s3zh4UcSKvn8KBGgyF3tKN7bNQp3bseROR0uJgySDp8iTQpcTfhJy41R+2Jr4xNLKGhr6Gzw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 7.1.0 + '@inquirer/type': 1.2.1 + ansi-escapes: 4.3.2 + dev: false + + /@inquirer/prompts@4.3.0: + resolution: {integrity: sha512-bSpFHqCnHrfmYgIMEFmA2YPPKxyw3n3ouI5S8m4N8krztJm1hFpQ8SdsZbBPRytoMaVvUgkASmiC0ih2VhDW9g==} + engines: {node: '>=18'} + dependencies: + '@inquirer/checkbox': 2.2.0 + '@inquirer/confirm': 3.1.0 + '@inquirer/core': 7.1.0 + '@inquirer/editor': 2.1.0 + '@inquirer/expand': 2.1.0 + '@inquirer/input': 2.1.0 + '@inquirer/password': 2.1.0 + '@inquirer/rawlist': 2.1.0 + '@inquirer/select': 2.2.0 + dev: false + + /@inquirer/rawlist@2.1.0: + resolution: {integrity: sha512-PykR/2LwcXcCeglDVj3OVVNrbhY2cyHTveWoSm9FmnksDtQDIXJqYgYGgvPOdPsDIj3VGVBKSXYNk+kHaQv0gw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 7.1.0 + '@inquirer/type': 1.2.1 + chalk: 4.1.2 + dev: false + + /@inquirer/select@2.2.0: + resolution: {integrity: sha512-Pml3DhVM1LnfqasUMIzaBtw+s5UjM5k0bzDeWrWOgqAMWe16AOg0DcAhXHf+SYbnj2CFBeP/TvkvedL4aAEWww==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 7.1.0 + '@inquirer/type': 1.2.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + figures: 3.2.0 + dev: false + + /@inquirer/type@1.2.1: + resolution: {integrity: sha512-xwMfkPAxeo8Ji/IxfUSqzRi0/+F2GIqJmpc5/thelgMGsjNZcjDDRBO9TLXT1s/hdx/mK5QbVIvgoLIFgXhTMQ==} + engines: {node: '>=18'} + dev: false + /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -718,6 +836,12 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true + /@types/mute-stream@0.0.4: + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + dependencies: + '@types/node': 20.11.27 + dev: false + /@types/node@17.0.45: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} dev: true @@ -726,7 +850,6 @@ packages: resolution: {integrity: sha512-qyUZfMnCg1KEz57r7pzFtSGt49f6RPkPBis3Vo4PbS7roQEDn22hiHzl/Lo1q4i4hDEgBJmBF/NTNg2XR0HbFg==} dependencies: undici-types: 5.26.5 - dev: true /@types/object-path@0.11.4: resolution: {integrity: sha512-4tgJ1Z3elF/tOMpA8JLVuR9spt9Ynsf7+JjqsQ2IqtiPJtcLoHoXcT6qU4E10cPFqyXX5HDm9QwIzZhBSkLxsw==} @@ -750,6 +873,10 @@ packages: resolution: {integrity: sha512-P/oDfpofrdtF5xw433SPALpdSchtJmY7nsJItf8h3KXqOslkbySh8zq4dSWXH2oTjRvJ5PczVEoCZPow6GicLg==} dev: true + /@types/wrap-ansi@3.0.0: + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + dev: false + /@typescript-eslint/eslint-plugin@7.2.0(@typescript-eslint/parser@7.2.0)(eslint@8.57.0)(typescript@5.4.2): resolution: {integrity: sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw==} engines: {node: ^16.0.0 || >=18.0.0} @@ -3496,7 +3623,6 @@ packages: /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - dev: true /simple-git-hooks@2.10.0: resolution: {integrity: sha512-TtCytVYfV77pILCkzVxpOSgYKHQyaO7fBI/iwG5bLGb0dIo/v/K1Y1IZ5DN40RQu6WNNJiN0gkuRvSYjxOhFog==} @@ -3823,7 +3949,6 @@ packages: /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true /unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} diff --git a/src/commands/plugin.cmd.ts b/src/commands/plugin.cmd.ts index b115648..40393e4 100644 --- a/src/commands/plugin.cmd.ts +++ b/src/commands/plugin.cmd.ts @@ -3,7 +3,16 @@ import { Command } from 'commander'; import chalk from 'chalk'; import inquirer from 'inquirer'; import { scanDependencyManager } from '@compass-aiden/helpers/cjs'; -import { addGithooksPlugin, addPrettierPlugin, removeGithooksPlugin, removePrettierPlugin } from '@/utils'; +import { + addCommitlintPlugin, + addGithooksPlugin, + addPrettierPlugin, + addPrettyQuickPlugin, + removeCommitlintPlugin, + removeGithooksPlugin, + removePrettierPlugin, + removePrettyQuickPlugin, +} from '@/utils'; import { PkgManager } from '@/interfaces'; /** @@ -21,7 +30,7 @@ export default (program: Command) => { .option('-T, --type [type]', '操作类型\n\t\t\t- add\t为项目添加插件\n\t\t\t- remove\t为项目移除插件') .option( '-N, --name [name]', - '插件名称\n\t\t\t- githooks\t使用SimpleGitHooks基于githooks对项目添加自动化任务\n\t\t\t- prettier\tPrettier 代码格式化', + '插件名称\n\t\t\t- githooks\t使用SimpleGitHooks基于githooks对项目添加自动化任务\n\t\t\t- prettier\tPrettier 代码格式化\n\t\t\t- prettyquick\tPrettyQuick 在Commit前仅对变更文件进行快速格式化,该插件依赖于githooks及prettier插件\n\t\t\t- commitlint\tCommitlint 提交信息格式校验,该插件依赖于githooks插件', ) .option('-P, --path [path]', '项目路径,默认为当前路径') .action(async ({ name: inputName, type: inputType, path: inputPath }) => { @@ -65,10 +74,10 @@ export default (program: Command) => { name: '使用SimpleGitHooks基于githooks对项目添加自动化任务', value: 'githooks', }, - { - name: 'Eslint 基于Airbnb规范对代码进行检查', - value: 'eslint', - }, + // { + // name: 'Eslint 基于Airbnb规范对代码进行检查', + // value: 'eslint', + // }, { name: 'Prettier 代码格式化', value: 'prettier', @@ -106,6 +115,26 @@ export default (program: Command) => { return; } + if (name === 'prettyquick') { + const action = { + add: addPrettyQuickPlugin, + remove: removePrettyQuickPlugin, + }; + const pkgManager: PkgManager = scanDependencyManager({ cwd: basePath }); + await action[type]({ pkgManager, cwd: basePath }); + return; + } + + if (name === 'commitlint') { + const action = { + add: addCommitlintPlugin, + remove: removeCommitlintPlugin, + }; + const pkgManager: PkgManager = scanDependencyManager({ cwd: basePath }); + await action[type]({ pkgManager, cwd: basePath }); + return; + } + // eslint-disable-next-line no-console console.log(chalk.red(`❌ ${name}不是可用的插件名称, 请通过 'compass plugin --help' 获取更多帮助信息`)); }); diff --git a/src/utils/commitlint.plugin.ts b/src/utils/commitlint.plugin.ts new file mode 100644 index 0000000..ec62b34 --- /dev/null +++ b/src/utils/commitlint.plugin.ts @@ -0,0 +1,75 @@ +import { execSync } from 'child_process'; +import { join } from 'path'; +import chalk from 'chalk'; +import { confirm } from '@inquirer/prompts'; +import { createFileSync } from '@compass-aiden/helpers/cjs'; +import { PkgManager } from '@/interfaces'; +import Logger from './logger'; +import { addGithooksPlugin } from './githooks.plugin'; +import { deleteFilesSync } from './delete-files-sync'; + +const COMMITLINT_CONFIG_FILE = `export default { + extends: ['@commitlint/config-conventional'], +}; +`; + +export async function addCommitlintPlugin(options?: { pkgManager?: PkgManager; cwd?: string }) { + const { pkgManager, cwd } = { + pkgManager: 'npm' as PkgManager, + ...options, + }; + const execOption = { stdio: 'inherit' as const, cwd }; + const loading = Logger.createLoading(); + loading.start(chalk.cyan('开始安装 Commitlint 插件')); + + const hasGithooks = execSync('npm pkg get devDependencies.simple-git-hooks', { cwd }).toString().trim(); + const isHasGithooks = !(hasGithooks === '{}' || hasGithooks === ''); + if (!isHasGithooks) { + loading.stop(); + + const confirmInstall = await confirm({ + message: '未发现前置Githooks插件,是否现在安装?', + default: true, + }); + + if (!confirmInstall) { + Logger.error(chalk.red('❌ 缺少前置插件安装失败')); + return; + } + await addGithooksPlugin(options); + loading.start(chalk.cyan('开始安装 Commitlint 插件')); + } + + execSync(`${pkgManager} add -D @commitlint/cli @commitlint/config-conventional`, execOption); + execSync('npm pkg set simple-git-hooks.commit-msg="npx --no -- commitlint --edit \\$1"', execOption); + createFileSync('commitlint.config.js', COMMITLINT_CONFIG_FILE, { cwd }); + execSync('npx simple-git-hooks', execOption); + + Logger.success(`Installed @commitlint/cli @commitlint/config-conventional at ${cwd || process.cwd()}`); + Logger.success(`Set 'simple-git-hooks.commit-msg' field at ${cwd || process.cwd()}/package.json`); + Logger.success(`Created file at ${cwd || process.cwd()}/commitlint.config.js`); + Logger.success(`Ran 'npx simple-git-hooks' to update hooks at ${cwd || process.cwd()}`); + loading.succeed(chalk.green('成功安装 Commitlint 插件,将在每次Commit提交时验证提交信息')); +} + +export async function removeCommitlintPlugin(options?: { pkgManager?: PkgManager; cwd?: string }) { + const { pkgManager, cwd } = { + pkgManager: 'npm' as PkgManager, + ...options, + }; + const execOption = { stdio: 'inherit' as const, cwd }; + const loading = Logger.createLoading(); + loading.start(chalk.cyan('开始卸载 Commitlint 插件')); + + execSync(`${pkgManager} remove @commitlint/cli @commitlint/config-conventional`, execOption); + execSync('npm pkg delete simple-git-hooks.commit-msg', execOption); + deleteFilesSync(join(cwd || './', 'commitlint.config.js')); + execSync('npx simple-git-hooks', execOption); + + Logger.success(`Uninstalled @commitlint/cli @commitlint/config-conventional at ${cwd || process.cwd()}`); + Logger.success(`Delete 'simple-git-hooks.commit-msg' field at ${cwd || process.cwd()}/package.json`); + Logger.success(`Delete file at ${cwd || process.cwd()}/commitlint.config.js`); + Logger.success(`Ran 'npx simple-git-hooks' to update hooks at ${cwd || process.cwd()}`); + + loading.succeed(chalk.green('成功卸载 Commitlint 插件')); +} diff --git a/src/utils/githooks.plugin.ts b/src/utils/githooks.plugin.ts index b72763d..5c12f64 100644 --- a/src/utils/githooks.plugin.ts +++ b/src/utils/githooks.plugin.ts @@ -14,8 +14,8 @@ export async function addGithooksPlugin(options?: { pkgManager?: PkgManager; cwd execSync('npm pkg set simple-git-hooks={} --json', { stdio: 'inherit', cwd }); execSync('npm pkg set scripts.prepare="npx simple-git-hooks"', { stdio: 'inherit', cwd }); Logger.success(`Installed simple-git-hooks at ${cwd || process.cwd()}`); - Logger.success(`Set 'simple-git-hooks' fields at ${cwd || process.cwd()}/package.json`); - Logger.success(`Set 'scripts.prepare' fields at ${cwd || process.cwd()}/package.json`); + Logger.success(`Set 'simple-git-hooks' field at ${cwd || process.cwd()}/package.json`); + Logger.success(`Set 'scripts.prepare' field at ${cwd || process.cwd()}/package.json`); loading.succeed( chalk.green('SimpleGitHooks 插件安装完成\n使用文档参考: https://github.com/toplenboren/simple-git-hooks'), @@ -29,11 +29,11 @@ export async function removeGithooksPlugin(options?: { pkgManager?: PkgManager; }; const loading = Logger.createLoading(); loading.start(chalk.cyan('开始移除SimpleGitHooks插件')); - execSync(`${pkgManager} remove -D simple-git-hooks`, { stdio: 'inherit', cwd }); + execSync(`${pkgManager} remove simple-git-hooks`, { stdio: 'inherit', cwd }); execSync('npm pkg delete simple-git-hooks', { stdio: 'inherit', cwd }); execSync('npm pkg delete scripts.prepare', { stdio: 'inherit', cwd }); Logger.success(`Uninstalled simple-git-hooks at ${cwd || process.cwd()}`); - Logger.success(`Delete 'simple-git-hooks' fields at ${cwd || process.cwd()}/package.json`); - Logger.success(`Delete 'scripts.prepare' fields at ${cwd || process.cwd()}/package.json`); + Logger.success(`Delete 'simple-git-hooks' field at ${cwd || process.cwd()}/package.json`); + Logger.success(`Delete 'scripts.prepare' field at ${cwd || process.cwd()}/package.json`); loading.succeed(chalk.green('SimpleGitHooks 插件移除完成')); } diff --git a/src/utils/index.ts b/src/utils/index.ts index 2328c45..e9efb37 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -13,8 +13,10 @@ export { default as createAngular } from './create-angular'; // tools export { default as batchCompileTemplates } from './batch-compile-templates'; export { default as Logger } from './logger'; +export * from './delete-files-sync'; // plugin utils export * from './githooks.plugin'; export * from './prettier.plugin'; -export * from './delete-files-sync'; +export * from './prettyquick.plugin'; +export * from './commitlint.plugin'; diff --git a/src/utils/prettier.plugin.ts b/src/utils/prettier.plugin.ts index 5a4e875..7a05fa3 100644 --- a/src/utils/prettier.plugin.ts +++ b/src/utils/prettier.plugin.ts @@ -70,10 +70,10 @@ export async function addPrettierPlugin(options?: { pkgManager?: PkgManager; cwd Logger.success( `Installed prettier${isHasEslint ? ' eslint-config-prettier eslint-plugin-prettier' : ''} at ${cwd || process.cwd()}`, ); - Logger.success(`Set 'scripts.format' fields at ${cwd || process.cwd()}/package.json`); + Logger.success(`Set 'scripts.format' field at ${cwd || process.cwd()}/package.json`); Logger.success(`Created file at ${cwd || process.cwd()}/.prettierrc.json`); Logger.success(`Created file at ${cwd || process.cwd()}/.prettierignore`); - loading.succeed(chalk.green('成功安装 Prettier 插件')); + loading.succeed(chalk.green('成功安装 Prettier 插件,可通过以下命令主动执行格式化:\n\n\tnpm run format')); } export async function removePrettierPlugin(options?: { pkgManager?: PkgManager; cwd?: string }) { @@ -97,7 +97,7 @@ export async function removePrettierPlugin(options?: { pkgManager?: PkgManager; Logger.success( `Uninstalled prettier${isHasEslint ? ' eslint-config-prettier eslint-plugin-prettier' : ''} at ${cwd || process.cwd()}`, ); - Logger.success(`Delete 'scripts.format' fields at ${cwd || process.cwd()}/package.json`); + Logger.success(`Delete 'scripts.format' field at ${cwd || process.cwd()}/package.json`); Logger.success(`Delete file at ${cwd || process.cwd()}/.prettierrc.json`); Logger.success(`Delete file at ${cwd || process.cwd()}/.prettierignore`); loading.succeed(chalk.green('成功移除 Prettier 插件')); diff --git a/src/utils/prettyquick.plugin.ts b/src/utils/prettyquick.plugin.ts new file mode 100644 index 0000000..d4c96aa --- /dev/null +++ b/src/utils/prettyquick.plugin.ts @@ -0,0 +1,80 @@ +import { execSync } from 'child_process'; +import chalk from 'chalk'; +import { confirm } from '@inquirer/prompts'; +import { PkgManager } from '@/interfaces'; +import Logger from './logger'; +import { addGithooksPlugin } from './githooks.plugin'; +import { addPrettierPlugin } from './prettier.plugin'; + +export async function addPrettyQuickPlugin(options?: { pkgManager?: PkgManager; cwd?: string }) { + const { pkgManager, cwd } = { + pkgManager: 'npm' as PkgManager, + ...options, + }; + const execOption = { stdio: 'inherit' as const, cwd }; + const loading = Logger.createLoading(); + loading.start(chalk.cyan('开始安装 PrettyQuick 插件')); + + const hasGithooks = execSync('npm pkg get devDependencies.simple-git-hooks', { cwd }).toString().trim(); + const isHasGithooks = !(hasGithooks === '{}' || hasGithooks === ''); + if (!isHasGithooks) { + loading.stop(); + + const confirmInstall = await confirm({ + message: '未发现前置Githooks插件,是否现在安装?', + default: true, + }); + + if (!confirmInstall) { + Logger.error(chalk.red('❌ 缺少前置插件安装失败')); + return; + } + await addGithooksPlugin(options); + loading.start(chalk.cyan('开始安装 PrettyQuick 插件')); + } + + const hasPrettier = execSync('npm pkg get devDependencies.prettier', { cwd }).toString().trim(); + const isHasPrettier = !(hasPrettier === '{}' || hasPrettier === ''); + if (!isHasPrettier) { + loading.stop(); + + const confirmInstall = await confirm({ + message: '未发现前置Prettier插件,是否现在安装?', + default: true, + }); + + if (!confirmInstall) { + Logger.error(chalk.red('❌ 缺少前置插件安装失败')); + return; + } + await addPrettierPlugin(options); + loading.start(chalk.cyan('开始安装 PrettyQuick 插件')); + } + + execSync(`${pkgManager} add -D pretty-quick`, execOption); + execSync('npm pkg set simple-git-hooks.pre-commit="npx pretty-quick --staged"', execOption); + execSync('npx simple-git-hooks', execOption); + + Logger.success(`Installed pretty-quick at ${cwd || process.cwd()}`); + Logger.success(`Set 'simple-git-hooks.pre-commit' field at ${cwd || process.cwd()}/package.json`); + Logger.success(`Ran 'npx simple-git-hooks' to install hooks at ${cwd || process.cwd()}`); + loading.succeed(chalk.green('成功安装 PrettyQuick 插件,将在每次commit前格式化变更文件')); +} + +export async function removePrettyQuickPlugin(options?: { pkgManager?: PkgManager; cwd?: string }) { + const { pkgManager, cwd } = { + pkgManager: 'npm' as PkgManager, + ...options, + }; + const execOption = { stdio: 'inherit' as const, cwd }; + const loading = Logger.createLoading(); + loading.start(chalk.cyan('开始移除 PrettyQuick 插件')); + execSync(`${pkgManager} remove pretty-quick`, execOption); + execSync('npm pkg delete simple-git-hooks.pre-commit', execOption); + execSync('npx simple-git-hooks', execOption); + + Logger.success(`Uninstalled pretty-quick at ${cwd || process.cwd()}`); + Logger.success(`Delete 'simple-git-hooks.pre-commit' field at ${cwd || process.cwd()}/package.json`); + Logger.success(`Ran 'npx simple-git-hooks' to update hooks at ${cwd || process.cwd()}`); + loading.succeed(chalk.green('成功移除 PrettyQuick 插件')); +}