fogact 1.1.6 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/frontend/assets/market-ui.css +152 -29
- package/frontend/index.html +31 -7
- package/lib/index.js +120 -0
- package/lib/services/cliproxy-api.js +1 -1
- package/lib/services/newapi.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,8 @@ That is the user-facing command. Running it opens the interactive menu:
|
|
|
27
27
|
|
|
28
28
|
Do not run `npm fogact`; npm treats that as an npm subcommand. Use `npx fogact`.
|
|
29
29
|
|
|
30
|
+
FogAct checks npm for the latest version before opening the menu. If an older installed version is detected, it updates first and then continues. Set `FOGACT_SKIP_UPDATE=1` to skip this check.
|
|
31
|
+
|
|
30
32
|
## Clean VPS
|
|
31
33
|
|
|
32
34
|
If the machine does not have Node.js/npm yet, use the bootstrap installer first:
|
package/README.zh-CN.md
CHANGED
|
@@ -731,6 +731,35 @@ body.market-dark .market-auth-card::before {
|
|
|
731
731
|
color: var(--market-primary);
|
|
732
732
|
}
|
|
733
733
|
|
|
734
|
+
.market-quick-links {
|
|
735
|
+
display: grid;
|
|
736
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
737
|
+
gap: 8px;
|
|
738
|
+
margin-top: 16px;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
.market-quick-links a {
|
|
742
|
+
display: inline-flex;
|
|
743
|
+
align-items: center;
|
|
744
|
+
justify-content: center;
|
|
745
|
+
min-height: 36px;
|
|
746
|
+
border: 1px solid var(--market-line);
|
|
747
|
+
border-radius: 14px;
|
|
748
|
+
color: var(--market-ink);
|
|
749
|
+
background: var(--market-panel-muted);
|
|
750
|
+
text-decoration: none;
|
|
751
|
+
font-size: 13px;
|
|
752
|
+
font-weight: 800;
|
|
753
|
+
transition: transform 0.18s ease, border-color 0.18s ease, background 0.18s ease, color 0.18s ease;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
.market-quick-links a:hover {
|
|
757
|
+
transform: translateY(-1px);
|
|
758
|
+
border-color: color-mix(in srgb, var(--market-primary) 42%, var(--market-line));
|
|
759
|
+
color: var(--market-primary);
|
|
760
|
+
background: color-mix(in srgb, var(--market-primary) 10%, var(--market-panel-muted));
|
|
761
|
+
}
|
|
762
|
+
|
|
734
763
|
.market-result-list {
|
|
735
764
|
display: grid;
|
|
736
765
|
gap: 10px;
|
|
@@ -1190,7 +1219,7 @@ body.market-user {
|
|
|
1190
1219
|
width: min(48vw, 440px);
|
|
1191
1220
|
height: min(48vw, 440px);
|
|
1192
1221
|
pointer-events: none;
|
|
1193
|
-
opacity: 0.
|
|
1222
|
+
opacity: 0.98;
|
|
1194
1223
|
}
|
|
1195
1224
|
|
|
1196
1225
|
.market-orbit-stage::before,
|
|
@@ -1200,69 +1229,139 @@ body.market-user {
|
|
|
1200
1229
|
inset: 12%;
|
|
1201
1230
|
border: 1px solid color-mix(in srgb, var(--market-ink) 12%, transparent);
|
|
1202
1231
|
border-radius: 999px;
|
|
1203
|
-
|
|
1232
|
+
background:
|
|
1233
|
+
radial-gradient(circle at center, color-mix(in srgb, var(--market-primary) 7%, transparent), transparent 62%);
|
|
1234
|
+
animation: orbitSpin 22s linear infinite;
|
|
1204
1235
|
}
|
|
1205
1236
|
|
|
1206
1237
|
.market-orbit-stage::after {
|
|
1207
1238
|
inset: 25%;
|
|
1208
1239
|
border-style: dashed;
|
|
1209
|
-
animation-duration:
|
|
1240
|
+
animation-duration: 16s;
|
|
1210
1241
|
animation-direction: reverse;
|
|
1211
1242
|
opacity: 0.72;
|
|
1212
1243
|
}
|
|
1213
1244
|
|
|
1214
|
-
.market-orbit-
|
|
1245
|
+
.market-orbit-core {
|
|
1215
1246
|
position: absolute;
|
|
1247
|
+
left: 50%;
|
|
1248
|
+
top: 50%;
|
|
1249
|
+
z-index: 2;
|
|
1250
|
+
display: grid;
|
|
1251
|
+
place-items: center;
|
|
1252
|
+
width: 132px;
|
|
1253
|
+
height: 132px;
|
|
1254
|
+
padding: 18px;
|
|
1255
|
+
border: 1px solid color-mix(in srgb, var(--market-primary) 30%, var(--market-line));
|
|
1256
|
+
border-radius: 36px;
|
|
1257
|
+
color: var(--market-ink);
|
|
1258
|
+
background:
|
|
1259
|
+
linear-gradient(145deg, color-mix(in srgb, var(--market-panel-strong) 92%, transparent), var(--market-panel-muted)),
|
|
1260
|
+
radial-gradient(circle at 30% 20%, color-mix(in srgb, var(--market-primary) 24%, transparent), transparent 58%);
|
|
1261
|
+
box-shadow: 0 24px 60px color-mix(in srgb, var(--market-primary) 20%, transparent);
|
|
1262
|
+
transform: translate(-50%, -50%) rotate(-2deg);
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
.market-orbit-core .material-symbols-outlined {
|
|
1216
1266
|
display: inline-flex;
|
|
1217
1267
|
align-items: center;
|
|
1218
1268
|
justify-content: center;
|
|
1219
|
-
width:
|
|
1220
|
-
height:
|
|
1221
|
-
border:
|
|
1222
|
-
border-radius: 24px;
|
|
1269
|
+
width: 42px;
|
|
1270
|
+
height: 42px;
|
|
1271
|
+
border-radius: 16px;
|
|
1223
1272
|
color: #fff;
|
|
1224
|
-
background: linear-gradient(135deg, var(--
|
|
1225
|
-
box-shadow: 0
|
|
1226
|
-
|
|
1273
|
+
background: linear-gradient(135deg, var(--market-primary), var(--market-primary-2));
|
|
1274
|
+
box-shadow: 0 14px 32px color-mix(in srgb, var(--market-primary) 28%, transparent);
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
.market-orbit-core strong {
|
|
1278
|
+
margin-top: 8px;
|
|
1279
|
+
font-family: var(--market-headline);
|
|
1280
|
+
font-size: 18px;
|
|
1281
|
+
letter-spacing: -0.04em;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
.market-orbit-core small {
|
|
1285
|
+
color: var(--market-muted);
|
|
1286
|
+
font-size: 12px;
|
|
1287
|
+
font-weight: 800;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
.market-orbit-node {
|
|
1291
|
+
position: absolute;
|
|
1292
|
+
z-index: 3;
|
|
1293
|
+
display: inline-flex;
|
|
1294
|
+
align-items: center;
|
|
1295
|
+
gap: 8px;
|
|
1296
|
+
min-width: 118px;
|
|
1297
|
+
min-height: 54px;
|
|
1298
|
+
padding: 10px 12px;
|
|
1299
|
+
border: 1px solid color-mix(in srgb, var(--node-a, var(--market-primary)) 30%, var(--market-line));
|
|
1300
|
+
border-radius: 20px;
|
|
1301
|
+
color: var(--market-ink);
|
|
1302
|
+
background:
|
|
1303
|
+
linear-gradient(145deg, color-mix(in srgb, var(--market-panel-strong) 94%, transparent), var(--market-panel-muted)),
|
|
1304
|
+
radial-gradient(circle at 15% 0%, color-mix(in srgb, var(--node-a, var(--market-primary)) 24%, transparent), transparent 64%);
|
|
1305
|
+
box-shadow: 0 18px 44px color-mix(in srgb, var(--node-a, var(--market-primary)) 18%, transparent);
|
|
1227
1306
|
transform: translate3d(0, 0, 0) rotate(var(--tilt, 0deg));
|
|
1228
1307
|
animation: nodeFloat var(--speed, 6s) ease-in-out infinite;
|
|
1229
1308
|
}
|
|
1230
1309
|
|
|
1231
|
-
.market-orbit-node
|
|
1310
|
+
.market-orbit-node .material-symbols-outlined {
|
|
1311
|
+
display: inline-flex;
|
|
1312
|
+
align-items: center;
|
|
1313
|
+
justify-content: center;
|
|
1314
|
+
flex: 0 0 auto;
|
|
1315
|
+
width: 32px;
|
|
1316
|
+
height: 32px;
|
|
1317
|
+
border-radius: 13px;
|
|
1318
|
+
color: #fff;
|
|
1319
|
+
background: linear-gradient(135deg, var(--node-a, var(--market-primary)), var(--node-b, var(--market-primary-2)));
|
|
1320
|
+
font-size: 18px;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
.market-orbit-node span:last-child {
|
|
1324
|
+
color: var(--market-ink);
|
|
1325
|
+
font-size: 13px;
|
|
1326
|
+
font-weight: 900;
|
|
1327
|
+
white-space: nowrap;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
.market-orbit-node-cli {
|
|
1232
1331
|
--node-a: #6d5dfc;
|
|
1233
1332
|
--node-b: #b86bff;
|
|
1234
|
-
--tilt: -
|
|
1333
|
+
--tilt: -8deg;
|
|
1235
1334
|
--speed: 6.5s;
|
|
1236
|
-
left:
|
|
1335
|
+
left: 1%;
|
|
1237
1336
|
top: 18%;
|
|
1238
1337
|
}
|
|
1239
1338
|
|
|
1240
|
-
.market-orbit-node
|
|
1339
|
+
.market-orbit-node-cdk {
|
|
1241
1340
|
--node-a: #ff7a59;
|
|
1242
1341
|
--node-b: #ffd166;
|
|
1243
|
-
--tilt:
|
|
1342
|
+
--tilt: 7deg;
|
|
1244
1343
|
--speed: 7.5s;
|
|
1245
|
-
right:
|
|
1246
|
-
top:
|
|
1344
|
+
right: 2%;
|
|
1345
|
+
top: 9%;
|
|
1247
1346
|
animation-delay: -1.8s;
|
|
1248
1347
|
}
|
|
1249
1348
|
|
|
1250
|
-
.market-orbit-node
|
|
1349
|
+
.market-orbit-node-quota {
|
|
1251
1350
|
--node-a: #17c3b2;
|
|
1252
1351
|
--node-b: #5eead4;
|
|
1253
|
-
--tilt:
|
|
1352
|
+
--tilt: 8deg;
|
|
1254
1353
|
--speed: 8s;
|
|
1255
|
-
right:
|
|
1256
|
-
bottom:
|
|
1354
|
+
right: 0;
|
|
1355
|
+
bottom: 20%;
|
|
1257
1356
|
animation-delay: -3s;
|
|
1258
1357
|
}
|
|
1259
1358
|
|
|
1260
|
-
.market-orbit-node
|
|
1261
|
-
--node-a: #
|
|
1359
|
+
.market-orbit-node-sync {
|
|
1360
|
+
--node-a: #111827;
|
|
1262
1361
|
--node-b: #6d5dfc;
|
|
1263
|
-
--tilt: -
|
|
1362
|
+
--tilt: -7deg;
|
|
1264
1363
|
--speed: 7s;
|
|
1265
|
-
left:
|
|
1364
|
+
left: 7%;
|
|
1266
1365
|
bottom: 8%;
|
|
1267
1366
|
animation-delay: -4.3s;
|
|
1268
1367
|
}
|
|
@@ -1279,6 +1378,11 @@ body.market-user {
|
|
|
1279
1378
|
overflow: hidden;
|
|
1280
1379
|
}
|
|
1281
1380
|
|
|
1381
|
+
.market-signal-line-alt {
|
|
1382
|
+
transform: rotate(36deg);
|
|
1383
|
+
opacity: 0.42;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1282
1386
|
.market-signal-line::after {
|
|
1283
1387
|
content: "";
|
|
1284
1388
|
position: absolute;
|
|
@@ -1288,6 +1392,10 @@ body.market-user {
|
|
|
1288
1392
|
animation: signalSweep 2.6s cubic-bezier(0.16, 1, 0.3, 1) infinite;
|
|
1289
1393
|
}
|
|
1290
1394
|
|
|
1395
|
+
.market-signal-line-alt::after {
|
|
1396
|
+
animation-delay: -1.1s;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1291
1399
|
.market-card-lab {
|
|
1292
1400
|
min-height: 318px;
|
|
1293
1401
|
padding: 0;
|
|
@@ -1880,11 +1988,26 @@ body.is-pointer-active .market-mouse-light {
|
|
|
1880
1988
|
height: 240px;
|
|
1881
1989
|
}
|
|
1882
1990
|
|
|
1991
|
+
.market-orbit-core {
|
|
1992
|
+
width: 104px;
|
|
1993
|
+
height: 104px;
|
|
1994
|
+
border-radius: 28px;
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
.market-orbit-core strong {
|
|
1998
|
+
font-size: 16px;
|
|
1999
|
+
}
|
|
2000
|
+
|
|
1883
2001
|
.market-orbit-node {
|
|
1884
|
-
width: 58px;
|
|
1885
|
-
height: 58px;
|
|
2002
|
+
min-width: 58px;
|
|
2003
|
+
min-height: 58px;
|
|
2004
|
+
padding: 8px;
|
|
1886
2005
|
border-radius: 20px;
|
|
1887
|
-
|
|
2006
|
+
justify-content: center;
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
.market-orbit-node span:last-child {
|
|
2010
|
+
display: none;
|
|
1888
2011
|
}
|
|
1889
2012
|
|
|
1890
2013
|
.market-mouse-light {
|
package/frontend/index.html
CHANGED
|
@@ -73,12 +73,30 @@
|
|
|
73
73
|
<span class="market-ambient-item"><span class="material-symbols-outlined">query_stats</span></span>
|
|
74
74
|
</div>
|
|
75
75
|
|
|
76
|
-
<div class="market-orbit-stage" aria-
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
<div class="market-orbit-stage" aria-label="FogAct 服务流程拓扑">
|
|
77
|
+
<div class="market-orbit-core">
|
|
78
|
+
<span class="material-symbols-outlined">hub</span>
|
|
79
|
+
<strong>FogAct</strong>
|
|
80
|
+
<small>统一入口</small>
|
|
81
|
+
</div>
|
|
82
|
+
<span class="market-orbit-node market-orbit-node-cli">
|
|
83
|
+
<span class="material-symbols-outlined">terminal</span>
|
|
84
|
+
<span>CLI 接入</span>
|
|
85
|
+
</span>
|
|
86
|
+
<span class="market-orbit-node market-orbit-node-cdk">
|
|
87
|
+
<span class="material-symbols-outlined">vpn_key</span>
|
|
88
|
+
<span>CDK 校验</span>
|
|
89
|
+
</span>
|
|
90
|
+
<span class="market-orbit-node market-orbit-node-quota">
|
|
91
|
+
<span class="material-symbols-outlined">monitoring</span>
|
|
92
|
+
<span>配额监控</span>
|
|
93
|
+
</span>
|
|
94
|
+
<span class="market-orbit-node market-orbit-node-sync">
|
|
95
|
+
<span class="material-symbols-outlined">cloud_sync</span>
|
|
96
|
+
<span>上游同步</span>
|
|
97
|
+
</span>
|
|
98
|
+
<span class="market-signal-line market-signal-line-main"></span>
|
|
99
|
+
<span class="market-signal-line market-signal-line-alt"></span>
|
|
82
100
|
</div>
|
|
83
101
|
</div>
|
|
84
102
|
|
|
@@ -112,12 +130,18 @@
|
|
|
112
130
|
|
|
113
131
|
<div class="market-panel" style="border-radius: 26px; padding: 18px;">
|
|
114
132
|
<div class="market-card-footer">
|
|
115
|
-
<span class="market-tag"
|
|
133
|
+
<span class="market-tag">本地服务</span>
|
|
116
134
|
<span class="market-status-pill"><span class="market-kicker-dot"></span> 34020</span>
|
|
117
135
|
</div>
|
|
118
136
|
<p class="market-mini-copy" style="margin-top: 14px; font-size: 14px; line-height: 1.7;">
|
|
119
137
|
本地 Web 服务默认运行在 34020 端口,提供首页、用户中心、管理中心和激活入口。
|
|
120
138
|
</p>
|
|
139
|
+
<div class="market-quick-links" aria-label="本地服务快捷入口">
|
|
140
|
+
<a href="/">首页</a>
|
|
141
|
+
<a href="/user/">用户中心</a>
|
|
142
|
+
<a href="/admin/">管理中心</a>
|
|
143
|
+
<a href="/activate.html">激活入口</a>
|
|
144
|
+
</div>
|
|
121
145
|
</div>
|
|
122
146
|
</aside>
|
|
123
147
|
</section>
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
const https = require("https");
|
|
4
|
+
const { spawnSync } = require("child_process");
|
|
3
5
|
const { Command } = require("commander");
|
|
4
6
|
const prompts = require("prompts");
|
|
5
7
|
const packageJson = require("../package.json");
|
|
@@ -15,6 +17,120 @@ const MENU_CHOICES = [
|
|
|
15
17
|
{ title: "4. 退出", value: "exit" },
|
|
16
18
|
];
|
|
17
19
|
|
|
20
|
+
const UPDATE_TIMEOUT_MS = 2500;
|
|
21
|
+
|
|
22
|
+
function parseVersion(version) {
|
|
23
|
+
return String(version || "")
|
|
24
|
+
.split("-")[0]
|
|
25
|
+
.split(".")
|
|
26
|
+
.map((part) => Number.parseInt(part, 10) || 0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isNewerVersion(latest, current) {
|
|
30
|
+
const latestParts = parseVersion(latest);
|
|
31
|
+
const currentParts = parseVersion(current);
|
|
32
|
+
const length = Math.max(latestParts.length, currentParts.length);
|
|
33
|
+
for (let index = 0; index < length; index += 1) {
|
|
34
|
+
const latestPart = latestParts[index] || 0;
|
|
35
|
+
const currentPart = currentParts[index] || 0;
|
|
36
|
+
if (latestPart > currentPart) return true;
|
|
37
|
+
if (latestPart < currentPart) return false;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function fetchLatestVersion() {
|
|
43
|
+
return new Promise((resolve) => {
|
|
44
|
+
const request = https.get(
|
|
45
|
+
"https://registry.npmjs.org/fogact/latest",
|
|
46
|
+
{
|
|
47
|
+
timeout: UPDATE_TIMEOUT_MS,
|
|
48
|
+
headers: {
|
|
49
|
+
Accept: "application/json",
|
|
50
|
+
"User-Agent": `fogact/${packageJson.version}`,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
(response) => {
|
|
54
|
+
if (response.statusCode !== 200) {
|
|
55
|
+
response.resume();
|
|
56
|
+
resolve(null);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let body = "";
|
|
61
|
+
response.setEncoding("utf8");
|
|
62
|
+
response.on("data", (chunk) => {
|
|
63
|
+
body += chunk;
|
|
64
|
+
});
|
|
65
|
+
response.on("end", () => {
|
|
66
|
+
try {
|
|
67
|
+
const metadata = JSON.parse(body);
|
|
68
|
+
resolve(metadata.version || null);
|
|
69
|
+
} catch (_error) {
|
|
70
|
+
resolve(null);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
request.on("timeout", () => {
|
|
77
|
+
request.destroy();
|
|
78
|
+
resolve(null);
|
|
79
|
+
});
|
|
80
|
+
request.on("error", () => resolve(null));
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function isNpmExecRun() {
|
|
85
|
+
const argvPath = process.argv[1] || "";
|
|
86
|
+
const npmCommand = process.env.npm_command || "";
|
|
87
|
+
const npmExecPath = process.env.npm_execpath || "";
|
|
88
|
+
return argvPath.includes("/_npx/") || npmCommand === "exec" || npmCommand === "x" || npmExecPath.includes("npx-cli");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function runLatestWithNpmExec(latestVersion, args, env) {
|
|
92
|
+
return spawnSync(
|
|
93
|
+
"npm",
|
|
94
|
+
["exec", "--yes", "--package", `fogact@${latestVersion}`, "--", "fogact", ...args],
|
|
95
|
+
{ stdio: "inherit", env }
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function ensureLatestVersion(argv = process.argv) {
|
|
100
|
+
if (process.env.FOGACT_SKIP_UPDATE === "1" || process.env.FOGACT_NO_UPDATE === "1") {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const latestVersion = await fetchLatestVersion();
|
|
105
|
+
if (!latestVersion || !isNewerVersion(latestVersion, packageJson.version)) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const args = argv.slice(2);
|
|
110
|
+
const env = { ...process.env, FOGACT_SKIP_UPDATE: "1" };
|
|
111
|
+
console.log(`检测到新版本 v${latestVersion},正在自动更新...`);
|
|
112
|
+
|
|
113
|
+
if (isNpmExecRun()) {
|
|
114
|
+
const result = runLatestWithNpmExec(latestVersion, args, env);
|
|
115
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const update = spawnSync("npm", ["install", "-g", `fogact@${latestVersion}`], {
|
|
119
|
+
stdio: "inherit",
|
|
120
|
+
env,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (update.status === 0) {
|
|
124
|
+
console.log("更新完成,正在重新启动...");
|
|
125
|
+
const restart = spawnSync(process.execPath, argv.slice(1), { stdio: "inherit", env });
|
|
126
|
+
process.exit(restart.status === null ? 1 : restart.status);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log("自动更新失败,正在尝试直接运行最新版...");
|
|
130
|
+
const result = runLatestWithNpmExec(latestVersion, args, env);
|
|
131
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
132
|
+
}
|
|
133
|
+
|
|
18
134
|
function displayWidth(value) {
|
|
19
135
|
return Array.from(value).reduce((width, char) => {
|
|
20
136
|
return width + (char.charCodeAt(0) > 0xff ? 2 : 1);
|
|
@@ -230,6 +346,8 @@ function buildProgram() {
|
|
|
230
346
|
}
|
|
231
347
|
|
|
232
348
|
async function runCli(argv = process.argv) {
|
|
349
|
+
await ensureLatestVersion(argv);
|
|
350
|
+
|
|
233
351
|
const args = argv.slice(2).filter((arg) => arg !== "--help" && arg !== "-h");
|
|
234
352
|
|
|
235
353
|
if (args.length === 0) {
|
|
@@ -243,6 +361,8 @@ async function runCli(argv = process.argv) {
|
|
|
243
361
|
|
|
244
362
|
module.exports = {
|
|
245
363
|
buildProgram,
|
|
364
|
+
ensureLatestVersion,
|
|
365
|
+
isNewerVersion,
|
|
246
366
|
runCli,
|
|
247
367
|
runInteractiveMenu,
|
|
248
368
|
runToolsMenu,
|
package/lib/services/newapi.js
CHANGED