@jerryc05/hi-tools 0.2.10 → 0.2.11

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 +13 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,22 +1,22 @@
1
1
  #!/usr/bin/env node
2
- typeof globalThis.CustomEvent>"u"&&(globalThis.CustomEvent=class extends Event{constructor(t,n={}){super(t,n),this.detail=n.detail}});import{readFile as Me}from"node:fs/promises";import{join as qe}from"node:path";import{intro as Xe}from"@clack/prompts";import We from"yargs";import{hideBin as Ke}from"yargs/helpers";import{networkInterfaces as me}from"node:os";function E(e){let t=me(),n={};for(let[r,i]of Object.entries(t))i=i?.filter(s=>e?.["only-ipv4"]?s.family==="IPv4":e?.["only-ipv6"]?s.family==="IPv6":!(s.family==="IPv6"&&le(s.address))),i?.length&&(n[r]=i);return n}function le(e){let t=e.toLowerCase().split("%")[0];return/^fe[89ab][0-9a-f](?::|$)/i.test(t??"")}var ue={"only-ipv4":{alias:"4",desc:"IPv4 only",boolean:!0},"only-ipv6":{alias:"6",desc:"IPv6 only",boolean:!0}},O=[{command:"ips",describe:"Show current machine's IP addrs",builder:ue,handler(e){let t=E(e),n={};for(let[r,i]of Object.entries(t))i&&(n[r]=e.verbose?i:i.map(s=>s.address));console.log(t)}}];import{hostname as de}from"node:os";var j=[{command:"mdns",describe:"Show mdns [hostname].local",handler(){let e=de();console.log(e.toLowerCase().endsWith(".local")?e:`${e}.local`)}}];import{spinner as fe}from"@clack/prompts";async function T(){let{execa:e}=await import("execa");try{let{stdout:t}=await e`git rev-parse --abbrev-ref --symbolic-full-name @{u}`;return t.split("/")[0]||"origin"}catch{return"origin"}}async function L({updBranch:e,branch:t,verbose:n}){let r=fe();r.start(`${e?"Updating":"Fetching"} ${t}...`);let{execa:i}=await import("execa");await i({stdio:"inherit",env:n?{GIT_TRACE:"1"}:{}})`git fetch ${await T()} ${t}${e?`:${t}`:""}`,r.message("Merging ..."),await i({stdio:"inherit",env:n?{GIT_TRACE:"1"}:{}})`git merge ${await T()}/${t} --no-verify --no-edit ${n?"":"-q"}`,r.stop("Done")}var k={branch:{alias:"b",default:"master",desc:'Default=master, or "main" if you wish'}},J=[{command:"mm",describe:"[M]erge [M]aster: Update local master to remote's, then merge into current branch",builder:k,handler(e){let{branch:t=k.branch.default,verbose:n}=e;L({updBranch:!0,branch:t,verbose:n})}},{command:"mmm",describe:"[M]erge [M]aster (don't [M]odify local master): Merge remote's master into current branch, without updating local master",builder:k,async handler(e){let{branch:t=k.branch.default,verbose:n}=e;await L({updBranch:!1,branch:t,verbose:n})}}];import{log as ge,spinner as be}from"@clack/prompts";var U=[{command:"tschk",describe:"My ts-check rules",handler:async()=>{let e=!0,{execa:t}=await import("execa");{let n=be();n.start("Running custom ts type-check...");let r="";try{({stdout:r}=await t({reject:!1,stderr:"ignore"})`pnpm --quiet exec tsgo --build --noEmit`)}catch(a){if(a.code!=="ENOENT")throw a;({stdout:r}=await t({reject:!1,stderr:"ignore"})`pnpm --quiet exec tsc --build --noEmit`)}let i=["2322","2551","6133","6192","18048"],s=/5\d\d\d/,o=r.split(`
3
- `).filter(a=>{if(a.includes("/node_modules/"))return!1;let c=a.match(/error TS(\d+):/);return!(!c?.[1]||i.includes(c[1])||s.test(c[1]))});o.length>0?(o.map(a=>ge.error(a)),n.stop("Type-check failed"),e=!1):n.stop("Type-check passed")}process.exit(e?0:1)}}];var G=[{command:"bam",describe:"Update BAM code-gen",handler:async()=>{let{execa:e}=await import("execa");await e({stdio:"inherit"})`pnpm dlx @byted-arch-fe/bam-code-generator update`}}];import{cancel as q,isCancel as X,log as h,note as W,select as K}from"@clack/prompts";import u from"picocolors";var H="https://bits.bytedance.net";async function D(e,t,n,r){let i={...e,pageNum:e.pageNum??1},s=`${H}/api/v1/pipelines/runs?${new URLSearchParams(i).toString()}`,o=await fetch(s,{method:"GET",headers:{"Content-Type":"application/json","X-jwt-token":t,Username:n.username},signal:r??null});return{response:o,getJson:async()=>await o.json()}}async function F(e,t,n){let r=`${H}/api/v1/pipelines/runs/${e}`,i=await fetch(r,{method:"GET",headers:{"Content-Type":"application/json","X-jwt-token":t,Username:n.username}});return{response:i,getJson:async()=>await i.json()}}var w={RUNNING:2,CANCELLED:7,SUCCESS:8,FAIL:9};function I(e){let t=new Date(e),n=new Intl.DateTimeFormat("en-US",{timeZoneName:"longOffset"}).formatToParts(t).find(r=>r.type==="timeZoneName")?.value.replace("GMT","");return`${t.toLocaleDateString("zh-CN")} ${t.toTimeString().split(" ")[0]} ${n??""}`}import{log as ye,spinner as he}from"@clack/prompts";import B from"picocolors";var v;async function M(){let e=he();if(e.start("Logging in..."),!v){let{AIPaaSAuth:r}=await import("@byted/aipaas-auth");v=new r("cn")}let t=await v.getJwt(),n=await v.getUserInfo();return e.stop(`Hi ${B.magenta(n.username)} from ${B.blue(`${n.scope} ${n.work_country}`)}`),ye.info(`Login will expire on ${I(n.exp*1e3)}`),{jwtStr:t,jwtObj:n}}async function we({pipelineId:e,url:t,region:n,verbose:r}){let{jwtStr:i,jwtObj:s}=await M(),o=(()=>{if(e==null&&!t)throw new Error("pipelineId or url is required");return e??Z(t??"")})(),a=await V(o,i,s,n);if(a.length<=0){h.error(`No Gecko info found${n?` matching region [${n}]`:""} in latest run`);return}let{default:c}=await import("qrcode");for(let p=0;p<a.length;p++){let m=a[p];try{let l=await c.toString(m?.qrCodeScheme??"",{type:"terminal",small:!0,errorCorrectionLevel:"L"});console.log(`
2
+ typeof globalThis.CustomEvent>"u"&&(globalThis.CustomEvent=class extends Event{constructor(t,n={}){super(t,n),this.detail=n.detail}});import{readFile as Me}from"node:fs/promises";import{join as qe}from"node:path";import{intro as Xe}from"@clack/prompts";import We from"yargs";import{hideBin as Ke}from"yargs/helpers";import{networkInterfaces as pe}from"node:os";function P(e){let t=pe(),n={};for(let[r,i]of Object.entries(t))i=i?.filter(s=>e?.["only-ipv4"]?s.family==="IPv4":e?.["only-ipv6"]?s.family==="IPv6":!(s.family==="IPv6"&&me(s.address))),i?.length&&(n[r]=i);return n}function me(e){let t=e.toLowerCase().split("%")[0];return/^fe[89ab][0-9a-f](?::|$)/i.test(t??"")}var le={"only-ipv4":{alias:"4",desc:"IPv4 only",boolean:!0},"only-ipv6":{alias:"6",desc:"IPv6 only",boolean:!0}},N=[{command:"ips",describe:"Show current machine's IP addrs",builder:le,handler(e){let t=P(e),n={};for(let[r,i]of Object.entries(t))i&&(n[r]=e.verbose?i:i.map(s=>s.address));console.log(t)}}];import{hostname as ue}from"node:os";var O=[{command:"mdns",describe:"Show mdns [hostname].local",handler(){let e=ue();console.log(e.toLowerCase().endsWith(".local")?e:`${e}.local`)}}];import{spinner as de}from"@clack/prompts";async function j(){let{execa:e}=await import("execa");try{let{stdout:t}=await e`git rev-parse --abbrev-ref --symbolic-full-name @{u}`;return t.split("/")[0]||"origin"}catch{return"origin"}}async function T({updBranch:e,branch:t,verbose:n}){let r=de();r.start(`${e?"Updating":"Fetching"} ${t}...`);let{execa:i}=await import("execa");await i({stdio:"inherit",env:n?{GIT_TRACE:"1"}:{}})`git fetch ${await j()} ${t}${e?`:${t}`:""}`,r.message("Merging ..."),await i({stdio:"inherit",env:n?{GIT_TRACE:"1"}:{}})`git merge ${await j()}/${t} --no-verify --no-edit ${n?"":"-q"}`,r.stop("Done")}var k={branch:{alias:"b",default:"master",desc:'Default=master, or "main" if you wish'}},L=[{command:"mm",describe:"[M]erge [M]aster: Update local master to remote's, then merge into current branch",builder:k,handler(e){let{branch:t=k.branch.default,verbose:n}=e;T({updBranch:!0,branch:t,verbose:n})}},{command:"mmm",describe:"[M]erge [M]aster (don't [M]odify local master): Merge remote's master into current branch, without updating local master",builder:k,async handler(e){let{branch:t=k.branch.default,verbose:n}=e;await T({updBranch:!1,branch:t,verbose:n})}}];import{log as fe,spinner as ge}from"@clack/prompts";var J=[{command:"tschk",describe:"My ts-check rules",handler:async()=>{let e=!0,{execa:t}=await import("execa");{let n=ge();n.start("Running custom ts type-check...");let r="";try{({stdout:r}=await t({reject:!1,stderr:"ignore"})`pnpm --quiet exec tsgo --build --noEmit`)}catch(a){if(a.code!=="ENOENT")throw a;({stdout:r}=await t({reject:!1,stderr:"ignore"})`pnpm --quiet exec tsc --build --noEmit`)}let i=["2322","2551","6133","6192","18048"],s=/5\d\d\d/,o=r.split(`
3
+ `).filter(a=>{if(a.includes("/node_modules/"))return!1;let c=a.match(/error TS(\d+):/);return!(!c?.[1]||i.includes(c[1])||s.test(c[1]))});o.length>0?(o.map(a=>fe.error(a)),n.stop("Type-check failed"),e=!1):n.stop("Type-check passed")}process.exit(e?0:1)}}];var U=[{command:"bam",describe:"Update BAM code-gen",handler:async()=>{let{execa:e}=await import("execa");await e({stdio:"inherit"})`pnpm dlx @byted-arch-fe/bam-code-generator update`}}];import{cancel as M,isCancel as q,log as h,note as X,select as W}from"@clack/prompts";import d from"picocolors";var G="https://bits.bytedance.net";async function E(e,t,n,r){let i={...e,pageNum:e.pageNum??1},s=`${G}/api/v1/pipelines/runs?${new URLSearchParams(i).toString()}`,o=await fetch(s,{method:"GET",headers:{"Content-Type":"application/json","X-jwt-token":t,Username:n.username},signal:r??null});return{response:o,getJson:async()=>await o.json()}}async function H(e,t,n){let r=`${G}/api/v1/pipelines/runs/${e}`,i=await fetch(r,{method:"GET",headers:{"Content-Type":"application/json","X-jwt-token":t,Username:n.username}});return{response:i,getJson:async()=>await i.json()}}var w={RUNNING:2,CANCELLED:7,SUCCESS:8,FAIL:9};function I(e){let t=new Date(e),n=new Intl.DateTimeFormat("en-US",{timeZoneName:"longOffset"}).formatToParts(t).find(r=>r.type==="timeZoneName")?.value.replace("GMT","");return`${t.toLocaleDateString("zh-CN")} ${t.toTimeString().split(" ")[0]} ${n??""}`}import{log as be,spinner as ye}from"@clack/prompts";import F from"picocolors";var v;async function B(){let e=ye();if(e.start("Logging in..."),!v){let{AIPaaSAuth:r}=await import("@byted/aipaas-auth");v=new r("cn")}let t=await v.getJwt(),n=await v.getUserInfo();return e.stop(`Hi ${F.magenta(n.username)} from ${F.blue(`${n.scope} ${n.work_country}`)}`),be.info(`Login will expire on ${I(n.exp*1e3)}`),{jwtStr:t,jwtObj:n}}async function he({pipelineId:e,url:t,region:n,verbose:r}){let{jwtStr:i,jwtObj:s}=await B(),o=(()=>{if(e==null&&!t)throw new Error("pipelineId or url is required");return e??Q(t??"")})(),a=await z(o,i,s,n);if(a.length<=0){h.error(`No Gecko info found${n?` matching region [${n}]`:""} in latest run`);return}let{default:c}=await import("qrcode");for(let p=0;p<a.length;p++){let m=a[p];try{let l=await c.toString(m?.qrCodeScheme??"",{type:"terminal",small:!0,errorCorrectionLevel:"L"});console.log(`
4
4
 
5
5
  ${l}`),console.dir(m),p<a.length-1&&console.log(`
6
6
 
7
7
  -----------------
8
8
 
9
- `)}catch(l){console.error("Failed to generate QR:",l)}}}var Ie={url:{alias:"u",desc:"Bits URL",string:!0,conflicts:["pipeline-id"]},"pipeline-id":{alias:"p",desc:"Pipeline ID (Overrides URL)",string:!0,conflicts:["url"]},region:{alias:"r",desc:"String-match based region filter",string:!0}},z=[{command:"gecko",describe:"Show gecko info by bits URL",builder:e=>e.options(Ie).example("$0 tt-gecko -r us -u 'https://b??.net/devops/??/develop/detail/??/flow?devops_space_type=server_fe&pipelineId=1139212901634&stage=dev_gatekeeper_stage'","Example of URL mode, filtering us region"),handler(e){let{url:t,pipelineId:n,region:r,verbose:i}=e;we({url:t,pipelineId:n,region:r,verbose:i})}}];async function V(e,t,n,r){let{response:i,getJson:s}=await D({pipelineId:e,pageSize:1,withoutJob:!1},t,n);i.ok||(h.error(`[getRunInfoByPipelineID] failed: ${i.status} ${i.statusText}
10
- ${await i.text()}`),process.exit(1));let o=await s();o.pipelineRuns[0]?.runStatus!==w.SUCCESS&&h.warn(`Latest run (runId=${o.pipelineRuns[0]?.runId}) status=${Y(o.pipelineRuns[0]?.runStatus)}. Gecko info may be unavailable.`);let a=Q(o.pipelineRuns,r);if(a.length)return a;let c=await $e(e,o.pipelineRuns);if(c)return V(c,t,n,r);let p=await Re(e,t,n);return await xe(p,t,n)}function Q(e,t){return e.flatMap(n=>n.jobs.map(r=>{try{let i=r.jobAtom.output;if(!i)return null;let s=i.GECKO_packageInfo;if(!s)return null;let o=i.GECKO_region;if(t&&!o?.includes(t))return null;let a=JSON.parse(s),{qrCodeScheme:c,candidatePackage:p,channel:m,updatedAt:l,creator:g,distributeRule:d}=a.package,{scmVersion:_}=p,P=I(Number.parseInt(l,10)*1e3),ce=d.envLaneList.flatMap(pe=>pe.values);return{qrCodeScheme:c,region:o,scmVersion:_,channel:m,updatedDate:P,creator:g,envs:ce,runId:n.runId,runSeq:n.runSeq}}catch(i){return console.error(i),null}}).filter(r=>r!=null)).filter(n=>!!n)}async function $e(e,t){let n=t.flatMap(s=>s.jobs.map(o=>o.jobAtom.inputs?.trigger_params).filter(o=>!!o).filter(o=>o.detail_url.length));if(!n.length)return;W(`Found ${n.length} possible alternative pipeline(s) you may want to try instead.`,"Mistyped the pipeline ID?");let r=[{value:"",label:`(Keep current pipeline id=${e})`}].concat(n.map(s=>({value:Z(s.detail_url),label:`${u.underline(s.development_task_name)} by ${s.developer.join(",")}`,hint:s.detail_url}))),i=await K({message:"Select a pipeline to change, or cancel [ESC] to use the current pipeline.",options:r});if(X(i)||!i){q("Keep using current pipeline");return}return h.success(`Using new pipeline id=${i}`),i}async function Re(e,t,n){let{response:i,getJson:s}=await D({pipelineId:e,pageSize:10,withoutJob:!0},t,n);i.ok||(h.error(`[getRunInfoByPipelineID] failed: ${i.status} ${i.statusText}
9
+ `)}catch(l){console.error("Failed to generate QR:",l)}}}var we={url:{alias:"u",desc:"Bits URL",string:!0,conflicts:["pipeline-id"]},"pipeline-id":{alias:"p",desc:"Pipeline ID (Overrides URL)",string:!0,conflicts:["url"]},region:{alias:"r",desc:"String-match based region filter",string:!0}},K=[{command:"gecko",describe:"Show gecko info by bits URL",builder:e=>e.options(we).example("$0 tt-gecko -r us -u 'https://b??.net/devops/??/develop/detail/??/flow?devops_space_type=server_fe&pipelineId=1139212901634&stage=dev_gatekeeper_stage'","Example of URL mode, filtering us region"),handler(e){let{url:t,pipelineId:n,region:r,verbose:i}=e;he({url:t,pipelineId:n,region:r,verbose:i})}}];async function z(e,t,n,r){let{response:i,getJson:s}=await E({pipelineId:e,pageSize:1,withoutJob:!1},t,n);i.ok||(h.error(`[getRunInfoByPipelineID] failed: ${i.status} ${i.statusText}
10
+ ${await i.text()}`),process.exit(1));let o=await s();o.pipelineRuns[0]?.runStatus!==w.SUCCESS&&h.warn(`Latest run (runId=${o.pipelineRuns[0]?.runId}) status=${Z(o.pipelineRuns[0]?.runStatus)}. Gecko info may be unavailable.`);let a=V(o.pipelineRuns,r);if(a.length)return a;let c=await Ie(e,o.pipelineRuns);if(c)return z(c,t,n,r);let p=await $e(e,t,n);return await Re(p,t,n)}function V(e,t){return e.flatMap(n=>n.jobs.map(r=>{try{let i=r.jobAtom.output;if(!i)return null;let s=i.GECKO_packageInfo;if(!s)return null;let o=i.GECKO_region;if(t&&!o?.includes(t))return null;let a=JSON.parse(s),{qrCodeScheme:c,candidatePackage:p,channel:m,updatedAt:l,creator:g,distributeRule:f}=a.package,{scmVersion:S}=p,_=I(Number.parseInt(l,10)*1e3),ae=f.envLaneList.flatMap(ce=>ce.values);return{qrCodeScheme:c,region:o,scmVersion:S,channel:m,updatedDate:_,creator:g,envs:ae,runId:n.runId,runSeq:n.runSeq}}catch(i){return console.error(i),null}}).filter(r=>r!=null)).filter(n=>!!n)}async function Ie(e,t){let n=t.flatMap(s=>s.jobs.map(o=>o.jobAtom.inputs?.trigger_params).filter(o=>!!o).filter(o=>o.detail_url.length));if(!n.length)return;X(`Found ${n.length} possible alternative pipeline(s) you may want to try instead.`,"Mistyped the pipeline ID?");let r=[{value:"",label:`(Keep current pipeline id=${e})`}].concat(n.map(s=>({value:Q(s.detail_url),label:`${d.underline(s.development_task_name)} by ${s.developer.join(",")}`,hint:s.detail_url}))),i=await W({message:"Select a pipeline to change, or cancel [ESC] to use the current pipeline.",options:r});if(q(i)||!i){M("Keep using current pipeline");return}return h.success(`Using new pipeline id=${i}`),i}async function $e(e,t,n){let{response:i,getJson:s}=await E({pipelineId:e,pageSize:10,withoutJob:!0},t,n);i.ok||(h.error(`[getRunInfoByPipelineID] failed: ${i.status} ${i.statusText}
11
11
  ${await i.text()}`),process.exit(1));let o=await s();o.pipelineRuns.length<=0&&(h.error(`No pipeline runs found in the most recent 10 runs
12
- ${JSON.stringify(o,null,1)}`),process.exit(1)),W("The latest pipeline run may be ongoing/failed. Try a previous run to inspect.","Select a previous run");let a=o.pipelineRuns.map(p=>{let m=Y(p.runStatus),l=ke(p),g=p.triggerInfo?.triggeredBy||p.createdBy||"?";return{value:p.runId,label:`#${p.runSeq} runId=${p.runId} ${m}`,hint:`${l} by ${g}`}}),c=await K({message:"Select the run ID to inspect",options:a});return X(c)&&(q("Run selection cancelled"),process.exit(0)),c}async function xe(e,t,n){let{response:r,getJson:i}=await F(e,t,n);r.ok||(h.error(`[getRunDetailByRunID] failed: ${r.status} ${r.statusText}
13
- ${await r.text()}`),process.exit(1));let s=await i();return Q([s.pipelineRun])}function Z(e){let t=/\bpipelineId=(\d+)\b/,r=e.match(t)?.[1]?.trim();if(r){if(!/^\d+$/.test(r))throw new Error("Invalid pipelineId query from URL. Expecting a pipelineId query value with all numbers");return r}throw new Error(`Invalid URL. Expecting a url containing ${u.bold(u.yellow("pipelineId"))} query param. E.g. `+u.underline(u.gray(`https://b??.net/devops/??/develop/detail/??/flow?devops_space_type=server_fe&${u.bold(u.magenta("pipelineId=1139212901634"))}&stage=dev_gatekeeper_stage`)))}function Y(e){switch(e){case w.RUNNING:return u.blue("RUNNING");case w.CANCELLED:return u.gray("CANCELLED");case w.SUCCESS:return u.green("SUCCESS");case w.FAIL:return u.red("FAIL")}return`status=${e}`}function ke(e){return e.startedAt?`started @ ${I(e.startedAt)}`:e.createdAt?`created @ ${I(e.createdAt)}`:"time=?"}import{access as ve,constants as Ce}from"node:fs/promises";async function ee(e){let t=[".js",".cjs",".mjs"].map(n=>`${e}${n}`);for(let n of t)try{return await ve(n,Ce.R_OK),n}catch{}console.error(`tt i18n: Failed to read one of ${t.join(", ")}`),process.exit(1)}var te=[{command:"i18n",describe:"I18n scan and sort",handler:async()=>{let[e,t]=await Promise.all([ee("starling.config"),ee("combine-lang")]),{execa:n,execaNode:r}=await import("execa");await n({stdio:"inherit"})`pnpm dlx @ies/starling-cli scan -c ${e} --fallback --disable-browser`,await r({stdio:"inherit"})`${t}`,await n({stdio:"inherit"})`pnpm --package=json-sort-cli dlx sortjson ./src/lang`.catch(i=>console.error("tt i18n sortjson error:",i))}}];import{log as $,note as Ee}from"@clack/prompts";import{lstat as Se,readFile as _e}from"node:fs/promises";import{join as Pe}from"node:path";async function C(){let e=Pe(process.cwd(),"./package.json");return(await Se(e)).isFile()?JSON.parse(await _e(e,"utf8")):null}async function De({repoId:e,hash:t,branch:n}){let r=await C();r||($.error(`Failed to get package.json at ${process.cwd()}`),process.exit(1));let i="SCM_USERNAME",s="SCM_PASSWORD",o=process.env[i],a=process.env[s];(!o||!a)&&($.error(`Missing ${o?s:i} in env var.
14
- Go to https://luban.bytedance.net/npm/publish and get your personal SCM username & password.`),process.exit(1));let{execa:c}=await import("execa");try{let p=c`git log -1 --pretty=%s`,m,l;n==null?t?m=t:m=(await c`git rev-parse HEAD`).stdout.trim():n?l=n:l=(await c`git branch --show-current`).stdout.trim();let g={repos:e,create_user:o,desc:`v${r?.version}: ${(await p).stdout.trim()}`,has_version_stage:!1,version:r?.version,...m?{pub_base:"commit_base",base_commit_hash:m}:{pub_base:"branch_base",branch_name:l}};Ee(`${g.create_user} is publishing ${r?.name}@${r?.version} to repoId=${g.repos}
15
- ${m?`hash: ${m}`:`brch: ${l}`}`);let d=await fetch("https://scm.byted.org/api/v2/npm_versions/",{method:"POST",headers:{Authorization:`Basic ${Buffer.from(`${o}:${a}`).toString("base64")}`,Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(g)});if(!d.ok){let P=await d.text();$.error(`HTTP ${d.status} Error: ${P}`),process.exit(1)}let _=await d.text();$.success(`\u{1F389} Successfully published: ${_}`)}catch(p){$.error("Execution Failed:"),console.error(p),process.exit(1)}}var Ae={"by-hash":{alias:"h",desc:"Publish pkg by hash (default)",string:!0,conflicts:["by-branch"]},"by-branch":{alias:"b",desc:"Publish pkg by branch",string:!0,conflicts:["by-hash"]}},ne=[{command:"luban <repoId>",describe:"Publish current repo pkg to Luban",builder:e=>e.options(Ae).example("$0 tt luban 1234","Example of hash mode (current commit)").example("$0 tt luban 1234 --by-hash 123321","Example of hash mode (commit hash: 123321)").example("$0 tt luban 1234 --by-branch master","Example of branch mode (master branch)"),async handler(e){let{byHash:t,byBranch:n}=e,r=Number(e.repoId);await De({repoId:r,hash:t,branch:n})}}];import{unlink as Ne}from"node:fs/promises";import{join as Oe}from"node:path";import{log as re,note as je}from"@clack/prompts";import oe from"picocolors";import R from"base62";var b;(a=>{let e=0;a.RAX_WEBPAGE="/",a.RAX_CONNECT=`/${R.encode(e++)}`,a.RAX_DEVICE_INFO=`/${R.encode(e++)}`,a.RAX_CHANGE_ACCOUNT=`/${R.encode(e++)}`,a.RAX_SCRSHOT=`/${R.encode(e++)}`,a.RAX_OPEN_SCHEMA=`/${R.encode(e++)}`})(b||={});var x=["pnpm","dlx","--silent","--allow-build=better-sqlite3","--allow-build=sharp","@tiktok-fe/rax-cli@>=0.3.28"];async function Te(e){let{execa:t}=await import("execa"),{default:n}=await import("express"),r=n();r.use(n.json()),r.get(b.RAX_WEBPAGE,(s,o)=>{o.sendFile(Oe(import.meta.dirname,"index.html"))}),r.post(b.RAX_CONNECT,async(s,o)=>{throw new Error("unimplemented")}),r.get(b.RAX_DEVICE_INFO,async(s,o)=>{let{stdout:a}=await t`${x} device info`;if(a.trim().startsWith("Error:")){o.status(400).send(a);return}let c=JSON.parse(a);delete c.appInfo.appInfo.appIconBase64,delete c.appInfo.appSettings.language;let{account:p}=c.appInfo.appSettings;p.current={customID:p.current.customID,nickname:p.current.nickname,userID:p.current.userID};for(let m=0;m<(p.loginAccountList?.length??0);m++){if(!p.loginAccountList)continue;let l=p.loginAccountList[m];l&&(p.loginAccountList[m]={customID:l.customID,nickname:l.nickname,userID:l.userID})}o.json(c)}),r.post(b.RAX_CHANGE_ACCOUNT,async(s,o)=>{let{userID:a}=s.body;if(!a){o.sendStatus(400);return}let{stdout:c}=await t`${x} app account change ${a} --json`,p=JSON.parse(c).content?.[0]?.text;o.type("json").send(p)}),r.get(b.RAX_SCRSHOT,async(s,o)=>{let{execa:a}=await import("execa"),{default:c}=await import("sharp"),{temporaryFile:p}=await import("tempy"),m=p({extension:"png"}),{stdout:l,stderr:g}=await a`${x} device screenshot --output ${m}`;if(l.trim().includes("Cannot screenshot")||l.trim().includes("no available device")){o.status(404).send(l);return}let d=p({extension:"webp"});await c(m).webp({quality:70,effort:5,smartSubsample:!0}).toFile(d),Ne(m).catch(),o.sendFile(d)}),r.post(b.RAX_OPEN_SCHEMA,async(s,o)=>{let{execa:a}=await import("execa"),{schema:c}=s.body,{stdout:p}=await a`${x} device open-schema ${c}`;o.send(p)});let i=r.listen(e.port??0,()=>{let s=i.address(),o=typeof s!="string"?s?.port:void 0;o||(re.error(`Failed to get port from addr [${s}]`),process.exit(1));let a=Object.values(E()??{"":["localhost"]}).flat().sort((c,p)=>c.internal&&!p.internal?-1:!c.internal&&p.internal?1:c.family==="IPv4"&&p.family==="IPv6"?-1:c.family==="IPv6"&&p.family==="IPv4"?1:c.address.localeCompare(p.address)).map(c=>` ${c.internal?oe.green("[LOCAL]"):oe.yellow("[ LAN ]")} http://${c.family==="IPv6"?`[${c.address}]`:c.address}:${o}
16
- `);je(`Server running at
17
- ${a.join("")}`),re.info(`\u{1F680} Try ${a[0]}`)})}var Le={port:{alias:"p",desc:"Port for helper",number:!0}},ie=[{command:"rax",describe:"Start rax helper (web)",builder:Le,handler:Te}];var se=[{command:"tt",describe:"TT/BD internal toolset",builder:e=>e.command([...G,...z,...te,...ne,...ie]).demandCommand(1),handler(){}}];import{lstatSync as Je}from"node:fs";import{log as f,note as Ue,spinner as S}from"@clack/prompts";import Ge from"string-argv";import y from"node:process";var He=e=>new Promise(t=>setTimeout(t,e)),Fe=1e4;async function Be(e){let t=await C();t||(f.error(`Failed to get package.json at ${y.cwd()}`),y.exit(1));let n=t.version,r=`${t.name}@${n}`,i=[...Ge(e.installCmdPrefix),r];Ue(`\u{1F680} Monitoring ${r}...
12
+ ${JSON.stringify(o,null,1)}`),process.exit(1)),X("The latest pipeline run may be ongoing/failed. Try a previous run to inspect.","Select a previous run");let a=o.pipelineRuns.map(p=>{let m=Z(p.runStatus),l=xe(p),g=p.triggerInfo?.triggeredBy||p.createdBy||"?";return{value:p.runId,label:`#${p.runSeq} runId=${p.runId} ${m}`,hint:`${l} by ${g}`}}),c=await W({message:"Select the run ID to inspect",options:a});return q(c)&&(M("Run selection cancelled"),process.exit(0)),c}async function Re(e,t,n){let{response:r,getJson:i}=await H(e,t,n);r.ok||(h.error(`[getRunDetailByRunID] failed: ${r.status} ${r.statusText}
13
+ ${await r.text()}`),process.exit(1));let s=await i();return V([s.pipelineRun])}function Q(e){let t=/\bpipelineId=(\d+)\b/,r=e.match(t)?.[1]?.trim();if(r){if(!/^\d+$/.test(r))throw new Error("Invalid pipelineId query from URL. Expecting a pipelineId query value with all numbers");return r}throw new Error(`Invalid URL. Expecting a url containing ${d.bold(d.yellow("pipelineId"))} query param. E.g. `+d.underline(d.gray(`https://b??.net/devops/??/develop/detail/??/flow?devops_space_type=server_fe&${d.bold(d.magenta("pipelineId=1139212901634"))}&stage=dev_gatekeeper_stage`)))}function Z(e){switch(e){case w.RUNNING:return d.blue("RUNNING");case w.CANCELLED:return d.gray("CANCELLED");case w.SUCCESS:return d.green("SUCCESS");case w.FAIL:return d.red("FAIL")}return`status=${e}`}function xe(e){return e.startedAt?`started @ ${I(e.startedAt)}`:e.createdAt?`created @ ${I(e.createdAt)}`:"time=?"}import{access as ke,constants as ve}from"node:fs/promises";async function Y(e){let t=[".js",".cjs",".mjs"].map(n=>`${e}${n}`);for(let n of t)try{return await ke(n,ve.R_OK),n}catch{}console.error(`tt i18n: Failed to read one of ${t.join(", ")}`),process.exit(1)}var ee=[{command:"i18n",describe:"I18n scan and sort",handler:async()=>{let[e,t]=await Promise.all([Y("starling.config"),Y("combine-lang")]),{execa:n,execaNode:r}=await import("execa");await n({stdio:"inherit"})`pnpm dlx @ies/starling-cli scan -c ${e} --fallback --disable-browser`,await r({stdio:"inherit"})`${t}`,await n({stdio:"inherit"})`pnpm --package=json-sort-cli dlx sortjson ./src/lang`.catch(i=>console.error("tt i18n sortjson error:",i))}}];import{log as $,note as Pe}from"@clack/prompts";import{lstat as Ce,readFile as Se}from"node:fs/promises";import{join as _e}from"node:path";async function C(){let e=_e(process.cwd(),"./package.json");return(await Ce(e)).isFile()?JSON.parse(await Se(e,"utf8")):null}async function Ee({repoId:e,hash:t,branch:n}){let r=await C();r||($.error(`Failed to get package.json at ${process.cwd()}`),process.exit(1));let i="SCM_USERNAME",s="SCM_PASSWORD",o=process.env[i],a=process.env[s];(!o||!a)&&($.error(`Missing ${o?s:i} in env var.
14
+ Go to https://luban.bytedance.net/npm/publish and get your personal SCM username & password.`),process.exit(1));let{execa:c}=await import("execa");try{let p=c`git log -1 --pretty=%s`,m,l;n==null?t?m=t:m=(await c`git rev-parse HEAD`).stdout.trim():n?l=n:l=(await c`git branch --show-current`).stdout.trim();let g={repos:e,create_user:o,desc:`v${r?.version}: ${(await p).stdout.trim()}`,has_version_stage:!1,version:r?.version,...m?{pub_base:"commit_base",base_commit_hash:m}:{pub_base:"branch_base",branch_name:l}};Pe(`${g.create_user} is publishing ${r?.name}@${r?.version} to repoId=${g.repos}
15
+ ${m?`hash: ${m}`:`brch: ${l}`}`);let f=await fetch("https://scm.byted.org/api/v2/npm_versions/",{method:"POST",headers:{Authorization:`Basic ${Buffer.from(`${o}:${a}`).toString("base64")}`,Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(g)});if(!f.ok){let _=await f.text();$.error(`HTTP ${f.status} Error: ${_}`),process.exit(1)}let S=await f.text();$.success(`\u{1F389} Successfully published: ${S}`)}catch(p){$.error("Execution Failed:"),console.error(p),process.exit(1)}}var De={"by-hash":{alias:"h",desc:"Publish pkg by hash (default)",string:!0,conflicts:["by-branch"]},"by-branch":{alias:"b",desc:"Publish pkg by branch",string:!0,conflicts:["by-hash"]}},te=[{command:"luban <repoId>",describe:"Publish current repo pkg to Luban",builder:e=>e.options(De).example("$0 tt luban 1234","Example of hash mode (current commit)").example("$0 tt luban 1234 --by-hash 123321","Example of hash mode (commit hash: 123321)").example("$0 tt luban 1234 --by-branch master","Example of branch mode (master branch)"),async handler(e){let{byHash:t,byBranch:n}=e,r=Number(e.repoId);await Ee({repoId:r,hash:t,branch:n})}}];import{unlink as Ae}from"node:fs/promises";import{join as Ne}from"node:path";import{log as ne,note as Oe}from"@clack/prompts";import re from"picocolors";import R from"base62";var b;(a=>{let e=0;a.RAX_WEBPAGE="/",a.RAX_CONNECT=`/${R.encode(e++)}`,a.RAX_DEVICE_INFO=`/${R.encode(e++)}`,a.RAX_CHANGE_ACCOUNT=`/${R.encode(e++)}`,a.RAX_SCRSHOT=`/${R.encode(e++)}`,a.RAX_OPEN_SCHEMA=`/${R.encode(e++)}`})(b||={});var x=["pnpm","dlx","--silent","--allow-build=better-sqlite3","--allow-build=sharp","@tiktok-fe/rax-cli@>=0.3.28"];async function je(e){let{execa:t}=await import("execa"),{default:n}=await import("express"),r=n();r.use(n.json()),r.get(b.RAX_WEBPAGE,(s,o)=>{o.sendFile(Ne(import.meta.dirname,"index.html"))}),r.post(b.RAX_CONNECT,async(s,o)=>{throw new Error("unimplemented")}),r.get(b.RAX_DEVICE_INFO,async(s,o)=>{let{stdout:a}=await t`${x} device info`;if(a.trim().startsWith("Error:")){o.status(400).send(a);return}let c=JSON.parse(a);delete c.appInfo.appInfo.appIconBase64,delete c.appInfo.appSettings.language;let{account:p}=c.appInfo.appSettings;p.current={customID:p.current.customID,nickname:p.current.nickname,userID:p.current.userID};for(let m=0;m<(p.loginAccountList?.length??0);m++){if(!p.loginAccountList)continue;let l=p.loginAccountList[m];l&&(p.loginAccountList[m]={customID:l.customID,nickname:l.nickname,userID:l.userID})}o.json(c)}),r.post(b.RAX_CHANGE_ACCOUNT,async(s,o)=>{let{userID:a}=s.body;if(!a){o.sendStatus(400);return}let{stdout:c}=await t`${x} app account change ${a} --json`,p=JSON.parse(c).content?.[0]?.text;o.type("json").send(p)}),r.get(b.RAX_SCRSHOT,async(s,o)=>{let{execa:a}=await import("execa"),{default:c}=await import("sharp"),{temporaryFile:p}=await import("tempy"),m=p({extension:"png"}),{stdout:l,stderr:g}=await a`${x} device screenshot --output ${m}`;if(l.trim().includes("Cannot screenshot")||l.trim().includes("no available device")){o.status(404).send(l);return}let f=p({extension:"webp"});await c(m).webp({quality:70,effort:5,smartSubsample:!0}).toFile(f),Ae(m).catch(),o.sendFile(f)}),r.post(b.RAX_OPEN_SCHEMA,async(s,o)=>{let{execa:a}=await import("execa"),{schema:c}=s.body,{stdout:p}=await a`${x} device open-schema ${c}`;o.send(p)});let i=r.listen(e.port??0,()=>{let s=i.address(),o=typeof s!="string"?s?.port:void 0;o||(ne.error(`Failed to get port from addr [${s}]`),process.exit(1));let a=Object.values(P()??{"":["localhost"]}).flat().sort((c,p)=>c.internal&&!p.internal?-1:!c.internal&&p.internal?1:c.family==="IPv4"&&p.family==="IPv6"?-1:c.family==="IPv6"&&p.family==="IPv4"?1:c.address.localeCompare(p.address)).map(c=>` ${c.internal?re.green("[LOCAL]"):re.yellow("[ LAN ]")} http://${c.family==="IPv6"?`[${c.address}]`:c.address}:${o}
16
+ `);Oe(`Server running at
17
+ ${a.join("")}`),ne.info(`\u{1F680} Try ${a[0]}`)})}var Te={port:{alias:"p",desc:"Port for helper",number:!0}},oe=[{command:"rax",describe:"Start rax helper (web)",builder:Te,handler:je}];var ie=[{command:"tt",describe:"TT/BD internal toolset",builder:e=>e.command([...U,...K,...ee,...te,...oe]).demandCommand(1),handler(){}}];import{lstatSync as Le}from"node:fs";import{log as u,note as Je,spinner as Ue}from"@clack/prompts";import Ge from"string-argv";import y from"node:process";var He=e=>new Promise(t=>setTimeout(t,e)),Fe=1e4;async function Be(e){let t=await C();t||(u.error(`Failed to get package.json at ${y.cwd()}`),y.exit(1));let n=t.version,r=`${t.name}@${n}`,i=[...Ge(e.installCmdPrefix),r];Je(`\u{1F680} Monitoring ${r}...
18
18
  \u{1F4C2} Target: ${e.target}
19
- \u{1F6E0} Install cmd: ${i.join(" ")}`);let{execa:s}=await import("execa");try{let o=S();o.start("Pulling latest changes in target repo..."),await s({cwd:e.target,stdio:"ignore"})`git pull`,o.stop("Latest commit pulled"),o=S(),o.start();let a=Date.now();for(let c=1;;c++){o.message(`Waiting for ${r}, attempt ${c}`);let{exitCode:p}=await s({reject:!1,stdio:"ignore"})`npm view ${r} version`;if(p===0){o.stop(`#${c}: ${r} is live! Found it \u2705`);try{f.info(`Installing ${r} via ${i}`),await s({cwd:e.target,stdio:"inherit"})`${i}`,f.success(`${r} installed! \u2705`);break}catch(l){f.error(`${r} was found in registry, but install command failed. Err: ${l}`),y.exit(1)}}(Date.now()-a)/1e3>=e.timeout&&(o.stop(`Didn't find ${r} in ${e.timeout} sec(s)`),y.exit(1)),await He(Fe)}if(e.skipCommit)f.info("Git-commit skipped");else{let{stdout:c}=await s({cwd:e.target})`git ls-files --others --exclude-standard`;c.trim()&&(f.error(`Target repo has untracked files. Please commit or remove them manually before running wup:
20
- ${c}`),y.exit(1)),o=S(),o.start("Committing changes..."),await s({cwd:e.target,stdio:"inherit"})`git commit -am ${`chore: upd ${r}`}`,o.stop("Committed \u2705"),o=S(),o.start("Pushing to remote..."),await s({cwd:e.target,stdio:"inherit"})`git push`,o.stop("Pushed \u2705")}f.success("\u{1F389} DONE!")}catch(o){console.error(`
21
- \u274C Task failed:`,o),y.exit(1)}}var A={target:{alias:"t",desc:"Target repository path",demandOption:!0,normalize:!0},"install-cmd-prefix":{alias:"cmd",desc:"Pkg install command prefix. Default: pnpm add",default:"pnpm add"},timeout:{desc:"Timeout checking new pkg version in sec",default:300,type:"number"},"skip-commit":{desc:"Do not commit changes",default:!1,type:"boolean"}},ae=[{command:"wup",describe:"[W]ait for pkg publish, [U]pdate target repo, and [P]ush",builder:e=>e.options(A).example('$0 wup -t "/tmp/..." --cmd "emo add"',"Install w/ eden-mono").example('$0 wup -t "/tmp/..." --cmd "rush add --make-consistent -p" --skip-commit',"Install w/ @microsoft/rush"),async handler(e){let{target:t,installCmdPrefix:n=A["install-cmd-prefix"].default,"skip-commit":r=A["skip-commit"].default,verbose:i}=e,s=Number(e.timeout);(!Number.isFinite(s)||s<=0)&&(f.error(`Timeout must be a positive number, received: ${e.timeout}`),y.exit(1));let o=`Path ${t} is not a directory.`;try{if(!t||!Je(t).isDirectory())throw new Error(o)}catch(a){f.error(`${o}. Err: ${a}`),y.exit(1)}await Be({target:t,installCmdPrefix:n,timeout:s,skipCommit:!!r,verbose:i})}}];var N=JSON.parse(await Me(qe(import.meta.dirname,"../package.json"),"utf8"));Xe(`\u{1F44B} ${N.name} v${N.version}`);var ze=[...J,...U,...ae,...O,...j,...se];We().scriptName("hi").version(N.version).option("verbose",{type:"boolean",description:"Run with verbose logging",global:!0}).strict().recommendCommands().command(ze).help().parse(Ke(process.argv));export{N as PKG};
19
+ \u{1F6E0} Install cmd: ${i.join(" ")}`);let{execa:s}=await import("execa");try{u.info("Pulling latest changes in target repo..."),await s({cwd:e.target,stdio:"ignore"})`git pull`,u.success("Latest commit pulled");let o=Ue();o.start();let a=Date.now();for(let c=1;;c++){o.message(`Waiting for ${r}, attempt ${c}`);let{exitCode:p}=await s({reject:!1,stdio:"ignore"})`npm view ${r} version`;if(p===0){o.stop(`#${c}: ${r} is live! Found it \u2705`);try{u.info(`Installing ${r} via ${i}`),await s({cwd:e.target,stdio:"inherit"})`${i}`,u.success(`${r} installed! \u2705`);break}catch(l){u.error(`${r} was found in registry, but install command failed. Err: ${l}`),y.exit(1)}}(Date.now()-a)/1e3>=e.timeout&&(o.stop(`Didn't find ${r} in ${e.timeout} sec(s)`),y.exit(1)),await He(Fe)}if(e.skipCommit)u.info("Git-commit skipped");else{let{stdout:c}=await s({cwd:e.target})`git ls-files --others --exclude-standard`;c.trim()&&(u.error(`Target repo has untracked files. Please commit or remove them manually before running wup:
20
+ ${c}`),y.exit(1)),u.info("Committing changes..."),await s({cwd:e.target,stdio:"inherit"})`git commit -am ${`chore: upd ${r}`}`,u.success("Committed \u2705"),u.info("Pushing to remote..."),await s({cwd:e.target,stdio:"inherit"})`git push`,u.success("Pushed \u2705")}u.success("\u{1F389} DONE!")}catch(o){console.error(`
21
+ \u274C Task failed:`,o),y.exit(1)}}var D={target:{alias:"t",desc:"Target repository path",demandOption:!0,normalize:!0},"install-cmd-prefix":{alias:"cmd",desc:"Pkg install command prefix. Default: pnpm add",default:"pnpm add"},timeout:{desc:"Timeout checking new pkg version in sec",default:300,type:"number"},"skip-commit":{desc:"Do not commit changes",default:!1,type:"boolean"}},se=[{command:"wup",describe:"[W]ait for pkg publish, [U]pdate target repo, and [P]ush",builder:e=>e.options(D).example('$0 wup -t "/tmp/..." --cmd "emo add"',"Install w/ eden-mono").example('$0 wup -t "/tmp/..." --cmd "rush add --make-consistent -p" --skip-commit',"Install w/ @microsoft/rush"),async handler(e){let{target:t,installCmdPrefix:n=D["install-cmd-prefix"].default,"skip-commit":r=D["skip-commit"].default,verbose:i}=e,s=Number(e.timeout);(!Number.isFinite(s)||s<=0)&&(u.error(`Timeout must be a positive number, received: ${e.timeout}`),y.exit(1));let o=`Path ${t} is not a directory.`;try{if(!t||!Le(t).isDirectory())throw new Error(o)}catch(a){u.error(`${o}. Err: ${a}`),y.exit(1)}await Be({target:t,installCmdPrefix:n,timeout:s,skipCommit:!!r,verbose:i})}}];var A=JSON.parse(await Me(qe(import.meta.dirname,"../package.json"),"utf8"));Xe(`\u{1F44B} ${A.name} v${A.version}`);var ze=[...L,...J,...se,...N,...O,...ie];We().scriptName("hi").version(A.version).option("verbose",{type:"boolean",description:"Run with verbose logging",global:!0}).strict().recommendCommands().command(ze).help().parse(Ke(process.argv));export{A as PKG};
22
22
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jerryc05/hi-tools",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "A collection of my everyday SDE tools.",
5
5
  "scripts": {
6
6
  "pub": "npm run build && export NPM_CONFIG_REGISTRY=https://registry.npmjs.org &&{ npm whoami || npm login ;} && npm publish --access public && git push",