@zrhsh/wukong-cli 0.1.6 → 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.
Files changed (4) hide show
  1. package/README.md +140 -120
  2. package/dist/cli.js +226 -153
  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)
@@ -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
- "Content-Type": "application/json"
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
- await fetch(`${config.AUTH_BASE_URL}${config.AUTH_ENDPOINTS.LOGOUT}`, {
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 url = `${global.__apiBaseUrl || ""}${endpoint}`;
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
- `${global.__apiBaseUrl || ""}${endpoint}`,
1377
+ retryUrl,
1324
1378
  {
1325
1379
  method: options.method || "GET",
1326
1380
  headers: {
@@ -1500,11 +1554,11 @@ 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 envConfig2 = allEnvs[env];
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, envConfig2.displayName);
1561
+ printEnvironmentInfo(env, envConfig.displayName);
1508
1562
  console.log("");
1509
1563
  const { verificationUri, deviceCode, expiresIn, interval } = await getDeviceCode();
1510
1564
  console.log("");
@@ -1542,7 +1596,7 @@ authCommands.command("login").description("Login using Device Authorization Flow
1542
1596
  console.log(chalk5.bgGreen.black.bold(" [OK] Login Successful "));
1543
1597
  console.log("");
1544
1598
  console.log(chalk5.green("[OK] Tokens saved securely"));
1545
- printEnvironmentInfo(env, envConfig2.displayName);
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"));
@@ -1557,23 +1611,25 @@ 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 envConfig2 = allEnvs[env];
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(`[OK] Logged out from ${env}`), chalk5.dim(`(${envConfig2.displayName})`));
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(`(${envConfig2.displayName})`));
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();
@@ -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 envConfig2 = allEnvs[env];
1673
+ const envConfig = allEnvs[env];
1618
1674
  const config = getOceanetConfig();
1619
1675
  try {
1620
1676
  const accessToken = await getAccessToken();
1621
1677
  if (!accessToken) {
1622
1678
  console.log(chalk5.yellow(`[ERROR] Not authenticated`));
1623
1679
  console.log("");
1624
- printEnvironmentInfo(env, envConfig2.displayName);
1680
+ printEnvironmentInfo(env, envConfig.displayName);
1625
1681
  console.log(chalk5.dim(`Run: wukong-cli auth login`));
1626
1682
  console.log("");
1627
1683
  return;
@@ -1633,7 +1689,7 @@ authCommands.command("status").description("Show authentication status").action(
1633
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, envConfig2.displayName);
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"));
@@ -1645,69 +1701,26 @@ authCommands.command("status").description("Show authentication status").action(
1645
1701
  console.log("");
1646
1702
  console.log(chalk5.red("Error:"), chalk5.dim(errorMsg));
1647
1703
  console.log("");
1648
- printEnvironmentInfo(env, envConfig2.displayName);
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, envConfig2.displayName);
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/test.ts
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("[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
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 base = baseUrl || OCEANET_CONFIG.API_BASE_URL;
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 = ora5("Sending request...").start();
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(chalk7.red("Please run: wukong-cli auth login"));
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} ${chalk7.cyan(fullUrl)}`;
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(chalk7.dim("Status:"), response.status, response.statusText);
1790
+ console.log(chalk6.dim("Status:"), response.status, response.statusText);
1773
1791
  console.log("");
1774
- console.log(chalk7.dim("Response:"));
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(chalk7.red(error.message));
1797
+ console.error(chalk6.red(error.message));
1780
1798
  }
1781
1799
  process.exit(1);
1782
1800
  }
1783
1801
  }
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) => {
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.6").option("--debug", "Enable debug mode (show HTTP requests)").hook("preAction", (thisCommand) => {
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
  }