eprolo-cli 1.0.31 → 1.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/eprolo-cli.js +87 -149
  2. package/package.json +1 -1
package/bin/eprolo-cli.js CHANGED
@@ -4,14 +4,16 @@
4
4
  const fs = require("fs");
5
5
  const os = require("os");
6
6
  const path = require("path");
7
- const https = require("https");
7
+ const http = require("http");
8
8
 
9
- const VERIFY_URL = "https://wixtest.eprolo.com/v1/auth/verify-code";
9
+ const LOGIN_API = "http://43.153.35.208:8081/aaa";
10
10
  const CONFIG_DIR = path.join(os.homedir(), ".dxb-toolkit");
11
11
  const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
12
12
 
13
13
  // ---------------------------------------------------------------------------
14
14
  // 凭据文件读写(~/.dxb-toolkit/config.json)
15
+ // 框架判定连接成功的唯一依据:凭据文件出现
16
+ // 框架读顶层明文 account 字段做授权卡片标签
15
17
  // ---------------------------------------------------------------------------
16
18
 
17
19
  function readConfig() {
@@ -64,38 +66,35 @@ function postJson(url, body) {
64
66
  return new Promise((resolve, reject) => {
65
67
  const target = new URL(url);
66
68
  const payload = JSON.stringify(body);
67
- const req = https.request(
68
- {
69
- hostname: target.hostname,
70
- port: target.port || 443,
71
- path: target.pathname + target.search,
72
- method: "POST",
73
- headers: {
74
- "Content-Type": "application/json",
75
- "Content-Length": Buffer.byteLength(payload)
76
- }
77
- },
78
- (res) => {
79
- const chunks = [];
80
- res.on("data", (chunk) => chunks.push(chunk));
81
- res.on("end", () => {
82
- const text = Buffer.concat(chunks).toString("utf8");
83
- let data;
84
- try {
85
- data = text ? JSON.parse(text) : {};
86
- } catch (_) {
87
- data = { raw: text };
88
- }
89
- if (res.statusCode < 200 || res.statusCode >= 300) {
90
- const err = new Error(`HTTP ${res.statusCode}`);
91
- err.response = data;
92
- reject(err);
93
- return;
94
- }
95
- resolve(data);
96
- });
69
+ const req = http.request({
70
+ hostname: target.hostname,
71
+ port: target.port,
72
+ path: `${target.pathname}${target.search}`,
73
+ method: "POST",
74
+ headers: {
75
+ "content-type": "application/json",
76
+ "content-length": Buffer.byteLength(payload)
97
77
  }
98
- );
78
+ }, (res) => {
79
+ const chunks = [];
80
+ res.on("data", (chunk) => chunks.push(chunk));
81
+ res.on("end", () => {
82
+ const text = Buffer.concat(chunks).toString("utf8");
83
+ let data;
84
+ try {
85
+ data = text ? JSON.parse(text) : {};
86
+ } catch (_) {
87
+ data = { raw: text };
88
+ }
89
+ if (res.statusCode < 200 || res.statusCode >= 300) {
90
+ const err = new Error(`HTTP ${res.statusCode} ${res.statusMessage || ""}`.trim());
91
+ err.response = data;
92
+ reject(err);
93
+ return;
94
+ }
95
+ resolve(data);
96
+ });
97
+ });
99
98
  req.on("error", reject);
100
99
  req.write(payload);
101
100
  req.end();
@@ -103,25 +102,19 @@ function postJson(url, body) {
103
102
  }
104
103
 
105
104
  // ---------------------------------------------------------------------------
106
- // 登录命令
107
- // 输入:env 通道 DXB_USER_CODE + arg 通道 --default-shop
108
- // 流程:调用 verify-code 接口校验密文 → 写凭据文件 → exit 0
105
+ // D2 · login 命令
106
+ // 输入契约(框架 CLI):
107
+ // userCode ← env 通道 process.env.DXB_USER_CODE
108
+ // defaultShop ← arg 通道 --default-shop
109
+ // 行为契约:
110
+ // 成功 → 写凭据文件 + exit 0
111
+ // 失败 → 非零退出 + stderr 错误信息
112
+ // ❌ 禁止交互式 prompt
109
113
  // ---------------------------------------------------------------------------
110
114
 
111
115
  async function login(argv) {
112
116
  // env 通道:框架通过 fieldInjection 注入 DXB_USER_CODE
113
- const userCode =
114
- process.env.DXB_USER_CODE ||
115
- readFlag(argv, "--user-code") ||
116
- readFlag(argv, "--userCode");
117
-
118
- if (!userCode) {
119
- console.error(JSON.stringify({
120
- success: false,
121
- errorMessage: "缺少用户密文:请在授权弹窗中填写,或设置环境变量 DXB_USER_CODE"
122
- }, null, 2));
123
- process.exit(2);
124
- }
117
+ const userCode = process.env.DXB_USER_CODE || readFlag(argv, "--user-code") || readFlag(argv, "--user-code");
125
118
 
126
119
  // arg 通道:框架通过 fieldInjection 追加 --default-shop
127
120
  const defaultShop =
@@ -132,55 +125,62 @@ async function login(argv) {
132
125
  null;
133
126
 
134
127
  // 账号标识
135
- const accountAlias =
128
+ const account =
136
129
  readFlag(argv, "--account") ||
137
130
  process.env.DXB_ACCOUNT ||
131
+ defaultShop ||
138
132
  null;
139
133
 
140
- // 调用 verify-code 接口校验密文
141
- let verifyResult;
134
+ if (!userCode) {
135
+ console.error(JSON.stringify({
136
+ success: false,
137
+ errorMessage: "缺少用户密文:请在授权弹窗中填写"
138
+ }));
139
+ process.exit(2);
140
+ }
141
+
142
+ // 调用登录接口验证密文
143
+ let loginResult;
142
144
  try {
143
- verifyResult = await postJson(VERIFY_URL, { 'openApiKey':userCode });
145
+ loginResult = await postJson(LOGIN_API, { userCode, defaultShop });
144
146
  } catch (err) {
145
147
  console.error(JSON.stringify({
146
148
  success: false,
147
- errorMessage: "密文无效或已吊销请到账号设置页重新复制",
149
+ errorMessage: "密文验证失败,请到账号设置页重新复制",
148
150
  detail: err.message,
149
151
  response: err.response || null
150
- }, null, 2));
152
+ }));
151
153
  process.exit(1);
152
154
  }
153
155
 
154
- // 校验成功,写凭据文件
155
- const account = accountAlias || verifyResult.accessToken || defaultShop || "unknown";
156
+ // 写凭据文件(D3 契约:顶层明文 account + version)
157
+ const finalAccount = account || loginResult.account || "unknown";
156
158
  const config = {
157
- account, // 顶层明文,框架读它做卡片标签
159
+ account: finalAccount,
158
160
  userCode,
159
- accessToken: verifyResult.accessToken || null,
160
- refreshToken: verifyResult.refreshToken || null,
161
- defaultShop: defaultShop || verifyResult.defaultShop || null,
162
161
  version: 1
163
162
  };
163
+ if (defaultShop) config.defaultShop = defaultShop;
164
+ if (loginResult.accessToken) config.accessToken = loginResult.accessToken;
164
165
 
165
166
  writeConfig(config);
166
167
 
167
- // 不打印敏感值
168
168
  console.log(JSON.stringify({
169
169
  success: true,
170
170
  connected: true,
171
171
  account: config.account,
172
- defaultShop: config.defaultShop
172
+ defaultShop: config.defaultShop || null
173
173
  }, null, 2));
174
174
  process.exit(0);
175
175
  }
176
176
 
177
177
  // ---------------------------------------------------------------------------
178
- // 授权状态
178
+ // auth status — 查看授权状态(凭据文件是否存在)
179
179
  // ---------------------------------------------------------------------------
180
180
 
181
181
  function authStatus() {
182
182
  const config = readConfig();
183
- const connected = fs.existsSync(CONFIG_FILE) && Boolean(config.userCode);
183
+ const connected = fs.existsSync(CONFIG_FILE);
184
184
  console.log(JSON.stringify({
185
185
  connected,
186
186
  account: config.account || null,
@@ -190,54 +190,7 @@ function authStatus() {
190
190
  }
191
191
 
192
192
  // ---------------------------------------------------------------------------
193
- // 授权验证
194
- // 读取凭据文件 → 调用 verify-code 接口验证密文是否仍然有效
195
- // ---------------------------------------------------------------------------
196
-
197
- async function authVerify(argv) {
198
- const config = readConfig();
199
-
200
- if (!config.userCode) {
201
- console.error(JSON.stringify({
202
- success: false,
203
- connected: false,
204
- errorMessage: "未连接或凭据不存在,请先执行 auth login"
205
- }, null, 2));
206
- process.exit(1);
207
- }
208
-
209
- // 支持传入额外 userCode 覆盖
210
- const userCode =
211
- readFlag(argv, "--user-code") ||
212
- process.env.DXB_USER_CODE ||
213
- config.userCode;
214
-
215
- try {
216
- const result = await postJson(VERIFY_URL, { 'openApiKey':userCode });
217
- console.log(JSON.stringify({
218
- success: true,
219
- connected: true,
220
- valid: true,
221
- account: config.account,
222
- accountFromServer: result.account || null,
223
- defaultShop: config.defaultShop
224
- }, null, 2));
225
- process.exit(0);
226
- } catch (err) {
227
- console.error(JSON.stringify({
228
- success: false,
229
- connected: false,
230
- valid: false,
231
- errorMessage: "凭据验证失败:密文无效或已过期,请重新登录",
232
- detail: err.message,
233
- response: err.response || null
234
- }, null, 2));
235
- process.exit(1);
236
- }
237
- }
238
-
239
- // ---------------------------------------------------------------------------
240
- // 退出授权
193
+ // auth logout — 退出授权(删除凭据文件)
241
194
  // ---------------------------------------------------------------------------
242
195
 
243
196
  function authLogout() {
@@ -247,82 +200,67 @@ function authLogout() {
247
200
  }
248
201
 
249
202
  // ---------------------------------------------------------------------------
250
- // 帮助
203
+ // help
251
204
  // ---------------------------------------------------------------------------
252
205
 
253
206
  function printHelp() {
254
- console.log(`DXB CLI
207
+ console.log(`DXB CLI (cli-login 形态)
255
208
 
256
209
  Usage:
257
- eprolo-cli auth login [--default-shop <shop>] [--account <alias>]
258
- 登录:调用 verify-code 校验密文,写凭据文件
259
- eprolo-cli auth verify [--user-code <code>]
260
- 验证:调用 verify-code 检查密文是否仍然有效
261
- eprolo-cli auth status
262
- 查看本地授权状态
263
- eprolo-cli auth logout
264
- 退出授权,删除凭据文件
210
+ eprolo-cli auth login [--default-shop <shop>] 登录并写凭据文件(框架通过 env 注入 DXB_USER_CODE)
211
+ eprolo-cli auth status 查看授权状态
212
+ eprolo-cli auth logout 退出授权
265
213
 
266
214
  Authorization:
267
215
  框架通过 fieldInjection 把表单值递交给 CLI:
268
- userCode → env 通道 → process.env.DXB_USER_CODE
216
+ userCode → env 通道 → process.env.DXB_USER_CODE
269
217
  defaultShop → arg 通道 → --default-shop
270
218
 
271
219
  连接成功的唯一判定:凭据文件 ~/.dxb-toolkit/config.json 出现
272
220
  凭据文件顶层明文 account 字段用于授权卡片标签
273
221
 
274
- Verify API:
275
- POST https://wixtest.eprolo.com//v1/auth/verify-code
276
- Body: { "userCode": "<用户密文>" }
277
- 200 ← { "account": "...", "accessToken": "...", ... }
278
- 401 ← { "error": "invalid_or_revoked_code" }
222
+ 登录时调用 ${LOGIN_API} 验证密文
223
+
224
+ Credential file (~/.dxb-toolkit/config.json):
225
+ {
226
+ "account": "user@example.com", // 顶层明文,框架读
227
+ "userCode": "...",
228
+ "defaultShop": "shop-001",
229
+ "version": 1
230
+ }
279
231
  `);
280
232
  }
281
233
 
282
234
  // ---------------------------------------------------------------------------
283
- // 入口
235
+ // 入口分发
284
236
  // ---------------------------------------------------------------------------
285
237
 
286
238
  async function main() {
287
239
  const argv = process.argv.slice(2);
288
- const [group, command] = argv;
289
-
290
- if (!group || group === "--help" || group === "-h") {
291
- printHelp();
292
- return;
293
- }
294
240
 
295
- if (group === "auth" && command === "login") {
241
+ if (argv[0] === "auth" && argv[1] === "login") {
296
242
  await login(argv.slice(2));
297
243
  return;
298
244
  }
299
245
 
300
- if (group === "auth" && command === "verify") {
301
- await authVerify(argv.slice(2));
302
- return;
303
- }
304
-
305
- if (group === "auth" && command === "status") {
246
+ if (argv[0] === "auth" && argv[1] === "status") {
306
247
  authStatus();
307
248
  return;
308
249
  }
309
250
 
310
- if (group === "auth" && command === "logout") {
251
+ if (argv[0] === "auth" && argv[1] === "logout") {
311
252
  authLogout();
312
253
  return;
313
254
  }
314
255
 
315
- console.error(JSON.stringify({
316
- success: false,
317
- errorMessage: `Unknown command: ${argv.join(" ")}`
318
- }, null, 2));
319
- process.exit(1);
256
+ printHelp();
320
257
  }
321
258
 
322
259
  main().catch((err) => {
323
260
  console.error(JSON.stringify({
324
261
  success: false,
325
- errorMessage: err.message
262
+ errorMessage: err.message,
263
+ response: err.response || null
326
264
  }, null, 2));
327
265
  process.exit(1);
328
266
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eprolo-cli",
3
- "version": "1.0.31",
3
+ "version": "1.0.33",
4
4
  "description": "CLI for Dianxiaobao ICBU AI publishing, authorization profile management, task submission, and task status checks.",
5
5
  "bin": {
6
6
  "eprolo": "bin/eprolo-cli.js"