@zrhsh/wukong-cli 0.1.6 → 0.1.8

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 (4) hide show
  1. package/README.md +140 -120
  2. package/dist/cli.js +292 -146
  3. package/dist/cli.js.map +1 -1
  4. 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({
@@ -167,17 +226,27 @@ function loadConfig() {
167
226
  }
168
227
  function getMergedEnvironmentConfig(env) {
169
228
  const config = loadConfig();
170
- const defaultConfig = ENVIRONMENTS[env] || ENVIRONMENTS[DEFAULT_ENVIRONMENT];
171
- const envAuthUrl = process.env[`OCEANET_${env.toUpperCase()}_AUTH_URL`];
172
- const envApiUrl = process.env[`OCEANET_${env.toUpperCase()}_API_URL`];
173
- const envClientId = process.env[`OCEANET_${env.toUpperCase()}_CLIENT_ID`];
174
- const customConfig = config.environments?.[env] || {};
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: defaultConfig.displayName,
178
- authBaseUrl: envAuthUrl || customConfig.authBaseUrl || defaultConfig.authBaseUrl,
179
- apiBaseUrl: envApiUrl || customConfig.apiBaseUrl || defaultConfig.apiBaseUrl,
180
- clientId: envClientId || customConfig.clientId || defaultConfig.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 envConfig2 = getEnvironmentConfig();
308
+ const envConfig = getEnvironmentConfig();
240
309
  const env = getCurrentEnvironment();
241
310
  return {
242
311
  // 认证服务基础地址 (设备码授权、登录、登出等)
243
- AUTH_BASE_URL: getEnv("OCEANET_AUTH_BASE_URL", envConfig2.authBaseUrl),
312
+ AUTH_BASE_URL: envConfig.authBaseUrl,
244
313
  // 业务 API 基础地址
245
- API_BASE_URL: getEnv("OCEANET_API_BASE_URL", envConfig2.apiBaseUrl),
314
+ API_BASE_URL: envConfig.apiBaseUrl,
246
315
  // 客户端 ID
247
- CLIENT_ID: getEnv("OCEANET_CLIENT_ID", envConfig2.clientId),
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: envConfig2.displayName
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)
@@ -419,7 +499,7 @@ var init_ora_ui_callbacks = __esm({
419
499
  });
420
500
 
421
501
  // src/core/auth/keytar-adapter.ts
422
- import { createRequire } from "module";
502
+ import { createRequire as createRequire2 } from "module";
423
503
  function isKeytarAvailable() {
424
504
  return keytarModule !== null;
425
505
  }
@@ -441,15 +521,15 @@ async function deletePassword(service, account) {
441
521
  }
442
522
  return await keytarModule.deletePassword(service, account);
443
523
  }
444
- var require2, keytarModule;
524
+ var require3, keytarModule;
445
525
  var init_keytar_adapter = __esm({
446
526
  "src/core/auth/keytar-adapter.ts"() {
447
527
  "use strict";
448
528
  init_esm_shims();
449
- require2 = createRequire(import.meta.url);
529
+ require3 = createRequire2(import.meta.url);
450
530
  keytarModule = null;
451
531
  try {
452
- keytarModule = require2("keytar");
532
+ keytarModule = require3("keytar");
453
533
  } catch (error) {
454
534
  keytarModule = null;
455
535
  }
@@ -634,60 +714,79 @@ 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
720
+ // src/utils/version-check.ts
640
721
  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;
722
+ import { createRequire } from "module";
723
+ var require2 = createRequire(import.meta.url);
724
+ var packageJson = require2("../package.json");
725
+ var PACKAGE_NAME = "@zrhsh/wukong-cli";
726
+ var NPM_REGISTRY_URL = "https://registry.npmjs.org";
727
+ var CHECK_INTERVAL = 24 * 60 * 60 * 1e3;
728
+ var lastCheckTime = 0;
729
+ var cachedLatestVersion = null;
730
+ async function getLatestVersion() {
731
+ try {
732
+ const response = await fetch(`${NPM_REGISTRY_URL}/${PACKAGE_NAME}`);
733
+ const data = await response.json();
734
+ return data["dist-tags"]?.latest || null;
735
+ } catch (error) {
736
+ return null;
648
737
  }
649
- global.__debugMode = enabled;
650
738
  }
651
- function isDebugMode() {
652
- if (explicitSet) {
653
- return debugMode === true;
739
+ async function checkForUpdate() {
740
+ const now = Date.now();
741
+ const currentVersion = packageJson.version;
742
+ if (now - lastCheckTime < CHECK_INTERVAL && cachedLatestVersion) {
743
+ return {
744
+ hasUpdate: cachedLatestVersion !== currentVersion,
745
+ currentVersion,
746
+ latestVersion: cachedLatestVersion
747
+ };
654
748
  }
655
- if (global.__debugMode === true) {
656
- return true;
749
+ const latestVersion = await getLatestVersion();
750
+ if (!latestVersion) {
751
+ return {
752
+ hasUpdate: false,
753
+ currentVersion,
754
+ latestVersion: null
755
+ };
657
756
  }
658
- return process.env.WUKONG_CLI_DEBUG === "true";
757
+ lastCheckTime = now;
758
+ cachedLatestVersion = latestVersion;
759
+ return {
760
+ hasUpdate: latestVersion !== currentVersion,
761
+ currentVersion,
762
+ latestVersion
763
+ };
659
764
  }
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)));
765
+ async function showUpdateNotification() {
766
+ const { hasUpdate, currentVersion, latestVersion } = await checkForUpdate();
767
+ if (!hasUpdate || !latestVersion) {
768
+ return;
679
769
  }
680
770
  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)));
771
+ console.log("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
772
+ console.log("\u2551" + " ".repeat(58) + "\u2551");
773
+ console.log("\u2551" + " \u{1F389} \u65B0\u7248\u672C\u53EF\u7528!".padEnd(60) + "\u2551");
774
+ console.log("\u2551" + " ".repeat(58) + "\u2551");
775
+ console.log(`\u2551 \u5F53\u524D\u7248\u672C: ${currentVersion.padEnd(10)} \u6700\u65B0\u7248\u672C: ${latestVersion.padEnd(10)} \u2551`);
776
+ console.log("\u2551" + " ".repeat(58) + "\u2551");
777
+ console.log("\u2551" + " \u66F4\u65B0\u547D\u4EE4:".padEnd(60) + "\u2551");
778
+ console.log(`\u2551 npm install -g ${PACKAGE_NAME}@latest`.padEnd(60) + "\u2551");
779
+ console.log("\u2551" + " ".repeat(58) + "\u2551");
780
+ console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
689
781
  console.log("");
690
782
  }
783
+ async function checkAndUpdate(silent = false) {
784
+ if (!silent) {
785
+ await showUpdateNotification();
786
+ } else {
787
+ await checkForUpdate();
788
+ }
789
+ }
691
790
 
692
791
  // src/commands/auth.ts
693
792
  init_esm_shims();
@@ -801,6 +900,7 @@ async function pollToken(deviceCode) {
801
900
  // src/core/auth/token-manager.ts
802
901
  init_esm_shims();
803
902
  init_oceanet();
903
+ init_debug();
804
904
  import ora2 from "ora";
805
905
  var TokenManager = class {
806
906
  /**
@@ -859,14 +959,20 @@ var TokenManager = class {
859
959
  try {
860
960
  const config = getOceanetConfig();
861
961
  const url = `${config.AUTH_BASE_URL}${config.AUTH_ENDPOINTS.REFRESH_TOKEN}`;
962
+ const requestHeaders = {
963
+ "Content-Type": "application/json"
964
+ };
965
+ const requestBody = { param: refreshToken };
966
+ debugRequest("POST", url, requestHeaders, requestBody);
967
+ const startTime = Date.now();
862
968
  const response = await fetch(url, {
863
969
  method: "POST",
864
- headers: {
865
- "Content-Type": "application/json"
866
- },
867
- body: JSON.stringify({ param: refreshToken })
970
+ headers: requestHeaders,
971
+ body: JSON.stringify(requestBody)
868
972
  });
973
+ const duration = Date.now() - startTime;
869
974
  const data = await response.json();
975
+ debugResponse(response.status, response.statusText, data, duration);
870
976
  if (data.code !== 200) {
871
977
  spinner.fail("Token refresh failed");
872
978
  throw new Error(data.message || "Refresh token failed");
@@ -906,13 +1012,24 @@ var TokenManager = class {
906
1012
  async logout(accessToken) {
907
1013
  try {
908
1014
  const config = getOceanetConfig();
909
- await fetch(`${config.AUTH_BASE_URL}${config.AUTH_ENDPOINTS.LOGOUT}`, {
1015
+ const url = `${config.AUTH_BASE_URL}${config.AUTH_ENDPOINTS.LOGOUT}`;
1016
+ const requestHeaders = {
1017
+ "Content-Type": "application/json",
1018
+ "Authorization": `Bearer ${accessToken}`
1019
+ };
1020
+ debugRequest("POST", url, requestHeaders);
1021
+ const startTime = Date.now();
1022
+ const response = await fetch(url, {
910
1023
  method: "POST",
911
- headers: {
912
- "Content-Type": "application/json",
913
- "Authorization": `Bearer ${accessToken}`
914
- }
1024
+ headers: requestHeaders
915
1025
  });
1026
+ const duration = Date.now() - startTime;
1027
+ let data;
1028
+ try {
1029
+ data = await response.json();
1030
+ } catch {
1031
+ }
1032
+ debugResponse(response.status, response.statusText, data || "No response body", duration);
916
1033
  } catch (error) {
917
1034
  }
918
1035
  await this.clearTokens();
@@ -961,6 +1078,7 @@ init_esm_shims();
961
1078
 
962
1079
  // src/core/http/base-http-client.ts
963
1080
  init_esm_shims();
1081
+ init_debug();
964
1082
  init_oceanet();
965
1083
  function buildUrl(endpoint, params) {
966
1084
  if (endpoint.startsWith("http://") || endpoint.startsWith("https://")) {
@@ -1265,6 +1383,8 @@ function getRetoken() {
1265
1383
  }
1266
1384
 
1267
1385
  // src/core/http/authenticating-http-client.ts
1386
+ init_debug();
1387
+ init_oceanet();
1268
1388
  var AuthenticatingHttpClient = class {
1269
1389
  constructor(baseClient, tokenCache) {
1270
1390
  this.baseClient = baseClient;
@@ -1296,7 +1416,9 @@ var AuthenticatingHttpClient = class {
1296
1416
  ...options.headers,
1297
1417
  "Authorization": `Bearer ${accessToken}`
1298
1418
  };
1299
- const url = `${global.__apiBaseUrl || ""}${endpoint}`;
1419
+ const config = getOceanetConfig();
1420
+ const baseUrl = options.baseUrl || config.API_BASE_URL;
1421
+ const url = endpoint.startsWith("http") ? endpoint : `${baseUrl}${endpoint}`;
1300
1422
  debugRequest(options.method || "GET", url, headers, options.body);
1301
1423
  const retoken = getRetoken();
1302
1424
  const startTime = Date.now();
@@ -1319,8 +1441,11 @@ var AuthenticatingHttpClient = class {
1319
1441
  await retoken.refreshToken();
1320
1442
  const newAccessToken = this.tokenCache.getAccessToken();
1321
1443
  if (newAccessToken) {
1444
+ const config2 = getOceanetConfig();
1445
+ const baseUrl2 = options.baseUrl || config2.API_BASE_URL;
1446
+ const retryUrl = endpoint.startsWith("http") ? endpoint : `${baseUrl2}${endpoint}`;
1322
1447
  const retryResponse = await fetch(
1323
- `${global.__apiBaseUrl || ""}${endpoint}`,
1448
+ retryUrl,
1324
1449
  {
1325
1450
  method: options.method || "GET",
1326
1451
  headers: {
@@ -1500,11 +1625,11 @@ authCommands.command("login").description("Login using Device Authorization Flow
1500
1625
  const allEnvs = getAllEnvironments();
1501
1626
  setCurrentEnvironment(env);
1502
1627
  const config = getOceanetConfig();
1503
- const envConfig2 = allEnvs[env];
1628
+ const envConfig = allEnvs[env];
1504
1629
  console.log("");
1505
1630
  console.log(chalk5.bgBlue.white.bold(" Wukong CLI Login "));
1506
1631
  console.log("");
1507
- printEnvironmentInfo(env, envConfig2.displayName);
1632
+ printEnvironmentInfo(env, envConfig.displayName);
1508
1633
  console.log("");
1509
1634
  const { verificationUri, deviceCode, expiresIn, interval } = await getDeviceCode();
1510
1635
  console.log("");
@@ -1542,7 +1667,7 @@ authCommands.command("login").description("Login using Device Authorization Flow
1542
1667
  console.log(chalk5.bgGreen.black.bold(" [OK] Login Successful "));
1543
1668
  console.log("");
1544
1669
  console.log(chalk5.green("[OK] Tokens saved securely"));
1545
- printEnvironmentInfo(env, envConfig2.displayName);
1670
+ printEnvironmentInfo(env, envConfig.displayName);
1546
1671
  console.log(chalk5.dim(`Access Token expires in: ${Math.floor(tokens.expiresIn / 60)} minutes`));
1547
1672
  console.log("");
1548
1673
  console.log(chalk5.dim("Next:"), chalk5.cyan("wukong-cli auth status"));
@@ -1557,23 +1682,25 @@ authCommands.command("logout").description("Logout and clear saved tokens").acti
1557
1682
  const env = getCurrentEnvironment();
1558
1683
  const allEnvs = getAllEnvironments();
1559
1684
  setCurrentEnvironment(env);
1560
- const envConfig2 = allEnvs[env];
1685
+ const envConfig = allEnvs[env];
1561
1686
  try {
1562
1687
  const accessToken = await getAccessToken();
1563
1688
  if (accessToken) {
1564
1689
  await logout(accessToken);
1565
1690
  }
1566
1691
  console.log("");
1567
- console.log(chalk5.green(`[OK] Logged out from ${env}`), chalk5.dim(`(${envConfig2.displayName})`));
1692
+ console.log(chalk5.green(`[OK] Logged out from ${env}`), chalk5.dim(`(${envConfig.displayName})`));
1568
1693
  console.log("");
1569
1694
  } catch {
1570
1695
  console.log("");
1571
- console.log(chalk5.yellow(`\u25CB Already logged out from ${env}`), chalk5.dim(`(${envConfig2.displayName})`));
1696
+ console.log(chalk5.yellow(`\u25CB Already logged out from ${env}`), chalk5.dim(`(${envConfig.displayName})`));
1572
1697
  console.log("");
1573
1698
  }
1574
1699
  });
1575
1700
  authCommands.command("refresh").description("Manually refresh access token").action(async () => {
1576
1701
  const env = getCurrentEnvironment();
1702
+ const allEnvs = getAllEnvironments();
1703
+ const envConfig = allEnvs[env];
1577
1704
  const config = getOceanetConfig();
1578
1705
  try {
1579
1706
  const accessToken = await getAccessToken();
@@ -1614,14 +1741,14 @@ authCommands.command("status").description("Show authentication status").action(
1614
1741
  const env = getCurrentEnvironment();
1615
1742
  const allEnvs = getAllEnvironments();
1616
1743
  setCurrentEnvironment(env);
1617
- const envConfig2 = allEnvs[env];
1744
+ const envConfig = allEnvs[env];
1618
1745
  const config = getOceanetConfig();
1619
1746
  try {
1620
1747
  const accessToken = await getAccessToken();
1621
1748
  if (!accessToken) {
1622
1749
  console.log(chalk5.yellow(`[ERROR] Not authenticated`));
1623
1750
  console.log("");
1624
- printEnvironmentInfo(env, envConfig2.displayName);
1751
+ printEnvironmentInfo(env, envConfig.displayName);
1625
1752
  console.log(chalk5.dim(`Run: wukong-cli auth login`));
1626
1753
  console.log("");
1627
1754
  return;
@@ -1633,7 +1760,7 @@ authCommands.command("status").description("Show authentication status").action(
1633
1760
  console.log(chalk5.green("[OK] Authenticated"));
1634
1761
  console.log("");
1635
1762
  const displayUser = userInfo.firstName ? `${userInfo.firstName} (${userInfo.username})` : userInfo.username || "N/A";
1636
- printEnvironmentInfo(env, envConfig2.displayName);
1763
+ printEnvironmentInfo(env, envConfig.displayName);
1637
1764
  console.log(chalk5.dim("User:"), chalk5.cyan(displayUser));
1638
1765
  console.log(chalk5.dim("Email:"), chalk5.cyan(userInfo.email || "N/A"));
1639
1766
  console.log(chalk5.dim("OrgCode:"), chalk5.cyan(userInfo.ouCode || "N/A"));
@@ -1645,69 +1772,26 @@ authCommands.command("status").description("Show authentication status").action(
1645
1772
  console.log("");
1646
1773
  console.log(chalk5.red("Error:"), chalk5.dim(errorMsg));
1647
1774
  console.log("");
1648
- printEnvironmentInfo(env, envConfig2.displayName);
1775
+ printEnvironmentInfo(env, envConfig.displayName);
1649
1776
  console.log(chalk5.dim(`Run: wukong-cli auth login`));
1650
1777
  console.log("");
1651
1778
  }
1652
1779
  } catch (error) {
1653
1780
  console.log(chalk5.yellow(`\u2717 Not authenticated`));
1654
1781
  console.log("");
1655
- printEnvironmentInfo(env, envConfig2.displayName);
1782
+ printEnvironmentInfo(env, envConfig.displayName);
1656
1783
  console.log(chalk5.dim(`Run: wukong-cli auth login`));
1657
1784
  console.log("");
1658
1785
  }
1659
1786
  });
1660
1787
 
1661
- // src/commands/test.ts
1788
+ // src/commands/http.ts
1662
1789
  init_esm_shims();
1663
1790
  import { Command as Command2 } from "commander";
1664
1791
  import ora4 from "ora";
1665
1792
  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("[ERROR] 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(`[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
1793
  init_oceanet();
1794
+ init_debug();
1711
1795
  function fixGitBashPath(url) {
1712
1796
  if (url.includes(":") && !url.startsWith("http")) {
1713
1797
  const oceanetIndex = url.indexOf("/oceanet-");
@@ -1734,16 +1818,17 @@ function buildUrl2(url, baseUrl) {
1734
1818
  if (cleanUrl.startsWith("http")) {
1735
1819
  return cleanUrl;
1736
1820
  }
1737
- const base = baseUrl || OCEANET_CONFIG.API_BASE_URL;
1821
+ const config = OCEANET_CONFIG();
1822
+ const base = baseUrl || config.API_BASE_URL;
1738
1823
  return `${base}${cleanUrl}`;
1739
1824
  }
1740
1825
  async function executeRequest(method, url, options) {
1741
- const spinner = ora5("Sending request...").start();
1826
+ const spinner = ora4("Sending request...").start();
1742
1827
  try {
1743
1828
  const accessToken = await getAccessToken();
1744
1829
  if (!accessToken) {
1745
1830
  spinner.fail("Not authenticated");
1746
- console.error(chalk7.red("Please run: wukong-cli auth login"));
1831
+ console.error(chalk6.red("Please run: wukong-cli auth login"));
1747
1832
  process.exit(1);
1748
1833
  }
1749
1834
  const fullUrl = buildUrl2(url, options.baseUrl);
@@ -1760,29 +1845,33 @@ async function executeRequest(method, url, options) {
1760
1845
  headers["Content-Type"] = "application/json";
1761
1846
  }
1762
1847
  }
1763
- spinner.text = `${method} ${chalk7.cyan(fullUrl)}`;
1848
+ spinner.text = `${method} ${chalk6.cyan(fullUrl)}`;
1849
+ debugRequest(method, fullUrl, headers, options.data ? JSON.parse(options.data) : void 0);
1850
+ const startTime = Date.now();
1764
1851
  const response = await fetch(fullUrl, {
1765
1852
  method,
1766
1853
  headers,
1767
1854
  body: method !== "GET" && method !== "DELETE" ? body : void 0
1768
1855
  });
1856
+ const duration = Date.now() - startTime;
1769
1857
  const data = await response.json();
1858
+ debugResponse(response.status, response.statusText, data, duration);
1770
1859
  spinner.succeed("Response received");
1771
1860
  console.log("");
1772
- console.log(chalk7.dim("Status:"), response.status, response.statusText);
1861
+ console.log(chalk6.dim("Status:"), response.status, response.statusText);
1773
1862
  console.log("");
1774
- console.log(chalk7.dim("Response:"));
1863
+ console.log(chalk6.dim("Response:"));
1775
1864
  console.log(JSON.stringify(data, null, 2));
1776
1865
  } catch (error) {
1777
1866
  spinner.fail("Request failed");
1778
1867
  if (error instanceof Error) {
1779
- console.error(chalk7.red(error.message));
1868
+ console.error(chalk6.red(error.message));
1780
1869
  }
1781
1870
  process.exit(1);
1782
1871
  }
1783
1872
  }
1784
- var httpCommand = new Command3("http");
1785
- httpCommand.command("get <url>").description("Send GET request (uses OCEANET_API_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) => {
1873
+ var httpCommand = new Command2("http");
1874
+ 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
1875
  await executeRequest("GET", url, options);
1787
1876
  });
1788
1877
  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 +1884,64 @@ httpCommand.command("delete <url>").description("Send DELETE request").option("-
1795
1884
  await executeRequest("DELETE", url, options);
1796
1885
  });
1797
1886
 
1887
+ // src/commands/init.ts
1888
+ init_esm_shims();
1889
+ import { Command as Command3 } from "commander";
1890
+ import { writeFileSync as writeFileSync3, existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
1891
+ import { join as join3, dirname as dirname3 } from "path";
1892
+ import { homedir as homedir3 } from "os";
1893
+ import { fileURLToPath as fileURLToPath3 } from "url";
1894
+ import chalk7 from "chalk";
1895
+ function getProjectRoot2() {
1896
+ let currentDir = dirname3(fileURLToPath3(import.meta.url));
1897
+ while (currentDir !== dirname3(currentDir)) {
1898
+ if (existsSync3(join3(currentDir, "package.json"))) {
1899
+ return currentDir;
1900
+ }
1901
+ currentDir = dirname3(currentDir);
1902
+ }
1903
+ return process.cwd();
1904
+ }
1905
+ async function executeInit() {
1906
+ const configPath = join3(homedir3(), "wukong-cli.json");
1907
+ const templatePath = join3(getProjectRoot2(), "wukong-cli.json.template");
1908
+ if (!existsSync3(templatePath)) {
1909
+ console.error(chalk7.red("\u274C Template configuration file not found"));
1910
+ console.error(chalk7.yellow(`Expected location: ${templatePath}`));
1911
+ process.exit(1);
1912
+ }
1913
+ try {
1914
+ const templateContent = readFileSync3(templatePath, "utf-8");
1915
+ const configExists = existsSync3(configPath);
1916
+ if (configExists) {
1917
+ console.log(chalk7.yellow("\u26A0\uFE0F Existing configuration file will be overwritten"));
1918
+ }
1919
+ writeFileSync3(configPath, templateContent, "utf-8");
1920
+ console.log(chalk7.green("\u2705 Configuration file created successfully"));
1921
+ console.log(chalk7.gray(`Location: ${configPath}`));
1922
+ if (configExists) {
1923
+ console.log(chalk7.yellow("Previous configuration has been overwritten"));
1924
+ }
1925
+ try {
1926
+ const config = JSON.parse(templateContent);
1927
+ console.log(chalk7.gray("\nConfiguration preview:"));
1928
+ console.log(chalk7.gray(` Default Environment: ${config.defaultEnv}`));
1929
+ console.log(chalk7.gray(` Configured Environments: ${Object.keys(config.environments).join(", ")}`));
1930
+ } catch (parseError) {
1931
+ }
1932
+ } catch (error) {
1933
+ console.error(chalk7.red("\u274C Failed to create configuration file"));
1934
+ console.error(chalk7.yellow(`Error: ${error}`));
1935
+ process.exit(1);
1936
+ }
1937
+ }
1938
+ var initCommand = new Command3("init").description("Initialize configuration file (creates or overwrites ~/wukong-cli.json)").action(async () => {
1939
+ await executeInit();
1940
+ });
1941
+
1798
1942
  // src/cli.ts
1799
1943
  var program = new Command4();
1800
- program.name("wukong-cli").description("Wukong CLI - TypeScript implementation").version("0.1.6").option("--debug", "Enable debug mode (show HTTP requests)").hook("preAction", (thisCommand) => {
1944
+ program.name("wukong-cli").description("Wukong CLI - TypeScript implementation").version("0.1.8").option("--debug", "Enable debug mode (show HTTP requests)").hook("preAction", (thisCommand) => {
1801
1945
  const options = thisCommand.opts();
1802
1946
  if (options.debug === true) {
1803
1947
  setDebugMode(true, true);
@@ -1806,10 +1950,12 @@ program.name("wukong-cli").description("Wukong CLI - TypeScript implementation")
1806
1950
  }
1807
1951
  });
1808
1952
  program.addCommand(authCommands);
1809
- program.addCommand(testCommand);
1810
1953
  program.addCommand(httpCommand);
1954
+ program.addCommand(initCommand);
1811
1955
  if (process.argv.length === 2) {
1812
1956
  program.help();
1813
1957
  }
1958
+ checkAndUpdate().catch(() => {
1959
+ });
1814
1960
  program.parse();
1815
1961
  //# sourceMappingURL=cli.js.map