@byh3071/vhk 1.6.4 → 1.6.6
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/{chunk-EJTVXWUZ.js → chunk-HLUFOT2T.js} +146 -116
- package/dist/index.js +485 -507
- package/dist/mcp/index.js +1 -1
- package/package.json +1 -1
|
@@ -483,8 +483,31 @@ var require_ignore = __commonJS({
|
|
|
483
483
|
}
|
|
484
484
|
});
|
|
485
485
|
|
|
486
|
+
// src/lib/interactive.ts
|
|
487
|
+
import chalk from "chalk";
|
|
488
|
+
function isInteractive(opts) {
|
|
489
|
+
if (opts?.yes) return false;
|
|
490
|
+
if (process.env.VHK_FORCE_INTERACTIVE === "1") return true;
|
|
491
|
+
return !!process.stdin.isTTY;
|
|
492
|
+
}
|
|
493
|
+
async function promptOrDefault(ask, fallback, opts) {
|
|
494
|
+
if (!isInteractive(opts)) return fallback;
|
|
495
|
+
return await ask();
|
|
496
|
+
}
|
|
497
|
+
function ensureInteractive(hint = "") {
|
|
498
|
+
if (isInteractive()) return true;
|
|
499
|
+
console.error(chalk.yellow(" \u26A0\uFE0F \uC774 \uBA85\uB839\uC740 \uB300\uD654\uD615 \uC785\uB825\uC774 \uD544\uC694\uD569\uB2C8\uB2E4 \u2014 \uBE44-TTY/\uD30C\uC774\uD504 \uD658\uACBD\uC5D0\uC11C\uB294 \uC2E4\uD589\uD560 \uC218 \uC5C6\uC5B4\uC694."));
|
|
500
|
+
if (hint) console.error(chalk.dim(` ${hint}`));
|
|
501
|
+
process.exitCode = 1;
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
function isPromptAbortError(err) {
|
|
505
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
506
|
+
return /ERR_USE_AFTER_CLOSE|force closed|ExitPromptError|readline was closed|User force closed/i.test(msg);
|
|
507
|
+
}
|
|
508
|
+
|
|
486
509
|
// src/commands/sync.ts
|
|
487
|
-
import
|
|
510
|
+
import chalk3 from "chalk";
|
|
488
511
|
import fs4 from "fs";
|
|
489
512
|
import path4 from "path";
|
|
490
513
|
import inquirer from "inquirer";
|
|
@@ -911,7 +934,7 @@ function t(key, ...args) {
|
|
|
911
934
|
// src/lib/next-step.ts
|
|
912
935
|
import fs2 from "fs";
|
|
913
936
|
import path2 from "path";
|
|
914
|
-
import
|
|
937
|
+
import chalk2 from "chalk";
|
|
915
938
|
|
|
916
939
|
// src/lib/drift.ts
|
|
917
940
|
import fs from "fs";
|
|
@@ -1029,39 +1052,39 @@ function checkContextDrift(rootDir) {
|
|
|
1029
1052
|
// src/lib/next-step.ts
|
|
1030
1053
|
function printNextStep(step) {
|
|
1031
1054
|
console.log("");
|
|
1032
|
-
console.log(
|
|
1055
|
+
console.log(chalk2.cyan.bold("\u2501\u2501\u2501 \uB2E4\uC74C\uC5D0 \uC774\uAC83\uB9CC \uD558\uC138\uC694 \u2501\u2501\u2501"));
|
|
1033
1056
|
console.log("");
|
|
1034
1057
|
console.log(` ${step.message}`);
|
|
1035
1058
|
if (step.command) {
|
|
1036
1059
|
console.log("");
|
|
1037
|
-
console.log(
|
|
1038
|
-
console.log(
|
|
1060
|
+
console.log(chalk2.white.bgGray(" \uD130\uBBF8\uB110\uC5D0 \uBCF5\uBD99 "));
|
|
1061
|
+
console.log(chalk2.green(` ${step.command}`));
|
|
1039
1062
|
}
|
|
1040
1063
|
if (step.cursorHint) {
|
|
1041
1064
|
console.log("");
|
|
1042
|
-
console.log(
|
|
1043
|
-
console.log(
|
|
1065
|
+
console.log(chalk2.white.bgBlue(" Cursor\uC5D0\uAC8C \uB9D0\uD558\uAE30 "));
|
|
1066
|
+
console.log(chalk2.blue(` "${step.cursorHint}"`));
|
|
1044
1067
|
}
|
|
1045
1068
|
if (step.alternative) {
|
|
1046
1069
|
console.log("");
|
|
1047
|
-
console.log(
|
|
1070
|
+
console.log(chalk2.dim(` \uB610\uB294: ${step.alternative}`));
|
|
1048
1071
|
}
|
|
1049
1072
|
console.log("");
|
|
1050
|
-
console.log(
|
|
1073
|
+
console.log(chalk2.cyan.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
1051
1074
|
console.log("");
|
|
1052
1075
|
}
|
|
1053
1076
|
function printContextResumeHint(cwd = process.cwd()) {
|
|
1054
1077
|
const ctxPath = path2.join(cwd, ".vhk", "context.md");
|
|
1055
1078
|
if (!fs2.existsSync(ctxPath)) {
|
|
1056
|
-
console.log(
|
|
1079
|
+
console.log(chalk2.dim(` ${t("context.resumeMissing")}`));
|
|
1057
1080
|
return;
|
|
1058
1081
|
}
|
|
1059
1082
|
const drift = checkContextDrift(cwd);
|
|
1060
1083
|
if (drift.checked && drift.stale) {
|
|
1061
|
-
console.log(
|
|
1084
|
+
console.log(chalk2.dim(` ${t("context.resumeStale")}`));
|
|
1062
1085
|
return;
|
|
1063
1086
|
}
|
|
1064
|
-
console.log(
|
|
1087
|
+
console.log(chalk2.dim(` ${t("context.resumeExists")}`));
|
|
1065
1088
|
}
|
|
1066
1089
|
|
|
1067
1090
|
// src/lib/backup.ts
|
|
@@ -1467,85 +1490,88 @@ async function syncCore(rootDir, opts, confirmOverwrite) {
|
|
|
1467
1490
|
return { dryRun: false, firstSync, backupId, backedUp, written, skipped, truncated, plan, unmapped };
|
|
1468
1491
|
}
|
|
1469
1492
|
async function sync(opts = {}) {
|
|
1470
|
-
console.log(
|
|
1493
|
+
console.log(chalk3.bold(`
|
|
1471
1494
|
${ko.sync.title}
|
|
1472
1495
|
`));
|
|
1473
1496
|
const cwd = process.cwd();
|
|
1474
1497
|
const rulesPath = path4.join(cwd, "RULES.md");
|
|
1475
1498
|
if (!fs4.existsSync(rulesPath)) {
|
|
1476
|
-
console.log(
|
|
1477
|
-
console.log(
|
|
1478
|
-
console.log(
|
|
1499
|
+
console.log(chalk3.yellow(ko.sync.noRules));
|
|
1500
|
+
console.log(chalk3.dim(" RULES.md\uB294 \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59\uC758 Single Source of Truth\uC785\uB2C8\uB2E4."));
|
|
1501
|
+
console.log(chalk3.dim(" \uC0DD\uC131\uD558\uB824\uBA74: vhk init \uC2E4\uD589 \uD6C4 RULES.md\uB97C \uC791\uC131\uD558\uC138\uC694."));
|
|
1479
1502
|
console.log("");
|
|
1480
|
-
console.log(
|
|
1481
|
-
console.log(
|
|
1482
|
-
console.log(
|
|
1483
|
-
console.log(
|
|
1484
|
-
console.log(
|
|
1485
|
-
console.log(
|
|
1503
|
+
console.log(chalk3.dim(" RULES.md \uAE30\uBCF8 \uAD6C\uC870:"));
|
|
1504
|
+
console.log(chalk3.dim(" ## \uD504\uB85C\uC81D\uD2B8 \uC815\uCCB4\uC131"));
|
|
1505
|
+
console.log(chalk3.dim(" ## \uAE30\uC220 \uC2A4\uD0DD"));
|
|
1506
|
+
console.log(chalk3.dim(" ## \uCF54\uB529 \uADDC\uCE59"));
|
|
1507
|
+
console.log(chalk3.dim(" ## \uAE30\uB85D \uADDC\uCE59"));
|
|
1508
|
+
console.log(chalk3.dim(" ## \uCEE4\uBC0B \uCEE8\uBCA4\uC158"));
|
|
1486
1509
|
return;
|
|
1487
1510
|
}
|
|
1488
1511
|
const sections = parseRulesMd(fs4.readFileSync(rulesPath, "utf-8"));
|
|
1489
|
-
console.log(
|
|
1490
|
-
const
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1512
|
+
console.log(chalk3.dim(` \u{1F4C4} RULES.md \uD30C\uC2F1 \uC644\uB8CC \u2014 ${sections.length}\uAC1C \uC139\uC158`));
|
|
1513
|
+
const confirmOverwrite = async (drifted) => promptOrDefault(
|
|
1514
|
+
async () => {
|
|
1515
|
+
for (const d of drifted) console.log(chalk3.yellow(` ${ko.sync.driftWarn(d.path)}`));
|
|
1516
|
+
const { confirm } = await inquirer.prompt([
|
|
1517
|
+
{
|
|
1518
|
+
type: "confirm",
|
|
1519
|
+
name: "confirm",
|
|
1520
|
+
message: ko.sync.driftConfirm(drifted.length),
|
|
1521
|
+
default: false
|
|
1522
|
+
}
|
|
1523
|
+
]);
|
|
1524
|
+
return confirm;
|
|
1525
|
+
},
|
|
1526
|
+
true,
|
|
1527
|
+
// 비대화형/--yes → 자동 덮어쓰기(백업이 먼저라 손실 0, 멱등)
|
|
1528
|
+
{ yes: opts.yes }
|
|
1529
|
+
);
|
|
1504
1530
|
const result = await syncCore(cwd, opts, confirmOverwrite);
|
|
1505
1531
|
if (result.unmapped.length) {
|
|
1506
1532
|
console.error(
|
|
1507
|
-
|
|
1533
|
+
chalk3.yellow(
|
|
1508
1534
|
` \u26A0\uFE0F ${result.unmapped.length}\uAC1C \uC139\uC158\uC774 \uC5B4\uB290 \uD0C0\uAE43\uC5D0\uB3C4 \uB9E4\uD551 \uC548 \uB3FC \uC0B0\uCD9C\uBB3C\uC5D0\uC11C \uC81C\uC678\uB428: ${result.unmapped.join(", ")}
|
|
1509
1535
|
(\uCF54\uB529 \uADDC\uCE59/\uAE30\uC220 \uC2A4\uD0DD/\uCEE4\uBC0B/\uAE30\uB85D \uB4F1 \uD45C\uC900 \uC81C\uBAA9\uC744 \uC4F0\uAC70\uB098, \uC774 \uC139\uC158\uC740 RULES.md \uC5D0\uB9CC \uBCF4\uC874\uB429\uB2C8\uB2E4.)`
|
|
1510
1536
|
)
|
|
1511
1537
|
);
|
|
1512
1538
|
}
|
|
1513
1539
|
if (result.dryRun) {
|
|
1514
|
-
console.log(
|
|
1540
|
+
console.log(chalk3.cyan(`
|
|
1515
1541
|
${ko.sync.dryRunHeader}`));
|
|
1516
1542
|
for (const item of result.plan) {
|
|
1517
1543
|
console.log(ko.sync.dryRunWouldWrite(item.path, item.exists && item.drift));
|
|
1518
1544
|
}
|
|
1519
1545
|
const wouldBackup = result.plan.filter((p) => p.exists && (p.drift || result.firstSync)).map((p) => p.path);
|
|
1520
1546
|
if (wouldBackup.length) {
|
|
1521
|
-
console.log(
|
|
1547
|
+
console.log(chalk3.dim(`
|
|
1522
1548
|
\uBC31\uC5C5 \uC608\uC815(${wouldBackup.length}): ${wouldBackup.join(", ")}`));
|
|
1523
1549
|
}
|
|
1524
1550
|
return;
|
|
1525
1551
|
}
|
|
1526
1552
|
if (result.backupId) {
|
|
1527
|
-
if (result.firstSync) console.log(
|
|
1528
|
-
if (!
|
|
1529
|
-
console.log(
|
|
1553
|
+
if (result.firstSync) console.log(chalk3.cyan(` ${ko.sync.firstSync}`));
|
|
1554
|
+
if (!isInteractive(opts)) {
|
|
1555
|
+
console.log(chalk3.yellow(` ${ko.sync.nonTtyAuto(result.backedUp.length, result.backupId)}`));
|
|
1530
1556
|
} else {
|
|
1531
|
-
console.log(
|
|
1557
|
+
console.log(chalk3.cyan(` ${ko.sync.backupSaved(result.backedUp.length, result.backupId)}`));
|
|
1532
1558
|
}
|
|
1533
1559
|
}
|
|
1534
1560
|
for (const p of result.written) {
|
|
1535
1561
|
const item = result.plan.find((i) => i.path === p);
|
|
1536
|
-
if (item) console.log(
|
|
1562
|
+
if (item) console.log(chalk3.green(` ${item.doneMessage}`));
|
|
1537
1563
|
}
|
|
1538
1564
|
for (const _ of result.truncated) {
|
|
1539
|
-
console.log(
|
|
1565
|
+
console.log(chalk3.yellow(` \u26A0\uFE0F ${ko.sync.antigravityTruncated}`));
|
|
1540
1566
|
}
|
|
1541
1567
|
for (const p of result.skipped) {
|
|
1542
|
-
console.log(
|
|
1568
|
+
console.log(chalk3.gray(` ${ko.sync.skipped(p)}`));
|
|
1543
1569
|
}
|
|
1544
|
-
console.log(
|
|
1570
|
+
console.log(chalk3.bold.green(`
|
|
1545
1571
|
${ko.sync.done}`));
|
|
1546
|
-
console.log(
|
|
1547
|
-
console.log(
|
|
1548
|
-
console.log(
|
|
1572
|
+
console.log(chalk3.dim(" RULES.md (\uC6D0\uBCF8) \u2192 .cursorrules + CLAUDE.md + .windsurfrules"));
|
|
1573
|
+
console.log(chalk3.dim(" + .github/copilot-instructions.md + .agents/rules/vhk-rules.md (\uC790\uB3D9 \uC0DD\uC131)"));
|
|
1574
|
+
console.log(chalk3.dim(" \uADDC\uCE59 \uBCC0\uACBD\uC740 \uD56D\uC0C1 RULES.md\uC5D0\uC11C\uB9CC \uD558\uC138\uC694."));
|
|
1549
1575
|
printNextStep({
|
|
1550
1576
|
message: "\uADDC\uCE59 \uB3D9\uAE30\uD654 \uC644\uB8CC! \uC774\uC81C Cursor\uAC00 \uC0C8 \uADDC\uCE59\uC744 \uB530\uB985\uB2C8\uB2E4.",
|
|
1551
1577
|
command: "vhk \uC810\uAC80",
|
|
@@ -1555,7 +1581,7 @@ ${ko.sync.done}`));
|
|
|
1555
1581
|
|
|
1556
1582
|
// src/commands/deploy.ts
|
|
1557
1583
|
import { existsSync as existsSync2 } from "fs";
|
|
1558
|
-
import
|
|
1584
|
+
import chalk4 from "chalk";
|
|
1559
1585
|
import inquirer2 from "inquirer";
|
|
1560
1586
|
|
|
1561
1587
|
// src/lib/exec.ts
|
|
@@ -1664,11 +1690,11 @@ function isCLIAvailable(cmd, checkArgs) {
|
|
|
1664
1690
|
return safeExecFile(cmd, checkArgs).ok;
|
|
1665
1691
|
}
|
|
1666
1692
|
async function deploy() {
|
|
1667
|
-
console.log(
|
|
1668
|
-
console.log(
|
|
1693
|
+
console.log(chalk4.bold("\n\u{1F680} " + t("deploy.title")));
|
|
1694
|
+
console.log(chalk4.gray("\u2500".repeat(40)));
|
|
1669
1695
|
let platform = detectPlatform();
|
|
1670
1696
|
if (platform) {
|
|
1671
|
-
console.log(
|
|
1697
|
+
console.log(chalk4.cyan(`
|
|
1672
1698
|
\u{1F50D} \uAC10\uC9C0\uB41C \uD50C\uB7AB\uD3FC: ${PLATFORMS[platform].name}`));
|
|
1673
1699
|
} else {
|
|
1674
1700
|
const { selected } = await inquirer2.prompt([
|
|
@@ -1687,9 +1713,9 @@ async function deploy() {
|
|
|
1687
1713
|
}
|
|
1688
1714
|
const config = PLATFORMS[platform];
|
|
1689
1715
|
if (!isCLIAvailable(config.command, config.checkArgs)) {
|
|
1690
|
-
console.log(
|
|
1716
|
+
console.log(chalk4.red(`
|
|
1691
1717
|
\u274C ${config.name} CLI\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.`));
|
|
1692
|
-
console.log(
|
|
1718
|
+
console.log(chalk4.yellow(` \u2192 ${config.installHint}`));
|
|
1693
1719
|
return;
|
|
1694
1720
|
}
|
|
1695
1721
|
const { confirm } = await inquirer2.prompt([
|
|
@@ -1701,15 +1727,15 @@ async function deploy() {
|
|
|
1701
1727
|
}
|
|
1702
1728
|
]);
|
|
1703
1729
|
if (!confirm) {
|
|
1704
|
-
console.log(
|
|
1730
|
+
console.log(chalk4.gray("\uCDE8\uC18C\uB428"));
|
|
1705
1731
|
return;
|
|
1706
1732
|
}
|
|
1707
|
-
console.log(
|
|
1733
|
+
console.log(chalk4.cyan(`
|
|
1708
1734
|
${t("deploy.deploying")}
|
|
1709
1735
|
`));
|
|
1710
1736
|
const result = safeExecFileStream(config.command, config.commandArgs);
|
|
1711
1737
|
if (result.ok) {
|
|
1712
|
-
console.log(
|
|
1738
|
+
console.log(chalk4.green(`
|
|
1713
1739
|
\u2705 ${t("deploy.success")}`));
|
|
1714
1740
|
printNextStep({
|
|
1715
1741
|
message: "\uBC30\uD3EC \uC644\uB8CC! \uC0AC\uC774\uD2B8\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
@@ -1717,16 +1743,16 @@ ${t("deploy.deploying")}
|
|
|
1717
1743
|
cursorHint: "\uC0C1\uD0DC \uD655\uC778\uD574\uC918"
|
|
1718
1744
|
});
|
|
1719
1745
|
} else {
|
|
1720
|
-
console.log(
|
|
1746
|
+
console.log(chalk4.red(`
|
|
1721
1747
|
\u274C ${t("deploy.failed")}`));
|
|
1722
|
-
console.log(
|
|
1748
|
+
console.log(chalk4.red(result.err));
|
|
1723
1749
|
}
|
|
1724
1750
|
}
|
|
1725
1751
|
|
|
1726
1752
|
// src/commands/env.ts
|
|
1727
1753
|
import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync, appendFileSync, readdirSync } from "fs";
|
|
1728
1754
|
import { join as join2 } from "path";
|
|
1729
|
-
import
|
|
1755
|
+
import chalk5 from "chalk";
|
|
1730
1756
|
function parseEnvKeys(content) {
|
|
1731
1757
|
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.split("=")[0].trim()).filter(Boolean);
|
|
1732
1758
|
}
|
|
@@ -1754,32 +1780,32 @@ function ensureGitignore() {
|
|
|
1754
1780
|
const content = readFileSync2(gitignorePath, "utf-8");
|
|
1755
1781
|
if (!content.split("\n").some((l) => l.trim() === ".env")) {
|
|
1756
1782
|
appendFileSync(gitignorePath, "\n.env\n");
|
|
1757
|
-
console.log(
|
|
1783
|
+
console.log(chalk5.green("\n\u{1F512} .gitignore\uC5D0 .env \uCD94\uAC00\uB428"));
|
|
1758
1784
|
}
|
|
1759
1785
|
} else {
|
|
1760
1786
|
writeFileSync(gitignorePath, ".env\nnode_modules/\ndist/\n");
|
|
1761
|
-
console.log(
|
|
1787
|
+
console.log(chalk5.green("\n\u{1F512} .gitignore \uC0DD\uC131 (.env \uD3EC\uD568)"));
|
|
1762
1788
|
}
|
|
1763
1789
|
}
|
|
1764
1790
|
async function env() {
|
|
1765
|
-
console.log(
|
|
1766
|
-
console.log(
|
|
1791
|
+
console.log(chalk5.bold("\n\u{1F510} " + t("env.title")));
|
|
1792
|
+
console.log(chalk5.gray("\u2500".repeat(40)));
|
|
1767
1793
|
if (!existsSync3(".env")) {
|
|
1768
|
-
console.log(
|
|
1769
|
-
console.log(
|
|
1794
|
+
console.log(chalk5.yellow("\n\u26A0\uFE0F .env \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
1795
|
+
console.log(chalk5.gray(" .env \uD30C\uC77C\uC744 \uBA3C\uC800 \uB9CC\uB4E4\uC5B4\uC8FC\uC138\uC694."));
|
|
1770
1796
|
return;
|
|
1771
1797
|
}
|
|
1772
1798
|
const envContent = readFileSync2(".env", "utf-8");
|
|
1773
1799
|
const keys = parseEnvKeys(envContent);
|
|
1774
1800
|
if (keys.length === 0) {
|
|
1775
|
-
console.log(
|
|
1801
|
+
console.log(chalk5.yellow("\n\u{1F4ED} .env\uC5D0 \uD658\uACBD\uBCC0\uC218\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
1776
1802
|
return;
|
|
1777
1803
|
}
|
|
1778
1804
|
const exampleContent = keys.map((k) => `${k}=`).join("\n") + "\n";
|
|
1779
1805
|
writeFileSync(".env.example", exampleContent, "utf-8");
|
|
1780
|
-
console.log(
|
|
1806
|
+
console.log(chalk5.green(`
|
|
1781
1807
|
\u2705 .env.example \uC0DD\uC131 (${keys.length}\uAC1C \uD0A4)`));
|
|
1782
|
-
keys.forEach((k) => console.log(
|
|
1808
|
+
keys.forEach((k) => console.log(chalk5.gray(` ${k}`)));
|
|
1783
1809
|
ensureGitignore();
|
|
1784
1810
|
printNextStep({
|
|
1785
1811
|
message: ".env.example \uC0DD\uC131 \uC644\uB8CC!",
|
|
@@ -1788,37 +1814,37 @@ async function env() {
|
|
|
1788
1814
|
});
|
|
1789
1815
|
}
|
|
1790
1816
|
async function envCheck() {
|
|
1791
|
-
console.log(
|
|
1792
|
-
console.log(
|
|
1817
|
+
console.log(chalk5.bold("\n\u{1F50D} " + t("env.checkTitle")));
|
|
1818
|
+
console.log(chalk5.gray("\u2500".repeat(40)));
|
|
1793
1819
|
if (!existsSync3(".env.example")) {
|
|
1794
|
-
console.log(
|
|
1820
|
+
console.log(chalk5.yellow("\n\u26A0\uFE0F .env.example\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 vhk env\uB97C \uC2E4\uD589\uD558\uC138\uC694."));
|
|
1795
1821
|
return;
|
|
1796
1822
|
}
|
|
1797
1823
|
const requiredKeys = parseEnvKeys(readFileSync2(".env.example", "utf-8"));
|
|
1798
1824
|
const currentKeys = loadDefinedEnvKeys();
|
|
1799
1825
|
const missing = requiredKeys.filter((k) => !currentKeys.includes(k));
|
|
1800
1826
|
const extra = currentKeys.filter((k) => !requiredKeys.includes(k));
|
|
1801
|
-
console.log(
|
|
1827
|
+
console.log(chalk5.cyan(`
|
|
1802
1828
|
\u{1F4CB} \uD544\uC218 \uD658\uACBD\uBCC0\uC218: ${requiredKeys.length}\uAC1C`));
|
|
1803
1829
|
if (missing.length === 0) {
|
|
1804
|
-
console.log(
|
|
1830
|
+
console.log(chalk5.green("\n\u2705 \uBAA8\uB4E0 \uD544\uC218 \uD658\uACBD\uBCC0\uC218\uAC00 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4!"));
|
|
1805
1831
|
} else {
|
|
1806
|
-
console.log(
|
|
1832
|
+
console.log(chalk5.red(`
|
|
1807
1833
|
\u274C \uB204\uB77D\uB41C \uD658\uACBD\uBCC0\uC218 (${missing.length}\uAC1C):`));
|
|
1808
|
-
missing.forEach((k) => console.log(
|
|
1834
|
+
missing.forEach((k) => console.log(chalk5.red(` \u2022 ${k}`)));
|
|
1809
1835
|
process.exitCode = 1;
|
|
1810
1836
|
}
|
|
1811
1837
|
if (extra.length > 0) {
|
|
1812
|
-
console.log(
|
|
1838
|
+
console.log(chalk5.yellow(`
|
|
1813
1839
|
\u{1F4A1} .env.example\uC5D0 \uC5C6\uB294 \uCD94\uAC00 \uBCC0\uC218 (${extra.length}\uAC1C):`));
|
|
1814
|
-
extra.forEach((k) => console.log(
|
|
1840
|
+
extra.forEach((k) => console.log(chalk5.yellow(` \u2022 ${k}`)));
|
|
1815
1841
|
}
|
|
1816
1842
|
ensureGitignore();
|
|
1817
1843
|
}
|
|
1818
1844
|
|
|
1819
1845
|
// src/commands/publish.ts
|
|
1820
1846
|
import { existsSync as existsSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
1821
|
-
import
|
|
1847
|
+
import chalk6 from "chalk";
|
|
1822
1848
|
import inquirer3 from "inquirer";
|
|
1823
1849
|
import ora from "ora";
|
|
1824
1850
|
|
|
@@ -1887,21 +1913,21 @@ function gitPostRelease(newVersion) {
|
|
|
1887
1913
|
};
|
|
1888
1914
|
}
|
|
1889
1915
|
async function publish() {
|
|
1890
|
-
console.log(
|
|
1891
|
-
console.log(
|
|
1916
|
+
console.log(chalk6.bold("\n\u{1F4E6} " + t("publish.title")));
|
|
1917
|
+
console.log(chalk6.gray("\u2500".repeat(40)));
|
|
1892
1918
|
if (!existsSync4("package.json")) {
|
|
1893
|
-
console.log(
|
|
1919
|
+
console.log(chalk6.red("\u274C package.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
1894
1920
|
return;
|
|
1895
1921
|
}
|
|
1896
1922
|
let pkg;
|
|
1897
1923
|
try {
|
|
1898
1924
|
pkg = readJsonFile("package.json");
|
|
1899
1925
|
} catch {
|
|
1900
|
-
console.log(
|
|
1926
|
+
console.log(chalk6.red("\u274C package.json \uD30C\uC2F1 \uC2E4\uD328"));
|
|
1901
1927
|
return;
|
|
1902
1928
|
}
|
|
1903
1929
|
const currentVersion = pkg.version || "0.0.0";
|
|
1904
|
-
console.log(
|
|
1930
|
+
console.log(chalk6.cyan(`
|
|
1905
1931
|
\u{1F4CC} \uD604\uC7AC \uBC84\uC804: v${currentVersion}`));
|
|
1906
1932
|
const { bumpType } = await inquirer3.prompt([
|
|
1907
1933
|
{
|
|
@@ -1916,16 +1942,16 @@ async function publish() {
|
|
|
1916
1942
|
}
|
|
1917
1943
|
]);
|
|
1918
1944
|
const newVersion = bumpVersion(currentVersion, bumpType);
|
|
1919
|
-
console.log(
|
|
1945
|
+
console.log(chalk6.cyan(`
|
|
1920
1946
|
\u{1F195} \uC0C8 \uBC84\uC804: v${newVersion}`));
|
|
1921
1947
|
pkg.version = newVersion;
|
|
1922
1948
|
writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
1923
|
-
console.log(
|
|
1949
|
+
console.log(chalk6.green("\u2705 package.json \uBC84\uC804 \uC5C5\uB370\uC774\uD2B8"));
|
|
1924
1950
|
const buildSpinner = ora(t("publish.building")).start();
|
|
1925
1951
|
const buildResult = safeExecFile("pnpm", ["build"]);
|
|
1926
1952
|
if (!buildResult.ok) {
|
|
1927
1953
|
buildSpinner.fail(t("publish.buildFailed"));
|
|
1928
|
-
console.log(
|
|
1954
|
+
console.log(chalk6.red(buildResult.err.slice(0, 500)));
|
|
1929
1955
|
pkg.version = currentVersion;
|
|
1930
1956
|
writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
1931
1957
|
return;
|
|
@@ -1935,7 +1961,7 @@ async function publish() {
|
|
|
1935
1961
|
const testResult = safeExecFile("pnpm", ["test", "--run"]);
|
|
1936
1962
|
if (!testResult.ok) {
|
|
1937
1963
|
testSpinner.fail(t("publish.testFailed"));
|
|
1938
|
-
console.log(
|
|
1964
|
+
console.log(chalk6.red(testResult.err.slice(0, 500)));
|
|
1939
1965
|
pkg.version = currentVersion;
|
|
1940
1966
|
writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
1941
1967
|
return;
|
|
@@ -1952,37 +1978,37 @@ async function publish() {
|
|
|
1952
1978
|
if (!confirm) {
|
|
1953
1979
|
pkg.version = currentVersion;
|
|
1954
1980
|
writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
1955
|
-
console.log(
|
|
1981
|
+
console.log(chalk6.gray("\uCDE8\uC18C\uB428. \uBC84\uC804\uC774 \uC6D0\uB798\uB300\uB85C \uBCF5\uAD6C\uB429\uB2C8\uB2E4."));
|
|
1956
1982
|
return;
|
|
1957
1983
|
}
|
|
1958
|
-
console.log(
|
|
1984
|
+
console.log(chalk6.cyan(`
|
|
1959
1985
|
\u{1F4E4} ${t("publish.publishing")}`));
|
|
1960
|
-
console.log(
|
|
1986
|
+
console.log(chalk6.gray(" 2FA \uD65C\uC131\uD654 \uC2DC: OTP 6\uC790\uB9AC \uC785\uB825 \uB610\uB294 \uBE0C\uB77C\uC6B0\uC800 \uC778\uC99D URL \uD074\uB9AD (Windows Hello / PIN \uC9C0\uC6D0)"));
|
|
1961
1987
|
const pubResult = safeExecFileStream("npm", ["publish", "--access", "public"]);
|
|
1962
1988
|
if (!pubResult.ok) {
|
|
1963
|
-
console.log(
|
|
1989
|
+
console.log(chalk6.red(`
|
|
1964
1990
|
\u2716 ${t("publish.publishFailed")}`));
|
|
1965
|
-
console.log(
|
|
1991
|
+
console.log(chalk6.red(pubResult.err.slice(0, 500)));
|
|
1966
1992
|
pkg.version = currentVersion;
|
|
1967
1993
|
writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
1968
|
-
console.log(
|
|
1994
|
+
console.log(chalk6.gray(`\u{1F4E6} package.json \uBC84\uC804\uC744 v${currentVersion}\uB85C \uBCF5\uAD6C\uD588\uC2B5\uB2C8\uB2E4.`));
|
|
1969
1995
|
return;
|
|
1970
1996
|
}
|
|
1971
|
-
console.log(
|
|
1997
|
+
console.log(chalk6.green(`
|
|
1972
1998
|
\u2714 ${t("publish.publishSuccess")}`));
|
|
1973
1999
|
const git = gitPostRelease(newVersion);
|
|
1974
2000
|
if (git.warning) {
|
|
1975
|
-
console.log(
|
|
2001
|
+
console.log(chalk6.yellow(`
|
|
1976
2002
|
\u26A0\uFE0F ${git.warning}`));
|
|
1977
|
-
console.log(
|
|
2003
|
+
console.log(chalk6.dim(` npm \uBC30\uD3EC\uB294 \uC774\uBBF8 \uC131\uACF5\uD588\uC2B5\uB2C8\uB2E4 (v${newVersion}).`));
|
|
1978
2004
|
} else if (git.tagged && git.pushed) {
|
|
1979
|
-
console.log(
|
|
2005
|
+
console.log(chalk6.green(`
|
|
1980
2006
|
\u{1F3F7}\uFE0F git tag v${newVersion} \uC0DD\uC131 + push \uC644\uB8CC`));
|
|
1981
2007
|
} else if (git.tagged) {
|
|
1982
|
-
console.log(
|
|
2008
|
+
console.log(chalk6.yellow(`
|
|
1983
2009
|
\u{1F3F7}\uFE0F git tag v${newVersion} \uC0DD\uC131\uB428 (push\uB294 \uC218\uB3D9\uC73C\uB85C)`));
|
|
1984
2010
|
}
|
|
1985
|
-
console.log(
|
|
2011
|
+
console.log(chalk6.green.bold(`
|
|
1986
2012
|
\u{1F389} v${newVersion} \uBC30\uD3EC \uC644\uB8CC!`));
|
|
1987
2013
|
printNextStep({
|
|
1988
2014
|
message: "npm \uBC30\uD3EC \uC644\uB8CC!",
|
|
@@ -1993,7 +2019,7 @@ async function publish() {
|
|
|
1993
2019
|
|
|
1994
2020
|
// src/commands/audit.ts
|
|
1995
2021
|
import { existsSync as existsSync5 } from "fs";
|
|
1996
|
-
import
|
|
2022
|
+
import chalk7 from "chalk";
|
|
1997
2023
|
import inquirer4 from "inquirer";
|
|
1998
2024
|
import ora2 from "ora";
|
|
1999
2025
|
function detectCurrentPM() {
|
|
@@ -2038,24 +2064,24 @@ function runAuditFix(pm) {
|
|
|
2038
2064
|
return result.ok ? { ok: true } : { ok: false, err: result.err };
|
|
2039
2065
|
}
|
|
2040
2066
|
async function audit(autoFix = false) {
|
|
2041
|
-
console.log(
|
|
2042
|
-
console.log(
|
|
2067
|
+
console.log(chalk7.bold("\n\u{1F6E1}\uFE0F " + t("audit.title")));
|
|
2068
|
+
console.log(chalk7.gray("\u2500".repeat(40)));
|
|
2043
2069
|
const pm = detectCurrentPM();
|
|
2044
|
-
console.log(
|
|
2070
|
+
console.log(chalk7.cyan(`\u{1F4E6} \uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800: ${pm}`));
|
|
2045
2071
|
const spinner = ora2("\uBCF4\uC548 \uAC10\uC0AC \uC2E4\uD589 \uC911...").start();
|
|
2046
2072
|
const output = runAuditJson(pm);
|
|
2047
2073
|
spinner.stop();
|
|
2048
2074
|
const summary = parseAuditOutput(output, pm);
|
|
2049
2075
|
if (summary.total === 0) {
|
|
2050
|
-
console.log(
|
|
2076
|
+
console.log(chalk7.green.bold("\n\u{1F389} \uCDE8\uC57D\uC810\uC774 \uBC1C\uACAC\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4!"));
|
|
2051
2077
|
return;
|
|
2052
2078
|
}
|
|
2053
|
-
console.log(
|
|
2054
|
-
if (summary.critical > 0) console.log(
|
|
2055
|
-
if (summary.high > 0) console.log(
|
|
2056
|
-
if (summary.moderate > 0) console.log(
|
|
2057
|
-
if (summary.low > 0) console.log(
|
|
2058
|
-
console.log(
|
|
2079
|
+
console.log(chalk7.bold("\n\u{1F4CA} \uCDE8\uC57D\uC810 \uC694\uC57D:"));
|
|
2080
|
+
if (summary.critical > 0) console.log(chalk7.red(` \u{1F534} Critical: ${summary.critical}`));
|
|
2081
|
+
if (summary.high > 0) console.log(chalk7.red(` \u{1F7E0} High: ${summary.high}`));
|
|
2082
|
+
if (summary.moderate > 0) console.log(chalk7.yellow(` \u{1F7E1} Moderate: ${summary.moderate}`));
|
|
2083
|
+
if (summary.low > 0) console.log(chalk7.gray(` \u26AA Low: ${summary.low}`));
|
|
2084
|
+
console.log(chalk7.bold(`
|
|
2059
2085
|
\uCD1D ${summary.total}\uAC1C\uC758 \uCDE8\uC57D\uC810`));
|
|
2060
2086
|
const shouldRunFix = autoFix ? true : summary.critical > 0 || summary.high > 0 ? (await inquirer4.prompt([
|
|
2061
2087
|
{
|
|
@@ -2205,7 +2231,7 @@ import path6 from "path";
|
|
|
2205
2231
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
2206
2232
|
import fs5 from "fs";
|
|
2207
2233
|
import path5 from "path";
|
|
2208
|
-
import
|
|
2234
|
+
import chalk8 from "chalk";
|
|
2209
2235
|
function loadGitignore(rootDir) {
|
|
2210
2236
|
const ig = (0, import_ignore.default)();
|
|
2211
2237
|
const gitignorePath = path5.join(rootDir, ".gitignore");
|
|
@@ -2279,7 +2305,7 @@ function printSecurityWarnings(rootDir = process.cwd()) {
|
|
|
2279
2305
|
const result = checkProjectSecurity(rootDir);
|
|
2280
2306
|
if (result.ok) return true;
|
|
2281
2307
|
for (const w of result.warnings) {
|
|
2282
|
-
console.log(
|
|
2308
|
+
console.log(chalk8.yellow(` \u26A0\uFE0F ${w}`));
|
|
2283
2309
|
}
|
|
2284
2310
|
return false;
|
|
2285
2311
|
}
|
|
@@ -2965,6 +2991,10 @@ export {
|
|
|
2965
2991
|
restoreBackup,
|
|
2966
2992
|
detectExistingRuleFiles,
|
|
2967
2993
|
buildAdoptedRules,
|
|
2994
|
+
isInteractive,
|
|
2995
|
+
promptOrDefault,
|
|
2996
|
+
ensureInteractive,
|
|
2997
|
+
isPromptAbortError,
|
|
2968
2998
|
sync,
|
|
2969
2999
|
getGitRoot,
|
|
2970
3000
|
gitOut,
|