@round2ai/r2-cli 1.0.10 → 1.0.12-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -12
- package/dist/README.md +24 -12
- package/dist/r2-cli.js +46 -1757
- package/package.json +7 -3
- package/scripts/install-skills.js +35 -0
- package/skills/r2-auth/SKILL.md +31 -45
- package/skills/r2-goods/SKILL.md +309 -98
- package/skills/r2-shared/SKILL.md +94 -0
- package/dist/package.json +0 -60
- package/skills/r2-cli/SKILL.md +0 -70
- /package/skills/{r2-cli → r2-shared}/_meta.json +0 -0
package/dist/r2-cli.js
CHANGED
|
@@ -1,1759 +1,48 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
lastLogin.toLocaleString()
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
] });
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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 Command15 } from "commander";
|
|
241
|
-
import { readFileSync } from "node:fs";
|
|
242
|
-
import path4 from "node:path";
|
|
243
|
-
import chalk14 from "chalk";
|
|
244
|
-
|
|
245
|
-
// src/commands/setup.ts
|
|
246
|
-
import "commander";
|
|
247
|
-
|
|
248
|
-
// src/commands/auth/login.ts
|
|
249
|
-
import { Command } from "commander";
|
|
250
|
-
|
|
251
|
-
// src/services/auth/login.ts
|
|
252
|
-
import chalk2 from "chalk";
|
|
253
|
-
|
|
254
|
-
// src/errors/index.ts
|
|
255
|
-
var R2Error = class _R2Error extends Error {
|
|
256
|
-
constructor(message, code, details) {
|
|
257
|
-
super(message);
|
|
258
|
-
this.code = code;
|
|
259
|
-
this.details = details;
|
|
260
|
-
this.name = "R2Error";
|
|
261
|
-
if (Error.captureStackTrace) {
|
|
262
|
-
Error.captureStackTrace(this, _R2Error);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
code;
|
|
266
|
-
details;
|
|
267
|
-
};
|
|
268
|
-
var ApiError = class extends R2Error {
|
|
269
|
-
constructor(message, status, response) {
|
|
270
|
-
super(message, "API_ERROR", response);
|
|
271
|
-
this.status = status;
|
|
272
|
-
this.response = response;
|
|
273
|
-
this.name = "ApiError";
|
|
274
|
-
}
|
|
275
|
-
status;
|
|
276
|
-
response;
|
|
277
|
-
};
|
|
278
|
-
var StorageError = class extends R2Error {
|
|
279
|
-
constructor(message, path5, code) {
|
|
280
|
-
super(message, "STORAGE_ERROR", { path: path5, code });
|
|
281
|
-
this.path = path5;
|
|
282
|
-
this.code = code;
|
|
283
|
-
this.name = "StorageError";
|
|
284
|
-
}
|
|
285
|
-
path;
|
|
286
|
-
code;
|
|
287
|
-
};
|
|
288
|
-
var AuthError = class extends R2Error {
|
|
289
|
-
constructor(message) {
|
|
290
|
-
super(message, "AUTH_ERROR");
|
|
291
|
-
this.name = "AuthError";
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
var PollingError = class extends R2Error {
|
|
295
|
-
constructor(message, attempts, timeout) {
|
|
296
|
-
super(message, "POLLING_ERROR", { attempts, timeout });
|
|
297
|
-
this.attempts = attempts;
|
|
298
|
-
this.timeout = timeout;
|
|
299
|
-
this.name = "PollingError";
|
|
300
|
-
}
|
|
301
|
-
attempts;
|
|
302
|
-
timeout;
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
// src/utils/polling.ts
|
|
306
|
-
async function callWithTimeout(fn, ms, parentSignal) {
|
|
307
|
-
const controller = new AbortController();
|
|
308
|
-
const onParentAbort = () => controller.abort();
|
|
309
|
-
parentSignal?.addEventListener("abort", onParentAbort, { once: true });
|
|
310
|
-
const timer = setTimeout(() => controller.abort(), ms);
|
|
311
|
-
try {
|
|
312
|
-
return await fn();
|
|
313
|
-
} catch (error) {
|
|
314
|
-
if (controller.signal.aborted && !parentSignal?.aborted) {
|
|
315
|
-
throw new PollingError("\u5355\u6B21\u8F6E\u8BE2\u8BF7\u6C42\u8D85\u65F6");
|
|
316
|
-
}
|
|
317
|
-
throw error;
|
|
318
|
-
} finally {
|
|
319
|
-
clearTimeout(timer);
|
|
320
|
-
parentSignal?.removeEventListener("abort", onParentAbort);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
async function poll(fn, options, signal) {
|
|
324
|
-
const { interval, timeout, condition } = options;
|
|
325
|
-
const startTime = Date.now();
|
|
326
|
-
let attempts = 0;
|
|
327
|
-
while (Date.now() - startTime < timeout) {
|
|
328
|
-
if (signal?.aborted) {
|
|
329
|
-
throw new PollingError("\u8F6E\u8BE2\u88AB\u4E2D\u6B62");
|
|
330
|
-
}
|
|
331
|
-
attempts++;
|
|
332
|
-
const remaining = timeout - (Date.now() - startTime);
|
|
333
|
-
const data = await callWithTimeout(fn, remaining, signal);
|
|
334
|
-
if (condition(data, attempts)) {
|
|
335
|
-
return data;
|
|
336
|
-
}
|
|
337
|
-
await sleep(interval, signal);
|
|
338
|
-
}
|
|
339
|
-
throw new PollingError(`\u8F6E\u8BE2\u8D85\u65F6 (\u5DF2\u7B49\u5F85 ${Date.now() - startTime}ms, \u5171 ${attempts} \u6B21)`);
|
|
340
|
-
}
|
|
341
|
-
function sleep(ms, signal) {
|
|
342
|
-
return new Promise((resolve, reject) => {
|
|
343
|
-
if (signal?.aborted) {
|
|
344
|
-
reject(new PollingError("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"));
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
const onAbort = () => {
|
|
348
|
-
clearTimeout(timer);
|
|
349
|
-
reject(new PollingError("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"));
|
|
350
|
-
};
|
|
351
|
-
const timer = setTimeout(() => {
|
|
352
|
-
signal?.removeEventListener("abort", onAbort);
|
|
353
|
-
resolve();
|
|
354
|
-
}, ms);
|
|
355
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// src/qr-server/render.ts
|
|
360
|
-
import fs from "node:fs";
|
|
361
|
-
import { fileURLToPath } from "node:url";
|
|
362
|
-
import { createRequire } from "node:module";
|
|
363
|
-
import path from "node:path";
|
|
364
|
-
import { exec } from "node:child_process";
|
|
365
|
-
|
|
366
|
-
// src/qr-server/server.ts
|
|
367
|
-
import http from "node:http";
|
|
368
|
-
var QrServer = class _QrServer {
|
|
369
|
-
server = null;
|
|
370
|
-
pages = /* @__PURE__ */ new Map();
|
|
371
|
-
port = 0;
|
|
372
|
-
idleTimer = null;
|
|
373
|
-
static IDLE_TIMEOUT_MS = 1e4;
|
|
374
|
-
async start() {
|
|
375
|
-
if (this.server) return this.port;
|
|
376
|
-
return new Promise((resolve, reject) => {
|
|
377
|
-
this.server = http.createServer((req, res) => this.handleRequest(req, res));
|
|
378
|
-
this.server.listen(0, "127.0.0.1", () => {
|
|
379
|
-
const addr = this.server.address();
|
|
380
|
-
if (typeof addr === "object" && addr) {
|
|
381
|
-
this.port = addr.port;
|
|
382
|
-
resolve(this.port);
|
|
383
|
-
} else {
|
|
384
|
-
reject(new Error("Failed to get server address"));
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
this.server.on("error", reject);
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
registerPage(route, html, qrBuffer, config) {
|
|
391
|
-
const existing = this.pages.get(route);
|
|
392
|
-
if (existing) {
|
|
393
|
-
existing.qrBuffer = qrBuffer;
|
|
394
|
-
existing.status = "waiting";
|
|
395
|
-
existing.config = config;
|
|
396
|
-
const payload = `data: ${JSON.stringify({ status: "waiting" })}
|
|
397
|
-
|
|
398
|
-
`;
|
|
399
|
-
for (const client4 of existing.sseClients) client4.write(payload);
|
|
400
|
-
} else {
|
|
401
|
-
this.pages.set(route, { html, qrBuffer, status: "waiting", sseClients: [], config });
|
|
402
|
-
}
|
|
403
|
-
this.resetIdleTimer();
|
|
404
|
-
}
|
|
405
|
-
unregisterPage(route) {
|
|
406
|
-
const page = this.pages.get(route);
|
|
407
|
-
if (!page) return;
|
|
408
|
-
for (const client4 of page.sseClients) client4.end();
|
|
409
|
-
page.sseClients.length = 0;
|
|
410
|
-
this.pages.delete(route);
|
|
411
|
-
if (this.pages.size === 0) this.close();
|
|
412
|
-
}
|
|
413
|
-
setStatus(route, status) {
|
|
414
|
-
const page = this.pages.get(route);
|
|
415
|
-
if (!page) return;
|
|
416
|
-
page.status = status;
|
|
417
|
-
const payload = `data: ${JSON.stringify({ status })}
|
|
418
|
-
|
|
419
|
-
`;
|
|
420
|
-
for (const client4 of page.sseClients) client4.write(payload);
|
|
421
|
-
}
|
|
422
|
-
close() {
|
|
423
|
-
if (!this.server) return;
|
|
424
|
-
if (this.idleTimer) {
|
|
425
|
-
clearTimeout(this.idleTimer);
|
|
426
|
-
this.idleTimer = null;
|
|
427
|
-
}
|
|
428
|
-
for (const page of this.pages.values()) {
|
|
429
|
-
for (const client4 of page.sseClients) client4.end();
|
|
430
|
-
page.sseClients.length = 0;
|
|
431
|
-
}
|
|
432
|
-
this.pages.clear();
|
|
433
|
-
this.server.close();
|
|
434
|
-
this.server = null;
|
|
435
|
-
this.port = 0;
|
|
436
|
-
instance = null;
|
|
437
|
-
}
|
|
438
|
-
resetIdleTimer() {
|
|
439
|
-
if (this.idleTimer) clearTimeout(this.idleTimer);
|
|
440
|
-
this.idleTimer = setTimeout(() => {
|
|
441
|
-
const hasClients = [...this.pages.values()].some((p) => p.sseClients.length > 0);
|
|
442
|
-
if (!hasClients) this.close();
|
|
443
|
-
}, _QrServer.IDLE_TIMEOUT_MS);
|
|
444
|
-
}
|
|
445
|
-
handleRequest(req, res) {
|
|
446
|
-
const url = req.url ?? "/";
|
|
447
|
-
for (const [route, page] of this.pages) {
|
|
448
|
-
if (url === route) {
|
|
449
|
-
res.writeHead(302, { Location: route + "/" });
|
|
450
|
-
res.end();
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
if (url === route + "/") {
|
|
454
|
-
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
455
|
-
res.end(page.html);
|
|
456
|
-
return;
|
|
457
|
-
}
|
|
458
|
-
if (url === route + "/qr.png") {
|
|
459
|
-
res.writeHead(200, { "Content-Type": "image/png", "Content-Length": page.qrBuffer.length });
|
|
460
|
-
res.end(page.qrBuffer);
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
if (url === route + "/events") {
|
|
464
|
-
res.writeHead(200, {
|
|
465
|
-
"Content-Type": "text/event-stream",
|
|
466
|
-
"Cache-Control": "no-cache",
|
|
467
|
-
Connection: "keep-alive"
|
|
468
|
-
});
|
|
469
|
-
res.write(`data: ${JSON.stringify({ status: page.status })}
|
|
470
|
-
|
|
471
|
-
`);
|
|
472
|
-
page.sseClients.push(res);
|
|
473
|
-
req.on("close", () => {
|
|
474
|
-
const idx = page.sseClients.indexOf(res);
|
|
475
|
-
if (idx >= 0) page.sseClients.splice(idx, 1);
|
|
476
|
-
});
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
if (url === route + "/config") {
|
|
480
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
481
|
-
res.end(JSON.stringify(page.config ?? {}));
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
486
|
-
res.end("Not Found");
|
|
487
|
-
}
|
|
488
|
-
};
|
|
489
|
-
var instance = null;
|
|
490
|
-
var listenersRegistered = false;
|
|
491
|
-
function cleanup() {
|
|
492
|
-
if (instance) instance.close();
|
|
493
|
-
}
|
|
494
|
-
function ensureProcessListeners() {
|
|
495
|
-
if (listenersRegistered) return;
|
|
496
|
-
listenersRegistered = true;
|
|
497
|
-
process.on("exit", cleanup);
|
|
498
|
-
process.on("SIGINT", cleanup);
|
|
499
|
-
process.on("SIGTERM", cleanup);
|
|
500
|
-
setInterval(() => {
|
|
501
|
-
if (process.stdin?.destroyed) cleanup();
|
|
502
|
-
}, 3e3).unref();
|
|
503
|
-
}
|
|
504
|
-
function getQrServer() {
|
|
505
|
-
if (!instance) {
|
|
506
|
-
instance = new QrServer();
|
|
507
|
-
ensureProcessListeners();
|
|
508
|
-
}
|
|
509
|
-
return instance;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
// src/qr-server/render.ts
|
|
513
|
-
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
514
|
-
var LOGIN_ROUTE = "/login";
|
|
515
|
-
var XIANYU_ROUTE = "/login-xianyu";
|
|
516
|
-
var _require = null;
|
|
517
|
-
async function loadHtml(filename) {
|
|
518
|
-
return fs.promises.readFile(path.join(__dirname, "pages", filename), "utf-8");
|
|
519
|
-
}
|
|
520
|
-
async function generateQRBuffer(content) {
|
|
521
|
-
if (!_require) _require = createRequire(import.meta.url);
|
|
522
|
-
const QRCodeLib = _require("qrcode");
|
|
523
|
-
return QRCodeLib.toBuffer(content, { width: 300, margin: 2 });
|
|
524
|
-
}
|
|
525
|
-
function openUrl(url) {
|
|
526
|
-
const cmd = process.platform === "win32" ? `start "" "${url}"` : process.platform === "darwin" ? `open "${url}"` : `xdg-open "${url}"`;
|
|
527
|
-
exec(cmd);
|
|
528
|
-
}
|
|
529
|
-
async function renderQRPage(route, htmlFile, content, config) {
|
|
530
|
-
const [html, qrBuffer] = await Promise.all([
|
|
531
|
-
loadHtml(htmlFile),
|
|
532
|
-
generateQRBuffer(content)
|
|
533
|
-
]);
|
|
534
|
-
const server = getQrServer();
|
|
535
|
-
const port = await server.start();
|
|
536
|
-
server.registerPage(route, html, qrBuffer, config);
|
|
537
|
-
const qrUrl = `http://127.0.0.1:${port}${route}/`;
|
|
538
|
-
return {
|
|
539
|
-
url: content,
|
|
540
|
-
qrUrl,
|
|
541
|
-
setStatus: (status) => server.setStatus(route, status),
|
|
542
|
-
closeServer: () => server.unregisterPage(route)
|
|
543
|
-
};
|
|
544
|
-
}
|
|
545
|
-
function renderLoginQR(content) {
|
|
546
|
-
return renderQRPage(LOGIN_ROUTE, "login.html", content);
|
|
547
|
-
}
|
|
548
|
-
function renderXianyuAuthQR(content, authUrl) {
|
|
549
|
-
return renderQRPage(XIANYU_ROUTE, "xianyu-auth.html", content, { authUrl });
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
// src/services/storage/config-store.ts
|
|
553
|
-
import { promises as fs2 } from "node:fs";
|
|
554
|
-
import path2 from "node:path";
|
|
555
|
-
import os from "node:os";
|
|
556
|
-
var CONFIG_FILE_NAME = ".r2-cli";
|
|
557
|
-
var ConfigStore = class {
|
|
558
|
-
configPath;
|
|
559
|
-
config;
|
|
560
|
-
configLoaded = false;
|
|
561
|
-
dirEnsured = false;
|
|
562
|
-
constructor() {
|
|
563
|
-
const homeDir = os.homedir();
|
|
564
|
-
const configDir = path2.join(homeDir, CONFIG_FILE_NAME);
|
|
565
|
-
this.configPath = path2.join(configDir, "config.json");
|
|
566
|
-
this.config = { credentials: null };
|
|
567
|
-
}
|
|
568
|
-
getConfigPath() {
|
|
569
|
-
return this.configPath;
|
|
570
|
-
}
|
|
571
|
-
async loadConfig() {
|
|
572
|
-
if (this.configLoaded) return this.config;
|
|
573
|
-
try {
|
|
574
|
-
const content = await fs2.readFile(this.configPath, "utf-8");
|
|
575
|
-
this.config = JSON.parse(content);
|
|
576
|
-
this.configLoaded = true;
|
|
577
|
-
return this.config;
|
|
578
|
-
} catch {
|
|
579
|
-
this.config = { credentials: null };
|
|
580
|
-
this.configLoaded = true;
|
|
581
|
-
return this.config;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
async ensureDir() {
|
|
585
|
-
if (this.dirEnsured) return;
|
|
586
|
-
const dirPath = path2.dirname(this.configPath);
|
|
587
|
-
try {
|
|
588
|
-
await fs2.stat(dirPath);
|
|
589
|
-
} catch (error) {
|
|
590
|
-
if (error.code === "ENOENT") {
|
|
591
|
-
await fs2.mkdir(dirPath, { recursive: true });
|
|
592
|
-
} else {
|
|
593
|
-
throw new StorageError("Failed to create directory", dirPath, error.code);
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
this.dirEnsured = true;
|
|
597
|
-
}
|
|
598
|
-
async saveConfig(config) {
|
|
599
|
-
this.config = config;
|
|
600
|
-
await this.ensureDir();
|
|
601
|
-
const content = JSON.stringify(config, null, 2);
|
|
602
|
-
const tmpPath = this.configPath + ".tmp";
|
|
603
|
-
try {
|
|
604
|
-
await fs2.writeFile(tmpPath, content, "utf-8");
|
|
605
|
-
await fs2.rename(tmpPath, this.configPath);
|
|
606
|
-
this.configLoaded = true;
|
|
607
|
-
} catch (error) {
|
|
608
|
-
await fs2.unlink(tmpPath).catch((e) => {
|
|
609
|
-
if (typeof process.env.DEBUG !== "undefined") console.error("[config] cleanup tmp failed:", e);
|
|
610
|
-
});
|
|
611
|
-
throw new StorageError("Failed to save config", this.configPath, error.code);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
};
|
|
615
|
-
var instance2 = null;
|
|
616
|
-
function getConfigStore() {
|
|
617
|
-
if (!instance2) instance2 = new ConfigStore();
|
|
618
|
-
return instance2;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// src/services/storage/auth-storage.ts
|
|
622
|
-
var TOKEN_EXPIRY_MARGIN_MS = 5 * 60 * 1e3;
|
|
623
|
-
var AuthStorage = class {
|
|
624
|
-
store = getConfigStore();
|
|
625
|
-
isTokenExpired(cred) {
|
|
626
|
-
if (!cred.expire) return false;
|
|
627
|
-
return Date.now() >= cred.expire - TOKEN_EXPIRY_MARGIN_MS;
|
|
628
|
-
}
|
|
629
|
-
async saveCredentials(token, userInfo) {
|
|
630
|
-
const now = Date.now();
|
|
631
|
-
const durationMs = userInfo.expire ? Number.parseInt(userInfo.expire, 10) : 0;
|
|
632
|
-
const credentials = {
|
|
633
|
-
token,
|
|
634
|
-
userInfo,
|
|
635
|
-
timestamp: now,
|
|
636
|
-
...durationMs > 0 && { expire: now + durationMs }
|
|
637
|
-
};
|
|
638
|
-
let config = await this.store.loadConfig();
|
|
639
|
-
config.credentials = credentials;
|
|
640
|
-
await this.store.saveConfig(config);
|
|
641
|
-
}
|
|
642
|
-
async getCredentials() {
|
|
643
|
-
const config = await this.store.loadConfig();
|
|
644
|
-
if (!config.credentials) return null;
|
|
645
|
-
if (this.isTokenExpired(config.credentials)) return null;
|
|
646
|
-
return config.credentials;
|
|
647
|
-
}
|
|
648
|
-
async clearCredentials() {
|
|
649
|
-
const config = await this.store.loadConfig();
|
|
650
|
-
config.credentials = null;
|
|
651
|
-
await this.store.saveConfig(config);
|
|
652
|
-
}
|
|
653
|
-
async getToken() {
|
|
654
|
-
const credentials = await this.getCredentials();
|
|
655
|
-
return credentials?.token ?? null;
|
|
656
|
-
}
|
|
657
|
-
async getUserInfo() {
|
|
658
|
-
const credentials = await this.getCredentials();
|
|
659
|
-
return credentials?.userInfo ?? null;
|
|
660
|
-
}
|
|
661
|
-
async isLoggedIn() {
|
|
662
|
-
const credentials = await this.getCredentials();
|
|
663
|
-
return credentials !== null;
|
|
664
|
-
}
|
|
665
|
-
};
|
|
666
|
-
var instance3 = null;
|
|
667
|
-
function getAuthStorage() {
|
|
668
|
-
if (!instance3) instance3 = new AuthStorage();
|
|
669
|
-
return instance3;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
// src/services/api/client.ts
|
|
673
|
-
var SERVER_BASEURL = "https://api.qiuxietang.com";
|
|
674
|
-
var ApiClientService = class {
|
|
675
|
-
config;
|
|
676
|
-
authStorage = null;
|
|
677
|
-
cachedToken = null;
|
|
678
|
-
tokenExpiry = 0;
|
|
679
|
-
constructor(config = {}) {
|
|
680
|
-
this.config = {
|
|
681
|
-
baseUrl: config.baseUrl ?? SERVER_BASEURL,
|
|
682
|
-
version: config.version ?? "v3",
|
|
683
|
-
debug: config.debug ?? false
|
|
684
|
-
};
|
|
685
|
-
this.authStorage = config.auth === false ? null : getAuthStorage();
|
|
686
|
-
}
|
|
687
|
-
buildUrl(path5) {
|
|
688
|
-
const cleanPath = path5.startsWith("/") ? path5.slice(1) : path5;
|
|
689
|
-
return `${this.config.baseUrl}/${this.config.version}/${cleanPath}`;
|
|
690
|
-
}
|
|
691
|
-
async getAuthToken() {
|
|
692
|
-
if (!this.authStorage) return void 0;
|
|
693
|
-
if (this.cachedToken && Date.now() < this.tokenExpiry) return this.cachedToken;
|
|
694
|
-
const credentials = await this.authStorage.getCredentials();
|
|
695
|
-
if (!credentials) {
|
|
696
|
-
throw new AuthError("\u8BF7\u5148\u8FD0\u884C r2-cli auth login \u767B\u5F55");
|
|
697
|
-
}
|
|
698
|
-
this.cachedToken = credentials.token;
|
|
699
|
-
this.tokenExpiry = credentials.expire ? credentials.expire - TOKEN_EXPIRY_MARGIN_MS : Date.now() + 30 * 60 * 1e3;
|
|
700
|
-
return credentials.token;
|
|
701
|
-
}
|
|
702
|
-
/**
|
|
703
|
-
* 发起请求,返回完整响应信封(含 token 等顶层字段)
|
|
704
|
-
*/
|
|
705
|
-
async requestFull(path5, reqConfig) {
|
|
706
|
-
const url = this.buildUrl(path5);
|
|
707
|
-
const { method, headers: rawHeaders, body, timeout = 3e4 } = reqConfig;
|
|
708
|
-
const token = await this.getAuthToken();
|
|
709
|
-
const headers = { ...rawHeaders, ...token ? { token } : {} };
|
|
710
|
-
const controller = new AbortController();
|
|
711
|
-
const timer = setTimeout(() => controller.abort(), timeout);
|
|
712
|
-
const init = {
|
|
713
|
-
method,
|
|
714
|
-
headers: { "Content-Type": "application/json", ...headers },
|
|
715
|
-
signal: controller.signal
|
|
716
|
-
};
|
|
717
|
-
if (body !== void 0) init.body = JSON.stringify(body);
|
|
718
|
-
if (this.config.debug) {
|
|
719
|
-
console.error(`[API ${method}]`, url, body);
|
|
720
|
-
}
|
|
721
|
-
try {
|
|
722
|
-
const response = await fetch(url, init);
|
|
723
|
-
if (!response.ok) {
|
|
724
|
-
if (response.status === 401) {
|
|
725
|
-
if (this.authStorage) {
|
|
726
|
-
this.cachedToken = null;
|
|
727
|
-
await this.authStorage.clearCredentials().catch((e) => {
|
|
728
|
-
console.error("[API] \u6E05\u9664\u51ED\u8BC1\u5931\u8D25:", e instanceof Error ? e.message : String(e));
|
|
729
|
-
});
|
|
730
|
-
}
|
|
731
|
-
throw new AuthError("\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C r2-cli auth login \u91CD\u65B0\u767B\u5F55");
|
|
732
|
-
}
|
|
733
|
-
const errorText = await response.text();
|
|
734
|
-
throw new ApiError(errorText || `${response.status} ${response.statusText}`, response.status);
|
|
735
|
-
}
|
|
736
|
-
const result = await response.json();
|
|
737
|
-
if (this.config.debug) {
|
|
738
|
-
console.error("[API Response]", result);
|
|
739
|
-
}
|
|
740
|
-
if (!result.success || result.status !== 0) {
|
|
741
|
-
throw new ApiError(result.msg || "\u672A\u77E5\u9519\u8BEF", result.status, result);
|
|
742
|
-
}
|
|
743
|
-
return result;
|
|
744
|
-
} catch (error) {
|
|
745
|
-
if (error instanceof DOMException && error.name === "AbortError") {
|
|
746
|
-
throw new ApiError(`\u8BF7\u6C42\u8D85\u65F6 (${timeout}ms)`, 408);
|
|
747
|
-
}
|
|
748
|
-
throw error;
|
|
749
|
-
} finally {
|
|
750
|
-
clearTimeout(timer);
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
async request(path5, config) {
|
|
754
|
-
const result = await this.requestFull(path5, config);
|
|
755
|
-
return result.data;
|
|
756
|
-
}
|
|
757
|
-
async get(path5, params, headers) {
|
|
758
|
-
const fullPath = params && params.size > 0 ? `${path5}?${params.toString()}` : path5;
|
|
759
|
-
return this.request(fullPath, { method: "GET", headers });
|
|
760
|
-
}
|
|
761
|
-
async post(path5, body, headers) {
|
|
762
|
-
return this.request(path5, { method: "POST", body, headers });
|
|
763
|
-
}
|
|
764
|
-
async put(path5, body, headers) {
|
|
765
|
-
return this.request(path5, { method: "PUT", body, headers });
|
|
766
|
-
}
|
|
767
|
-
async delete(path5, headers) {
|
|
768
|
-
return this.request(path5, { method: "DELETE", headers });
|
|
769
|
-
}
|
|
770
|
-
};
|
|
771
|
-
|
|
772
|
-
// src/services/api/modules/qrcode-auth.ts
|
|
773
|
-
var client = new ApiClientService({ auth: false });
|
|
774
|
-
async function generateQRCode() {
|
|
775
|
-
return client.post("app/qrcode/generate");
|
|
776
|
-
}
|
|
777
|
-
async function getQRCodeStatus(qrToken) {
|
|
778
|
-
const params = new URLSearchParams();
|
|
779
|
-
params.append("qrToken", qrToken);
|
|
780
|
-
const fullPath = `app/qrcode/status?${params.toString()}`;
|
|
781
|
-
const full = await client.requestFull(fullPath, { method: "GET" });
|
|
782
|
-
if (full.token && typeof full.data === "object" && full.data !== null) {
|
|
783
|
-
full.data.token = full.token;
|
|
784
|
-
}
|
|
785
|
-
return full.data;
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
// src/services/auth/login.ts
|
|
789
|
-
async function displayUserInfo(userInfo, lastLogin, daysSinceLogin) {
|
|
790
|
-
const { UserInfoCard: UserInfoCard2 } = await Promise.resolve().then(() => (init_UserInfoCard(), UserInfoCard_exports));
|
|
791
|
-
const { renderComponent: renderComponent2 } = await Promise.resolve().then(() => (init_render(), render_exports));
|
|
792
|
-
const props = lastLogin != null ? { userInfo, lastLogin, daysSinceLogin: daysSinceLogin ?? 0 } : { userInfo };
|
|
793
|
-
renderComponent2(UserInfoCard2, props);
|
|
794
|
-
}
|
|
795
|
-
var LoginService = class {
|
|
796
|
-
storage;
|
|
797
|
-
constructor(storage) {
|
|
798
|
-
this.storage = storage ?? getAuthStorage();
|
|
799
|
-
}
|
|
800
|
-
async generateQR() {
|
|
801
|
-
const qrData = await generateQRCode();
|
|
802
|
-
const qrContent = `https://m.puresnake.com/r2/auth/login?qrToken=${qrData.qrContent}&from=wechat`;
|
|
803
|
-
const rendered = await renderLoginQR(qrContent);
|
|
804
|
-
return { qrData, ...rendered };
|
|
805
|
-
}
|
|
806
|
-
async waitForLogin(qrToken, expireTimeMs, pollIntervalMs, signal, setStatus, silent) {
|
|
807
|
-
const result = await poll(
|
|
808
|
-
() => getQRCodeStatus(qrToken),
|
|
809
|
-
{
|
|
810
|
-
interval: pollIntervalMs,
|
|
811
|
-
timeout: expireTimeMs,
|
|
812
|
-
condition: (data) => {
|
|
813
|
-
switch (data.status) {
|
|
814
|
-
case "scanned":
|
|
815
|
-
if (!silent) {
|
|
816
|
-
console.log(chalk2.cyan(`
|
|
817
|
-
\u{1F50D} \u5DF2\u626B\u7801: ${data.userInfo?.nickname || "\u672A\u77E5\u7528\u6237"}`));
|
|
818
|
-
console.log(chalk2.yellow("\u8BF7\u5728 APP \u4E0A\u786E\u8BA4\u767B\u5F55"));
|
|
819
|
-
}
|
|
820
|
-
setStatus?.("scanning");
|
|
821
|
-
return false;
|
|
822
|
-
case "confirmed":
|
|
823
|
-
if (!silent) console.log(chalk2.green("\n\u2705 \u7528\u6237\u5DF2\u786E\u8BA4\u767B\u5F55"));
|
|
824
|
-
setStatus?.("success");
|
|
825
|
-
return true;
|
|
826
|
-
case "expired":
|
|
827
|
-
if (!silent) console.log(chalk2.red("\n\u23F0 \u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F"));
|
|
828
|
-
setStatus?.("expired");
|
|
829
|
-
return true;
|
|
830
|
-
case "canceled":
|
|
831
|
-
if (!silent) console.log(chalk2.red("\n\u{1F6AB} \u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55"));
|
|
832
|
-
setStatus?.("expired");
|
|
833
|
-
return true;
|
|
834
|
-
default:
|
|
835
|
-
return false;
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
},
|
|
839
|
-
signal ?? void 0
|
|
840
|
-
);
|
|
841
|
-
if (result.status === "confirmed" && result.token && result.userInfo) {
|
|
842
|
-
await this.storage.saveCredentials(result.token, result.userInfo);
|
|
843
|
-
return { userInfo: result.userInfo, token: result.token };
|
|
844
|
-
}
|
|
845
|
-
if (result.status === "expired") throw new AuthError("\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55");
|
|
846
|
-
if (result.status === "canceled") throw new AuthError("\u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55");
|
|
847
|
-
throw new AuthError("\u767B\u5F55\u5931\u8D25: \u672A\u83B7\u53D6\u5230\u51ED\u8BC1");
|
|
848
|
-
}
|
|
849
|
-
async login(signal) {
|
|
850
|
-
console.log(chalk2.cyan("\n\u{1F510} \u6B63\u5728\u542F\u52A8\u626B\u7801\u767B\u5F55..."));
|
|
851
|
-
const { qrData, qrUrl, setStatus, closeServer } = await this.generateQR();
|
|
852
|
-
console.log(chalk2.green("\u2705 \u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\n"));
|
|
853
|
-
console.log(chalk2.cyan(` \u94FE\u63A5: ${qrUrl}
|
|
854
|
-
`));
|
|
855
|
-
openUrl(qrUrl);
|
|
856
|
-
console.log(chalk2.yellow("\u23F3 \u7B49\u5F85\u626B\u7801...\n"));
|
|
857
|
-
const expireTimeMs = Number.parseInt(qrData.expireTime, 10);
|
|
858
|
-
const pollIntervalMs = Number.parseInt(qrData.pollInterval, 10);
|
|
859
|
-
try {
|
|
860
|
-
const result = await this.waitForLogin(qrData.qrToken, expireTimeMs, pollIntervalMs, signal, setStatus);
|
|
861
|
-
console.log(chalk2.green("\n\u2705 \u767B\u5F55\u6210\u529F\uFF01\n"));
|
|
862
|
-
displayUserInfo(result.userInfo);
|
|
863
|
-
return result;
|
|
864
|
-
} catch (error) {
|
|
865
|
-
console.log(chalk2.red("\n\u274C \u767B\u5F55\u5931\u8D25\n"));
|
|
866
|
-
throw error;
|
|
867
|
-
} finally {
|
|
868
|
-
closeServer();
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
async logout() {
|
|
872
|
-
console.log(chalk2.cyan("\n\u{1F6AA} \u6B63\u5728\u9000\u51FA\u767B\u5F55..."));
|
|
873
|
-
await this.storage.clearCredentials();
|
|
874
|
-
console.log(chalk2.green("\u2705 \u5DF2\u9000\u51FA\u767B\u5F55\n"));
|
|
875
|
-
}
|
|
876
|
-
async status() {
|
|
877
|
-
const isLoggedIn = await this.storage.isLoggedIn();
|
|
878
|
-
if (!isLoggedIn) {
|
|
879
|
-
console.log(chalk2.yellow("\u26A0\uFE0F \u5C1A\u672A\u767B\u5F55\u6216\u51ED\u8BC1\u5DF2\u8FC7\u671F\n"));
|
|
880
|
-
return;
|
|
881
|
-
}
|
|
882
|
-
const credentials = await this.storage.getCredentials();
|
|
883
|
-
const userInfo = credentials.userInfo;
|
|
884
|
-
const lastLogin = new Date(credentials.timestamp);
|
|
885
|
-
const daysSinceLogin = Math.floor((Date.now() - credentials.timestamp) / (1e3 * 60 * 60 * 24));
|
|
886
|
-
console.log(chalk2.green("\u2705 \u5DF2\u767B\u5F55\n"));
|
|
887
|
-
await displayUserInfo(userInfo, lastLogin, daysSinceLogin);
|
|
888
|
-
}
|
|
889
|
-
};
|
|
890
|
-
var loginInstance = null;
|
|
891
|
-
function getLoginService() {
|
|
892
|
-
if (!loginInstance) loginInstance = new LoginService();
|
|
893
|
-
return loginInstance;
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
// src/services/auth/xianyu-auth.ts
|
|
897
|
-
import chalk3 from "chalk";
|
|
898
|
-
|
|
899
|
-
// src/services/api/modules/xianyu-auth.ts
|
|
900
|
-
var client2 = new ApiClientService();
|
|
901
|
-
async function getAuthUrl() {
|
|
902
|
-
return client2.get("mms/xianyu/auth/url");
|
|
903
|
-
}
|
|
904
|
-
async function getAuthStatus(state) {
|
|
905
|
-
const params = new URLSearchParams({ state });
|
|
906
|
-
return client2.get("mms/xianyu/auth/status", params);
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
// src/services/auth/xianyu-auth.ts
|
|
910
|
-
async function generateAuthQR() {
|
|
911
|
-
const authData = await getAuthUrl();
|
|
912
|
-
const rendered = await renderXianyuAuthQR(authData.url, authData.url);
|
|
913
|
-
return { authData, ...rendered };
|
|
914
|
-
}
|
|
915
|
-
async function waitForAuth(state, expireMs, intervalMs, signal, setStatus) {
|
|
916
|
-
return poll(
|
|
917
|
-
() => getAuthStatus(state),
|
|
918
|
-
{
|
|
919
|
-
interval: intervalMs,
|
|
920
|
-
timeout: expireMs,
|
|
921
|
-
condition: (data) => {
|
|
922
|
-
if (data.status === "success") {
|
|
923
|
-
console.log(chalk3.green(`
|
|
924
|
-
\u2705 \u6388\u6743\u6210\u529F\uFF01\u5E97\u94FA: ${data.shopName} (${data.shopId})`));
|
|
925
|
-
setStatus?.("success");
|
|
926
|
-
return true;
|
|
927
|
-
}
|
|
928
|
-
if (data.status === "expired") {
|
|
929
|
-
console.log(chalk3.red("\n\u23F0 \u6388\u6743\u94FE\u63A5\u5DF2\u8FC7\u671F"));
|
|
930
|
-
setStatus?.("expired");
|
|
931
|
-
return true;
|
|
932
|
-
}
|
|
933
|
-
return false;
|
|
934
|
-
}
|
|
935
|
-
},
|
|
936
|
-
signal
|
|
937
|
-
);
|
|
938
|
-
}
|
|
939
|
-
async function authorize(signal) {
|
|
940
|
-
console.log(chalk3.cyan("\n\u{1F517} \u6B63\u5728\u83B7\u53D6\u95F2\u9C7C\u6388\u6743\u5730\u5740..."));
|
|
941
|
-
const { authData, qrUrl, setStatus, closeServer } = await generateAuthQR();
|
|
942
|
-
console.log(chalk3.green("\u2705 \u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\n"));
|
|
943
|
-
console.log(chalk3.cyan(` \u94FE\u63A5: ${qrUrl}`));
|
|
944
|
-
console.log(chalk3.gray(` \u6216\u590D\u5236\u94FE\u63A5\u6253\u5F00: ${authData.url}`));
|
|
945
|
-
openUrl(qrUrl);
|
|
946
|
-
console.log(chalk3.yellow("\n\u23F3 \u7B49\u5F85\u6388\u6743...\n"));
|
|
947
|
-
const expireMs = authData.expireTime ? Number.parseInt(authData.expireTime, 10) : 3e5;
|
|
948
|
-
const intervalMs = authData.pollInterval ? Number.parseInt(authData.pollInterval, 10) : 1e3;
|
|
949
|
-
try {
|
|
950
|
-
const result = await waitForAuth(authData.state, expireMs, intervalMs, signal, setStatus);
|
|
951
|
-
if (result.status === "success") return result;
|
|
952
|
-
throw new AuthError("\u95F2\u9C7C\u6388\u6743\u5931\u8D25: " + (result.status === "expired" ? "\u94FE\u63A5\u5DF2\u8FC7\u671F" : "\u672A\u77E5\u72B6\u6001"));
|
|
953
|
-
} finally {
|
|
954
|
-
closeServer();
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
// src/commands/shared.ts
|
|
959
|
-
import chalk4 from "chalk";
|
|
960
|
-
function handleCommandError(error) {
|
|
961
|
-
if (error instanceof AuthError) {
|
|
962
|
-
console.error(chalk4.red(`
|
|
963
|
-
\u25B2 ${error.message}`));
|
|
964
|
-
console.error(chalk4.gray(`\u2192 \u8BF7\u5148\u8FD0\u884C: r2-cli auth login
|
|
965
|
-
`));
|
|
966
|
-
} else if (error instanceof ApiError) {
|
|
967
|
-
console.error(chalk4.red(`\u25B2 \u64CD\u4F5C\u5931\u8D25: ${error.message}`));
|
|
968
|
-
if (error.status) {
|
|
969
|
-
console.error(chalk4.gray(` \u72B6\u6001\u7801: ${error.status}`));
|
|
970
|
-
}
|
|
971
|
-
} else if (error instanceof StorageError) {
|
|
972
|
-
console.error(chalk4.red(`\u25B2 \u914D\u7F6E\u6587\u4EF6\u5F02\u5E38: ${error.message}`));
|
|
973
|
-
if (error.path) console.error(chalk4.gray(` \u8DEF\u5F84: ${error.path}`));
|
|
974
|
-
console.error(chalk4.gray(`\u2192 \u8BF7\u5C1D\u8BD5\u91CD\u65B0\u767B\u5F55: r2-cli auth login
|
|
975
|
-
`));
|
|
976
|
-
} else {
|
|
977
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
978
|
-
console.error(chalk4.red(`\u25B2 ${msg}`));
|
|
979
|
-
}
|
|
980
|
-
process.exit(1);
|
|
981
|
-
}
|
|
982
|
-
function agentError(msg) {
|
|
983
|
-
console.log(JSON.stringify({ success: false, error: msg }));
|
|
984
|
-
process.exit(1);
|
|
985
|
-
}
|
|
986
|
-
function agentAction(fn) {
|
|
987
|
-
return async (...args) => {
|
|
988
|
-
try {
|
|
989
|
-
await fn(...args);
|
|
990
|
-
} catch (error) {
|
|
991
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
992
|
-
agentError(msg);
|
|
993
|
-
}
|
|
994
|
-
};
|
|
995
|
-
}
|
|
996
|
-
var SENSITIVE_KEYS = /* @__PURE__ */ new Set(["accessToken", "refreshExpireIn"]);
|
|
997
|
-
function sanitizeShops(shops) {
|
|
998
|
-
return shops.map((shop) => {
|
|
999
|
-
const safe = {};
|
|
1000
|
-
for (const [key, value] of Object.entries(shop)) {
|
|
1001
|
-
if (!SENSITIVE_KEYS.has(key)) safe[key] = value;
|
|
1002
|
-
}
|
|
1003
|
-
return safe;
|
|
1004
|
-
});
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
// src/commands/auth/login.ts
|
|
1008
|
-
function createLoginCommand() {
|
|
1009
|
-
const command = new Command("login");
|
|
1010
|
-
command.description("\u626B\u7801\u767B\u5F55 Round2AI \u8D26\u6237").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
|
|
1011
|
-
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) => {
|
|
1012
|
-
const service = getLoginService();
|
|
1013
|
-
const result = await service.waitForLogin(
|
|
1014
|
-
options.token,
|
|
1015
|
-
Number.parseInt(options.expire, 10),
|
|
1016
|
-
Number.parseInt(options.interval, 10)
|
|
1017
|
-
);
|
|
1018
|
-
console.log(JSON.stringify({ success: true, ...result }));
|
|
1019
|
-
}));
|
|
1020
|
-
command.addCommand(pollCmd);
|
|
1021
|
-
command.action(async (options) => {
|
|
1022
|
-
try {
|
|
1023
|
-
if (options.json) {
|
|
1024
|
-
const service = getLoginService();
|
|
1025
|
-
const { qrData, qrUrl, setStatus, closeServer } = await service.generateQR();
|
|
1026
|
-
const expireMs = Number.parseInt(qrData.expireTime, 10);
|
|
1027
|
-
const intervalMs = Number.parseInt(qrData.pollInterval, 10);
|
|
1028
|
-
console.log(JSON.stringify({
|
|
1029
|
-
qrToken: qrData.qrToken,
|
|
1030
|
-
expireTimeMs: expireMs,
|
|
1031
|
-
pollIntervalMs: intervalMs,
|
|
1032
|
-
url: `https://m.puresnake.com/r2/auth/login?qrToken=${qrData.qrContent}&from=wechat`,
|
|
1033
|
-
qrUrl
|
|
1034
|
-
}, null, 2));
|
|
1035
|
-
openUrl(qrUrl);
|
|
1036
|
-
try {
|
|
1037
|
-
const result = await service.waitForLogin(qrData.qrToken, expireMs, intervalMs, void 0, setStatus, true);
|
|
1038
|
-
console.log(JSON.stringify({ success: true, userInfo: result.userInfo }));
|
|
1039
|
-
} catch (error) {
|
|
1040
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
1041
|
-
console.log(JSON.stringify({ success: false, error: msg }));
|
|
1042
|
-
} finally {
|
|
1043
|
-
setTimeout(closeServer, 1e3);
|
|
1044
|
-
}
|
|
1045
|
-
} else {
|
|
1046
|
-
await getLoginService().login();
|
|
1047
|
-
}
|
|
1048
|
-
} catch (error) {
|
|
1049
|
-
if (options.json) {
|
|
1050
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
1051
|
-
console.log(JSON.stringify({ success: false, error: msg }));
|
|
1052
|
-
process.exit(1);
|
|
1053
|
-
}
|
|
1054
|
-
handleCommandError(error);
|
|
1055
|
-
}
|
|
1056
|
-
});
|
|
1057
|
-
return command;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
// src/commands/auth/logout.ts
|
|
1061
|
-
import { Command as Command2 } from "commander";
|
|
1062
|
-
function createLogoutCommand() {
|
|
1063
|
-
const command = new Command2("logout");
|
|
1064
|
-
command.description("\u9000\u51FA\u767B\u5F55");
|
|
1065
|
-
command.action(async () => {
|
|
1066
|
-
try {
|
|
1067
|
-
const loginService = getLoginService();
|
|
1068
|
-
await loginService.logout();
|
|
1069
|
-
} catch (error) {
|
|
1070
|
-
handleCommandError(error);
|
|
1071
|
-
}
|
|
1072
|
-
});
|
|
1073
|
-
return command;
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
// src/commands/auth/status.ts
|
|
1077
|
-
import { Command as Command3 } from "commander";
|
|
1078
|
-
function createStatusCommand() {
|
|
1079
|
-
const command = new Command3("status");
|
|
1080
|
-
command.description("\u67E5\u770B\u767B\u5F55\u72B6\u6001");
|
|
1081
|
-
command.action(async () => {
|
|
1082
|
-
try {
|
|
1083
|
-
const loginService = getLoginService();
|
|
1084
|
-
await loginService.status();
|
|
1085
|
-
} catch (error) {
|
|
1086
|
-
handleCommandError(error);
|
|
1087
|
-
}
|
|
1088
|
-
});
|
|
1089
|
-
return command;
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
// src/commands/auth/xianyu.ts
|
|
1093
|
-
import { Command as Command4 } from "commander";
|
|
1094
|
-
function createXianyuAuthCommand() {
|
|
1095
|
-
const command = new Command4("xianyu");
|
|
1096
|
-
command.description("\u95F2\u9C7C\u5E97\u94FA\u6388\u6743").option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
|
|
1097
|
-
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) => {
|
|
1098
|
-
const result = await waitForAuth(
|
|
1099
|
-
options.state,
|
|
1100
|
-
Number.parseInt(options.expire, 10),
|
|
1101
|
-
Number.parseInt(options.interval, 10)
|
|
1102
|
-
);
|
|
1103
|
-
if (result.status === "success") {
|
|
1104
|
-
console.log(JSON.stringify({ success: true, shopId: result.shopId, shopName: result.shopName }));
|
|
1105
|
-
} else {
|
|
1106
|
-
agentError(`\u6388\u6743\u72B6\u6001: ${result.status}`);
|
|
1107
|
-
}
|
|
1108
|
-
}));
|
|
1109
|
-
command.addCommand(pollCmd);
|
|
1110
|
-
command.action(async (options) => {
|
|
1111
|
-
try {
|
|
1112
|
-
if (options.json) {
|
|
1113
|
-
const { authData, qrUrl, setStatus, closeServer } = await generateAuthQR();
|
|
1114
|
-
const expireMs = authData.expireTime ? Number.parseInt(authData.expireTime, 10) : 3e5;
|
|
1115
|
-
const intervalMs = authData.pollInterval ? Number.parseInt(authData.pollInterval, 10) : 1e3;
|
|
1116
|
-
console.log(JSON.stringify({
|
|
1117
|
-
state: authData.state,
|
|
1118
|
-
expireTimeMs: expireMs,
|
|
1119
|
-
pollIntervalMs: intervalMs,
|
|
1120
|
-
qrUrl
|
|
1121
|
-
}, null, 2));
|
|
1122
|
-
openUrl(qrUrl);
|
|
1123
|
-
try {
|
|
1124
|
-
const result = await waitForAuth(authData.state, expireMs, intervalMs, void 0, setStatus);
|
|
1125
|
-
if (result.status === "success") {
|
|
1126
|
-
console.log(JSON.stringify({ success: true, shopId: result.shopId, shopName: result.shopName }));
|
|
1127
|
-
} else {
|
|
1128
|
-
console.log(JSON.stringify({ success: false, error: `\u6388\u6743\u72B6\u6001: ${result.status}` }));
|
|
1129
|
-
process.exit(1);
|
|
1130
|
-
}
|
|
1131
|
-
} catch (error) {
|
|
1132
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
1133
|
-
console.log(JSON.stringify({ success: false, error: msg }));
|
|
1134
|
-
process.exit(1);
|
|
1135
|
-
} finally {
|
|
1136
|
-
setTimeout(closeServer, 1e3);
|
|
1137
|
-
}
|
|
1138
|
-
} else {
|
|
1139
|
-
await authorize();
|
|
1140
|
-
}
|
|
1141
|
-
} catch (error) {
|
|
1142
|
-
if (options.json) {
|
|
1143
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
1144
|
-
console.log(JSON.stringify({ success: false, error: msg }));
|
|
1145
|
-
process.exit(1);
|
|
1146
|
-
}
|
|
1147
|
-
handleCommandError(error);
|
|
1148
|
-
}
|
|
1149
|
-
});
|
|
1150
|
-
return command;
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
// src/commands/goods/index.ts
|
|
1154
|
-
import { Command as Command12 } from "commander";
|
|
1155
|
-
|
|
1156
|
-
// src/commands/goods/up/index.ts
|
|
1157
|
-
import { Command as Command5 } from "commander";
|
|
1158
|
-
import chalk5 from "chalk";
|
|
1159
|
-
import { select, input, confirm } from "@inquirer/prompts";
|
|
1160
|
-
|
|
1161
|
-
// src/services/api/modules/goods.ts
|
|
1162
|
-
var client3 = new ApiClientService();
|
|
1163
|
-
function toParams(obj) {
|
|
1164
|
-
const params = new URLSearchParams();
|
|
1165
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
1166
|
-
if (value !== void 0 && value !== null && value !== "") {
|
|
1167
|
-
params.append(key, String(value));
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
return params;
|
|
1171
|
-
}
|
|
1172
|
-
async function listingUpXianyu(params) {
|
|
1173
|
-
return client3.post("mms/goods/listing/up/xianyu", params);
|
|
1174
|
-
}
|
|
1175
|
-
async function getListingInfo(params) {
|
|
1176
|
-
return client3.get("mms/goods/listing/get", toParams({ ...params }));
|
|
1177
|
-
}
|
|
1178
|
-
async function listingDownXianyu(params) {
|
|
1179
|
-
return client3.post("mms/goods/listing/down/xianyu", params);
|
|
1180
|
-
}
|
|
1181
|
-
async function listingUpdatePrice(params) {
|
|
1182
|
-
return client3.post("mms/goods/listing/update/xyPrice", params);
|
|
1183
|
-
}
|
|
1184
|
-
async function getListingList(params) {
|
|
1185
|
-
return client3.get("mms/goods/listing/list", params ? toParams({ ...params }) : void 0);
|
|
1186
|
-
}
|
|
1187
|
-
async function getUserShopList() {
|
|
1188
|
-
const data = await client3.get("mms/user/shop/list");
|
|
1189
|
-
return data ?? [];
|
|
1190
|
-
}
|
|
1191
|
-
async function getUserStockList() {
|
|
1192
|
-
const data = await client3.get("mms/user/stock/list");
|
|
1193
|
-
return data ?? [];
|
|
1194
|
-
}
|
|
1195
|
-
async function getSelectGoodsList(params) {
|
|
1196
|
-
const queryParams = params ? toParams({ ...params }) : void 0;
|
|
1197
|
-
return client3.get("mms/seller/goods/select/list", queryParams);
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
// src/commands/goods/up/index.ts
|
|
1201
|
-
var LISTING_POLL_INTERVAL = 2e3;
|
|
1202
|
-
var LISTING_POLL_TIMEOUT = 1e4;
|
|
1203
|
-
function isProcessing(info) {
|
|
1204
|
-
const status = info.status?.toLowerCase() ?? "";
|
|
1205
|
-
return status === "" || status === "init" || status === "pending" || status === "processing";
|
|
1206
|
-
}
|
|
1207
|
-
async function pollListingStatus(stockGoodsId, shopId, platform, json) {
|
|
1208
|
-
if (!json) {
|
|
1209
|
-
process.stdout.write(chalk5.cyan("\u23F3 \u6B63\u5728\u67E5\u8BE2\u4E0A\u67B6\u8FDB\u5EA6..."));
|
|
1210
|
-
}
|
|
1211
|
-
const result = await poll(
|
|
1212
|
-
() => getListingInfo({ stockGoodsId, shopId, platform }),
|
|
1213
|
-
{
|
|
1214
|
-
interval: LISTING_POLL_INTERVAL,
|
|
1215
|
-
timeout: LISTING_POLL_TIMEOUT,
|
|
1216
|
-
condition: (data) => !isProcessing(data)
|
|
1217
|
-
}
|
|
1218
|
-
);
|
|
1219
|
-
if (!json) {
|
|
1220
|
-
process.stdout.write("\r" + " ".repeat(30) + "\r");
|
|
1221
|
-
}
|
|
1222
|
-
return result;
|
|
1223
|
-
}
|
|
1224
|
-
function createUpCommand() {
|
|
1225
|
-
const command = new Command5("up");
|
|
1226
|
-
command.description("\u4E0A\u67B6\u5546\u54C1\u5230\u95F2\u9C7C");
|
|
1227
|
-
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(async (options) => {
|
|
1228
|
-
try {
|
|
1229
|
-
if (options.stockGoodsId && options.shopId && options.price) {
|
|
1230
|
-
const stockGoodsId2 = Number(options.stockGoodsId);
|
|
1231
|
-
const shopId = options.shopId;
|
|
1232
|
-
const price = Number(options.price);
|
|
1233
|
-
const platform = options.platform;
|
|
1234
|
-
const result = await listingUpXianyu({ stockGoodsId: stockGoodsId2, shopId, price, platform });
|
|
1235
|
-
const listingInfo2 = await pollListingStatus(stockGoodsId2, shopId, platform, options.json);
|
|
1236
|
-
if (options.json) {
|
|
1237
|
-
console.log(JSON.stringify({ success: true, data: { submit: result, listing: listingInfo2 } }, null, 2));
|
|
1238
|
-
} else {
|
|
1239
|
-
const statusOk2 = listingInfo2.status?.toLowerCase() !== "failed";
|
|
1240
|
-
console.log(statusOk2 ? chalk5.green("\u2713 \u4E0A\u67B6\u6210\u529F") : chalk5.red("\u2717 \u4E0A\u67B6\u5931\u8D25"));
|
|
1241
|
-
console.log(JSON.stringify(listingInfo2, null, 2));
|
|
1242
|
-
}
|
|
1243
|
-
return;
|
|
1244
|
-
}
|
|
1245
|
-
const shops = await getUserShopList();
|
|
1246
|
-
if (shops.length === 0) {
|
|
1247
|
-
console.log(chalk5.yellow("\u6CA1\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF0C\u8BF7\u5148\u8FD0\u884C r2-cli auth xianyu \u6388\u6743"));
|
|
1248
|
-
return;
|
|
1249
|
-
}
|
|
1250
|
-
const selectedShop = await select({
|
|
1251
|
-
message: "\u9009\u62E9\u5E97\u94FA",
|
|
1252
|
-
choices: shops.map((s) => ({ name: `${s.shopName} (${s.platform})`, value: s.shopId }))
|
|
1253
|
-
});
|
|
1254
|
-
const stocks = await getUserStockList();
|
|
1255
|
-
if (stocks.length === 0) {
|
|
1256
|
-
console.log(chalk5.yellow("\u6CA1\u6709\u53EF\u7528\u7684\u4ED3\u5E93"));
|
|
1257
|
-
return;
|
|
1258
|
-
}
|
|
1259
|
-
const selectedStock = await select({
|
|
1260
|
-
message: "\u9009\u62E9\u4ED3\u5E93",
|
|
1261
|
-
choices: stocks.map((s) => ({ name: s.stockName, value: s.stockId }))
|
|
1262
|
-
});
|
|
1263
|
-
const goodsList = await getSelectGoodsList({ stockId: selectedStock, size: 100 });
|
|
1264
|
-
if (!goodsList.items?.length) {
|
|
1265
|
-
console.log(chalk5.yellow("\u8BE5\u4ED3\u5E93\u6CA1\u6709\u53EF\u9009\u7684\u5546\u54C1"));
|
|
1266
|
-
return;
|
|
1267
|
-
}
|
|
1268
|
-
const selectedGoods = await select({
|
|
1269
|
-
message: "\u9009\u62E9\u5546\u54C1",
|
|
1270
|
-
choices: goodsList.items.map((g) => ({
|
|
1271
|
-
name: `${g.goodsName} ${g.size ? `| ${g.size}` : ""} | \xA5${g.salePrice}`,
|
|
1272
|
-
value: g.stockGoodsId
|
|
1273
|
-
}))
|
|
1274
|
-
});
|
|
1275
|
-
const priceInput = await input({
|
|
1276
|
-
message: "\u8F93\u5165\u4E0A\u67B6\u4EF7\u683C",
|
|
1277
|
-
default: goodsList.items.find((g) => g.stockGoodsId === selectedGoods)?.salePrice?.toString() ?? "",
|
|
1278
|
-
validate: (v) => {
|
|
1279
|
-
const n = Number(v);
|
|
1280
|
-
return n > 0 ? true : "\u4EF7\u683C\u5FC5\u987B\u4E3A\u6B63\u6570";
|
|
1281
|
-
}
|
|
1282
|
-
});
|
|
1283
|
-
const confirmed = await confirm({
|
|
1284
|
-
message: `\u786E\u8BA4\u4E0A\u67B6\uFF1F\u4EF7\u683C \xA5${priceInput}`,
|
|
1285
|
-
default: true
|
|
1286
|
-
});
|
|
1287
|
-
if (!confirmed) {
|
|
1288
|
-
console.log(chalk5.gray("\u5DF2\u53D6\u6D88"));
|
|
1289
|
-
return;
|
|
1290
|
-
}
|
|
1291
|
-
const stockGoodsId = Number(selectedGoods);
|
|
1292
|
-
await listingUpXianyu({
|
|
1293
|
-
stockGoodsId,
|
|
1294
|
-
shopId: selectedShop,
|
|
1295
|
-
price: Number(priceInput),
|
|
1296
|
-
platform: "xianyu"
|
|
1297
|
-
});
|
|
1298
|
-
console.log(chalk5.green("\u2713 \u4E0A\u67B6\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u67E5\u8BE2\u8FDB\u5EA6..."));
|
|
1299
|
-
const listingInfo = await pollListingStatus(stockGoodsId, selectedShop, "xianyu");
|
|
1300
|
-
const statusOk = listingInfo.status?.toLowerCase() !== "failed";
|
|
1301
|
-
console.log(statusOk ? chalk5.green("\u2713 \u4E0A\u67B6\u6210\u529F") : chalk5.red("\u2717 \u4E0A\u67B6\u5931\u8D25"));
|
|
1302
|
-
console.log(JSON.stringify(listingInfo, null, 2));
|
|
1303
|
-
} catch (error) {
|
|
1304
|
-
handleCommandError(error);
|
|
1305
|
-
}
|
|
1306
|
-
});
|
|
1307
|
-
return command;
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
// src/commands/goods/shops.ts
|
|
1311
|
-
import { Command as Command6 } from "commander";
|
|
1312
|
-
import chalk6 from "chalk";
|
|
1313
|
-
function createShopsCommand() {
|
|
1314
|
-
const command = new Command6("shops");
|
|
1315
|
-
command.description("\u67E5\u770B\u6240\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF08\u8DE8\u5E73\u53F0\uFF09");
|
|
1316
|
-
command.option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
|
|
1317
|
-
command.action(async (options) => {
|
|
1318
|
-
try {
|
|
1319
|
-
const shops = await getUserShopList();
|
|
1320
|
-
if (options.json) {
|
|
1321
|
-
console.log(JSON.stringify(sanitizeShops(shops), null, 2));
|
|
1322
|
-
return;
|
|
1323
|
-
}
|
|
1324
|
-
if (!shops.length) {
|
|
1325
|
-
console.log(chalk6.yellow("\u672A\u627E\u5230\u5DF2\u6388\u6743\u7684\u5E97\u94FA"));
|
|
1326
|
-
console.log(chalk6.gray(" \u63D0\u793A: \u8BF7\u5148\u5728\u7B2C\u4E8C\u56DE\u5408 APP \u4E2D\u6388\u6743\u5E97\u94FA"));
|
|
1327
|
-
return;
|
|
1328
|
-
}
|
|
1329
|
-
const { ShopsTable: ShopsTable2 } = await Promise.resolve().then(() => (init_ShopsTable(), ShopsTable_exports));
|
|
1330
|
-
const { renderComponent: renderComponent2 } = await Promise.resolve().then(() => (init_render(), render_exports));
|
|
1331
|
-
renderComponent2(ShopsTable2, { shops, platform: "all" });
|
|
1332
|
-
} catch (error) {
|
|
1333
|
-
handleCommandError(error);
|
|
1334
|
-
}
|
|
1335
|
-
});
|
|
1336
|
-
return command;
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
// src/commands/goods/stocks.ts
|
|
1340
|
-
import { Command as Command7 } from "commander";
|
|
1341
|
-
import chalk7 from "chalk";
|
|
1342
|
-
function createStocksCommand() {
|
|
1343
|
-
const command = new Command7("stocks");
|
|
1344
|
-
command.description("\u67E5\u770B\u6240\u6709\u4ED3\u5E93");
|
|
1345
|
-
command.option("--json", "\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");
|
|
1346
|
-
command.action(async (options) => {
|
|
1347
|
-
try {
|
|
1348
|
-
const stocks = await getUserStockList();
|
|
1349
|
-
if (options.json) {
|
|
1350
|
-
console.log(JSON.stringify(stocks, null, 2));
|
|
1351
|
-
return;
|
|
1352
|
-
}
|
|
1353
|
-
if (!stocks.length) {
|
|
1354
|
-
console.log(chalk7.yellow("\u672A\u627E\u5230\u4ED3\u5E93\u4FE1\u606F"));
|
|
1355
|
-
return;
|
|
1356
|
-
}
|
|
1357
|
-
const { StocksTable: StocksTable2 } = await Promise.resolve().then(() => (init_StocksTable(), StocksTable_exports));
|
|
1358
|
-
const { renderComponent: renderComponent2 } = await Promise.resolve().then(() => (init_render(), render_exports));
|
|
1359
|
-
renderComponent2(StocksTable2, { stocks });
|
|
1360
|
-
} catch (error) {
|
|
1361
|
-
handleCommandError(error);
|
|
1362
|
-
}
|
|
1363
|
-
});
|
|
1364
|
-
return command;
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
|
-
// src/commands/goods/list.ts
|
|
1368
|
-
import { Command as Command8 } from "commander";
|
|
1369
|
-
import chalk8 from "chalk";
|
|
1370
|
-
function createListCommand() {
|
|
1371
|
-
const command = new Command8("list");
|
|
1372
|
-
command.description("\u67E5\u770B\u4ED3\u5E93\u4E2D\u7684\u9009\u54C1\u5546\u54C1");
|
|
1373
|
-
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");
|
|
1374
|
-
command.action(
|
|
1375
|
-
async (options) => {
|
|
1376
|
-
try {
|
|
1377
|
-
const result = await getSelectGoodsList({
|
|
1378
|
-
stockId: options.stockId || void 0,
|
|
1379
|
-
stockGoodsId: options.stockGoodsId || void 0,
|
|
1380
|
-
page: Number(options.page) || 1,
|
|
1381
|
-
size: Number(options.size) || 20
|
|
1382
|
-
});
|
|
1383
|
-
const data = result ?? { items: [], total: 0 };
|
|
1384
|
-
if (options.json) {
|
|
1385
|
-
if (!data.items?.length) {
|
|
1386
|
-
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));
|
|
1387
|
-
} else {
|
|
1388
|
-
console.log(JSON.stringify(data, null, 2));
|
|
1389
|
-
}
|
|
1390
|
-
return;
|
|
1391
|
-
}
|
|
1392
|
-
if (!data.items?.length) {
|
|
1393
|
-
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"));
|
|
1394
|
-
return;
|
|
1395
|
-
}
|
|
1396
|
-
console.log(chalk8.cyan(`
|
|
1397
|
-
\u9009\u54C1\u5546\u54C1\uFF08\u5171 ${data.total} \u4EF6\uFF0C\u7B2C ${data.page} \u9875\uFF09
|
|
1398
|
-
`));
|
|
1399
|
-
for (const item of data.items) {
|
|
1400
|
-
console.log(
|
|
1401
|
-
` ${chalk8.bold(item.goodsName)} ${item.size ? chalk8.gray(`| ${item.size}`) : ""}`
|
|
1402
|
-
);
|
|
1403
|
-
console.log(
|
|
1404
|
-
` \u54C1\u724C: ${item.brand} \u5EFA\u8BAE\u552E\u4EF7: \xA5${item.salePrice} stockGoodsId: ${chalk8.green(item.stockGoodsId)}`
|
|
1405
|
-
);
|
|
1406
|
-
console.log(chalk8.gray(` \u5206\u7C7B: ${item.cate1Name} > ${item.cate2Name} > ${item.cate3Name}`));
|
|
1407
|
-
console.log();
|
|
1408
|
-
}
|
|
1409
|
-
} catch (error) {
|
|
1410
|
-
if (options.json) {
|
|
1411
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
1412
|
-
console.log(JSON.stringify({ success: false, error: msg }));
|
|
1413
|
-
process.exit(1);
|
|
1414
|
-
}
|
|
1415
|
-
handleCommandError(error);
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
);
|
|
1419
|
-
return command;
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
// src/commands/goods/listing.ts
|
|
1423
|
-
import { Command as Command9 } from "commander";
|
|
1424
|
-
import chalk9 from "chalk";
|
|
1425
|
-
var STATUS_MAP = {
|
|
1426
|
-
init: "\u5F85\u4E0A\u67B6",
|
|
1427
|
-
up: "\u5DF2\u4E0A\u67B6",
|
|
1428
|
-
down: "\u5DF2\u4E0B\u67B6",
|
|
1429
|
-
fail: "\u5931\u8D25"
|
|
1430
|
-
};
|
|
1431
|
-
function createListingCommand() {
|
|
1432
|
-
const command = new Command9("listing");
|
|
1433
|
-
command.description("\u67E5\u8BE2\u4E0A\u67B6\u5546\u54C1\u5217\u8868");
|
|
1434
|
-
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");
|
|
1435
|
-
command.action(
|
|
1436
|
-
async (options) => {
|
|
1437
|
-
try {
|
|
1438
|
-
const result = await getListingList({
|
|
1439
|
-
id: options.id,
|
|
1440
|
-
stockGoodsId: options.stockGoodsId ? Number(options.stockGoodsId) : void 0,
|
|
1441
|
-
shopId: options.shopId,
|
|
1442
|
-
stockId: options.stockId,
|
|
1443
|
-
status: options.status,
|
|
1444
|
-
platform: options.platform
|
|
1445
|
-
});
|
|
1446
|
-
const data = result ?? { list: [], total: 0 };
|
|
1447
|
-
if (options.json) {
|
|
1448
|
-
if (!data.list?.length) {
|
|
1449
|
-
console.log(JSON.stringify({ ...data, hint: "\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55" }, null, 2));
|
|
1450
|
-
} else {
|
|
1451
|
-
console.log(JSON.stringify(data, null, 2));
|
|
1452
|
-
}
|
|
1453
|
-
return;
|
|
1454
|
-
}
|
|
1455
|
-
if (!data.list?.length) {
|
|
1456
|
-
console.log(chalk9.yellow("\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"));
|
|
1457
|
-
return;
|
|
1458
|
-
}
|
|
1459
|
-
console.log(chalk9.green(`\u2705 \u5171 ${data.total} \u6761\u8BB0\u5F55
|
|
1460
|
-
`));
|
|
1461
|
-
for (const item of data.list) {
|
|
1462
|
-
const statusText = STATUS_MAP[item.status] ?? item.status;
|
|
1463
|
-
console.log(` ID: ${item.id} | \u72B6\u6001: ${statusText} | \u4EF7\u683C: ${item.price} | stockGoodsId: ${item.stockGoodsId}`);
|
|
1464
|
-
}
|
|
1465
|
-
} catch (error) {
|
|
1466
|
-
if (options.json) {
|
|
1467
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
1468
|
-
console.log(JSON.stringify({ success: false, error: msg }));
|
|
1469
|
-
process.exit(1);
|
|
1470
|
-
}
|
|
1471
|
-
handleCommandError(error);
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
);
|
|
1475
|
-
return command;
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1478
|
-
// src/commands/goods/down.ts
|
|
1479
|
-
import { Command as Command10 } from "commander";
|
|
1480
|
-
import chalk10 from "chalk";
|
|
1481
|
-
function createDownCommand() {
|
|
1482
|
-
const command = new Command10("down");
|
|
1483
|
-
command.description("\u4E0B\u67B6\u95F2\u9C7C\u5546\u54C1");
|
|
1484
|
-
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");
|
|
1485
|
-
command.action(
|
|
1486
|
-
async (options) => {
|
|
1487
|
-
try {
|
|
1488
|
-
if (!options.id && !(options.stockGoodsId && options.shopId)) {
|
|
1489
|
-
if (options.json) {
|
|
1490
|
-
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>" }));
|
|
1491
|
-
process.exit(1);
|
|
1492
|
-
}
|
|
1493
|
-
console.log(chalk10.yellow("\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));
|
|
1494
|
-
return;
|
|
1495
|
-
}
|
|
1496
|
-
const params = {};
|
|
1497
|
-
if (options.id) params.id = options.id;
|
|
1498
|
-
if (options.stockGoodsId) params.stockGoodsId = Number(options.stockGoodsId);
|
|
1499
|
-
if (options.shopId) params.shopId = options.shopId;
|
|
1500
|
-
if (!options.json) console.log(chalk10.cyan("\u{1F4E6} \u6B63\u5728\u4E0B\u67B6\u5546\u54C1..."));
|
|
1501
|
-
const result = await listingDownXianyu(params);
|
|
1502
|
-
if (options.json) {
|
|
1503
|
-
console.log(JSON.stringify({ success: true, data: result }, null, 2));
|
|
1504
|
-
} else {
|
|
1505
|
-
console.log(chalk10.green("\u2705 \u4E0B\u67B6\u6210\u529F"));
|
|
1506
|
-
console.log(JSON.stringify(result, null, 2));
|
|
1507
|
-
}
|
|
1508
|
-
} catch (error) {
|
|
1509
|
-
if (options.json) {
|
|
1510
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
1511
|
-
console.log(JSON.stringify({ success: false, error: msg }));
|
|
1512
|
-
process.exit(1);
|
|
1513
|
-
}
|
|
1514
|
-
handleCommandError(error);
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
);
|
|
1518
|
-
return command;
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
// src/commands/goods/price.ts
|
|
1522
|
-
import { Command as Command11 } from "commander";
|
|
1523
|
-
import chalk11 from "chalk";
|
|
1524
|
-
function createPriceCommand() {
|
|
1525
|
-
const command = new Command11("price");
|
|
1526
|
-
command.description("\u4FEE\u6539\u95F2\u9C7C\u4E0A\u67B6\u5546\u54C1\u4EF7\u683C");
|
|
1527
|
-
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");
|
|
1528
|
-
command.action(
|
|
1529
|
-
async (options) => {
|
|
1530
|
-
try {
|
|
1531
|
-
if (!options.price) {
|
|
1532
|
-
if (options.json) {
|
|
1533
|
-
console.log(JSON.stringify({ success: false, error: "--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570" }));
|
|
1534
|
-
process.exit(1);
|
|
1535
|
-
}
|
|
1536
|
-
console.log(chalk11.yellow("--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570"));
|
|
1537
|
-
return;
|
|
1538
|
-
}
|
|
1539
|
-
if (!options.id && !(options.stockGoodsId && options.shopId)) {
|
|
1540
|
-
if (options.json) {
|
|
1541
|
-
console.log(JSON.stringify({ success: false, error: "\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>" }));
|
|
1542
|
-
process.exit(1);
|
|
1543
|
-
}
|
|
1544
|
-
console.log(chalk11.yellow("\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));
|
|
1545
|
-
return;
|
|
1546
|
-
}
|
|
1547
|
-
const params = { price: Number(options.price) };
|
|
1548
|
-
if (options.id) params.id = options.id;
|
|
1549
|
-
if (options.stockGoodsId) params.stockGoodsId = Number(options.stockGoodsId);
|
|
1550
|
-
if (options.shopId) params.shopId = options.shopId;
|
|
1551
|
-
if (!options.json) console.log(chalk11.cyan(`\u{1F4B0} \u6B63\u5728\u4FEE\u6539\u4EF7\u683C\u4E3A ${options.price}...`));
|
|
1552
|
-
const result = await listingUpdatePrice(params);
|
|
1553
|
-
if (options.json) {
|
|
1554
|
-
console.log(JSON.stringify({ success: true, data: result }, null, 2));
|
|
1555
|
-
} else {
|
|
1556
|
-
console.log(chalk11.green("\u2705 \u4EF7\u683C\u4FEE\u6539\u6210\u529F"));
|
|
1557
|
-
console.log(JSON.stringify(result, null, 2));
|
|
1558
|
-
}
|
|
1559
|
-
} catch (error) {
|
|
1560
|
-
if (options.json) {
|
|
1561
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
1562
|
-
console.log(JSON.stringify({ success: false, error: msg }));
|
|
1563
|
-
process.exit(1);
|
|
1564
|
-
}
|
|
1565
|
-
handleCommandError(error);
|
|
1566
|
-
}
|
|
1567
|
-
}
|
|
1568
|
-
);
|
|
1569
|
-
return command;
|
|
1570
|
-
}
|
|
1571
|
-
|
|
1572
|
-
// src/commands/goods/index.ts
|
|
1573
|
-
function createGoodsCommand() {
|
|
1574
|
-
const command = new Command12("goods");
|
|
1575
|
-
command.description("\u5546\u54C1\u7BA1\u7406");
|
|
1576
|
-
command.addCommand(createShopsCommand());
|
|
1577
|
-
command.addCommand(createStocksCommand());
|
|
1578
|
-
command.addCommand(createListCommand());
|
|
1579
|
-
command.addCommand(createListingCommand());
|
|
1580
|
-
command.addCommand(createDownCommand());
|
|
1581
|
-
command.addCommand(createPriceCommand());
|
|
1582
|
-
command.addCommand(createUpCommand());
|
|
1583
|
-
return command;
|
|
1584
|
-
}
|
|
1585
|
-
|
|
1586
|
-
// src/commands/uninstall.ts
|
|
1587
|
-
import { Command as Command13 } from "commander";
|
|
1588
|
-
import chalk12 from "chalk";
|
|
1589
|
-
import { promises as fs3 } from "node:fs";
|
|
1590
|
-
import path3 from "node:path";
|
|
1591
|
-
import os2 from "node:os";
|
|
1592
|
-
import { spawn } from "node:child_process";
|
|
1593
|
-
var PKG_NAME = "@round2ai/r2-cli";
|
|
1594
|
-
function createUninstallCommand() {
|
|
1595
|
-
const command = new Command13("uninstall");
|
|
1596
|
-
command.description("\u5378\u8F7D R2-CLI \u5E76\u6E05\u9664\u6240\u6709\u914D\u7F6E");
|
|
1597
|
-
command.action(async () => {
|
|
1598
|
-
try {
|
|
1599
|
-
console.log(chalk12.yellow("\n\u26A0\uFE0F \u5373\u5C06\u6267\u884C\u4EE5\u4E0B\u64CD\u4F5C\uFF1A"));
|
|
1600
|
-
console.log(chalk12.gray(` 1. \u5220\u9664\u914D\u7F6E\u76EE\u5F55 ~/.r2-cli/`));
|
|
1601
|
-
console.log(chalk12.gray(` 2. \u5168\u5C40\u5378\u8F7D ${PKG_NAME}
|
|
1602
|
-
`));
|
|
1603
|
-
const { confirm: confirm2 } = await import("@inquirer/prompts");
|
|
1604
|
-
const confirmed = await confirm2({ message: "\u786E\u8BA4\u5378\u8F7D\uFF1F", default: false });
|
|
1605
|
-
if (!confirmed) {
|
|
1606
|
-
console.log(chalk12.gray("\u5DF2\u53D6\u6D88\u5378\u8F7D"));
|
|
1607
|
-
return;
|
|
1608
|
-
}
|
|
1609
|
-
const configDir = path3.join(os2.homedir(), ".r2-cli");
|
|
1610
|
-
try {
|
|
1611
|
-
await fs3.rm(configDir, { recursive: true, force: true });
|
|
1612
|
-
console.log(chalk12.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u6E05\u9664"));
|
|
1613
|
-
} catch {
|
|
1614
|
-
console.log(chalk12.yellow("\u26A0\uFE0F \u914D\u7F6E\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u5220\u9664\uFF08\u53EF\u5FFD\u7565\uFF09"));
|
|
1615
|
-
}
|
|
1616
|
-
console.log(chalk12.cyan(`\u6B63\u5728\u5378\u8F7D ${PKG_NAME}...`));
|
|
1617
|
-
const child = spawn("npm", ["uninstall", "-g", PKG_NAME], {
|
|
1618
|
-
stdio: "inherit",
|
|
1619
|
-
shell: true
|
|
1620
|
-
});
|
|
1621
|
-
child.on("exit", (code) => {
|
|
1622
|
-
if (code === 0) {
|
|
1623
|
-
console.log(chalk12.green(`
|
|
1624
|
-
\u2705 ${PKG_NAME} \u5DF2\u5378\u8F7D`));
|
|
1625
|
-
} else {
|
|
1626
|
-
console.log(chalk12.yellow(`
|
|
1627
|
-
\u26A0\uFE0F npm \u5378\u8F7D\u5931\u8D25 (exit code: ${code})`));
|
|
1628
|
-
console.log(chalk12.gray(" \u5982\u901A\u8FC7 yarn/pnpm \u5B89\u88C5\uFF0C\u8BF7\u624B\u52A8\u5378\u8F7D"));
|
|
1629
|
-
}
|
|
1630
|
-
process.exit(code ?? 1);
|
|
1631
|
-
});
|
|
1632
|
-
} catch (error) {
|
|
1633
|
-
handleCommandError(error);
|
|
1634
|
-
}
|
|
1635
|
-
});
|
|
1636
|
-
return command;
|
|
1637
|
-
}
|
|
1638
|
-
|
|
1639
|
-
// src/commands/setup.ts
|
|
1640
|
-
function setupCommands(program2) {
|
|
1641
|
-
const authCommand = program2.command("auth").description("\u6388\u6743\u7BA1\u7406");
|
|
1642
|
-
authCommand.addCommand(createLoginCommand());
|
|
1643
|
-
authCommand.addCommand(createLogoutCommand());
|
|
1644
|
-
authCommand.addCommand(createStatusCommand());
|
|
1645
|
-
authCommand.addCommand(createXianyuAuthCommand());
|
|
1646
|
-
program2.addCommand(createGoodsCommand());
|
|
1647
|
-
program2.addCommand(createUninstallCommand());
|
|
1648
|
-
}
|
|
1649
|
-
|
|
1650
|
-
// src/services/update-check/index.ts
|
|
1651
|
-
import chalk13 from "chalk";
|
|
1652
|
-
var PKG_NAME2 = "@round2ai/r2-cli";
|
|
1653
|
-
var REGISTRY_URLS = [
|
|
1654
|
-
`https://registry.npmmirror.com/${encodeURIComponent(PKG_NAME2)}/latest`,
|
|
1655
|
-
`https://registry.npmjs.org/${encodeURIComponent(PKG_NAME2)}/latest`
|
|
1656
|
-
];
|
|
1657
|
-
var FETCH_TIMEOUT_MS = 5e3;
|
|
1658
|
-
async function fetchVersionFromRegistry(url) {
|
|
1659
|
-
const controller = new AbortController();
|
|
1660
|
-
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
1661
|
-
try {
|
|
1662
|
-
const res = await fetch(url, { signal: controller.signal });
|
|
1663
|
-
if (!res.ok) return null;
|
|
1664
|
-
return (await res.json()).version ?? null;
|
|
1665
|
-
} catch {
|
|
1666
|
-
return null;
|
|
1667
|
-
} finally {
|
|
1668
|
-
clearTimeout(timer);
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
async function fetchLatestVersion() {
|
|
1672
|
-
const results = await Promise.allSettled(REGISTRY_URLS.map(fetchVersionFromRegistry));
|
|
1673
|
-
for (const r of results) {
|
|
1674
|
-
if (r.status === "fulfilled" && r.value) return r.value;
|
|
1675
|
-
}
|
|
1676
|
-
return null;
|
|
1677
|
-
}
|
|
1678
|
-
function isNewer(latest, current) {
|
|
1679
|
-
const la = latest.split(".").map(Number);
|
|
1680
|
-
const cu = current.split(".").map(Number);
|
|
1681
|
-
for (let i = 0; i < 3; i++) {
|
|
1682
|
-
if ((la[i] ?? 0) !== (cu[i] ?? 0)) return (la[i] ?? 0) > (cu[i] ?? 0);
|
|
1683
|
-
}
|
|
1684
|
-
return false;
|
|
1685
|
-
}
|
|
1686
|
-
async function checkForUpdate(currentVersion) {
|
|
1687
|
-
const latest = await fetchLatestVersion();
|
|
1688
|
-
if (!latest) return;
|
|
1689
|
-
if (isNewer(latest, currentVersion)) {
|
|
1690
|
-
showUpdateNotification(currentVersion, latest);
|
|
1691
|
-
}
|
|
1692
|
-
}
|
|
1693
|
-
function showUpdateNotification(current, latest) {
|
|
1694
|
-
console.error(
|
|
1695
|
-
chalk13.yellow(`
|
|
1696
|
-
Update available: ${current} \u2192 ${latest}`) + chalk13.gray(`
|
|
1697
|
-
Run: npm update -g ${PKG_NAME2}
|
|
1698
|
-
`)
|
|
1699
|
-
);
|
|
1700
|
-
}
|
|
1701
|
-
|
|
1702
|
-
// src/entrypoints/r2-cli.tsx
|
|
1703
|
-
async function displayWelcomeMessage() {
|
|
1704
|
-
const { default: figlet } = await import("figlet");
|
|
1705
|
-
console.log(
|
|
1706
|
-
chalk14.cyan.bold(
|
|
1707
|
-
figlet.textSync("R2-CLI", {
|
|
1708
|
-
font: "Standard",
|
|
1709
|
-
horizontalLayout: "full"
|
|
1710
|
-
})
|
|
1711
|
-
)
|
|
1712
|
-
);
|
|
1713
|
-
console.log(chalk14.gray(" \u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B\n"));
|
|
1714
|
-
}
|
|
1715
|
-
function setupCliApp() {
|
|
1716
|
-
const program2 = new Command15();
|
|
1717
|
-
program2.name("r2-cli").description("R2-CLI\uFF0C\u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B");
|
|
1718
|
-
const pkgPaths = [
|
|
1719
|
-
path4.join(import.meta.dirname, "../../package.json"),
|
|
1720
|
-
// 项目根目录
|
|
1721
|
-
path4.join(import.meta.dirname, "package.json")
|
|
1722
|
-
// dist 目录下
|
|
1723
|
-
];
|
|
1724
|
-
let version = "0.0.0";
|
|
1725
|
-
for (const p of pkgPaths) {
|
|
1726
|
-
try {
|
|
1727
|
-
version = JSON.parse(readFileSync(p, "utf-8")).version;
|
|
1728
|
-
break;
|
|
1729
|
-
} catch {
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
if (version === "0.0.0") {
|
|
1733
|
-
console.error(chalk14.yellow("Warning: unable to read version from package.json"));
|
|
1734
|
-
}
|
|
1735
|
-
program2.version(version, "-v, --version");
|
|
1736
|
-
const updateCheckPromise2 = checkForUpdate(version);
|
|
1737
|
-
program2.configureOutput({
|
|
1738
|
-
writeErr: (str) => {
|
|
1739
|
-
console.error(chalk14.red(str.replace("error:", "").trim()));
|
|
1740
|
-
}
|
|
1741
|
-
});
|
|
1742
|
-
program2.action(async () => {
|
|
1743
|
-
await displayWelcomeMessage();
|
|
1744
|
-
program2.help();
|
|
1745
|
-
});
|
|
1746
|
-
setupCommands(program2);
|
|
1747
|
-
return { program: program2, updateCheckPromise: updateCheckPromise2 };
|
|
1748
|
-
}
|
|
1749
|
-
function handleSignal() {
|
|
1750
|
-
console.log(chalk14.gray("\n\u64CD\u4F5C\u5DF2\u53D6\u6D88"));
|
|
1751
|
-
process.exit(130);
|
|
1752
|
-
}
|
|
1753
|
-
process.on("SIGINT", handleSignal);
|
|
1754
|
-
process.on("SIGTERM", handleSignal);
|
|
1755
|
-
var { program, updateCheckPromise } = setupCliApp();
|
|
1756
|
-
program.parse(process.argv);
|
|
1757
|
-
updateCheckPromise.catch((e) => {
|
|
1758
|
-
console.error(chalk14.gray(`[update-check] ${e instanceof Error ? e.message : String(e)}`));
|
|
1759
|
-
});
|
|
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)}`))});
|