js-xcmd
Version:
XCmd library for node.js.
864 lines (785 loc) • 28.8 kB
JavaScript
// 是执行这个文件时使用 node 方式执行
/*
* @Author: HxB
* @Date: 2022-04-25 16:27:06
* @LastEditors: DoubleAm
* @LastEditTime: 2025-12-26 18:21:45
* @Description: 命令处理文件
* @FilePath: /js-xcmd/bin/xcmd.js
*/
const program = require('commander');
const download = require('download-git-repo');
const pkg = require('../package.json');
const {
copyDir,
copyFile,
setFileContent,
getFileContent,
getJSONFileObj,
deleteDir,
deleteFile,
addDir,
addFile,
renameDir,
renameFile,
rmRf,
emptyDir,
getFullPath,
getResolvePath,
getAllFilePath
} = require('../utils/files');
const { cmd } = require('../utils/cmd');
const { node2es6, sortJSON, mergeObj, versionUpgrade, isValidJson, jsonToExcel } = require('../utils/tools');
const { extractParamsFromFiles, parseGitFile, filterGitFiles } = require('../utils/ast');
const { downloadTpl } = require('../utils/tpl');
const { FILTER_KEYS } = require('../utils/data');
const nodeCmd = require('node-cmd');
const readline = require('readline');
const util = require('util');
const { exec } = require('child_process');
// http://patorjk.com/software/taag/
const logo = () => {
/*
___ _______ ________ ___ ___ _______
|\ \ |\ ___ \ |\ __ \|\ \|\ \|\ ___ \
\ \ \ \ \ __/|\ \ \|\ \ \ \\\ \ \ __/|
\ \ \ \ \ \_|/_\ \ \\\ \ \ __ \ \ \_|/__
\ \ \____\ \ \_|\ \ \ \\\ \ \ \ \ \ \ \_|\ \
\ \_______\ \_______\ \_______\ \__\ \__\ \_______\
\|_______|\|_______|\|_______|\|__|\|__|\|_______|
*/
};
const logLogo = (strFoo) => {
let l = new String(strFoo);
l = l.substring(l.indexOf('/*') + 3, l.lastIndexOf('*/'));
return l;
};
const getTimeCode = () => {
let dateObj = new Date();
return `${Math.round(Math.random() * 100)
.toString()
.padEnd(2, '0')}${dateObj.getSeconds().toString().padStart(2, '0')}${dateObj
.getMinutes()
.toString()
.padStart(2, '0')}${dateObj.getHours().toString().padStart(2, '0')}${dateObj
.getDate()
.toString()
.padStart(2, '0')}${String(dateObj.getMonth() + 1).padStart(2, '0')}${dateObj.getFullYear()}`;
};
program.version(pkg.version, '-v, --version', 'output the version number');
program
.option('create-react-view [dir]', 'create react-view cli')
.command('create-react-view [dir]')
.description('创建 react-view 模板')
.action((dir) => {
console.log('----------Clone Template----------');
console.log(logLogo(logo));
download('github:pandaoh/react-view', !dir ? 'react-view' : dir, function (err) {
console.log(err ? err : '----------Successful----------');
});
});
program
.option('create-vue-admin [dir]', 'create vue-admin cli')
.command('create-vue-admin [dir]')
.description('创建 vue-admin 模板')
.action((dir) => {
console.log('----------Clone Template----------');
console.log(logLogo(logo));
download('github:biugle/vue-admin', !dir ? 'vue-admin' : dir, function (err) {
console.log(err ? err : '----------Successful----------');
});
});
program
.option('create-micro-web [dir]', 'create micro-web cli')
.command('create-micro-web [dir]')
.description('创建 react-micro-web 模板')
.action((dir) => {
console.log('----------Clone Template----------');
console.log(logLogo(logo));
download('github:pandaoh/react_micro_web', !dir ? 'react_micro_web' : dir, function (err) {
console.log(err ? err : '----------Successful----------');
});
});
program
.option('create-web-base [dir] [branch]', 'create web-base cli')
.command('create-web-base [dir] [branch]')
.description('获取 web-base 通用开发模板-推荐~')
.action((dir, branch) => {
console.log('----------Clone Template----------');
console.log(logLogo(logo));
const branchs = {
main: 'main',
modules: 'modules',
'c-modules': 'client-modules',
'c-main': 'client-main',
cross: 'simple-cross-platform'
};
download(
'github:biugle/web_base' + (branch ? `#${branchs[branch] ?? branch ?? 'main'}` : ''),
!dir ? 'web_base' : dir,
function (err) {
console.log(err ? err : '----------Successful----------');
}
);
});
// xcmd copy-file ./package.json ./target/package.json
program
.option('copy-file <fileSrc> <fileTarget>', 'copy file')
.command('copy-file <fileSrc> <fileTarget>')
.description('复制文件')
.action((fileSrc, fileTarget) => {
console.log('----------Copying----------');
console.log({ fileSrc, fileTarget });
copyFile(fileSrc, fileTarget);
console.log('----------Successful----------');
});
program
.option('copy-dir <dirSrc> <dirTarget>', 'copy dir')
.command('copy-dir <dirSrc> <dirTarget>')
.description('复制目录')
.action((dirSrc, dirTarget) => {
console.log('----------Copying----------');
console.log({ dirSrc, dirTarget });
copyDir(dirSrc, dirTarget);
console.log('----------Successful----------');
});
program
.option('delete-dir <dir>', 'delete dir')
.command('delete-dir <dir>')
.description('删除目录')
.action((dir) => {
console.log('----------Deleting----------');
console.log({ dir });
deleteDir(dir);
console.log('----------Successful----------');
});
program
.option('empty-dir <dir>', 'empty dir')
.command('empty-dir <dir>')
.description('清空目录')
.action((dir) => {
console.log('----------Emptying----------');
console.log({ dir });
emptyDir(dir);
console.log('----------Successful----------');
});
program
.option('rm-rf <path>', 'rm rf')
.command('rm-rf <path>')
.description('彻底删除目录/文件')
// .option('rmrf <path>', 'rmrf')
// .command('rmrf <path>')
.action((path) => {
console.log('----------RimRaf----------');
console.log({ path });
rmRf(path);
console.log('----------Successful----------');
});
program
.option('delete-file <file>', 'delete file')
.command('delete-file <file>')
.description('删除文件')
.action((file) => {
console.log('----------Deleting----------');
console.log({ file });
deleteFile(file);
console.log('----------Successful----------');
});
program
.option('add-dir <dir>', 'add dir')
.command('add-dir <dir>')
.description('添加目录')
.action((dir) => {
console.log('----------Adding----------');
console.log({ dir });
addDir(dir);
console.log('----------Successful----------');
});
program
.option('add-file <file> [content]', 'add file')
.command('add-file <file> [content]')
.description('添加文件')
.action((file, content = '') => {
console.log('----------Adding----------');
console.log({ file, content });
addFile(file, content);
console.log('----------Successful----------');
});
program
.option('rename-dir <dirSrc> <dirTarget>', 'rename dir')
.command('rename-dir <dirSrc> <dirTarget>')
.description('重命名目录/移动目录')
.action((dirSrc, dirTarget) => {
console.log('----------Renaming----------');
console.log({ dirSrc, dirTarget });
renameDir(dirSrc, dirTarget);
console.log('----------Successful----------');
});
program
.option('rename-file <fileSrc> <fileTarget>', 'rename file')
.command('rename-file <fileSrc> <fileTarget>')
.description('重命名文件')
.action((fileSrc, fileTarget) => {
console.log('----------Renaming----------');
console.log({ fileSrc, fileTarget });
renameFile(fileSrc, fileTarget);
console.log('----------Successful----------');
});
// xcmd replace-file-content .\README.md "npm i js-xcmd -g" "test"
program
.option('replace-file-content <fileSrc> <content> <contentTarget>', 'replace file content')
.command('replace-file-content <fileSrc> <content> <contentTarget>')
.description('替换文件内容')
.action((fileSrc, content, contentTarget) => {
contentTarget = contentTarget.replace('[space]', ' ');
contentTarget = contentTarget.replace('[none]', '');
contentTarget = contentTarget.replace('[backslash]', '\\');
contentTarget = contentTarget.replace('[forward]', '/');
contentTarget = contentTarget.replace('[vLine]', '|');
contentTarget = contentTarget.replace('[and]', '&');
contentTarget = contentTarget.replace('[percent]', '%');
contentTarget = contentTarget.replace('[leftABracket]', '<');
contentTarget = contentTarget.replace('[rightABracket]', '>');
console.log('----------Replacing----------');
console.table({ fileSrc, content, contentTarget });
let srcFileContent = getFileContent(fileSrc);
// setFileContent(fileSrc, srcFileContent.replace(content, contentTarget));
setFileContent(fileSrc, srcFileContent.replace(new RegExp(content, 'g'), contentTarget));
console.log('----------Successful----------');
});
program
.option('update-v [filePath]', 'update package.json version [filePath]')
.command('update-v [filePath]')
.description('更新 json 中的 version 字段')
.action((filePath) => {
console.log('----------Updating----------');
const packageFilePath = filePath || './package.json';
const packageJson = getJSONFileObj(packageFilePath);
console.log('old version: ' + packageJson.version);
packageJson.version = versionUpgrade(packageJson.version);
console.log('new version: ' + packageJson.version);
setFileContent(packageFilePath, JSON.stringify(packageJson, '', 2));
console.log('----------Successful----------');
});
program
.option('update-time [filePath]', 'update package.json time [filePath]')
.command('update-time [filePath]')
.description('更新 json 中的 time 字段')
// .option('time [filePath]', 'update package.json time [filePath]')
// .command('time [filePath]')
.action((filePath) => {
try {
console.log(new Date().toLocaleString());
} catch (e) {
console.log('IOS', e);
}
console.log('----------Updating----------');
const packageFilePath = filePath || './package.json';
const packageJson = getJSONFileObj(packageFilePath);
packageJson.time = getTimeCode();
console.log({ time: packageJson.time });
setFileContent(packageFilePath, JSON.stringify(packageJson, '', 2));
console.log('----------Successful----------');
});
program
.option('clean [target]', 'clean node_modules [default: ./node_modules]')
.command('clean [target]')
.description('清理某个目录下的 node_modules 目录')
.action((target = './') => {
console.log('----------Cleaning----------');
let rimrafCmd = `rimraf ${target}/node_modules`;
console.log(rimrafCmd);
nodeCmd.run(rimrafCmd, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Successful----------');
});
});
program
.option('npm-clean', 'npm-clean')
.command('npm-clean')
.description('清理 npm 缓存')
.action(() => {
console.log('----------Npm-CacheClean-Start----------');
const cmdStr = 'npm cache clean --force';
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Npm-CacheClean-End----------');
});
});
program
.option('yarn-clean', 'yarn-clean')
.command('yarn-clean')
.description('清理 yarn 缓存')
.action(() => {
console.log('----------Yarn-CacheClean-Start----------');
const cmdStr = 'yarn cache clean --force';
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Yarn-CacheClean-End----------');
});
});
program
.option('i', 'npm i --ignore-scripts')
.command('i')
.description('执行 npm i --ignore-scripts')
.action(() => {
console.log('----------Npm-Install-IgnoreScripts-Start----------');
const cmdStr = 'npm i --ignore-scripts';
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Npm-Install-IgnoreScripts-End----------');
});
});
program
.option('eslint', 'eslint ./ --fix --ext .ts,.tsx,.js,.jsx,.vue')
.command('eslint')
.description('执行 eslint 修复')
.action(() => {
console.log('----------Eslint-Start----------');
const cmdStr = 'eslint ./ --fix --ext .ts,.tsx,.js,.jsx,.vue';
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Eslint-End----------');
});
});
program
.option('prettier', 'prettier --write ./**/*.{ts,tsx,js,jsx,vue,html,css,scss,less}')
.command('prettier')
.description('执行 prettier 格式化')
.action(() => {
console.log('----------Prettier-Start----------');
const cmdStr = 'prettier --write ./**/*.{ts,tsx,js,jsx,vue,html,css,scss,less}';
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Prettier-End----------');
});
});
program
.option('list [global]', 'list [global]')
.command('list [global]')
.description('查看安装的 npm 插件列表')
// .option('ls [global]', 'ls [global]')
// .command('ls [global]')
.action((global) => {
let cmdStr = '';
if (global) {
console.log('----------Npm-List-Global-Start----------');
cmdStr = 'npm list -g --depth 0';
} else {
console.log('----------Npm-List-Start----------');
cmdStr = 'npm list --depth 0';
}
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Npm-List-End----------');
});
});
program
.option('lsn', 'lsn')
.command('lsn')
.description('查看 nvm 可用 node 版本列表')
.action(() => {
let cmdStr = 'nvm list available';
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Successful----------');
});
});
program
.option('ig [all]', 'ig [all]')
.command('ig [all]')
.description('全局安装必要的 npm 开发插件')
.action((all) => {
let cmdStr = '';
if (!all) {
cmdStr = 'npm i nrm pnpm js-xcmd nodemon pm2 yarn rimraf turbo tsx taze knip yalc -g';
} else {
cmdStr =
'npm i increase-memory-limit nrm pnpm js-xcmd nodemon pm2 yarn rimraf turbo tsx taze knip yalc protobufjs protobufjs-cli @changesets/cli create-react-app @vue/cli @angular/cli cordova cnpm -g -force';
}
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
console.log(stderr);
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Successful----------');
});
});
program
.option('i-react-tools', 'i-react-tools')
.command('i-react-tools')
.description('安装 react 开发相关库')
.action(() => {
// zod react-hook-form @tanstack/react-query
// @mui/material @mui/lab @mui/base @mui/system @mui/utils @mui/types
// rebass
let cmdStr =
'npm i ahooks rxjs dayjs immer@9.0.21 @sigi/core@2.12.1 @sigi/di@2.11.3 @sigi/types@2.11.3 @sigi/devtool@2.12.1 @sigi/react@2.12.2 @sigi/ssr@2.13.0 @abraham/reflection@0.12.0 @emotion/styled @emotion/css @emotion/react react-hook-form';
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
console.log(stderr);
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Successful----------');
});
});
program
.option('i-vue-tools', 'i-vue-tools')
.command('i-vue-tools')
.description('安装 vue 开发相关库')
.action(() => {
let cmdStr = 'npm i ...';
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
console.log(stderr);
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Successful----------');
});
});
program
.option('dev [src]', 'dev [src]')
.command('dev [src]')
.description('帮助执行 pnpm --filter ${src} dev')
.action((src) => {
let cmdStr = '';
if (src) {
src = src.replace(/[\'\"\‘\’\“\”]/g, '');
console.log(`----------${src}-Dev----------`);
cmdStr = `pnpm --filter ${src} dev`;
} else {
console.log('----------Npm-Run-Dev----------');
cmdStr = 'npm run dev';
}
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Successful-OKK!----------');
});
});
program
.option('start [src]', 'start [src]')
.command('start [src]')
.description('帮助执行 pnpm --filter ${src} start')
.action((src) => {
let cmdStr = '';
if (src) {
src = src.replace(/[\'\"\‘\’\“\”]/g, '');
console.log(`----------${src}-Start----------`);
cmdStr = `pnpm --filter ${src} start`;
} else {
console.log('----------Npm-Run-Start----------');
cmdStr = 'npm run start';
}
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Successful-OKK!----------');
});
});
program
.option('build [src]', 'build [src]')
.command('build [src]')
.description('帮助执行 pnpm --filter ${src} build')
.action((src) => {
let cmdStr = '';
if (src) {
src = src.replace(/[\'\"\‘\’\“\”]/g, '');
console.log(`----------${src}-Build----------`);
cmdStr = `pnpm --filter ${src} build`;
} else {
console.log('----------Npm-Run-Build----------');
cmdStr = 'npm run build';
}
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Successful-OKK!----------');
});
});
// xcmd run "git status"
program
.option('run <cmdStr>', 'run cmd')
.command('run <cmdStr>')
.description('执行某个命令')
.action((cmdStr) => {
console.log('----------Executing ----------');
cmd(cmdStr)
.then((data) => {
console.log(data);
console.log('----------Successful----------');
})
.catch((err) => {
console.log('----------Error----------');
console.log(err);
});
});
program
.option('node2es6 <filePath> <outputPath>', 'node2es6 <filePath> <outputPath>')
.command('node2es6 <filePath> <outputPath>')
.description('将 CommonJS 文件转换为 ES6 模块')
.action((filePath, outputPath) => {
filePath = getFullPath(filePath); // 获取当前运行目录
const obj = require(filePath);
const result = node2es6(obj);
setFileContent(outputPath, result);
});
program
.option('sort-json <jsonPath> [outputPath]', 'sort-json <jsonPath> [outputPath]')
.command('sort-json <jsonPath> [outputPath]')
.description('将指定 json 文件排序去重并输出')
.action((jsonPath, outputPath) => {
outputPath = outputPath ? outputPath : jsonPath;
const obj = getJSONFileObj(jsonPath);
const result = sortJSON(obj);
setFileContent(outputPath, result);
});
program
.option('check-i18n [dirPath] [depth] [addKeys] [isExited]', 'check-i18n [dirPath] [depth] [addKeys] [isExited]')
.command('check-i18n [dirPath] [depth] [addKeys] [isExited]')
.description('检查 i18n 目录下的 json 文件 Key 是否有差异')
.action((dirPath = './src/locales/', depth = 0, addKeys = false, isExited = false) => {
console.log(`${dirPath} 目录检查中...`);
const i18nDirectory = getResolvePath(dirPath);
const files = getAllFilePath(i18nDirectory, depth == 'true' ? true : depth, ['json']);
console.log(`${i18nDirectory} 目录检查完成...`, files);
if (files.length === 0) {
console.error(`${i18nDirectory} 目录下没有 json 文件`);
return;
}
const getKeys = (filePath) => {
const jsonContent = getJSONFileObj(filePath);
return Object.keys(jsonContent);
};
let baseFile = files[0];
let baseKeys = getKeys(baseFile);
for (let i = 1; i < files.length; i++) {
const currentFile = files[i];
const currentKeys = getKeys(currentFile);
if (currentKeys.length > baseKeys.length) {
baseFile = currentFile;
baseKeys = currentKeys;
}
}
let isValid = true;
for (let i = 0; i < files.length; i++) {
const currentFile = files[i];
if (currentFile !== baseFile) {
const currentKeys = getKeys(currentFile);
const missingKeys = baseKeys.filter((key) => !currentKeys.includes(key));
if (missingKeys.length > 0) {
isValid = false;
console.info(`\n\n${currentFile} 相比基准【${baseFile}】缺失 key: ${missingKeys.join(', ')}\n\n`);
}
if (addKeys && missingKeys.length) {
console.log(`正在补充 ${currentFile} 缺失的 key: ${missingKeys.join(', ')}`);
const obj = getJSONFileObj(currentFile);
missingKeys.forEach((key) => {
obj[key] = '';
});
setFileContent(currentFile, JSON.stringify(obj, null, 2));
}
}
}
if (isValid) {
console.log('所有文件 key 一致,通过校验!');
files.forEach((jsonPath) => {
console.log(`正在排序 ${jsonPath}`);
const obj = getJSONFileObj(jsonPath);
const result = sortJSON(obj);
setFileContent(jsonPath, result);
});
} else {
console.info(addKeys ? '校验未通过,已补充缺失的 key,请前往修改。' : '校验未通过,存在缺失的 key。');
isExited && process.exit(1);
}
});
program
.option('merge-json [filePaths...]', 'merge-json [filePaths...]')
.command('merge-json [filePaths...]')
.description('合并指定 JSON 文件内容,并去重排序。')
.action((filePaths) => {
if (!filePaths) {
console.error('请提供需要合并的 JSON 文件路径,或者文件目录!');
return;
}
if (filePaths.length === 1) {
if (`${filePaths[0]}`.includes('json')) {
console.error('请提供至少 2 个 JSON 文件!');
return;
}
const i18nDirectory = getResolvePath(filePaths[0]);
const files = getAllFilePath(i18nDirectory, true, ['json']);
console.log(`${i18nDirectory} 目录检查完成...`, files);
if (files.length === 0) {
console.error(`${i18nDirectory} 目录下没有 json 文件`);
return;
}
filePaths = files;
}
const objArgs = filePaths.map((filePath) => {
filePath = getResolvePath(filePath);
return getJSONFileObj(filePath);
});
const mergedData = mergeObj(...objArgs);
const mergedFilePath = getFullPath('./xcmd-auto-merge.json');
console.log(`正在排序 ${mergedFilePath}`);
const result = sortJSON(mergedData);
setFileContent(mergedFilePath, result);
console.log(`JSON 文件合并完成,并保存为 【${mergedFilePath}】。`);
});
program
.option('json2excel <projectCode> [jsonFilePath] [notFilter]', 'json2excel <projectCode> [jsonFilePath] [notFilter]')
.command('json2excel <projectCode> [jsonFilePath] [notFilter]')
.description('将 JSON 数据转化为 Excel')
.action((projectCode, jsonFilePath, notFilter) => {
notFilter = `${notFilter}` === 'true';
if (!projectCode) {
console.error('请提供 Project Code');
return;
}
const _filterJsonData = (data) => {
if (notFilter) return data;
FILTER_KEYS.forEach((key) => {
delete data[key];
});
return data;
};
if (!jsonFilePath) {
// 如果未提供JSON文件路径,则提示输入JSON内容
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('请输入 JSON 数据: \n', (jsonData) => {
rl.close();
if (isValidJson(jsonData)) {
jsonToExcel(projectCode, _filterJsonData(JSON.parse(jsonData)));
} else {
console.error('输入的内容不是有效的JSON格式');
}
});
} else if (`${jsonFilePath}`?.toLowerCase()?.includes('.json')) {
const filePath = getResolvePath(jsonFilePath);
const jsonData = getJSONFileObj(filePath);
if (jsonData) {
jsonToExcel(projectCode, _filterJsonData(jsonData));
} else {
console.error('JSON 文件中的内容不是有效的 JSON 格式');
}
} else {
const filePath = getResolvePath(jsonFilePath);
const listData = extractParamsFromFiles(filePath);
if (!listData) {
console.error('读取文件失败');
return;
}
const jsonData = {};
listData?.forEach((i) => {
jsonData[i] = i;
});
jsonToExcel(projectCode, _filterJsonData(jsonData));
}
});
program
.option('increase-memory-limit', 'increase-memory-limit')
.command('increase-memory-limit')
.description('解决内存溢出神器')
.action(() => {
console.log('----------increase-memory-limit-Start----------');
const cmdStr = 'npm install -g increase-memory-limit && increase-memory-limit';
console.log({ cmdStr });
nodeCmd.run(cmdStr, (err, data, stderr) => {
if (err) return console.log(`%c出错啦!${data}`, 'color:red;');
console.log(data);
console.log('----------Npm-Install-IgnoreScripts-End----------');
});
});
program
.option('add-umi-page [dir]', 'add-umi-page [dir]')
.command('add-umi-page [dir]')
.description('创建简单页面模板')
.action((dir) => {
downloadTpl('http://cdn.biugle.cn/umi_page.zip', dir || '', ['PageCode', 'Author']);
});
program
.option('add-tpl <name> [dir]', 'add-tpl <name> [dir]')
.command('add-tpl <name> [dir]')
.description('创建简单ds页面模板-内部')
.action((name, dir) => {
downloadTpl(
'https://git.imile.com/hank.he/ds-web-tpl/-/archive/main/ds-web-tpl-main.zip',
dir || '',
['PageCode', 'Author'],
`ds-web-tpl-main/${name}`
);
});
program
.command('git2excel <projectCode> [notFilter]')
.description('从 Git 暂存区的 JavaScript/TypeScript 文件中提取 t、$t 或 .t、.$t 方法的参数并转换为 Excel')
.action(async (projectCode, notFilter) => {
notFilter = `${notFilter}` === 'true';
if (!projectCode) {
console.error('请提供 Project Code');
return;
}
const dir = process.cwd();
console.log(`正在扫描Git暂存区: ${dir}`);
// 获取Git暂存区改动
const execPromise = util.promisify(exec);
let files;
try {
const { stdout } = await execPromise('git diff --name-only --cached', { cwd: dir });
files = await filterGitFiles(stdout, dir);
} catch (err) {
console.error(`无法获取Git暂存区改动: ${err.message}`);
return;
}
if (files.length === 0) {
console.log('暂存区没有JavaScript/TypeScript文件改动。');
return;
}
// 提取所有文件的t/$t方法参数
const jsonData = {};
for (const file of files) {
const params = await parseGitFile(file.path, file.changedLines);
console.log(`解析结果 for ${file.path}:`, params); // 调试输出
params.forEach((param) => {
jsonData[param] = param; // 将提取的字符串参数添加到 jsonData 中
});
}
if (Object.keys(jsonData).length === 0) {
console.log('未找到任何 t、$t 或 .t、.$t 方法调用。');
return;
}
const _filterJsonData = (data) => {
if (notFilter) return data;
FILTER_KEYS.forEach((key) => {
delete data[key];
});
return data;
};
console.log({ jsonData });
// 使用现有方法过滤和转换
jsonToExcel(projectCode, _filterJsonData(jsonData));
});
program.parse(process.argv);