@cnbcool/cnb-cli 1.6.2 → 1.6.3

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 qu(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 Iu(e,t){if(!e||!t)return null;let r=e==="issues"?Be:e==="pulls"?Ge:null;if(!r)return null;let i=r.find((p)=>p.shortName===t);if(!i)return null;return{module:e,tool:i.realTool,autoPath:qu(e,!!i.repoOnly),autoData:i.autoData||null,upload:!!i.upload}}});var Dn=o((Re)=>{Object.defineProperty(Re,"__esModule",{value:!0});Re.handleUpload=Vu;var Le=Rn(require("fs")),Ln=Rn(require("path"));function Rn(e){return e&&e.__esModule?e:{default:e}}var Su={".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 Tu(e){let t=Ln.default.extname(e).toLowerCase();return Su[t]||"application/octet-stream"}var On=104857600;async function Vu(e,t,r,i){if(!t)return{status:400,data:{error:`上传命令需要指定文件路径,如: --data '{"file":"./path/to/file"}'`}};if(!Le.default.existsSync(t))return{status:400,data:{error:`文件不存在: ${t}`}};let p=Le.default.statSync(t);if(!p.isFile())return{status:400,data:{error:`不是文件: ${t}`}};let s=Ln.default.basename(t),n=p.size;if(n===0)return{status:400,data:{error:"文件为空"}};if(n>On)return{status:400,data:{error:`文件过大 (${(n/1024/1024).toFixed(1)}MB),上限 ${On/1024/1024}MB`}};let a=Tu(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,h=_?.upload_url;if(!h)return g;let f=Le.default.createReadStream(t),m={"Content-Type":a,"Content-Length":String(n)},b;try{b=await fetch(h,{method:"PUT",headers:m,body:f,duplex:"half"})}catch(v){throw f.destroy(),v}if(!b.ok){f.destroy();let v=await b.text().catch(()=>"");return{status:b.status,data:{error:`文件上传失败: ${b.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 L=o((De)=>{Object.defineProperty(De,"__esModule",{value:!0});De.getTokenPath=Wu;var Eu=Cn(require("path")),Uu=Cn(require("os"));function Cn(e){return e&&e.__esModule?e:{default:e}}function Wu(){return Eu.default.join(Uu.default.homedir(),".cnb","token")}});var R=o((Ce)=>{Object.defineProperty(Ce,"__esModule",{value:!0});Ce.loadToken=Yu;var xn=Fu(require("fs")),Ju=L();function Fu(e){return e&&e.__esModule?e:{default:e}}function Yu(){let e=(0,Ju.getTokenPath)();if(!xn.default.existsSync(e))return null;try{return JSON.parse(xn.default.readFileSync(e,"utf-8"))}catch{return null}}});var tt=o((et)=>{Object.defineProperty(et,"__esModule",{value:!0});et.saveToken=Xu;var xe=eo(require("fs")),$u=eo(require("path")),Zu=L();function eo(e){return e&&e.__esModule?e:{default:e}}function Xu(e){let t=(0,Zu.getTokenPath)(),r=$u.default.dirname(t);if(!xe.default.existsSync(r))xe.default.mkdirSync(r,{recursive:!0});xe.default.writeFileSync(t,JSON.stringify(e,null,2),{mode:384})}});var ye=o((rt)=>{Object.defineProperty(rt,"__esModule",{value:!0});rt.refreshAccessToken=Qu;var Mu=tt();async function Qu(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,login_host:e.login_host};return(0,Mu.saveToken)(d),n.access_token}});var pt=o((it)=>{Object.defineProperty(it,"__esModule",{value:!0});it.resolveToken=Gu;var Hu=R(),Bu=ye();async function Gu(){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,Hu.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,Bu.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 nt=o((st)=>{Object.defineProperty(st,"__esModule",{value:!0});st.resolveApiDomain=Lu;var Ou=R();function Lu(){let e=process.env.CNB_API_ENDPOINT||"https://api.cnb.cool";if(process.env.CNB_TOKEN_FOR_CODEBUDDY||process.env.CNB_TOKEN)return e;let t=(0,Ou.loadToken)();if(t?.login_host)return t.login_host;return e}});var yt=o((S)=>{Object.defineProperty(S,"__esModule",{value:!0});S.SN_PATTERN=void 0;S.apiRequest=ro;S.apiRequestText=Cu;S.extractSnFromStatuses=io;S.extractSnFromUrl=at;S.invalidSnMessage=to;S.resolveBuildContext=xu;var Ru=pt(),Du=nt(),ot=S.SN_PATTERN=/^cnb-[a-z0-9]+-[a-z0-9]+$/i;function to(e){return[`参数 --sn 的值不是合法的构建号: "${e}"`,"","构建号(sn)格式应为 cnb-xxx-xxxxxxxxx,例如 cnb-9p9-1jnfh8rv5。","常见错误:把 `cnb pulls check-status` 返回的 context 字段(形如",'"cnb/pull_request/common-lint")当成 sn 传入,这是 CI 状态的检查项名,',"不是构建号。","","请去掉 --sn 参数重试,工具会自动从当前 PR 的 CI 状态中解析失败构建的 sn。"].join(`
90
+ `)}}function qu(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 Iu(e,t){if(!e||!t)return null;let r=e==="issues"?Be:e==="pulls"?Ge:null;if(!r)return null;let i=r.find((a)=>a.shortName===t);if(!i)return null;let p=i.realTool,s=qu(e,!!i.repoOnly),n=i.autoData||null;if(e==="pulls"&&i.realTool==="post-pull-comment"&&process.env.CNB_REVIEW_ID)p="post-pull-request-review-reply",s.review_id=process.env.CNB_REVIEW_ID,n={...n||{},reply_to_comment_id:process.env.CNB_REVIEW_ID};return{module:e,tool:p,autoPath:s,autoData:n,upload:!!i.upload}}});var Dn=o((Re)=>{Object.defineProperty(Re,"__esModule",{value:!0});Re.handleUpload=Vu;var Le=Rn(require("fs")),Ln=Rn(require("path"));function Rn(e){return e&&e.__esModule?e:{default:e}}var Su={".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 Tu(e){let t=Ln.default.extname(e).toLowerCase();return Su[t]||"application/octet-stream"}var On=104857600;async function Vu(e,t,r,i){if(!t)return{status:400,data:{error:`上传命令需要指定文件路径,如: --data '{"file":"./path/to/file"}'`}};if(!Le.default.existsSync(t))return{status:400,data:{error:`文件不存在: ${t}`}};let p=Le.default.statSync(t);if(!p.isFile())return{status:400,data:{error:`不是文件: ${t}`}};let s=Ln.default.basename(t),n=p.size;if(n===0)return{status:400,data:{error:"文件为空"}};if(n>On)return{status:400,data:{error:`文件过大 (${(n/1024/1024).toFixed(1)}MB),上限 ${On/1024/1024}MB`}};let a=Tu(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,h=_?.upload_url;if(!h)return g;let f=Le.default.createReadStream(t),m={"Content-Type":a,"Content-Length":String(n)},b;try{b=await fetch(h,{method:"PUT",headers:m,body:f,duplex:"half"})}catch(v){throw f.destroy(),v}if(!b.ok){f.destroy();let v=await b.text().catch(()=>"");return{status:b.status,data:{error:`文件上传失败: ${b.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 L=o((De)=>{Object.defineProperty(De,"__esModule",{value:!0});De.getTokenPath=Wu;var Eu=Cn(require("path")),Uu=Cn(require("os"));function Cn(e){return e&&e.__esModule?e:{default:e}}function Wu(){return Eu.default.join(Uu.default.homedir(),".cnb","token")}});var R=o((Ce)=>{Object.defineProperty(Ce,"__esModule",{value:!0});Ce.loadToken=Yu;var xn=Fu(require("fs")),Ju=L();function Fu(e){return e&&e.__esModule?e:{default:e}}function Yu(){let e=(0,Ju.getTokenPath)();if(!xn.default.existsSync(e))return null;try{return JSON.parse(xn.default.readFileSync(e,"utf-8"))}catch{return null}}});var tt=o((et)=>{Object.defineProperty(et,"__esModule",{value:!0});et.saveToken=Xu;var xe=eo(require("fs")),$u=eo(require("path")),Zu=L();function eo(e){return e&&e.__esModule?e:{default:e}}function Xu(e){let t=(0,Zu.getTokenPath)(),r=$u.default.dirname(t);if(!xe.default.existsSync(r))xe.default.mkdirSync(r,{recursive:!0});xe.default.writeFileSync(t,JSON.stringify(e,null,2),{mode:384})}});var ye=o((rt)=>{Object.defineProperty(rt,"__esModule",{value:!0});rt.refreshAccessToken=Qu;var Mu=tt();async function Qu(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,login_host:e.login_host};return(0,Mu.saveToken)(d),n.access_token}});var pt=o((it)=>{Object.defineProperty(it,"__esModule",{value:!0});it.resolveToken=Gu;var Hu=R(),Bu=ye();async function Gu(){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,Hu.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,Bu.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 nt=o((st)=>{Object.defineProperty(st,"__esModule",{value:!0});st.resolveApiDomain=Lu;var Ou=R();function Lu(){let e=process.env.CNB_API_ENDPOINT||"https://api.cnb.cool";if(process.env.CNB_TOKEN_FOR_CODEBUDDY||process.env.CNB_TOKEN)return e;let t=(0,Ou.loadToken)();if(t?.login_host)return t.login_host;return e}});var yt=o((S)=>{Object.defineProperty(S,"__esModule",{value:!0});S.SN_PATTERN=void 0;S.apiRequest=ro;S.apiRequestText=Cu;S.extractSnFromStatuses=io;S.extractSnFromUrl=at;S.invalidSnMessage=to;S.resolveBuildContext=xu;var Ru=pt(),Du=nt(),ot=S.SN_PATTERN=/^cnb-[a-z0-9]+-[a-z0-9]+$/i;function to(e){return[`参数 --sn 的值不是合法的构建号: "${e}"`,"","构建号(sn)格式应为 cnb-xxx-xxxxxxxxx,例如 cnb-9p9-1jnfh8rv5。","常见错误:把 `cnb pulls check-status` 返回的 context 字段(形如",'"cnb/pull_request/common-lint")当成 sn 传入,这是 CI 状态的检查项名,',"不是构建号。","","请去掉 --sn 参数重试,工具会自动从当前 PR 的 CI 状态中解析失败构建的 sn。"].join(`
91
91
  `)}async function ro(e,t){let r=await fetch(e,{headers:t});if(!r.ok)throw Error(`请求失败: ${r.status} ${r.statusText} — ${e}`);return r.json()}async function Cu(e,t){let r=await fetch(e,{headers:t});if(!r.ok)throw Error(`请求失败: ${r.status} ${r.statusText} — ${e}`);return r.text()}function io(e){let t=e?.statuses||e;if(!Array.isArray(t)||t.length===0)return null;let r=t.find((i)=>i.state==="error"||i.state==="failure");if(!r)return null;return at(r.target_url||"")}function at(e){if(!e)return null;let t=e.match(/\/-\/build\/logs\/([^/?#]+)/);if(t&&ot.test(t[1]))return t[1];let r=e.match(/\/-\/build\/([^/?#]+)/);if(r&&ot.test(r[1]))return r[1];return null}async function xu(e){let t=(0,Du.resolveApiDomain)(),{repo:r}=e,i=e.sn;if(i&&!ot.test(i))return{ok:!1,message:to(i)};let s={Accept:"application/vnd.cnb.api+json",Authorization:`Bearer ${await(0,Ru.resolveToken)()}`};if(!i&&e.prNumber)try{let n=`${t}/${r}/-/pulls/${e.prNumber}/commit-statuses`,a=await ro(n,s);if(i=io(a)??void 0,!i&&e.fallbackToLatestStatus){let d=a?.statuses||a;if(Array.isArray(d))for(let u of d){let l=at(u?.target_url||"");if(l){i=l;break}}}}catch(n){return{ok:!1,message:`获取 PR CI 状态失败: ${n.message}`}}if(!i){if(e.prNumber)return{ok:!1,message:e.fallbackToLatestStatus?"未从 PR CI 状态中找到任何可分析的构建。":"未从 PR CI 状态中找到失败的构建,所有构建均为成功状态。"};return{ok:!1,message:"缺少构建号(sn):未传入 --sn 且未检测到 PR 上下文(CNB_PULL_REQUEST_IID)。"}}return{ok:!0,ctx:{sn:i,domain:t,baseUrl:`${t}/${r}`,headers:s}}}});var po=o((ct)=>{Object.defineProperty(ct,"__esModule",{value:!0});ct.diagnoseBuild=tg;var ce=yt();async function eg(e,t,r){let i=await(0,ce.apiRequestText)(`${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 tg(e){let t=await(0,ce.resolveBuildContext)(e);if(!t.ok)return t.message;let{sn:r,baseUrl:i,headers:p}=t.ctx,s=[];s.push(`查询构建 sn=${r} 的流水线状态...
92
92
  `);let n;try{n=await(0,ce.apiRequest)(`${i}/-/build/status/${r}`,p)}catch(u){return`获取构建状态失败: ${u.message}`}if(!n.pipelinesStatus||typeof n.pipelinesStatus!=="object")return s.push("未找到流水线状态信息"),s.push("返回数据:"),s.push(JSON.stringify(n,null,2)),s.join(`
93
93
  `);let a=Object.entries(n.pipelinesStatus);if(a.length===0)return"该构建没有流水线";let d=!1;for(let[u,l]of a){let{id:g,status:_,stages:h}=l;if(!Array.isArray(h))continue;let f=h.filter((m)=>m.status==="error");if(f.length===0)continue;d=!0,s.push(`━━━ 流水线: ${u} (status: ${_}) ━━━
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnbcool/cnb-cli",
3
- "version": "1.6.2",
3
+ "version": "1.6.3",
4
4
  "description": "CNB OpenAPI 命令行工具,基于 CNB 平台 Swagger 自动生成,支持 Issues、PR、Git、组织管理等全部 API 操作",
5
5
  "main": "skills/cnb-api/scripts/core/index.js",
6
6
  "bin": {
@@ -42,7 +42,7 @@
42
42
  "author": "",
43
43
  "license": "MIT",
44
44
  "devDependencies": {
45
- "@cnbcool/cnb-api-generate": "^2.4.6",
45
+ "@cnbcool/cnb-api-generate": "^2.4.7",
46
46
  "bun": "^1.3.9",
47
47
  "skills": "^1.4.4"
48
48
  }