@zrhsh/wukong-cli 0.4.11 → 0.4.14
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/dist/cli.js +396 -74
- package/dist/cli.js.map +1 -1
- package/package.json +72 -72
package/dist/cli.js
CHANGED
|
@@ -141,6 +141,7 @@ var init_config = __esm({
|
|
|
141
141
|
DEVICE_AUTHORIZE: "/oceanet-auth/pkce/device/authorize",
|
|
142
142
|
DEVICE_TOKEN: "/oceanet-auth/pkce/device/token",
|
|
143
143
|
REFRESH_TOKEN: "/oceanet-auth/manage/refreshToken",
|
|
144
|
+
REFRESH_TOKEN_NRP: "/oceanet-auth/manage/refreshTokenNRP",
|
|
144
145
|
LOGOUT: "/oceanet-auth/manage/logout"
|
|
145
146
|
},
|
|
146
147
|
API: {
|
|
@@ -491,14 +492,18 @@ var init_device_flow_service = __esm({
|
|
|
491
492
|
refresh_token,
|
|
492
493
|
expires_in,
|
|
493
494
|
token_type,
|
|
494
|
-
scope
|
|
495
|
+
scope,
|
|
496
|
+
yst_access_token,
|
|
497
|
+
yst_refresh_token
|
|
495
498
|
} = data.result;
|
|
496
499
|
return {
|
|
497
500
|
accessToken: access_token,
|
|
498
501
|
refreshToken: refresh_token,
|
|
499
502
|
expiresIn: expires_in,
|
|
500
503
|
tokenType: token_type,
|
|
501
|
-
scope: Array.isArray(scope) ? scope : [scope || ""]
|
|
504
|
+
scope: Array.isArray(scope) ? scope : [scope || ""],
|
|
505
|
+
...yst_access_token ? { ystAccessToken: yst_access_token } : {},
|
|
506
|
+
...yst_refresh_token ? { ystRefreshToken: yst_refresh_token } : {}
|
|
502
507
|
};
|
|
503
508
|
}
|
|
504
509
|
throw new Error("Authorization timed out. Please try again.");
|
|
@@ -733,19 +738,31 @@ var init_token_cache = __esm({
|
|
|
733
738
|
MemoryTokenCache = class {
|
|
734
739
|
accessToken = null;
|
|
735
740
|
refreshToken = null;
|
|
741
|
+
ystAccessToken = null;
|
|
742
|
+
ystRefreshToken = null;
|
|
736
743
|
getAccessToken() {
|
|
737
744
|
return this.accessToken;
|
|
738
745
|
}
|
|
739
746
|
getRefreshToken() {
|
|
740
747
|
return this.refreshToken;
|
|
741
748
|
}
|
|
742
|
-
|
|
749
|
+
getYstAccessToken() {
|
|
750
|
+
return this.ystAccessToken;
|
|
751
|
+
}
|
|
752
|
+
getYstRefreshToken() {
|
|
753
|
+
return this.ystRefreshToken;
|
|
754
|
+
}
|
|
755
|
+
setTokens(accessToken, refreshToken, ystAccessToken, ystRefreshToken) {
|
|
743
756
|
if (accessToken !== null) this.accessToken = accessToken;
|
|
744
757
|
if (refreshToken !== null) this.refreshToken = refreshToken;
|
|
758
|
+
if (ystAccessToken !== void 0 && ystAccessToken !== null) this.ystAccessToken = ystAccessToken;
|
|
759
|
+
if (ystRefreshToken !== void 0 && ystRefreshToken !== null) this.ystRefreshToken = ystRefreshToken;
|
|
745
760
|
}
|
|
746
761
|
clear() {
|
|
747
762
|
this.accessToken = null;
|
|
748
763
|
this.refreshToken = null;
|
|
764
|
+
this.ystAccessToken = null;
|
|
765
|
+
this.ystRefreshToken = null;
|
|
749
766
|
}
|
|
750
767
|
hasAccessToken() {
|
|
751
768
|
return this.accessToken !== null && this.accessToken.length > 0;
|
|
@@ -1106,27 +1123,21 @@ init_oceanet();
|
|
|
1106
1123
|
init_debug();
|
|
1107
1124
|
import ora2 from "ora";
|
|
1108
1125
|
var TokenManager = class {
|
|
1109
|
-
/**
|
|
1110
|
-
* 构造函数
|
|
1111
|
-
* @param credentialStore 凭据存储实例
|
|
1112
|
-
* @param tokenCache token 缓存实例
|
|
1113
|
-
*/
|
|
1114
1126
|
constructor(credentialStore, tokenCache) {
|
|
1115
1127
|
this.credentialStore = credentialStore;
|
|
1116
1128
|
this.tokenCache = tokenCache;
|
|
1117
1129
|
}
|
|
1118
|
-
|
|
1119
|
-
* 保存 Token
|
|
1120
|
-
*/
|
|
1121
|
-
async saveToken(accessToken, refreshToken) {
|
|
1130
|
+
async saveToken(options) {
|
|
1122
1131
|
const config = getOceanetConfig();
|
|
1123
|
-
|
|
1124
|
-
await
|
|
1125
|
-
|
|
1132
|
+
const { accessToken, refreshToken, ystAccessToken, ystRefreshToken } = options;
|
|
1133
|
+
await Promise.all([
|
|
1134
|
+
this.credentialStore.setPassword(config.SERVICE_NAME, "access_token", accessToken),
|
|
1135
|
+
this.credentialStore.setPassword(config.SERVICE_NAME, "refresh_token", refreshToken),
|
|
1136
|
+
...ystAccessToken ? [this.credentialStore.setPassword(config.SERVICE_NAME, "yst_access_token", ystAccessToken)] : [],
|
|
1137
|
+
...ystRefreshToken ? [this.credentialStore.setPassword(config.SERVICE_NAME, "yst_refresh_token", ystRefreshToken)] : []
|
|
1138
|
+
]);
|
|
1139
|
+
this.tokenCache.setTokens(accessToken, refreshToken, ystAccessToken ?? null, ystRefreshToken ?? null);
|
|
1126
1140
|
}
|
|
1127
|
-
/**
|
|
1128
|
-
* 获取 Access Token
|
|
1129
|
-
*/
|
|
1130
1141
|
async getAccessToken() {
|
|
1131
1142
|
const cached = this.tokenCache.getAccessToken();
|
|
1132
1143
|
if (cached) {
|
|
@@ -1139,9 +1150,6 @@ var TokenManager = class {
|
|
|
1139
1150
|
}
|
|
1140
1151
|
return token;
|
|
1141
1152
|
}
|
|
1142
|
-
/**
|
|
1143
|
-
* 获取 Refresh Token
|
|
1144
|
-
*/
|
|
1145
1153
|
async getRefreshToken() {
|
|
1146
1154
|
const cached = this.tokenCache.getRefreshToken();
|
|
1147
1155
|
if (cached) {
|
|
@@ -1154,9 +1162,30 @@ var TokenManager = class {
|
|
|
1154
1162
|
}
|
|
1155
1163
|
return token;
|
|
1156
1164
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1165
|
+
async getYstAccessToken() {
|
|
1166
|
+
const cached = this.tokenCache.getYstAccessToken();
|
|
1167
|
+
if (cached) {
|
|
1168
|
+
return cached;
|
|
1169
|
+
}
|
|
1170
|
+
const config = getOceanetConfig();
|
|
1171
|
+
const token = await this.credentialStore.getPassword(config.SERVICE_NAME, "yst_access_token");
|
|
1172
|
+
if (token) {
|
|
1173
|
+
this.tokenCache.setTokens(null, null, token, null);
|
|
1174
|
+
}
|
|
1175
|
+
return token;
|
|
1176
|
+
}
|
|
1177
|
+
async getYstRefreshToken() {
|
|
1178
|
+
const cached = this.tokenCache.getYstRefreshToken();
|
|
1179
|
+
if (cached) {
|
|
1180
|
+
return cached;
|
|
1181
|
+
}
|
|
1182
|
+
const config = getOceanetConfig();
|
|
1183
|
+
const token = await this.credentialStore.getPassword(config.SERVICE_NAME, "yst_refresh_token");
|
|
1184
|
+
if (token) {
|
|
1185
|
+
this.tokenCache.setTokens(null, null, null, token);
|
|
1186
|
+
}
|
|
1187
|
+
return token;
|
|
1188
|
+
}
|
|
1160
1189
|
async refreshAccessToken(refreshToken) {
|
|
1161
1190
|
const spinner = ora2("Refreshing access token...").start();
|
|
1162
1191
|
try {
|
|
@@ -1185,7 +1214,9 @@ var TokenManager = class {
|
|
|
1185
1214
|
refresh_token: new_refresh_token,
|
|
1186
1215
|
expires_in,
|
|
1187
1216
|
token_type,
|
|
1188
|
-
scope
|
|
1217
|
+
scope,
|
|
1218
|
+
yst_access_token,
|
|
1219
|
+
yst_refresh_token: yst_new_refresh_token
|
|
1189
1220
|
} = data.result;
|
|
1190
1221
|
spinner.succeed("Token refreshed");
|
|
1191
1222
|
return {
|
|
@@ -1193,38 +1224,78 @@ var TokenManager = class {
|
|
|
1193
1224
|
refreshToken: new_refresh_token,
|
|
1194
1225
|
expiresIn: expires_in,
|
|
1195
1226
|
tokenType: token_type,
|
|
1196
|
-
scope: Array.isArray(scope) ? scope : [scope || ""]
|
|
1227
|
+
scope: Array.isArray(scope) ? scope : [scope || ""],
|
|
1228
|
+
...yst_access_token ? { ystAccessToken: yst_access_token } : {},
|
|
1229
|
+
...yst_new_refresh_token ? { ystRefreshToken: yst_new_refresh_token } : {}
|
|
1197
1230
|
};
|
|
1198
1231
|
} catch (error) {
|
|
1199
1232
|
spinner.fail("Token refresh error");
|
|
1200
1233
|
throw error;
|
|
1201
1234
|
}
|
|
1202
1235
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1236
|
+
async refreshYstAccessToken(ystRefreshToken) {
|
|
1237
|
+
const spinner = ora2("Refreshing YST access token...").start();
|
|
1238
|
+
try {
|
|
1239
|
+
const config = getOceanetConfig();
|
|
1240
|
+
const url = `${config.AUTH_BASE_URL}${config.AUTH_ENDPOINTS.REFRESH_TOKEN_NRP}`;
|
|
1241
|
+
const requestHeaders = {
|
|
1242
|
+
"Content-Type": "application/json"
|
|
1243
|
+
};
|
|
1244
|
+
const requestBody = { param: ystRefreshToken };
|
|
1245
|
+
debugRequest("POST", url, requestHeaders, requestBody);
|
|
1246
|
+
const startTime = Date.now();
|
|
1247
|
+
const response = await fetch(url, {
|
|
1248
|
+
method: "POST",
|
|
1249
|
+
headers: requestHeaders,
|
|
1250
|
+
body: JSON.stringify(requestBody)
|
|
1251
|
+
});
|
|
1252
|
+
const duration = Date.now() - startTime;
|
|
1253
|
+
const data = await response.json();
|
|
1254
|
+
debugResponse(response.status, response.statusText, data, duration);
|
|
1255
|
+
if (data.code !== 200) {
|
|
1256
|
+
spinner.fail("YST token refresh failed");
|
|
1257
|
+
throw new Error(data.message || "YST refresh token failed");
|
|
1258
|
+
}
|
|
1259
|
+
const { access_token, refresh_token } = data.result;
|
|
1260
|
+
spinner.succeed("YST token refreshed");
|
|
1261
|
+
return {
|
|
1262
|
+
ystAccessToken: access_token,
|
|
1263
|
+
ystRefreshToken: refresh_token
|
|
1264
|
+
};
|
|
1265
|
+
} catch (error) {
|
|
1266
|
+
spinner.fail("YST token refresh error");
|
|
1267
|
+
throw error;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1206
1270
|
async clearTokens() {
|
|
1207
1271
|
const config = getOceanetConfig();
|
|
1208
|
-
await
|
|
1209
|
-
|
|
1272
|
+
await Promise.all([
|
|
1273
|
+
this.credentialStore.deletePassword(config.SERVICE_NAME, "access_token"),
|
|
1274
|
+
this.credentialStore.deletePassword(config.SERVICE_NAME, "refresh_token"),
|
|
1275
|
+
this.credentialStore.deletePassword(config.SERVICE_NAME, "yst_access_token"),
|
|
1276
|
+
this.credentialStore.deletePassword(config.SERVICE_NAME, "yst_refresh_token")
|
|
1277
|
+
]);
|
|
1210
1278
|
this.tokenCache.clear();
|
|
1211
1279
|
}
|
|
1212
|
-
|
|
1213
|
-
* 退出登录
|
|
1214
|
-
*/
|
|
1215
|
-
async logout(accessToken) {
|
|
1280
|
+
async logout(accessToken, ocAccessToken) {
|
|
1216
1281
|
try {
|
|
1217
1282
|
const config = getOceanetConfig();
|
|
1218
1283
|
const url = `${config.AUTH_BASE_URL}${config.AUTH_ENDPOINTS.LOGOUT}`;
|
|
1219
1284
|
const requestHeaders = {
|
|
1220
|
-
"Content-Type": "application/json"
|
|
1221
|
-
"Authorization": `Bearer ${accessToken}`
|
|
1285
|
+
"Content-Type": "application/json"
|
|
1222
1286
|
};
|
|
1223
|
-
|
|
1287
|
+
const requestBody = {
|
|
1288
|
+
access_token: accessToken
|
|
1289
|
+
};
|
|
1290
|
+
if (ocAccessToken) {
|
|
1291
|
+
requestBody.oc_access_token = ocAccessToken;
|
|
1292
|
+
}
|
|
1293
|
+
debugRequest("POST", url, requestHeaders, requestBody);
|
|
1224
1294
|
const startTime = Date.now();
|
|
1225
1295
|
const response = await fetch(url, {
|
|
1226
1296
|
method: "POST",
|
|
1227
|
-
headers: requestHeaders
|
|
1297
|
+
headers: requestHeaders,
|
|
1298
|
+
body: JSON.stringify(requestBody)
|
|
1228
1299
|
});
|
|
1229
1300
|
const duration = Date.now() - startTime;
|
|
1230
1301
|
let data;
|
|
@@ -1237,18 +1308,21 @@ var TokenManager = class {
|
|
|
1237
1308
|
}
|
|
1238
1309
|
await this.clearTokens();
|
|
1239
1310
|
}
|
|
1240
|
-
/**
|
|
1241
|
-
* 初始化 Token 缓存
|
|
1242
|
-
* 从持久化存储加载 token 到内存缓存
|
|
1243
|
-
*/
|
|
1244
1311
|
async initTokenCache() {
|
|
1245
1312
|
const config = getOceanetConfig();
|
|
1246
|
-
const [accessToken, refreshToken] = await Promise.all([
|
|
1313
|
+
const [accessToken, refreshToken, ystAccessToken, ystRefreshToken] = await Promise.all([
|
|
1247
1314
|
this.credentialStore.getPassword(config.SERVICE_NAME, "access_token"),
|
|
1248
|
-
this.credentialStore.getPassword(config.SERVICE_NAME, "refresh_token")
|
|
1315
|
+
this.credentialStore.getPassword(config.SERVICE_NAME, "refresh_token"),
|
|
1316
|
+
this.credentialStore.getPassword(config.SERVICE_NAME, "yst_access_token"),
|
|
1317
|
+
this.credentialStore.getPassword(config.SERVICE_NAME, "yst_refresh_token")
|
|
1249
1318
|
]);
|
|
1250
|
-
if (accessToken || refreshToken) {
|
|
1251
|
-
this.tokenCache.setTokens(
|
|
1319
|
+
if (accessToken || refreshToken || ystAccessToken || ystRefreshToken) {
|
|
1320
|
+
this.tokenCache.setTokens(
|
|
1321
|
+
accessToken || null,
|
|
1322
|
+
refreshToken || null,
|
|
1323
|
+
ystAccessToken || null,
|
|
1324
|
+
ystRefreshToken || null
|
|
1325
|
+
);
|
|
1252
1326
|
}
|
|
1253
1327
|
}
|
|
1254
1328
|
};
|
|
@@ -1263,17 +1337,30 @@ function getTokenManager() {
|
|
|
1263
1337
|
}
|
|
1264
1338
|
return tokenManagerInstance;
|
|
1265
1339
|
}
|
|
1266
|
-
async function saveToken(
|
|
1340
|
+
async function saveToken(accessTokenOrOptions, refreshToken) {
|
|
1267
1341
|
const manager = getTokenManager();
|
|
1268
|
-
|
|
1342
|
+
const options = typeof accessTokenOrOptions === "string" ? { accessToken: accessTokenOrOptions, refreshToken } : accessTokenOrOptions;
|
|
1343
|
+
await manager.saveToken(options);
|
|
1269
1344
|
}
|
|
1270
1345
|
async function getAccessToken() {
|
|
1271
1346
|
const manager = getTokenManager();
|
|
1272
1347
|
return await manager.getAccessToken();
|
|
1273
1348
|
}
|
|
1274
|
-
async function
|
|
1349
|
+
async function getRefreshToken() {
|
|
1350
|
+
const manager = getTokenManager();
|
|
1351
|
+
return await manager.getRefreshToken();
|
|
1352
|
+
}
|
|
1353
|
+
async function getYstAccessToken() {
|
|
1354
|
+
const manager = getTokenManager();
|
|
1355
|
+
return await manager.getYstAccessToken();
|
|
1356
|
+
}
|
|
1357
|
+
async function getYstRefreshToken() {
|
|
1275
1358
|
const manager = getTokenManager();
|
|
1276
|
-
await manager.
|
|
1359
|
+
return await manager.getYstRefreshToken();
|
|
1360
|
+
}
|
|
1361
|
+
async function logout(accessToken, ocAccessToken) {
|
|
1362
|
+
const manager = getTokenManager();
|
|
1363
|
+
await manager.logout(accessToken, ocAccessToken);
|
|
1277
1364
|
}
|
|
1278
1365
|
|
|
1279
1366
|
// src/core/http/client.ts
|
|
@@ -1511,7 +1598,6 @@ function createRetokenInstance(credentialStore, tokenCache) {
|
|
|
1511
1598
|
refreshEndpoint: {
|
|
1512
1599
|
url: `${config.AUTH_BASE_URL}${config.AUTH_ENDPOINTS.REFRESH_TOKEN}`,
|
|
1513
1600
|
method: "POST",
|
|
1514
|
-
// Oceanet API 要求: { "param": "refresh_token_string" }
|
|
1515
1601
|
buildBody: (token) => JSON.stringify({ param: token }),
|
|
1516
1602
|
headers: {
|
|
1517
1603
|
"Content-Type": "application/json"
|
|
@@ -1547,18 +1633,18 @@ function createRetokenInstance(credentialStore, tokenCache) {
|
|
|
1547
1633
|
}
|
|
1548
1634
|
return {
|
|
1549
1635
|
accessToken: result.access_token || result.accessToken,
|
|
1550
|
-
refreshToken: result.refresh_token || result.refreshToken
|
|
1636
|
+
refreshToken: result.refresh_token || result.refreshToken,
|
|
1637
|
+
...result.yst_access_token ? { ystAccessToken: result.yst_access_token } : {},
|
|
1638
|
+
...result.yst_refresh_token ? { ystRefreshToken: result.yst_refresh_token } : {}
|
|
1551
1639
|
};
|
|
1552
1640
|
}
|
|
1553
1641
|
},
|
|
1554
|
-
// 从缓存获取 token(同步函数)
|
|
1555
1642
|
getAccessToken: () => {
|
|
1556
1643
|
return cache.getAccessToken();
|
|
1557
1644
|
},
|
|
1558
1645
|
getRefreshToken: () => {
|
|
1559
1646
|
return cache.getRefreshToken();
|
|
1560
1647
|
},
|
|
1561
|
-
// 保存 token 到持久化存储和缓存
|
|
1562
1648
|
setTokens: (tokens) => {
|
|
1563
1649
|
const accessToken = tokens?.accessToken;
|
|
1564
1650
|
const refreshToken = tokens?.refreshToken;
|
|
@@ -1566,10 +1652,17 @@ function createRetokenInstance(credentialStore, tokenCache) {
|
|
|
1566
1652
|
throw new Error("Invalid tokens: missing access_token or refresh_token");
|
|
1567
1653
|
}
|
|
1568
1654
|
const cfg = getOceanetConfig();
|
|
1569
|
-
cache.setTokens(
|
|
1655
|
+
cache.setTokens(
|
|
1656
|
+
accessToken,
|
|
1657
|
+
refreshToken,
|
|
1658
|
+
tokens?.ystAccessToken ?? null,
|
|
1659
|
+
tokens?.ystRefreshToken ?? null
|
|
1660
|
+
);
|
|
1570
1661
|
void Promise.all([
|
|
1571
1662
|
store.setPassword(cfg.SERVICE_NAME, "access_token", accessToken),
|
|
1572
|
-
store.setPassword(cfg.SERVICE_NAME, "refresh_token", refreshToken)
|
|
1663
|
+
store.setPassword(cfg.SERVICE_NAME, "refresh_token", refreshToken),
|
|
1664
|
+
...tokens?.ystAccessToken ? [store.setPassword(cfg.SERVICE_NAME, "yst_access_token", tokens.ystAccessToken)] : [],
|
|
1665
|
+
...tokens?.ystRefreshToken ? [store.setPassword(cfg.SERVICE_NAME, "yst_refresh_token", tokens.ystRefreshToken)] : []
|
|
1573
1666
|
]).catch((error) => {
|
|
1574
1667
|
if (cfg.DEBUG || global.__debugMode) {
|
|
1575
1668
|
console.log("");
|
|
@@ -1583,26 +1676,36 @@ function createRetokenInstance(credentialStore, tokenCache) {
|
|
|
1583
1676
|
console.log("=== Token Saved ===");
|
|
1584
1677
|
console.log("Access token saved (length:", accessToken.length, ")");
|
|
1585
1678
|
console.log("Refresh token saved (length:", refreshToken.length, ")");
|
|
1679
|
+
if (tokens?.ystAccessToken) {
|
|
1680
|
+
console.log("YST access token saved (length:", tokens.ystAccessToken.length, ")");
|
|
1681
|
+
}
|
|
1682
|
+
if (tokens?.ystRefreshToken) {
|
|
1683
|
+
console.log("YST refresh token saved (length:", tokens.ystRefreshToken.length, ")");
|
|
1684
|
+
}
|
|
1586
1685
|
console.log("");
|
|
1587
1686
|
}
|
|
1588
1687
|
},
|
|
1589
|
-
// 清除 token
|
|
1590
1688
|
clearTokens: async () => {
|
|
1591
1689
|
const cfg = getOceanetConfig();
|
|
1592
|
-
await
|
|
1593
|
-
|
|
1690
|
+
await Promise.all([
|
|
1691
|
+
store.deletePassword(cfg.SERVICE_NAME, "access_token"),
|
|
1692
|
+
store.deletePassword(cfg.SERVICE_NAME, "refresh_token"),
|
|
1693
|
+
store.deletePassword(cfg.SERVICE_NAME, "yst_access_token"),
|
|
1694
|
+
store.deletePassword(cfg.SERVICE_NAME, "yst_refresh_token")
|
|
1695
|
+
]);
|
|
1594
1696
|
cache.clear();
|
|
1595
1697
|
},
|
|
1596
|
-
// 提前 1 分钟(60 秒)主动刷新
|
|
1597
1698
|
expirationLeeway: 60,
|
|
1598
|
-
// 401 时触发重试
|
|
1599
1699
|
retryStatuses: [401],
|
|
1600
|
-
// 认证完全失败时的回调
|
|
1601
1700
|
onAuthFailure: async () => {
|
|
1602
1701
|
const cfg = getOceanetConfig();
|
|
1603
1702
|
try {
|
|
1604
|
-
await
|
|
1605
|
-
|
|
1703
|
+
await Promise.all([
|
|
1704
|
+
store.deletePassword(cfg.SERVICE_NAME, "access_token"),
|
|
1705
|
+
store.deletePassword(cfg.SERVICE_NAME, "refresh_token"),
|
|
1706
|
+
store.deletePassword(cfg.SERVICE_NAME, "yst_access_token"),
|
|
1707
|
+
store.deletePassword(cfg.SERVICE_NAME, "yst_refresh_token")
|
|
1708
|
+
]);
|
|
1606
1709
|
cache.clear();
|
|
1607
1710
|
} catch {
|
|
1608
1711
|
}
|
|
@@ -1659,9 +1762,19 @@ var AuthenticatingHttpClient = class {
|
|
|
1659
1762
|
async refreshTokenAndPersist(retoken = getRetoken()) {
|
|
1660
1763
|
const tokens = await retoken.refreshToken();
|
|
1661
1764
|
if (tokens?.accessToken && tokens?.refreshToken) {
|
|
1662
|
-
this.tokenCache.setTokens(
|
|
1765
|
+
this.tokenCache.setTokens(
|
|
1766
|
+
tokens.accessToken,
|
|
1767
|
+
tokens.refreshToken,
|
|
1768
|
+
tokens.ystAccessToken ?? null,
|
|
1769
|
+
tokens.ystRefreshToken ?? null
|
|
1770
|
+
);
|
|
1663
1771
|
const tokenManager = getTokenManager();
|
|
1664
|
-
await tokenManager.saveToken(
|
|
1772
|
+
await tokenManager.saveToken({
|
|
1773
|
+
accessToken: tokens.accessToken,
|
|
1774
|
+
refreshToken: tokens.refreshToken,
|
|
1775
|
+
ystAccessToken: tokens.ystAccessToken,
|
|
1776
|
+
ystRefreshToken: tokens.ystRefreshToken
|
|
1777
|
+
});
|
|
1665
1778
|
}
|
|
1666
1779
|
}
|
|
1667
1780
|
/**
|
|
@@ -1954,7 +2067,12 @@ authCommands.command("login").description("Login using Device Authorization Flow
|
|
|
1954
2067
|
console.log(chalk5.dim("\u2550".repeat(50)));
|
|
1955
2068
|
console.log("");
|
|
1956
2069
|
const tokens = await adapter.pollToken(deviceCode);
|
|
1957
|
-
await saveToken(
|
|
2070
|
+
await saveToken({
|
|
2071
|
+
accessToken: tokens.accessToken,
|
|
2072
|
+
refreshToken: tokens.refreshToken,
|
|
2073
|
+
ystAccessToken: tokens.ystAccessToken,
|
|
2074
|
+
ystRefreshToken: tokens.ystRefreshToken
|
|
2075
|
+
});
|
|
1958
2076
|
console.log("");
|
|
1959
2077
|
console.log(chalk5.bgGreen.black.bold(" [OK] Login Successful "));
|
|
1960
2078
|
console.log("");
|
|
@@ -1985,8 +2103,9 @@ authCommands.command("logout").description("Logout and clear saved tokens").acti
|
|
|
1985
2103
|
const envConfig = allEnvs[env];
|
|
1986
2104
|
try {
|
|
1987
2105
|
const accessToken = await getAccessToken();
|
|
2106
|
+
const ystAccessToken = await getYstAccessToken();
|
|
1988
2107
|
if (accessToken) {
|
|
1989
|
-
await logout(accessToken);
|
|
2108
|
+
await logout(accessToken, ystAccessToken ?? void 0);
|
|
1990
2109
|
}
|
|
1991
2110
|
console.log("");
|
|
1992
2111
|
console.log(chalk5.green(`[OK] Logged out from ${env}`), chalk5.dim(`(${envConfig.displayName})`));
|
|
@@ -2099,6 +2218,165 @@ authCommands.command("status").description("Show authentication status").action(
|
|
|
2099
2218
|
console.log("");
|
|
2100
2219
|
}
|
|
2101
2220
|
});
|
|
2221
|
+
authCommands.command("token").description("Display current token structure and JWT payload claims").action(async () => {
|
|
2222
|
+
console.log("");
|
|
2223
|
+
const env = getCurrentEnvironment();
|
|
2224
|
+
const allEnvs = getAllEnvironments();
|
|
2225
|
+
setCurrentEnvironment(env);
|
|
2226
|
+
const envConfig = allEnvs[env];
|
|
2227
|
+
try {
|
|
2228
|
+
let decodeJwt2 = function(token) {
|
|
2229
|
+
try {
|
|
2230
|
+
const parts = token.split(".");
|
|
2231
|
+
if (parts.length !== 3) return null;
|
|
2232
|
+
const header = JSON.parse(Buffer.from(parts[0], "base64url").toString("utf-8"));
|
|
2233
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
|
|
2234
|
+
return { header, payload };
|
|
2235
|
+
} catch {
|
|
2236
|
+
return null;
|
|
2237
|
+
}
|
|
2238
|
+
};
|
|
2239
|
+
var decodeJwt = decodeJwt2;
|
|
2240
|
+
const config = getOceanetConfig();
|
|
2241
|
+
const accessToken = await getAccessToken();
|
|
2242
|
+
const refreshToken = await getRefreshToken();
|
|
2243
|
+
if (!accessToken) {
|
|
2244
|
+
console.log(chalk5.yellow("[ERROR] Not authenticated"));
|
|
2245
|
+
console.log("");
|
|
2246
|
+
printEnvironmentInfo(env, envConfig.displayName);
|
|
2247
|
+
console.log(chalk5.dim("Run: wukong-cli auth login"));
|
|
2248
|
+
console.log("");
|
|
2249
|
+
return;
|
|
2250
|
+
}
|
|
2251
|
+
console.log(chalk5.bgGreen.black.bold(" Token Information "));
|
|
2252
|
+
console.log("");
|
|
2253
|
+
printEnvironmentInfo(env, envConfig.displayName);
|
|
2254
|
+
console.log("");
|
|
2255
|
+
const decoded = decodeJwt2(accessToken);
|
|
2256
|
+
if (!decoded) {
|
|
2257
|
+
console.log(chalk5.yellow("[WARNING] Access token is not a valid JWT"));
|
|
2258
|
+
console.log("");
|
|
2259
|
+
console.log(chalk5.dim("Access Token (raw):"), chalk5.cyan(accessToken.substring(0, 40) + "..."));
|
|
2260
|
+
if (refreshToken) {
|
|
2261
|
+
console.log(chalk5.dim("Refresh Token:"), chalk5.cyan(refreshToken.substring(0, 20) + "..." + refreshToken.slice(-4)));
|
|
2262
|
+
}
|
|
2263
|
+
console.log("");
|
|
2264
|
+
return;
|
|
2265
|
+
}
|
|
2266
|
+
console.log(chalk5.bold("JWT Header:"));
|
|
2267
|
+
console.log(chalk5.dim(" alg:"), chalk5.cyan(String(decoded.header.alg ?? "N/A")));
|
|
2268
|
+
console.log(chalk5.dim(" typ:"), chalk5.cyan(String(decoded.header.typ ?? "N/A")));
|
|
2269
|
+
console.log("");
|
|
2270
|
+
console.log(chalk5.bold("JWT Payload:"));
|
|
2271
|
+
const skipKeys = /* @__PURE__ */ new Set(["exp", "iat", "nbf", "jti"]);
|
|
2272
|
+
for (const [key, value] of Object.entries(decoded.payload)) {
|
|
2273
|
+
if (skipKeys.has(key)) continue;
|
|
2274
|
+
console.log(chalk5.dim(` ${key}:`), chalk5.cyan(String(value)));
|
|
2275
|
+
}
|
|
2276
|
+
console.log("");
|
|
2277
|
+
const now = Date.now();
|
|
2278
|
+
const exp = typeof decoded.payload.exp === "number" ? decoded.payload.exp * 1e3 : null;
|
|
2279
|
+
const iat = typeof decoded.payload.iat === "number" ? decoded.payload.iat * 1e3 : null;
|
|
2280
|
+
console.log(chalk5.bold("Expiration:"));
|
|
2281
|
+
if (exp) {
|
|
2282
|
+
const expDate = new Date(exp);
|
|
2283
|
+
const diffMs = exp - now;
|
|
2284
|
+
if (diffMs <= 0) {
|
|
2285
|
+
console.log(chalk5.dim(" Status:"), chalk5.red("EXPIRED"));
|
|
2286
|
+
console.log(chalk5.dim(" Expired at:"), chalk5.red(expDate.toLocaleString()));
|
|
2287
|
+
} else if (diffMs < 5 * 60 * 1e3) {
|
|
2288
|
+
console.log(chalk5.dim(" Status:"), chalk5.yellow("Expiring soon"));
|
|
2289
|
+
console.log(chalk5.dim(" Expires at:"), chalk5.yellow(expDate.toLocaleString()));
|
|
2290
|
+
console.log(chalk5.dim(" Remaining:"), chalk5.yellow(`${Math.floor(diffMs / 6e4)} minutes`));
|
|
2291
|
+
} else {
|
|
2292
|
+
console.log(chalk5.dim(" Status:"), chalk5.green("Valid"));
|
|
2293
|
+
console.log(chalk5.dim(" Expires at:"), chalk5.green(expDate.toLocaleString()));
|
|
2294
|
+
console.log(chalk5.dim(" Remaining:"), chalk5.green(`${Math.floor(diffMs / 6e4)} minutes`));
|
|
2295
|
+
}
|
|
2296
|
+
} else {
|
|
2297
|
+
console.log(chalk5.dim(" exp:"), chalk5.yellow("N/A"));
|
|
2298
|
+
}
|
|
2299
|
+
if (iat) {
|
|
2300
|
+
console.log(chalk5.dim(" Issued at:"), chalk5.cyan(new Date(iat).toLocaleString()));
|
|
2301
|
+
}
|
|
2302
|
+
console.log("");
|
|
2303
|
+
if (refreshToken) {
|
|
2304
|
+
console.log(chalk5.bold("Refresh Token:"));
|
|
2305
|
+
console.log(chalk5.dim(" Token:"), chalk5.cyan(refreshToken.substring(0, 20) + "..." + refreshToken.slice(-4)));
|
|
2306
|
+
console.log(chalk5.dim(" Length:"), chalk5.cyan(`${refreshToken.length} characters`));
|
|
2307
|
+
console.log("");
|
|
2308
|
+
} else {
|
|
2309
|
+
console.log(chalk5.dim("Refresh Token:"), chalk5.yellow("Not available"));
|
|
2310
|
+
console.log("");
|
|
2311
|
+
}
|
|
2312
|
+
const ystAccessToken = await getYstAccessToken();
|
|
2313
|
+
const ystRefreshToken = await getYstRefreshToken();
|
|
2314
|
+
if (ystAccessToken || ystRefreshToken) {
|
|
2315
|
+
console.log(chalk5.bold("YST Token (NRP):"));
|
|
2316
|
+
if (ystAccessToken) {
|
|
2317
|
+
console.log(chalk5.dim(" Access Token:"), chalk5.cyan(ystAccessToken.substring(0, 20) + "..." + ystAccessToken.slice(-4)));
|
|
2318
|
+
console.log(chalk5.dim(" Length:"), chalk5.cyan(`${ystAccessToken.length} characters`));
|
|
2319
|
+
const ystDecoded = decodeJwt2(ystAccessToken);
|
|
2320
|
+
if (ystDecoded) {
|
|
2321
|
+
const ystExp = typeof ystDecoded.payload.exp === "number" ? ystDecoded.payload.exp * 1e3 : null;
|
|
2322
|
+
if (ystExp) {
|
|
2323
|
+
const ystDiffMs = ystExp - now;
|
|
2324
|
+
if (ystDiffMs <= 0) {
|
|
2325
|
+
console.log(chalk5.dim(" JWT Status:"), chalk5.red("EXPIRED"));
|
|
2326
|
+
console.log(chalk5.dim(" Expires at:"), chalk5.red(new Date(ystExp).toLocaleString()));
|
|
2327
|
+
} else if (ystDiffMs < 5 * 60 * 1e3) {
|
|
2328
|
+
console.log(chalk5.dim(" JWT Status:"), chalk5.yellow("Expiring soon"));
|
|
2329
|
+
console.log(chalk5.dim(" Expires at:"), chalk5.yellow(new Date(ystExp).toLocaleString()));
|
|
2330
|
+
} else {
|
|
2331
|
+
console.log(chalk5.dim(" JWT Status:"), chalk5.green("Valid"));
|
|
2332
|
+
console.log(chalk5.dim(" Expires at:"), chalk5.green(new Date(ystExp).toLocaleString()));
|
|
2333
|
+
console.log(chalk5.dim(" Remaining:"), chalk5.green(`${Math.floor(ystDiffMs / 6e4)} minutes`));
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
console.log(chalk5.dim(" Server:"));
|
|
2338
|
+
try {
|
|
2339
|
+
const ystVerifyUrl = `${config.API_BASE_URL}/yst-system/sys/users/current`;
|
|
2340
|
+
const ystResponse = await fetch(ystVerifyUrl, {
|
|
2341
|
+
headers: { "Authorization": `Bearer ${ystAccessToken}` }
|
|
2342
|
+
});
|
|
2343
|
+
if (ystResponse.ok) {
|
|
2344
|
+
console.log(chalk5.dim(" Status:"), chalk5.green("Valid (server verified)"));
|
|
2345
|
+
} else {
|
|
2346
|
+
const ystErrText = await ystResponse.text().catch(() => "");
|
|
2347
|
+
console.log(chalk5.dim(" Status:"), chalk5.red(`Invalid (HTTP ${ystResponse.status})`));
|
|
2348
|
+
if (ystErrText) {
|
|
2349
|
+
console.log(chalk5.dim(" Error:"), chalk5.red(ystErrText.substring(0, 100)));
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
} catch (ystVerifyError) {
|
|
2353
|
+
console.log(chalk5.dim(" Status:"), chalk5.yellow("Unable to verify (network error)"));
|
|
2354
|
+
}
|
|
2355
|
+
} else {
|
|
2356
|
+
console.log(chalk5.dim(" Access Token:"), chalk5.yellow("Not available"));
|
|
2357
|
+
}
|
|
2358
|
+
if (ystRefreshToken) {
|
|
2359
|
+
console.log(chalk5.dim(" Refresh Token:"), chalk5.cyan(ystRefreshToken.substring(0, 20) + "..." + ystRefreshToken.slice(-4)));
|
|
2360
|
+
console.log(chalk5.dim(" Refresh Length:"), chalk5.cyan(`${ystRefreshToken.length} characters`));
|
|
2361
|
+
} else {
|
|
2362
|
+
console.log(chalk5.dim(" Refresh Token:"), chalk5.yellow("Not available"));
|
|
2363
|
+
}
|
|
2364
|
+
console.log("");
|
|
2365
|
+
}
|
|
2366
|
+
} catch (error) {
|
|
2367
|
+
if (error instanceof ConfigFileError) {
|
|
2368
|
+
console.log("");
|
|
2369
|
+
console.log(chalk5.red("[ERROR] Configuration Error"));
|
|
2370
|
+
console.log("");
|
|
2371
|
+
console.log(chalk5.red(error.toUserMessage()));
|
|
2372
|
+
console.log("");
|
|
2373
|
+
return;
|
|
2374
|
+
}
|
|
2375
|
+
console.log("");
|
|
2376
|
+
console.log(chalk5.red(`[ERROR] ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
2377
|
+
console.log("");
|
|
2378
|
+
}
|
|
2379
|
+
});
|
|
2102
2380
|
|
|
2103
2381
|
// src/commands/http.ts
|
|
2104
2382
|
init_esm_shims();
|
|
@@ -2158,8 +2436,48 @@ async function executeRequest(method, url, options) {
|
|
|
2158
2436
|
}
|
|
2159
2437
|
const fullUrl = buildUrl2(url, options.baseUrl);
|
|
2160
2438
|
const customHeaders = parseHeaders(options.headers);
|
|
2161
|
-
const client = getClient();
|
|
2162
2439
|
const requestData = options.data ? JSON.parse(options.data) : void 0;
|
|
2440
|
+
const isYstRequest = fullUrl.includes("/yst-");
|
|
2441
|
+
if (isYstRequest) {
|
|
2442
|
+
const ystAccessToken = await getYstAccessToken();
|
|
2443
|
+
if (!ystAccessToken) {
|
|
2444
|
+
spinner.fail("YST token not available");
|
|
2445
|
+
console.error(chalk6.red("YST token not found. Please re-login: wukong-cli auth login"));
|
|
2446
|
+
process.exit(1);
|
|
2447
|
+
}
|
|
2448
|
+
spinner.text = `${method} ${chalk6.cyan(fullUrl)} (using YST token)`;
|
|
2449
|
+
const startTime2 = Date.now();
|
|
2450
|
+
const fetchOptions = {
|
|
2451
|
+
method: method.toUpperCase(),
|
|
2452
|
+
headers: {
|
|
2453
|
+
"Authorization": `Bearer ${ystAccessToken}`,
|
|
2454
|
+
"Content-Type": "application/json",
|
|
2455
|
+
...customHeaders
|
|
2456
|
+
}
|
|
2457
|
+
};
|
|
2458
|
+
if (requestData) {
|
|
2459
|
+
fetchOptions.body = JSON.stringify(requestData);
|
|
2460
|
+
}
|
|
2461
|
+
const response = await fetch(fullUrl + parseParams(options.params), fetchOptions);
|
|
2462
|
+
const duration2 = Date.now() - startTime2;
|
|
2463
|
+
if (!response.ok) {
|
|
2464
|
+
const errText = await response.text().catch(() => "");
|
|
2465
|
+
spinner.fail(`Request failed (${response.status})`);
|
|
2466
|
+
console.error(chalk6.red(`HTTP ${response.status}: ${errText.substring(0, 200)}`));
|
|
2467
|
+
process.exit(1);
|
|
2468
|
+
}
|
|
2469
|
+
const data2 = await response.json();
|
|
2470
|
+
spinner.succeed("Response received");
|
|
2471
|
+
console.log("");
|
|
2472
|
+
console.log(chalk6.dim("Status:"), `${response.status} ${response.statusText}`);
|
|
2473
|
+
console.log(chalk6.dim("Token:"), "YST");
|
|
2474
|
+
console.log(chalk6.dim("Duration:"), `${duration2}ms`);
|
|
2475
|
+
console.log("");
|
|
2476
|
+
console.log(chalk6.dim("Response:"));
|
|
2477
|
+
console.log(JSON.stringify(data2, null, 2));
|
|
2478
|
+
return;
|
|
2479
|
+
}
|
|
2480
|
+
const client = getClient();
|
|
2163
2481
|
spinner.text = `${method} ${chalk6.cyan(fullUrl)}`;
|
|
2164
2482
|
const startTime = Date.now();
|
|
2165
2483
|
let data;
|
|
@@ -2300,6 +2618,7 @@ import { Command as Command4 } from "commander";
|
|
|
2300
2618
|
// src/core/update/npm-updater.ts
|
|
2301
2619
|
init_esm_shims();
|
|
2302
2620
|
import { spawn } from "child_process";
|
|
2621
|
+
import { platform } from "process";
|
|
2303
2622
|
var UpdateExecutionError = class extends Error {
|
|
2304
2623
|
constructor(message, exitCode = null) {
|
|
2305
2624
|
super(message);
|
|
@@ -2311,12 +2630,15 @@ var NpmUpdater = class {
|
|
|
2311
2630
|
constructor(spawnFn = spawn) {
|
|
2312
2631
|
this.spawnFn = spawnFn;
|
|
2313
2632
|
}
|
|
2633
|
+
getSpawnOptions() {
|
|
2634
|
+
return platform === "win32" ? { shell: true, stdio: ["ignore", "pipe", "pipe"] } : { stdio: ["ignore", "pipe", "pipe"] };
|
|
2635
|
+
}
|
|
2314
2636
|
updateToLatest() {
|
|
2315
2637
|
return new Promise((resolve, reject) => {
|
|
2316
2638
|
const child = this.spawnFn(
|
|
2317
2639
|
"npm",
|
|
2318
2640
|
["install", "-g", "@zrhsh/wukong-cli@latest"],
|
|
2319
|
-
|
|
2641
|
+
this.getSpawnOptions()
|
|
2320
2642
|
);
|
|
2321
2643
|
child.stdout?.pipe(process.stdout);
|
|
2322
2644
|
child.stderr?.pipe(process.stderr);
|
|
@@ -2387,7 +2709,7 @@ async function runUpdateCommand({
|
|
|
2387
2709
|
}
|
|
2388
2710
|
var updateCommand = new Command4("update").description("Update wukong-cli to the latest npm version").action(async () => {
|
|
2389
2711
|
const exitCode = await runUpdateCommand({
|
|
2390
|
-
currentVersion: "0.4.
|
|
2712
|
+
currentVersion: "0.4.14",
|
|
2391
2713
|
versionProvider: new NpmVersionProvider(
|
|
2392
2714
|
"@zrhsh/wukong-cli",
|
|
2393
2715
|
"https://registry.npmjs.org"
|
|
@@ -2402,7 +2724,7 @@ var updateCommand = new Command4("update").description("Update wukong-cli to the
|
|
|
2402
2724
|
|
|
2403
2725
|
// src/cli.ts
|
|
2404
2726
|
var program = new Command5();
|
|
2405
|
-
program.name("wukong-cli").description("Wukong CLI - TypeScript implementation").version("0.4.
|
|
2727
|
+
program.name("wukong-cli").description("Wukong CLI - TypeScript implementation").version("0.4.14").option("--debug", "Enable debug mode (show HTTP requests)").hook("preAction", (thisCommand) => {
|
|
2406
2728
|
const options = thisCommand.opts();
|
|
2407
2729
|
if (options.debug === true) {
|
|
2408
2730
|
setDebugMode(true, true);
|
|
@@ -2420,7 +2742,7 @@ if (process.argv.length === 2) {
|
|
|
2420
2742
|
program.parse();
|
|
2421
2743
|
setImmediate(() => {
|
|
2422
2744
|
try {
|
|
2423
|
-
const versionChecker = getVersionChecker("0.4.
|
|
2745
|
+
const versionChecker = getVersionChecker("0.4.14");
|
|
2424
2746
|
const notifier = new ConsoleNotifier();
|
|
2425
2747
|
versionChecker.checkInBackground(notifier).catch(() => {
|
|
2426
2748
|
});
|