@zrhsh/wukong-cli 0.1.5 → 0.1.7
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 +140 -120
- package/dist/cli.js +248 -175
- package/dist/cli.js.map +1 -1
- package/package.json +18 -2
package/dist/cli.js
CHANGED
|
@@ -29,6 +29,65 @@ var init_esm_shims = __esm({
|
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
+
// src/utils/debug.ts
|
|
33
|
+
import chalk from "chalk";
|
|
34
|
+
function setDebugMode(enabled, explicit = true) {
|
|
35
|
+
if (explicit) {
|
|
36
|
+
debugMode = enabled;
|
|
37
|
+
explicitSet = true;
|
|
38
|
+
}
|
|
39
|
+
global.__debugMode = enabled;
|
|
40
|
+
}
|
|
41
|
+
function isDebugMode() {
|
|
42
|
+
if (explicitSet) {
|
|
43
|
+
return debugMode === true;
|
|
44
|
+
}
|
|
45
|
+
if (global.__debugMode === true) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return process.env.WUKONG_CLI_DEBUG === "true";
|
|
49
|
+
}
|
|
50
|
+
function debugRequest(method, url, headers, body) {
|
|
51
|
+
if (!isDebugMode()) return;
|
|
52
|
+
console.log("");
|
|
53
|
+
console.log(chalk.dim("=== HTTP Request ==="));
|
|
54
|
+
console.log(chalk.cyan(`${method} ${url}`));
|
|
55
|
+
if (headers) {
|
|
56
|
+
console.log(chalk.dim("Headers:"));
|
|
57
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
58
|
+
if (key.toLowerCase() === "authorization") {
|
|
59
|
+
const truncated = value.length > 50 ? value.substring(0, 50) + "..." : value;
|
|
60
|
+
console.log(chalk.dim(` ${key}: ${truncated}`));
|
|
61
|
+
} else {
|
|
62
|
+
console.log(chalk.dim(` ${key}: ${value}`));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (body) {
|
|
67
|
+
console.log(chalk.dim("Body:"));
|
|
68
|
+
console.log(chalk.dim(JSON.stringify(body, null, 2)));
|
|
69
|
+
}
|
|
70
|
+
console.log("");
|
|
71
|
+
}
|
|
72
|
+
function debugResponse(status, statusText, body, duration) {
|
|
73
|
+
if (!isDebugMode()) return;
|
|
74
|
+
const statusColor = status >= 200 && status < 300 ? chalk.green : chalk.red;
|
|
75
|
+
console.log(chalk.dim("=== HTTP Response") + chalk.dim(` (${duration}ms) ===`));
|
|
76
|
+
console.log(statusColor(`Status: ${status} ${statusText}`));
|
|
77
|
+
console.log(chalk.dim("Body:"));
|
|
78
|
+
console.log(chalk.dim(JSON.stringify(body, null, 2)));
|
|
79
|
+
console.log("");
|
|
80
|
+
}
|
|
81
|
+
var debugMode, explicitSet;
|
|
82
|
+
var init_debug = __esm({
|
|
83
|
+
"src/utils/debug.ts"() {
|
|
84
|
+
"use strict";
|
|
85
|
+
init_esm_shims();
|
|
86
|
+
debugMode = null;
|
|
87
|
+
explicitSet = false;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
32
91
|
// src/constants/config.ts
|
|
33
92
|
var API_ENDPOINTS, POLL_CONFIG;
|
|
34
93
|
var init_config = __esm({
|
|
@@ -67,30 +126,30 @@ var init_environments = __esm({
|
|
|
67
126
|
ENVIRONMENTS = {
|
|
68
127
|
dev: {
|
|
69
128
|
name: "dev",
|
|
70
|
-
displayName: "
|
|
129
|
+
displayName: "Development",
|
|
71
130
|
authBaseUrl: "https://portal-dev.zrhsh.com",
|
|
72
131
|
apiBaseUrl: "https://nrp-recode-dev.zrhsh.com",
|
|
73
132
|
clientId: "wukong-cli-dev"
|
|
74
133
|
},
|
|
75
134
|
beta: {
|
|
76
135
|
name: "beta",
|
|
77
|
-
displayName: "
|
|
136
|
+
displayName: "Testing",
|
|
78
137
|
authBaseUrl: "https://portal-beta.zrhsh.com",
|
|
79
138
|
apiBaseUrl: "https://nrp-recode.zrhsh.com",
|
|
80
139
|
clientId: "wukong-cli-beta"
|
|
81
140
|
},
|
|
82
141
|
uat: {
|
|
83
142
|
name: "uat",
|
|
84
|
-
displayName: "UAT
|
|
143
|
+
displayName: "UAT (User Acceptance Testing)",
|
|
85
144
|
authBaseUrl: "https://portal-uat.zrhsh.com",
|
|
86
|
-
apiBaseUrl: "https://nrp-
|
|
145
|
+
apiBaseUrl: "https://nrp-pd.zrhsh.com",
|
|
87
146
|
clientId: "wukong-cli-uat"
|
|
88
147
|
},
|
|
89
148
|
prod: {
|
|
90
149
|
name: "prod",
|
|
91
|
-
displayName: "
|
|
150
|
+
displayName: "Production",
|
|
92
151
|
authBaseUrl: "https://portal.zrhsh.com",
|
|
93
|
-
apiBaseUrl: "https://nrp
|
|
152
|
+
apiBaseUrl: "https://nrp.zrhsh.com",
|
|
94
153
|
clientId: "wukong-cli-prod"
|
|
95
154
|
}
|
|
96
155
|
};
|
|
@@ -167,17 +226,27 @@ function loadConfig() {
|
|
|
167
226
|
}
|
|
168
227
|
function getMergedEnvironmentConfig(env) {
|
|
169
228
|
const config = loadConfig();
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
229
|
+
if (!config.environments || !(env in config.environments)) {
|
|
230
|
+
throw new Error(
|
|
231
|
+
`Environment '${env}' not found in configuration. Please run 'wukong-cli init' to create a valid configuration file.`
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
const envConfig = config.environments[env];
|
|
235
|
+
const requiredFields = ["authBaseUrl", "apiBaseUrl", "clientId"];
|
|
236
|
+
const missingFields = requiredFields.filter((field) => !(field in envConfig));
|
|
237
|
+
if (missingFields.length > 0) {
|
|
238
|
+
throw new Error(
|
|
239
|
+
`Missing required configuration fields for environment '${env}': ${missingFields.join(", ")}. Please run 'wukong-cli init' to create a valid configuration file.`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
const defaultConfig = ENVIRONMENTS[env];
|
|
243
|
+
const displayName = defaultConfig?.displayName || env;
|
|
175
244
|
return {
|
|
176
245
|
name: env,
|
|
177
|
-
displayName
|
|
178
|
-
authBaseUrl:
|
|
179
|
-
apiBaseUrl:
|
|
180
|
-
clientId:
|
|
246
|
+
displayName,
|
|
247
|
+
authBaseUrl: envConfig.authBaseUrl,
|
|
248
|
+
apiBaseUrl: envConfig.apiBaseUrl,
|
|
249
|
+
clientId: envConfig.clientId
|
|
181
250
|
};
|
|
182
251
|
}
|
|
183
252
|
function getAllEnvironments() {
|
|
@@ -236,15 +305,15 @@ function getEnvironmentConfig() {
|
|
|
236
305
|
return getMergedEnvironmentConfig(getCurrentEnvironment());
|
|
237
306
|
}
|
|
238
307
|
function getOceanetConfig() {
|
|
239
|
-
const
|
|
308
|
+
const envConfig = getEnvironmentConfig();
|
|
240
309
|
const env = getCurrentEnvironment();
|
|
241
310
|
return {
|
|
242
311
|
// 认证服务基础地址 (设备码授权、登录、登出等)
|
|
243
|
-
AUTH_BASE_URL:
|
|
312
|
+
AUTH_BASE_URL: envConfig.authBaseUrl,
|
|
244
313
|
// 业务 API 基础地址
|
|
245
|
-
API_BASE_URL:
|
|
314
|
+
API_BASE_URL: envConfig.apiBaseUrl,
|
|
246
315
|
// 客户端 ID
|
|
247
|
-
CLIENT_ID:
|
|
316
|
+
CLIENT_ID: envConfig.clientId,
|
|
248
317
|
// Token 存储服务名(不同环境分开存储)
|
|
249
318
|
SERVICE_NAME: `wukong-cli-${env}`,
|
|
250
319
|
// 轮询配置
|
|
@@ -253,11 +322,11 @@ function getOceanetConfig() {
|
|
|
253
322
|
AUTH_ENDPOINTS: API_ENDPOINTS.AUTH,
|
|
254
323
|
// 业务 API 端点
|
|
255
324
|
API_ENDPOINTS: API_ENDPOINTS.API,
|
|
256
|
-
// 调试模式
|
|
325
|
+
// 调试模式 (保留这个环境变量,因为它是运行时选项)
|
|
257
326
|
DEBUG: getEnv("WUKONG_CLI_DEBUG", "false") === "true",
|
|
258
327
|
// 当前环境信息
|
|
259
328
|
ENVIRONMENT: env,
|
|
260
|
-
ENVIRONMENT_DISPLAY:
|
|
329
|
+
ENVIRONMENT_DISPLAY: envConfig.displayName
|
|
261
330
|
};
|
|
262
331
|
}
|
|
263
332
|
var currentEnv, getEnv, OCEANET_CONFIG;
|
|
@@ -272,7 +341,7 @@ var init_oceanet = __esm({
|
|
|
272
341
|
getEnv = (key, defaultValue) => {
|
|
273
342
|
return process.env[key] || defaultValue;
|
|
274
343
|
};
|
|
275
|
-
OCEANET_CONFIG = getOceanetConfig
|
|
344
|
+
OCEANET_CONFIG = getOceanetConfig;
|
|
276
345
|
}
|
|
277
346
|
});
|
|
278
347
|
|
|
@@ -291,6 +360,7 @@ var init_device_flow_service = __esm({
|
|
|
291
360
|
"use strict";
|
|
292
361
|
init_esm_shims();
|
|
293
362
|
init_oceanet();
|
|
363
|
+
init_debug();
|
|
294
364
|
DeviceFlowService = class {
|
|
295
365
|
/**
|
|
296
366
|
* 获取设备授权码
|
|
@@ -303,14 +373,19 @@ var init_device_flow_service = __esm({
|
|
|
303
373
|
clientId: config.CLIENT_ID
|
|
304
374
|
}
|
|
305
375
|
};
|
|
376
|
+
const requestHeaders = {
|
|
377
|
+
"Content-Type": "application/json"
|
|
378
|
+
};
|
|
379
|
+
debugRequest("POST", url, requestHeaders, requestBody);
|
|
380
|
+
const startTime = Date.now();
|
|
306
381
|
const response = await fetch(url, {
|
|
307
382
|
method: "POST",
|
|
308
|
-
headers:
|
|
309
|
-
"Content-Type": "application/json"
|
|
310
|
-
},
|
|
383
|
+
headers: requestHeaders,
|
|
311
384
|
body: JSON.stringify(requestBody)
|
|
312
385
|
});
|
|
386
|
+
const duration = Date.now() - startTime;
|
|
313
387
|
const data = await response.json();
|
|
388
|
+
debugResponse(response.status, response.statusText, data, duration);
|
|
314
389
|
if (data.code !== 200) {
|
|
315
390
|
throw new Error(
|
|
316
391
|
`(${data.code}) ${data.message || "Failed to get device code"}`
|
|
@@ -340,14 +415,19 @@ var init_device_flow_service = __esm({
|
|
|
340
415
|
deviceCode
|
|
341
416
|
}
|
|
342
417
|
};
|
|
418
|
+
const requestHeaders = {
|
|
419
|
+
"Content-Type": "application/json"
|
|
420
|
+
};
|
|
421
|
+
debugRequest("POST", url, requestHeaders, requestBody);
|
|
422
|
+
const requestStartTime = Date.now();
|
|
343
423
|
const response = await fetch(url, {
|
|
344
424
|
method: "POST",
|
|
345
|
-
headers:
|
|
346
|
-
"Content-Type": "application/json"
|
|
347
|
-
},
|
|
425
|
+
headers: requestHeaders,
|
|
348
426
|
body: JSON.stringify(requestBody)
|
|
349
427
|
});
|
|
428
|
+
const duration = Date.now() - requestStartTime;
|
|
350
429
|
const data = await response.json();
|
|
430
|
+
debugResponse(response.status, response.statusText, data, duration);
|
|
351
431
|
if (data.code !== 200) {
|
|
352
432
|
await new Promise(
|
|
353
433
|
(resolve) => setTimeout(resolve, config.POLL.INTERVAL * 1e3)
|
|
@@ -634,61 +714,9 @@ var init_token_cache = __esm({
|
|
|
634
714
|
|
|
635
715
|
// src/cli.ts
|
|
636
716
|
init_esm_shims();
|
|
717
|
+
init_debug();
|
|
637
718
|
import { Command as Command4 } from "commander";
|
|
638
719
|
|
|
639
|
-
// src/utils/debug.ts
|
|
640
|
-
init_esm_shims();
|
|
641
|
-
import chalk from "chalk";
|
|
642
|
-
var debugMode = null;
|
|
643
|
-
var explicitSet = false;
|
|
644
|
-
function setDebugMode(enabled, explicit = true) {
|
|
645
|
-
if (explicit) {
|
|
646
|
-
debugMode = enabled;
|
|
647
|
-
explicitSet = true;
|
|
648
|
-
}
|
|
649
|
-
global.__debugMode = enabled;
|
|
650
|
-
}
|
|
651
|
-
function isDebugMode() {
|
|
652
|
-
if (explicitSet) {
|
|
653
|
-
return debugMode === true;
|
|
654
|
-
}
|
|
655
|
-
if (global.__debugMode === true) {
|
|
656
|
-
return true;
|
|
657
|
-
}
|
|
658
|
-
return process.env.WUKONG_CLI_DEBUG === "true";
|
|
659
|
-
}
|
|
660
|
-
function debugRequest(method, url, headers, body) {
|
|
661
|
-
if (!isDebugMode()) return;
|
|
662
|
-
console.log("");
|
|
663
|
-
console.log(chalk.dim("=== HTTP Request ==="));
|
|
664
|
-
console.log(chalk.cyan(`${method} ${url}`));
|
|
665
|
-
if (headers) {
|
|
666
|
-
console.log(chalk.dim("Headers:"));
|
|
667
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
668
|
-
if (key.toLowerCase() === "authorization") {
|
|
669
|
-
const truncated = value.length > 50 ? value.substring(0, 50) + "..." : value;
|
|
670
|
-
console.log(chalk.dim(` ${key}: ${truncated}`));
|
|
671
|
-
} else {
|
|
672
|
-
console.log(chalk.dim(` ${key}: ${value}`));
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
if (body) {
|
|
677
|
-
console.log(chalk.dim("Body:"));
|
|
678
|
-
console.log(chalk.dim(JSON.stringify(body, null, 2)));
|
|
679
|
-
}
|
|
680
|
-
console.log("");
|
|
681
|
-
}
|
|
682
|
-
function debugResponse(status, statusText, body, duration) {
|
|
683
|
-
if (!isDebugMode()) return;
|
|
684
|
-
const statusColor = status >= 200 && status < 300 ? chalk.green : chalk.red;
|
|
685
|
-
console.log(chalk.dim("=== HTTP Response") + chalk.dim(` (${duration}ms) ===`));
|
|
686
|
-
console.log(statusColor(`Status: ${status} ${statusText}`));
|
|
687
|
-
console.log(chalk.dim("Body:"));
|
|
688
|
-
console.log(chalk.dim(JSON.stringify(body, null, 2)));
|
|
689
|
-
console.log("");
|
|
690
|
-
}
|
|
691
|
-
|
|
692
720
|
// src/commands/auth.ts
|
|
693
721
|
init_esm_shims();
|
|
694
722
|
import { Command } from "commander";
|
|
@@ -801,6 +829,7 @@ async function pollToken(deviceCode) {
|
|
|
801
829
|
// src/core/auth/token-manager.ts
|
|
802
830
|
init_esm_shims();
|
|
803
831
|
init_oceanet();
|
|
832
|
+
init_debug();
|
|
804
833
|
import ora2 from "ora";
|
|
805
834
|
var TokenManager = class {
|
|
806
835
|
/**
|
|
@@ -859,14 +888,20 @@ var TokenManager = class {
|
|
|
859
888
|
try {
|
|
860
889
|
const config = getOceanetConfig();
|
|
861
890
|
const url = `${config.AUTH_BASE_URL}${config.AUTH_ENDPOINTS.REFRESH_TOKEN}`;
|
|
891
|
+
const requestHeaders = {
|
|
892
|
+
"Content-Type": "application/json"
|
|
893
|
+
};
|
|
894
|
+
const requestBody = { param: refreshToken };
|
|
895
|
+
debugRequest("POST", url, requestHeaders, requestBody);
|
|
896
|
+
const startTime = Date.now();
|
|
862
897
|
const response = await fetch(url, {
|
|
863
898
|
method: "POST",
|
|
864
|
-
headers:
|
|
865
|
-
|
|
866
|
-
},
|
|
867
|
-
body: JSON.stringify({ param: refreshToken })
|
|
899
|
+
headers: requestHeaders,
|
|
900
|
+
body: JSON.stringify(requestBody)
|
|
868
901
|
});
|
|
902
|
+
const duration = Date.now() - startTime;
|
|
869
903
|
const data = await response.json();
|
|
904
|
+
debugResponse(response.status, response.statusText, data, duration);
|
|
870
905
|
if (data.code !== 200) {
|
|
871
906
|
spinner.fail("Token refresh failed");
|
|
872
907
|
throw new Error(data.message || "Refresh token failed");
|
|
@@ -906,13 +941,24 @@ var TokenManager = class {
|
|
|
906
941
|
async logout(accessToken) {
|
|
907
942
|
try {
|
|
908
943
|
const config = getOceanetConfig();
|
|
909
|
-
|
|
944
|
+
const url = `${config.AUTH_BASE_URL}${config.AUTH_ENDPOINTS.LOGOUT}`;
|
|
945
|
+
const requestHeaders = {
|
|
946
|
+
"Content-Type": "application/json",
|
|
947
|
+
"Authorization": `Bearer ${accessToken}`
|
|
948
|
+
};
|
|
949
|
+
debugRequest("POST", url, requestHeaders);
|
|
950
|
+
const startTime = Date.now();
|
|
951
|
+
const response = await fetch(url, {
|
|
910
952
|
method: "POST",
|
|
911
|
-
headers:
|
|
912
|
-
"Content-Type": "application/json",
|
|
913
|
-
"Authorization": `Bearer ${accessToken}`
|
|
914
|
-
}
|
|
953
|
+
headers: requestHeaders
|
|
915
954
|
});
|
|
955
|
+
const duration = Date.now() - startTime;
|
|
956
|
+
let data;
|
|
957
|
+
try {
|
|
958
|
+
data = await response.json();
|
|
959
|
+
} catch {
|
|
960
|
+
}
|
|
961
|
+
debugResponse(response.status, response.statusText, data || "No response body", duration);
|
|
916
962
|
} catch (error) {
|
|
917
963
|
}
|
|
918
964
|
await this.clearTokens();
|
|
@@ -961,6 +1007,7 @@ init_esm_shims();
|
|
|
961
1007
|
|
|
962
1008
|
// src/core/http/base-http-client.ts
|
|
963
1009
|
init_esm_shims();
|
|
1010
|
+
init_debug();
|
|
964
1011
|
init_oceanet();
|
|
965
1012
|
function buildUrl(endpoint, params) {
|
|
966
1013
|
if (endpoint.startsWith("http://") || endpoint.startsWith("https://")) {
|
|
@@ -1265,6 +1312,8 @@ function getRetoken() {
|
|
|
1265
1312
|
}
|
|
1266
1313
|
|
|
1267
1314
|
// src/core/http/authenticating-http-client.ts
|
|
1315
|
+
init_debug();
|
|
1316
|
+
init_oceanet();
|
|
1268
1317
|
var AuthenticatingHttpClient = class {
|
|
1269
1318
|
constructor(baseClient, tokenCache) {
|
|
1270
1319
|
this.baseClient = baseClient;
|
|
@@ -1296,7 +1345,9 @@ var AuthenticatingHttpClient = class {
|
|
|
1296
1345
|
...options.headers,
|
|
1297
1346
|
"Authorization": `Bearer ${accessToken}`
|
|
1298
1347
|
};
|
|
1299
|
-
const
|
|
1348
|
+
const config = getOceanetConfig();
|
|
1349
|
+
const baseUrl = options.baseUrl || config.API_BASE_URL;
|
|
1350
|
+
const url = endpoint.startsWith("http") ? endpoint : `${baseUrl}${endpoint}`;
|
|
1300
1351
|
debugRequest(options.method || "GET", url, headers, options.body);
|
|
1301
1352
|
const retoken = getRetoken();
|
|
1302
1353
|
const startTime = Date.now();
|
|
@@ -1319,8 +1370,11 @@ var AuthenticatingHttpClient = class {
|
|
|
1319
1370
|
await retoken.refreshToken();
|
|
1320
1371
|
const newAccessToken = this.tokenCache.getAccessToken();
|
|
1321
1372
|
if (newAccessToken) {
|
|
1373
|
+
const config2 = getOceanetConfig();
|
|
1374
|
+
const baseUrl2 = options.baseUrl || config2.API_BASE_URL;
|
|
1375
|
+
const retryUrl = endpoint.startsWith("http") ? endpoint : `${baseUrl2}${endpoint}`;
|
|
1322
1376
|
const retryResponse = await fetch(
|
|
1323
|
-
|
|
1377
|
+
retryUrl,
|
|
1324
1378
|
{
|
|
1325
1379
|
method: options.method || "GET",
|
|
1326
1380
|
headers: {
|
|
@@ -1500,35 +1554,35 @@ authCommands.command("login").description("Login using Device Authorization Flow
|
|
|
1500
1554
|
const allEnvs = getAllEnvironments();
|
|
1501
1555
|
setCurrentEnvironment(env);
|
|
1502
1556
|
const config = getOceanetConfig();
|
|
1503
|
-
const
|
|
1557
|
+
const envConfig = allEnvs[env];
|
|
1504
1558
|
console.log("");
|
|
1505
1559
|
console.log(chalk5.bgBlue.white.bold(" Wukong CLI Login "));
|
|
1506
1560
|
console.log("");
|
|
1507
|
-
printEnvironmentInfo(env,
|
|
1561
|
+
printEnvironmentInfo(env, envConfig.displayName);
|
|
1508
1562
|
console.log("");
|
|
1509
1563
|
const { verificationUri, deviceCode, expiresIn, interval } = await getDeviceCode();
|
|
1510
1564
|
console.log("");
|
|
1511
|
-
console.log(chalk5.bold("
|
|
1512
|
-
console.log(chalk5.bold("
|
|
1513
|
-
console.log(chalk5.bold("
|
|
1565
|
+
console.log(chalk5.bold("=".repeat(50)));
|
|
1566
|
+
console.log(chalk5.bold(" Please complete authorization"));
|
|
1567
|
+
console.log(chalk5.bold("=".repeat(50)));
|
|
1514
1568
|
console.log("");
|
|
1515
|
-
console.log(chalk5.green("
|
|
1569
|
+
console.log(chalk5.green(" Authorization URL:"));
|
|
1516
1570
|
console.log("");
|
|
1517
1571
|
console.log(chalk5.cyan(` ${verificationUri}`));
|
|
1518
1572
|
console.log("");
|
|
1519
|
-
console.error(chalk5.yellow.bold(">>>
|
|
1573
|
+
console.error(chalk5.yellow.bold(">>> Please open this link in your browser <<<"));
|
|
1520
1574
|
console.error(chalk5.cyan(verificationUri));
|
|
1521
1575
|
console.error("");
|
|
1522
1576
|
const open = await import("open").catch(() => null);
|
|
1523
1577
|
if (open) {
|
|
1524
1578
|
try {
|
|
1525
1579
|
await open.default(verificationUri);
|
|
1526
|
-
console.log(chalk5.dim("
|
|
1580
|
+
console.log(chalk5.dim(" Browser opened automatically"));
|
|
1527
1581
|
} catch {
|
|
1528
|
-
console.log(chalk5.dim("
|
|
1582
|
+
console.log(chalk5.dim(" Please copy link to browser"));
|
|
1529
1583
|
}
|
|
1530
1584
|
} else {
|
|
1531
|
-
console.log(chalk5.dim("
|
|
1585
|
+
console.log(chalk5.dim(" Please copy link to browser"));
|
|
1532
1586
|
}
|
|
1533
1587
|
console.log("");
|
|
1534
1588
|
console.log(chalk5.dim("\u2550".repeat(50)));
|
|
@@ -1539,17 +1593,17 @@ authCommands.command("login").description("Login using Device Authorization Flow
|
|
|
1539
1593
|
const tokens = await pollToken(deviceCode);
|
|
1540
1594
|
await saveToken(tokens.accessToken, tokens.refreshToken);
|
|
1541
1595
|
console.log("");
|
|
1542
|
-
console.log(chalk5.bgGreen.black.bold("
|
|
1596
|
+
console.log(chalk5.bgGreen.black.bold(" [OK] Login Successful "));
|
|
1543
1597
|
console.log("");
|
|
1544
|
-
console.log(chalk5.green("
|
|
1545
|
-
printEnvironmentInfo(env,
|
|
1598
|
+
console.log(chalk5.green("[OK] Tokens saved securely"));
|
|
1599
|
+
printEnvironmentInfo(env, envConfig.displayName);
|
|
1546
1600
|
console.log(chalk5.dim(`Access Token expires in: ${Math.floor(tokens.expiresIn / 60)} minutes`));
|
|
1547
1601
|
console.log("");
|
|
1548
1602
|
console.log(chalk5.dim("Next:"), chalk5.cyan("wukong-cli auth status"));
|
|
1549
1603
|
console.log("");
|
|
1550
1604
|
} catch (error) {
|
|
1551
1605
|
console.log("");
|
|
1552
|
-
console.log(chalk5.red(
|
|
1606
|
+
console.log(chalk5.red(`[ERROR] ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
1553
1607
|
console.log("");
|
|
1554
1608
|
}
|
|
1555
1609
|
});
|
|
@@ -1557,29 +1611,31 @@ authCommands.command("logout").description("Logout and clear saved tokens").acti
|
|
|
1557
1611
|
const env = getCurrentEnvironment();
|
|
1558
1612
|
const allEnvs = getAllEnvironments();
|
|
1559
1613
|
setCurrentEnvironment(env);
|
|
1560
|
-
const
|
|
1614
|
+
const envConfig = allEnvs[env];
|
|
1561
1615
|
try {
|
|
1562
1616
|
const accessToken = await getAccessToken();
|
|
1563
1617
|
if (accessToken) {
|
|
1564
1618
|
await logout(accessToken);
|
|
1565
1619
|
}
|
|
1566
1620
|
console.log("");
|
|
1567
|
-
console.log(chalk5.green(
|
|
1621
|
+
console.log(chalk5.green(`[OK] Logged out from ${env}`), chalk5.dim(`(${envConfig.displayName})`));
|
|
1568
1622
|
console.log("");
|
|
1569
1623
|
} catch {
|
|
1570
1624
|
console.log("");
|
|
1571
|
-
console.log(chalk5.yellow(`\u25CB Already logged out from ${env}`), chalk5.dim(`(${
|
|
1625
|
+
console.log(chalk5.yellow(`\u25CB Already logged out from ${env}`), chalk5.dim(`(${envConfig.displayName})`));
|
|
1572
1626
|
console.log("");
|
|
1573
1627
|
}
|
|
1574
1628
|
});
|
|
1575
1629
|
authCommands.command("refresh").description("Manually refresh access token").action(async () => {
|
|
1576
1630
|
const env = getCurrentEnvironment();
|
|
1631
|
+
const allEnvs = getAllEnvironments();
|
|
1632
|
+
const envConfig = allEnvs[env];
|
|
1577
1633
|
const config = getOceanetConfig();
|
|
1578
1634
|
try {
|
|
1579
1635
|
const accessToken = await getAccessToken();
|
|
1580
1636
|
if (!accessToken) {
|
|
1581
1637
|
console.log("");
|
|
1582
|
-
console.log(chalk5.yellow("
|
|
1638
|
+
console.log(chalk5.yellow("[ERROR] Not authenticated"));
|
|
1583
1639
|
printEnvironmentInfo(env, envConfig.displayName);
|
|
1584
1640
|
console.log("");
|
|
1585
1641
|
console.log(chalk5.dim(`Run: wukong-cli auth login`));
|
|
@@ -1601,7 +1657,7 @@ authCommands.command("refresh").description("Manually refresh access token").act
|
|
|
1601
1657
|
}
|
|
1602
1658
|
} catch (error) {
|
|
1603
1659
|
console.log("");
|
|
1604
|
-
console.log(chalk5.red(
|
|
1660
|
+
console.log(chalk5.red(`[ERROR] ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
1605
1661
|
console.log("");
|
|
1606
1662
|
printEnvironmentInfo(env, envConfig.displayName);
|
|
1607
1663
|
console.log(chalk5.dim(`Your session may have expired. Please run:`));
|
|
@@ -1614,14 +1670,14 @@ authCommands.command("status").description("Show authentication status").action(
|
|
|
1614
1670
|
const env = getCurrentEnvironment();
|
|
1615
1671
|
const allEnvs = getAllEnvironments();
|
|
1616
1672
|
setCurrentEnvironment(env);
|
|
1617
|
-
const
|
|
1673
|
+
const envConfig = allEnvs[env];
|
|
1618
1674
|
const config = getOceanetConfig();
|
|
1619
1675
|
try {
|
|
1620
1676
|
const accessToken = await getAccessToken();
|
|
1621
1677
|
if (!accessToken) {
|
|
1622
|
-
console.log(chalk5.yellow(
|
|
1678
|
+
console.log(chalk5.yellow(`[ERROR] Not authenticated`));
|
|
1623
1679
|
console.log("");
|
|
1624
|
-
printEnvironmentInfo(env,
|
|
1680
|
+
printEnvironmentInfo(env, envConfig.displayName);
|
|
1625
1681
|
console.log(chalk5.dim(`Run: wukong-cli auth login`));
|
|
1626
1682
|
console.log("");
|
|
1627
1683
|
return;
|
|
@@ -1630,10 +1686,10 @@ authCommands.command("status").description("Show authentication status").action(
|
|
|
1630
1686
|
const client = getClient();
|
|
1631
1687
|
const userInfoUrl = `${config.AUTH_BASE_URL}/oceanet-auth/web/userInfo`;
|
|
1632
1688
|
const userInfo = await client.get(userInfoUrl);
|
|
1633
|
-
console.log(chalk5.green(
|
|
1689
|
+
console.log(chalk5.green("[OK] Authenticated"));
|
|
1634
1690
|
console.log("");
|
|
1635
1691
|
const displayUser = userInfo.firstName ? `${userInfo.firstName} (${userInfo.username})` : userInfo.username || "N/A";
|
|
1636
|
-
printEnvironmentInfo(env,
|
|
1692
|
+
printEnvironmentInfo(env, envConfig.displayName);
|
|
1637
1693
|
console.log(chalk5.dim("User:"), chalk5.cyan(displayUser));
|
|
1638
1694
|
console.log(chalk5.dim("Email:"), chalk5.cyan(userInfo.email || "N/A"));
|
|
1639
1695
|
console.log(chalk5.dim("OrgCode:"), chalk5.cyan(userInfo.ouCode || "N/A"));
|
|
@@ -1641,73 +1697,30 @@ authCommands.command("status").description("Show authentication status").action(
|
|
|
1641
1697
|
console.log("");
|
|
1642
1698
|
} catch (error) {
|
|
1643
1699
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
1644
|
-
console.log(chalk5.yellow(
|
|
1700
|
+
console.log(chalk5.yellow(`[ERROR] Not authenticated`));
|
|
1645
1701
|
console.log("");
|
|
1646
1702
|
console.log(chalk5.red("Error:"), chalk5.dim(errorMsg));
|
|
1647
1703
|
console.log("");
|
|
1648
|
-
printEnvironmentInfo(env,
|
|
1704
|
+
printEnvironmentInfo(env, envConfig.displayName);
|
|
1649
1705
|
console.log(chalk5.dim(`Run: wukong-cli auth login`));
|
|
1650
1706
|
console.log("");
|
|
1651
1707
|
}
|
|
1652
1708
|
} catch (error) {
|
|
1653
1709
|
console.log(chalk5.yellow(`\u2717 Not authenticated`));
|
|
1654
1710
|
console.log("");
|
|
1655
|
-
printEnvironmentInfo(env,
|
|
1711
|
+
printEnvironmentInfo(env, envConfig.displayName);
|
|
1656
1712
|
console.log(chalk5.dim(`Run: wukong-cli auth login`));
|
|
1657
1713
|
console.log("");
|
|
1658
1714
|
}
|
|
1659
1715
|
});
|
|
1660
1716
|
|
|
1661
|
-
// src/commands/
|
|
1717
|
+
// src/commands/http.ts
|
|
1662
1718
|
init_esm_shims();
|
|
1663
1719
|
import { Command as Command2 } from "commander";
|
|
1664
1720
|
import ora4 from "ora";
|
|
1665
1721
|
import chalk6 from "chalk";
|
|
1666
|
-
var testCommand = new Command2("test").description("Test API request with saved token").action(async () => {
|
|
1667
|
-
try {
|
|
1668
|
-
const accessToken = await getAccessToken();
|
|
1669
|
-
if (!accessToken) {
|
|
1670
|
-
console.log("");
|
|
1671
|
-
console.log(chalk6.red("\u2717 Not authenticated"));
|
|
1672
|
-
console.log("");
|
|
1673
|
-
console.log(chalk6.dim("Please run: wukong-cli auth login"));
|
|
1674
|
-
console.log("");
|
|
1675
|
-
process.exit(1);
|
|
1676
|
-
}
|
|
1677
|
-
const spinner = ora4("Testing API connection...").start();
|
|
1678
|
-
try {
|
|
1679
|
-
const client = getClient();
|
|
1680
|
-
const userInfo = await client.get("/oceanet-auth/web/userInfo");
|
|
1681
|
-
spinner.succeed("API request successful");
|
|
1682
|
-
console.log("");
|
|
1683
|
-
console.log(chalk6.green("User Info:"));
|
|
1684
|
-
console.log(chalk6.dim(JSON.stringify(userInfo, null, 2)));
|
|
1685
|
-
console.log("");
|
|
1686
|
-
} catch (error) {
|
|
1687
|
-
spinner.fail("API request failed");
|
|
1688
|
-
if (error.message.includes("401") || error.message.includes("expired")) {
|
|
1689
|
-
console.log("");
|
|
1690
|
-
console.log(chalk6.yellow("Token expired or invalid"));
|
|
1691
|
-
console.log(chalk6.dim("Try: wukong-cli auth refresh"));
|
|
1692
|
-
console.log("");
|
|
1693
|
-
} else {
|
|
1694
|
-
throw error;
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
} catch (error) {
|
|
1698
|
-
console.log("");
|
|
1699
|
-
console.log(chalk6.red(`\u2717 Error: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
1700
|
-
console.log("");
|
|
1701
|
-
process.exit(1);
|
|
1702
|
-
}
|
|
1703
|
-
});
|
|
1704
|
-
|
|
1705
|
-
// src/commands/http.ts
|
|
1706
|
-
init_esm_shims();
|
|
1707
|
-
import { Command as Command3 } from "commander";
|
|
1708
|
-
import ora5 from "ora";
|
|
1709
|
-
import chalk7 from "chalk";
|
|
1710
1722
|
init_oceanet();
|
|
1723
|
+
init_debug();
|
|
1711
1724
|
function fixGitBashPath(url) {
|
|
1712
1725
|
if (url.includes(":") && !url.startsWith("http")) {
|
|
1713
1726
|
const oceanetIndex = url.indexOf("/oceanet-");
|
|
@@ -1734,16 +1747,17 @@ function buildUrl2(url, baseUrl) {
|
|
|
1734
1747
|
if (cleanUrl.startsWith("http")) {
|
|
1735
1748
|
return cleanUrl;
|
|
1736
1749
|
}
|
|
1737
|
-
const
|
|
1750
|
+
const config = OCEANET_CONFIG();
|
|
1751
|
+
const base = baseUrl || config.API_BASE_URL;
|
|
1738
1752
|
return `${base}${cleanUrl}`;
|
|
1739
1753
|
}
|
|
1740
1754
|
async function executeRequest(method, url, options) {
|
|
1741
|
-
const spinner =
|
|
1755
|
+
const spinner = ora4("Sending request...").start();
|
|
1742
1756
|
try {
|
|
1743
1757
|
const accessToken = await getAccessToken();
|
|
1744
1758
|
if (!accessToken) {
|
|
1745
1759
|
spinner.fail("Not authenticated");
|
|
1746
|
-
console.error(
|
|
1760
|
+
console.error(chalk6.red("Please run: wukong-cli auth login"));
|
|
1747
1761
|
process.exit(1);
|
|
1748
1762
|
}
|
|
1749
1763
|
const fullUrl = buildUrl2(url, options.baseUrl);
|
|
@@ -1760,29 +1774,33 @@ async function executeRequest(method, url, options) {
|
|
|
1760
1774
|
headers["Content-Type"] = "application/json";
|
|
1761
1775
|
}
|
|
1762
1776
|
}
|
|
1763
|
-
spinner.text = `${method} ${
|
|
1777
|
+
spinner.text = `${method} ${chalk6.cyan(fullUrl)}`;
|
|
1778
|
+
debugRequest(method, fullUrl, headers, options.data ? JSON.parse(options.data) : void 0);
|
|
1779
|
+
const startTime = Date.now();
|
|
1764
1780
|
const response = await fetch(fullUrl, {
|
|
1765
1781
|
method,
|
|
1766
1782
|
headers,
|
|
1767
1783
|
body: method !== "GET" && method !== "DELETE" ? body : void 0
|
|
1768
1784
|
});
|
|
1785
|
+
const duration = Date.now() - startTime;
|
|
1769
1786
|
const data = await response.json();
|
|
1787
|
+
debugResponse(response.status, response.statusText, data, duration);
|
|
1770
1788
|
spinner.succeed("Response received");
|
|
1771
1789
|
console.log("");
|
|
1772
|
-
console.log(
|
|
1790
|
+
console.log(chalk6.dim("Status:"), response.status, response.statusText);
|
|
1773
1791
|
console.log("");
|
|
1774
|
-
console.log(
|
|
1792
|
+
console.log(chalk6.dim("Response:"));
|
|
1775
1793
|
console.log(JSON.stringify(data, null, 2));
|
|
1776
1794
|
} catch (error) {
|
|
1777
1795
|
spinner.fail("Request failed");
|
|
1778
1796
|
if (error instanceof Error) {
|
|
1779
|
-
console.error(
|
|
1797
|
+
console.error(chalk6.red(error.message));
|
|
1780
1798
|
}
|
|
1781
1799
|
process.exit(1);
|
|
1782
1800
|
}
|
|
1783
1801
|
}
|
|
1784
|
-
var httpCommand = new
|
|
1785
|
-
httpCommand.command("get <url>").description("Send GET request (uses
|
|
1802
|
+
var httpCommand = new Command2("http");
|
|
1803
|
+
httpCommand.command("get <url>").description("Send GET request (uses configured base URL or override with -b)").option("-b, --base-url <url>", "Override base URL").option("-H, --header <key:value>", "Custom header (can be used multiple times)", []).action(async (url, options) => {
|
|
1786
1804
|
await executeRequest("GET", url, options);
|
|
1787
1805
|
});
|
|
1788
1806
|
httpCommand.command("post <url>").description("Send POST request with JSON data").option("-b, --base-url <url>", "Override base URL").option("-H, --header <key:value>", "Custom header (can be used multiple times)", []).option("-d, --data <json>", "Request body as JSON string").action(async (url, options) => {
|
|
@@ -1795,9 +1813,64 @@ httpCommand.command("delete <url>").description("Send DELETE request").option("-
|
|
|
1795
1813
|
await executeRequest("DELETE", url, options);
|
|
1796
1814
|
});
|
|
1797
1815
|
|
|
1816
|
+
// src/commands/init.ts
|
|
1817
|
+
init_esm_shims();
|
|
1818
|
+
import { Command as Command3 } from "commander";
|
|
1819
|
+
import { writeFileSync as writeFileSync3, existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
1820
|
+
import { join as join3, dirname as dirname3 } from "path";
|
|
1821
|
+
import { homedir as homedir3 } from "os";
|
|
1822
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1823
|
+
import chalk7 from "chalk";
|
|
1824
|
+
function getProjectRoot2() {
|
|
1825
|
+
let currentDir = dirname3(fileURLToPath3(import.meta.url));
|
|
1826
|
+
while (currentDir !== dirname3(currentDir)) {
|
|
1827
|
+
if (existsSync3(join3(currentDir, "package.json"))) {
|
|
1828
|
+
return currentDir;
|
|
1829
|
+
}
|
|
1830
|
+
currentDir = dirname3(currentDir);
|
|
1831
|
+
}
|
|
1832
|
+
return process.cwd();
|
|
1833
|
+
}
|
|
1834
|
+
async function executeInit() {
|
|
1835
|
+
const configPath = join3(homedir3(), "wukong-cli.json");
|
|
1836
|
+
const templatePath = join3(getProjectRoot2(), "wukong-cli.json.template");
|
|
1837
|
+
if (!existsSync3(templatePath)) {
|
|
1838
|
+
console.error(chalk7.red("\u274C Template configuration file not found"));
|
|
1839
|
+
console.error(chalk7.yellow(`Expected location: ${templatePath}`));
|
|
1840
|
+
process.exit(1);
|
|
1841
|
+
}
|
|
1842
|
+
try {
|
|
1843
|
+
const templateContent = readFileSync3(templatePath, "utf-8");
|
|
1844
|
+
const configExists = existsSync3(configPath);
|
|
1845
|
+
if (configExists) {
|
|
1846
|
+
console.log(chalk7.yellow("\u26A0\uFE0F Existing configuration file will be overwritten"));
|
|
1847
|
+
}
|
|
1848
|
+
writeFileSync3(configPath, templateContent, "utf-8");
|
|
1849
|
+
console.log(chalk7.green("\u2705 Configuration file created successfully"));
|
|
1850
|
+
console.log(chalk7.gray(`Location: ${configPath}`));
|
|
1851
|
+
if (configExists) {
|
|
1852
|
+
console.log(chalk7.yellow("Previous configuration has been overwritten"));
|
|
1853
|
+
}
|
|
1854
|
+
try {
|
|
1855
|
+
const config = JSON.parse(templateContent);
|
|
1856
|
+
console.log(chalk7.gray("\nConfiguration preview:"));
|
|
1857
|
+
console.log(chalk7.gray(` Default Environment: ${config.defaultEnv}`));
|
|
1858
|
+
console.log(chalk7.gray(` Configured Environments: ${Object.keys(config.environments).join(", ")}`));
|
|
1859
|
+
} catch (parseError) {
|
|
1860
|
+
}
|
|
1861
|
+
} catch (error) {
|
|
1862
|
+
console.error(chalk7.red("\u274C Failed to create configuration file"));
|
|
1863
|
+
console.error(chalk7.yellow(`Error: ${error}`));
|
|
1864
|
+
process.exit(1);
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
var initCommand = new Command3("init").description("Initialize configuration file (creates or overwrites ~/wukong-cli.json)").action(async () => {
|
|
1868
|
+
await executeInit();
|
|
1869
|
+
});
|
|
1870
|
+
|
|
1798
1871
|
// src/cli.ts
|
|
1799
1872
|
var program = new Command4();
|
|
1800
|
-
program.name("wukong-cli").description("Wukong CLI - TypeScript implementation").version("0.1.
|
|
1873
|
+
program.name("wukong-cli").description("Wukong CLI - TypeScript implementation").version("0.1.7").option("--debug", "Enable debug mode (show HTTP requests)").hook("preAction", (thisCommand) => {
|
|
1801
1874
|
const options = thisCommand.opts();
|
|
1802
1875
|
if (options.debug === true) {
|
|
1803
1876
|
setDebugMode(true, true);
|
|
@@ -1806,8 +1879,8 @@ program.name("wukong-cli").description("Wukong CLI - TypeScript implementation")
|
|
|
1806
1879
|
}
|
|
1807
1880
|
});
|
|
1808
1881
|
program.addCommand(authCommands);
|
|
1809
|
-
program.addCommand(testCommand);
|
|
1810
1882
|
program.addCommand(httpCommand);
|
|
1883
|
+
program.addCommand(initCommand);
|
|
1811
1884
|
if (process.argv.length === 2) {
|
|
1812
1885
|
program.help();
|
|
1813
1886
|
}
|