@byh3071/vhk 0.6.0 → 0.7.1
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 +5 -1
- package/dist/chunk-3HHU7V77.js +770 -0
- package/dist/index.js +524 -524
- package/dist/mcp/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-IU37BEQA.js +0 -298
package/dist/index.js
CHANGED
|
@@ -2,8 +2,15 @@
|
|
|
2
2
|
import {
|
|
3
3
|
__commonJS,
|
|
4
4
|
__toESM,
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
env,
|
|
6
|
+
envCheck,
|
|
7
|
+
ko,
|
|
8
|
+
printNextStep,
|
|
9
|
+
safeExecFile,
|
|
10
|
+
safeExecFileStream,
|
|
11
|
+
startMcpServer,
|
|
12
|
+
t
|
|
13
|
+
} from "./chunk-3HHU7V77.js";
|
|
7
14
|
|
|
8
15
|
// node_modules/.pnpm/ignore@7.0.5/node_modules/ignore/index.js
|
|
9
16
|
var require_ignore = __commonJS({
|
|
@@ -465,7 +472,7 @@ var require_ignore = __commonJS({
|
|
|
465
472
|
|
|
466
473
|
// src/index.ts
|
|
467
474
|
import { Command, Help } from "commander";
|
|
468
|
-
import
|
|
475
|
+
import inquirer10 from "inquirer";
|
|
469
476
|
|
|
470
477
|
// src/lib/nlp-router.ts
|
|
471
478
|
function normalize(input) {
|
|
@@ -571,9 +578,33 @@ var RULES = [
|
|
|
571
578
|
},
|
|
572
579
|
{
|
|
573
580
|
command: "ship",
|
|
574
|
-
explanation: "\uBC30\uD3EC \uCCB4\uD06C + \uD68C\uACE0 (vhk
|
|
581
|
+
explanation: "\uBC30\uD3EC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 + \uD68C\uACE0 (vhk \uCD9C\uD558)",
|
|
582
|
+
confidence: "high",
|
|
583
|
+
test: (t2) => /^출하$|^ship$|빌드\s*전|(배포|출하)\s*(체크|준비|점검)/.test(t2)
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
command: "deploy",
|
|
587
|
+
explanation: "\uD504\uB85C\uB355\uC158 \uBC30\uD3EC (vhk deploy)",
|
|
588
|
+
confidence: "high",
|
|
589
|
+
test: (t2) => /^배포$|배포\s*해|배포하|배포해줘|^deploy$|디플로이|vercel|netlify|cloudflare|wrangler|프로덕션|올려줘/.test(t2) && !/체크|준비|점검|출하|회고|빌드\s*전/.test(t2)
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
command: "env-check",
|
|
593
|
+
explanation: "\uD658\uACBD\uBCC0\uC218 \uB204\uB77D \uAC80\uC0AC (vhk env-check)",
|
|
594
|
+
confidence: "high",
|
|
595
|
+
test: (t2) => /환경변수\s*(점검|확인|누락)|env\s*(체크|확인|check)|키\s*(확인|누락)/.test(t2)
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
command: "env",
|
|
599
|
+
explanation: "\uD658\uACBD\uBCC0\uC218 \uAD00\uB9AC (vhk env)",
|
|
600
|
+
confidence: "high",
|
|
601
|
+
test: (t2) => /환경변수|\.env|env\s*example|env\s*동기화|시크릿\s*정리|키\s*설정/.test(t2) && !/점검|확인|누락|체크|check/.test(t2)
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
command: "publish",
|
|
605
|
+
explanation: "npm \uBC30\uD3EC (vhk publish)",
|
|
575
606
|
confidence: "high",
|
|
576
|
-
test: (t2) =>
|
|
607
|
+
test: (t2) => /^출시$|출시\s*해|^publish$|퍼블리시|npm\s*(배포|출시)|버전\s*올|^릴리즈$|^release$/.test(t2) && !/체크|준비|회고/.test(t2)
|
|
577
608
|
}
|
|
578
609
|
];
|
|
579
610
|
function routeNaturalLanguage(input) {
|
|
@@ -618,8 +649,6 @@ var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
|
|
|
618
649
|
"scan",
|
|
619
650
|
"\uC2A4\uCE94",
|
|
620
651
|
"ship",
|
|
621
|
-
"\uBC30\uD3EC",
|
|
622
|
-
"\uB9B4\uB9AC\uC988",
|
|
623
652
|
"doctor",
|
|
624
653
|
"\uD658\uACBD",
|
|
625
654
|
"\uC9C4\uB2E8",
|
|
@@ -636,6 +665,15 @@ var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
|
|
|
636
665
|
"mcp",
|
|
637
666
|
"mcp-init",
|
|
638
667
|
"mcp\uC124\uC815",
|
|
668
|
+
"deploy",
|
|
669
|
+
"\uBC30\uD3EC",
|
|
670
|
+
"env",
|
|
671
|
+
"\uD658\uACBD\uBCC0\uC218",
|
|
672
|
+
"env-check",
|
|
673
|
+
"\uD658\uACBD\uBCC0\uC218\uC810\uAC80",
|
|
674
|
+
"publish",
|
|
675
|
+
"\uCD9C\uC2DC",
|
|
676
|
+
"\uCD9C\uD558",
|
|
639
677
|
"help"
|
|
640
678
|
]);
|
|
641
679
|
function isOptionToken(token) {
|
|
@@ -659,306 +697,12 @@ function detectNaturalLanguageInput(argv) {
|
|
|
659
697
|
}
|
|
660
698
|
|
|
661
699
|
// src/lib/nlp-run.ts
|
|
662
|
-
import
|
|
663
|
-
import
|
|
664
|
-
|
|
665
|
-
// src/i18n/ko.ts
|
|
666
|
-
var ko = {
|
|
667
|
-
status: {
|
|
668
|
-
title: "\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC",
|
|
669
|
-
notGitRepo: "Git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2C8\uC5D0\uC694. \uBA3C\uC800 git init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
|
|
670
|
-
branch: "\uBE0C\uB79C\uCE58:",
|
|
671
|
-
changes: "\uBCC0\uACBD:",
|
|
672
|
-
recentCommits: "\uCD5C\uADFC \uCEE4\uBC0B (3):",
|
|
673
|
-
noCommits: "\uCEE4\uBC0B \uC5C6\uC74C",
|
|
674
|
-
remote: "\uC6D0\uACA9:",
|
|
675
|
-
noUpstream: "upstream \uC5C6\uC74C",
|
|
676
|
-
inSync: "\uB3D9\uAE30\uD654\uB428",
|
|
677
|
-
ahead: (n) => `\u2191${n} ahead`,
|
|
678
|
-
behind: (n) => `\u2193${n} behind`,
|
|
679
|
-
package: "package.json:",
|
|
680
|
-
noPackage: "package.json \uC5C6\uC74C",
|
|
681
|
-
detached: "(detached HEAD)",
|
|
682
|
-
unknownBranch: "(\uC54C \uC218 \uC5C6\uC74C)"
|
|
683
|
-
},
|
|
684
|
-
save: {
|
|
685
|
-
title: "\uC800\uC7A5\uD558\uAE30",
|
|
686
|
-
notGitRepo: "git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4. \uBA3C\uC800 git init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
|
|
687
|
-
noChanges: "\uC800\uC7A5\uD560 \uBCC0\uACBD\uC0AC\uD56D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
688
|
-
filesHeader: (n) => `\uBCC0\uACBD\uB41C \uD30C\uC77C (${n}\uAC1C):`,
|
|
689
|
-
commitMessage: "\uCEE4\uBC0B \uBA54\uC2DC\uC9C0 (Enter\uB85C \uAE30\uBCF8\uAC12 \uC0AC\uC6A9):",
|
|
690
|
-
saving: "\uC800\uC7A5 \uC911...",
|
|
691
|
-
pushing: "\uC6D0\uACA9 \uC800\uC7A5\uC18C\uC5D0 \uC62C\uB9AC\uB294 \uC911...",
|
|
692
|
-
successWithPush: "\uC800\uC7A5 + \uC6D0\uACA9 \uC5C5\uB85C\uB4DC \uC644\uB8CC!",
|
|
693
|
-
successLocal: "\uB85C\uCEEC \uC800\uC7A5 \uC644\uB8CC!",
|
|
694
|
-
noRemote: "\uC6D0\uACA9 \uC800\uC7A5\uC18C\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC544 push\uB97C \uAC74\uB108\uB6F0\uC5C8\uC2B5\uB2C8\uB2E4.",
|
|
695
|
-
failed: "\uC800\uC7A5 \uC2E4\uD328",
|
|
696
|
-
stagedAfterFail: "\uCEE4\uBC0B\uC740 \uC2E4\uD328\uD588\uC9C0\uB9CC \uD30C\uC77C\uC740 \uC2A4\uD14C\uC774\uC9D5\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4. \uD655\uC778: git status / \uCDE8\uC18C: git reset HEAD",
|
|
697
|
-
securityWarnHeader: "\uC800\uC7A5 \uC804 \uBCF4\uC548 \uD655\uC778:",
|
|
698
|
-
secretsFound: (n) => `\uCF54\uB4DC\uC5D0\uC11C CRITICAL/HIGH \uC2DC\uD06C\uB9BF \uD328\uD134 ${n}\uAC74 \uAC10\uC9C0`,
|
|
699
|
-
secretsConfirm: "\uADF8\uB798\uB3C4 \uCEE4\uBC0B\xB7push\uB97C \uC9C4\uD589\uD560\uAE4C\uC694?",
|
|
700
|
-
cancelled: "\uC800\uC7A5\uC744 \uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4.",
|
|
701
|
-
pushFailed: "push \uC2E4\uD328 (\uB85C\uCEEC \uCEE4\uBC0B\uC740 \uC644\uB8CC\uB428)",
|
|
702
|
-
commitOkPushFailed: "\uB85C\uCEEC \uCEE4\uBC0B\uC740 \uB410\uC9C0\uB9CC \uC6D0\uACA9 push\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. git push\uB97C \uC9C1\uC811 \uD655\uC778\uD558\uC138\uC694.",
|
|
703
|
-
done: (n) => `${n}\uAC1C \uD30C\uC77C \uC800\uC7A5 \uC644\uB8CC!`,
|
|
704
|
-
doneLocalOnly: (n) => `${n}\uAC1C \uD30C\uC77C \uB85C\uCEEC \uC800\uC7A5\uB428 (push\uB294 \uC2E4\uD328)`
|
|
705
|
-
},
|
|
706
|
-
undo: {
|
|
707
|
-
title: "\uB418\uB3CC\uB9AC\uAE30",
|
|
708
|
-
notGitRepo: "git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
709
|
-
noCommits: "\uB418\uB3CC\uB9B4 \uCEE4\uBC0B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
710
|
-
recentHeader: "\u{1F4CB} \uCD5C\uADFC \uCEE4\uBC0B:",
|
|
711
|
-
howMany: "\uBA87 \uAC1C\uC758 \uCEE4\uBC0B\uC744 \uB418\uB3CC\uB9B4\uAE4C\uC694?",
|
|
712
|
-
alreadyPushed: "\uC774 \uCEE4\uBC0B\uC740 \uC774\uBBF8 \uC6D0\uACA9\uC5D0 \uC62C\uB77C\uAC14\uC2B5\uB2C8\uB2E4. \uB418\uB3CC\uB9AC\uBA74 \uCDA9\uB3CC\uC774 \uC0DD\uAE38 \uC218 \uC788\uC5B4\uC694.",
|
|
713
|
-
noUpstreamWarning: "upstream \uBE0C\uB79C\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uC774\uBBF8 push\uD55C \uCEE4\uBC0B\uC77C \uC218 \uC788\uC5B4\uC694. \uB418\uB3CC\uB9B0 \uB4A4 force push\uAC00 \uD544\uC694\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
714
|
-
confirmMessage: "\uCD5C\uADFC \uCEE4\uBC0B\uC744 \uB418\uB3CC\uB9AC\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
|
|
715
|
-
confirmRisky: (n) => `\u26A0\uFE0F \uC704\uD5D8: \uCD5C\uADFC ${n}\uAC1C \uCEE4\uBC0B\uC744 soft reset\uD569\uB2C8\uB2E4. \uC6D0\uACA9\uACFC \uC5B4\uAE0B\uB0A0 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uACC4\uC18D\uD560\uAE4C\uC694?`,
|
|
716
|
-
cancelled: "\uCDE8\uC18C\uB428",
|
|
717
|
-
success: "\uB418\uB3CC\uB9AC\uAE30 \uC644\uB8CC! \uBCC0\uACBD\uC0AC\uD56D\uC740 \uADF8\uB300\uB85C \uB0A8\uC544\uC788\uC2B5\uB2C8\uB2E4.",
|
|
718
|
-
stagedHint: "\uBCC0\uACBD\uC0AC\uD56D\uC740 \uC2A4\uD14C\uC774\uC9D5 \uC601\uC5ED\uC5D0 \uB0A8\uC544 \uC788\uC5B4\uC694.",
|
|
719
|
-
rootCommit: "\uCCAB \uCEE4\uBC0B\uB9CC \uC788\uC5B4\uC11C \uB354 \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
720
|
-
forcePushHint: "\uC6D0\uACA9\uACFC \uB9DE\uCD94\uB824\uBA74: git push --force-with-lease (\uD63C\uC790 \uC791\uC5C5\uD55C \uBE0C\uB79C\uCE58\uC5D0\uC11C\uB9CC, \uD300\uACFC \uD569\uC758 \uD6C4)",
|
|
721
|
-
failed: "\uB418\uB3CC\uB9AC\uAE30 \uC2E4\uD328"
|
|
722
|
-
},
|
|
723
|
-
diff: {
|
|
724
|
-
title: "\uBCC0\uACBD\uC0AC\uD56D \uD655\uC778",
|
|
725
|
-
notGitRepo: "git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
726
|
-
noChanges: "\uBCC0\uACBD\uC0AC\uD56D \uC5C6\uC74C! \uAE68\uB057\uD569\uB2C8\uB2E4.",
|
|
727
|
-
stagedHeader: "\u{1F4E6} \uCEE4\uBC0B \uB300\uAE30 (staged):",
|
|
728
|
-
unstagedHeader: "\u270F\uFE0F \uC218\uC815\uB428 (unstaged):",
|
|
729
|
-
untrackedHeader: (n) => `\u2795 \uC0C8 \uD30C\uC77C (${n}\uAC1C):`,
|
|
730
|
-
summaryHeader: "\u{1F4CA} \uCD1D \uBCC0\uACBD \uC694\uC57D (\uC791\uC5C5 \uD2B8\uB9AC vs HEAD)",
|
|
731
|
-
filesLine: (n) => `\uD30C\uC77C: ${n}\uAC1C`
|
|
732
|
-
},
|
|
733
|
-
start: {
|
|
734
|
-
title: "\u{1F527} VHK \u2014 \uBB34\uC5C7\uC744 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?",
|
|
735
|
-
subtitle: "\uBC88\uD638\uB9CC \uACE0\uB974\uBA74 \uB429\uB2C8\uB2E4. \uBA85\uB839\uC5B4\uB97C \uC678\uC6B8 \uD544\uC694 \uC5C6\uC5B4\uC694.",
|
|
736
|
-
menuPrompt: "\uC5B4\uB5A4 \uC791\uC5C5\uC744 \uD560\uAE4C\uC694?",
|
|
737
|
-
choiceGate: "1) \uC0C8 \uC544\uC774\uB514\uC5B4 \uAC80\uC99D\uD558\uAE30",
|
|
738
|
-
choiceInit: "2) \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791\uD558\uAE30 \u2014 \uD3F4\uB354\xB7\uD30C\uC77C \uB9CC\uB4E4\uAE30",
|
|
739
|
-
choiceInitSkipGate: "3) \uAE30\uD68D\uC740 \uB05D\uB0AC\uC5B4\uC694 \u2014 \uBC14\uB85C \uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uAE30",
|
|
740
|
-
choiceRecap: "4) \uC624\uB298 \uD55C \uC77C \uC815\uB9AC\uD558\uAE30",
|
|
741
|
-
choiceSync: "5) \uADDC\uCE59 \uD30C\uC77C \uB9DE\uCD94\uAE30",
|
|
742
|
-
choiceCheck: "6) \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59 \uC810\uAC80\uD558\uAE30",
|
|
743
|
-
choiceSecure: "7) \uBE44\uBC00\uBC88\uD638\xB7\uD0A4 \uC720\uCD9C \uAC80\uC0AC\uD558\uAE30",
|
|
744
|
-
choiceExit: "\uB098\uAC00\uAE30",
|
|
745
|
-
goodbye: "\uB2E4\uC74C\uC5D0 \uB610 \uBD88\uB7EC\uC8FC\uC138\uC694."
|
|
746
|
-
},
|
|
747
|
-
gate: {
|
|
748
|
-
title: "\u{1F4A1} \uC544\uC774\uB514\uC5B4 \uAC80\uC99D",
|
|
749
|
-
welcome: "\uC0C8 \uC544\uC774\uB514\uC5B4\uB97C \uAC80\uC99D\uD569\uB2C8\uB2E4. \uC9C8\uBB38\uC5D0 \uB2F5\uD574\uC8FC\uC138\uC694.",
|
|
750
|
-
modePrompt: "\uC5B4\uB5BB\uAC8C \uAC80\uC99D\uD560\uAE4C\uC694?",
|
|
751
|
-
modeQuickLabel: "\u26A1 \uC9E7\uAC8C (\uD575\uC2EC 5\uBB38\uD56D) \u2014 \uB9C9 \uB5A0\uC62C\uB790\uC744 \uB54C",
|
|
752
|
-
modeFullLabel: "\u{1F50D} \uC790\uC138\uD788 (13\uBB38\uD56D) \u2014 \uAE30\uD68D\uC774 \uC5B4\uB290 \uC815\uB3C4 \uC7A1\uD614\uC744 \uB54C",
|
|
753
|
-
modeSkipLabel: "\u23ED\uFE0F \uAC74\uB108\uB6F0\uAE30 \u2014 \uB178\uC158\xB7\uBB38\uC11C\uC5D0 \uC774\uBBF8 \uAE30\uD68D\uD574 \uB460",
|
|
754
|
-
skipSourcePrompt: "\u{1F4C4} \uAE30\uD68D \uBB38\uC11C \uC704\uCE58 (\uB178\uC158 \uC8FC\uC18C, \uD30C\uC77C \uACBD\uB85C \uB4F1):",
|
|
755
|
-
skipGo: "\u2705 \uC2DC\uC791\uD574\uB3C4 \uB3FC\uC694! \uC774\uC81C \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4E4\uC5B4 \uBCF4\uC138\uC694 (vhk init)",
|
|
756
|
-
skipSourceLabel: (source) => `\uAE30\uD68D \uBB38\uC11C: ${source}`,
|
|
757
|
-
quickHeader: "\u26A1 \uC9E7\uC740 \uAC80\uC99D",
|
|
758
|
-
fullHeader: "\u{1F50D} \uC790\uC138\uD55C \uAC80\uC99D",
|
|
759
|
-
modeCountSuffix: (total) => `\u2014 ${total}\uBB38\uD56D`,
|
|
760
|
-
idea: "\u{1F4A1} \uC5B4\uB5A4 \uAC78 \uB9CC\uB4E4 \uAC74\uAC00\uC694? (\uD55C \uC904)",
|
|
761
|
-
ideaHint: '\uC608: "\uD300 \uD560 \uC77C\uC744 3\uCD08\uC5D0 \uCD94\uAC00\uD558\uB294 \uC571"',
|
|
762
|
-
painPoint: "\u{1F624} \uC774 \uBB38\uC81C, \uB204\uAC00 \uC5BC\uB9C8\uB098 \uC544\uD30C\uD574\uC694?",
|
|
763
|
-
painPointHint: '\uC608: "\uB9E4\uC77C \uC5D1\uC140\uC5D0 \uBCF5\uBD99\uD558\uB290\uB77C 30\uBD84\uC529 \uB0A0\uB9BC"',
|
|
764
|
-
edge: "\u{1F4AA} \uB098\uB9CC\uC758 \uAC15\uC810\uC740? (\uBE44\uC2B7\uD55C \uAC8C \uC788\uB294\uB370 \uC65C \uC774\uAC78?)",
|
|
765
|
-
edgeHint: '\uC608: "\uD55C\uAD6D\uC5B4\uB85C \uB41C \uAC00\uC774\uB4DC + \uBC14\uB85C \uC4F0\uB294 \uD15C\uD50C\uB9BF"',
|
|
766
|
-
checklistStart: "\u2500\u2500\u2500 \uC774\uC5B4\uC11C \uC9C8\uBB38\uD569\uB2C8\uB2E4 \u2500\u2500\u2500",
|
|
767
|
-
hintPrefix: " \u{1F4A1}",
|
|
768
|
-
verdictPrompt: (_failIf) => " \u2192 \uC9C0\uAE08 \uC0C1\uD0DC\uB294?",
|
|
769
|
-
statusPassChoice: "\u2705 \uAD1C\uCC2E\uC544\uC694",
|
|
770
|
-
statusHoldChoice: "\u{1F7E1} \uC544\uC9C1 \uBAA8\uB974\uACA0\uC5B4\uC694 (\uB098\uC911\uC5D0 \uCC44\uC6CC\uB3C4 \uB429\uB2C8\uB2E4)",
|
|
771
|
-
statusFailChoice: "\u{1F504} \uBC94\uC704\uB97C \uC904\uC5EC\uBCFC\uAC8C\uC694",
|
|
772
|
-
statusPassLine: " \u2705 \uAD1C\uCC2E\uC544\uC694",
|
|
773
|
-
statusHoldLine: " \u{1F7E1} \uBCF4\uB958 \u2014 \uAC1C\uBC1C\uD558\uBA74\uC11C \uCC44\uC6CC\uB3C4 \uB429\uB2C8\uB2E4",
|
|
774
|
-
statusFailLine: " \u{1F504} \uBC94\uC704 \uC870\uC815\uC774 \uD544\uC694\uD574 \uBCF4\uC5EC\uC694",
|
|
775
|
-
verdictTitle: "\u2550\u2550\u2550 \uACB0\uACFC \u2550\u2550\u2550",
|
|
776
|
-
ideaLabel: "\uB9CC\uB4E4 \uAC83:",
|
|
777
|
-
painPointLabel: "\uC544\uD508 \uC810:",
|
|
778
|
-
edgeLabel: "\uB098\uB9CC\uC758 \uAC15\uC810:",
|
|
779
|
-
countLine: (failCount, holdCount, total) => `\uBC94\uC704 \uC870\uC815 ${failCount}\uAC1C \xB7 \uBCF4\uB958 ${holdCount}\uAC1C / ${total}\uBB38\uD56D`,
|
|
780
|
-
go: "\u2705 \uC2DC\uC791\uD574\uB3C4 \uB3FC\uC694! \uB2E4\uC74C \uB2E8\uACC4(\uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uAE30)\uB85C \uB118\uC5B4\uAC00\uC138\uC694.",
|
|
781
|
-
refine: "\u{1F504} \uC870\uAE08 \uB354 \uB2E4\uB4EC\uC73C\uBA74 \uC88B\uACA0\uC5B4\uC694. \uC704 \uD56D\uBAA9\uC744 \uBCF4\uC644\uD574 \uBCF4\uC138\uC694.",
|
|
782
|
-
drop: "\u{1F4A1} \uB2E4\uB978 \uC544\uC774\uB514\uC5B4\uB97C \uAC80\uD1A0\uD574 \uBCF4\uB294 \uAC74 \uC5B4\uB5A8\uAE4C\uC694?",
|
|
783
|
-
nextCommand: "\uB2E4\uC74C: vhk init (\uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791\uD558\uAE30)",
|
|
784
|
-
holdRemainHint: "\u{1F4A1} \uBCF4\uB958\uD55C \uD56D\uBAA9\uC740 \uAC1C\uBC1C\uD558\uBA74\uC11C \uCC44\uC6CC\uB3C4 \uAD1C\uCC2E\uC544\uC694.",
|
|
785
|
-
failMessage: "\uC544\uC9C1 \uBAA8\uB974\uACA0\uC5B4\uC694 \u2192 \uAD1C\uCC2E\uC544\uC694, \uAC1C\uBC1C\uD558\uBA74\uC11C \uCC44\uC6CC\uB3C4 \uB429\uB2C8\uB2E4."
|
|
786
|
-
},
|
|
787
|
-
init: {
|
|
788
|
-
title: "\u{1F6E0}\uFE0F \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791\uD558\uAE30",
|
|
789
|
-
skipGate: "\u23ED\uFE0F 1\uB2E8\uACC4(\uC544\uC774\uB514\uC5B4 \uAC80\uC99D) \uAC74\uB108\uB6F0\uAE30 \u2014 \uAE30\uD68D\xB7\uC124\uACC4\uAC00 \uC774\uBBF8 \uC788\uC5B4\uC694",
|
|
790
|
-
projectName: "\u{1F4E6} \uD504\uB85C\uC81D\uD2B8 \uC774\uB984\uC740?",
|
|
791
|
-
projectNameHint: '\uC608: "\uD300 \uD560 \uC77C \uC571"',
|
|
792
|
-
description: "\u{1F4DD} \uD55C \uC904\uB85C \uC124\uBA85\uD558\uBA74?",
|
|
793
|
-
descriptionHint: '\uC608: "3\uCD08 \uB9CC\uC5D0 \uD560 \uC77C \uCD94\uAC00"',
|
|
794
|
-
projectType: "\u{1F3D7}\uFE0F \uC5B4\uB5A4 \uC885\uB958\uC778\uAC00\uC694?",
|
|
795
|
-
confirmStack: "\uC774 \uAE30\uC220 \uBB36\uC74C\uC73C\uB85C \uC9C4\uD589\uD560\uAE4C\uC694?",
|
|
796
|
-
canceled: "\uCDE8\uC18C\uD588\uC5B4\uC694. \uAE30\uC220 \uBB36\uC74C\uC744 \uBC14\uAFB8\uB824\uBA74 \uB2E4\uC2DC vhk init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
|
|
797
|
-
recommendedStack: "\uCD94\uCC9C \uAE30\uC220 \uBB36\uC74C:",
|
|
798
|
-
filesGenerating: "\u{1F4C2} \uD544\uC694\uD55C \uD30C\uC77C \uB9CC\uB4DC\uB294 \uC911...",
|
|
799
|
-
overwrite: (filePath) => ` \u26A0\uFE0F ${filePath} \uD30C\uC77C\uC774 \uC788\uC5B4\uC694. \uB36E\uC5B4\uC4F8\uAE4C\uC694?`,
|
|
800
|
-
skipped: (filePath) => `${filePath} \u2014 \uAC74\uB108\uB700`,
|
|
801
|
-
done: "\u{1F389} \uD504\uB85C\uC81D\uD2B8 \uBF08\uB300\uAC00 \uC900\uBE44\uB410\uC5B4\uC694!",
|
|
802
|
-
nextSteps: "\uB2E4\uC74C\uC5D0 \uD560 \uC77C:",
|
|
803
|
-
fillHint: "CLAUDE.md \xB7 .cursorrules\uC5D0\uC11C \u{1F449} \uC5EC\uAE30\uB97C \uCC44\uC6CC\uC8FC\uC138\uC694 \uD45C\uC2DC\uB97C \uCC3E\uC544 \uCC44\uC6B0\uC138\uC694",
|
|
804
|
-
prdHint: "docs/PRD.md\uC5D0 1\uCC28 \uBC84\uC804\uC5D0 \uB123\uC744 \uAE30\uB2A5\xB7\uBE7C\uB294 \uAE30\uB2A5\uC744 \uC801\uC5B4 \uBCF4\uC138\uC694",
|
|
805
|
-
notionFetching: "\u{1F4E1} \uB178\uC158 \uAE30\uD68D \uD398\uC774\uC9C0 \uBD88\uB7EC\uC624\uB294 \uC911...",
|
|
806
|
-
notionDone: (name) => `\uB178\uC158\uC5D0\uC11C \uAC00\uC838\uC624\uAE30 \uC644\uB8CC: ${name}`,
|
|
807
|
-
notionReviewHint: "docs/PRD.md\uB97C \uC77D\uACE0 \u{1F449} \uC5EC\uAE30\uB97C \uCC44\uC6CC\uC8FC\uC138\uC694 \uD56D\uBAA9\uC744 \uCC44\uC6B0\uC138\uC694",
|
|
808
|
-
gitHintLabel: "\uD130\uBBF8\uB110\uC5D0 \uBCF5\uC0AC\uD560 \uBA85\uB839 (\uC544\uB798 \uBC15\uC2A4 \uBCF5\uBD99):",
|
|
809
|
-
gitHintCommand: 'git init && git add . && git commit -m "feat: \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791"',
|
|
810
|
-
startDev: "\uC774\uC81C \uAC1C\uBC1C\uD574 \uBCF4\uC138\uC694! \u{1F680}",
|
|
811
|
-
commandsMdDone: "\u{1F4CB} COMMANDS.md \uC0DD\uC131",
|
|
812
|
-
scriptsDone: "\u{1F4E6} package.json scripts \uCD94\uAC00"
|
|
813
|
-
},
|
|
814
|
-
recap: {
|
|
815
|
-
title: "\u{1F4DD} \uC624\uB298 \uD55C \uC77C \uC815\uB9AC",
|
|
816
|
-
analyzing: "\u{1F4CA} \uC624\uB298 \uBC14\uB010 \uD30C\uC77C\xB7\uCEE4\uBC0B\uC744 \uC0B4\uD3B4\uBCF4\uB294 \uC911...",
|
|
817
|
-
noRepo: "\u274C Git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2C8\uC5D0\uC694. \uBA3C\uC800 git init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
|
|
818
|
-
noChanges: "\u26A0\uFE0F \uC624\uB298 \uBC14\uB010 \uB0B4\uC6A9\uC774 \uC5C6\uC5B4\uC694.",
|
|
819
|
-
summary: "\u{1F4DD} \uC774\uBC88\uC5D0 \uBB58 \uD588\uB098\uC694? (1~3\uC904)",
|
|
820
|
-
summaryHint: '\uC608: "\uB85C\uADF8\uC778 \uD654\uBA74 \uB9CC\uB4E4\uACE0 \uBC84\uD2BC \uC0C9 \uACE0\uCE68"',
|
|
821
|
-
decisions: "\u{1F9ED} \uC815\uD55C \uACB0\uC815\uC774 \uC788\uB098\uC694? (\uC5C6\uC73C\uBA74 Enter)",
|
|
822
|
-
nextTodo: "\u23ED\uFE0F \uB2E4\uC74C\uC5D0 \uD560 \uC77C\uC740?",
|
|
823
|
-
blockers: "\u{1F6A7} \uB9C9\uD78C \uAC8C \uC788\uB098\uC694? (\uC5C6\uC73C\uBA74 Enter)",
|
|
824
|
-
done: "\u2705 \uC624\uB298 \uAE30\uB85D\uC744 \uC800\uC7A5\uD588\uC5B4\uC694!",
|
|
825
|
-
updateClaude: 'CLAUDE.md "\uC9C0\uAE08 \uC0C1\uD0DC"\uB3C4 \uAC19\uC774 \uACE0\uCE60\uAE4C\uC694?',
|
|
826
|
-
adrDetected: "\u{1F4D0} \uC4F0\uB294 \uAE30\uC220\xB7\uC124\uC815\uC774 \uBC14\uB010 \uAC83 \uAC19\uC544\uC694!",
|
|
827
|
-
createAdr: "\uC65C \uADF8\uB807\uAC8C \uD588\uB294\uC9C0 \uAE30\uB85D \uBB38\uC11C\uB97C \uB9CC\uB4E4\uAE4C\uC694?",
|
|
828
|
-
troubleDetected: "\u{1F527} \uBC84\uADF8\xB7\uC624\uB958\uB97C \uACE0\uCE5C \uCEE4\uBC0B\uC774 \uBCF4\uC5EC\uC694!",
|
|
829
|
-
createTroubleshoot: "\uC5B4\uB5BB\uAC8C \uACE0\uCCE4\uB294\uC9C0 \uBA54\uBAA8\uB97C \uB0A8\uAE38\uAE4C\uC694?"
|
|
830
|
-
},
|
|
831
|
-
check: {
|
|
832
|
-
title: "\u{1F50D} \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59 \uC810\uAC80",
|
|
833
|
-
noRules: "\u26A0\uFE0F RULES.md \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694.",
|
|
834
|
-
noAutoRules: "\u26A0\uFE0F \uC790\uB3D9\uC73C\uB85C \uAC80\uC0AC\uD560 \uADDC\uCE59\uC774 \uC5C6\uC5B4\uC694.",
|
|
835
|
-
allPassed: "\u{1F389} \uADDC\uCE59\uC744 \uBAA8\uB450 \uC9C0\uCF30\uC5B4\uC694!",
|
|
836
|
-
summary: "\u{1F4CA} \uC810\uAC80 \uACB0\uACFC:"
|
|
837
|
-
},
|
|
838
|
-
doctor: {
|
|
839
|
-
title: "\u{1FA7A} \uAC1C\uBC1C \uD658\uACBD \uC810\uAC80",
|
|
840
|
-
allOk: "\u{1F389} \uAC1C\uBC1C \uD658\uACBD \uC900\uBE44 \uC644\uB8CC!",
|
|
841
|
-
missing: "\u26A0\uFE0F \uC77C\uBD80 \uB3C4\uAD6C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
842
|
-
missingHint: "\uC704 \uC548\uB0B4\uB97C \uB530\uB77C \uC124\uCE58\uD558\uC138\uC694.",
|
|
843
|
-
projectFiles: "\u{1F4C1} \uD504\uB85C\uC81D\uD2B8 \uD30C\uC77C \uD655\uC778:",
|
|
844
|
-
envNotIgnored: "\u26A0\uFE0F .env\uAC00 .gitignore\uC5D0 \uC5C6\uC74C! \uCD94\uAC00\uD558\uC138\uC694",
|
|
845
|
-
nextOkMessage: "\uD658\uACBD \uC810\uAC80 \uD1B5\uACFC! \uC774\uC81C \uD504\uB85C\uC81D\uD2B8\uB97C \uC2DC\uC791\uD558\uC138\uC694.",
|
|
846
|
-
nextRetryMessage: "\uC704 \uB3C4\uAD6C\uB97C \uC124\uCE58\uD55C \uD6C4 \uB2E4\uC2DC \uC810\uAC80\uD558\uC138\uC694.",
|
|
847
|
-
updateAvailable: (latest) => `\u{1F195} v${latest} \uC0AC\uC6A9 \uAC00\uB2A5 \u2014 npm i -g @byh3071/vhk`,
|
|
848
|
-
updateCurrent: "\uCD5C\uC2E0 \uBC84\uC804\uC744 \uC4F0\uACE0 \uC788\uC5B4\uC694"
|
|
849
|
-
},
|
|
850
|
-
nlp: {
|
|
851
|
-
matched: "\uC774\uAC8C \uB9DE\uB098\uC694?",
|
|
852
|
-
notMatched: "\uBB34\uC2A8 \uB73B\uC778\uC9C0 \uBAA8\uB974\uACA0\uC5B4\uC694. vhk\uB97C \uC785\uB825\uD558\uBA74 \uBA54\uB274\uC5D0\uC11C \uC120\uD0DD\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
853
|
-
menuHint: "vhk\uB97C \uC785\uB825\uD558\uBA74 \uBA54\uB274\uC5D0\uC11C \uC120\uD0DD\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
|
|
854
|
-
},
|
|
855
|
-
secure: {
|
|
856
|
-
title: "\u{1F512} \uBE44\uBC00\uBC88\uD638\xB7\uD0A4 \uC720\uCD9C \uAC80\uC0AC",
|
|
857
|
-
noGitignore: "\u26A0\uFE0F .gitignore \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694!",
|
|
858
|
-
noEnvInGitignore: "\u26A0\uFE0F .gitignore\uC5D0 .env\uAC00 \uC5C6\uC5B4\uC694!",
|
|
859
|
-
scanning: "\u{1F50D} \uD30C\uC77C\uC744 \uC0B4\uD3B4\uBCF4\uB294 \uC911...",
|
|
860
|
-
clean: "\u{1F389} \uBE44\uBC00\uBC88\uD638\xB7\uD0A4\uAC00 \uCF54\uB4DC\uC5D0 \uBCF4\uC774\uC9C0 \uC54A\uC544\uC694!",
|
|
861
|
-
summary: "\u{1F4CA} \uAC80\uC0AC \uC694\uC57D:"
|
|
862
|
-
},
|
|
863
|
-
sync: {
|
|
864
|
-
title: "\u{1F504} \uADDC\uCE59 \uD30C\uC77C \uB9DE\uCD94\uAE30",
|
|
865
|
-
noRules: "\u26A0\uFE0F RULES.md \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694.",
|
|
866
|
-
cursorrulesDone: "\u2705 .cursorrules \uB9DE\uCDA4 \uC644\uB8CC",
|
|
867
|
-
claudeDone: "\u2705 CLAUDE.md \uB9DE\uCDA4 \uC644\uB8CC",
|
|
868
|
-
done: "\u{1F504} \uB9DE\uCD94\uAE30 \uC644\uB8CC!"
|
|
869
|
-
},
|
|
870
|
-
ship: {
|
|
871
|
-
title: "\u{1F680} \uBC30\uD3EC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8",
|
|
872
|
-
checklist: "\u{1F4CB} \uBC30\uD3EC \uC804 \uCCB4\uD06C\uB9AC\uC2A4\uD2B8",
|
|
873
|
-
retro: "\u{1F50D} \uBC30\uD3EC \uD68C\uACE0",
|
|
874
|
-
buildLogCreated: "\u2705 \uBE4C\uB4DC \uB85C\uADF8 \uC0DD\uC131 \uC644\uB8CC",
|
|
875
|
-
buildLogDone: (rel) => `\u2705 \uBE4C\uB4DC \uB85C\uADF8 \uC0DD\uC131 \uC644\uB8CC: ${rel}`,
|
|
876
|
-
questionWell: "\uC798\uB41C \uC810\uC740?",
|
|
877
|
-
questionWrong: "\uC5B4\uB824\uC6E0\uB358 \uC810\uC740?",
|
|
878
|
-
questionLearned: "\uBC30\uC6B4 \uC810\uC740?",
|
|
879
|
-
questionNext: "\uB2E4\uC74C \uBC84\uC804\uC5D0\uC11C \uD560 \uAC83\uC740?",
|
|
880
|
-
checkboxPrompt: "\uC644\uB8CC\uD55C \uD56D\uBAA9\uC744 \uC120\uD0DD\uD558\uC138\uC694:",
|
|
881
|
-
incompleteHeader: "\u26A0\uFE0F \uC544\uC9C1 \uC644\uB8CC\uD558\uC9C0 \uC54A\uC740 \uD56D\uBAA9:",
|
|
882
|
-
proceedConfirm: "\uADF8\uB798\uB3C4 \uACC4\uC18D \uC9C4\uD589\uD560\uAE4C\uC694?",
|
|
883
|
-
allPassed: "\u2705 \uBAA8\uB4E0 \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 \uD1B5\uACFC!",
|
|
884
|
-
retryMessage: "\uCCB4\uD06C\uB9AC\uC2A4\uD2B8\uB97C \uB9C8\uCE5C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD574 \uBCF4\uC138\uC694.",
|
|
885
|
-
retryCursorHint: "\uBE4C\uB4DC\uD558\uACE0 \uD14C\uC2A4\uD2B8 \uB3CC\uB824\uC918",
|
|
886
|
-
versionPrompt: "\uBC30\uD3EC \uBC84\uC804\uC740?",
|
|
887
|
-
versionHint: "\uC608: 0.4.0",
|
|
888
|
-
emptySection: "(\uBBF8\uC791\uC131)",
|
|
889
|
-
emptyNext: "(\uBBF8\uC815)",
|
|
890
|
-
deployMessage: "\uBE4C\uB4DC \uB85C\uADF8\uB97C \uC800\uC7A5\uD588\uC5B4\uC694! \uC774\uC81C \uC2E4\uC81C \uBC30\uD3EC\uB97C \uC9C4\uD589\uD558\uC138\uC694.",
|
|
891
|
-
deployCursorHint: "\uBC30\uD3EC\uD574\uC918",
|
|
892
|
-
checkBuild: "\uBE4C\uB4DC\uAC00 \uC131\uACF5\uD588\uB098\uC694?",
|
|
893
|
-
hintBuild: "pnpm build",
|
|
894
|
-
checkTest: "\uBAA8\uB4E0 \uD14C\uC2A4\uD2B8\uAC00 \uD1B5\uACFC\uD588\uB098\uC694?",
|
|
895
|
-
hintTest: "pnpm test --run",
|
|
896
|
-
checkVersion: "package.json \uBC84\uC804\uC744 \uC62C\uB838\uB098\uC694?",
|
|
897
|
-
hintVersion: "version \uD544\uB4DC \uD655\uC778",
|
|
898
|
-
checkChangelog: "\uBCC0\uACBD \uB0B4\uC6A9\uC744 \uAE30\uB85D\uD588\uB098\uC694?",
|
|
899
|
-
hintChangelog: "README \uB610\uB294 CHANGELOG",
|
|
900
|
-
checkSecurity: "\uBCF4\uC548 \uC2A4\uCE94\uC744 \uB3CC\uB838\uB098\uC694?",
|
|
901
|
-
hintSecurity: "vhk \uBCF4\uC548 scan",
|
|
902
|
-
checkCommit: "\uBAA8\uB4E0 \uBCC0\uACBD\uC774 \uCEE4\uBC0B\uB418\uC5C8\uB098\uC694?",
|
|
903
|
-
hintCommit: "git status \uD655\uC778",
|
|
904
|
-
changelogUpdated: (version) => `CHANGELOG.md \uAC31\uC2E0\uB428 \u2014 [Unreleased] \u2192 [${version}] \uC139\uC158\uC73C\uB85C \uC774\uB3D9`,
|
|
905
|
-
changelogNoUnreleased: "CHANGELOG.md\uC5D0 [Unreleased] \uC139\uC158\uC774 \uC5C6\uC5B4 \uC790\uB3D9 \uAC31\uC2E0\uC744 \uC2A4\uD0B5\uD588\uC5B4\uC694",
|
|
906
|
-
changelogMissing: "CHANGELOG.md\uAC00 \uC5C6\uC5B4\uC694. \uB9CC\uB4E4\uBA74 ship\uC774 \uC790\uB3D9\uC73C\uB85C [Unreleased] \u2192 \uBC84\uC804 \uC139\uC158\uC73C\uB85C \uC62E\uACA8\uC90D\uB2C8\uB2E4."
|
|
907
|
-
},
|
|
908
|
-
mcp: {
|
|
909
|
-
initTitle: "Cursor MCP \uC5F0\uB3D9 \uC124\uC815",
|
|
910
|
-
serverStarted: "VHK MCP \uC11C\uBC84 \uC2DC\uC791\uB428"
|
|
911
|
-
}
|
|
912
|
-
};
|
|
913
|
-
function lookup(path15) {
|
|
914
|
-
const parts = path15.split(".");
|
|
915
|
-
let cur = ko;
|
|
916
|
-
for (const part of parts) {
|
|
917
|
-
if (cur === null || typeof cur !== "object") return void 0;
|
|
918
|
-
cur = cur[part];
|
|
919
|
-
}
|
|
920
|
-
return cur;
|
|
921
|
-
}
|
|
922
|
-
function t(key, ...args) {
|
|
923
|
-
const value = lookup(key);
|
|
924
|
-
if (typeof value === "function") {
|
|
925
|
-
return value(...args);
|
|
926
|
-
}
|
|
927
|
-
if (typeof value === "string") return value;
|
|
928
|
-
return key;
|
|
929
|
-
}
|
|
700
|
+
import chalk18 from "chalk";
|
|
701
|
+
import inquirer9 from "inquirer";
|
|
930
702
|
|
|
931
703
|
// src/commands/gate.ts
|
|
932
704
|
import inquirer from "inquirer";
|
|
933
|
-
import chalk2 from "chalk";
|
|
934
|
-
|
|
935
|
-
// src/lib/next-step.ts
|
|
936
705
|
import chalk from "chalk";
|
|
937
|
-
function printNextStep(step) {
|
|
938
|
-
console.log("");
|
|
939
|
-
console.log(chalk.cyan.bold("\u2501\u2501\u2501 \uB2E4\uC74C\uC5D0 \uC774\uAC83\uB9CC \uD558\uC138\uC694 \u2501\u2501\u2501"));
|
|
940
|
-
console.log("");
|
|
941
|
-
console.log(` ${step.message}`);
|
|
942
|
-
if (step.command) {
|
|
943
|
-
console.log("");
|
|
944
|
-
console.log(chalk.white.bgGray(" \uD130\uBBF8\uB110\uC5D0 \uBCF5\uBD99 "));
|
|
945
|
-
console.log(chalk.green(` ${step.command}`));
|
|
946
|
-
}
|
|
947
|
-
if (step.cursorHint) {
|
|
948
|
-
console.log("");
|
|
949
|
-
console.log(chalk.white.bgBlue(" Cursor\uC5D0\uAC8C \uB9D0\uD558\uAE30 "));
|
|
950
|
-
console.log(chalk.blue(` "${step.cursorHint}"`));
|
|
951
|
-
}
|
|
952
|
-
if (step.alternative) {
|
|
953
|
-
console.log("");
|
|
954
|
-
console.log(chalk.dim(` \uB610\uB294: ${step.alternative}`));
|
|
955
|
-
}
|
|
956
|
-
console.log("");
|
|
957
|
-
console.log(chalk.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"));
|
|
958
|
-
console.log("");
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
// src/commands/gate.ts
|
|
962
706
|
var GATE_QUESTIONS = [
|
|
963
707
|
{ id: 1, stage: "\uBB38\uC81C \uC815\uC758", question: "\uC774 \uC544\uC774\uB514\uC5B4\uAC00 \uD574\uACB0\uD558\uB294 \uBB38\uC81C\uB97C \uD55C \uBB38\uC7A5\uC73C\uB85C \uB9D0\uD574\uBCF4\uC138\uC694.", failIf: "\uD55C \uBB38\uC7A5 \uBD88\uAC00 \u2192 \uBBF8\uC131\uC219", quick: true },
|
|
964
708
|
{ id: 2, stage: "\uD575\uC2EC \uAE30\uB2A5", question: "\uB531 1\uAC1C \uAE30\uB2A5\uB9CC \uACE0\uB974\uBA74?", failIf: "2\uAC1C \uC774\uC0C1 \u2192 \uBC94\uC704 \uCD08\uACFC", quick: true },
|
|
@@ -980,7 +724,7 @@ function judgeGate(failCount, holdCount) {
|
|
|
980
724
|
return "DROP";
|
|
981
725
|
}
|
|
982
726
|
async function gate() {
|
|
983
|
-
console.log(
|
|
727
|
+
console.log(chalk.bold(`
|
|
984
728
|
${ko.gate.title}
|
|
985
729
|
`));
|
|
986
730
|
const { mode } = await inquirer.prompt([{
|
|
@@ -999,33 +743,33 @@ ${ko.gate.title}
|
|
|
999
743
|
name: "source",
|
|
1000
744
|
message: ko.gate.skipSourcePrompt
|
|
1001
745
|
}]);
|
|
1002
|
-
console.log(
|
|
746
|
+
console.log(chalk.green.bold(`
|
|
1003
747
|
${ko.gate.skipGo}`));
|
|
1004
|
-
console.log(
|
|
748
|
+
console.log(chalk.dim(ko.gate.skipSourceLabel(source)));
|
|
1005
749
|
return;
|
|
1006
750
|
}
|
|
1007
751
|
const questions = mode === "quick" ? GATE_QUESTIONS.filter((q) => q.quick) : GATE_QUESTIONS;
|
|
1008
752
|
const total = questions.length;
|
|
1009
753
|
const header = mode === "quick" ? ko.gate.quickHeader : ko.gate.fullHeader;
|
|
1010
|
-
console.log(
|
|
754
|
+
console.log(chalk.dim(`
|
|
1011
755
|
${header} ${ko.gate.modeCountSuffix(total)}
|
|
1012
756
|
`));
|
|
1013
|
-
console.log(
|
|
757
|
+
console.log(chalk.dim(`
|
|
1014
758
|
${ko.gate.welcome}
|
|
1015
759
|
`));
|
|
1016
|
-
console.log(
|
|
760
|
+
console.log(chalk.dim(` ${ko.gate.ideaHint}`));
|
|
1017
761
|
const { idea } = await inquirer.prompt([
|
|
1018
762
|
{ type: "input", name: "idea", message: ko.gate.idea }
|
|
1019
763
|
]);
|
|
1020
|
-
console.log(
|
|
764
|
+
console.log(chalk.dim(` ${ko.gate.painPointHint}`));
|
|
1021
765
|
const { painPoint } = await inquirer.prompt([
|
|
1022
766
|
{ type: "input", name: "painPoint", message: ko.gate.painPoint }
|
|
1023
767
|
]);
|
|
1024
|
-
console.log(
|
|
768
|
+
console.log(chalk.dim(` ${ko.gate.edgeHint}`));
|
|
1025
769
|
const { edge } = await inquirer.prompt([
|
|
1026
770
|
{ type: "input", name: "edge", message: ko.gate.edge }
|
|
1027
771
|
]);
|
|
1028
|
-
console.log(
|
|
772
|
+
console.log(chalk.dim(`
|
|
1029
773
|
${ko.gate.checklistStart}
|
|
1030
774
|
`));
|
|
1031
775
|
let failCount = 0;
|
|
@@ -1033,7 +777,7 @@ ${ko.gate.checklistStart}
|
|
|
1033
777
|
const results = [];
|
|
1034
778
|
for (let i = 0; i < questions.length; i++) {
|
|
1035
779
|
const q = questions[i];
|
|
1036
|
-
if (q.hint) console.log(
|
|
780
|
+
if (q.hint) console.log(chalk.dim(`${ko.gate.hintPrefix} ${q.hint}`));
|
|
1037
781
|
const { answer } = await inquirer.prompt([{
|
|
1038
782
|
type: "input",
|
|
1039
783
|
name: "answer",
|
|
@@ -1052,22 +796,22 @@ ${ko.gate.checklistStart}
|
|
|
1052
796
|
if (status2 === "fail") failCount++;
|
|
1053
797
|
if (status2 === "hold") holdCount++;
|
|
1054
798
|
results.push({ id: q.id, stage: q.stage, status: status2, answer });
|
|
1055
|
-
const icon = status2 === "pass" ?
|
|
799
|
+
const icon = status2 === "pass" ? chalk.green(ko.gate.statusPassLine) : status2 === "hold" ? chalk.yellow(ko.gate.statusHoldLine) : chalk.red(ko.gate.statusFailLine);
|
|
1056
800
|
console.log(icon);
|
|
1057
801
|
}
|
|
1058
|
-
console.log(
|
|
802
|
+
console.log(chalk.bold(`
|
|
1059
803
|
${ko.gate.verdictTitle}
|
|
1060
804
|
`));
|
|
1061
|
-
console.log(`${ko.gate.ideaLabel} ${
|
|
805
|
+
console.log(`${ko.gate.ideaLabel} ${chalk.cyan(idea)}`);
|
|
1062
806
|
console.log(`${ko.gate.painPointLabel} ${painPoint}`);
|
|
1063
807
|
console.log(`${ko.gate.edgeLabel} ${edge}`);
|
|
1064
808
|
console.log(`${ko.gate.countLine(failCount, holdCount, total)}
|
|
1065
809
|
`);
|
|
1066
810
|
const verdict = judgeGate(failCount, holdCount);
|
|
1067
811
|
if (verdict === "GO") {
|
|
1068
|
-
console.log(
|
|
812
|
+
console.log(chalk.green.bold(ko.gate.go));
|
|
1069
813
|
if (holdCount > 0) {
|
|
1070
|
-
console.log(
|
|
814
|
+
console.log(chalk.yellow(ko.gate.holdRemainHint));
|
|
1071
815
|
}
|
|
1072
816
|
printNextStep({
|
|
1073
817
|
message: "\uC544\uC774\uB514\uC5B4 \uD1B5\uACFC! \uC774\uC81C \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4E4\uC5B4\uBCF4\uC138\uC694.",
|
|
@@ -1075,20 +819,20 @@ ${ko.gate.verdictTitle}
|
|
|
1075
819
|
cursorHint: "\uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uC5B4\uC918"
|
|
1076
820
|
});
|
|
1077
821
|
} else if (verdict === "REFINE") {
|
|
1078
|
-
console.log(
|
|
822
|
+
console.log(chalk.yellow.bold(ko.gate.refine));
|
|
1079
823
|
printNextStep({
|
|
1080
824
|
message: "\uC870\uAE08 \uB354 \uB2E4\uB4EC\uC740 \uD6C4 \uB2E4\uC2DC \uAC80\uC99D\uD574\uBCF4\uC138\uC694.",
|
|
1081
825
|
command: "vhk \uAC80\uC99D",
|
|
1082
826
|
cursorHint: "\uC544\uC774\uB514\uC5B4 \uB2E4\uC2DC \uAC80\uC99D\uD574\uC918"
|
|
1083
827
|
});
|
|
1084
828
|
} else {
|
|
1085
|
-
console.log(
|
|
829
|
+
console.log(chalk.red.bold(ko.gate.drop));
|
|
1086
830
|
}
|
|
1087
831
|
}
|
|
1088
832
|
|
|
1089
833
|
// src/commands/init.ts
|
|
1090
834
|
import inquirer2 from "inquirer";
|
|
1091
|
-
import
|
|
835
|
+
import chalk4 from "chalk";
|
|
1092
836
|
import fs3 from "fs";
|
|
1093
837
|
import path3 from "path";
|
|
1094
838
|
|
|
@@ -1304,7 +1048,7 @@ function COMMANDS_MD_TEMPLATE() {
|
|
|
1304
1048
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
1305
1049
|
import fs from "fs";
|
|
1306
1050
|
import path from "path";
|
|
1307
|
-
import
|
|
1051
|
+
import chalk2 from "chalk";
|
|
1308
1052
|
function loadGitignore(rootDir) {
|
|
1309
1053
|
const ig = (0, import_ignore.default)();
|
|
1310
1054
|
const gitignorePath = path.join(rootDir, ".gitignore");
|
|
@@ -1377,7 +1121,7 @@ function printSecurityWarnings(rootDir = process.cwd()) {
|
|
|
1377
1121
|
const result = checkProjectSecurity(rootDir);
|
|
1378
1122
|
if (result.ok) return true;
|
|
1379
1123
|
for (const w of result.warnings) {
|
|
1380
|
-
console.log(
|
|
1124
|
+
console.log(chalk2.yellow(` \u26A0\uFE0F ${w}`));
|
|
1381
1125
|
}
|
|
1382
1126
|
return false;
|
|
1383
1127
|
}
|
|
@@ -1387,13 +1131,13 @@ function filterTrackedPaths(paths, rootDir = process.cwd()) {
|
|
|
1387
1131
|
}
|
|
1388
1132
|
|
|
1389
1133
|
// src/utils/logger.ts
|
|
1390
|
-
import
|
|
1134
|
+
import chalk3 from "chalk";
|
|
1391
1135
|
var log = {
|
|
1392
|
-
success: (msg) => console.log(
|
|
1393
|
-
error: (msg) => console.log(
|
|
1394
|
-
warn: (msg) => console.log(
|
|
1395
|
-
info: (msg) => console.log(
|
|
1396
|
-
step: (msg) => console.log(
|
|
1136
|
+
success: (msg) => console.log(chalk3.green(`\u2705 ${msg}`)),
|
|
1137
|
+
error: (msg) => console.log(chalk3.red(`\u274C ${msg}`)),
|
|
1138
|
+
warn: (msg) => console.log(chalk3.yellow(`\u26A0\uFE0F ${msg}`)),
|
|
1139
|
+
info: (msg) => console.log(chalk3.blue(`\u2139\uFE0F ${msg}`)),
|
|
1140
|
+
step: (msg) => console.log(chalk3.bold(`
|
|
1397
1141
|
\u25B8 ${msg}`))
|
|
1398
1142
|
};
|
|
1399
1143
|
|
|
@@ -1598,11 +1342,11 @@ async function collectAnswers(options, defaults = {}) {
|
|
|
1598
1342
|
async function init(options = {}) {
|
|
1599
1343
|
const skipGate = Boolean(options.skipGate || options.fromNotion);
|
|
1600
1344
|
if (skipGate) {
|
|
1601
|
-
console.log(
|
|
1345
|
+
console.log(chalk4.dim(`
|
|
1602
1346
|
${ko.init.skipGate}
|
|
1603
1347
|
`));
|
|
1604
1348
|
}
|
|
1605
|
-
console.log(
|
|
1349
|
+
console.log(chalk4.bold(`
|
|
1606
1350
|
${ko.init.title}
|
|
1607
1351
|
`));
|
|
1608
1352
|
printSecurityWarnings();
|
|
@@ -1627,7 +1371,7 @@ ${ko.init.title}
|
|
|
1627
1371
|
process.exit(1);
|
|
1628
1372
|
}
|
|
1629
1373
|
const stack = STACK_PRESETS[answers.type];
|
|
1630
|
-
console.log(
|
|
1374
|
+
console.log(chalk4.dim(`
|
|
1631
1375
|
${ko.init.recommendedStack} ${stack.join(" + ")}
|
|
1632
1376
|
`));
|
|
1633
1377
|
if (!options.yes) {
|
|
@@ -1663,21 +1407,21 @@ ${ko.init.recommendedStack} ${stack.join(" + ")}
|
|
|
1663
1407
|
log.success(filePath);
|
|
1664
1408
|
}
|
|
1665
1409
|
await writeInitExtras(cwd);
|
|
1666
|
-
console.log(
|
|
1410
|
+
console.log(chalk4.bold.green(`
|
|
1667
1411
|
${ko.init.done}`));
|
|
1668
|
-
console.log(
|
|
1412
|
+
console.log(chalk4.dim(`
|
|
1669
1413
|
${ko.init.nextSteps}`));
|
|
1670
1414
|
if (options.fromNotion) {
|
|
1671
1415
|
console.log(` 1. ${ko.init.notionReviewHint}`);
|
|
1672
1416
|
console.log(` 2. ${ko.init.gitHintLabel}`);
|
|
1673
|
-
console.log(` ${
|
|
1417
|
+
console.log(` ${chalk4.cyan(ko.init.gitHintCommand)}`);
|
|
1674
1418
|
console.log(` 3. ${ko.init.startDev}
|
|
1675
1419
|
`);
|
|
1676
1420
|
} else {
|
|
1677
1421
|
console.log(` 1. ${ko.init.fillHint}`);
|
|
1678
1422
|
console.log(` 2. ${ko.init.prdHint}`);
|
|
1679
1423
|
console.log(` 3. ${ko.init.gitHintLabel}`);
|
|
1680
|
-
console.log(` ${
|
|
1424
|
+
console.log(` ${chalk4.cyan(ko.init.gitHintCommand)}`);
|
|
1681
1425
|
console.log(` 4. ${ko.init.startDev}
|
|
1682
1426
|
`);
|
|
1683
1427
|
}
|
|
@@ -1758,7 +1502,7 @@ async function writeInitExtras(projectDir) {
|
|
|
1758
1502
|
|
|
1759
1503
|
// src/commands/recap.ts
|
|
1760
1504
|
import inquirer3 from "inquirer";
|
|
1761
|
-
import
|
|
1505
|
+
import chalk5 from "chalk";
|
|
1762
1506
|
import fs5 from "fs";
|
|
1763
1507
|
import path6 from "path";
|
|
1764
1508
|
|
|
@@ -1917,40 +1661,40 @@ function createAdrFile(cwd, title, context, decision, consequences) {
|
|
|
1917
1661
|
|
|
1918
1662
|
// src/commands/recap.ts
|
|
1919
1663
|
async function recap(options = {}) {
|
|
1920
|
-
console.log(
|
|
1664
|
+
console.log(chalk5.bold(`
|
|
1921
1665
|
${ko.recap.title}
|
|
1922
1666
|
`));
|
|
1923
1667
|
if (!await isGitRepo()) {
|
|
1924
|
-
console.log(
|
|
1668
|
+
console.log(chalk5.red(ko.recap.noRepo));
|
|
1925
1669
|
return;
|
|
1926
1670
|
}
|
|
1927
1671
|
printSecurityWarnings();
|
|
1928
|
-
console.log(
|
|
1672
|
+
console.log(chalk5.dim(`${ko.recap.analyzing}
|
|
1929
1673
|
`));
|
|
1930
1674
|
const since = options.since || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1931
1675
|
const diff2 = await getSessionDiff(since);
|
|
1932
1676
|
const commits = await getRecentCommits(10, since);
|
|
1933
1677
|
if (diff2.filesChanged === 0 && commits.length === 0) {
|
|
1934
|
-
console.log(
|
|
1678
|
+
console.log(chalk5.yellow(ko.recap.noChanges));
|
|
1935
1679
|
return;
|
|
1936
1680
|
}
|
|
1937
|
-
console.log(
|
|
1938
|
-
console.log(` \uD30C\uC77C: ${
|
|
1939
|
-
console.log(` \uCD94\uAC00: ${
|
|
1681
|
+
console.log(chalk5.bold("\u{1F4CA} \uBCC0\uACBD \uC694\uC57D:"));
|
|
1682
|
+
console.log(` \uD30C\uC77C: ${chalk5.cyan(String(diff2.filesChanged))}\uAC1C \uBCC0\uACBD`);
|
|
1683
|
+
console.log(` \uCD94\uAC00: ${chalk5.green("+" + diff2.insertions)} / \uC0AD\uC81C: ${chalk5.red("-" + diff2.deletions)}`);
|
|
1940
1684
|
if (diff2.files.length > 0) {
|
|
1941
|
-
console.log(
|
|
1685
|
+
console.log(chalk5.dim("\n \uBCC0\uACBD \uD30C\uC77C:"));
|
|
1942
1686
|
diff2.files.slice(0, 15).forEach((f) => {
|
|
1943
|
-
const icon = f.status === "new" ?
|
|
1687
|
+
const icon = f.status === "new" ? chalk5.green("\u{1F195}") : f.status === "deleted" ? chalk5.red("\u{1F5D1}\uFE0F") : chalk5.yellow("\u270F\uFE0F");
|
|
1944
1688
|
console.log(` ${icon} ${f.file}`);
|
|
1945
1689
|
});
|
|
1946
1690
|
if (diff2.files.length > 15) {
|
|
1947
|
-
console.log(
|
|
1691
|
+
console.log(chalk5.dim(` ... \uC678 ${diff2.files.length - 15}\uAC1C`));
|
|
1948
1692
|
}
|
|
1949
1693
|
}
|
|
1950
1694
|
if (commits.length > 0) {
|
|
1951
|
-
console.log(
|
|
1695
|
+
console.log(chalk5.dim("\n \uCD5C\uADFC \uCEE4\uBC0B:"));
|
|
1952
1696
|
commits.slice(0, 5).forEach((c) => {
|
|
1953
|
-
console.log(
|
|
1697
|
+
console.log(chalk5.dim(` \u2022 ${c.message}`));
|
|
1954
1698
|
});
|
|
1955
1699
|
}
|
|
1956
1700
|
console.log("");
|
|
@@ -2018,11 +1762,11 @@ ${ko.recap.title}
|
|
|
2018
1762
|
fs5.writeFileSync(filePath, content, "utf-8");
|
|
2019
1763
|
const adrCandidates = detectAdrCandidates(diff2);
|
|
2020
1764
|
if (adrCandidates.length > 0) {
|
|
2021
|
-
console.log(
|
|
1765
|
+
console.log(chalk5.cyan.bold(`
|
|
2022
1766
|
${ko.recap.adrDetected} (${adrCandidates.length}\uAC74)`));
|
|
2023
1767
|
for (const candidate of adrCandidates) {
|
|
2024
|
-
console.log(
|
|
2025
|
-
candidate.files.forEach((f) => console.log(
|
|
1768
|
+
console.log(chalk5.cyan(` \u2022 ${candidate.title}: ${candidate.context}`));
|
|
1769
|
+
candidate.files.forEach((f) => console.log(chalk5.dim(` ${f}`)));
|
|
2026
1770
|
}
|
|
2027
1771
|
const { createAdr } = await inquirer3.prompt([{
|
|
2028
1772
|
type: "confirm",
|
|
@@ -2052,17 +1796,17 @@ ${ko.recap.adrDetected} (${adrCandidates.length}\uAC74)`));
|
|
|
2052
1796
|
adrAnswers.decision,
|
|
2053
1797
|
adrAnswers.consequences
|
|
2054
1798
|
);
|
|
2055
|
-
console.log(
|
|
1799
|
+
console.log(chalk5.green(` \u2705 ADR \uC0DD\uC131: ${path6.relative(process.cwd(), adrPath)}`));
|
|
2056
1800
|
}
|
|
2057
1801
|
}
|
|
2058
1802
|
}
|
|
2059
1803
|
const troubleshootingKeywords = /fix|bug|error|crash|hotfix|patch|revert|트러블|에러|버그|수정|핫픽스/i;
|
|
2060
1804
|
const troubleCommits = commits.filter((c) => troubleshootingKeywords.test(c.message));
|
|
2061
1805
|
if (troubleCommits.length > 0) {
|
|
2062
|
-
console.log(
|
|
1806
|
+
console.log(chalk5.yellow.bold(`
|
|
2063
1807
|
${ko.recap.troubleDetected} (${troubleCommits.length}\uAC74)`));
|
|
2064
1808
|
troubleCommits.forEach((c) => {
|
|
2065
|
-
console.log(
|
|
1809
|
+
console.log(chalk5.dim(` \u2022 ${c.message}`));
|
|
2066
1810
|
});
|
|
2067
1811
|
const { createTroubleshoot } = await inquirer3.prompt([{
|
|
2068
1812
|
type: "confirm",
|
|
@@ -2113,12 +1857,12 @@ ${ko.recap.troubleDetected} (${troubleCommits.length}\uAC74)`));
|
|
|
2113
1857
|
`*Generated by \`vhk recap\` at ${(/* @__PURE__ */ new Date()).toISOString()}*`
|
|
2114
1858
|
].join("\n");
|
|
2115
1859
|
fs5.writeFileSync(tsFilePath, tsContent, "utf-8");
|
|
2116
|
-
console.log(
|
|
1860
|
+
console.log(chalk5.green(` \u2705 \uD2B8\uB7EC\uBE14\uC288\uD305 \uBB38\uC11C \uC0DD\uC131: ${path6.relative(process.cwd(), tsFilePath)}`));
|
|
2117
1861
|
}
|
|
2118
1862
|
}
|
|
2119
|
-
console.log(
|
|
1863
|
+
console.log(chalk5.green.bold(`
|
|
2120
1864
|
${ko.recap.done}`));
|
|
2121
|
-
console.log(
|
|
1865
|
+
console.log(chalk5.dim(` \u{1F4C4} ${path6.relative(process.cwd(), filePath)}`));
|
|
2122
1866
|
const claudeMdPath = path6.join(process.cwd(), "CLAUDE.md");
|
|
2123
1867
|
if (fs5.existsSync(claudeMdPath)) {
|
|
2124
1868
|
const { updateClaude } = await inquirer3.prompt([{
|
|
@@ -2138,7 +1882,7 @@ ${ko.recap.done}`));
|
|
|
2138
1882
|
`- **\uB2E4\uC74C \uC561\uC158:** ${answers.nextTodo}`
|
|
2139
1883
|
);
|
|
2140
1884
|
fs5.writeFileSync(claudeMdPath, claudeContent, "utf-8");
|
|
2141
|
-
console.log(
|
|
1885
|
+
console.log(chalk5.green(" \u2705 CLAUDE.md \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC"));
|
|
2142
1886
|
}
|
|
2143
1887
|
}
|
|
2144
1888
|
const gitSaveCmd = process.platform === "win32" ? 'git add .; git commit -m "recap: \uC138\uC158 \uAE30\uB85D"' : 'git add . && git commit -m "recap: \uC138\uC158 \uAE30\uB85D"';
|
|
@@ -2150,7 +1894,7 @@ ${ko.recap.done}`));
|
|
|
2150
1894
|
}
|
|
2151
1895
|
|
|
2152
1896
|
// src/commands/sync.ts
|
|
2153
|
-
import
|
|
1897
|
+
import chalk6 from "chalk";
|
|
2154
1898
|
import fs6 from "fs";
|
|
2155
1899
|
import path7 from "path";
|
|
2156
1900
|
var CURSORRULES_KEYS = ["\uCF54\uB529 \uADDC\uCE59", "\uAE30\uC220 \uC2A4\uD0DD", "\uC544\uD0A4\uD14D\uCC98", "\uB514\uC790\uC778", "Anti-patterns", "\uCEE4\uBC0B"];
|
|
@@ -2220,32 +1964,32 @@ function toClaudeMd(sections, existing) {
|
|
|
2220
1964
|
return lines.join("\n");
|
|
2221
1965
|
}
|
|
2222
1966
|
async function sync() {
|
|
2223
|
-
console.log(
|
|
1967
|
+
console.log(chalk6.bold(`
|
|
2224
1968
|
${ko.sync.title}
|
|
2225
1969
|
`));
|
|
2226
1970
|
const cwd = process.cwd();
|
|
2227
1971
|
const rulesPath = path7.join(cwd, "RULES.md");
|
|
2228
1972
|
if (!fs6.existsSync(rulesPath)) {
|
|
2229
|
-
console.log(
|
|
2230
|
-
console.log(
|
|
2231
|
-
console.log(
|
|
1973
|
+
console.log(chalk6.yellow(ko.sync.noRules));
|
|
1974
|
+
console.log(chalk6.dim(" RULES.md\uB294 \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59\uC758 Single Source of Truth\uC785\uB2C8\uB2E4."));
|
|
1975
|
+
console.log(chalk6.dim(" \uC0DD\uC131\uD558\uB824\uBA74: vhk init \uC2E4\uD589 \uD6C4 RULES.md\uB97C \uC791\uC131\uD558\uC138\uC694."));
|
|
2232
1976
|
console.log("");
|
|
2233
|
-
console.log(
|
|
2234
|
-
console.log(
|
|
2235
|
-
console.log(
|
|
2236
|
-
console.log(
|
|
2237
|
-
console.log(
|
|
2238
|
-
console.log(
|
|
1977
|
+
console.log(chalk6.dim(" RULES.md \uAE30\uBCF8 \uAD6C\uC870:"));
|
|
1978
|
+
console.log(chalk6.dim(" ## \uD504\uB85C\uC81D\uD2B8 \uC815\uCCB4\uC131"));
|
|
1979
|
+
console.log(chalk6.dim(" ## \uAE30\uC220 \uC2A4\uD0DD"));
|
|
1980
|
+
console.log(chalk6.dim(" ## \uCF54\uB529 \uADDC\uCE59"));
|
|
1981
|
+
console.log(chalk6.dim(" ## \uAE30\uB85D \uADDC\uCE59"));
|
|
1982
|
+
console.log(chalk6.dim(" ## \uCEE4\uBC0B \uCEE8\uBCA4\uC158"));
|
|
2239
1983
|
return;
|
|
2240
1984
|
}
|
|
2241
1985
|
const rulesContent = fs6.readFileSync(rulesPath, "utf-8");
|
|
2242
1986
|
const sections = parseRulesMd(rulesContent);
|
|
2243
|
-
console.log(
|
|
1987
|
+
console.log(chalk6.dim(` \u{1F4C4} RULES.md \uD30C\uC2F1 \uC644\uB8CC \u2014 ${sections.length}\uAC1C \uC139\uC158`));
|
|
2244
1988
|
const firstLine = rulesContent.split("\n")[0];
|
|
2245
1989
|
const projectName = firstLine.replace(/^#\s*/, "").replace(/\s*—.*/, "").trim() || "Project";
|
|
2246
1990
|
const cursorrulesPath = path7.join(cwd, ".cursorrules");
|
|
2247
1991
|
fs6.writeFileSync(cursorrulesPath, toCursorrules(sections, projectName), "utf-8");
|
|
2248
|
-
console.log(
|
|
1992
|
+
console.log(chalk6.green(` ${ko.sync.cursorrulesDone}`));
|
|
2249
1993
|
const claudePath = path7.join(cwd, "CLAUDE.md");
|
|
2250
1994
|
const existingClaude = fs6.existsSync(claudePath) ? fs6.readFileSync(claudePath, "utf-8") : `# \uAE30\uB85D \uADDC\uCE59 (${projectName})
|
|
2251
1995
|
|
|
@@ -2255,11 +1999,11 @@ ${ko.sync.title}
|
|
|
2255
1999
|
- **\uB2E4\uC74C \uC561\uC158:** __FILL__
|
|
2256
2000
|
- **\uB9C8\uC9C0\uB9C9 \uC5C5\uB370\uC774\uD2B8:** ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`;
|
|
2257
2001
|
fs6.writeFileSync(claudePath, toClaudeMd(sections, existingClaude), "utf-8");
|
|
2258
|
-
console.log(
|
|
2259
|
-
console.log(
|
|
2002
|
+
console.log(chalk6.green(` ${ko.sync.claudeDone}`));
|
|
2003
|
+
console.log(chalk6.bold.green(`
|
|
2260
2004
|
${ko.sync.done}`));
|
|
2261
|
-
console.log(
|
|
2262
|
-
console.log(
|
|
2005
|
+
console.log(chalk6.dim(" RULES.md (\uC6D0\uBCF8) \u2192 .cursorrules + CLAUDE.md (\uC790\uB3D9 \uC0DD\uC131)"));
|
|
2006
|
+
console.log(chalk6.dim(" \uADDC\uCE59 \uBCC0\uACBD\uC740 \uD56D\uC0C1 RULES.md\uC5D0\uC11C\uB9CC \uD558\uC138\uC694."));
|
|
2263
2007
|
printNextStep({
|
|
2264
2008
|
message: "\uADDC\uCE59 \uB3D9\uAE30\uD654 \uC644\uB8CC! \uC774\uC81C Cursor\uAC00 \uC0C8 \uADDC\uCE59\uC744 \uB530\uB985\uB2C8\uB2E4.",
|
|
2265
2009
|
command: "vhk \uC810\uAC80",
|
|
@@ -2268,7 +2012,7 @@ ${ko.sync.done}`));
|
|
|
2268
2012
|
}
|
|
2269
2013
|
|
|
2270
2014
|
// src/commands/check.ts
|
|
2271
|
-
import
|
|
2015
|
+
import chalk7 from "chalk";
|
|
2272
2016
|
import path9 from "path";
|
|
2273
2017
|
import fs8 from "fs";
|
|
2274
2018
|
|
|
@@ -2427,22 +2171,22 @@ function escapeRegex(str) {
|
|
|
2427
2171
|
|
|
2428
2172
|
// src/commands/check.ts
|
|
2429
2173
|
async function check() {
|
|
2430
|
-
console.log(
|
|
2174
|
+
console.log(chalk7.bold(`
|
|
2431
2175
|
${ko.check.title}
|
|
2432
2176
|
`));
|
|
2433
2177
|
const cwd = process.cwd();
|
|
2434
2178
|
const rulesPath = path9.join(cwd, "RULES.md");
|
|
2435
2179
|
if (!fs8.existsSync(rulesPath)) {
|
|
2436
|
-
console.log(
|
|
2437
|
-
console.log(
|
|
2180
|
+
console.log(chalk7.yellow(ko.check.noRules));
|
|
2181
|
+
console.log(chalk7.dim(" vhk init\uC73C\uB85C \uC2DC\uC791\uD558\uAC70\uB098 RULES.md\uB97C \uB9CC\uB4E4\uC5B4 \uBCF4\uC138\uC694."));
|
|
2438
2182
|
return;
|
|
2439
2183
|
}
|
|
2440
2184
|
const rules = parseRules(rulesPath);
|
|
2441
|
-
console.log(
|
|
2185
|
+
console.log(chalk7.dim(` \u{1F4CF} ${rules.length}\uAC1C \uAC80\uC99D \uAC00\uB2A5\uD55C \uADDC\uCE59 \uAC10\uC9C0
|
|
2442
2186
|
`));
|
|
2443
2187
|
if (rules.length === 0) {
|
|
2444
|
-
console.log(
|
|
2445
|
-
console.log(
|
|
2188
|
+
console.log(chalk7.yellow(ko.check.noAutoRules));
|
|
2189
|
+
console.log(chalk7.dim(" RULES.md\uC5D0 \uD30C\uC77C \uC774\uB984\xB7\uD3F4\uB354 \uADDC\uCE59\uC744 \uC801\uC73C\uBA74 \uC790\uB3D9\uC73C\uB85C \uC810\uAC80\uD574\uC694."));
|
|
2446
2190
|
return;
|
|
2447
2191
|
}
|
|
2448
2192
|
const allViolations = [];
|
|
@@ -2450,13 +2194,13 @@ ${ko.check.title}
|
|
|
2450
2194
|
for (const rule of rules) {
|
|
2451
2195
|
const violations = rule.check(cwd);
|
|
2452
2196
|
if (violations.length === 0) {
|
|
2453
|
-
console.log(
|
|
2197
|
+
console.log(chalk7.green(` \u2705 ${rule.id}`) + chalk7.dim(` \u2014 ${rule.description.slice(0, 60)}`));
|
|
2454
2198
|
passCount++;
|
|
2455
2199
|
} else {
|
|
2456
|
-
console.log(
|
|
2200
|
+
console.log(chalk7.red(` \u274C ${rule.id}`) + chalk7.dim(` \u2014 ${violations.length}\uAC74 \uC704\uBC18`));
|
|
2457
2201
|
violations.forEach((v) => {
|
|
2458
|
-
const loc = v.file ?
|
|
2459
|
-
const icon = v.severity === "error" ?
|
|
2202
|
+
const loc = v.file ? chalk7.dim(` (${v.file}${v.line ? ":" + v.line : ""})`) : "";
|
|
2203
|
+
const icon = v.severity === "error" ? chalk7.red("\u2716") : v.severity === "warning" ? chalk7.yellow("\u26A0") : chalk7.blue("\u2139");
|
|
2460
2204
|
console.log(` ${icon} ${v.message}${loc}`);
|
|
2461
2205
|
});
|
|
2462
2206
|
allViolations.push(...violations);
|
|
@@ -2466,17 +2210,17 @@ ${ko.check.title}
|
|
|
2466
2210
|
const errors = allViolations.filter((v) => v.severity === "error").length;
|
|
2467
2211
|
const warnings = allViolations.filter((v) => v.severity === "warning").length;
|
|
2468
2212
|
if (allViolations.length === 0) {
|
|
2469
|
-
console.log(
|
|
2213
|
+
console.log(chalk7.green.bold(`${ko.check.allPassed} (${passCount}/${rules.length})`));
|
|
2470
2214
|
printNextStep({
|
|
2471
2215
|
message: "\uBAA8\uB4E0 \uADDC\uCE59 \uD1B5\uACFC! \uBCF4\uC548 \uC2A4\uCE94\uB3C4 \uD574\uBCFC\uAE4C\uC694?",
|
|
2472
2216
|
command: "vhk \uBCF4\uC548 scan",
|
|
2473
2217
|
cursorHint: "\uBCF4\uC548 \uC2A4\uCE94 \uB3CC\uB824\uC918"
|
|
2474
2218
|
});
|
|
2475
2219
|
} else {
|
|
2476
|
-
console.log(
|
|
2477
|
-
console.log(` \uADDC\uCE59: ${
|
|
2478
|
-
if (errors > 0) console.log(` ${
|
|
2479
|
-
if (warnings > 0) console.log(` ${
|
|
2220
|
+
console.log(chalk7.bold(ko.check.summary));
|
|
2221
|
+
console.log(` \uADDC\uCE59: ${chalk7.cyan(String(rules.length))}\uAC1C | \uD1B5\uACFC: ${chalk7.green(String(passCount))}\uAC1C | \uC704\uBC18: ${chalk7.red(String(allViolations.length))}\uAC74`);
|
|
2222
|
+
if (errors > 0) console.log(` ${chalk7.red(`\u2716 ${errors}\uAC1C \uC5D0\uB7EC`)}`);
|
|
2223
|
+
if (warnings > 0) console.log(` ${chalk7.yellow(`\u26A0 ${warnings}\uAC1C \uACBD\uACE0`)}`);
|
|
2480
2224
|
printNextStep({
|
|
2481
2225
|
message: "\uC704\uBC18 \uD56D\uBAA9\uC744 \uC218\uC815\uD55C \uD6C4 \uB2E4\uC2DC \uC810\uAC80\uD558\uC138\uC694.",
|
|
2482
2226
|
command: "vhk \uC810\uAC80",
|
|
@@ -2489,7 +2233,7 @@ ${ko.check.title}
|
|
|
2489
2233
|
}
|
|
2490
2234
|
|
|
2491
2235
|
// src/commands/secure.ts
|
|
2492
|
-
import
|
|
2236
|
+
import chalk8 from "chalk";
|
|
2493
2237
|
import fs11 from "fs";
|
|
2494
2238
|
import path11 from "path";
|
|
2495
2239
|
|
|
@@ -2690,32 +2434,32 @@ function filterSevereFindings(findings) {
|
|
|
2690
2434
|
|
|
2691
2435
|
// src/commands/secure.ts
|
|
2692
2436
|
async function secure() {
|
|
2693
|
-
console.log(
|
|
2437
|
+
console.log(chalk8.bold(`
|
|
2694
2438
|
${ko.secure.title}
|
|
2695
2439
|
`));
|
|
2696
2440
|
const cwd = process.cwd();
|
|
2697
2441
|
const gitignorePath = path11.join(cwd, ".gitignore");
|
|
2698
2442
|
const hasGitignore = fs11.existsSync(gitignorePath);
|
|
2699
2443
|
if (!hasGitignore) {
|
|
2700
|
-
console.log(
|
|
2701
|
-
console.log(
|
|
2444
|
+
console.log(chalk8.yellow(` ${ko.secure.noGitignore}`));
|
|
2445
|
+
console.log(chalk8.dim(" .env \uD30C\uC77C\uC774 \uCEE4\uBC0B\uB420 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\n"));
|
|
2702
2446
|
} else {
|
|
2703
2447
|
const gitignoreContent = fs11.readFileSync(gitignorePath, "utf-8");
|
|
2704
2448
|
if (!gitignoreContent.includes(".env")) {
|
|
2705
|
-
console.log(
|
|
2706
|
-
console.log(
|
|
2449
|
+
console.log(chalk8.yellow(` ${ko.secure.noEnvInGitignore}`));
|
|
2450
|
+
console.log(chalk8.dim(" \uCD94\uAC00\uB97C \uAD8C\uC7A5\uD569\uB2C8\uB2E4.\n"));
|
|
2707
2451
|
}
|
|
2708
2452
|
}
|
|
2709
|
-
console.log(
|
|
2453
|
+
console.log(chalk8.dim(` ${ko.secure.scanning}
|
|
2710
2454
|
`));
|
|
2711
2455
|
const { findings, scannedFiles, truncated } = scanProjectForSecrets(cwd);
|
|
2712
|
-
console.log(
|
|
2456
|
+
console.log(chalk8.dim(` \u{1F4C2} ${scannedFiles}\uAC1C \uD30C\uC77C \uC2A4\uCE94 \uC644\uB8CC (lock\xB7node_modules\xB7>${MAX_SCAN_FILE_BYTES / 1024}KB \uC81C\uC678)`));
|
|
2713
2457
|
if (truncated) {
|
|
2714
|
-
console.log(
|
|
2458
|
+
console.log(chalk8.yellow(` \u26A0\uFE0F \uACB0\uACFC ${MAX_SECRET_FINDINGS}\uAC74\uC5D0\uC11C \uCD9C\uB825\uC744 \uC81C\uD55C\uD588\uC2B5\uB2C8\uB2E4. lock \uD30C\uC77C \uB4F1\uC740 \uC790\uB3D9 \uC81C\uC678\uB429\uB2C8\uB2E4.`));
|
|
2715
2459
|
}
|
|
2716
2460
|
console.log("");
|
|
2717
2461
|
if (findings.length === 0) {
|
|
2718
|
-
console.log(
|
|
2462
|
+
console.log(chalk8.green.bold(` ${ko.secure.clean}`));
|
|
2719
2463
|
printNextStep({
|
|
2720
2464
|
message: "\uBCF4\uC548 \uC774\uC0C1 \uC5C6\uC74C! \uAE68\uB057\uD569\uB2C8\uB2E4.",
|
|
2721
2465
|
command: "vhk \uC815\uB9AC",
|
|
@@ -2727,43 +2471,43 @@ ${ko.secure.title}
|
|
|
2727
2471
|
const high = findings.filter((f) => f.severity === "high");
|
|
2728
2472
|
const medium = findings.filter((f) => f.severity === "medium");
|
|
2729
2473
|
if (critical.length > 0) {
|
|
2730
|
-
console.log(
|
|
2474
|
+
console.log(chalk8.red.bold(` \u{1F6A8} CRITICAL \u2014 ${critical.length}\uAC74`));
|
|
2731
2475
|
critical.forEach((f) => {
|
|
2732
|
-
console.log(
|
|
2733
|
-
console.log(
|
|
2476
|
+
console.log(chalk8.red(` \u2716 ${f.patternName}`));
|
|
2477
|
+
console.log(chalk8.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
|
|
2734
2478
|
});
|
|
2735
2479
|
console.log("");
|
|
2736
2480
|
}
|
|
2737
2481
|
if (high.length > 0) {
|
|
2738
|
-
console.log(
|
|
2482
|
+
console.log(chalk8.yellow.bold(` \u26A0\uFE0F HIGH \u2014 ${high.length}\uAC74`));
|
|
2739
2483
|
high.forEach((f) => {
|
|
2740
|
-
console.log(
|
|
2741
|
-
console.log(
|
|
2484
|
+
console.log(chalk8.yellow(` \u26A0 ${f.patternName}`));
|
|
2485
|
+
console.log(chalk8.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
|
|
2742
2486
|
});
|
|
2743
2487
|
console.log("");
|
|
2744
2488
|
}
|
|
2745
2489
|
if (medium.length > 0) {
|
|
2746
|
-
console.log(
|
|
2490
|
+
console.log(chalk8.blue.bold(` \u2139 MEDIUM \u2014 ${medium.length}\uAC74`));
|
|
2747
2491
|
medium.forEach((f) => {
|
|
2748
|
-
console.log(
|
|
2749
|
-
console.log(
|
|
2492
|
+
console.log(chalk8.blue(` \u2139 ${f.patternName}`));
|
|
2493
|
+
console.log(chalk8.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
|
|
2750
2494
|
});
|
|
2751
2495
|
console.log("");
|
|
2752
2496
|
}
|
|
2753
|
-
console.log(
|
|
2754
|
-
console.log(` \uCD1D ${
|
|
2497
|
+
console.log(chalk8.bold(` ${ko.secure.summary}`));
|
|
2498
|
+
console.log(` \uCD1D ${chalk8.red(String(findings.length))}\uAC74 \uAC10\uC9C0 | CRITICAL: ${critical.length} | HIGH: ${high.length} | MEDIUM: ${medium.length}`);
|
|
2755
2499
|
console.log("");
|
|
2756
|
-
console.log(
|
|
2757
|
-
console.log(
|
|
2758
|
-
console.log(
|
|
2759
|
-
console.log(
|
|
2500
|
+
console.log(chalk8.dim(" \u{1F4A1} \uC870\uCE58 \uBC29\uBC95:"));
|
|
2501
|
+
console.log(chalk8.dim(" 1. \uD574\uB2F9 \uD30C\uC77C\uC5D0\uC11C \uC2DC\uD06C\uB9BF\uC744 \uC81C\uAC70\uD558\uACE0 \uD658\uACBD\uBCC0\uC218\uB85C \uC774\uB3D9"));
|
|
2502
|
+
console.log(chalk8.dim(" 2. git history\uC5D0\uC11C\uB3C4 \uC81C\uAC70: git filter-branch \uB610\uB294 BFG Repo-Cleaner"));
|
|
2503
|
+
console.log(chalk8.dim(" 3. \uC720\uCD9C\uB41C \uD0A4\uB294 \uC989\uC2DC \uD3D0\uAE30\uD558\uACE0 \uC7AC\uBC1C\uAE09\n"));
|
|
2760
2504
|
if (critical.length > 0 || high.length > 0) {
|
|
2761
2505
|
process.exitCode = 1;
|
|
2762
2506
|
}
|
|
2763
2507
|
}
|
|
2764
2508
|
|
|
2765
2509
|
// src/commands/doctor.ts
|
|
2766
|
-
import
|
|
2510
|
+
import chalk9 from "chalk";
|
|
2767
2511
|
import { execSync } from "child_process";
|
|
2768
2512
|
import fs12 from "fs";
|
|
2769
2513
|
import path12 from "path";
|
|
@@ -2816,7 +2560,7 @@ function compareSemver(a, b) {
|
|
|
2816
2560
|
return a3 - b3;
|
|
2817
2561
|
}
|
|
2818
2562
|
async function doctor() {
|
|
2819
|
-
console.log(
|
|
2563
|
+
console.log(chalk9.bold(`
|
|
2820
2564
|
${ko.doctor.title}
|
|
2821
2565
|
`));
|
|
2822
2566
|
const checks = [
|
|
@@ -2828,30 +2572,30 @@ ${ko.doctor.title}
|
|
|
2828
2572
|
let allOk = true;
|
|
2829
2573
|
for (const check2 of checks) {
|
|
2830
2574
|
if (check2.ok) {
|
|
2831
|
-
console.log(
|
|
2575
|
+
console.log(chalk9.green(` \u2705 ${check2.name}`) + chalk9.dim(` \u2014 ${check2.version}`));
|
|
2832
2576
|
} else {
|
|
2833
|
-
console.log(
|
|
2834
|
-
console.log(
|
|
2577
|
+
console.log(chalk9.red(` \u274C ${check2.name} \uC5C6\uC74C`));
|
|
2578
|
+
console.log(chalk9.dim(` \u2192 ${check2.hint}`));
|
|
2835
2579
|
allOk = false;
|
|
2836
2580
|
}
|
|
2837
2581
|
}
|
|
2838
2582
|
console.log("");
|
|
2839
2583
|
const vhkVersion = getVhkVersion();
|
|
2840
2584
|
if (vhkVersion) {
|
|
2841
|
-
console.log(
|
|
2585
|
+
console.log(chalk9.green(" \u2705 VHK") + chalk9.dim(` \u2014 v${vhkVersion}`));
|
|
2842
2586
|
} else {
|
|
2843
|
-
console.log(
|
|
2587
|
+
console.log(chalk9.green(" \u2705 VHK") + chalk9.dim(" \u2014 \uC124\uCE58\uB428"));
|
|
2844
2588
|
}
|
|
2845
2589
|
if (vhkVersion) {
|
|
2846
2590
|
const latest = fetchLatestNpmVersion("@byh3071/vhk");
|
|
2847
2591
|
if (latest && compareSemver(latest, vhkVersion) > 0) {
|
|
2848
|
-
console.log(
|
|
2592
|
+
console.log(chalk9.yellow(` ${ko.doctor.updateAvailable(latest)}`));
|
|
2849
2593
|
} else if (latest) {
|
|
2850
|
-
console.log(
|
|
2594
|
+
console.log(chalk9.dim(` ${ko.doctor.updateCurrent}`));
|
|
2851
2595
|
}
|
|
2852
2596
|
}
|
|
2853
2597
|
console.log("");
|
|
2854
|
-
console.log(
|
|
2598
|
+
console.log(chalk9.bold(` ${ko.doctor.projectFiles}`));
|
|
2855
2599
|
const cwd = process.cwd();
|
|
2856
2600
|
const projectFiles = [
|
|
2857
2601
|
{ name: "RULES.md", hint: "vhk init\uC73C\uB85C \uC0DD\uC131 \uAC00\uB2A5" },
|
|
@@ -2863,30 +2607,30 @@ ${ko.doctor.title}
|
|
|
2863
2607
|
for (const file of projectFiles) {
|
|
2864
2608
|
const exists = fs12.existsSync(path12.join(cwd, file.name));
|
|
2865
2609
|
if (exists) {
|
|
2866
|
-
console.log(
|
|
2610
|
+
console.log(chalk9.green(` \u2705 ${file.name}`));
|
|
2867
2611
|
if (file.name === ".env") {
|
|
2868
2612
|
const gitignorePath = path12.join(cwd, ".gitignore");
|
|
2869
2613
|
if (fs12.existsSync(gitignorePath)) {
|
|
2870
2614
|
const gitignore = fs12.readFileSync(gitignorePath, "utf-8");
|
|
2871
2615
|
if (!gitignore.includes(".env")) {
|
|
2872
|
-
console.log(
|
|
2616
|
+
console.log(chalk9.yellow(` ${ko.doctor.envNotIgnored}`));
|
|
2873
2617
|
}
|
|
2874
2618
|
}
|
|
2875
2619
|
}
|
|
2876
2620
|
} else {
|
|
2877
|
-
console.log(
|
|
2621
|
+
console.log(chalk9.dim(` \u2B1A ${file.name}`) + chalk9.dim(` \u2014 ${file.hint}`));
|
|
2878
2622
|
}
|
|
2879
2623
|
}
|
|
2880
2624
|
console.log("");
|
|
2881
2625
|
if (allOk) {
|
|
2882
|
-
console.log(
|
|
2626
|
+
console.log(chalk9.green.bold(` ${ko.doctor.allOk}`));
|
|
2883
2627
|
printNextStep({
|
|
2884
2628
|
message: ko.doctor.nextOkMessage,
|
|
2885
2629
|
command: "vhk \uC2DC\uC791",
|
|
2886
2630
|
cursorHint: "\uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uC5B4\uC918"
|
|
2887
2631
|
});
|
|
2888
2632
|
} else {
|
|
2889
|
-
console.log(
|
|
2633
|
+
console.log(chalk9.yellow.bold(` ${ko.doctor.missing} ${ko.doctor.missingHint}`));
|
|
2890
2634
|
printNextStep({
|
|
2891
2635
|
message: ko.doctor.nextRetryMessage,
|
|
2892
2636
|
command: "vhk doctor",
|
|
@@ -2897,7 +2641,7 @@ ${ko.doctor.title}
|
|
|
2897
2641
|
}
|
|
2898
2642
|
|
|
2899
2643
|
// src/commands/ship.ts
|
|
2900
|
-
import
|
|
2644
|
+
import chalk10 from "chalk";
|
|
2901
2645
|
import inquirer4 from "inquirer";
|
|
2902
2646
|
import fs13 from "fs";
|
|
2903
2647
|
import path13 from "path";
|
|
@@ -2936,29 +2680,29 @@ function updateChangelogUnreleased(cwd, version, date) {
|
|
|
2936
2680
|
return { status: "updated", version };
|
|
2937
2681
|
}
|
|
2938
2682
|
async function ship() {
|
|
2939
|
-
console.log(
|
|
2683
|
+
console.log(chalk10.bold(`
|
|
2940
2684
|
${ko.ship.title}
|
|
2941
2685
|
`));
|
|
2942
2686
|
const cwd = process.cwd();
|
|
2943
|
-
console.log(
|
|
2687
|
+
console.log(chalk10.cyan.bold(` ${ko.ship.checklist}
|
|
2944
2688
|
`));
|
|
2945
2689
|
const { passed } = await inquirer4.prompt([{
|
|
2946
2690
|
type: "checkbox",
|
|
2947
2691
|
name: "passed",
|
|
2948
2692
|
message: ko.ship.checkboxPrompt,
|
|
2949
2693
|
choices: CHECKLIST.map((c) => ({
|
|
2950
|
-
name: `${ko.ship[c.questionKey]} ${
|
|
2694
|
+
name: `${ko.ship[c.questionKey]} ${chalk10.dim(`(${ko.ship[c.hintKey]})`)}`,
|
|
2951
2695
|
value: c.id
|
|
2952
2696
|
}))
|
|
2953
2697
|
}]);
|
|
2954
2698
|
const allPassed = passed.length === CHECKLIST.length;
|
|
2955
2699
|
const skipped = CHECKLIST.filter((c) => !passed.includes(c.id));
|
|
2956
2700
|
if (!allPassed) {
|
|
2957
|
-
console.log(
|
|
2701
|
+
console.log(chalk10.yellow(`
|
|
2958
2702
|
${ko.ship.incompleteHeader}`));
|
|
2959
2703
|
skipped.forEach((s) => {
|
|
2960
|
-
console.log(
|
|
2961
|
-
console.log(
|
|
2704
|
+
console.log(chalk10.yellow(` \u2022 ${ko.ship[s.questionKey]}`));
|
|
2705
|
+
console.log(chalk10.dim(` \u2192 ${ko.ship[s.hintKey]}`));
|
|
2962
2706
|
});
|
|
2963
2707
|
const { proceed } = await inquirer4.prompt([{
|
|
2964
2708
|
type: "confirm",
|
|
@@ -2975,13 +2719,13 @@ ${ko.ship.title}
|
|
|
2975
2719
|
return;
|
|
2976
2720
|
}
|
|
2977
2721
|
} else {
|
|
2978
|
-
console.log(
|
|
2722
|
+
console.log(chalk10.green(`
|
|
2979
2723
|
${ko.ship.allPassed}
|
|
2980
2724
|
`));
|
|
2981
2725
|
}
|
|
2982
|
-
console.log(
|
|
2726
|
+
console.log(chalk10.cyan.bold(` ${ko.ship.retro}
|
|
2983
2727
|
`));
|
|
2984
|
-
console.log(
|
|
2728
|
+
console.log(chalk10.dim(` ${ko.ship.versionHint}`));
|
|
2985
2729
|
const retro = await inquirer4.prompt([
|
|
2986
2730
|
{ type: "input", name: "version", message: ko.ship.versionPrompt },
|
|
2987
2731
|
{ type: "input", name: "whatWentWell", message: ko.ship.questionWell },
|
|
@@ -3024,7 +2768,7 @@ ${ko.ship.title}
|
|
|
3024
2768
|
`*Generated by \`vhk ship\` at ${(/* @__PURE__ */ new Date()).toISOString()}*`
|
|
3025
2769
|
].join("\n");
|
|
3026
2770
|
fs13.writeFileSync(filePath, content, "utf-8");
|
|
3027
|
-
console.log(
|
|
2771
|
+
console.log(chalk10.green(`
|
|
3028
2772
|
${ko.ship.buildLogDone(path13.relative(cwd, filePath))}`));
|
|
3029
2773
|
const changelogResult = updateChangelogUnreleased(cwd, versionSlug, today);
|
|
3030
2774
|
if (changelogResult.status === "updated") {
|
|
@@ -3044,7 +2788,7 @@ ${ko.ship.title}
|
|
|
3044
2788
|
|
|
3045
2789
|
// src/commands/save.ts
|
|
3046
2790
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
3047
|
-
import
|
|
2791
|
+
import chalk11 from "chalk";
|
|
3048
2792
|
import ora from "ora";
|
|
3049
2793
|
import inquirer5 from "inquirer";
|
|
3050
2794
|
|
|
@@ -3115,29 +2859,29 @@ function statusIcon(code) {
|
|
|
3115
2859
|
return "\u{1F4C4}";
|
|
3116
2860
|
}
|
|
3117
2861
|
async function save() {
|
|
3118
|
-
console.log(
|
|
2862
|
+
console.log(chalk11.bold(`
|
|
3119
2863
|
\u{1F4BE} ${t("save.title")}`));
|
|
3120
|
-
console.log(
|
|
2864
|
+
console.log(chalk11.gray("\u2500".repeat(40)));
|
|
3121
2865
|
let gitRoot;
|
|
3122
2866
|
try {
|
|
3123
2867
|
execFileSync2("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
|
|
3124
2868
|
gitRoot = getGitRoot();
|
|
3125
2869
|
} catch {
|
|
3126
|
-
console.log(
|
|
2870
|
+
console.log(chalk11.red(`\u274C ${t("save.notGitRepo")}`));
|
|
3127
2871
|
return;
|
|
3128
2872
|
}
|
|
3129
|
-
console.log(
|
|
2873
|
+
console.log(chalk11.cyan(`
|
|
3130
2874
|
\u{1F512} ${t("save.securityWarnHeader")}`));
|
|
3131
2875
|
printSecurityWarnings(gitRoot);
|
|
3132
2876
|
const severe = filterSevereFindings(scanProjectForSecrets(gitRoot).findings);
|
|
3133
2877
|
if (severe.length > 0) {
|
|
3134
|
-
console.log(
|
|
2878
|
+
console.log(chalk11.red(`
|
|
3135
2879
|
\u26A0\uFE0F ${t("save.secretsFound", severe.length)}`));
|
|
3136
2880
|
severe.slice(0, 5).forEach((f) => {
|
|
3137
|
-
console.log(
|
|
2881
|
+
console.log(chalk11.dim(` ${f.file}:${f.line} \u2014 ${f.patternName}`));
|
|
3138
2882
|
});
|
|
3139
2883
|
if (severe.length > 5) {
|
|
3140
|
-
console.log(
|
|
2884
|
+
console.log(chalk11.dim(` ... \uC678 ${severe.length - 5}\uAC74 (vhk \uBCF4\uC548 scan)`));
|
|
3141
2885
|
}
|
|
3142
2886
|
const { proceed } = await inquirer5.prompt([{
|
|
3143
2887
|
type: "confirm",
|
|
@@ -3146,16 +2890,16 @@ async function save() {
|
|
|
3146
2890
|
default: false
|
|
3147
2891
|
}]);
|
|
3148
2892
|
if (!proceed) {
|
|
3149
|
-
console.log(
|
|
2893
|
+
console.log(chalk11.gray(t("save.cancelled")));
|
|
3150
2894
|
return;
|
|
3151
2895
|
}
|
|
3152
2896
|
}
|
|
3153
2897
|
const lines = parsePorcelainLines(gitOut(["status", "--porcelain"], gitRoot));
|
|
3154
2898
|
if (lines.length === 0) {
|
|
3155
|
-
console.log(
|
|
2899
|
+
console.log(chalk11.yellow(`\u{1F4ED} ${t("save.noChanges")}`));
|
|
3156
2900
|
return;
|
|
3157
2901
|
}
|
|
3158
|
-
console.log(
|
|
2902
|
+
console.log(chalk11.cyan(`
|
|
3159
2903
|
\u{1F4CB} ${t("save.filesHeader", lines.length)}`));
|
|
3160
2904
|
lines.forEach((line) => {
|
|
3161
2905
|
const code = line.substring(0, 2);
|
|
@@ -3177,34 +2921,34 @@ async function save() {
|
|
|
3177
2921
|
spinner.text = t("save.pushing");
|
|
3178
2922
|
if (!hasGitRemote(gitRoot)) {
|
|
3179
2923
|
spinner.succeed(t("save.successLocal"));
|
|
3180
|
-
console.log(
|
|
2924
|
+
console.log(chalk11.yellow(` \u{1F4A1} ${t("save.noRemote")}`));
|
|
3181
2925
|
} else {
|
|
3182
2926
|
try {
|
|
3183
2927
|
gitRun(["push"], gitRoot);
|
|
3184
2928
|
spinner.succeed(t("save.successWithPush"));
|
|
3185
2929
|
} catch (pushErr) {
|
|
3186
2930
|
spinner.fail(t("save.pushFailed"));
|
|
3187
|
-
console.log(
|
|
3188
|
-
console.log(
|
|
2931
|
+
console.log(chalk11.red(getExecErrorMessage(pushErr)));
|
|
2932
|
+
console.log(chalk11.yellow(`
|
|
3189
2933
|
\u{1F4A1} ${t("save.commitOkPushFailed")}`));
|
|
3190
2934
|
process.exitCode = 1;
|
|
3191
2935
|
}
|
|
3192
2936
|
}
|
|
3193
2937
|
if (process.exitCode !== 1) {
|
|
3194
|
-
console.log(
|
|
2938
|
+
console.log(chalk11.green(`
|
|
3195
2939
|
\u2705 ${t("save.done", lines.length)}`));
|
|
3196
2940
|
} else {
|
|
3197
|
-
console.log(
|
|
2941
|
+
console.log(chalk11.green(`
|
|
3198
2942
|
\u2705 ${t("save.doneLocalOnly", lines.length)}`));
|
|
3199
2943
|
}
|
|
3200
2944
|
} catch (err) {
|
|
3201
2945
|
spinner.fail(t("save.failed"));
|
|
3202
|
-
console.log(
|
|
2946
|
+
console.log(chalk11.red(getExecErrorMessage(err)));
|
|
3203
2947
|
if (didAdd) {
|
|
3204
2948
|
try {
|
|
3205
2949
|
const staged = gitOut(["diff", "--cached", "--stat"], gitRoot).trim();
|
|
3206
2950
|
if (staged) {
|
|
3207
|
-
console.log(
|
|
2951
|
+
console.log(chalk11.yellow(`
|
|
3208
2952
|
\u{1F4A1} ${t("save.stagedAfterFail")}`));
|
|
3209
2953
|
}
|
|
3210
2954
|
} catch {
|
|
@@ -3216,7 +2960,7 @@ async function save() {
|
|
|
3216
2960
|
|
|
3217
2961
|
// src/commands/undo.ts
|
|
3218
2962
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
3219
|
-
import
|
|
2963
|
+
import chalk12 from "chalk";
|
|
3220
2964
|
import inquirer6 from "inquirer";
|
|
3221
2965
|
function parseRecentCommits(logOutput) {
|
|
3222
2966
|
return logOutput.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
@@ -3240,30 +2984,30 @@ function isUndoRisky(undoCount, unpushedCount, hasRemote) {
|
|
|
3240
2984
|
return false;
|
|
3241
2985
|
}
|
|
3242
2986
|
async function undo() {
|
|
3243
|
-
console.log(
|
|
2987
|
+
console.log(chalk12.bold(`
|
|
3244
2988
|
\u23EA ${t("undo.title")}`));
|
|
3245
|
-
console.log(
|
|
2989
|
+
console.log(chalk12.gray("\u2500".repeat(40)));
|
|
3246
2990
|
let gitRoot;
|
|
3247
2991
|
try {
|
|
3248
2992
|
execFileSync3("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
|
|
3249
2993
|
gitRoot = getGitRoot();
|
|
3250
2994
|
} catch {
|
|
3251
|
-
console.log(
|
|
2995
|
+
console.log(chalk12.red(`\u274C ${t("undo.notGitRepo")}`));
|
|
3252
2996
|
return;
|
|
3253
2997
|
}
|
|
3254
2998
|
let logOutput;
|
|
3255
2999
|
try {
|
|
3256
3000
|
logOutput = gitOut(["log", "--oneline", "-5"], gitRoot).trim();
|
|
3257
3001
|
} catch {
|
|
3258
|
-
console.log(
|
|
3002
|
+
console.log(chalk12.yellow(`\u{1F4ED} ${t("undo.noCommits")}`));
|
|
3259
3003
|
return;
|
|
3260
3004
|
}
|
|
3261
3005
|
const commits = parseRecentCommits(logOutput);
|
|
3262
3006
|
if (commits.length === 0) {
|
|
3263
|
-
console.log(
|
|
3007
|
+
console.log(chalk12.yellow(`\u{1F4ED} ${t("undo.noCommits")}`));
|
|
3264
3008
|
return;
|
|
3265
3009
|
}
|
|
3266
|
-
console.log(
|
|
3010
|
+
console.log(chalk12.cyan(`
|
|
3267
3011
|
${t("undo.recentHeader")}`));
|
|
3268
3012
|
commits.forEach((c, i) => {
|
|
3269
3013
|
console.log(` ${i === 0 ? "\u{1F449}" : " "} ${c}`);
|
|
@@ -3280,7 +3024,7 @@ ${t("undo.recentHeader")}`));
|
|
|
3280
3024
|
const undoCount = Math.min(Math.max(1, count || 1), maxUndo);
|
|
3281
3025
|
const headCount = countLocalCommits(gitRoot);
|
|
3282
3026
|
if (undoCount >= headCount) {
|
|
3283
|
-
console.log(
|
|
3027
|
+
console.log(chalk12.yellow(`
|
|
3284
3028
|
\u{1F4ED} ${t("undo.rootCommit")}`));
|
|
3285
3029
|
return;
|
|
3286
3030
|
}
|
|
@@ -3289,10 +3033,10 @@ ${t("undo.recentHeader")}`));
|
|
|
3289
3033
|
const risky = isUndoRisky(undoCount, unpushed, remote);
|
|
3290
3034
|
if (risky) {
|
|
3291
3035
|
if (unpushed < 0) {
|
|
3292
|
-
console.log(
|
|
3036
|
+
console.log(chalk12.red(`
|
|
3293
3037
|
\u26A0\uFE0F ${t("undo.noUpstreamWarning")}`));
|
|
3294
3038
|
} else {
|
|
3295
|
-
console.log(
|
|
3039
|
+
console.log(chalk12.red(`
|
|
3296
3040
|
\u26A0\uFE0F ${t("undo.alreadyPushed")}`));
|
|
3297
3041
|
}
|
|
3298
3042
|
}
|
|
@@ -3303,22 +3047,22 @@ ${t("undo.recentHeader")}`));
|
|
|
3303
3047
|
default: false
|
|
3304
3048
|
}]);
|
|
3305
3049
|
if (!confirm) {
|
|
3306
|
-
console.log(
|
|
3050
|
+
console.log(chalk12.gray(t("undo.cancelled")));
|
|
3307
3051
|
return;
|
|
3308
3052
|
}
|
|
3309
3053
|
try {
|
|
3310
3054
|
gitRun(["reset", "--soft", `HEAD~${undoCount}`], gitRoot);
|
|
3311
|
-
console.log(
|
|
3055
|
+
console.log(chalk12.green(`
|
|
3312
3056
|
\u2705 ${t("undo.success")}`));
|
|
3313
|
-
console.log(
|
|
3057
|
+
console.log(chalk12.gray(` \u{1F4A1} ${t("undo.stagedHint")}`));
|
|
3314
3058
|
if (risky) {
|
|
3315
|
-
console.log(
|
|
3059
|
+
console.log(chalk12.yellow(`
|
|
3316
3060
|
\u{1F4A1} ${t("undo.forcePushHint")}`));
|
|
3317
3061
|
}
|
|
3318
3062
|
} catch (err) {
|
|
3319
|
-
console.log(
|
|
3063
|
+
console.log(chalk12.red(`\u274C ${t("undo.failed")}`));
|
|
3320
3064
|
const msg = err instanceof Error ? err.message : String(err);
|
|
3321
|
-
console.log(
|
|
3065
|
+
console.log(chalk12.red(msg));
|
|
3322
3066
|
process.exitCode = 1;
|
|
3323
3067
|
}
|
|
3324
3068
|
}
|
|
@@ -3327,7 +3071,7 @@ ${t("undo.recentHeader")}`));
|
|
|
3327
3071
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
3328
3072
|
import fs15 from "fs";
|
|
3329
3073
|
import path14 from "path";
|
|
3330
|
-
import
|
|
3074
|
+
import chalk13 from "chalk";
|
|
3331
3075
|
|
|
3332
3076
|
// src/lib/read-json.ts
|
|
3333
3077
|
import fs14 from "fs";
|
|
@@ -3399,15 +3143,15 @@ function getSyncCounts(gitRoot) {
|
|
|
3399
3143
|
}
|
|
3400
3144
|
}
|
|
3401
3145
|
async function status() {
|
|
3402
|
-
console.log(
|
|
3146
|
+
console.log(chalk13.bold(`
|
|
3403
3147
|
\u{1F4CA} ${t("status.title")}`));
|
|
3404
|
-
console.log(
|
|
3148
|
+
console.log(chalk13.gray("\u2500".repeat(40)));
|
|
3405
3149
|
let gitRoot;
|
|
3406
3150
|
try {
|
|
3407
3151
|
execFileSync4("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
|
|
3408
3152
|
gitRoot = getGitRoot();
|
|
3409
3153
|
} catch {
|
|
3410
|
-
console.log(
|
|
3154
|
+
console.log(chalk13.red(`\u274C ${t("status.notGitRepo")}`));
|
|
3411
3155
|
return;
|
|
3412
3156
|
}
|
|
3413
3157
|
let branch;
|
|
@@ -3426,36 +3170,36 @@ async function status() {
|
|
|
3426
3170
|
commits = [];
|
|
3427
3171
|
}
|
|
3428
3172
|
const pkg = readProjectPackage();
|
|
3429
|
-
console.log(
|
|
3430
|
-
\u{1F33F} ${t("status.branch")}`) +
|
|
3173
|
+
console.log(chalk13.cyan(`
|
|
3174
|
+
\u{1F33F} ${t("status.branch")}`) + chalk13.white(` ${branch}`));
|
|
3431
3175
|
console.log(
|
|
3432
|
-
|
|
3176
|
+
chalk13.cyan(`\u{1F4C1} ${t("status.changes")}`) + chalk13.white(
|
|
3433
3177
|
` staged ${counts.staged} \xB7 unstaged ${counts.unstaged} \xB7 untracked ${counts.untracked}`
|
|
3434
3178
|
)
|
|
3435
3179
|
);
|
|
3436
|
-
console.log(
|
|
3180
|
+
console.log(chalk13.cyan(`
|
|
3437
3181
|
\u{1F4CB} ${t("status.recentCommits")}`));
|
|
3438
3182
|
if (commits.length === 0) {
|
|
3439
|
-
console.log(
|
|
3183
|
+
console.log(chalk13.dim(` ${t("status.noCommits")}`));
|
|
3440
3184
|
} else {
|
|
3441
|
-
commits.forEach((c) => console.log(` ${
|
|
3185
|
+
commits.forEach((c) => console.log(` ${chalk13.dim("\u2022")} ${c}`));
|
|
3442
3186
|
}
|
|
3443
3187
|
console.log(
|
|
3444
|
-
|
|
3445
|
-
\u{1F504} ${t("status.remote")}`) +
|
|
3188
|
+
chalk13.cyan(`
|
|
3189
|
+
\u{1F504} ${t("status.remote")}`) + chalk13.white(` ${formatSyncLabel(sync2)}`)
|
|
3446
3190
|
);
|
|
3447
|
-
console.log(
|
|
3191
|
+
console.log(chalk13.gray("\n" + "\u2500".repeat(40)));
|
|
3448
3192
|
if (pkg) {
|
|
3449
|
-
console.log(
|
|
3193
|
+
console.log(chalk13.cyan(`\u{1F4E6} ${t("status.package")}`) + chalk13.white(` ${pkg.name} v${pkg.version}`));
|
|
3450
3194
|
} else {
|
|
3451
|
-
console.log(
|
|
3195
|
+
console.log(chalk13.dim(`\u{1F4E6} ${t("status.noPackage")}`));
|
|
3452
3196
|
}
|
|
3453
3197
|
console.log("");
|
|
3454
3198
|
}
|
|
3455
3199
|
|
|
3456
3200
|
// src/commands/diff.ts
|
|
3457
3201
|
import { execFileSync as execFileSync5, execSync as execSync2 } from "child_process";
|
|
3458
|
-
import
|
|
3202
|
+
import chalk14 from "chalk";
|
|
3459
3203
|
function gitOut2(args) {
|
|
3460
3204
|
try {
|
|
3461
3205
|
return execFileSync5("git", args, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
@@ -3495,53 +3239,53 @@ function summarizeNumstat(numstat) {
|
|
|
3495
3239
|
return { fileCount, totalAdd, totalDel };
|
|
3496
3240
|
}
|
|
3497
3241
|
function printFile(f) {
|
|
3498
|
-
const adds = f.additions > 0 ?
|
|
3499
|
-
const dels = f.deletions > 0 ?
|
|
3242
|
+
const adds = f.additions > 0 ? chalk14.green(`+${f.additions}`) : "";
|
|
3243
|
+
const dels = f.deletions > 0 ? chalk14.red(`-${f.deletions}`) : "";
|
|
3500
3244
|
const change = [adds, dels].filter(Boolean).join(" ");
|
|
3501
3245
|
console.log(` ${f.name} ${change}`);
|
|
3502
3246
|
}
|
|
3503
3247
|
async function diff() {
|
|
3504
|
-
console.log(
|
|
3248
|
+
console.log(chalk14.bold(`
|
|
3505
3249
|
\u{1F50D} ${t("diff.title")}`));
|
|
3506
|
-
console.log(
|
|
3250
|
+
console.log(chalk14.gray("\u2500".repeat(40)));
|
|
3507
3251
|
try {
|
|
3508
3252
|
execSync2("git rev-parse --is-inside-work-tree", { stdio: "pipe" });
|
|
3509
3253
|
} catch {
|
|
3510
|
-
console.log(
|
|
3254
|
+
console.log(chalk14.red(`\u274C ${t("diff.notGitRepo")}`));
|
|
3511
3255
|
return;
|
|
3512
3256
|
}
|
|
3513
3257
|
const unstaged = gitOut2(["diff", "--stat"]);
|
|
3514
3258
|
const staged = gitOut2(["diff", "--cached", "--stat"]);
|
|
3515
3259
|
const untracked = gitOut2(["ls-files", "--others", "--exclude-standard"]);
|
|
3516
3260
|
if (!unstaged && !staged && !untracked) {
|
|
3517
|
-
console.log(
|
|
3261
|
+
console.log(chalk14.green(`
|
|
3518
3262
|
\u2705 ${t("diff.noChanges")}`));
|
|
3519
3263
|
return;
|
|
3520
3264
|
}
|
|
3521
3265
|
if (staged) {
|
|
3522
|
-
console.log(
|
|
3266
|
+
console.log(chalk14.cyan(`
|
|
3523
3267
|
${t("diff.stagedHeader")}`));
|
|
3524
3268
|
parseDiffStat(staged).forEach((f) => printFile(f));
|
|
3525
3269
|
}
|
|
3526
3270
|
if (unstaged) {
|
|
3527
|
-
console.log(
|
|
3271
|
+
console.log(chalk14.cyan(`
|
|
3528
3272
|
${t("diff.unstagedHeader")}`));
|
|
3529
3273
|
parseDiffStat(unstaged).forEach((f) => printFile(f));
|
|
3530
3274
|
}
|
|
3531
3275
|
if (untracked) {
|
|
3532
3276
|
const files = untracked.split("\n").filter(Boolean);
|
|
3533
|
-
console.log(
|
|
3277
|
+
console.log(chalk14.cyan(`
|
|
3534
3278
|
${t("diff.untrackedHeader", files.length)}`));
|
|
3535
|
-
files.forEach((f) => console.log(` ${
|
|
3279
|
+
files.forEach((f) => console.log(` ${chalk14.green("+")} ${f}`));
|
|
3536
3280
|
}
|
|
3537
3281
|
const numstat = gitOut2(["diff", "--numstat", "HEAD"]);
|
|
3538
3282
|
if (numstat) {
|
|
3539
3283
|
const { fileCount, totalAdd, totalDel } = summarizeNumstat(numstat);
|
|
3540
|
-
console.log(
|
|
3284
|
+
console.log(chalk14.cyan(`
|
|
3541
3285
|
${t("diff.summaryHeader")}`));
|
|
3542
3286
|
console.log(` ${t("diff.filesLine", fileCount)}`);
|
|
3543
|
-
console.log(` \uCD94\uAC00: ${
|
|
3544
|
-
console.log(` \uC0AD\uC81C: ${
|
|
3287
|
+
console.log(` \uCD94\uAC00: ${chalk14.green(`+${totalAdd}`)}\uC904`);
|
|
3288
|
+
console.log(` \uC0AD\uC81C: ${chalk14.red(`-${totalDel}`)}\uC904`);
|
|
3545
3289
|
}
|
|
3546
3290
|
console.log("");
|
|
3547
3291
|
}
|
|
@@ -3550,8 +3294,18 @@ ${t("diff.summaryHeader")}`));
|
|
|
3550
3294
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
3551
3295
|
import { join } from "path";
|
|
3552
3296
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3553
|
-
import
|
|
3297
|
+
import chalk15 from "chalk";
|
|
3554
3298
|
function resolveVhkMcpPath() {
|
|
3299
|
+
try {
|
|
3300
|
+
const pkgPath = join(process.cwd(), "package.json");
|
|
3301
|
+
if (existsSync(pkgPath)) {
|
|
3302
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
3303
|
+
if (pkg.name === "@byh3071/vhk") {
|
|
3304
|
+
return join(process.cwd(), "dist", "mcp", "index.js");
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
} catch {
|
|
3308
|
+
}
|
|
3555
3309
|
try {
|
|
3556
3310
|
const url = import.meta.resolve?.("@byh3071/vhk/dist/mcp/index.js");
|
|
3557
3311
|
if (typeof url === "string") return fileURLToPath2(url);
|
|
@@ -3560,8 +3314,8 @@ function resolveVhkMcpPath() {
|
|
|
3560
3314
|
return join(process.cwd(), "node_modules", "@byh3071", "vhk", "dist", "mcp", "index.js");
|
|
3561
3315
|
}
|
|
3562
3316
|
async function mcpInit() {
|
|
3563
|
-
console.log(
|
|
3564
|
-
console.log(
|
|
3317
|
+
console.log(chalk15.bold("\n\u{1F50C} " + t("mcp.initTitle")));
|
|
3318
|
+
console.log(chalk15.gray("\u2500".repeat(40)));
|
|
3565
3319
|
const cursorDir = join(process.cwd(), ".cursor");
|
|
3566
3320
|
if (!existsSync(cursorDir)) {
|
|
3567
3321
|
mkdirSync(cursorDir, { recursive: true });
|
|
@@ -3579,20 +3333,242 @@ async function mcpInit() {
|
|
|
3579
3333
|
mcpServers: { ...parsed.mcpServers ?? {}, vhk: vhkEntry }
|
|
3580
3334
|
};
|
|
3581
3335
|
} catch {
|
|
3582
|
-
console.log(
|
|
3336
|
+
console.log(chalk15.yellow("\u26A0\uFE0F \uAE30\uC874 .cursor/mcp.json \uD30C\uC2F1 \uC2E4\uD328 \u2014 \uC0C8 \uD30C\uC77C\uB85C \uB36E\uC5B4\uC501\uB2C8\uB2E4."));
|
|
3583
3337
|
config = { mcpServers: { vhk: vhkEntry } };
|
|
3584
3338
|
}
|
|
3585
3339
|
} else {
|
|
3586
3340
|
config = { mcpServers: { vhk: vhkEntry } };
|
|
3587
3341
|
}
|
|
3588
3342
|
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
3589
|
-
console.log(
|
|
3590
|
-
console.log(
|
|
3343
|
+
console.log(chalk15.green("\n\u2705 Cursor MCP \uC124\uC815 \uC644\uB8CC!"));
|
|
3344
|
+
console.log(chalk15.cyan("\u{1F4C1} \uC0DD\uC131\uB41C \uD30C\uC77C:"));
|
|
3591
3345
|
console.log(` ${configPath}`);
|
|
3592
|
-
console.log(
|
|
3346
|
+
console.log(chalk15.cyan("\n\u{1F504} \uB2E4\uC74C \uB2E8\uACC4:"));
|
|
3593
3347
|
console.log(" 1. Cursor\uB97C \uC7AC\uC2DC\uC791\uD558\uC138\uC694");
|
|
3594
3348
|
console.log(" 2. Cursor \uCC44\uD305\uC5D0\uC11C vhk \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4");
|
|
3595
|
-
console.log(
|
|
3349
|
+
console.log(chalk15.gray('\n\u{1F4A1} \uC608: "\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC \uC54C\uB824\uC918" \u2192 Cursor\uAC00 vhk status \uD638\uCD9C'));
|
|
3350
|
+
}
|
|
3351
|
+
|
|
3352
|
+
// src/commands/deploy.ts
|
|
3353
|
+
import { existsSync as existsSync2 } from "fs";
|
|
3354
|
+
import chalk16 from "chalk";
|
|
3355
|
+
import inquirer7 from "inquirer";
|
|
3356
|
+
var PLATFORMS = {
|
|
3357
|
+
vercel: {
|
|
3358
|
+
name: "Vercel",
|
|
3359
|
+
detectFiles: ["vercel.json", ".vercel"],
|
|
3360
|
+
command: "vercel",
|
|
3361
|
+
commandArgs: ["--prod"],
|
|
3362
|
+
checkArgs: ["--version"],
|
|
3363
|
+
installHint: "npm i -g vercel"
|
|
3364
|
+
},
|
|
3365
|
+
netlify: {
|
|
3366
|
+
name: "Netlify",
|
|
3367
|
+
detectFiles: ["netlify.toml", ".netlify"],
|
|
3368
|
+
command: "netlify",
|
|
3369
|
+
commandArgs: ["deploy", "--prod"],
|
|
3370
|
+
checkArgs: ["--version"],
|
|
3371
|
+
installHint: "npm i -g netlify-cli"
|
|
3372
|
+
},
|
|
3373
|
+
cloudflare: {
|
|
3374
|
+
name: "Cloudflare Workers",
|
|
3375
|
+
detectFiles: ["wrangler.toml"],
|
|
3376
|
+
command: "wrangler",
|
|
3377
|
+
commandArgs: ["deploy"],
|
|
3378
|
+
checkArgs: ["--version"],
|
|
3379
|
+
installHint: "npm i -g wrangler"
|
|
3380
|
+
}
|
|
3381
|
+
};
|
|
3382
|
+
function detectPlatform() {
|
|
3383
|
+
for (const [key, config] of Object.entries(PLATFORMS)) {
|
|
3384
|
+
for (const file of config.detectFiles) {
|
|
3385
|
+
if (existsSync2(file)) return key;
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
return null;
|
|
3389
|
+
}
|
|
3390
|
+
function isCLIAvailable(cmd, checkArgs) {
|
|
3391
|
+
return safeExecFile(cmd, checkArgs).ok;
|
|
3392
|
+
}
|
|
3393
|
+
async function deploy() {
|
|
3394
|
+
console.log(chalk16.bold("\n\u{1F680} " + t("deploy.title")));
|
|
3395
|
+
console.log(chalk16.gray("\u2500".repeat(40)));
|
|
3396
|
+
let platform = detectPlatform();
|
|
3397
|
+
if (platform) {
|
|
3398
|
+
console.log(chalk16.cyan(`
|
|
3399
|
+
\u{1F50D} \uAC10\uC9C0\uB41C \uD50C\uB7AB\uD3FC: ${PLATFORMS[platform].name}`));
|
|
3400
|
+
} else {
|
|
3401
|
+
const { selected } = await inquirer7.prompt([
|
|
3402
|
+
{
|
|
3403
|
+
type: "list",
|
|
3404
|
+
name: "selected",
|
|
3405
|
+
message: t("deploy.selectPlatform"),
|
|
3406
|
+
choices: [
|
|
3407
|
+
{ name: "\u25B2 Vercel", value: "vercel" },
|
|
3408
|
+
{ name: "\u25C6 Netlify", value: "netlify" },
|
|
3409
|
+
{ name: "\u2601 Cloudflare Workers", value: "cloudflare" }
|
|
3410
|
+
]
|
|
3411
|
+
}
|
|
3412
|
+
]);
|
|
3413
|
+
platform = selected;
|
|
3414
|
+
}
|
|
3415
|
+
const config = PLATFORMS[platform];
|
|
3416
|
+
if (!isCLIAvailable(config.command, config.checkArgs)) {
|
|
3417
|
+
console.log(chalk16.red(`
|
|
3418
|
+
\u274C ${config.name} CLI\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.`));
|
|
3419
|
+
console.log(chalk16.yellow(` \u2192 ${config.installHint}`));
|
|
3420
|
+
return;
|
|
3421
|
+
}
|
|
3422
|
+
const { confirm } = await inquirer7.prompt([
|
|
3423
|
+
{
|
|
3424
|
+
type: "confirm",
|
|
3425
|
+
name: "confirm",
|
|
3426
|
+
message: `${config.name}\uC5D0 \uD504\uB85C\uB355\uC158 \uBC30\uD3EC\uD560\uAE4C\uC694?`,
|
|
3427
|
+
default: true
|
|
3428
|
+
}
|
|
3429
|
+
]);
|
|
3430
|
+
if (!confirm) {
|
|
3431
|
+
console.log(chalk16.gray("\uCDE8\uC18C\uB428"));
|
|
3432
|
+
return;
|
|
3433
|
+
}
|
|
3434
|
+
console.log(chalk16.cyan(`
|
|
3435
|
+
${t("deploy.deploying")}
|
|
3436
|
+
`));
|
|
3437
|
+
const result = safeExecFileStream(config.command, config.commandArgs);
|
|
3438
|
+
if (result.ok) {
|
|
3439
|
+
console.log(chalk16.green(`
|
|
3440
|
+
\u2705 ${t("deploy.success")}`));
|
|
3441
|
+
printNextStep({
|
|
3442
|
+
message: "\uBC30\uD3EC \uC644\uB8CC! \uC0AC\uC774\uD2B8\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
3443
|
+
command: "vhk status",
|
|
3444
|
+
cursorHint: "\uC0C1\uD0DC \uD655\uC778\uD574\uC918"
|
|
3445
|
+
});
|
|
3446
|
+
} else {
|
|
3447
|
+
console.log(chalk16.red(`
|
|
3448
|
+
\u274C ${t("deploy.failed")}`));
|
|
3449
|
+
console.log(chalk16.red(result.err));
|
|
3450
|
+
}
|
|
3451
|
+
}
|
|
3452
|
+
|
|
3453
|
+
// src/commands/publish.ts
|
|
3454
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
3455
|
+
import chalk17 from "chalk";
|
|
3456
|
+
import inquirer8 from "inquirer";
|
|
3457
|
+
import ora2 from "ora";
|
|
3458
|
+
function bumpVersion(current, type) {
|
|
3459
|
+
const [major, minor, patch] = current.split(".").map((n) => parseInt(n, 10) || 0);
|
|
3460
|
+
switch (type) {
|
|
3461
|
+
case "major":
|
|
3462
|
+
return `${major + 1}.0.0`;
|
|
3463
|
+
case "minor":
|
|
3464
|
+
return `${major}.${minor + 1}.0`;
|
|
3465
|
+
case "patch":
|
|
3466
|
+
return `${major}.${minor}.${patch + 1}`;
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
async function publish() {
|
|
3470
|
+
console.log(chalk17.bold("\n\u{1F4E6} " + t("publish.title")));
|
|
3471
|
+
console.log(chalk17.gray("\u2500".repeat(40)));
|
|
3472
|
+
if (!existsSync3("package.json")) {
|
|
3473
|
+
console.log(chalk17.red("\u274C package.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
3474
|
+
return;
|
|
3475
|
+
}
|
|
3476
|
+
let pkg;
|
|
3477
|
+
try {
|
|
3478
|
+
pkg = JSON.parse(readFileSync2("package.json", "utf-8"));
|
|
3479
|
+
} catch {
|
|
3480
|
+
console.log(chalk17.red("\u274C package.json \uD30C\uC2F1 \uC2E4\uD328"));
|
|
3481
|
+
return;
|
|
3482
|
+
}
|
|
3483
|
+
const currentVersion = pkg.version || "0.0.0";
|
|
3484
|
+
console.log(chalk17.cyan(`
|
|
3485
|
+
\u{1F4CC} \uD604\uC7AC \uBC84\uC804: v${currentVersion}`));
|
|
3486
|
+
const { bumpType } = await inquirer8.prompt([
|
|
3487
|
+
{
|
|
3488
|
+
type: "list",
|
|
3489
|
+
name: "bumpType",
|
|
3490
|
+
message: t("publish.selectBump"),
|
|
3491
|
+
choices: [
|
|
3492
|
+
{ name: `\u{1F527} patch (${bumpVersion(currentVersion, "patch")}) \u2014 \uBC84\uADF8 \uC218\uC815`, value: "patch" },
|
|
3493
|
+
{ name: `\u2728 minor (${bumpVersion(currentVersion, "minor")}) \u2014 \uC0C8 \uAE30\uB2A5`, value: "minor" },
|
|
3494
|
+
{ name: `\u{1F4A5} major (${bumpVersion(currentVersion, "major")}) \u2014 \uD638\uD658\uC131 \uBCC0\uACBD`, value: "major" }
|
|
3495
|
+
]
|
|
3496
|
+
}
|
|
3497
|
+
]);
|
|
3498
|
+
const newVersion = bumpVersion(currentVersion, bumpType);
|
|
3499
|
+
console.log(chalk17.cyan(`
|
|
3500
|
+
\u{1F195} \uC0C8 \uBC84\uC804: v${newVersion}`));
|
|
3501
|
+
pkg.version = newVersion;
|
|
3502
|
+
writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
3503
|
+
console.log(chalk17.green("\u2705 package.json \uBC84\uC804 \uC5C5\uB370\uC774\uD2B8"));
|
|
3504
|
+
const buildSpinner = ora2(t("publish.building")).start();
|
|
3505
|
+
const buildResult = safeExecFile("pnpm", ["build"]);
|
|
3506
|
+
if (!buildResult.ok) {
|
|
3507
|
+
buildSpinner.fail(t("publish.buildFailed"));
|
|
3508
|
+
console.log(chalk17.red(buildResult.err.slice(0, 500)));
|
|
3509
|
+
pkg.version = currentVersion;
|
|
3510
|
+
writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
3511
|
+
return;
|
|
3512
|
+
}
|
|
3513
|
+
buildSpinner.succeed(t("publish.buildSuccess"));
|
|
3514
|
+
const testSpinner = ora2(t("publish.testing")).start();
|
|
3515
|
+
const testResult = safeExecFile("pnpm", ["test", "--run"]);
|
|
3516
|
+
if (!testResult.ok) {
|
|
3517
|
+
testSpinner.fail(t("publish.testFailed"));
|
|
3518
|
+
console.log(chalk17.red(testResult.err.slice(0, 500)));
|
|
3519
|
+
pkg.version = currentVersion;
|
|
3520
|
+
writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
3521
|
+
return;
|
|
3522
|
+
}
|
|
3523
|
+
testSpinner.succeed(t("publish.testSuccess"));
|
|
3524
|
+
const { confirm } = await inquirer8.prompt([
|
|
3525
|
+
{
|
|
3526
|
+
type: "confirm",
|
|
3527
|
+
name: "confirm",
|
|
3528
|
+
message: `v${newVersion}\uC744 npm\uC5D0 \uBC30\uD3EC\uD560\uAE4C\uC694?`,
|
|
3529
|
+
default: true
|
|
3530
|
+
}
|
|
3531
|
+
]);
|
|
3532
|
+
if (!confirm) {
|
|
3533
|
+
pkg.version = currentVersion;
|
|
3534
|
+
writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
3535
|
+
console.log(chalk17.gray("\uCDE8\uC18C\uB428. \uBC84\uC804\uC774 \uC6D0\uB798\uB300\uB85C \uBCF5\uAD6C\uB429\uB2C8\uB2E4."));
|
|
3536
|
+
return;
|
|
3537
|
+
}
|
|
3538
|
+
const pubSpinner = ora2(t("publish.publishing")).start();
|
|
3539
|
+
const pubResult = safeExecFile("npm", ["publish", "--access", "public"]);
|
|
3540
|
+
if (!pubResult.ok) {
|
|
3541
|
+
pubSpinner.fail(t("publish.publishFailed"));
|
|
3542
|
+
console.log(chalk17.red(pubResult.err.slice(0, 500)));
|
|
3543
|
+
pkg.version = currentVersion;
|
|
3544
|
+
writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
3545
|
+
console.log(chalk17.gray(`\u{1F4E6} package.json \uBC84\uC804\uC744 v${currentVersion}\uB85C \uBCF5\uAD6C\uD588\uC2B5\uB2C8\uB2E4.`));
|
|
3546
|
+
return;
|
|
3547
|
+
}
|
|
3548
|
+
pubSpinner.succeed(t("publish.publishSuccess"));
|
|
3549
|
+
const addResult = safeExecFile("git", ["add", "package.json"]);
|
|
3550
|
+
if (addResult.ok) {
|
|
3551
|
+
safeExecFile("git", ["commit", "-m", `chore: release v${newVersion}`]);
|
|
3552
|
+
const tagResult = safeExecFile("git", ["tag", `v${newVersion}`]);
|
|
3553
|
+
if (tagResult.ok) {
|
|
3554
|
+
const pushResult = safeExecFile("git", ["push"]);
|
|
3555
|
+
const pushTagsResult = safeExecFile("git", ["push", "--tags"]);
|
|
3556
|
+
if (pushResult.ok && pushTagsResult.ok) {
|
|
3557
|
+
console.log(chalk17.green(`
|
|
3558
|
+
\u{1F3F7}\uFE0F git tag v${newVersion} \uC0DD\uC131 + push \uC644\uB8CC`));
|
|
3559
|
+
} else {
|
|
3560
|
+
console.log(chalk17.yellow(`
|
|
3561
|
+
\u{1F3F7}\uFE0F git tag v${newVersion} \uC0DD\uC131\uB428 (push\uB294 \uC218\uB3D9\uC73C\uB85C)`));
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
console.log(chalk17.green.bold(`
|
|
3566
|
+
\u{1F389} v${newVersion} \uBC30\uD3EC \uC644\uB8CC!`));
|
|
3567
|
+
printNextStep({
|
|
3568
|
+
message: "npm \uBC30\uD3EC \uC644\uB8CC!",
|
|
3569
|
+
command: "vhk status",
|
|
3570
|
+
cursorHint: "\uC0C1\uD0DC \uD655\uC778\uD574\uC918"
|
|
3571
|
+
});
|
|
3596
3572
|
}
|
|
3597
3573
|
|
|
3598
3574
|
// src/lib/nlp-run.ts
|
|
@@ -3627,28 +3603,36 @@ async function dispatchNlpRoute(route, input) {
|
|
|
3627
3603
|
return diff();
|
|
3628
3604
|
case "mcp-init":
|
|
3629
3605
|
return mcpInit();
|
|
3606
|
+
case "deploy":
|
|
3607
|
+
return deploy();
|
|
3608
|
+
case "env":
|
|
3609
|
+
return env();
|
|
3610
|
+
case "env-check":
|
|
3611
|
+
return envCheck();
|
|
3612
|
+
case "publish":
|
|
3613
|
+
return publish();
|
|
3630
3614
|
}
|
|
3631
3615
|
}
|
|
3632
3616
|
async function runNaturalLanguageRoute(input) {
|
|
3633
3617
|
const route = routeNaturalLanguage(input);
|
|
3634
3618
|
if (!route) {
|
|
3635
|
-
console.log(
|
|
3619
|
+
console.log(chalk18.yellow(`
|
|
3636
3620
|
\u2753 "${input}" \u2014 ${ko.nlp.notMatched}
|
|
3637
3621
|
`));
|
|
3638
3622
|
return;
|
|
3639
3623
|
}
|
|
3640
3624
|
console.log("");
|
|
3641
|
-
console.log(
|
|
3642
|
-
console.log(
|
|
3625
|
+
console.log(chalk18.cyan(` \u{1F4AC} "${input}"`));
|
|
3626
|
+
console.log(chalk18.cyan(` \u2192 ${route.explanation}`));
|
|
3643
3627
|
if (route.confidence === "low") {
|
|
3644
|
-
const { confirm } = await
|
|
3628
|
+
const { confirm } = await inquirer9.prompt([{
|
|
3645
3629
|
type: "confirm",
|
|
3646
3630
|
name: "confirm",
|
|
3647
3631
|
message: `${route.explanation} \u2014 ${ko.nlp.matched}`,
|
|
3648
3632
|
default: true
|
|
3649
3633
|
}]);
|
|
3650
3634
|
if (!confirm) {
|
|
3651
|
-
console.log(
|
|
3635
|
+
console.log(chalk18.dim(` ${ko.nlp.menuHint}`));
|
|
3652
3636
|
return;
|
|
3653
3637
|
}
|
|
3654
3638
|
}
|
|
@@ -3666,14 +3650,18 @@ var KO_ALIASES = {
|
|
|
3666
3650
|
sync: "\uADDC\uCE59",
|
|
3667
3651
|
check: "\uC810\uAC80",
|
|
3668
3652
|
secure: "\uBCF4\uC548",
|
|
3669
|
-
ship: "\
|
|
3653
|
+
ship: "\uCD9C\uD558",
|
|
3670
3654
|
doctor: "\uD658\uACBD",
|
|
3671
3655
|
save: "\uC800\uC7A5",
|
|
3672
3656
|
undo: "\uB418\uB3CC\uB9AC\uAE30",
|
|
3673
3657
|
status: "\uC0C1\uD0DC",
|
|
3674
|
-
diff: "\uBCC0\uACBD"
|
|
3658
|
+
diff: "\uBCC0\uACBD",
|
|
3659
|
+
deploy: "\uBC30\uD3EC",
|
|
3660
|
+
env: "\uD658\uACBD\uBCC0\uC218",
|
|
3661
|
+
"env-check": "\uD658\uACBD\uBCC0\uC218\uC810\uAC80",
|
|
3662
|
+
publish: "\uCD9C\uC2DC"
|
|
3675
3663
|
};
|
|
3676
|
-
program.name("vhk").description("VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58 (\uD55C\uAD6D\uC5B4\uB85C \uC548\uB0B4\uD569\uB2C8\uB2E4)").version("0.
|
|
3664
|
+
program.name("vhk").description("VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58 (\uD55C\uAD6D\uC5B4\uB85C \uC548\uB0B4\uD569\uB2C8\uB2E4)").version("0.7.1");
|
|
3677
3665
|
program.configureHelp({
|
|
3678
3666
|
formatHelp(cmd, helper) {
|
|
3679
3667
|
if (cmd.parent) {
|
|
@@ -3704,7 +3692,7 @@ program.command("sync").alias("\uB9DE\uCD94\uAE30").alias("\uADDC\uCE59").descri
|
|
|
3704
3692
|
program.command("check").alias("\uC810\uAC80").alias("\uB9B0\uD2B8").description("RULES.md \uADDC\uCE59 \uC810\uAC80 \u2014 \uCF54\uB4DC \uC704\uBC18 \uAC80\uC0AC").action(check);
|
|
3705
3693
|
var secureCmd = program.command("secure").alias("\uBCF4\uC548").description("\uBCF4\uC548 \uB3C4\uAD6C \uBAA8\uC74C \u2014 scan: \uC2DC\uD06C\uB9BF\xB7\uD0A4 \uC720\uCD9C \uAC80\uC0AC").action(secure);
|
|
3706
3694
|
secureCmd.command("scan").alias("\uC2A4\uCE94").description("\uC2DC\uD06C\uB9BF/\uD0A4 \uC720\uCD9C \uC2A4\uCE94").action(secure);
|
|
3707
|
-
program.command("ship").alias("\
|
|
3695
|
+
program.command("ship").alias("\uCD9C\uD558").description("\uBC30\uD3EC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 + \uD68C\uACE0 + \uBE4C\uB4DC \uB85C\uADF8 \uC0DD\uC131").action(ship);
|
|
3708
3696
|
program.command("doctor").alias("\uD658\uACBD").alias("\uC9C4\uB2E8").description("\uAC1C\uBC1C \uD658\uACBD \uC810\uAC80 \u2014 Node/Git/npm \uC0C1\uD0DC \uD655\uC778").action(doctor);
|
|
3709
3697
|
program.command("save").alias("\uC800\uC7A5").description("\uBCC0\uACBD\uC0AC\uD56D \uC800\uC7A5 (git add \u2192 commit \u2192 push)").action(async () => {
|
|
3710
3698
|
await save();
|
|
@@ -3722,6 +3710,18 @@ program.command("mcp").description("MCP \uC11C\uBC84 \uC2DC\uC791 (Cursor \uB4F1
|
|
|
3722
3710
|
program.command("mcp-init").alias("mcp\uC124\uC815").description("Cursor MCP \uC5F0\uB3D9 \uC124\uC815 \uC790\uB3D9 \uC0DD\uC131 (.cursor/mcp.json)").action(async () => {
|
|
3723
3711
|
await mcpInit();
|
|
3724
3712
|
});
|
|
3713
|
+
program.command("deploy").alias("\uBC30\uD3EC").description("\uD504\uB85C\uB355\uC158 \uBC30\uD3EC (Vercel/Netlify/Cloudflare \uC790\uB3D9 \uAC10\uC9C0)").action(async () => {
|
|
3714
|
+
await deploy();
|
|
3715
|
+
});
|
|
3716
|
+
program.command("env").alias("\uD658\uACBD\uBCC0\uC218").description(".env \u2192 .env.example \uB3D9\uAE30\uD654 + .gitignore \uC790\uB3D9 \uCD94\uAC00").action(async () => {
|
|
3717
|
+
await env();
|
|
3718
|
+
});
|
|
3719
|
+
program.command("env-check").alias("\uD658\uACBD\uBCC0\uC218\uC810\uAC80").description("\uD544\uC218 \uD658\uACBD\uBCC0\uC218 \uB204\uB77D \uAC80\uC0AC").action(async () => {
|
|
3720
|
+
await envCheck();
|
|
3721
|
+
});
|
|
3722
|
+
program.command("publish").alias("\uCD9C\uC2DC").description("npm \uBC30\uD3EC (\uBC84\uC804 \uBC94\uD504 \u2192 \uBE4C\uB4DC \u2192 \uD14C\uC2A4\uD2B8 \u2192 publish)").action(async () => {
|
|
3723
|
+
await publish();
|
|
3724
|
+
});
|
|
3725
3725
|
program.on("command:*", async (operands) => {
|
|
3726
3726
|
const unknown = operands[0] ?? "";
|
|
3727
3727
|
const rest = operands.slice(1);
|
|
@@ -3730,7 +3730,7 @@ program.on("command:*", async (operands) => {
|
|
|
3730
3730
|
});
|
|
3731
3731
|
program.action(async () => {
|
|
3732
3732
|
console.log("\n\u{1F3AF} VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58\n");
|
|
3733
|
-
const { choice } = await
|
|
3733
|
+
const { choice } = await inquirer10.prompt([{
|
|
3734
3734
|
type: "list",
|
|
3735
3735
|
name: "choice",
|
|
3736
3736
|
message: "\uBB58 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?",
|