cli-z-develop 0.9.2 → 0.10.1

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/dist/index.js CHANGED
@@ -1 +1,2159 @@
1
- import{program as e}from"commander";import t from"node:child_process";import{existsSync as n,readdirSync as a,lstatSync as i}from"node:fs";import r from"node:path";import s,{AxiosError as o}from"axios";import c from"chalk";import l from"dayjs";import u from"shelljs";import p from"node:os";import m from"child_process";import{mkdir as d,writeFile as f,rename as g,readFile as h,readdir as w,stat as y}from"node:fs/promises";import{confirm as v,select as $,input as b,password as E,checkbox as j}from"@inquirer/prompts";import S from"ora";import A from"fs-extra";import{select as T}from"inquirer-select-pro";import k from"lint-staged";import N from"semver";import{run as C}from"npm-check-updates";import D from"minimist";var x,R,O;!function(e){e.DEV="dev",e.TEST="test",e.RELEASE="release",e.PROD="production"}(x||(x={})),function(e){e.DEV="dev",e.TEST="test",e.RELEASE="release",e.MASTER="master"}(R||(R={})),function(e){e.H5="h5",e.NPM="npm",e.SERVER="server"}(O||(O={}));const M=[{name:`开发环境 - ${x.DEV}`,value:x.DEV},{name:`测试环境 - ${x.TEST}`,value:x.TEST},{name:`预发环境 - ${x.RELEASE}`,value:x.RELEASE},{name:`正式环境 - ${x.PROD}`,value:x.PROD}],z=[{name:`网页 - ${O.H5}`,value:O.H5},{name:`依赖包 - ${O.NPM}`,value:O.NPM},{name:`服务端 - ${O.SERVER}`,value:O.SERVER}];var I,P,B;!function(e){e.FEAT="feat",e.FIX="fix",e.REFACTOR="refactor"}(I||(I={})),function(e){e.FRONT_END="fe",e.BACK_END="be",e.QUALITY_ASSURANCE="qa"}(P||(P={})),function(e){e.JAVA="Java",e.JAVASCRIPT="JavaScript",e.PYTHON="Python"}(B||(B={}));const _={1:"研发",2:"测试",3:"产品",4:"设计",5:"运营",6:"销售",7:"行政",8:"财务",9:"其他"},F="http://git.cxlqd.com",L=["fe-biz","fe-base","fe-tpl","fe-component","fe-demo"];var U;!function(e){e.FEAT="feat",e.FIX="fix",e.REFACTOR="refactor",e.CHORE="chore",e.CI="ci",e.Break="BREAKING CHANGE"}(U||(U={}));const W="fe-biz7tvsd",J="https://hxhtbr8t8uy.feishu.cn/wiki/LWW5wAQFPiXkmRkKcjOcyDDknLg";var V;!function(e){e.MODULE="module",e.CASE="case"}(V||(V={}));const q=[{name:"拉取远程模块(包含产品)",value:V.MODULE},{name:"拉取远程用例",value:V.CASE}],H=[{name:"创建模块",value:V.MODULE},{name:"创建用例",value:V.CASE}],G=".z",K="develop-config.json",Q=".z",Y=".commit-msg-tpl",X="project.json";function Z(e=""){return r.join(Q,e)}function ee(){return Z(X)}function te(){return Z(Y)}function ne(){m.spawnSync("git",["config","core.hooksPath",Z()]),m.spawnSync("git",["config","commit.template",te()])}function ae(e=""){return r.resolve(p.homedir(),G,e)}function ie(){return ae(K)}function re(){return n(ae())&&n(ie())}function se(e){let t=e.trim();const n=t.match(/^git@([^:]+):(.+)$/);if(n)t=n[2];else{const e=F.replace(/^https?:\/\//,"").replace(/\/$/,"");t=t.replace(/^https?:\/\//,""),t=t.startsWith(`${e}/`)?t.slice(e.length+1):t.replace(`${F.replace(/\/$/,"")}/`,"")}return encodeURIComponent(t.replace(/\.git$/,""))}const{red:oe,green:ce,blue:le,magenta:ue}=c;function pe(...e){console.log(ce(...e))}function me(e){e instanceof Error&&("ExitPromptError"===e.name||e.message.includes("User force closed the prompt with"))&&(console.log(),console.log(c.cyan(" 👋 下次见~")),console.log(),process.exit(1))}function de(e,t=!1){me(e);let n=e;e instanceof Error?(n=e.message,s.isAxiosError(e)&&(n=`请求失败:${e.message}`),console.log(oe(n)),console.log(ue(e.stack))):console.log(oe(e)),t||process.exit(1)}function fe(e){return!!n(e)&&i(e).isDirectory()}function ge(e=process.cwd()){if(fe(e)){return a(e).filter((t=>fe(r.resolve(e,t))))}return[]}async function he(e,t={removeTailLinkBreak:!0,silent:!0}){let n=await new Promise(((n,a)=>{try{n(u.exec(e,{silent:t.silent}))}catch(e){a(e)}}));return n=n.toString(),t.removeTailLinkBreak&&(n=n.replace(/\n$/,"")),n}function we(e){t.execSync(e,{stdio:"inherit"})}function ye(){return l(Date.now()).format("YYMMDD")}function ve(){n(Z())||de("当前不在项目根目录。请切换到项目根目录")}function $e(){n(r.resolve(".git"))||de("当前不是git项目根目录,请先执行git init,或切换到根目录")}async function be(){""!==await he("git status -s")&&de("请先提交代码变动,再进行操作")}async function Ee(e,...t){try{await e(...t)}catch(e){throw me(e),e}}const je='{\n "printWidth": 120,\n "tabWidth": 2,\n "useTabs": false,\n "semi": true,\n "singleQuote": false,\n "quoteProps": "as-needed",\n "jsxSingleQuote": false,\n "trailingComma": "all",\n "bracketSpacing": true,\n "bracketSameLine": false,\n "arrowParens": "always",\n "requirePragma": false,\n "insertPragma": false,\n "proseWrap": "preserve",\n "htmlWhitespaceSensitivity": "css",\n "vueIndentScriptAndStyle": false,\n "endOfLine": "lf",\n "embeddedLanguageFormatting": "auto",\n "singleAttributePerLine": false\n}\n',Se="# 系统 信息文件\n.DS_Store/\nThumbs.db\n\n# 编辑器配置文件\n.idea/\n.vscode/\n\n# 输出目录\ndist/\n\n# Log files\n*.log\n\n# 本地配置文件\n*.local\n\n# 缓存文件\n*.cache\n\n# 垃圾文件\n.Trashes\n",Ae={[B.JAVA]:{"**/*.{java}":"echo 'todo'"},[B.JAVASCRIPT]:{"**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}":"eslint --fix","*":"prettier -wu"},[B.PYTHON]:{"**/*.{py}":"echo 'todo'"}},Te='[\n {\n "Precondition": "前置条件",\n "Title": "用例名称",\n "URL": "接口地址",\n "Data": "接口入参",\n "Method": "接口类型",\n "Expected": "期望结果"\n }\n]',ke="# from assets";var Ne={name:"cli-z-develop",version:"0.9.2",description:"前端本地开发命令行工具",main:"dist/index.js",bin:{z:"bin/z.js","z-develop":"bin/z.js"},scripts:{prepare:"[ -n '$z' ] && z init prepare || echo 'Warning: z not exist at global'",dev:"rollup -c -w --environment DEBUG:true",build:"rollup -c",eslint:"eslint '**/*.{ts,js}' --fix",prettier:"prettier -wu .",upload:"npm run build && npm publish --access public --registry https://registry.npmjs.org/","upload:patch":"npm version patch && npm run upload","upload:minor":"npm version minor && npm run upload","upload:major":"npm version major && npm run upload"},type:"module",author:"z",devDependencies:{"@lonely9/eslint-config-team":"^1.3.5","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^16.0.3","@rollup/plugin-replace":"v6.0.3","@rollup/plugin-terser":"^0.4.4","@tsconfig/node22":"^22.0.5","@types/fs-extra":"^11.0.4","@types/inquirer":"^9.0.9","@types/minimist":"^1.2.5","@types/node":"^22.15.29","@types/semver":"^7.7.1","@types/shelljs":"^0.10.0","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0",eslint:"^9.39.2",jiti:"^2.6.1",prettier:"^3.7.4",rollup:"^4.55.1","rollup-plugin-typescript2":"^0.36.0",typescript:"^5.9.3","vue-tsc":"^3.2.2"},dependencies:{"@inquirer/prompts":"^8.2.0",axios:"^1.13.6",chalk:"^5.6.2",commander:"^14.0.2",dayjs:"^1.11.19","fs-extra":"^11.3.3","inquirer-select-pro":"^1.0.0-alpha.9","lint-staged":"^16.2.7",minimist:"^1.2.8","npm-check-updates":"^19.3.1",ora:"^9.0.0",semver:"^7.7.3",shelljs:"^0.10.0"}};const Ce={profile:{ldapAccount:"",ldapPassword:"",gitToken:"",gitUserId:0,gitName:"",gitEnglishName:"",gitEmail:"",weWorkName:"",weWorkUserId:"",jobType:P.FRONT_END,zenTaoToken:"",k8sToken:""},main:{version:Ne.version,latestCheckVersionTimestamp:0,versionCheckDuring:3,weWorkListCache:[]},constants:{ZenTaoDomain:"",K8sDomain:"",FEServerDomain:"",K8SWebDomain:""}};function De(e){return e?Ce.profile[e]:Ce.profile}function xe(e){return e?Ce.main[e]:Ce.main}function Re(e){return e?Ce.constants[e]:Ce.constants}let Oe=null,Me=null;function ze(){if(Oe)return Oe;const e=r.join("package.json");return n(e)||de(`当前目录(${u.pwd()})不存在${e}文件,请在项目根目录执行该命令。`),Oe=A.readJsonSync(e),Oe}function Ie(){if(Me)return Me;const e=ee();return n(e)||de(`当前目录(${u.pwd()})不存在${e}文件,请在项目根目录执行该命令,或者初始化项目(z init .)。`),Me=A.readJsonSync(e),Me}const Pe={id:0,path:"",group:"",sourceBranch:"",mergeRequestUrl:""};async function Be(){if(!Pe.id)try{const e=se(Ie().repository.url),t=await Ze(e);Pe.id=t.id,Pe.path=e,Pe.group=t.namespace.full_path,Pe.mergeRequestUrl=`${t.web_url}/merge_requests`}catch(e){de(e)}return Pe.sourceBranch||(Pe.sourceBranch=await he("git branch --show-current")),Pe}function _e(){A.writeJSONSync(ie(),{main:xe(),profile:De(),constants:Re()},{spaces:2})}function Fe(e,t){void 0!==t?Ce.profile[e]=t:Ce.profile={...Ce.profile,...e}}function Le(e,t){Ce.constants={...Ce.constants,...e}}function Ue(e,t){void 0!==t?Ce.main[e]=t:Ce.main={...Ce.main,...e}}async function We(e){const t=e.method||"get",n=e.headers||{},a=e.data||{},i=e.dataKey??(["GET","get"].includes(t)?"params":"data");try{const r={url:e.url,method:t,[i]:a,headers:n};c.magenta(r.method.toUpperCase()),c.yellow(r.url),JSON.stringify(r.headers),c.gray(JSON.stringify(r[i],null,2));const o=await s(r);return c.green("Response"),c.grey(JSON.stringify(o.data,null,2)),Promise.resolve(o.data)}catch(e){return e instanceof o&&(c.red("Error"),c.grey(JSON.stringify(e?.response?.data))),Promise.reject(e)}}async function Je(){const e=De("gitToken");if(e)return e;{const{access_token:e}=await We({url:`${F}/oauth/token`,method:"post",data:{grant_type:"password",username:De("ldapAccount"),password:De("ldapPassword")}}),t=`Bearer ${e}`;return Fe("gitToken",t),_e(),t}}async function Ve(e){return We({...e,headers:{Authorization:await Je()}})}async function qe(){const e=De("zenTaoToken");if(e)return e;{const{token:e}=await We({url:`${Re("ZenTaoDomain")}/api.php/v1/tokens`,method:"post",data:{account:De("ldapAccount"),password:De("ldapPassword")}});return Fe("zenTaoToken",e),_e(),e}}async function He(e){const t=await We({...e,headers:{Token:await qe()}});if(!e.url.includes("local")){const{status:n,data:a}=t;if("success"===n){const t=JSON.parse(a);return"用户登录"===t.title?(Fe("zenTaoToken",""),He({...e})):t}return{}}if("string"==typeof t){const e=JSON.parse(t.slice(0,t.indexOf("<script>")));return JSON.parse(e.data)}if("object"==typeof t)return"Unauthorized"===t.error||t.data.indexOf("<script>")<0?(Fe("zenTaoToken",""),He({...e})):t}async function Ge(){const e=De("k8sToken");if(e)return e;{const{access_token:e}=await We({url:`${Re("K8sDomain")}/oauth/login/LDAP`,method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},data:{username:De("ldapAccount"),password:De("ldapPassword")}}),t=`Bearer ${e}`;return Fe("k8sToken",t),_e(),t}}async function Ke(e){const t=await We({...e,headers:{Authorization:await Ge()}});return 401===t.code?(Fe("k8sToken",""),Ke({...e})):t}const Qe=()=>`${F}/api/v4`,Ye=e=>`${Qe()}/projects/100/repository/files/${encodeURIComponent(e)}/raw?ref=master`;function Xe(){return Ve({url:Ye("src/data/z-develop-config.json")})}function Ze(e){return Ve({url:`${Qe()}/projects/${e}`})}async function et(){const e=await Ve({url:`${Qe()}/groups`}),t=L.map((t=>{const n=e.find((e=>e.name===t));return!!n&&{name:n.name,id:n.id,description:n.description}})).filter((e=>Boolean(e)));A.writeJSONSync(ae("fe-groups.json"),{groups:t},{spaces:2})}async function tt(e){const t=`${Re("FEServerDomain")}/api`,{data:n}=await We({url:`${t}/auth/z-develop/login`,method:"post"}),a=await We({url:t+e.url,headers:{Authorization:`Bearer ${n}`},data:e.data,method:e.method||"post"});return 0!==a.code&&de(`${a.code}: ${a.message}`),a.data}function nt(e){return tt({url:"/zen/testcase/product/module/list",data:{product:e}})}async function at(){const e=(await tt({url:"/user/list2"})).filter((e=>[1,2,3,4,5].includes(e.title))).map((e=>({name:`${e.nick} - ${_[e.title]}`,value:e.weWorkUserId}))),t=xe("weWorkListCache"),n=t.map((e=>e.value)),a=[];return e.forEach((e=>{const i=n.indexOf(e.value);a.push({...e,usageCount:i>-1?t[i].usageCount:0})})),a.sort(((e,t)=>t.usageCount-e.usageCount))}async function it(e,t,n){const a=await at();let i=await T({message:e,loop:!0,pageSize:a.length||5,clearInputWhenSelected:!0,multiple:n,options:e=>e?a.filter((t=>t.name.includes(e))):a,validate:t});return i=Array.isArray(i)?i:[i],function(e,t){const n=[];t.forEach((t=>{e.includes(t.value)&&n.push(t)}));const a=xe("weWorkListCache"),i=a.map((e=>e.value));n.forEach((e=>{const t=i.indexOf(e.value);t>-1?a[t].usageCount+=1:a.push({...e,usageCount:1})})),Ue({weWorkListCache:a.sort(((e,t)=>t.usageCount-e.usageCount))}),_e()}(i,a),i}async function rt(e,t,n){const{groups:a}=await Ve({url:Ye("src/data/project-group-chats.json")}),i=a.map((e=>({name:e.name,value:e.url})));let r=await T({message:e,loop:!0,pageSize:i.length||5,clearInputWhenSelected:!0,multiple:n,options:e=>e?i.filter((t=>t.name.includes(e))):i,validate:t});return r=Array.isArray(r)?r:[r],r}async function st(){try{if(re()){await v({message:"系统中已存在z的配置文件,确认重新配置?"})?u.rm("-rf",ie()):process.exit(0)}await d(ae(),{recursive:!0});const e=await $({message:"请选择岗位类型",choices:[{name:"前端",value:P.FRONT_END},{name:"后端",value:P.BACK_END},{name:"测试",value:P.QUALITY_ASSURANCE}]}),t=await b({message:"请输入LDAP账号:"}),n=await E({message:"请输入LDAP密码:",mask:!0});Fe("jobType",e),Fe("ldapAccount",t),Fe("ldapPassword",n);Le(await Xe());const a=await at(),i=await it("请选择你自己(用于企微通知):",(e=>e.length>1?"只能选一个":!(e.length<1)||"请选一个")),{name:r,value:s}=a.find((e=>e.value===i[0]));Fe({weWorkName:r,weWorkUserId:s})}catch(e){de(e)}const e=S("配置信息初始化中").start();try{const t=await Ve({url:`${Qe()}/user`});Fe({gitUserId:t.id,gitName:t.name,gitEnglishName:t.username,gitEmail:t.email}),Ue("latestCheckVersionTimestamp",Date.now()),_e(),De("jobType")===P.FRONT_END&&await et(),e.succeed("配置信息初始化完成"),process.exit(0)}catch(t){e.fail("配置信息初始化失败"),s.isAxiosError(t)&&de("请检查你的域名及令牌配置"),de(t)}}const ot='{\n "$schema": "https://json.schemastore.org/tsconfig",\n "_version": "0.0.1",\n "compilerOptions": {\n "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.browser.tsbuildinfo",\n "lib": ["ESNext", "DOM", "DOM.Iterable", "WebWorker"],\n // 编译时无需导出类型文件\n "noEmit": true,\n\n // 编译时用模块最新规范,至于打包代码时的兼容问题,交给vite/webpack们解决\n "module": "ESNext",\n // 模块解析策略。同上\n "moduleResolution": "bundler",\n // 可以使用import...from导入json文件\n "resolveJsonModule": true,\n // 带上文件后缀,避免歧义。至于兼容性,交给vite/webpack们解决\n "allowImportingTsExtensions": true,\n // 识别一个文件是模块还是脚本,由于使用了打包工具,所以所有文件都是模块\n "moduleDetection": "force",\n\n // tsc编译时不转化jsx,留给打包工具处理\n "jsx": "preserve",\n // 指定处理jsx的库\n "jsxImportSource": "vue",\n\n // 必须显式声明this的类型,否则报错\n "noImplicitThis": true,\n // 严格模式。将默认开启以下规则:\n // noImplicitAny noImplicitThis alwaysStrict strictBindCallApply strictNullChecks strictFunctionTypes strictPropertyInitialization\n "strict": true,\n\n // 引入类型需要type关键字\n "verbatimModuleSyntax": true,\n\n // 编译目标用最新规范,至于打包代码时的兼容问题,交给vite/webpack们解决\n "target": "ESNext",\n // 合理编译class\n "useDefineForClassFields": true,\n\n // commonjs 和 es module之间可以互操作\n "esModuleInterop": true,\n // 引用路径中文件名大小写敏感\n "forceConsistentCasingInFileNames": true,\n // 会检查自建的和依赖库的所有.d.ts。调试自建d.ts文件时可以考虑打开\n "skipLibCheck": true\n }\n}\n',ct='{\n "$schema": "https://json.schemastore.org/tsconfig",\n "_version": "0.0.1",\n "compilerOptions": {\n "lib": ["ESNext"],\n // 编译时无需导出类型文件\n "noEmit": true,\n\n // 编译时用模块最新规范,至于打包代码时的兼容问题,交给vite/webpack们解决\n "module": "ESNext",\n // 模块解析策略。同上\n "moduleResolution": "bundler",\n // 可以使用import...from导入json文件\n "resolveJsonModule": true,\n // 识别一个文件是模块还是脚本,由于使用了打包工具,所以所有文件都是模块\n "moduleDetection": "force",\n\n // 必须显式声明this的类型,否则报错\n "noImplicitThis": true,\n // 严格模式。将默认开启以下规则:\n // noImplicitAny noImplicitThis alwaysStrict strictBindCallApply strictNullChecks strictFunctionTypes strictPropertyInitialization\n "strict": true,\n\n // 引入类型需要type关键字\n "verbatimModuleSyntax": true,\n\n // 编译目标用最新规范,至于打包代码时的兼容问题,交给vite/webpack们解决\n "target": "ESNext",\n // 合理编译class\n "useDefineForClassFields": true,\n\n // commonjs 和 es module之间可以互操作\n "esModuleInterop": true,\n // 引用路径中文件名大小写敏感\n "forceConsistentCasingInFileNames": true,\n // 会检查自建的和依赖库的所有.d.ts。调试自建d.ts文件时可以考虑打开\n "skipLibCheck": true\n }\n}\n';async function lt(e,t){const n=await he("git remote get-url --push origin");n||de("获取项目远程git地址失败,请配置后重试");let a=e;a||(a=await $({message:"请选择项目语言",choices:[{name:B.JAVASCRIPT,value:B.JAVASCRIPT},{name:B.JAVA,value:B.JAVA},{name:B.PYTHON,value:B.PYTHON}]}));let i=t;if(!i){const e=se(n),t=await Ze(e);if(!t)return de(`未找到项目,请确认项目${n}是否存在,或者当前账号权限`);i=t.namespace.full_path}var r;r={language:a,"lint-staged":Ae[a],repository:{url:n,group:i}},Me=Me?{...Me,...r}:r,A.writeJSONSync(ee(),Me,{spaces:2})}async function ut(e,t){if(e)u.rm("-rf",Q);else if(n(Z())){await v({message:`当前项目中已存在配置文件夹${Q},确认重新配置?`})?u.rm("-rf",Q):process.exit(0)}await d(Z(),{recursive:!0}),await lt(e,t),await async function(){await f(te(),"",{mode:493}),await f(Z(".gitignore"),".commit-msg-tpl\n",{mode:493}),await f(Z("commit-msg"),"#!/usr/bin/env sh\nz run commit-msg",{mode:493}),await f(Z("pre-commit"),"#!/usr/bin/env sh\nz run commit-files",{mode:493});const{language:e}=Ie();e===B.JAVASCRIPT&&(await f(Z(".prettierrc.json"),je,{mode:493}),await f(Z(".prettierignore"),Se,{mode:493}),await f(Z("tsconfig.node.json"),ct,{mode:493}),await f(Z("tsconfig.browser.json"),ot,{mode:493})),ne()}(),pe("项目初始化完成")}async function pt(e,t){t.projectLanguage&&!Object.values(B).includes(t.projectLanguage)&&de("项目语言不支持"),e?($e(),"."===e?(await ut(t.projectLanguage,void 0),process.exit(0)):"prepare"===e?await async function(){n(Z())&&n(te())?ne():await ut(),process.exit(0)}():de("参数错误。执行 z init -h 查看帮助。")):await st()}async function mt(e,t){if(!e)return"不能为空";if(!/^[a-z0-9-]+$/.test(e))return"格式为小写字母、中横线(可选)、数字(不推荐)。如apple, apple-tree";if(ge().includes(e))return"当前目录下已存在同名文件夹,请先处理。";var n;const a=(await(n=e,Ve({url:`${Qe()}/projects`,data:{search:n,search_namespaces:!0}}))).find((n=>n.path_with_namespace===`${t}/${e}`));return!a||`远程仓库中已存在同名项目(${a.http_url_to_repo}),请更名后重试`}function dt(e){return!!e||"不能为空"}function ft(e){return e?!!/^[a-zA-Z0-9.]+$/.test(e)||"格式为大小写字母、数字、小数点,小驼峰命名。如userInfo、systemRouter3":"不能为空"}e.command("init").alias("i").argument("[type]","非必填。不传为初始化全局配置;传 . 为初始化当前项目;传 prepare 为初始化GIT HOOKS").option("--project-language",`项目语言。可选值:${Object.values(B).join("/")} `).description("初始化工具配置、项目配置").action(((...e)=>Ee(pt,...e)));const gt=e=>`${Re("ZenTaoDomain")}${e}`;async function ht(e,t){let n="";if([U.FEAT,U.FIX,U.REFACTOR].includes(e)){n=`${e}(${t.map((e=>e.value)).join(",")}): ${t.map((e=>e.name)).join(";")}`}e===U.CHORE&&(n=`${e}: ${t}`),await f(te(),n,"utf-8"),console.log(c.yellow(n)),pe("commit msg模板写入成功,可以进行提交了")}async function wt(){const e=await $({message:"请选择你要创建的模板类型",choices:[{name:"feat - 业务需求/功能开发/BUG修复",value:U.FEAT},{name:"fix - bug修复",value:U.FIX},{name:"refactor - 技术重构/性能优化/代码规范",value:U.REFACTOR},{name:"chore - 其他",value:U.CHORE}]});if([U.FEAT,U.REFACTOR].includes(e)){const e=await async function(){const e=await He({url:gt("/my-work-task.json?tid=mrrferp8"),method:"get"});return e?.tasks?e.tasks.filter((e=>"done"!==e.status)).map((({id:e,name:t})=>({value:{name:t,value:e},name:t}))):[]}();if(!e.length)return pe("🤷 暂无开发任务");const t=await j({message:"请关联开发任务(可多选):",validate:e=>0!==e.length||"请选择项",choices:e.map((e=>({...e,name:`[${e.value.value}]: ${e.name}`}))),pageSize:e.length});await ht(U.FEAT,t)}if(e===U.FIX){const e=await async function(){const e=await He({url:gt("/my-work-bug.json?tid=mrrferp8"),method:"get"});return e?.bugs?Object.values(e.bugs).map((({id:e,title:t})=>({name:t,value:{name:t,value:e}}))):[]}();if(!e.length)return pe("🤷 暂无BUG");const t=await j({message:"请关联Bug(可多选):",validate:e=>0!==e.length||"请选择项",choices:e.map((e=>({...e,name:`[${e.value.value}]: ${e.name}`}))),pageSize:e.length});await ht(U.FIX,t)}if(e===U.CHORE){const e=await b({message:"请输入commit msg:",validate:e=>0!==e.length||"请输入commit msg"});await ht(U.CHORE,e)}process.exit(0)}async function yt(){try{const a={},i=async()=>{const e=ge(),{projects:t}=await Ve({url:Ye("src/data/template-projects.json")}),n=t.map((t=>{const n={name:`${t.name} [${t.desc}]`,value:t.name,disabled:!1};return e.includes(t.name)&&(n.disabled="目录下已存在同名文件夹"),n})),i=await $({message:"请选择一个项目模板",choices:n}),r=t.find((e=>e.name===i));a.tplName=r.name,a.tplUrl=r.url,a.tplLanguage=r.language},s=async()=>{const{groups:e}=function(){const e=ae("fe-groups.json");return n(e)?A.readJSONSync(e):{groups:[]}}(),t=await $({message:"请选择一个分组",choices:e.map((e=>({name:`${e.name} [${e.description}]`,value:e.id,short:e.name})))});a.group={id:t,name:e.find((e=>e.id===t))?.name}},o=async()=>{a.projectName=await b({message:"请输入项目名称",validate:e=>mt(e,a.group?.name||"")}),a.projectDesc=await b({message:"请输入项目描述",validate:dt})};await i(),await s(),await o();const l=`${F}/${a.group?.name}/${a.projectName}.git`,p=S("模版初始化中").start();await he(`git clone --depth=1 ${a.tplUrl}`),await g(a.tplName,a.projectName),u.cd(a.projectName),u.rm("-rf",".git"),await he(`git init --initial-branch=${R.MASTER}`),await he(`git remote add origin ${l}`),await he(`git config user.name ${De("gitName")}`),await he(`git config user.email ${De("gitEmail")}`);const m=ze();t={...m,name:a.projectName,description:a.projectDesc,scripts:{...m.scripts,prepare:"[ -n '$z' ] && z init prepare || echo 'Warning: z not exist at global'"}},Oe=Oe?{...Oe,...t}:t,A.writeJSONSync(r.join("package.json"),Oe,{spaces:2}),await A.writeFile(r.resolve("README.md"),function(e="项目中文名",t="项目描述"){return`\n# ${e}\n${t}\n\n## 快速开始\n### 安装依赖\n\`\`\`bash\n npm i\n\`\`\`\n\n### 本地开发\n\`\`\`bash\n npm run dev:<environment>:[platform]\n\`\`\`\n\n### 打包代码\n\`\`\`bash\n npm run build:<environment>:[platform]\n\`\`\`\n\n\n### 查找、修复代码问题\n\`\`\`bash\n z run eslint\n # 或者\n z r e\n\`\`\`\n\n### 格式化代码\n\`\`\`bash\n z run prettier\n # 或者\n z r p\n\`\`\`\n\n### 检测类型问题\n\`\`\`bash\n z run type-check\n # 或者\n z r tc\n\`\`\`\n\n### 检测依赖更新\n\`\`\`bash\n z run dependency-check\n # 或者\n z r dc\n\`\`\`\n\n## 常见问题\n列出开发中常见的问题和解决方案\n\n## 了解更多\n在此处放入飞书文档链接。请在[前端团队-项目手册](https://hxhtbr8t8uy.feishu.cn/drive/folder/QfQ7favVWljQk7d63Prc8mUGnJf)中按照分类新建文档。\n`}(a.projectName,a.projectDesc)),p.succeed("模版初始化完成"),await ut(a.tplLanguage,a.group?.name);const d=S("依赖安装中").start();await he("npm install --registry https://registry.npmmirror.com/"),d.succeed("依赖安装完成");const f=S("项目推送中").start();await he('git add . && git commit -m "chore: 项目初始化"'),await he("git tag v0.0.1");const h=await(e={name:a.projectName,description:a.projectDesc,path:a.projectName,visibility:"private",namespace_id:a.group?.id},Ve({url:`${Qe()}/projects`,method:"post",data:e}));await he(`git push -u origin ${R.MASTER}`),await he(`git push origin HEAD:${R.MASTER} --tags`),f.succeed(`项目已推送到远程,地址: ${c.blue(l)}`);const w=S("初始化分支中").start(),y=`feat_init_${ye()}`,v=[R.DEV,R.TEST,R.RELEASE,y],E=await Promise.allSettled(v.map((e=>function(e){return Ve({url:`${Qe()}/projects/${e.id}/repository/branches`,method:"post",data:e})}({id:h.id,branch:e,ref:R.MASTER})))),j=[];E.forEach((({status:e},t)=>{"fulfilled"===e&&j.push(v[t])})),await he("git pull"),j.includes(y)?(await he(`git checkout -b ${y} origin/${y}`),w.succeed(`项目已切换到初始分支: ${c.blue(y)}`)):w.warn("开发分支检出失败!项目当前在主分支,请自行检出开发分支。");const T=`cd ${a.projectName} && z start`;console.log(`输入 ${c.green(T)} 开始开发吧~`),process.exit(0)}catch(e){de(e)}var e,t}var vt,$t;async function bt(e,t){let n;e?[vt.Project,vt.ProjectAbbr].includes(e)?n=vt.Project:[vt.Branch,vt.BranchAbbr].includes(e)?n=vt.Branch:[vt.CommitMsg,vt.CommitMsgAbbr].includes(e)?n=vt.CommitMsg:de("参数输入错误"):n=await $({message:"请选择你要创建的类型",choices:[{name:"提交信息(commit message)",value:vt.CommitMsg},{name:"分支(branch)",value:vt.Branch},{name:"项目(project)",value:vt.Project}]}),n===vt.Project?await yt():(ve(),$e(),n===vt.Branch?(await be(),await async function(e){let t,n;ve(),$e(),await be(),t=e.branchType?e.branchType:await $({message:"请选择创建分支的类型",choices:[{name:"开发新功能(feat)",value:I.FEAT},{name:"修复BUG(fix)",value:I.FIX},{name:"重构/优化代码(refactor)",value:I.REFACTOR}]}),n=e.branchPurpose?e.branchPurpose:await b({message:"请输入创建分支的目的(大小写字母、数字,小驼峰式命名。如userInfo)",validate:ft});const a=`${t}_${n}_${ye()}`;await he(`git fetch origin ${R.MASTER}`),await he(`git checkout -b ${a} origin/${R.MASTER}`),await he(`git push -u origin ${a}`),process.exit(0)}(t)):n===vt.CommitMsg&&await wt())}function Et(e){return Ke({url:`${Re("K8sDomain")}/kapis/clusters/youshou-local/devops.kubesphere.io/v1alpha3/namespaces/${W}/pipelines/${e.projectName}/pipelineruns?branch=${e.branchName}`,method:"post",data:e.params})}async function jt(e,t){ve(),$e(),await be();let n=e,a=t.platform;if(n&&!Object.values(R).includes(n)&&de("仅支持发布指定环境分支"),a&&!Object.values(O).includes(a)&&de("发布平台错误"),a||(a=await $({message:"请选择平台",choices:z})),a===O.NPM&&(n=R.MASTER),!n){const e=await $({message:"请选择部署环境",choices:M});n=(i=e)===x.PROD?R.MASTER:i}var i;let r=[];t.skipSelectionNotification||(r=await it("请选择部署成功要通知的人员:",(()=>!0),!0));let s=[];t.skipGroupNotification||(s=await rt("请选择部署成功要通知的群组:",(()=>!0),!0));var o;!function(e,t){const n=ze(),a=Ie();if(a?.repository?.url||de(".z/project.json中缺少repository.url"),t===O.H5){const t=`build:${e}`;n?.scripts[t]||de(`项目package.json文件scripts不存在命令${t}。`)}t===O.NPM&&(n?.scripts.build||de("项目package.json文件scripts不存在命令build。")),t===O.SERVER&&(n?.scripts.build||de("项目package.json文件scripts不存在命令build。"))}((o=n)===R.MASTER?x.PROD:o,a);const l=ze();await async function(e){const t=S("部署任务创建中").start(),{targetBranch:n,notify:a,projectName:i}=e,r=a?[...new Set([De("weWorkUserId"),...a])]:[De("weWorkUserId")];try{const{metadata:a,spec:s}=await Et({projectName:i,branchName:n,params:{parameters:[{name:"QW_NOTIFY_USER",value:r.join(",")},{name:"QW_NOTIFY_GROUP",value:e.notifyGroup.join(",")}]}}),o=`${Re("K8SWebDomain")}/youshou-local/clusters/youshou-local/devops/${a.namespace}/pipelines/${s.pipelineRef.name}/branch/${s.scm.refName}/run/${a.name}/task-status`;t.succeed("部署任务创建完成"),console.log(`如有需要,可在k8s中查看 ${c.blue(o)}`),process.exit(0)}catch(e){t.fail("部署任务创建失败"),de(e)}}({projectName:l.name,targetBranch:n,notify:r,notifyGroup:s})}async function St(e,t,n,a){const i=S(`分支合并中,${e} -> ${t}`).start();let r=0;try{const{iid:i}=await(o={title:`${e} -> ${t} by z-develop`,id:n.id,source_branch:e,target_branch:t,remove_source_branch:!a&&R.MASTER===t},Ve({url:`${Qe()}/projects/${o.id}/merge_requests`,method:"post",data:o}));r=i}catch(e){if(s.isAxiosError(e)){const t=e?.response?.status;409===t&&de(`存在重复的合并请求,前往查看${n.mergeRequestUrl}`)}de(e)}var o;const c=async()=>{try{await new Promise((e=>{setTimeout(e,5e3)})),await function(e){return Ve({url:`${Qe()}/projects/${e.id}/merge_requests/${e.iid}/merge`,method:"put"})}({id:n.id,iid:r}),i.succeed(`分支${e}已合并到分支${t}`)}catch(e){s.isAxiosError(e)||de(e);const t=e?.response?.status;if(406===t)return await c();if(await function(e){return Ve({url:`${Qe()}/projects/${e.id}/merge_requests/${e.iid}`,method:"put",data:e})}({id:n.id,iid:r,state_event:"close"}),405===t){const e=await function(e){return Ve({url:`${Qe()}/projects/${e.id}/merge_requests/${e.iid}`,method:"get"})}({id:n.id,iid:r});if("cannot_be_merged"===e.merge_status&&e.diff_refs.base_sha===e.diff_refs.head_sha)return void i.warn("MR已关闭。判定为空的合并请求(没有新内容),可继续进行部署")}i.fail("合并过程中出现冲突,MR已关闭。建议在本地完成合并。"),process.exit(1)}};await c()}async function At(e,t){ve(),$e(),await be();const n=await Be();Object.values(R).includes(n.sourceBranch)&&de(`当前分支${n.sourceBranch}不可作为源分支合并到目标分支。`);var a;const i=(await(a=n.id,Ve({url:`${Qe()}/projects/${a}/repository/branches`}))).filter((e=>![n.sourceBranch].includes(e.name))).map((e=>{let t=e.name;return Object.values(R).includes(t)&&(t=c.bold.blue(t)),{name:t,value:e.name}}));let r;e&&!i.filter((t=>t.value===e)).length&&de(`未找到目标分支${e}`),r=e||await $({message:"请选择要合并到的目标分支:",choices:i});const s=S(`本地分支${n.sourceBranch}检测中`).start();if(await he(`git ls-remote --heads origin ${n.sourceBranch}`)){s.text=`存在远程分支origin/${n.sourceBranch}`,await he("git fetch");const e=await he(`git rev-parse ${n.sourceBranch}`),t=await he(`git rev-parse origin/${n.sourceBranch}`);if(await he(`git merge-base ${t} HEAD`)===t)await he(`git push -u origin ${n.sourceBranch}`),s.succeed(`本地分支${n.sourceBranch}已推送到远程分支origin/${n.sourceBranch}`);else{await he(`git merge-base ${e} ${t}`)===e?(await he("git pull"),s.succeed(`本地分支${n.sourceBranch}已更新`)):(s.fail(`远程分支origin/${n.sourceBranch}和本地分支${n.sourceBranch}都有新的提交,请手动合并后再试。`),process.exit(1))}}else await he(`git push -u origin ${n.sourceBranch}`),s.succeed(`本地分支${n.sourceBranch}已推送到远程分支origin/${n.sourceBranch}`);await async function(e,t){const n=`origin/${e.sourceBranch}`,a=await he(`git log -b origin/${R.MASTER} -1 --format=%H`),i=await he(`git log -b origin/${e.sourceBranch} -1 --format=%H`),r=await he(`git log ${a}...${i} -b ${n}`);if(r||de(`分支${e.sourceBranch}上不存在新的commit,不需要合并。`),await he(`git branch --contains ${a} -r ${n}`)||(console.log(c.yellow("注意:当前分支上不存在远程主分支最新代码,将在自动合入后继续。")),await St(R.MASTER,e.sourceBranch,e)),t===R.MASTER){const e=r.split("\n").filter((e=>e)),t=await he(`git log -b origin/${x.TEST} -1 --format=%H`);(function(e,t){for(const n of t)if(!e.includes(n))return!1;return!0})((await he(`git log ${a}...${t} -b origin/${x.TEST}`)).split("\n").filter((e=>e)),e)||de("请先在测试环境发布要部署的代码")}}(n,r),await St(n.sourceBranch,r,n,t.keepBranchAfterMergeMaster),R.MASTER!==r||t.keepBranchAfterMergeMaster||(await he(`git checkout ${R.MASTER}`),await he(`git pull origin ${R.MASTER}`),await he(`git branch -d ${n.sourceBranch}`),pe(`${n.sourceBranch}分支已移除,当前已切换到最新的${R.MASTER}。如需继续开发,请检出新分支(z c b)。`)),Object.values(R).includes(r)&&await jt(r,{platform:t.deployPlatform,skipSelectionNotification:t.deploySkipSelectionNotification,skipGroupNotification:t.skipGroupNotification})}function Tt(){const e=ee();if(n(e)){const t=A.readJsonSync(e);if(t["lint-staged"])return t["lint-staged"];throw new Error("未找到lint配置")}throw new Error("请先初始化项目(z i .)。")}async function kt(){const e=function(e){if(e.includes("Merge")&&e.includes("# Conflicts:"))return!0;if(N.valid(e))return!0;const t=e.split(": ");if(1===t.length)return"body前缺少「: 」";const n=t[0];return/^(feat|fix|refactor)/.test(n)?!!/\(\d+(?:,\d+)*\)/.test(n)||"ID缺少或者格式不正确。":/^(chore|ci)/.test(n)?!![U.CHORE,U.CI].includes(n)||"chore/ci类型无需填写ID。":U.Break===n||"不存在的提交类型。"}(await h(r.resolve(".git","COMMIT_EDITMSG"),"utf-8"));!0===e?(pe("提交信息格式校验通过 ✅ "),process.exit(0)):de(`提交信息格式校验失败。${e}`)}async function Nt(e,t){let a;ve(),$e(),e?[$t.CommitMsg,$t.CommitMsgAbbr].includes(e)?a=$t.CommitMsg:[$t.CommitFiles,$t.CommitFilesAbbr].includes(e)?a=$t.CommitFiles:[$t.Prettier,$t.PrettierAbbr].includes(e)?a=$t.Prettier:[$t.Eslint,$t.EslintAbbr].includes(e)?a=$t.Eslint:[$t.TypeCheck,$t.TypeCheckAbbr].includes(e)?a=$t.TypeCheck:[$t.DependencyCheck,$t.DependencyCheckAbbr].includes(e)?a=$t.DependencyCheck:de("参数输入错误"):a=await $({message:"请选择你要执行的操作",choices:[{name:"执行 prettier",value:$t.Prettier},{name:"执行 eslint",value:$t.Eslint},{name:"执行 type-check",value:$t.TypeCheck},{name:"执行 dependency-check",value:$t.DependencyCheck}]}),a===$t.CommitMsg?await kt():a===$t.CommitFiles?await async function(){await k({concurrent:4,debug:!1,config:Tt(),quiet:!0,relative:!0})?(pe("代码风格检测通过!"),process.exit(0)):de("代码风格检测未通过!")}():a===$t.Prettier?await async function(){n(r.resolve("node_modules",".bin","prettier"))||de("该项目未安装prettier,请安装后重试");try{await he("npx prettier --write . --config .z/.prettierrc.json --ignore-path .z/.prettierignore --ignore-unknown --no-error-on-unmatched-pattern",{silent:!1}),pe("prettier执行成功"),process.exit(0)}catch(e){de("prettier校验出错")}}():a===$t.Eslint?await async function(e){n(r.resolve("node_modules",".bin","eslint"))||de("该项目未安装eslint,请安装后重试");try{let t="npx eslint '**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}' --fix";"win32"===process.platform&&(t='npx eslint "**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}" --fix'),e.quiet&&(t+=" --quiet"),e.maxWarnings&&!isNaN(Number(e.maxWarnings))?t+=` --max-warnings ${Number(e.maxWarnings)}`:t+=" --max-warnings 100",await he(t,{silent:!1}),pe("eslint执行成功"),process.exit(0)}catch(e){de("eslint校验出错")}}(t):a===$t.TypeCheck?(n(r.resolve("./node_modules/.bin/vue-tsc"))||de("请先安装vue-tsc。推荐命令: npm i -D vue-tsc"),we("npx vue-tsc --build"),process.exit(0)):a===$t.DependencyCheck&&await async function(){await be();const e=await C({format:["group","repo"],interactive:!0,upgrade:!0,install:"always"});if(e&&Object.keys(e).length){pe("升级完成 🎉");const t=Object.entries(e).map((([e,t])=>`${e}@${t}`)).join("; ");await he(`git add . && git commit -m "chore: 依赖升级。${t}"`)}process.exit(0)}()}async function Ct(e="latest"){await he(`npm i -g ${Ne.name}@${e} --registry https://registry.npmmirror.com/`),Ue("latestCheckVersionTimestamp",Date.now()),Ue("version",e),_e(),pe(`升级完成,当前版本${e}`),process.exit(0)}async function Dt(e){let t=e;t?[x.DEV,x.TEST,x.RELEASE,x.PROD,"d","t","r","p"].includes(e)?"d"===t?t=x.DEV:"t"===t?t=x.TEST:"r"===t?t=x.RELEASE:"p"===t&&(t=x.PROD):de("参数输入有误"):t=await $({message:"请选择环境",choices:M});const n=`dev:${t}`;ze().scripts[n]?we(`npm run ${n}`):de(`项目中(package.json > scripts)不存在命令${n},请先添加!`)}!function(e){e.Project="project",e.ProjectAbbr="pr",e.Branch="branch",e.BranchAbbr="b",e.CommitMsg="commit-msg",e.CommitMsgAbbr="cm"}(vt||(vt={})),e.command("create").alias("c").argument("[type]","可选值为project|pr, branch|b, commit-msg|cm").option("--branch-type <type>",`分支类型。可选值:${Object.values(I).join(", ")}`).option("--branch-purpose <purpose>","创建分支的目的").description("创建项目/分支/提交信息").action(((...e)=>Ee(bt,...e))),e.command("merge").alias("m").argument("[branch]","目标分支名称").option("--deploy-platform <platform>",`合并成功后要部署的平台。可选值:${Object.values(O).join("/")}`).option("--deploy-skip-selection-notification","部署时,是否跳过选择部署通知人环节").option("--skip-group-notification","是否跳过选择部署通知群聊环节").option("--keep-branch-after-merge-master","在合并到主分支之后,是否保留分支。默认否").description("合并当前分支到指定远程分支,并部署。").action(((...e)=>Ee(At,...e))),e.command("deploy").alias("d").description("部署到指定环境").argument("[branchName]",`部署环境。可选值:${Object.values(R).join("/")}`).option("--platform <platform>",`部署平台。可选值:${Object.values(O).join("/")}`).option("--skip-selection-notification","是否跳过选择部署通知人环节").option("--skip-group-notification","是否跳过选择部署通知群聊环节").action(((...e)=>Ee(jt,...e))),function(e){e.CommitMsg="commit-msg",e.CommitMsgAbbr="cm",e.CommitFiles="commit-files",e.CommitFilesAbbr="cf",e.Prettier="prettier",e.PrettierAbbr="p",e.Eslint="eslint",e.EslintAbbr="e",e.TypeCheck="type-check",e.TypeCheckAbbr="tc",e.DependencyCheck="dependency-check",e.DependencyCheckAbbr="dc"}($t||($t={})),e.command("run").aliases(["r","l","lint"]).argument("[type]","非必填。可选值为commit-msg|cm, commit-files|cf, prettier|p, eslint|e, type-check|tc, dependency-check|dc。").option("--quiet","eslint只打印error").option("--max-warnings [VALUE]","eslint结果warn超过多少个会异常退出,默认为100",parseInt).description("执行 eslint / prettier / type-check / dependency-check 脚本。").action(((...e)=>Ee(Nt,...e))),e.command("update").alias("u").argument("[version]","版本号","latest").description("升级").action(((...e)=>Ee(Ct,...e))),e.command("start").alias("s").description("启动本地开发环境").argument("[env]","业务环境。可选值 dev|d, test|t, release|r, prod|p").action(((...e)=>Ee(Dt,...e)));const xt=/Thumbs\.db|\.git|DS_Store|idea/,Rt="testcase";function Ot(e){const t=e.match(/^(.*[^[])?\[(\d+)]$/);if(t&&!e.startsWith("["))return{type:"module",id:t[2],displayName:t[1]?.trim()||""};const n=e.match(/^\[(\d+)](.+)$/);return n?{type:"case",id:n[1],displayName:n[2]?.trim()||""}:{type:"directory",id:void 0,displayName:e}}async function Mt(e,t={}){const{exclude:n=xt}=t,a=[];return await async function i(s){const o=r.basename(s);if((await y(s)).isFile())return null;const c=await w(s,{withFileTypes:!0}),l=(await Promise.all(c.filter((e=>e.isDirectory()&&!n.test(e.name))).map((e=>i(r.join(s,e.name)))))).filter(Boolean),{type:u,id:p,displayName:m}=Ot(o),d={name:o,id:p,displayName:m,path:s,type:u,children:l};return(t.hasRoot||r.resolve(e)!==s)&&a.push(d),d}(r.resolve(e)),a}async function zt(e,t={}){const{exclude:n=xt}=t;try{const t=await w(r.resolve(e),{withFileTypes:!0});return await Promise.all(t.filter((e=>e.isDirectory()&&!n.test(e.name))).map((t=>{const n=r.join(e,t.name),{type:a,id:i,displayName:s}=Ot(t.name);return{name:t.name,id:i,displayName:s,path:n,type:a}})))}catch(t){return de(`读取目录失败: ${e} : ${t}`),[]}}function It(e,t,n){switch(e){case"module":return n?`${t}[${n}]`:t;case"case":return n?`[${n}]${t}`:t;default:return t}}async function Pt(e,t,n,a){try{const i=r.basename(e),s=r.dirname(e),o=It(n,t,a),c=r.join(s,o);return i===o||(await he(`git mv "${e}" "${c}"`),await he("git add .")),!0}catch(n){return de(`Git重命名文件夹失败: ${e} -> ${t}。${n}`),!1}}async function Bt(e){const t={id:0,name:"",path:""};if(e)Number.isNaN(Number(e))&&de("请输入正确的产品ID"),t.id=Number(e);else{const e=await tt({url:"/zen/testcase/product/list"});t.id=await $({message:"请选择产品",choices:e.map((e=>({name:`${e.label}[${e.value}]`,value:e.value})))})}return t.name=await function(e){return tt({url:"/zen/testcase/product/name",data:{product:e}})}(t.id),t.path=r.join(Rt,It("module",t.name,String(t.id))),t}async function _t(e){return(await zt(Rt)).find((t=>Number(t.id)===e.id))}async function Ft(e,t){const n={precondition:e.precondition,priority:e.pri,steps:[]};var a;n.steps=await(a=e.id,tt({url:"/zen/testcase/step/list",data:{id:a}})),A.writeJSONSync(t,n,{spaces:2})}async function Lt(e,t){await d(t,{recursive:!0}),await Ft(e,r.join(t,"config.json")),A.ensureFileSync(r.join(t,"data.json")),await f(r.join(t,"data.json"),n(r.resolve(Q,"data.json"))?await h(r.resolve(Q,"data.json")):Te),A.ensureFileSync(r.join(t,"main.py")),await f(r.join(t,"main.py"),n(r.resolve(Q,"main.py"))?await h(r.resolve(Q,"main.py")):ke)}async function Ut(e,t){await _t(e)||de(`本地未找到产品【${e.name}[${e.id}]】`);let n=[];if(t){const e=t.split(",").map((e=>e.trim())).filter((e=>{const t=Number(e);return Number.isInteger(t)&&t>0})).map((e=>Number(e)));if(0===e.length)return de('未找到有效的用例ID,请输入格式如 "1,2,3,4" 的正整数ID');n=e}let a=await Mt(e.path);const i=await function(e,t){return tt({url:"/zen/testcase/product/auto-case/list",data:{product:e,caseIds:t}})}(e.id,n);for(const t of i){let n;if(n=0===t.module?r.resolve(e.path):a.find((e=>Number(e.id)===t.module))?.path||"",!n)return de(`用例${t.title}[${t.id}]未找到所属模块(${t.module}),请先拉取模块`);const i=a.find((({id:e})=>t.id===Number(e)));if(i){if(i.displayName!==t.title){await Pt(i.path,t.title,i.type,i.id)&&pe(`重命名成功: ${i.displayName} -> ${t.title}`)}a=await Mt(e.path),n=0===t.module?r.resolve(e.path):a.find((e=>Number(e.id)===t.module))?.path||"",await Ft(t,r.join(n,It("case",t.title,String(t.id)),"config.json"))}else{const e=r.join(n,It("case",t.title,String(t.id)));await Lt(t,e)}}}async function Wt(e){const t=await _t(e);if(t){if(t.displayName!==e.name){await Pt(t.path,e.name,t.type,t.id)&&pe(`重命名成功: ${t.displayName} -> ${e.name}`)}}else await d(e.path,{recursive:!0}),await he("git add .");const n=await nt(e.id);await async function(e,t,n={}){const{exclude:a=xt}=n;await async function e(t,n){if(!t||0===t.length)return;const i=await zt(n,{exclude:a});for(const a of t){const t=String(a.value),s=It("module",a.label,t),o=i.find((e=>e.id===t));let c=o?.path||r.join(n,s);o?o.displayName!==a.label&&await Pt(o.path,a.label,"module",t)&&(c=r.join(n,s)):(await d(c,{recursive:!0}),await he(`git add "${c}"`)),a.children&&a.children.length>0&&await e(a.children,c)}}(e,r.resolve(t))}(n||[],e.path)}async function Jt(e,t){let n;ve(),$e(),await be(),e?([V.MODULE,V.CASE].includes(e)||de(`不支持的参数${e}。同步类型参数为 ${V.MODULE} 或者 ${V.CASE}。`),n=e):n=await $({message:"请选择拉取数据类型",choices:q});const a=await Bt(t.productId),i=n===V.MODULE?"模块":V.CASE===n?"用例":"",r=S(`${i}同步中`).start();V.MODULE===n&&await Wt(a),V.CASE===n&&await Ut(a,t.caseIds),r.succeed(`${i}同步完成 🎉`),!t.disableAutoCommit&&await he("git status -s")&&(await he('git add . && git commit -m "chore: 同步禅道数据"'),pe("代码已提交"))}async function Vt(e,t,a){const i=await b({message:"请输入你要创建的用例的前置条件(可不填)"}),s=S(`用例【${a}】创建中`).start(),o=await(c={product:Number(e.id),module:r.resolve(e?.path)===t?.path?0:Number(t?.id||0),title:a,type:"interface",openedBy:De("ldapAccount"),precondition:i||""},tt({url:"/zen/testcase/create",data:c}));var c;await function(e){return tt({url:"/zen/testcase/step/create",data:e})}({case:o,type:"step",desc:"按照预期执行",expect:"正常执行,符合预期"});const l=r.join(t.path,It("case",a,String(o)));if(n(l))return pe(`${l}已存在,请检查是否对应,本地不再创建。`);await Lt({id:o,pri:3,precondition:i},l),s.succeed(`用例【[${l}】创建完成 🎉`)}async function qt(e,t,a){const i=S(`模块【${a}】创建中`).start(),s=await(o={root:Number(e.id),name:a,parent:r.resolve(e?.path)===t?.path?0:Number(t?.id||0)},tt({url:"/zen/testcase/module/create",data:o}));var o;const c=r.join(t.path,It("module",a,String(s)));if(n(c))return pe(`${c}已存在,请检查是否对应,本地不再创建。`);await d(c,{recursive:!0}),i.succeed(`模块【${c}】创建完成 🎉`)}async function Ht(e,t){let a;ve(),$e(),await be(),e?([V.MODULE,V.CASE].includes(e)||de(`不支持的参数${e}。同步类型参数为 ${V.MODULE} 或者 ${V.CASE}。`),a=e):a=await $({message:"请选择拉创建的数据类型",choices:H});const i=a===V.MODULE?"模块":V.CASE===a?"用例":"",r=await Bt(t.productId),s=await _t(r);if(!s)return de(`本地未找到产品【${r.name}[${r.id}]】`);const o=await nt(r.id),c=await(l=o,async function e(t,n=[]){const a=n.length?`请选择层级(当前:${n.join(" / ")})`:"请选择层级",i=await $({message:a,choices:t.map((e=>({name:`${e.tempTitle?e.tempTitle:e.label} ${e.children?.length?"(有子级)":""}`,value:e})))});return i?.children?.length?(function(e){if(!e.children||0===e.children.length)return;const t=e.children[0];t&&t.label===e.label&&t.value===e.value&&(!t.children||0===t.children.length)||e.children.unshift({value:e.value,label:e.label,type:e.type,children:void 0,tempTitle:"当前层级"})}(i),e(i.children,[...n,i.label])):i}(l));var l;const u=It("module",c.label,String(c.value)),p=(await Mt(r.path,{hasRoot:!0})).find((e=>e.name===u));if(!p?.path||!n(p.path))return de(`本地不存在${u}模块`);const m=await b({message:`请输入你要创建的${i}名称`,required:!0,validate:e=>e.length>0&&e.length<255});V.MODULE===a&&await qt(s,p,m),V.CASE===a&&await Vt(s,p,m),t.disableAutoCommit||V.CASE!==a||(await he('git add . && git commit -m "chore: 同步创建的用例"'),pe("代码已提交"))}async function Gt(){const e=D(process.argv.slice(2));if(!(e.h||e.help||e.v||e.version)&&(!["init","i"].includes(e._[0])||[".","prepare"].includes(e._[1])))if(re()){const e=A.readJSONSync(ie());Fe(e.profile),Ue(e.main),Le(e.constants),await async function(){const e=xe("latestCheckVersionTimestamp"),t=xe("versionCheckDuring");if(Date.now()-Number(e)>24*Number(t)*3600*1e3){let e;Le(await Xe());try{const t="TIME_OUT",n=new Promise((e=>{setTimeout((()=>e(t)),3e3)}));e=await Promise.race([n,he(`npm view ${Ne.name} version --registry https://registry.npmmirror.com/`)]),e!==t&&e!==Ne.version&&(console.log(`${c.blue(Ne.name)}本地版本为${Ne.version},低于线上版本${e},开始升级`),await Ct(e)),Ue("latestCheckVersionTimestamp",Date.now()),_e()}catch(e){console.log("升级出错!请重试,或者手动升级"),de(e)}}}()}else de(`请先初始化z-develop(执行 z i)。更多见${J}`)}e.command("qa-pull").alias("qp").argument("[type]","可选值为module/case").option("--product-id <productId>","指定产品ID").option("--case-ids <caseIds>","type=case时,可传指定用例ID(可传N个,逗号隔开);不传则为产品下全部用例").option("--disable-auto-commit","是否跳过自动将修改结果提交。").description("将禅道中的模块或者用例同步到本地").action(((...e)=>Ee(Jt,...e))),e.command("qa-create").alias("qc").argument("[type]","可选值为module/case").option("--product-id <product>","指定产品ID").option("--disable-auto-commit","是否跳过自动将修改结果提交。").description("创建模块或者用例").action(((...e)=>Ee(Ht,...e))),e.name("z-develop").alias("z").description(`z-develop, 开发流程管理工具。了解更多: ${c.blue(J)}`).usage("<command> [options]").hook("preAction",(async function(){process.on("unhandledRejection",(e=>{})),process.on("uncaughtException",(e=>{})),u.config.fatal=!0,u.config.silent=!0,u.config.verbose=Boolean(void 0)||!1,await Gt()})).version(Ne.version,"-v, --version","当前版本号").helpOption("-h, --help","帮助").showHelpAfterError("可以使用z -h查看帮助。"),e.parse();
1
+ import { program as x } from "commander";
2
+ import yt from "node:child_process";
3
+ import { existsSync as $, readdirSync as $t, lstatSync as vt } from "node:fs";
4
+ import { readdir as je, mkdir as se, writeFile as M, rename as Fe, readFile as Se, stat as bt } from "node:fs/promises";
5
+ import l from "node:path";
6
+ import le, { AxiosError as Nt } from "axios";
7
+ import N from "chalk";
8
+ import St from "dayjs";
9
+ import D from "shelljs";
10
+ import jt from "node:os";
11
+ import Le from "child_process";
12
+ import { confirm as _e, select as E, input as _, password as At, checkbox as Pe, number as Oe } from "@inquirer/prompts";
13
+ import w from "ora";
14
+ import j from "fs-extra";
15
+ import { select as re } from "inquirer-select-pro";
16
+ import Et from "lint-staged";
17
+ import Tt from "semver";
18
+ import { run as kt } from "npm-check-updates";
19
+ import Ct from "minimist";
20
+ const Be = "dev", Ue = "test", Je = "release", Rt = "production", It = "master";
21
+ var v = /* @__PURE__ */ ((e) => (e[e.DEV = Be] = "DEV", e[e.TEST = Ue] = "TEST", e[e.RELEASE = Je] = "RELEASE", e[e.PROD = Rt] = "PROD", e))(v || {}), h = /* @__PURE__ */ ((e) => (e[e.DEV = Be] = "DEV", e[e.TEST = Ue] = "TEST", e[e.RELEASE = Je] = "RELEASE", e[e.MASTER = It] = "MASTER", e))(h || {}), H = /* @__PURE__ */ ((e) => (e.H5 = "h5", e.NPM = "npm", e.SERVER = "server", e))(H || {});
22
+ const Ge = [
23
+ {
24
+ name: `开发环境 - ${v.DEV}`,
25
+ value: v.DEV
26
+ },
27
+ {
28
+ name: `测试环境 - ${v.TEST}`,
29
+ value: v.TEST
30
+ },
31
+ {
32
+ name: `预发环境 - ${v.RELEASE}`,
33
+ value: v.RELEASE
34
+ },
35
+ {
36
+ name: `正式环境 - ${v.PROD}`,
37
+ value: v.PROD
38
+ }
39
+ ], Dt = [
40
+ {
41
+ name: "网页 - h5",
42
+ value: "h5"
43
+ /* H5 */
44
+ },
45
+ {
46
+ name: "依赖包 - npm",
47
+ value: "npm"
48
+ /* NPM */
49
+ },
50
+ {
51
+ name: "服务端 - server",
52
+ value: "server"
53
+ /* SERVER */
54
+ }
55
+ ];
56
+ var ue = /* @__PURE__ */ ((e) => (e.FEAT = "feat", e.FIX = "fix", e.REFACTOR = "refactor", e))(ue || {}), ae = /* @__PURE__ */ ((e) => (e.FRONT_END = "fe", e.BACK_END = "be", e.QUALITY_ASSURANCE = "qa", e))(ae || {}), I = /* @__PURE__ */ ((e) => (e.JAVA = "Java", e.JAVASCRIPT = "JavaScript", e.PYTHON = "Python", e))(I || {});
57
+ const xt = {
58
+ 1: "研发",
59
+ 2: "测试",
60
+ 3: "产品",
61
+ 4: "设计",
62
+ 5: "运营",
63
+ 6: "销售",
64
+ 7: "行政",
65
+ 8: "财务",
66
+ 9: "其他"
67
+ }, me = "http://git.cxlqd.com", Lt = ["fe-biz", "fe-base", "fe-tpl", "fe-component", "fe-demo"];
68
+ var b = /* @__PURE__ */ ((e) => (e.FEAT = "feat", e.FIX = "fix", e.REFACTOR = "refactor", e.CHORE = "chore", e.CI = "ci", e.Break = "BREAKING CHANGE", e))(b || {});
69
+ const Pt = "fe-biz7tvsd", We = "https://hxhtbr8t8uy.feishu.cn/wiki/LWW5wAQFPiXkmRkKcjOcyDDknLg";
70
+ var S = /* @__PURE__ */ ((e) => (e.MODULE = "module", e.CASE = "case", e))(S || {});
71
+ const Ot = [
72
+ {
73
+ name: "模块",
74
+ value: "module"
75
+ /* MODULE */
76
+ },
77
+ {
78
+ name: "用例",
79
+ value: "case"
80
+ /* CASE */
81
+ }
82
+ ], Mt = ".z", zt = "develop-config.json", q = ".z", Ft = ".commit-msg-tpl", _t = "project.json";
83
+ function k(e = "") {
84
+ return l.join(q, e);
85
+ }
86
+ function Ae() {
87
+ return k(_t);
88
+ }
89
+ function we() {
90
+ return k(Ft);
91
+ }
92
+ function Ve() {
93
+ Le.spawnSync("git", ["config", "core.hooksPath", k()]), Le.spawnSync("git", ["config", "commit.template", we()]);
94
+ }
95
+ function de(e = "") {
96
+ return l.resolve(jt.homedir(), Mt, e);
97
+ }
98
+ function ye() {
99
+ return de(zt);
100
+ }
101
+ function Bt() {
102
+ return $(de());
103
+ }
104
+ function qe() {
105
+ return Bt() && $(ye());
106
+ }
107
+ function He(e) {
108
+ let t = e.trim();
109
+ const i = t.match(/^git@([^:]+):(.+)$/);
110
+ if (i)
111
+ t = i[2];
112
+ else {
113
+ const n = me.replace(/^https?:\/\//, "").replace(/\/$/, "");
114
+ t = t.replace(/^https?:\/\//, ""), t.startsWith(`${n}/`) ? t = t.slice(n.length + 1) : t = t.replace(`${me.replace(/\/$/, "")}/`, "");
115
+ }
116
+ return encodeURIComponent(t.replace(/\.git$/, ""));
117
+ }
118
+ const { red: Me, green: Ut, blue: on, magenta: Jt } = N;
119
+ function ge(...e) {
120
+ }
121
+ function J(...e) {
122
+ console.log(Ut(...e));
123
+ }
124
+ function Ze(e) {
125
+ e instanceof Error && (e.name === "ExitPromptError" || e.message.includes("User force closed the prompt with")) && (console.log(), console.log(N.cyan(" 👋 下次见~")), console.log(), process.exit(1));
126
+ }
127
+ function m(e, t = !1) {
128
+ Ze(e);
129
+ let i = e;
130
+ e instanceof Error ? (i = e.message, le.isAxiosError(e) && (i = `请求失败:${e.message}`), console.log(Me(i)), console.log(Jt(e.stack))) : console.log(Me(e)), t || process.exit(1);
131
+ }
132
+ function ze(e) {
133
+ return $(e) ? vt(e).isDirectory() : !1;
134
+ }
135
+ function Ke(e = process.cwd()) {
136
+ return ze(e) ? $t(e).filter((i) => ze(l.resolve(e, i))) : [];
137
+ }
138
+ async function u(e, t = {
139
+ removeTailLinkBreak: !0,
140
+ silent: !0
141
+ }) {
142
+ let i = await new Promise((n, a) => {
143
+ try {
144
+ const s = D.exec(e, {
145
+ silent: t.silent
146
+ });
147
+ n(s);
148
+ } catch (s) {
149
+ a(s);
150
+ }
151
+ });
152
+ return i = i.toString(), t.removeTailLinkBreak && (i = i.replace(/\n$/, "")), i;
153
+ }
154
+ function Qe(e) {
155
+ yt.execSync(e, {
156
+ stdio: "inherit"
157
+ });
158
+ }
159
+ function Ye() {
160
+ return St(Date.now()).format("YYMMDD");
161
+ }
162
+ function Gt(e, t) {
163
+ for (const i of t)
164
+ if (!e.includes(i))
165
+ return !1;
166
+ return !0;
167
+ }
168
+ function oe() {
169
+ $(k()) || m("当前不在项目根目录。请切换到项目根目录");
170
+ }
171
+ function X() {
172
+ $(l.resolve(".git")) || m("当前不是git项目根目录,请先执行git init,或切换到根目录");
173
+ }
174
+ async function ce() {
175
+ await u("git status -s") !== "" && m("请先提交代码变动,再进行操作");
176
+ }
177
+ function Wt(e) {
178
+ return e === h.MASTER ? v.PROD : e;
179
+ }
180
+ function Vt(e) {
181
+ return e === v.PROD ? h.MASTER : e;
182
+ }
183
+ async function z(e, ...t) {
184
+ try {
185
+ await e(...t);
186
+ } catch (i) {
187
+ throw Ze(i), i;
188
+ }
189
+ }
190
+ async function qt(e) {
191
+ return (await je(e)).length === 0;
192
+ }
193
+ function Ht(e = "项目中文名", t = "项目描述") {
194
+ return `
195
+ # ${e}
196
+ ${t}
197
+
198
+ ## 快速开始
199
+ ### 安装依赖
200
+ \`\`\`bash
201
+ npm i
202
+ \`\`\`
203
+
204
+ ### 本地开发
205
+ \`\`\`bash
206
+ npm run dev:<environment>:[platform]
207
+ \`\`\`
208
+
209
+ ### 打包代码
210
+ \`\`\`bash
211
+ npm run build:<environment>:[platform]
212
+ \`\`\`
213
+
214
+
215
+ ### 查找、修复代码问题
216
+ \`\`\`bash
217
+ z run eslint
218
+ # 或者
219
+ z r e
220
+ \`\`\`
221
+
222
+ ### 格式化代码
223
+ \`\`\`bash
224
+ z run prettier
225
+ # 或者
226
+ z r p
227
+ \`\`\`
228
+
229
+ ### 检测类型问题
230
+ \`\`\`bash
231
+ z run type-check
232
+ # 或者
233
+ z r tc
234
+ \`\`\`
235
+
236
+ ### 检测依赖更新
237
+ \`\`\`bash
238
+ z run dependency-check
239
+ # 或者
240
+ z r dc
241
+ \`\`\`
242
+
243
+ ## 常见问题
244
+ 列出开发中常见的问题和解决方案
245
+
246
+ ## 了解更多
247
+ 在此处放入飞书文档链接。请在[前端团队-项目手册](https://hxhtbr8t8uy.feishu.cn/drive/folder/QfQ7favVWljQk7d63Prc8mUGnJf)中按照分类新建文档。
248
+ `;
249
+ }
250
+ const Zt = `{
251
+ "printWidth": 120,
252
+ "tabWidth": 2,
253
+ "useTabs": false,
254
+ "semi": true,
255
+ "singleQuote": false,
256
+ "quoteProps": "as-needed",
257
+ "jsxSingleQuote": false,
258
+ "trailingComma": "all",
259
+ "bracketSpacing": true,
260
+ "bracketSameLine": false,
261
+ "arrowParens": "always",
262
+ "requirePragma": false,
263
+ "insertPragma": false,
264
+ "proseWrap": "preserve",
265
+ "htmlWhitespaceSensitivity": "css",
266
+ "vueIndentScriptAndStyle": false,
267
+ "endOfLine": "lf",
268
+ "embeddedLanguageFormatting": "auto",
269
+ "singleAttributePerLine": false
270
+ }
271
+ `, Kt = `# 系统 信息文件
272
+ .DS_Store/
273
+ Thumbs.db
274
+
275
+ # 编辑器配置文件
276
+ .idea/
277
+ .vscode/
278
+
279
+ # 输出目录
280
+ dist/
281
+
282
+ # Log files
283
+ *.log
284
+
285
+ # 本地配置文件
286
+ *.local
287
+
288
+ # 缓存文件
289
+ *.cache
290
+
291
+ # 垃圾文件
292
+ .Trashes
293
+ `, Qt = {
294
+ [I.JAVA]: {
295
+ // TODO: 需要优化
296
+ // "**/*.{java}": "java -jar ./.z/checkstyle.jar -c ./.z/checkstyle.xml",
297
+ "**/*.{java}": "echo 'todo'"
298
+ },
299
+ [I.JAVASCRIPT]: {
300
+ "**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}": "eslint --fix",
301
+ "*": "prettier -wu"
302
+ },
303
+ [I.PYTHON]: {
304
+ // TODO: 需要优化
305
+ // "**/*.{py}": "python --fix",
306
+ "**/*.{py}": "echo 'todo'"
307
+ }
308
+ }, Yt = `[
309
+ {
310
+ "Precondition": "前置条件",
311
+ "Title": "用例名称",
312
+ "URL": "接口地址",
313
+ "Data": "接口入参",
314
+ "Method": "接口类型",
315
+ "Expected": "期望结果"
316
+ }
317
+ ]`, Xt = "# from assets", ei = "cli-z-develop", ti = "0.10.1", ii = "技术团队开发流程管理工具", ai = "dist/index.js", ni = { z: "bin/z.js", "z-develop": "bin/z.js" }, si = { prepare: "[ -n '$z' ] && z init prepare || echo 'Warning: z not exist at global'", dev: "vite build --watch", "dev:debug": "DEBUG=true vite build --watch", build: "vite build", eslint: "eslint '**/*.{ts,js}' --fix", prettier: "prettier -wu .", upload: "npm run build && npm publish --access public --registry https://registry.npmjs.org/", "upload:patch": "npm version patch && npm run upload", "upload:minor": "npm version minor && npm run upload", "upload:major": "npm version major && npm run upload" }, ri = "module", oi = "z", ci = { "@lonely9/eslint-config-team": "^1.3.5", "@tsconfig/node22": "^22.0.5", "@types/fs-extra": "^11.0.4", "@types/inquirer": "^9.0.9", "@types/minimist": "^1.2.5", "@types/node": "^22.15.29", "@types/semver": "^7.7.1", "@types/shelljs": "^0.10.0", "@typescript-eslint/eslint-plugin": "^8.53.0", "@typescript-eslint/parser": "^8.53.0", eslint: "^9.39.2", jiti: "^2.6.1", prettier: "^3.7.4", typescript: "^5.9.3", vite: "^7.3.1", "vue-tsc": "^3.2.2" }, ui = { "@inquirer/prompts": "^8.2.0", axios: "^1.13.6", chalk: "^5.6.2", commander: "^14.0.2", dayjs: "^1.11.19", "fs-extra": "^11.3.3", "inquirer-select-pro": "^1.0.0-alpha.9", "lint-staged": "^16.2.7", minimist: "^1.2.8", "npm-check-updates": "^19.3.1", ora: "^9.0.0", semver: "^7.7.3", shelljs: "^0.10.0" }, Q = {
318
+ name: ei,
319
+ version: ti,
320
+ description: ii,
321
+ main: ai,
322
+ bin: ni,
323
+ scripts: si,
324
+ type: ri,
325
+ author: oi,
326
+ devDependencies: ci,
327
+ dependencies: ui
328
+ }, C = {
329
+ // 个人数据
330
+ profile: {
331
+ ldapAccount: "",
332
+ ldapPassword: "",
333
+ gitToken: "",
334
+ gitUserId: 0,
335
+ gitName: "",
336
+ gitEnglishName: "",
337
+ gitEmail: "",
338
+ weWorkName: "",
339
+ weWorkUserId: "",
340
+ jobType: ae.FRONT_END,
341
+ zenTaoToken: "",
342
+ k8sToken: ""
343
+ },
344
+ // 包数据
345
+ main: {
346
+ version: Q.version,
347
+ latestCheckVersionTimestamp: 0,
348
+ // 3天检查一次
349
+ versionCheckDuring: 3,
350
+ // 企微用户数据使用缓存
351
+ weWorkListCache: []
352
+ },
353
+ // 一些静态数据
354
+ constants: {
355
+ ZenTaoDomain: "",
356
+ K8sDomain: "",
357
+ FEServerDomain: "",
358
+ K8SWebDomain: ""
359
+ }
360
+ };
361
+ function A(e) {
362
+ return e ? C.profile[e] : C.profile;
363
+ }
364
+ function pe(e) {
365
+ return e ? C.main[e] : C.main;
366
+ }
367
+ function ee(e) {
368
+ return e ? C.constants[e] : C.constants;
369
+ }
370
+ let B = null, U = null;
371
+ function $e() {
372
+ if (B)
373
+ return B;
374
+ const e = l.join("package.json");
375
+ return $(e) || m(`当前目录(${D.pwd()})不存在${e}文件,请在项目根目录执行该命令。`), B = j.readJsonSync(e), B;
376
+ }
377
+ function Ee() {
378
+ if (U)
379
+ return U;
380
+ const e = Ae();
381
+ return $(e) || m(
382
+ `当前目录(${D.pwd()})不存在${e}文件,请在项目根目录执行该命令,或者初始化项目(z init .)。`
383
+ ), U = j.readJsonSync(e), U;
384
+ }
385
+ function li(e) {
386
+ U ? U = {
387
+ ...U,
388
+ ...e
389
+ } : U = e, j.writeJSONSync(Ae(), U, { spaces: 2 });
390
+ }
391
+ function mi(e) {
392
+ B ? B = {
393
+ ...B,
394
+ ...e
395
+ } : B = e, j.writeJSONSync(l.join("package.json"), B, { spaces: 2 });
396
+ }
397
+ const V = {
398
+ id: 0,
399
+ path: "",
400
+ group: "",
401
+ sourceBranch: "",
402
+ mergeRequestUrl: ""
403
+ };
404
+ async function pi() {
405
+ if (!V.id)
406
+ try {
407
+ const e = Ee(), t = He(e.repository.url), i = await tt(t);
408
+ V.id = i.id, V.path = t, V.group = i.namespace.full_path, V.mergeRequestUrl = `${i.web_url}/merge_requests`;
409
+ } catch (e) {
410
+ m(e);
411
+ }
412
+ return V.sourceBranch || (V.sourceBranch = await u("git branch --show-current")), V;
413
+ }
414
+ function te() {
415
+ j.writeJSONSync(
416
+ ye(),
417
+ {
418
+ main: pe(),
419
+ profile: A(),
420
+ constants: ee()
421
+ },
422
+ {
423
+ spaces: 2
424
+ }
425
+ );
426
+ }
427
+ function L(e, t) {
428
+ t !== void 0 ? C.profile[e] = t : C.profile = {
429
+ ...C.profile,
430
+ ...e
431
+ };
432
+ }
433
+ function Te(e, t) {
434
+ C.constants = {
435
+ ...C.constants,
436
+ ...e
437
+ };
438
+ }
439
+ function ne(e, t) {
440
+ t !== void 0 ? C.main[e] = t : C.main = {
441
+ ...C.main,
442
+ ...e
443
+ };
444
+ }
445
+ async function Z(e) {
446
+ const t = e.method || "get", i = e.headers || {}, n = e.data || {}, a = e.dataKey ?? (["GET", "get"].includes(t) ? "params" : "data");
447
+ try {
448
+ const s = {
449
+ url: e.url,
450
+ method: t,
451
+ [a]: n,
452
+ headers: i
453
+ };
454
+ ge(N.magenta(s.method.toUpperCase()), N.yellow(s.url), JSON.stringify(s.headers)), ge(N.gray(JSON.stringify(s[a], null, 2)));
455
+ const o = await le(s);
456
+ return ge(N.green("Response"), N.grey(JSON.stringify(o.data, null, 2))), Promise.resolve(o.data);
457
+ } catch (s) {
458
+ return s instanceof Nt && ge(N.red("Error"), N.grey(JSON.stringify(s?.response?.data))), Promise.reject(s);
459
+ }
460
+ }
461
+ async function di() {
462
+ const e = A("gitToken");
463
+ if (e)
464
+ return e;
465
+ {
466
+ const { access_token: t } = await Z({
467
+ url: `${me}/oauth/token`,
468
+ method: "post",
469
+ data: {
470
+ grant_type: "password",
471
+ username: A("ldapAccount"),
472
+ password: A("ldapPassword")
473
+ }
474
+ }), i = `Bearer ${t}`;
475
+ return L("gitToken", i), te(), i;
476
+ }
477
+ }
478
+ async function R(e) {
479
+ return Z({
480
+ ...e,
481
+ headers: {
482
+ Authorization: await di()
483
+ }
484
+ });
485
+ }
486
+ async function fi() {
487
+ const e = A("zenTaoToken");
488
+ if (e)
489
+ return e;
490
+ {
491
+ const { token: t } = await Z({
492
+ url: `${ee("ZenTaoDomain")}/api.php/v1/tokens`,
493
+ method: "post",
494
+ data: {
495
+ account: A("ldapAccount"),
496
+ password: A("ldapPassword")
497
+ }
498
+ });
499
+ return L("zenTaoToken", t), te(), t;
500
+ }
501
+ }
502
+ async function he(e) {
503
+ const t = await Z({
504
+ ...e,
505
+ headers: {
506
+ Token: await fi()
507
+ }
508
+ });
509
+ if (e.url.includes("local")) {
510
+ if (typeof t == "string") {
511
+ const i = JSON.parse(t.slice(0, t.indexOf("<script>")));
512
+ return JSON.parse(i.data);
513
+ }
514
+ if (typeof t == "object")
515
+ return t.error === "Unauthorized" || t.data.indexOf("<script>") < 0 ? (L("zenTaoToken", ""), he({
516
+ ...e
517
+ })) : t;
518
+ } else {
519
+ const { status: i, data: n } = t;
520
+ if (i === "success") {
521
+ const a = JSON.parse(n);
522
+ return a.title === "用户登录" ? (L("zenTaoToken", ""), he({
523
+ ...e
524
+ })) : a;
525
+ } else
526
+ return {};
527
+ }
528
+ }
529
+ async function gi() {
530
+ const e = A("k8sToken");
531
+ if (e)
532
+ return e;
533
+ {
534
+ const { access_token: t } = await Z({
535
+ url: `${ee("K8sDomain")}/oauth/login/LDAP`,
536
+ method: "post",
537
+ headers: {
538
+ "Content-Type": "application/x-www-form-urlencoded"
539
+ },
540
+ data: {
541
+ username: A("ldapAccount"),
542
+ password: A("ldapPassword")
543
+ }
544
+ }), i = `Bearer ${t}`;
545
+ return L("k8sToken", i), te(), i;
546
+ }
547
+ }
548
+ async function Xe(e) {
549
+ const t = await Z({
550
+ ...e,
551
+ headers: {
552
+ Authorization: await gi()
553
+ }
554
+ });
555
+ return t.code === 401 ? (L("k8sToken", ""), Xe({
556
+ ...e
557
+ })) : t;
558
+ }
559
+ const P = () => `${me}/api/v4`, ke = (e) => `${P()}/projects/100/repository/files/${encodeURIComponent(e)}/raw?ref=master`;
560
+ function hi() {
561
+ return R({
562
+ url: ke("src/data/template-projects.json")
563
+ });
564
+ }
565
+ function et() {
566
+ return R({
567
+ url: ke("src/data/z-develop-config.json")
568
+ });
569
+ }
570
+ function wi() {
571
+ return R({
572
+ url: ke("src/data/project-group-chats.json")
573
+ });
574
+ }
575
+ function yi() {
576
+ return R({
577
+ url: `${P()}/user`
578
+ });
579
+ }
580
+ function $i() {
581
+ return R({
582
+ url: `${P()}/groups`
583
+ });
584
+ }
585
+ function vi(e) {
586
+ return R({
587
+ url: `${P()}/projects`,
588
+ method: "post",
589
+ data: e
590
+ });
591
+ }
592
+ function tt(e) {
593
+ return R({
594
+ url: `${P()}/projects/${e}`
595
+ });
596
+ }
597
+ function bi(e) {
598
+ return R({
599
+ url: `${P()}/projects`,
600
+ data: {
601
+ search: e,
602
+ search_namespaces: !0
603
+ }
604
+ });
605
+ }
606
+ function Ni(e) {
607
+ return R({
608
+ url: `${P()}/projects/${e.id}/merge_requests`,
609
+ method: "post",
610
+ data: e
611
+ });
612
+ }
613
+ function Si(e) {
614
+ return R({
615
+ url: `${P()}/projects/${e.id}/merge_requests/${e.iid}/merge`,
616
+ method: "put"
617
+ });
618
+ }
619
+ function ji(e) {
620
+ return R({
621
+ url: `${P()}/projects/${e.id}/merge_requests/${e.iid}`,
622
+ method: "put",
623
+ data: e
624
+ });
625
+ }
626
+ function Ai(e) {
627
+ return R({
628
+ url: `${P()}/projects/${e.id}/merge_requests/${e.iid}`,
629
+ method: "get"
630
+ });
631
+ }
632
+ function Ei(e) {
633
+ return R({
634
+ url: `${P()}/projects/${e.id}/repository/branches`,
635
+ method: "post",
636
+ data: e
637
+ });
638
+ }
639
+ function Ti(e) {
640
+ return R({
641
+ url: `${P()}/projects/${e}/repository/branches`
642
+ });
643
+ }
644
+ function ki() {
645
+ const e = de("fe-groups.json");
646
+ return $(e) ? j.readJSONSync(e) : { groups: [] };
647
+ }
648
+ async function Ci() {
649
+ const e = await $i(), t = Lt.map((i) => {
650
+ const n = e.find((a) => a.name === i);
651
+ return n ? {
652
+ name: n.name,
653
+ id: n.id,
654
+ description: n.description
655
+ } : !1;
656
+ }).filter((i) => !!i);
657
+ j.writeJSONSync(de("fe-groups.json"), { groups: t }, { spaces: 2 });
658
+ }
659
+ async function T(e) {
660
+ const t = `${ee("FEServerDomain")}/api`, { data: i } = await Z({
661
+ url: `${t}/auth/z-develop/login`,
662
+ method: "post"
663
+ }), n = await Z({
664
+ url: t + e.url,
665
+ headers: {
666
+ Authorization: `Bearer ${i}`
667
+ },
668
+ data: e.data,
669
+ method: e.method || "post"
670
+ });
671
+ return n.code !== 0 && m(`${n.code}: ${n.message}`), n.data;
672
+ }
673
+ function Ri() {
674
+ return T({
675
+ url: "/user/list2"
676
+ });
677
+ }
678
+ function Ii() {
679
+ return T({
680
+ url: "/zen/testcase/product/list"
681
+ });
682
+ }
683
+ function it(e) {
684
+ return T({
685
+ url: "/zen/testcase/product/module/list",
686
+ data: {
687
+ product: e
688
+ }
689
+ });
690
+ }
691
+ function Di(e) {
692
+ return T({
693
+ url: "/zen/testcase/product/name",
694
+ data: {
695
+ product: e
696
+ }
697
+ });
698
+ }
699
+ function xi(e, t) {
700
+ return T({
701
+ url: "/zen/testcase/product/auto-case/list",
702
+ data: {
703
+ product: e,
704
+ caseIds: t
705
+ }
706
+ });
707
+ }
708
+ function Li(e) {
709
+ return T({
710
+ url: "/zen/testcase/step/list",
711
+ data: {
712
+ id: e
713
+ }
714
+ });
715
+ }
716
+ function Pi(e) {
717
+ return T({
718
+ url: "/zen/testcase/module/create",
719
+ data: e
720
+ });
721
+ }
722
+ function Oi(e) {
723
+ return T({
724
+ url: "/zen/testcase/create",
725
+ data: e
726
+ });
727
+ }
728
+ function Mi(e) {
729
+ return T({
730
+ url: "/zen/testcase/step/create",
731
+ data: e
732
+ });
733
+ }
734
+ function zi(e) {
735
+ return T({
736
+ url: "/zen/testcase/modules/remove",
737
+ data: e
738
+ });
739
+ }
740
+ function Fi(e) {
741
+ return T({
742
+ url: "/zen/testcase/cases/remove",
743
+ data: e
744
+ });
745
+ }
746
+ function _i(e) {
747
+ return T({
748
+ url: "/zen/testcase/module/update/name",
749
+ data: e
750
+ });
751
+ }
752
+ function Bi(e) {
753
+ return T({
754
+ url: "/zen/testcase/case/update/name",
755
+ data: e
756
+ });
757
+ }
758
+ function Ui(e) {
759
+ return T({
760
+ url: "/zen/testcase/case/update/priority",
761
+ data: e
762
+ });
763
+ }
764
+ function Ji(e) {
765
+ return T({
766
+ url: "/zen/testcase/case/update/precondition",
767
+ data: e
768
+ });
769
+ }
770
+ function Gi(e, t) {
771
+ const i = [];
772
+ t.forEach((s) => {
773
+ e.includes(s.value) && i.push(s);
774
+ });
775
+ const n = pe("weWorkListCache"), a = n.map((s) => s.value);
776
+ i.forEach((s) => {
777
+ const o = a.indexOf(s.value);
778
+ o > -1 ? n[o].usageCount += 1 : n.push({
779
+ ...s,
780
+ usageCount: 1
781
+ });
782
+ }), ne({
783
+ weWorkListCache: n.sort((s, o) => o.usageCount - s.usageCount)
784
+ }), te();
785
+ }
786
+ async function at() {
787
+ const t = (await Ri()).filter((s) => [1, 2, 3, 4, 5].includes(s.title)).map((s) => ({
788
+ name: `${s.nick} - ${xt[s.title]}`,
789
+ value: s.weWorkUserId
790
+ })), i = pe("weWorkListCache"), n = i.map((s) => s.value), a = [];
791
+ return t.forEach((s) => {
792
+ const o = n.indexOf(s.value);
793
+ a.push({
794
+ ...s,
795
+ usageCount: o > -1 ? i[o].usageCount : 0
796
+ });
797
+ }), a.sort((s, o) => o.usageCount - s.usageCount);
798
+ }
799
+ async function nt(e, t, i) {
800
+ const n = await at();
801
+ let a = await re({
802
+ message: e,
803
+ loop: !0,
804
+ pageSize: n.length || 5,
805
+ clearInputWhenSelected: !0,
806
+ multiple: i,
807
+ options: (s) => s ? n.filter((o) => o.name.includes(s)) : n,
808
+ validate: t
809
+ });
810
+ return a = Array.isArray(a) ? a : [a], Gi(a, n), a;
811
+ }
812
+ async function Wi(e, t, i) {
813
+ const { groups: n } = await wi(), a = n.map((o) => ({
814
+ name: o.name,
815
+ value: o.url
816
+ }));
817
+ let s = await re({
818
+ message: e,
819
+ loop: !0,
820
+ pageSize: a.length || 5,
821
+ clearInputWhenSelected: !0,
822
+ multiple: i,
823
+ options: (o) => o ? a.filter((r) => r.name.includes(o)) : a,
824
+ validate: t
825
+ });
826
+ return s = Array.isArray(s) ? s : [s], s;
827
+ }
828
+ async function Vi() {
829
+ try {
830
+ qe() && (await _e({
831
+ message: "系统中已存在z的配置文件,确认重新配置?"
832
+ }) ? D.rm("-rf", ye()) : process.exit(0)), await se(de(), { recursive: !0 });
833
+ const t = await E({
834
+ message: "请选择岗位类型",
835
+ choices: [
836
+ {
837
+ name: "前端",
838
+ value: ae.FRONT_END
839
+ },
840
+ {
841
+ name: "后端",
842
+ value: ae.BACK_END
843
+ },
844
+ {
845
+ name: "测试",
846
+ value: ae.QUALITY_ASSURANCE
847
+ }
848
+ ]
849
+ }), i = await _({
850
+ message: "请输入LDAP账号:"
851
+ }), n = await At({
852
+ message: "请输入LDAP密码:",
853
+ mask: !0
854
+ });
855
+ L("jobType", t), L("ldapAccount", i), L("ldapPassword", n);
856
+ const a = await et();
857
+ Te(a);
858
+ const s = await at(), o = await nt("请选择你自己(用于企微通知):", (p) => p.length > 1 ? "只能选一个" : p.length < 1 ? "请选一个" : !0), { name: r, value: c } = s.find((p) => p.value === o[0]);
859
+ L({
860
+ weWorkName: r,
861
+ weWorkUserId: c
862
+ });
863
+ } catch (t) {
864
+ m(t);
865
+ }
866
+ const e = w("配置信息初始化中").start();
867
+ try {
868
+ const t = await yi();
869
+ L({
870
+ gitUserId: t.id,
871
+ gitName: t.name,
872
+ gitEnglishName: t.username,
873
+ gitEmail: t.email
874
+ }), ne("latestCheckVersionTimestamp", Date.now()), te(), A("jobType") === ae.FRONT_END && await Ci(), e.succeed("配置信息初始化完成"), process.exit(0);
875
+ } catch (t) {
876
+ e.fail("配置信息初始化失败"), le.isAxiosError(t) && m("请检查你的域名及令牌配置"), m(t);
877
+ }
878
+ }
879
+ const qi = `{
880
+ "$schema": "https://json.schemastore.org/tsconfig",
881
+ "_version": "0.0.1",
882
+ "compilerOptions": {
883
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.browser.tsbuildinfo",
884
+ "lib": ["ESNext", "DOM", "DOM.Iterable", "WebWorker"],
885
+ // 编译时无需导出类型文件
886
+ "noEmit": true,
887
+
888
+ // 编译时用模块最新规范,至于打包代码时的兼容问题,交给vite/webpack们解决
889
+ "module": "ESNext",
890
+ // 模块解析策略。同上
891
+ "moduleResolution": "bundler",
892
+ // 可以使用import...from导入json文件
893
+ "resolveJsonModule": true,
894
+ // 带上文件后缀,避免歧义。至于兼容性,交给vite/webpack们解决
895
+ "allowImportingTsExtensions": true,
896
+ // 识别一个文件是模块还是脚本,由于使用了打包工具,所以所有文件都是模块
897
+ "moduleDetection": "force",
898
+
899
+ // tsc编译时不转化jsx,留给打包工具处理
900
+ "jsx": "preserve",
901
+ // 指定处理jsx的库
902
+ "jsxImportSource": "vue",
903
+
904
+ // 必须显式声明this的类型,否则报错
905
+ "noImplicitThis": true,
906
+ // 严格模式。将默认开启以下规则:
907
+ // noImplicitAny noImplicitThis alwaysStrict strictBindCallApply strictNullChecks strictFunctionTypes strictPropertyInitialization
908
+ "strict": true,
909
+
910
+ // 引入类型需要type关键字
911
+ "verbatimModuleSyntax": true,
912
+
913
+ // 编译目标用最新规范,至于打包代码时的兼容问题,交给vite/webpack们解决
914
+ "target": "ESNext",
915
+ // 合理编译class
916
+ "useDefineForClassFields": true,
917
+
918
+ // commonjs 和 es module之间可以互操作
919
+ "esModuleInterop": true,
920
+ // 引用路径中文件名大小写敏感
921
+ "forceConsistentCasingInFileNames": true,
922
+ // 会检查自建的和依赖库的所有.d.ts。调试自建d.ts文件时可以考虑打开
923
+ "skipLibCheck": true
924
+ }
925
+ }
926
+ `, Hi = `{
927
+ "$schema": "https://json.schemastore.org/tsconfig",
928
+ "_version": "0.0.1",
929
+ "compilerOptions": {
930
+ "lib": ["ESNext"],
931
+ // 编译时无需导出类型文件
932
+ "noEmit": true,
933
+
934
+ // 编译时用模块最新规范,至于打包代码时的兼容问题,交给vite/webpack们解决
935
+ "module": "ESNext",
936
+ // 模块解析策略。同上
937
+ "moduleResolution": "bundler",
938
+ // 可以使用import...from导入json文件
939
+ "resolveJsonModule": true,
940
+ // 识别一个文件是模块还是脚本,由于使用了打包工具,所以所有文件都是模块
941
+ "moduleDetection": "force",
942
+
943
+ // 必须显式声明this的类型,否则报错
944
+ "noImplicitThis": true,
945
+ // 严格模式。将默认开启以下规则:
946
+ // noImplicitAny noImplicitThis alwaysStrict strictBindCallApply strictNullChecks strictFunctionTypes strictPropertyInitialization
947
+ "strict": true,
948
+
949
+ // 引入类型需要type关键字
950
+ "verbatimModuleSyntax": true,
951
+
952
+ // 编译目标用最新规范,至于打包代码时的兼容问题,交给vite/webpack们解决
953
+ "target": "ESNext",
954
+ // 合理编译class
955
+ "useDefineForClassFields": true,
956
+
957
+ // commonjs 和 es module之间可以互操作
958
+ "esModuleInterop": true,
959
+ // 引用路径中文件名大小写敏感
960
+ "forceConsistentCasingInFileNames": true,
961
+ // 会检查自建的和依赖库的所有.d.ts。调试自建d.ts文件时可以考虑打开
962
+ "skipLibCheck": true
963
+ }
964
+ }
965
+ `;
966
+ async function Zi() {
967
+ await M(we(), "", { mode: 493 }), await M(k(".gitignore"), `.commit-msg-tpl
968
+ `, { mode: 493 }), await M(k("commit-msg"), `#!/usr/bin/env sh
969
+ z run commit-msg`, { mode: 493 }), await M(k("pre-commit"), `#!/usr/bin/env sh
970
+ z run commit-files`, { mode: 493 });
971
+ const { language: e } = Ee();
972
+ e === I.JAVASCRIPT && (await M(k(".prettierrc.json"), Zt, { mode: 493 }), await M(k(".prettierignore"), Kt, { mode: 493 }), await M(k("tsconfig.node.json"), Hi, { mode: 493 }), await M(k("tsconfig.browser.json"), qi, {
973
+ mode: 493
974
+ })), Ve();
975
+ }
976
+ async function Ki(e, t) {
977
+ const i = await u("git remote get-url --push origin");
978
+ i || m("获取项目远程git地址失败,请配置后重试");
979
+ let n = e;
980
+ n || (n = await E({
981
+ message: "请选择项目语言",
982
+ choices: [
983
+ {
984
+ name: I.JAVASCRIPT,
985
+ value: I.JAVASCRIPT
986
+ },
987
+ {
988
+ name: I.JAVA,
989
+ value: I.JAVA
990
+ },
991
+ {
992
+ name: I.PYTHON,
993
+ value: I.PYTHON
994
+ }
995
+ ]
996
+ }));
997
+ let a = t;
998
+ if (!a) {
999
+ const s = He(i), o = await tt(s);
1000
+ if (!o)
1001
+ return m(`未找到项目,请确认项目${i}是否存在,或者当前账号权限`);
1002
+ a = o.namespace.full_path;
1003
+ }
1004
+ li({
1005
+ language: n,
1006
+ "lint-staged": Qt[n],
1007
+ repository: {
1008
+ url: i,
1009
+ group: a
1010
+ }
1011
+ });
1012
+ }
1013
+ async function Ce(e, t) {
1014
+ e ? D.rm("-rf", q) : $(k()) && (await _e({
1015
+ message: `当前项目中已存在配置文件夹${q},确认重新配置?`
1016
+ }) ? D.rm("-rf", q) : process.exit(0)), await se(k(), { recursive: !0 }), await Ki(e, t), await Zi(), J("项目初始化完成");
1017
+ }
1018
+ async function Qi() {
1019
+ $(k()) && $(we()) ? Ve() : await Ce(), process.exit(0);
1020
+ }
1021
+ async function Yi(e, t) {
1022
+ t.projectLanguage && !Object.values(I).includes(t.projectLanguage) && m("项目语言不支持"), e ? (X(), e === "." ? (await Ce(t.projectLanguage, void 0), process.exit(0)) : e === "prepare" ? await Qi() : m("参数错误。执行 z init -h 查看帮助。")) : await Vi();
1023
+ }
1024
+ x.command("init").alias("i").description("初始化工具配置、项目配置").argument("[type]", "非必填。不传为初始化全局配置;传 . 为初始化当前项目;传 prepare 为初始化GIT HOOKS").option("--project-language", `项目语言。可选值:${Object.values(I).join("/")} `).action((...e) => z(Yi, ...e));
1025
+ async function Xi(e, t) {
1026
+ if (!e)
1027
+ return "不能为空";
1028
+ if (!/^[a-z0-9-]+$/.test(e))
1029
+ return "格式为小写字母、中横线(可选)、数字(不推荐)。如apple, apple-tree";
1030
+ if (Ke().includes(e))
1031
+ return "当前目录下已存在同名文件夹,请先处理。";
1032
+ const a = (await bi(e)).find((s) => s.path_with_namespace === `${t}/${e}`);
1033
+ return a ? `远程仓库中已存在同名项目(${a.http_url_to_repo}),请更名后重试` : !0;
1034
+ }
1035
+ function ea(e) {
1036
+ return e ? !0 : "不能为空";
1037
+ }
1038
+ function ta(e) {
1039
+ return e ? /^[a-zA-Z0-9.]+$/.test(e) ? !0 : "格式为大小写字母、数字、小数点,小驼峰命名。如userInfo、systemRouter3" : "不能为空";
1040
+ }
1041
+ async function ia(e) {
1042
+ oe(), X(), await ce();
1043
+ let t, i;
1044
+ e.branchType ? t = e.branchType : t = await E({
1045
+ message: "请选择创建分支的类型",
1046
+ choices: [
1047
+ {
1048
+ name: "开发新功能(feat)",
1049
+ value: ue.FEAT
1050
+ },
1051
+ {
1052
+ name: "修复BUG(fix)",
1053
+ value: ue.FIX
1054
+ },
1055
+ {
1056
+ name: "重构/优化代码(refactor)",
1057
+ value: ue.REFACTOR
1058
+ }
1059
+ ]
1060
+ }), e.branchPurpose ? i = e.branchPurpose : i = await _({
1061
+ message: "请输入创建分支的目的(大小写字母、数字,小驼峰式命名。如userInfo)",
1062
+ validate: ta
1063
+ });
1064
+ const n = `${t}_${i}_${Ye()}`;
1065
+ await u(`git fetch origin ${h.MASTER}`), await u(`git checkout -b ${n} origin/${h.MASTER}`), await u(`git push -u origin ${n}`), process.exit(0);
1066
+ }
1067
+ const st = (e) => `${ee("ZenTaoDomain")}${e}`;
1068
+ async function aa() {
1069
+ const e = await he({
1070
+ url: st("/my-work-task.json?tid=mrrferp8"),
1071
+ method: "get"
1072
+ });
1073
+ return e?.tasks ? e.tasks.filter((t) => t.status !== "done").map(({ id: t, name: i }) => ({
1074
+ value: {
1075
+ name: i,
1076
+ value: t
1077
+ },
1078
+ name: i
1079
+ })) : [];
1080
+ }
1081
+ async function na() {
1082
+ const e = await he({
1083
+ url: st("/my-work-bug.json?tid=mrrferp8"),
1084
+ method: "get"
1085
+ });
1086
+ return e?.bugs ? Object.values(e.bugs).map(({ id: t, title: i }) => ({
1087
+ name: i,
1088
+ value: {
1089
+ name: i,
1090
+ value: t
1091
+ }
1092
+ })) : [];
1093
+ }
1094
+ async function Ne(e, t) {
1095
+ let i = "";
1096
+ if ([b.FEAT, b.FIX, b.REFACTOR].includes(e)) {
1097
+ const n = t.map((s) => s.value).join(","), a = t.map((s) => s.name).join(";");
1098
+ i = `${e}(${n}): ${a}`;
1099
+ }
1100
+ e === b.CHORE && (i = `${e}: ${t}`), await M(we(), i, "utf-8"), console.log(N.yellow(i)), J("commit msg模板写入成功,可以进行提交了");
1101
+ }
1102
+ async function sa() {
1103
+ const e = await E({
1104
+ message: "请选择你要创建的模板类型",
1105
+ choices: [
1106
+ {
1107
+ name: "feat - 业务需求/功能开发/BUG修复",
1108
+ value: b.FEAT
1109
+ },
1110
+ {
1111
+ name: "fix - bug修复",
1112
+ value: b.FIX
1113
+ },
1114
+ {
1115
+ name: "refactor - 技术重构/性能优化/代码规范",
1116
+ value: b.REFACTOR
1117
+ },
1118
+ {
1119
+ name: "chore - 其他",
1120
+ value: b.CHORE
1121
+ }
1122
+ ]
1123
+ });
1124
+ if ([b.FEAT, b.REFACTOR].includes(e)) {
1125
+ const t = await aa();
1126
+ if (!t.length)
1127
+ return J("🤷 暂无开发任务");
1128
+ const i = await Pe({
1129
+ message: "请关联开发任务(可多选):",
1130
+ validate: (n) => n.length === 0 ? "请选择项" : !0,
1131
+ choices: t.map((n) => ({
1132
+ ...n,
1133
+ name: `[${n.value.value}]: ${n.name}`
1134
+ })),
1135
+ pageSize: t.length
1136
+ });
1137
+ await Ne(b.FEAT, i);
1138
+ }
1139
+ if (e === b.FIX) {
1140
+ const t = await na();
1141
+ if (!t.length)
1142
+ return J("🤷 暂无BUG");
1143
+ const i = await Pe({
1144
+ message: "请关联Bug(可多选):",
1145
+ validate: (n) => n.length === 0 ? "请选择项" : !0,
1146
+ choices: t.map((n) => ({
1147
+ ...n,
1148
+ name: `[${n.value.value}]: ${n.name}`
1149
+ })),
1150
+ pageSize: t.length
1151
+ });
1152
+ await Ne(b.FIX, i);
1153
+ }
1154
+ if (e === b.CHORE) {
1155
+ const t = await _({
1156
+ message: "请输入commit msg:",
1157
+ validate: (i) => i.length === 0 ? "请输入commit msg" : !0
1158
+ });
1159
+ await Ne(b.CHORE, t);
1160
+ }
1161
+ process.exit(0);
1162
+ }
1163
+ async function ra() {
1164
+ try {
1165
+ const e = {}, t = async () => {
1166
+ const F = Ke(), { projects: K } = await hi(), W = K.map((ie) => {
1167
+ const xe = {
1168
+ name: `${ie.name} [${ie.desc}]`,
1169
+ value: ie.name,
1170
+ disabled: !1
1171
+ };
1172
+ return F.includes(ie.name) && (xe.disabled = "目录下已存在同名文件夹"), xe;
1173
+ }), wt = await E({
1174
+ message: "请选择一个项目模板",
1175
+ choices: W
1176
+ }), be = K.find((ie) => ie.name === wt);
1177
+ e.tplName = be.name, e.tplUrl = be.url, e.tplLanguage = be.language;
1178
+ }, i = async () => {
1179
+ const { groups: F } = ki(), K = await E({
1180
+ message: "请选择一个分组",
1181
+ choices: F.map((W) => ({
1182
+ name: `${W.name} [${W.description}]`,
1183
+ value: W.id,
1184
+ short: W.name
1185
+ }))
1186
+ });
1187
+ e.group = {
1188
+ id: K,
1189
+ name: F.find((W) => W.id === K)?.name
1190
+ };
1191
+ }, n = async () => {
1192
+ e.projectName = await _({
1193
+ message: "请输入项目名称",
1194
+ validate: (F) => Xi(F, e.group?.name || "")
1195
+ }), e.projectDesc = await _({
1196
+ message: "请输入项目描述",
1197
+ validate: ea
1198
+ });
1199
+ };
1200
+ await t(), await i(), await n();
1201
+ const a = `${me}/${e.group?.name}/${e.projectName}.git`, s = w("模版初始化中").start();
1202
+ await u(`git clone --depth=1 ${e.tplUrl}`), await Fe(e.tplName, e.projectName), D.cd(e.projectName), D.rm("-rf", ".git"), await u(`git init --initial-branch=${h.MASTER}`), await u(`git remote add origin ${a}`), await u(`git config user.name ${A("gitName")}`), await u(`git config user.email ${A("gitEmail")}`);
1203
+ const o = $e();
1204
+ mi({
1205
+ ...o,
1206
+ name: e.projectName,
1207
+ description: e.projectDesc,
1208
+ scripts: {
1209
+ ...o.scripts,
1210
+ prepare: "[ -n '$z' ] && z init prepare || echo 'Warning: z not exist at global'"
1211
+ }
1212
+ }), await j.writeFile(l.resolve("README.md"), Ht(e.projectName, e.projectDesc)), s.succeed("模版初始化完成"), await Ce(e.tplLanguage, e.group?.name);
1213
+ const r = w("依赖安装中").start();
1214
+ await u("npm install --registry https://registry.npmmirror.com/"), r.succeed("依赖安装完成");
1215
+ const c = w("项目推送中").start();
1216
+ await u('git add . && git commit -m "chore: 项目初始化"'), await u("git tag v0.0.1");
1217
+ const p = await vi({
1218
+ name: e.projectName,
1219
+ description: e.projectDesc,
1220
+ path: e.projectName,
1221
+ visibility: "private",
1222
+ namespace_id: e.group?.id
1223
+ });
1224
+ await u(`git push -u origin ${h.MASTER}`), await u(`git push origin HEAD:${h.MASTER} --tags`), c.succeed(`项目已推送到远程,地址: ${N.blue(a)}`);
1225
+ const d = w("初始化分支中").start(), y = `feat_init_${Ye()}`, f = [h.DEV, h.TEST, h.RELEASE, y], g = await Promise.allSettled(
1226
+ f.map(
1227
+ (F) => Ei({
1228
+ id: p.id,
1229
+ branch: F,
1230
+ ref: h.MASTER
1231
+ })
1232
+ )
1233
+ ), O = [];
1234
+ g.forEach(({ status: F }, K) => {
1235
+ F === "fulfilled" && O.push(f[K]);
1236
+ }), await u("git pull"), O.includes(y) ? (await u(`git checkout -b ${y} origin/${y}`), d.succeed(`项目已切换到初始分支: ${N.blue(y)}`)) : d.warn("开发分支检出失败!项目当前在主分支,请自行检出开发分支。");
1237
+ const ht = `cd ${e.projectName} && z start`;
1238
+ console.log(`输入 ${N.green(ht)} 开始开发吧~`), process.exit(0);
1239
+ } catch (e) {
1240
+ m(e);
1241
+ }
1242
+ }
1243
+ async function oa(e, t) {
1244
+ let i;
1245
+ e ? [
1246
+ "project",
1247
+ "pr"
1248
+ /* ProjectAbbr */
1249
+ ].includes(e) ? i = "project" : [
1250
+ "branch",
1251
+ "b"
1252
+ /* BranchAbbr */
1253
+ ].includes(e) ? i = "branch" : [
1254
+ "commit-msg",
1255
+ "cm"
1256
+ /* CommitMsgAbbr */
1257
+ ].includes(e) ? i = "commit-msg" : m("参数输入错误") : i = await E({
1258
+ message: "请选择你要创建的类型",
1259
+ choices: [
1260
+ {
1261
+ name: "提交信息(commit message)",
1262
+ value: "commit-msg"
1263
+ /* CommitMsg */
1264
+ },
1265
+ {
1266
+ name: "分支(branch)",
1267
+ value: "branch"
1268
+ /* Branch */
1269
+ },
1270
+ {
1271
+ name: "项目(project)",
1272
+ value: "project"
1273
+ /* Project */
1274
+ }
1275
+ ]
1276
+ }), i === "project" ? await ra() : (oe(), X(), i === "branch" ? (await ce(), await ia(t)) : i === "commit-msg" && await sa());
1277
+ }
1278
+ x.command("create").alias("c").description("创建项目/分支/提交信息").argument("[type]", "可选值为project|pr, branch|b, commit-msg|cm").option("--branch-type <type>", `分支类型。可选值:${Object.values(ue).join(", ")}`).option("--branch-purpose <purpose>", "创建分支的目的").action((...e) => z(oa, ...e));
1279
+ function ca(e) {
1280
+ return Xe({
1281
+ url: `${ee("K8sDomain")}/kapis/clusters/youshou-local/devops.kubesphere.io/v1alpha3/namespaces/${Pt}/pipelines/${e.projectName}/pipelineruns?branch=${e.branchName}`,
1282
+ method: "post",
1283
+ data: e.params
1284
+ });
1285
+ }
1286
+ async function ua(e) {
1287
+ const t = w("部署任务创建中").start(), { targetBranch: i, notify: n, projectName: a } = e, s = n ? [.../* @__PURE__ */ new Set([A("weWorkUserId"), ...n])] : [A("weWorkUserId")];
1288
+ try {
1289
+ const { metadata: o, spec: r } = await ca({
1290
+ projectName: a,
1291
+ branchName: i,
1292
+ params: {
1293
+ parameters: [
1294
+ {
1295
+ name: "QW_NOTIFY_USER",
1296
+ value: s.join(",")
1297
+ },
1298
+ {
1299
+ name: "QW_NOTIFY_GROUP",
1300
+ value: e.notifyGroup.join(",")
1301
+ }
1302
+ ]
1303
+ }
1304
+ }), c = `${ee("K8SWebDomain")}/youshou-local/clusters/youshou-local/devops/${o.namespace}/pipelines/${r.pipelineRef.name}/branch/${r.scm.refName}/run/${o.name}/task-status`;
1305
+ t.succeed("部署任务创建完成"), console.log(`如有需要,可在k8s中查看 ${N.blue(c)}`), process.exit(0);
1306
+ } catch (o) {
1307
+ t.fail("部署任务创建失败"), m(o);
1308
+ }
1309
+ }
1310
+ function la(e, t) {
1311
+ const i = $e();
1312
+ if (Ee()?.repository?.url || m(".z/project.json中缺少repository.url"), t === H.H5) {
1313
+ const a = `build:${e}`;
1314
+ i?.scripts[a] || m(`项目package.json文件scripts不存在命令${a}。`);
1315
+ }
1316
+ t === H.NPM && (i?.scripts.build || m("项目package.json文件scripts不存在命令build。")), t === H.SERVER && (i?.scripts.build || m("项目package.json文件scripts不存在命令build。"));
1317
+ }
1318
+ async function rt(e, t) {
1319
+ oe(), X(), await ce();
1320
+ let i = e, n = t.platform;
1321
+ if (i && !Object.values(h).includes(i) && m("仅支持发布指定环境分支"), n && !Object.values(H).includes(n) && m("发布平台错误"), n || (n = await E({
1322
+ message: "请选择平台",
1323
+ choices: Dt
1324
+ })), n === H.NPM && (i = h.MASTER), !i) {
1325
+ const c = await E({
1326
+ message: "请选择部署环境",
1327
+ choices: Ge
1328
+ });
1329
+ i = Vt(c);
1330
+ }
1331
+ let a = [];
1332
+ t.skipSelectionNotification || (a = await nt("请选择部署成功要通知的人员:", () => !0, !0));
1333
+ let s = [];
1334
+ t.skipGroupNotification || (s = await Wi("请选择部署成功要通知的群组:", () => !0, !0));
1335
+ const o = Wt(i);
1336
+ la(o, n);
1337
+ const r = $e();
1338
+ await ua({
1339
+ projectName: r.name,
1340
+ targetBranch: i,
1341
+ notify: a,
1342
+ notifyGroup: s
1343
+ });
1344
+ }
1345
+ async function ot(e, t, i, n) {
1346
+ const a = w(`分支合并中,${e} -> ${t}`).start();
1347
+ let s = 0;
1348
+ try {
1349
+ const { iid: r } = await Ni({
1350
+ title: `${e} -> ${t} by z-develop`,
1351
+ id: i.id,
1352
+ source_branch: e,
1353
+ target_branch: t,
1354
+ // 合到主分支上的分支需要在合并完成后被移除
1355
+ remove_source_branch: n ? !1 : h.MASTER === t
1356
+ });
1357
+ s = r;
1358
+ } catch (r) {
1359
+ le.isAxiosError(r) && r?.response?.status === 409 && m(`存在重复的合并请求,前往查看${i.mergeRequestUrl}`), m(r);
1360
+ }
1361
+ const o = async () => {
1362
+ try {
1363
+ await new Promise((r) => {
1364
+ setTimeout(r, 5e3);
1365
+ }), await Si({
1366
+ id: i.id,
1367
+ iid: s
1368
+ }), a.succeed(`分支${e}已合并到分支${t}`);
1369
+ } catch (r) {
1370
+ le.isAxiosError(r) || m(r);
1371
+ const c = r?.response?.status;
1372
+ if (c === 406)
1373
+ return await o();
1374
+ if (await ji({
1375
+ id: i.id,
1376
+ iid: s,
1377
+ state_event: "close"
1378
+ }), c === 405) {
1379
+ const p = await Ai({
1380
+ id: i.id,
1381
+ iid: s
1382
+ });
1383
+ if (p.merge_status === "cannot_be_merged" && p.diff_refs.base_sha === p.diff_refs.head_sha) {
1384
+ a.warn("MR已关闭。判定为空的合并请求(没有新内容),可继续进行部署");
1385
+ return;
1386
+ }
1387
+ }
1388
+ a.fail("合并过程中出现冲突,MR已关闭。建议在本地完成合并。"), process.exit(1);
1389
+ }
1390
+ };
1391
+ await o();
1392
+ }
1393
+ async function ma(e, t) {
1394
+ const i = `origin/${e.sourceBranch}`, n = await u(`git log -b origin/${h.MASTER} -1 --format=%H`), a = await u(`git log -b origin/${e.sourceBranch} -1 --format=%H`), s = await u(
1395
+ `git log ${n}...${a} -b ${i}`
1396
+ );
1397
+ if (s || m(`分支${e.sourceBranch}上不存在新的commit,不需要合并。`), await u(
1398
+ `git branch --contains ${n} -r ${i}`
1399
+ ) || (console.log(N.yellow("注意:当前分支上不存在远程主分支最新代码,将在自动合入后继续。")), await ot(h.MASTER, e.sourceBranch, e)), t === h.MASTER) {
1400
+ const r = s.split(`
1401
+ `).filter((y) => y), c = await u(`git log -b origin/${v.TEST} -1 --format=%H`), d = (await u(
1402
+ `git log ${n}...${c} -b origin/${v.TEST}`
1403
+ )).split(`
1404
+ `).filter((y) => y);
1405
+ Gt(d, r) || m("请先在测试环境发布要部署的代码");
1406
+ }
1407
+ }
1408
+ async function pa(e, t) {
1409
+ oe(), X(), await ce();
1410
+ const i = await pi();
1411
+ Object.values(h).includes(i.sourceBranch) && m(`当前分支${i.sourceBranch}不可作为源分支合并到目标分支。`);
1412
+ const a = (await Ti(i.id)).filter((c) => ![i.sourceBranch].includes(c.name)).map((c) => {
1413
+ let p = c.name;
1414
+ return Object.values(h).includes(p) && (p = N.bold.blue(p)), {
1415
+ name: p,
1416
+ value: c.name
1417
+ };
1418
+ });
1419
+ let s;
1420
+ e && !a.filter((c) => c.value === e).length && m(`未找到目标分支${e}`), e ? s = e : s = await E({
1421
+ message: "请选择要合并到的目标分支:",
1422
+ choices: a
1423
+ });
1424
+ const o = w(`本地分支${i.sourceBranch}检测中`).start();
1425
+ if (await u(`git ls-remote --heads origin ${i.sourceBranch}`)) {
1426
+ o.text = `存在远程分支origin/${i.sourceBranch}`, await u("git fetch");
1427
+ const c = await u(`git rev-parse ${i.sourceBranch}`), p = await u(`git rev-parse origin/${i.sourceBranch}`);
1428
+ await u(`git merge-base ${p} HEAD`) === p ? (await u(`git push -u origin ${i.sourceBranch}`), o.succeed(`本地分支${i.sourceBranch}已推送到远程分支origin/${i.sourceBranch}`)) : await u(`git merge-base ${c} ${p}`) === c ? (await u("git pull"), o.succeed(`本地分支${i.sourceBranch}已更新`)) : (o.fail(
1429
+ `远程分支origin/${i.sourceBranch}和本地分支${i.sourceBranch}都有新的提交,请手动合并后再试。`
1430
+ ), process.exit(1));
1431
+ } else
1432
+ await u(`git push -u origin ${i.sourceBranch}`), o.succeed(`本地分支${i.sourceBranch}已推送到远程分支origin/${i.sourceBranch}`);
1433
+ await ma(i, s), await ot(i.sourceBranch, s, i, t.keepBranchAfterMergeMaster), h.MASTER === s && !t.keepBranchAfterMergeMaster && (await u(`git checkout ${h.MASTER}`), await u(`git pull origin ${h.MASTER}`), await u(`git branch -d ${i.sourceBranch}`), J(
1434
+ `${i.sourceBranch}分支已移除,当前已切换到最新的${h.MASTER}。如需继续开发,请检出新分支(z c b)。`
1435
+ )), Object.values(h).includes(s) && await rt(s, {
1436
+ platform: t.deployPlatform,
1437
+ skipSelectionNotification: t.deploySkipSelectionNotification,
1438
+ skipGroupNotification: t.skipGroupNotification
1439
+ });
1440
+ }
1441
+ x.command("merge").alias("m").description("合并当前分支到指定远程分支,并部署。").argument("[branch]", "目标分支名称").option("--deploy-platform <platform>", `合并成功后要部署的平台。可选值:${Object.values(H).join("/")}`).option("--deploy-skip-selection-notification", "部署时,是否跳过选择部署通知人环节").option("--skip-group-notification", "是否跳过选择部署通知群聊环节").option("--keep-branch-after-merge-master", "在合并到主分支之后,是否保留分支。默认否").action((...e) => z(pa, ...e));
1442
+ x.command("deploy").alias("d").description("部署到指定环境").argument("[branchName]", `部署环境。可选值:${Object.values(h).join("/")}`).option("--platform <platform>", `部署平台。可选值:${Object.values(H).join("/")}`).option("--skip-selection-notification", "是否跳过选择部署通知人环节").option("--skip-group-notification", "是否跳过选择部署通知群聊环节").action((...e) => z(rt, ...e));
1443
+ function da() {
1444
+ const e = Ae();
1445
+ if ($(e)) {
1446
+ const t = j.readJsonSync(e);
1447
+ if (t["lint-staged"])
1448
+ return t["lint-staged"];
1449
+ throw new Error("未找到lint配置");
1450
+ } else
1451
+ throw new Error("请先初始化项目(z i .)。");
1452
+ }
1453
+ async function fa() {
1454
+ const e = w("代码风格检测中...").start();
1455
+ await Et({
1456
+ concurrent: 4,
1457
+ debug: !1,
1458
+ config: da(),
1459
+ quiet: !0,
1460
+ relative: !0
1461
+ }) ? (e.succeed("代码风格检测通过!"), process.exit(0)) : e.fail("代码风格检测未通过!");
1462
+ }
1463
+ function ga(e) {
1464
+ if (e.includes("Merge") && e.includes("# Conflicts:") || Tt.valid(e))
1465
+ return !0;
1466
+ const t = e.split(": ");
1467
+ if (t.length === 1)
1468
+ return "body前缺少「: 」";
1469
+ const i = t[0];
1470
+ return /^(feat|fix|refactor)/.test(i) ? /\(\d+(?:,\d+)*\)/.test(i) ? !0 : "ID缺少或者格式不正确。" : /^(chore|ci)/.test(i) ? [b.CHORE, b.CI].includes(i) ? !0 : "chore/ci类型无需填写ID。" : b.Break === i ? !0 : "不存在的提交类型。";
1471
+ }
1472
+ async function ha() {
1473
+ const e = await Se(l.resolve(".git", "COMMIT_EDITMSG"), "utf-8"), t = w("提交信息格式校验中...").start(), i = ga(e);
1474
+ i === !0 ? (t.succeed("提交信息格式校验通过"), process.exit(0)) : t.fail(`提交信息格式校验失败。${i}`);
1475
+ }
1476
+ async function wa() {
1477
+ await ce();
1478
+ const e = await kt({
1479
+ // 分组,展示仓库链接
1480
+ format: ["group", "repo"],
1481
+ // 交互式弹窗
1482
+ interactive: !0,
1483
+ // 版本是否需要升级
1484
+ upgrade: !0,
1485
+ // 是否自动安装
1486
+ install: "always"
1487
+ });
1488
+ if (e && Object.keys(e).length) {
1489
+ J("升级完成 🎉");
1490
+ const t = Object.entries(e).map(([i, n]) => `${i}@${n}`).join("; ");
1491
+ await u(`git add . && git commit -m "chore: 依赖升级。${t}"`);
1492
+ }
1493
+ process.exit(0);
1494
+ }
1495
+ async function ya(e) {
1496
+ $(l.resolve("node_modules", ".bin", "eslint")) || m("该项目未安装eslint,请安装后重试");
1497
+ const t = w("eslint执行中...").start();
1498
+ try {
1499
+ let i = "npx eslint '**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}' --fix";
1500
+ process.platform === "win32" && (i = 'npx eslint "**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}" --fix'), e.quiet && (i += " --quiet"), e.maxWarnings && !isNaN(Number(e.maxWarnings)) ? i += ` --max-warnings ${Number(e.maxWarnings)}` : i += " --max-warnings 100", await u(i, {
1501
+ silent: !1
1502
+ }), t.succeed("eslint执行成功"), process.exit(0);
1503
+ } catch {
1504
+ t.fail("eslint校验出错");
1505
+ }
1506
+ }
1507
+ async function $a() {
1508
+ $(l.resolve("node_modules", ".bin", "prettier")) || m("该项目未安装prettier,请安装后重试");
1509
+ const e = w("prettier执行中...").start();
1510
+ try {
1511
+ await u(
1512
+ "npx prettier --write . --config .z/.prettierrc.json --ignore-path .z/.prettierignore --ignore-unknown --no-error-on-unmatched-pattern",
1513
+ {
1514
+ silent: !1
1515
+ }
1516
+ ), e.succeed("prettier执行成功"), process.exit(0);
1517
+ } catch {
1518
+ e.fail("prettier校验出错");
1519
+ }
1520
+ }
1521
+ function va() {
1522
+ $(l.resolve("./node_modules/.bin/vue-tsc")) || m("请先安装vue-tsc。推荐命令: npm i -D vue-tsc"), Qe("npx vue-tsc --build"), process.exit(0);
1523
+ }
1524
+ async function ba(e, t) {
1525
+ oe(), X();
1526
+ let i;
1527
+ e ? [
1528
+ "commit-msg",
1529
+ "cm"
1530
+ /* CommitMsgAbbr */
1531
+ ].includes(e) ? i = "commit-msg" : [
1532
+ "commit-files",
1533
+ "cf"
1534
+ /* CommitFilesAbbr */
1535
+ ].includes(e) ? i = "commit-files" : [
1536
+ "prettier",
1537
+ "p"
1538
+ /* PrettierAbbr */
1539
+ ].includes(e) ? i = "prettier" : [
1540
+ "eslint",
1541
+ "e"
1542
+ /* EslintAbbr */
1543
+ ].includes(e) ? i = "eslint" : [
1544
+ "type-check",
1545
+ "tc"
1546
+ /* TypeCheckAbbr */
1547
+ ].includes(e) ? i = "type-check" : [
1548
+ "dependency-check",
1549
+ "dc"
1550
+ /* DependencyCheckAbbr */
1551
+ ].includes(e) ? i = "dependency-check" : m("参数输入错误") : i = await E({
1552
+ message: "请选择你要执行的操作",
1553
+ choices: [
1554
+ {
1555
+ name: "执行 prettier",
1556
+ value: "prettier"
1557
+ /* Prettier */
1558
+ },
1559
+ {
1560
+ name: "执行 eslint",
1561
+ value: "eslint"
1562
+ /* Eslint */
1563
+ },
1564
+ {
1565
+ name: "执行 type-check",
1566
+ value: "type-check"
1567
+ /* TypeCheck */
1568
+ },
1569
+ {
1570
+ name: "执行 dependency-check",
1571
+ value: "dependency-check"
1572
+ /* DependencyCheck */
1573
+ }
1574
+ ]
1575
+ }), i === "commit-msg" ? await ha() : i === "commit-files" ? await fa() : i === "prettier" ? await $a() : i === "eslint" ? await ya(t) : i === "type-check" ? va() : i === "dependency-check" && await wa();
1576
+ }
1577
+ x.command("run").alias("r").description("执行 eslint / prettier / type-check / dependency-check 脚本。").argument(
1578
+ "[type]",
1579
+ "非必填。可选值为commit-msg|cm, commit-files|cf, prettier|p, eslint|e, type-check|tc, dependency-check|dc。"
1580
+ ).option("--quiet", "eslint只打印error").option("--max-warnings [VALUE]", "eslint结果warn超过多少个会异常退出,默认为100", parseInt).action((...e) => z(ba, ...e));
1581
+ async function ct(e = "latest") {
1582
+ const t = w("安装中...").start();
1583
+ await u(`npm i -g ${Q.name}@${e} --registry https://registry.npmmirror.com/`), t.text = "本地配置更新中...", ne("latestCheckVersionTimestamp", Date.now()), ne("version", e), te(), t.succeed(`升级完成,当前版本${e}`), process.exit(0);
1584
+ }
1585
+ x.command("update").alias("u").description("升级").argument("[version]", "版本号", "latest").action((...e) => z(ct, ...e));
1586
+ async function Na(e) {
1587
+ let t = e;
1588
+ t ? [v.DEV, v.TEST, v.RELEASE, v.PROD, "d", "t", "r", "p"].includes(e) ? t === "d" ? t = v.DEV : t === "t" ? t = v.TEST : t === "r" ? t = v.RELEASE : t === "p" && (t = v.PROD) : m("参数输入有误") : t = await E({
1589
+ message: "请选择环境",
1590
+ choices: Ge
1591
+ });
1592
+ const i = $e(), n = `dev:${t}`;
1593
+ i.scripts[n] ? Qe(`npm run ${n}`) : m(`项目中(package.json > scripts)不存在命令${n},请先添加!`);
1594
+ }
1595
+ x.command("start").alias("s").description("启动本地开发环境").argument("[env]", "业务环境。可选值 dev|d, test|t, release|r, prod|p").action((...e) => z(Na, ...e));
1596
+ const Re = /Thumbs\.db|\.git|DS_Store|idea/, ut = "testcase";
1597
+ function lt(e) {
1598
+ const t = e.match(/^(.*[^[])?\[(\d+)]$/);
1599
+ if (t && !e.startsWith("["))
1600
+ return {
1601
+ type: "module",
1602
+ id: t[2],
1603
+ displayName: t[1]?.trim() || ""
1604
+ };
1605
+ const i = e.match(/^\[(\d+)](.+)$/);
1606
+ return i ? {
1607
+ type: "case",
1608
+ id: i[1],
1609
+ displayName: i[2]?.trim() || ""
1610
+ } : {
1611
+ type: "directory",
1612
+ id: void 0,
1613
+ displayName: e
1614
+ };
1615
+ }
1616
+ async function Y(e, t = {}) {
1617
+ const { exclude: i = Re } = t, n = [];
1618
+ async function a(s) {
1619
+ const o = l.basename(s);
1620
+ if ((await bt(s)).isFile())
1621
+ return null;
1622
+ const c = await je(s, { withFileTypes: !0 }), p = (await Promise.all(
1623
+ c.filter((O) => O.isDirectory() && !i.test(O.name)).map((O) => a(l.join(s, O.name)))
1624
+ )).filter(Boolean), { type: d, id: y, displayName: f } = lt(o), g = {
1625
+ name: o,
1626
+ id: y,
1627
+ displayName: f,
1628
+ path: s,
1629
+ type: d,
1630
+ children: p
1631
+ };
1632
+ return (t.hasRoot || l.resolve(e) !== s) && n.push(g), g;
1633
+ }
1634
+ return await a(l.resolve(e)), n;
1635
+ }
1636
+ async function mt(e, t = {}) {
1637
+ const { exclude: i = Re } = t;
1638
+ try {
1639
+ const n = await je(l.resolve(e), { withFileTypes: !0 });
1640
+ return await Promise.all(
1641
+ n.filter((a) => a.isDirectory() && !i.test(a.name)).map((a) => {
1642
+ const s = l.join(e, a.name), { type: o, id: r, displayName: c } = lt(a.name);
1643
+ return {
1644
+ name: a.name,
1645
+ id: r,
1646
+ displayName: c,
1647
+ path: s,
1648
+ type: o
1649
+ };
1650
+ })
1651
+ );
1652
+ } catch (n) {
1653
+ return m(`读取目录失败: ${e} : ${n}`), [];
1654
+ }
1655
+ }
1656
+ function G(e, t, i) {
1657
+ switch (e) {
1658
+ case "module":
1659
+ return i ? `${t}[${i}]` : t;
1660
+ case "case":
1661
+ return i ? `[${i}]${t}` : t;
1662
+ default:
1663
+ return t;
1664
+ }
1665
+ }
1666
+ async function fe(e, t, i, n) {
1667
+ try {
1668
+ const a = l.basename(e), s = G(i, t, n);
1669
+ if (a === s)
1670
+ return !0;
1671
+ const o = l.dirname(e), r = l.join(o, s);
1672
+ return await qt(e) ? await Fe(e, r) : (await u(`git mv "${e}" "${r}"`), await u("git add .")), !0;
1673
+ } catch (a) {
1674
+ return m(`重命名文件夹失败: ${e} -> ${t}。${a}`), !1;
1675
+ }
1676
+ }
1677
+ async function Sa(e, t, i = {}) {
1678
+ const { exclude: n = Re } = i;
1679
+ async function a(s, o) {
1680
+ if (!s || s.length === 0) return;
1681
+ const r = await mt(o, { exclude: n });
1682
+ for (const c of s) {
1683
+ const p = String(c.value), d = G("module", c.label, p), y = r.find((g) => g.id === p);
1684
+ let f = y?.path || l.join(o, d);
1685
+ y ? y.displayName !== c.label && await fe(y.path, c.label, "module", p) && (f = l.join(o, d)) : (await se(f, { recursive: !0 }), await u(`git add "${f}"`)), c.children && c.children.length > 0 && await a(c.children, f);
1686
+ }
1687
+ }
1688
+ await a(e, l.resolve(t));
1689
+ }
1690
+ async function pt(e) {
1691
+ const t = {
1692
+ id: 0,
1693
+ name: "",
1694
+ path: ""
1695
+ };
1696
+ if (e)
1697
+ Number.isNaN(Number(e)) && m("请输入正确的产品ID"), t.id = Number(e);
1698
+ else {
1699
+ const i = await Ii();
1700
+ t.id = await E({
1701
+ message: "请选择产品",
1702
+ choices: i.map((n) => ({
1703
+ name: `${n.label}[${n.value}]`,
1704
+ value: n.value
1705
+ }))
1706
+ });
1707
+ }
1708
+ return t.name = await Di(t.id), t.path = l.join(ut, G("module", t.name, String(t.id))), t;
1709
+ }
1710
+ async function Ie(e) {
1711
+ return (await mt(ut)).find((i) => Number(i.id) === e.id);
1712
+ }
1713
+ async function dt(e, t) {
1714
+ const i = {
1715
+ precondition: e.precondition,
1716
+ priority: e.pri,
1717
+ steps: []
1718
+ };
1719
+ i.steps = await Li(e.id), j.writeJSONSync(t, i, {
1720
+ spaces: 2
1721
+ });
1722
+ }
1723
+ async function ft(e, t) {
1724
+ await se(t, {
1725
+ recursive: !0
1726
+ }), await dt(e, l.join(t, "config.json")), j.ensureFileSync(l.join(t, "data.json")), await M(
1727
+ l.join(t, "data.json"),
1728
+ $(l.resolve(q, "data.json")) ? await Se(l.resolve(q, "data.json")) : Yt
1729
+ ), j.ensureFileSync(l.join(t, "main.py")), await M(
1730
+ l.join(t, "main.py"),
1731
+ $(l.resolve(q, "main.py")) ? await Se(l.resolve(q, "main.py")) : Xt
1732
+ );
1733
+ }
1734
+ function gt(e) {
1735
+ if (e) {
1736
+ const t = e.split(",").map((i) => i.trim()).filter((i) => {
1737
+ const n = Number(i);
1738
+ return Number.isInteger(n) && n > 0;
1739
+ }).map((i) => Number(i));
1740
+ return t.length === 0 ? (m('未找到有效的ID,请输入格式如 "1,2,3,4" 的正整数ID'), []) : t;
1741
+ }
1742
+ return [];
1743
+ }
1744
+ async function ve(e, t) {
1745
+ oe(), X(), await ce();
1746
+ let i;
1747
+ t ? ([S.MODULE, S.CASE].includes(t) || m(`不支持的参数${t}。参数值应为 ${S.MODULE} 或者 ${S.CASE}。`), i = t) : i = await E({
1748
+ message: `请选择要${e}的数据类型`,
1749
+ choices: Ot
1750
+ });
1751
+ const n = i === S.MODULE ? "模块" : S.CASE === i ? "用例" : "";
1752
+ return {
1753
+ type: i,
1754
+ typeStr: n
1755
+ };
1756
+ }
1757
+ async function De(e) {
1758
+ const t = await pt(e), i = await Ie(t);
1759
+ return i || m(`本地未找到产品【${t.name}[${t.id}]】`), {
1760
+ product: t,
1761
+ localProduct: i
1762
+ };
1763
+ }
1764
+ async function ja(e, t, i) {
1765
+ e.text = "查找本地产品目录...", await Ie(t) || m(`本地未找到产品【${t.name}[${t.id}]】`), e.text = "解析ID参数...";
1766
+ const a = gt(i);
1767
+ let s = await Y(t.path);
1768
+ e.text = "获取远程用例列表...";
1769
+ const o = await xi(t.id, a);
1770
+ e.text = "本地用例同步中...";
1771
+ for (const r of o) {
1772
+ let c;
1773
+ if (r.module === 0 ? c = l.resolve(t.path) : c = s.find((d) => Number(d.id) === r.module)?.path || "", !c)
1774
+ return m(`用例${r.title}[${r.id}]未找到所属模块(${r.module}),请先拉取模块`);
1775
+ const p = s.find(({ id: d }) => r.id === Number(d));
1776
+ if (p)
1777
+ p.displayName !== r.title && await fe(p.path, r.title, p.type, p.id) && J(`重命名成功: ${p.displayName} -> ${r.title}`), s = await Y(t.path), r.module === 0 ? c = l.resolve(t.path) : c = s.find((d) => Number(d.id) === r.module)?.path || "", await dt(
1778
+ r,
1779
+ l.join(c, G("case", r.title, String(r.id)), "config.json")
1780
+ );
1781
+ else {
1782
+ const d = l.join(c, G("case", r.title, String(r.id)));
1783
+ await ft(r, d);
1784
+ }
1785
+ }
1786
+ }
1787
+ async function Aa(e, t) {
1788
+ e.text = "本地产品目录查找中...";
1789
+ const i = await Ie(t);
1790
+ i ? (e.text = "找到产品目录。开始重命名...", i.displayName !== t.name && await fe(i.path, t.name, i.type, i.id) && (e.text = `重命名成功: ${i.displayName} -> ${t.name}`)) : (e.text = "未找到。开始创建产品目录...", await se(t.path, { recursive: !0 }), await u("git add .")), e.text = "获取远程模块列表...";
1791
+ const n = await it(t.id);
1792
+ e.text = "本地同步模块中...", await Sa(n || [], t.path);
1793
+ }
1794
+ async function Ea(e, t) {
1795
+ const { type: i, typeStr: n } = await ve("拉取", e), a = await pt(t.productId), s = w(`${n}同步中...`).start();
1796
+ if (S.MODULE === i && await Aa(s, a), S.CASE === i && await ja(s, a, t.caseIds), s.succeed(`${n}同步完成 🎉`), !t.disableAutoCommit && await u("git status -s")) {
1797
+ const o = w("代码提交中...").start();
1798
+ try {
1799
+ await u(`git add . && git commit -m "chore: 同步禅道${n}数据"`), o.succeed("代码已提交 ✅");
1800
+ } catch (r) {
1801
+ o.fail(`提交失败,${r}`);
1802
+ }
1803
+ }
1804
+ }
1805
+ x.command("qa-pull").alias("qp").description("将禅道中的模块或者用例同步到本地").argument("[type]", "可选值为module/case").option("--product-id <productId>", "指定产品ID").option("--case-ids <caseIds>", "type=case时,可传指定用例ID(可传N个,逗号隔开);不传则为产品下全部用例").option("--disable-auto-commit", "是否跳过自动将修改结果提交。").action((...e) => z(Ea, ...e));
1806
+ async function Ta(e, t, i) {
1807
+ const n = await _({
1808
+ message: "请输入你要创建的用例的前置条件(可不填)"
1809
+ }), a = w(`用例【${i}】开始创建...`).start();
1810
+ a.text = "远程用例创建中...";
1811
+ const s = await Oi({
1812
+ product: Number(e.id),
1813
+ // 如果父模块是产品根目录,parent=0
1814
+ module: l.resolve(e?.path) === t?.path ? 0 : Number(t?.id || 0),
1815
+ title: i,
1816
+ type: "interface",
1817
+ openedBy: A("ldapAccount"),
1818
+ precondition: n || ""
1819
+ });
1820
+ a.text = "远程用例步骤创建中...", await Mi({
1821
+ case: s,
1822
+ type: "step",
1823
+ desc: "按照预期执行",
1824
+ expect: "正常执行,符合预期"
1825
+ }), a.text = "本地用例创建中...";
1826
+ const o = l.join(t.path, G("case", i, String(s)));
1827
+ return $(o) ? J(`${o}已存在,请检查是否对应,本地不再创建。`) : (await ft(
1828
+ {
1829
+ id: s,
1830
+ pri: 3,
1831
+ precondition: n
1832
+ },
1833
+ o
1834
+ ), a.succeed(`用例【[${o}】创建完成 🎉`), o);
1835
+ }
1836
+ async function ka(e, t, i) {
1837
+ const n = w(`模块【${i}】开始创建...`).start();
1838
+ n.text = "远程模块创建中...";
1839
+ const a = await Pi({
1840
+ root: Number(e.id),
1841
+ name: i,
1842
+ // 如果父模块是产品根目录,parent=0
1843
+ parent: l.resolve(e?.path) === t?.path ? 0 : Number(t?.id || 0)
1844
+ });
1845
+ n.text = "本地模块创建中...";
1846
+ const s = l.join(t.path, G("module", i, String(a)));
1847
+ if ($(s))
1848
+ return J(`${s}已存在,请检查是否对应,本地不再创建。`);
1849
+ await se(s, {
1850
+ recursive: !0
1851
+ }), n.succeed(`模块【${s}】创建完成 🎉`);
1852
+ }
1853
+ function Ca(e) {
1854
+ function t(n) {
1855
+ if (!n.children || n.children.length === 0) return;
1856
+ const a = n.children[0];
1857
+ a && a.label === n.label && a.value === n.value && (!a.children || a.children.length === 0) || n.children.unshift({
1858
+ value: n.value,
1859
+ label: n.label,
1860
+ type: n.type,
1861
+ children: void 0,
1862
+ tempTitle: "当前层级"
1863
+ });
1864
+ }
1865
+ async function i(n, a = []) {
1866
+ const s = a.length ? `请选择层级(当前:${a.join(" / ")})` : "请选择层级", o = await E({
1867
+ message: s,
1868
+ choices: n.map((r) => ({
1869
+ name: `${r.tempTitle ? r.tempTitle : r.label} ${r.children?.length ? "(有子级)" : ""}`,
1870
+ value: r
1871
+ }))
1872
+ });
1873
+ return o?.children?.length ? (t(o), i(o.children, [...a, o.label])) : o;
1874
+ }
1875
+ return i(e);
1876
+ }
1877
+ async function Ra(e, t) {
1878
+ const { type: i, typeStr: n } = await ve("创建", e), { product: a, localProduct: s } = await De(t.productId), o = await it(a.id), r = await Ca(o), c = G("module", r.label, String(r.value)), d = (await Y(a.path, { hasRoot: !0 })).find((g) => g.name === c);
1879
+ if (!d?.path || !$(d.path))
1880
+ return m(`本地不存在${c}模块`);
1881
+ const y = await _({
1882
+ message: `请输入你要创建的${n}名称`,
1883
+ required: !0,
1884
+ validate: (g) => g.length > 0 && g.length < 255
1885
+ });
1886
+ let f = "";
1887
+ if (S.MODULE === i && await ka(s, d, y), S.CASE === i && (f = await Ta(s, d, y)), !t.disableAutoCommit && S.CASE === i) {
1888
+ const g = w("代码提交中...").start();
1889
+ try {
1890
+ await u(`git add . && git commit -m "chore: 创建了用例${l.basename(f)}"`), g.succeed("代码已提交 ✅");
1891
+ } catch (O) {
1892
+ g.fail(`提交失败,${O}`);
1893
+ }
1894
+ }
1895
+ }
1896
+ x.command("qa-create").alias("qc").description("创建模块或者用例").argument("[type]", "可选值为module/case").option("--product-id <productId>", "指定产品ID").option("--disable-auto-commit", "是否跳过自动将修改结果提交。").action((...e) => z(Ra, ...e));
1897
+ async function Ia(e, t) {
1898
+ const n = (await Y(e.path)).filter((r) => r.type === "case");
1899
+ let a = [];
1900
+ if (t.length)
1901
+ a = n.filter((r) => t.includes(Number(r.id))).map((r) => ({
1902
+ id: Number(r.id),
1903
+ path: r.path
1904
+ })), a.length || m(`未找到对应用例,请确认输入的用例ID(${t.join(", ")})是否正确`);
1905
+ else {
1906
+ const r = n.map((c) => ({
1907
+ value: {
1908
+ id: Number(c.id),
1909
+ path: c.path
1910
+ },
1911
+ name: c.path.replace(l.resolve(e.path), "")
1912
+ }));
1913
+ a = await re({
1914
+ message: "选择要删除的用例",
1915
+ pageSize: 100,
1916
+ loop: !1,
1917
+ options: (c) => c ? r.filter((p) => p.name.includes(c)) : r,
1918
+ validate(c) {
1919
+ return c.length === 0 ? "至少选择一项" : !0;
1920
+ }
1921
+ });
1922
+ }
1923
+ const s = w("远程用例删除中...").start(), o = a.map((r) => r.id);
1924
+ await Fi({
1925
+ product: Number(e.id),
1926
+ caseIds: o
1927
+ }), s.text = "本地用例删除中...";
1928
+ for (const r of a)
1929
+ $(r.path) && D.rm("-rf", r.path);
1930
+ return s.succeed("用例删除完成"), o;
1931
+ }
1932
+ async function Da(e, t) {
1933
+ const n = (await Y(e.path)).filter((r) => r.type === "module");
1934
+ let a = [];
1935
+ if (t.length)
1936
+ a = n.filter((r) => t.includes(Number(r.id))).map((r) => ({
1937
+ id: Number(r.id),
1938
+ path: r.path
1939
+ })), a.length || m(`未找到对应模块,请确认输入的模块ID(${t.join(", ")})是否正确`);
1940
+ else {
1941
+ const r = n.map((c) => ({
1942
+ value: {
1943
+ id: Number(c.id),
1944
+ path: c.path
1945
+ },
1946
+ name: c.path.replace(l.resolve(e.path), "")
1947
+ }));
1948
+ a = await re({
1949
+ message: "选择要删除的模块",
1950
+ pageSize: 100,
1951
+ loop: !1,
1952
+ options: (c) => c ? r.filter((p) => p.name.includes(c)) : r,
1953
+ validate(c) {
1954
+ return c.length === 0 ? "至少选择一项" : !0;
1955
+ }
1956
+ });
1957
+ }
1958
+ a = a.sort((r, c) => r.path.localeCompare(c.path));
1959
+ const s = w("远程模块删除中...").start(), o = a.map((r) => r.id);
1960
+ await zi({
1961
+ product: Number(e.id),
1962
+ moduleIds: o
1963
+ }), s.text = "本地模块删除中...";
1964
+ for (const r of a)
1965
+ $(r.path) && D.rm("-rf", r.path);
1966
+ return s.succeed("模块删除完成"), o;
1967
+ }
1968
+ async function xa(e, t) {
1969
+ const { type: i, typeStr: n } = await ve("删除", e), { localProduct: a } = await De(t.productId), s = gt(t.targetIds);
1970
+ let o = [];
1971
+ if (S.MODULE === i ? o = await Da(a, s) : S.CASE === i && (o = await Ia(a, s)), !t.disableAutoCommit && await u("git status -s")) {
1972
+ const r = w("代码提交中...").start();
1973
+ try {
1974
+ await u(`git add . && git commit -m 'chore: 删除了一些${n}(${o.join(", ")})'`), r.succeed("代码已提交 ✅");
1975
+ } catch (c) {
1976
+ r.fail(`提交失败,${c}`);
1977
+ }
1978
+ }
1979
+ }
1980
+ x.command("qa-remove").alias("qr").description("删除模块或者用例").argument("[type]", "可选值为module/case").option("--product-id <productId>", "指定产品ID").option("--target-ids <targetIds>", "可传指定目标(用例/模块)ID。可传N个,逗号隔开").option("--disable-auto-commit", "是否跳过自动将修改结果提交。").action((...e) => z(xa, ...e));
1981
+ async function La(e, t) {
1982
+ const n = (await Y(e.path)).filter((f) => f.type === "case");
1983
+ let a;
1984
+ if (t.targetId) {
1985
+ if (a = n.find((f) => Number(f.id) === Number(t.targetId)), !a)
1986
+ return m(`未找到对应用例,请确认输入的用例ID(${t.targetId})是否正确`);
1987
+ } else {
1988
+ const f = n.map((g) => ({
1989
+ value: {
1990
+ id: Number(g.id),
1991
+ path: g.path,
1992
+ displayName: g.displayName
1993
+ },
1994
+ name: g.path.replace(l.resolve(e.path), "")
1995
+ }));
1996
+ [a] = await re({
1997
+ message: "选择要更新的用例",
1998
+ pageSize: 100,
1999
+ loop: !1,
2000
+ multiple: void 0,
2001
+ options: (g) => g ? f.filter((O) => O.name.includes(g)) : f,
2002
+ validate(g) {
2003
+ return g.length > 1 ? "只能选一个" : g.length < 1 ? "请选一个" : !0;
2004
+ }
2005
+ });
2006
+ }
2007
+ const s = await _({
2008
+ message: "修改用例名称",
2009
+ default: a.displayName,
2010
+ required: !0,
2011
+ validate: (f) => f.length > 0 && f.length < 255,
2012
+ prefill: "editable"
2013
+ }), o = w("用例重命名中...").start();
2014
+ if (s !== a.displayName) {
2015
+ await Bi({
2016
+ id: Number(a.id),
2017
+ name: s
2018
+ });
2019
+ const f = await fe(a.path, s, "case", String(a.id));
2020
+ a.displayName = s, a.path = l.join(l.dirname(a.path), G("case", s, String(a.id))), f && o.succeed(`用例重命名成功: ${a.displayName} -> ${s}`);
2021
+ } else
2022
+ o.succeed("用例名称无变动");
2023
+ const r = j.readJsonSync(l.join(a.path, "config.json"));
2024
+ let c;
2025
+ t.casePriority ? Number.isInteger(t.casePriority) && Number(t.casePriority) > 0 && Number(t.casePriority) < 6 ? c = Number(t.casePriority) : c = await Oe({
2026
+ message: "修改用例优先级",
2027
+ min: 1,
2028
+ max: 5,
2029
+ required: !0,
2030
+ default: r.priority,
2031
+ validate: (f) => f > 0 && f < 6
2032
+ }) : c = await Oe({
2033
+ message: "修改用例优先级",
2034
+ min: 1,
2035
+ max: 5,
2036
+ required: !0,
2037
+ default: r.priority,
2038
+ validate: (f) => f > 0 && f < 6
2039
+ });
2040
+ const p = w("用例优先级设置中...").start();
2041
+ c !== r.priority ? (await Ui({
2042
+ id: Number(a.id),
2043
+ priority: c
2044
+ }), j.writeJSONSync(
2045
+ l.join(a.path, "config.json"),
2046
+ {
2047
+ ...r,
2048
+ priority: c
2049
+ },
2050
+ { spaces: 2 }
2051
+ ), p.succeed(`用例优先级修改成功:${r.priority} -> ${c}`)) : p.succeed("用例优先级无变动");
2052
+ let d;
2053
+ t.casePrecondition ? d = t.casePrecondition : d = await _({
2054
+ message: "修改用例前置条件",
2055
+ default: r.precondition,
2056
+ prefill: "editable"
2057
+ });
2058
+ const y = w("用例前置条件设置中...").start();
2059
+ return d !== r.precondition ? (await Ji({
2060
+ id: Number(a.id),
2061
+ precondition: d
2062
+ }), j.writeJSONSync(
2063
+ l.join(a.path, "config.json"),
2064
+ {
2065
+ ...r,
2066
+ precondition: d
2067
+ },
2068
+ { spaces: 2 }
2069
+ ), y.succeed(`用例前置条件修改成功:${r.priority} -> ${c}`)) : y.succeed("用例前置条件无变动"), a.id;
2070
+ }
2071
+ async function Pa(e, t) {
2072
+ const n = (await Y(e.path)).filter((r) => r.type === "module");
2073
+ let a;
2074
+ if (t.targetId) {
2075
+ if (a = n.find((r) => Number(r.id) === Number(t.targetId)), !a)
2076
+ return m(`未找到对应模块,请确认输入的模块ID(${t.targetId})是否正确`);
2077
+ } else {
2078
+ const r = n.map((c) => ({
2079
+ value: {
2080
+ id: Number(c.id),
2081
+ path: c.path,
2082
+ displayName: c.displayName
2083
+ },
2084
+ name: c.path.replace(l.resolve(e.path), "")
2085
+ }));
2086
+ [a] = await re({
2087
+ message: "选择要更新的模块",
2088
+ pageSize: 100,
2089
+ loop: !1,
2090
+ multiple: void 0,
2091
+ options: (c) => c ? r.filter((p) => p.name.includes(c)) : r,
2092
+ validate(c) {
2093
+ return c.length > 1 ? "只能选一个" : c.length < 1 ? "请选一个" : !0;
2094
+ }
2095
+ });
2096
+ }
2097
+ const s = await _({
2098
+ message: "修改模块名称",
2099
+ default: a.displayName,
2100
+ required: !0,
2101
+ validate: (r) => r.length > 0 && r.length < 255,
2102
+ prefill: "editable"
2103
+ }), o = w("模块重命名中...").start();
2104
+ return s !== a.displayName ? (await _i({
2105
+ id: Number(a.id),
2106
+ name: s
2107
+ }), await fe(a.path, s, "module", String(a.id)) && o.succeed(`模块重命名成功: ${a.displayName} -> ${s}`)) : o.succeed("模块名称无变动"), a.id;
2108
+ }
2109
+ async function Oa(e, t) {
2110
+ const { type: i, typeStr: n } = await ve("修改", e), { localProduct: a } = await De(t.productId);
2111
+ let s;
2112
+ if (S.MODULE === i ? s = await Pa(a, t) : S.CASE === i && (s = await La(a, t)), !t.disableAutoCommit && await u("git status -s")) {
2113
+ const o = w("代码提交中...").start();
2114
+ try {
2115
+ await u(`git add . && git commit -m 'chore: 修改了一个${n}(${s})'`), o.succeed("代码已提交 ✅");
2116
+ } catch (r) {
2117
+ o.fail(`提交失败,${r}`);
2118
+ }
2119
+ }
2120
+ }
2121
+ x.command("qa-update").alias("qu").description("修改模块或者用例").argument("[type]", "可选值为module/case").option("--product-id <productId>", "指定产品ID").option("--target-id <targetId>", "可传指定目标(用例/模块)ID").option("--target-name <targetName>", "可传指定目标(用例/模块)修改后的名称").option("--case-priority <casePriority>", "如果是用例,指定修改后的优先级").option("--case-precondition <casePrecondition>", "如果是用例,指定修改后的前置条件").option("--disable-auto-commit", "是否跳过自动将修改结果提交。").action((...e) => z(Oa, ...e));
2122
+ function Ma() {
2123
+ process.on("unhandledRejection", (e) => {
2124
+ }), process.on("uncaughtException", (e) => {
2125
+ }), D.config.fatal = !0, D.config.silent = !0, D.config.verbose = !1;
2126
+ }
2127
+ async function za() {
2128
+ const e = pe("latestCheckVersionTimestamp"), t = pe("versionCheckDuring");
2129
+ if (Date.now() - Number(e) > Number(t) * 24 * 3600 * 1e3) {
2130
+ const i = await et();
2131
+ Te(i);
2132
+ let n;
2133
+ try {
2134
+ const a = "TIME_OUT", s = new Promise((o) => {
2135
+ setTimeout(() => o(a), 3e3);
2136
+ });
2137
+ n = await Promise.race([
2138
+ s,
2139
+ u(`npm view ${Q.name} version --registry https://registry.npmmirror.com/`)
2140
+ ]), n !== a && n !== Q.version && (console.log(`${N.blue(Q.name)}本地版本为${Q.version},低于线上版本${n},开始升级`), await ct(n)), ne("latestCheckVersionTimestamp", Date.now()), te();
2141
+ } catch (a) {
2142
+ console.log("升级出错!请重试,或者手动升级"), m(a);
2143
+ }
2144
+ }
2145
+ }
2146
+ async function Fa() {
2147
+ const e = Ct(process.argv.slice(2));
2148
+ if (!(e.h || e.help || e.v || e.version) && !(["init", "i"].includes(e._[0]) && ![".", "prepare"].includes(e._[1])))
2149
+ if (qe()) {
2150
+ const t = j.readJSONSync(ye());
2151
+ L(t.profile), ne(t.main), Te(t.constants), await za();
2152
+ } else
2153
+ m(`请先初始化z-develop(执行 z i)。更多见${We}`);
2154
+ }
2155
+ async function _a() {
2156
+ Ma(), await Fa();
2157
+ }
2158
+ x.name("z-develop").alias("z").description(`z-develop, 开发流程管理工具。了解更多: ${N.blue(We)}`).usage("<command> [options]").hook("preAction", _a).version(Q.version, "-v, --version", "当前版本号").helpOption("-h, --help", "帮助").showHelpAfterError("可以使用z -h查看帮助。");
2159
+ x.parse();