specline 1.3.2 → 1.3.3
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/cli.mjs +71 -15
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -5,6 +5,8 @@ import { join, dirname, resolve, relative, basename } from 'path';
|
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import { createHash } from 'crypto';
|
|
7
7
|
import { get } from 'https';
|
|
8
|
+
import { execSync, spawnSync } from 'child_process';
|
|
9
|
+
import { createInterface } from 'readline/promises';
|
|
8
10
|
|
|
9
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
12
|
const TEMPLATES_DIR = join(__dirname, 'templates');
|
|
@@ -455,7 +457,26 @@ function fetchLatestVersion() {
|
|
|
455
457
|
});
|
|
456
458
|
}
|
|
457
459
|
|
|
460
|
+
/**
|
|
461
|
+
* 交互式确认提问:回车/Y/y/Yes/yes → true, N/n/No/no → false
|
|
462
|
+
* 非 TTY 环境直接返回 true(无人值守模式)
|
|
463
|
+
*/
|
|
464
|
+
async function askConfirm(question) {
|
|
465
|
+
if (!process.stdin.isTTY) return true;
|
|
466
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
467
|
+
try {
|
|
468
|
+
const answer = await rl.question(question + ' ');
|
|
469
|
+
const trimmed = answer.trim().toLowerCase();
|
|
470
|
+
return trimmed === '' || trimmed === 'y' || trimmed === 'yes';
|
|
471
|
+
} catch {
|
|
472
|
+
return false;
|
|
473
|
+
} finally {
|
|
474
|
+
rl.close();
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
458
478
|
async function cmd_update() {
|
|
479
|
+
// 1. 从 npm registry 获取最新版本
|
|
459
480
|
let latest;
|
|
460
481
|
try {
|
|
461
482
|
latest = await fetchLatestVersion();
|
|
@@ -473,25 +494,60 @@ async function cmd_update() {
|
|
|
473
494
|
process.exit(0);
|
|
474
495
|
}
|
|
475
496
|
|
|
476
|
-
|
|
477
|
-
|
|
497
|
+
// 2. 版本比较
|
|
498
|
+
if (compareVersions(VERSION, latest) >= 0) {
|
|
499
|
+
success('已是最新版本 (v' + VERSION + ')');
|
|
500
|
+
process.exit(0);
|
|
501
|
+
}
|
|
478
502
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
503
|
+
// 3. 交互确认
|
|
504
|
+
log('✨ 新版本可用: v' + latest + '(当前: v' + VERSION + ')');
|
|
505
|
+
|
|
506
|
+
if (!process.stdin.isTTY) {
|
|
507
|
+
log('在非交互环境中无法自动升级,请手动执行: npm install -g specline@latest');
|
|
508
|
+
process.exit(0);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const proceed = await askConfirm('是否升级到 v' + latest + '?[Y/n]');
|
|
512
|
+
if (!proceed) {
|
|
513
|
+
log('已取消升级');
|
|
514
|
+
process.exit(0);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// 4. 执行 npm install -g specline@latest
|
|
518
|
+
log('正在升级 specline...');
|
|
519
|
+
try {
|
|
520
|
+
execSync('npm install -g specline@latest', { stdio: 'inherit' });
|
|
521
|
+
} catch (err) {
|
|
522
|
+
const stderr = (err.stderr || '').toString();
|
|
523
|
+
if (stderr.includes('EACCES') || stderr.includes('permission denied')) {
|
|
524
|
+
error('权限不足。请尝试:');
|
|
525
|
+
log(' sudo npm install -g specline@latest');
|
|
526
|
+
log(' 或使用 Node 版本管理器(nvm / fnm / n)');
|
|
527
|
+
} else {
|
|
528
|
+
error('升级失败:' + (stderr || err.message));
|
|
488
529
|
}
|
|
530
|
+
process.exit(1);
|
|
489
531
|
}
|
|
490
532
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
533
|
+
success('已升级至 v' + latest);
|
|
534
|
+
|
|
535
|
+
// 5. 检测是否为 specline 项目,询问是否同步模板
|
|
536
|
+
const cwd = process.cwd();
|
|
537
|
+
const lockFile = join(cwd, 'specline', '.specline-lock.yaml');
|
|
538
|
+
if (existsSync(lockFile)) {
|
|
539
|
+
const doSync = await askConfirm('检测到 specline 项目,是否同步最新模板?[Y/n]');
|
|
540
|
+
if (doSync) {
|
|
541
|
+
log('正在同步模板文件...');
|
|
542
|
+
try {
|
|
543
|
+
const result = spawnSync('specline', ['sync'], { stdio: 'inherit' });
|
|
544
|
+
if (result.status !== 0) {
|
|
545
|
+
warn('模板同步失败(退出码: ' + result.status + '),请手动运行 specline sync');
|
|
546
|
+
}
|
|
547
|
+
} catch (err) {
|
|
548
|
+
warn('无法运行 specline sync:' + err.message);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
495
551
|
}
|
|
496
552
|
|
|
497
553
|
process.exit(0);
|