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.
- package/bin/eprolo-cli.js +87 -149
- 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
|
|
7
|
+
const http = require("http");
|
|
8
8
|
|
|
9
|
-
const
|
|
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 =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
//
|
|
108
|
-
//
|
|
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
|
|
128
|
+
const account =
|
|
136
129
|
readFlag(argv, "--account") ||
|
|
137
130
|
process.env.DXB_ACCOUNT ||
|
|
131
|
+
defaultShop ||
|
|
138
132
|
null;
|
|
139
133
|
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
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
|
-
}
|
|
152
|
+
}));
|
|
151
153
|
process.exit(1);
|
|
152
154
|
}
|
|
153
155
|
|
|
154
|
-
//
|
|
155
|
-
const
|
|
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)
|
|
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>]
|
|
258
|
-
|
|
259
|
-
eprolo-cli auth
|
|
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
|
|
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
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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 (
|
|
241
|
+
if (argv[0] === "auth" && argv[1] === "login") {
|
|
296
242
|
await login(argv.slice(2));
|
|
297
243
|
return;
|
|
298
244
|
}
|
|
299
245
|
|
|
300
|
-
if (
|
|
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 (
|
|
251
|
+
if (argv[0] === "auth" && argv[1] === "logout") {
|
|
311
252
|
authLogout();
|
|
312
253
|
return;
|
|
313
254
|
}
|
|
314
255
|
|
|
315
|
-
|
|
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