cli-z-develop 0.9.2 → 0.10.0

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