@round2ai/r2-cli 1.0.12-beta.0 → 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,48 +1,2162 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- var _e=Object.defineProperty;var tt=(e,t)=>()=>(e&&(t=e(e=0)),t);var et=(e,t)=>{for(var n in t)_e(e,n,{get:t[n],enumerable:!0})};var ee={};et(ee,{UserInfoCard:()=>co});import{Box as _,Text as E}from"ink";import{jsx as j,jsxs as M}from"react/jsx-runtime";function co({userInfo:e,lastLogin:t,daysSinceLogin:n}){let o=e.mobile?e.mobile.replace(/(\d{3})\d{4}(\d{4})/,"$1****$2"):"-";return M(_,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[j(E,{bold:!0,color:"cyan",children:"\u7528\u6237\u4FE1\u606F"}),M(_,{flexDirection:"row",marginTop:1,children:[j(_,{width:10,children:j(E,{color:"gray",children:"\u6635\u79F0"})}),j(E,{color:"yellow",children:e.nickname})]}),M(_,{flexDirection:"row",children:[j(_,{width:10,children:j(E,{color:"gray",children:"\u624B\u673A\u53F7"})}),j(E,{color:"yellow",children:o})]}),t&&M(_,{flexDirection:"column",marginTop:1,children:[M(E,{color:"gray",children:["\u6700\u540E\u767B\u5F55: ",t.toLocaleString()]}),n!==void 0&&M(E,{color:"gray",children:[" \u8DDD\u4ECA: ",n," \u5929"]})]})]})}var oe=tt(()=>{"use strict"});var at={};et(at,{renderComponent:()=>po,renderOnce:()=>ne});import lo from"react";import kt from"chalk";import{render as uo}from"ink";import{Writable as mo}from"node:stream";function ne(e){let t=kt.level;process.env.NO_COLOR||(kt.level=3);try{let n=[],o=new mo({write(c,u,d){n.push(Buffer.from(c)),d()}});o.isTTY=!0,o.columns=process.stdout.columns||80,o.rows=process.stdout.rows||24,uo(e,{stdout:o,patchConsole:!1}).unmount();let s=Buffer.concat(n).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{kt.level=t}}function po(e,t){ne(lo.createElement(e,t))}var ct=tt(()=>{"use strict"});var Pe={};et(Pe,{ShopsTable:()=>Ro});import{Box as S,Text as A}from"ink";import{jsx as g,jsxs as z}from"react/jsx-runtime";function Ao(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 vo({hasPlatform:e,fillWidth:t}){return z(S,{flexDirection:"row",paddingBottom:0,children:[e&&g(S,{width:qt,children:g(A,{bold:!0,color:"white",children:"\u5E73\u53F0"})}),g(S,{width:t,children:g(A,{bold:!0,color:"white",children:"\u5E97\u94FA\u540D"})}),g(S,{width:Bt,children:g(A,{bold:!0,color:"white",children:"ID"})}),g(S,{width:Gt,children:g(A,{bold:!0,color:"white",children:"\u72B6\u6001"})})]})}function ko({shop:e,hasPlatform:t,fillWidth:n}){let o=Ce[e.platform]??e.platform;return z(S,{flexDirection:"row",children:[t&&g(S,{width:qt,children:g(A,{color:"cyan",children:o})}),g(S,{width:n,children:g(A,{bold:!0,children:e.name})}),g(S,{width:Bt,children:g(A,{color:"gray",children:e.id})}),g(S,{width:Gt,children:g(A,{color:"green",children:"\u25CF \u6388\u6743\u4E2D"})})]})}function Ro({shops:e,platform:t}){let n=Ao(e),o=t==="all",r=t==="all"?"\u6240\u6709\u6388\u6743\u5E97\u94FA":`${Ce[t]??t}\u6388\u6743\u5E97\u94FA`,s=process.stdout.columns||80,i=4,a=Bt+Gt+(o?qt:0),c=Math.max(s-i-a,20),u=a+c;return z(S,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[z(S,{flexDirection:"row",children:[g(A,{bold:!0,color:"cyan",children:r}),z(A,{color:"gray",children:[" \xB7 ",n.length," \u5BB6"]})]}),z(S,{flexDirection:"column",marginTop:1,children:[g(vo,{hasPlatform:o,fillWidth:c}),g(A,{color:"gray",children:"\u2500".repeat(u)}),n.map(d=>g(ko,{shop:d,hasPlatform:o,fillWidth:c},d.id))]})]})}var Ce,qt,Bt,Gt,Te=tt(()=>{"use strict";Ce={xianyu:"\u95F2\u9C7C",douyin:"\u6296\u97F3"},qt=8,Bt=16,Gt=10});var ve={};et(ve,{StocksTable:()=>Uo});import{Box as h,Text as C}from"ink";import{jsx as m,jsxs as H}from"react/jsx-runtime";function Lo({fillWidth:e}){return H(h,{flexDirection:"row",paddingBottom:0,children:[m(h,{width:Jt,children:m(C,{bold:!0,color:"white",children:"ID"})}),m(h,{width:Xt,children:m(C,{bold:!0,color:"white",children:"\u7528\u6237ID"})}),m(h,{width:Qt,children:m(C,{bold:!0,color:"white",children:"\u4ED3\u5E93ID"})}),m(h,{width:e,children:m(C,{bold:!0,color:"white",children:"\u4ED3\u5E93\u540D\u79F0"})}),m(h,{width:_t,children:m(C,{bold:!0,color:"white",children:"\u521B\u5EFA\u65F6\u95F4"})})]})}function Oo({stock:e,fillWidth:t}){let n=new Date(e.gmtCreate).toLocaleString("zh-CN");return H(h,{flexDirection:"row",children:[m(h,{width:Jt,children:m(C,{color:"gray",children:e.id})}),m(h,{width:Xt,children:m(C,{color:"gray",children:e.userId})}),m(h,{width:Qt,children:m(C,{color:"gray",children:e.stockId})}),m(h,{width:t,children:m(C,{bold:!0,children:e.stockName})}),m(h,{width:_t,children:m(C,{color:"gray",children:n})})]})}function Uo({stocks:e}){let t=process.stdout.columns||80,n=4,o=Jt+Xt+Qt+_t,r=Math.max(t-n-o,20),s=o+r;return H(h,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[H(h,{flexDirection:"row",children:[m(C,{bold:!0,color:"cyan",children:"\u4ED3\u5E93\u5217\u8868"}),H(C,{color:"gray",children:[" \xB7 ",e.length," \u4E2A"]})]}),H(h,{flexDirection:"column",marginTop:1,children:[m(Lo,{fillWidth:r}),m(C,{color:"gray",children:"\u2500".repeat(s)}),e.map(i=>m(Oo,{stock:i,fillWidth:r},i.id))]})]})}var Jt,Xt,Qt,_t,ke=tt(()=>{"use strict";Jt=6,Xt=10,Qt=10,_t=22});import{Command as tn}from"commander";import{readFileSync as en}from"node:fs";import on from"node:path";import K from"chalk";import"commander";import{Command as le}from"commander";import f from"chalk";var G=class e extends Error{constructor(n,o,r){super(n);this.code=o;this.details=r;this.name="R2Error",Error.captureStackTrace&&Error.captureStackTrace(this,e)}code;details},T=class extends G{constructor(n,o,r){super(n,"API_ERROR",r);this.status=o;this.response=r;this.name="ApiError"}status;response},D=class extends G{constructor(n,o,r){super(n,"STORAGE_ERROR",{path:o,code:r});this.path=o;this.code=r;this.name="StorageError"}path;code},x=class extends G{constructor(t){super(t,"AUTH_ERROR"),this.name="AuthError"}},L=class extends G{constructor(n,o,r){super(n,"POLLING_ERROR",{attempts:o,timeout:r});this.attempts=o;this.timeout=r;this.name="PollingError"}attempts;timeout};async function Me(e,t,n){let o=new AbortController,r=()=>o.abort();n?.addEventListener("abort",r,{once:!0});let s=setTimeout(()=>o.abort(),t);try{return await e()}catch(i){throw o.signal.aborted&&!n?.aborted?new L("\u5355\u6B21\u8F6E\u8BE2\u8BF7\u6C42\u8D85\u65F6"):i}finally{clearTimeout(s),n?.removeEventListener("abort",r)}}async function J(e,t,n){let{interval:o,timeout:r,condition:s}=t,i=Date.now(),a=0;for(;Date.now()-i<r;){if(n?.aborted)throw new L("\u8F6E\u8BE2\u88AB\u4E2D\u6B62");a++;let c=r-(Date.now()-i),u=await Me(e,c,n);if(s(u,a))return u;await Fe(o,n)}throw new L(`\u8F6E\u8BE2\u8D85\u65F6 (\u5DF2\u7B49\u5F85 ${Date.now()-i}ms, \u5171 ${a} \u6B21)`)}function Fe(e,t){return new Promise((n,o)=>{if(t?.aborted){o(new L("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"));return}let r=()=>{clearTimeout(s),o(new L("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"))},s=setTimeout(()=>{t?.removeEventListener("abort",r),n()},e);t?.addEventListener("abort",r,{once:!0})})}import We from"node:fs";import{fileURLToPath as Ve}from"node:url";import{createRequire as Ke}from"node:module";import Wt from"node:path";import{exec as Ye}from"node:child_process";import ze from"node:http";var xt=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,n)=>{this.server=ze.createServer((o,r)=>this.handleRequest(o,r)),this.server.listen(0,"127.0.0.1",()=>{let o=this.server.address();typeof o=="object"&&o?(this.port=o.port,t(this.port)):n(new Error("Failed to get server address"))}),this.server.on("error",n)})}registerPage(t,n,o,r){let s=this.pages.get(t);if(s){s.qrBuffer=o,s.status="waiting",s.config=r;let i=`data: ${JSON.stringify({status:"waiting"})}
5
-
6
- `;for(let a of s.sseClients)a.write(i)}else this.pages.set(t,{html:n,qrBuffer:o,status:"waiting",sseClients:[],config:r});this.resetIdleTimer()}unregisterPage(t){let n=this.pages.get(t);if(n){for(let o of n.sseClients)o.end();n.sseClients.length=0,this.pages.delete(t),this.pages.size===0&&this.close()}}setStatus(t,n){let o=this.pages.get(t);if(!o)return;o.status=n;let r=`data: ${JSON.stringify({status:n})}
7
-
8
- `;for(let s of o.sseClients)s.write(r)}close(){if(this.server){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null);for(let t of this.pages.values()){for(let n of t.sseClients)n.end();t.sseClients.length=0}this.pages.clear(),this.server.close(),this.server=null,this.port=0,X=null}}resetIdleTimer(){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{[...this.pages.values()].some(n=>n.sseClients.length>0)||this.close()},e.IDLE_TIMEOUT_MS)}handleRequest(t,n){let o=t.url??"/";for(let[r,s]of this.pages){if(o===r){n.writeHead(302,{Location:r+"/"}),n.end();return}if(o===r+"/"){n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(s.html);return}if(o===r+"/qr.png"){n.writeHead(200,{"Content-Type":"image/png","Content-Length":s.qrBuffer.length}),n.end(s.qrBuffer);return}if(o===r+"/events"){n.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),n.write(`data: ${JSON.stringify({status:s.status})}
9
-
10
- `),s.sseClients.push(n),t.on("close",()=>{let i=s.sseClients.indexOf(n);i>=0&&s.sseClients.splice(i,1)});return}if(o===r+"/config"){n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify(s.config??{}));return}}n.writeHead(404,{"Content-Type":"text/plain"}),n.end("Not Found")}},X=null,zt=!1;function ot(){X&&X.close()}function He(){zt||(zt=!0,process.on("exit",ot),process.on("SIGINT",ot),process.on("SIGTERM",ot),setInterval(()=>{process.stdin?.destroyed&&ot()},3e3).unref())}function Ht(){return X||(X=new xt,He()),X}var Ze=Wt.dirname(Ve(import.meta.url)),to="/login",eo="/login-xianyu",It=null;async function oo(e){return We.promises.readFile(Wt.join(Ze,"pages",e),"utf-8")}async function no(e){return It||(It=Ke(import.meta.url)),It("qrcode").toBuffer(e,{width:300,margin:2})}function R(e){let t=process.platform==="win32"?`start "" "${e}"`:process.platform==="darwin"?`open "${e}"`:`xdg-open "${e}"`;Ye(t)}async function Vt(e,t,n,o){let[r,s]=await Promise.all([oo(t),no(n)]),i=Ht(),a=await i.start();i.registerPage(e,r,s,o);let c=`http://127.0.0.1:${a}${e}/`;return{url:n,qrUrl:c,setStatus:u=>i.setStatus(e,u),closeServer:()=>i.unregisterPage(e)}}function St(e){return Vt(to,"login.html",e)}function Ct(e,t){return Vt(eo,"xianyu-auth.html",e,{authUrl:t})}import{promises as Q}from"node:fs";import Pt from"node:path";import ro from"node:os";var so=".r2-cli",nt=class{configPath;config;configLoaded=!1;dirEnsured=!1;constructor(){let t=ro.homedir(),n=Pt.join(t,so);this.configPath=Pt.join(n,"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=Pt.dirname(this.configPath);try{await Q.stat(t)}catch(n){if(n.code==="ENOENT")await Q.mkdir(t,{recursive:!0});else throw new D("Failed to create directory",t,n.code)}this.dirEnsured=!0}async saveConfig(t){this.config=t,await this.ensureDir();let n=JSON.stringify(t,null,2),o=this.configPath+".tmp";try{await Q.writeFile(o,n,"utf-8"),await Q.rename(o,this.configPath),this.configLoaded=!0}catch(r){throw await Q.unlink(o).catch(s=>{typeof process.env.DEBUG<"u"&&console.error("[config] cleanup tmp failed:",s)}),new D("Failed to save config",this.configPath,r.code)}}},Tt=null;function bt(){return Tt||(Tt=new nt),Tt}var vt=300*1e3,rt=class{store=bt();isTokenExpired(t){return t.expire?Date.now()>=t.expire-vt:!1}async saveCredentials(t,n){let o=Date.now(),r=n.expire?Number.parseInt(n.expire,10):0,s={token:t,userInfo:n,timestamp:o,...r>0&&{expire:o+r}},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}},At=null;function Y(){return At||(At=new rt),At}var io="https://api.puresnake.com",st=class{config;authStorage=null;cachedToken=null;tokenExpiry=0;constructor(t={}){this.config={baseUrl:t.baseUrl??io,version:t.version??"v3",debug:t.debug??!1},this.authStorage=t.auth===!1?null:Y()}buildUrl(t){let n=t.startsWith("/")?t.slice(1):t;return`${this.config.baseUrl}/${this.config.version}/${n}`}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 x("\u8BF7\u5148\u8FD0\u884C r2-cli auth login \u767B\u5F55");return this.cachedToken=t.token,this.tokenExpiry=t.expire?t.expire-vt:Date.now()+1800*1e3,t.token}async requestFull(t,n){let o=this.buildUrl(t),{method:r,headers:s,body:i,timeout:a=3e4}=n,c=await this.getAuthToken(),u={...s,...c?{token:c}:{}},d=new AbortController,w=setTimeout(()=>d.abort(),a),q={method:r,headers:{"Content-Type":"application/json",...u},signal:d.signal};i!==void 0&&(q.body=JSON.stringify(i)),this.config.debug&&console.error(`[API ${r}]`,o,i);try{let l=await fetch(o,q);if(!l.ok){if(l.status===401)throw this.authStorage&&(this.cachedToken=null,await this.authStorage.clearCredentials().catch(B=>{console.error("[API] \u6E05\u9664\u51ED\u8BC1\u5931\u8D25:",B instanceof Error?B.message:String(B))})),new x("\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C r2-cli auth login \u91CD\u65B0\u767B\u5F55");let yt=await l.text();throw new T(yt||`${l.status} ${l.statusText}`,l.status)}let P=await l.json();if(this.config.debug&&console.error("[API Response]",P),!P.success||P.status!==0)throw new T(P.msg||"\u672A\u77E5\u9519\u8BEF",P.status,P);return P}catch(l){throw l instanceof DOMException&&l.name==="AbortError"?new T(`\u8BF7\u6C42\u8D85\u65F6 (${a}ms)`,408):l}finally{clearTimeout(w)}}async request(t,n){return(await this.requestFull(t,n)).data}async get(t,n,o){let r=n&&n.size>0?`${t}?${n.toString()}`:t;return this.request(r,{method:"GET",headers:o})}async post(t,n,o){return this.request(t,{method:"POST",body:n,headers:o})}async put(t,n,o){return this.request(t,{method:"PUT",body:n,headers:o})}async delete(t,n){return this.request(t,{method:"DELETE",headers:n})}async upload(t,n,o){let r=this.buildUrl(t),s=await this.getAuthToken(),i={...o,...s?{token:s}:{}},a=new AbortController,c=setTimeout(()=>a.abort(),6e4),u={method:"POST",headers:i,body:n,signal:a.signal};this.config.debug&&console.error("[API UPLOAD]",r);try{let d=await fetch(r,u);if(!d.ok){if(d.status===401)throw this.authStorage&&(this.cachedToken=null,await this.authStorage.clearCredentials().catch(()=>{})),new x("\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C r2-cli auth login \u91CD\u65B0\u767B\u5F55");let q=await d.text();throw new T(q||`${d.status} ${d.statusText}`,d.status)}let w=await d.json();if(this.config.debug&&console.error("[API Response]",w),!w.success||w.status!==0)throw new T(w.msg||"\u672A\u77E5\u9519\u8BEF",w.status,w);return w.data}catch(d){throw d instanceof DOMException&&d.name==="AbortError"?new T("\u4E0A\u4F20\u8D85\u65F6 (60000ms)",408):d}finally{clearTimeout(c)}}},it=new st,Kt=new st({auth:!1});var Yt=Kt;async function Zt(){return Yt.post("app/qrcode/generate")}async function te(e){let t=new URLSearchParams;t.append("qrToken",e);let n=`app/qrcode/status?${t.toString()}`,o=await Yt.requestFull(n,{method:"GET"});return o.token&&typeof o.data=="object"&&o.data!==null&&(o.data.token=o.token),o.data}async function re(e,t,n){let{UserInfoCard:o}=await Promise.resolve().then(()=>(oe(),ee)),{renderComponent:r}=await Promise.resolve().then(()=>(ct(),at)),s=t!=null?{userInfo:e,lastLogin:t,daysSinceLogin:n??0}:{userInfo:e};r(o,s)}var lt=class{storage;constructor(t){this.storage=t??Y()}async generateQR(){let t=await Zt(),n=`https://m.puresnake.com/r2/auth/login?qrToken=${t.qrContent}&from=wechat`,o=await St(n);return{qrData:t,...o}}async waitForLogin(t,n,o,r,s,i){let a=await J(()=>te(t),{interval:o,timeout:n,condition:c=>{switch(c.status){case"scanned":return i||(console.log(f.cyan(`
11
- \u{1F50D} \u5DF2\u626B\u7801: ${c.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}}},r??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 x("\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55"):a.status==="canceled"?new x("\u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55"):new x("\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:n,qrUrl:o,setStatus:r,closeServer:s}=await this.generateQR();console.log(f.green(`\u2705 \u4E8C\u7EF4\u7801\u5DF2\u751F\u6210
16
- `)),console.log(f.cyan(` \u94FE\u63A5: ${o}
17
- `)),R(o),console.log(f.yellow(`\u23F3 \u7B49\u5F85\u626B\u7801...
18
- `));let i=Number.parseInt(n.expireTime,10),a=Number.parseInt(n.pollInterval,10);try{let c=await this.waitForLogin(n.qrToken,i,a,t,r);return console.log(f.green(`
19
- \u2705 \u767B\u5F55\u6210\u529F\uFF01
20
- `)),re(c.userInfo),c}catch(c){throw console.log(f.red(`
21
- \u274C \u767B\u5F55\u5931\u8D25
22
- `)),c}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 n=await this.storage.getCredentials(),o=n.userInfo,r=new Date(n.timestamp),s=Math.floor((Date.now()-n.timestamp)/(1e3*60*60*24));console.log(f.green(`\u2705 \u5DF2\u767B\u5F55
26
- `)),await re(o,r,s)}},Rt=null;function N(){return Rt||(Rt=new lt),Rt}import $ from"chalk";var se=it;async function ie(){return se.get("mms/xianyu/auth/url")}async function ae(e){let t=new URLSearchParams({state:e});return se.get("mms/xianyu/auth/status",t)}async function dt(){let e=await ie(),t=await Ct(e.url,e.url);return{authData:e,...t}}async function Z(e,t,n,o,r){return J(()=>ae(e),{interval:n,timeout:t,condition:s=>s.status==="success"?(console.log($.green(`
27
- \u2705 \u6388\u6743\u6210\u529F\uFF01\u5E97\u94FA: ${s.shopName} (${s.shopId})`)),r?.("success"),!0):s.status==="expired"?(console.log($.red(`
28
- \u23F0 \u6388\u6743\u94FE\u63A5\u5DF2\u8FC7\u671F`)),r?.("expired"),!0):!1},o)}async function Nt(e){console.log($.cyan(`
29
- \u{1F517} \u6B63\u5728\u83B7\u53D6\u95F2\u9C7C\u6388\u6743\u5730\u5740...`));let{authData:t,qrUrl:n,setStatus:o,closeServer:r}=await dt();console.log($.green(`\u2705 \u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210
30
- `)),console.log($.cyan(` \u94FE\u63A5: ${n}`)),console.log($.gray(` \u6216\u590D\u5236\u94FE\u63A5\u6253\u5F00: ${t.url}`)),R(n),console.log($.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 Z(t.state,s,i,e,o);if(a.status==="success")return a;throw new x("\u95F2\u9C7C\u6388\u6743\u5931\u8D25: "+(a.status==="expired"?"\u94FE\u63A5\u5DF2\u8FC7\u671F":"\u672A\u77E5\u72B6\u6001"))}finally{r()}}import O from"chalk";function b(e){if(e instanceof x)console.error(O.red(`
33
- \u25B2 ${e.message}`)),console.error(O.gray(`\u2192 \u8BF7\u5148\u8FD0\u884C: r2-cli auth login
34
- `));else if(e instanceof T)console.error(O.red(`\u25B2 \u64CD\u4F5C\u5931\u8D25: ${e.message}`)),e.status&&console.error(O.gray(` \u72B6\u6001\u7801: ${e.status}`));else if(e instanceof D)console.error(O.red(`\u25B2 \u914D\u7F6E\u6587\u4EF6\u5F02\u5E38: ${e.message}`)),e.path&&console.error(O.gray(` \u8DEF\u5F84: ${e.path}`)),console.error(O.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(O.red(`\u25B2 ${t}`))}process.exit(1)}function Lt(e){console.log(JSON.stringify({success:!1,error:e})),process.exit(1)}function p(e){return async t=>{try{await e(t)}catch(n){if(t.json){let o=n instanceof Error?n.message:String(n);console.log(JSON.stringify({success:!1,error:o})),process.exit(1)}b(n)}}}function ut(e){return async(...t)=>{try{await e(...t)}catch(n){let o=n instanceof Error?n.message:String(n);Lt(o)}}}var fo=new Set(["accessToken","refreshExpireIn"]);function ce(e){return e.map(t=>{let n={};for(let[o,r]of Object.entries(t))fo.has(o)||(n[o]=r);return n})}function Ot(){let e=new le("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 le("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(ut(async n=>{let r=await N().waitForLogin(n.token,Number.parseInt(n.expire,10),Number.parseInt(n.interval,10));console.log(JSON.stringify({success:!0,...r}))}));return e.addCommand(t),e.action(async n=>{try{if(n.json){let o=N(),{qrData:r,qrUrl:s,setStatus:i,closeServer:a}=await o.generateQR(),c=Number.parseInt(r.expireTime,10),u=Number.parseInt(r.pollInterval,10);console.log(JSON.stringify({qrToken:r.qrToken,expireTimeMs:c,pollIntervalMs:u,url:`https://m.puresnake.com/r2/auth/login?qrToken=${r.qrContent}&from=wechat`,qrUrl:s},null,2)),R(s);try{let d=await o.waitForLogin(r.qrToken,c,u,void 0,i,!0);console.log(JSON.stringify({success:!0,userInfo:d.userInfo}))}catch(d){let w=d instanceof Error?d.message:String(d);console.log(JSON.stringify({success:!1,error:w}))}finally{setTimeout(a,1e3)}}else await N().login()}catch(o){if(n.json){let r=o instanceof Error?o.message:String(o);console.log(JSON.stringify({success:!1,error:r})),process.exit(1)}b(o)}}),e}import{Command as ho}from"commander";function Ut(){let e=new ho("logout");return e.description("\u9000\u51FA\u767B\u5F55"),e.action(async()=>{try{await N().logout()}catch(t){b(t)}}),e}import{Command as yo}from"commander";function Dt(){let e=new yo("status");return e.description("\u67E5\u770B\u767B\u5F55\u72B6\u6001"),e.action(async()=>{try{await N().status()}catch(t){b(t)}}),e}import{Command as de}from"commander";function Et(){let e=new de("xianyu");e.description("\u95F2\u9C7C\u5E97\u94FA\u6388\u6743").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new de("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(ut(async n=>{let o=await Z(n.state,Number.parseInt(n.expire,10),Number.parseInt(n.interval,10));o.status==="success"?console.log(JSON.stringify({success:!0,shopId:o.shopId,shopName:o.shopName})):Lt(`\u6388\u6743\u72B6\u6001: ${o.status}`)}));return e.addCommand(t),e.action(async n=>{try{if(n.json){let{authData:o,qrUrl:r,setStatus:s,closeServer:i}=await dt(),a=o.expireTime?Number.parseInt(o.expireTime,10):3e5,c=o.pollInterval?Number.parseInt(o.pollInterval,10):1e3;console.log(JSON.stringify({state:o.state,expireTimeMs:a,pollIntervalMs:c,qrUrl:r},null,2)),R(r);try{let u=await Z(o.state,a,c,void 0,s);u.status==="success"?console.log(JSON.stringify({success:!0,shopId:u.shopId,shopName:u.shopName})):(console.log(JSON.stringify({success:!1,error:`\u6388\u6743\u72B6\u6001: ${u.status}`})),process.exit(1))}catch(u){let d=u instanceof Error?u.message:String(u);console.log(JSON.stringify({success:!1,error:d})),process.exit(1)}finally{setTimeout(i,1e3)}}else await Nt()}catch(o){if(n.json){let r=o instanceof Error?o.message:String(o);console.log(JSON.stringify({success:!1,error:r})),process.exit(1)}b(o)}}),e}import{Command as Xo}from"commander";import{Command as Io}from"commander";import v from"chalk";import{select as $t,input as So,confirm as Co}from"@inquirer/prompts";import{readFileSync as wo}from"node:fs";import{basename as xo}from"node:path";var I=it;function F(e){let t=new URLSearchParams;for(let[n,o]of Object.entries(e))o!=null&&o!==""&&t.append(n,String(o));return t}async function jt(e){return I.post("mms/goods/listing/up/xianyu",e)}async function ue(e){return I.get("mms/goods/listing/get",F({...e}))}async function me(e){return I.post("mms/goods/listing/down/xianyu",e)}async function pe(e){return I.post("mms/goods/listing/update/xyPrice",e)}async function ge(e){return I.get("mms/goods/listing/list",e?F({...e}):void 0)}async function mt(){return await I.get("mms/user/shop/list")??[]}async function pt(){return await I.get("mms/user/stock/list")??[]}async function gt(e){let t=e?F({...e}):void 0;return I.get("mms/seller/goods/select/list",t)}async function fe(e,t){let n=[];for(let o of t){let r=wo(o),s=xo(o),i=new FormData;i.append("file",new Blob([r]),s);let a=await I.upload(`platform/xy/media/upload?shopId=${encodeURIComponent(e)}`,i);n.push(a)}return n}async function he(e){return I.post("mms/goods/listing/hang/up/xianyu",e)}async function ye(e=16){return await I.get("platform/xy/cat",F({spBizType:e}))??[]}async function we(e){return await I.get("platform/xy/props",F({channelCatId:e}))??[]}async function xe(e,t,n){return await I.get("platform/xy/props/value",F({channelCatId:e,propId:t,key:n}))??[]}var Po=2e3,To=1e4;function bo(e){let t=e.status?.toLowerCase()??"";return t===""||t==="init"||t==="pending"||t==="processing"}async function Ie(e,t,n,o){o||process.stdout.write(v.cyan("\u23F3 \u6B63\u5728\u67E5\u8BE2\u4E0A\u67B6\u8FDB\u5EA6..."));let r=await J(()=>ue({stockGoodsId:e,shopId:t,platform:n}),{interval:Po,timeout:To,condition:s=>!bo(s)});return o||process.stdout.write("\r"+" ".repeat(30)+"\r"),r}function Se(){let e=new Io("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(p(async t=>{if(t.json&&!(t.stockGoodsId&&t.shopId&&t.price)&&(console.log(JSON.stringify({success:!1,error:"Agent \u6A21\u5F0F\u9700\u8981 --stock-goods-id, --shop-id, --price"})),process.exit(1)),t.stockGoodsId&&t.shopId&&t.price){let l=Number(t.stockGoodsId),P=t.shopId,yt=Number(t.price),B=t.platform,Xe=await jt({stockGoodsId:l,shopId:P,price:yt,platform:B}),wt=await Ie(l,P,B,t.json);if(t.json)console.log(JSON.stringify({success:!0,data:{submit:Xe,listing:wt}},null,2));else{let Qe=wt.status?.toLowerCase()!=="failed";console.log(Qe?v.green("\u2713 \u4E0A\u67B6\u6210\u529F"):v.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify(wt,null,2))}return}let n=await mt();if(n.length===0){console.log(v.yellow("\u6CA1\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF0C\u8BF7\u5148\u8FD0\u884C r2-cli auth xianyu \u6388\u6743"));return}let o=await $t({message:"\u9009\u62E9\u5E97\u94FA",choices:n.map(l=>({name:`${l.shopName} (${l.platform})`,value:l.shopId}))}),r=await pt();if(r.length===0){console.log(v.yellow("\u6CA1\u6709\u53EF\u7528\u7684\u4ED3\u5E93"));return}let s=await $t({message:"\u9009\u62E9\u4ED3\u5E93",choices:r.map(l=>({name:l.stockName,value:l.stockId}))}),i=await gt({stockId:s,size:100});if(!i.items?.length){console.log(v.yellow("\u8BE5\u4ED3\u5E93\u6CA1\u6709\u53EF\u9009\u7684\u5546\u54C1"));return}let a=await $t({message:"\u9009\u62E9\u5546\u54C1",choices:i.items.map(l=>({name:`${l.goodsName} ${l.size?`| ${l.size}`:""} | \xA5${l.salePrice}`,value:l.stockGoodsId}))}),c=await So({message:"\u8F93\u5165\u4E0A\u67B6\u4EF7\u683C",default:i.items.find(l=>l.stockGoodsId===a)?.salePrice?.toString()??"",validate:l=>Number(l)>0?!0:"\u4EF7\u683C\u5FC5\u987B\u4E3A\u6B63\u6570"});if(!await Co({message:`\u786E\u8BA4\u4E0A\u67B6\uFF1F\u4EF7\u683C \xA5${c}`,default:!0})){console.log(v.gray("\u5DF2\u53D6\u6D88"));return}let d=Number(a);await jt({stockGoodsId:d,shopId:o,price:Number(c),platform:"xianyu"}),console.log(v.green("\u2713 \u4E0A\u67B6\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u67E5\u8BE2\u8FDB\u5EA6..."));let w=await Ie(d,o,"xianyu"),q=w.status?.toLowerCase()!=="failed";console.log(q?v.green("\u2713 \u4E0A\u67B6\u6210\u529F"):v.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify(w,null,2))})),e}import{Command as No}from"commander";import be from"chalk";function Ae(){let e=new No("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(p(async t=>{let n=await mt();if(t.json){console.log(JSON.stringify(ce(n),null,2));return}if(!n.length){console.log(be.yellow("\u672A\u627E\u5230\u5DF2\u6388\u6743\u7684\u5E97\u94FA")),console.log(be.gray(" \u63D0\u793A: \u8BF7\u5148\u5728\u7B2C\u4E8C\u56DE\u5408 APP \u4E2D\u6388\u6743\u5E97\u94FA"));return}let{ShopsTable:o}=await Promise.resolve().then(()=>(Te(),Pe)),{renderComponent:r}=await Promise.resolve().then(()=>(ct(),at));r(o,{shops:n,platform:"all"})})),e}import{Command as Do}from"commander";import Eo from"chalk";function Re(){let e=new Do("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(p(async t=>{let n=await pt();if(t.json){console.log(JSON.stringify(n,null,2));return}if(!n.length){console.log(Eo.yellow("\u672A\u627E\u5230\u4ED3\u5E93\u4FE1\u606F"));return}let{StocksTable:o}=await Promise.resolve().then(()=>(ke(),ve)),{renderComponent:r}=await Promise.resolve().then(()=>(ct(),at));r(o,{stocks:n})})),e}import{Command as jo}from"commander";import W from"chalk";function Ne(){let e=new jo("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(p(async t=>{let o=await gt({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){o.items?.length?console.log(JSON.stringify(o,null,2)):console.log(JSON.stringify({...o,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(!o.items?.length){console.log(W.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(W.cyan(`
36
- \u9009\u54C1\u5546\u54C1\uFF08\u5171 ${o.total} \u4EF6\uFF0C\u7B2C ${o.page} \u9875\uFF09
37
- `));for(let r of o.items)console.log(` ${W.bold(r.goodsName)} ${r.size?W.gray(`| ${r.size}`):""}`),console.log(` \u54C1\u724C: ${r.brand} \u5EFA\u8BAE\u552E\u4EF7: \xA5${r.salePrice} stockGoodsId: ${W.green(r.stockGoodsId)}`),console.log(W.gray(` \u5206\u7C7B: ${r.cate1Name} > ${r.cate2Name} > ${r.cate3Name}`)),console.log()})),e}import{Command as $o}from"commander";import Le from"chalk";var qo={init:"\u5F85\u4E0A\u67B6",up:"\u5DF2\u4E0A\u67B6",down:"\u5DF2\u4E0B\u67B6",fail:"\u5931\u8D25"};function Oe(){let e=new $o("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(p(async t=>{let o=await ge({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){o.list?.length?console.log(JSON.stringify(o,null,2)):console.log(JSON.stringify({...o,hint:"\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"},null,2));return}if(!o.list?.length){console.log(Le.yellow("\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"));return}console.log(Le.green(`\u2705 \u5171 ${o.total} \u6761\u8BB0\u5F55
38
- `));for(let r of o.list){let s=qo[r.status]??r.status;console.log(` ID: ${r.id} | \u72B6\u6001: ${s} | \u4EF7\u683C: ${r.price} | stockGoodsId: ${r.stockGoodsId}`)}})),e}import{Command as Bo}from"commander";import Mt from"chalk";function Ue(){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(p(async t=>{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(Mt.yellow("\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));return}let n={};t.id&&(n.id=t.id),t.stockGoodsId&&(n.stockGoodsId=Number(t.stockGoodsId)),t.shopId&&(n.shopId=t.shopId),t.json||console.log(Mt.cyan("\u{1F4E6} \u6B63\u5728\u4E0B\u67B6\u5546\u54C1..."));let o=await me(n);t.json?console.log(JSON.stringify({success:!0,data:o},null,2)):(console.log(Mt.green("\u2705 \u4E0B\u67B6\u6210\u529F")),console.log(JSON.stringify(o,null,2)))})),e}import{Command as Go}from"commander";import ft from"chalk";function De(){let e=new Go("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(p(async t=>{if(!t.price){t.json&&(console.log(JSON.stringify({success:!1,error:"--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570"})),process.exit(1)),console.log(ft.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(ft.yellow("\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));return}let n={price:Number(t.price)};t.id&&(n.id=t.id),t.stockGoodsId&&(n.stockGoodsId=Number(t.stockGoodsId)),t.shopId&&(n.shopId=t.shopId),t.json||console.log(ft.cyan(`\u{1F4B0} \u6B63\u5728\u4FEE\u6539\u4EF7\u683C\u4E3A ${t.price}...`));let o=await pe(n);t.json?console.log(JSON.stringify({success:!0,data:o},null,2)):(console.log(ft.green("\u2705 \u4EF7\u683C\u4FEE\u6539\u6210\u529F")),console.log(JSON.stringify(o,null,2)))})),e}import{Command as V}from"commander";import y from"chalk";var Jo={100:"\u5168\u65B0",[-1]:"\u51C6\u65B0",99:"99\u65B0",95:"95\u65B0",90:"9\u65B0"};function Ee(){let e=new V("hang-up");return e.description("\u95F2\u9C7C\u6302\u552E\u4E0A\u67B6\uFF08\u5B8C\u6574\u5546\u54C1\u4FE1\u606F\u6A21\u5F0F\uFF09"),e.addCommand(new V("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(p(async t=>{let n=await ye(Number(t.spBizType));if(t.json){console.log(JSON.stringify(n,null,2));return}let o=new Map;for(let r of n){let s=String(r.catId);o.has(s)||o.set(s,{catName:r.catName,children:[]}),o.get(s).children.push({channel:r.channel,channelCatId:r.channelCatId})}for(let[,r]of o){console.log(y.bold(r.catName));for(let s of r.children)console.log(` ${s.channel} (channelCatId: ${y.green(s.channelCatId)})`)}}))),e.addCommand(new V("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(p(async t=>{let n=await we(t.channelCatId);if(t.json){console.log(JSON.stringify(n,null,2));return}for(let o of n)if(console.log(y.bold(`
39
- ${o.propName} (propId: ${o.propId})`)),o.propsValues?.length)for(let r of o.propsValues)console.log(` ${r.valueName} (valueId: ${r.valueId})`);else console.log(y.gray(" \uFF08\u4F7F\u7528 brands \u5B50\u547D\u4EE4\u641C\u7D22\uFF09"))}))),e.addCommand(new V("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(p(async t=>{let n=await xe(t.channelCatId,t.propId,t.key);if(t.json){console.log(JSON.stringify(n,null,2));return}if(!n.length){console.log(y.yellow("\u672A\u627E\u5230\u5339\u914D\u7684\u54C1\u724C"));return}for(let o of n)console.log(` ${o.valueName} (valueId: ${o.valueId})`)}))),e.addCommand(new V("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(p(async t=>{let n=t.files.split(",").map(r=>r.trim()).filter(Boolean);if(n.length===0){t.json&&(console.log(JSON.stringify({success:!1,error:"\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u5F20\u56FE\u7247"})),process.exit(1)),console.log(y.yellow("\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u5F20\u56FE\u7247"));return}t.json||console.log(y.cyan(`\u6B63\u5728\u4E0A\u4F20 ${n.length} \u5F20\u56FE\u7247...`));let o=await fe(t.shopId,n);if(t.json)console.log(JSON.stringify({success:!0,images:o},null,2));else{console.log(y.green(`\u4E0A\u4F20\u6210\u529F\uFF0C\u5171 ${o.length} \u5F20`));for(let r of o)console.log(` \u56FE\u7247ID: ${r.value}`)}}))),e.addCommand(new V("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(p(async t=>{let n=t.imageIds.split(",").map(s=>s.trim()),o={account:t.shopId,title:t.title,reservePrice:Number(t.price),categoryId:Number(t.categoryId),channelCatId:t.channelCatId,imageIdList:n,stuffStatus:Number(t.stuffStatus),itemBizType:2,spBizType:"16",tradeType:Number(t.tradeType)||0,transportFee:Number(t.transportFee)||0,yhb:t.yhb??!1,...t.brandName&&{brandName:t.brandName},...t.desc&&{desc:t.desc},...t.size&&{size:t.size},...t.goodsNo&&{goodsNo:t.goodsNo},...t.originalPrice&&{originalPrice:Number(t.originalPrice)},outItemNo:t.outItemNo,divisionId:Number(t.divisionId)||330100,apiAfterSalesDo:{supportFd10msPolicy:!1,supportFd24hsPolicy:!0,supportNfrPolicy:!0,supportSdrPolicy:!0,supportVnrPolicy:!1,supportGpaPolicy:!1,supportFd48hsPolicy:!1},...t.itemAttrs&&{itemAttrList:JSON.parse(t.itemAttrs)}};t.json||(console.log(y.cyan("\u6B63\u5728\u63D0\u4EA4\u6302\u552E...")),console.log(y.gray(` \u6807\u9898: ${o.title}`)),console.log(y.gray(` \u552E\u4EF7: \xA5${o.reservePrice}`)),console.log(y.gray(` \u6210\u8272: ${Jo[o.stuffStatus]??o.stuffStatus}`)),console.log(y.gray(` \u56FE\u7247: ${n.length} \u5F20`)),o.itemAttrList?.length&&console.log(y.gray(` \u5C5E\u6027: ${o.itemAttrList.length} \u9879`)));let r=await he(o);t.json?console.log(JSON.stringify({success:!0,data:r},null,2)):(console.log(y.green("\u6302\u552E\u63D0\u4EA4\u6210\u529F")),console.log(JSON.stringify(r,null,2)))}))),e}function je(){let e=new Xo("goods");return e.description("\u5546\u54C1\u7BA1\u7406"),e.addCommand(Ae()),e.addCommand(Re()),e.addCommand(Ne()),e.addCommand(Oe()),e.addCommand(Ue()),e.addCommand(De()),e.addCommand(Se()),e.addCommand(Ee()),e}import{Command as Qo}from"commander";import k from"chalk";import{promises as _o}from"node:fs";import Mo from"node:path";import Fo from"node:os";import{spawn as zo}from"node:child_process";var ht="@round2ai/r2-cli";function $e(){let e=new Qo("uninstall");return e.description("\u5378\u8F7D R2-CLI \u5E76\u6E05\u9664\u6240\u6709\u914D\u7F6E"),e.action(async()=>{try{console.log(k.yellow(`
40
- \u26A0\uFE0F \u5373\u5C06\u6267\u884C\u4EE5\u4E0B\u64CD\u4F5C\uFF1A`)),console.log(k.gray(" 1. \u5220\u9664\u914D\u7F6E\u76EE\u5F55 ~/.r2-cli/")),console.log(k.gray(` 2. \u5168\u5C40\u5378\u8F7D ${ht}
41
- `));let{confirm:t}=await import("@inquirer/prompts");if(!await t({message:"\u786E\u8BA4\u5378\u8F7D\uFF1F",default:!1})){console.log(k.gray("\u5DF2\u53D6\u6D88\u5378\u8F7D"));return}let o=Mo.join(Fo.homedir(),".r2-cli");try{await _o.rm(o,{recursive:!0,force:!0}),console.log(k.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u6E05\u9664"))}catch{console.log(k.yellow("\u26A0\uFE0F \u914D\u7F6E\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u5220\u9664\uFF08\u53EF\u5FFD\u7565\uFF09"))}console.log(k.cyan(`\u6B63\u5728\u5378\u8F7D ${ht}...`)),zo("npm",["uninstall","-g",ht],{stdio:"inherit",shell:!0}).on("exit",s=>{s===0?console.log(k.green(`
42
- \u2705 ${ht} \u5DF2\u5378\u8F7D`)):(console.log(k.yellow(`
43
- \u26A0\uFE0F npm \u5378\u8F7D\u5931\u8D25 (exit code: ${s})`)),console.log(k.gray(" \u5982\u901A\u8FC7 yarn/pnpm \u5B89\u88C5\uFF0C\u8BF7\u624B\u52A8\u5378\u8F7D"))),process.exit(s??1)})}catch(t){b(t)}}),e}function qe(e){let t=e.command("auth").description("\u6388\u6743\u7BA1\u7406");t.addCommand(Ot()),t.addCommand(Ut()),t.addCommand(Dt()),t.addCommand(Et()),e.addCommand(je()),e.addCommand($e())}import Be from"chalk";var Ft="@round2ai/r2-cli",Ho=[`https://registry.npmmirror.com/${encodeURIComponent(Ft)}/latest`,`https://registry.npmjs.org/${encodeURIComponent(Ft)}/latest`],Wo=5e3;async function Vo(e){let t=new AbortController,n=setTimeout(()=>t.abort(),Wo);try{let o=await fetch(e,{signal:t.signal});return o.ok?(await o.json()).version??null:null}catch{return null}finally{clearTimeout(n)}}async function Ko(){let e=await Promise.allSettled(Ho.map(Vo));for(let t of e)if(t.status==="fulfilled"&&t.value)return t.value;return null}function Yo(e,t){let n=e.split(".").map(Number),o=t.split(".").map(Number);for(let r=0;r<3;r++)if((n[r]??0)!==(o[r]??0))return(n[r]??0)>(o[r]??0);return!1}async function Ge(e){let t=await Ko();t&&Yo(t,e)&&Zo(e,t)}function Zo(e,t){console.error(Be.yellow(`
44
- Update available: ${e} \u2192 ${t}`)+Be.gray(`
45
- Run: npm update -g ${Ft}
46
- `))}async function nn(){let{default:e}=await import("figlet");console.log(K.cyan.bold(e.textSync("R2-CLI",{font:"Standard",horizontalLayout:"full"}))),console.log(K.gray(` \u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B
47
- `))}function rn(){let e=new tn;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="0.0.0";for(let o of["../package.json","../../package.json"])try{t=JSON.parse(en(on.join(import.meta.dirname,o),"utf-8")).version;break}catch{}t==="0.0.0"&&console.error(K.yellow("Warning: unable to read version from package.json")),e.version(t,"-v, --version");let n=Ge(t);return e.configureOutput({writeErr:o=>{console.error(K.red(o.replace("error:","").trim()))}}),e.action(async()=>{await nn(),e.help()}),qe(e),{program:e,updateCheckPromise:n}}function Je(){console.log(K.gray(`
48
- \u64CD\u4F5C\u5DF2\u53D6\u6D88`)),process.exit(130)}process.on("SIGINT",Je);process.on("SIGTERM",Je);var{program:sn,updateCheckPromise:an}=rn();sn.parse(process.argv);an.catch(e=>{console.error(K.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
+ });