@cnbcool/cnb-cli 1.4.6 → 1.5.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.
Files changed (2) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -87,7 +87,7 @@ ${p}
87
87
  CNB_PULL_REQUEST_IID - PR 编号(PR 相关快捷命令)
88
88
 
89
89
  默认只输出摘要信息,添加 --v 可输出全部信息
90
- `)}}function xl(e,t){let r=process.env.CNB_REPO_SLUG||"";if(t)return{repo:r};let i=e==="issues"?process.env.CNB_ISSUE_IID||"":process.env.CNB_PULL_REQUEST_IID||"";return{repo:r,number:i}}function eu(e,t){if(!e||!t)return null;let r=e==="issues"?Fe:e==="pulls"?Ye:null;if(!r)return null;let i=r.find((p)=>p.shortName===t);if(!i)return null;return{module:e,tool:i.realTool,autoPath:xl(e,!!i.repoOnly),autoData:i.autoData||null,upload:!!i.upload}}});var En=o((Xe)=>{Object.defineProperty(Xe,"__esModule",{value:!0});Xe.handleUpload=iu;var Ze=Vn(require("fs")),Tn=Vn(require("path"));function Vn(e){return e&&e.__esModule?e:{default:e}}var tu={".txt":"text/plain",".html":"text/html",".htm":"text/html",".css":"text/css",".csv":"text/csv",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".pdf":"application/pdf",".zip":"application/zip",".gz":"application/gzip",".gzip":"application/gzip",".tar":"application/x-tar",".7z":"application/x-7z-compressed",".rar":"application/vnd.rar",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".webp":"image/webp",".ico":"image/x-icon",".bmp":"image/bmp",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".mp4":"video/mp4",".webm":"video/webm",".avi":"video/x-msvideo",".mov":"video/quicktime",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".md":"text/markdown",".yaml":"text/yaml",".yml":"text/yaml",".sh":"application/x-sh",".py":"text/x-python",".rb":"text/x-ruby",".go":"text/x-go",".rs":"text/x-rust",".ts":"text/typescript",".tsx":"text/typescript",".jsx":"text/jsx",".java":"text/x-java-source",".c":"text/x-c",".h":"text/x-c",".cpp":"text/x-c++src",".hpp":"text/x-c++hdr",".log":"text/plain",".patch":"text/x-diff",".diff":"text/x-diff"};function ru(e){let t=Tn.default.extname(e).toLowerCase();return tu[t]||"application/octet-stream"}var Sn=104857600;async function iu(e,t,r,i){if(!t)return{status:400,data:{error:`上传命令需要指定文件路径,如: --data '{"file":"./path/to/file"}'`}};if(!Ze.default.existsSync(t))return{status:400,data:{error:`文件不存在: ${t}`}};let p=Ze.default.statSync(t);if(!p.isFile())return{status:400,data:{error:`不是文件: ${t}`}};let s=Tn.default.basename(t),n=p.size;if(n===0)return{status:400,data:{error:"文件为空"}};if(n>Sn)return{status:400,data:{error:`文件过大 (${(n/1024/1024).toFixed(1)}MB),上限 ${Sn/1024/1024}MB`}};let a=ru(t),d=e.module==="issues",u=d?{name:s,size:n,content_type:a}:{name:s,size:n},l=d?i:i.repo,g=await r(l,u),_=g?.data,b=_?.upload_url;if(!b)return g;let h=Ze.default.createReadStream(t),m={"Content-Type":a,"Content-Length":String(n)},f;try{f=await fetch(b,{method:"PUT",headers:m,body:h,duplex:"half"})}catch(v){throw h.destroy(),v}if(!f.ok){h.destroy();let v=await f.text().catch(()=>"");return{status:f.status,data:{error:`文件上传失败: ${f.statusText}`,detail:v}}}if(d)return{status:200,data:{asset_link:_.asset_link,name:s,size:n}};return{status:200,data:{name:_.assets?.name||s,path:_.assets?.path,size:n,token:_.token}}}});var ie=o((Me)=>{Object.defineProperty(Me,"__esModule",{value:!0});Me.getTokenPath=nu;var pu=Un(require("path")),su=Un(require("os"));function Un(e){return e&&e.__esModule?e:{default:e}}function nu(){return pu.default.join(su.default.homedir(),".cnb","token")}});var Qe=o((He)=>{Object.defineProperty(He,"__esModule",{value:!0});He.loadToken=yu;var Wn=au(require("fs")),ou=ie();function au(e){return e&&e.__esModule?e:{default:e}}function yu(){let e=(0,ou.getTokenPath)();if(!Wn.default.existsSync(e))return null;try{return JSON.parse(Wn.default.readFileSync(e,"utf-8"))}catch{return null}}});var Oe=o((Ge)=>{Object.defineProperty(Ge,"__esModule",{value:!0});Ge.saveToken=lu;var Be=Jn(require("fs")),cu=Jn(require("path")),du=ie();function Jn(e){return e&&e.__esModule?e:{default:e}}function lu(e){let t=(0,du.getTokenPath)(),r=cu.default.dirname(t);if(!Be.default.existsSync(r))Be.default.mkdirSync(r,{recursive:!0});Be.default.writeFileSync(t,JSON.stringify(e,null,2),{mode:384})}});var Re=o((Le)=>{Object.defineProperty(Le,"__esModule",{value:!0});Le.refreshAccessToken=gu;var uu=Oe();async function gu(e){if(!e.refresh_token)throw Error("no refresh_token");let t=e.platform_url||"https://cnb-dev.woa.com",r=e.client_id||process.env.OAUTH2_CLIENT_ID||"cnb_cli",i=`${t.replace(/\/+$/,"")}/oauth2/token`,p=new URLSearchParams;p.set("grant_type","refresh_token"),p.set("refresh_token",e.refresh_token),p.set("client_id",r);let s=await fetch(i,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:p.toString()});if(s.status!==200){let u=await s.text();throw Error(`refresh token failed: status=${s.status} body=${u}`)}let n=await s.json(),a=Math.floor(Date.now()/1000),d={access_token:n.access_token,expires_at:a+n.expires_in,refresh_token:n.refresh_token||e.refresh_token,platform_url:e.platform_url,client_id:e.client_id};return(0,uu.saveToken)(d),n.access_token}});var Ce=o((De)=>{Object.defineProperty(De,"__esModule",{value:!0});De.resolveToken=hu;var bu=Qe(),mu=Re();async function hu(){if(process.env.CNB_TOKEN)return process.env.CNB_TOKEN;let e=(0,bu.loadToken)();if(!e||!e.access_token)console.error("未找到有效的登录凭证,请先执行 `cnb login` 进行授权。"),process.exit(1);if(Math.floor(Date.now()/1000)<e.expires_at)return e.access_token;if(e.refresh_token)try{return await(0,mu.refreshAccessToken)(e)}catch(r){console.error(`Token 已过期,刷新失败: ${r.message}`),console.error("请重新执行 `cnb login` 进行授权。"),process.exit(1)}console.error("Token 已过期且无 refresh_token,请重新执行 `cnb login` 进行授权。"),process.exit(1)}});var Fn=o((et)=>{Object.defineProperty(et,"__esModule",{value:!0});et.diagnoseBuild=ju;var _u=Ce();async function xe(e,t){let r=await fetch(e,{headers:t});if(!r.ok)throw Error(`请求失败: ${r.status} ${r.statusText} — ${e}`);return r.json()}async function fu(e,t){let r=await fetch(e,{headers:t});if(!r.ok)throw Error(`请求失败: ${r.status} ${r.statusText} — ${e}`);return r.text()}function vu(e){let t=e?.statuses||e;if(!Array.isArray(t)||t.length===0)return null;let r=t.find((s)=>s.state==="error"||s.state==="failure");if(!r)return null;let p=(r.target_url||"").match(/\/-\/build\/([^/?#]+)/);return p?p[1]:null}async function Pu(e,t,r){let i=await fu(`${e}/-/build/logs/${t}`,r);try{let p=JSON.parse(i);if(p.data&&typeof p.data==="string")return Buffer.from(p.data,"base64").toString("utf-8");if(p.data?.data&&typeof p.data.data==="string")return Buffer.from(p.data.data,"base64").toString("utf-8");return JSON.stringify(p,null,2)}catch{return i}}async function ju(e){let t=process.env.CNB_API_ENDPOINT||"https://api.cnb.cool",{repo:r}=e,i=e.sn,s={Accept:"application/vnd.cnb.api+json",Authorization:`Bearer ${await(0,_u.resolveToken)()}`};if(!i&&process.env.CNB_BUILD_ID)i=process.env.CNB_BUILD_ID;if(!i&&e.prNumber)try{let g=`${t}/${r}/-/pulls/${e.prNumber}/statuses`,_=await xe(g,s);if(i=vu(_),!i)return"未从 PR CI 状态中找到失败的构建,所有构建均为成功状态。"}catch(g){return`获取 PR CI 状态失败: ${g.message}`}if(!i)return"缺少构建号(sn):未传入 --sn、未设置 CNB_BUILD_ID、且未检测到 PR 上下文。";let n=`${t}/${r}`,a=[];a.push(`查询构建 sn=${i} 的流水线状态...
90
+ `)}}function xl(e,t){let r=process.env.CNB_REPO_SLUG||"";if(t)return{repo:r};let i=e==="issues"?process.env.CNB_ISSUE_IID||"":process.env.CNB_PULL_REQUEST_IID||"";return{repo:r,number:i}}function eu(e,t){if(!e||!t)return null;let r=e==="issues"?Fe:e==="pulls"?Ye:null;if(!r)return null;let i=r.find((p)=>p.shortName===t);if(!i)return null;return{module:e,tool:i.realTool,autoPath:xl(e,!!i.repoOnly),autoData:i.autoData||null,upload:!!i.upload}}});var En=o((Xe)=>{Object.defineProperty(Xe,"__esModule",{value:!0});Xe.handleUpload=iu;var Ze=Vn(require("fs")),Tn=Vn(require("path"));function Vn(e){return e&&e.__esModule?e:{default:e}}var tu={".txt":"text/plain",".html":"text/html",".htm":"text/html",".css":"text/css",".csv":"text/csv",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".pdf":"application/pdf",".zip":"application/zip",".gz":"application/gzip",".gzip":"application/gzip",".tar":"application/x-tar",".7z":"application/x-7z-compressed",".rar":"application/vnd.rar",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".webp":"image/webp",".ico":"image/x-icon",".bmp":"image/bmp",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".mp4":"video/mp4",".webm":"video/webm",".avi":"video/x-msvideo",".mov":"video/quicktime",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".md":"text/markdown",".yaml":"text/yaml",".yml":"text/yaml",".sh":"application/x-sh",".py":"text/x-python",".rb":"text/x-ruby",".go":"text/x-go",".rs":"text/x-rust",".ts":"text/typescript",".tsx":"text/typescript",".jsx":"text/jsx",".java":"text/x-java-source",".c":"text/x-c",".h":"text/x-c",".cpp":"text/x-c++src",".hpp":"text/x-c++hdr",".log":"text/plain",".patch":"text/x-diff",".diff":"text/x-diff"};function ru(e){let t=Tn.default.extname(e).toLowerCase();return tu[t]||"application/octet-stream"}var Sn=104857600;async function iu(e,t,r,i){if(!t)return{status:400,data:{error:`上传命令需要指定文件路径,如: --data '{"file":"./path/to/file"}'`}};if(!Ze.default.existsSync(t))return{status:400,data:{error:`文件不存在: ${t}`}};let p=Ze.default.statSync(t);if(!p.isFile())return{status:400,data:{error:`不是文件: ${t}`}};let s=Tn.default.basename(t),n=p.size;if(n===0)return{status:400,data:{error:"文件为空"}};if(n>Sn)return{status:400,data:{error:`文件过大 (${(n/1024/1024).toFixed(1)}MB),上限 ${Sn/1024/1024}MB`}};let a=ru(t),d=e.module==="issues",u=d?{name:s,size:n,content_type:a}:{name:s,size:n},l=d?i:i.repo,g=await r(l,u),_=g?.data,b=_?.upload_url;if(!b)return g;let h=Ze.default.createReadStream(t),m={"Content-Type":a,"Content-Length":String(n)},f;try{f=await fetch(b,{method:"PUT",headers:m,body:h,duplex:"half"})}catch(v){throw h.destroy(),v}if(!f.ok){h.destroy();let v=await f.text().catch(()=>"");return{status:f.status,data:{error:`文件上传失败: ${f.statusText}`,detail:v}}}if(d)return{status:200,data:{asset_link:_.asset_link,name:s,size:n}};return{status:200,data:{name:_.assets?.name||s,path:_.assets?.path,size:n,token:_.token}}}});var ie=o((Me)=>{Object.defineProperty(Me,"__esModule",{value:!0});Me.getTokenPath=nu;var pu=Un(require("path")),su=Un(require("os"));function Un(e){return e&&e.__esModule?e:{default:e}}function nu(){return pu.default.join(su.default.homedir(),".cnb","token")}});var Qe=o((He)=>{Object.defineProperty(He,"__esModule",{value:!0});He.loadToken=yu;var Wn=au(require("fs")),ou=ie();function au(e){return e&&e.__esModule?e:{default:e}}function yu(){let e=(0,ou.getTokenPath)();if(!Wn.default.existsSync(e))return null;try{return JSON.parse(Wn.default.readFileSync(e,"utf-8"))}catch{return null}}});var Oe=o((Ge)=>{Object.defineProperty(Ge,"__esModule",{value:!0});Ge.saveToken=lu;var Be=Jn(require("fs")),cu=Jn(require("path")),du=ie();function Jn(e){return e&&e.__esModule?e:{default:e}}function lu(e){let t=(0,du.getTokenPath)(),r=cu.default.dirname(t);if(!Be.default.existsSync(r))Be.default.mkdirSync(r,{recursive:!0});Be.default.writeFileSync(t,JSON.stringify(e,null,2),{mode:384})}});var Re=o((Le)=>{Object.defineProperty(Le,"__esModule",{value:!0});Le.refreshAccessToken=gu;var uu=Oe();async function gu(e){if(!e.refresh_token)throw Error("no refresh_token");let t=e.platform_url||"https://cnb-dev.woa.com",r=e.client_id||process.env.OAUTH2_CLIENT_ID||"cnb_cli",i=`${t.replace(/\/+$/,"")}/oauth2/token`,p=new URLSearchParams;p.set("grant_type","refresh_token"),p.set("refresh_token",e.refresh_token),p.set("client_id",r);let s=await fetch(i,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:p.toString()});if(s.status!==200){let u=await s.text();throw Error(`refresh token failed: status=${s.status} body=${u}`)}let n=await s.json(),a=Math.floor(Date.now()/1000),d={access_token:n.access_token,expires_at:a+n.expires_in,refresh_token:n.refresh_token||e.refresh_token,platform_url:e.platform_url,client_id:e.client_id};return(0,uu.saveToken)(d),n.access_token}});var Ce=o((De)=>{Object.defineProperty(De,"__esModule",{value:!0});De.resolveToken=hu;var bu=Qe(),mu=Re();async function hu(){if(process.env.CNB_TOKEN_FOR_CODEBUDDY){if(!process.env.CNB_NPC_SLUG&&process.env.CNB_NPC_NAME==="CodeBuddy")return process.env.CNB_TOKEN_FOR_CODEBUDDY}if(process.env.CNB_TOKEN)return process.env.CNB_TOKEN;let e=(0,bu.loadToken)();if(!e||!e.access_token)console.error("未找到有效的登录凭证,请先执行 `cnb login` 进行授权。"),process.exit(1);if(Math.floor(Date.now()/1000)<e.expires_at)return e.access_token;if(e.refresh_token)try{return await(0,mu.refreshAccessToken)(e)}catch(r){console.error(`Token 已过期,刷新失败: ${r.message}`),console.error("请重新执行 `cnb login` 进行授权。"),process.exit(1)}console.error("Token 已过期且无 refresh_token,请重新执行 `cnb login` 进行授权。"),process.exit(1)}});var Fn=o((et)=>{Object.defineProperty(et,"__esModule",{value:!0});et.diagnoseBuild=ju;var _u=Ce();async function xe(e,t){let r=await fetch(e,{headers:t});if(!r.ok)throw Error(`请求失败: ${r.status} ${r.statusText} — ${e}`);return r.json()}async function fu(e,t){let r=await fetch(e,{headers:t});if(!r.ok)throw Error(`请求失败: ${r.status} ${r.statusText} — ${e}`);return r.text()}function vu(e){let t=e?.statuses||e;if(!Array.isArray(t)||t.length===0)return null;let r=t.find((s)=>s.state==="error"||s.state==="failure");if(!r)return null;let p=(r.target_url||"").match(/\/-\/build\/([^/?#]+)/);return p?p[1]:null}async function Pu(e,t,r){let i=await fu(`${e}/-/build/logs/${t}`,r);try{let p=JSON.parse(i);if(p.data&&typeof p.data==="string")return Buffer.from(p.data,"base64").toString("utf-8");if(p.data?.data&&typeof p.data.data==="string")return Buffer.from(p.data.data,"base64").toString("utf-8");return JSON.stringify(p,null,2)}catch{return i}}async function ju(e){let t=process.env.CNB_API_ENDPOINT||"https://api.cnb.cool",{repo:r}=e,i=e.sn,s={Accept:"application/vnd.cnb.api+json",Authorization:`Bearer ${await(0,_u.resolveToken)()}`};if(!i&&process.env.CNB_BUILD_ID)i=process.env.CNB_BUILD_ID;if(!i&&e.prNumber)try{let g=`${t}/${r}/-/pulls/${e.prNumber}/statuses`,_=await xe(g,s);if(i=vu(_),!i)return"未从 PR CI 状态中找到失败的构建,所有构建均为成功状态。"}catch(g){return`获取 PR CI 状态失败: ${g.message}`}if(!i)return"缺少构建号(sn):未传入 --sn、未设置 CNB_BUILD_ID、且未检测到 PR 上下文。";let n=`${t}/${r}`,a=[];a.push(`查询构建 sn=${i} 的流水线状态...
91
91
  `);let d;try{d=await xe(`${n}/-/build/status/${i}`,s)}catch(g){return`获取构建状态失败: ${g.message}`}if(!d.pipelinesStatus||typeof d.pipelinesStatus!=="object")return a.push("未找到流水线状态信息"),a.push("返回数据:"),a.push(JSON.stringify(d,null,2)),a.join(`
92
92
  `);let u=Object.entries(d.pipelinesStatus);if(u.length===0)return"该构建没有流水线";let l=!1;for(let[g,_]of u){let{id:b,status:h,stages:m}=_;if(!Array.isArray(m))continue;let f=m.filter((v)=>v.status==="error");if(f.length===0)continue;l=!0,a.push(`━━━ 流水线: ${g} (status: ${h}) ━━━
93
93
  `);for(let v of f){a.push(`▸ 失败 Stage: ${v.name||v.id} (status: ${v.status})`);try{let j=await xe(`${n}/-/build/logs/stage/${i}/${b}/${v.id}`,s);if(j.error)a.push(` 错误信息: ${j.error}`);if(j.duration!=null)a.push(` 耗时: ${j.duration}ms`);if(Array.isArray(j.content)&&j.content.length>0){a.push(" ─── 日志 ───");for(let K of j.content)a.push(` ${K}`);a.push(" ─── 日志结束 ───")}else throw Error("Stage 详情无日志内容,降级到全量日志")}catch(j){a.push(` Stage 详情获取失败(${j.message}),尝试全量日志下载...`);try{let K=await Pu(n,b,s);if(K?.trim()){a.push(" ─── 全量日志(末尾 100 行)───");let w=K.split(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnbcool/cnb-cli",
3
- "version": "1.4.6",
3
+ "version": "1.5.0",
4
4
  "description": "CNB OpenAPI 命令行工具,基于 CNB 平台 Swagger 自动生成,支持 Issues、PR、Git、组织管理等全部 API 操作",
5
5
  "main": "skills/cnb-api/scripts/core/index.js",
6
6
  "bin": {
@@ -41,8 +41,8 @@
41
41
  "author": "",
42
42
  "license": "MIT",
43
43
  "devDependencies": {
44
- "bun": "^1.3.9",
45
44
  "@cnbcool/cnb-api-generate": "^2.3.5",
45
+ "bun": "^1.3.9",
46
46
  "skills": "^1.4.4"
47
47
  }
48
48
  }