@lambertkeith/spec-go 0.3.0 → 0.3.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/dist/cli/index.js +418 -34
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -7,13 +7,13 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
// src/cli/cli.ts
|
|
10
|
-
import
|
|
11
|
-
import
|
|
10
|
+
import path8 from "path";
|
|
11
|
+
import fs6 from "fs";
|
|
12
12
|
import { Command } from "commander";
|
|
13
|
-
import
|
|
13
|
+
import pc7 from "picocolors";
|
|
14
14
|
|
|
15
15
|
// package.json
|
|
16
|
-
var version = "0.3.
|
|
16
|
+
var version = "0.3.1";
|
|
17
17
|
|
|
18
18
|
// src/cli/prompts.ts
|
|
19
19
|
import path5 from "path";
|
|
@@ -146,11 +146,11 @@ function toValidPackageName(name) {
|
|
|
146
146
|
return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
|
|
147
147
|
}
|
|
148
148
|
function isEmpty(dirPath) {
|
|
149
|
-
const
|
|
150
|
-
if (!
|
|
149
|
+
const fs7 = __require("fs");
|
|
150
|
+
if (!fs7.existsSync(dirPath)) {
|
|
151
151
|
return true;
|
|
152
152
|
}
|
|
153
|
-
const files =
|
|
153
|
+
const files = fs7.readdirSync(dirPath);
|
|
154
154
|
return files.length === 0 || files.length === 1 && files[0] === ".git";
|
|
155
155
|
}
|
|
156
156
|
function execAsync(command, args, options = {}) {
|
|
@@ -831,23 +831,404 @@ async function runUpdate(currentVersion, checkOnly) {
|
|
|
831
831
|
}
|
|
832
832
|
}
|
|
833
833
|
|
|
834
|
-
// src/cli/
|
|
834
|
+
// src/cli/guide.ts
|
|
835
|
+
import path7 from "path";
|
|
836
|
+
import fs5 from "fs";
|
|
837
|
+
import { select as select2 } from "@inquirer/prompts";
|
|
838
|
+
import pc5 from "picocolors";
|
|
839
|
+
|
|
840
|
+
// src/cli/guide-content.ts
|
|
835
841
|
import pc4 from "picocolors";
|
|
842
|
+
var guideTopics = [
|
|
843
|
+
// 入门指南类
|
|
844
|
+
{
|
|
845
|
+
id: "quickstart",
|
|
846
|
+
title: "\u5FEB\u901F\u5F00\u59CB",
|
|
847
|
+
description: "5\u5206\u949F\u5FEB\u901F\u4E0A\u624B spec-go",
|
|
848
|
+
category: "\u5165\u95E8\u6307\u5357",
|
|
849
|
+
content: () => `
|
|
850
|
+
${pc4.cyan("\u5FEB\u901F\u5F00\u59CB")}
|
|
851
|
+
|
|
852
|
+
${pc4.bold("1. \u521B\u5EFA\u9879\u76EE")}
|
|
853
|
+
${pc4.green("spec-go my-app")}
|
|
854
|
+
|
|
855
|
+
\u6309\u7167\u4EA4\u4E92\u5F0F\u63D0\u793A\u9009\u62E9\u6A21\u677F\u548C\u914D\u7F6E\u9009\u9879\u3002
|
|
856
|
+
|
|
857
|
+
${pc4.bold("2. \u8FDB\u5165\u9879\u76EE\u76EE\u5F55")}
|
|
858
|
+
${pc4.green("cd my-app")}
|
|
859
|
+
|
|
860
|
+
${pc4.bold("3. \u542F\u52A8\u5F00\u53D1\u670D\u52A1\u5668")}
|
|
861
|
+
${pc4.green("pnpm dev")}
|
|
862
|
+
|
|
863
|
+
\u6839\u636E\u4E0D\u540C\u6A21\u677F\uFF0C\u542F\u52A8\u547D\u4EE4\u53EF\u80FD\u6709\u6240\u4E0D\u540C\u3002
|
|
864
|
+
|
|
865
|
+
${pc4.dim("\u63D0\u793A\uFF1A\u4F7F\u7528")} ${pc4.green("spec-go guide templates")} ${pc4.dim("\u67E5\u770B\u6240\u6709\u53EF\u7528\u6A21\u677F")}
|
|
866
|
+
${pc4.dim("\u63D0\u793A\uFF1A\u4F7F\u7528")} ${pc4.green("spec-go guide examples")} ${pc4.dim("\u67E5\u770B\u66F4\u591A\u4F7F\u7528\u793A\u4F8B")}
|
|
867
|
+
`
|
|
868
|
+
},
|
|
869
|
+
{
|
|
870
|
+
id: "templates",
|
|
871
|
+
title: "\u6A21\u677F\u5217\u8868",
|
|
872
|
+
description: "\u67E5\u770B\u6240\u6709\u53EF\u7528\u7684\u9879\u76EE\u6A21\u677F",
|
|
873
|
+
category: "\u5165\u95E8\u6307\u5357",
|
|
874
|
+
content: (data) => {
|
|
875
|
+
const templates = data?.templates || [];
|
|
876
|
+
const singleTemplates = templates.filter((t) => t.category !== "fullstack");
|
|
877
|
+
const fullstackTemplates = templates.filter((t) => t.category === "fullstack");
|
|
878
|
+
let output = `
|
|
879
|
+
${pc4.cyan("\u53EF\u7528\u6A21\u677F")}
|
|
880
|
+
|
|
881
|
+
`;
|
|
882
|
+
if (singleTemplates.length > 0) {
|
|
883
|
+
output += `${pc4.bold("\u5355\u4F53\u9879\u76EE\uFF1A")}
|
|
884
|
+
`;
|
|
885
|
+
for (const t of singleTemplates) {
|
|
886
|
+
output += ` ${pc4.green(t.name.padEnd(24))} ${pc4.dim(t.displayName)}
|
|
887
|
+
`;
|
|
888
|
+
output += ` ${" ".repeat(24)} ${pc4.dim(t.description)}
|
|
889
|
+
`;
|
|
890
|
+
}
|
|
891
|
+
output += "\n";
|
|
892
|
+
}
|
|
893
|
+
if (fullstackTemplates.length > 0) {
|
|
894
|
+
output += `${pc4.bold("\u524D\u540E\u7AEF\u5206\u79BB\uFF1A")}
|
|
895
|
+
`;
|
|
896
|
+
for (const t of fullstackTemplates) {
|
|
897
|
+
output += ` ${pc4.green(t.name.padEnd(24))} ${pc4.dim(t.displayName)}
|
|
898
|
+
`;
|
|
899
|
+
output += ` ${" ".repeat(24)} ${pc4.dim(t.description)}
|
|
900
|
+
`;
|
|
901
|
+
}
|
|
902
|
+
output += "\n";
|
|
903
|
+
}
|
|
904
|
+
output += `${pc4.dim("\u4F7F\u7528\u65B9\u5F0F\uFF1A")}
|
|
905
|
+
`;
|
|
906
|
+
output += ` ${pc4.green("spec-go my-app --template <\u6A21\u677F\u540D>")}
|
|
907
|
+
`;
|
|
908
|
+
output += ` ${pc4.green("spec-go list")} ${pc4.dim("# \u67E5\u770B\u7B80\u6D01\u5217\u8868")}
|
|
909
|
+
`;
|
|
910
|
+
return output;
|
|
911
|
+
}
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
id: "examples",
|
|
915
|
+
title: "\u4F7F\u7528\u793A\u4F8B",
|
|
916
|
+
description: "\u5E38\u89C1\u4F7F\u7528\u573A\u666F\u548C\u6700\u4F73\u5B9E\u8DF5",
|
|
917
|
+
category: "\u5165\u95E8\u6307\u5357",
|
|
918
|
+
content: () => `
|
|
919
|
+
${pc4.cyan("\u4F7F\u7528\u793A\u4F8B")}
|
|
920
|
+
|
|
921
|
+
${pc4.bold("1. \u521B\u5EFA React \u9879\u76EE")}
|
|
922
|
+
${pc4.green("spec-go my-react-app --template react-ts")}
|
|
923
|
+
|
|
924
|
+
${pc4.bold("2. \u521B\u5EFA\u5168\u6808\u9879\u76EE\uFF08\u524D\u540E\u7AEF\u5206\u79BB\uFF09")}
|
|
925
|
+
${pc4.green("spec-go my-fullstack --template fullstack-react-node")}
|
|
926
|
+
|
|
927
|
+
${pc4.bold("3. \u521B\u5EFA API \u9879\u76EE")}
|
|
928
|
+
${pc4.green("spec-go my-api --template express-ts")}
|
|
929
|
+
|
|
930
|
+
${pc4.bold("4. \u975E\u4EA4\u4E92\u6A21\u5F0F\uFF08CI/CD\uFF09")}
|
|
931
|
+
${pc4.green("spec-go my-app --template node-ts --yes --no-install")}
|
|
932
|
+
|
|
933
|
+
${pc4.bold("5. \u521B\u5EFA\u5E76\u63A8\u9001\u5230 GitHub")}
|
|
934
|
+
${pc4.green("spec-go my-app --template react-ts --github --public")}
|
|
935
|
+
|
|
936
|
+
${pc4.bold("6. \u8DF3\u8FC7 Git \u521D\u59CB\u5316")}
|
|
937
|
+
${pc4.green("spec-go my-app --template vue-ts --no-git")}
|
|
938
|
+
|
|
939
|
+
${pc4.dim("\u63D0\u793A\uFF1A\u4F7F\u7528")} ${pc4.green("spec-go --help")} ${pc4.dim("\u67E5\u770B\u6240\u6709\u53EF\u7528\u9009\u9879")}
|
|
940
|
+
`
|
|
941
|
+
},
|
|
942
|
+
// 功能特性类
|
|
943
|
+
{
|
|
944
|
+
id: "github",
|
|
945
|
+
title: "GitHub \u96C6\u6210",
|
|
946
|
+
description: "GitHub \u4ED3\u5E93\u521B\u5EFA\u548C\u914D\u7F6E",
|
|
947
|
+
category: "\u529F\u80FD\u7279\u6027",
|
|
948
|
+
content: (data) => `
|
|
949
|
+
${pc4.cyan("GitHub \u96C6\u6210")}
|
|
950
|
+
|
|
951
|
+
${pc4.bold("\u914D\u7F6E GitHub Token")}
|
|
952
|
+
|
|
953
|
+
${pc4.dim("1. \u751F\u6210 Personal Access Token")}
|
|
954
|
+
\u8BBF\u95EE\uFF1Ahttps://github.com/settings/tokens
|
|
955
|
+
\u6743\u9650\uFF1Arepo (\u5B8C\u6574\u4ED3\u5E93\u8BBF\u95EE\u6743\u9650)
|
|
956
|
+
|
|
957
|
+
${pc4.dim("2. \u914D\u7F6E Token")}
|
|
958
|
+
${pc4.green("spec-go config --setup-github")}
|
|
959
|
+
|
|
960
|
+
${pc4.dim("3. \u9A8C\u8BC1\u914D\u7F6E")}
|
|
961
|
+
${pc4.green("spec-go config --show")}
|
|
962
|
+
|
|
963
|
+
${pc4.bold("\u4F7F\u7528 GitHub \u96C6\u6210")}
|
|
964
|
+
|
|
965
|
+
${pc4.dim("\u521B\u5EFA\u9879\u76EE\u5E76\u63A8\u9001\u5230 GitHub\uFF1A")}
|
|
966
|
+
${pc4.green("spec-go my-app --github")} ${pc4.dim("# \u521B\u5EFA\u79C1\u6709\u4ED3\u5E93")}
|
|
967
|
+
${pc4.green("spec-go my-app --github --public")} ${pc4.dim("# \u521B\u5EFA\u516C\u5F00\u4ED3\u5E93")}
|
|
968
|
+
|
|
969
|
+
${pc4.bold("\u914D\u7F6E\u6587\u4EF6\u4F4D\u7F6E")}
|
|
970
|
+
${data?.configPath || "~/.spec-go.json"}
|
|
971
|
+
|
|
972
|
+
${pc4.dim("\u63D0\u793A\uFF1AToken \u4F1A\u5B89\u5168\u5B58\u50A8\u5728\u672C\u5730\u914D\u7F6E\u6587\u4EF6\u4E2D")}
|
|
973
|
+
`
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
id: "mcp",
|
|
977
|
+
title: "MCP Server",
|
|
978
|
+
description: "MCP Server \u914D\u7F6E\u548C\u4F7F\u7528",
|
|
979
|
+
category: "\u529F\u80FD\u7279\u6027",
|
|
980
|
+
content: () => `
|
|
981
|
+
${pc4.cyan("MCP Server \u914D\u7F6E")}
|
|
982
|
+
|
|
983
|
+
${pc4.bold("\u4EC0\u4E48\u662F MCP Server\uFF1F")}
|
|
984
|
+
|
|
985
|
+
MCP (Model Context Protocol) Server \u5141\u8BB8 Claude Code \u76F4\u63A5\u8C03\u7528 spec-go \u7684\u529F\u80FD\u3002
|
|
986
|
+
|
|
987
|
+
${pc4.bold("\u6784\u5EFA MCP Server")}
|
|
988
|
+
|
|
989
|
+
${pc4.dim("1. \u6784\u5EFA\u9879\u76EE")}
|
|
990
|
+
${pc4.green("pnpm build")}
|
|
991
|
+
|
|
992
|
+
${pc4.dim("2. \u914D\u7F6E Claude Code")}
|
|
993
|
+
\u7F16\u8F91 ${pc4.dim("~/.claude/settings.json")}\uFF1A
|
|
994
|
+
|
|
995
|
+
{
|
|
996
|
+
"mcpServers": {
|
|
997
|
+
"spec-go": {
|
|
998
|
+
"command": "node",
|
|
999
|
+
"args": ["/path/to/create-idp/dist/mcp/index.js"]
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
${pc4.dim("3. \u91CD\u542F Claude Code")}
|
|
1005
|
+
|
|
1006
|
+
${pc4.bold("\u53EF\u7528\u5DE5\u5177")}
|
|
1007
|
+
|
|
1008
|
+
\u2022 create_project - \u521B\u5EFA\u65B0\u9879\u76EE
|
|
1009
|
+
\u2022 list_templates - \u5217\u51FA\u6240\u6709\u6A21\u677F
|
|
1010
|
+
\u2022 validate_project_name - \u9A8C\u8BC1\u9879\u76EE\u540D\u79F0
|
|
1011
|
+
\u2022 init_git_repo - \u521D\u59CB\u5316 Git \u4ED3\u5E93
|
|
1012
|
+
\u2022 create_github_repo - \u521B\u5EFA GitHub \u4ED3\u5E93
|
|
1013
|
+
|
|
1014
|
+
${pc4.bold("\u4F7F\u7528\u793A\u4F8B")}
|
|
1015
|
+
|
|
1016
|
+
\u5728 Claude Code \u4E2D\u76F4\u63A5\u8BF4\uFF1A
|
|
1017
|
+
${pc4.dim('"\u4F7F\u7528 spec-go \u521B\u5EFA\u4E00\u4E2A React \u9879\u76EE"')}
|
|
1018
|
+
|
|
1019
|
+
${pc4.dim("\u63D0\u793A\uFF1A\u67E5\u770B\u9879\u76EE README \u4E86\u89E3\u66F4\u591A MCP \u914D\u7F6E\u7EC6\u8282")}
|
|
1020
|
+
`
|
|
1021
|
+
},
|
|
1022
|
+
// 参考文档类
|
|
1023
|
+
{
|
|
1024
|
+
id: "commands",
|
|
1025
|
+
title: "\u547D\u4EE4\u53C2\u8003",
|
|
1026
|
+
description: "\u6240\u6709\u547D\u4EE4\u7684\u5B8C\u6574\u8BF4\u660E",
|
|
1027
|
+
category: "\u53C2\u8003\u6587\u6863",
|
|
1028
|
+
content: () => `
|
|
1029
|
+
${pc4.cyan("\u547D\u4EE4\u53C2\u8003")}
|
|
1030
|
+
|
|
1031
|
+
${pc4.bold("\u4E3B\u547D\u4EE4")}
|
|
1032
|
+
|
|
1033
|
+
${pc4.green("spec-go [project-name] [options]")}
|
|
1034
|
+
\u521B\u5EFA\u65B0\u9879\u76EE
|
|
1035
|
+
|
|
1036
|
+
${pc4.dim("\u9009\u9879\uFF1A")}
|
|
1037
|
+
-t, --template <name> \u6307\u5B9A\u6A21\u677F
|
|
1038
|
+
--github \u521B\u5EFA GitHub \u4ED3\u5E93
|
|
1039
|
+
--public \u521B\u5EFA\u516C\u5F00\u4ED3\u5E93\uFF08\u9ED8\u8BA4\u79C1\u6709\uFF09
|
|
1040
|
+
--no-git \u8DF3\u8FC7 Git \u521D\u59CB\u5316
|
|
1041
|
+
--no-install \u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5
|
|
1042
|
+
-y, --yes \u975E\u4EA4\u4E92\u6A21\u5F0F\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u503C
|
|
1043
|
+
--debug \u542F\u7528\u8C03\u8BD5\u8F93\u51FA
|
|
1044
|
+
|
|
1045
|
+
${pc4.bold("\u5B50\u547D\u4EE4")}
|
|
1046
|
+
|
|
1047
|
+
${pc4.green("spec-go list [--json]")}
|
|
1048
|
+
\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u677F
|
|
1049
|
+
|
|
1050
|
+
${pc4.green("spec-go config")}
|
|
1051
|
+
\u7BA1\u7406\u914D\u7F6E
|
|
1052
|
+
--setup-github \u914D\u7F6E GitHub Token
|
|
1053
|
+
--show \u663E\u793A\u5F53\u524D\u914D\u7F6E
|
|
1054
|
+
--path \u663E\u793A\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84
|
|
1055
|
+
|
|
1056
|
+
${pc4.green("spec-go update [--check]")}
|
|
1057
|
+
\u68C0\u67E5\u5E76\u66F4\u65B0\u5230\u6700\u65B0\u7248\u672C
|
|
1058
|
+
--check \u4EC5\u68C0\u67E5\u7248\u672C\uFF0C\u4E0D\u6267\u884C\u66F4\u65B0
|
|
1059
|
+
|
|
1060
|
+
${pc4.green("spec-go guide [topic] [--list] [--json]")}
|
|
1061
|
+
\u663E\u793A\u4F7F\u7528\u6307\u5357
|
|
1062
|
+
--list \u5217\u51FA\u6240\u6709\u53EF\u7528\u4E3B\u9898
|
|
1063
|
+
--json JSON \u683C\u5F0F\u8F93\u51FA
|
|
1064
|
+
|
|
1065
|
+
${pc4.dim("\u63D0\u793A\uFF1A\u4F7F\u7528")} ${pc4.green("spec-go <command> --help")} ${pc4.dim("\u67E5\u770B\u547D\u4EE4\u8BE6\u7EC6\u5E2E\u52A9")}
|
|
1066
|
+
`
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
id: "config",
|
|
1070
|
+
title: "\u914D\u7F6E\u8BE6\u89E3",
|
|
1071
|
+
description: "\u914D\u7F6E\u6587\u4EF6\u7ED3\u6784\u548C\u8BF4\u660E",
|
|
1072
|
+
category: "\u53C2\u8003\u6587\u6863",
|
|
1073
|
+
content: (data) => `
|
|
1074
|
+
${pc4.cyan("\u914D\u7F6E\u8BE6\u89E3")}
|
|
1075
|
+
|
|
1076
|
+
${pc4.bold("\u914D\u7F6E\u6587\u4EF6\u4F4D\u7F6E")}
|
|
1077
|
+
|
|
1078
|
+
${data?.configPath || "~/.spec-go.json"}
|
|
1079
|
+
|
|
1080
|
+
${pc4.bold("\u914D\u7F6E\u7ED3\u6784")}
|
|
1081
|
+
|
|
1082
|
+
{
|
|
1083
|
+
"github": {
|
|
1084
|
+
"token": "ghp_xxxxxxxxxxxx" ${pc4.dim("// GitHub Personal Access Token")}
|
|
1085
|
+
},
|
|
1086
|
+
"defaults": {
|
|
1087
|
+
"template": "node-ts", ${pc4.dim("// \u9ED8\u8BA4\u6A21\u677F")}
|
|
1088
|
+
"github": false, ${pc4.dim("// \u9ED8\u8BA4\u662F\u5426\u521B\u5EFA GitHub \u4ED3\u5E93")}
|
|
1089
|
+
"public": false ${pc4.dim("// \u9ED8\u8BA4\u4ED3\u5E93\u53EF\u89C1\u6027")}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
${pc4.bold("\u914D\u7F6E\u7BA1\u7406\u547D\u4EE4")}
|
|
1094
|
+
|
|
1095
|
+
${pc4.green("spec-go config --setup-github")} ${pc4.dim("# \u914D\u7F6E GitHub Token")}
|
|
1096
|
+
${pc4.green("spec-go config --show")} ${pc4.dim("# \u663E\u793A\u5F53\u524D\u914D\u7F6E")}
|
|
1097
|
+
${pc4.green("spec-go config --path")} ${pc4.dim("# \u663E\u793A\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84")}
|
|
1098
|
+
|
|
1099
|
+
${pc4.bold("\u5B89\u5168\u6027\u8BF4\u660E")}
|
|
1100
|
+
|
|
1101
|
+
\u2022 Token \u5B58\u50A8\u5728\u672C\u5730\u914D\u7F6E\u6587\u4EF6\u4E2D
|
|
1102
|
+
\u2022 \u914D\u7F6E\u6587\u4EF6\u6743\u9650\u5E94\u8BBE\u7F6E\u4E3A\u4EC5\u5F53\u524D\u7528\u6237\u53EF\u8BFB
|
|
1103
|
+
\u2022 \u4E0D\u8981\u5C06\u914D\u7F6E\u6587\u4EF6\u63D0\u4EA4\u5230\u7248\u672C\u63A7\u5236\u7CFB\u7EDF
|
|
1104
|
+
|
|
1105
|
+
${pc4.dim("\u63D0\u793A\uFF1A\u4F7F\u7528")} ${pc4.green("spec-go guide github")} ${pc4.dim("\u4E86\u89E3\u5982\u4F55\u914D\u7F6E GitHub \u96C6\u6210")}
|
|
1106
|
+
`
|
|
1107
|
+
}
|
|
1108
|
+
];
|
|
1109
|
+
|
|
1110
|
+
// src/cli/guide.ts
|
|
1111
|
+
function prepareDynamicData() {
|
|
1112
|
+
const data = {};
|
|
1113
|
+
try {
|
|
1114
|
+
const templatesDir = getTemplatesDir();
|
|
1115
|
+
const registryPath = path7.join(templatesDir, "template.config.json");
|
|
1116
|
+
const registry = JSON.parse(
|
|
1117
|
+
fs5.readFileSync(registryPath, "utf-8")
|
|
1118
|
+
);
|
|
1119
|
+
data.templates = registry.templates;
|
|
1120
|
+
} catch (err) {
|
|
1121
|
+
data.templates = [];
|
|
1122
|
+
}
|
|
1123
|
+
try {
|
|
1124
|
+
data.configPath = getConfigPath();
|
|
1125
|
+
} catch (err) {
|
|
1126
|
+
data.configPath = "~/.spec-go.json";
|
|
1127
|
+
}
|
|
1128
|
+
return data;
|
|
1129
|
+
}
|
|
1130
|
+
async function showGuideMenu(data) {
|
|
1131
|
+
const categories = Array.from(new Set(guideTopics.map((t) => t.category)));
|
|
1132
|
+
const choices = categories.flatMap((category) => {
|
|
1133
|
+
const topicsInCategory = guideTopics.filter((t) => t.category === category);
|
|
1134
|
+
return [
|
|
1135
|
+
{ name: pc5.cyan(`\u2500\u2500 ${category} \u2500\u2500`), value: "", disabled: true },
|
|
1136
|
+
...topicsInCategory.map((t) => ({
|
|
1137
|
+
name: `${t.title} ${pc5.dim(`- ${t.description}`)}`,
|
|
1138
|
+
value: t.id
|
|
1139
|
+
}))
|
|
1140
|
+
];
|
|
1141
|
+
});
|
|
1142
|
+
const topicId = await select2({
|
|
1143
|
+
message: "\u9009\u62E9\u4E3B\u9898:",
|
|
1144
|
+
choices
|
|
1145
|
+
});
|
|
1146
|
+
if (topicId) {
|
|
1147
|
+
showTopic(topicId, data);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
function showTopic(topicId, data) {
|
|
1151
|
+
const topic = guideTopics.find((t) => t.id === topicId);
|
|
1152
|
+
if (!topic) {
|
|
1153
|
+
console.log(pc5.red(`\u9519\u8BEF: \u672A\u627E\u5230\u4E3B\u9898 "${topicId}"`));
|
|
1154
|
+
console.log(pc5.dim(`\u4F7F\u7528 ${pc5.green("spec-go guide --list")} \u67E5\u770B\u6240\u6709\u53EF\u7528\u4E3B\u9898`));
|
|
1155
|
+
process.exit(1);
|
|
1156
|
+
}
|
|
1157
|
+
console.log();
|
|
1158
|
+
console.log(topic.content(data));
|
|
1159
|
+
console.log();
|
|
1160
|
+
}
|
|
1161
|
+
function listTopics() {
|
|
1162
|
+
const categories = Array.from(new Set(guideTopics.map((t) => t.category)));
|
|
1163
|
+
console.log();
|
|
1164
|
+
console.log(pc5.cyan("\u53EF\u7528\u4E3B\u9898"));
|
|
1165
|
+
console.log();
|
|
1166
|
+
for (const category of categories) {
|
|
1167
|
+
console.log(pc5.bold(`${category}:`));
|
|
1168
|
+
const topicsInCategory = guideTopics.filter((t) => t.category === category);
|
|
1169
|
+
for (const topic of topicsInCategory) {
|
|
1170
|
+
console.log(` ${pc5.green(topic.id.padEnd(16))} ${pc5.dim(topic.description)}`);
|
|
1171
|
+
}
|
|
1172
|
+
console.log();
|
|
1173
|
+
}
|
|
1174
|
+
console.log(pc5.dim("\u4F7F\u7528\u65B9\u5F0F:"));
|
|
1175
|
+
console.log(` ${pc5.green("spec-go guide <\u4E3B\u9898ID>")}`);
|
|
1176
|
+
console.log();
|
|
1177
|
+
}
|
|
1178
|
+
function outputJson() {
|
|
1179
|
+
const output = {
|
|
1180
|
+
topics: guideTopics.map((t) => ({
|
|
1181
|
+
id: t.id,
|
|
1182
|
+
title: t.title,
|
|
1183
|
+
description: t.description,
|
|
1184
|
+
category: t.category
|
|
1185
|
+
}))
|
|
1186
|
+
};
|
|
1187
|
+
console.log(JSON.stringify(output, null, 2));
|
|
1188
|
+
}
|
|
1189
|
+
async function runGuide(topic, options) {
|
|
1190
|
+
const data = prepareDynamicData();
|
|
1191
|
+
if (options.json) {
|
|
1192
|
+
outputJson();
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
if (options.list) {
|
|
1196
|
+
listTopics();
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
if (topic) {
|
|
1200
|
+
showTopic(topic, data);
|
|
1201
|
+
return;
|
|
1202
|
+
}
|
|
1203
|
+
try {
|
|
1204
|
+
await showGuideMenu(data);
|
|
1205
|
+
} catch (err) {
|
|
1206
|
+
const error = err;
|
|
1207
|
+
if (error.message === "PROMPT_CANCELLED" || error.name === "ExitPromptError" || error.message.includes("User force closed")) {
|
|
1208
|
+
console.log(pc5.yellow("\n\u64CD\u4F5C\u5DF2\u53D6\u6D88"));
|
|
1209
|
+
process.exit(0);
|
|
1210
|
+
}
|
|
1211
|
+
throw err;
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
// src/cli/console-logger.ts
|
|
1216
|
+
import pc6 from "picocolors";
|
|
836
1217
|
var consoleLogger = {
|
|
837
1218
|
info(message) {
|
|
838
1219
|
console.log(message);
|
|
839
1220
|
},
|
|
840
1221
|
success(message) {
|
|
841
|
-
console.log(
|
|
1222
|
+
console.log(pc6.green(message));
|
|
842
1223
|
},
|
|
843
1224
|
warn(message) {
|
|
844
|
-
console.log(
|
|
1225
|
+
console.log(pc6.yellow(message));
|
|
845
1226
|
},
|
|
846
1227
|
error(message) {
|
|
847
|
-
console.log(
|
|
1228
|
+
console.log(pc6.red(message));
|
|
848
1229
|
},
|
|
849
1230
|
dim(message) {
|
|
850
|
-
console.log(
|
|
1231
|
+
console.log(pc6.dim(message));
|
|
851
1232
|
}
|
|
852
1233
|
};
|
|
853
1234
|
|
|
@@ -863,7 +1244,7 @@ async function createCli() {
|
|
|
863
1244
|
setDebugEnabled(true);
|
|
864
1245
|
}
|
|
865
1246
|
console.log();
|
|
866
|
-
console.log(` ${
|
|
1247
|
+
console.log(` ${pc7.cyan("spec-go")} ${pc7.dim(`v${version}`)}`);
|
|
867
1248
|
console.log();
|
|
868
1249
|
checkForUpdates(version).catch(() => {
|
|
869
1250
|
});
|
|
@@ -875,7 +1256,7 @@ async function createCli() {
|
|
|
875
1256
|
} catch (err) {
|
|
876
1257
|
const error = err;
|
|
877
1258
|
if (error.message === "PROMPT_CANCELLED" || error.name === "ExitPromptError" || error.message.includes("User force closed")) {
|
|
878
|
-
console.log(
|
|
1259
|
+
console.log(pc7.yellow("\n\u64CD\u4F5C\u5DF2\u53D6\u6D88"));
|
|
879
1260
|
process.exit(ExitCodes.SUCCESS);
|
|
880
1261
|
}
|
|
881
1262
|
throw err;
|
|
@@ -883,9 +1264,9 @@ async function createCli() {
|
|
|
883
1264
|
});
|
|
884
1265
|
program.command("list").description("\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u677F").option("--json", "\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA").action((options) => {
|
|
885
1266
|
const templatesDir = getTemplatesDir();
|
|
886
|
-
const registryPath =
|
|
1267
|
+
const registryPath = path8.join(templatesDir, "template.config.json");
|
|
887
1268
|
const registry = JSON.parse(
|
|
888
|
-
|
|
1269
|
+
fs6.readFileSync(registryPath, "utf-8")
|
|
889
1270
|
);
|
|
890
1271
|
if (options.json) {
|
|
891
1272
|
const output = {
|
|
@@ -902,15 +1283,15 @@ async function createCli() {
|
|
|
902
1283
|
const singleTemplates = registry.templates.filter((t) => t.category !== "fullstack");
|
|
903
1284
|
const fullstackTemplates = registry.templates.filter((t) => t.category === "fullstack");
|
|
904
1285
|
console.log();
|
|
905
|
-
console.log(
|
|
1286
|
+
console.log(pc7.cyan(" \u5355\u4F53\u9879\u76EE:"));
|
|
906
1287
|
for (const t of singleTemplates) {
|
|
907
|
-
console.log(` ${
|
|
1288
|
+
console.log(` ${pc7.green(t.name.padEnd(24))} ${pc7.dim(t.displayName)}`);
|
|
908
1289
|
}
|
|
909
1290
|
if (fullstackTemplates.length > 0) {
|
|
910
1291
|
console.log();
|
|
911
|
-
console.log(
|
|
1292
|
+
console.log(pc7.cyan(" \u524D\u540E\u7AEF\u5206\u79BB:"));
|
|
912
1293
|
for (const t of fullstackTemplates) {
|
|
913
|
-
console.log(` ${
|
|
1294
|
+
console.log(` ${pc7.green(t.name.padEnd(24))} ${pc7.dim(t.displayName)}`);
|
|
914
1295
|
}
|
|
915
1296
|
}
|
|
916
1297
|
console.log();
|
|
@@ -925,34 +1306,37 @@ async function createCli() {
|
|
|
925
1306
|
console.log(getConfigPath());
|
|
926
1307
|
} else {
|
|
927
1308
|
console.log();
|
|
928
|
-
console.log(
|
|
1309
|
+
console.log(pc7.cyan("\u914D\u7F6E\u7BA1\u7406\u547D\u4EE4:"));
|
|
929
1310
|
console.log();
|
|
930
|
-
console.log(` ${
|
|
931
|
-
console.log(` ${
|
|
932
|
-
console.log(` ${
|
|
1311
|
+
console.log(` ${pc7.dim("spec-go config --setup-github")} \u914D\u7F6E GitHub Token`);
|
|
1312
|
+
console.log(` ${pc7.dim("spec-go config --show")} \u663E\u793A\u5F53\u524D\u914D\u7F6E`);
|
|
1313
|
+
console.log(` ${pc7.dim("spec-go config --path")} \u663E\u793A\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84`);
|
|
933
1314
|
console.log();
|
|
934
1315
|
}
|
|
935
1316
|
});
|
|
936
1317
|
program.command("update").description("\u68C0\u67E5\u5E76\u66F4\u65B0\u5230\u6700\u65B0\u7248\u672C").option("--check", "\u4EC5\u68C0\u67E5\u7248\u672C\uFF0C\u4E0D\u6267\u884C\u66F4\u65B0").action(async (options) => {
|
|
937
1318
|
await runUpdate(version, options.check ?? false);
|
|
938
1319
|
});
|
|
1320
|
+
program.command("guide [topic]").description("\u663E\u793A\u4F7F\u7528\u6307\u5357\u548C\u5E2E\u52A9\u6587\u6863").option("--list", "\u5217\u51FA\u6240\u6709\u53EF\u7528\u4E3B\u9898").option("--json", "\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA").action(async (topic, options) => {
|
|
1321
|
+
await runGuide(topic, options);
|
|
1322
|
+
});
|
|
939
1323
|
return program;
|
|
940
1324
|
}
|
|
941
1325
|
async function executeProject(options) {
|
|
942
1326
|
const templateConfig = await scaffoldProject(options);
|
|
943
|
-
console.log(
|
|
1327
|
+
console.log(pc7.green("\u2714 \u9879\u76EE\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
944
1328
|
if (!options.noInstall && templateConfig) {
|
|
945
1329
|
if (templateConfig.type === "workspace") {
|
|
946
1330
|
await runWorkspacePostInit(options.targetDir, templateConfig, { logger: consoleLogger });
|
|
947
|
-
console.log(
|
|
1331
|
+
console.log(pc7.green("\u2714 \u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210"));
|
|
948
1332
|
} else if (templateConfig.postInit) {
|
|
949
1333
|
await runPostInit(options.targetDir, templateConfig.postInit, { logger: consoleLogger });
|
|
950
|
-
console.log(
|
|
1334
|
+
console.log(pc7.green("\u2714 \u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210"));
|
|
951
1335
|
}
|
|
952
1336
|
}
|
|
953
1337
|
if (options.initGit) {
|
|
954
1338
|
await initGit(options.targetDir);
|
|
955
|
-
console.log(
|
|
1339
|
+
console.log(pc7.green("\u2714 Git \u4ED3\u5E93\u5DF2\u521D\u59CB\u5316"));
|
|
956
1340
|
}
|
|
957
1341
|
if (options.createGithub) {
|
|
958
1342
|
const repoUrl = await createGithubRepo({
|
|
@@ -962,7 +1346,7 @@ async function executeProject(options) {
|
|
|
962
1346
|
logger: consoleLogger
|
|
963
1347
|
});
|
|
964
1348
|
if (repoUrl) {
|
|
965
|
-
console.log(
|
|
1349
|
+
console.log(pc7.green(`\u2714 GitHub \u4ED3\u5E93\u5DF2\u521B\u5EFA: ${pc7.cyan(repoUrl)}`));
|
|
966
1350
|
}
|
|
967
1351
|
}
|
|
968
1352
|
console.log();
|
|
@@ -970,16 +1354,16 @@ async function executeProject(options) {
|
|
|
970
1354
|
const cdCmd = options.targetDir !== process.cwd() ? `cd ${options.projectName} && ` : "";
|
|
971
1355
|
if (templateConfig?.type === "workspace") {
|
|
972
1356
|
if (pm === "pnpm") {
|
|
973
|
-
console.log(
|
|
1357
|
+
console.log(pc7.dim(` ${cdCmd}pnpm dev`));
|
|
974
1358
|
} else {
|
|
975
|
-
console.log(
|
|
1359
|
+
console.log(pc7.dim(` ${cdCmd}make dev`));
|
|
976
1360
|
}
|
|
977
1361
|
} else if (pm === "maven") {
|
|
978
|
-
console.log(
|
|
1362
|
+
console.log(pc7.dim(` ${cdCmd}./mvnw spring-boot:run`));
|
|
979
1363
|
} else if (pm === "gradle") {
|
|
980
|
-
console.log(
|
|
1364
|
+
console.log(pc7.dim(` ${cdCmd}./gradlew bootRun`));
|
|
981
1365
|
} else {
|
|
982
|
-
console.log(
|
|
1366
|
+
console.log(pc7.dim(` ${cdCmd}${pm} dev`));
|
|
983
1367
|
}
|
|
984
1368
|
console.log();
|
|
985
1369
|
}
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/cli.ts","../../package.json","../../src/cli/prompts.ts","../../src/core/types.ts","../../src/core/config.ts","../../src/core/debug.ts","../../src/core/exit-codes.ts","../../src/core/utils.ts","../../src/core/scaffold.ts","../../src/core/github-api.ts","../../src/core/git.ts","../../src/core/post-init.ts","../../src/cli/github-setup.ts","../../src/cli/update-check.ts","../../src/cli/console-logger.ts","../../src/cli/index.ts"],"sourcesContent":["import path from 'node:path'\nimport fs from 'node:fs'\nimport { Command } from 'commander'\nimport pc from 'picocolors'\nimport { version } from '../../package.json'\nimport { runPrompts } from './prompts.js'\nimport { runGitHubSetup, showConfig } from './github-setup.js'\nimport { checkForUpdates, runUpdate } from './update-check.js'\nimport { consoleLogger } from './console-logger.js'\nimport {\n scaffoldProject,\n initGit,\n createGithubRepo,\n runPostInit,\n runWorkspacePostInit,\n loadConfig,\n getConfigPath,\n getTemplatesDir,\n ExitCodes,\n CliError,\n setDebugEnabled,\n} from '../core/index.js'\nimport type { CliOptions, ProjectOptions, TemplateRegistry } from '../core/index.js'\n\n/**\n * 检查是否在交互模式下运行\n */\nfunction isInteractive(options: CliOptions): boolean {\n // --yes 选项强制非交互模式\n if (options.yes) return false\n // 检查 stdin 是否是 TTY\n return process.stdin.isTTY === true\n}\n\nexport async function createCli(): Promise<Command> {\n const program = new Command()\n\n program\n .name('spec-go')\n .description('CLI 脚手架工具,快速创建项目并可选初始化 GitHub 仓库')\n .version(version)\n .argument('[project-name]', '项目名称')\n .option('-t, --template <template>', '使用指定模板')\n .option('--github', '在 GitHub 创建远程仓库')\n .option('--public', '创建公开仓库 (默认私有)')\n .option('--no-git', '跳过 Git 初始化')\n .option('--no-install', '跳过依赖安装')\n .option('-y, --yes', '跳过所有确认提示,使用默认值(非交互模式)')\n .option('--debug', '启用调试输出')\n .action(async (projectName: string | undefined, options: CliOptions) => {\n // 启用调试模式\n if (options.debug) {\n setDebugEnabled(true)\n }\n\n console.log()\n console.log(` ${pc.cyan('spec-go')} ${pc.dim(`v${version}`)}`)\n console.log()\n\n // 异步检查更新(不阻塞主流程)\n checkForUpdates(version).catch(() => {})\n\n // 加载用户配置\n const userConfig = loadConfig()\n\n // 检查是否为交互模式\n const interactive = isInteractive(options)\n\n try {\n const projectOptions = await runPrompts(projectName, options, userConfig, interactive)\n await executeProject(projectOptions)\n } catch (err) {\n const error = err as Error\n // @inquirer/prompts 在 Ctrl+C 时抛出 ExitPromptError\n // 检查多种可能的中断标识\n if (\n error.message === 'PROMPT_CANCELLED' ||\n error.name === 'ExitPromptError' ||\n error.message.includes('User force closed')\n ) {\n console.log(pc.yellow('\\n操作已取消'))\n process.exit(ExitCodes.SUCCESS)\n }\n throw err\n }\n })\n\n // list 子命令\n program\n .command('list')\n .description('列出所有可用模板')\n .option('--json', '以 JSON 格式输出')\n .action((options: { json?: boolean }) => {\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n const registry: TemplateRegistry = JSON.parse(\n fs.readFileSync(registryPath, 'utf-8')\n )\n\n // JSON 输出模式\n if (options.json) {\n const output = {\n templates: registry.templates.map(t => ({\n name: t.name,\n displayName: t.displayName,\n description: t.description,\n category: t.category || 'single'\n }))\n }\n console.log(JSON.stringify(output, null, 2))\n return\n }\n\n // 人类可读输出模式\n const singleTemplates = registry.templates.filter(t => t.category !== 'fullstack')\n const fullstackTemplates = registry.templates.filter(t => t.category === 'fullstack')\n\n console.log()\n console.log(pc.cyan(' 单体项目:'))\n for (const t of singleTemplates) {\n console.log(` ${pc.green(t.name.padEnd(24))} ${pc.dim(t.displayName)}`)\n }\n\n if (fullstackTemplates.length > 0) {\n console.log()\n console.log(pc.cyan(' 前后端分离:'))\n for (const t of fullstackTemplates) {\n console.log(` ${pc.green(t.name.padEnd(24))} ${pc.dim(t.displayName)}`)\n }\n }\n console.log()\n })\n\n // config 子命令\n program\n .command('config')\n .description('管理配置')\n .option('--setup-github', '配置 GitHub Token')\n .option('--show', '显示当前配置')\n .option('--path', '显示配置文件路径')\n .action(async (options: { setupGithub?: boolean; show?: boolean; path?: boolean }) => {\n if (options.setupGithub) {\n const success = await runGitHubSetup()\n process.exit(success ? ExitCodes.SUCCESS : ExitCodes.USER_ERROR)\n } else if (options.show) {\n showConfig()\n } else if (options.path) {\n console.log(getConfigPath())\n } else {\n // 默认显示帮助\n console.log()\n console.log(pc.cyan('配置管理命令:'))\n console.log()\n console.log(` ${pc.dim('spec-go config --setup-github')} 配置 GitHub Token`)\n console.log(` ${pc.dim('spec-go config --show')} 显示当前配置`)\n console.log(` ${pc.dim('spec-go config --path')} 显示配置文件路径`)\n console.log()\n }\n })\n\n // update 子命令\n program\n .command('update')\n .description('检查并更新到最新版本')\n .option('--check', '仅检查版本,不执行更新')\n .action(async (options: { check?: boolean }) => {\n await runUpdate(version, options.check ?? false)\n })\n\n return program\n}\n\nasync function executeProject(options: ProjectOptions): Promise<void> {\n const templateConfig = await scaffoldProject(options)\n console.log(pc.green('✔ 项目文件已生成'))\n\n if (!options.noInstall && templateConfig) {\n if (templateConfig.type === 'workspace') {\n await runWorkspacePostInit(options.targetDir, templateConfig, { logger: consoleLogger })\n console.log(pc.green('✔ 依赖安装完成'))\n } else if (templateConfig.postInit) {\n await runPostInit(options.targetDir, templateConfig.postInit, { logger: consoleLogger })\n console.log(pc.green('✔ 依赖安装完成'))\n }\n }\n\n if (options.initGit) {\n await initGit(options.targetDir)\n console.log(pc.green('✔ Git 仓库已初始化'))\n }\n\n if (options.createGithub) {\n const repoUrl = await createGithubRepo({\n repoName: options.projectName,\n targetDir: options.targetDir,\n isPublic: options.isPublic,\n logger: consoleLogger,\n })\n if (repoUrl) {\n console.log(pc.green(`✔ GitHub 仓库已创建: ${pc.cyan(repoUrl)}`))\n }\n }\n\n console.log()\n const pm = templateConfig?.packageManager ?? 'pnpm'\n const cdCmd = options.targetDir !== process.cwd()\n ? `cd ${options.projectName} && `\n : ''\n\n // workspace 类型的项目显示不同的提示\n if (templateConfig?.type === 'workspace') {\n if (pm === 'pnpm') {\n console.log(pc.dim(` ${cdCmd}pnpm dev`))\n } else {\n console.log(pc.dim(` ${cdCmd}make dev`))\n }\n } else if (pm === 'maven') {\n console.log(pc.dim(` ${cdCmd}./mvnw spring-boot:run`))\n } else if (pm === 'gradle') {\n console.log(pc.dim(` ${cdCmd}./gradlew bootRun`))\n } else {\n console.log(pc.dim(` ${cdCmd}${pm} dev`))\n }\n console.log()\n}\n","{\n \"name\": \"@lambertkeith/spec-go\",\n \"version\": \"0.3.0\",\n \"description\": \"CLI 脚手架工具,快速创建项目并可选初始化 GitHub 仓库\",\n \"type\": \"module\",\n \"bin\": {\n \"spec-go\": \"./dist/cli/index.js\",\n \"spec-go-mcp\": \"./dist/mcp/index.js\"\n },\n \"files\": [\n \"dist\",\n \"templates\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\",\n \"prepublishOnly\": \"pnpm build\"\n },\n \"keywords\": [\n \"cli\",\n \"scaffold\",\n \"create\",\n \"spec-go\",\n \"template\",\n \"generator\",\n \"mcp\"\n ],\n \"author\": \"\",\n \"license\": \"MIT\",\n \"devDependencies\": {\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/node\": \"^22.10.7\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.3\",\n \"vitest\": \"^3.0.4\"\n },\n \"dependencies\": {\n \"@inquirer/prompts\": \"^7.2.1\",\n \"@modelcontextprotocol/sdk\": \"^1.25.3\",\n \"commander\": \"^13.0.0\",\n \"fs-extra\": \"^11.2.0\",\n \"picocolors\": \"^1.1.1\",\n \"zod\": \"^4.3.6\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n}\n","import path from 'node:path'\nimport fs from 'node:fs'\nimport { input, select, confirm, Separator } from '@inquirer/prompts'\nimport pc from 'picocolors'\nimport {\n getTemplatesDir,\n isValidPackageName,\n toValidPackageName,\n isEmpty,\n ExitCodes,\n CliError,\n debug,\n} from '../core/index.js'\nimport type { CliOptions, ProjectOptions, TemplateRegistry, UserConfig } from '../core/index.js'\n\n/** 默认模板名称 */\nconst DEFAULT_TEMPLATE = 'node-ts'\n\nexport async function runPrompts(\n argProjectName: string | undefined,\n options: CliOptions,\n userConfig: UserConfig = {},\n interactive: boolean = true\n): Promise<ProjectOptions> {\n const defaults = userConfig.defaults ?? {}\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n const registry: TemplateRegistry = JSON.parse(\n fs.readFileSync(registryPath, 'utf-8')\n )\n\n debug('prompts', `交互模式: ${interactive}`)\n debug('prompts', `CLI 参数`, { argProjectName, options })\n\n let projectName = argProjectName\n\n // 获取项目名称\n if (!projectName) {\n if (!interactive) {\n // 非交互模式下,项目名称是必需的\n console.log(pc.red('错误: 非交互模式下必须提供项目名称'))\n throw new CliError('非交互模式下必须提供项目名称', ExitCodes.USER_ERROR)\n }\n projectName = await input({\n message: '项目名称:',\n default: 'my-project',\n validate: (value) => {\n if (!value.trim()) {\n return '项目名称不能为空'\n }\n if (!isValidPackageName(toValidPackageName(value))) {\n return '无效的项目名称'\n }\n return true\n }\n })\n }\n\n const validName = toValidPackageName(projectName)\n const targetDir = path.resolve(process.cwd(), validName)\n\n // 检查目标目录\n if (fs.existsSync(targetDir) && !isEmpty(targetDir)) {\n if (!interactive) {\n // 非交互模式下,警告并覆盖\n console.log(pc.yellow(`警告: 目标目录 \"${validName}\" 非空,将覆盖已有文件`))\n } else {\n const overwrite = await confirm({\n message: `目标目录 \"${validName}\" 非空,是否继续? (将覆盖已有文件)`,\n default: false\n })\n if (!overwrite) {\n const error = new Error('PROMPT_CANCELLED')\n throw error\n }\n }\n }\n\n // 选择模板\n let template = options.template\n if (!template) {\n if (!interactive) {\n // 非交互模式下,使用配置默认值或 node-ts\n template = defaults.template || DEFAULT_TEMPLATE\n console.log(pc.dim(`使用默认模板: ${template}`))\n } else {\n // 配置文件中的默认模板\n const defaultTemplate = defaults.template\n\n // 分组模板\n const singleTemplates = registry.templates.filter(t => t.category !== 'fullstack')\n const fullstackTemplates = registry.templates.filter(t => t.category === 'fullstack')\n\n const templateChoices: Array<{ name: string; value: string } | Separator> = []\n\n // 单体项目组\n templateChoices.push(new Separator('── 单体项目 ──'))\n for (const t of singleTemplates) {\n templateChoices.push({\n name: `${t.displayName} ${pc.dim(`- ${t.description}`)}`,\n value: t.name\n })\n }\n\n // 前后端分离组\n if (fullstackTemplates.length > 0) {\n templateChoices.push(new Separator('── 前后端分离 ──'))\n for (const t of fullstackTemplates) {\n templateChoices.push({\n name: `${t.displayName} ${pc.dim(`- ${t.description}`)}`,\n value: t.name\n })\n }\n }\n\n template = await select({\n message: '选择模板:',\n choices: templateChoices,\n default: defaultTemplate && registry.templates.some((t) => t.name === defaultTemplate)\n ? defaultTemplate\n : undefined\n })\n }\n }\n\n // 验证模板是否存在\n const found = registry.templates.find((t) => t.name === template)\n if (!found) {\n console.log(pc.red(`错误: 未找到模板 \"${template}\"`))\n console.log(pc.dim(`可用模板: ${registry.templates.map((t) => t.name).join(', ')}`))\n throw new CliError(`未找到模板 \"${template}\"`, ExitCodes.USER_ERROR)\n }\n\n // Git 初始化\n let initGit = options.git !== false\n if (options.git === undefined && interactive) {\n initGit = await confirm({\n message: '初始化 Git 仓库?',\n default: true\n })\n }\n\n // GitHub 仓库创建\n let createGithub = options.github ?? false\n if (initGit && options.github === undefined && interactive) {\n createGithub = await confirm({\n message: '在 GitHub 创建远程仓库?',\n default: defaults.github ?? false\n })\n }\n\n // 仓库可见性\n let isPublic = options.public ?? false\n if (createGithub && options.public === undefined && interactive) {\n const publicDefault = defaults.public ?? false\n isPublic = await select({\n message: '仓库可见性:',\n choices: [\n { name: 'private (私有)', value: false },\n { name: 'public (公开)', value: true }\n ],\n default: publicDefault\n }) as boolean\n }\n\n const result: ProjectOptions = {\n projectName: validName,\n template,\n targetDir,\n initGit,\n createGithub,\n isPublic,\n noInstall: options.install === false\n }\n\n debug('prompts', '最终项目选项', result)\n\n return result\n}\n","export interface TemplateConfig {\n description: string\n packageManager?: 'pnpm' | 'npm' | 'yarn' | 'uv' | 'maven' | 'gradle'\n postInit?: PostInitCommand[]\n variables?: Record<string, string>\n fileRenames?: Record<string, string>\n type?: 'single' | 'workspace'\n workspaces?: WorkspaceEntry[]\n}\n\nexport interface WorkspaceEntry {\n name: string\n packageManager?: 'pnpm' | 'npm' | 'yarn' | 'uv' | 'maven' | 'gradle'\n postInit?: PostInitCommand[]\n}\n\nexport interface PostInitCommand {\n command: string\n description: string\n}\n\nexport interface TemplateRegistry {\n templates: TemplateEntry[]\n}\n\nexport interface TemplateEntry {\n name: string\n displayName: string\n description: string\n dir: string\n category?: 'single' | 'fullstack'\n}\n\nexport interface ProjectOptions {\n projectName: string\n template: string\n targetDir: string\n initGit: boolean\n createGithub: boolean\n isPublic: boolean\n noInstall: boolean\n}\n\nexport interface CliOptions {\n template?: string\n github?: boolean\n public?: boolean\n git?: boolean\n install?: boolean\n yes?: boolean\n debug?: boolean\n}\n\nexport interface UserConfig {\n defaults?: {\n github?: boolean\n public?: boolean\n template?: string\n }\n github?: {\n token?: string\n defaultOrg?: string\n }\n}\n\nexport interface GitHubUser {\n login: string\n name: string | null\n}\n\nexport interface GitHubRepoResponse {\n html_url: string\n clone_url: string\n ssh_url: string\n full_name: string\n}\n\nexport interface GitHubApiError {\n message: string\n documentation_url?: string\n errors?: Array<{\n resource: string\n code: string\n field: string\n message?: string\n }>\n}\n\n/**\n * Logger 接口 - 用于解耦核心逻辑与 UI 输出\n * CLI 使用 picocolors 实现,MCP 使用静默实现\n */\nexport interface Logger {\n info(message: string): void\n success(message: string): void\n warn(message: string): void\n error(message: string): void\n dim(message: string): void\n}\n\n/**\n * 静默 Logger - 用于 MCP Server 等不需要控制台输出的场景\n */\nexport const silentLogger: Logger = {\n info: () => {},\n success: () => {},\n warn: () => {},\n error: () => {},\n dim: () => {},\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport type { UserConfig } from './types.js'\n\nconst CONFIG_PATH = path.join(os.homedir(), '.spec-go.json')\n\nconst DEFAULT_CONFIG: UserConfig = {\n defaults: {\n github: false,\n public: false,\n template: ''\n },\n github: {\n token: '',\n defaultOrg: ''\n }\n}\n\n/**\n * 确保配置文件存在,如果不存在则创建默认配置\n */\nexport function ensureConfigExists(): void {\n if (!fs.existsSync(CONFIG_PATH)) {\n saveConfig(DEFAULT_CONFIG)\n }\n}\n\nexport function loadConfig(): UserConfig {\n try {\n if (fs.existsSync(CONFIG_PATH)) {\n const content = fs.readFileSync(CONFIG_PATH, 'utf-8')\n return JSON.parse(content) as UserConfig\n }\n } catch {\n // 配置文件损坏或读取失败,返回空配置\n }\n return {}\n}\n\nexport function saveConfig(config: UserConfig): void {\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), 'utf-8')\n // 设置文件权限为 600 (仅所有者可读写),保护 Token 安全\n fs.chmodSync(CONFIG_PATH, 0o600)\n}\n\nexport function getConfigPath(): string {\n return CONFIG_PATH\n}\n","/**\n * 调试输出模块\n *\n * 用于在 --debug 模式下输出详细的调试信息到 stderr\n */\n\nlet debugEnabled = false\n\n/**\n * 设置调试模式是否启用\n */\nexport function setDebugEnabled(enabled: boolean): void {\n debugEnabled = enabled\n}\n\n/**\n * 检查调试模式是否启用\n */\nexport function isDebugEnabled(): boolean {\n return debugEnabled\n}\n\n/**\n * 输出调试信息到 stderr\n *\n * @param category 日志分类,如 'github-api', 'scaffold', 'git'\n * @param message 日志消息\n * @param data 可选的附加数据\n */\nexport function debug(category: string, message: string, data?: unknown): void {\n if (!debugEnabled) return\n\n const timestamp = new Date().toISOString()\n const prefix = `[DEBUG ${timestamp}] [${category}]`\n\n if (data !== undefined) {\n // 限制数据长度,避免输出过长\n const dataStr = formatData(data)\n console.error(`${prefix} ${message}`, dataStr)\n } else {\n console.error(`${prefix} ${message}`)\n }\n}\n\n/**\n * 格式化数据输出,限制长度\n */\nfunction formatData(data: unknown): string {\n try {\n const str = JSON.stringify(data, null, 2)\n // 限制每个值不超过 255 字符\n if (str.length > 500) {\n return str.slice(0, 500) + '...(truncated)'\n }\n return str\n } catch {\n return String(data)\n }\n}\n","/**\n * 标准化退出码定义\n *\n * 用于确保 CLI 工具在不同场景下返回一致的退出码\n */\nexport const ExitCodes = {\n /** 成功完成 */\n SUCCESS: 0,\n /** 用户错误:参数错误、输入无效 */\n USER_ERROR: 1,\n /** 外部错误:网络、GitHub API、包管理器 */\n EXTERNAL_ERROR: 2,\n /** 未知内部错误 */\n INTERNAL_ERROR: 10,\n /** 模板相关错误 */\n TEMPLATE_ERROR: 11,\n /** 文件系统错误 */\n FILE_SYSTEM_ERROR: 12,\n /** Git 操作错误 */\n GIT_ERROR: 13,\n} as const\n\nexport type ExitCode = (typeof ExitCodes)[keyof typeof ExitCodes]\n\n/**\n * 带退出码的错误类\n */\nexport class CliError extends Error {\n constructor(\n message: string,\n public readonly exitCode: ExitCode = ExitCodes.INTERNAL_ERROR\n ) {\n super(message)\n this.name = 'CliError'\n }\n}\n","import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { spawn } from 'node:child_process'\nimport { debug } from './debug.js'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nexport function getTemplatesDir(): string {\n return path.resolve(__dirname, '..', '..', 'templates')\n}\n\nexport function isValidPackageName(name: string): boolean {\n return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name)\n}\n\nexport function toValidPackageName(name: string): string {\n return name\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/^[._]/, '')\n .replace(/[^a-z0-9-~]+/g, '-')\n}\n\nexport function isEmpty(dirPath: string): boolean {\n const fs = require('node:fs')\n if (!fs.existsSync(dirPath)) {\n return true\n }\n const files = fs.readdirSync(dirPath)\n return files.length === 0 || (files.length === 1 && files[0] === '.git')\n}\n\nexport function execAsync(\n command: string,\n args: string[],\n options: { cwd?: string; stdio?: 'inherit' | 'pipe' } = {}\n): Promise<{ code: number; stdout: string; stderr: string }> {\n debug('exec', `执行命令: ${command} ${args.join(' ')}`, { cwd: options.cwd })\n\n return new Promise((resolve) => {\n const proc = spawn(command, args, {\n cwd: options.cwd,\n stdio: options.stdio === 'inherit' ? 'inherit' : 'pipe',\n shell: true\n })\n\n let stdout = ''\n let stderr = ''\n\n if (proc.stdout) {\n proc.stdout.on('data', (data) => {\n stdout += data.toString()\n })\n }\n\n if (proc.stderr) {\n proc.stderr.on('data', (data) => {\n stderr += data.toString()\n })\n }\n\n proc.on('close', (code) => {\n debug('exec', `命令完成,退出码: ${code ?? 1}`)\n resolve({ code: code ?? 1, stdout, stderr })\n })\n\n proc.on('error', (err) => {\n debug('exec', `命令错误: ${err.message}`)\n resolve({ code: 1, stdout, stderr })\n })\n })\n}\n\nexport async function commandExists(command: string): Promise<boolean> {\n const result = await execAsync('which', [command])\n return result.code === 0\n}\n","import path from 'node:path'\nimport fs from 'fs-extra'\nimport { getTemplatesDir } from './utils.js'\nimport { debug } from './debug.js'\nimport type { ProjectOptions, TemplateConfig, TemplateRegistry } from './types.js'\n\nexport async function scaffoldProject(\n options: ProjectOptions\n): Promise<TemplateConfig | null> {\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n const registry: TemplateRegistry = await fs.readJson(registryPath)\n\n debug('scaffold', `开始脚手架项目: ${options.projectName}`)\n debug('scaffold', `模板: ${options.template}`)\n debug('scaffold', `目标目录: ${options.targetDir}`)\n\n const templateEntry = registry.templates.find((t) => t.name === options.template)\n if (!templateEntry) {\n throw new Error(`未找到模板: ${options.template}`)\n }\n\n const templateDir = path.join(templatesDir, templateEntry.dir)\n const templateConfigPath = path.join(templateDir, '_template.json')\n\n debug('scaffold', `模板目录: ${templateDir}`)\n\n let templateConfig: TemplateConfig | null = null\n if (await fs.pathExists(templateConfigPath)) {\n templateConfig = await fs.readJson(templateConfigPath)\n debug('scaffold', '模板配置', templateConfig)\n }\n\n await fs.ensureDir(options.targetDir)\n\n const files = await fs.readdir(templateDir)\n debug('scaffold', `模板文件数量: ${files.length}`)\n\n for (const file of files) {\n if (file === '_template.json') {\n continue\n }\n\n const srcPath = path.join(templateDir, file)\n let destFileName = file\n\n if (templateConfig?.fileRenames?.[file]) {\n destFileName = templateConfig.fileRenames[file]\n if (destFileName === '{{projectName}}') {\n destFileName = options.projectName\n }\n }\n\n const destPath = path.join(options.targetDir, destFileName)\n const stat = await fs.stat(srcPath)\n\n debug('scaffold', `复制: ${file} -> ${destFileName}`)\n\n if (stat.isDirectory()) {\n await copyDirectory(srcPath, destPath, options.projectName, templateConfig)\n } else {\n await copyFile(srcPath, destPath, options.projectName, templateConfig)\n }\n }\n\n debug('scaffold', '脚手架完成')\n\n return templateConfig\n}\n\nasync function copyDirectory(\n srcDir: string,\n destDir: string,\n projectName: string,\n config: TemplateConfig | null\n): Promise<void> {\n await fs.ensureDir(destDir)\n const files = await fs.readdir(srcDir)\n\n for (const file of files) {\n const srcPath = path.join(srcDir, file)\n let destFileName = file\n\n if (config?.fileRenames?.[file]) {\n destFileName = config.fileRenames[file]\n if (destFileName === '{{projectName}}') {\n destFileName = projectName\n }\n }\n\n const destPath = path.join(destDir, destFileName)\n const stat = await fs.stat(srcPath)\n\n if (stat.isDirectory()) {\n await copyDirectory(srcPath, destPath, projectName, config)\n } else {\n await copyFile(srcPath, destPath, projectName, config)\n }\n }\n}\n\nasync function copyFile(\n srcPath: string,\n destPath: string,\n projectName: string,\n config: TemplateConfig | null\n): Promise<void> {\n const binaryExtensions = [\n '.png', '.jpg', '.jpeg', '.gif', '.ico', '.webp',\n '.woff', '.woff2', '.ttf', '.eot',\n '.zip', '.tar', '.gz'\n ]\n\n const ext = path.extname(srcPath).toLowerCase()\n\n if (binaryExtensions.includes(ext)) {\n await fs.copy(srcPath, destPath)\n return\n }\n\n let content = await fs.readFile(srcPath, 'utf-8')\n\n content = content.replace(/\\{\\{projectName\\}\\}/g, projectName)\n\n if (config?.variables) {\n for (const [key, value] of Object.entries(config.variables)) {\n const placeholder = `{{${key}}}`\n const replacement = value === '{{projectName}}' ? projectName : value\n content = content.replace(new RegExp(placeholder.replace(/[{}]/g, '\\\\$&'), 'g'), replacement)\n }\n }\n\n await fs.writeFile(destPath, content, 'utf-8')\n}\n\n/**\n * 获取所有可用模板列表\n */\nexport async function listTemplates(): Promise<TemplateRegistry> {\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n return fs.readJson(registryPath)\n}\n","import { debug } from './debug.js'\nimport type { GitHubUser, GitHubRepoResponse, GitHubApiError } from './types.js'\n\nconst GITHUB_API_BASE = 'https://api.github.com'\n\ninterface GitHubApiResult<T> {\n success: true\n data: T\n}\n\ninterface GitHubApiFailure {\n success: false\n error: string\n statusCode?: number\n rateLimitReset?: Date\n}\n\nexport type GitHubApiResponse<T> = GitHubApiResult<T> | GitHubApiFailure\n\nasync function githubFetch<T>(\n endpoint: string,\n token: string,\n options: RequestInit = {}\n): Promise<GitHubApiResponse<T>> {\n const url = `${GITHUB_API_BASE}${endpoint}`\n\n debug('github-api', `请求: ${options.method || 'GET'} ${endpoint}`)\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Accept': 'application/vnd.github+json',\n 'Authorization': `Bearer ${token}`,\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': 'spec-go',\n ...options.headers,\n },\n })\n\n debug('github-api', `响应状态: ${response.status}`)\n\n // 处理 Rate Limit\n if (response.status === 403) {\n const rateLimitRemaining = response.headers.get('x-ratelimit-remaining')\n const rateLimitReset = response.headers.get('x-ratelimit-reset')\n\n debug('github-api', `Rate Limit 信息`, { rateLimitRemaining, rateLimitReset })\n\n if (rateLimitRemaining === '0' && rateLimitReset) {\n const resetDate = new Date(parseInt(rateLimitReset) * 1000)\n return {\n success: false,\n error: 'API 请求次数已达上限',\n statusCode: 403,\n rateLimitReset: resetDate,\n }\n }\n }\n\n // 处理未授权\n if (response.status === 401) {\n debug('github-api', 'Token 验证失败')\n return {\n success: false,\n error: 'Token 无效或已过期',\n statusCode: 401,\n }\n }\n\n // 处理其他错误\n if (!response.ok) {\n const errorData = await response.json() as GitHubApiError\n debug('github-api', '请求失败', errorData)\n return {\n success: false,\n error: errorData.message || `请求失败: ${response.status}`,\n statusCode: response.status,\n }\n }\n\n const data = await response.json() as T\n debug('github-api', '请求成功')\n return { success: true, data }\n } catch (err) {\n debug('github-api', '网络请求异常', { error: err instanceof Error ? err.message : String(err) })\n return {\n success: false,\n error: err instanceof Error ? err.message : '网络请求失败',\n }\n }\n}\n\n/**\n * 验证 Token 并获取用户信息\n */\nexport async function validateToken(token: string): Promise<GitHubApiResponse<GitHubUser>> {\n return githubFetch<GitHubUser>('/user', token)\n}\n\nexport interface CreateRepoOptions {\n name: string\n description?: string\n isPrivate: boolean\n org?: string\n}\n\n/**\n * 创建 GitHub 仓库\n */\nexport async function createRepository(\n token: string,\n options: CreateRepoOptions\n): Promise<GitHubApiResponse<GitHubRepoResponse>> {\n const endpoint = options.org\n ? `/orgs/${options.org}/repos`\n : '/user/repos'\n\n const body = {\n name: options.name,\n description: options.description || `Created with spec-go`,\n private: options.isPrivate,\n auto_init: false,\n }\n\n return githubFetch<GitHubRepoResponse>(endpoint, token, {\n method: 'POST',\n body: JSON.stringify(body),\n })\n}\n\n/**\n * 检查仓库是否存在\n */\nexport async function checkRepoExists(\n token: string,\n owner: string,\n repo: string\n): Promise<boolean> {\n const result = await githubFetch<GitHubRepoResponse>(\n `/repos/${owner}/${repo}`,\n token\n )\n return result.success\n}\n","import { execAsync } from './utils.js'\nimport { loadConfig, getConfigPath } from './config.js'\nimport { validateToken, createRepository } from './github-api.js'\nimport { debug } from './debug.js'\nimport { silentLogger } from './types.js'\nimport type { Logger } from './types.js'\n\nexport async function initGit(targetDir: string): Promise<void> {\n debug('git', `初始化 Git 仓库: ${targetDir}`)\n await execAsync('git', ['init'], { cwd: targetDir })\n await execAsync('git', ['add', '-A'], { cwd: targetDir })\n await execAsync('git', ['commit', '-m', 'Initial commit'], { cwd: targetDir })\n debug('git', 'Git 初始化完成')\n}\n\nexport interface CreateGithubRepoResult {\n success: boolean\n repoUrl?: string\n error?: string\n}\n\nexport interface CreateGithubRepoOptions {\n repoName: string\n targetDir: string\n isPublic: boolean\n organization?: string\n logger?: Logger\n}\n\n/**\n * 创建 GitHub 仓库并推送代码\n * @param options 创建选项\n * @returns 仓库 URL 或 null(失败时)\n */\nexport async function createGithubRepo(\n options: CreateGithubRepoOptions\n): Promise<string | null> {\n const { repoName, targetDir, isPublic, organization, logger = silentLogger } = options\n\n debug('git', `创建 GitHub 仓库: ${repoName}, 公开: ${isPublic}`)\n const config = loadConfig()\n\n // 检查 Token 是否配置\n if (!config.github?.token) {\n logger.warn('⚠ 未配置 GitHub Token,跳过仓库创建')\n logger.dim(` 运行 spec-go config --setup-github 配置 Token`)\n logger.dim(` 配置文件路径: ${getConfigPath()}`)\n return null\n }\n\n const token = config.github.token\n const defaultOrg = organization || config.github.defaultOrg\n\n // 验证 Token\n const validateResult = await validateToken(token)\n if (!validateResult.success) {\n logger.warn(`⚠ GitHub Token 无效: ${validateResult.error}`)\n if (validateResult.rateLimitReset) {\n logger.dim(` Rate limit 将在 ${validateResult.rateLimitReset.toLocaleString()} 重置`)\n }\n logger.dim(` 运行 spec-go config --setup-github 重新配置`)\n return null\n }\n\n // 创建仓库\n const createResult = await createRepository(token, {\n name: repoName,\n isPrivate: !isPublic,\n org: defaultOrg\n })\n\n if (!createResult.success) {\n if (createResult.statusCode === 422) {\n logger.warn(`⚠ 仓库 \"${repoName}\" 已存在,请选择其他名称`)\n } else if (createResult.rateLimitReset) {\n logger.warn(`⚠ API 请求次数已达上限`)\n logger.dim(` 将在 ${createResult.rateLimitReset.toLocaleString()} 重置`)\n } else {\n logger.warn(`⚠ 创建仓库失败: ${createResult.error}`)\n }\n return null\n }\n\n const repo = createResult.data\n\n // 添加远程仓库并推送\n const remoteResult = await execAsync(\n 'git',\n ['remote', 'add', 'origin', repo.clone_url],\n { cwd: targetDir }\n )\n\n if (remoteResult.code !== 0) {\n // remote 可能已存在,尝试更新\n await execAsync(\n 'git',\n ['remote', 'set-url', 'origin', repo.clone_url],\n { cwd: targetDir }\n )\n }\n\n // 推送到远程\n const pushResult = await execAsync(\n 'git',\n ['push', '-u', 'origin', 'main'],\n { cwd: targetDir }\n )\n\n if (pushResult.code !== 0) {\n // 尝试推送 master 分支\n const pushMaster = await execAsync(\n 'git',\n ['push', '-u', 'origin', 'master'],\n { cwd: targetDir }\n )\n if (pushMaster.code !== 0) {\n logger.warn(`⚠ 推送失败: ${pushResult.stderr || pushMaster.stderr}`)\n logger.dim(` 仓库已创建: ${repo.html_url}`)\n logger.dim(' 请手动推送代码')\n return repo.html_url\n }\n }\n\n return repo.html_url\n}\n\n/**\n * 仅创建 GitHub 仓库(不推送代码)- 用于 MCP\n */\nexport async function createGithubRepoOnly(\n repoName: string,\n isPublic: boolean,\n organization?: string\n): Promise<CreateGithubRepoResult> {\n const config = loadConfig()\n\n if (!config.github?.token) {\n return {\n success: false,\n error: '未配置 GitHub Token,请运行 spec-go config --setup-github 配置'\n }\n }\n\n const token = config.github.token\n const defaultOrg = organization || config.github.defaultOrg\n\n const validateResult = await validateToken(token)\n if (!validateResult.success) {\n return {\n success: false,\n error: `GitHub Token 无效: ${validateResult.error}`\n }\n }\n\n const createResult = await createRepository(token, {\n name: repoName,\n isPrivate: !isPublic,\n org: defaultOrg\n })\n\n if (!createResult.success) {\n if (createResult.statusCode === 422) {\n return { success: false, error: `仓库 \"${repoName}\" 已存在` }\n }\n return { success: false, error: createResult.error }\n }\n\n return {\n success: true,\n repoUrl: createResult.data.html_url\n }\n}\n","import path from 'node:path'\nimport { execAsync } from './utils.js'\nimport { silentLogger } from './types.js'\nimport type { PostInitCommand, TemplateConfig, Logger } from './types.js'\n\nexport interface RunPostInitOptions {\n logger?: Logger\n}\n\nexport async function runPostInit(\n targetDir: string,\n commands: PostInitCommand[],\n options: RunPostInitOptions = {}\n): Promise<void> {\n const { logger = silentLogger } = options\n\n for (const cmd of commands) {\n logger.dim(` ${cmd.description}...`)\n const [command, ...args] = cmd.command.split(' ')\n const result = await execAsync(command, args, {\n cwd: targetDir,\n stdio: 'pipe'\n })\n\n if (result.code !== 0) {\n logger.warn(`⚠ ${cmd.description} 失败`)\n if (result.stderr) {\n logger.dim(result.stderr.slice(0, 200))\n }\n }\n }\n}\n\nexport async function runWorkspacePostInit(\n targetDir: string,\n config: TemplateConfig,\n options: RunPostInitOptions = {}\n): Promise<void> {\n const { logger = silentLogger } = options\n\n // 先执行根目录的 postInit 命令(如果有)\n if (config.postInit && config.postInit.length > 0) {\n await runPostInit(targetDir, config.postInit, options)\n }\n\n // 再执行各子目录的 postInit 命令\n if (config.workspaces) {\n for (const ws of config.workspaces) {\n if (ws.postInit && ws.postInit.length > 0) {\n const wsDir = path.join(targetDir, ws.name)\n logger.dim(` [${ws.name}]`)\n await runPostInit(wsDir, ws.postInit, options)\n }\n }\n }\n}\n","import { input, confirm } from '@inquirer/prompts'\nimport pc from 'picocolors'\nimport { loadConfig, saveConfig, validateToken } from '../core/index.js'\n\nconst TOKEN_HELP_URL = 'https://github.com/settings/tokens/new?scopes=repo&description=spec-go'\n\n/**\n * 检查是否为用户中断操作(Ctrl+C)\n */\nfunction isUserCancelled(err: unknown): boolean {\n const error = err as Error\n return (\n error.message === 'PROMPT_CANCELLED' ||\n error.name === 'ExitPromptError' ||\n error.message.includes('User force closed')\n )\n}\n\n/**\n * 运行 GitHub Token 配置引导\n */\nexport async function runGitHubSetup(): Promise<boolean> {\n console.log()\n console.log(pc.cyan('配置 GitHub Token'))\n console.log()\n console.log('需要一个具有 repo 权限的 Personal Access Token (Classic) 来创建仓库。')\n console.log()\n console.log(pc.dim('获取步骤:'))\n console.log(pc.dim('1. 访问 GitHub Settings > Developer settings > Personal access tokens'))\n console.log(pc.dim('2. 点击 \"Generate new token (classic)\"'))\n console.log(pc.dim('3. 勾选 \"repo\" 权限'))\n console.log(pc.dim('4. 生成并复制 Token'))\n console.log()\n console.log(pc.dim(`快捷链接: ${TOKEN_HELP_URL}`))\n console.log()\n\n try {\n const token = await input({\n message: '请输入 GitHub Token:',\n validate: (value) => {\n if (!value.trim()) {\n return 'Token 不能为空'\n }\n if (!value.startsWith('ghp_') && !value.startsWith('github_pat_')) {\n return 'Token 格式不正确,应以 ghp_ 或 github_pat_ 开头'\n }\n return true\n }\n })\n\n console.log()\n console.log(pc.dim('正在验证 Token...'))\n\n const result = await validateToken(token.trim())\n\n if (!result.success) {\n console.log(pc.red(`✗ Token 验证失败: ${result.error}`))\n if (result.rateLimitReset) {\n console.log(pc.dim(` Rate limit 将在 ${result.rateLimitReset.toLocaleString()} 重置`))\n }\n return false\n }\n\n const user = result.data\n console.log(pc.green(`✔ Token 有效,已登录为: ${user.login}${user.name ? ` (${user.name})` : ''}`))\n console.log()\n\n // 询问是否设置默认组织\n const setOrg = await confirm({\n message: '是否设置默认组织? (否则仓库将创建在个人账户下)',\n default: false\n })\n\n let defaultOrg: string | undefined\n if (setOrg) {\n defaultOrg = await input({\n message: '默认组织名称:',\n validate: (value) => {\n if (!value.trim()) {\n return '组织名称不能为空'\n }\n return true\n }\n })\n defaultOrg = defaultOrg.trim()\n }\n\n // 保存配置\n const config = loadConfig()\n config.github = {\n token: token.trim(),\n ...(defaultOrg && { defaultOrg })\n }\n saveConfig(config)\n\n console.log()\n console.log(pc.green('✔ GitHub 配置已保存'))\n console.log(pc.dim(' 配置文件已设置为仅当前用户可读'))\n\n return true\n } catch (err) {\n if (isUserCancelled(err)) {\n console.log(pc.yellow('\\n操作已取消'))\n return false\n }\n throw err\n }\n}\n\n/**\n * 显示当前配置\n */\nexport function showConfig(): void {\n const config = loadConfig()\n\n console.log()\n console.log(pc.cyan('当前配置:'))\n console.log()\n\n if (config.defaults) {\n console.log(pc.dim('defaults:'))\n if (config.defaults.github !== undefined) {\n console.log(` github: ${config.defaults.github}`)\n }\n if (config.defaults.public !== undefined) {\n console.log(` public: ${config.defaults.public}`)\n }\n if (config.defaults.template !== undefined) {\n console.log(` template: ${config.defaults.template}`)\n }\n }\n\n if (config.github) {\n console.log(pc.dim('github:'))\n if (config.github.token) {\n const masked = config.github.token.slice(0, 8) + '...' + config.github.token.slice(-4)\n console.log(` token: ${masked}`)\n }\n if (config.github.defaultOrg) {\n console.log(` defaultOrg: ${config.github.defaultOrg}`)\n }\n }\n\n if (!config.defaults && !config.github) {\n console.log(pc.dim('(无配置)'))\n }\n\n console.log()\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { execSync } from 'node:child_process'\nimport pc from 'picocolors'\nimport { ExitCodes } from '../core/index.js'\n\nconst CACHE_PATH = path.join(os.homedir(), '.spec-go-update-check')\nconst CACHE_TTL = 24 * 60 * 60 * 1000 // 24 小时\nconst PACKAGE_NAME = '@lambertkeith/spec-go'\n\ninterface UpdateCache {\n lastCheck: number\n latestVersion: string\n}\n\nfunction readCache(): UpdateCache | null {\n try {\n if (fs.existsSync(CACHE_PATH)) {\n const content = fs.readFileSync(CACHE_PATH, 'utf-8')\n return JSON.parse(content) as UpdateCache\n }\n } catch {\n // 忽略缓存读取错误\n }\n return null\n}\n\nfunction writeCache(cache: UpdateCache): void {\n try {\n fs.writeFileSync(CACHE_PATH, JSON.stringify(cache), 'utf-8')\n } catch {\n // 忽略缓存写入错误\n }\n}\n\nasync function fetchLatestVersion(): Promise<string | null> {\n try {\n const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`)\n if (!response.ok) {\n return null\n }\n const data = (await response.json()) as { version: string }\n return data.version\n } catch {\n // 网络请求失败,静默处理\n return null\n }\n}\n\nfunction compareVersions(current: string, latest: string): number {\n const currentParts = current.split('.').map(Number)\n const latestParts = latest.split('.').map(Number)\n\n for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {\n const c = currentParts[i] || 0\n const l = latestParts[i] || 0\n if (c < l) return -1\n if (c > l) return 1\n }\n return 0\n}\n\nexport async function checkForUpdates(currentVersion: string): Promise<void> {\n const cache = readCache()\n const now = Date.now()\n\n let latestVersion: string | null = null\n\n // 检查缓存是否有效\n if (cache && now - cache.lastCheck < CACHE_TTL) {\n latestVersion = cache.latestVersion\n } else {\n // 缓存过期,重新获取\n latestVersion = await fetchLatestVersion()\n if (latestVersion) {\n writeCache({ lastCheck: now, latestVersion })\n }\n }\n\n // 比较版本并提示\n if (latestVersion && compareVersions(currentVersion, latestVersion) < 0) {\n console.log()\n console.log(\n pc.yellow(` \\u26A0 发现新版本 ${pc.bold(latestVersion)},当前 ${currentVersion}`)\n )\n console.log(pc.cyan(` 运行 ${pc.bold(`npm update -g ${PACKAGE_NAME}`)} 更新`))\n console.log()\n }\n}\n\ntype PackageManager = 'npm' | 'pnpm' | 'yarn'\n\nfunction detectPackageManager(): PackageManager {\n // 检查 spec-go 是通过哪个包管理器安装的\n // 方法:检查全局安装路径中是否包含 pnpm/yarn 特征\n const execPath = process.argv[1] || ''\n\n if (execPath.includes('pnpm')) return 'pnpm'\n if (execPath.includes('yarn')) return 'yarn'\n return 'npm'\n}\n\nfunction getUpdateCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return `pnpm update -g ${PACKAGE_NAME}`\n case 'yarn':\n return `yarn global upgrade ${PACKAGE_NAME}`\n default:\n return `npm update -g ${PACKAGE_NAME}`\n }\n}\n\nexport async function runUpdate(currentVersion: string, checkOnly: boolean): Promise<void> {\n // 1. 强制获取最新版本(跳过缓存)\n const latestVersion = await fetchLatestVersion()\n\n if (!latestVersion) {\n console.log(pc.red('✗ 无法获取最新版本信息'))\n process.exit(ExitCodes.EXTERNAL_ERROR)\n }\n\n // 2. 版本比较\n const comparison = compareVersions(currentVersion, latestVersion)\n\n if (comparison >= 0) {\n console.log(pc.green(`✔ 已是最新版本 (${currentVersion})`))\n return\n }\n\n console.log(pc.cyan(`发现新版本: ${currentVersion} → ${latestVersion}`))\n\n if (checkOnly) {\n console.log(pc.dim(`运行 spec-go update 更新`))\n return\n }\n\n // 3. 检测包管理器并执行更新\n const pm = detectPackageManager()\n const updateCmd = getUpdateCommand(pm)\n\n console.log(pc.dim(`正在执行: ${updateCmd}`))\n\n // 4. 执行更新命令\n try {\n execSync(updateCmd, { stdio: 'inherit' })\n console.log(pc.green(`✔ 更新完成`))\n } catch {\n console.log(pc.red('✗ 更新失败,请手动执行更新命令'))\n process.exit(ExitCodes.EXTERNAL_ERROR)\n }\n}\n","import pc from 'picocolors'\nimport type { Logger } from '../core/index.js'\n\n/**\n * CLI 专用 Logger 实现\n * 使用 picocolors 进行彩色输出\n */\nexport const consoleLogger: Logger = {\n info(message: string): void {\n console.log(message)\n },\n success(message: string): void {\n console.log(pc.green(message))\n },\n warn(message: string): void {\n console.log(pc.yellow(message))\n },\n error(message: string): void {\n console.log(pc.red(message))\n },\n dim(message: string): void {\n console.log(pc.dim(message))\n },\n}\n","import { createCli } from './cli.js'\nimport { ensureConfigExists, ExitCodes, CliError, isDebugEnabled } from '../core/index.js'\n\nasync function main(): Promise<void> {\n // 确保配置文件存在\n ensureConfigExists()\n\n const program = await createCli()\n await program.parseAsync(process.argv)\n}\n\nmain().catch((err) => {\n // CliError 已经在 prompts.ts 等地方输出了用户友好的错误信息\n // 只在调试模式下输出完整堆栈\n if (err instanceof CliError) {\n if (isDebugEnabled()) {\n console.error(err)\n }\n process.exit(err.exitCode)\n }\n // 其他未知错误始终输出\n console.error(err)\n process.exit(ExitCodes.INTERNAL_ERROR)\n})\n"],"mappings":"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","names":["path","fs","pc","path","fs","path","path","fs","path","fs","path","fs","path","path","path","fs","initGit","input","confirm","pc","pc","input","confirm","fs","path","os","pc","path","os","fs","pc","pc","pc","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/cli.ts","../../package.json","../../src/cli/prompts.ts","../../src/core/types.ts","../../src/core/config.ts","../../src/core/debug.ts","../../src/core/exit-codes.ts","../../src/core/utils.ts","../../src/core/scaffold.ts","../../src/core/github-api.ts","../../src/core/git.ts","../../src/core/post-init.ts","../../src/cli/github-setup.ts","../../src/cli/update-check.ts","../../src/cli/guide.ts","../../src/cli/guide-content.ts","../../src/cli/console-logger.ts","../../src/cli/index.ts"],"sourcesContent":["import path from 'node:path'\nimport fs from 'node:fs'\nimport { Command } from 'commander'\nimport pc from 'picocolors'\nimport { version } from '../../package.json'\nimport { runPrompts } from './prompts.js'\nimport { runGitHubSetup, showConfig } from './github-setup.js'\nimport { checkForUpdates, runUpdate } from './update-check.js'\nimport { runGuide } from './guide.js'\nimport { consoleLogger } from './console-logger.js'\nimport {\n scaffoldProject,\n initGit,\n createGithubRepo,\n runPostInit,\n runWorkspacePostInit,\n loadConfig,\n getConfigPath,\n getTemplatesDir,\n ExitCodes,\n CliError,\n setDebugEnabled,\n} from '../core/index.js'\nimport type { CliOptions, ProjectOptions, TemplateRegistry } from '../core/index.js'\n\n/**\n * 检查是否在交互模式下运行\n */\nfunction isInteractive(options: CliOptions): boolean {\n // --yes 选项强制非交互模式\n if (options.yes) return false\n // 检查 stdin 是否是 TTY\n return process.stdin.isTTY === true\n}\n\nexport async function createCli(): Promise<Command> {\n const program = new Command()\n\n program\n .name('spec-go')\n .description('CLI 脚手架工具,快速创建项目并可选初始化 GitHub 仓库')\n .version(version)\n .argument('[project-name]', '项目名称')\n .option('-t, --template <template>', '使用指定模板')\n .option('--github', '在 GitHub 创建远程仓库')\n .option('--public', '创建公开仓库 (默认私有)')\n .option('--no-git', '跳过 Git 初始化')\n .option('--no-install', '跳过依赖安装')\n .option('-y, --yes', '跳过所有确认提示,使用默认值(非交互模式)')\n .option('--debug', '启用调试输出')\n .action(async (projectName: string | undefined, options: CliOptions) => {\n // 启用调试模式\n if (options.debug) {\n setDebugEnabled(true)\n }\n\n console.log()\n console.log(` ${pc.cyan('spec-go')} ${pc.dim(`v${version}`)}`)\n console.log()\n\n // 异步检查更新(不阻塞主流程)\n checkForUpdates(version).catch(() => {})\n\n // 加载用户配置\n const userConfig = loadConfig()\n\n // 检查是否为交互模式\n const interactive = isInteractive(options)\n\n try {\n const projectOptions = await runPrompts(projectName, options, userConfig, interactive)\n await executeProject(projectOptions)\n } catch (err) {\n const error = err as Error\n // @inquirer/prompts 在 Ctrl+C 时抛出 ExitPromptError\n // 检查多种可能的中断标识\n if (\n error.message === 'PROMPT_CANCELLED' ||\n error.name === 'ExitPromptError' ||\n error.message.includes('User force closed')\n ) {\n console.log(pc.yellow('\\n操作已取消'))\n process.exit(ExitCodes.SUCCESS)\n }\n throw err\n }\n })\n\n // list 子命令\n program\n .command('list')\n .description('列出所有可用模板')\n .option('--json', '以 JSON 格式输出')\n .action((options: { json?: boolean }) => {\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n const registry: TemplateRegistry = JSON.parse(\n fs.readFileSync(registryPath, 'utf-8')\n )\n\n // JSON 输出模式\n if (options.json) {\n const output = {\n templates: registry.templates.map(t => ({\n name: t.name,\n displayName: t.displayName,\n description: t.description,\n category: t.category || 'single'\n }))\n }\n console.log(JSON.stringify(output, null, 2))\n return\n }\n\n // 人类可读输出模式\n const singleTemplates = registry.templates.filter(t => t.category !== 'fullstack')\n const fullstackTemplates = registry.templates.filter(t => t.category === 'fullstack')\n\n console.log()\n console.log(pc.cyan(' 单体项目:'))\n for (const t of singleTemplates) {\n console.log(` ${pc.green(t.name.padEnd(24))} ${pc.dim(t.displayName)}`)\n }\n\n if (fullstackTemplates.length > 0) {\n console.log()\n console.log(pc.cyan(' 前后端分离:'))\n for (const t of fullstackTemplates) {\n console.log(` ${pc.green(t.name.padEnd(24))} ${pc.dim(t.displayName)}`)\n }\n }\n console.log()\n })\n\n // config 子命令\n program\n .command('config')\n .description('管理配置')\n .option('--setup-github', '配置 GitHub Token')\n .option('--show', '显示当前配置')\n .option('--path', '显示配置文件路径')\n .action(async (options: { setupGithub?: boolean; show?: boolean; path?: boolean }) => {\n if (options.setupGithub) {\n const success = await runGitHubSetup()\n process.exit(success ? ExitCodes.SUCCESS : ExitCodes.USER_ERROR)\n } else if (options.show) {\n showConfig()\n } else if (options.path) {\n console.log(getConfigPath())\n } else {\n // 默认显示帮助\n console.log()\n console.log(pc.cyan('配置管理命令:'))\n console.log()\n console.log(` ${pc.dim('spec-go config --setup-github')} 配置 GitHub Token`)\n console.log(` ${pc.dim('spec-go config --show')} 显示当前配置`)\n console.log(` ${pc.dim('spec-go config --path')} 显示配置文件路径`)\n console.log()\n }\n })\n\n // update 子命令\n program\n .command('update')\n .description('检查并更新到最新版本')\n .option('--check', '仅检查版本,不执行更新')\n .action(async (options: { check?: boolean }) => {\n await runUpdate(version, options.check ?? false)\n })\n\n // guide 子命令\n program\n .command('guide [topic]')\n .description('显示使用指南和帮助文档')\n .option('--list', '列出所有可用主题')\n .option('--json', '以 JSON 格式输出')\n .action(async (topic: string | undefined, options: { list?: boolean; json?: boolean }) => {\n await runGuide(topic, options)\n })\n\n return program\n}\n\nasync function executeProject(options: ProjectOptions): Promise<void> {\n const templateConfig = await scaffoldProject(options)\n console.log(pc.green('✔ 项目文件已生成'))\n\n if (!options.noInstall && templateConfig) {\n if (templateConfig.type === 'workspace') {\n await runWorkspacePostInit(options.targetDir, templateConfig, { logger: consoleLogger })\n console.log(pc.green('✔ 依赖安装完成'))\n } else if (templateConfig.postInit) {\n await runPostInit(options.targetDir, templateConfig.postInit, { logger: consoleLogger })\n console.log(pc.green('✔ 依赖安装完成'))\n }\n }\n\n if (options.initGit) {\n await initGit(options.targetDir)\n console.log(pc.green('✔ Git 仓库已初始化'))\n }\n\n if (options.createGithub) {\n const repoUrl = await createGithubRepo({\n repoName: options.projectName,\n targetDir: options.targetDir,\n isPublic: options.isPublic,\n logger: consoleLogger,\n })\n if (repoUrl) {\n console.log(pc.green(`✔ GitHub 仓库已创建: ${pc.cyan(repoUrl)}`))\n }\n }\n\n console.log()\n const pm = templateConfig?.packageManager ?? 'pnpm'\n const cdCmd = options.targetDir !== process.cwd()\n ? `cd ${options.projectName} && `\n : ''\n\n // workspace 类型的项目显示不同的提示\n if (templateConfig?.type === 'workspace') {\n if (pm === 'pnpm') {\n console.log(pc.dim(` ${cdCmd}pnpm dev`))\n } else {\n console.log(pc.dim(` ${cdCmd}make dev`))\n }\n } else if (pm === 'maven') {\n console.log(pc.dim(` ${cdCmd}./mvnw spring-boot:run`))\n } else if (pm === 'gradle') {\n console.log(pc.dim(` ${cdCmd}./gradlew bootRun`))\n } else {\n console.log(pc.dim(` ${cdCmd}${pm} dev`))\n }\n console.log()\n}\n","{\n \"name\": \"@lambertkeith/spec-go\",\n \"version\": \"0.3.1\",\n \"description\": \"CLI 脚手架工具,快速创建项目并可选初始化 GitHub 仓库\",\n \"type\": \"module\",\n \"bin\": {\n \"spec-go\": \"./dist/cli/index.js\",\n \"spec-go-mcp\": \"./dist/mcp/index.js\"\n },\n \"files\": [\n \"dist\",\n \"templates\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\",\n \"prepublishOnly\": \"pnpm build\"\n },\n \"keywords\": [\n \"cli\",\n \"scaffold\",\n \"create\",\n \"spec-go\",\n \"template\",\n \"generator\",\n \"mcp\"\n ],\n \"author\": \"\",\n \"license\": \"MIT\",\n \"devDependencies\": {\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/node\": \"^22.10.7\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.3\",\n \"vitest\": \"^3.0.4\"\n },\n \"dependencies\": {\n \"@inquirer/prompts\": \"^7.2.1\",\n \"@modelcontextprotocol/sdk\": \"^1.25.3\",\n \"commander\": \"^13.0.0\",\n \"fs-extra\": \"^11.2.0\",\n \"picocolors\": \"^1.1.1\",\n \"zod\": \"^4.3.6\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n}\n","import path from 'node:path'\nimport fs from 'node:fs'\nimport { input, select, confirm, Separator } from '@inquirer/prompts'\nimport pc from 'picocolors'\nimport {\n getTemplatesDir,\n isValidPackageName,\n toValidPackageName,\n isEmpty,\n ExitCodes,\n CliError,\n debug,\n} from '../core/index.js'\nimport type { CliOptions, ProjectOptions, TemplateRegistry, UserConfig } from '../core/index.js'\n\n/** 默认模板名称 */\nconst DEFAULT_TEMPLATE = 'node-ts'\n\nexport async function runPrompts(\n argProjectName: string | undefined,\n options: CliOptions,\n userConfig: UserConfig = {},\n interactive: boolean = true\n): Promise<ProjectOptions> {\n const defaults = userConfig.defaults ?? {}\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n const registry: TemplateRegistry = JSON.parse(\n fs.readFileSync(registryPath, 'utf-8')\n )\n\n debug('prompts', `交互模式: ${interactive}`)\n debug('prompts', `CLI 参数`, { argProjectName, options })\n\n let projectName = argProjectName\n\n // 获取项目名称\n if (!projectName) {\n if (!interactive) {\n // 非交互模式下,项目名称是必需的\n console.log(pc.red('错误: 非交互模式下必须提供项目名称'))\n throw new CliError('非交互模式下必须提供项目名称', ExitCodes.USER_ERROR)\n }\n projectName = await input({\n message: '项目名称:',\n default: 'my-project',\n validate: (value) => {\n if (!value.trim()) {\n return '项目名称不能为空'\n }\n if (!isValidPackageName(toValidPackageName(value))) {\n return '无效的项目名称'\n }\n return true\n }\n })\n }\n\n const validName = toValidPackageName(projectName)\n const targetDir = path.resolve(process.cwd(), validName)\n\n // 检查目标目录\n if (fs.existsSync(targetDir) && !isEmpty(targetDir)) {\n if (!interactive) {\n // 非交互模式下,警告并覆盖\n console.log(pc.yellow(`警告: 目标目录 \"${validName}\" 非空,将覆盖已有文件`))\n } else {\n const overwrite = await confirm({\n message: `目标目录 \"${validName}\" 非空,是否继续? (将覆盖已有文件)`,\n default: false\n })\n if (!overwrite) {\n const error = new Error('PROMPT_CANCELLED')\n throw error\n }\n }\n }\n\n // 选择模板\n let template = options.template\n if (!template) {\n if (!interactive) {\n // 非交互模式下,使用配置默认值或 node-ts\n template = defaults.template || DEFAULT_TEMPLATE\n console.log(pc.dim(`使用默认模板: ${template}`))\n } else {\n // 配置文件中的默认模板\n const defaultTemplate = defaults.template\n\n // 分组模板\n const singleTemplates = registry.templates.filter(t => t.category !== 'fullstack')\n const fullstackTemplates = registry.templates.filter(t => t.category === 'fullstack')\n\n const templateChoices: Array<{ name: string; value: string } | Separator> = []\n\n // 单体项目组\n templateChoices.push(new Separator('── 单体项目 ──'))\n for (const t of singleTemplates) {\n templateChoices.push({\n name: `${t.displayName} ${pc.dim(`- ${t.description}`)}`,\n value: t.name\n })\n }\n\n // 前后端分离组\n if (fullstackTemplates.length > 0) {\n templateChoices.push(new Separator('── 前后端分离 ──'))\n for (const t of fullstackTemplates) {\n templateChoices.push({\n name: `${t.displayName} ${pc.dim(`- ${t.description}`)}`,\n value: t.name\n })\n }\n }\n\n template = await select({\n message: '选择模板:',\n choices: templateChoices,\n default: defaultTemplate && registry.templates.some((t) => t.name === defaultTemplate)\n ? defaultTemplate\n : undefined\n })\n }\n }\n\n // 验证模板是否存在\n const found = registry.templates.find((t) => t.name === template)\n if (!found) {\n console.log(pc.red(`错误: 未找到模板 \"${template}\"`))\n console.log(pc.dim(`可用模板: ${registry.templates.map((t) => t.name).join(', ')}`))\n throw new CliError(`未找到模板 \"${template}\"`, ExitCodes.USER_ERROR)\n }\n\n // Git 初始化\n let initGit = options.git !== false\n if (options.git === undefined && interactive) {\n initGit = await confirm({\n message: '初始化 Git 仓库?',\n default: true\n })\n }\n\n // GitHub 仓库创建\n let createGithub = options.github ?? false\n if (initGit && options.github === undefined && interactive) {\n createGithub = await confirm({\n message: '在 GitHub 创建远程仓库?',\n default: defaults.github ?? false\n })\n }\n\n // 仓库可见性\n let isPublic = options.public ?? false\n if (createGithub && options.public === undefined && interactive) {\n const publicDefault = defaults.public ?? false\n isPublic = await select({\n message: '仓库可见性:',\n choices: [\n { name: 'private (私有)', value: false },\n { name: 'public (公开)', value: true }\n ],\n default: publicDefault\n }) as boolean\n }\n\n const result: ProjectOptions = {\n projectName: validName,\n template,\n targetDir,\n initGit,\n createGithub,\n isPublic,\n noInstall: options.install === false\n }\n\n debug('prompts', '最终项目选项', result)\n\n return result\n}\n","export interface TemplateConfig {\n description: string\n packageManager?: 'pnpm' | 'npm' | 'yarn' | 'uv' | 'maven' | 'gradle'\n postInit?: PostInitCommand[]\n variables?: Record<string, string>\n fileRenames?: Record<string, string>\n type?: 'single' | 'workspace'\n workspaces?: WorkspaceEntry[]\n}\n\nexport interface WorkspaceEntry {\n name: string\n packageManager?: 'pnpm' | 'npm' | 'yarn' | 'uv' | 'maven' | 'gradle'\n postInit?: PostInitCommand[]\n}\n\nexport interface PostInitCommand {\n command: string\n description: string\n}\n\nexport interface TemplateRegistry {\n templates: TemplateEntry[]\n}\n\nexport interface TemplateEntry {\n name: string\n displayName: string\n description: string\n dir: string\n category?: 'single' | 'fullstack'\n}\n\nexport interface ProjectOptions {\n projectName: string\n template: string\n targetDir: string\n initGit: boolean\n createGithub: boolean\n isPublic: boolean\n noInstall: boolean\n}\n\nexport interface CliOptions {\n template?: string\n github?: boolean\n public?: boolean\n git?: boolean\n install?: boolean\n yes?: boolean\n debug?: boolean\n}\n\nexport interface UserConfig {\n defaults?: {\n github?: boolean\n public?: boolean\n template?: string\n }\n github?: {\n token?: string\n defaultOrg?: string\n }\n}\n\nexport interface GitHubUser {\n login: string\n name: string | null\n}\n\nexport interface GitHubRepoResponse {\n html_url: string\n clone_url: string\n ssh_url: string\n full_name: string\n}\n\nexport interface GitHubApiError {\n message: string\n documentation_url?: string\n errors?: Array<{\n resource: string\n code: string\n field: string\n message?: string\n }>\n}\n\n/**\n * Logger 接口 - 用于解耦核心逻辑与 UI 输出\n * CLI 使用 picocolors 实现,MCP 使用静默实现\n */\nexport interface Logger {\n info(message: string): void\n success(message: string): void\n warn(message: string): void\n error(message: string): void\n dim(message: string): void\n}\n\n/**\n * 静默 Logger - 用于 MCP Server 等不需要控制台输出的场景\n */\nexport const silentLogger: Logger = {\n info: () => {},\n success: () => {},\n warn: () => {},\n error: () => {},\n dim: () => {},\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport type { UserConfig } from './types.js'\n\nconst CONFIG_PATH = path.join(os.homedir(), '.spec-go.json')\n\nconst DEFAULT_CONFIG: UserConfig = {\n defaults: {\n github: false,\n public: false,\n template: ''\n },\n github: {\n token: '',\n defaultOrg: ''\n }\n}\n\n/**\n * 确保配置文件存在,如果不存在则创建默认配置\n */\nexport function ensureConfigExists(): void {\n if (!fs.existsSync(CONFIG_PATH)) {\n saveConfig(DEFAULT_CONFIG)\n }\n}\n\nexport function loadConfig(): UserConfig {\n try {\n if (fs.existsSync(CONFIG_PATH)) {\n const content = fs.readFileSync(CONFIG_PATH, 'utf-8')\n return JSON.parse(content) as UserConfig\n }\n } catch {\n // 配置文件损坏或读取失败,返回空配置\n }\n return {}\n}\n\nexport function saveConfig(config: UserConfig): void {\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), 'utf-8')\n // 设置文件权限为 600 (仅所有者可读写),保护 Token 安全\n fs.chmodSync(CONFIG_PATH, 0o600)\n}\n\nexport function getConfigPath(): string {\n return CONFIG_PATH\n}\n","/**\n * 调试输出模块\n *\n * 用于在 --debug 模式下输出详细的调试信息到 stderr\n */\n\nlet debugEnabled = false\n\n/**\n * 设置调试模式是否启用\n */\nexport function setDebugEnabled(enabled: boolean): void {\n debugEnabled = enabled\n}\n\n/**\n * 检查调试模式是否启用\n */\nexport function isDebugEnabled(): boolean {\n return debugEnabled\n}\n\n/**\n * 输出调试信息到 stderr\n *\n * @param category 日志分类,如 'github-api', 'scaffold', 'git'\n * @param message 日志消息\n * @param data 可选的附加数据\n */\nexport function debug(category: string, message: string, data?: unknown): void {\n if (!debugEnabled) return\n\n const timestamp = new Date().toISOString()\n const prefix = `[DEBUG ${timestamp}] [${category}]`\n\n if (data !== undefined) {\n // 限制数据长度,避免输出过长\n const dataStr = formatData(data)\n console.error(`${prefix} ${message}`, dataStr)\n } else {\n console.error(`${prefix} ${message}`)\n }\n}\n\n/**\n * 格式化数据输出,限制长度\n */\nfunction formatData(data: unknown): string {\n try {\n const str = JSON.stringify(data, null, 2)\n // 限制每个值不超过 255 字符\n if (str.length > 500) {\n return str.slice(0, 500) + '...(truncated)'\n }\n return str\n } catch {\n return String(data)\n }\n}\n","/**\n * 标准化退出码定义\n *\n * 用于确保 CLI 工具在不同场景下返回一致的退出码\n */\nexport const ExitCodes = {\n /** 成功完成 */\n SUCCESS: 0,\n /** 用户错误:参数错误、输入无效 */\n USER_ERROR: 1,\n /** 外部错误:网络、GitHub API、包管理器 */\n EXTERNAL_ERROR: 2,\n /** 未知内部错误 */\n INTERNAL_ERROR: 10,\n /** 模板相关错误 */\n TEMPLATE_ERROR: 11,\n /** 文件系统错误 */\n FILE_SYSTEM_ERROR: 12,\n /** Git 操作错误 */\n GIT_ERROR: 13,\n} as const\n\nexport type ExitCode = (typeof ExitCodes)[keyof typeof ExitCodes]\n\n/**\n * 带退出码的错误类\n */\nexport class CliError extends Error {\n constructor(\n message: string,\n public readonly exitCode: ExitCode = ExitCodes.INTERNAL_ERROR\n ) {\n super(message)\n this.name = 'CliError'\n }\n}\n","import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { spawn } from 'node:child_process'\nimport { debug } from './debug.js'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nexport function getTemplatesDir(): string {\n return path.resolve(__dirname, '..', '..', 'templates')\n}\n\nexport function isValidPackageName(name: string): boolean {\n return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name)\n}\n\nexport function toValidPackageName(name: string): string {\n return name\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/^[._]/, '')\n .replace(/[^a-z0-9-~]+/g, '-')\n}\n\nexport function isEmpty(dirPath: string): boolean {\n const fs = require('node:fs')\n if (!fs.existsSync(dirPath)) {\n return true\n }\n const files = fs.readdirSync(dirPath)\n return files.length === 0 || (files.length === 1 && files[0] === '.git')\n}\n\nexport function execAsync(\n command: string,\n args: string[],\n options: { cwd?: string; stdio?: 'inherit' | 'pipe' } = {}\n): Promise<{ code: number; stdout: string; stderr: string }> {\n debug('exec', `执行命令: ${command} ${args.join(' ')}`, { cwd: options.cwd })\n\n return new Promise((resolve) => {\n const proc = spawn(command, args, {\n cwd: options.cwd,\n stdio: options.stdio === 'inherit' ? 'inherit' : 'pipe',\n shell: true\n })\n\n let stdout = ''\n let stderr = ''\n\n if (proc.stdout) {\n proc.stdout.on('data', (data) => {\n stdout += data.toString()\n })\n }\n\n if (proc.stderr) {\n proc.stderr.on('data', (data) => {\n stderr += data.toString()\n })\n }\n\n proc.on('close', (code) => {\n debug('exec', `命令完成,退出码: ${code ?? 1}`)\n resolve({ code: code ?? 1, stdout, stderr })\n })\n\n proc.on('error', (err) => {\n debug('exec', `命令错误: ${err.message}`)\n resolve({ code: 1, stdout, stderr })\n })\n })\n}\n\nexport async function commandExists(command: string): Promise<boolean> {\n const result = await execAsync('which', [command])\n return result.code === 0\n}\n","import path from 'node:path'\nimport fs from 'fs-extra'\nimport { getTemplatesDir } from './utils.js'\nimport { debug } from './debug.js'\nimport type { ProjectOptions, TemplateConfig, TemplateRegistry } from './types.js'\n\nexport async function scaffoldProject(\n options: ProjectOptions\n): Promise<TemplateConfig | null> {\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n const registry: TemplateRegistry = await fs.readJson(registryPath)\n\n debug('scaffold', `开始脚手架项目: ${options.projectName}`)\n debug('scaffold', `模板: ${options.template}`)\n debug('scaffold', `目标目录: ${options.targetDir}`)\n\n const templateEntry = registry.templates.find((t) => t.name === options.template)\n if (!templateEntry) {\n throw new Error(`未找到模板: ${options.template}`)\n }\n\n const templateDir = path.join(templatesDir, templateEntry.dir)\n const templateConfigPath = path.join(templateDir, '_template.json')\n\n debug('scaffold', `模板目录: ${templateDir}`)\n\n let templateConfig: TemplateConfig | null = null\n if (await fs.pathExists(templateConfigPath)) {\n templateConfig = await fs.readJson(templateConfigPath)\n debug('scaffold', '模板配置', templateConfig)\n }\n\n await fs.ensureDir(options.targetDir)\n\n const files = await fs.readdir(templateDir)\n debug('scaffold', `模板文件数量: ${files.length}`)\n\n for (const file of files) {\n if (file === '_template.json') {\n continue\n }\n\n const srcPath = path.join(templateDir, file)\n let destFileName = file\n\n if (templateConfig?.fileRenames?.[file]) {\n destFileName = templateConfig.fileRenames[file]\n if (destFileName === '{{projectName}}') {\n destFileName = options.projectName\n }\n }\n\n const destPath = path.join(options.targetDir, destFileName)\n const stat = await fs.stat(srcPath)\n\n debug('scaffold', `复制: ${file} -> ${destFileName}`)\n\n if (stat.isDirectory()) {\n await copyDirectory(srcPath, destPath, options.projectName, templateConfig)\n } else {\n await copyFile(srcPath, destPath, options.projectName, templateConfig)\n }\n }\n\n debug('scaffold', '脚手架完成')\n\n return templateConfig\n}\n\nasync function copyDirectory(\n srcDir: string,\n destDir: string,\n projectName: string,\n config: TemplateConfig | null\n): Promise<void> {\n await fs.ensureDir(destDir)\n const files = await fs.readdir(srcDir)\n\n for (const file of files) {\n const srcPath = path.join(srcDir, file)\n let destFileName = file\n\n if (config?.fileRenames?.[file]) {\n destFileName = config.fileRenames[file]\n if (destFileName === '{{projectName}}') {\n destFileName = projectName\n }\n }\n\n const destPath = path.join(destDir, destFileName)\n const stat = await fs.stat(srcPath)\n\n if (stat.isDirectory()) {\n await copyDirectory(srcPath, destPath, projectName, config)\n } else {\n await copyFile(srcPath, destPath, projectName, config)\n }\n }\n}\n\nasync function copyFile(\n srcPath: string,\n destPath: string,\n projectName: string,\n config: TemplateConfig | null\n): Promise<void> {\n const binaryExtensions = [\n '.png', '.jpg', '.jpeg', '.gif', '.ico', '.webp',\n '.woff', '.woff2', '.ttf', '.eot',\n '.zip', '.tar', '.gz'\n ]\n\n const ext = path.extname(srcPath).toLowerCase()\n\n if (binaryExtensions.includes(ext)) {\n await fs.copy(srcPath, destPath)\n return\n }\n\n let content = await fs.readFile(srcPath, 'utf-8')\n\n content = content.replace(/\\{\\{projectName\\}\\}/g, projectName)\n\n if (config?.variables) {\n for (const [key, value] of Object.entries(config.variables)) {\n const placeholder = `{{${key}}}`\n const replacement = value === '{{projectName}}' ? projectName : value\n content = content.replace(new RegExp(placeholder.replace(/[{}]/g, '\\\\$&'), 'g'), replacement)\n }\n }\n\n await fs.writeFile(destPath, content, 'utf-8')\n}\n\n/**\n * 获取所有可用模板列表\n */\nexport async function listTemplates(): Promise<TemplateRegistry> {\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n return fs.readJson(registryPath)\n}\n","import { debug } from './debug.js'\nimport type { GitHubUser, GitHubRepoResponse, GitHubApiError } from './types.js'\n\nconst GITHUB_API_BASE = 'https://api.github.com'\n\ninterface GitHubApiResult<T> {\n success: true\n data: T\n}\n\ninterface GitHubApiFailure {\n success: false\n error: string\n statusCode?: number\n rateLimitReset?: Date\n}\n\nexport type GitHubApiResponse<T> = GitHubApiResult<T> | GitHubApiFailure\n\nasync function githubFetch<T>(\n endpoint: string,\n token: string,\n options: RequestInit = {}\n): Promise<GitHubApiResponse<T>> {\n const url = `${GITHUB_API_BASE}${endpoint}`\n\n debug('github-api', `请求: ${options.method || 'GET'} ${endpoint}`)\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Accept': 'application/vnd.github+json',\n 'Authorization': `Bearer ${token}`,\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': 'spec-go',\n ...options.headers,\n },\n })\n\n debug('github-api', `响应状态: ${response.status}`)\n\n // 处理 Rate Limit\n if (response.status === 403) {\n const rateLimitRemaining = response.headers.get('x-ratelimit-remaining')\n const rateLimitReset = response.headers.get('x-ratelimit-reset')\n\n debug('github-api', `Rate Limit 信息`, { rateLimitRemaining, rateLimitReset })\n\n if (rateLimitRemaining === '0' && rateLimitReset) {\n const resetDate = new Date(parseInt(rateLimitReset) * 1000)\n return {\n success: false,\n error: 'API 请求次数已达上限',\n statusCode: 403,\n rateLimitReset: resetDate,\n }\n }\n }\n\n // 处理未授权\n if (response.status === 401) {\n debug('github-api', 'Token 验证失败')\n return {\n success: false,\n error: 'Token 无效或已过期',\n statusCode: 401,\n }\n }\n\n // 处理其他错误\n if (!response.ok) {\n const errorData = await response.json() as GitHubApiError\n debug('github-api', '请求失败', errorData)\n return {\n success: false,\n error: errorData.message || `请求失败: ${response.status}`,\n statusCode: response.status,\n }\n }\n\n const data = await response.json() as T\n debug('github-api', '请求成功')\n return { success: true, data }\n } catch (err) {\n debug('github-api', '网络请求异常', { error: err instanceof Error ? err.message : String(err) })\n return {\n success: false,\n error: err instanceof Error ? err.message : '网络请求失败',\n }\n }\n}\n\n/**\n * 验证 Token 并获取用户信息\n */\nexport async function validateToken(token: string): Promise<GitHubApiResponse<GitHubUser>> {\n return githubFetch<GitHubUser>('/user', token)\n}\n\nexport interface CreateRepoOptions {\n name: string\n description?: string\n isPrivate: boolean\n org?: string\n}\n\n/**\n * 创建 GitHub 仓库\n */\nexport async function createRepository(\n token: string,\n options: CreateRepoOptions\n): Promise<GitHubApiResponse<GitHubRepoResponse>> {\n const endpoint = options.org\n ? `/orgs/${options.org}/repos`\n : '/user/repos'\n\n const body = {\n name: options.name,\n description: options.description || `Created with spec-go`,\n private: options.isPrivate,\n auto_init: false,\n }\n\n return githubFetch<GitHubRepoResponse>(endpoint, token, {\n method: 'POST',\n body: JSON.stringify(body),\n })\n}\n\n/**\n * 检查仓库是否存在\n */\nexport async function checkRepoExists(\n token: string,\n owner: string,\n repo: string\n): Promise<boolean> {\n const result = await githubFetch<GitHubRepoResponse>(\n `/repos/${owner}/${repo}`,\n token\n )\n return result.success\n}\n","import { execAsync } from './utils.js'\nimport { loadConfig, getConfigPath } from './config.js'\nimport { validateToken, createRepository } from './github-api.js'\nimport { debug } from './debug.js'\nimport { silentLogger } from './types.js'\nimport type { Logger } from './types.js'\n\nexport async function initGit(targetDir: string): Promise<void> {\n debug('git', `初始化 Git 仓库: ${targetDir}`)\n await execAsync('git', ['init'], { cwd: targetDir })\n await execAsync('git', ['add', '-A'], { cwd: targetDir })\n await execAsync('git', ['commit', '-m', 'Initial commit'], { cwd: targetDir })\n debug('git', 'Git 初始化完成')\n}\n\nexport interface CreateGithubRepoResult {\n success: boolean\n repoUrl?: string\n error?: string\n}\n\nexport interface CreateGithubRepoOptions {\n repoName: string\n targetDir: string\n isPublic: boolean\n organization?: string\n logger?: Logger\n}\n\n/**\n * 创建 GitHub 仓库并推送代码\n * @param options 创建选项\n * @returns 仓库 URL 或 null(失败时)\n */\nexport async function createGithubRepo(\n options: CreateGithubRepoOptions\n): Promise<string | null> {\n const { repoName, targetDir, isPublic, organization, logger = silentLogger } = options\n\n debug('git', `创建 GitHub 仓库: ${repoName}, 公开: ${isPublic}`)\n const config = loadConfig()\n\n // 检查 Token 是否配置\n if (!config.github?.token) {\n logger.warn('⚠ 未配置 GitHub Token,跳过仓库创建')\n logger.dim(` 运行 spec-go config --setup-github 配置 Token`)\n logger.dim(` 配置文件路径: ${getConfigPath()}`)\n return null\n }\n\n const token = config.github.token\n const defaultOrg = organization || config.github.defaultOrg\n\n // 验证 Token\n const validateResult = await validateToken(token)\n if (!validateResult.success) {\n logger.warn(`⚠ GitHub Token 无效: ${validateResult.error}`)\n if (validateResult.rateLimitReset) {\n logger.dim(` Rate limit 将在 ${validateResult.rateLimitReset.toLocaleString()} 重置`)\n }\n logger.dim(` 运行 spec-go config --setup-github 重新配置`)\n return null\n }\n\n // 创建仓库\n const createResult = await createRepository(token, {\n name: repoName,\n isPrivate: !isPublic,\n org: defaultOrg\n })\n\n if (!createResult.success) {\n if (createResult.statusCode === 422) {\n logger.warn(`⚠ 仓库 \"${repoName}\" 已存在,请选择其他名称`)\n } else if (createResult.rateLimitReset) {\n logger.warn(`⚠ API 请求次数已达上限`)\n logger.dim(` 将在 ${createResult.rateLimitReset.toLocaleString()} 重置`)\n } else {\n logger.warn(`⚠ 创建仓库失败: ${createResult.error}`)\n }\n return null\n }\n\n const repo = createResult.data\n\n // 添加远程仓库并推送\n const remoteResult = await execAsync(\n 'git',\n ['remote', 'add', 'origin', repo.clone_url],\n { cwd: targetDir }\n )\n\n if (remoteResult.code !== 0) {\n // remote 可能已存在,尝试更新\n await execAsync(\n 'git',\n ['remote', 'set-url', 'origin', repo.clone_url],\n { cwd: targetDir }\n )\n }\n\n // 推送到远程\n const pushResult = await execAsync(\n 'git',\n ['push', '-u', 'origin', 'main'],\n { cwd: targetDir }\n )\n\n if (pushResult.code !== 0) {\n // 尝试推送 master 分支\n const pushMaster = await execAsync(\n 'git',\n ['push', '-u', 'origin', 'master'],\n { cwd: targetDir }\n )\n if (pushMaster.code !== 0) {\n logger.warn(`⚠ 推送失败: ${pushResult.stderr || pushMaster.stderr}`)\n logger.dim(` 仓库已创建: ${repo.html_url}`)\n logger.dim(' 请手动推送代码')\n return repo.html_url\n }\n }\n\n return repo.html_url\n}\n\n/**\n * 仅创建 GitHub 仓库(不推送代码)- 用于 MCP\n */\nexport async function createGithubRepoOnly(\n repoName: string,\n isPublic: boolean,\n organization?: string\n): Promise<CreateGithubRepoResult> {\n const config = loadConfig()\n\n if (!config.github?.token) {\n return {\n success: false,\n error: '未配置 GitHub Token,请运行 spec-go config --setup-github 配置'\n }\n }\n\n const token = config.github.token\n const defaultOrg = organization || config.github.defaultOrg\n\n const validateResult = await validateToken(token)\n if (!validateResult.success) {\n return {\n success: false,\n error: `GitHub Token 无效: ${validateResult.error}`\n }\n }\n\n const createResult = await createRepository(token, {\n name: repoName,\n isPrivate: !isPublic,\n org: defaultOrg\n })\n\n if (!createResult.success) {\n if (createResult.statusCode === 422) {\n return { success: false, error: `仓库 \"${repoName}\" 已存在` }\n }\n return { success: false, error: createResult.error }\n }\n\n return {\n success: true,\n repoUrl: createResult.data.html_url\n }\n}\n","import path from 'node:path'\nimport { execAsync } from './utils.js'\nimport { silentLogger } from './types.js'\nimport type { PostInitCommand, TemplateConfig, Logger } from './types.js'\n\nexport interface RunPostInitOptions {\n logger?: Logger\n}\n\nexport async function runPostInit(\n targetDir: string,\n commands: PostInitCommand[],\n options: RunPostInitOptions = {}\n): Promise<void> {\n const { logger = silentLogger } = options\n\n for (const cmd of commands) {\n logger.dim(` ${cmd.description}...`)\n const [command, ...args] = cmd.command.split(' ')\n const result = await execAsync(command, args, {\n cwd: targetDir,\n stdio: 'pipe'\n })\n\n if (result.code !== 0) {\n logger.warn(`⚠ ${cmd.description} 失败`)\n if (result.stderr) {\n logger.dim(result.stderr.slice(0, 200))\n }\n }\n }\n}\n\nexport async function runWorkspacePostInit(\n targetDir: string,\n config: TemplateConfig,\n options: RunPostInitOptions = {}\n): Promise<void> {\n const { logger = silentLogger } = options\n\n // 先执行根目录的 postInit 命令(如果有)\n if (config.postInit && config.postInit.length > 0) {\n await runPostInit(targetDir, config.postInit, options)\n }\n\n // 再执行各子目录的 postInit 命令\n if (config.workspaces) {\n for (const ws of config.workspaces) {\n if (ws.postInit && ws.postInit.length > 0) {\n const wsDir = path.join(targetDir, ws.name)\n logger.dim(` [${ws.name}]`)\n await runPostInit(wsDir, ws.postInit, options)\n }\n }\n }\n}\n","import { input, confirm } from '@inquirer/prompts'\nimport pc from 'picocolors'\nimport { loadConfig, saveConfig, validateToken } from '../core/index.js'\n\nconst TOKEN_HELP_URL = 'https://github.com/settings/tokens/new?scopes=repo&description=spec-go'\n\n/**\n * 检查是否为用户中断操作(Ctrl+C)\n */\nfunction isUserCancelled(err: unknown): boolean {\n const error = err as Error\n return (\n error.message === 'PROMPT_CANCELLED' ||\n error.name === 'ExitPromptError' ||\n error.message.includes('User force closed')\n )\n}\n\n/**\n * 运行 GitHub Token 配置引导\n */\nexport async function runGitHubSetup(): Promise<boolean> {\n console.log()\n console.log(pc.cyan('配置 GitHub Token'))\n console.log()\n console.log('需要一个具有 repo 权限的 Personal Access Token (Classic) 来创建仓库。')\n console.log()\n console.log(pc.dim('获取步骤:'))\n console.log(pc.dim('1. 访问 GitHub Settings > Developer settings > Personal access tokens'))\n console.log(pc.dim('2. 点击 \"Generate new token (classic)\"'))\n console.log(pc.dim('3. 勾选 \"repo\" 权限'))\n console.log(pc.dim('4. 生成并复制 Token'))\n console.log()\n console.log(pc.dim(`快捷链接: ${TOKEN_HELP_URL}`))\n console.log()\n\n try {\n const token = await input({\n message: '请输入 GitHub Token:',\n validate: (value) => {\n if (!value.trim()) {\n return 'Token 不能为空'\n }\n if (!value.startsWith('ghp_') && !value.startsWith('github_pat_')) {\n return 'Token 格式不正确,应以 ghp_ 或 github_pat_ 开头'\n }\n return true\n }\n })\n\n console.log()\n console.log(pc.dim('正在验证 Token...'))\n\n const result = await validateToken(token.trim())\n\n if (!result.success) {\n console.log(pc.red(`✗ Token 验证失败: ${result.error}`))\n if (result.rateLimitReset) {\n console.log(pc.dim(` Rate limit 将在 ${result.rateLimitReset.toLocaleString()} 重置`))\n }\n return false\n }\n\n const user = result.data\n console.log(pc.green(`✔ Token 有效,已登录为: ${user.login}${user.name ? ` (${user.name})` : ''}`))\n console.log()\n\n // 询问是否设置默认组织\n const setOrg = await confirm({\n message: '是否设置默认组织? (否则仓库将创建在个人账户下)',\n default: false\n })\n\n let defaultOrg: string | undefined\n if (setOrg) {\n defaultOrg = await input({\n message: '默认组织名称:',\n validate: (value) => {\n if (!value.trim()) {\n return '组织名称不能为空'\n }\n return true\n }\n })\n defaultOrg = defaultOrg.trim()\n }\n\n // 保存配置\n const config = loadConfig()\n config.github = {\n token: token.trim(),\n ...(defaultOrg && { defaultOrg })\n }\n saveConfig(config)\n\n console.log()\n console.log(pc.green('✔ GitHub 配置已保存'))\n console.log(pc.dim(' 配置文件已设置为仅当前用户可读'))\n\n return true\n } catch (err) {\n if (isUserCancelled(err)) {\n console.log(pc.yellow('\\n操作已取消'))\n return false\n }\n throw err\n }\n}\n\n/**\n * 显示当前配置\n */\nexport function showConfig(): void {\n const config = loadConfig()\n\n console.log()\n console.log(pc.cyan('当前配置:'))\n console.log()\n\n if (config.defaults) {\n console.log(pc.dim('defaults:'))\n if (config.defaults.github !== undefined) {\n console.log(` github: ${config.defaults.github}`)\n }\n if (config.defaults.public !== undefined) {\n console.log(` public: ${config.defaults.public}`)\n }\n if (config.defaults.template !== undefined) {\n console.log(` template: ${config.defaults.template}`)\n }\n }\n\n if (config.github) {\n console.log(pc.dim('github:'))\n if (config.github.token) {\n const masked = config.github.token.slice(0, 8) + '...' + config.github.token.slice(-4)\n console.log(` token: ${masked}`)\n }\n if (config.github.defaultOrg) {\n console.log(` defaultOrg: ${config.github.defaultOrg}`)\n }\n }\n\n if (!config.defaults && !config.github) {\n console.log(pc.dim('(无配置)'))\n }\n\n console.log()\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { execSync } from 'node:child_process'\nimport pc from 'picocolors'\nimport { ExitCodes } from '../core/index.js'\n\nconst CACHE_PATH = path.join(os.homedir(), '.spec-go-update-check')\nconst CACHE_TTL = 24 * 60 * 60 * 1000 // 24 小时\nconst PACKAGE_NAME = '@lambertkeith/spec-go'\n\ninterface UpdateCache {\n lastCheck: number\n latestVersion: string\n}\n\nfunction readCache(): UpdateCache | null {\n try {\n if (fs.existsSync(CACHE_PATH)) {\n const content = fs.readFileSync(CACHE_PATH, 'utf-8')\n return JSON.parse(content) as UpdateCache\n }\n } catch {\n // 忽略缓存读取错误\n }\n return null\n}\n\nfunction writeCache(cache: UpdateCache): void {\n try {\n fs.writeFileSync(CACHE_PATH, JSON.stringify(cache), 'utf-8')\n } catch {\n // 忽略缓存写入错误\n }\n}\n\nasync function fetchLatestVersion(): Promise<string | null> {\n try {\n const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`)\n if (!response.ok) {\n return null\n }\n const data = (await response.json()) as { version: string }\n return data.version\n } catch {\n // 网络请求失败,静默处理\n return null\n }\n}\n\nfunction compareVersions(current: string, latest: string): number {\n const currentParts = current.split('.').map(Number)\n const latestParts = latest.split('.').map(Number)\n\n for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {\n const c = currentParts[i] || 0\n const l = latestParts[i] || 0\n if (c < l) return -1\n if (c > l) return 1\n }\n return 0\n}\n\nexport async function checkForUpdates(currentVersion: string): Promise<void> {\n const cache = readCache()\n const now = Date.now()\n\n let latestVersion: string | null = null\n\n // 检查缓存是否有效\n if (cache && now - cache.lastCheck < CACHE_TTL) {\n latestVersion = cache.latestVersion\n } else {\n // 缓存过期,重新获取\n latestVersion = await fetchLatestVersion()\n if (latestVersion) {\n writeCache({ lastCheck: now, latestVersion })\n }\n }\n\n // 比较版本并提示\n if (latestVersion && compareVersions(currentVersion, latestVersion) < 0) {\n console.log()\n console.log(\n pc.yellow(` \\u26A0 发现新版本 ${pc.bold(latestVersion)},当前 ${currentVersion}`)\n )\n console.log(pc.cyan(` 运行 ${pc.bold(`npm update -g ${PACKAGE_NAME}`)} 更新`))\n console.log()\n }\n}\n\ntype PackageManager = 'npm' | 'pnpm' | 'yarn'\n\nfunction detectPackageManager(): PackageManager {\n // 检查 spec-go 是通过哪个包管理器安装的\n // 方法:检查全局安装路径中是否包含 pnpm/yarn 特征\n const execPath = process.argv[1] || ''\n\n if (execPath.includes('pnpm')) return 'pnpm'\n if (execPath.includes('yarn')) return 'yarn'\n return 'npm'\n}\n\nfunction getUpdateCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return `pnpm update -g ${PACKAGE_NAME}`\n case 'yarn':\n return `yarn global upgrade ${PACKAGE_NAME}`\n default:\n return `npm update -g ${PACKAGE_NAME}`\n }\n}\n\nexport async function runUpdate(currentVersion: string, checkOnly: boolean): Promise<void> {\n // 1. 强制获取最新版本(跳过缓存)\n const latestVersion = await fetchLatestVersion()\n\n if (!latestVersion) {\n console.log(pc.red('✗ 无法获取最新版本信息'))\n process.exit(ExitCodes.EXTERNAL_ERROR)\n }\n\n // 2. 版本比较\n const comparison = compareVersions(currentVersion, latestVersion)\n\n if (comparison >= 0) {\n console.log(pc.green(`✔ 已是最新版本 (${currentVersion})`))\n return\n }\n\n console.log(pc.cyan(`发现新版本: ${currentVersion} → ${latestVersion}`))\n\n if (checkOnly) {\n console.log(pc.dim(`运行 spec-go update 更新`))\n return\n }\n\n // 3. 检测包管理器并执行更新\n const pm = detectPackageManager()\n const updateCmd = getUpdateCommand(pm)\n\n console.log(pc.dim(`正在执行: ${updateCmd}`))\n\n // 4. 执行更新命令\n try {\n execSync(updateCmd, { stdio: 'inherit' })\n console.log(pc.green(`✔ 更新完成`))\n } catch {\n console.log(pc.red('✗ 更新失败,请手动执行更新命令'))\n process.exit(ExitCodes.EXTERNAL_ERROR)\n }\n}\n","import path from 'node:path'\nimport fs from 'node:fs'\nimport { select } from '@inquirer/prompts'\nimport pc from 'picocolors'\nimport { guideTopics, type GuideTopic } from './guide-content.js'\nimport { getTemplatesDir, getConfigPath } from '../core/index.js'\nimport type { TemplateRegistry } from '../core/index.js'\n\n/**\n * 准备动态数据\n */\nfunction prepareDynamicData() {\n const data: any = {}\n\n // 读取模板列表\n try {\n const templatesDir = getTemplatesDir()\n const registryPath = path.join(templatesDir, 'template.config.json')\n const registry: TemplateRegistry = JSON.parse(\n fs.readFileSync(registryPath, 'utf-8')\n )\n data.templates = registry.templates\n } catch (err) {\n data.templates = []\n }\n\n // 获取配置路径\n try {\n data.configPath = getConfigPath()\n } catch (err) {\n data.configPath = '~/.spec-go.json'\n }\n\n return data\n}\n\n/**\n * 显示交互式主题菜单\n */\nasync function showGuideMenu(data: any): Promise<void> {\n // 按分类组织主题\n const categories = Array.from(new Set(guideTopics.map(t => t.category)))\n\n const choices = categories.flatMap(category => {\n const topicsInCategory = guideTopics.filter(t => t.category === category)\n return [\n { name: pc.cyan(`── ${category} ──`), value: '', disabled: true },\n ...topicsInCategory.map(t => ({\n name: `${t.title} ${pc.dim(`- ${t.description}`)}`,\n value: t.id\n }))\n ]\n })\n\n const topicId = await select({\n message: '选择主题:',\n choices\n })\n\n if (topicId) {\n showTopic(topicId, data)\n }\n}\n\n/**\n * 显示指定主题内容\n */\nfunction showTopic(topicId: string, data: any): void {\n const topic = guideTopics.find(t => t.id === topicId)\n\n if (!topic) {\n console.log(pc.red(`错误: 未找到主题 \"${topicId}\"`))\n console.log(pc.dim(`使用 ${pc.green('spec-go guide --list')} 查看所有可用主题`))\n process.exit(1)\n }\n\n console.log()\n console.log(topic.content(data))\n console.log()\n}\n\n/**\n * 列出所有可用主题\n */\nfunction listTopics(): void {\n const categories = Array.from(new Set(guideTopics.map(t => t.category)))\n\n console.log()\n console.log(pc.cyan('可用主题'))\n console.log()\n\n for (const category of categories) {\n console.log(pc.bold(`${category}:`))\n const topicsInCategory = guideTopics.filter(t => t.category === category)\n for (const topic of topicsInCategory) {\n console.log(` ${pc.green(topic.id.padEnd(16))} ${pc.dim(topic.description)}`)\n }\n console.log()\n }\n\n console.log(pc.dim('使用方式:'))\n console.log(` ${pc.green('spec-go guide <主题ID>')}`)\n console.log()\n}\n\n/**\n * JSON 格式输出\n */\nfunction outputJson(): void {\n const output = {\n topics: guideTopics.map(t => ({\n id: t.id,\n title: t.title,\n description: t.description,\n category: t.category\n }))\n }\n console.log(JSON.stringify(output, null, 2))\n}\n\n/**\n * guide 命令主入口\n */\nexport async function runGuide(\n topic: string | undefined,\n options: { list?: boolean; json?: boolean }\n): Promise<void> {\n const data = prepareDynamicData()\n\n // JSON 输出模式\n if (options.json) {\n outputJson()\n return\n }\n\n // 列表模式\n if (options.list) {\n listTopics()\n return\n }\n\n // 显示指定主题\n if (topic) {\n showTopic(topic, data)\n return\n }\n\n // 交互式菜单\n try {\n await showGuideMenu(data)\n } catch (err) {\n const error = err as Error\n // 用户取消操作\n if (\n error.message === 'PROMPT_CANCELLED' ||\n error.name === 'ExitPromptError' ||\n error.message.includes('User force closed')\n ) {\n console.log(pc.yellow('\\n操作已取消'))\n process.exit(0)\n }\n throw err\n }\n}\n","import pc from 'picocolors'\n\nexport interface GuideTopic {\n id: string\n title: string\n description: string\n category: string\n content: (data?: any) => string\n}\n\nexport const guideTopics: GuideTopic[] = [\n // 入门指南类\n {\n id: 'quickstart',\n title: '快速开始',\n description: '5分钟快速上手 spec-go',\n category: '入门指南',\n content: () => `\n${pc.cyan('快速开始')}\n\n${pc.bold('1. 创建项目')}\n ${pc.green('spec-go my-app')}\n\n 按照交互式提示选择模板和配置选项。\n\n${pc.bold('2. 进入项目目录')}\n ${pc.green('cd my-app')}\n\n${pc.bold('3. 启动开发服务器')}\n ${pc.green('pnpm dev')}\n\n 根据不同模板,启动命令可能有所不同。\n\n${pc.dim('提示:使用')} ${pc.green('spec-go guide templates')} ${pc.dim('查看所有可用模板')}\n${pc.dim('提示:使用')} ${pc.green('spec-go guide examples')} ${pc.dim('查看更多使用示例')}\n`\n },\n\n {\n id: 'templates',\n title: '模板列表',\n description: '查看所有可用的项目模板',\n category: '入门指南',\n content: (data?: { templates?: any[] }) => {\n const templates = data?.templates || []\n const singleTemplates = templates.filter(t => t.category !== 'fullstack')\n const fullstackTemplates = templates.filter(t => t.category === 'fullstack')\n\n let output = `\\n${pc.cyan('可用模板')}\\n\\n`\n\n if (singleTemplates.length > 0) {\n output += `${pc.bold('单体项目:')}\\n`\n for (const t of singleTemplates) {\n output += ` ${pc.green(t.name.padEnd(24))} ${pc.dim(t.displayName)}\\n`\n output += ` ${' '.repeat(24)} ${pc.dim(t.description)}\\n`\n }\n output += '\\n'\n }\n\n if (fullstackTemplates.length > 0) {\n output += `${pc.bold('前后端分离:')}\\n`\n for (const t of fullstackTemplates) {\n output += ` ${pc.green(t.name.padEnd(24))} ${pc.dim(t.displayName)}\\n`\n output += ` ${' '.repeat(24)} ${pc.dim(t.description)}\\n`\n }\n output += '\\n'\n }\n\n output += `${pc.dim('使用方式:')}\\n`\n output += ` ${pc.green('spec-go my-app --template <模板名>')}\\n`\n output += ` ${pc.green('spec-go list')} ${pc.dim('# 查看简洁列表')}\\n`\n\n return output\n }\n },\n\n {\n id: 'examples',\n title: '使用示例',\n description: '常见使用场景和最佳实践',\n category: '入门指南',\n content: () => `\n${pc.cyan('使用示例')}\n\n${pc.bold('1. 创建 React 项目')}\n ${pc.green('spec-go my-react-app --template react-ts')}\n\n${pc.bold('2. 创建全栈项目(前后端分离)')}\n ${pc.green('spec-go my-fullstack --template fullstack-react-node')}\n\n${pc.bold('3. 创建 API 项目')}\n ${pc.green('spec-go my-api --template express-ts')}\n\n${pc.bold('4. 非交互模式(CI/CD)')}\n ${pc.green('spec-go my-app --template node-ts --yes --no-install')}\n\n${pc.bold('5. 创建并推送到 GitHub')}\n ${pc.green('spec-go my-app --template react-ts --github --public')}\n\n${pc.bold('6. 跳过 Git 初始化')}\n ${pc.green('spec-go my-app --template vue-ts --no-git')}\n\n${pc.dim('提示:使用')} ${pc.green('spec-go --help')} ${pc.dim('查看所有可用选项')}\n`\n },\n\n // 功能特性类\n {\n id: 'github',\n title: 'GitHub 集成',\n description: 'GitHub 仓库创建和配置',\n category: '功能特性',\n content: (data?: { configPath?: string }) => `\n${pc.cyan('GitHub 集成')}\n\n${pc.bold('配置 GitHub Token')}\n\n${pc.dim('1. 生成 Personal Access Token')}\n 访问:https://github.com/settings/tokens\n 权限:repo (完整仓库访问权限)\n\n${pc.dim('2. 配置 Token')}\n ${pc.green('spec-go config --setup-github')}\n\n${pc.dim('3. 验证配置')}\n ${pc.green('spec-go config --show')}\n\n${pc.bold('使用 GitHub 集成')}\n\n${pc.dim('创建项目并推送到 GitHub:')}\n ${pc.green('spec-go my-app --github')} ${pc.dim('# 创建私有仓库')}\n ${pc.green('spec-go my-app --github --public')} ${pc.dim('# 创建公开仓库')}\n\n${pc.bold('配置文件位置')}\n ${data?.configPath || '~/.spec-go.json'}\n\n${pc.dim('提示:Token 会安全存储在本地配置文件中')}\n`\n },\n\n {\n id: 'mcp',\n title: 'MCP Server',\n description: 'MCP Server 配置和使用',\n category: '功能特性',\n content: () => `\n${pc.cyan('MCP Server 配置')}\n\n${pc.bold('什么是 MCP Server?')}\n\n MCP (Model Context Protocol) Server 允许 Claude Code 直接调用 spec-go 的功能。\n\n${pc.bold('构建 MCP Server')}\n\n ${pc.dim('1. 构建项目')}\n ${pc.green('pnpm build')}\n\n ${pc.dim('2. 配置 Claude Code')}\n 编辑 ${pc.dim('~/.claude/settings.json')}:\n\n {\n \"mcpServers\": {\n \"spec-go\": {\n \"command\": \"node\",\n \"args\": [\"/path/to/create-idp/dist/mcp/index.js\"]\n }\n }\n }\n\n ${pc.dim('3. 重启 Claude Code')}\n\n${pc.bold('可用工具')}\n\n • create_project - 创建新项目\n • list_templates - 列出所有模板\n • validate_project_name - 验证项目名称\n • init_git_repo - 初始化 Git 仓库\n • create_github_repo - 创建 GitHub 仓库\n\n${pc.bold('使用示例')}\n\n 在 Claude Code 中直接说:\n ${pc.dim('\"使用 spec-go 创建一个 React 项目\"')}\n\n${pc.dim('提示:查看项目 README 了解更多 MCP 配置细节')}\n`\n },\n\n // 参考文档类\n {\n id: 'commands',\n title: '命令参考',\n description: '所有命令的完整说明',\n category: '参考文档',\n content: () => `\n${pc.cyan('命令参考')}\n\n${pc.bold('主命令')}\n\n ${pc.green('spec-go [project-name] [options]')}\n 创建新项目\n\n ${pc.dim('选项:')}\n -t, --template <name> 指定模板\n --github 创建 GitHub 仓库\n --public 创建公开仓库(默认私有)\n --no-git 跳过 Git 初始化\n --no-install 跳过依赖安装\n -y, --yes 非交互模式,使用默认值\n --debug 启用调试输出\n\n${pc.bold('子命令')}\n\n ${pc.green('spec-go list [--json]')}\n 列出所有可用模板\n\n ${pc.green('spec-go config')}\n 管理配置\n --setup-github 配置 GitHub Token\n --show 显示当前配置\n --path 显示配置文件路径\n\n ${pc.green('spec-go update [--check]')}\n 检查并更新到最新版本\n --check 仅检查版本,不执行更新\n\n ${pc.green('spec-go guide [topic] [--list] [--json]')}\n 显示使用指南\n --list 列出所有可用主题\n --json JSON 格式输出\n\n${pc.dim('提示:使用')} ${pc.green('spec-go <command> --help')} ${pc.dim('查看命令详细帮助')}\n`\n },\n\n {\n id: 'config',\n title: '配置详解',\n description: '配置文件结构和说明',\n category: '参考文档',\n content: (data?: { configPath?: string }) => `\n${pc.cyan('配置详解')}\n\n${pc.bold('配置文件位置')}\n\n ${data?.configPath || '~/.spec-go.json'}\n\n${pc.bold('配置结构')}\n\n {\n \"github\": {\n \"token\": \"ghp_xxxxxxxxxxxx\" ${pc.dim('// GitHub Personal Access Token')}\n },\n \"defaults\": {\n \"template\": \"node-ts\", ${pc.dim('// 默认模板')}\n \"github\": false, ${pc.dim('// 默认是否创建 GitHub 仓库')}\n \"public\": false ${pc.dim('// 默认仓库可见性')}\n }\n }\n\n${pc.bold('配置管理命令')}\n\n ${pc.green('spec-go config --setup-github')} ${pc.dim('# 配置 GitHub Token')}\n ${pc.green('spec-go config --show')} ${pc.dim('# 显示当前配置')}\n ${pc.green('spec-go config --path')} ${pc.dim('# 显示配置文件路径')}\n\n${pc.bold('安全性说明')}\n\n • Token 存储在本地配置文件中\n • 配置文件权限应设置为仅当前用户可读\n • 不要将配置文件提交到版本控制系统\n\n${pc.dim('提示:使用')} ${pc.green('spec-go guide github')} ${pc.dim('了解如何配置 GitHub 集成')}\n`\n }\n]\n","import pc from 'picocolors'\nimport type { Logger } from '../core/index.js'\n\n/**\n * CLI 专用 Logger 实现\n * 使用 picocolors 进行彩色输出\n */\nexport const consoleLogger: Logger = {\n info(message: string): void {\n console.log(message)\n },\n success(message: string): void {\n console.log(pc.green(message))\n },\n warn(message: string): void {\n console.log(pc.yellow(message))\n },\n error(message: string): void {\n console.log(pc.red(message))\n },\n dim(message: string): void {\n console.log(pc.dim(message))\n },\n}\n","import { createCli } from './cli.js'\nimport { ensureConfigExists, ExitCodes, CliError, isDebugEnabled } from '../core/index.js'\n\nasync function main(): Promise<void> {\n // 确保配置文件存在\n ensureConfigExists()\n\n const program = await createCli()\n await program.parseAsync(process.argv)\n}\n\nmain().catch((err) => {\n // CliError 已经在 prompts.ts 等地方输出了用户友好的错误信息\n // 只在调试模式下输出完整堆栈\n if (err instanceof CliError) {\n if (isDebugEnabled()) {\n console.error(err)\n }\n process.exit(err.exitCode)\n }\n // 其他未知错误始终输出\n console.error(err)\n process.exit(ExitCodes.INTERNAL_ERROR)\n})\n"],"mappings":";;;;;;;;;AAAA,OAAOA,WAAU;AACjB,OAAOC,SAAQ;AACf,SAAS,eAAe;AACxB,OAAOC,SAAQ;;;ACDb,cAAW;;;ACFb,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AACf,SAAS,OAAO,QAAQ,SAAS,iBAAiB;AAClD,OAAO,QAAQ;;;ACoGR,IAAM,eAAuB;AAAA,EAClC,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,SAAS,MAAM;AAAA,EAAC;AAAA,EAChB,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,KAAK,MAAM;AAAA,EAAC;AACd;;;AC7GA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAGf,IAAM,cAAc,KAAK,KAAK,GAAG,QAAQ,GAAG,eAAe;AAE3D,IAAM,iBAA6B;AAAA,EACjC,UAAU;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,YAAY;AAAA,EACd;AACF;AAKO,SAAS,qBAA2B;AACzC,MAAI,CAAC,GAAG,WAAW,WAAW,GAAG;AAC/B,eAAW,cAAc;AAAA,EAC3B;AACF;AAEO,SAAS,aAAyB;AACvC,MAAI;AACF,QAAI,GAAG,WAAW,WAAW,GAAG;AAC9B,YAAM,UAAU,GAAG,aAAa,aAAa,OAAO;AACpD,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO,CAAC;AACV;AAEO,SAAS,WAAW,QAA0B;AACnD,KAAG,cAAc,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,OAAO;AAEtE,KAAG,UAAU,aAAa,GAAK;AACjC;AAEO,SAAS,gBAAwB;AACtC,SAAO;AACT;;;AC1CA,IAAI,eAAe;AAKZ,SAAS,gBAAgB,SAAwB;AACtD,iBAAe;AACjB;AAKO,SAAS,iBAA0B;AACxC,SAAO;AACT;AASO,SAAS,MAAM,UAAkB,SAAiB,MAAsB;AAC7E,MAAI,CAAC,aAAc;AAEnB,QAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AACzC,QAAM,SAAS,UAAU,SAAS,MAAM,QAAQ;AAEhD,MAAI,SAAS,QAAW;AAEtB,UAAM,UAAU,WAAW,IAAI;AAC/B,YAAQ,MAAM,GAAG,MAAM,IAAI,OAAO,IAAI,OAAO;AAAA,EAC/C,OAAO;AACL,YAAQ,MAAM,GAAG,MAAM,IAAI,OAAO,EAAE;AAAA,EACtC;AACF;AAKA,SAAS,WAAW,MAAuB;AACzC,MAAI;AACF,UAAM,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC;AAExC,QAAI,IAAI,SAAS,KAAK;AACpB,aAAO,IAAI,MAAM,GAAG,GAAG,IAAI;AAAA,IAC7B;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO,OAAO,IAAI;AAAA,EACpB;AACF;;;ACrDO,IAAM,YAAY;AAAA;AAAA,EAEvB,SAAS;AAAA;AAAA,EAET,YAAY;AAAA;AAAA,EAEZ,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAAA;AAAA,EAEhB,mBAAmB;AAAA;AAAA,EAEnB,WAAW;AACb;AAOO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAClC,YACE,SACgB,WAAqB,UAAU,gBAC/C;AACA,UAAM,OAAO;AAFG;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;;;ACnCA,OAAOC,WAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,aAAa;AAGtB,IAAM,aAAa,cAAc,YAAY,GAAG;AAChD,IAAM,YAAYC,MAAK,QAAQ,UAAU;AAElC,SAAS,kBAA0B;AACxC,SAAOA,MAAK,QAAQ,WAAW,MAAM,MAAM,WAAW;AACxD;AAEO,SAAS,mBAAmB,MAAuB;AACxD,SAAO,6DAA6D,KAAK,IAAI;AAC/E;AAEO,SAAS,mBAAmB,MAAsB;AACvD,SAAO,KACJ,KAAK,EACL,YAAY,EACZ,QAAQ,QAAQ,GAAG,EACnB,QAAQ,SAAS,EAAE,EACnB,QAAQ,iBAAiB,GAAG;AACjC;AAEO,SAAS,QAAQ,SAA0B;AAChD,QAAMC,MAAK,UAAQ,IAAS;AAC5B,MAAI,CAACA,IAAG,WAAW,OAAO,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,QAAM,QAAQA,IAAG,YAAY,OAAO;AACpC,SAAO,MAAM,WAAW,KAAM,MAAM,WAAW,KAAK,MAAM,CAAC,MAAM;AACnE;AAEO,SAAS,UACd,SACA,MACA,UAAwD,CAAC,GACE;AAC3D,QAAM,QAAQ,6BAAS,OAAO,IAAI,KAAK,KAAK,GAAG,CAAC,IAAI,EAAE,KAAK,QAAQ,IAAI,CAAC;AAExE,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,OAAO,MAAM,SAAS,MAAM;AAAA,MAChC,KAAK,QAAQ;AAAA,MACb,OAAO,QAAQ,UAAU,YAAY,YAAY;AAAA,MACjD,OAAO;AAAA,IACT,CAAC;AAED,QAAI,SAAS;AACb,QAAI,SAAS;AAEb,QAAI,KAAK,QAAQ;AACf,WAAK,OAAO,GAAG,QAAQ,CAAC,SAAS;AAC/B,kBAAU,KAAK,SAAS;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,QAAQ;AACf,WAAK,OAAO,GAAG,QAAQ,CAAC,SAAS;AAC/B,kBAAU,KAAK,SAAS;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,SAAK,GAAG,SAAS,CAAC,SAAS;AACzB,YAAM,QAAQ,qDAAa,QAAQ,CAAC,EAAE;AACtC,cAAQ,EAAE,MAAM,QAAQ,GAAG,QAAQ,OAAO,CAAC;AAAA,IAC7C,CAAC;AAED,SAAK,GAAG,SAAS,CAAC,QAAQ;AACxB,YAAM,QAAQ,6BAAS,IAAI,OAAO,EAAE;AACpC,cAAQ,EAAE,MAAM,GAAG,QAAQ,OAAO,CAAC;AAAA,IACrC,CAAC;AAAA,EACH,CAAC;AACH;;;ACzEA,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AAKf,eAAsB,gBACpB,SACgC;AAChC,QAAM,eAAe,gBAAgB;AACrC,QAAM,eAAeC,MAAK,KAAK,cAAc,sBAAsB;AACnE,QAAM,WAA6B,MAAMC,IAAG,SAAS,YAAY;AAEjE,QAAM,YAAY,+CAAY,QAAQ,WAAW,EAAE;AACnD,QAAM,YAAY,iBAAO,QAAQ,QAAQ,EAAE;AAC3C,QAAM,YAAY,6BAAS,QAAQ,SAAS,EAAE;AAE9C,QAAM,gBAAgB,SAAS,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,QAAQ;AAChF,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,mCAAU,QAAQ,QAAQ,EAAE;AAAA,EAC9C;AAEA,QAAM,cAAcD,MAAK,KAAK,cAAc,cAAc,GAAG;AAC7D,QAAM,qBAAqBA,MAAK,KAAK,aAAa,gBAAgB;AAElE,QAAM,YAAY,6BAAS,WAAW,EAAE;AAExC,MAAI,iBAAwC;AAC5C,MAAI,MAAMC,IAAG,WAAW,kBAAkB,GAAG;AAC3C,qBAAiB,MAAMA,IAAG,SAAS,kBAAkB;AACrD,UAAM,YAAY,4BAAQ,cAAc;AAAA,EAC1C;AAEA,QAAMA,IAAG,UAAU,QAAQ,SAAS;AAEpC,QAAM,QAAQ,MAAMA,IAAG,QAAQ,WAAW;AAC1C,QAAM,YAAY,yCAAW,MAAM,MAAM,EAAE;AAE3C,aAAW,QAAQ,OAAO;AACxB,QAAI,SAAS,kBAAkB;AAC7B;AAAA,IACF;AAEA,UAAM,UAAUD,MAAK,KAAK,aAAa,IAAI;AAC3C,QAAI,eAAe;AAEnB,QAAI,gBAAgB,cAAc,IAAI,GAAG;AACvC,qBAAe,eAAe,YAAY,IAAI;AAC9C,UAAI,iBAAiB,mBAAmB;AACtC,uBAAe,QAAQ;AAAA,MACzB;AAAA,IACF;AAEA,UAAM,WAAWA,MAAK,KAAK,QAAQ,WAAW,YAAY;AAC1D,UAAM,OAAO,MAAMC,IAAG,KAAK,OAAO;AAElC,UAAM,YAAY,iBAAO,IAAI,OAAO,YAAY,EAAE;AAElD,QAAI,KAAK,YAAY,GAAG;AACtB,YAAM,cAAc,SAAS,UAAU,QAAQ,aAAa,cAAc;AAAA,IAC5E,OAAO;AACL,YAAM,SAAS,SAAS,UAAU,QAAQ,aAAa,cAAc;AAAA,IACvE;AAAA,EACF;AAEA,QAAM,YAAY,gCAAO;AAEzB,SAAO;AACT;AAEA,eAAe,cACb,QACA,SACA,aACA,QACe;AACf,QAAMA,IAAG,UAAU,OAAO;AAC1B,QAAM,QAAQ,MAAMA,IAAG,QAAQ,MAAM;AAErC,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAUD,MAAK,KAAK,QAAQ,IAAI;AACtC,QAAI,eAAe;AAEnB,QAAI,QAAQ,cAAc,IAAI,GAAG;AAC/B,qBAAe,OAAO,YAAY,IAAI;AACtC,UAAI,iBAAiB,mBAAmB;AACtC,uBAAe;AAAA,MACjB;AAAA,IACF;AAEA,UAAM,WAAWA,MAAK,KAAK,SAAS,YAAY;AAChD,UAAM,OAAO,MAAMC,IAAG,KAAK,OAAO;AAElC,QAAI,KAAK,YAAY,GAAG;AACtB,YAAM,cAAc,SAAS,UAAU,aAAa,MAAM;AAAA,IAC5D,OAAO;AACL,YAAM,SAAS,SAAS,UAAU,aAAa,MAAM;AAAA,IACvD;AAAA,EACF;AACF;AAEA,eAAe,SACb,SACA,UACA,aACA,QACe;AACf,QAAM,mBAAmB;AAAA,IACvB;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAQ;AAAA,IACzC;AAAA,IAAS;AAAA,IAAU;AAAA,IAAQ;AAAA,IAC3B;AAAA,IAAQ;AAAA,IAAQ;AAAA,EAClB;AAEA,QAAM,MAAMD,MAAK,QAAQ,OAAO,EAAE,YAAY;AAE9C,MAAI,iBAAiB,SAAS,GAAG,GAAG;AAClC,UAAMC,IAAG,KAAK,SAAS,QAAQ;AAC/B;AAAA,EACF;AAEA,MAAI,UAAU,MAAMA,IAAG,SAAS,SAAS,OAAO;AAEhD,YAAU,QAAQ,QAAQ,wBAAwB,WAAW;AAE7D,MAAI,QAAQ,WAAW;AACrB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,SAAS,GAAG;AAC3D,YAAM,cAAc,KAAK,GAAG;AAC5B,YAAM,cAAc,UAAU,oBAAoB,cAAc;AAChE,gBAAU,QAAQ,QAAQ,IAAI,OAAO,YAAY,QAAQ,SAAS,MAAM,GAAG,GAAG,GAAG,WAAW;AAAA,IAC9F;AAAA,EACF;AAEA,QAAMA,IAAG,UAAU,UAAU,SAAS,OAAO;AAC/C;;;AClIA,IAAM,kBAAkB;AAgBxB,eAAe,YACb,UACA,OACA,UAAuB,CAAC,GACO;AAC/B,QAAM,MAAM,GAAG,eAAe,GAAG,QAAQ;AAEzC,QAAM,cAAc,iBAAO,QAAQ,UAAU,KAAK,IAAI,QAAQ,EAAE;AAEhE,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,GAAG;AAAA,MACH,SAAS;AAAA,QACP,UAAU;AAAA,QACV,iBAAiB,UAAU,KAAK;AAAA,QAChC,wBAAwB;AAAA,QACxB,cAAc;AAAA,QACd,GAAG,QAAQ;AAAA,MACb;AAAA,IACF,CAAC;AAED,UAAM,cAAc,6BAAS,SAAS,MAAM,EAAE;AAG9C,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,qBAAqB,SAAS,QAAQ,IAAI,uBAAuB;AACvE,YAAM,iBAAiB,SAAS,QAAQ,IAAI,mBAAmB;AAE/D,YAAM,cAAc,2BAAiB,EAAE,oBAAoB,eAAe,CAAC;AAE3E,UAAI,uBAAuB,OAAO,gBAAgB;AAChD,cAAM,YAAY,IAAI,KAAK,SAAS,cAAc,IAAI,GAAI;AAC1D,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO;AAAA,UACP,YAAY;AAAA,UACZ,gBAAgB;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAGA,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,cAAc,gCAAY;AAChC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,QACP,YAAY;AAAA,MACd;AAAA,IACF;AAGA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,SAAS,KAAK;AACtC,YAAM,cAAc,4BAAQ,SAAS;AACrC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,UAAU,WAAW,6BAAS,SAAS,MAAM;AAAA,QACpD,YAAY,SAAS;AAAA,MACvB;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAM,cAAc,0BAAM;AAC1B,WAAO,EAAE,SAAS,MAAM,KAAK;AAAA,EAC/B,SAAS,KAAK;AACZ,UAAM,cAAc,wCAAU,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AACzF,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,eAAe,QAAQ,IAAI,UAAU;AAAA,IAC9C;AAAA,EACF;AACF;AAKA,eAAsB,cAAc,OAAuD;AACzF,SAAO,YAAwB,SAAS,KAAK;AAC/C;AAYA,eAAsB,iBACpB,OACA,SACgD;AAChD,QAAM,WAAW,QAAQ,MACrB,SAAS,QAAQ,GAAG,WACpB;AAEJ,QAAM,OAAO;AAAA,IACX,MAAM,QAAQ;AAAA,IACd,aAAa,QAAQ,eAAe;AAAA,IACpC,SAAS,QAAQ;AAAA,IACjB,WAAW;AAAA,EACb;AAEA,SAAO,YAAgC,UAAU,OAAO;AAAA,IACtD,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACH;;;AC1HA,eAAsB,QAAQ,WAAkC;AAC9D,QAAM,OAAO,wCAAe,SAAS,EAAE;AACvC,QAAM,UAAU,OAAO,CAAC,MAAM,GAAG,EAAE,KAAK,UAAU,CAAC;AACnD,QAAM,UAAU,OAAO,CAAC,OAAO,IAAI,GAAG,EAAE,KAAK,UAAU,CAAC;AACxD,QAAM,UAAU,OAAO,CAAC,UAAU,MAAM,gBAAgB,GAAG,EAAE,KAAK,UAAU,CAAC;AAC7E,QAAM,OAAO,oCAAW;AAC1B;AAqBA,eAAsB,iBACpB,SACwB;AACxB,QAAM,EAAE,UAAU,WAAW,UAAU,cAAc,SAAS,aAAa,IAAI;AAE/E,QAAM,OAAO,qCAAiB,QAAQ,mBAAS,QAAQ,EAAE;AACzD,QAAM,SAAS,WAAW;AAG1B,MAAI,CAAC,OAAO,QAAQ,OAAO;AACzB,WAAO,KAAK,kFAA2B;AACvC,WAAO,IAAI,iEAA6C;AACxD,WAAO,IAAI,2CAAa,cAAc,CAAC,EAAE;AACzC,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,OAAO,OAAO;AAC5B,QAAM,aAAa,gBAAgB,OAAO,OAAO;AAGjD,QAAM,iBAAiB,MAAM,cAAc,KAAK;AAChD,MAAI,CAAC,eAAe,SAAS;AAC3B,WAAO,KAAK,qCAAsB,eAAe,KAAK,EAAE;AACxD,QAAI,eAAe,gBAAgB;AACjC,aAAO,IAAI,6BAAmB,eAAe,eAAe,eAAe,CAAC,eAAK;AAAA,IACnF;AACA,WAAO,IAAI,uEAAyC;AACpD,WAAO;AAAA,EACT;AAGA,QAAM,eAAe,MAAM,iBAAiB,OAAO;AAAA,IACjD,MAAM;AAAA,IACN,WAAW,CAAC;AAAA,IACZ,KAAK;AAAA,EACP,CAAC;AAED,MAAI,CAAC,aAAa,SAAS;AACzB,QAAI,aAAa,eAAe,KAAK;AACnC,aAAO,KAAK,wBAAS,QAAQ,sEAAe;AAAA,IAC9C,WAAW,aAAa,gBAAgB;AACtC,aAAO,KAAK,6DAAgB;AAC5B,aAAO,IAAI,kBAAQ,aAAa,eAAe,eAAe,CAAC,eAAK;AAAA,IACtE,OAAO;AACL,aAAO,KAAK,gDAAa,aAAa,KAAK,EAAE;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,aAAa;AAG1B,QAAM,eAAe,MAAM;AAAA,IACzB;AAAA,IACA,CAAC,UAAU,OAAO,UAAU,KAAK,SAAS;AAAA,IAC1C,EAAE,KAAK,UAAU;AAAA,EACnB;AAEA,MAAI,aAAa,SAAS,GAAG;AAE3B,UAAM;AAAA,MACJ;AAAA,MACA,CAAC,UAAU,WAAW,UAAU,KAAK,SAAS;AAAA,MAC9C,EAAE,KAAK,UAAU;AAAA,IACnB;AAAA,EACF;AAGA,QAAM,aAAa,MAAM;AAAA,IACvB;AAAA,IACA,CAAC,QAAQ,MAAM,UAAU,MAAM;AAAA,IAC/B,EAAE,KAAK,UAAU;AAAA,EACnB;AAEA,MAAI,WAAW,SAAS,GAAG;AAEzB,UAAM,aAAa,MAAM;AAAA,MACvB;AAAA,MACA,CAAC,QAAQ,MAAM,UAAU,QAAQ;AAAA,MACjC,EAAE,KAAK,UAAU;AAAA,IACnB;AACA,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO,KAAK,oCAAW,WAAW,UAAU,WAAW,MAAM,EAAE;AAC/D,aAAO,IAAI,qCAAY,KAAK,QAAQ,EAAE;AACtC,aAAO,IAAI,8CAAW;AACtB,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AAEA,SAAO,KAAK;AACd;;;AC5HA,OAAOC,WAAU;AASjB,eAAsB,YACpB,WACA,UACA,UAA8B,CAAC,GAChB;AACf,QAAM,EAAE,SAAS,aAAa,IAAI;AAElC,aAAW,OAAO,UAAU;AAC1B,WAAO,IAAI,KAAK,IAAI,WAAW,KAAK;AACpC,UAAM,CAAC,SAAS,GAAG,IAAI,IAAI,IAAI,QAAQ,MAAM,GAAG;AAChD,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAAA,MAC5C,KAAK;AAAA,MACL,OAAO;AAAA,IACT,CAAC;AAED,QAAI,OAAO,SAAS,GAAG;AACrB,aAAO,KAAK,UAAK,IAAI,WAAW,eAAK;AACrC,UAAI,OAAO,QAAQ;AACjB,eAAO,IAAI,OAAO,OAAO,MAAM,GAAG,GAAG,CAAC;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,qBACpB,WACA,QACA,UAA8B,CAAC,GAChB;AACf,QAAM,EAAE,SAAS,aAAa,IAAI;AAGlC,MAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AACjD,UAAM,YAAY,WAAW,OAAO,UAAU,OAAO;AAAA,EACvD;AAGA,MAAI,OAAO,YAAY;AACrB,eAAW,MAAM,OAAO,YAAY;AAClC,UAAI,GAAG,YAAY,GAAG,SAAS,SAAS,GAAG;AACzC,cAAM,QAAQC,MAAK,KAAK,WAAW,GAAG,IAAI;AAC1C,eAAO,IAAI,MAAM,GAAG,IAAI,GAAG;AAC3B,cAAM,YAAY,OAAO,GAAG,UAAU,OAAO;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AACF;;;ATvCA,IAAM,mBAAmB;AAEzB,eAAsB,WACpB,gBACA,SACA,aAAyB,CAAC,GAC1B,cAAuB,MACE;AACzB,QAAM,WAAW,WAAW,YAAY,CAAC;AACzC,QAAM,eAAe,gBAAgB;AACrC,QAAM,eAAeC,MAAK,KAAK,cAAc,sBAAsB;AACnE,QAAM,WAA6B,KAAK;AAAA,IACtCC,IAAG,aAAa,cAAc,OAAO;AAAA,EACvC;AAEA,QAAM,WAAW,6BAAS,WAAW,EAAE;AACvC,QAAM,WAAW,oBAAU,EAAE,gBAAgB,QAAQ,CAAC;AAEtD,MAAI,cAAc;AAGlB,MAAI,CAAC,aAAa;AAChB,QAAI,CAAC,aAAa;AAEhB,cAAQ,IAAI,GAAG,IAAI,oGAAoB,CAAC;AACxC,YAAM,IAAI,SAAS,wFAAkB,UAAU,UAAU;AAAA,IAC3D;AACA,kBAAc,MAAM,MAAM;AAAA,MACxB,SAAS;AAAA,MACT,SAAS;AAAA,MACT,UAAU,CAAC,UAAU;AACnB,YAAI,CAAC,MAAM,KAAK,GAAG;AACjB,iBAAO;AAAA,QACT;AACA,YAAI,CAAC,mBAAmB,mBAAmB,KAAK,CAAC,GAAG;AAClD,iBAAO;AAAA,QACT;AACA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,YAAY,mBAAmB,WAAW;AAChD,QAAM,YAAYD,MAAK,QAAQ,QAAQ,IAAI,GAAG,SAAS;AAGvD,MAAIC,IAAG,WAAW,SAAS,KAAK,CAAC,QAAQ,SAAS,GAAG;AACnD,QAAI,CAAC,aAAa;AAEhB,cAAQ,IAAI,GAAG,OAAO,2CAAa,SAAS,gEAAc,CAAC;AAAA,IAC7D,OAAO;AACL,YAAM,YAAY,MAAM,QAAQ;AAAA,QAC9B,SAAS,6BAAS,SAAS;AAAA,QAC3B,SAAS;AAAA,MACX,CAAC;AACD,UAAI,CAAC,WAAW;AACd,cAAM,QAAQ,IAAI,MAAM,kBAAkB;AAC1C,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,MAAI,WAAW,QAAQ;AACvB,MAAI,CAAC,UAAU;AACb,QAAI,CAAC,aAAa;AAEhB,iBAAW,SAAS,YAAY;AAChC,cAAQ,IAAI,GAAG,IAAI,yCAAW,QAAQ,EAAE,CAAC;AAAA,IAC3C,OAAO;AAEL,YAAM,kBAAkB,SAAS;AAGjC,YAAM,kBAAkB,SAAS,UAAU,OAAO,OAAK,EAAE,aAAa,WAAW;AACjF,YAAM,qBAAqB,SAAS,UAAU,OAAO,OAAK,EAAE,aAAa,WAAW;AAEpF,YAAM,kBAAsE,CAAC;AAG7E,sBAAgB,KAAK,IAAI,UAAU,oDAAY,CAAC;AAChD,iBAAW,KAAK,iBAAiB;AAC/B,wBAAgB,KAAK;AAAA,UACnB,MAAM,GAAG,EAAE,WAAW,IAAI,GAAG,IAAI,KAAK,EAAE,WAAW,EAAE,CAAC;AAAA,UACtD,OAAO,EAAE;AAAA,QACX,CAAC;AAAA,MACH;AAGA,UAAI,mBAAmB,SAAS,GAAG;AACjC,wBAAgB,KAAK,IAAI,UAAU,0DAAa,CAAC;AACjD,mBAAW,KAAK,oBAAoB;AAClC,0BAAgB,KAAK;AAAA,YACnB,MAAM,GAAG,EAAE,WAAW,IAAI,GAAG,IAAI,KAAK,EAAE,WAAW,EAAE,CAAC;AAAA,YACtD,OAAO,EAAE;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AAEA,iBAAW,MAAM,OAAO;AAAA,QACtB,SAAS;AAAA,QACT,SAAS;AAAA,QACT,SAAS,mBAAmB,SAAS,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,eAAe,IACjF,kBACA;AAAA,MACN,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,QAAQ,SAAS,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AAChE,MAAI,CAAC,OAAO;AACV,YAAQ,IAAI,GAAG,IAAI,iDAAc,QAAQ,GAAG,CAAC;AAC7C,YAAQ,IAAI,GAAG,IAAI,6BAAS,SAAS,UAAU,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;AAC/E,UAAM,IAAI,SAAS,mCAAU,QAAQ,KAAK,UAAU,UAAU;AAAA,EAChE;AAGA,MAAIC,WAAU,QAAQ,QAAQ;AAC9B,MAAI,QAAQ,QAAQ,UAAa,aAAa;AAC5C,IAAAA,WAAU,MAAM,QAAQ;AAAA,MACtB,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAGA,MAAI,eAAe,QAAQ,UAAU;AACrC,MAAIA,YAAW,QAAQ,WAAW,UAAa,aAAa;AAC1D,mBAAe,MAAM,QAAQ;AAAA,MAC3B,SAAS;AAAA,MACT,SAAS,SAAS,UAAU;AAAA,IAC9B,CAAC;AAAA,EACH;AAGA,MAAI,WAAW,QAAQ,UAAU;AACjC,MAAI,gBAAgB,QAAQ,WAAW,UAAa,aAAa;AAC/D,UAAM,gBAAgB,SAAS,UAAU;AACzC,eAAW,MAAM,OAAO;AAAA,MACtB,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,MAAM,0BAAgB,OAAO,MAAM;AAAA,QACrC,EAAE,MAAM,yBAAe,OAAO,KAAK;AAAA,MACrC;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,QAAM,SAAyB;AAAA,IAC7B,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,SAAAA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,QAAQ,YAAY;AAAA,EACjC;AAEA,QAAM,WAAW,wCAAU,MAAM;AAEjC,SAAO;AACT;;;AUlLA,SAAS,SAAAC,QAAO,WAAAC,gBAAe;AAC/B,OAAOC,SAAQ;AAGf,IAAM,iBAAiB;AAKvB,SAAS,gBAAgB,KAAuB;AAC9C,QAAM,QAAQ;AACd,SACE,MAAM,YAAY,sBAClB,MAAM,SAAS,qBACf,MAAM,QAAQ,SAAS,mBAAmB;AAE9C;AAKA,eAAsB,iBAAmC;AACvD,UAAQ,IAAI;AACZ,UAAQ,IAAIC,IAAG,KAAK,2BAAiB,CAAC;AACtC,UAAQ,IAAI;AACZ,UAAQ,IAAI,mIAAwD;AACpE,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,IAAI,2BAAO,CAAC;AAC3B,UAAQ,IAAIA,IAAG,IAAI,+EAAqE,CAAC;AACzF,UAAQ,IAAIA,IAAG,IAAI,gDAAsC,CAAC;AAC1D,UAAQ,IAAIA,IAAG,IAAI,qCAAiB,CAAC;AACrC,UAAQ,IAAIA,IAAG,IAAI,yCAAgB,CAAC;AACpC,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,IAAI,6BAAS,cAAc,EAAE,CAAC;AAC7C,UAAQ,IAAI;AAEZ,MAAI;AACF,UAAM,QAAQ,MAAMC,OAAM;AAAA,MACxB,SAAS;AAAA,MACT,UAAU,CAAC,UAAU;AACnB,YAAI,CAAC,MAAM,KAAK,GAAG;AACjB,iBAAO;AAAA,QACT;AACA,YAAI,CAAC,MAAM,WAAW,MAAM,KAAK,CAAC,MAAM,WAAW,aAAa,GAAG;AACjE,iBAAO;AAAA,QACT;AACA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,YAAQ,IAAI;AACZ,YAAQ,IAAID,IAAG,IAAI,mCAAe,CAAC;AAEnC,UAAM,SAAS,MAAM,cAAc,MAAM,KAAK,CAAC;AAE/C,QAAI,CAAC,OAAO,SAAS;AACnB,cAAQ,IAAIA,IAAG,IAAI,0CAAiB,OAAO,KAAK,EAAE,CAAC;AACnD,UAAI,OAAO,gBAAgB;AACzB,gBAAQ,IAAIA,IAAG,IAAI,6BAAmB,OAAO,eAAe,eAAe,CAAC,eAAK,CAAC;AAAA,MACpF;AACA,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,OAAO;AACpB,YAAQ,IAAIA,IAAG,MAAM,4DAAoB,KAAK,KAAK,GAAG,KAAK,OAAO,KAAK,KAAK,IAAI,MAAM,EAAE,EAAE,CAAC;AAC3F,YAAQ,IAAI;AAGZ,UAAM,SAAS,MAAME,SAAQ;AAAA,MAC3B,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AAED,QAAI;AACJ,QAAI,QAAQ;AACV,mBAAa,MAAMD,OAAM;AAAA,QACvB,SAAS;AAAA,QACT,UAAU,CAAC,UAAU;AACnB,cAAI,CAAC,MAAM,KAAK,GAAG;AACjB,mBAAO;AAAA,UACT;AACA,iBAAO;AAAA,QACT;AAAA,MACF,CAAC;AACD,mBAAa,WAAW,KAAK;AAAA,IAC/B;AAGA,UAAM,SAAS,WAAW;AAC1B,WAAO,SAAS;AAAA,MACd,OAAO,MAAM,KAAK;AAAA,MAClB,GAAI,cAAc,EAAE,WAAW;AAAA,IACjC;AACA,eAAW,MAAM;AAEjB,YAAQ,IAAI;AACZ,YAAQ,IAAID,IAAG,MAAM,8CAAgB,CAAC;AACtC,YAAQ,IAAIA,IAAG,IAAI,8FAAmB,CAAC;AAEvC,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,QAAI,gBAAgB,GAAG,GAAG;AACxB,cAAQ,IAAIA,IAAG,OAAO,kCAAS,CAAC;AAChC,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAKO,SAAS,aAAmB;AACjC,QAAM,SAAS,WAAW;AAE1B,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,KAAK,2BAAO,CAAC;AAC5B,UAAQ,IAAI;AAEZ,MAAI,OAAO,UAAU;AACnB,YAAQ,IAAIA,IAAG,IAAI,WAAW,CAAC;AAC/B,QAAI,OAAO,SAAS,WAAW,QAAW;AACxC,cAAQ,IAAI,aAAa,OAAO,SAAS,MAAM,EAAE;AAAA,IACnD;AACA,QAAI,OAAO,SAAS,WAAW,QAAW;AACxC,cAAQ,IAAI,aAAa,OAAO,SAAS,MAAM,EAAE;AAAA,IACnD;AACA,QAAI,OAAO,SAAS,aAAa,QAAW;AAC1C,cAAQ,IAAI,eAAe,OAAO,SAAS,QAAQ,EAAE;AAAA,IACvD;AAAA,EACF;AAEA,MAAI,OAAO,QAAQ;AACjB,YAAQ,IAAIA,IAAG,IAAI,SAAS,CAAC;AAC7B,QAAI,OAAO,OAAO,OAAO;AACvB,YAAM,SAAS,OAAO,OAAO,MAAM,MAAM,GAAG,CAAC,IAAI,QAAQ,OAAO,OAAO,MAAM,MAAM,EAAE;AACrF,cAAQ,IAAI,YAAY,MAAM,EAAE;AAAA,IAClC;AACA,QAAI,OAAO,OAAO,YAAY;AAC5B,cAAQ,IAAI,iBAAiB,OAAO,OAAO,UAAU,EAAE;AAAA,IACzD;AAAA,EACF;AAEA,MAAI,CAAC,OAAO,YAAY,CAAC,OAAO,QAAQ;AACtC,YAAQ,IAAIA,IAAG,IAAI,sBAAO,CAAC;AAAA,EAC7B;AAEA,UAAQ,IAAI;AACd;;;ACpJA,OAAOG,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AACf,SAAS,gBAAgB;AACzB,OAAOC,SAAQ;AAGf,IAAM,aAAaC,MAAK,KAAKC,IAAG,QAAQ,GAAG,uBAAuB;AAClE,IAAM,YAAY,KAAK,KAAK,KAAK;AACjC,IAAM,eAAe;AAOrB,SAAS,YAAgC;AACvC,MAAI;AACF,QAAIC,IAAG,WAAW,UAAU,GAAG;AAC7B,YAAM,UAAUA,IAAG,aAAa,YAAY,OAAO;AACnD,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEA,SAAS,WAAW,OAA0B;AAC5C,MAAI;AACF,IAAAA,IAAG,cAAc,YAAY,KAAK,UAAU,KAAK,GAAG,OAAO;AAAA,EAC7D,QAAQ;AAAA,EAER;AACF;AAEA,eAAe,qBAA6C;AAC1D,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,8BAA8B,YAAY,SAAS;AAChF,QAAI,CAAC,SAAS,IAAI;AAChB,aAAO;AAAA,IACT;AACA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,WAAO,KAAK;AAAA,EACd,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,gBAAgB,SAAiB,QAAwB;AAChE,QAAM,eAAe,QAAQ,MAAM,GAAG,EAAE,IAAI,MAAM;AAClD,QAAM,cAAc,OAAO,MAAM,GAAG,EAAE,IAAI,MAAM;AAEhD,WAAS,IAAI,GAAG,IAAI,KAAK,IAAI,aAAa,QAAQ,YAAY,MAAM,GAAG,KAAK;AAC1E,UAAM,IAAI,aAAa,CAAC,KAAK;AAC7B,UAAM,IAAI,YAAY,CAAC,KAAK;AAC5B,QAAI,IAAI,EAAG,QAAO;AAClB,QAAI,IAAI,EAAG,QAAO;AAAA,EACpB;AACA,SAAO;AACT;AAEA,eAAsB,gBAAgB,gBAAuC;AAC3E,QAAM,QAAQ,UAAU;AACxB,QAAM,MAAM,KAAK,IAAI;AAErB,MAAI,gBAA+B;AAGnC,MAAI,SAAS,MAAM,MAAM,YAAY,WAAW;AAC9C,oBAAgB,MAAM;AAAA,EACxB,OAAO;AAEL,oBAAgB,MAAM,mBAAmB;AACzC,QAAI,eAAe;AACjB,iBAAW,EAAE,WAAW,KAAK,cAAc,CAAC;AAAA,IAC9C;AAAA,EACF;AAGA,MAAI,iBAAiB,gBAAgB,gBAAgB,aAAa,IAAI,GAAG;AACvE,YAAQ,IAAI;AACZ,YAAQ;AAAA,MACNC,IAAG,OAAO,2CAAkBA,IAAG,KAAK,aAAa,CAAC,sBAAO,cAAc,EAAE;AAAA,IAC3E;AACA,YAAQ,IAAIA,IAAG,KAAK,oBAAUA,IAAG,KAAK,iBAAiB,YAAY,EAAE,CAAC,eAAK,CAAC;AAC5E,YAAQ,IAAI;AAAA,EACd;AACF;AAIA,SAAS,uBAAuC;AAG9C,QAAM,WAAW,QAAQ,KAAK,CAAC,KAAK;AAEpC,MAAI,SAAS,SAAS,MAAM,EAAG,QAAO;AACtC,MAAI,SAAS,SAAS,MAAM,EAAG,QAAO;AACtC,SAAO;AACT;AAEA,SAAS,iBAAiB,IAA4B;AACpD,UAAQ,IAAI;AAAA,IACV,KAAK;AACH,aAAO,kBAAkB,YAAY;AAAA,IACvC,KAAK;AACH,aAAO,uBAAuB,YAAY;AAAA,IAC5C;AACE,aAAO,iBAAiB,YAAY;AAAA,EACxC;AACF;AAEA,eAAsB,UAAU,gBAAwB,WAAmC;AAEzF,QAAM,gBAAgB,MAAM,mBAAmB;AAE/C,MAAI,CAAC,eAAe;AAClB,YAAQ,IAAIA,IAAG,IAAI,qEAAc,CAAC;AAClC,YAAQ,KAAK,UAAU,cAAc;AAAA,EACvC;AAGA,QAAM,aAAa,gBAAgB,gBAAgB,aAAa;AAEhE,MAAI,cAAc,GAAG;AACnB,YAAQ,IAAIA,IAAG,MAAM,gDAAa,cAAc,GAAG,CAAC;AACpD;AAAA,EACF;AAEA,UAAQ,IAAIA,IAAG,KAAK,mCAAU,cAAc,WAAM,aAAa,EAAE,CAAC;AAElE,MAAI,WAAW;AACb,YAAQ,IAAIA,IAAG,IAAI,0CAAsB,CAAC;AAC1C;AAAA,EACF;AAGA,QAAM,KAAK,qBAAqB;AAChC,QAAM,YAAY,iBAAiB,EAAE;AAErC,UAAQ,IAAIA,IAAG,IAAI,6BAAS,SAAS,EAAE,CAAC;AAGxC,MAAI;AACF,aAAS,WAAW,EAAE,OAAO,UAAU,CAAC;AACxC,YAAQ,IAAIA,IAAG,MAAM,iCAAQ,CAAC;AAAA,EAChC,QAAQ;AACN,YAAQ,IAAIA,IAAG,IAAI,6FAAkB,CAAC;AACtC,YAAQ,KAAK,UAAU,cAAc;AAAA,EACvC;AACF;;;ACxJA,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AACf,SAAS,UAAAC,eAAc;AACvB,OAAOC,SAAQ;;;ACHf,OAAOC,SAAQ;AAUR,IAAM,cAA4B;AAAA;AAAA,EAEvC;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,SAAS,MAAM;AAAA,EACjBA,IAAG,KAAK,0BAAM,CAAC;AAAA;AAAA,EAEfA,IAAG,KAAK,6BAAS,CAAC;AAAA,IAChBA,IAAG,MAAM,gBAAgB,CAAC;AAAA;AAAA;AAAA;AAAA,EAI5BA,IAAG,KAAK,yCAAW,CAAC;AAAA,IAClBA,IAAG,MAAM,WAAW,CAAC;AAAA;AAAA,EAEvBA,IAAG,KAAK,+CAAY,CAAC;AAAA,IACnBA,IAAG,MAAM,UAAU,CAAC;AAAA;AAAA;AAAA;AAAA,EAItBA,IAAG,IAAI,gCAAO,CAAC,IAAIA,IAAG,MAAM,yBAAyB,CAAC,IAAIA,IAAG,IAAI,kDAAU,CAAC;AAAA,EAC5EA,IAAG,IAAI,gCAAO,CAAC,IAAIA,IAAG,MAAM,wBAAwB,CAAC,IAAIA,IAAG,IAAI,kDAAU,CAAC;AAAA;AAAA,EAE3E;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,SAAS,CAAC,SAAiC;AACzC,YAAM,YAAY,MAAM,aAAa,CAAC;AACtC,YAAM,kBAAkB,UAAU,OAAO,OAAK,EAAE,aAAa,WAAW;AACxE,YAAM,qBAAqB,UAAU,OAAO,OAAK,EAAE,aAAa,WAAW;AAE3E,UAAI,SAAS;AAAA,EAAKA,IAAG,KAAK,0BAAM,CAAC;AAAA;AAAA;AAEjC,UAAI,gBAAgB,SAAS,GAAG;AAC9B,kBAAU,GAAGA,IAAG,KAAK,gCAAO,CAAC;AAAA;AAC7B,mBAAW,KAAK,iBAAiB;AAC/B,oBAAU,KAAKA,IAAG,MAAM,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,EAAE,WAAW,CAAC;AAAA;AACnE,oBAAU,KAAK,IAAI,OAAO,EAAE,CAAC,IAAIA,IAAG,IAAI,EAAE,WAAW,CAAC;AAAA;AAAA,QACxD;AACA,kBAAU;AAAA,MACZ;AAEA,UAAI,mBAAmB,SAAS,GAAG;AACjC,kBAAU,GAAGA,IAAG,KAAK,sCAAQ,CAAC;AAAA;AAC9B,mBAAW,KAAK,oBAAoB;AAClC,oBAAU,KAAKA,IAAG,MAAM,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,EAAE,WAAW,CAAC;AAAA;AACnE,oBAAU,KAAK,IAAI,OAAO,EAAE,CAAC,IAAIA,IAAG,IAAI,EAAE,WAAW,CAAC;AAAA;AAAA,QACxD;AACA,kBAAU;AAAA,MACZ;AAEA,gBAAU,GAAGA,IAAG,IAAI,gCAAO,CAAC;AAAA;AAC5B,gBAAU,KAAKA,IAAG,MAAM,gDAAiC,CAAC;AAAA;AAC1D,gBAAU,KAAKA,IAAG,MAAM,cAAc,CAAC,IAAIA,IAAG,IAAI,wCAAU,CAAC;AAAA;AAE7D,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,SAAS,MAAM;AAAA,EACjBA,IAAG,KAAK,0BAAM,CAAC;AAAA;AAAA,EAEfA,IAAG,KAAK,oCAAgB,CAAC;AAAA,IACvBA,IAAG,MAAM,0CAA0C,CAAC;AAAA;AAAA,EAEtDA,IAAG,KAAK,mFAAkB,CAAC;AAAA,IACzBA,IAAG,MAAM,sDAAsD,CAAC;AAAA;AAAA,EAElEA,IAAG,KAAK,kCAAc,CAAC;AAAA,IACrBA,IAAG,MAAM,sCAAsC,CAAC;AAAA;AAAA,EAElDA,IAAG,KAAK,oDAAiB,CAAC;AAAA,IACxBA,IAAG,MAAM,sDAAsD,CAAC;AAAA;AAAA,EAElEA,IAAG,KAAK,gDAAkB,CAAC;AAAA,IACzBA,IAAG,MAAM,sDAAsD,CAAC;AAAA;AAAA,EAElEA,IAAG,KAAK,wCAAe,CAAC;AAAA,IACtBA,IAAG,MAAM,2CAA2C,CAAC;AAAA;AAAA,EAEvDA,IAAG,IAAI,gCAAO,CAAC,IAAIA,IAAG,MAAM,gBAAgB,CAAC,IAAIA,IAAG,IAAI,kDAAU,CAAC;AAAA;AAAA,EAEnE;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,SAAS,CAAC,SAAmC;AAAA,EAC/CA,IAAG,KAAK,qBAAW,CAAC;AAAA;AAAA,EAEpBA,IAAG,KAAK,2BAAiB,CAAC;AAAA;AAAA,EAE1BA,IAAG,IAAI,uCAA6B,CAAC;AAAA;AAAA;AAAA;AAAA,EAIrCA,IAAG,IAAI,uBAAa,CAAC;AAAA,KAClBA,IAAG,MAAM,+BAA+B,CAAC;AAAA;AAAA,EAE5CA,IAAG,IAAI,6BAAS,CAAC;AAAA,KACdA,IAAG,MAAM,uBAAuB,CAAC;AAAA;AAAA,EAEpCA,IAAG,KAAK,kCAAc,CAAC;AAAA;AAAA,EAEvBA,IAAG,IAAI,+DAAkB,CAAC;AAAA,IACxBA,IAAG,MAAM,yBAAyB,CAAC,aAAaA,IAAG,IAAI,wCAAU,CAAC;AAAA,IAClEA,IAAG,MAAM,kCAAkC,CAAC,IAAIA,IAAG,IAAI,wCAAU,CAAC;AAAA;AAAA,EAEpEA,IAAG,KAAK,sCAAQ,CAAC;AAAA,IACf,MAAM,cAAc,iBAAiB;AAAA;AAAA,EAEvCA,IAAG,IAAI,wGAAwB,CAAC;AAAA;AAAA,EAEhC;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,SAAS,MAAM;AAAA,EACjBA,IAAG,KAAK,yBAAe,CAAC;AAAA;AAAA,EAExBA,IAAG,KAAK,qCAAiB,CAAC;AAAA;AAAA;AAAA;AAAA,EAI1BA,IAAG,KAAK,yBAAe,CAAC;AAAA;AAAA,IAEtBA,IAAG,IAAI,6BAAS,CAAC;AAAA,OACdA,IAAG,MAAM,YAAY,CAAC;AAAA;AAAA,IAEzBA,IAAG,IAAI,6BAAmB,CAAC;AAAA,oBACrBA,IAAG,IAAI,yBAAyB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWvCA,IAAG,IAAI,6BAAmB,CAAC;AAAA;AAAA,EAE7BA,IAAG,KAAK,0BAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQfA,IAAG,KAAK,0BAAM,CAAC;AAAA;AAAA;AAAA,IAGbA,IAAG,IAAI,oEAA4B,CAAC;AAAA;AAAA,EAEtCA,IAAG,IAAI,yGAA8B,CAAC;AAAA;AAAA,EAEtC;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,SAAS,MAAM;AAAA,EACjBA,IAAG,KAAK,0BAAM,CAAC;AAAA;AAAA,EAEfA,IAAG,KAAK,oBAAK,CAAC;AAAA;AAAA,IAEZA,IAAG,MAAM,kCAAkC,CAAC;AAAA;AAAA;AAAA,IAG5CA,IAAG,IAAI,oBAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASfA,IAAG,KAAK,oBAAK,CAAC;AAAA;AAAA,IAEZA,IAAG,MAAM,uBAAuB,CAAC;AAAA;AAAA;AAAA,IAGjCA,IAAG,MAAM,gBAAgB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAM1BA,IAAG,MAAM,0BAA0B,CAAC;AAAA;AAAA;AAAA;AAAA,IAIpCA,IAAG,MAAM,yCAAyC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKrDA,IAAG,IAAI,gCAAO,CAAC,IAAIA,IAAG,MAAM,0BAA0B,CAAC,IAAIA,IAAG,IAAI,kDAAU,CAAC;AAAA;AAAA,EAE7E;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,SAAS,CAAC,SAAmC;AAAA,EAC/CA,IAAG,KAAK,0BAAM,CAAC;AAAA;AAAA,EAEfA,IAAG,KAAK,sCAAQ,CAAC;AAAA;AAAA,IAEf,MAAM,cAAc,iBAAiB;AAAA;AAAA,EAEvCA,IAAG,KAAK,0BAAM,CAAC;AAAA;AAAA;AAAA;AAAA,qCAIoBA,IAAG,IAAI,iCAAiC,CAAC;AAAA;AAAA;AAAA,wCAGtCA,IAAG,IAAI,6BAAS,CAAC;AAAA,wCACjBA,IAAG,IAAI,6DAAqB,CAAC;AAAA,wCAC7BA,IAAG,IAAI,+CAAY,CAAC;AAAA;AAAA;AAAA;AAAA,EAI1DA,IAAG,KAAK,sCAAQ,CAAC;AAAA;AAAA,IAEfA,IAAG,MAAM,+BAA+B,CAAC,KAAKA,IAAG,IAAI,6BAAmB,CAAC;AAAA,IACzEA,IAAG,MAAM,uBAAuB,CAAC,aAAaA,IAAG,IAAI,wCAAU,CAAC;AAAA,IAChEA,IAAG,MAAM,uBAAuB,CAAC,aAAaA,IAAG,IAAI,oDAAY,CAAC;AAAA;AAAA,EAEpEA,IAAG,KAAK,gCAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhBA,IAAG,IAAI,gCAAO,CAAC,IAAIA,IAAG,MAAM,sBAAsB,CAAC,IAAIA,IAAG,IAAI,0DAAkB,CAAC;AAAA;AAAA,EAEjF;AACF;;;ADxQA,SAAS,qBAAqB;AAC5B,QAAM,OAAY,CAAC;AAGnB,MAAI;AACF,UAAM,eAAe,gBAAgB;AACrC,UAAM,eAAeC,MAAK,KAAK,cAAc,sBAAsB;AACnE,UAAM,WAA6B,KAAK;AAAA,MACtCC,IAAG,aAAa,cAAc,OAAO;AAAA,IACvC;AACA,SAAK,YAAY,SAAS;AAAA,EAC5B,SAAS,KAAK;AACZ,SAAK,YAAY,CAAC;AAAA,EACpB;AAGA,MAAI;AACF,SAAK,aAAa,cAAc;AAAA,EAClC,SAAS,KAAK;AACZ,SAAK,aAAa;AAAA,EACpB;AAEA,SAAO;AACT;AAKA,eAAe,cAAc,MAA0B;AAErD,QAAM,aAAa,MAAM,KAAK,IAAI,IAAI,YAAY,IAAI,OAAK,EAAE,QAAQ,CAAC,CAAC;AAEvE,QAAM,UAAU,WAAW,QAAQ,cAAY;AAC7C,UAAM,mBAAmB,YAAY,OAAO,OAAK,EAAE,aAAa,QAAQ;AACxE,WAAO;AAAA,MACL,EAAE,MAAMC,IAAG,KAAK,gBAAM,QAAQ,eAAK,GAAG,OAAO,IAAI,UAAU,KAAK;AAAA,MAChE,GAAG,iBAAiB,IAAI,QAAM;AAAA,QAC5B,MAAM,GAAG,EAAE,KAAK,IAAIA,IAAG,IAAI,KAAK,EAAE,WAAW,EAAE,CAAC;AAAA,QAChD,OAAO,EAAE;AAAA,MACX,EAAE;AAAA,IACJ;AAAA,EACF,CAAC;AAED,QAAM,UAAU,MAAMC,QAAO;AAAA,IAC3B,SAAS;AAAA,IACT;AAAA,EACF,CAAC;AAED,MAAI,SAAS;AACX,cAAU,SAAS,IAAI;AAAA,EACzB;AACF;AAKA,SAAS,UAAU,SAAiB,MAAiB;AACnD,QAAM,QAAQ,YAAY,KAAK,OAAK,EAAE,OAAO,OAAO;AAEpD,MAAI,CAAC,OAAO;AACV,YAAQ,IAAID,IAAG,IAAI,iDAAc,OAAO,GAAG,CAAC;AAC5C,YAAQ,IAAIA,IAAG,IAAI,gBAAMA,IAAG,MAAM,sBAAsB,CAAC,mDAAW,CAAC;AACrE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAI,MAAM,QAAQ,IAAI,CAAC;AAC/B,UAAQ,IAAI;AACd;AAKA,SAAS,aAAmB;AAC1B,QAAM,aAAa,MAAM,KAAK,IAAI,IAAI,YAAY,IAAI,OAAK,EAAE,QAAQ,CAAC,CAAC;AAEvE,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,KAAK,0BAAM,CAAC;AAC3B,UAAQ,IAAI;AAEZ,aAAW,YAAY,YAAY;AACjC,YAAQ,IAAIA,IAAG,KAAK,GAAG,QAAQ,GAAG,CAAC;AACnC,UAAM,mBAAmB,YAAY,OAAO,OAAK,EAAE,aAAa,QAAQ;AACxE,eAAW,SAAS,kBAAkB;AACpC,cAAQ,IAAI,KAAKA,IAAG,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,MAAM,WAAW,CAAC,EAAE;AAAA,IAC/E;AACA,YAAQ,IAAI;AAAA,EACd;AAEA,UAAQ,IAAIA,IAAG,IAAI,2BAAO,CAAC;AAC3B,UAAQ,IAAI,KAAKA,IAAG,MAAM,gCAAsB,CAAC,EAAE;AACnD,UAAQ,IAAI;AACd;AAKA,SAAS,aAAmB;AAC1B,QAAM,SAAS;AAAA,IACb,QAAQ,YAAY,IAAI,QAAM;AAAA,MAC5B,IAAI,EAAE;AAAA,MACN,OAAO,EAAE;AAAA,MACT,aAAa,EAAE;AAAA,MACf,UAAU,EAAE;AAAA,IACd,EAAE;AAAA,EACJ;AACA,UAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC7C;AAKA,eAAsB,SACpB,OACA,SACe;AACf,QAAM,OAAO,mBAAmB;AAGhC,MAAI,QAAQ,MAAM;AAChB,eAAW;AACX;AAAA,EACF;AAGA,MAAI,QAAQ,MAAM;AAChB,eAAW;AACX;AAAA,EACF;AAGA,MAAI,OAAO;AACT,cAAU,OAAO,IAAI;AACrB;AAAA,EACF;AAGA,MAAI;AACF,UAAM,cAAc,IAAI;AAAA,EAC1B,SAAS,KAAK;AACZ,UAAM,QAAQ;AAEd,QACE,MAAM,YAAY,sBAClB,MAAM,SAAS,qBACf,MAAM,QAAQ,SAAS,mBAAmB,GAC1C;AACA,cAAQ,IAAIA,IAAG,OAAO,kCAAS,CAAC;AAChC,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM;AAAA,EACR;AACF;;;AEnKA,OAAOE,SAAQ;AAOR,IAAM,gBAAwB;AAAA,EACnC,KAAK,SAAuB;AAC1B,YAAQ,IAAI,OAAO;AAAA,EACrB;AAAA,EACA,QAAQ,SAAuB;AAC7B,YAAQ,IAAIA,IAAG,MAAM,OAAO,CAAC;AAAA,EAC/B;AAAA,EACA,KAAK,SAAuB;AAC1B,YAAQ,IAAIA,IAAG,OAAO,OAAO,CAAC;AAAA,EAChC;AAAA,EACA,MAAM,SAAuB;AAC3B,YAAQ,IAAIA,IAAG,IAAI,OAAO,CAAC;AAAA,EAC7B;AAAA,EACA,IAAI,SAAuB;AACzB,YAAQ,IAAIA,IAAG,IAAI,OAAO,CAAC;AAAA,EAC7B;AACF;;;AhBKA,SAAS,cAAc,SAA8B;AAEnD,MAAI,QAAQ,IAAK,QAAO;AAExB,SAAO,QAAQ,MAAM,UAAU;AACjC;AAEA,eAAsB,YAA8B;AAClD,QAAM,UAAU,IAAI,QAAQ;AAE5B,UACG,KAAK,SAAS,EACd,YAAY,sIAAkC,EAC9C,QAAQ,OAAO,EACf,SAAS,kBAAkB,0BAAM,EACjC,OAAO,6BAA6B,sCAAQ,EAC5C,OAAO,YAAY,oDAAiB,EACpC,OAAO,YAAY,iEAAe,EAClC,OAAO,YAAY,qCAAY,EAC/B,OAAO,gBAAgB,sCAAQ,EAC/B,OAAO,aAAa,gIAAuB,EAC3C,OAAO,WAAW,sCAAQ,EAC1B,OAAO,OAAO,aAAiC,YAAwB;AAEtE,QAAI,QAAQ,OAAO;AACjB,sBAAgB,IAAI;AAAA,IACtB;AAEA,YAAQ,IAAI;AACZ,YAAQ,IAAI,KAAKC,IAAG,KAAK,SAAS,CAAC,IAAIA,IAAG,IAAI,IAAI,OAAO,EAAE,CAAC,EAAE;AAC9D,YAAQ,IAAI;AAGZ,oBAAgB,OAAO,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAGvC,UAAM,aAAa,WAAW;AAG9B,UAAM,cAAc,cAAc,OAAO;AAEzC,QAAI;AACF,YAAM,iBAAiB,MAAM,WAAW,aAAa,SAAS,YAAY,WAAW;AACrF,YAAM,eAAe,cAAc;AAAA,IACrC,SAAS,KAAK;AACZ,YAAM,QAAQ;AAGd,UACE,MAAM,YAAY,sBAClB,MAAM,SAAS,qBACf,MAAM,QAAQ,SAAS,mBAAmB,GAC1C;AACA,gBAAQ,IAAIA,IAAG,OAAO,kCAAS,CAAC;AAChC,gBAAQ,KAAK,UAAU,OAAO;AAAA,MAChC;AACA,YAAM;AAAA,IACR;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,MAAM,EACd,YAAY,kDAAU,EACtB,OAAO,UAAU,sCAAa,EAC9B,OAAO,CAAC,YAAgC;AACvC,UAAM,eAAe,gBAAgB;AACrC,UAAM,eAAeC,MAAK,KAAK,cAAc,sBAAsB;AACnE,UAAM,WAA6B,KAAK;AAAA,MACtCC,IAAG,aAAa,cAAc,OAAO;AAAA,IACvC;AAGA,QAAI,QAAQ,MAAM;AAChB,YAAM,SAAS;AAAA,QACb,WAAW,SAAS,UAAU,IAAI,QAAM;AAAA,UACtC,MAAM,EAAE;AAAA,UACR,aAAa,EAAE;AAAA,UACf,aAAa,EAAE;AAAA,UACf,UAAU,EAAE,YAAY;AAAA,QAC1B,EAAE;AAAA,MACJ;AACA,cAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,IACF;AAGA,UAAM,kBAAkB,SAAS,UAAU,OAAO,OAAK,EAAE,aAAa,WAAW;AACjF,UAAM,qBAAqB,SAAS,UAAU,OAAO,OAAK,EAAE,aAAa,WAAW;AAEpF,YAAQ,IAAI;AACZ,YAAQ,IAAIF,IAAG,KAAK,6BAAS,CAAC;AAC9B,eAAW,KAAK,iBAAiB;AAC/B,cAAQ,IAAI,OAAOA,IAAG,MAAM,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,EAAE,WAAW,CAAC,EAAE;AAAA,IAC3E;AAEA,QAAI,mBAAmB,SAAS,GAAG;AACjC,cAAQ,IAAI;AACZ,cAAQ,IAAIA,IAAG,KAAK,mCAAU,CAAC;AAC/B,iBAAW,KAAK,oBAAoB;AAClC,gBAAQ,IAAI,OAAOA,IAAG,MAAM,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,EAAE,WAAW,CAAC,EAAE;AAAA,MAC3E;AAAA,IACF;AACA,YAAQ,IAAI;AAAA,EACd,CAAC;AAGH,UACG,QAAQ,QAAQ,EAChB,YAAY,0BAAM,EAClB,OAAO,kBAAkB,2BAAiB,EAC1C,OAAO,UAAU,sCAAQ,EACzB,OAAO,UAAU,kDAAU,EAC3B,OAAO,OAAO,YAAuE;AACpF,QAAI,QAAQ,aAAa;AACvB,YAAM,UAAU,MAAM,eAAe;AACrC,cAAQ,KAAK,UAAU,UAAU,UAAU,UAAU,UAAU;AAAA,IACjE,WAAW,QAAQ,MAAM;AACvB,iBAAW;AAAA,IACb,WAAW,QAAQ,MAAM;AACvB,cAAQ,IAAI,cAAc,CAAC;AAAA,IAC7B,OAAO;AAEL,cAAQ,IAAI;AACZ,cAAQ,IAAIA,IAAG,KAAK,uCAAS,CAAC;AAC9B,cAAQ,IAAI;AACZ,cAAQ,IAAI,KAAKA,IAAG,IAAI,+BAA+B,CAAC,6BAAmB;AAC3E,cAAQ,IAAI,KAAKA,IAAG,IAAI,uBAAuB,CAAC,gDAAkB;AAClE,cAAQ,IAAI,KAAKA,IAAG,IAAI,uBAAuB,CAAC,4DAAoB;AACpE,cAAQ,IAAI;AAAA,IACd;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,QAAQ,EAChB,YAAY,8DAAY,EACxB,OAAO,WAAW,oEAAa,EAC/B,OAAO,OAAO,YAAiC;AAC9C,UAAM,UAAU,SAAS,QAAQ,SAAS,KAAK;AAAA,EACjD,CAAC;AAGH,UACG,QAAQ,eAAe,EACvB,YAAY,oEAAa,EACzB,OAAO,UAAU,kDAAU,EAC3B,OAAO,UAAU,sCAAa,EAC9B,OAAO,OAAO,OAA2B,YAAgD;AACxF,UAAM,SAAS,OAAO,OAAO;AAAA,EAC/B,CAAC;AAEH,SAAO;AACT;AAEA,eAAe,eAAe,SAAwC;AACpE,QAAM,iBAAiB,MAAM,gBAAgB,OAAO;AACpD,UAAQ,IAAIA,IAAG,MAAM,mDAAW,CAAC;AAEjC,MAAI,CAAC,QAAQ,aAAa,gBAAgB;AACxC,QAAI,eAAe,SAAS,aAAa;AACvC,YAAM,qBAAqB,QAAQ,WAAW,gBAAgB,EAAE,QAAQ,cAAc,CAAC;AACvF,cAAQ,IAAIA,IAAG,MAAM,6CAAU,CAAC;AAAA,IAClC,WAAW,eAAe,UAAU;AAClC,YAAM,YAAY,QAAQ,WAAW,eAAe,UAAU,EAAE,QAAQ,cAAc,CAAC;AACvF,cAAQ,IAAIA,IAAG,MAAM,6CAAU,CAAC;AAAA,IAClC;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS;AACnB,UAAM,QAAQ,QAAQ,SAAS;AAC/B,YAAQ,IAAIA,IAAG,MAAM,iDAAc,CAAC;AAAA,EACtC;AAEA,MAAI,QAAQ,cAAc;AACxB,UAAM,UAAU,MAAM,iBAAiB;AAAA,MACrC,UAAU,QAAQ;AAAA,MAClB,WAAW,QAAQ;AAAA,MACnB,UAAU,QAAQ;AAAA,MAClB,QAAQ;AAAA,IACV,CAAC;AACD,QAAI,SAAS;AACX,cAAQ,IAAIA,IAAG,MAAM,iDAAmBA,IAAG,KAAK,OAAO,CAAC,EAAE,CAAC;AAAA,IAC7D;AAAA,EACF;AAEA,UAAQ,IAAI;AACZ,QAAM,KAAK,gBAAgB,kBAAkB;AAC7C,QAAM,QAAQ,QAAQ,cAAc,QAAQ,IAAI,IAC5C,MAAM,QAAQ,WAAW,SACzB;AAGJ,MAAI,gBAAgB,SAAS,aAAa;AACxC,QAAI,OAAO,QAAQ;AACjB,cAAQ,IAAIA,IAAG,IAAI,KAAK,KAAK,UAAU,CAAC;AAAA,IAC1C,OAAO;AACL,cAAQ,IAAIA,IAAG,IAAI,KAAK,KAAK,UAAU,CAAC;AAAA,IAC1C;AAAA,EACF,WAAW,OAAO,SAAS;AACzB,YAAQ,IAAIA,IAAG,IAAI,KAAK,KAAK,wBAAwB,CAAC;AAAA,EACxD,WAAW,OAAO,UAAU;AAC1B,YAAQ,IAAIA,IAAG,IAAI,KAAK,KAAK,mBAAmB,CAAC;AAAA,EACnD,OAAO;AACL,YAAQ,IAAIA,IAAG,IAAI,KAAK,KAAK,GAAG,EAAE,MAAM,CAAC;AAAA,EAC3C;AACA,UAAQ,IAAI;AACd;;;AiBxOA,eAAe,OAAsB;AAEnC,qBAAmB;AAEnB,QAAM,UAAU,MAAM,UAAU;AAChC,QAAM,QAAQ,WAAW,QAAQ,IAAI;AACvC;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AAGpB,MAAI,eAAe,UAAU;AAC3B,QAAI,eAAe,GAAG;AACpB,cAAQ,MAAM,GAAG;AAAA,IACnB;AACA,YAAQ,KAAK,IAAI,QAAQ;AAAA,EAC3B;AAEA,UAAQ,MAAM,GAAG;AACjB,UAAQ,KAAK,UAAU,cAAc;AACvC,CAAC;","names":["path","fs","pc","path","fs","path","path","fs","path","fs","path","fs","path","path","path","fs","initGit","input","confirm","pc","pc","input","confirm","fs","path","os","pc","path","os","fs","pc","path","fs","select","pc","pc","path","fs","pc","select","pc","pc","path","fs"]}
|