@zjex/git-workflow 0.2.19 → 0.2.20
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/index.js +317 -183
- package/package.json +4 -2
- package/src/commands/help.ts +3 -0
- package/src/commands/update.ts +43 -8
- package/src/index.ts +9 -1
- package/src/update-notifier.ts +122 -34
package/dist/index.js
CHANGED
|
@@ -1,31 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --no-warnings=ExperimentalWarning
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
7
11
|
|
|
8
12
|
// src/utils.ts
|
|
9
13
|
import { execSync } from "child_process";
|
|
10
|
-
var colors = {
|
|
11
|
-
red: (s) => `\x1B[31m${s}\x1B[0m`,
|
|
12
|
-
green: (s) => `\x1B[32m${s}\x1B[0m`,
|
|
13
|
-
yellow: (s) => `\x1B[33m${s}\x1B[0m`,
|
|
14
|
-
cyan: (s) => `\x1B[36m${s}\x1B[0m`,
|
|
15
|
-
dim: (s) => `\x1B[2m${s}\x1B[0m`,
|
|
16
|
-
bold: (s) => `\x1B[1m${s}\x1B[0m`,
|
|
17
|
-
reset: "\x1B[0m"
|
|
18
|
-
};
|
|
19
|
-
var TODAY = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "");
|
|
20
|
-
var theme = {
|
|
21
|
-
helpMode: "always",
|
|
22
|
-
style: {
|
|
23
|
-
keysHelpTip: (keys) => {
|
|
24
|
-
const tips = keys.map(([key, label]) => `${key} ${label}`).join(" \u2022 ");
|
|
25
|
-
return `\x1B[2m${tips} \u2022 Ctrl+C quit\x1B[0m`;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
14
|
function exec(cmd, silent = false) {
|
|
30
15
|
try {
|
|
31
16
|
const options = {
|
|
@@ -66,13 +51,267 @@ function getMainBranch() {
|
|
|
66
51
|
function divider() {
|
|
67
52
|
console.log(colors.dim("\u2500".repeat(40)));
|
|
68
53
|
}
|
|
54
|
+
var colors, TODAY, theme;
|
|
55
|
+
var init_utils = __esm({
|
|
56
|
+
"src/utils.ts"() {
|
|
57
|
+
"use strict";
|
|
58
|
+
colors = {
|
|
59
|
+
red: (s) => `\x1B[31m${s}\x1B[0m`,
|
|
60
|
+
green: (s) => `\x1B[32m${s}\x1B[0m`,
|
|
61
|
+
yellow: (s) => `\x1B[33m${s}\x1B[0m`,
|
|
62
|
+
cyan: (s) => `\x1B[36m${s}\x1B[0m`,
|
|
63
|
+
dim: (s) => `\x1B[2m${s}\x1B[0m`,
|
|
64
|
+
bold: (s) => `\x1B[1m${s}\x1B[0m`,
|
|
65
|
+
reset: "\x1B[0m"
|
|
66
|
+
};
|
|
67
|
+
TODAY = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "");
|
|
68
|
+
theme = {
|
|
69
|
+
helpMode: "always",
|
|
70
|
+
style: {
|
|
71
|
+
keysHelpTip: (keys) => {
|
|
72
|
+
const tips = keys.map(([key, label]) => `${key} ${label}`).join(" \u2022 ");
|
|
73
|
+
return `\x1B[2m${tips} \u2022 Ctrl+C quit\x1B[0m`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// src/update-notifier.ts
|
|
81
|
+
var update_notifier_exports = {};
|
|
82
|
+
__export(update_notifier_exports, {
|
|
83
|
+
checkForUpdates: () => checkForUpdates,
|
|
84
|
+
clearUpdateCache: () => clearUpdateCache
|
|
85
|
+
});
|
|
86
|
+
import { execSync as execSync6 } from "child_process";
|
|
87
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync3, unlinkSync } from "fs";
|
|
88
|
+
import { homedir as homedir3 } from "os";
|
|
89
|
+
import { join as join3 } from "path";
|
|
90
|
+
import boxen from "boxen";
|
|
91
|
+
import { select as select7 } from "@inquirer/prompts";
|
|
92
|
+
import ora5 from "ora";
|
|
93
|
+
import semver from "semver";
|
|
94
|
+
async function checkForUpdates(currentVersion, packageName = "@zjex/git-workflow", interactive = false) {
|
|
95
|
+
try {
|
|
96
|
+
const cache = readCache();
|
|
97
|
+
const now = Date.now();
|
|
98
|
+
if (cache?.latestVersion && cache.checkedVersion === currentVersion) {
|
|
99
|
+
if (cache.lastDismiss && now - cache.lastDismiss < DISMISS_INTERVAL) {
|
|
100
|
+
backgroundCheck(currentVersion, packageName);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (semver.gt(cache.latestVersion, currentVersion)) {
|
|
104
|
+
if (interactive) {
|
|
105
|
+
const action = await showUpdateMessage(
|
|
106
|
+
currentVersion,
|
|
107
|
+
cache.latestVersion,
|
|
108
|
+
packageName
|
|
109
|
+
);
|
|
110
|
+
if (action === "update") {
|
|
111
|
+
await performUpdate(packageName);
|
|
112
|
+
} else if (action === "dismiss") {
|
|
113
|
+
writeCache({ ...cache, lastDismiss: now });
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
showSimpleNotification(currentVersion, cache.latestVersion);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
backgroundCheck(currentVersion, packageName);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
if (error?.constructor?.name === "ExitPromptError") {
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function backgroundCheck(currentVersion, packageName) {
|
|
128
|
+
const cache = readCache();
|
|
129
|
+
const now = Date.now();
|
|
130
|
+
if (cache?.lastCheck && now - cache.lastCheck < CHECK_INTERVAL) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
Promise.resolve().then(async () => {
|
|
134
|
+
try {
|
|
135
|
+
const latestVersion = await getLatestVersion(packageName);
|
|
136
|
+
if (latestVersion) {
|
|
137
|
+
writeCache({
|
|
138
|
+
...cache,
|
|
139
|
+
lastCheck: now,
|
|
140
|
+
latestVersion,
|
|
141
|
+
checkedVersion: currentVersion
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
} catch {
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async function getLatestVersion(packageName) {
|
|
149
|
+
try {
|
|
150
|
+
const result = execSync6(`npm view ${packageName} version`, {
|
|
151
|
+
encoding: "utf-8",
|
|
152
|
+
timeout: 3e3,
|
|
153
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
154
|
+
// 忽略 stderr
|
|
155
|
+
});
|
|
156
|
+
return result.trim();
|
|
157
|
+
} catch {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function showSimpleNotification(current, latest) {
|
|
162
|
+
const message = `${colors.yellow("\u{1F389} \u53D1\u73B0\u65B0\u7248\u672C")} ${colors.dim(
|
|
163
|
+
current
|
|
164
|
+
)} \u2192 ${colors.green(latest)} ${colors.dim("\u8FD0\u884C")} ${colors.cyan(
|
|
165
|
+
"gw update"
|
|
166
|
+
)} ${colors.dim("\u66F4\u65B0")}`;
|
|
167
|
+
console.log("");
|
|
168
|
+
console.log(
|
|
169
|
+
boxen(message, {
|
|
170
|
+
padding: { top: 0, bottom: 0, left: 2, right: 2 },
|
|
171
|
+
margin: { top: 0, bottom: 1, left: 0, right: 0 },
|
|
172
|
+
borderStyle: "round",
|
|
173
|
+
borderColor: "yellow",
|
|
174
|
+
align: "center"
|
|
175
|
+
})
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
async function showUpdateMessage(current, latest, packageName) {
|
|
179
|
+
const message = [
|
|
180
|
+
colors.yellow(colors.bold("\u{1F389} \u53D1\u73B0\u65B0\u7248\u672C\uFF01")),
|
|
181
|
+
"",
|
|
182
|
+
`${colors.dim(current)} \u2192 ${colors.green(colors.bold(latest))}`
|
|
183
|
+
].join("\n");
|
|
184
|
+
console.log("");
|
|
185
|
+
console.log(
|
|
186
|
+
boxen(message, {
|
|
187
|
+
padding: { top: 1, bottom: 1, left: 3, right: 3 },
|
|
188
|
+
margin: 1,
|
|
189
|
+
borderStyle: "round",
|
|
190
|
+
borderColor: "yellow",
|
|
191
|
+
align: "center",
|
|
192
|
+
width: 40
|
|
193
|
+
})
|
|
194
|
+
);
|
|
195
|
+
try {
|
|
196
|
+
const action = await select7({
|
|
197
|
+
message: "\u4F60\u60F3\u505A\u4EC0\u4E48\uFF1F",
|
|
198
|
+
choices: [
|
|
199
|
+
{
|
|
200
|
+
name: "\u{1F680} \u7ACB\u5373\u66F4\u65B0",
|
|
201
|
+
value: "update",
|
|
202
|
+
description: `\u8FD0\u884C npm install -g ${packageName}`
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: "\u23ED\uFE0F \u7A0D\u540E\u66F4\u65B0\uFF0C\u7EE7\u7EED\u4F7F\u7528",
|
|
206
|
+
value: "continue",
|
|
207
|
+
description: "\u4E0B\u6B21\u542F\u52A8\u65F6\u4F1A\u518D\u6B21\u63D0\u793A"
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: "\u{1F648} \u8DF3\u8FC7\u6B64\u7248\u672C (24h \u5185\u4E0D\u518D\u63D0\u793A)",
|
|
211
|
+
value: "dismiss",
|
|
212
|
+
description: "24 \u5C0F\u65F6\u5185\u4E0D\u4F1A\u518D\u63D0\u793A\u6B64\u7248\u672C"
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
});
|
|
216
|
+
return action;
|
|
217
|
+
} catch (error) {
|
|
218
|
+
console.log("");
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
async function performUpdate(packageName) {
|
|
223
|
+
console.log("");
|
|
224
|
+
const spinner = ora5({
|
|
225
|
+
text: "\u6B63\u5728\u66F4\u65B0...",
|
|
226
|
+
spinner: "dots"
|
|
227
|
+
}).start();
|
|
228
|
+
try {
|
|
229
|
+
execSync6(`npm install -g ${packageName}@latest`, {
|
|
230
|
+
encoding: "utf-8",
|
|
231
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
232
|
+
});
|
|
233
|
+
spinner.succeed(colors.green("\u66F4\u65B0\u6210\u529F\uFF01"));
|
|
234
|
+
clearUpdateCache();
|
|
235
|
+
console.log("");
|
|
236
|
+
console.log(
|
|
237
|
+
boxen(
|
|
238
|
+
[
|
|
239
|
+
colors.green(colors.bold("\u2728 \u66F4\u65B0\u5B8C\u6210\uFF01")),
|
|
240
|
+
"",
|
|
241
|
+
colors.dim("\u8BF7\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF\u4F7F\u7528\u65B0\u7248\u672C")
|
|
242
|
+
].join("\n"),
|
|
243
|
+
{
|
|
244
|
+
padding: { top: 1, bottom: 1, left: 3, right: 3 },
|
|
245
|
+
margin: { top: 0, bottom: 1, left: 2, right: 2 },
|
|
246
|
+
borderStyle: "round",
|
|
247
|
+
borderColor: "green",
|
|
248
|
+
align: "center",
|
|
249
|
+
width: 40
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
);
|
|
253
|
+
process.exit(0);
|
|
254
|
+
} catch (error) {
|
|
255
|
+
spinner.fail(colors.red("\u66F4\u65B0\u5931\u8D25"));
|
|
256
|
+
console.log("");
|
|
257
|
+
console.log(colors.dim(" \u4F60\u53EF\u4EE5\u624B\u52A8\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u66F4\u65B0:"));
|
|
258
|
+
console.log(colors.cyan(` npm install -g ${packageName}@latest`));
|
|
259
|
+
console.log("");
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function clearUpdateCache() {
|
|
263
|
+
try {
|
|
264
|
+
const cacheFile = join3(homedir3(), CACHE_FILE);
|
|
265
|
+
if (existsSync3(cacheFile)) {
|
|
266
|
+
unlinkSync(cacheFile);
|
|
267
|
+
}
|
|
268
|
+
} catch {
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function readCache() {
|
|
272
|
+
try {
|
|
273
|
+
const cacheFile = join3(homedir3(), CACHE_FILE);
|
|
274
|
+
if (!existsSync3(cacheFile)) {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
const content = readFileSync3(cacheFile, "utf-8");
|
|
278
|
+
return JSON.parse(content);
|
|
279
|
+
} catch {
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function writeCache(cache) {
|
|
284
|
+
try {
|
|
285
|
+
const cacheFile = join3(homedir3(), CACHE_FILE);
|
|
286
|
+
writeFileSync3(cacheFile, JSON.stringify(cache), "utf-8");
|
|
287
|
+
} catch {
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
var CHECK_INTERVAL, DISMISS_INTERVAL, CACHE_FILE;
|
|
291
|
+
var init_update_notifier = __esm({
|
|
292
|
+
"src/update-notifier.ts"() {
|
|
293
|
+
"use strict";
|
|
294
|
+
init_utils();
|
|
295
|
+
CHECK_INTERVAL = 1e3 * 60 * 60 * 4;
|
|
296
|
+
DISMISS_INTERVAL = 1e3 * 60 * 60 * 24;
|
|
297
|
+
CACHE_FILE = ".gw-update-check";
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// src/index.ts
|
|
302
|
+
init_utils();
|
|
303
|
+
import { cac } from "cac";
|
|
304
|
+
import { select as select8 } from "@inquirer/prompts";
|
|
305
|
+
import { ExitPromptError } from "@inquirer/core";
|
|
69
306
|
|
|
70
307
|
// src/commands/branch.ts
|
|
308
|
+
init_utils();
|
|
71
309
|
import { execSync as execSync2 } from "child_process";
|
|
72
310
|
import { select, input } from "@inquirer/prompts";
|
|
73
311
|
import ora from "ora";
|
|
74
312
|
|
|
75
313
|
// src/config.ts
|
|
314
|
+
init_utils();
|
|
76
315
|
import { existsSync, readFileSync } from "fs";
|
|
77
316
|
import { join } from "path";
|
|
78
317
|
import { homedir } from "os";
|
|
@@ -392,6 +631,7 @@ async function deleteBranch(branchArg) {
|
|
|
392
631
|
}
|
|
393
632
|
|
|
394
633
|
// src/commands/tag.ts
|
|
634
|
+
init_utils();
|
|
395
635
|
import { execSync as execSync3 } from "child_process";
|
|
396
636
|
import { select as select2, input as input2 } from "@inquirer/prompts";
|
|
397
637
|
import ora2 from "ora";
|
|
@@ -790,6 +1030,7 @@ async function updateTag() {
|
|
|
790
1030
|
}
|
|
791
1031
|
|
|
792
1032
|
// src/commands/release.ts
|
|
1033
|
+
init_utils();
|
|
793
1034
|
import { readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
794
1035
|
import { select as select3 } from "@inquirer/prompts";
|
|
795
1036
|
function getPackageVersion() {
|
|
@@ -888,6 +1129,7 @@ async function release() {
|
|
|
888
1129
|
}
|
|
889
1130
|
|
|
890
1131
|
// src/commands/init.ts
|
|
1132
|
+
init_utils();
|
|
891
1133
|
import { existsSync as existsSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
892
1134
|
import { join as join2 } from "path";
|
|
893
1135
|
import { homedir as homedir2 } from "os";
|
|
@@ -1172,6 +1414,7 @@ async function init() {
|
|
|
1172
1414
|
}
|
|
1173
1415
|
|
|
1174
1416
|
// src/commands/stash.ts
|
|
1417
|
+
init_utils();
|
|
1175
1418
|
import { execSync as execSync4 } from "child_process";
|
|
1176
1419
|
import { select as select5, input as input4 } from "@inquirer/prompts";
|
|
1177
1420
|
import ora3 from "ora";
|
|
@@ -1406,11 +1649,13 @@ async function dropStash(index) {
|
|
|
1406
1649
|
}
|
|
1407
1650
|
|
|
1408
1651
|
// src/commands/commit.ts
|
|
1652
|
+
init_utils();
|
|
1409
1653
|
import { execSync as execSync5 } from "child_process";
|
|
1410
1654
|
import { select as select6, input as input5, checkbox } from "@inquirer/prompts";
|
|
1411
1655
|
import ora4 from "ora";
|
|
1412
1656
|
|
|
1413
1657
|
// src/ai-service.ts
|
|
1658
|
+
init_utils();
|
|
1414
1659
|
var AI_PROVIDERS = {
|
|
1415
1660
|
github: {
|
|
1416
1661
|
name: "GitHub Models",
|
|
@@ -1890,6 +2135,7 @@ ${issues}`;
|
|
|
1890
2135
|
}
|
|
1891
2136
|
|
|
1892
2137
|
// src/commands/help.ts
|
|
2138
|
+
init_utils();
|
|
1893
2139
|
function showHelp() {
|
|
1894
2140
|
return `
|
|
1895
2141
|
\u5206\u652F\u547D\u4EE4:
|
|
@@ -1932,6 +2178,9 @@ Tag \u547D\u4EE4:
|
|
|
1932
2178
|
gw update \u68C0\u67E5\u5E76\u66F4\u65B0\u5230\u6700\u65B0\u7248\u672C
|
|
1933
2179
|
gw upt \u540C\u4E0A (\u522B\u540D)
|
|
1934
2180
|
|
|
2181
|
+
\u6E05\u7406\u547D\u4EE4:
|
|
2182
|
+
gw clean \u6E05\u7406\u7F13\u5B58\u6587\u4EF6
|
|
2183
|
+
|
|
1935
2184
|
Stash \u547D\u4EE4:
|
|
1936
2185
|
gw stash \u4EA4\u4E92\u5F0F\u7BA1\u7406 stash
|
|
1937
2186
|
gw s \u540C\u4E0A (\u522B\u540D)
|
|
@@ -1962,160 +2211,28 @@ Commit \u547D\u4EE4:
|
|
|
1962
2211
|
`;
|
|
1963
2212
|
}
|
|
1964
2213
|
|
|
1965
|
-
// src/
|
|
1966
|
-
|
|
1967
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync3 } from "fs";
|
|
1968
|
-
import { homedir as homedir3 } from "os";
|
|
1969
|
-
import { join as join3 } from "path";
|
|
1970
|
-
import boxen from "boxen";
|
|
1971
|
-
import { select as select7 } from "@inquirer/prompts";
|
|
1972
|
-
import ora5 from "ora";
|
|
1973
|
-
var DISMISS_INTERVAL = 1e3 * 60 * 60 * 24;
|
|
1974
|
-
var CACHE_FILE = ".gw-update-check";
|
|
1975
|
-
async function checkForUpdates(currentVersion, packageName = "@zjex/git-workflow") {
|
|
1976
|
-
try {
|
|
1977
|
-
const cache = readCache();
|
|
1978
|
-
const now = Date.now();
|
|
1979
|
-
if (cache?.lastDismiss && now - cache.lastDismiss < DISMISS_INTERVAL) {
|
|
1980
|
-
return;
|
|
1981
|
-
}
|
|
1982
|
-
const latestVersion = await getLatestVersion(packageName);
|
|
1983
|
-
if (latestVersion && latestVersion !== currentVersion) {
|
|
1984
|
-
const action = await showUpdateMessage(
|
|
1985
|
-
currentVersion,
|
|
1986
|
-
latestVersion,
|
|
1987
|
-
packageName
|
|
1988
|
-
);
|
|
1989
|
-
if (action === "update") {
|
|
1990
|
-
await performUpdate(packageName);
|
|
1991
|
-
} else if (action === "dismiss") {
|
|
1992
|
-
writeCache({ lastDismiss: now, latestVersion });
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
} catch (error) {
|
|
1996
|
-
if (error?.constructor?.name === "ExitPromptError") {
|
|
1997
|
-
throw error;
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
async function getLatestVersion(packageName) {
|
|
2002
|
-
try {
|
|
2003
|
-
const result = execSync6(`npm view ${packageName} version`, {
|
|
2004
|
-
encoding: "utf-8",
|
|
2005
|
-
timeout: 3e3,
|
|
2006
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
2007
|
-
// 忽略 stderr
|
|
2008
|
-
});
|
|
2009
|
-
return result.trim();
|
|
2010
|
-
} catch {
|
|
2011
|
-
return null;
|
|
2012
|
-
}
|
|
2013
|
-
}
|
|
2014
|
-
async function showUpdateMessage(current, latest, packageName) {
|
|
2015
|
-
const message = [
|
|
2016
|
-
colors.bold("\uFFFD \u53D1\u73B0\u65B0\u7248\u65B0\u672C\u53EF\u7528\uFF01"),
|
|
2017
|
-
"",
|
|
2018
|
-
`${colors.dim(current)} \u2192 ${colors.green(colors.bold(latest))}`
|
|
2019
|
-
].join("\n");
|
|
2020
|
-
console.log("");
|
|
2021
|
-
console.log(
|
|
2022
|
-
boxen(message, {
|
|
2023
|
-
padding: 1,
|
|
2024
|
-
margin: 1,
|
|
2025
|
-
borderStyle: "round",
|
|
2026
|
-
borderColor: "yellow",
|
|
2027
|
-
align: "left"
|
|
2028
|
-
})
|
|
2029
|
-
);
|
|
2030
|
-
try {
|
|
2031
|
-
const action = await select7({
|
|
2032
|
-
message: "\u4F60\u60F3\u505A\u4EC0\u4E48\uFF1F",
|
|
2033
|
-
choices: [
|
|
2034
|
-
{
|
|
2035
|
-
name: "\u{1F680} \u7ACB\u5373\u66F4\u65B0",
|
|
2036
|
-
value: "update",
|
|
2037
|
-
description: `\u8FD0\u884C npm install -g ${packageName}`
|
|
2038
|
-
},
|
|
2039
|
-
{
|
|
2040
|
-
name: "\u23ED\uFE0F \u7A0D\u540E\u66F4\u65B0\uFF0C\u7EE7\u7EED\u4F7F\u7528",
|
|
2041
|
-
value: "continue",
|
|
2042
|
-
description: "\u4E0B\u6B21\u542F\u52A8\u65F6\u4F1A\u518D\u6B21\u63D0\u793A"
|
|
2043
|
-
},
|
|
2044
|
-
{
|
|
2045
|
-
name: "\u{1F648} \u8DF3\u8FC7\u6B64\u7248\u672C (24h \u5185\u4E0D\u518D\u63D0\u793A)",
|
|
2046
|
-
value: "dismiss",
|
|
2047
|
-
description: "24 \u5C0F\u65F6\u5185\u4E0D\u4F1A\u518D\u63D0\u793A\u6B64\u7248\u672C"
|
|
2048
|
-
}
|
|
2049
|
-
]
|
|
2050
|
-
});
|
|
2051
|
-
return action;
|
|
2052
|
-
} catch (error) {
|
|
2053
|
-
console.log("");
|
|
2054
|
-
throw error;
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
|
-
async function performUpdate(packageName) {
|
|
2058
|
-
console.log("");
|
|
2059
|
-
const spinner = ora5({
|
|
2060
|
-
text: "\u6B63\u5728\u66F4\u65B0...",
|
|
2061
|
-
spinner: "dots"
|
|
2062
|
-
}).start();
|
|
2063
|
-
try {
|
|
2064
|
-
execSync6(`npm install -g ${packageName}@latest`, {
|
|
2065
|
-
encoding: "utf-8",
|
|
2066
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
2067
|
-
});
|
|
2068
|
-
spinner.succeed(colors.green("\u66F4\u65B0\u6210\u529F\uFF01"));
|
|
2069
|
-
console.log("");
|
|
2070
|
-
console.log(
|
|
2071
|
-
boxen(
|
|
2072
|
-
[
|
|
2073
|
-
colors.bold("\u2728 \u66F4\u65B0\u5B8C\u6210\uFF01"),
|
|
2074
|
-
"",
|
|
2075
|
-
colors.dim("\u8BF7\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF\u4F7F\u7528\u65B0\u7248\u672C")
|
|
2076
|
-
].join("\n"),
|
|
2077
|
-
{
|
|
2078
|
-
padding: 1,
|
|
2079
|
-
margin: { top: 0, bottom: 1, left: 2, right: 2 },
|
|
2080
|
-
borderStyle: "round",
|
|
2081
|
-
borderColor: "green",
|
|
2082
|
-
align: "left"
|
|
2083
|
-
}
|
|
2084
|
-
)
|
|
2085
|
-
);
|
|
2086
|
-
process.exit(0);
|
|
2087
|
-
} catch (error) {
|
|
2088
|
-
spinner.fail(colors.red("\u66F4\u65B0\u5931\u8D25"));
|
|
2089
|
-
console.log("");
|
|
2090
|
-
console.log(colors.dim(" \u4F60\u53EF\u4EE5\u624B\u52A8\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u66F4\u65B0:"));
|
|
2091
|
-
console.log(colors.cyan(` npm install -g ${packageName}@latest`));
|
|
2092
|
-
console.log("");
|
|
2093
|
-
}
|
|
2094
|
-
}
|
|
2095
|
-
function readCache() {
|
|
2096
|
-
try {
|
|
2097
|
-
const cacheFile = join3(homedir3(), CACHE_FILE);
|
|
2098
|
-
if (!existsSync3(cacheFile)) {
|
|
2099
|
-
return null;
|
|
2100
|
-
}
|
|
2101
|
-
const content = readFileSync3(cacheFile, "utf-8");
|
|
2102
|
-
return JSON.parse(content);
|
|
2103
|
-
} catch {
|
|
2104
|
-
return null;
|
|
2105
|
-
}
|
|
2106
|
-
}
|
|
2107
|
-
function writeCache(cache) {
|
|
2108
|
-
try {
|
|
2109
|
-
const cacheFile = join3(homedir3(), CACHE_FILE);
|
|
2110
|
-
writeFileSync3(cacheFile, JSON.stringify(cache), "utf-8");
|
|
2111
|
-
} catch {
|
|
2112
|
-
}
|
|
2113
|
-
}
|
|
2214
|
+
// src/index.ts
|
|
2215
|
+
init_update_notifier();
|
|
2114
2216
|
|
|
2115
2217
|
// src/commands/update.ts
|
|
2218
|
+
init_utils();
|
|
2116
2219
|
import { execSync as execSync7 } from "child_process";
|
|
2117
2220
|
import ora6 from "ora";
|
|
2118
2221
|
import boxen2 from "boxen";
|
|
2222
|
+
import semver2 from "semver";
|
|
2223
|
+
import { existsSync as existsSync4, unlinkSync as unlinkSync2 } from "fs";
|
|
2224
|
+
import { homedir as homedir4 } from "os";
|
|
2225
|
+
import { join as join4 } from "path";
|
|
2226
|
+
var CACHE_FILE2 = ".gw-update-check";
|
|
2227
|
+
function clearUpdateCache2() {
|
|
2228
|
+
try {
|
|
2229
|
+
const cacheFile = join4(homedir4(), CACHE_FILE2);
|
|
2230
|
+
if (existsSync4(cacheFile)) {
|
|
2231
|
+
unlinkSync2(cacheFile);
|
|
2232
|
+
}
|
|
2233
|
+
} catch {
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2119
2236
|
async function getLatestVersion2(packageName) {
|
|
2120
2237
|
try {
|
|
2121
2238
|
const result = execSync7(`npm view ${packageName} version`, {
|
|
@@ -2142,11 +2259,11 @@ async function update(currentVersion) {
|
|
|
2142
2259
|
return;
|
|
2143
2260
|
}
|
|
2144
2261
|
spinner.stop();
|
|
2145
|
-
if (latestVersion
|
|
2262
|
+
if (semver2.gte(currentVersion, latestVersion)) {
|
|
2146
2263
|
console.log(
|
|
2147
2264
|
boxen2(
|
|
2148
2265
|
[
|
|
2149
|
-
colors.bold("\u2705 \u5DF2\u662F\u6700\u65B0\u7248\u672C"),
|
|
2266
|
+
colors.green(colors.bold("\u2705 \u5DF2\u662F\u6700\u65B0\u7248\u672C")),
|
|
2150
2267
|
"",
|
|
2151
2268
|
`\u5F53\u524D\u7248\u672C: ${colors.green(currentVersion)}`
|
|
2152
2269
|
].join("\n"),
|
|
@@ -2161,21 +2278,29 @@ async function update(currentVersion) {
|
|
|
2161
2278
|
);
|
|
2162
2279
|
return;
|
|
2163
2280
|
}
|
|
2281
|
+
const versionText = `${currentVersion} \u2192 ${latestVersion}`;
|
|
2282
|
+
const maxWidth = Math.max(
|
|
2283
|
+
"\u{1F389} \u53D1\u73B0\u65B0\u7248\u672C\uFF01".length,
|
|
2284
|
+
versionText.length,
|
|
2285
|
+
"\u2728 \u66F4\u65B0\u5B8C\u6210\uFF01".length,
|
|
2286
|
+
"\u8BF7\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF\u4F7F\u7528\u65B0\u7248\u672C".length
|
|
2287
|
+
);
|
|
2164
2288
|
console.log(
|
|
2165
2289
|
boxen2(
|
|
2166
2290
|
[
|
|
2167
|
-
colors.bold("\u{1F389} \u53D1\u73B0\u65B0\u7248\u672C\uFF01"),
|
|
2291
|
+
colors.yellow(colors.bold("\u{1F389} \u53D1\u73B0\u65B0\u7248\u672C\uFF01")),
|
|
2168
2292
|
"",
|
|
2169
2293
|
`${colors.dim(currentVersion)} \u2192 ${colors.green(
|
|
2170
2294
|
colors.bold(latestVersion)
|
|
2171
2295
|
)}`
|
|
2172
2296
|
].join("\n"),
|
|
2173
2297
|
{
|
|
2174
|
-
padding: 1,
|
|
2298
|
+
padding: { top: 1, bottom: 1, left: 3, right: 3 },
|
|
2175
2299
|
margin: { top: 0, bottom: 1, left: 2, right: 2 },
|
|
2176
2300
|
borderStyle: "round",
|
|
2177
2301
|
borderColor: "yellow",
|
|
2178
|
-
align: "
|
|
2302
|
+
align: "center",
|
|
2303
|
+
width: 40
|
|
2179
2304
|
}
|
|
2180
2305
|
)
|
|
2181
2306
|
);
|
|
@@ -2185,20 +2310,22 @@ async function update(currentVersion) {
|
|
|
2185
2310
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2186
2311
|
});
|
|
2187
2312
|
updateSpinner.succeed(colors.green("\u66F4\u65B0\u6210\u529F\uFF01"));
|
|
2313
|
+
clearUpdateCache2();
|
|
2188
2314
|
console.log("");
|
|
2189
2315
|
console.log(
|
|
2190
2316
|
boxen2(
|
|
2191
2317
|
[
|
|
2192
|
-
colors.bold("\u2728 \u66F4\u65B0\u5B8C\u6210\uFF01"),
|
|
2318
|
+
colors.green(colors.bold("\u2728 \u66F4\u65B0\u5B8C\u6210\uFF01")),
|
|
2193
2319
|
"",
|
|
2194
2320
|
colors.dim("\u8BF7\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF\u4F7F\u7528\u65B0\u7248\u672C")
|
|
2195
2321
|
].join("\n"),
|
|
2196
2322
|
{
|
|
2197
|
-
padding: 1,
|
|
2323
|
+
padding: { top: 1, bottom: 1, left: 3, right: 3 },
|
|
2198
2324
|
margin: { top: 0, bottom: 1, left: 2, right: 2 },
|
|
2199
2325
|
borderStyle: "round",
|
|
2200
2326
|
borderColor: "green",
|
|
2201
|
-
align: "
|
|
2327
|
+
align: "center",
|
|
2328
|
+
width: 40
|
|
2202
2329
|
}
|
|
2203
2330
|
)
|
|
2204
2331
|
);
|
|
@@ -2238,7 +2365,7 @@ process.on("SIGTERM", () => {
|
|
|
2238
2365
|
console.log("");
|
|
2239
2366
|
process.exit(0);
|
|
2240
2367
|
});
|
|
2241
|
-
var version = true ? "0.2.
|
|
2368
|
+
var version = true ? "0.2.20" : "0.0.0-dev";
|
|
2242
2369
|
async function mainMenu() {
|
|
2243
2370
|
console.log(
|
|
2244
2371
|
colors.green(`
|
|
@@ -2357,7 +2484,7 @@ async function mainMenu() {
|
|
|
2357
2484
|
}
|
|
2358
2485
|
var cli = cac("gw");
|
|
2359
2486
|
cli.command("", "\u663E\u793A\u4EA4\u4E92\u5F0F\u83DC\u5355").action(async () => {
|
|
2360
|
-
await checkForUpdates(version, "@zjex/git-workflow");
|
|
2487
|
+
await checkForUpdates(version, "@zjex/git-workflow", true);
|
|
2361
2488
|
return mainMenu();
|
|
2362
2489
|
});
|
|
2363
2490
|
cli.command("feature", "\u521B\u5EFA feature \u5206\u652F").alias("feat").alias("f").option("--base <branch>", "\u6307\u5B9A\u57FA\u7840\u5206\u652F").action(async (options) => {
|
|
@@ -2416,6 +2543,13 @@ cli.command("commit", "\u4EA4\u4E92\u5F0F\u63D0\u4EA4 (Conventional Commits + Gi
|
|
|
2416
2543
|
cli.command("update", "\u68C0\u67E5\u5E76\u66F4\u65B0\u5230\u6700\u65B0\u7248\u672C").alias("upt").action(async () => {
|
|
2417
2544
|
return update(version);
|
|
2418
2545
|
});
|
|
2546
|
+
cli.command("clean", "\u6E05\u7406\u7F13\u5B58\u6587\u4EF6").action(async () => {
|
|
2547
|
+
const { clearUpdateCache: clearUpdateCache3 } = await Promise.resolve().then(() => (init_update_notifier(), update_notifier_exports));
|
|
2548
|
+
clearUpdateCache3();
|
|
2549
|
+
console.log("");
|
|
2550
|
+
console.log(colors.green("\u2714 \u7F13\u5B58\u5DF2\u6E05\u7406"));
|
|
2551
|
+
console.log("");
|
|
2552
|
+
});
|
|
2419
2553
|
cli.help((sections) => {
|
|
2420
2554
|
sections.push({
|
|
2421
2555
|
body: showHelp()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zjex/git-workflow",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.20",
|
|
4
4
|
"description": "🚀 极简的 Git 工作流 CLI 工具,让分支管理和版本发布变得轻松愉快",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,10 +42,12 @@
|
|
|
42
42
|
"@inquirer/prompts": "^7.0.0",
|
|
43
43
|
"boxen": "^8.0.1",
|
|
44
44
|
"cac": "^6.7.14",
|
|
45
|
-
"ora": "^9.0.0"
|
|
45
|
+
"ora": "^9.0.0",
|
|
46
|
+
"semver": "^7.7.3"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@types/node": "^25.0.3",
|
|
50
|
+
"@types/semver": "^7.7.1",
|
|
49
51
|
"changelogen": "^0.6.2",
|
|
50
52
|
"husky": "^9.1.7",
|
|
51
53
|
"tsup": "^8.5.1",
|
package/src/commands/help.ts
CHANGED
package/src/commands/update.ts
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
import { execSync } from "child_process";
|
|
2
2
|
import ora from "ora";
|
|
3
3
|
import boxen from "boxen";
|
|
4
|
+
import semver from "semver";
|
|
5
|
+
import { existsSync, unlinkSync } from "fs";
|
|
6
|
+
import { homedir } from "os";
|
|
7
|
+
import { join } from "path";
|
|
4
8
|
import { colors } from "../utils.js";
|
|
5
9
|
|
|
10
|
+
const CACHE_FILE = ".gw-update-check";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 清理更新缓存文件
|
|
14
|
+
*/
|
|
15
|
+
function clearUpdateCache(): void {
|
|
16
|
+
try {
|
|
17
|
+
const cacheFile = join(homedir(), CACHE_FILE);
|
|
18
|
+
if (existsSync(cacheFile)) {
|
|
19
|
+
unlinkSync(cacheFile);
|
|
20
|
+
}
|
|
21
|
+
} catch {
|
|
22
|
+
// 静默失败
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
6
26
|
/**
|
|
7
27
|
* 获取 npm 上的最新版本
|
|
8
28
|
*/
|
|
@@ -42,11 +62,12 @@ export async function update(currentVersion: string): Promise<void> {
|
|
|
42
62
|
|
|
43
63
|
spinner.stop();
|
|
44
64
|
|
|
45
|
-
|
|
65
|
+
// 使用 semver 比较版本
|
|
66
|
+
if (semver.gte(currentVersion, latestVersion)) {
|
|
46
67
|
console.log(
|
|
47
68
|
boxen(
|
|
48
69
|
[
|
|
49
|
-
colors.bold("✅ 已是最新版本"),
|
|
70
|
+
colors.green(colors.bold("✅ 已是最新版本")),
|
|
50
71
|
"",
|
|
51
72
|
`当前版本: ${colors.green(currentVersion)}`,
|
|
52
73
|
].join("\n"),
|
|
@@ -63,21 +84,30 @@ export async function update(currentVersion: string): Promise<void> {
|
|
|
63
84
|
}
|
|
64
85
|
|
|
65
86
|
// 有新版本
|
|
87
|
+
const versionText = `${currentVersion} → ${latestVersion}`;
|
|
88
|
+
const maxWidth = Math.max(
|
|
89
|
+
"🎉 发现新版本!".length,
|
|
90
|
+
versionText.length,
|
|
91
|
+
"✨ 更新完成!".length,
|
|
92
|
+
"请重新打开终端使用新版本".length
|
|
93
|
+
);
|
|
94
|
+
|
|
66
95
|
console.log(
|
|
67
96
|
boxen(
|
|
68
97
|
[
|
|
69
|
-
colors.bold("🎉 发现新版本!"),
|
|
98
|
+
colors.yellow(colors.bold("🎉 发现新版本!")),
|
|
70
99
|
"",
|
|
71
100
|
`${colors.dim(currentVersion)} → ${colors.green(
|
|
72
101
|
colors.bold(latestVersion)
|
|
73
102
|
)}`,
|
|
74
103
|
].join("\n"),
|
|
75
104
|
{
|
|
76
|
-
padding: 1,
|
|
105
|
+
padding: { top: 1, bottom: 1, left: 3, right: 3 },
|
|
77
106
|
margin: { top: 0, bottom: 1, left: 2, right: 2 },
|
|
78
107
|
borderStyle: "round",
|
|
79
108
|
borderColor: "yellow",
|
|
80
|
-
align: "
|
|
109
|
+
align: "center",
|
|
110
|
+
width: 40,
|
|
81
111
|
}
|
|
82
112
|
)
|
|
83
113
|
);
|
|
@@ -91,20 +121,25 @@ export async function update(currentVersion: string): Promise<void> {
|
|
|
91
121
|
});
|
|
92
122
|
|
|
93
123
|
updateSpinner.succeed(colors.green("更新成功!"));
|
|
124
|
+
|
|
125
|
+
// 清理缓存文件
|
|
126
|
+
clearUpdateCache();
|
|
127
|
+
|
|
94
128
|
console.log("");
|
|
95
129
|
console.log(
|
|
96
130
|
boxen(
|
|
97
131
|
[
|
|
98
|
-
colors.bold("✨ 更新完成!"),
|
|
132
|
+
colors.green(colors.bold("✨ 更新完成!")),
|
|
99
133
|
"",
|
|
100
134
|
colors.dim("请重新打开终端使用新版本"),
|
|
101
135
|
].join("\n"),
|
|
102
136
|
{
|
|
103
|
-
padding: 1,
|
|
137
|
+
padding: { top: 1, bottom: 1, left: 3, right: 3 },
|
|
104
138
|
margin: { top: 0, bottom: 1, left: 2, right: 2 },
|
|
105
139
|
borderStyle: "round",
|
|
106
140
|
borderColor: "green",
|
|
107
|
-
align: "
|
|
141
|
+
align: "center",
|
|
142
|
+
width: 40,
|
|
108
143
|
}
|
|
109
144
|
)
|
|
110
145
|
);
|
package/src/index.ts
CHANGED
|
@@ -178,7 +178,7 @@ const cli = cac("gw");
|
|
|
178
178
|
|
|
179
179
|
// 默认命令 - 显示交互式菜单
|
|
180
180
|
cli.command("", "显示交互式菜单").action(async () => {
|
|
181
|
-
await checkForUpdates(version, "@zjex/git-workflow");
|
|
181
|
+
await checkForUpdates(version, "@zjex/git-workflow", true);
|
|
182
182
|
return mainMenu();
|
|
183
183
|
});
|
|
184
184
|
|
|
@@ -290,6 +290,14 @@ cli
|
|
|
290
290
|
return update(version);
|
|
291
291
|
});
|
|
292
292
|
|
|
293
|
+
cli.command("clean", "清理缓存文件").action(async () => {
|
|
294
|
+
const { clearUpdateCache } = await import("./update-notifier.js");
|
|
295
|
+
clearUpdateCache();
|
|
296
|
+
console.log("");
|
|
297
|
+
console.log(colors.green("✔ 缓存已清理"));
|
|
298
|
+
console.log("");
|
|
299
|
+
});
|
|
300
|
+
|
|
293
301
|
cli.help((sections) => {
|
|
294
302
|
sections.push({
|
|
295
303
|
body: showHelp(),
|
package/src/update-notifier.ts
CHANGED
|
@@ -1,57 +1,72 @@
|
|
|
1
1
|
import { execSync } from "child_process";
|
|
2
|
-
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, unlinkSync } from "fs";
|
|
3
3
|
import { homedir } from "os";
|
|
4
4
|
import { join } from "path";
|
|
5
5
|
import boxen from "boxen";
|
|
6
6
|
import { select } from "@inquirer/prompts";
|
|
7
7
|
import ora from "ora";
|
|
8
|
+
import semver from "semver";
|
|
8
9
|
import { colors } from "./utils.js";
|
|
9
10
|
|
|
11
|
+
const CHECK_INTERVAL = 1000 * 60 * 60 * 4; // 4 小时检查一次
|
|
10
12
|
const DISMISS_INTERVAL = 1000 * 60 * 60 * 24; // 24 小时后再次提示
|
|
11
13
|
const CACHE_FILE = ".gw-update-check";
|
|
12
14
|
|
|
13
15
|
interface UpdateCache {
|
|
16
|
+
lastCheck?: number; // 上次检查更新的时间
|
|
14
17
|
lastDismiss?: number; // 用户上次关闭提示的时间
|
|
15
|
-
latestVersion?: string;
|
|
18
|
+
latestVersion?: string; // 最新版本号
|
|
19
|
+
checkedVersion?: string; // 检查时的当前版本
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
/**
|
|
19
|
-
*
|
|
23
|
+
* 检查是否有新版本(异步静默检查)
|
|
24
|
+
* @param currentVersion 当前版本
|
|
25
|
+
* @param packageName 包名
|
|
26
|
+
* @param interactive 是否交互式(true: 显示完整提示并可选择更新,false: 只显示简单提示)
|
|
20
27
|
*/
|
|
21
28
|
export async function checkForUpdates(
|
|
22
29
|
currentVersion: string,
|
|
23
|
-
packageName: string = "@zjex/git-workflow"
|
|
30
|
+
packageName: string = "@zjex/git-workflow",
|
|
31
|
+
interactive: boolean = false
|
|
24
32
|
): Promise<void> {
|
|
25
33
|
try {
|
|
26
|
-
// 读取缓存
|
|
27
34
|
const cache = readCache();
|
|
28
35
|
const now = Date.now();
|
|
29
36
|
|
|
30
|
-
//
|
|
31
|
-
if (cache?.
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
// 1. 先检查缓存中是否有新版本需要提示
|
|
38
|
+
if (cache?.latestVersion && cache.checkedVersion === currentVersion) {
|
|
39
|
+
// 如果用户在 24 小时内关闭过提示,跳过
|
|
40
|
+
if (cache.lastDismiss && now - cache.lastDismiss < DISMISS_INTERVAL) {
|
|
41
|
+
// 继续后台检查(不阻塞)
|
|
42
|
+
backgroundCheck(currentVersion, packageName);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 使用 semver 比较版本
|
|
47
|
+
if (semver.gt(cache.latestVersion, currentVersion)) {
|
|
48
|
+
if (interactive) {
|
|
49
|
+
// 交互式模式:显示完整提示,可选择更新
|
|
50
|
+
const action = await showUpdateMessage(
|
|
51
|
+
currentVersion,
|
|
52
|
+
cache.latestVersion,
|
|
53
|
+
packageName
|
|
54
|
+
);
|
|
34
55
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
if (action === "update") {
|
|
47
|
-
// 用户选择立即更新
|
|
48
|
-
await performUpdate(packageName);
|
|
49
|
-
} else if (action === "dismiss") {
|
|
50
|
-
// 用户选择跳过,记录时间
|
|
51
|
-
writeCache({ lastDismiss: now, latestVersion });
|
|
56
|
+
if (action === "update") {
|
|
57
|
+
await performUpdate(packageName);
|
|
58
|
+
} else if (action === "dismiss") {
|
|
59
|
+
writeCache({ ...cache, lastDismiss: now });
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
// 非交互式模式:只显示简单提示
|
|
63
|
+
showSimpleNotification(currentVersion, cache.latestVersion);
|
|
64
|
+
}
|
|
52
65
|
}
|
|
53
|
-
// action === "continue" 时直接继续,不记录
|
|
54
66
|
}
|
|
67
|
+
|
|
68
|
+
// 2. 后台异步检查更新(不阻塞当前命令)
|
|
69
|
+
backgroundCheck(currentVersion, packageName);
|
|
55
70
|
} catch (error) {
|
|
56
71
|
// 如果是用户按 Ctrl+C,重新抛出让全局处理
|
|
57
72
|
if (error?.constructor?.name === "ExitPromptError") {
|
|
@@ -61,6 +76,37 @@ export async function checkForUpdates(
|
|
|
61
76
|
}
|
|
62
77
|
}
|
|
63
78
|
|
|
79
|
+
/**
|
|
80
|
+
* 后台异步检查更新(不阻塞)
|
|
81
|
+
*/
|
|
82
|
+
function backgroundCheck(currentVersion: string, packageName: string): void {
|
|
83
|
+
const cache = readCache();
|
|
84
|
+
const now = Date.now();
|
|
85
|
+
|
|
86
|
+
// 如果距离上次检查不到 4 小时,跳过
|
|
87
|
+
if (cache?.lastCheck && now - cache.lastCheck < CHECK_INTERVAL) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 使用 Promise 异步执行,不阻塞当前命令
|
|
92
|
+
Promise.resolve().then(async () => {
|
|
93
|
+
try {
|
|
94
|
+
const latestVersion = await getLatestVersion(packageName);
|
|
95
|
+
|
|
96
|
+
if (latestVersion) {
|
|
97
|
+
writeCache({
|
|
98
|
+
...cache,
|
|
99
|
+
lastCheck: now,
|
|
100
|
+
latestVersion,
|
|
101
|
+
checkedVersion: currentVersion,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
// 静默失败
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
64
110
|
/**
|
|
65
111
|
* 获取 npm 上的最新版本
|
|
66
112
|
*/
|
|
@@ -78,7 +124,29 @@ async function getLatestVersion(packageName: string): Promise<string | null> {
|
|
|
78
124
|
}
|
|
79
125
|
|
|
80
126
|
/**
|
|
81
|
-
*
|
|
127
|
+
* 显示简单的更新通知(非交互式,不阻塞)
|
|
128
|
+
*/
|
|
129
|
+
function showSimpleNotification(current: string, latest: string): void {
|
|
130
|
+
const message = `${colors.yellow("🎉 发现新版本")} ${colors.dim(
|
|
131
|
+
current
|
|
132
|
+
)} → ${colors.green(latest)} ${colors.dim("运行")} ${colors.cyan(
|
|
133
|
+
"gw update"
|
|
134
|
+
)} ${colors.dim("更新")}`;
|
|
135
|
+
|
|
136
|
+
console.log("");
|
|
137
|
+
console.log(
|
|
138
|
+
boxen(message, {
|
|
139
|
+
padding: { top: 0, bottom: 0, left: 2, right: 2 },
|
|
140
|
+
margin: { top: 0, bottom: 1, left: 0, right: 0 },
|
|
141
|
+
borderStyle: "round",
|
|
142
|
+
borderColor: "yellow",
|
|
143
|
+
align: "center",
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 显示更新提示消息并让用户选择(交互式)
|
|
82
150
|
* @returns "update" | "continue" | "dismiss"
|
|
83
151
|
*/
|
|
84
152
|
async function showUpdateMessage(
|
|
@@ -87,7 +155,7 @@ async function showUpdateMessage(
|
|
|
87
155
|
packageName: string
|
|
88
156
|
): Promise<"update" | "continue" | "dismiss"> {
|
|
89
157
|
const message = [
|
|
90
|
-
colors.bold("
|
|
158
|
+
colors.yellow(colors.bold("🎉 发现新版本!")),
|
|
91
159
|
"",
|
|
92
160
|
`${colors.dim(current)} → ${colors.green(colors.bold(latest))}`,
|
|
93
161
|
].join("\n");
|
|
@@ -95,11 +163,12 @@ async function showUpdateMessage(
|
|
|
95
163
|
console.log("");
|
|
96
164
|
console.log(
|
|
97
165
|
boxen(message, {
|
|
98
|
-
padding: 1,
|
|
166
|
+
padding: { top: 1, bottom: 1, left: 3, right: 3 },
|
|
99
167
|
margin: 1,
|
|
100
168
|
borderStyle: "round",
|
|
101
169
|
borderColor: "yellow",
|
|
102
|
-
align: "
|
|
170
|
+
align: "center",
|
|
171
|
+
width: 40,
|
|
103
172
|
})
|
|
104
173
|
);
|
|
105
174
|
|
|
@@ -152,20 +221,25 @@ async function performUpdate(packageName: string): Promise<void> {
|
|
|
152
221
|
});
|
|
153
222
|
|
|
154
223
|
spinner.succeed(colors.green("更新成功!"));
|
|
224
|
+
|
|
225
|
+
// 清理缓存文件
|
|
226
|
+
clearUpdateCache();
|
|
227
|
+
|
|
155
228
|
console.log("");
|
|
156
229
|
console.log(
|
|
157
230
|
boxen(
|
|
158
231
|
[
|
|
159
|
-
colors.bold("✨ 更新完成!"),
|
|
232
|
+
colors.green(colors.bold("✨ 更新完成!")),
|
|
160
233
|
"",
|
|
161
234
|
colors.dim("请重新打开终端使用新版本"),
|
|
162
235
|
].join("\n"),
|
|
163
236
|
{
|
|
164
|
-
padding: 1,
|
|
237
|
+
padding: { top: 1, bottom: 1, left: 3, right: 3 },
|
|
165
238
|
margin: { top: 0, bottom: 1, left: 2, right: 2 },
|
|
166
239
|
borderStyle: "round",
|
|
167
240
|
borderColor: "green",
|
|
168
|
-
align: "
|
|
241
|
+
align: "center",
|
|
242
|
+
width: 40,
|
|
169
243
|
}
|
|
170
244
|
)
|
|
171
245
|
);
|
|
@@ -181,6 +255,20 @@ async function performUpdate(packageName: string): Promise<void> {
|
|
|
181
255
|
}
|
|
182
256
|
}
|
|
183
257
|
|
|
258
|
+
/**
|
|
259
|
+
* 清理更新缓存文件
|
|
260
|
+
*/
|
|
261
|
+
export function clearUpdateCache(): void {
|
|
262
|
+
try {
|
|
263
|
+
const cacheFile = join(homedir(), CACHE_FILE);
|
|
264
|
+
if (existsSync(cacheFile)) {
|
|
265
|
+
unlinkSync(cacheFile);
|
|
266
|
+
}
|
|
267
|
+
} catch {
|
|
268
|
+
// 静默失败
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
184
272
|
/**
|
|
185
273
|
* 读取缓存
|
|
186
274
|
*/
|