jjb-cmd 2.5.3 → 2.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SECURITY.md +71 -0
- package/bin/command.js +6 -0
- package/build.js +20 -0
- package/obf.config.json +3 -0
- package/package.json +4 -2
- package/src/ai-pull.js +675 -0
- package/src/auth.js +71 -1
- package/src/code-optimization.js +46 -1
- package/src/config.js +122 -1
- package/src/crypto-utils.js +183 -1
- package/src/password-input.js +79 -1
- package/src/publish.js +307 -1
- package/src/push.js +417 -1
- package/src/rm-rf.js +49 -1
- package/src/utils.js +228 -1
package/src/push.js
CHANGED
|
@@ -1 +1,417 @@
|
|
|
1
|
-
const a6_0x271645=a6_0x2c3a;(function(_0x2232d0,_0x3f82cd){const _0x5cd49e=a6_0x2c3a,_0x5863cf=_0x2232d0();while(!![]){try{const _0xf9e4a4=-parseInt(_0x5cd49e(0x150))/0x1*(-parseInt(_0x5cd49e(0xfc))/0x2)+parseInt(_0x5cd49e(0x154))/0x3*(parseInt(_0x5cd49e(0x11e))/0x4)+-parseInt(_0x5cd49e(0x13a))/0x5*(-parseInt(_0x5cd49e(0x12e))/0x6)+parseInt(_0x5cd49e(0x157))/0x7*(-parseInt(_0x5cd49e(0x137))/0x8)+-parseInt(_0x5cd49e(0x167))/0x9+-parseInt(_0x5cd49e(0x17b))/0xa*(parseInt(_0x5cd49e(0x12c))/0xb)+parseInt(_0x5cd49e(0x15e))/0xc;if(_0xf9e4a4===_0x3f82cd)break;else _0x5863cf['push'](_0x5863cf['shift']());}catch(_0x433a6e){_0x5863cf['push'](_0x5863cf['shift']());}}}(a6_0x1784,0x5aba1));function a6_0x2c3a(_0x18d8fb,_0x5a83d8){const _0x178479=a6_0x1784();return a6_0x2c3a=function(_0x2c3a5b,_0x28c877){_0x2c3a5b=_0x2c3a5b-0xfc;let _0x1c541b=_0x178479[_0x2c3a5b];return _0x1c541b;},a6_0x2c3a(_0x18d8fb,_0x5a83d8);}function a6_0x1784(){const _0x1e09e8=['10daJhrQ','26212laMeUx','认证信息加载成功','then','请选择环境:','uncaughtException','join','split','yarn\x20run\x20','git\x20checkout\x20','node_modules','appIdentifier','清理临时目录失败:\x20','正在准备临时工作目录...','javaGit','selectedScript','username','exit','项目依赖安装完成','./utils','toLowerCase','DEFAULT_BRANCH','.html','正在加载认证信息...','environment\x20配置为空,将使用默认分支','构建产物复制完成','读取认证信息失败:\x20','package.json','临时工作目录已创建','prompt','request','default','代码提交跳过:\x20没有需要提交的变更','javaGitName','\x22\x20--no-verify','16OxmMvI','正在处理构建产物...','代码推送完成','正在检查项目配置文件...','项目依赖检查通过','正在推送代码到远程仓库...','MAX_BUFFER_SIZE','data','scripts','input','代码提交成功','random','正在请求服务器授权...','response','5648236ouOFhH','keys','107892NkRsTV','password','构建产物目录不存在,请检查构建输出配置','yarn','build','tmpdir','./config','已生成\x20','index.html','24gVfxDq','git\x20clone\x20','正在切换到目标分支:\x20','90FuBJxB','length','git\x20commit\x20-m\x20\x22','未知错误','服务器授权成功','substr','已选择环境:\x20','正在添加文件变更...','catch','package.json\x20读取成功','utf8','commitMessage','正在清理目标目录...','已选择打包命令:\x20','now','exports','检测到已存在的仓库,正在强制清理...','未找到\x20jjb.config.json\x20文件','message','/api/auth','list','请求失败\x20(','27aORxiZ','git\x20push','envType','Git\x20仓库克隆完成','151818caUZYu','已生成\x20index.html\x20文件','临时工作目录已清理:\x20','416339kzcooW','未找到\x20environment\x20配置,将使用默认分支','检测到未安装项目依赖','正在安装项目依赖,请稍候...','no\x20message','readFileSync','includes','2947212VEIlwk','trim','解析\x20jjb.config.json\x20失败:\x20','配置文件中缺少必要字段:\x20','inquirer','javaGitBranch','object','some','.html\x20文件','558351GEhcDZ','__esModule','分支切换完成','CONFIG_FILE_NAME','git\x20pull','resolve','force','../.auth','请输入提交信息:','isValid','未找到打包相关的命令,请检查\x20package.json\x20中的\x20scripts\x20配置','TEMPLATES_PATH','正在提交代码变更...','项目构建完成','正在同步\x20Git\x20仓库最新代码...','environment','toString','SYNC_DELAY','正在克隆\x20Git\x20仓库...','missingFields'];a6_0x1784=function(){return _0x1e09e8;};return a6_0x1784();}const os=require('os'),path=require('path'),fs=require('fs'),inquirer=require(a6_0x271645(0x162)),{CopyFolder,DeleteDirAllFile}=require(a6_0x271645(0x10e)),{GIT_TEMP_JAVA,getApiHost}=require(a6_0x271645(0x134)),axios=require('axios'),{CONSTANTS,logInfo,logSuccess,logWarning,logError,executeCommand,deleteFolderRecursive,fileExists,readFile,writeFile,createDir,isViteProject,validateConfig}=require(a6_0x271645(0x10e)),{loadAuth}=require('./crypto-utils');module[a6_0x271645(0x149)]=async arguments=>{const _0x352baa=a6_0x271645;let _0x18febf=null;const _0x2d2c90=path[_0x352baa(0x101)](__dirname,_0x352baa(0x16e));!fileExists(_0x2d2c90)&&(logError('未检测到认证信息,请先执行登录操作'),process[_0x352baa(0x10c)](0x1));let _0x5126af,_0x38aaec;try{logInfo(_0x352baa(0x112));const _0x5b82fc=loadAuth(_0x2d2c90);_0x5126af=_0x5b82fc[_0x352baa(0x10b)],_0x38aaec=_0x5b82fc[_0x352baa(0x12f)],logSuccess(_0x352baa(0xfd));}catch(_0x5f5a9e){logError(_0x352baa(0x115)+_0x5f5a9e[_0x352baa(0x14c)]),process['exit'](0x1);}const _0x3bc4cd=arguments[0x1]?arguments[0x1][_0x352baa(0x102)]('-'):[],_0x521eb5=path[_0x352baa(0x16c)]('./'),_0x33dd88=path[_0x352baa(0x101)](_0x521eb5,_0x352baa(0x116)),_0x3067a4=path[_0x352baa(0x101)](_0x521eb5,CONSTANTS[_0x352baa(0x16a)]),_0x2e28b8=path[_0x352baa(0x101)](_0x521eb5,CONSTANTS['BUILD_OUTPUT_DIR']),_0xff2cb6=os['tmpdir']();logInfo(_0x352baa(0x121));!fileExists(_0x33dd88)&&(logError('未找到\x20package.json\x20文件'),process['exit'](0x1));let _0x1ddc26;try{_0x1ddc26=JSON['parse'](fs[_0x352baa(0x15c)](_0x33dd88,_0x352baa(0x144))),logSuccess(_0x352baa(0x143));}catch(_0x1f2291){logError('解析\x20package.json\x20失败:\x20'+_0x1f2291[_0x352baa(0x14c)]),process[_0x352baa(0x10c)](0x1);}const _0x4f3425=_0x1ddc26[_0x352baa(0x126)]||{},_0xfd5261=[_0x352baa(0x132)],_0xa68502=Object[_0x352baa(0x12d)](_0x4f3425)['filter'](_0x295d95=>{const _0x4da627=_0x352baa;return _0xfd5261[_0x4da627(0x165)](_0x938756=>_0x295d95[_0x4da627(0x10f)]()[_0x4da627(0x15d)](_0x938756));});_0xa68502[_0x352baa(0x13b)]===0x0&&(logError(_0x352baa(0x171)),process[_0x352baa(0x10c)](0x1));const {selectedScript:_0x4ce257}=await inquirer[_0x352baa(0x118)]([{'type':'list','name':_0x352baa(0x10a),'message':'请选择要执行的打包命令:','choices':_0xa68502['map'](_0x3b541c=>({'name':_0x3b541c+'\x20('+_0x4f3425[_0x3b541c]+')','value':_0x3b541c}))}]);logInfo(_0x352baa(0x147)+_0x4ce257),logInfo(_0x352baa(0x121));!fileExists(_0x3067a4)&&(logError(_0x352baa(0x14b)),process['exit'](0x1));let _0x29fda4;try{_0x29fda4=require(_0x3067a4),_0x29fda4=_0x29fda4[_0x352baa(0x168)]?_0x29fda4[_0x352baa(0x11a)]:_0x29fda4,logSuccess('jjb.config.json\x20读取成功');}catch(_0x52cc40){logError(_0x352baa(0x160)+_0x52cc40[_0x352baa(0x14c)]),process[_0x352baa(0x10c)](0x1);}const _0x54ac90=['javaGit',_0x352baa(0x11c),_0x352baa(0x106)],_0x468d1b=validateConfig(_0x29fda4,_0x54ac90);!_0x468d1b[_0x352baa(0x170)]&&(logError(_0x352baa(0x161)+_0x468d1b[_0x352baa(0x17a)][_0x352baa(0x101)](',\x20')),process[_0x352baa(0x10c)](0x1));let _0x1c799e=null;if(_0x29fda4[_0x352baa(0x176)]&&typeof _0x29fda4[_0x352baa(0x176)]===_0x352baa(0x164)){const _0xa250d0=Object[_0x352baa(0x12d)](_0x29fda4[_0x352baa(0x176)]);if(_0xa250d0[_0x352baa(0x13b)]>0x0){const {envType:_0x480205}=await inquirer[_0x352baa(0x118)]([{'type':_0x352baa(0x14e),'name':_0x352baa(0x152),'message':_0x352baa(0xff),'choices':_0xa250d0['map'](_0x38121e=>({'name':_0x38121e,'value':_0x38121e}))}]);_0x1c799e=_0x480205,logInfo(_0x352baa(0x140)+_0x1c799e);}else logWarning(_0x352baa(0x113));}else logWarning(_0x352baa(0x158));logInfo(_0x352baa(0x12a)),axios['post'](getApiHost()+_0x352baa(0x14d),{'username':_0x5126af,'password':_0x38aaec})[_0x352baa(0xfe)](async _0x47d9cf=>{const _0x7c9e79=_0x352baa;if(_0x47d9cf['data']['status']){logSuccess(_0x7c9e79(0x13e));const _0x61a451=GIT_TEMP_JAVA+'-'+Date[_0x7c9e79(0x148)]()+'-'+Math[_0x7c9e79(0x129)]()[_0x7c9e79(0x177)](0x24)[_0x7c9e79(0x13f)](0x2,0x9);_0x18febf=_0x61a451;const _0x4ae37c=path[_0x7c9e79(0x101)](_0xff2cb6,_0x61a451);logInfo(_0x7c9e79(0x108));fileExists(_0x4ae37c)&&deleteFolderRecursive(_0x4ae37c);createDir(_0x4ae37c),logSuccess(_0x7c9e79(0x117));const _0x32b713=path[_0x7c9e79(0x101)](_0x4ae37c,_0x29fda4[_0x7c9e79(0x11c)]);logInfo(_0x7c9e79(0x179)),fileExists(_0x32b713)?_0x3bc4cd['includes'](_0x7c9e79(0x16d))?(logInfo(_0x7c9e79(0x14a)),DeleteDirAllFile(_0x32b713,()=>{const _0x498c78=_0x7c9e79;executeCommand(_0x498c78(0x138)+_0x29fda4[_0x498c78(0x109)],_0x4ae37c),logSuccess('Git\x20仓库克隆完成');})):(executeCommand(_0x7c9e79(0x138)+_0x29fda4['javaGit'],_0x4ae37c),logSuccess(_0x7c9e79(0x153))):(executeCommand('git\x20clone\x20'+_0x29fda4[_0x7c9e79(0x109)],_0x4ae37c),logSuccess(_0x7c9e79(0x153))),_0x4c8a98(_0x4ae37c,_0x29fda4,_0x61a451,_0x4ce257,_0x1c799e);}else logError('授权失败:\x20'+(_0x47d9cf[_0x7c9e79(0x125)][_0x7c9e79(0x14c)]||_0x7c9e79(0x13d))),process[_0x7c9e79(0x10c)](0x1);})[_0x352baa(0x142)](_0x411571=>{const _0x3dd791=_0x352baa;if(_0x411571&&_0x411571[_0x3dd791(0x12b)]){const _0x2caafb=_0x411571[_0x3dd791(0x12b)]['status'];_0x2caafb===0x191||_0x2caafb===0x193?logError('授权失败\x20('+_0x2caafb+'):\x20认证信息无效或无权限'):logError(_0x3dd791(0x14f)+_0x2caafb+'):\x20'+(_0x411571[_0x3dd791(0x12b)][_0x3dd791(0x125)]?.[_0x3dd791(0x14c)]||_0x411571[_0x3dd791(0x14c)]));}else _0x411571&&_0x411571[_0x3dd791(0x119)]?logError('网络连接失败:\x20无法连接到服务器'):logError('操作失败:\x20'+(_0x411571[_0x3dd791(0x14c)]||'未知错误'));process[_0x3dd791(0x10c)](0x1);}),process['on'](_0x352baa(0x10c),()=>{const _0x83f3e9=_0x352baa;if(_0x18febf){const _0x2f8126=path[_0x83f3e9(0x101)](os[_0x83f3e9(0x133)](),_0x18febf);if(fileExists(_0x2f8126))try{deleteFolderRecursive(_0x2f8126);}catch(_0x2c39b9){}}}),process['on'](_0x352baa(0x100),_0x927da=>{const _0x34748f=_0x352baa;if(_0x18febf){const _0x57226e=path[_0x34748f(0x101)](os[_0x34748f(0x133)](),_0x18febf);if(fileExists(_0x57226e))try{deleteFolderRecursive(_0x57226e);}catch(_0x2c2a6d){}}throw _0x927da;});function _0x4c8a98(_0x47d43a,_0x1558d7,_0x38be31,_0x4db1c1,_0x483a48){const _0x568e63=_0x352baa,_0x1e918f=path[_0x568e63(0x101)](_0x47d43a,_0x1558d7[_0x568e63(0x11c)]);logInfo(_0x568e63(0x175)),executeCommand(_0x568e63(0x16b),_0x1e918f),logSuccess('代码同步完成');!fileExists(path[_0x568e63(0x101)](_0x521eb5,_0x568e63(0x105)))?(logWarning(_0x568e63(0x159)),logInfo(_0x568e63(0x15a)),executeCommand(_0x568e63(0x131),_0x521eb5),logSuccess(_0x568e63(0x10d))):logInfo(_0x568e63(0x122));try{logInfo('正在执行构建命令:\x20yarn\x20run\x20'+_0x4db1c1),executeCommand(_0x568e63(0x103)+_0x4db1c1,_0x521eb5,{'maxBuffer':CONSTANTS[_0x568e63(0x124)]}),logSuccess(_0x568e63(0x174));}catch(_0x39232d){logError('项目构建失败:\x20'+_0x39232d[_0x568e63(0x14c)]);const _0x24859a=path[_0x568e63(0x101)](os['tmpdir'](),_0x38be31);if(fileExists(_0x24859a))try{deleteFolderRecursive(_0x24859a),logInfo('临时工作目录已清理:\x20'+_0x38be31);}catch(_0x25b765){logWarning(_0x568e63(0x107)+_0x25b765[_0x568e63(0x14c)]);}process['exit'](0x1);}if(fileExists(_0x2e28b8)){logInfo(_0x568e63(0x11f));const _0x43057c=_0x1558d7['appIdentifier'],_0x516074=readFile(path[_0x568e63(0x101)](_0x2e28b8,_0x568e63(0x136)));_0x3bc4cd[_0x568e63(0x15d)]('index')?(writeFile(path[_0x568e63(0x101)](_0x2e28b8,_0x568e63(0x136)),_0x516074),logInfo(_0x568e63(0x155))):(writeFile(path['join'](_0x2e28b8,_0x43057c+'.html'),_0x516074),logInfo(_0x568e63(0x135)+_0x43057c+_0x568e63(0x166)));const _0x39fccc=path[_0x568e63(0x101)](_0x1e918f,CONSTANTS[_0x568e63(0x172)]);logInfo('正在创建模板目录...'),createDir(_0x39fccc);const _0x427e90=_0x483a48&&_0x1558d7[_0x568e63(0x176)]&&_0x1558d7['environment'][_0x483a48]&&_0x1558d7[_0x568e63(0x176)][_0x483a48]['javaGitBranch']?_0x1558d7['environment'][_0x483a48][_0x568e63(0x163)]:CONSTANTS[_0x568e63(0x110)];logInfo(_0x568e63(0x139)+_0x427e90),executeCommand(_0x568e63(0x104)+_0x427e90,_0x1e918f),logSuccess(_0x568e63(0x169));const _0x5f0502=path[_0x568e63(0x101)](_0x39fccc,_0x1558d7[_0x568e63(0x106)]);logInfo(_0x568e63(0x146)),DeleteDirAllFile(_0x5f0502,()=>{const _0x1fefdc=_0x568e63;createDir(_0x5f0502),logInfo('正在复制构建产物到目标目录...'),writeFile(path[_0x1fefdc(0x101)](_0x39fccc,_0x43057c+_0x1fefdc(0x111)),_0x516074),CopyFolder(path[_0x1fefdc(0x101)](_0x2e28b8,_0x1558d7[_0x1fefdc(0x106)]),_0x5f0502,async()=>{const _0x3a0744=_0x1fefdc;logSuccess(_0x3a0744(0x114)),setTimeout(async()=>{const _0x205b92=_0x3a0744;logInfo('正在同步远程仓库...'),executeCommand(_0x205b92(0x16b),_0x1e918f),logInfo(_0x205b92(0x141)),executeCommand('git\x20add\x20.',_0x1e918f);const {commitMessage:_0x276690}=await inquirer[_0x205b92(0x118)]([{'type':_0x205b92(0x127),'name':_0x205b92(0x145),'message':_0x205b92(0x16f),'default':_0x205b92(0x15b)}]),_0xd63afc=_0x276690[_0x205b92(0x15f)]()||_0x205b92(0x15b);try{logInfo(_0x205b92(0x173)),executeCommand(_0x205b92(0x13c)+_0xd63afc+_0x205b92(0x11d),_0x1e918f),logSuccess(_0x205b92(0x128));}catch(_0x24db03){logWarning(_0x205b92(0x11b));}logInfo(_0x205b92(0x123)),executeCommand(_0x205b92(0x151),_0x1e918f),logSuccess(_0x205b92(0x120)),setTimeout(()=>{const _0x49fcb3=_0x205b92;logInfo('正在清理临时工作目录...');const _0x1fe90f=path[_0x49fcb3(0x101)](os['tmpdir'](),_0x38be31);if(fileExists(_0x1fe90f))try{deleteFolderRecursive(_0x1fe90f),logSuccess(_0x49fcb3(0x156)+_0x38be31);}catch(_0x5b5fc0){logWarning(_0x49fcb3(0x107)+_0x5b5fc0[_0x49fcb3(0x14c)]);}},CONSTANTS['SYNC_DELAY']*0x2);},CONSTANTS[_0x3a0744(0x178)]);});});}else{logError(_0x568e63(0x130));const _0x4b4b14=path[_0x568e63(0x101)](os[_0x568e63(0x133)](),_0x38be31);if(fileExists(_0x4b4b14))try{deleteFolderRecursive(_0x4b4b14),logInfo(_0x568e63(0x156)+_0x38be31);}catch(_0x12818d){logWarning(_0x568e63(0x107)+_0x12818d['message']);}process[_0x568e63(0x10c)](0x1);}}};
|
|
1
|
+
const os = require('os');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const inquirer = require('inquirer');
|
|
5
|
+
const {
|
|
6
|
+
CopyFolder,
|
|
7
|
+
DeleteDirAllFile
|
|
8
|
+
} = require('./utils');
|
|
9
|
+
const {
|
|
10
|
+
GIT_TEMP_JAVA,
|
|
11
|
+
getApiHost
|
|
12
|
+
} = require('./config');
|
|
13
|
+
const axios = require('axios');
|
|
14
|
+
const {
|
|
15
|
+
CONSTANTS,
|
|
16
|
+
logInfo,
|
|
17
|
+
logSuccess,
|
|
18
|
+
logWarning,
|
|
19
|
+
logError,
|
|
20
|
+
executeCommand,
|
|
21
|
+
deleteFolderRecursive,
|
|
22
|
+
fileExists,
|
|
23
|
+
readFile,
|
|
24
|
+
writeFile,
|
|
25
|
+
createDir,
|
|
26
|
+
isViteProject,
|
|
27
|
+
validateConfig
|
|
28
|
+
} = require('./utils');
|
|
29
|
+
const { loadAuth } = require('./crypto-utils');
|
|
30
|
+
|
|
31
|
+
module.exports = async arguments => {
|
|
32
|
+
|
|
33
|
+
// 存储当前任务的临时文件夹名称,用于进程退出时清理
|
|
34
|
+
let currentTempDir = null;
|
|
35
|
+
|
|
36
|
+
const authPath = path.join(__dirname, '../.auth');
|
|
37
|
+
|
|
38
|
+
if (!fileExists(authPath)) {
|
|
39
|
+
logError('未检测到认证信息,请先执行登录操作');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 安全读取认证信息
|
|
44
|
+
let username, password;
|
|
45
|
+
try {
|
|
46
|
+
logInfo('正在加载认证信息...');
|
|
47
|
+
const authData = loadAuth(authPath);
|
|
48
|
+
username = authData.username;
|
|
49
|
+
password = authData.password;
|
|
50
|
+
logSuccess('认证信息加载成功');
|
|
51
|
+
} catch (error) {
|
|
52
|
+
logError(`读取认证信息失败: ${error.message}`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 更多参数
|
|
58
|
+
* @type {*|*[]}
|
|
59
|
+
*/
|
|
60
|
+
const parameter = arguments[ 1 ]
|
|
61
|
+
? arguments[ 1 ].split('-')
|
|
62
|
+
: [];
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 当前根路径
|
|
66
|
+
* @type {Promise<void> | Promise<string>}
|
|
67
|
+
*/
|
|
68
|
+
const root_path = path.resolve('./');
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* package.json 路径
|
|
72
|
+
* @type {string}
|
|
73
|
+
*/
|
|
74
|
+
const package_json_path = path.join(root_path, 'package.json');
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* jjb配置文件路径
|
|
78
|
+
* @type {string}
|
|
79
|
+
*/
|
|
80
|
+
const config_json_path = path.join(root_path, CONSTANTS.CONFIG_FILE_NAME);
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 打包输出目录
|
|
84
|
+
* @type {string}
|
|
85
|
+
*/
|
|
86
|
+
const build_output_dir = path.join(root_path, CONSTANTS.BUILD_OUTPUT_DIR);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 临时目录
|
|
90
|
+
*/
|
|
91
|
+
const tmpdir = os.tmpdir();
|
|
92
|
+
|
|
93
|
+
// 读取 package.json 并筛选打包命令
|
|
94
|
+
logInfo('正在检查项目配置文件...');
|
|
95
|
+
if (!fileExists(package_json_path)) {
|
|
96
|
+
logError('未找到 package.json 文件');
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let packageJson;
|
|
101
|
+
try {
|
|
102
|
+
packageJson = JSON.parse(fs.readFileSync(package_json_path, 'utf8'));
|
|
103
|
+
logSuccess('package.json 读取成功');
|
|
104
|
+
} catch (error) {
|
|
105
|
+
logError(`解析 package.json 失败: ${error.message}`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const scripts = packageJson.scripts || {};
|
|
110
|
+
|
|
111
|
+
// 筛选打包相关的命令(只判断键名,包含 build、compile、打包等关键字)
|
|
112
|
+
const buildKeywords = ['build'];
|
|
113
|
+
const buildScripts = Object.keys(scripts).filter(key => {
|
|
114
|
+
return buildKeywords.some(keyword =>
|
|
115
|
+
key.toLowerCase().includes(keyword)
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
if (buildScripts.length === 0) {
|
|
120
|
+
logError('未找到打包相关的命令,请检查 package.json 中的 scripts 配置');
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 使用 inquirer 让用户选择打包命令
|
|
125
|
+
const { selectedScript } = await inquirer.prompt([
|
|
126
|
+
{
|
|
127
|
+
type: 'list',
|
|
128
|
+
name: 'selectedScript',
|
|
129
|
+
message: '请选择要执行的打包命令:',
|
|
130
|
+
choices: buildScripts.map(script => ({
|
|
131
|
+
name: `${script} (${scripts[script]})`,
|
|
132
|
+
value: script
|
|
133
|
+
}))
|
|
134
|
+
}
|
|
135
|
+
]);
|
|
136
|
+
|
|
137
|
+
logInfo(`已选择打包命令: ${selectedScript}`);
|
|
138
|
+
|
|
139
|
+
// 读取 jjb.config.json 以获取 environment 配置
|
|
140
|
+
logInfo('正在检查项目配置文件...');
|
|
141
|
+
if (!fileExists(config_json_path)) {
|
|
142
|
+
logError('未找到 jjb.config.json 文件');
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 支持 ESM 和 CJS 模块导入
|
|
147
|
+
let jjbConfig;
|
|
148
|
+
try {
|
|
149
|
+
// 如果 ESM 导入失败,回退到 require
|
|
150
|
+
jjbConfig = require(config_json_path);
|
|
151
|
+
jjbConfig = jjbConfig.__esModule ? jjbConfig.default : jjbConfig;
|
|
152
|
+
logSuccess('jjb.config.json 读取成功');
|
|
153
|
+
} catch (error) {
|
|
154
|
+
logError(`解析 jjb.config.json 失败: ${error.message}`);
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 验证必要的配置字段
|
|
159
|
+
const requiredFields = ['javaGit', 'javaGitName', 'appIdentifier'];
|
|
160
|
+
const configValidation = validateConfig(jjbConfig, requiredFields);
|
|
161
|
+
|
|
162
|
+
if (!configValidation.isValid) {
|
|
163
|
+
logError(`配置文件中缺少必要字段: ${configValidation.missingFields.join(', ')}`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// 选择 environment
|
|
168
|
+
let selectedEnvType = null;
|
|
169
|
+
if (jjbConfig.environment && typeof jjbConfig.environment === 'object') {
|
|
170
|
+
const envKeys = Object.keys(jjbConfig.environment);
|
|
171
|
+
if (envKeys.length > 0) {
|
|
172
|
+
const { envType } = await inquirer.prompt([
|
|
173
|
+
{
|
|
174
|
+
type: 'list',
|
|
175
|
+
name: 'envType',
|
|
176
|
+
message: '请选择环境:',
|
|
177
|
+
choices: envKeys.map(key => ({
|
|
178
|
+
name: key,
|
|
179
|
+
value: key
|
|
180
|
+
}))
|
|
181
|
+
}
|
|
182
|
+
]);
|
|
183
|
+
selectedEnvType = envType;
|
|
184
|
+
logInfo(`已选择环境: ${selectedEnvType}`);
|
|
185
|
+
} else {
|
|
186
|
+
logWarning('environment 配置为空,将使用默认分支');
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
logWarning('未找到 environment 配置,将使用默认分支');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
logInfo('正在请求服务器授权...');
|
|
193
|
+
axios.post(`${getApiHost()}/api/auth`, {
|
|
194
|
+
username,
|
|
195
|
+
password
|
|
196
|
+
}).then(async res => {
|
|
197
|
+
if (res.data.status) {
|
|
198
|
+
logSuccess('服务器授权成功');
|
|
199
|
+
|
|
200
|
+
// 为每个打包任务创建唯一的临时文件夹
|
|
201
|
+
const uniqueTempDir = `${GIT_TEMP_JAVA}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
202
|
+
currentTempDir = uniqueTempDir; // 存储当前临时文件夹名称
|
|
203
|
+
const tempGit = path.join(tmpdir, uniqueTempDir);
|
|
204
|
+
|
|
205
|
+
logInfo('正在准备临时工作目录...');
|
|
206
|
+
if (fileExists(tempGit)) {
|
|
207
|
+
deleteFolderRecursive(tempGit);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
createDir(tempGit);
|
|
211
|
+
logSuccess('临时工作目录已创建');
|
|
212
|
+
|
|
213
|
+
const projectDir = path.join(tempGit, jjbConfig.javaGitName);
|
|
214
|
+
|
|
215
|
+
logInfo('正在克隆 Git 仓库...');
|
|
216
|
+
if (fileExists(projectDir)) {
|
|
217
|
+
if (parameter.includes('force')) {
|
|
218
|
+
logInfo('检测到已存在的仓库,正在强制清理...');
|
|
219
|
+
DeleteDirAllFile(projectDir, () => {
|
|
220
|
+
executeCommand(`git clone ${jjbConfig.javaGit}`, tempGit);
|
|
221
|
+
logSuccess('Git 仓库克隆完成');
|
|
222
|
+
});
|
|
223
|
+
} else {
|
|
224
|
+
executeCommand(`git clone ${jjbConfig.javaGit}`, tempGit);
|
|
225
|
+
logSuccess('Git 仓库克隆完成');
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
executeCommand(`git clone ${jjbConfig.javaGit}`, tempGit);
|
|
229
|
+
logSuccess('Git 仓库克隆完成');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
project_sync(tempGit, jjbConfig, uniqueTempDir, selectedScript, selectedEnvType);
|
|
233
|
+
} else {
|
|
234
|
+
logError(`授权失败: ${res.data.message || '未知错误'}`);
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
}).catch(e => {
|
|
238
|
+
if (e && e.response) {
|
|
239
|
+
const status = e.response.status;
|
|
240
|
+
if (status === 401 || status === 403) {
|
|
241
|
+
logError(`授权失败 (${status}): 认证信息无效或无权限`);
|
|
242
|
+
} else {
|
|
243
|
+
logError(`请求失败 (${status}): ${e.response.data?.message || e.message}`);
|
|
244
|
+
}
|
|
245
|
+
} else if (e && e.request) {
|
|
246
|
+
logError(`网络连接失败: 无法连接到服务器`);
|
|
247
|
+
} else {
|
|
248
|
+
logError(`操作失败: ${e.message || '未知错误'}`);
|
|
249
|
+
}
|
|
250
|
+
process.exit(1);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// 进程退出时清理临时文件夹
|
|
254
|
+
process.on('exit', () => {
|
|
255
|
+
if (currentTempDir) {
|
|
256
|
+
const tempDirToClean = path.join(os.tmpdir(), currentTempDir);
|
|
257
|
+
if (fileExists(tempDirToClean)) {
|
|
258
|
+
try {
|
|
259
|
+
deleteFolderRecursive(tempDirToClean);
|
|
260
|
+
} catch (e) {
|
|
261
|
+
// 静默处理清理失败的情况
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// 处理未捕获的异常
|
|
268
|
+
process.on('uncaughtException', (error) => {
|
|
269
|
+
if (currentTempDir) {
|
|
270
|
+
const tempDirToClean = path.join(os.tmpdir(), currentTempDir);
|
|
271
|
+
if (fileExists(tempDirToClean)) {
|
|
272
|
+
try {
|
|
273
|
+
deleteFolderRecursive(tempDirToClean);
|
|
274
|
+
} catch (e) {
|
|
275
|
+
// 静默处理清理失败的情况
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
throw error;
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* 应用git同步
|
|
284
|
+
*/
|
|
285
|
+
function project_sync(tempGit, jjbConfig, uniqueTempDir, buildScript, envType) {
|
|
286
|
+
const projectDir = path.join(tempGit, jjbConfig.javaGitName);
|
|
287
|
+
|
|
288
|
+
logInfo('正在同步 Git 仓库最新代码...');
|
|
289
|
+
executeCommand(`git pull`, projectDir);
|
|
290
|
+
logSuccess('代码同步完成');
|
|
291
|
+
|
|
292
|
+
if (!fileExists(path.join(root_path, 'node_modules'))) {
|
|
293
|
+
logWarning('检测到未安装项目依赖');
|
|
294
|
+
logInfo('正在安装项目依赖,请稍候...');
|
|
295
|
+
executeCommand(`yarn`, root_path);
|
|
296
|
+
logSuccess('项目依赖安装完成');
|
|
297
|
+
} else {
|
|
298
|
+
logInfo('项目依赖检查通过');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
try {
|
|
302
|
+
logInfo(`正在执行构建命令: yarn run ${buildScript}`);
|
|
303
|
+
executeCommand(`yarn run ${buildScript}`, root_path, { maxBuffer: CONSTANTS.MAX_BUFFER_SIZE });
|
|
304
|
+
logSuccess('项目构建完成');
|
|
305
|
+
} catch (e) {
|
|
306
|
+
logError(`项目构建失败: ${e.message}`);
|
|
307
|
+
// 清理临时文件夹
|
|
308
|
+
const tempDirToClean = path.join(os.tmpdir(), uniqueTempDir);
|
|
309
|
+
if (fileExists(tempDirToClean)) {
|
|
310
|
+
try {
|
|
311
|
+
deleteFolderRecursive(tempDirToClean);
|
|
312
|
+
logInfo(`临时工作目录已清理: ${uniqueTempDir}`);
|
|
313
|
+
} catch (err) {
|
|
314
|
+
logWarning(`清理临时目录失败: ${err.message}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
process.exit(1);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (fileExists(build_output_dir)) {
|
|
321
|
+
logInfo('正在处理构建产物...');
|
|
322
|
+
const appIdentifier = jjbConfig.appIdentifier;
|
|
323
|
+
const indexContent = readFile(path.join(build_output_dir, 'index.html'));
|
|
324
|
+
|
|
325
|
+
if (parameter.includes('index')) {
|
|
326
|
+
writeFile(path.join(build_output_dir, 'index.html'), indexContent);
|
|
327
|
+
logInfo('已生成 index.html 文件');
|
|
328
|
+
} else {
|
|
329
|
+
writeFile(path.join(build_output_dir, `${appIdentifier}.html`), indexContent);
|
|
330
|
+
logInfo(`已生成 ${appIdentifier}.html 文件`);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const tempJavaPath = path.join(projectDir, CONSTANTS.TEMPLATES_PATH);
|
|
334
|
+
|
|
335
|
+
logInfo('正在创建模板目录...');
|
|
336
|
+
createDir(tempJavaPath);
|
|
337
|
+
|
|
338
|
+
// 从选择的 environment 中获取分支,如果没有则使用默认分支
|
|
339
|
+
const javaGitBranch = (envType && jjbConfig.environment && jjbConfig.environment[envType] && jjbConfig.environment[envType].javaGitBranch)
|
|
340
|
+
? jjbConfig.environment[envType].javaGitBranch
|
|
341
|
+
: CONSTANTS.DEFAULT_BRANCH;
|
|
342
|
+
|
|
343
|
+
logInfo(`正在切换到目标分支: ${javaGitBranch}`);
|
|
344
|
+
executeCommand(`git checkout ${javaGitBranch}`, projectDir);
|
|
345
|
+
logSuccess('分支切换完成');
|
|
346
|
+
|
|
347
|
+
const projectJavaPath = path.join(tempJavaPath, jjbConfig.appIdentifier);
|
|
348
|
+
|
|
349
|
+
logInfo('正在清理目标目录...');
|
|
350
|
+
DeleteDirAllFile(projectJavaPath, () => {
|
|
351
|
+
createDir(projectJavaPath);
|
|
352
|
+
logInfo('正在复制构建产物到目标目录...');
|
|
353
|
+
writeFile(path.join(tempJavaPath, `${appIdentifier}.html`), indexContent);
|
|
354
|
+
|
|
355
|
+
CopyFolder(path.join(build_output_dir, jjbConfig.appIdentifier), projectJavaPath, async () => {
|
|
356
|
+
logSuccess('构建产物复制完成');
|
|
357
|
+
setTimeout(async () => {
|
|
358
|
+
logInfo('正在同步远程仓库...');
|
|
359
|
+
executeCommand(`git pull`, projectDir);
|
|
360
|
+
logInfo('正在添加文件变更...');
|
|
361
|
+
executeCommand(`git add .`, projectDir);
|
|
362
|
+
|
|
363
|
+
// 提示用户输入提交信息
|
|
364
|
+
const { commitMessage: inputMessage } = await inquirer.prompt([
|
|
365
|
+
{
|
|
366
|
+
type: 'input',
|
|
367
|
+
name: 'commitMessage',
|
|
368
|
+
message: '请输入提交信息:',
|
|
369
|
+
default: 'no message'
|
|
370
|
+
}
|
|
371
|
+
]);
|
|
372
|
+
const commitMessage = inputMessage.trim() || 'no message';
|
|
373
|
+
|
|
374
|
+
try {
|
|
375
|
+
logInfo('正在提交代码变更...');
|
|
376
|
+
executeCommand(`git commit -m "${commitMessage}" --no-verify`, projectDir);
|
|
377
|
+
logSuccess('代码提交成功');
|
|
378
|
+
} catch (e) {
|
|
379
|
+
logWarning(`代码提交跳过: 没有需要提交的变更`);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
logInfo('正在推送代码到远程仓库...');
|
|
383
|
+
executeCommand(`git push`, projectDir);
|
|
384
|
+
logSuccess('代码推送完成');
|
|
385
|
+
|
|
386
|
+
// 清理临时文件夹
|
|
387
|
+
setTimeout(() => {
|
|
388
|
+
logInfo('正在清理临时工作目录...');
|
|
389
|
+
const tempDirToClean = path.join(os.tmpdir(), uniqueTempDir);
|
|
390
|
+
if (fileExists(tempDirToClean)) {
|
|
391
|
+
try {
|
|
392
|
+
deleteFolderRecursive(tempDirToClean);
|
|
393
|
+
logSuccess(`临时工作目录已清理: ${uniqueTempDir}`);
|
|
394
|
+
} catch (e) {
|
|
395
|
+
logWarning(`清理临时目录失败: ${e.message}`);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}, CONSTANTS.SYNC_DELAY * 2); // 延迟清理,确保git操作完成
|
|
399
|
+
}, CONSTANTS.SYNC_DELAY);
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
} else {
|
|
403
|
+
logError('构建产物目录不存在,请检查构建输出配置');
|
|
404
|
+
// 清理临时文件夹
|
|
405
|
+
const tempDirToClean = path.join(os.tmpdir(), uniqueTempDir);
|
|
406
|
+
if (fileExists(tempDirToClean)) {
|
|
407
|
+
try {
|
|
408
|
+
deleteFolderRecursive(tempDirToClean);
|
|
409
|
+
logInfo(`临时工作目录已清理: ${uniqueTempDir}`);
|
|
410
|
+
} catch (e) {
|
|
411
|
+
logWarning(`清理临时目录失败: ${e.message}`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
process.exit(1);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
};
|
package/src/rm-rf.js
CHANGED
|
@@ -1 +1,49 @@
|
|
|
1
|
-
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const {
|
|
4
|
+
logInfo,
|
|
5
|
+
logSuccess,
|
|
6
|
+
logError,
|
|
7
|
+
logWarning,
|
|
8
|
+
deleteFolderRecursive
|
|
9
|
+
} = require('./utils');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 递归删除目录模块
|
|
13
|
+
* 危险操作:删除当前目录下的所有文件和文件夹
|
|
14
|
+
*/
|
|
15
|
+
module.exports = async function () {
|
|
16
|
+
const rootPath = path.resolve('./');
|
|
17
|
+
|
|
18
|
+
logWarning('危险操作:此命令将删除当前目录下的所有文件和文件夹');
|
|
19
|
+
logWarning('删除后不可恢复,请谨慎操作');
|
|
20
|
+
|
|
21
|
+
const { confirm } = await inquirer.prompt([
|
|
22
|
+
{
|
|
23
|
+
type: 'confirm',
|
|
24
|
+
name: 'confirm',
|
|
25
|
+
message: '是否确认删除?删除后不可恢复!',
|
|
26
|
+
default: false
|
|
27
|
+
}
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
if (confirm) {
|
|
31
|
+
logInfo('正在扫描目录结构...');
|
|
32
|
+
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
try {
|
|
35
|
+
logInfo('开始执行删除操作...');
|
|
36
|
+
deleteFolderRecursive(rootPath);
|
|
37
|
+
logSuccess('所有文件已成功删除');
|
|
38
|
+
process.exit(0);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
logError(`删除操作失败: ${error.message}`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
}, 1000);
|
|
44
|
+
} else {
|
|
45
|
+
logInfo('操作已取消');
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|