@round2ai/r2-cli 1.0.11 → 1.0.12-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/r2-cli.js CHANGED
@@ -1,47 +1,2162 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- var Ue=Object.defineProperty;var Y=(e,t)=>()=>(e&&(t=e(e=0)),t);var V=(e,t)=>{for(var o in t)Ue(e,o,{get:t[o],enumerable:!0})};var Kt={};V(Kt,{UserInfoCard:()=>Ve});import{Box as Q,Text as E}from"ink";import{jsx as O,jsxs as _}from"react/jsx-runtime";function Ve({userInfo:e,lastLogin:t,daysSinceLogin:o}){let r=e.mobile?e.mobile.replace(/(\d{3})\d{4}(\d{4})/,"$1****$2"):"-";return _(Q,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[O(E,{bold:!0,color:"cyan",children:"\u7528\u6237\u4FE1\u606F"}),_(Q,{flexDirection:"row",marginTop:1,children:[O(Q,{width:10,children:O(E,{color:"gray",children:"\u6635\u79F0"})}),O(E,{color:"yellow",children:e.nickname})]}),_(Q,{flexDirection:"row",children:[O(Q,{width:10,children:O(E,{color:"gray",children:"\u624B\u673A\u53F7"})}),O(E,{color:"yellow",children:r})]}),t&&_(Q,{flexDirection:"column",marginTop:1,children:[_(E,{color:"gray",children:["\u6700\u540E\u767B\u5F55: ",t.toLocaleString()]}),o!==void 0&&_(E,{color:"gray",children:[" \u8DDD\u4ECA: ",o," \u5929"]})]})]})}var Yt=Y(()=>{"use strict"});var ot={};V(ot,{renderComponent:()=>oo,renderOnce:()=>Vt});import Ze from"react";import Tt from"chalk";import{render as to}from"ink";import{Writable as eo}from"node:stream";function Vt(e){let t=Tt.level;process.env.NO_COLOR||(Tt.level=3);try{let o=[],r=new eo({write(l,d,g){o.push(Buffer.from(l)),g()}});r.isTTY=!0,r.columns=process.stdout.columns||80,r.rows=process.stdout.rows||24,to(e,{stdout:r,patchConsole:!1}).unmount();let s=Buffer.concat(o).toString("utf8"),a=(s.split(/\x1B\[2J\x1B\[3J\x1B\[H/).at(-1)||s).replace(/\x1B\[\?[\d;]+[hl]/g,"").trimEnd()+`
4
- `;process.stdout.write(a)}finally{Tt.level=t}}function oo(e,t){Vt(Ze.createElement(e,t))}var rt=Y(()=>{"use strict"});var pe={};V(pe,{ShopsTable:()=>yo});import{Box as w,Text as C}from"ink";import{jsx as p,jsxs as M}from"react/jsx-runtime";function go(e){return e.map(t=>"shopName"in t?{id:t.shopId,name:t.shopName,platform:t.platform,expiresIn:t.expiresIn}:{id:t.id,name:t.name,platform:t.thirdUserId,expiresIn:t.expiresIn})}function fo({hasPlatform:e,fillWidth:t}){return M(w,{flexDirection:"row",paddingBottom:0,children:[e&&p(w,{width:Ut,children:p(C,{bold:!0,color:"white",children:"\u5E73\u53F0"})}),p(w,{width:t,children:p(C,{bold:!0,color:"white",children:"\u5E97\u94FA\u540D"})}),p(w,{width:Dt,children:p(C,{bold:!0,color:"white",children:"ID"})}),p(w,{width:$t,children:p(C,{bold:!0,color:"white",children:"\u72B6\u6001"})})]})}function ho({shop:e,hasPlatform:t,fillWidth:o}){let r=de[e.platform]??e.platform;return M(w,{flexDirection:"row",children:[t&&p(w,{width:Ut,children:p(C,{color:"cyan",children:r})}),p(w,{width:o,children:p(C,{bold:!0,children:e.name})}),p(w,{width:Dt,children:p(C,{color:"gray",children:e.id})}),p(w,{width:$t,children:p(C,{color:"green",children:"\u25CF \u6388\u6743\u4E2D"})})]})}function yo({shops:e,platform:t}){let o=go(e),r=t==="all",n=t==="all"?"\u6240\u6709\u6388\u6743\u5E97\u94FA":`${de[t]??t}\u6388\u6743\u5E97\u94FA`,s=process.stdout.columns||80,i=4,a=Dt+$t+(r?Ut:0),l=Math.max(s-i-a,20),d=a+l;return M(w,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[M(w,{flexDirection:"row",children:[p(C,{bold:!0,color:"cyan",children:n}),M(C,{color:"gray",children:[" \xB7 ",o.length," \u5BB6"]})]}),M(w,{flexDirection:"column",marginTop:1,children:[p(fo,{hasPlatform:r,fillWidth:l}),p(C,{color:"gray",children:"\u2500".repeat(d)}),o.map(g=>p(ho,{shop:g,hasPlatform:r,fillWidth:l},g.id))]})]})}var de,Ut,Dt,$t,ge=Y(()=>{"use strict";de={xianyu:"\u95F2\u9C7C",douyin:"\u6296\u97F3"},Ut=8,Dt=16,$t=10});var ye={};V(ye,{StocksTable:()=>Co});import{Box as h,Text as x}from"ink";import{jsx as u,jsxs as X}from"react/jsx-runtime";function xo({fillWidth:e}){return X(h,{flexDirection:"row",paddingBottom:0,children:[u(h,{width:jt,children:u(x,{bold:!0,color:"white",children:"ID"})}),u(h,{width:Gt,children:u(x,{bold:!0,color:"white",children:"\u7528\u6237ID"})}),u(h,{width:Bt,children:u(x,{bold:!0,color:"white",children:"\u4ED3\u5E93ID"})}),u(h,{width:e,children:u(x,{bold:!0,color:"white",children:"\u4ED3\u5E93\u540D\u79F0"})}),u(h,{width:Jt,children:u(x,{bold:!0,color:"white",children:"\u521B\u5EFA\u65F6\u95F4"})})]})}function So({stock:e,fillWidth:t}){let o=new Date(e.gmtCreate).toLocaleString("zh-CN");return X(h,{flexDirection:"row",children:[u(h,{width:jt,children:u(x,{color:"gray",children:e.id})}),u(h,{width:Gt,children:u(x,{color:"gray",children:e.userId})}),u(h,{width:Bt,children:u(x,{color:"gray",children:e.stockId})}),u(h,{width:t,children:u(x,{bold:!0,children:e.stockName})}),u(h,{width:Jt,children:u(x,{color:"gray",children:o})})]})}function Co({stocks:e}){let t=process.stdout.columns||80,o=4,r=jt+Gt+Bt+Jt,n=Math.max(t-o-r,20),s=r+n;return X(h,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[X(h,{flexDirection:"row",children:[u(x,{bold:!0,color:"cyan",children:"\u4ED3\u5E93\u5217\u8868"}),X(x,{color:"gray",children:[" \xB7 ",e.length," \u4E2A"]})]}),X(h,{flexDirection:"column",marginTop:1,children:[u(xo,{fillWidth:n}),u(x,{color:"gray",children:"\u2500".repeat(s)}),e.map(i=>u(So,{stock:i,fillWidth:n},i.id))]})]})}var jt,Gt,Bt,Jt,we=Y(()=>{"use strict";jt=6,Gt=10,Bt=10,Jt=22});import{Command as qo}from"commander";import{readFileSync as Qo}from"node:fs";import Re from"node:path";import z from"chalk";import"commander";import{Command as ne}from"commander";import f from"chalk";var G=class e extends Error{constructor(o,r,n){super(o);this.code=r;this.details=n;this.name="R2Error",Error.captureStackTrace&&Error.captureStackTrace(this,e)}code;details},v=class extends G{constructor(o,r,n){super(o,"API_ERROR",n);this.status=r;this.response=n;this.name="ApiError"}status;response},N=class extends G{constructor(o,r,n){super(o,"STORAGE_ERROR",{path:r,code:n});this.path=r;this.code=n;this.name="StorageError"}path;code},y=class extends G{constructor(t){super(t,"AUTH_ERROR"),this.name="AuthError"}},b=class extends G{constructor(o,r,n){super(o,"POLLING_ERROR",{attempts:r,timeout:n});this.attempts=r;this.timeout=n;this.name="PollingError"}attempts;timeout};async function De(e,t,o){let r=new AbortController,n=()=>r.abort();o?.addEventListener("abort",n,{once:!0});let s=setTimeout(()=>r.abort(),t);try{return await e()}catch(i){throw r.signal.aborted&&!o?.aborted?new b("\u5355\u6B21\u8F6E\u8BE2\u8BF7\u6C42\u8D85\u65F6"):i}finally{clearTimeout(s),o?.removeEventListener("abort",n)}}async function B(e,t,o){let{interval:r,timeout:n,condition:s}=t,i=Date.now(),a=0;for(;Date.now()-i<n;){if(o?.aborted)throw new b("\u8F6E\u8BE2\u88AB\u4E2D\u6B62");a++;let l=n-(Date.now()-i),d=await De(e,l,o);if(s(d,a))return d;await $e(r,o)}throw new b(`\u8F6E\u8BE2\u8D85\u65F6 (\u5DF2\u7B49\u5F85 ${Date.now()-i}ms, \u5171 ${a} \u6B21)`)}function $e(e,t){return new Promise((o,r)=>{if(t?.aborted){r(new b("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"));return}let n=()=>{clearTimeout(s),r(new b("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"))},s=setTimeout(()=>{t?.removeEventListener("abort",n),o()},e);t?.addEventListener("abort",n,{once:!0})})}import Be from"node:fs";import{fileURLToPath as Je}from"node:url";import{createRequire as qe}from"node:module";import Xt from"node:path";import{exec as Qe}from"node:child_process";import je from"node:http";var gt=class e{server=null;pages=new Map;port=0;idleTimer=null;static IDLE_TIMEOUT_MS=1e4;async start(){return this.server?this.port:new Promise((t,o)=>{this.server=je.createServer((r,n)=>this.handleRequest(r,n)),this.server.listen(0,"127.0.0.1",()=>{let r=this.server.address();typeof r=="object"&&r?(this.port=r.port,t(this.port)):o(new Error("Failed to get server address"))}),this.server.on("error",o)})}registerPage(t,o,r,n){let s=this.pages.get(t);if(s){s.qrBuffer=r,s.status="waiting",s.config=n;let i=`data: ${JSON.stringify({status:"waiting"})}
5
-
6
- `;for(let a of s.sseClients)a.write(i)}else this.pages.set(t,{html:o,qrBuffer:r,status:"waiting",sseClients:[],config:n});this.resetIdleTimer()}unregisterPage(t){let o=this.pages.get(t);if(o){for(let r of o.sseClients)r.end();o.sseClients.length=0,this.pages.delete(t),this.pages.size===0&&this.close()}}setStatus(t,o){let r=this.pages.get(t);if(!r)return;r.status=o;let n=`data: ${JSON.stringify({status:o})}
7
-
8
- `;for(let s of r.sseClients)s.write(n)}close(){if(this.server){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null);for(let t of this.pages.values()){for(let o of t.sseClients)o.end();t.sseClients.length=0}this.pages.clear(),this.server.close(),this.server=null,this.port=0,J=null}}resetIdleTimer(){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{[...this.pages.values()].some(o=>o.sseClients.length>0)||this.close()},e.IDLE_TIMEOUT_MS)}handleRequest(t,o){let r=t.url??"/";for(let[n,s]of this.pages){if(r===n){o.writeHead(302,{Location:n+"/"}),o.end();return}if(r===n+"/"){o.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),o.end(s.html);return}if(r===n+"/qr.png"){o.writeHead(200,{"Content-Type":"image/png","Content-Length":s.qrBuffer.length}),o.end(s.qrBuffer);return}if(r===n+"/events"){o.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),o.write(`data: ${JSON.stringify({status:s.status})}
9
-
10
- `),s.sseClients.push(o),t.on("close",()=>{let i=s.sseClients.indexOf(o);i>=0&&s.sseClients.splice(i,1)});return}if(r===n+"/config"){o.writeHead(200,{"Content-Type":"application/json"}),o.end(JSON.stringify(s.config??{}));return}}o.writeHead(404,{"Content-Type":"text/plain"}),o.end("Not Found")}},J=null,_t=!1;function Z(){J&&J.close()}function Ge(){_t||(_t=!0,process.on("exit",Z),process.on("SIGINT",Z),process.on("SIGTERM",Z),setInterval(()=>{process.stdin?.destroyed&&Z()},3e3).unref())}function Mt(){return J||(J=new gt,Ge()),J}var _e=Xt.dirname(Je(import.meta.url)),Me="/login",Xe="/login-xianyu",ft=null;async function Fe(e){return Be.promises.readFile(Xt.join(_e,"pages",e),"utf-8")}async function ze(e){return ft||(ft=qe(import.meta.url)),ft("qrcode").toBuffer(e,{width:300,margin:2})}function P(e){let t=process.platform==="win32"?`start "" "${e}"`:process.platform==="darwin"?`open "${e}"`:`xdg-open "${e}"`;Qe(t)}async function Ft(e,t,o,r){let[n,s]=await Promise.all([Fe(t),ze(o)]),i=Mt(),a=await i.start();i.registerPage(e,n,s,r);let l=`http://127.0.0.1:${a}${e}/`;return{url:o,qrUrl:l,setStatus:d=>i.setStatus(e,d),closeServer:()=>i.unregisterPage(e)}}function ht(e){return Ft(Me,"login.html",e)}function yt(e,t){return Ft(Xe,"xianyu-auth.html",e,{authUrl:t})}import{promises as q}from"node:fs";import wt from"node:path";import We from"node:os";var He=".r2-cli",tt=class{configPath;config;configLoaded=!1;dirEnsured=!1;constructor(){let t=We.homedir(),o=wt.join(t,He);this.configPath=wt.join(o,"config.json"),this.config={credentials:null}}getConfigPath(){return this.configPath}async loadConfig(){if(this.configLoaded)return this.config;try{let t=await q.readFile(this.configPath,"utf-8");return this.config=JSON.parse(t),this.configLoaded=!0,this.config}catch{return this.config={credentials:null},this.configLoaded=!0,this.config}}async ensureDir(){if(this.dirEnsured)return;let t=wt.dirname(this.configPath);try{await q.stat(t)}catch(o){if(o.code==="ENOENT")await q.mkdir(t,{recursive:!0});else throw new N("Failed to create directory",t,o.code)}this.dirEnsured=!0}async saveConfig(t){this.config=t,await this.ensureDir();let o=JSON.stringify(t,null,2),r=this.configPath+".tmp";try{await q.writeFile(r,o,"utf-8"),await q.rename(r,this.configPath),this.configLoaded=!0}catch(n){throw await q.unlink(r).catch(s=>{typeof process.env.DEBUG<"u"&&console.error("[config] cleanup tmp failed:",s)}),new N("Failed to save config",this.configPath,n.code)}}},xt=null;function St(){return xt||(xt=new tt),xt}var It=300*1e3,et=class{store=St();isTokenExpired(t){return t.expire?Date.now()>=t.expire-It:!1}async saveCredentials(t,o){let r=Date.now(),n=o.expire?Number.parseInt(o.expire,10):0,s={token:t,userInfo:o,timestamp:r,...n>0&&{expire:r+n}},i=await this.store.loadConfig();i.credentials=s,await this.store.saveConfig(i)}async getCredentials(){let t=await this.store.loadConfig();return!t.credentials||this.isTokenExpired(t.credentials)?null:t.credentials}async clearCredentials(){let t=await this.store.loadConfig();t.credentials=null,await this.store.saveConfig(t)}async getToken(){return(await this.getCredentials())?.token??null}async getUserInfo(){return(await this.getCredentials())?.userInfo??null}async isLoggedIn(){return await this.getCredentials()!==null}},Ct=null;function W(){return Ct||(Ct=new et),Ct}var Ke="https://api.puresnake.com",A=class{config;authStorage=null;cachedToken=null;tokenExpiry=0;constructor(t={}){this.config={baseUrl:t.baseUrl??Ke,version:t.version??"v3",debug:t.debug??!1},this.authStorage=t.auth===!1?null:W()}buildUrl(t){let o=t.startsWith("/")?t.slice(1):t;return`${this.config.baseUrl}/${this.config.version}/${o}`}async getAuthToken(){if(!this.authStorage)return;if(this.cachedToken&&Date.now()<this.tokenExpiry)return this.cachedToken;let t=await this.authStorage.getCredentials();if(!t)throw new y("\u8BF7\u5148\u8FD0\u884C r2-cli auth login \u767B\u5F55");return this.cachedToken=t.token,this.tokenExpiry=t.expire?t.expire-It:Date.now()+1800*1e3,t.token}async requestFull(t,o){let r=this.buildUrl(t),{method:n,headers:s,body:i,timeout:a=3e4}=o,l=await this.getAuthToken(),d={...s,...l?{token:l}:{}},g=new AbortController,$=setTimeout(()=>g.abort(),a),K={method:n,headers:{"Content-Type":"application/json",...d},signal:g.signal};i!==void 0&&(K.body=JSON.stringify(i)),this.config.debug&&console.error(`[API ${n}]`,r,i);try{let c=await fetch(r,K);if(!c.ok){if(c.status===401)throw this.authStorage&&(this.cachedToken=null,await this.authStorage.clearCredentials().catch(j=>{console.error("[API] \u6E05\u9664\u51ED\u8BC1\u5931\u8D25:",j instanceof Error?j.message:String(j))})),new y("\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C r2-cli auth login \u91CD\u65B0\u767B\u5F55");let dt=await c.text();throw new v(dt||`${c.status} ${c.statusText}`,c.status)}let S=await c.json();if(this.config.debug&&console.error("[API Response]",S),!S.success||S.status!==0)throw new v(S.msg||"\u672A\u77E5\u9519\u8BEF",S.status,S);return S}catch(c){throw c instanceof DOMException&&c.name==="AbortError"?new v(`\u8BF7\u6C42\u8D85\u65F6 (${a}ms)`,408):c}finally{clearTimeout($)}}async request(t,o){return(await this.requestFull(t,o)).data}async get(t,o,r){let n=o&&o.size>0?`${t}?${o.toString()}`:t;return this.request(n,{method:"GET",headers:r})}async post(t,o,r){return this.request(t,{method:"POST",body:o,headers:r})}async put(t,o,r){return this.request(t,{method:"PUT",body:o,headers:r})}async delete(t,o){return this.request(t,{method:"DELETE",headers:o})}};var zt=new A({auth:!1});async function Wt(){return zt.post("app/qrcode/generate")}async function Ht(e){let t=new URLSearchParams;t.append("qrToken",e);let o=`app/qrcode/status?${t.toString()}`,r=await zt.requestFull(o,{method:"GET"});return r.token&&typeof r.data=="object"&&r.data!==null&&(r.data.token=r.token),r.data}async function Zt(e,t,o){let{UserInfoCard:r}=await Promise.resolve().then(()=>(Yt(),Kt)),{renderComponent:n}=await Promise.resolve().then(()=>(rt(),ot)),s=t!=null?{userInfo:e,lastLogin:t,daysSinceLogin:o??0}:{userInfo:e};n(r,s)}var nt=class{storage;constructor(t){this.storage=t??W()}async generateQR(){let t=await Wt(),o=`https://m.puresnake.com/r2/auth/login?qrToken=${t.qrContent}&from=wechat`,r=await ht(o);return{qrData:t,...r}}async waitForLogin(t,o,r,n,s,i){let a=await B(()=>Ht(t),{interval:r,timeout:o,condition:l=>{switch(l.status){case"scanned":return i||(console.log(f.cyan(`
11
- \u{1F50D} \u5DF2\u626B\u7801: ${l.userInfo?.nickname||"\u672A\u77E5\u7528\u6237"}`)),console.log(f.yellow("\u8BF7\u5728 APP \u4E0A\u786E\u8BA4\u767B\u5F55"))),s?.("scanning"),!1;case"confirmed":return i||console.log(f.green(`
12
- \u2705 \u7528\u6237\u5DF2\u786E\u8BA4\u767B\u5F55`)),s?.("success"),!0;case"expired":return i||console.log(f.red(`
13
- \u23F0 \u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F`)),s?.("expired"),!0;case"canceled":return i||console.log(f.red(`
14
- \u{1F6AB} \u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55`)),s?.("expired"),!0;default:return!1}}},n??void 0);if(a.status==="confirmed"&&a.token&&a.userInfo)return await this.storage.saveCredentials(a.token,a.userInfo),{userInfo:a.userInfo,token:a.token};throw a.status==="expired"?new y("\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55"):a.status==="canceled"?new y("\u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55"):new y("\u767B\u5F55\u5931\u8D25: \u672A\u83B7\u53D6\u5230\u51ED\u8BC1")}async login(t){console.log(f.cyan(`
15
- \u{1F510} \u6B63\u5728\u542F\u52A8\u626B\u7801\u767B\u5F55...`));let{qrData:o,qrUrl:r,setStatus:n,closeServer:s}=await this.generateQR();console.log(f.green(`\u2705 \u4E8C\u7EF4\u7801\u5DF2\u751F\u6210
16
- `)),console.log(f.cyan(` \u94FE\u63A5: ${r}
17
- `)),P(r),console.log(f.yellow(`\u23F3 \u7B49\u5F85\u626B\u7801...
18
- `));let i=Number.parseInt(o.expireTime,10),a=Number.parseInt(o.pollInterval,10);try{let l=await this.waitForLogin(o.qrToken,i,a,t,n);return console.log(f.green(`
19
- \u2705 \u767B\u5F55\u6210\u529F\uFF01
20
- `)),Zt(l.userInfo),l}catch(l){throw console.log(f.red(`
21
- \u274C \u767B\u5F55\u5931\u8D25
22
- `)),l}finally{s()}}async logout(){console.log(f.cyan(`
23
- \u{1F6AA} \u6B63\u5728\u9000\u51FA\u767B\u5F55...`)),await this.storage.clearCredentials(),console.log(f.green(`\u2705 \u5DF2\u9000\u51FA\u767B\u5F55
24
- `))}async status(){if(!await this.storage.isLoggedIn()){console.log(f.yellow(`\u26A0\uFE0F \u5C1A\u672A\u767B\u5F55\u6216\u51ED\u8BC1\u5DF2\u8FC7\u671F
25
- `));return}let o=await this.storage.getCredentials(),r=o.userInfo,n=new Date(o.timestamp),s=Math.floor((Date.now()-o.timestamp)/(1e3*60*60*24));console.log(f.green(`\u2705 \u5DF2\u767B\u5F55
26
- `)),await Zt(r,n,s)}},Pt=null;function k(){return Pt||(Pt=new nt),Pt}import U from"chalk";var te=new A;async function ee(){return te.get("mms/xianyu/auth/url")}async function oe(e){let t=new URLSearchParams({state:e});return te.get("mms/xianyu/auth/status",t)}async function st(){let e=await ee(),t=await yt(e.url,e.url);return{authData:e,...t}}async function H(e,t,o,r,n){return B(()=>oe(e),{interval:o,timeout:t,condition:s=>s.status==="success"?(console.log(U.green(`
27
- \u2705 \u6388\u6743\u6210\u529F\uFF01\u5E97\u94FA: ${s.shopName} (${s.shopId})`)),n?.("success"),!0):s.status==="expired"?(console.log(U.red(`
28
- \u23F0 \u6388\u6743\u94FE\u63A5\u5DF2\u8FC7\u671F`)),n?.("expired"),!0):!1},r)}async function kt(e){console.log(U.cyan(`
29
- \u{1F517} \u6B63\u5728\u83B7\u53D6\u95F2\u9C7C\u6388\u6743\u5730\u5740...`));let{authData:t,qrUrl:o,setStatus:r,closeServer:n}=await st();console.log(U.green(`\u2705 \u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210
30
- `)),console.log(U.cyan(` \u94FE\u63A5: ${o}`)),console.log(U.gray(` \u6216\u590D\u5236\u94FE\u63A5\u6253\u5F00: ${t.url}`)),P(o),console.log(U.yellow(`
31
- \u23F3 \u7B49\u5F85\u6388\u6743...
32
- `));let s=t.expireTime?Number.parseInt(t.expireTime,10):3e5,i=t.pollInterval?Number.parseInt(t.pollInterval,10):1e3;try{let a=await H(t.state,s,i,e,r);if(a.status==="success")return a;throw new y("\u95F2\u9C7C\u6388\u6743\u5931\u8D25: "+(a.status==="expired"?"\u94FE\u63A5\u5DF2\u8FC7\u671F":"\u672A\u77E5\u72B6\u6001"))}finally{n()}}import L from"chalk";function m(e){if(e instanceof y)console.error(L.red(`
33
- \u25B2 ${e.message}`)),console.error(L.gray(`\u2192 \u8BF7\u5148\u8FD0\u884C: r2-cli auth login
34
- `));else if(e instanceof v)console.error(L.red(`\u25B2 \u64CD\u4F5C\u5931\u8D25: ${e.message}`)),e.status&&console.error(L.gray(` \u72B6\u6001\u7801: ${e.status}`));else if(e instanceof N)console.error(L.red(`\u25B2 \u914D\u7F6E\u6587\u4EF6\u5F02\u5E38: ${e.message}`)),e.path&&console.error(L.gray(` \u8DEF\u5F84: ${e.path}`)),console.error(L.gray(`\u2192 \u8BF7\u5C1D\u8BD5\u91CD\u65B0\u767B\u5F55: r2-cli auth login
35
- `));else{let t=e instanceof Error?e.message:String(e);console.error(L.red(`\u25B2 ${t}`))}process.exit(1)}function vt(e){console.log(JSON.stringify({success:!1,error:e})),process.exit(1)}function it(e){return async(...t)=>{try{await e(...t)}catch(o){let r=o instanceof Error?o.message:String(o);vt(r)}}}var no=new Set(["accessToken","refreshExpireIn"]);function re(e){return e.map(t=>{let o={};for(let[r,n]of Object.entries(t))no.has(r)||(o[r]=n);return o})}function bt(){let e=new ne("login");e.description("\u626B\u7801\u767B\u5F55 Round2AI \u8D26\u6237").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new ne("poll").description("\u8F6E\u8BE2\u767B\u5F55\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--token <qrToken>","\u4E8C\u7EF4\u7801 token").option("--expire <ms>","\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09","300000").option("--interval <ms>","\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09","1000").action(it(async o=>{let n=await k().waitForLogin(o.token,Number.parseInt(o.expire,10),Number.parseInt(o.interval,10));console.log(JSON.stringify({success:!0,...n}))}));return e.addCommand(t),e.action(async o=>{try{if(o.json){let r=k(),{qrData:n,qrUrl:s,setStatus:i,closeServer:a}=await r.generateQR(),l=Number.parseInt(n.expireTime,10),d=Number.parseInt(n.pollInterval,10);console.log(JSON.stringify({qrToken:n.qrToken,expireTimeMs:l,pollIntervalMs:d,url:`https://m.puresnake.com/r2/auth/login?qrToken=${n.qrContent}&from=wechat`,qrUrl:s},null,2)),P(s);try{let g=await r.waitForLogin(n.qrToken,l,d,void 0,i,!0);console.log(JSON.stringify({success:!0,userInfo:g.userInfo}))}catch(g){let $=g instanceof Error?g.message:String(g);console.log(JSON.stringify({success:!1,error:$}))}finally{setTimeout(a,1e3)}}else await k().login()}catch(r){if(o.json){let n=r instanceof Error?r.message:String(r);console.log(JSON.stringify({success:!1,error:n})),process.exit(1)}m(r)}}),e}import{Command as so}from"commander";function At(){let e=new so("logout");return e.description("\u9000\u51FA\u767B\u5F55"),e.action(async()=>{try{await k().logout()}catch(t){m(t)}}),e}import{Command as io}from"commander";function Lt(){let e=new io("status");return e.description("\u67E5\u770B\u767B\u5F55\u72B6\u6001"),e.action(async()=>{try{await k().status()}catch(t){m(t)}}),e}import{Command as se}from"commander";function Rt(){let e=new se("xianyu");e.description("\u95F2\u9C7C\u5E97\u94FA\u6388\u6743").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new se("poll").description("\u8F6E\u8BE2\u95F2\u9C7C\u6388\u6743\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--state <state>","\u6388\u6743\u8F6E\u8BE2 token").option("--expire <ms>","\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09","300000").option("--interval <ms>","\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09","1000").action(it(async o=>{let r=await H(o.state,Number.parseInt(o.expire,10),Number.parseInt(o.interval,10));r.status==="success"?console.log(JSON.stringify({success:!0,shopId:r.shopId,shopName:r.shopName})):vt(`\u6388\u6743\u72B6\u6001: ${r.status}`)}));return e.addCommand(t),e.action(async o=>{try{if(o.json){let{authData:r,qrUrl:n,setStatus:s,closeServer:i}=await st(),a=r.expireTime?Number.parseInt(r.expireTime,10):3e5,l=r.pollInterval?Number.parseInt(r.pollInterval,10):1e3;console.log(JSON.stringify({state:r.state,expireTimeMs:a,pollIntervalMs:l,qrUrl:n},null,2)),P(n);try{let d=await H(r.state,a,l,void 0,s);d.status==="success"?console.log(JSON.stringify({success:!0,shopId:d.shopId,shopName:d.shopName})):(console.log(JSON.stringify({success:!1,error:`\u6388\u6743\u72B6\u6001: ${d.status}`})),process.exit(1))}catch(d){let g=d instanceof Error?d.message:String(d);console.log(JSON.stringify({success:!1,error:g})),process.exit(1)}finally{setTimeout(i,1e3)}}else await kt()}catch(r){if(o.json){let n=r instanceof Error?r.message:String(r);console.log(JSON.stringify({success:!1,error:n})),process.exit(1)}m(r)}}),e}import{Command as Lo}from"commander";import{Command as ao}from"commander";import I from"chalk";import{select as Ot,input as co,confirm as lo}from"@inquirer/prompts";var R=new A;function Nt(e){let t=new URLSearchParams;for(let[o,r]of Object.entries(e))r!=null&&r!==""&&t.append(o,String(r));return t}async function Et(e){return R.post("mms/goods/listing/up/xianyu",e)}async function ie(e){return R.get("mms/goods/listing/get",Nt({...e}))}async function ae(e){return R.post("mms/goods/listing/down/xianyu",e)}async function ce(e){return R.post("mms/goods/listing/update/xyPrice",e)}async function le(e){return R.get("mms/goods/listing/list",e?Nt({...e}):void 0)}async function at(){return await R.get("mms/user/shop/list")??[]}async function ct(){return await R.get("mms/user/stock/list")??[]}async function lt(e){let t=e?Nt({...e}):void 0;return R.get("mms/seller/goods/select/list",t)}var mo=2e3,uo=1e4;function po(e){let t=e.status?.toLowerCase()??"";return t===""||t==="init"||t==="pending"||t==="processing"}async function me(e,t,o,r){r||process.stdout.write(I.cyan("\u23F3 \u6B63\u5728\u67E5\u8BE2\u4E0A\u67B6\u8FDB\u5EA6..."));let n=await B(()=>ie({stockGoodsId:e,shopId:t,platform:o}),{interval:mo,timeout:uo,condition:s=>!po(s)});return r||process.stdout.write("\r"+" ".repeat(30)+"\r"),n}function ue(){let e=new ao("up");return e.description("\u4E0A\u67B6\u5546\u54C1\u5230\u95F2\u9C7C"),e.option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1ID\uFF08\u4ECE goods list \u83B7\u53D6\uFF09").option("--shop-id <id>","\u5E97\u94FAID\uFF08\u4ECE goods shops \u83B7\u53D6\uFF09").option("--price <amount>","\u4E0A\u67B6\u4EF7\u683C").option("-p, --platform <platform>","\u5E73\u53F0","xianyu").option("--json","\u8F93\u51FA JSON\uFF08Agent \u7528\uFF09").action(async t=>{try{if(t.stockGoodsId&&t.shopId&&t.price){let c=Number(t.stockGoodsId),S=t.shopId,dt=Number(t.price),j=t.platform,Ee=await Et({stockGoodsId:c,shopId:S,price:dt,platform:j}),pt=await me(c,S,j,t.json);if(t.json)console.log(JSON.stringify({success:!0,data:{submit:Ee,listing:pt}},null,2));else{let Oe=pt.status?.toLowerCase()!=="failed";console.log(Oe?I.green("\u2713 \u4E0A\u67B6\u6210\u529F"):I.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify(pt,null,2))}return}let o=await at();if(o.length===0){console.log(I.yellow("\u6CA1\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF0C\u8BF7\u5148\u8FD0\u884C r2-cli auth xianyu \u6388\u6743"));return}let r=await Ot({message:"\u9009\u62E9\u5E97\u94FA",choices:o.map(c=>({name:`${c.shopName} (${c.platform})`,value:c.shopId}))}),n=await ct();if(n.length===0){console.log(I.yellow("\u6CA1\u6709\u53EF\u7528\u7684\u4ED3\u5E93"));return}let s=await Ot({message:"\u9009\u62E9\u4ED3\u5E93",choices:n.map(c=>({name:c.stockName,value:c.stockId}))}),i=await lt({stockId:s,size:100});if(!i.items?.length){console.log(I.yellow("\u8BE5\u4ED3\u5E93\u6CA1\u6709\u53EF\u9009\u7684\u5546\u54C1"));return}let a=await Ot({message:"\u9009\u62E9\u5546\u54C1",choices:i.items.map(c=>({name:`${c.goodsName} ${c.size?`| ${c.size}`:""} | \xA5${c.salePrice}`,value:c.stockGoodsId}))}),l=await co({message:"\u8F93\u5165\u4E0A\u67B6\u4EF7\u683C",default:i.items.find(c=>c.stockGoodsId===a)?.salePrice?.toString()??"",validate:c=>Number(c)>0?!0:"\u4EF7\u683C\u5FC5\u987B\u4E3A\u6B63\u6570"});if(!await lo({message:`\u786E\u8BA4\u4E0A\u67B6\uFF1F\u4EF7\u683C \xA5${l}`,default:!0})){console.log(I.gray("\u5DF2\u53D6\u6D88"));return}let g=Number(a);await Et({stockGoodsId:g,shopId:r,price:Number(l),platform:"xianyu"}),console.log(I.green("\u2713 \u4E0A\u67B6\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u67E5\u8BE2\u8FDB\u5EA6..."));let $=await me(g,r,"xianyu"),K=$.status?.toLowerCase()!=="failed";console.log(K?I.green("\u2713 \u4E0A\u67B6\u6210\u529F"):I.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify($,null,2))}catch(o){m(o)}}),e}import{Command as wo}from"commander";import fe from"chalk";function he(){let e=new wo("shops");return e.description("\u67E5\u770B\u6240\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF08\u8DE8\u5E73\u53F0\uFF09"),e.option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(async t=>{try{let o=await at();if(t.json){console.log(JSON.stringify(re(o),null,2));return}if(!o.length){console.log(fe.yellow("\u672A\u627E\u5230\u5DF2\u6388\u6743\u7684\u5E97\u94FA")),console.log(fe.gray(" \u63D0\u793A: \u8BF7\u5148\u5728\u7B2C\u4E8C\u56DE\u5408 APP \u4E2D\u6388\u6743\u5E97\u94FA"));return}let{ShopsTable:r}=await Promise.resolve().then(()=>(ge(),pe)),{renderComponent:n}=await Promise.resolve().then(()=>(rt(),ot));n(r,{shops:o,platform:"all"})}catch(o){m(o)}}),e}import{Command as Io}from"commander";import To from"chalk";function xe(){let e=new Io("stocks");return e.description("\u67E5\u770B\u6240\u6709\u4ED3\u5E93"),e.option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(async t=>{try{let o=await ct();if(t.json){console.log(JSON.stringify(o,null,2));return}if(!o.length){console.log(To.yellow("\u672A\u627E\u5230\u4ED3\u5E93\u4FE1\u606F"));return}let{StocksTable:r}=await Promise.resolve().then(()=>(we(),ye)),{renderComponent:n}=await Promise.resolve().then(()=>(rt(),ot));n(r,{stocks:o})}catch(o){m(o)}}),e}import{Command as Po}from"commander";import F from"chalk";function Se(){let e=new Po("list");return e.description("\u67E5\u770B\u4ED3\u5E93\u4E2D\u7684\u9009\u54C1\u5546\u54C1"),e.option("--stock-id <id>","\u4ED3\u5E93 ID\uFF08\u4ECE goods stocks \u83B7\u53D6\uFF09").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--page <n>","\u9875\u7801","1").option("--size <n>","\u6BCF\u9875\u6570\u91CF","20").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(async t=>{try{let r=await lt({stockId:t.stockId||void 0,stockGoodsId:t.stockGoodsId||void 0,page:Number(t.page)||1,size:Number(t.size)||20})??{items:[],total:0};if(t.json){r.items?.length?console.log(JSON.stringify(r,null,2)):console.log(JSON.stringify({...r,hint:"\u9009\u54C1\u5546\u54C1\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E\u540E\u518D\u8BD5"},null,2));return}if(!r.items?.length){console.log(F.yellow("\u6682\u65E0\u9009\u54C1\u5546\u54C1\uFF0C\u8BF7\u5148\u7ED1\u5B9A\u4ED3\u5E93\u6216\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E"));return}console.log(F.cyan(`
36
- \u9009\u54C1\u5546\u54C1\uFF08\u5171 ${r.total} \u4EF6\uFF0C\u7B2C ${r.page} \u9875\uFF09
37
- `));for(let n of r.items)console.log(` ${F.bold(n.goodsName)} ${n.size?F.gray(`| ${n.size}`):""}`),console.log(` \u54C1\u724C: ${n.brand} \u5EFA\u8BAE\u552E\u4EF7: \xA5${n.salePrice} stockGoodsId: ${F.green(n.stockGoodsId)}`),console.log(F.gray(` \u5206\u7C7B: ${n.cate1Name} > ${n.cate2Name} > ${n.cate3Name}`)),console.log()}catch(o){if(t.json){let r=o instanceof Error?o.message:String(o);console.log(JSON.stringify({success:!1,error:r})),process.exit(1)}m(o)}}),e}import{Command as ko}from"commander";import Ce from"chalk";var vo={init:"\u5F85\u4E0A\u67B6",up:"\u5DF2\u4E0A\u67B6",down:"\u5DF2\u4E0B\u67B6",fail:"\u5931\u8D25"};function Ie(){let e=new ko("listing");return e.description("\u67E5\u8BE2\u4E0A\u67B6\u5546\u54C1\u5217\u8868"),e.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--stock-id <id>","\u4ED3\u5E93 ID").option("-s, --status <status>","\u72B6\u6001\u8FC7\u6EE4\uFF08init/up/down/fail\uFF09").option("-p, --platform <platform>","\u5E73\u53F0","xianyu").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(async t=>{try{let r=await le({id:t.id,stockGoodsId:t.stockGoodsId?Number(t.stockGoodsId):void 0,shopId:t.shopId,stockId:t.stockId,status:t.status,platform:t.platform})??{list:[],total:0};if(t.json){r.list?.length?console.log(JSON.stringify(r,null,2)):console.log(JSON.stringify({...r,hint:"\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"},null,2));return}if(!r.list?.length){console.log(Ce.yellow("\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"));return}console.log(Ce.green(`\u2705 \u5171 ${r.total} \u6761\u8BB0\u5F55
38
- `));for(let n of r.list){let s=vo[n.status]??n.status;console.log(` ID: ${n.id} | \u72B6\u6001: ${s} | \u4EF7\u683C: ${n.price} | stockGoodsId: ${n.stockGoodsId}`)}}catch(o){if(t.json){let r=o instanceof Error?o.message:String(o);console.log(JSON.stringify({success:!1,error:r})),process.exit(1)}m(o)}}),e}import{Command as bo}from"commander";import qt from"chalk";function Te(){let e=new bo("down");return e.description("\u4E0B\u67B6\u95F2\u9C7C\u5546\u54C1"),e.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(async t=>{try{if(!t.id&&!(t.stockGoodsId&&t.shopId)){t.json&&(console.log(JSON.stringify({success:!1,error:"\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"})),process.exit(1)),console.log(qt.yellow("\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));return}let o={};t.id&&(o.id=t.id),t.stockGoodsId&&(o.stockGoodsId=Number(t.stockGoodsId)),t.shopId&&(o.shopId=t.shopId),t.json||console.log(qt.cyan("\u{1F4E6} \u6B63\u5728\u4E0B\u67B6\u5546\u54C1..."));let r=await ae(o);t.json?console.log(JSON.stringify({success:!0,data:r},null,2)):(console.log(qt.green("\u2705 \u4E0B\u67B6\u6210\u529F")),console.log(JSON.stringify(r,null,2)))}catch(o){if(t.json){let r=o instanceof Error?o.message:String(o);console.log(JSON.stringify({success:!1,error:r})),process.exit(1)}m(o)}}),e}import{Command as Ao}from"commander";import mt from"chalk";function Pe(){let e=new Ao("price");return e.description("\u4FEE\u6539\u95F2\u9C7C\u4E0A\u67B6\u5546\u54C1\u4EF7\u683C"),e.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--price <amount>","\u65B0\u4EF7\u683C\uFF08\u5FC5\u586B\uFF09").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),e.action(async t=>{try{if(!t.price){t.json&&(console.log(JSON.stringify({success:!1,error:"--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570"})),process.exit(1)),console.log(mt.yellow("--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570"));return}if(!t.id&&!(t.stockGoodsId&&t.shopId)){t.json&&(console.log(JSON.stringify({success:!1,error:"\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"})),process.exit(1)),console.log(mt.yellow("\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));return}let o={price:Number(t.price)};t.id&&(o.id=t.id),t.stockGoodsId&&(o.stockGoodsId=Number(t.stockGoodsId)),t.shopId&&(o.shopId=t.shopId),t.json||console.log(mt.cyan(`\u{1F4B0} \u6B63\u5728\u4FEE\u6539\u4EF7\u683C\u4E3A ${t.price}...`));let r=await ce(o);t.json?console.log(JSON.stringify({success:!0,data:r},null,2)):(console.log(mt.green("\u2705 \u4EF7\u683C\u4FEE\u6539\u6210\u529F")),console.log(JSON.stringify(r,null,2)))}catch(o){if(t.json){let r=o instanceof Error?o.message:String(o);console.log(JSON.stringify({success:!1,error:r})),process.exit(1)}m(o)}}),e}function ke(){let e=new Lo("goods");return e.description("\u5546\u54C1\u7BA1\u7406"),e.addCommand(he()),e.addCommand(xe()),e.addCommand(Se()),e.addCommand(Ie()),e.addCommand(Te()),e.addCommand(Pe()),e.addCommand(ue()),e}import{Command as Ro}from"commander";import T from"chalk";import{promises as No}from"node:fs";import Eo from"node:path";import Oo from"node:os";import{spawn as Uo}from"node:child_process";var ut="@round2ai/r2-cli";function ve(){let e=new Ro("uninstall");return e.description("\u5378\u8F7D R2-CLI \u5E76\u6E05\u9664\u6240\u6709\u914D\u7F6E"),e.action(async()=>{try{console.log(T.yellow(`
39
- \u26A0\uFE0F \u5373\u5C06\u6267\u884C\u4EE5\u4E0B\u64CD\u4F5C\uFF1A`)),console.log(T.gray(" 1. \u5220\u9664\u914D\u7F6E\u76EE\u5F55 ~/.r2-cli/")),console.log(T.gray(` 2. \u5168\u5C40\u5378\u8F7D ${ut}
40
- `));let{confirm:t}=await import("@inquirer/prompts");if(!await t({message:"\u786E\u8BA4\u5378\u8F7D\uFF1F",default:!1})){console.log(T.gray("\u5DF2\u53D6\u6D88\u5378\u8F7D"));return}let r=Eo.join(Oo.homedir(),".r2-cli");try{await No.rm(r,{recursive:!0,force:!0}),console.log(T.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u6E05\u9664"))}catch{console.log(T.yellow("\u26A0\uFE0F \u914D\u7F6E\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u5220\u9664\uFF08\u53EF\u5FFD\u7565\uFF09"))}console.log(T.cyan(`\u6B63\u5728\u5378\u8F7D ${ut}...`)),Uo("npm",["uninstall","-g",ut],{stdio:"inherit",shell:!0}).on("exit",s=>{s===0?console.log(T.green(`
41
- \u2705 ${ut} \u5DF2\u5378\u8F7D`)):(console.log(T.yellow(`
42
- \u26A0\uFE0F npm \u5378\u8F7D\u5931\u8D25 (exit code: ${s})`)),console.log(T.gray(" \u5982\u901A\u8FC7 yarn/pnpm \u5B89\u88C5\uFF0C\u8BF7\u624B\u52A8\u5378\u8F7D"))),process.exit(s??1)})}catch(t){m(t)}}),e}function be(e){let t=e.command("auth").description("\u6388\u6743\u7BA1\u7406");t.addCommand(bt()),t.addCommand(At()),t.addCommand(Lt()),t.addCommand(Rt()),e.addCommand(ke()),e.addCommand(ve())}import Ae from"chalk";var Qt="@round2ai/r2-cli",Do=[`https://registry.npmmirror.com/${encodeURIComponent(Qt)}/latest`,`https://registry.npmjs.org/${encodeURIComponent(Qt)}/latest`],$o=5e3;async function jo(e){let t=new AbortController,o=setTimeout(()=>t.abort(),$o);try{let r=await fetch(e,{signal:t.signal});return r.ok?(await r.json()).version??null:null}catch{return null}finally{clearTimeout(o)}}async function Go(){let e=await Promise.allSettled(Do.map(jo));for(let t of e)if(t.status==="fulfilled"&&t.value)return t.value;return null}function Bo(e,t){let o=e.split(".").map(Number),r=t.split(".").map(Number);for(let n=0;n<3;n++)if((o[n]??0)!==(r[n]??0))return(o[n]??0)>(r[n]??0);return!1}async function Le(e){let t=await Go();t&&Bo(t,e)&&Jo(e,t)}function Jo(e,t){console.error(Ae.yellow(`
43
- Update available: ${e} \u2192 ${t}`)+Ae.gray(`
44
- Run: npm update -g ${Qt}
45
- `))}async function _o(){let{default:e}=await import("figlet");console.log(z.cyan.bold(e.textSync("R2-CLI",{font:"Standard",horizontalLayout:"full"}))),console.log(z.gray(` \u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B
46
- `))}function Mo(){let e=new qo;e.name("r2-cli").description("R2-CLI\uFF0C\u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B");let t=[Re.join(import.meta.dirname,"../../package.json"),Re.join(import.meta.dirname,"package.json")],o="0.0.0";for(let n of t)try{o=JSON.parse(Qo(n,"utf-8")).version;break}catch{}o==="0.0.0"&&console.error(z.yellow("Warning: unable to read version from package.json")),e.version(o,"-v, --version");let r=Le(o);return e.configureOutput({writeErr:n=>{console.error(z.red(n.replace("error:","").trim()))}}),e.action(async()=>{await _o(),e.help()}),be(e),{program:e,updateCheckPromise:r}}function Ne(){console.log(z.gray(`
47
- \u64CD\u4F5C\u5DF2\u53D6\u6D88`)),process.exit(130)}process.on("SIGINT",Ne);process.on("SIGTERM",Ne);var{program:Xo,updateCheckPromise:Fo}=Mo();Xo.parse(process.argv);Fo.catch(e=>{console.error(z.gray(`[update-check] ${e instanceof Error?e.message:String(e)}`))});
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __esm = (fn, res) => function __init() {
6
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
7
+ };
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+
13
+ // src/components/UserInfoCard.tsx
14
+ var UserInfoCard_exports = {};
15
+ __export(UserInfoCard_exports, {
16
+ UserInfoCard: () => UserInfoCard
17
+ });
18
+ import { Box, Text } from "ink";
19
+ import { jsx, jsxs } from "react/jsx-runtime";
20
+ function UserInfoCard({ userInfo, lastLogin, daysSinceLogin }) {
21
+ const maskedMobile = userInfo.mobile ? userInfo.mobile.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2") : "-";
22
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
23
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u7528\u6237\u4FE1\u606F" }),
24
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", marginTop: 1, children: [
25
+ /* @__PURE__ */ jsx(Box, { width: 10, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u6635\u79F0" }) }),
26
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: userInfo.nickname })
27
+ ] }),
28
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
29
+ /* @__PURE__ */ jsx(Box, { width: 10, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u624B\u673A\u53F7" }) }),
30
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: maskedMobile })
31
+ ] }),
32
+ lastLogin && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
33
+ /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
34
+ "\u6700\u540E\u767B\u5F55: ",
35
+ lastLogin.toLocaleString()
36
+ ] }),
37
+ daysSinceLogin !== void 0 && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
38
+ " \u8DDD\u4ECA: ",
39
+ daysSinceLogin,
40
+ " \u5929"
41
+ ] })
42
+ ] })
43
+ ] });
44
+ }
45
+ var init_UserInfoCard = __esm({
46
+ "src/components/UserInfoCard.tsx"() {
47
+ "use strict";
48
+ }
49
+ });
50
+
51
+ // src/utils/render.tsx
52
+ var render_exports = {};
53
+ __export(render_exports, {
54
+ renderComponent: () => renderComponent,
55
+ renderOnce: () => renderOnce
56
+ });
57
+ import React from "react";
58
+ import chalk from "chalk";
59
+ import { render } from "ink";
60
+ import { Writable } from "node:stream";
61
+ function renderOnce(component) {
62
+ const prevLevel = chalk.level;
63
+ if (!process.env.NO_COLOR) {
64
+ chalk.level = 3;
65
+ }
66
+ try {
67
+ const chunks = [];
68
+ const buffer = new Writable({
69
+ write(chunk, _, done) {
70
+ chunks.push(Buffer.from(chunk));
71
+ done();
72
+ }
73
+ });
74
+ buffer.isTTY = true;
75
+ buffer.columns = process.stdout.columns || 80;
76
+ buffer.rows = process.stdout.rows || 24;
77
+ const instance4 = render(component, {
78
+ stdout: buffer,
79
+ patchConsole: false
80
+ });
81
+ instance4.unmount();
82
+ const raw = Buffer.concat(chunks).toString("utf8");
83
+ const lastRender = raw.split(/\x1B\[2J\x1B\[3J\x1B\[H/).at(-1) || raw;
84
+ const cleaned = lastRender.replace(/\x1B\[\?[\d;]+[hl]/g, "").trimEnd() + "\n";
85
+ process.stdout.write(cleaned);
86
+ } finally {
87
+ chalk.level = prevLevel;
88
+ }
89
+ }
90
+ function renderComponent(Component, props) {
91
+ renderOnce(React.createElement(Component, props));
92
+ }
93
+ var init_render = __esm({
94
+ "src/utils/render.tsx"() {
95
+ "use strict";
96
+ }
97
+ });
98
+
99
+ // src/components/ShopsTable.tsx
100
+ var ShopsTable_exports = {};
101
+ __export(ShopsTable_exports, {
102
+ ShopsTable: () => ShopsTable
103
+ });
104
+ import { Box as Box2, Text as Text2 } from "ink";
105
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
106
+ function normalizeShops(shops) {
107
+ return shops.map((s) => {
108
+ if ("shopName" in s) {
109
+ return {
110
+ id: s.shopId,
111
+ name: s.shopName,
112
+ platform: s.platform,
113
+ expiresIn: s.expiresIn
114
+ };
115
+ }
116
+ return {
117
+ id: s.id,
118
+ name: s.name,
119
+ platform: s.thirdUserId,
120
+ expiresIn: s.expiresIn
121
+ };
122
+ });
123
+ }
124
+ function Header({ hasPlatform, fillWidth }) {
125
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", paddingBottom: 0, children: [
126
+ hasPlatform && /* @__PURE__ */ jsx2(Box2, { width: COL_PLATFORM, children: /* @__PURE__ */ jsx2(Text2, { bold: true, color: "white", children: "\u5E73\u53F0" }) }),
127
+ /* @__PURE__ */ jsx2(Box2, { width: fillWidth, children: /* @__PURE__ */ jsx2(Text2, { bold: true, color: "white", children: "\u5E97\u94FA\u540D" }) }),
128
+ /* @__PURE__ */ jsx2(Box2, { width: COL_ID, children: /* @__PURE__ */ jsx2(Text2, { bold: true, color: "white", children: "ID" }) }),
129
+ /* @__PURE__ */ jsx2(Box2, { width: COL_STATUS, children: /* @__PURE__ */ jsx2(Text2, { bold: true, color: "white", children: "\u72B6\u6001" }) })
130
+ ] });
131
+ }
132
+ function Row({ shop, hasPlatform, fillWidth }) {
133
+ const platformLabel = PLATFORM_LABELS[shop.platform] ?? shop.platform;
134
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", children: [
135
+ hasPlatform && /* @__PURE__ */ jsx2(Box2, { width: COL_PLATFORM, children: /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: platformLabel }) }),
136
+ /* @__PURE__ */ jsx2(Box2, { width: fillWidth, children: /* @__PURE__ */ jsx2(Text2, { bold: true, children: shop.name }) }),
137
+ /* @__PURE__ */ jsx2(Box2, { width: COL_ID, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", children: shop.id }) }),
138
+ /* @__PURE__ */ jsx2(Box2, { width: COL_STATUS, children: /* @__PURE__ */ jsx2(Text2, { color: "green", children: "\u25CF \u6388\u6743\u4E2D" }) })
139
+ ] });
140
+ }
141
+ function ShopsTable({ shops, platform }) {
142
+ const items = normalizeShops(shops);
143
+ const hasPlatform = platform === "all";
144
+ const title = platform === "all" ? "\u6240\u6709\u6388\u6743\u5E97\u94FA" : `${PLATFORM_LABELS[platform] ?? platform}\u6388\u6743\u5E97\u94FA`;
145
+ const termWidth = process.stdout.columns || 80;
146
+ const borderPadding = 4;
147
+ const fixedCols = COL_ID + COL_STATUS + (hasPlatform ? COL_PLATFORM : 0);
148
+ const fillWidth = Math.max(termWidth - borderPadding - fixedCols, 20);
149
+ const totalWidth = fixedCols + fillWidth;
150
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
151
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", children: [
152
+ /* @__PURE__ */ jsx2(Text2, { bold: true, color: "cyan", children: title }),
153
+ /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
154
+ " \xB7 ",
155
+ items.length,
156
+ " \u5BB6"
157
+ ] })
158
+ ] }),
159
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginTop: 1, children: [
160
+ /* @__PURE__ */ jsx2(Header, { hasPlatform, fillWidth }),
161
+ /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "\u2500".repeat(totalWidth) }),
162
+ items.map((shop) => /* @__PURE__ */ jsx2(Row, { shop, hasPlatform, fillWidth }, shop.id))
163
+ ] })
164
+ ] });
165
+ }
166
+ var PLATFORM_LABELS, COL_PLATFORM, COL_ID, COL_STATUS;
167
+ var init_ShopsTable = __esm({
168
+ "src/components/ShopsTable.tsx"() {
169
+ "use strict";
170
+ PLATFORM_LABELS = {
171
+ xianyu: "\u95F2\u9C7C",
172
+ douyin: "\u6296\u97F3"
173
+ };
174
+ COL_PLATFORM = 8;
175
+ COL_ID = 16;
176
+ COL_STATUS = 10;
177
+ }
178
+ });
179
+
180
+ // src/components/StocksTable.tsx
181
+ var StocksTable_exports = {};
182
+ __export(StocksTable_exports, {
183
+ StocksTable: () => StocksTable
184
+ });
185
+ import { Box as Box3, Text as Text3 } from "ink";
186
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
187
+ function Header2({ fillWidth }) {
188
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", paddingBottom: 0, children: [
189
+ /* @__PURE__ */ jsx3(Box3, { width: COL_ID2, children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: "white", children: "ID" }) }),
190
+ /* @__PURE__ */ jsx3(Box3, { width: COL_USER_ID, children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: "white", children: "\u7528\u6237ID" }) }),
191
+ /* @__PURE__ */ jsx3(Box3, { width: COL_STOCK_ID, children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: "white", children: "\u4ED3\u5E93ID" }) }),
192
+ /* @__PURE__ */ jsx3(Box3, { width: fillWidth, children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: "white", children: "\u4ED3\u5E93\u540D\u79F0" }) }),
193
+ /* @__PURE__ */ jsx3(Box3, { width: COL_TIME, children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: "white", children: "\u521B\u5EFA\u65F6\u95F4" }) })
194
+ ] });
195
+ }
196
+ function Row2({ stock, fillWidth }) {
197
+ const created = new Date(stock.gmtCreate).toLocaleString("zh-CN");
198
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", children: [
199
+ /* @__PURE__ */ jsx3(Box3, { width: COL_ID2, children: /* @__PURE__ */ jsx3(Text3, { color: "gray", children: stock.id }) }),
200
+ /* @__PURE__ */ jsx3(Box3, { width: COL_USER_ID, children: /* @__PURE__ */ jsx3(Text3, { color: "gray", children: stock.userId }) }),
201
+ /* @__PURE__ */ jsx3(Box3, { width: COL_STOCK_ID, children: /* @__PURE__ */ jsx3(Text3, { color: "gray", children: stock.stockId }) }),
202
+ /* @__PURE__ */ jsx3(Box3, { width: fillWidth, children: /* @__PURE__ */ jsx3(Text3, { bold: true, children: stock.stockName }) }),
203
+ /* @__PURE__ */ jsx3(Box3, { width: COL_TIME, children: /* @__PURE__ */ jsx3(Text3, { color: "gray", children: created }) })
204
+ ] });
205
+ }
206
+ function StocksTable({ stocks }) {
207
+ const termWidth = process.stdout.columns || 80;
208
+ const borderPadding = 4;
209
+ const fixedCols = COL_ID2 + COL_USER_ID + COL_STOCK_ID + COL_TIME;
210
+ const fillWidth = Math.max(termWidth - borderPadding - fixedCols, 20);
211
+ const totalWidth = fixedCols + fillWidth;
212
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
213
+ /* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", children: [
214
+ /* @__PURE__ */ jsx3(Text3, { bold: true, color: "cyan", children: "\u4ED3\u5E93\u5217\u8868" }),
215
+ /* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
216
+ " \xB7 ",
217
+ stocks.length,
218
+ " \u4E2A"
219
+ ] })
220
+ ] }),
221
+ /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
222
+ /* @__PURE__ */ jsx3(Header2, { fillWidth }),
223
+ /* @__PURE__ */ jsx3(Text3, { color: "gray", children: "\u2500".repeat(totalWidth) }),
224
+ stocks.map((stock) => /* @__PURE__ */ jsx3(Row2, { stock, fillWidth }, stock.id))
225
+ ] })
226
+ ] });
227
+ }
228
+ var COL_ID2, COL_USER_ID, COL_STOCK_ID, COL_TIME;
229
+ var init_StocksTable = __esm({
230
+ "src/components/StocksTable.tsx"() {
231
+ "use strict";
232
+ COL_ID2 = 6;
233
+ COL_USER_ID = 10;
234
+ COL_STOCK_ID = 10;
235
+ COL_TIME = 22;
236
+ }
237
+ });
238
+
239
+ // src/entrypoints/r2-cli.tsx
240
+ import { Command as Command18 } from "commander";
241
+ import chalk17 from "chalk";
242
+
243
+ // src/commands/setup.ts
244
+ import "commander";
245
+
246
+ // src/commands/auth/login.ts
247
+ import { Command } from "commander";
248
+
249
+ // src/services/auth/login.ts
250
+ import chalk2 from "chalk";
251
+
252
+ // src/errors/index.ts
253
+ var R2Error = class _R2Error extends Error {
254
+ constructor(message, code, details) {
255
+ super(message);
256
+ this.code = code;
257
+ this.details = details;
258
+ this.name = "R2Error";
259
+ if (Error.captureStackTrace) {
260
+ Error.captureStackTrace(this, _R2Error);
261
+ }
262
+ }
263
+ code;
264
+ details;
265
+ };
266
+ var ApiError = class extends R2Error {
267
+ constructor(message, status, response) {
268
+ super(message, "API_ERROR", response);
269
+ this.status = status;
270
+ this.response = response;
271
+ this.name = "ApiError";
272
+ }
273
+ status;
274
+ response;
275
+ };
276
+ var StorageError = class extends R2Error {
277
+ constructor(message, path4, code) {
278
+ super(message, "STORAGE_ERROR", { path: path4, code });
279
+ this.path = path4;
280
+ this.code = code;
281
+ this.name = "StorageError";
282
+ }
283
+ path;
284
+ code;
285
+ };
286
+ var AuthError = class extends R2Error {
287
+ constructor(message) {
288
+ super(message, "AUTH_ERROR");
289
+ this.name = "AuthError";
290
+ }
291
+ };
292
+ var PollingError = class extends R2Error {
293
+ constructor(message, attempts, timeout) {
294
+ super(message, "POLLING_ERROR", { attempts, timeout });
295
+ this.attempts = attempts;
296
+ this.timeout = timeout;
297
+ this.name = "PollingError";
298
+ }
299
+ attempts;
300
+ timeout;
301
+ };
302
+
303
+ // src/utils/polling.ts
304
+ async function callWithTimeout(fn, ms, parentSignal) {
305
+ const controller = new AbortController();
306
+ const onParentAbort = () => controller.abort();
307
+ parentSignal?.addEventListener("abort", onParentAbort, { once: true });
308
+ const timer = setTimeout(() => controller.abort(), ms);
309
+ try {
310
+ return await fn();
311
+ } catch (error) {
312
+ if (controller.signal.aborted && !parentSignal?.aborted) {
313
+ throw new PollingError("\u5355\u6B21\u8F6E\u8BE2\u8BF7\u6C42\u8D85\u65F6");
314
+ }
315
+ throw error;
316
+ } finally {
317
+ clearTimeout(timer);
318
+ parentSignal?.removeEventListener("abort", onParentAbort);
319
+ }
320
+ }
321
+ async function poll(fn, options, signal) {
322
+ const { interval, timeout, condition } = options;
323
+ const startTime = Date.now();
324
+ let attempts = 0;
325
+ while (Date.now() - startTime < timeout) {
326
+ if (signal?.aborted) {
327
+ throw new PollingError("\u8F6E\u8BE2\u88AB\u4E2D\u6B62");
328
+ }
329
+ attempts++;
330
+ const remaining = timeout - (Date.now() - startTime);
331
+ const data = await callWithTimeout(fn, remaining, signal);
332
+ if (condition(data, attempts)) {
333
+ return data;
334
+ }
335
+ await sleep(interval, signal);
336
+ }
337
+ throw new PollingError(`\u8F6E\u8BE2\u8D85\u65F6 (\u5DF2\u7B49\u5F85 ${Date.now() - startTime}ms, \u5171 ${attempts} \u6B21)`);
338
+ }
339
+ function sleep(ms, signal) {
340
+ return new Promise((resolve, reject) => {
341
+ if (signal?.aborted) {
342
+ reject(new PollingError("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"));
343
+ return;
344
+ }
345
+ const onAbort = () => {
346
+ clearTimeout(timer);
347
+ reject(new PollingError("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"));
348
+ };
349
+ const timer = setTimeout(() => {
350
+ signal?.removeEventListener("abort", onAbort);
351
+ resolve();
352
+ }, ms);
353
+ signal?.addEventListener("abort", onAbort, { once: true });
354
+ });
355
+ }
356
+
357
+ // src/qr-server/render.ts
358
+ import fs from "node:fs";
359
+ import { fileURLToPath } from "node:url";
360
+ import { createRequire } from "node:module";
361
+ import path from "node:path";
362
+ import { exec } from "node:child_process";
363
+
364
+ // src/qr-server/server.ts
365
+ import http from "node:http";
366
+ var QrServer = class _QrServer {
367
+ server = null;
368
+ pages = /* @__PURE__ */ new Map();
369
+ port = 0;
370
+ idleTimer = null;
371
+ static IDLE_TIMEOUT_MS = 1e4;
372
+ async start() {
373
+ if (this.server) return this.port;
374
+ return new Promise((resolve, reject) => {
375
+ this.server = http.createServer((req, res) => this.handleRequest(req, res));
376
+ this.server.listen(0, "127.0.0.1", () => {
377
+ const addr = this.server.address();
378
+ if (typeof addr === "object" && addr) {
379
+ this.port = addr.port;
380
+ resolve(this.port);
381
+ } else {
382
+ reject(new Error("Failed to get server address"));
383
+ }
384
+ });
385
+ this.server.on("error", reject);
386
+ });
387
+ }
388
+ registerPage(route, html, qrBuffer, config) {
389
+ const existing = this.pages.get(route);
390
+ if (existing) {
391
+ existing.qrBuffer = qrBuffer;
392
+ existing.status = "waiting";
393
+ existing.config = config;
394
+ const payload = `data: ${JSON.stringify({ status: "waiting" })}
395
+
396
+ `;
397
+ for (const client4 of existing.sseClients) client4.write(payload);
398
+ } else {
399
+ this.pages.set(route, { html, qrBuffer, status: "waiting", sseClients: [], config });
400
+ }
401
+ this.resetIdleTimer();
402
+ }
403
+ unregisterPage(route) {
404
+ const page = this.pages.get(route);
405
+ if (!page) return;
406
+ for (const client4 of page.sseClients) client4.end();
407
+ page.sseClients.length = 0;
408
+ this.pages.delete(route);
409
+ if (this.pages.size === 0) this.close();
410
+ }
411
+ setStatus(route, status) {
412
+ const page = this.pages.get(route);
413
+ if (!page) return;
414
+ page.status = status;
415
+ const payload = `data: ${JSON.stringify({ status })}
416
+
417
+ `;
418
+ for (const client4 of page.sseClients) client4.write(payload);
419
+ }
420
+ close() {
421
+ if (!this.server) return;
422
+ if (this.idleTimer) {
423
+ clearTimeout(this.idleTimer);
424
+ this.idleTimer = null;
425
+ }
426
+ for (const page of this.pages.values()) {
427
+ for (const client4 of page.sseClients) client4.end();
428
+ page.sseClients.length = 0;
429
+ }
430
+ this.pages.clear();
431
+ this.server.close();
432
+ this.server = null;
433
+ this.port = 0;
434
+ instance = null;
435
+ }
436
+ resetIdleTimer() {
437
+ if (this.idleTimer) clearTimeout(this.idleTimer);
438
+ this.idleTimer = setTimeout(() => {
439
+ const hasClients = [...this.pages.values()].some((p) => p.sseClients.length > 0);
440
+ if (!hasClients) this.close();
441
+ }, _QrServer.IDLE_TIMEOUT_MS);
442
+ }
443
+ handleRequest(req, res) {
444
+ const url = req.url ?? "/";
445
+ for (const [route, page] of this.pages) {
446
+ if (url === route) {
447
+ res.writeHead(302, { Location: route + "/" });
448
+ res.end();
449
+ return;
450
+ }
451
+ if (url === route + "/") {
452
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
453
+ res.end(page.html);
454
+ return;
455
+ }
456
+ if (url === route + "/qr.png") {
457
+ res.writeHead(200, { "Content-Type": "image/png", "Content-Length": page.qrBuffer.length });
458
+ res.end(page.qrBuffer);
459
+ return;
460
+ }
461
+ if (url === route + "/events") {
462
+ res.writeHead(200, {
463
+ "Content-Type": "text/event-stream",
464
+ "Cache-Control": "no-cache",
465
+ Connection: "keep-alive"
466
+ });
467
+ res.write(`data: ${JSON.stringify({ status: page.status })}
468
+
469
+ `);
470
+ page.sseClients.push(res);
471
+ req.on("close", () => {
472
+ const idx = page.sseClients.indexOf(res);
473
+ if (idx >= 0) page.sseClients.splice(idx, 1);
474
+ });
475
+ return;
476
+ }
477
+ if (url === route + "/config") {
478
+ res.writeHead(200, { "Content-Type": "application/json" });
479
+ res.end(JSON.stringify(page.config ?? {}));
480
+ return;
481
+ }
482
+ }
483
+ res.writeHead(404, { "Content-Type": "text/plain" });
484
+ res.end("Not Found");
485
+ }
486
+ };
487
+ var instance = null;
488
+ var listenersRegistered = false;
489
+ function cleanup() {
490
+ if (instance) instance.close();
491
+ }
492
+ function ensureProcessListeners() {
493
+ if (listenersRegistered) return;
494
+ listenersRegistered = true;
495
+ process.on("exit", cleanup);
496
+ process.on("SIGINT", cleanup);
497
+ process.on("SIGTERM", cleanup);
498
+ setInterval(() => {
499
+ if (process.stdin?.destroyed) cleanup();
500
+ }, 3e3).unref();
501
+ }
502
+ function getQrServer() {
503
+ if (!instance) {
504
+ instance = new QrServer();
505
+ ensureProcessListeners();
506
+ }
507
+ return instance;
508
+ }
509
+
510
+ // src/qr-server/render.ts
511
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
512
+ var LOGIN_ROUTE = "/login";
513
+ var XIANYU_ROUTE = "/login-xianyu";
514
+ var _require = null;
515
+ async function loadHtml(filename) {
516
+ return fs.promises.readFile(path.join(__dirname, "pages", filename), "utf-8");
517
+ }
518
+ async function generateQRBuffer(content) {
519
+ if (!_require) _require = createRequire(import.meta.url);
520
+ const QRCodeLib = _require("qrcode");
521
+ return QRCodeLib.toBuffer(content, { width: 300, margin: 2 });
522
+ }
523
+ function openUrl(url) {
524
+ const cmd = process.platform === "win32" ? `start "" "${url}"` : process.platform === "darwin" ? `open "${url}"` : `xdg-open "${url}"`;
525
+ exec(cmd);
526
+ }
527
+ async function renderQRPage(route, htmlFile, content, config) {
528
+ const [html, qrBuffer] = await Promise.all([
529
+ loadHtml(htmlFile),
530
+ generateQRBuffer(content)
531
+ ]);
532
+ const server = getQrServer();
533
+ const port = await server.start();
534
+ server.registerPage(route, html, qrBuffer, config);
535
+ const qrUrl = `http://127.0.0.1:${port}${route}/`;
536
+ return {
537
+ url: content,
538
+ qrUrl,
539
+ setStatus: (status) => server.setStatus(route, status),
540
+ closeServer: () => server.unregisterPage(route)
541
+ };
542
+ }
543
+ function renderLoginQR(content) {
544
+ return renderQRPage(LOGIN_ROUTE, "login.html", content);
545
+ }
546
+ function renderXianyuAuthQR(content, authUrl) {
547
+ return renderQRPage(XIANYU_ROUTE, "xianyu-auth.html", content, { authUrl });
548
+ }
549
+
550
+ // src/services/storage/config-store.ts
551
+ import { promises as fs2 } from "node:fs";
552
+ import path2 from "node:path";
553
+ import os from "node:os";
554
+ var CONFIG_FILE_NAME = ".r2-cli";
555
+ var ConfigStore = class {
556
+ configPath;
557
+ config;
558
+ configLoaded = false;
559
+ dirEnsured = false;
560
+ constructor() {
561
+ const homeDir = os.homedir();
562
+ const configDir = path2.join(homeDir, CONFIG_FILE_NAME);
563
+ this.configPath = path2.join(configDir, "config.json");
564
+ this.config = { credentials: null };
565
+ }
566
+ getConfigPath() {
567
+ return this.configPath;
568
+ }
569
+ async loadConfig() {
570
+ if (this.configLoaded) return this.config;
571
+ try {
572
+ const content = await fs2.readFile(this.configPath, "utf-8");
573
+ this.config = JSON.parse(content);
574
+ this.configLoaded = true;
575
+ return this.config;
576
+ } catch {
577
+ this.config = { credentials: null };
578
+ this.configLoaded = true;
579
+ return this.config;
580
+ }
581
+ }
582
+ async ensureDir() {
583
+ if (this.dirEnsured) return;
584
+ const dirPath = path2.dirname(this.configPath);
585
+ try {
586
+ await fs2.stat(dirPath);
587
+ } catch (error) {
588
+ if (error.code === "ENOENT") {
589
+ await fs2.mkdir(dirPath, { recursive: true });
590
+ } else {
591
+ throw new StorageError("Failed to create directory", dirPath, error.code);
592
+ }
593
+ }
594
+ this.dirEnsured = true;
595
+ }
596
+ async saveConfig(config) {
597
+ this.config = config;
598
+ await this.ensureDir();
599
+ const content = JSON.stringify(config, null, 2);
600
+ const tmpPath = this.configPath + ".tmp";
601
+ try {
602
+ await fs2.writeFile(tmpPath, content, "utf-8");
603
+ await fs2.rename(tmpPath, this.configPath);
604
+ this.configLoaded = true;
605
+ } catch (error) {
606
+ await fs2.unlink(tmpPath).catch((e) => {
607
+ if (typeof process.env.DEBUG !== "undefined") console.error("[config] cleanup tmp failed:", e);
608
+ });
609
+ throw new StorageError("Failed to save config", this.configPath, error.code);
610
+ }
611
+ }
612
+ };
613
+ var instance2 = null;
614
+ function getConfigStore() {
615
+ if (!instance2) instance2 = new ConfigStore();
616
+ return instance2;
617
+ }
618
+
619
+ // src/services/storage/auth-storage.ts
620
+ var TOKEN_EXPIRY_MARGIN_MS = 5 * 60 * 1e3;
621
+ var AuthStorage = class {
622
+ store = getConfigStore();
623
+ isTokenExpired(cred) {
624
+ if (!cred.expire) return false;
625
+ return Date.now() >= cred.expire - TOKEN_EXPIRY_MARGIN_MS;
626
+ }
627
+ async saveCredentials(token, userInfo) {
628
+ const now = Date.now();
629
+ const durationMs = userInfo.expire ? Number.parseInt(userInfo.expire, 10) : 0;
630
+ const credentials = {
631
+ token,
632
+ userInfo,
633
+ timestamp: now,
634
+ ...durationMs > 0 && { expire: now + durationMs }
635
+ };
636
+ let config = await this.store.loadConfig();
637
+ config.credentials = credentials;
638
+ await this.store.saveConfig(config);
639
+ }
640
+ async getCredentials() {
641
+ const config = await this.store.loadConfig();
642
+ if (!config.credentials) return null;
643
+ if (this.isTokenExpired(config.credentials)) return null;
644
+ return config.credentials;
645
+ }
646
+ async clearCredentials() {
647
+ const config = await this.store.loadConfig();
648
+ config.credentials = null;
649
+ await this.store.saveConfig(config);
650
+ }
651
+ async getToken() {
652
+ const credentials = await this.getCredentials();
653
+ return credentials?.token ?? null;
654
+ }
655
+ async getUserInfo() {
656
+ const credentials = await this.getCredentials();
657
+ return credentials?.userInfo ?? null;
658
+ }
659
+ async isLoggedIn() {
660
+ const credentials = await this.getCredentials();
661
+ return credentials !== null;
662
+ }
663
+ };
664
+ var instance3 = null;
665
+ function getAuthStorage() {
666
+ if (!instance3) instance3 = new AuthStorage();
667
+ return instance3;
668
+ }
669
+
670
+ // src/services/api/client.ts
671
+ var SERVER_BASEURL = "https://api.qiuxietang.com";
672
+ var ApiClientService = class {
673
+ config;
674
+ authStorage = null;
675
+ cachedToken = null;
676
+ tokenExpiry = 0;
677
+ constructor(config = {}) {
678
+ this.config = {
679
+ baseUrl: config.baseUrl ?? SERVER_BASEURL,
680
+ version: config.version ?? "v3",
681
+ debug: config.debug ?? false
682
+ };
683
+ this.authStorage = config.auth === false ? null : getAuthStorage();
684
+ }
685
+ buildUrl(path4) {
686
+ const cleanPath = path4.startsWith("/") ? path4.slice(1) : path4;
687
+ return `${this.config.baseUrl}/${this.config.version}/${cleanPath}`;
688
+ }
689
+ async getAuthToken() {
690
+ if (!this.authStorage) return void 0;
691
+ if (this.cachedToken && Date.now() < this.tokenExpiry) return this.cachedToken;
692
+ const credentials = await this.authStorage.getCredentials();
693
+ if (!credentials) {
694
+ throw new AuthError("\u8BF7\u5148\u8FD0\u884C r2-cli auth login \u767B\u5F55");
695
+ }
696
+ this.cachedToken = credentials.token;
697
+ this.tokenExpiry = credentials.expire ? credentials.expire - TOKEN_EXPIRY_MARGIN_MS : Date.now() + 30 * 60 * 1e3;
698
+ return credentials.token;
699
+ }
700
+ /**
701
+ * 发起请求,返回完整响应信封(含 token 等顶层字段)
702
+ */
703
+ async requestFull(path4, reqConfig) {
704
+ const url = this.buildUrl(path4);
705
+ const { method, headers: rawHeaders, body, timeout = 3e4 } = reqConfig;
706
+ const token = await this.getAuthToken();
707
+ const headers = { ...rawHeaders, ...token ? { token } : {} };
708
+ const controller = new AbortController();
709
+ const timer = setTimeout(() => controller.abort(), timeout);
710
+ const init = {
711
+ method,
712
+ headers: { "Content-Type": "application/json", ...headers },
713
+ signal: controller.signal
714
+ };
715
+ if (body !== void 0) init.body = JSON.stringify(body);
716
+ if (this.config.debug) {
717
+ console.error(`[API ${method}]`, url, body);
718
+ }
719
+ try {
720
+ const response = await fetch(url, init);
721
+ if (!response.ok) {
722
+ if (response.status === 401) {
723
+ if (this.authStorage) {
724
+ this.cachedToken = null;
725
+ await this.authStorage.clearCredentials().catch((e) => {
726
+ console.error("[API] \u6E05\u9664\u51ED\u8BC1\u5931\u8D25:", e instanceof Error ? e.message : String(e));
727
+ });
728
+ }
729
+ throw new AuthError("\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C r2-cli auth login \u91CD\u65B0\u767B\u5F55");
730
+ }
731
+ const errorText = await response.text();
732
+ throw new ApiError(errorText || `${response.status} ${response.statusText}`, response.status);
733
+ }
734
+ const result = await response.json();
735
+ if (this.config.debug) {
736
+ console.error("[API Response]", result);
737
+ }
738
+ if (!result.success || result.status !== 0) {
739
+ throw new ApiError(result.msg || "\u672A\u77E5\u9519\u8BEF", result.status, result);
740
+ }
741
+ return result;
742
+ } catch (error) {
743
+ if (error instanceof DOMException && error.name === "AbortError") {
744
+ throw new ApiError(`\u8BF7\u6C42\u8D85\u65F6 (${timeout}ms)`, 408);
745
+ }
746
+ throw error;
747
+ } finally {
748
+ clearTimeout(timer);
749
+ }
750
+ }
751
+ async request(path4, config) {
752
+ const result = await this.requestFull(path4, config);
753
+ return result.data;
754
+ }
755
+ async get(path4, params, headers) {
756
+ const fullPath = params && params.size > 0 ? `${path4}?${params.toString()}` : path4;
757
+ return this.request(fullPath, { method: "GET", headers });
758
+ }
759
+ async post(path4, body, headers) {
760
+ return this.request(path4, { method: "POST", body, headers });
761
+ }
762
+ async put(path4, body, headers) {
763
+ return this.request(path4, { method: "PUT", body, headers });
764
+ }
765
+ async delete(path4, headers) {
766
+ return this.request(path4, { method: "DELETE", headers });
767
+ }
768
+ /** 上传文件(multipart/form-data),不设置 Content-Type 让运行时自动处理 boundary */
769
+ async upload(path4, formData, headers) {
770
+ const url = this.buildUrl(path4);
771
+ const token = await this.getAuthToken();
772
+ const allHeaders = { ...headers, ...token ? { token } : {} };
773
+ const controller = new AbortController();
774
+ const timer = setTimeout(() => controller.abort(), 6e4);
775
+ const init = {
776
+ method: "POST",
777
+ headers: allHeaders,
778
+ body: formData,
779
+ signal: controller.signal
780
+ };
781
+ if (this.config.debug) {
782
+ console.error("[API UPLOAD]", url);
783
+ }
784
+ try {
785
+ const response = await fetch(url, init);
786
+ if (!response.ok) {
787
+ if (response.status === 401) {
788
+ if (this.authStorage) {
789
+ this.cachedToken = null;
790
+ await this.authStorage.clearCredentials().catch(() => {
791
+ });
792
+ }
793
+ throw new AuthError("\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C r2-cli auth login \u91CD\u65B0\u767B\u5F55");
794
+ }
795
+ const errorText = await response.text();
796
+ throw new ApiError(errorText || `${response.status} ${response.statusText}`, response.status);
797
+ }
798
+ const result = await response.json();
799
+ if (this.config.debug) {
800
+ console.error("[API Response]", result);
801
+ }
802
+ if (!result.success || result.status !== 0) {
803
+ throw new ApiError(result.msg || "\u672A\u77E5\u9519\u8BEF", result.status, result);
804
+ }
805
+ return result.data;
806
+ } catch (error) {
807
+ if (error instanceof DOMException && error.name === "AbortError") {
808
+ throw new ApiError("\u4E0A\u4F20\u8D85\u65F6 (60000ms)", 408);
809
+ }
810
+ throw error;
811
+ } finally {
812
+ clearTimeout(timer);
813
+ }
814
+ }
815
+ };
816
+ var authClient = new ApiClientService();
817
+ var noAuthClient = new ApiClientService({ auth: false });
818
+
819
+ // src/services/api/modules/qrcode-auth.ts
820
+ var client = noAuthClient;
821
+ async function generateQRCode() {
822
+ return client.post("app/qrcode/generate");
823
+ }
824
+ async function getQRCodeStatus(qrToken) {
825
+ const params = new URLSearchParams();
826
+ params.append("qrToken", qrToken);
827
+ const fullPath = `app/qrcode/status?${params.toString()}`;
828
+ const full = await client.requestFull(fullPath, { method: "GET" });
829
+ if (full.token && typeof full.data === "object" && full.data !== null) {
830
+ full.data.token = full.token;
831
+ }
832
+ return full.data;
833
+ }
834
+
835
+ // src/services/auth/login.ts
836
+ async function displayUserInfo(userInfo, lastLogin, daysSinceLogin) {
837
+ const { UserInfoCard: UserInfoCard2 } = await Promise.resolve().then(() => (init_UserInfoCard(), UserInfoCard_exports));
838
+ const { renderComponent: renderComponent2 } = await Promise.resolve().then(() => (init_render(), render_exports));
839
+ const props = lastLogin != null ? { userInfo, lastLogin, daysSinceLogin: daysSinceLogin ?? 0 } : { userInfo };
840
+ renderComponent2(UserInfoCard2, props);
841
+ }
842
+ var LoginService = class {
843
+ storage;
844
+ constructor(storage) {
845
+ this.storage = storage ?? getAuthStorage();
846
+ }
847
+ async generateQR() {
848
+ const qrData = await generateQRCode();
849
+ const qrContent = `https://m.puresnake.com/r2/auth/login?qrToken=${qrData.qrContent}&from=wechat`;
850
+ const rendered = await renderLoginQR(qrContent);
851
+ return { qrData, ...rendered };
852
+ }
853
+ async waitForLogin(qrToken, expireTimeMs, pollIntervalMs, signal, setStatus, silent) {
854
+ const result = await poll(
855
+ () => getQRCodeStatus(qrToken),
856
+ {
857
+ interval: pollIntervalMs,
858
+ timeout: expireTimeMs,
859
+ condition: (data) => {
860
+ switch (data.status) {
861
+ case "scanned":
862
+ if (!silent) {
863
+ console.log(chalk2.cyan(`
864
+ \u{1F50D} \u5DF2\u626B\u7801: ${data.userInfo?.nickname || "\u672A\u77E5\u7528\u6237"}`));
865
+ console.log(chalk2.yellow("\u8BF7\u5728 APP \u4E0A\u786E\u8BA4\u767B\u5F55"));
866
+ }
867
+ setStatus?.("scanning");
868
+ return false;
869
+ case "confirmed":
870
+ if (!silent) console.log(chalk2.green("\n\u2705 \u7528\u6237\u5DF2\u786E\u8BA4\u767B\u5F55"));
871
+ setStatus?.("success");
872
+ return true;
873
+ case "expired":
874
+ if (!silent) console.log(chalk2.red("\n\u23F0 \u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F"));
875
+ setStatus?.("expired");
876
+ return true;
877
+ case "canceled":
878
+ if (!silent) console.log(chalk2.red("\n\u{1F6AB} \u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55"));
879
+ setStatus?.("expired");
880
+ return true;
881
+ default:
882
+ return false;
883
+ }
884
+ }
885
+ },
886
+ signal ?? void 0
887
+ );
888
+ if (result.status === "confirmed" && result.token && result.userInfo) {
889
+ await this.storage.saveCredentials(result.token, result.userInfo);
890
+ return { userInfo: result.userInfo, token: result.token };
891
+ }
892
+ if (result.status === "expired") throw new AuthError("\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55");
893
+ if (result.status === "canceled") throw new AuthError("\u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55");
894
+ throw new AuthError("\u767B\u5F55\u5931\u8D25: \u672A\u83B7\u53D6\u5230\u51ED\u8BC1");
895
+ }
896
+ async login(signal) {
897
+ console.log(chalk2.cyan("\n\u{1F510} \u6B63\u5728\u542F\u52A8\u626B\u7801\u767B\u5F55..."));
898
+ const { qrData, qrUrl, setStatus, closeServer } = await this.generateQR();
899
+ console.log(chalk2.green("\u2705 \u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\n"));
900
+ console.log(chalk2.cyan(` \u94FE\u63A5: ${qrUrl}
901
+ `));
902
+ openUrl(qrUrl);
903
+ console.log(chalk2.yellow("\u23F3 \u7B49\u5F85\u626B\u7801...\n"));
904
+ const expireTimeMs = Number.parseInt(qrData.expireTime, 10);
905
+ const pollIntervalMs = Number.parseInt(qrData.pollInterval, 10);
906
+ try {
907
+ const result = await this.waitForLogin(qrData.qrToken, expireTimeMs, pollIntervalMs, signal, setStatus);
908
+ console.log(chalk2.green("\n\u2705 \u767B\u5F55\u6210\u529F\uFF01\n"));
909
+ displayUserInfo(result.userInfo);
910
+ return result;
911
+ } catch (error) {
912
+ console.log(chalk2.red("\n\u274C \u767B\u5F55\u5931\u8D25\n"));
913
+ throw error;
914
+ } finally {
915
+ closeServer();
916
+ }
917
+ }
918
+ async logout() {
919
+ console.log(chalk2.cyan("\n\u{1F6AA} \u6B63\u5728\u9000\u51FA\u767B\u5F55..."));
920
+ await this.storage.clearCredentials();
921
+ console.log(chalk2.green("\u2705 \u5DF2\u9000\u51FA\u767B\u5F55\n"));
922
+ }
923
+ async status() {
924
+ const isLoggedIn = await this.storage.isLoggedIn();
925
+ if (!isLoggedIn) {
926
+ console.log(chalk2.yellow("\u26A0\uFE0F \u5C1A\u672A\u767B\u5F55\u6216\u51ED\u8BC1\u5DF2\u8FC7\u671F\n"));
927
+ return;
928
+ }
929
+ const credentials = await this.storage.getCredentials();
930
+ const userInfo = credentials.userInfo;
931
+ const lastLogin = new Date(credentials.timestamp);
932
+ const daysSinceLogin = Math.floor((Date.now() - credentials.timestamp) / (1e3 * 60 * 60 * 24));
933
+ console.log(chalk2.green("\u2705 \u5DF2\u767B\u5F55\n"));
934
+ await displayUserInfo(userInfo, lastLogin, daysSinceLogin);
935
+ }
936
+ };
937
+ var loginInstance = null;
938
+ function getLoginService() {
939
+ if (!loginInstance) loginInstance = new LoginService();
940
+ return loginInstance;
941
+ }
942
+
943
+ // src/services/auth/xianyu-auth.ts
944
+ import chalk3 from "chalk";
945
+
946
+ // src/services/api/modules/xianyu-auth.ts
947
+ var client2 = authClient;
948
+ async function getAuthUrl() {
949
+ return client2.get("mms/xianyu/auth/url");
950
+ }
951
+ async function getAuthStatus(state) {
952
+ const params = new URLSearchParams({ state });
953
+ return client2.get("mms/xianyu/auth/status", params);
954
+ }
955
+
956
+ // src/services/auth/xianyu-auth.ts
957
+ async function generateAuthQR() {
958
+ const authData = await getAuthUrl();
959
+ const rendered = await renderXianyuAuthQR(authData.url, authData.url);
960
+ return { authData, ...rendered };
961
+ }
962
+ async function waitForAuth(state, expireMs, intervalMs, signal, setStatus) {
963
+ return poll(
964
+ () => getAuthStatus(state),
965
+ {
966
+ interval: intervalMs,
967
+ timeout: expireMs,
968
+ condition: (data) => {
969
+ if (data.status === "success") {
970
+ console.log(chalk3.green(`
971
+ \u2705 \u6388\u6743\u6210\u529F\uFF01\u5E97\u94FA: ${data.shopName} (${data.shopId})`));
972
+ setStatus?.("success");
973
+ return true;
974
+ }
975
+ if (data.status === "expired") {
976
+ console.log(chalk3.red("\n\u23F0 \u6388\u6743\u94FE\u63A5\u5DF2\u8FC7\u671F"));
977
+ setStatus?.("expired");
978
+ return true;
979
+ }
980
+ return false;
981
+ }
982
+ },
983
+ signal
984
+ );
985
+ }
986
+ async function authorize(signal) {
987
+ console.log(chalk3.cyan("\n\u{1F517} \u6B63\u5728\u83B7\u53D6\u95F2\u9C7C\u6388\u6743\u5730\u5740..."));
988
+ const { authData, qrUrl, setStatus, closeServer } = await generateAuthQR();
989
+ console.log(chalk3.green("\u2705 \u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\n"));
990
+ console.log(chalk3.cyan(` \u94FE\u63A5: ${qrUrl}`));
991
+ console.log(chalk3.gray(` \u6216\u590D\u5236\u94FE\u63A5\u6253\u5F00: ${authData.url}`));
992
+ openUrl(qrUrl);
993
+ console.log(chalk3.yellow("\n\u23F3 \u7B49\u5F85\u6388\u6743...\n"));
994
+ const expireMs = authData.expireTime ? Number.parseInt(authData.expireTime, 10) : 3e5;
995
+ const intervalMs = authData.pollInterval ? Number.parseInt(authData.pollInterval, 10) : 1e3;
996
+ try {
997
+ const result = await waitForAuth(authData.state, expireMs, intervalMs, signal, setStatus);
998
+ if (result.status === "success") return result;
999
+ throw new AuthError("\u95F2\u9C7C\u6388\u6743\u5931\u8D25: " + (result.status === "expired" ? "\u94FE\u63A5\u5DF2\u8FC7\u671F" : "\u672A\u77E5\u72B6\u6001"));
1000
+ } finally {
1001
+ closeServer();
1002
+ }
1003
+ }
1004
+
1005
+ // src/commands/shared.ts
1006
+ import chalk4 from "chalk";
1007
+ function handleCommandError(error) {
1008
+ if (error instanceof AuthError) {
1009
+ console.error(chalk4.red(`
1010
+ \u25B2 ${error.message}`));
1011
+ console.error(chalk4.gray(`\u2192 \u8BF7\u5148\u8FD0\u884C: r2-cli auth login
1012
+ `));
1013
+ } else if (error instanceof ApiError) {
1014
+ console.error(chalk4.red(`\u25B2 \u64CD\u4F5C\u5931\u8D25: ${error.message}`));
1015
+ if (error.status) {
1016
+ console.error(chalk4.gray(` \u72B6\u6001\u7801: ${error.status}`));
1017
+ }
1018
+ } else if (error instanceof StorageError) {
1019
+ console.error(chalk4.red(`\u25B2 \u914D\u7F6E\u6587\u4EF6\u5F02\u5E38: ${error.message}`));
1020
+ if (error.path) console.error(chalk4.gray(` \u8DEF\u5F84: ${error.path}`));
1021
+ console.error(chalk4.gray(`\u2192 \u8BF7\u5C1D\u8BD5\u91CD\u65B0\u767B\u5F55: r2-cli auth login
1022
+ `));
1023
+ } else {
1024
+ const msg = error instanceof Error ? error.message : String(error);
1025
+ console.error(chalk4.red(`\u25B2 ${msg}`));
1026
+ }
1027
+ process.exit(1);
1028
+ }
1029
+ function agentError(msg) {
1030
+ console.log(JSON.stringify({ success: false, error: msg }));
1031
+ process.exit(1);
1032
+ }
1033
+ function jsonAction(fn) {
1034
+ return async (options) => {
1035
+ try {
1036
+ await fn(options);
1037
+ } catch (error) {
1038
+ if (options.json) {
1039
+ const msg = error instanceof Error ? error.message : String(error);
1040
+ const status = error instanceof ApiError ? error.status : void 0;
1041
+ console.log(JSON.stringify({ success: false, error: msg, ...status != null && { status } }));
1042
+ process.exit(1);
1043
+ }
1044
+ handleCommandError(error);
1045
+ }
1046
+ };
1047
+ }
1048
+ function agentAction(fn) {
1049
+ return async (...args) => {
1050
+ try {
1051
+ await fn(...args);
1052
+ } catch (error) {
1053
+ const msg = error instanceof Error ? error.message : String(error);
1054
+ agentError(msg);
1055
+ }
1056
+ };
1057
+ }
1058
+ var SENSITIVE_KEYS = /* @__PURE__ */ new Set(["accessToken", "refreshExpireIn"]);
1059
+ function sanitizeShops(shops) {
1060
+ return shops.map((shop) => {
1061
+ const safe = {};
1062
+ for (const [key, value] of Object.entries(shop)) {
1063
+ if (!SENSITIVE_KEYS.has(key)) safe[key] = value;
1064
+ }
1065
+ return safe;
1066
+ });
1067
+ }
1068
+
1069
+ // src/commands/auth/qr-flow.ts
1070
+ async function runQRJsonFlow(config) {
1071
+ const { qrInfo, qrUrl, setStatus, closeServer, waitArgs } = await config.generate();
1072
+ console.log(JSON.stringify(qrInfo, null, 2));
1073
+ openUrl(qrUrl);
1074
+ try {
1075
+ const result = await config.waitResult(waitArgs, setStatus);
1076
+ console.log(JSON.stringify(config.formatSuccess(result)));
1077
+ } catch (error) {
1078
+ const msg = error instanceof Error ? error.message : String(error);
1079
+ console.log(JSON.stringify({ success: false, error: msg }));
1080
+ process.exit(1);
1081
+ } finally {
1082
+ setTimeout(closeServer, 1e3);
1083
+ }
1084
+ }
1085
+
1086
+ // src/commands/auth/login.ts
1087
+ function createLoginCommand() {
1088
+ const command = new Command("login");
1089
+ command.description("\u626B\u7801\u767B\u5F55 Round2AI \u8D26\u6237").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
1090
+ const pollCmd = new Command("poll").description("\u8F6E\u8BE2\u767B\u5F55\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--token <qrToken>", "\u4E8C\u7EF4\u7801 token").option("--expire <ms>", "\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09", "300000").option("--interval <ms>", "\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09", "1000").action(agentAction(async (options) => {
1091
+ const service = getLoginService();
1092
+ const result = await service.waitForLogin(
1093
+ options.token,
1094
+ Number.parseInt(options.expire, 10),
1095
+ Number.parseInt(options.interval, 10)
1096
+ );
1097
+ console.log(JSON.stringify({ success: true, ...result }));
1098
+ }));
1099
+ command.addCommand(pollCmd);
1100
+ command.action(async (options) => {
1101
+ try {
1102
+ if (options.json) {
1103
+ await runQRJsonFlow({
1104
+ generate: async () => {
1105
+ const service = getLoginService();
1106
+ const { qrData, qrUrl, setStatus, closeServer } = await service.generateQR();
1107
+ const expireMs = Number.parseInt(qrData.expireTime, 10);
1108
+ const intervalMs = Number.parseInt(qrData.pollInterval, 10);
1109
+ return {
1110
+ qrInfo: {
1111
+ qrToken: qrData.qrToken,
1112
+ expireTimeMs: expireMs,
1113
+ pollIntervalMs: intervalMs,
1114
+ url: `https://m.puresnake.com/r2/auth/login?qrToken=${qrData.qrContent}&from=wechat`,
1115
+ qrUrl
1116
+ },
1117
+ qrUrl,
1118
+ setStatus,
1119
+ closeServer,
1120
+ waitArgs: { qrToken: qrData.qrToken, expireMs, intervalMs }
1121
+ };
1122
+ },
1123
+ waitResult: ({ qrToken, expireMs, intervalMs }, setStatus) => getLoginService().waitForLogin(qrToken, expireMs, intervalMs, void 0, setStatus, true),
1124
+ formatSuccess: (result) => ({ success: true, userInfo: result.userInfo })
1125
+ });
1126
+ } else {
1127
+ await getLoginService().login();
1128
+ }
1129
+ } catch (error) {
1130
+ if (options.json) {
1131
+ const msg = error instanceof Error ? error.message : String(error);
1132
+ console.log(JSON.stringify({ success: false, error: msg }));
1133
+ process.exit(1);
1134
+ }
1135
+ handleCommandError(error);
1136
+ }
1137
+ });
1138
+ return command;
1139
+ }
1140
+
1141
+ // src/commands/auth/logout.ts
1142
+ import { Command as Command2 } from "commander";
1143
+ function createLogoutCommand() {
1144
+ const command = new Command2("logout");
1145
+ command.description("\u9000\u51FA\u767B\u5F55");
1146
+ command.action(async () => {
1147
+ try {
1148
+ const loginService = getLoginService();
1149
+ await loginService.logout();
1150
+ } catch (error) {
1151
+ handleCommandError(error);
1152
+ }
1153
+ });
1154
+ return command;
1155
+ }
1156
+
1157
+ // src/commands/auth/status.ts
1158
+ import { Command as Command3 } from "commander";
1159
+ function createStatusCommand() {
1160
+ const command = new Command3("status");
1161
+ command.description("\u67E5\u770B\u767B\u5F55\u72B6\u6001");
1162
+ command.action(async () => {
1163
+ try {
1164
+ const loginService = getLoginService();
1165
+ await loginService.status();
1166
+ } catch (error) {
1167
+ handleCommandError(error);
1168
+ }
1169
+ });
1170
+ return command;
1171
+ }
1172
+
1173
+ // src/commands/auth/xianyu.ts
1174
+ import { Command as Command4 } from "commander";
1175
+ function createXianyuAuthCommand() {
1176
+ const command = new Command4("xianyu");
1177
+ command.description("\u95F2\u9C7C\u5E97\u94FA\u6388\u6743").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
1178
+ const pollCmd = new Command4("poll").description("\u8F6E\u8BE2\u95F2\u9C7C\u6388\u6743\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--state <state>", "\u6388\u6743\u8F6E\u8BE2 token").option("--expire <ms>", "\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09", "300000").option("--interval <ms>", "\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09", "1000").action(agentAction(async (options) => {
1179
+ const result = await waitForAuth(
1180
+ options.state,
1181
+ Number.parseInt(options.expire, 10),
1182
+ Number.parseInt(options.interval, 10)
1183
+ );
1184
+ if (result.status === "success") {
1185
+ console.log(JSON.stringify({ success: true, shopId: result.shopId, shopName: result.shopName }));
1186
+ } else {
1187
+ agentError(`\u6388\u6743\u72B6\u6001: ${result.status}`);
1188
+ }
1189
+ }));
1190
+ command.addCommand(pollCmd);
1191
+ command.action(async (options) => {
1192
+ try {
1193
+ if (options.json) {
1194
+ await runQRJsonFlow({
1195
+ generate: async () => {
1196
+ const { authData, qrUrl, setStatus, closeServer } = await generateAuthQR();
1197
+ const expireMs = authData.expireTime ? Number.parseInt(authData.expireTime, 10) : 3e5;
1198
+ const intervalMs = authData.pollInterval ? Number.parseInt(authData.pollInterval, 10) : 1e3;
1199
+ return {
1200
+ qrInfo: {
1201
+ state: authData.state,
1202
+ expireTimeMs: expireMs,
1203
+ pollIntervalMs: intervalMs,
1204
+ qrUrl
1205
+ },
1206
+ qrUrl,
1207
+ setStatus,
1208
+ closeServer,
1209
+ waitArgs: { state: authData.state, expireMs, intervalMs }
1210
+ };
1211
+ },
1212
+ waitResult: async ({ state, expireMs, intervalMs }, setStatus) => {
1213
+ const result = await waitForAuth(state, expireMs, intervalMs, void 0, setStatus);
1214
+ if (result.status !== "success") throw new Error(`\u6388\u6743\u72B6\u6001: ${result.status}`);
1215
+ return result;
1216
+ },
1217
+ formatSuccess: (result) => ({ success: true, shopId: result.shopId, shopName: result.shopName })
1218
+ });
1219
+ } else {
1220
+ await authorize();
1221
+ }
1222
+ } catch (error) {
1223
+ if (options.json) {
1224
+ const msg = error instanceof Error ? error.message : String(error);
1225
+ console.log(JSON.stringify({ success: false, error: msg }));
1226
+ process.exit(1);
1227
+ }
1228
+ handleCommandError(error);
1229
+ }
1230
+ });
1231
+ return command;
1232
+ }
1233
+
1234
+ // src/commands/goods/index.ts
1235
+ import { Command as Command14 } from "commander";
1236
+
1237
+ // src/commands/goods/up/index.ts
1238
+ import { Command as Command5 } from "commander";
1239
+ import chalk5 from "chalk";
1240
+ import { select, input, confirm } from "@inquirer/prompts";
1241
+
1242
+ // src/services/api/modules/goods.ts
1243
+ import { readFileSync } from "node:fs";
1244
+ import { basename } from "node:path";
1245
+
1246
+ // src/utils/params.ts
1247
+ function toParams(obj) {
1248
+ const params = new URLSearchParams();
1249
+ for (const [key, value] of Object.entries(obj)) {
1250
+ if (value !== void 0 && value !== null && value !== "") {
1251
+ params.append(key, String(value));
1252
+ }
1253
+ }
1254
+ return params;
1255
+ }
1256
+
1257
+ // src/services/api/modules/goods.ts
1258
+ var client3 = authClient;
1259
+ async function listingUpXianyu(params) {
1260
+ return client3.post("mms/goods/listing/up/xianyu", params);
1261
+ }
1262
+ async function getListingInfo(params) {
1263
+ return client3.get("mms/goods/listing/get", toParams({ ...params }));
1264
+ }
1265
+ async function listingDownXianyu(params) {
1266
+ return client3.post("mms/goods/listing/down/xianyu", params);
1267
+ }
1268
+ async function listingUpdatePrice(params) {
1269
+ return client3.post("mms/goods/listing/update/xyPrice", params);
1270
+ }
1271
+ async function updateGoodsInfo(params) {
1272
+ return client3.post("mms/goods/listing/update/goodsInfo", params);
1273
+ }
1274
+ async function getListingList(params) {
1275
+ return client3.get("mms/goods/listing/list", params ? toParams({ ...params }) : void 0);
1276
+ }
1277
+ async function getUserShopList() {
1278
+ const data = await client3.get("mms/user/shop/list");
1279
+ return data ?? [];
1280
+ }
1281
+ async function getUserStockList() {
1282
+ const data = await client3.get("mms/user/stock/list");
1283
+ return data ?? [];
1284
+ }
1285
+ async function getSelectGoodsList(params) {
1286
+ const queryParams = params ? toParams({ ...params }) : void 0;
1287
+ return client3.get("mms/seller/goods/select/list", queryParams);
1288
+ }
1289
+ async function uploadXyImages(shopId, filePaths) {
1290
+ const results = [];
1291
+ for (const filePath of filePaths) {
1292
+ const fileBuffer = readFileSync(filePath);
1293
+ const fileName = basename(filePath);
1294
+ const formData = new FormData();
1295
+ formData.append("file", new Blob([fileBuffer]), fileName);
1296
+ const result = await client3.upload(
1297
+ `platform/xy/media/upload?shopId=${encodeURIComponent(shopId)}`,
1298
+ formData
1299
+ );
1300
+ results.push(result);
1301
+ }
1302
+ return results;
1303
+ }
1304
+ async function listingHangUpXianyu(params) {
1305
+ return client3.post("mms/goods/listing/hang/up/xianyu", params);
1306
+ }
1307
+ async function getXyCategories(spBizType = 16) {
1308
+ const data = await client3.get("platform/xy/cat", toParams({ spBizType }));
1309
+ return data ?? [];
1310
+ }
1311
+ async function getXyProps(channelCatId) {
1312
+ const data = await client3.get("platform/xy/props", toParams({ channelCatId }));
1313
+ return data ?? [];
1314
+ }
1315
+ async function getXyPropValues(channelCatId, propId, key) {
1316
+ const data = await client3.get("platform/xy/props/value", toParams({ channelCatId, propId, key }));
1317
+ return data ?? [];
1318
+ }
1319
+
1320
+ // src/commands/goods/up/index.ts
1321
+ var LISTING_POLL_INTERVAL = 2e3;
1322
+ var LISTING_POLL_TIMEOUT = 1e4;
1323
+ function isProcessing(info) {
1324
+ const status = info.status?.toLowerCase() ?? "";
1325
+ return status === "" || status === "init" || status === "pending" || status === "processing";
1326
+ }
1327
+ async function pollListingStatus(stockGoodsId, shopId, platform, json) {
1328
+ if (!json) {
1329
+ process.stdout.write(chalk5.cyan("\u23F3 \u6B63\u5728\u67E5\u8BE2\u4E0A\u67B6\u8FDB\u5EA6..."));
1330
+ }
1331
+ const result = await poll(
1332
+ () => getListingInfo({ stockGoodsId, shopId, platform }),
1333
+ {
1334
+ interval: LISTING_POLL_INTERVAL,
1335
+ timeout: LISTING_POLL_TIMEOUT,
1336
+ condition: (data) => !isProcessing(data)
1337
+ }
1338
+ );
1339
+ if (!json) {
1340
+ process.stdout.write("\r" + " ".repeat(30) + "\r");
1341
+ }
1342
+ return result;
1343
+ }
1344
+ function createUpCommand() {
1345
+ const command = new Command5("up");
1346
+ command.description("\u4E0A\u67B6\u5546\u54C1\u5230\u95F2\u9C7C");
1347
+ command.option("--stock-goods-id <id>", "\u5E93\u5B58\u5546\u54C1ID\uFF08\u4ECE goods list \u83B7\u53D6\uFF09").option("--shop-id <id>", "\u5E97\u94FAID\uFF08\u4ECE goods shops \u83B7\u53D6\uFF09").option("--price <amount>", "\u4E0A\u67B6\u4EF7\u683C").option("-p, --platform <platform>", "\u5E73\u53F0", "xianyu").option("--json", "\u8F93\u51FA JSON\uFF08Agent \u7528\uFF09").action(jsonAction(async (options) => {
1348
+ if (options.json && !(options.stockGoodsId && options.shopId && options.price)) {
1349
+ console.log(JSON.stringify({ success: false, error: "Agent \u6A21\u5F0F\u9700\u8981 --stock-goods-id, --shop-id, --price" }));
1350
+ process.exit(1);
1351
+ }
1352
+ if (options.stockGoodsId && options.shopId && options.price) {
1353
+ const stockGoodsId2 = Number(options.stockGoodsId);
1354
+ const shopId = options.shopId;
1355
+ const price = Number(options.price);
1356
+ const platform = options.platform;
1357
+ const result = await listingUpXianyu({ stockGoodsId: stockGoodsId2, shopId, price, platform });
1358
+ const listingInfo2 = await pollListingStatus(stockGoodsId2, shopId, platform, options.json);
1359
+ if (options.json) {
1360
+ console.log(JSON.stringify({ success: true, data: { submit: result, listing: listingInfo2 } }, null, 2));
1361
+ } else {
1362
+ const statusOk2 = listingInfo2.status?.toLowerCase() !== "failed";
1363
+ console.log(statusOk2 ? chalk5.green("\u2713 \u4E0A\u67B6\u6210\u529F") : chalk5.red("\u2717 \u4E0A\u67B6\u5931\u8D25"));
1364
+ console.log(JSON.stringify(listingInfo2, null, 2));
1365
+ }
1366
+ return;
1367
+ }
1368
+ const shops = await getUserShopList();
1369
+ if (shops.length === 0) {
1370
+ console.log(chalk5.yellow("\u6CA1\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF0C\u8BF7\u5148\u8FD0\u884C r2-cli auth xianyu \u6388\u6743"));
1371
+ return;
1372
+ }
1373
+ const selectedShop = await select({
1374
+ message: "\u9009\u62E9\u5E97\u94FA",
1375
+ choices: shops.map((s) => ({ name: `${s.shopName} (${s.platform})`, value: s.shopId }))
1376
+ });
1377
+ const stocks = await getUserStockList();
1378
+ if (stocks.length === 0) {
1379
+ console.log(chalk5.yellow("\u6CA1\u6709\u53EF\u7528\u7684\u4ED3\u5E93"));
1380
+ return;
1381
+ }
1382
+ const selectedStock = await select({
1383
+ message: "\u9009\u62E9\u4ED3\u5E93",
1384
+ choices: stocks.map((s) => ({ name: s.stockName, value: s.stockId }))
1385
+ });
1386
+ const goodsList = await getSelectGoodsList({ stockId: selectedStock, size: 100 });
1387
+ if (!goodsList.items?.length) {
1388
+ console.log(chalk5.yellow("\u8BE5\u4ED3\u5E93\u6CA1\u6709\u53EF\u9009\u7684\u5546\u54C1"));
1389
+ return;
1390
+ }
1391
+ const selectedGoods = await select({
1392
+ message: "\u9009\u62E9\u5546\u54C1",
1393
+ choices: goodsList.items.map((g) => ({
1394
+ name: `${g.goodsName} ${g.size ? `| ${g.size}` : ""} | \xA5${g.salePrice}`,
1395
+ value: g.stockGoodsId
1396
+ }))
1397
+ });
1398
+ const priceInput = await input({
1399
+ message: "\u8F93\u5165\u4E0A\u67B6\u4EF7\u683C",
1400
+ default: goodsList.items.find((g) => g.stockGoodsId === selectedGoods)?.salePrice?.toString() ?? "",
1401
+ validate: (v) => {
1402
+ const n = Number(v);
1403
+ return n > 0 ? true : "\u4EF7\u683C\u5FC5\u987B\u4E3A\u6B63\u6570";
1404
+ }
1405
+ });
1406
+ const confirmed = await confirm({
1407
+ message: `\u786E\u8BA4\u4E0A\u67B6\uFF1F\u4EF7\u683C \xA5${priceInput}`,
1408
+ default: true
1409
+ });
1410
+ if (!confirmed) {
1411
+ console.log(chalk5.gray("\u5DF2\u53D6\u6D88"));
1412
+ return;
1413
+ }
1414
+ const stockGoodsId = Number(selectedGoods);
1415
+ await listingUpXianyu({
1416
+ stockGoodsId,
1417
+ shopId: selectedShop,
1418
+ price: Number(priceInput),
1419
+ platform: "xianyu"
1420
+ });
1421
+ console.log(chalk5.green("\u2713 \u4E0A\u67B6\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u67E5\u8BE2\u8FDB\u5EA6..."));
1422
+ const listingInfo = await pollListingStatus(stockGoodsId, selectedShop, "xianyu");
1423
+ const statusOk = listingInfo.status?.toLowerCase() !== "failed";
1424
+ console.log(statusOk ? chalk5.green("\u2713 \u4E0A\u67B6\u6210\u529F") : chalk5.red("\u2717 \u4E0A\u67B6\u5931\u8D25"));
1425
+ console.log(JSON.stringify(listingInfo, null, 2));
1426
+ }));
1427
+ return command;
1428
+ }
1429
+
1430
+ // src/commands/goods/shops.ts
1431
+ import { Command as Command6 } from "commander";
1432
+ import chalk6 from "chalk";
1433
+ function createShopsCommand() {
1434
+ const command = new Command6("shops");
1435
+ command.description("\u67E5\u770B\u6240\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF08\u8DE8\u5E73\u53F0\uFF09");
1436
+ command.option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
1437
+ command.action(jsonAction(async (options) => {
1438
+ const shops = await getUserShopList();
1439
+ if (options.json) {
1440
+ console.log(JSON.stringify(sanitizeShops(shops), null, 2));
1441
+ return;
1442
+ }
1443
+ if (!shops.length) {
1444
+ console.log(chalk6.yellow("\u672A\u627E\u5230\u5DF2\u6388\u6743\u7684\u5E97\u94FA"));
1445
+ console.log(chalk6.gray(" \u63D0\u793A: \u8BF7\u5148\u5728\u7B2C\u4E8C\u56DE\u5408 APP \u4E2D\u6388\u6743\u5E97\u94FA"));
1446
+ return;
1447
+ }
1448
+ const { ShopsTable: ShopsTable2 } = await Promise.resolve().then(() => (init_ShopsTable(), ShopsTable_exports));
1449
+ const { renderComponent: renderComponent2 } = await Promise.resolve().then(() => (init_render(), render_exports));
1450
+ renderComponent2(ShopsTable2, { shops, platform: "all" });
1451
+ }));
1452
+ return command;
1453
+ }
1454
+
1455
+ // src/commands/goods/stocks.ts
1456
+ import { Command as Command7 } from "commander";
1457
+ import chalk7 from "chalk";
1458
+ function createStocksCommand() {
1459
+ const command = new Command7("stocks");
1460
+ command.description("\u67E5\u770B\u6240\u6709\u4ED3\u5E93");
1461
+ command.option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
1462
+ command.action(jsonAction(async (options) => {
1463
+ const stocks = await getUserStockList();
1464
+ if (options.json) {
1465
+ console.log(JSON.stringify(stocks, null, 2));
1466
+ return;
1467
+ }
1468
+ if (!stocks.length) {
1469
+ console.log(chalk7.yellow("\u672A\u627E\u5230\u4ED3\u5E93\u4FE1\u606F"));
1470
+ return;
1471
+ }
1472
+ const { StocksTable: StocksTable2 } = await Promise.resolve().then(() => (init_StocksTable(), StocksTable_exports));
1473
+ const { renderComponent: renderComponent2 } = await Promise.resolve().then(() => (init_render(), render_exports));
1474
+ renderComponent2(StocksTable2, { stocks });
1475
+ }));
1476
+ return command;
1477
+ }
1478
+
1479
+ // src/commands/goods/list.ts
1480
+ import { Command as Command8 } from "commander";
1481
+ import chalk8 from "chalk";
1482
+ function createListCommand() {
1483
+ const command = new Command8("list");
1484
+ command.description("\u67E5\u770B\u4ED3\u5E93\u4E2D\u7684\u9009\u54C1\u5546\u54C1");
1485
+ command.option("--stock-id <id>", "\u4ED3\u5E93 ID\uFF08\u4ECE goods stocks \u83B7\u53D6\uFF09").option("--stock-goods-id <id>", "\u5E93\u5B58\u5546\u54C1 ID").option("--page <n>", "\u9875\u7801", "1").option("--size <n>", "\u6BCF\u9875\u6570\u91CF", "20").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
1486
+ command.action(
1487
+ jsonAction(async (options) => {
1488
+ const result = await getSelectGoodsList({
1489
+ stockId: options.stockId || void 0,
1490
+ stockGoodsId: options.stockGoodsId || void 0,
1491
+ page: Number(options.page) || 1,
1492
+ size: Number(options.size) || 20
1493
+ });
1494
+ const data = result ?? { items: [], total: 0 };
1495
+ if (options.json) {
1496
+ if (!data.items?.length) {
1497
+ console.log(JSON.stringify({ ...data, hint: "\u9009\u54C1\u5546\u54C1\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E\u540E\u518D\u8BD5" }, null, 2));
1498
+ } else {
1499
+ console.log(JSON.stringify(data, null, 2));
1500
+ }
1501
+ return;
1502
+ }
1503
+ if (!data.items?.length) {
1504
+ console.log(chalk8.yellow("\u6682\u65E0\u9009\u54C1\u5546\u54C1\uFF0C\u8BF7\u5148\u7ED1\u5B9A\u4ED3\u5E93\u6216\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E"));
1505
+ return;
1506
+ }
1507
+ console.log(chalk8.cyan(`
1508
+ \u9009\u54C1\u5546\u54C1\uFF08\u5171 ${data.total} \u4EF6\uFF0C\u7B2C ${data.page} \u9875\uFF09
1509
+ `));
1510
+ for (const item of data.items) {
1511
+ console.log(
1512
+ ` ${chalk8.bold(item.goodsName)} ${item.size ? chalk8.gray(`| ${item.size}`) : ""}`
1513
+ );
1514
+ console.log(
1515
+ ` \u54C1\u724C: ${item.brand} \u5EFA\u8BAE\u552E\u4EF7: \xA5${item.salePrice} stockGoodsId: ${chalk8.green(item.stockGoodsId)}`
1516
+ );
1517
+ console.log(chalk8.gray(` \u5206\u7C7B: ${item.cate1Name} > ${item.cate2Name} > ${item.cate3Name}`));
1518
+ console.log();
1519
+ }
1520
+ })
1521
+ );
1522
+ return command;
1523
+ }
1524
+
1525
+ // src/commands/goods/listing.ts
1526
+ import { Command as Command9 } from "commander";
1527
+ import chalk9 from "chalk";
1528
+ init_render();
1529
+
1530
+ // src/components/ListingTable.tsx
1531
+ import { Box as Box4, Text as Text4 } from "ink";
1532
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1533
+ var STATUS_MAP = {
1534
+ init: { label: "\u5F85\u4E0A\u67B6", color: "yellow" },
1535
+ up: { label: "\u5DF2\u4E0A\u67B6", color: "green" },
1536
+ down: { label: "\u5DF2\u4E0B\u67B6", color: "gray" },
1537
+ fail: { label: "\u5931\u8D25", color: "red" }
1538
+ };
1539
+ var COL_ID3 = 4;
1540
+ var COL_STATUS2 = 8;
1541
+ var COL_BRAND = 12;
1542
+ var COL_PRICE = 10;
1543
+ var COL_SPEC = 6;
1544
+ var COL_STOCK = 8;
1545
+ function truncate(str, maxLen) {
1546
+ return str.length > maxLen ? str.slice(0, maxLen - 1) + "\u2026" : str;
1547
+ }
1548
+ function formatTime(ts) {
1549
+ if (!ts) return "-";
1550
+ const d = new Date(ts);
1551
+ const pad = (n) => String(n).padStart(2, "0");
1552
+ return `${pad(d.getMonth() + 1)}/${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
1553
+ }
1554
+ function Header3({ fillWidth }) {
1555
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "row", children: [
1556
+ /* @__PURE__ */ jsx4(Box4, { width: COL_ID3, children: /* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", children: "ID" }) }),
1557
+ /* @__PURE__ */ jsx4(Box4, { width: COL_STATUS2, children: /* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", children: "\u72B6\u6001" }) }),
1558
+ /* @__PURE__ */ jsx4(Box4, { width: COL_BRAND, children: /* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", children: "\u54C1\u724C" }) }),
1559
+ /* @__PURE__ */ jsx4(Box4, { width: fillWidth, children: /* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", children: "\u5546\u54C1\u540D\u79F0" }) }),
1560
+ /* @__PURE__ */ jsx4(Box4, { width: COL_PRICE, children: /* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", children: "\u4EF7\u683C" }) }),
1561
+ /* @__PURE__ */ jsx4(Box4, { width: COL_SPEC, children: /* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", children: "\u89C4\u683C" }) }),
1562
+ /* @__PURE__ */ jsx4(Box4, { width: COL_STOCK, children: /* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", children: "\u5E93\u5B58ID" }) })
1563
+ ] });
1564
+ }
1565
+ function DetailRow({ item }) {
1566
+ return /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", children: /* @__PURE__ */ jsx4(Text4, { color: "gray", children: ` shopId: ${item.shopId} thirdItemNo: ${item.thirdItemNo || "-"} outItemNo: ${item.outItemNo || "-"} \u8D27\u53F7: ${item.goodsNo || "-"} ${item.type || "-"} ${item.platform} \u521B\u5EFA: ${formatTime(item.gmtCreate)} \u4FEE\u6539: ${formatTime(item.gmtModified)}` }) });
1567
+ }
1568
+ function Row3({ item, fillWidth }) {
1569
+ const status = STATUS_MAP[item.status] ?? { label: item.status, color: "white" };
1570
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
1571
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "row", children: [
1572
+ /* @__PURE__ */ jsx4(Box4, { width: COL_ID3, children: /* @__PURE__ */ jsx4(Text4, { color: "gray", children: item.id }) }),
1573
+ /* @__PURE__ */ jsx4(Box4, { width: COL_STATUS2, children: /* @__PURE__ */ jsx4(Text4, { color: status.color, children: status.label }) }),
1574
+ /* @__PURE__ */ jsx4(Box4, { width: COL_BRAND, children: /* @__PURE__ */ jsx4(Text4, { color: "cyan", children: truncate(item.brandName || "-", COL_BRAND - 1) }) }),
1575
+ /* @__PURE__ */ jsx4(Box4, { width: fillWidth, children: /* @__PURE__ */ jsx4(Text4, { children: truncate(item.goodsName, fillWidth - 1) }) }),
1576
+ /* @__PURE__ */ jsx4(Box4, { width: COL_PRICE, children: /* @__PURE__ */ jsxs4(Text4, { color: "yellow", children: [
1577
+ "\xA5",
1578
+ item.price
1579
+ ] }) }),
1580
+ /* @__PURE__ */ jsx4(Box4, { width: COL_SPEC, children: /* @__PURE__ */ jsx4(Text4, { color: "gray", children: item.spec || "-" }) }),
1581
+ /* @__PURE__ */ jsx4(Box4, { width: COL_STOCK, children: /* @__PURE__ */ jsx4(Text4, { color: "gray", children: item.stockGoodsId }) })
1582
+ ] }),
1583
+ /* @__PURE__ */ jsx4(DetailRow, { item })
1584
+ ] });
1585
+ }
1586
+ function ListingTable({ items, total }) {
1587
+ const termWidth = process.stdout.columns || 80;
1588
+ const borderPadding = 4;
1589
+ const fixedCols = COL_ID3 + COL_STATUS2 + COL_BRAND + COL_PRICE + COL_SPEC + COL_STOCK;
1590
+ const fillWidth = Math.max(termWidth - borderPadding - fixedCols, 20);
1591
+ const totalWidth = fixedCols + fillWidth;
1592
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
1593
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "row", children: [
1594
+ /* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: "\u4E0A\u67B6\u5217\u8868" }),
1595
+ /* @__PURE__ */ jsxs4(Text4, { color: "gray", children: [
1596
+ " \xB7 \u5171 ",
1597
+ total,
1598
+ " \u6761"
1599
+ ] })
1600
+ ] }),
1601
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
1602
+ /* @__PURE__ */ jsx4(Header3, { fillWidth }),
1603
+ /* @__PURE__ */ jsx4(Text4, { color: "gray", children: "\u2500".repeat(totalWidth) }),
1604
+ items.map((item) => /* @__PURE__ */ jsx4(Row3, { item, fillWidth }, item.id))
1605
+ ] })
1606
+ ] });
1607
+ }
1608
+
1609
+ // src/commands/goods/listing.ts
1610
+ function createListingCommand() {
1611
+ const command = new Command9("listing");
1612
+ command.description("\u67E5\u8BE2\u4E0A\u67B6\u5546\u54C1\u5217\u8868");
1613
+ command.option("--id <id>", "\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>", "\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>", "\u5E97\u94FA ID").option("--stock-id <id>", "\u4ED3\u5E93 ID").option("-s, --status <status>", "\u72B6\u6001\u8FC7\u6EE4\uFF08init/up/down/fail\uFF09").option("-p, --platform <platform>", "\u5E73\u53F0", "xianyu").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
1614
+ command.action(
1615
+ jsonAction(async (options) => {
1616
+ const result = await getListingList({
1617
+ id: options.id,
1618
+ stockGoodsId: options.stockGoodsId ? Number(options.stockGoodsId) : void 0,
1619
+ shopId: options.shopId,
1620
+ stockId: options.stockId,
1621
+ status: options.status,
1622
+ platform: options.platform
1623
+ });
1624
+ const data = result ?? { items: [], total: 0 };
1625
+ if (options.json) {
1626
+ if (!data.items?.length) {
1627
+ console.log(JSON.stringify({ ...data, hint: "\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55" }, null, 2));
1628
+ } else {
1629
+ console.log(JSON.stringify(data, null, 2));
1630
+ }
1631
+ return;
1632
+ }
1633
+ if (!data.items?.length) {
1634
+ console.log(chalk9.yellow("\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"));
1635
+ return;
1636
+ }
1637
+ renderComponent(ListingTable, { items: data.items, total: data.total });
1638
+ })
1639
+ );
1640
+ return command;
1641
+ }
1642
+
1643
+ // src/commands/goods/down.ts
1644
+ import { Command as Command10 } from "commander";
1645
+ import chalk10 from "chalk";
1646
+ function createDownCommand() {
1647
+ const command = new Command10("down");
1648
+ command.description("\u4E0B\u67B6\u95F2\u9C7C\u5546\u54C1");
1649
+ command.option("--id <id>", "\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>", "\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>", "\u5E97\u94FA ID").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
1650
+ command.action(
1651
+ jsonAction(async (options) => {
1652
+ if (!options.id && !(options.stockGoodsId && options.shopId)) {
1653
+ if (options.json) {
1654
+ console.log(JSON.stringify({ success: false, error: "\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>" }));
1655
+ process.exit(1);
1656
+ }
1657
+ console.log(chalk10.yellow("\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));
1658
+ return;
1659
+ }
1660
+ const params = {};
1661
+ if (options.id) params.id = options.id;
1662
+ if (options.stockGoodsId) params.stockGoodsId = Number(options.stockGoodsId);
1663
+ if (options.shopId) params.shopId = options.shopId;
1664
+ if (!options.json) console.log(chalk10.cyan("\u{1F4E6} \u6B63\u5728\u4E0B\u67B6\u5546\u54C1..."));
1665
+ const result = await listingDownXianyu(params);
1666
+ if (options.json) {
1667
+ console.log(JSON.stringify({ success: true, data: result }, null, 2));
1668
+ } else {
1669
+ console.log(chalk10.green("\u2705 \u4E0B\u67B6\u6210\u529F"));
1670
+ console.log(JSON.stringify(result, null, 2));
1671
+ }
1672
+ })
1673
+ );
1674
+ return command;
1675
+ }
1676
+
1677
+ // src/commands/goods/price.ts
1678
+ import { Command as Command11 } from "commander";
1679
+ import chalk11 from "chalk";
1680
+ function createPriceCommand() {
1681
+ const command = new Command11("price");
1682
+ command.description("\u4FEE\u6539\u95F2\u9C7C\u4E0A\u67B6\u5546\u54C1\u4EF7\u683C");
1683
+ command.option("--id <id>", "\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>", "\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>", "\u5E97\u94FA ID").option("--price <amount>", "\u65B0\u4EF7\u683C\uFF08\u5FC5\u586B\uFF09").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
1684
+ command.action(
1685
+ jsonAction(async (options) => {
1686
+ if (!options.price) {
1687
+ if (options.json) {
1688
+ console.log(JSON.stringify({ success: false, error: "--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570" }));
1689
+ process.exit(1);
1690
+ }
1691
+ console.log(chalk11.yellow("--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570"));
1692
+ return;
1693
+ }
1694
+ if (!options.id && !(options.stockGoodsId && options.shopId)) {
1695
+ if (options.json) {
1696
+ console.log(JSON.stringify({ success: false, error: "\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>" }));
1697
+ process.exit(1);
1698
+ }
1699
+ console.log(chalk11.yellow("\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));
1700
+ return;
1701
+ }
1702
+ const params = { price: Number(options.price) };
1703
+ if (options.id) params.id = options.id;
1704
+ if (options.stockGoodsId) params.stockGoodsId = Number(options.stockGoodsId);
1705
+ if (options.shopId) params.shopId = options.shopId;
1706
+ if (!options.json) console.log(chalk11.cyan(`\u{1F4B0} \u6B63\u5728\u4FEE\u6539\u4EF7\u683C\u4E3A ${options.price}...`));
1707
+ const result = await listingUpdatePrice(params);
1708
+ if (options.json) {
1709
+ console.log(JSON.stringify({ success: true, data: result }, null, 2));
1710
+ } else {
1711
+ console.log(chalk11.green("\u2705 \u4EF7\u683C\u4FEE\u6539\u6210\u529F"));
1712
+ console.log(JSON.stringify(result, null, 2));
1713
+ }
1714
+ })
1715
+ );
1716
+ return command;
1717
+ }
1718
+
1719
+ // src/commands/goods/edit.ts
1720
+ import { Command as Command12 } from "commander";
1721
+ import chalk12 from "chalk";
1722
+ function createEditCommand() {
1723
+ const command = new Command12("edit");
1724
+ command.description("\u4FEE\u6539\u5DF2\u4E0A\u67B6\u5546\u54C1\u4FE1\u606F\uFF08\u6807\u9898\u3001\u63CF\u8FF0\u3001\u54C1\u724C\u3001\u7C7B\u76EE\u3001\u56FE\u7247\u3001\u5C5E\u6027\u7B49\uFF09");
1725
+ command.option("--id <id>", "\u5546\u54C1\u4E0A\u67B6 ID\uFF08goodsListingId\uFF0C\u63A8\u8350\uFF09").option("--stock-goods-id <id>", "\u5E93\u5B58\u5546\u54C1 ID\uFF08\u4E0E --account \u914D\u5408\uFF09").option("--account <shopId>", "\u95F2\u9C7C\u7528\u6237\u540D/\u5E97\u94FA ID\uFF08\u4E0E --stock-goods-id \u914D\u5408\uFF09").option("--title <title>", "\u5546\u54C1\u6807\u9898").option("--desc <desc>", "\u5546\u54C1\u63CF\u8FF0").option("--category-id <id>", "\u5546\u54C1\u7C7B\u76EE ID\uFF08\u5927\u5206\u7C7B\uFF0C\u540E\u7AEF\u5FC5\u586B\uFF09").option("--channel-cat-id <id>", "\u6E20\u9053\u7C7B\u76EE ID\uFF08\u5C0F\u5206\u7C7B\uFF0C\u540E\u7AEF\u5FC5\u586B\uFF09").option("--image-ids <ids>", "\u56FE\u7247 ID \u5217\u8868\uFF08\u9017\u53F7\u5206\u9694\uFF09").option("--item-attrs <json>", "\u5546\u54C1\u5C5E\u6027\u5217\u8868\uFF08JSON \u5B57\u7B26\u4E32\uFF09").option("--brand-name <name>", "\u54C1\u724C\u540D\u79F0").option("--stuff-status <status>", "\u6210\u8272\u7B49\u7EA7\uFF1A100=\u5168\u65B0 -1=\u51C6\u65B0 99=99\u65B0 95=95\u65B0 90=9\u65B0").option("--goods-no <no>", "\u8D27\u53F7").option("--original-price <price>", "\u539F\u4EF7\uFF08\u5355\u4F4D\uFF1A\u5143\uFF09").option("--size <size>", "\u5C3A\u7801").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
1726
+ command.action(
1727
+ jsonAction(async (options) => {
1728
+ if (!options.id && !(options.stockGoodsId && options.account)) {
1729
+ if (options.json) {
1730
+ console.log(JSON.stringify({ success: false, status: 400, error: "\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <goodsListingId> \u6216 --stock-goods-id <id> --account <shopId>" }));
1731
+ process.exit(1);
1732
+ }
1733
+ console.log(chalk12.yellow("\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <goodsListingId> \u6216 --stock-goods-id <id> --account <shopId>"));
1734
+ return;
1735
+ }
1736
+ const params = {};
1737
+ if (options.id) params.goodsListingId = Number(options.id);
1738
+ if (options.stockGoodsId) params.stockGoodsId = Number(options.stockGoodsId);
1739
+ if (options.account) params.account = options.account;
1740
+ if (options.title) params.title = options.title;
1741
+ if (options.desc) params.desc = options.desc;
1742
+ if (options.categoryId) params.categoryId = Number(options.categoryId);
1743
+ if (options.channelCatId) params.channelCatId = options.channelCatId;
1744
+ if (options.imageIds) params.imageIdList = options.imageIds.split(",").map((s) => s.trim());
1745
+ if (options.brandName) params.brandName = options.brandName;
1746
+ if (options.stuffStatus) params.stuffStatus = Number(options.stuffStatus);
1747
+ if (options.goodsNo) params.goodsNo = options.goodsNo;
1748
+ if (options.originalPrice) params.originalPrice = Number(options.originalPrice);
1749
+ if (options.size) params.size = options.size;
1750
+ if (options.itemAttrs) {
1751
+ try {
1752
+ params.itemAttrList = JSON.parse(options.itemAttrs);
1753
+ } catch {
1754
+ if (options.json) {
1755
+ console.log(JSON.stringify({ success: false, status: 400, error: "--item-attrs JSON \u89E3\u6790\u5931\u8D25" }));
1756
+ process.exit(1);
1757
+ }
1758
+ console.log(chalk12.yellow("--item-attrs JSON \u89E3\u6790\u5931\u8D25"));
1759
+ return;
1760
+ }
1761
+ }
1762
+ const hasUpdate = Object.keys(params).some(
1763
+ (k) => !["goodsListingId", "stockGoodsId", "account"].includes(k)
1764
+ );
1765
+ if (!hasUpdate) {
1766
+ if (options.json) {
1767
+ console.log(JSON.stringify({ success: false, status: 400, error: "\u672A\u6307\u5B9A\u9700\u8981\u4FEE\u6539\u7684\u5B57\u6BB5" }));
1768
+ process.exit(1);
1769
+ }
1770
+ console.log(chalk12.yellow("\u672A\u6307\u5B9A\u9700\u8981\u4FEE\u6539\u7684\u5B57\u6BB5"));
1771
+ return;
1772
+ }
1773
+ if (!options.json) console.log(chalk12.cyan("\u6B63\u5728\u4FEE\u6539\u5546\u54C1\u4FE1\u606F..."));
1774
+ const result = await updateGoodsInfo(params);
1775
+ if (options.json) {
1776
+ console.log(JSON.stringify({ success: true, data: result }, null, 2));
1777
+ } else {
1778
+ console.log(chalk12.green("\u2705 \u5546\u54C1\u4FE1\u606F\u4FEE\u6539\u6210\u529F"));
1779
+ console.log(JSON.stringify(result, null, 2));
1780
+ }
1781
+ })
1782
+ );
1783
+ return command;
1784
+ }
1785
+
1786
+ // src/commands/goods/hang-up.ts
1787
+ import { Command as Command13 } from "commander";
1788
+ import chalk13 from "chalk";
1789
+ var STUFF_STATUS_MAP = {
1790
+ 100: "\u5168\u65B0",
1791
+ [-1]: "\u51C6\u65B0",
1792
+ 99: "99\u65B0",
1793
+ 95: "95\u65B0",
1794
+ 90: "9\u65B0"
1795
+ };
1796
+ function createHangUpCommand() {
1797
+ const command = new Command13("hang-up");
1798
+ command.description("\u95F2\u9C7C\u6302\u552E\u4E0A\u67B6\uFF08\u5B8C\u6574\u5546\u54C1\u4FE1\u606F\u6A21\u5F0F\uFF09");
1799
+ command.addCommand(
1800
+ new Command13("categories").description("\u83B7\u53D6\u95F2\u9C7C\u7C7B\u76EE\u5217\u8868\uFF08\u5927\u5206\u7C7B \u2192 \u5C0F\u5206\u7C7B\uFF09").option("--sp-biz-type <n>", "\u4E1A\u52A1\u5206\u7C7B\uFF0C16=\u5962\u54C1", "16").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(jsonAction(async (options) => {
1801
+ const cats = await getXyCategories(Number(options.spBizType));
1802
+ if (options.json) {
1803
+ console.log(JSON.stringify(cats, null, 2));
1804
+ return;
1805
+ }
1806
+ const grouped = /* @__PURE__ */ new Map();
1807
+ for (const cat of cats) {
1808
+ const key = String(cat.catId);
1809
+ if (!grouped.has(key)) grouped.set(key, { catName: cat.catName, children: [] });
1810
+ grouped.get(key).children.push({ channel: cat.channel, channelCatId: cat.channelCatId });
1811
+ }
1812
+ for (const [catId, group] of grouped) {
1813
+ console.log(chalk13.bold(`${group.catName} (catId: ${chalk13.green(catId)})`));
1814
+ for (const child of group.children) {
1815
+ console.log(` ${child.channel} (channelCatId: ${chalk13.green(child.channelCatId)})`);
1816
+ }
1817
+ }
1818
+ }))
1819
+ );
1820
+ command.addCommand(
1821
+ new Command13("props").description("\u83B7\u53D6\u6307\u5B9A\u7C7B\u76EE\u4E0B\u7684\u5C5E\u6027\u5217\u8868\uFF08\u542B\u53EF\u9009\u503C\uFF09").requiredOption("--channel-cat-id <id>", "\u5C0F\u5206\u7C7B ID\uFF08\u4ECE categories \u83B7\u53D6\uFF09").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(jsonAction(async (options) => {
1822
+ const props = await getXyProps(options.channelCatId);
1823
+ if (options.json) {
1824
+ console.log(JSON.stringify(props, null, 2));
1825
+ return;
1826
+ }
1827
+ for (const prop of props) {
1828
+ console.log(chalk13.bold(`
1829
+ ${prop.propName} (propId: ${prop.propId})`));
1830
+ if (prop.propsValues?.length) {
1831
+ for (const val of prop.propsValues) {
1832
+ console.log(` ${val.valueName} (valueId: ${val.valueId})`);
1833
+ }
1834
+ } else {
1835
+ console.log(chalk13.gray(" \uFF08\u4F7F\u7528 brands \u5B50\u547D\u4EE4\u641C\u7D22\uFF09"));
1836
+ }
1837
+ }
1838
+ }))
1839
+ );
1840
+ command.addCommand(
1841
+ new Command13("brands").description("\u641C\u7D22\u95F2\u9C7C\u54C1\u724C\uFF08\u6309\u5173\u952E\u5B57\u8FC7\u6EE4\uFF09").requiredOption("--channel-cat-id <id>", "\u5C0F\u5206\u7C7B ID").requiredOption("--prop-id <id>", "\u5C5E\u6027 ID\uFF08\u54C1\u724C\u5C5E\u6027\u7684 propId\uFF09").requiredOption("--key <keyword>", "\u641C\u7D22\u5173\u952E\u5B57").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(jsonAction(async (options) => {
1842
+ const values = await getXyPropValues(options.channelCatId, options.propId, options.key);
1843
+ if (options.json) {
1844
+ console.log(JSON.stringify(values, null, 2));
1845
+ return;
1846
+ }
1847
+ if (!values.length) {
1848
+ console.log(chalk13.yellow("\u672A\u627E\u5230\u5339\u914D\u7684\u54C1\u724C"));
1849
+ return;
1850
+ }
1851
+ for (const val of values) {
1852
+ console.log(` ${val.valueName} (valueId: ${val.valueId})`);
1853
+ }
1854
+ }))
1855
+ );
1856
+ command.addCommand(
1857
+ new Command13("upload-images").description("\u6279\u91CF\u4E0A\u4F20\u56FE\u7247\u5230\u95F2\u9C7C\uFF08\u6302\u552E\u524D\u5FC5\u987B\u5148\u4E0A\u4F20\u56FE\u7247\uFF09").requiredOption("--shop-id <id>", "\u5E97\u94FA ID").requiredOption("--files <paths>", "\u56FE\u7247\u6587\u4EF6\u8DEF\u5F84\uFF0C\u9017\u53F7\u5206\u9694").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(jsonAction(async (options) => {
1858
+ const filePaths = options.files.split(",").map((p) => p.trim()).filter(Boolean);
1859
+ if (filePaths.length === 0) {
1860
+ if (options.json) {
1861
+ console.log(JSON.stringify({ success: false, error: "\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u5F20\u56FE\u7247" }));
1862
+ process.exit(1);
1863
+ }
1864
+ console.log(chalk13.yellow("\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u5F20\u56FE\u7247"));
1865
+ return;
1866
+ }
1867
+ if (!options.json) console.log(chalk13.cyan(`\u6B63\u5728\u4E0A\u4F20 ${filePaths.length} \u5F20\u56FE\u7247...`));
1868
+ const images = await uploadXyImages(options.shopId, filePaths);
1869
+ if (options.json) {
1870
+ console.log(JSON.stringify({ success: true, images }, null, 2));
1871
+ } else {
1872
+ console.log(chalk13.green(`\u4E0A\u4F20\u6210\u529F\uFF0C\u5171 ${images.length} \u5F20`));
1873
+ for (const img of images) {
1874
+ console.log(` \u56FE\u7247ID: ${img.value}`);
1875
+ }
1876
+ }
1877
+ }))
1878
+ );
1879
+ command.addCommand(
1880
+ new Command13("submit").description("\u63D0\u4EA4\u6302\u552E\u4E0A\u67B6").requiredOption("--shop-id <id>", "\u5E97\u94FA ID\uFF08\u5373\u95F2\u9C7C\u7528\u6237\u540D account\uFF09").requiredOption("--title <title>", "\u5546\u54C1\u6807\u9898").requiredOption("--price <amount>", "\u552E\u4EF7").requiredOption("--category-id <id>", "\u5927\u5206\u7C7B ID\uFF08\u4ECE categories \u83B7\u53D6\uFF09").requiredOption("--channel-cat-id <id>", "\u5C0F\u5206\u7C7B ID\uFF08\u4ECE categories \u83B7\u53D6\uFF09").requiredOption("--image-ids <ids>", "\u56FE\u7247 ID \u5217\u8868\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u5148\u901A\u8FC7 upload-images \u83B7\u53D6\uFF09").requiredOption("--stuff-status <n>", "\u6210\u8272\uFF1A100 \u5168\u65B0 / -1 \u51C6\u65B0 / 99 99\u65B0 / 95 95\u65B0 / 90 9\u65B0").option("--item-attrs <json>", '\u5546\u54C1\u5C5E\u6027\u5217\u8868 JSON\uFF0C\u683C\u5F0F: [{"propId":"x","valueId":"y","valueName":"z"}]').option("--brand-name <name>", "\u54C1\u724C\u540D\u79F0").option("--desc <desc>", "\u5546\u54C1\u63CF\u8FF0").option("--size <size>", "\u5C3A\u7801").option("--goods-no <no>", "\u8D27\u53F7").option("--original-price <amount>", "\u539F\u4EF7").option("--trade-type <n>", "\u4EA4\u6613\u65B9\u5F0F\uFF1A0 \u4EC5\u5728\u7EBF / 1 \u4EC5\u7EBF\u4E0B / 2 \u7EBF\u4E0A\u6216\u7EBF\u4E0B", "0").option("--transport-fee <amount>", "\u8FD0\u8D39\uFF08\u9ED8\u8BA4 0 \u5305\u90AE\uFF09", "0").option("--yhb", "\u662F\u5426\u5F00\u542F\u9A8C\u8D27\u5B9D").requiredOption("--out-item-no <no>", "\u5546\u5BB6\u7F16\u7801\uFF08\u540C\u5E97\u94FA\u552F\u4E00\uFF0C\u7528\u6237\u81EA\u5B9A\u4E49\uFF09").option("--division-id <id>", "\u884C\u653F\u533A\u5212 ID\uFF08\u5E02\u7EA7 ID\uFF0C\u9ED8\u8BA4\u676D\u5DDE 330100\uFF09", "330100").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(jsonAction(async (options) => {
1881
+ const imageIdList = options.imageIds.split(",").map((id) => id.trim());
1882
+ const params = {
1883
+ account: options.shopId,
1884
+ title: options.title,
1885
+ reservePrice: Number(options.price),
1886
+ categoryId: Number(options.categoryId),
1887
+ channelCatId: options.channelCatId,
1888
+ imageIdList,
1889
+ stuffStatus: Number(options.stuffStatus),
1890
+ itemBizType: 2,
1891
+ spBizType: "16",
1892
+ tradeType: Number(options.tradeType) || 0,
1893
+ transportFee: Number(options.transportFee) || 0,
1894
+ yhb: options.yhb ?? false,
1895
+ ...options.brandName && { brandName: options.brandName },
1896
+ ...options.desc && { desc: options.desc },
1897
+ ...options.size && { size: options.size },
1898
+ ...options.goodsNo && { goodsNo: options.goodsNo },
1899
+ ...options.originalPrice && { originalPrice: Number(options.originalPrice) },
1900
+ outItemNo: options.outItemNo,
1901
+ divisionId: Number(options.divisionId) || 330100,
1902
+ apiAfterSalesDo: {
1903
+ supportFd10msPolicy: false,
1904
+ supportFd24hsPolicy: false,
1905
+ supportNfrPolicy: false,
1906
+ supportSdrPolicy: false,
1907
+ supportVnrPolicy: false,
1908
+ supportGpaPolicy: false,
1909
+ supportFd48hsPolicy: false
1910
+ },
1911
+ ...options.itemAttrs && { itemAttrList: JSON.parse(options.itemAttrs) }
1912
+ };
1913
+ if (!options.json) {
1914
+ console.log(chalk13.cyan("\u6B63\u5728\u63D0\u4EA4\u6302\u552E..."));
1915
+ console.log(chalk13.gray(` \u6807\u9898: ${params.title}`));
1916
+ console.log(chalk13.gray(` \u552E\u4EF7: \xA5${params.reservePrice}`));
1917
+ console.log(chalk13.gray(` \u6210\u8272: ${STUFF_STATUS_MAP[params.stuffStatus] ?? params.stuffStatus}`));
1918
+ console.log(chalk13.gray(` \u56FE\u7247: ${imageIdList.length} \u5F20`));
1919
+ if (params.itemAttrList?.length) {
1920
+ console.log(chalk13.gray(` \u5C5E\u6027: ${params.itemAttrList.length} \u9879`));
1921
+ }
1922
+ }
1923
+ const result = await listingHangUpXianyu(params);
1924
+ if (options.json) {
1925
+ console.log(JSON.stringify({ success: true, data: result }, null, 2));
1926
+ } else {
1927
+ console.log(chalk13.green("\u6302\u552E\u63D0\u4EA4\u6210\u529F"));
1928
+ console.log(JSON.stringify(result, null, 2));
1929
+ }
1930
+ }))
1931
+ );
1932
+ return command;
1933
+ }
1934
+
1935
+ // src/commands/goods/index.ts
1936
+ function createGoodsCommand() {
1937
+ const command = new Command14("goods");
1938
+ command.description("\u5546\u54C1\u7BA1\u7406");
1939
+ command.addCommand(createShopsCommand());
1940
+ command.addCommand(createStocksCommand());
1941
+ command.addCommand(createListCommand());
1942
+ command.addCommand(createListingCommand());
1943
+ command.addCommand(createDownCommand());
1944
+ command.addCommand(createPriceCommand());
1945
+ command.addCommand(createEditCommand());
1946
+ command.addCommand(createUpCommand());
1947
+ command.addCommand(createHangUpCommand());
1948
+ return command;
1949
+ }
1950
+
1951
+ // src/commands/uninstall.ts
1952
+ import { Command as Command15 } from "commander";
1953
+ import chalk14 from "chalk";
1954
+ import { promises as fs3 } from "node:fs";
1955
+ import path3 from "node:path";
1956
+ import os2 from "node:os";
1957
+ import { spawn } from "node:child_process";
1958
+ var PKG_NAME = "@round2ai/r2-cli";
1959
+ function createUninstallCommand() {
1960
+ const command = new Command15("uninstall");
1961
+ command.description("\u5378\u8F7D R2-CLI \u5E76\u6E05\u9664\u6240\u6709\u914D\u7F6E");
1962
+ command.action(async () => {
1963
+ try {
1964
+ console.log(chalk14.yellow("\n\u26A0\uFE0F \u5373\u5C06\u6267\u884C\u4EE5\u4E0B\u64CD\u4F5C\uFF1A"));
1965
+ console.log(chalk14.gray(` 1. \u5220\u9664\u914D\u7F6E\u76EE\u5F55 ~/.r2-cli/`));
1966
+ console.log(chalk14.gray(` 2. \u5168\u5C40\u5378\u8F7D ${PKG_NAME}
1967
+ `));
1968
+ const { confirm: confirm2 } = await import("@inquirer/prompts");
1969
+ const confirmed = await confirm2({ message: "\u786E\u8BA4\u5378\u8F7D\uFF1F", default: false });
1970
+ if (!confirmed) {
1971
+ console.log(chalk14.gray("\u5DF2\u53D6\u6D88\u5378\u8F7D"));
1972
+ return;
1973
+ }
1974
+ const configDir = path3.join(os2.homedir(), ".r2-cli");
1975
+ try {
1976
+ await fs3.rm(configDir, { recursive: true, force: true });
1977
+ console.log(chalk14.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u6E05\u9664"));
1978
+ } catch {
1979
+ console.log(chalk14.yellow("\u26A0\uFE0F \u914D\u7F6E\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u5220\u9664\uFF08\u53EF\u5FFD\u7565\uFF09"));
1980
+ }
1981
+ console.log(chalk14.cyan(`\u6B63\u5728\u5378\u8F7D ${PKG_NAME}...`));
1982
+ const child = spawn("npm", ["uninstall", "-g", PKG_NAME], {
1983
+ stdio: "inherit",
1984
+ shell: true
1985
+ });
1986
+ child.on("exit", (code) => {
1987
+ if (code === 0) {
1988
+ console.log(chalk14.green(`
1989
+ \u2705 ${PKG_NAME} \u5DF2\u5378\u8F7D`));
1990
+ } else {
1991
+ console.log(chalk14.yellow(`
1992
+ \u26A0\uFE0F npm \u5378\u8F7D\u5931\u8D25 (exit code: ${code})`));
1993
+ console.log(chalk14.gray(" \u5982\u901A\u8FC7 yarn/pnpm \u5B89\u88C5\uFF0C\u8BF7\u624B\u52A8\u5378\u8F7D"));
1994
+ }
1995
+ process.exit(code ?? 1);
1996
+ });
1997
+ } catch (error) {
1998
+ handleCommandError(error);
1999
+ }
2000
+ });
2001
+ return command;
2002
+ }
2003
+
2004
+ // src/commands/update.ts
2005
+ import { Command as Command16 } from "commander";
2006
+ import chalk15 from "chalk";
2007
+ import { spawn as spawn2, execSync } from "node:child_process";
2008
+
2009
+ // src/utils/version.ts
2010
+ import { readFileSync as readFileSync2 } from "node:fs";
2011
+ import { join } from "node:path";
2012
+ function getVersion() {
2013
+ for (const rel of ["../package.json", "../../package.json"]) {
2014
+ try {
2015
+ return JSON.parse(readFileSync2(join(import.meta.dirname, rel), "utf-8")).version;
2016
+ } catch {
2017
+ }
2018
+ }
2019
+ return "0.0.0";
2020
+ }
2021
+
2022
+ // src/commands/update.ts
2023
+ var PKG_NAME2 = "@round2ai/r2-cli";
2024
+ function run(cmd, args) {
2025
+ return new Promise((resolve) => {
2026
+ const child = spawn2(cmd, args, { stdio: "inherit" });
2027
+ child.on("close", (code) => resolve(code ?? 1));
2028
+ child.on("error", () => resolve(1));
2029
+ });
2030
+ }
2031
+ function createUpdateCommand() {
2032
+ return new Command16("update").description("\u4E00\u952E\u66F4\u65B0 CLI \u548C\u6280\u80FD").action(async () => {
2033
+ const oldVersion = getVersion();
2034
+ console.log(chalk15.cyan(`\u5F53\u524D\u7248\u672C: ${oldVersion}`));
2035
+ console.log(chalk15.cyan("\u6B63\u5728\u66F4\u65B0 CLI..."));
2036
+ const code = await run("npm", ["install", "-g", `${PKG_NAME2}@latest`]);
2037
+ if (code !== 0) {
2038
+ console.error(chalk15.red(`
2039
+ \u2717 update failed \xB7 Try: npm install -g ${PKG_NAME2}@latest`));
2040
+ process.exit(1);
2041
+ }
2042
+ let newVersion = oldVersion;
2043
+ try {
2044
+ const output = execSync("r2-cli --version", { encoding: "utf-8" }).trim();
2045
+ newVersion = output || oldVersion;
2046
+ } catch {
2047
+ }
2048
+ console.log(chalk15.green(`
2049
+ \u2713 \u66F4\u65B0\u5B8C\u6210: ${oldVersion} \u2192 ${newVersion}`));
2050
+ console.log(chalk15.green("\u2713 \u6280\u80FD\u5DF2\u540C\u6B65\u66F4\u65B0"));
2051
+ });
2052
+ }
2053
+
2054
+ // src/commands/setup.ts
2055
+ function setupCommands(program2) {
2056
+ const authCommand = program2.command("auth").description("\u6388\u6743\u7BA1\u7406");
2057
+ authCommand.addCommand(createLoginCommand());
2058
+ authCommand.addCommand(createLogoutCommand());
2059
+ authCommand.addCommand(createStatusCommand());
2060
+ authCommand.addCommand(createXianyuAuthCommand());
2061
+ program2.addCommand(createGoodsCommand());
2062
+ program2.addCommand(createUninstallCommand());
2063
+ program2.addCommand(createUpdateCommand());
2064
+ }
2065
+
2066
+ // src/services/update-check/index.ts
2067
+ import chalk16 from "chalk";
2068
+ var PKG_NAME3 = "@round2ai/r2-cli";
2069
+ var REGISTRY_URLS = [
2070
+ `https://registry.npmmirror.com/${encodeURIComponent(PKG_NAME3)}/latest`,
2071
+ `https://registry.npmjs.org/${encodeURIComponent(PKG_NAME3)}/latest`
2072
+ ];
2073
+ var FETCH_TIMEOUT_MS = 5e3;
2074
+ async function fetchVersionFromRegistry(url) {
2075
+ const controller = new AbortController();
2076
+ const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
2077
+ try {
2078
+ const res = await fetch(url, { signal: controller.signal });
2079
+ if (!res.ok) return null;
2080
+ return (await res.json()).version ?? null;
2081
+ } catch {
2082
+ return null;
2083
+ } finally {
2084
+ clearTimeout(timer);
2085
+ }
2086
+ }
2087
+ async function fetchLatestVersion() {
2088
+ const results = await Promise.allSettled(REGISTRY_URLS.map(fetchVersionFromRegistry));
2089
+ for (const r of results) {
2090
+ if (r.status === "fulfilled" && r.value) return r.value;
2091
+ }
2092
+ return null;
2093
+ }
2094
+ function isNewer(latest, current) {
2095
+ const la = latest.split(".").map(Number);
2096
+ const cu = current.split(".").map(Number);
2097
+ for (let i = 0; i < 3; i++) {
2098
+ if ((la[i] ?? 0) !== (cu[i] ?? 0)) return (la[i] ?? 0) > (cu[i] ?? 0);
2099
+ }
2100
+ return false;
2101
+ }
2102
+ async function checkForUpdate(currentVersion) {
2103
+ const latest = await fetchLatestVersion();
2104
+ if (!latest) return;
2105
+ if (isNewer(latest, currentVersion)) {
2106
+ showUpdateNotification(currentVersion, latest);
2107
+ }
2108
+ }
2109
+ function showUpdateNotification(current, latest) {
2110
+ console.error(
2111
+ chalk16.yellow(`
2112
+ Update available: ${current} \u2192 ${latest}`) + chalk16.gray(`
2113
+ Run: r2-cli update
2114
+ `)
2115
+ );
2116
+ }
2117
+
2118
+ // src/entrypoints/r2-cli.tsx
2119
+ async function displayWelcomeMessage() {
2120
+ const { default: figlet } = await import("figlet");
2121
+ console.log(
2122
+ chalk17.cyan.bold(
2123
+ figlet.textSync("R2-CLI", {
2124
+ font: "Standard",
2125
+ horizontalLayout: "full"
2126
+ })
2127
+ )
2128
+ );
2129
+ console.log(chalk17.gray(" \u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B\n"));
2130
+ }
2131
+ function setupCliApp() {
2132
+ const program2 = new Command18();
2133
+ program2.name("r2-cli").description("R2-CLI\uFF0C\u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B");
2134
+ let version = getVersion();
2135
+ if (version === "0.0.0") {
2136
+ console.error(chalk17.yellow("Warning: unable to read version from package.json"));
2137
+ }
2138
+ program2.version(version, "-v, --version");
2139
+ const updateCheckPromise2 = checkForUpdate(version);
2140
+ program2.configureOutput({
2141
+ writeErr: (str) => {
2142
+ console.error(chalk17.red(str.replace("error:", "").trim()));
2143
+ }
2144
+ });
2145
+ program2.action(async () => {
2146
+ await displayWelcomeMessage();
2147
+ program2.help();
2148
+ });
2149
+ setupCommands(program2);
2150
+ return { program: program2, updateCheckPromise: updateCheckPromise2 };
2151
+ }
2152
+ function handleSignal() {
2153
+ console.log(chalk17.gray("\n\u64CD\u4F5C\u5DF2\u53D6\u6D88"));
2154
+ process.exit(130);
2155
+ }
2156
+ process.on("SIGINT", handleSignal);
2157
+ process.on("SIGTERM", handleSignal);
2158
+ var { program, updateCheckPromise } = setupCliApp();
2159
+ program.parse(process.argv);
2160
+ updateCheckPromise.catch((e) => {
2161
+ console.error(chalk17.gray(`[update-check] ${e instanceof Error ? e.message : String(e)}`));
2162
+ });