cli-z-develop 0.1.4 → 0.1.5
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/README.md +2 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{program as e}from"commander";import t from"node:fs";import n from"node:path";import a,{AxiosError as i}from"axios";import s from"chalk";import r from"dayjs";import o from"shelljs";import c from"node:os";import l from"child_process";import{confirm as u,select as m,input as p,password as d,checkbox as g}from"@inquirer/prompts";import f from"ora";import h from"fs-extra";import{select as w}from"inquirer-select-pro";import v from"lint-staged";import y from"semver";import $ from"minimist";const j=".z",b="develop-config.json",x=".z",S=".commit-msg-tpl",k="project.json";function O(e=""){return n.join(x,e)}function z(){return O(k)}function N(){return O(S)}function T(){l.spawnSync("git",["config","core.hooksPath",O()]),l.spawnSync("git",["config","commit.template",N()])}function E(e=""){return n.resolve(c.homedir(),j,e)}function _(){return E(b)}function B(){return t.existsSync(E())&&t.existsSync(_())}const{red:D,green:A,blue:C,magenta:U}=s;function W(...e){console.log(A(...e))}function J(e,t=!1){let n=e;e instanceof Error?(n=e.message,a.isAxiosError(e)&&(n=`请求失败:${e.message}`),console.log(D(n)),console.log(U(e.stack))):console.log(D(e)),t||process.exit(1)}function P(e){return!!t.existsSync(e)&&t.lstatSync(e).isDirectory()}function I(e=process.cwd()){if(P(e)){return t.readdirSync(e).filter((t=>P(n.resolve(e,t))))}return[]}function q(e=process.cwd()){if(P(e)){return t.readdirSync(e).filter((t=>!P(n.resolve(e,t))))}return[]}async function L(e,t={removeTailLinkBreak:!0,silent:!0}){let n=await new Promise(((n,a)=>{try{n(o.exec(e,{silent:t.silent}))}catch(e){a(e)}}));return n=n.toString(),t.removeTailLinkBreak&&(n=n.replace(/\n$/,"")),n}function R(){return r(Date.now()).format("YYMMDD")}function F(){t.existsSync(O())||J("当前不在项目根目录。请切换到项目根目录")}function M(){t.existsSync(n.resolve(".git"))||J("当前不是git项目根目录,请先执行git init,或切换到根目录")}async function G(){""!==await L("git status -s")&&J("请先提交代码变动,再进行操作")}function H(e){return["fe-biz"].includes(e)}const K=[{name:"开发环境 - dev",value:"dev"},{name:"测试环境 - test",value:"test"},{name:"预发环境 - release",value:"release"},{name:"正式环境 - production",value:"production"}],Q=[{name:"网页 - h5",value:"h5"},{name:"依赖包 - npm",value:"npm"}],V=["master","dev","test","release"],Z={1:"研发",2:"测试",3:"产品",4:"设计",5:"运营",6:"销售",7:"行政",8:"财务",9:"其他"},Y="http://git.cxlqd.com",X={PROJECT_NAME:"fe-pages-tpl",GIT_URL:`${Y}/fe-component/fe-pages-tpl.git`},ee=["fe-biz","fe-base","fe-tpl","fe-component","fe-demo"],te="fe-biz7tvsd";var ne={name:"cli-z-develop",version:"0.1.3",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.2.1","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^16.0.1","@rollup/plugin-replace":"v6.0.2","@rollup/plugin-terser":"^0.4.4","@types/fs-extra":"^11.0.4","@types/inquirer":"^9.0.7","@types/minimist":"^1.2.5","@types/node":" ^22.14.1","@types/semver":"^7.7.0","@types/shelljs":"^0.8.15","@typescript-eslint/eslint-plugin":"^8.31.0","@typescript-eslint/parser":"^8.31.0",eslint:"^9.25.1",jiti:"^2.4.2",prettier:"^3.5.3",rollup:" 4.40.0","rollup-plugin-typescript2":"^0.36.0",typescript:" ^5.8.3"},dependencies:{"@inquirer/prompts":"^7.4.1",axios:"^1.8.4",chalk:"^5.4.1",commander:"^13.1.0",dayjs:"^1.11.13",figures:"^6.1.0","fs-extra":"^11.3.0","inquirer-select-pro":"^1.0.0-alpha.9","lint-staged":"^15.5.1",minimist:"^1.2.8",ora:"^8.2.0",rxjs:"^7.8.2",semver:"^7.7.1",shelljs:"^0.9.2"}};const ae={profile:{ldapAccount:"",ldapPassword:"",gitToken:"",gitUserId:0,gitName:"",gitEnglishName:"",gitEmail:"",weWorkName:"",weWorkUserId:"",jobType:"fe",zenTaoToken:"",k8sToken:""},main:{version:ne.version,latestCheckVersionTimestamp:0,versionCheckDuring:3,weWorkListCache:[]},constants:{ZenTaoDomain:"",K8sDomain:"",FEServerDomain:"",K8SWebDomain:""}};function ie(e){return e?ae.profile[e]:ae.profile}function se(e){return e?ae.main[e]:ae.main}function re(e){return e?ae.constants[e]:ae.constants}let oe=null,ce=null;function le(){if(oe)return oe;const e=n.join("package.json");return t.existsSync(e)||J(`当前目录(${o.pwd()})不存在${e}文件,请在项目根目录执行该命令。`),oe=h.readJsonSync(e),oe}function ue(){if(ce)return ce;const e=z();return t.existsSync(e)||J(`当前目录(${o.pwd()})不存在${e}文件,请在项目根目录执行该命令,或者初始化项目(z init .)。`),ce=h.readJsonSync(e),ce}function me(e){ce=ce?Object.assign(Object.assign({},ce),e):e,h.writeJSONSync(z(),ce,{spaces:2})}const pe={id:0,name:"",group:"",sourceBranch:"",mergeRequestUrl:""};async function de(){if(!pe.name){const e=le();pe.name=e.name}if(!pe.group){const e=ue();e.repository.group&&(pe.group=e.repository.group)}if(!pe.id)try{const e=pe.group?`${pe.group}/${pe.name}`:pe.name,[t]=await Be(e);pe.mergeRequestUrl=`${t.web_url}/merge_requests`,pe.id=t.id,pe.group=t.namespace.path;const n=ue();n.repository.group||me({repository:Object.assign(Object.assign({},n.repository),{group:t.namespace.path})})}catch(e){J(e)}return pe.sourceBranch||(pe.sourceBranch=await L("git branch --show-current")),pe}function ge(){h.writeJSONSync(_(),{main:se(),profile:ie(),constants:re()},{spaces:2})}async function fe(e){const a=E(),i=process.cwd(),s=n.join(a,X.PROJECT_NAME);t.existsSync(s)?(o.cd(s),await L("git pull"),o.cd(i)):(o.cd(a),await L(`git clone ${X.GIT_URL} --depth=1`),o.cd(i));const r=n.join(s,"src",e);return t.existsSync(r)||J("模板库错误!"),r}function he(e){return e.split("-").map((e=>e.charAt(0).toUpperCase()+e.slice(1))).join("")}function we(e,n){const a=t.readFileSync(e,"utf-8"),i=n.replace(/\//g,"-"),s=a.replace(/name: "-_-NAME-_-"/g,`name: "${he(i)}"`).replace(/class="-_-NAME-_-"/g,`class="${i}"`).replace(/.-_-NAME-_-/g,`.${i}`);t.writeFileSync(e,s,"utf-8")}function ve(e,t){void 0!==t?ae.profile[e]=t:ae.profile=Object.assign(Object.assign({},ae.profile),e)}function ye(e,t){ae.constants=Object.assign(Object.assign({},ae.constants),e)}function $e(e,t){void 0!==t?ae.main[e]=t:ae.main=Object.assign(Object.assign({},ae.main),e)}async function je(e){var t;const n=e.method||"get",r=e.headers||{},o=e.data||{},c=e.dataKey||["GET","get"].includes(n)?"params":"data";try{const t={url:e.url,method:n,[c]:o,headers:r};s.magenta(t.method.toUpperCase()),s.yellow(t.url),JSON.stringify(t.headers),s.gray(JSON.stringify(t[c],null,2));const i=await a(t);return s.green("Response"),s.grey(JSON.stringify(i.data,null,2)),Promise.resolve(i.data)}catch(e){return e instanceof i&&(s.red("Error"),s.grey(JSON.stringify(null===(t=null==e?void 0:e.response)||void 0===t?void 0:t.data))),Promise.reject(e)}}async function be(){const e=ie("gitToken");if(e)return e;{const{access_token:e}=await je({url:`${Y}/oauth/token`,method:"post",data:{grant_type:"password",username:ie("ldapAccount"),password:ie("ldapPassword")}}),t=`Bearer ${e}`;return ve("gitToken",t),ge(),t}}async function xe(e){return je(Object.assign(Object.assign({},e),{headers:{Authorization:await be()}}))}async function Se(){const e=ie("zenTaoToken");if(e)return e;{const{token:e}=await je({url:`${re("ZenTaoDomain")}/api.php/v1/tokens`,method:"post",data:{account:ie("ldapAccount"),password:ie("ldapPassword")}});return ve("zenTaoToken",e),ge(),e}}async function ke(e){const t=await je(Object.assign(Object.assign({},e),{headers:{Token:await Se()}}));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?(ve("zenTaoToken",""),ke(Object.assign({},e))):t}async function Oe(){const e=ie("k8sToken");if(e)return e;{const{access_token:e}=await je({url:`${re("K8sDomain")}/oauth/login/LDAP`,method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},data:{username:ie("ldapAccount"),password:ie("ldapPassword")}}),t=`Bearer ${e}`;return ve("k8sToken",t),ge(),t}}async function ze(e){const t=await je(Object.assign(Object.assign({},e),{headers:{Authorization:await Oe()}}));return 401===t.code?(ve("k8sToken",""),ze(Object.assign({},e))):t}const Ne=()=>`${Y}/api/v4`,Te=e=>`${Ne()}/projects/100/repository/files/${encodeURIComponent(e)}/raw?ref=master`;function Ee(){return xe({url:Te("src/data/template-projects.json")})}function _e(){return xe({url:Te("src/data/z-develop-config.json")})}function Be(e){return xe({url:`${Ne()}/projects`,data:{search:e,search_namespaces:!0}})}async function De(){const e=await xe({url:`${Ne()}/groups`}),t=ee.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)));h.writeJSONSync(E("fe-groups.json"),{groups:t},{spaces:2})}function Ae(){return async function(e){const t=`${re("FEServerDomain")}/api`,{data:n}=await je({url:`${t}/auth/z-develop/login`,method:"post"}),a=await je({url:t+e.url,headers:{Authorization:`Bearer ${n}`},data:e.data,method:e.method||"post"});return 0!==a.code&&J(`${a.code}: ${a.message}`),a.data}({url:"/user/list2"})}async function Ce(){const e=(await Ae()).filter((e=>[1,2,3,4,5].includes(e.title))).map((e=>({name:`${e.nick} - ${Z[e.title]}`,value:e.weWorkUserId}))),t=se("weWorkListCache"),n=t.map((e=>e.value)),a=[];return e.forEach((e=>{const i=n.indexOf(e.value);a.push(Object.assign(Object.assign({},e),{usageCount:i>-1?t[i].usageCount:0}))})),a.sort(((e,t)=>t.usageCount-e.usageCount))}async function Ue(e,t,n){const a=await Ce();let i=await w({message:e,loop:!0,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=se("weWorkListCache"),i=a.map((e=>e.value));n.forEach((e=>{const t=i.indexOf(e.value);t>-1?a[t].usageCount+=1:a.push(Object.assign(Object.assign({},e),{usageCount:1}))})),$e({weWorkListCache:a.sort(((e,t)=>t.usageCount-e.usageCount))}),ge()}(i,a),i}async function We(){try{if(B()){await u({message:"系统中已存在z的配置文件,确认重新配置?"})?o.rm("-rf",_()):process.exit(0)}t.mkdirSync(E(),{recursive:!0});const e=await m({message:"请选择岗位类型",choices:[{name:"前端",value:"fe"},{name:"后端",value:"be"}]}),n=await p({message:"请输入LDAP账号:"}),a=await d({message:"请输入LDAP密码:",mask:!0});ve("jobType",e),ve("ldapAccount",n),ve("ldapPassword",a);ye(await _e());const i=await Ce(),s=await Ue("请选择你自己(用于企微通知):",(e=>e.length>1?"只能选一个":!(e.length<1)||"请选一个"),!1),{name:r,value:c}=i.find((e=>e.value===s[0]));ve({weWorkName:r,weWorkUserId:c})}catch(e){J(e)}const e=f("配置信息初始化中").start();try{const t=await xe({url:`${Ne()}/user`});ve({gitUserId:t.id,gitName:t.name,gitEnglishName:t.username,gitEmail:t.email}),$e("latestCheckVersionTimestamp",Date.now()),ge(),await De(),e.succeed("配置信息初始化完成"),process.exit(0)}catch(t){e.fail("配置信息初始化失败"),a.isAxiosError(t)&&J("请检查你的域名及令牌配置"),J(t)}}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',Pe="# 系统 信息文件\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",Ie={Java:{"**/*.{java}":"./run.sh pmd -d ../../../src/main/java/ -f text -R rulesets/java/quickstart.xml"},JavaScript:{"**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}":"eslint --fix","*":"prettier -wu"}};let qe;async function Le(e,n){if(e)o.rm("-rf",x);else if(t.existsSync(O())){await u({message:`当前项目中已存在配置文件夹${x},确认重新配置?`})?o.rm("-rf",x):process.exit(0)}t.mkdirSync(O(),{recursive:!0}),await async function(e,t){const n=await L("git remote get-url --push origin");n||J("获取项目远程地址失败,请配置后重试");let a=e;a||(a=await m({message:"请选择项目语言",choices:[{name:"JavaScript",value:"JavaScript"},{name:"Java",value:"Java"}]}));let i=t;const s=le();if(!i){const e=await Be(s.name);1===e.length?i=e[0].namespace.path:e.length>1&&(i=await m({message:"请选择当前项目所属分组",choices:e.map((e=>({name:e.namespace.path,value:e.namespace.path})))}))}qe=f("项目初始化中").start(),me({language:a,"lint-staged":Ie[a],repository:{url:n,group:i}})}(e,n),await(t.writeFileSync(N(),"",{mode:493}),t.writeFileSync(O("commit-msg"),"#!/usr/bin/env sh\nz lint commit-msg",{mode:493}),t.writeFileSync(O("pre-commit"),"#!/usr/bin/env sh\nz lint commit-files",{mode:493}),t.writeFileSync(O(".prettierrc.json"),Je,{mode:493}),t.writeFileSync(O(".prettierignore"),Pe,{mode:493}),t.writeFileSync(O(".gitignore"),".commit-msg-tpl\n",{mode:493}),void T()),null==qe||qe.succeed("初始化完成。")}async function Re(e){if(!e)return"不能为空";if(!/^[a-z0-9-]+$/.test(e))return"格式为小写字母、中横线(可选)、数字(不推荐)。如apple, apple-tree";if(I().includes(e))return"当前目录下已存在同名文件夹,请先处理。";return!(await Be(e)).find((t=>t.name===e))||"远程仓库中已存在同名项目"}function Fe(e){return!!e||"不能为空"}function Me(e){return e?!!/^[a-zA-Z0-9.]+$/.test(e)||"格式为大小写字母、数字、小数点,小驼峰命名。如userInfo、systemRouter3":"不能为空"}function Ge(e){if(!e)return"目录名称不能为空";if(!/^[a-z][a-z0-9\-/]*$/.test(e))return"支持小写字母、数字,连字符(-)命名,小写字母开头,多层目录使用/隔开。如user、modules-3、setting/profile";if(e.includes("/")){const t=e.split("/");for(const e of t){if(!e)return"子级目录/页面名称不能为空";if(!/^[a-z][a-z0-9-]*$/.test(e))return"支持小写字母、数字,连字符(-)命名,小写字母开头。如user、modules-3"}}let a,i;a=e.includes("/")?n.resolve("src","pages",...e.split("/")):n.resolve("src","pages",e);const s=n.resolve(a,"..");return i=!!t.existsSync(s)&&t.readdirSync(s).map((e=>{const t=e.lastIndexOf(".");return t>-1?e.slice(0,t):e})).includes(e),!i||"本地目录已存在该文件"}e.command("init").alias("i").argument("[type]","非必填。不传为初始化工具配置;传 . 为初始化当前项目。").description("初始化工具配置、项目配置").action((async function(e){e?"."===e?(M(),await Le(void 0,void 0),process.exit(0)):"prepare"===e?(M(),await async function(){t.existsSync(O())&&t.existsSync(N())?T():await Le(),process.exit(0)}()):J("参数错误。执行 z init -h 查看帮助。"):await We()}));const He=e=>`${re("ZenTaoDomain")}${e}`;function Ke(e,n){let a="";if(["feat","fix","refactor"].includes(e)){a=`${e}(${n.map((e=>e.value)).join(",")}): ${n.map((e=>e.name)).join(";")}`}"chore"===e&&(a=`${e}: ${n}`),t.writeFileSync(N(),a,"utf-8"),console.log(s.yellow(a)),W("commit msg模板写入成功,可以进行提交了")}async function Qe(){const e=await m({message:"请选择你要创建的模板类型",choices:[{name:"feat - 业务需求开发",value:"feat"},{name:"fix - bug修复",value:"fix"},{name:"refactor - 技术内部需求",value:"refactor"},{name:"chore - 其他",value:"chore"}]});if(["feat","refactor"].includes(e)){const e=await async function(){const e=await ke({url:He("/my-work-task.json?tid=mrrferp8"),method:"get"});return null==e?void 0:e.tasks.filter((e=>"done"!==e.status)).map((({id:e,name:t})=>({value:{name:t,value:e},name:t})))}();Ke("feat",await g({message:"请关联开发任务(可多选):",validate:e=>0!==e.length||"请选择项",choices:e.map((e=>Object.assign(Object.assign({},e),{name:`[${e.value.value}]: ${e.name}`})))}))}if("fix"===e){const e=await async function(){const e=await ke({url:He("/my-work-bug.json?tid=mrrferp8"),method:"get"});return null==e?void 0:e.bugs.map((({id:e,title:t})=>({name:t,value:{name:t,value:e}})))}();Ke("fix",await g({message:"请关联Bug(可多选):",validate:e=>0!==e.length||"请选择项",choices:e.map((e=>Object.assign(Object.assign({},e),{name:`[${e.value.value}]: ${e.name}`})))}))}if("chore"===e){Ke("chore",await p({message:"请输入commit msg:",validate:e=>0!==e.length||"请输入commit msg"}))}}async function Ve(){var e,a,i,r,c,l;try{const u={},d=async()=>{const e=I(),{projects:t}=await Ee(),n=t.map((t=>{const n={name:`${t.name} [${t.desc}]`,value:t.name,disabled:!1};return e.includes(t.name)&&(n.disabled="目录下已存在同名文件夹"),n})),a=await m({message:"请选择一个项目模板",choices:n}),i=t.find((e=>e.name===a));u.tplName=i.name,u.tplUrl=i.url,u.tplLanguage=i.language},g=async()=>{var e;const{groups:n}=function(){const e=E("fe-groups.json");return t.existsSync(e)?h.readJSONSync(e):{groups:[]}}(),a=await m({message:"请选择一个分组",choices:n.map((e=>({name:`${e.name} [${e.description}]`,value:e.id,short:e.name})))});u.group={id:a,name:null===(e=n.find((e=>e.id===a)))||void 0===e?void 0:e.name}},w=async()=>{u.projectName=await p({message:"请输入项目名称",validate:Re}),u.projectDesc=await p({message:"请输入项目描述",validate:Fe})};await d(),await g(),await w();const v=`${Y}/${null===(e=u.group)||void 0===e?void 0:e.name}/${u.projectName}.git`,y=f("模版初始化中").start();await L(`git clone --depth=1 ${u.tplUrl}`),t.renameSync(u.tplName,u.projectName),o.cd(u.projectName),o.rm("-rf",".git"),await L("git init --initial-branch=master"),await L(`git remote add origin ${v}`),await L(`git config user.name ${ie("gitName")}`),await L(`git config user.email ${ie("gitEmail")}`);const $=le();l=Object.assign(Object.assign({},$),{name:u.projectName,description:u.projectDesc,scripts:Object.assign(Object.assign({},$.scripts),{prepare:"[ -n '$z' ] && z init prepare || echo 'Warning: z not exist at global'"})}),oe=oe?Object.assign(Object.assign({},oe),l):l,h.writeJSONSync(n.join("package.json"),oe,{spaces:2}),await h.writeFile(n.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 lint eslint\n # 或者\n z l e\n\`\`\`\n\n### 格式化代码\n\`\`\`bash\n z lint prettier\n # 或者\n z l p\n\`\`\`\n\n## 常见问题\n列出开发中常见的问题和解决方案\n\n## 了解更多\n在此处放入飞书文档链接。请在[前端团队-项目手册](https://hxhtbr8t8uy.feishu.cn/drive/folder/QfQ7favVWljQk7d63Prc8mUGnJf)中按照分类新建文档。\n`}(u.projectName,u.projectDesc)),y.succeed("模版初始化完成"),await Le(u.tplLanguage,null===(a=u.group)||void 0===a?void 0:a.name);const j=f("依赖安装中").start();await L("npm install --registry https://registry.npmmirror.com/"),j.succeed("依赖安装完成");const b=f("项目推送中").start();await L('git add . && git commit -m "chore: 项目初始化"'),await L("git tag v0.0.1");const x=await(c={name:u.projectName,description:u.projectDesc,path:u.projectName,visibility:"private",namespace_id:null===(i=u.group)||void 0===i?void 0:i.id},xe({url:`${Ne()}/projects`,method:"post",data:c}));await L("git push -u origin master"),await L("git push origin HEAD:master --tags"),b.succeed(`项目已推送到远程,地址: ${s.blue(v)}`);const S=f("初始化分支中").start(),k=`feat_init_${R()}`,O=H(null===(r=u.group)||void 0===r?void 0:r.name)?["dev","test","release",k]:[k],z=await Promise.allSettled(O.map((e=>function(e){return xe({url:`${Ne()}/projects/${e.id}/repository/branches`,method:"post",data:e})}({id:x.id,branch:e,ref:"master"})))),N=[];z.forEach((({status:e},t)=>{"fulfilled"===e&&N.push(O[t])})),await L("git pull"),N.includes(k)?(await L(`git checkout -b ${k} origin/${k}`),S.succeed(`项目已切换到初始分支: ${s.blue(k)}`)):S.warn("开发分支检出失败!项目当前在主分支,请自行检出开发分支。");const T=`cd ${u.projectName} && z start`;console.log(`输入 ${s.green(T)} 开始开发吧~`),process.exit(0)}catch(e){J(e)}}function Ze(e){return ze({url:`${re("K8sDomain")}/kapis/clusters/youshou-local/devops.kubesphere.io/v1alpha3/namespaces/${te}/pipelines/${e.projectName}/pipelineruns?branch=${e.branchName}`,method:"post",data:e.params})}async function Ye(e){F(),M(),await G();let t=e;t&&!V.includes(t)&&J("仅支持发布指定环境分支");const n=await m({message:"请选择平台",choices:Q});if("npm"===n&&(t="master"),!t){const e=await m({message:"请选择部署环境",choices:K});t="production"===(a=e)?"master":a}var a;const i=await Ue("请选择部署成功要通知的人员:",(()=>!0),!0);var r;!function(e){var t;const n=le(),a=ue();(null===(t=null==a?void 0:a.repository)||void 0===t?void 0:t.url)||J(".z/project.json中缺少repository.url");const i=`build:${e}`;(null==n?void 0:n.scripts[i])||J(`项目package.json文件scripts不存在命令${i}。`)}("master"===(r=t)?"production":r);const o=le();await async function(e){const t=f("部署任务创建中").start(),{targetBranch:n,platform:a,notify:i,projectName:r}=e,o=i?[...new Set([ie("weWorkUserId"),...i])]:[ie("weWorkUserId")];try{const{metadata:e,spec:i}=await Ze({projectName:r,branchName:n,params:{parameters:[{name:"platform",value:a},{name:"QW_NOTIFY_USER",value:o.join(",")}]}}),c=`${re("K8SWebDomain")}/youshou-local/clusters/youshou-local/devops/${e.namespace}/pipelines/${i.pipelineRef.name}/branch/${i.scm.refName}/run/${e.name}/task-status`;t.succeed("部署任务创建完成"),console.log(`如有需要,可在k8s中查看 ${s.blue(c)}`),process.exit(0)}catch(e){t.fail("部署任务创建失败"),J(e)}}({projectName:o.name,targetBranch:t,platform:n,notify:i})}async function Xe(e,t,n){var i;const s=f(`分支合并中,${e} -> ${t}`).start();let r=0;try{const{iid:a}=await(o={title:`${e} -> ${t} by z-develop`,id:n.id,source_branch:e,target_branch:t,remove_source_branch:"master"===t},xe({url:`${Ne()}/projects/${o.id}/merge_requests`,method:"post",data:o}));r=a}catch(e){if(a.isAxiosError(e)){409===(null===(i=null==e?void 0:e.response)||void 0===i?void 0:i.status)&&J(`存在重复的合并请求,前往查看${n.mergeRequestUrl}`)}J(e)}var o;const c=async()=>{var e;try{await new Promise((e=>{setTimeout(e,5e3)})),await function(e){return xe({url:`${Ne()}/projects/${e.id}/merge_requests/${e.iid}/merge`,method:"put"})}({id:n.id,iid:r})}catch(t){if(a.isAxiosError(t)){406===(null===(e=null==t?void 0:t.response)||void 0===e?void 0:e.status)?await c():(await function(e){return xe({url:`${Ne()}/projects/${e.id}/merge_requests/${e.iid}`,method:"put",data:e})}({id:n.id,iid:r,state_event:"close"}),s.fail("合并过程中出现冲突,MR已关闭。建议在本地完成合并。"),process.exit(1))}else J(t)}};await c(),s.succeed(`分支${e}已合并到分支${t}`)}function et(){const e=z();if(t.existsSync(e)){const t=h.readJsonSync(e);if(t["lint-staged"])return t["lint-staged"];throw new Error("未找到lint配置")}throw new Error("请先初始化项目(z i .)。")}function tt(){const e=function(e){if(e.includes("Merge")&&e.includes("# Conflicts:"))return!0;if(y.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)?!!["chore","ci"].includes(n)||"chore/ci类型无需填写ID。":"BREAKING CHANGE"===n||"不存在的提交类型。"}(t.readFileSync(n.resolve(".git","COMMIT_EDITMSG"),"utf-8"));!0===e?(W("commit msg validate success."),process.exit(0)):J(`commit msg格式错误。${e}`)}async function nt(e="latest"){await L(`npm i -g ${ne.name}@${e} --registry https://registry.npmmirror.com/`),$e("latestCheckVersionTimestamp",Date.now()),$e("version",e),ge(),console.log(s.green(`升级完成,当前版本${e}`)),process.exit(0)}async function at(){const e=$(process.argv.slice(2));if(!(e.h||e.help||e.v||e.version)&&(!["init","i"].includes(e._[0])||[".","prepare"].includes(e._[1])))if(B()){const e=h.readJSONSync(_());ve(e.profile),$e(e.main),ye(e.constants),await async function(){const e=se("latestCheckVersionTimestamp"),t=se("versionCheckDuring");if(Date.now()-Number(e)>24*Number(t)*3600*1e3){let e;ye(await _e());try{const t="TIME_OUT",n=new Promise((e=>{setTimeout((()=>e(t)),3e3)}));e=await Promise.race([n,L(`npm view ${ne.name} version --registry https://registry.npmmirror.com/`)]),e!==t&&e!==ne.version&&(console.log(`${s.blue(ne.name)}本地版本为${ne.version},低于线上版本${e},开始升级`),await nt(e)),$e("latestCheckVersionTimestamp",Date.now()),ge()}catch(e){console.log("升级出错!请重试,或者手动升级"),J(e)}}}()}else J("请先初始化z-develop(执行 z i)。更多见https://hxhtbr8t8uy.feishu.cn/docx/RnOhdtqJWo5UooxHTaUcQFwtnKg")}e.command("create").alias("c").argument("[type]","可选值为project|pr, branch|b, commit-msg|cm, page|p, component|co").description("创建项目/分支/提交信息/页面/组件").action((async function(e){let a;e?["project","pr"].includes(e)?a="project":["branch","b"].includes(e)?a="branch":["page","pa"].includes(e)?a="page":["component","co"].includes(e)?a="component":["commit-msg","cm"].includes(e)?a="commit-msg":J("参数输入错误"):a=await m({message:"请选择你要创建的类型",choices:[{name:"提交信息(commit message)",value:"commit-msg"},{name:"分支(branch)",value:"branch"},{name:"页面(page)",value:"page"},{name:"组件(component)",value:"component"},{name:"项目(project)",value:"project"}]}),"project"===a?await Ve():"branch"===a?(F(),M(),await G(),await async function(){F(),M(),await G();const e=`${await m({message:"请选择创建分支的类型",choices:[{name:"开发新功能(feat)",value:"feat"},{name:"修复BUG(fix)",value:"fix"},{name:"重构/优化代码(refactor)",value:"refactor"}]})}_${await p({message:"请输入创建分支的目的(大小写字母、数字,小驼峰式命名。如userInfo)",validate:Me})}_${R()}`;await L("git fetch origin master"),await L(`git checkout -b ${e} origin/master`),await L(`git push -u origin ${e}`)}()):"commit-msg"===a?(F(),M(),await Qe()):"page"===a?(F(),M(),await async function(){const e="pages",a=await fe(e);t.mkdirSync(n.resolve("src",e),{recursive:!0});const i=await p({message:"请输入目录及页面名称(如user/list,不带文件后缀)",validate:Ge});let s;if(i.includes("/")){const a=i.split("/");a.pop(),s=n.resolve("src",e,...i.split("/")),t.mkdirSync(n.resolve("src",e,...a),{recursive:!0})}else s=n.resolve("src",e,i);const{pages:r}=await Ee(),c=t.readdirSync(a),l=await m({message:"请选择模版",choices:r.filter((e=>c.includes(e.name))).map((e=>({name:`${e.name}: ${e.desc}(${e.author})`,value:e.name})))}),u=f("页面生成中...").start(),d=s+n.extname(n.join(a,l));o.cp("-r",n.join(a,l),d),P(d)?q(d).forEach((e=>{we(n.join(d,e),i)})):we(d,i),u.succeed("页面生成成功")}()):"component"===a&&(F(),M(),await async function(){const e="components",a=await fe("components");t.mkdirSync(n.resolve("src",e),{recursive:!0});const i=await p({message:"请输入目录及组件名称(如user/list,不带文件后缀)",validate:Ge});let s;if(i.includes("/")){const a=i.split("/"),r=a.pop();s=n.resolve("src",e,...a,he(r)),t.mkdirSync(n.resolve("src",e,...a),{recursive:!0})}else s=n.resolve("src",e,he(i));const{components:r}=await Ee(),c=t.readdirSync(a),l=await m({message:"请选择模版",choices:r.filter((e=>c.includes(e.name))).map((e=>({name:`${e.name}: ${e.desc}(${e.author})`,value:e.name})))}),u=f("组件生成中...").start(),d=s+n.extname(n.join(a,l));o.cp("-r",n.join(a,l),d),P(d)?q(d).forEach((e=>{we(n.join(d,e),i)})):we(d,i),u.succeed("组件生成成功")}()),process.exit(0)})),e.command("merge").alias("m").description("合并当前分支到指定远程分支,并部署。").action((async function(){F(),M(),await G();const e=await de();V.includes(e.sourceBranch)&&J(`当前分支${e.sourceBranch}不可作为源分支合并到目标分支。`);const t=await(n=e.id,xe({url:`${Ne()}/projects/${n}/repository/branches`}));var n;const a=H(e.group),i=t.filter((t=>![e.sourceBranch].includes(t.name))).map((e=>{let t=e.name;return a&&V.includes(t)&&(t=s.bold.blue(t)),{name:t,value:e.name}})),r=await m({message:"请选择要合并到的目标分支:",choices:i}),o=f(`${e.sourceBranch}分支代码检测中`).start();if(await L(`git ls-remote --heads origin ${e.sourceBranch}`)){o.text=`存在远程分支origin/${e.sourceBranch}`,await L("git fetch");const t=await L(`git rev-parse ${e.sourceBranch}`),n=await L(`git rev-parse origin/${e.sourceBranch}`);if(await L(`git merge-base ${n} HEAD`)===n)await L(`git push -u origin ${e.sourceBranch}`),o.succeed(`${e.sourceBranch}分支代码已推送到远程`);else{await L(`git merge-base ${t} ${n}`)===t?(await L("git pull"),o.succeed(`${e.sourceBranch}分支代码已更新`)):(o.fail(`远程分支origin/${e.sourceBranch}和本地分支${e.sourceBranch}都有新的提交,请手动合并后再试。`),process.exit(1))}}else await L(`git push -u origin ${e.sourceBranch}`),o.succeed(`${e.sourceBranch}已推送到远程`);await async function(e,t,n){const a=`origin/${e.sourceBranch}`,i=await L("git log -b origin/master -1 --format=%H"),r=await L(`git log -b origin/${e.sourceBranch} -1 --format=%H`),o=await L(`git log ${i}...${r} -b ${a}`);if(o||J(`分支${e.sourceBranch}上不存在新的commit,不需要合并。`),await L(`git branch --contains ${i} -r ${a}`)||(console.log(s.yellow("注意:当前分支上不存在远程主分支最新代码,将在自动合入后继续。")),await Xe("master",e.sourceBranch,e)),"master"===t&&n){const e=o.split("\n").filter((e=>e)),t=await L("git log -b origin/test -1 --format=%H");(function(e,t){for(const n of t)if(!e.includes(n))return!1;return!0})((await L(`git log ${i}...${t} -b origin/test`)).split("\n").filter((e=>e)),e)||J("请先在测试环境发布要部署的代码")}}(e,r,a),await Xe(e.sourceBranch,r,e),"master"===r&&(await L("git checkout master"),await L("git pull"),await L(`git branch -d ${e.sourceBranch}`),W(`${e.sourceBranch}分支已移除,当前已切换到最新的master。如需继续开发,请检出新分支(z c b)。`)),a&&V.includes(r)&&await Ye(r)})),e.command("deploy").alias("d").description("发布指定远程分支").argument("[branchName]","可选值为dev/test/release/master").action(Ye),e.command("start").alias("s").description("启动本地开发环境").argument("[env]","可选值 dev|d, test|t, release|r, prod|p").action((async function(e){let t=e;t?["dev","test","release","production","d","t","r","p"].includes(e)?"d"===t?t="dev":"t"===t?t="test":"r"===t?t="release":"p"===t&&(t="production"):J("参数输入有误"):t=await m({message:"请选择环境",choices:K});const n=`dev:${t}`;if(le().scripts[n])try{o.exec(`npm run ${n}`,{silent:!1})}catch(e){J(e)}else J(`项目中(package.josn > scripts)不存在命令${n},请先添加!`)})),e.command("lint").alias("l").argument("[type]","非必填。可选值为commit-msg|cm, commit-files|cf, prettier|p, eslint|e。").option("--quiet","eslint只打印error").option("--max-warnings [VALUE]","eslint结果warn超过多少个会异常退出,默认为100",parseInt).description("执行 lint 脚本。包含 lint staged 、 lint commit message、 prettier、 eslint。").action((async function(e,a){let i;if(F(),M(),e?["commit-msg","cm"].includes(e)?i="commit-msg":["commit-files","cf"].includes(e)?i="commit-files":["prettier","p"].includes(e)?i="prettier":["eslint","e"].includes(e)?i="eslint":J("参数输入错误"):i=await m({message:"请选择你要执行的操作",choices:[{name:"全局执行 prettier",value:"prettier"},{name:"全局执行 eslint",value:"eslint"}]}),"commit-msg"===i)await tt();else if("commit-files"===i)await async function(){await v({concurrent:!1,debug:!1,config:et()})?(W("代码风格检测通过!"),process.exit(0)):J("代码风格检测未通过!")}();else if("prettier"===i){t.existsSync(n.resolve("node_modules",".bin","prettier"))||J("该项目未安装prettier,请安装后重试");try{await L("npx prettier --write . --config .z/.prettierrc.json --ignore-path .z/.prettierignore --ignore-unknown --no-error-on-unmatched-pattern",{silent:!1}),W("prettier执行成功"),process.exit(0)}catch(e){J("prettier校验出错")}}else if("eslint"===i){t.existsSync(n.resolve("node_modules",".bin","eslint"))||J("该项目未安装eslint,请安装后重试");try{let e="npx eslint '**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}' --fix";"win32"===process.platform&&(e='npx eslint "**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}" --fix'),a.quiet&&(e+=" --quiet"),a.maxWarnings&&!isNaN(Number(a.maxWarnings))?e+=` --max-warnings ${Number(a.maxWarnings)}`:e+=" --max-warnings 100",await L(e,{silent:!1}),W("eslint执行成功"),process.exit(0)}catch(e){J("eslint校验出错")}}})),e.command("update").alias("u").argument("[version]","版本号","latest").description("升级").action(nt),e.name("z-develop").alias("z").description(`z-develop, 开发流程管理工具。\n了解更多: ${s.blue("https://hxhtbr8t8uy.feishu.cn/docx/RnOhdtqJWo5UooxHTaUcQFwtnKg")}`).usage("<command> [options]").hook("preAction",(async function(){process.on("unhandledRejection",(e=>{})),process.on("uncaughtException",(e=>{})),o.config.fatal=!0,o.config.silent=!0,o.config.verbose=Boolean(void 0)||!1,await at()})).version(ne.version,"-v, --version","当前版本号").helpOption("-h, --help","帮助").showHelpAfterError("可以使用z -h查看帮助。"),e.parse();
|
|
1
|
+
import{program as e}from"commander";import t from"node:fs";import n from"node:path";import a,{AxiosError as i}from"axios";import s from"chalk";import r from"dayjs";import o from"shelljs";import c from"node:os";import l from"child_process";import{confirm as u,select as m,input as p,password as d,checkbox as g}from"@inquirer/prompts";import f from"ora";import h from"fs-extra";import{select as w}from"inquirer-select-pro";import v from"lint-staged";import y from"semver";import $ from"minimist";const j=".z",b="develop-config.json",x=".z",S=".commit-msg-tpl",k="project.json";function O(e=""){return n.join(x,e)}function z(){return O(k)}function N(){return O(S)}function T(){l.spawnSync("git",["config","core.hooksPath",O()]),l.spawnSync("git",["config","commit.template",N()])}function E(e=""){return n.resolve(c.homedir(),j,e)}function _(){return E(b)}function B(){return t.existsSync(E())&&t.existsSync(_())}const{red:D,green:A,blue:C,magenta:U}=s;function W(...e){console.log(A(...e))}function J(e,t=!1){let n=e;e instanceof Error?(n=e.message,a.isAxiosError(e)&&(n=`请求失败:${e.message}`),console.log(D(n)),console.log(U(e.stack))):console.log(D(e)),t||process.exit(1)}function P(e){return!!t.existsSync(e)&&t.lstatSync(e).isDirectory()}function I(e=process.cwd()){if(P(e)){return t.readdirSync(e).filter((t=>P(n.resolve(e,t))))}return[]}function q(e=process.cwd()){if(P(e)){return t.readdirSync(e).filter((t=>!P(n.resolve(e,t))))}return[]}async function L(e,t={removeTailLinkBreak:!0,silent:!0}){let n=await new Promise(((n,a)=>{try{n(o.exec(e,{silent:t.silent}))}catch(e){a(e)}}));return n=n.toString(),t.removeTailLinkBreak&&(n=n.replace(/\n$/,"")),n}function R(){return r(Date.now()).format("YYMMDD")}function F(){t.existsSync(O())||J("当前不在项目根目录。请切换到项目根目录")}function M(){t.existsSync(n.resolve(".git"))||J("当前不是git项目根目录,请先执行git init,或切换到根目录")}async function G(){""!==await L("git status -s")&&J("请先提交代码变动,再进行操作")}function H(e){return["fe-biz"].includes(e)}const K=[{name:"开发环境 - dev",value:"dev"},{name:"测试环境 - test",value:"test"},{name:"预发环境 - release",value:"release"},{name:"正式环境 - production",value:"production"}],Q=[{name:"网页 - h5",value:"h5"},{name:"依赖包 - npm",value:"npm"}],V=["master","dev","test","release"],Z={1:"研发",2:"测试",3:"产品",4:"设计",5:"运营",6:"销售",7:"行政",8:"财务",9:"其他"},Y="http://git.cxlqd.com",X={PROJECT_NAME:"fe-pages-tpl",GIT_URL:`${Y}/fe-component/fe-pages-tpl.git`},ee=["fe-biz","fe-base","fe-tpl","fe-component","fe-demo"],te="fe-biz7tvsd";var ne={name:"cli-z-develop",version:"0.1.4",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.2.1","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^16.0.1","@rollup/plugin-replace":"v6.0.2","@rollup/plugin-terser":"^0.4.4","@types/fs-extra":"^11.0.4","@types/inquirer":"^9.0.7","@types/minimist":"^1.2.5","@types/node":" ^22.14.1","@types/semver":"^7.7.0","@types/shelljs":"^0.8.15","@typescript-eslint/eslint-plugin":"^8.31.0","@typescript-eslint/parser":"^8.31.0",eslint:"^9.25.1",jiti:"^2.4.2",prettier:"^3.5.3",rollup:" 4.40.0","rollup-plugin-typescript2":"^0.36.0",typescript:" ^5.8.3"},dependencies:{"@inquirer/prompts":"^7.4.1",axios:"^1.8.4",chalk:"^5.4.1",commander:"^13.1.0",dayjs:"^1.11.13",figures:"^6.1.0","fs-extra":"^11.3.0","inquirer-select-pro":"^1.0.0-alpha.9","lint-staged":"^15.5.1",minimist:"^1.2.8",ora:"^8.2.0",rxjs:"^7.8.2",semver:"^7.7.1",shelljs:"^0.9.2"}};const ae={profile:{ldapAccount:"",ldapPassword:"",gitToken:"",gitUserId:0,gitName:"",gitEnglishName:"",gitEmail:"",weWorkName:"",weWorkUserId:"",jobType:"fe",zenTaoToken:"",k8sToken:""},main:{version:ne.version,latestCheckVersionTimestamp:0,versionCheckDuring:3,weWorkListCache:[]},constants:{ZenTaoDomain:"",K8sDomain:"",FEServerDomain:"",K8SWebDomain:""}};function ie(e){return e?ae.profile[e]:ae.profile}function se(e){return e?ae.main[e]:ae.main}function re(e){return e?ae.constants[e]:ae.constants}let oe=null,ce=null;function le(){if(oe)return oe;const e=n.join("package.json");return t.existsSync(e)||J(`当前目录(${o.pwd()})不存在${e}文件,请在项目根目录执行该命令。`),oe=h.readJsonSync(e),oe}function ue(){if(ce)return ce;const e=z();return t.existsSync(e)||J(`当前目录(${o.pwd()})不存在${e}文件,请在项目根目录执行该命令,或者初始化项目(z init .)。`),ce=h.readJsonSync(e),ce}function me(e){ce=ce?Object.assign(Object.assign({},ce),e):e,h.writeJSONSync(z(),ce,{spaces:2})}const pe={id:0,name:"",group:"",sourceBranch:"",mergeRequestUrl:""};async function de(){if(!pe.name){const e=le();pe.name=e.name}if(!pe.group){const e=ue();e.repository.group&&(pe.group=e.repository.group)}if(!pe.id)try{const e=pe.group?`${pe.group}/${pe.name}`:pe.name,[t]=await Be(e);pe.mergeRequestUrl=`${t.web_url}/merge_requests`,pe.id=t.id,pe.group=t.namespace.path;const n=ue();n.repository.group||me({repository:Object.assign(Object.assign({},n.repository),{group:t.namespace.path})})}catch(e){J(e)}return pe.sourceBranch||(pe.sourceBranch=await L("git branch --show-current")),pe}function ge(){h.writeJSONSync(_(),{main:se(),profile:ie(),constants:re()},{spaces:2})}async function fe(e){const a=E(),i=process.cwd(),s=n.join(a,X.PROJECT_NAME);t.existsSync(s)?(o.cd(s),await L("git pull"),o.cd(i)):(o.cd(a),await L(`git clone ${X.GIT_URL} --depth=1`),o.cd(i));const r=n.join(s,"src",e);return t.existsSync(r)||J("模板库错误!"),r}function he(e){return e.split("-").map((e=>e.charAt(0).toUpperCase()+e.slice(1))).join("")}function we(e,n){const a=t.readFileSync(e,"utf-8"),i=n.replace(/\//g,"-"),s=a.replace(/name: "-_-NAME-_-"/g,`name: "${he(i)}"`).replace(/class="-_-NAME-_-"/g,`class="${i}"`).replace(/.-_-NAME-_-/g,`.${i}`);t.writeFileSync(e,s,"utf-8")}function ve(e,t){void 0!==t?ae.profile[e]=t:ae.profile=Object.assign(Object.assign({},ae.profile),e)}function ye(e,t){ae.constants=Object.assign(Object.assign({},ae.constants),e)}function $e(e,t){void 0!==t?ae.main[e]=t:ae.main=Object.assign(Object.assign({},ae.main),e)}async function je(e){var t;const n=e.method||"get",r=e.headers||{},o=e.data||{},c=e.dataKey||["GET","get"].includes(n)?"params":"data";try{const t={url:e.url,method:n,[c]:o,headers:r};s.magenta(t.method.toUpperCase()),s.yellow(t.url),JSON.stringify(t.headers),s.gray(JSON.stringify(t[c],null,2));const i=await a(t);return s.green("Response"),s.grey(JSON.stringify(i.data,null,2)),Promise.resolve(i.data)}catch(e){return e instanceof i&&(s.red("Error"),s.grey(JSON.stringify(null===(t=null==e?void 0:e.response)||void 0===t?void 0:t.data))),Promise.reject(e)}}async function be(){const e=ie("gitToken");if(e)return e;{const{access_token:e}=await je({url:`${Y}/oauth/token`,method:"post",data:{grant_type:"password",username:ie("ldapAccount"),password:ie("ldapPassword")}}),t=`Bearer ${e}`;return ve("gitToken",t),ge(),t}}async function xe(e){return je(Object.assign(Object.assign({},e),{headers:{Authorization:await be()}}))}async function Se(){const e=ie("zenTaoToken");if(e)return e;{const{token:e}=await je({url:`${re("ZenTaoDomain")}/api.php/v1/tokens`,method:"post",data:{account:ie("ldapAccount"),password:ie("ldapPassword")}});return ve("zenTaoToken",e),ge(),e}}async function ke(e){const t=await je(Object.assign(Object.assign({},e),{headers:{Token:await Se()}}));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?(ve("zenTaoToken",""),ke(Object.assign({},e))):t}async function Oe(){const e=ie("k8sToken");if(e)return e;{const{access_token:e}=await je({url:`${re("K8sDomain")}/oauth/login/LDAP`,method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},data:{username:ie("ldapAccount"),password:ie("ldapPassword")}}),t=`Bearer ${e}`;return ve("k8sToken",t),ge(),t}}async function ze(e){const t=await je(Object.assign(Object.assign({},e),{headers:{Authorization:await Oe()}}));return 401===t.code?(ve("k8sToken",""),ze(Object.assign({},e))):t}const Ne=()=>`${Y}/api/v4`,Te=e=>`${Ne()}/projects/100/repository/files/${encodeURIComponent(e)}/raw?ref=master`;function Ee(){return xe({url:Te("src/data/template-projects.json")})}function _e(){return xe({url:Te("src/data/z-develop-config.json")})}function Be(e){return xe({url:`${Ne()}/projects`,data:{search:e,search_namespaces:!0}})}async function De(){const e=await xe({url:`${Ne()}/groups`}),t=ee.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)));h.writeJSONSync(E("fe-groups.json"),{groups:t},{spaces:2})}function Ae(){return async function(e){const t=`${re("FEServerDomain")}/api`,{data:n}=await je({url:`${t}/auth/z-develop/login`,method:"post"}),a=await je({url:t+e.url,headers:{Authorization:`Bearer ${n}`},data:e.data,method:e.method||"post"});return 0!==a.code&&J(`${a.code}: ${a.message}`),a.data}({url:"/user/list2"})}async function Ce(){const e=(await Ae()).filter((e=>[1,2,3,4,5].includes(e.title))).map((e=>({name:`${e.nick} - ${Z[e.title]}`,value:e.weWorkUserId}))),t=se("weWorkListCache"),n=t.map((e=>e.value)),a=[];return e.forEach((e=>{const i=n.indexOf(e.value);a.push(Object.assign(Object.assign({},e),{usageCount:i>-1?t[i].usageCount:0}))})),a.sort(((e,t)=>t.usageCount-e.usageCount))}async function Ue(e,t,n){const a=await Ce();let i=await w({message:e,loop:!0,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=se("weWorkListCache"),i=a.map((e=>e.value));n.forEach((e=>{const t=i.indexOf(e.value);t>-1?a[t].usageCount+=1:a.push(Object.assign(Object.assign({},e),{usageCount:1}))})),$e({weWorkListCache:a.sort(((e,t)=>t.usageCount-e.usageCount))}),ge()}(i,a),i}async function We(){try{if(B()){await u({message:"系统中已存在z的配置文件,确认重新配置?"})?o.rm("-rf",_()):process.exit(0)}t.mkdirSync(E(),{recursive:!0});const e=await m({message:"请选择岗位类型",choices:[{name:"前端",value:"fe"},{name:"后端",value:"be"}]}),n=await p({message:"请输入LDAP账号:"}),a=await d({message:"请输入LDAP密码:",mask:!0});ve("jobType",e),ve("ldapAccount",n),ve("ldapPassword",a);ye(await _e());const i=await Ce(),s=await Ue("请选择你自己(用于企微通知):",(e=>e.length>1?"只能选一个":!(e.length<1)||"请选一个"),!1),{name:r,value:c}=i.find((e=>e.value===s[0]));ve({weWorkName:r,weWorkUserId:c})}catch(e){J(e)}const e=f("配置信息初始化中").start();try{const t=await xe({url:`${Ne()}/user`});ve({gitUserId:t.id,gitName:t.name,gitEnglishName:t.username,gitEmail:t.email}),$e("latestCheckVersionTimestamp",Date.now()),ge(),await De(),e.succeed("配置信息初始化完成"),process.exit(0)}catch(t){e.fail("配置信息初始化失败"),a.isAxiosError(t)&&J("请检查你的域名及令牌配置"),J(t)}}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',Pe="# 系统 信息文件\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",Ie={Java:{"**/*.{java}":"./run.sh pmd -d ../../../src/main/java/ -f text -R rulesets/java/quickstart.xml"},JavaScript:{"**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}":"eslint --fix","*":"prettier -wu"}};let qe;async function Le(e,n){if(e)o.rm("-rf",x);else if(t.existsSync(O())){await u({message:`当前项目中已存在配置文件夹${x},确认重新配置?`})?o.rm("-rf",x):process.exit(0)}t.mkdirSync(O(),{recursive:!0}),await async function(e,t){const n=await L("git remote get-url --push origin");n||J("获取项目远程地址失败,请配置后重试");let a=e;a||(a=await m({message:"请选择项目语言",choices:[{name:"JavaScript",value:"JavaScript"},{name:"Java",value:"Java"}]}));let i=t;const s=le();if(!i){const e=await Be(s.name);1===e.length?i=e[0].namespace.path:e.length>1&&(i=await m({message:"请选择当前项目所属分组",choices:e.map((e=>({name:e.namespace.path,value:e.namespace.path})))}))}qe=f("项目初始化中").start(),me({language:a,"lint-staged":Ie[a],repository:{url:n,group:i}})}(e,n),await(t.writeFileSync(N(),"",{mode:493}),t.writeFileSync(O("commit-msg"),"#!/usr/bin/env sh\nz lint commit-msg",{mode:493}),t.writeFileSync(O("pre-commit"),"#!/usr/bin/env sh\nz lint commit-files",{mode:493}),t.writeFileSync(O(".prettierrc.json"),Je,{mode:493}),t.writeFileSync(O(".prettierignore"),Pe,{mode:493}),t.writeFileSync(O(".gitignore"),".commit-msg-tpl\n",{mode:493}),void T()),null==qe||qe.succeed("初始化完成。")}async function Re(e){if(!e)return"不能为空";if(!/^[a-z0-9-]+$/.test(e))return"格式为小写字母、中横线(可选)、数字(不推荐)。如apple, apple-tree";if(I().includes(e))return"当前目录下已存在同名文件夹,请先处理。";return!(await Be(e)).find((t=>t.name===e))||"远程仓库中已存在同名项目"}function Fe(e){return!!e||"不能为空"}function Me(e){return e?!!/^[a-zA-Z0-9.]+$/.test(e)||"格式为大小写字母、数字、小数点,小驼峰命名。如userInfo、systemRouter3":"不能为空"}function Ge(e){if(!e)return"目录名称不能为空";if(!/^[a-z][a-z0-9\-/]*$/.test(e))return"支持小写字母、数字,连字符(-)命名,小写字母开头,多层目录使用/隔开。如user、modules-3、setting/profile";if(e.includes("/")){const t=e.split("/");for(const e of t){if(!e)return"子级目录/页面名称不能为空";if(!/^[a-z][a-z0-9-]*$/.test(e))return"支持小写字母、数字,连字符(-)命名,小写字母开头。如user、modules-3"}}let a,i;a=e.includes("/")?n.resolve("src","pages",...e.split("/")):n.resolve("src","pages",e);const s=n.resolve(a,"..");return i=!!t.existsSync(s)&&t.readdirSync(s).map((e=>{const t=e.lastIndexOf(".");return t>-1?e.slice(0,t):e})).includes(e),!i||"本地目录已存在该文件"}e.command("init").alias("i").argument("[type]","非必填。不传为初始化工具配置;传 . 为初始化当前项目。").description("初始化工具配置、项目配置").action((async function(e){e?"."===e?(M(),await Le(void 0,void 0),process.exit(0)):"prepare"===e?(M(),await async function(){t.existsSync(O())&&t.existsSync(N())?T():await Le(),process.exit(0)}()):J("参数错误。执行 z init -h 查看帮助。"):await We()}));const He=e=>`${re("ZenTaoDomain")}${e}`;function Ke(e,n){let a="";if(["feat","fix","refactor"].includes(e)){a=`${e}(${n.map((e=>e.value)).join(",")}): ${n.map((e=>e.name)).join(";")}`}"chore"===e&&(a=`${e}: ${n}`),t.writeFileSync(N(),a,"utf-8"),console.log(s.yellow(a)),W("commit msg模板写入成功,可以进行提交了")}async function Qe(){const e=await m({message:"请选择你要创建的模板类型",choices:[{name:"feat - 业务需求开发",value:"feat"},{name:"fix - bug修复",value:"fix"},{name:"refactor - 技术内部需求",value:"refactor"},{name:"chore - 其他",value:"chore"}]});if(["feat","refactor"].includes(e)){const e=await async function(){const e=await ke({url:He("/my-work-task.json?tid=mrrferp8"),method:"get"});return null==e?void 0:e.tasks.filter((e=>"done"!==e.status)).map((({id:e,name:t})=>({value:{name:t,value:e},name:t})))}();Ke("feat",await g({message:"请关联开发任务(可多选):",validate:e=>0!==e.length||"请选择项",choices:e.map((e=>Object.assign(Object.assign({},e),{name:`[${e.value.value}]: ${e.name}`})))}))}if("fix"===e){const e=await async function(){const e=await ke({url:He("/my-work-bug.json?tid=mrrferp8"),method:"get"});return null==e?void 0:e.bugs.map((({id:e,title:t})=>({name:t,value:{name:t,value:e}})))}();Ke("fix",await g({message:"请关联Bug(可多选):",validate:e=>0!==e.length||"请选择项",choices:e.map((e=>Object.assign(Object.assign({},e),{name:`[${e.value.value}]: ${e.name}`})))}))}if("chore"===e){Ke("chore",await p({message:"请输入commit msg:",validate:e=>0!==e.length||"请输入commit msg"}))}}async function Ve(){var e,a,i,r,c,l;try{const u={},d=async()=>{const e=I(),{projects:t}=await Ee(),n=t.map((t=>{const n={name:`${t.name} [${t.desc}]`,value:t.name,disabled:!1};return e.includes(t.name)&&(n.disabled="目录下已存在同名文件夹"),n})),a=await m({message:"请选择一个项目模板",choices:n}),i=t.find((e=>e.name===a));u.tplName=i.name,u.tplUrl=i.url,u.tplLanguage=i.language},g=async()=>{var e;const{groups:n}=function(){const e=E("fe-groups.json");return t.existsSync(e)?h.readJSONSync(e):{groups:[]}}(),a=await m({message:"请选择一个分组",choices:n.map((e=>({name:`${e.name} [${e.description}]`,value:e.id,short:e.name})))});u.group={id:a,name:null===(e=n.find((e=>e.id===a)))||void 0===e?void 0:e.name}},w=async()=>{u.projectName=await p({message:"请输入项目名称",validate:Re}),u.projectDesc=await p({message:"请输入项目描述",validate:Fe})};await d(),await g(),await w();const v=`${Y}/${null===(e=u.group)||void 0===e?void 0:e.name}/${u.projectName}.git`,y=f("模版初始化中").start();await L(`git clone --depth=1 ${u.tplUrl}`),t.renameSync(u.tplName,u.projectName),o.cd(u.projectName),o.rm("-rf",".git"),await L("git init --initial-branch=master"),await L(`git remote add origin ${v}`),await L(`git config user.name ${ie("gitName")}`),await L(`git config user.email ${ie("gitEmail")}`);const $=le();l=Object.assign(Object.assign({},$),{name:u.projectName,description:u.projectDesc,scripts:Object.assign(Object.assign({},$.scripts),{prepare:"[ -n '$z' ] && z init prepare || echo 'Warning: z not exist at global'"})}),oe=oe?Object.assign(Object.assign({},oe),l):l,h.writeJSONSync(n.join("package.json"),oe,{spaces:2}),await h.writeFile(n.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 lint eslint\n # 或者\n z l e\n\`\`\`\n\n### 格式化代码\n\`\`\`bash\n z lint prettier\n # 或者\n z l p\n\`\`\`\n\n## 常见问题\n列出开发中常见的问题和解决方案\n\n## 了解更多\n在此处放入飞书文档链接。请在[前端团队-项目手册](https://hxhtbr8t8uy.feishu.cn/drive/folder/QfQ7favVWljQk7d63Prc8mUGnJf)中按照分类新建文档。\n`}(u.projectName,u.projectDesc)),y.succeed("模版初始化完成"),await Le(u.tplLanguage,null===(a=u.group)||void 0===a?void 0:a.name);const j=f("依赖安装中").start();await L("npm install --registry https://registry.npmmirror.com/"),j.succeed("依赖安装完成");const b=f("项目推送中").start();await L('git add . && git commit -m "chore: 项目初始化"'),await L("git tag v0.0.1");const x=await(c={name:u.projectName,description:u.projectDesc,path:u.projectName,visibility:"private",namespace_id:null===(i=u.group)||void 0===i?void 0:i.id},xe({url:`${Ne()}/projects`,method:"post",data:c}));await L("git push -u origin master"),await L("git push origin HEAD:master --tags"),b.succeed(`项目已推送到远程,地址: ${s.blue(v)}`);const S=f("初始化分支中").start(),k=`feat_init_${R()}`,O=H(null===(r=u.group)||void 0===r?void 0:r.name)?["dev","test","release",k]:[k],z=await Promise.allSettled(O.map((e=>function(e){return xe({url:`${Ne()}/projects/${e.id}/repository/branches`,method:"post",data:e})}({id:x.id,branch:e,ref:"master"})))),N=[];z.forEach((({status:e},t)=>{"fulfilled"===e&&N.push(O[t])})),await L("git pull"),N.includes(k)?(await L(`git checkout -b ${k} origin/${k}`),S.succeed(`项目已切换到初始分支: ${s.blue(k)}`)):S.warn("开发分支检出失败!项目当前在主分支,请自行检出开发分支。");const T=`cd ${u.projectName} && z start`;console.log(`输入 ${s.green(T)} 开始开发吧~`),process.exit(0)}catch(e){J(e)}}function Ze(e){return ze({url:`${re("K8sDomain")}/kapis/clusters/youshou-local/devops.kubesphere.io/v1alpha3/namespaces/${te}/pipelines/${e.projectName}/pipelineruns?branch=${e.branchName}`,method:"post",data:e.params})}async function Ye(e){F(),M(),await G();let t=e;t&&!V.includes(t)&&J("仅支持发布指定环境分支");const n=await m({message:"请选择平台",choices:Q});if("npm"===n&&(t="master"),!t){const e=await m({message:"请选择部署环境",choices:K});t="production"===(a=e)?"master":a}var a;const i=await Ue("请选择部署成功要通知的人员:",(()=>!0),!0);var r;!function(e){var t;const n=le(),a=ue();(null===(t=null==a?void 0:a.repository)||void 0===t?void 0:t.url)||J(".z/project.json中缺少repository.url");const i=`build:${e}`;(null==n?void 0:n.scripts[i])||J(`项目package.json文件scripts不存在命令${i}。`)}("master"===(r=t)?"production":r);const o=le();await async function(e){const t=f("部署任务创建中").start(),{targetBranch:n,platform:a,notify:i,projectName:r}=e,o=i?[...new Set([ie("weWorkUserId"),...i])]:[ie("weWorkUserId")];try{const{metadata:e,spec:i}=await Ze({projectName:r,branchName:n,params:{parameters:[{name:"platform",value:a},{name:"QW_NOTIFY_USER",value:o.join(",")}]}}),c=`${re("K8SWebDomain")}/youshou-local/clusters/youshou-local/devops/${e.namespace}/pipelines/${i.pipelineRef.name}/branch/${i.scm.refName}/run/${e.name}/task-status`;t.succeed("部署任务创建完成"),console.log(`如有需要,可在k8s中查看 ${s.blue(c)}`),process.exit(0)}catch(e){t.fail("部署任务创建失败"),J(e)}}({projectName:o.name,targetBranch:t,platform:n,notify:i})}async function Xe(e,t,n){var i;const s=f(`分支合并中,${e} -> ${t}`).start();let r=0;try{const{iid:a}=await(o={title:`${e} -> ${t} by z-develop`,id:n.id,source_branch:e,target_branch:t,remove_source_branch:"master"===t},xe({url:`${Ne()}/projects/${o.id}/merge_requests`,method:"post",data:o}));r=a}catch(e){if(a.isAxiosError(e)){409===(null===(i=null==e?void 0:e.response)||void 0===i?void 0:i.status)&&J(`存在重复的合并请求,前往查看${n.mergeRequestUrl}`)}J(e)}var o;const c=async()=>{var e;try{await new Promise((e=>{setTimeout(e,5e3)})),await function(e){return xe({url:`${Ne()}/projects/${e.id}/merge_requests/${e.iid}/merge`,method:"put"})}({id:n.id,iid:r})}catch(t){if(a.isAxiosError(t)){406===(null===(e=null==t?void 0:t.response)||void 0===e?void 0:e.status)?await c():(await function(e){return xe({url:`${Ne()}/projects/${e.id}/merge_requests/${e.iid}`,method:"put",data:e})}({id:n.id,iid:r,state_event:"close"}),s.fail("合并过程中出现冲突,MR已关闭。建议在本地完成合并。"),process.exit(1))}else J(t)}};await c(),s.succeed(`分支${e}已合并到分支${t}`)}function et(){const e=z();if(t.existsSync(e)){const t=h.readJsonSync(e);if(t["lint-staged"])return t["lint-staged"];throw new Error("未找到lint配置")}throw new Error("请先初始化项目(z i .)。")}function tt(){const e=function(e){if(e.includes("Merge")&&e.includes("# Conflicts:"))return!0;if(y.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)?!!["chore","ci"].includes(n)||"chore/ci类型无需填写ID。":"BREAKING CHANGE"===n||"不存在的提交类型。"}(t.readFileSync(n.resolve(".git","COMMIT_EDITMSG"),"utf-8"));!0===e?(W("commit msg validate success."),process.exit(0)):J(`commit msg格式错误。${e}`)}async function nt(e="latest"){await L(`npm i -g ${ne.name}@${e} --registry https://registry.npmmirror.com/`),$e("latestCheckVersionTimestamp",Date.now()),$e("version",e),ge(),console.log(s.green(`升级完成,当前版本${e}`)),process.exit(0)}async function at(){const e=$(process.argv.slice(2));if(!(e.h||e.help||e.v||e.version)&&(!["init","i"].includes(e._[0])||[".","prepare"].includes(e._[1])))if(B()){const e=h.readJSONSync(_());ve(e.profile),$e(e.main),ye(e.constants),await async function(){const e=se("latestCheckVersionTimestamp"),t=se("versionCheckDuring");if(Date.now()-Number(e)>24*Number(t)*3600*1e3){let e;ye(await _e());try{const t="TIME_OUT",n=new Promise((e=>{setTimeout((()=>e(t)),3e3)}));e=await Promise.race([n,L(`npm view ${ne.name} version --registry https://registry.npmmirror.com/`)]),e!==t&&e!==ne.version&&(console.log(`${s.blue(ne.name)}本地版本为${ne.version},低于线上版本${e},开始升级`),await nt(e)),$e("latestCheckVersionTimestamp",Date.now()),ge()}catch(e){console.log("升级出错!请重试,或者手动升级"),J(e)}}}()}else J("请先初始化z-develop(执行 z i)。更多见https://hxhtbr8t8uy.feishu.cn/docx/RnOhdtqJWo5UooxHTaUcQFwtnKg")}e.command("create").alias("c").argument("[type]","可选值为project|pr, branch|b, commit-msg|cm, page|p, component|co").description("创建项目/分支/提交信息/页面/组件").action((async function(e){let a;e?["project","pr"].includes(e)?a="project":["branch","b"].includes(e)?a="branch":["page","pa"].includes(e)?a="page":["component","co"].includes(e)?a="component":["commit-msg","cm"].includes(e)?a="commit-msg":J("参数输入错误"):a=await m({message:"请选择你要创建的类型",choices:[{name:"提交信息(commit message)",value:"commit-msg"},{name:"分支(branch)",value:"branch"},{name:"页面(page)",value:"page"},{name:"组件(component)",value:"component"},{name:"项目(project)",value:"project"}]}),"project"===a?await Ve():"branch"===a?(F(),M(),await G(),await async function(){F(),M(),await G();const e=`${await m({message:"请选择创建分支的类型",choices:[{name:"开发新功能(feat)",value:"feat"},{name:"修复BUG(fix)",value:"fix"},{name:"重构/优化代码(refactor)",value:"refactor"}]})}_${await p({message:"请输入创建分支的目的(大小写字母、数字,小驼峰式命名。如userInfo)",validate:Me})}_${R()}`;await L("git fetch origin master"),await L(`git checkout -b ${e} origin/master`),await L(`git push -u origin ${e}`)}()):"commit-msg"===a?(F(),M(),await Qe()):"page"===a?(F(),M(),await async function(){const e="pages",a=await fe(e);t.mkdirSync(n.resolve("src",e),{recursive:!0});const i=await p({message:"请输入目录及页面名称(如user/list,不带文件后缀)",validate:Ge});let s;if(i.includes("/")){const a=i.split("/");a.pop(),s=n.resolve("src",e,...i.split("/")),t.mkdirSync(n.resolve("src",e,...a),{recursive:!0})}else s=n.resolve("src",e,i);const{pages:r}=await Ee(),c=t.readdirSync(a),l=await m({message:"请选择模版",choices:r.filter((e=>c.includes(e.name))).map((e=>({name:`${e.name}: ${e.desc}(${e.author})`,value:e.name})))}),u=f("页面生成中...").start(),d=s+n.extname(n.join(a,l));o.cp("-r",n.join(a,l),d),P(d)?q(d).forEach((e=>{we(n.join(d,e),i)})):we(d,i),u.succeed("页面生成成功")}()):"component"===a&&(F(),M(),await async function(){const e="components",a=await fe("components");t.mkdirSync(n.resolve("src",e),{recursive:!0});const i=await p({message:"请输入目录及组件名称(如user/list,不带文件后缀)",validate:Ge});let s;if(i.includes("/")){const a=i.split("/"),r=a.pop();s=n.resolve("src",e,...a,he(r)),t.mkdirSync(n.resolve("src",e,...a),{recursive:!0})}else s=n.resolve("src",e,he(i));const{components:r}=await Ee(),c=t.readdirSync(a),l=await m({message:"请选择模版",choices:r.filter((e=>c.includes(e.name))).map((e=>({name:`${e.name}: ${e.desc}(${e.author})`,value:e.name})))}),u=f("组件生成中...").start(),d=s+n.extname(n.join(a,l));o.cp("-r",n.join(a,l),d),P(d)?q(d).forEach((e=>{we(n.join(d,e),i)})):we(d,i),u.succeed("组件生成成功")}()),process.exit(0)})),e.command("merge").alias("m").description("合并当前分支到指定远程分支,并部署。").action((async function(){F(),M(),await G();const e=await de();V.includes(e.sourceBranch)&&J(`当前分支${e.sourceBranch}不可作为源分支合并到目标分支。`);const t=await(n=e.id,xe({url:`${Ne()}/projects/${n}/repository/branches`}));var n;const a=H(e.group),i=t.filter((t=>![e.sourceBranch].includes(t.name))).map((e=>{let t=e.name;return a&&V.includes(t)&&(t=s.bold.blue(t)),{name:t,value:e.name}})),r=await m({message:"请选择要合并到的目标分支:",choices:i}),o=f(`${e.sourceBranch}分支代码检测中`).start();if(await L(`git ls-remote --heads origin ${e.sourceBranch}`)){o.text=`存在远程分支origin/${e.sourceBranch}`,await L("git fetch");const t=await L(`git rev-parse ${e.sourceBranch}`),n=await L(`git rev-parse origin/${e.sourceBranch}`);if(await L(`git merge-base ${n} HEAD`)===n)await L(`git push -u origin ${e.sourceBranch}`),o.succeed(`${e.sourceBranch}分支代码已推送到远程`);else{await L(`git merge-base ${t} ${n}`)===t?(await L("git pull"),o.succeed(`${e.sourceBranch}分支代码已更新`)):(o.fail(`远程分支origin/${e.sourceBranch}和本地分支${e.sourceBranch}都有新的提交,请手动合并后再试。`),process.exit(1))}}else await L(`git push -u origin ${e.sourceBranch}`),o.succeed(`${e.sourceBranch}已推送到远程`);await async function(e,t,n){const a=`origin/${e.sourceBranch}`,i=await L("git log -b origin/master -1 --format=%H"),r=await L(`git log -b origin/${e.sourceBranch} -1 --format=%H`),o=await L(`git log ${i}...${r} -b ${a}`);if(o||J(`分支${e.sourceBranch}上不存在新的commit,不需要合并。`),await L(`git branch --contains ${i} -r ${a}`)||(console.log(s.yellow("注意:当前分支上不存在远程主分支最新代码,将在自动合入后继续。")),await Xe("master",e.sourceBranch,e)),"master"===t&&n){const e=o.split("\n").filter((e=>e)),t=await L("git log -b origin/test -1 --format=%H");(function(e,t){for(const n of t)if(!e.includes(n))return!1;return!0})((await L(`git log ${i}...${t} -b origin/test`)).split("\n").filter((e=>e)),e)||J("请先在测试环境发布要部署的代码")}}(e,r,a),await Xe(e.sourceBranch,r,e),"master"===r&&(await L("git checkout master"),await L("git pull"),await L(`git branch -d ${e.sourceBranch}`),W(`${e.sourceBranch}分支已移除,当前已切换到最新的master。如需继续开发,请检出新分支(z c b)。`)),a&&V.includes(r)&&await Ye(r)})),e.command("deploy").alias("d").description("发布指定远程分支").argument("[branchName]","可选值为dev/test/release/master").action(Ye),e.command("start").alias("s").description("启动本地开发环境").argument("[env]","可选值 dev|d, test|t, release|r, prod|p").action((async function(e){let t=e;t?["dev","test","release","production","d","t","r","p"].includes(e)?"d"===t?t="dev":"t"===t?t="test":"r"===t?t="release":"p"===t&&(t="production"):J("参数输入有误"):t=await m({message:"请选择环境",choices:K});const n=`dev:${t}`;if(le().scripts[n])try{o.exec(`npm run ${n}`,{silent:!1})}catch(e){J(e)}else J(`项目中(package.josn > scripts)不存在命令${n},请先添加!`)})),e.command("lint").alias("l").argument("[type]","非必填。可选值为commit-msg|cm, commit-files|cf, prettier|p, eslint|e。").option("--quiet","eslint只打印error").option("--max-warnings [VALUE]","eslint结果warn超过多少个会异常退出,默认为100",parseInt).description("执行 lint 脚本。包含 lint staged 、 lint commit message、 prettier、 eslint。").action((async function(e,a){let i;if(F(),M(),e?["commit-msg","cm"].includes(e)?i="commit-msg":["commit-files","cf"].includes(e)?i="commit-files":["prettier","p"].includes(e)?i="prettier":["eslint","e"].includes(e)?i="eslint":J("参数输入错误"):i=await m({message:"请选择你要执行的操作",choices:[{name:"全局执行 prettier",value:"prettier"},{name:"全局执行 eslint",value:"eslint"}]}),"commit-msg"===i)await tt();else if("commit-files"===i)await async function(){await v({concurrent:!1,debug:!1,config:et()})?(W("代码风格检测通过!"),process.exit(0)):J("代码风格检测未通过!")}();else if("prettier"===i){t.existsSync(n.resolve("node_modules",".bin","prettier"))||J("该项目未安装prettier,请安装后重试");try{await L("npx prettier --write . --config .z/.prettierrc.json --ignore-path .z/.prettierignore --ignore-unknown --no-error-on-unmatched-pattern",{silent:!1}),W("prettier执行成功"),process.exit(0)}catch(e){J("prettier校验出错")}}else if("eslint"===i){t.existsSync(n.resolve("node_modules",".bin","eslint"))||J("该项目未安装eslint,请安装后重试");try{let e="npx eslint '**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}' --fix";"win32"===process.platform&&(e='npx eslint "**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}" --fix'),a.quiet&&(e+=" --quiet"),a.maxWarnings&&!isNaN(Number(a.maxWarnings))?e+=` --max-warnings ${Number(a.maxWarnings)}`:e+=" --max-warnings 100",await L(e,{silent:!1}),W("eslint执行成功"),process.exit(0)}catch(e){J("eslint校验出错")}}})),e.command("update").alias("u").argument("[version]","版本号","latest").description("升级").action(nt),e.name("z-develop").alias("z").description(`z-develop, 开发流程管理工具。\n了解更多: ${s.blue("https://hxhtbr8t8uy.feishu.cn/docx/RnOhdtqJWo5UooxHTaUcQFwtnKg")}`).usage("<command> [options]").hook("preAction",(async function(){process.on("unhandledRejection",(e=>{})),process.on("uncaughtException",(e=>{})),o.config.fatal=!0,o.config.silent=!0,o.config.verbose=Boolean(void 0)||!1,await at()})).version(ne.version,"-v, --version","当前版本号").helpOption("-h, --help","帮助").showHelpAfterError("可以使用z -h查看帮助。"),e.parse();
|