yg-team-cli 2.3.0 → 2.3.2
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.js +346 -134
- package/dist/cli.js.map +1 -1
- package/dist/index.js +338 -133
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -264,6 +264,12 @@ var init_utils = __esm({
|
|
|
264
264
|
static async writeJson(file, data) {
|
|
265
265
|
await fs.writeJson(file, data, { spaces: 2 });
|
|
266
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* 获取路径的目录名 (ESM 兼容)
|
|
269
|
+
*/
|
|
270
|
+
static getDirName(url) {
|
|
271
|
+
return path2.dirname(new URL(url).pathname);
|
|
272
|
+
}
|
|
267
273
|
};
|
|
268
274
|
StringUtils2 = class {
|
|
269
275
|
/**
|
|
@@ -310,6 +316,12 @@ var init_utils = __esm({
|
|
|
310
316
|
static slugify(str) {
|
|
311
317
|
return str.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
312
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* 验证项目名称
|
|
321
|
+
*/
|
|
322
|
+
static validateProjectName(name) {
|
|
323
|
+
return /^[a-z0-9-]+$/.test(name);
|
|
324
|
+
}
|
|
313
325
|
};
|
|
314
326
|
DateUtils = class _DateUtils {
|
|
315
327
|
/**
|
|
@@ -883,13 +895,141 @@ var init_template_version = __esm({
|
|
|
883
895
|
}
|
|
884
896
|
});
|
|
885
897
|
|
|
898
|
+
// src/lib/module-registry.ts
|
|
899
|
+
import path5 from "path";
|
|
900
|
+
import fs3 from "fs-extra";
|
|
901
|
+
var ModuleManager;
|
|
902
|
+
var init_module_registry = __esm({
|
|
903
|
+
"src/lib/module-registry.ts"() {
|
|
904
|
+
"use strict";
|
|
905
|
+
init_esm_shims();
|
|
906
|
+
init_utils();
|
|
907
|
+
ModuleManager = class {
|
|
908
|
+
static MODULES = [
|
|
909
|
+
{
|
|
910
|
+
id: "acl",
|
|
911
|
+
name: "ACL (Access Control List)",
|
|
912
|
+
description: "\u57FA\u4E8E\u89D2\u8272\u7684\u8BBF\u95EE\u63A7\u5236\u6A21\u5757\uFF08\u672C\u5730\u6A21\u677F\u7248\uFF09",
|
|
913
|
+
type: "local",
|
|
914
|
+
specs: ["acl/spec.md"],
|
|
915
|
+
backendFragments: [
|
|
916
|
+
{
|
|
917
|
+
source: "acl/backend/AclResultCode.java",
|
|
918
|
+
target: "common/enums/AclResultCode.java"
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
source: "acl/backend/RequiredPermission.java",
|
|
922
|
+
target: "common/annotation/RequiredPermission.java"
|
|
923
|
+
}
|
|
924
|
+
]
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
id: "permission-remote",
|
|
928
|
+
name: "\u6743\u9650\u7BA1\u7406 (\u8FDC\u7A0B MCP \u7248)",
|
|
929
|
+
description: "\u4ECE api-metadata \u5B9E\u65F6\u83B7\u53D6\u6700\u65B0\u6743\u9650\u63A5\u53E3\u5B9A\u4E49\u5E76\u751F\u6210\u4EE3\u7801",
|
|
930
|
+
type: "remote",
|
|
931
|
+
mcpServer: "api-metadata",
|
|
932
|
+
specs: ["permission-remote/spec.md"]
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
id: "audit-log",
|
|
936
|
+
name: "\u5BA1\u8BA1\u65E5\u5FD7 (Audit Log)",
|
|
937
|
+
description: "\u8BB0\u5F55\u7528\u6237\u64CD\u4F5C\u65E5\u5FD7\uFF0C\u652F\u6301 AOP \u81EA\u52A8\u62E6\u622A\u548C\u5F02\u6B65\u5B58\u50A8",
|
|
938
|
+
type: "local",
|
|
939
|
+
specs: ["audit-log/spec.md"]
|
|
940
|
+
}
|
|
941
|
+
];
|
|
942
|
+
/**
|
|
943
|
+
* 获取所有可用模块
|
|
944
|
+
*/
|
|
945
|
+
static getAvailableModules() {
|
|
946
|
+
return [...this.MODULES];
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* 根据 ID 获取模块
|
|
950
|
+
*/
|
|
951
|
+
static getModuleById(id) {
|
|
952
|
+
return this.MODULES.find((m) => m.id === id);
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* 注入模块到项目
|
|
956
|
+
*/
|
|
957
|
+
static async injectModule(projectPath, moduleId, templatesDir) {
|
|
958
|
+
const module = this.getModuleById(moduleId);
|
|
959
|
+
if (!module) return;
|
|
960
|
+
for (const specRelPath of module.specs) {
|
|
961
|
+
const sourcePath = path5.join(templatesDir, "modules", specRelPath);
|
|
962
|
+
const targetPath = path5.join(projectPath, "docs/specs", path5.basename(specRelPath));
|
|
963
|
+
if (await FileUtils.exists(sourcePath)) {
|
|
964
|
+
await FileUtils.copy(sourcePath, targetPath);
|
|
965
|
+
} else if (module.type === "remote") {
|
|
966
|
+
await this.generateRemoteSpecPlaceholder(targetPath, module);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
if (module.type === "local" && module.backendFragments) {
|
|
970
|
+
const backendBase = path5.join(projectPath, "backend/src/main/java");
|
|
971
|
+
const basePackagePath = await this.findBasePackage(backendBase);
|
|
972
|
+
if (basePackagePath) {
|
|
973
|
+
for (const fragment of module.backendFragments) {
|
|
974
|
+
const sourcePath = path5.join(templatesDir, "modules", fragment.source);
|
|
975
|
+
const targetPath = path5.join(basePackagePath, fragment.target);
|
|
976
|
+
if (await FileUtils.exists(sourcePath)) {
|
|
977
|
+
await FileUtils.ensureDir(path5.dirname(targetPath));
|
|
978
|
+
await FileUtils.copy(sourcePath, targetPath);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
} else if (module.type === "remote") {
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* 生成远程模块的 Spec 占位符
|
|
987
|
+
*/
|
|
988
|
+
static async generateRemoteSpecPlaceholder(targetPath, module) {
|
|
989
|
+
const content = `# ${module.name} (Remote)
|
|
990
|
+
|
|
991
|
+
## \u529F\u80FD\u6982\u8FF0
|
|
992
|
+
\u8BE5\u6A21\u5757\u901A\u8FC7\u8FDC\u7A0B MCP \u670D\u52A1 \`${module.mcpServer}\` \u83B7\u53D6\u5B9E\u65F6\u5143\u6570\u636E\u3002
|
|
993
|
+
|
|
994
|
+
## \u4F7F\u7528\u8BF4\u660E
|
|
995
|
+
1. \u786E\u4FDD\u5DF2\u5B89\u88C5\u5E76\u914D\u7F6E MCP \u670D\u52A1\u3002
|
|
996
|
+
2. \u8FD0\u884C \`team-cli dev\` \u5E76\u9009\u62E9\u6B64 Spec\u3002
|
|
997
|
+
3. Claude \u5C06\u81EA\u52A8\u8C03\u7528 MCP \u83B7\u53D6\u6700\u65B0\u7684 API \u4FE1\u606F\u5E76\u5B8C\u6210\u5B9E\u73B0\u3002
|
|
998
|
+
`;
|
|
999
|
+
await FileUtils.write(targetPath, content);
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* 自动探测项目的 Base Package
|
|
1003
|
+
*/
|
|
1004
|
+
static async findBasePackage(searchDir) {
|
|
1005
|
+
if (!await FileUtils.exists(searchDir)) return null;
|
|
1006
|
+
const files = await FileUtils.findFiles("**/Application.java", searchDir);
|
|
1007
|
+
if (files.length > 0) {
|
|
1008
|
+
return path5.dirname(path5.join(searchDir, files[0]));
|
|
1009
|
+
}
|
|
1010
|
+
let current = searchDir;
|
|
1011
|
+
while (true) {
|
|
1012
|
+
const items = await fs3.readdir(current);
|
|
1013
|
+
const dirs = items.filter((c) => fs3.statSync(path5.join(current, c)).isDirectory());
|
|
1014
|
+
if (dirs.length === 1 && !["model", "controller", "service", "mapper", "config", "common"].includes(dirs[0])) {
|
|
1015
|
+
current = path5.join(current, dirs[0]);
|
|
1016
|
+
} else {
|
|
1017
|
+
break;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
return current;
|
|
1021
|
+
}
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
1025
|
+
|
|
886
1026
|
// src/lib/user-config.ts
|
|
887
1027
|
var user_config_exports = {};
|
|
888
1028
|
__export(user_config_exports, {
|
|
889
1029
|
UserConfigManager: () => UserConfigManager,
|
|
890
1030
|
userConfigManager: () => userConfigManager
|
|
891
1031
|
});
|
|
892
|
-
import
|
|
1032
|
+
import path6 from "path";
|
|
893
1033
|
import os2 from "os";
|
|
894
1034
|
import crypto from "crypto";
|
|
895
1035
|
var UserConfigManager, userConfigManager;
|
|
@@ -902,8 +1042,8 @@ var init_user_config = __esm({
|
|
|
902
1042
|
UserConfigManager = class {
|
|
903
1043
|
configPath;
|
|
904
1044
|
constructor() {
|
|
905
|
-
const configDir =
|
|
906
|
-
this.configPath =
|
|
1045
|
+
const configDir = path6.join(os2.homedir(), ".team-cli");
|
|
1046
|
+
this.configPath = path6.join(configDir, "config.json");
|
|
907
1047
|
}
|
|
908
1048
|
/**
|
|
909
1049
|
* 加载用户配置
|
|
@@ -930,7 +1070,7 @@ var init_user_config = __esm({
|
|
|
930
1070
|
*/
|
|
931
1071
|
async save(config) {
|
|
932
1072
|
try {
|
|
933
|
-
const configDir =
|
|
1073
|
+
const configDir = path6.dirname(this.configPath);
|
|
934
1074
|
await FileUtils.ensureDir(configDir);
|
|
935
1075
|
const configToSave = JSON.parse(JSON.stringify(config));
|
|
936
1076
|
if (configToSave.gitlab?.accessToken) {
|
|
@@ -1036,7 +1176,7 @@ var init_user_config = __esm({
|
|
|
1036
1176
|
* 获取配置目录
|
|
1037
1177
|
*/
|
|
1038
1178
|
getConfigDir() {
|
|
1039
|
-
return
|
|
1179
|
+
return path6.dirname(this.configPath);
|
|
1040
1180
|
}
|
|
1041
1181
|
/**
|
|
1042
1182
|
* 获取配置文件路径
|
|
@@ -1251,22 +1391,22 @@ var init_gitlab_api = __esm({
|
|
|
1251
1391
|
* 从 Git URL 中提取项目路径
|
|
1252
1392
|
*/
|
|
1253
1393
|
static parseProjectPath(repository) {
|
|
1254
|
-
let
|
|
1255
|
-
if (
|
|
1256
|
-
|
|
1257
|
-
const colonIndex =
|
|
1394
|
+
let path20 = repository;
|
|
1395
|
+
if (path20.startsWith("git@")) {
|
|
1396
|
+
path20 = path20.replace(/^git@/, "");
|
|
1397
|
+
const colonIndex = path20.indexOf(":");
|
|
1258
1398
|
if (colonIndex !== -1) {
|
|
1259
|
-
|
|
1399
|
+
path20 = path20.substring(colonIndex + 1);
|
|
1260
1400
|
}
|
|
1261
1401
|
} else {
|
|
1262
|
-
|
|
1263
|
-
const parts =
|
|
1402
|
+
path20 = path20.replace(/^https?:\/\//, "");
|
|
1403
|
+
const parts = path20.split("/");
|
|
1264
1404
|
if (parts.length > 1) {
|
|
1265
|
-
|
|
1405
|
+
path20 = parts.slice(1).join("/");
|
|
1266
1406
|
}
|
|
1267
1407
|
}
|
|
1268
|
-
|
|
1269
|
-
return
|
|
1408
|
+
path20 = path20.replace(/\.git$/, "");
|
|
1409
|
+
return path20;
|
|
1270
1410
|
}
|
|
1271
1411
|
/**
|
|
1272
1412
|
* 编码项目路径用于 API 请求
|
|
@@ -1320,8 +1460,8 @@ var init_gitlab_api = __esm({
|
|
|
1320
1460
|
// src/commands/init.ts
|
|
1321
1461
|
import { Command } from "commander";
|
|
1322
1462
|
import inquirer from "inquirer";
|
|
1323
|
-
import
|
|
1324
|
-
import
|
|
1463
|
+
import path7 from "path";
|
|
1464
|
+
import fs4 from "fs-extra";
|
|
1325
1465
|
import { Listr } from "listr2";
|
|
1326
1466
|
async function generateTechStack(projectPath) {
|
|
1327
1467
|
const content = `# \u6280\u672F\u6808
|
|
@@ -1419,7 +1559,7 @@ docs/
|
|
|
1419
1559
|
\u2514\u2500\u2500 sessions/ # \u5F00\u53D1\u4F1A\u8BDD\u8BB0\u5F55
|
|
1420
1560
|
\`\`\`
|
|
1421
1561
|
`;
|
|
1422
|
-
await FileUtils.write(
|
|
1562
|
+
await FileUtils.write(path7.join(projectPath, "TECH_STACK.md"), content);
|
|
1423
1563
|
}
|
|
1424
1564
|
async function generateConventions(projectPath) {
|
|
1425
1565
|
const content = `# \u5F00\u53D1\u89C4\u8303
|
|
@@ -1722,7 +1862,7 @@ test('renders user name', () => {
|
|
|
1722
1862
|
});
|
|
1723
1863
|
\`\`\`
|
|
1724
1864
|
`;
|
|
1725
|
-
await FileUtils.write(
|
|
1865
|
+
await FileUtils.write(path7.join(projectPath, "CONVENTIONS.md"), content);
|
|
1726
1866
|
}
|
|
1727
1867
|
async function generateAIMemory(projectPath, projectName) {
|
|
1728
1868
|
const content = `# AI Memory - \u9879\u76EE\u72B6\u6001\u8BB0\u5F55
|
|
@@ -1781,7 +1921,7 @@ async function generateAIMemory(projectPath, projectName) {
|
|
|
1781
1921
|
| Bug ID | \u65E5\u671F | \u95EE\u9898\u63CF\u8FF0 | \u72B6\u6001 |
|
|
1782
1922
|
|--------|------|---------|------|
|
|
1783
1923
|
`;
|
|
1784
|
-
await FileUtils.write(
|
|
1924
|
+
await FileUtils.write(path7.join(projectPath, "AI_MEMORY.md"), content);
|
|
1785
1925
|
}
|
|
1786
1926
|
async function generateSpecTemplate(projectPath) {
|
|
1787
1927
|
const content = `# [\u529F\u80FD\u6807\u9898]
|
|
@@ -1845,14 +1985,14 @@ async function generateSpecTemplate(projectPath) {
|
|
|
1845
1985
|
----
|
|
1846
1986
|
*\u751F\u6210\u4E8E: {{TIMESTAMP}} by team-cli*
|
|
1847
1987
|
`;
|
|
1848
|
-
await FileUtils.write(
|
|
1988
|
+
await FileUtils.write(path7.join(projectPath, "docs/specs/template.md"), content);
|
|
1849
1989
|
}
|
|
1850
1990
|
async function cloneBackendTemplate(projectPath, versionOptions) {
|
|
1851
1991
|
const templateRepo = process.env.TEMPLATE_REPO || "git@gitlab.yungu-inc.org:yungu-app/java-scaffold-template.git";
|
|
1852
|
-
const backendPath =
|
|
1992
|
+
const backendPath = path7.join(projectPath, "backend");
|
|
1853
1993
|
try {
|
|
1854
1994
|
const { execaCommand } = await import("execa");
|
|
1855
|
-
const tempDir =
|
|
1995
|
+
const tempDir = path7.join(projectPath, ".template-temp");
|
|
1856
1996
|
if (versionOptions?.tag || versionOptions?.branch) {
|
|
1857
1997
|
const { userConfigManager: userConfigManager2 } = await Promise.resolve().then(() => (init_user_config(), user_config_exports));
|
|
1858
1998
|
const { GitLabAPI: GitLabAPI2 } = await Promise.resolve().then(() => (init_gitlab_api(), gitlab_api_exports));
|
|
@@ -1895,11 +2035,11 @@ async function cloneBackendTemplate(projectPath, versionOptions) {
|
|
|
1895
2035
|
stdio: "pipe"
|
|
1896
2036
|
});
|
|
1897
2037
|
const latestTag = tags.split("\n")[0] || void 0;
|
|
1898
|
-
await
|
|
2038
|
+
await fs4.copy(tempDir, backendPath, {
|
|
1899
2039
|
filter: (src) => !src.includes(".git")
|
|
1900
2040
|
});
|
|
1901
|
-
await
|
|
1902
|
-
const gitDir =
|
|
2041
|
+
await fs4.remove(tempDir);
|
|
2042
|
+
const gitDir = path7.join(backendPath, ".git");
|
|
1903
2043
|
if (await FileUtils.exists(gitDir)) {
|
|
1904
2044
|
await FileUtils.remove(gitDir);
|
|
1905
2045
|
}
|
|
@@ -1910,13 +2050,13 @@ async function cloneBackendTemplate(projectPath, versionOptions) {
|
|
|
1910
2050
|
});
|
|
1911
2051
|
} catch (error) {
|
|
1912
2052
|
logger.warn("\u514B\u9686\u540E\u7AEF\u6A21\u677F\u5931\u8D25\uFF0C\u521B\u5EFA\u57FA\u7840\u7ED3\u6784");
|
|
1913
|
-
await FileUtils.ensureDir(
|
|
1914
|
-
await FileUtils.ensureDir(
|
|
1915
|
-
await FileUtils.ensureDir(
|
|
2053
|
+
await FileUtils.ensureDir(path7.join(backendPath, "src/main/java/com/example"));
|
|
2054
|
+
await FileUtils.ensureDir(path7.join(backendPath, "src/main/resources"));
|
|
2055
|
+
await FileUtils.ensureDir(path7.join(backendPath, "src/test/java"));
|
|
1916
2056
|
}
|
|
1917
2057
|
}
|
|
1918
2058
|
async function generateFrontendScaffold(projectPath) {
|
|
1919
|
-
const frontendPath =
|
|
2059
|
+
const frontendPath = path7.join(projectPath, "frontend");
|
|
1920
2060
|
try {
|
|
1921
2061
|
const prompt = `Read TECH_STACK.md and CONVENTIONS.md.
|
|
1922
2062
|
Initialize a Next.js 14 frontend in ./frontend with:
|
|
@@ -1929,19 +2069,19 @@ Initialize a Next.js 14 frontend in ./frontend with:
|
|
|
1929
2069
|
Do not run any servers, just generate the folder structure and configuration files.`;
|
|
1930
2070
|
await claudeAI.prompt(prompt, {
|
|
1931
2071
|
contextFiles: [
|
|
1932
|
-
|
|
1933
|
-
|
|
2072
|
+
path7.join(projectPath, "TECH_STACK.md"),
|
|
2073
|
+
path7.join(projectPath, "CONVENTIONS.md")
|
|
1934
2074
|
]
|
|
1935
2075
|
});
|
|
1936
2076
|
} catch (error) {
|
|
1937
2077
|
logger.warn("Claude \u751F\u6210\u524D\u7AEF\u5931\u8D25\uFF0C\u5C06\u521B\u5EFA\u57FA\u7840\u7ED3\u6784");
|
|
1938
|
-
await FileUtils.ensureDir(
|
|
1939
|
-
await FileUtils.ensureDir(
|
|
1940
|
-
await FileUtils.ensureDir(
|
|
1941
|
-
await FileUtils.ensureDir(
|
|
2078
|
+
await FileUtils.ensureDir(path7.join(frontendPath, "src/app"));
|
|
2079
|
+
await FileUtils.ensureDir(path7.join(frontendPath, "src/components"));
|
|
2080
|
+
await FileUtils.ensureDir(path7.join(frontendPath, "src/lib"));
|
|
2081
|
+
await FileUtils.ensureDir(path7.join(frontendPath, "public"));
|
|
1942
2082
|
}
|
|
1943
2083
|
}
|
|
1944
|
-
async function generateDockerFiles(
|
|
2084
|
+
async function generateDockerFiles() {
|
|
1945
2085
|
logger.info("Docker \u914D\u7F6E\u751F\u6210\u5F85\u5B9E\u73B0");
|
|
1946
2086
|
}
|
|
1947
2087
|
async function initGit(projectPath, projectName) {
|
|
@@ -1967,6 +2107,7 @@ var init_init = __esm({
|
|
|
1967
2107
|
init_claude();
|
|
1968
2108
|
init_utils();
|
|
1969
2109
|
init_template_version();
|
|
2110
|
+
init_module_registry();
|
|
1970
2111
|
initCommand = new Command("init").argument("[project-name]", "\u9879\u76EE\u540D\u79F0").description("\u521D\u59CB\u5316\u65B0\u9879\u76EE").option("-d, --dir <directory>", "\u9879\u76EE\u76EE\u5F55", ".").option("--no-docker", "\u4E0D\u751F\u6210 Docker \u914D\u7F6E").option("--no-git", "\u4E0D\u521D\u59CB\u5316 Git").option("--tag <tag>", "\u6307\u5B9A\u6A21\u677F\u6807\u7B7E (\u524D\u540E\u7AEF\u901A\u7528)").option("--backend-tag <tag>", "\u6307\u5B9A\u540E\u7AEF\u6A21\u677F\u6807\u7B7E").option("--frontend-tag <tag>", "\u6307\u5B9A\u524D\u7AEF\u6A21\u677F\u6807\u7B7E").option("--backend-branch <branch>", "\u6307\u5B9A\u540E\u7AEF\u6A21\u677F\u5206\u652F").option("--frontend-branch <branch>", "\u6307\u5B9A\u524D\u7AEF\u6A21\u677F\u5206\u652F").action(async (projectName, options) => {
|
|
1971
2112
|
try {
|
|
1972
2113
|
if (!projectName) {
|
|
@@ -1998,7 +2139,19 @@ var init_init = __esm({
|
|
|
1998
2139
|
logger.info("\u8BF7\u5B89\u88C5 Claude CLI: npm install -g @anthropic-ai/claude-code");
|
|
1999
2140
|
process.exit(1);
|
|
2000
2141
|
}
|
|
2001
|
-
const projectPath =
|
|
2142
|
+
const projectPath = path7.resolve(options.dir, projectName);
|
|
2143
|
+
const availableModules = ModuleManager.getAvailableModules();
|
|
2144
|
+
const { selectedModules } = await inquirer.prompt([
|
|
2145
|
+
{
|
|
2146
|
+
type: "checkbox",
|
|
2147
|
+
name: "selectedModules",
|
|
2148
|
+
message: "\u8BF7\u9009\u62E9\u8981\u5F00\u542F\u7684\u5185\u7F6E\u901A\u7528\u6A21\u5757:",
|
|
2149
|
+
choices: availableModules.map((m) => ({
|
|
2150
|
+
name: `${m.name} - ${m.description}`,
|
|
2151
|
+
value: m.id
|
|
2152
|
+
}))
|
|
2153
|
+
}
|
|
2154
|
+
]);
|
|
2002
2155
|
if (await FileUtils.exists(projectPath)) {
|
|
2003
2156
|
logger.error(`\u76EE\u5F55\u5DF2\u5B58\u5728: ${projectPath}`);
|
|
2004
2157
|
logger.info("\u8BF7\u9009\u62E9\u5176\u4ED6\u9879\u76EE\u540D\u79F0\u6216\u5220\u9664\u73B0\u6709\u76EE\u5F55");
|
|
@@ -2017,11 +2170,11 @@ var init_init = __esm({
|
|
|
2017
2170
|
title: "\u521B\u5EFA\u9879\u76EE\u76EE\u5F55",
|
|
2018
2171
|
task: async () => {
|
|
2019
2172
|
await FileUtils.ensureDir(projectPath);
|
|
2020
|
-
await FileUtils.ensureDir(
|
|
2021
|
-
await FileUtils.ensureDir(
|
|
2022
|
-
await FileUtils.ensureDir(
|
|
2023
|
-
await FileUtils.ensureDir(
|
|
2024
|
-
await FileUtils.ensureDir(
|
|
2173
|
+
await FileUtils.ensureDir(path7.join(projectPath, "frontend"));
|
|
2174
|
+
await FileUtils.ensureDir(path7.join(projectPath, "backend"));
|
|
2175
|
+
await FileUtils.ensureDir(path7.join(projectPath, "docs/specs"));
|
|
2176
|
+
await FileUtils.ensureDir(path7.join(projectPath, "docs/api"));
|
|
2177
|
+
await FileUtils.ensureDir(path7.join(projectPath, "docs/sessions"));
|
|
2025
2178
|
}
|
|
2026
2179
|
},
|
|
2027
2180
|
{
|
|
@@ -2069,7 +2222,7 @@ var init_init = __esm({
|
|
|
2069
2222
|
{
|
|
2070
2223
|
title: "\u751F\u6210 Docker \u914D\u7F6E",
|
|
2071
2224
|
task: async () => {
|
|
2072
|
-
await generateDockerFiles(
|
|
2225
|
+
await generateDockerFiles();
|
|
2073
2226
|
}
|
|
2074
2227
|
}
|
|
2075
2228
|
] : [],
|
|
@@ -2080,7 +2233,61 @@ var init_init = __esm({
|
|
|
2080
2233
|
await initGit(projectPath, projectName);
|
|
2081
2234
|
}
|
|
2082
2235
|
}
|
|
2083
|
-
] : []
|
|
2236
|
+
] : [],
|
|
2237
|
+
{
|
|
2238
|
+
title: "\u6CE8\u518C\u8FDC\u7A0B MCP \u670D\u52A1",
|
|
2239
|
+
task: async () => {
|
|
2240
|
+
const hasRemoteModule = selectedModules.some(
|
|
2241
|
+
(id) => ModuleManager.getModuleById(id)?.type === "remote"
|
|
2242
|
+
);
|
|
2243
|
+
if (hasRemoteModule) {
|
|
2244
|
+
const mcpCmd = 'claude_m2 mcp add --transport sse --header "Authorization: Bearer mcp_00557dabb71297b4f9ac5fe748395f2c" -- api-metadata https://api-metadata.yungu.org/sse';
|
|
2245
|
+
const { execaCommand } = await import("execa");
|
|
2246
|
+
try {
|
|
2247
|
+
await execaCommand(mcpCmd);
|
|
2248
|
+
logger.info("\u8FDC\u7A0B MCP \u670D\u52A1 api-metadata \u5DF2\u6CE8\u518C");
|
|
2249
|
+
} catch (err) {
|
|
2250
|
+
logger.warn("\u8FDC\u7A0B MCP \u670D\u52A1\u6CE8\u518C\u5931\u8D25\uFF0C\u53EF\u80FD\u5DF2\u5B58\u5728\u6216\u6743\u9650\u4E0D\u8DB3");
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
},
|
|
2255
|
+
{
|
|
2256
|
+
title: "\u6CE8\u5165\u901A\u7528\u6A21\u5757",
|
|
2257
|
+
task: async () => {
|
|
2258
|
+
if (selectedModules.length === 0) return;
|
|
2259
|
+
const templatesDir = path7.resolve(FileUtils.getDirName(import.meta.url), "../templates");
|
|
2260
|
+
for (const moduleId of selectedModules) {
|
|
2261
|
+
await ModuleManager.injectModule(projectPath, moduleId, templatesDir);
|
|
2262
|
+
logger.info(`\u6CE8\u5165\u6A21\u5757: ${moduleId}`);
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
},
|
|
2266
|
+
{
|
|
2267
|
+
title: "\u6267\u884C\u8FDC\u7A0B\u6A21\u5757\u4EE3\u7801\u751F\u6210",
|
|
2268
|
+
task: async () => {
|
|
2269
|
+
const remoteModules = selectedModules.map((id) => ModuleManager.getModuleById(id)).filter((m) => m?.type === "remote");
|
|
2270
|
+
if (remoteModules.length === 0) return;
|
|
2271
|
+
const { execaCommand } = await import("execa");
|
|
2272
|
+
for (const module of remoteModules) {
|
|
2273
|
+
if (!module) continue;
|
|
2274
|
+
logger.info(`\u6B63\u5728\u4E3A\u60A8\u751F\u6210 ${module.name} \u7684\u8FDC\u7A0B\u8C03\u7528\u4EE3\u7801...`);
|
|
2275
|
+
const prompt = `\u4F7F\u7528 api-metadata MCP \u5DE5\u5177\u83B7\u53D6\u6240\u6709\u4E0E "${module.id.replace("-remote", "")}" \u76F8\u5173\u7684 API \u5143\u6570\u636E\u3002
|
|
2276
|
+
\u7136\u540E\u5728\u9879\u76EE\u8DEF\u5F84 \`${projectPath}\` \u7684\u540E\u7AEF\u76EE\u5F55\u4E2D\uFF0C\u76F4\u63A5\u751F\u6210\u5BF9\u5E94\u7684 Java \u8C03\u7528\u4EE3\u7801\uFF08\u5982 Feign Client \u6216 RestTemplate \u5C01\u88C5\uFF09\u3002
|
|
2277
|
+
\u8BF7\u786E\u4FDD\u4EE3\u7801\u7B26\u5408 \`CONVENTIONS.md\` \u4E2D\u7684\u89C4\u8303\u3002
|
|
2278
|
+
\u751F\u6210\u5B8C\u6210\u540E\uFF0C\u8BF7\u7B80\u8981\u5217\u51FA\u751F\u6210\u7684\u6587\u4EF6\u3002`;
|
|
2279
|
+
try {
|
|
2280
|
+
await execaCommand(`claude_m2 -p "${prompt}" --add-dir ${projectPath}`, {
|
|
2281
|
+
stdio: "inherit",
|
|
2282
|
+
timeout: 3e5
|
|
2283
|
+
// 5分钟超时
|
|
2284
|
+
});
|
|
2285
|
+
} catch (err) {
|
|
2286
|
+
logger.error(`${module.name} \u4EE3\u7801\u751F\u6210\u5931\u8D25\uFF0C\u60A8\u53EF\u4EE5\u7A0D\u540E\u5728\u5F00\u53D1\u6A21\u5F0F\u4E0B\u624B\u52A8\u8FD0\u884C\u3002`);
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2084
2291
|
],
|
|
2085
2292
|
{
|
|
2086
2293
|
concurrent: false,
|
|
@@ -2111,7 +2318,7 @@ var init_init = __esm({
|
|
|
2111
2318
|
// src/commands/breakdown.ts
|
|
2112
2319
|
import { Command as Command2 } from "commander";
|
|
2113
2320
|
import inquirer2 from "inquirer";
|
|
2114
|
-
import
|
|
2321
|
+
import path8 from "path";
|
|
2115
2322
|
import { Listr as Listr2 } from "listr2";
|
|
2116
2323
|
function buildBreakdownPrompt(specContent) {
|
|
2117
2324
|
return `Role: Senior Technical Lead and Agile Coach
|
|
@@ -2226,9 +2433,9 @@ var init_breakdown = __esm({
|
|
|
2226
2433
|
choices: ctx.specs
|
|
2227
2434
|
}
|
|
2228
2435
|
]);
|
|
2229
|
-
return
|
|
2436
|
+
return path8.join("docs/specs", selectedFile);
|
|
2230
2437
|
}
|
|
2231
|
-
const fullPath = specFile.startsWith("docs/specs/") ? specFile :
|
|
2438
|
+
const fullPath = specFile.startsWith("docs/specs/") ? specFile : path8.join("docs/specs", specFile);
|
|
2232
2439
|
const exists = await FileUtils.exists(fullPath);
|
|
2233
2440
|
if (!exists) {
|
|
2234
2441
|
throw new Error(`Spec \u6587\u4EF6\u4E0D\u5B58\u5728: ${specFile}`);
|
|
@@ -2298,7 +2505,7 @@ var init_breakdown = __esm({
|
|
|
2298
2505
|
// src/commands/dev.ts
|
|
2299
2506
|
import { Command as Command3 } from "commander";
|
|
2300
2507
|
import inquirer3 from "inquirer";
|
|
2301
|
-
import
|
|
2508
|
+
import path9 from "path";
|
|
2302
2509
|
async function selectSpec() {
|
|
2303
2510
|
logger.step("\u6B65\u9AA4 1/3: \u9009\u62E9 spec \u6587\u4EF6...");
|
|
2304
2511
|
logger.newLine();
|
|
@@ -2314,7 +2521,7 @@ async function selectSpec() {
|
|
|
2314
2521
|
}
|
|
2315
2522
|
const specs = [];
|
|
2316
2523
|
for (let i = 0; i < specFiles.length; i++) {
|
|
2317
|
-
const file =
|
|
2524
|
+
const file = path9.join(specDir, specFiles[i]);
|
|
2318
2525
|
const spec = await FileUtils.read(file);
|
|
2319
2526
|
const status = parseSpecStatus(spec);
|
|
2320
2527
|
const dependencies = parseDependencies(spec);
|
|
@@ -2636,8 +2843,8 @@ async function generateSessionLog(specFile, milestone, todo, taskDescription, re
|
|
|
2636
2843
|
const sessionDir = "docs/sessions";
|
|
2637
2844
|
await FileUtils.ensureDir(sessionDir);
|
|
2638
2845
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2639
|
-
const specName =
|
|
2640
|
-
const logFile =
|
|
2846
|
+
const specName = path9.basename(specFile, ".md");
|
|
2847
|
+
const logFile = path9.join(sessionDir, `${timestamp}_${specName}.md`);
|
|
2641
2848
|
const content = `# \u5F00\u53D1\u4F1A\u8BDD\u8BB0\u5F55
|
|
2642
2849
|
|
|
2643
2850
|
**\u65F6\u95F4**: ${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN")}
|
|
@@ -2776,7 +2983,7 @@ var init_dev = __esm({
|
|
|
2776
2983
|
// src/commands/add-feature.ts
|
|
2777
2984
|
import { Command as Command4 } from "commander";
|
|
2778
2985
|
import inquirer4 from "inquirer";
|
|
2779
|
-
import
|
|
2986
|
+
import path10 from "path";
|
|
2780
2987
|
import { Listr as Listr3 } from "listr2";
|
|
2781
2988
|
async function addFeatureFromPrd(featureName, featureSlug, specFile) {
|
|
2782
2989
|
const { prdPath } = await inquirer4.prompt([
|
|
@@ -2805,7 +3012,7 @@ async function addFeatureFromPrd(featureName, featureSlug, specFile) {
|
|
|
2805
3012
|
const specs = files.filter((f) => !f.includes("template"));
|
|
2806
3013
|
ctx2.completedSpecs = [];
|
|
2807
3014
|
for (const file of specs) {
|
|
2808
|
-
const status = await SpecUtils.getSpecStatus(
|
|
3015
|
+
const status = await SpecUtils.getSpecStatus(path10.join(specDir, file));
|
|
2809
3016
|
if (status === "\u5DF2\u5B8C\u6210") {
|
|
2810
3017
|
ctx2.completedSpecs.push(file.replace(".md", ""));
|
|
2811
3018
|
}
|
|
@@ -2877,7 +3084,7 @@ async function addFeatureSimple(featureName, featureSlug, specFile) {
|
|
|
2877
3084
|
const specs = files.filter((f) => !f.includes("template"));
|
|
2878
3085
|
ctx2.completedSpecs = [];
|
|
2879
3086
|
for (const file of specs) {
|
|
2880
|
-
const status = await SpecUtils.getSpecStatus(
|
|
3087
|
+
const status = await SpecUtils.getSpecStatus(path10.join(specDir, file));
|
|
2881
3088
|
if (status === "\u5DF2\u5B8C\u6210") {
|
|
2882
3089
|
ctx2.completedSpecs.push(file.replace(".md", ""));
|
|
2883
3090
|
}
|
|
@@ -2974,7 +3181,7 @@ async function buildProjectContext() {
|
|
|
2974
3181
|
const files = await FileUtils.findFiles("*.md", "docs/specs");
|
|
2975
3182
|
const specs = files.filter((f) => !f.includes("template"));
|
|
2976
3183
|
for (const file of specs) {
|
|
2977
|
-
const status = await SpecUtils.getSpecStatus(
|
|
3184
|
+
const status = await SpecUtils.getSpecStatus(path10.join("docs/specs", file));
|
|
2978
3185
|
context.push(` - ${file.replace(".md", "")} [${status}]`);
|
|
2979
3186
|
}
|
|
2980
3187
|
}
|
|
@@ -3237,7 +3444,7 @@ var init_add_feature = __esm({
|
|
|
3237
3444
|
process.exit(1);
|
|
3238
3445
|
}
|
|
3239
3446
|
const featureSlug = StringUtils2.toKebabCase(featureName);
|
|
3240
|
-
const specFile =
|
|
3447
|
+
const specFile = path10.join("docs/specs", `${featureSlug}.md`);
|
|
3241
3448
|
const specExists = await FileUtils.exists(specFile);
|
|
3242
3449
|
if (specExists) {
|
|
3243
3450
|
logger.error(`Spec \u6587\u4EF6\u5DF2\u5B58\u5728: ${specFile}`);
|
|
@@ -3274,7 +3481,7 @@ var init_add_feature = __esm({
|
|
|
3274
3481
|
|
|
3275
3482
|
// src/commands/split-prd.ts
|
|
3276
3483
|
import { Command as Command5 } from "commander";
|
|
3277
|
-
import
|
|
3484
|
+
import path11 from "path";
|
|
3278
3485
|
import { Listr as Listr4 } from "listr2";
|
|
3279
3486
|
function buildSplitPrdPrompt(prdContent, screenshots, demoRepos) {
|
|
3280
3487
|
let prompt = `Role: Senior Product Manager and Technical Architect
|
|
@@ -3420,7 +3627,7 @@ var init_split_prd = __esm({
|
|
|
3420
3627
|
ctx2.prdFiles = [];
|
|
3421
3628
|
for (const ext of supportedExtensions) {
|
|
3422
3629
|
const files = await FileUtils.findFiles(`*.${ext}`, prdFolder);
|
|
3423
|
-
ctx2.prdFiles.push(...files.map((f) =>
|
|
3630
|
+
ctx2.prdFiles.push(...files.map((f) => path11.join(prdFolder, f)));
|
|
3424
3631
|
}
|
|
3425
3632
|
if (ctx2.prdFiles.length === 0) {
|
|
3426
3633
|
throw new Error(
|
|
@@ -3438,7 +3645,7 @@ var init_split_prd = __esm({
|
|
|
3438
3645
|
{
|
|
3439
3646
|
title: "\u626B\u63CF\u622A\u56FE\u6587\u4EF6",
|
|
3440
3647
|
task: async (ctx2) => {
|
|
3441
|
-
const screenshotDir =
|
|
3648
|
+
const screenshotDir = path11.join(prdFolder, "screenshots");
|
|
3442
3649
|
const dirExists = await FileUtils.exists(screenshotDir);
|
|
3443
3650
|
if (!dirExists) {
|
|
3444
3651
|
logger.info("\u672A\u627E\u5230 screenshots \u76EE\u5F55\uFF0C\u8DF3\u8FC7\u622A\u56FE");
|
|
@@ -3449,7 +3656,7 @@ var init_split_prd = __esm({
|
|
|
3449
3656
|
ctx2.screenshots = [];
|
|
3450
3657
|
for (const ext of imageExtensions) {
|
|
3451
3658
|
const files = await FileUtils.findFiles(`*.${ext}`, screenshotDir);
|
|
3452
|
-
ctx2.screenshots.push(...files.map((f) =>
|
|
3659
|
+
ctx2.screenshots.push(...files.map((f) => path11.join(screenshotDir, f)));
|
|
3453
3660
|
}
|
|
3454
3661
|
logger.success(`\u627E\u5230 ${ctx2.screenshots.length} \u4E2A\u622A\u56FE\u6587\u4EF6`);
|
|
3455
3662
|
}
|
|
@@ -3460,8 +3667,8 @@ var init_split_prd = __esm({
|
|
|
3460
3667
|
const entries = await FileUtils.findFiles("*/", prdFolder);
|
|
3461
3668
|
ctx2.demoRepos = [];
|
|
3462
3669
|
for (const entry of entries) {
|
|
3463
|
-
const dirPath =
|
|
3464
|
-
const gitDir =
|
|
3670
|
+
const dirPath = path11.join(prdFolder, entry);
|
|
3671
|
+
const gitDir = path11.join(dirPath, ".git");
|
|
3465
3672
|
const hasGit = await FileUtils.exists(gitDir);
|
|
3466
3673
|
if (hasGit) {
|
|
3467
3674
|
ctx2.demoRepos.push(dirPath);
|
|
@@ -3525,7 +3732,7 @@ var init_split_prd = __esm({
|
|
|
3525
3732
|
// src/commands/bugfix.ts
|
|
3526
3733
|
import { Command as Command6 } from "commander";
|
|
3527
3734
|
import inquirer5 from "inquirer";
|
|
3528
|
-
import
|
|
3735
|
+
import path12 from "path";
|
|
3529
3736
|
import { Listr as Listr5 } from "listr2";
|
|
3530
3737
|
function generateBugId() {
|
|
3531
3738
|
const date = /* @__PURE__ */ new Date();
|
|
@@ -3552,7 +3759,7 @@ async function findRelatedSpec(description) {
|
|
|
3552
3759
|
}
|
|
3553
3760
|
const keywords = extractKeywords(description);
|
|
3554
3761
|
for (const file of specs) {
|
|
3555
|
-
const filePath =
|
|
3762
|
+
const filePath = path12.join(specDir, file);
|
|
3556
3763
|
const content = await FileUtils.read(filePath);
|
|
3557
3764
|
for (const keyword of keywords) {
|
|
3558
3765
|
if (content.toLowerCase().includes(keyword.toLowerCase())) {
|
|
@@ -3692,7 +3899,7 @@ var init_bugfix = __esm({
|
|
|
3692
3899
|
const relatedSpec = await findRelatedSpec(answers.description);
|
|
3693
3900
|
const bugfixDir = "docs/bugfixes";
|
|
3694
3901
|
await FileUtils.ensureDir(bugfixDir);
|
|
3695
|
-
const bugfixFile =
|
|
3902
|
+
const bugfixFile = path12.join(bugfixDir, `${timestamp}_${bugId}.md`);
|
|
3696
3903
|
const content = formatBugfixDocument({
|
|
3697
3904
|
id: bugId,
|
|
3698
3905
|
severity: answers.severity,
|
|
@@ -3768,7 +3975,7 @@ var init_bugfix = __esm({
|
|
|
3768
3975
|
const timestamp = DateUtils.format(/* @__PURE__ */ new Date(), "YYYY-MM-DD HH:mm:ss");
|
|
3769
3976
|
const hotfixDir = "docs/hotfixes";
|
|
3770
3977
|
await FileUtils.ensureDir(hotfixDir);
|
|
3771
|
-
const hotfixFile =
|
|
3978
|
+
const hotfixFile = path12.join(hotfixDir, `${timestamp}_${hotfixId}.md`);
|
|
3772
3979
|
const content = formatHotfixDocument({
|
|
3773
3980
|
id: hotfixId,
|
|
3774
3981
|
description: answers.description,
|
|
@@ -3955,7 +4162,7 @@ var init_lint = __esm({
|
|
|
3955
4162
|
|
|
3956
4163
|
// src/commands/status.ts
|
|
3957
4164
|
import { Command as Command8 } from "commander";
|
|
3958
|
-
import
|
|
4165
|
+
import path13 from "path";
|
|
3959
4166
|
async function displayProjectInfo() {
|
|
3960
4167
|
logger.info("\u9879\u76EE\u4FE1\u606F:");
|
|
3961
4168
|
logger.newLine();
|
|
@@ -3991,7 +4198,7 @@ async function displayFeatureInventory() {
|
|
|
3991
4198
|
}
|
|
3992
4199
|
const inventory = [];
|
|
3993
4200
|
for (const file of specs) {
|
|
3994
|
-
const filePath =
|
|
4201
|
+
const filePath = path13.join(specDir, file);
|
|
3995
4202
|
const content = await FileUtils.read(filePath);
|
|
3996
4203
|
const status = parseSpecStatus2(content);
|
|
3997
4204
|
inventory.push({
|
|
@@ -4050,7 +4257,7 @@ async function displayRecentActivity() {
|
|
|
4050
4257
|
}
|
|
4051
4258
|
const sorted = files.sort().reverse().slice(0, 5);
|
|
4052
4259
|
for (const file of sorted) {
|
|
4053
|
-
const filePath =
|
|
4260
|
+
const filePath = path13.join(sessionDir, file);
|
|
4054
4261
|
const stat = await FileUtils.read(filePath);
|
|
4055
4262
|
const specMatch = stat.match(/\*\*Spec\*\*:\s*(.+)/);
|
|
4056
4263
|
const spec = specMatch ? specMatch[1].trim() : "\u672A\u77E5";
|
|
@@ -4120,13 +4327,13 @@ var init_status = __esm({
|
|
|
4120
4327
|
|
|
4121
4328
|
// src/commands/detect-deps.ts
|
|
4122
4329
|
import { Command as Command9 } from "commander";
|
|
4123
|
-
import
|
|
4330
|
+
import path14 from "path";
|
|
4124
4331
|
import inquirer6 from "inquirer";
|
|
4125
4332
|
async function detectDependencies(specFile) {
|
|
4126
4333
|
logger.step("\u81EA\u52A8\u68C0\u6D4B\u4F9D\u8D56\u5173\u7CFB...");
|
|
4127
4334
|
const projectDir = ".";
|
|
4128
4335
|
const allDeps = /* @__PURE__ */ new Set();
|
|
4129
|
-
const backendDir =
|
|
4336
|
+
const backendDir = path14.join(projectDir, "backend");
|
|
4130
4337
|
const backendExists = await FileUtils.exists(backendDir);
|
|
4131
4338
|
if (backendExists) {
|
|
4132
4339
|
const apiDeps = await scanBackendApiCalls(backendDir);
|
|
@@ -4136,7 +4343,7 @@ async function detectDependencies(specFile) {
|
|
|
4136
4343
|
const serviceDeps = await scanBackendServiceRefs(backendDir);
|
|
4137
4344
|
serviceDeps.forEach((d) => allDeps.add(d));
|
|
4138
4345
|
}
|
|
4139
|
-
const frontendDir =
|
|
4346
|
+
const frontendDir = path14.join(projectDir, "frontend");
|
|
4140
4347
|
const frontendExists = await FileUtils.exists(frontendDir);
|
|
4141
4348
|
if (frontendExists) {
|
|
4142
4349
|
const frontendDeps = await scanFrontendApiCalls(frontendDir);
|
|
@@ -4177,11 +4384,11 @@ async function detectDependencies(specFile) {
|
|
|
4177
4384
|
}
|
|
4178
4385
|
async function scanBackendApiCalls(backendDir) {
|
|
4179
4386
|
const deps = [];
|
|
4180
|
-
const srcDir =
|
|
4387
|
+
const srcDir = path14.join(backendDir, "src");
|
|
4181
4388
|
try {
|
|
4182
4389
|
const javaFiles = await FileUtils.findFiles("*.java", srcDir);
|
|
4183
4390
|
for (const file of javaFiles) {
|
|
4184
|
-
const filePath =
|
|
4391
|
+
const filePath = path14.join(srcDir, file);
|
|
4185
4392
|
const content = await FileUtils.read(filePath);
|
|
4186
4393
|
const pathRegex = /"(\/api\/[^"]+)"/g;
|
|
4187
4394
|
let match;
|
|
@@ -4199,11 +4406,11 @@ async function scanBackendApiCalls(backendDir) {
|
|
|
4199
4406
|
}
|
|
4200
4407
|
async function scanBackendEntityRelations(backendDir) {
|
|
4201
4408
|
const deps = [];
|
|
4202
|
-
const srcDir =
|
|
4409
|
+
const srcDir = path14.join(backendDir, "src");
|
|
4203
4410
|
try {
|
|
4204
4411
|
const javaFiles = await FileUtils.findFiles("*.java", srcDir);
|
|
4205
4412
|
for (const file of javaFiles) {
|
|
4206
|
-
const filePath =
|
|
4413
|
+
const filePath = path14.join(srcDir, file);
|
|
4207
4414
|
const content = await FileUtils.read(filePath);
|
|
4208
4415
|
if (content.includes("@JoinColumn") || content.includes("@ManyToOne") || content.includes("@OneToMany")) {
|
|
4209
4416
|
const typeRegex = /type\s*=\s*(\w+)/g;
|
|
@@ -4219,11 +4426,11 @@ async function scanBackendEntityRelations(backendDir) {
|
|
|
4219
4426
|
}
|
|
4220
4427
|
async function scanBackendServiceRefs(backendDir) {
|
|
4221
4428
|
const deps = [];
|
|
4222
|
-
const srcDir =
|
|
4429
|
+
const srcDir = path14.join(backendDir, "src");
|
|
4223
4430
|
try {
|
|
4224
4431
|
const javaFiles = await FileUtils.findFiles("*.java", srcDir);
|
|
4225
4432
|
for (const file of javaFiles) {
|
|
4226
|
-
const filePath =
|
|
4433
|
+
const filePath = path14.join(srcDir, file);
|
|
4227
4434
|
const content = await FileUtils.read(filePath);
|
|
4228
4435
|
const serviceRegex = /private\s+(\w+)Service/g;
|
|
4229
4436
|
let match;
|
|
@@ -4239,11 +4446,11 @@ async function scanBackendServiceRefs(backendDir) {
|
|
|
4239
4446
|
}
|
|
4240
4447
|
async function scanFrontendApiCalls(frontendDir) {
|
|
4241
4448
|
const deps = [];
|
|
4242
|
-
const srcDir =
|
|
4449
|
+
const srcDir = path14.join(frontendDir, "src");
|
|
4243
4450
|
try {
|
|
4244
4451
|
const tsFiles = await FileUtils.findFiles("*.{ts,tsx,js,jsx}", srcDir);
|
|
4245
4452
|
for (const file of tsFiles) {
|
|
4246
|
-
const filePath =
|
|
4453
|
+
const filePath = path14.join(srcDir, file);
|
|
4247
4454
|
const content = await FileUtils.read(filePath);
|
|
4248
4455
|
const pathRegex = /"(\/api\/[^"]+)"/g;
|
|
4249
4456
|
let match;
|
|
@@ -4360,7 +4567,7 @@ var init_detect_deps = __esm({
|
|
|
4360
4567
|
process.exit(1);
|
|
4361
4568
|
}
|
|
4362
4569
|
for (const spec of specs) {
|
|
4363
|
-
const specPath =
|
|
4570
|
+
const specPath = path14.join(specsDir, spec);
|
|
4364
4571
|
logger.step(`\u5904\u7406: ${spec}`);
|
|
4365
4572
|
await detectDependencies(specPath);
|
|
4366
4573
|
logger.newLine();
|
|
@@ -4387,10 +4594,10 @@ var init_detect_deps = __esm({
|
|
|
4387
4594
|
|
|
4388
4595
|
// src/commands/sync-memory.ts
|
|
4389
4596
|
import { Command as Command10 } from "commander";
|
|
4390
|
-
import
|
|
4597
|
+
import path15 from "path";
|
|
4391
4598
|
async function syncFeatureInventory(aiMemoryFile, projectDir) {
|
|
4392
4599
|
logger.step("\u540C\u6B65\u529F\u80FD\u6E05\u5355...");
|
|
4393
|
-
const specsDir =
|
|
4600
|
+
const specsDir = path15.join(projectDir, "docs/specs");
|
|
4394
4601
|
const exists = await FileUtils.exists(specsDir);
|
|
4395
4602
|
if (!exists) {
|
|
4396
4603
|
return;
|
|
@@ -4405,7 +4612,7 @@ async function syncFeatureInventory(aiMemoryFile, projectDir) {
|
|
|
4405
4612
|
for (const specFile of specs) {
|
|
4406
4613
|
const name = specFile.replace(".md", "");
|
|
4407
4614
|
const displayName = name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
4408
|
-
const specPath =
|
|
4615
|
+
const specPath = path15.join(specsDir, specFile);
|
|
4409
4616
|
const content = await FileUtils.read(specPath);
|
|
4410
4617
|
const status = parseSpecStatus3(content);
|
|
4411
4618
|
const progress = getSpecProgress(content);
|
|
@@ -4423,7 +4630,7 @@ async function syncFeatureInventory(aiMemoryFile, projectDir) {
|
|
|
4423
4630
|
}
|
|
4424
4631
|
async function syncApiInventory(aiMemoryFile, projectDir) {
|
|
4425
4632
|
logger.step("\u540C\u6B65 API \u5217\u8868...");
|
|
4426
|
-
const backendDir =
|
|
4633
|
+
const backendDir = path15.join(projectDir, "backend");
|
|
4427
4634
|
const exists = await FileUtils.exists(backendDir);
|
|
4428
4635
|
if (!exists) {
|
|
4429
4636
|
return;
|
|
@@ -4433,13 +4640,13 @@ async function syncApiInventory(aiMemoryFile, projectDir) {
|
|
|
4433
4640
|
lines.push("");
|
|
4434
4641
|
lines.push("> \u672C\u90E8\u5206\u7531 team-cli \u81EA\u52A8\u626B\u63CF\u540E\u7AEF Controller \u751F\u6210");
|
|
4435
4642
|
lines.push("");
|
|
4436
|
-
const srcDir =
|
|
4643
|
+
const srcDir = path15.join(backendDir, "src");
|
|
4437
4644
|
const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
|
|
4438
4645
|
if (controllers.length === 0) {
|
|
4439
4646
|
lines.push("\u6682\u65E0 API");
|
|
4440
4647
|
} else {
|
|
4441
4648
|
for (const controllerFile of controllers) {
|
|
4442
|
-
const controllerPath =
|
|
4649
|
+
const controllerPath = path15.join(srcDir, controllerFile);
|
|
4443
4650
|
const controllerName = controllerFile.replace(".java", "");
|
|
4444
4651
|
const module = controllerName.replace(/Controller$/, "").toLowerCase();
|
|
4445
4652
|
lines.push(`### ${module} \u6A21\u5757`);
|
|
@@ -4516,7 +4723,7 @@ function extractMethodComment(content, methodName) {
|
|
|
4516
4723
|
}
|
|
4517
4724
|
async function syncDataModels(aiMemoryFile, projectDir) {
|
|
4518
4725
|
logger.step("\u540C\u6B65\u6570\u636E\u6A21\u578B...");
|
|
4519
|
-
const backendDir =
|
|
4726
|
+
const backendDir = path15.join(projectDir, "backend");
|
|
4520
4727
|
const exists = await FileUtils.exists(backendDir);
|
|
4521
4728
|
if (!exists) {
|
|
4522
4729
|
return;
|
|
@@ -4526,7 +4733,7 @@ async function syncDataModels(aiMemoryFile, projectDir) {
|
|
|
4526
4733
|
lines.push("");
|
|
4527
4734
|
lines.push("> \u672C\u90E8\u5206\u7531 team-cli \u81EA\u52A8\u626B\u63CF\u540E\u7AEF Entity \u751F\u6210");
|
|
4528
4735
|
lines.push("");
|
|
4529
|
-
const srcDir =
|
|
4736
|
+
const srcDir = path15.join(backendDir, "src");
|
|
4530
4737
|
const entities = await FileUtils.findFiles("*Entity.java", srcDir);
|
|
4531
4738
|
if (entities.length === 0) {
|
|
4532
4739
|
lines.push("\u6682\u65E0\u6570\u636E\u6A21\u578B");
|
|
@@ -4534,7 +4741,7 @@ async function syncDataModels(aiMemoryFile, projectDir) {
|
|
|
4534
4741
|
lines.push("| \u6A21\u578B | \u8BF4\u660E | \u5B57\u6BB5 | \u5173\u8054 |");
|
|
4535
4742
|
lines.push("|------|------|------|------|");
|
|
4536
4743
|
for (const entityFile of entities) {
|
|
4537
|
-
const entityPath =
|
|
4744
|
+
const entityPath = path15.join(srcDir, entityFile);
|
|
4538
4745
|
const entityName = entityFile.replace(".java", "").replace(/Entity$/, "");
|
|
4539
4746
|
const displayName = entityName.split(/(?=[A-Z])/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
4540
4747
|
const content = await FileUtils.read(entityPath);
|
|
@@ -4656,15 +4863,15 @@ async function syncTemplateVersions(aiMemoryFile, projectDir) {
|
|
|
4656
4863
|
await replaceOrInsertSection(aiMemoryFile, "## \u6A21\u677F\u7248\u672C\u4FE1\u606F", newContent);
|
|
4657
4864
|
}
|
|
4658
4865
|
function extractRepoName(repository) {
|
|
4659
|
-
let
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
const parts =
|
|
4866
|
+
let path20 = repository;
|
|
4867
|
+
path20 = path20.replace(/^https?:\/\//, "");
|
|
4868
|
+
path20 = path20.replace(/^git@/, "");
|
|
4869
|
+
const parts = path20.split("/");
|
|
4663
4870
|
if (parts.length > 1) {
|
|
4664
|
-
|
|
4871
|
+
path20 = parts.slice(1).join("/");
|
|
4665
4872
|
}
|
|
4666
|
-
|
|
4667
|
-
return
|
|
4873
|
+
path20 = path20.replace(/\.git$/, "");
|
|
4874
|
+
return path20;
|
|
4668
4875
|
}
|
|
4669
4876
|
var syncMemoryCommand;
|
|
4670
4877
|
var init_sync_memory = __esm({
|
|
@@ -4709,11 +4916,11 @@ var init_sync_memory = __esm({
|
|
|
4709
4916
|
|
|
4710
4917
|
// src/commands/check-api.ts
|
|
4711
4918
|
import { Command as Command11 } from "commander";
|
|
4712
|
-
import
|
|
4919
|
+
import path16 from "path";
|
|
4713
4920
|
import inquirer7 from "inquirer";
|
|
4714
4921
|
import { Listr as Listr6 } from "listr2";
|
|
4715
4922
|
async function checkApiConflicts(projectDir) {
|
|
4716
|
-
const backendDir =
|
|
4923
|
+
const backendDir = path16.join(projectDir, "backend");
|
|
4717
4924
|
const exists = await FileUtils.exists(backendDir);
|
|
4718
4925
|
if (!exists) {
|
|
4719
4926
|
logger.info("\u672A\u627E\u5230\u540E\u7AEF\u9879\u76EE");
|
|
@@ -4722,10 +4929,10 @@ async function checkApiConflicts(projectDir) {
|
|
|
4722
4929
|
logger.step("\u626B\u63CF\u540E\u7AEF API...");
|
|
4723
4930
|
logger.newLine();
|
|
4724
4931
|
const apiMap = /* @__PURE__ */ new Map();
|
|
4725
|
-
const srcDir =
|
|
4932
|
+
const srcDir = path16.join(backendDir, "src");
|
|
4726
4933
|
const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
|
|
4727
4934
|
for (const controllerFile of controllers) {
|
|
4728
|
-
const controllerPath =
|
|
4935
|
+
const controllerPath = path16.join(srcDir, controllerFile);
|
|
4729
4936
|
const apis = await extractApisFromController(controllerPath);
|
|
4730
4937
|
for (const api of apis) {
|
|
4731
4938
|
const key = `${api.method}:${api.path}`;
|
|
@@ -4756,8 +4963,8 @@ async function checkApiConflicts(projectDir) {
|
|
|
4756
4963
|
}
|
|
4757
4964
|
}
|
|
4758
4965
|
async function detectApiChanges(projectDir) {
|
|
4759
|
-
const backendDir =
|
|
4760
|
-
const registryFile =
|
|
4966
|
+
const backendDir = path16.join(projectDir, "backend");
|
|
4967
|
+
const registryFile = path16.join(projectDir, "docs/api-registry.md");
|
|
4761
4968
|
const registryExists = await FileUtils.exists(registryFile);
|
|
4762
4969
|
if (!registryExists) {
|
|
4763
4970
|
logger.info("API Registry \u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u53D8\u66F4\u68C0\u6D4B");
|
|
@@ -4769,10 +4976,10 @@ async function detectApiChanges(projectDir) {
|
|
|
4769
4976
|
const registryContent = await FileUtils.read(registryFile);
|
|
4770
4977
|
const existingApis = extractApisFromRegistry(registryContent);
|
|
4771
4978
|
const currentApis = /* @__PURE__ */ new Map();
|
|
4772
|
-
const srcDir =
|
|
4979
|
+
const srcDir = path16.join(backendDir, "src");
|
|
4773
4980
|
const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
|
|
4774
4981
|
for (const controllerFile of controllers) {
|
|
4775
|
-
const controllerPath =
|
|
4982
|
+
const controllerPath = path16.join(srcDir, controllerFile);
|
|
4776
4983
|
const apis = await extractApisFromController(controllerPath);
|
|
4777
4984
|
for (const api of apis) {
|
|
4778
4985
|
const key = `${api.method}:${api.path}`;
|
|
@@ -4834,9 +5041,9 @@ async function detectApiChanges(projectDir) {
|
|
|
4834
5041
|
}
|
|
4835
5042
|
}
|
|
4836
5043
|
async function generateApiRegistry(projectDir) {
|
|
4837
|
-
const registryFile =
|
|
5044
|
+
const registryFile = path16.join(projectDir, "docs/api-registry.md");
|
|
4838
5045
|
logger.step("\u626B\u63CF\u5E76\u751F\u6210 API Registry...");
|
|
4839
|
-
await FileUtils.ensureDir(
|
|
5046
|
+
await FileUtils.ensureDir(path16.dirname(registryFile));
|
|
4840
5047
|
const header = `# API Registry
|
|
4841
5048
|
|
|
4842
5049
|
> \u672C\u6587\u4EF6\u8BB0\u5F55\u6240\u6709 API \u7684\u5B9A\u4E49\u3001\u7248\u672C\u548C\u53D8\u66F4\u5386\u53F2
|
|
@@ -4865,14 +5072,14 @@ async function generateApiRegistry(projectDir) {
|
|
|
4865
5072
|
*\u6700\u540E\u66F4\u65B0: ${DateUtils.format(/* @__PURE__ */ new Date(), "YYYY-MM-DD HH:mm:ss")}*
|
|
4866
5073
|
`;
|
|
4867
5074
|
let content = header;
|
|
4868
|
-
const backendDir =
|
|
5075
|
+
const backendDir = path16.join(projectDir, "backend");
|
|
4869
5076
|
const exists = await FileUtils.exists(backendDir);
|
|
4870
5077
|
if (exists) {
|
|
4871
|
-
const srcDir =
|
|
5078
|
+
const srcDir = path16.join(backendDir, "src");
|
|
4872
5079
|
const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
|
|
4873
5080
|
const moduleMap = /* @__PURE__ */ new Map();
|
|
4874
5081
|
for (const controllerFile of controllers) {
|
|
4875
|
-
const controllerPath =
|
|
5082
|
+
const controllerPath = path16.join(srcDir, controllerFile);
|
|
4876
5083
|
const controllerName = controllerFile.replace(".java", "");
|
|
4877
5084
|
const module = controllerName.replace(/Controller$/, "").toLowerCase();
|
|
4878
5085
|
if (!moduleMap.has(module)) {
|
|
@@ -4956,10 +5163,10 @@ function extractApisFromRegistry(registryContent) {
|
|
|
4956
5163
|
let match;
|
|
4957
5164
|
while ((match = apiRegex.exec(registryContent)) !== null) {
|
|
4958
5165
|
const method = match[1];
|
|
4959
|
-
const
|
|
5166
|
+
const path20 = match[2].trim();
|
|
4960
5167
|
const description = match[3].trim();
|
|
4961
|
-
const key = `${method}:${
|
|
4962
|
-
apis.set(key, { method, path:
|
|
5168
|
+
const key = `${method}:${path20}`;
|
|
5169
|
+
apis.set(key, { method, path: path20, description });
|
|
4963
5170
|
}
|
|
4964
5171
|
return apis;
|
|
4965
5172
|
}
|
|
@@ -5047,7 +5254,7 @@ var init_check_api = __esm({
|
|
|
5047
5254
|
|
|
5048
5255
|
// src/commands/logs.ts
|
|
5049
5256
|
import { Command as Command12 } from "commander";
|
|
5050
|
-
import
|
|
5257
|
+
import path17 from "path";
|
|
5051
5258
|
import inquirer8 from "inquirer";
|
|
5052
5259
|
async function collectLogFiles(targetDir) {
|
|
5053
5260
|
const logs = [];
|
|
@@ -5055,7 +5262,7 @@ async function collectLogFiles(targetDir) {
|
|
|
5055
5262
|
const allFiles = await FileUtils.findFiles("*.md", targetDir);
|
|
5056
5263
|
const filtered = allFiles.filter((f) => f !== "index.md");
|
|
5057
5264
|
for (const file of filtered) {
|
|
5058
|
-
const filePath =
|
|
5265
|
+
const filePath = path17.join(targetDir, file);
|
|
5059
5266
|
const stat = await FileUtils.exists(filePath);
|
|
5060
5267
|
if (stat) {
|
|
5061
5268
|
logs.push(filePath);
|
|
@@ -5095,7 +5302,7 @@ var init_logs = __esm({
|
|
|
5095
5302
|
case "":
|
|
5096
5303
|
case "today": {
|
|
5097
5304
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
5098
|
-
targetDir =
|
|
5305
|
+
targetDir = path17.join(sessionsDir, today);
|
|
5099
5306
|
const todayExists = await FileUtils.exists(targetDir);
|
|
5100
5307
|
if (!todayExists) {
|
|
5101
5308
|
logger.info("\u4ECA\u65E5\u6682\u65E0\u4F1A\u8BDD\u65E5\u5FD7");
|
|
@@ -5111,7 +5318,7 @@ var init_logs = __esm({
|
|
|
5111
5318
|
break;
|
|
5112
5319
|
}
|
|
5113
5320
|
default: {
|
|
5114
|
-
targetDir =
|
|
5321
|
+
targetDir = path17.join(sessionsDir, filter);
|
|
5115
5322
|
const dateExists = await FileUtils.exists(targetDir);
|
|
5116
5323
|
if (!dateExists) {
|
|
5117
5324
|
logger.error(`\u672A\u627E\u5230\u65E5\u671F '${filter}' \u7684\u65E5\u5FD7`);
|
|
@@ -5135,7 +5342,7 @@ var init_logs = __esm({
|
|
|
5135
5342
|
process.exit(0);
|
|
5136
5343
|
}
|
|
5137
5344
|
for (let i = 0; i < logs.length; i++) {
|
|
5138
|
-
const relPath =
|
|
5345
|
+
const relPath = path17.relative(sessionsDir, logs[i]);
|
|
5139
5346
|
logger.step(`${i + 1}) ${relPath}`);
|
|
5140
5347
|
}
|
|
5141
5348
|
logger.newLine();
|
|
@@ -5175,17 +5382,17 @@ var init_logs = __esm({
|
|
|
5175
5382
|
|
|
5176
5383
|
// src/commands/update.ts
|
|
5177
5384
|
import { Command as Command13 } from "commander";
|
|
5178
|
-
import
|
|
5385
|
+
import path18 from "path";
|
|
5179
5386
|
import { execa as execa4 } from "execa";
|
|
5180
5387
|
import inquirer9 from "inquirer";
|
|
5181
|
-
import
|
|
5388
|
+
import fs5 from "fs-extra";
|
|
5182
5389
|
async function performUpdate(projectPath, updates) {
|
|
5183
5390
|
logger.newLine();
|
|
5184
5391
|
logger.info("\u5F00\u59CB\u66F4\u65B0\u6A21\u677F...");
|
|
5185
5392
|
for (const update of updates) {
|
|
5186
5393
|
const { type, info, updateOptions } = update;
|
|
5187
5394
|
const targetDir = type === "frontend" ? "frontend" : "backend";
|
|
5188
|
-
const targetPath =
|
|
5395
|
+
const targetPath = path18.join(projectPath, targetDir);
|
|
5189
5396
|
logger.newLine();
|
|
5190
5397
|
logger.step(`\u66F4\u65B0 ${type === "frontend" ? "\u524D\u7AEF" : "\u540E\u7AEF"}\u6A21\u677F...`);
|
|
5191
5398
|
if (updateOptions?.tag || updateOptions?.branch) {
|
|
@@ -5216,8 +5423,8 @@ async function performUpdate(projectPath, updates) {
|
|
|
5216
5423
|
}
|
|
5217
5424
|
}
|
|
5218
5425
|
const ref = updateOptions?.tag || updateOptions?.branch || "HEAD";
|
|
5219
|
-
const backupDir =
|
|
5220
|
-
await
|
|
5426
|
+
const backupDir = path18.join(projectPath, `.backup-${Date.now()}`);
|
|
5427
|
+
await fs5.copy(targetPath, path18.join(backupDir, targetDir));
|
|
5221
5428
|
logger.info(`\u5DF2\u521B\u5EFA\u5907\u4EFD: ${backupDir}`);
|
|
5222
5429
|
if (updateOptions?.dryRun) {
|
|
5223
5430
|
logger.info("[Dry Run] \u5C06\u4F1A\u66F4\u65B0\u5230\u4EE5\u4E0B\u7248\u672C:");
|
|
@@ -5227,7 +5434,7 @@ async function performUpdate(projectPath, updates) {
|
|
|
5227
5434
|
continue;
|
|
5228
5435
|
}
|
|
5229
5436
|
try {
|
|
5230
|
-
const tempDir =
|
|
5437
|
+
const tempDir = path18.join(projectPath, `.template-update-${Date.now()}`);
|
|
5231
5438
|
await execa4("git", ["clone", "--depth=1", "--branch", ref, info.repository, tempDir], {
|
|
5232
5439
|
stdio: "pipe"
|
|
5233
5440
|
});
|
|
@@ -5244,17 +5451,17 @@ async function performUpdate(projectPath, updates) {
|
|
|
5244
5451
|
const currentFiles = await FileUtils.findFiles("*", targetPath);
|
|
5245
5452
|
for (const file of currentFiles) {
|
|
5246
5453
|
if (!keepFiles.includes(file)) {
|
|
5247
|
-
const filePath =
|
|
5454
|
+
const filePath = path18.join(targetPath, file);
|
|
5248
5455
|
try {
|
|
5249
|
-
await
|
|
5456
|
+
await fs5.remove(filePath);
|
|
5250
5457
|
} catch {
|
|
5251
5458
|
}
|
|
5252
5459
|
}
|
|
5253
5460
|
}
|
|
5254
|
-
await
|
|
5461
|
+
await fs5.copy(tempDir, targetPath, {
|
|
5255
5462
|
filter: (src) => !src.includes(".git")
|
|
5256
5463
|
});
|
|
5257
|
-
await
|
|
5464
|
+
await fs5.remove(tempDir);
|
|
5258
5465
|
await updateTemplateVersion(projectPath, type, commit.trim(), {
|
|
5259
5466
|
tag: updateOptions?.tag || latestTag,
|
|
5260
5467
|
branch: updateOptions?.branch
|
|
@@ -5265,9 +5472,9 @@ async function performUpdate(projectPath, updates) {
|
|
|
5265
5472
|
} catch (error) {
|
|
5266
5473
|
logger.error(`\u66F4\u65B0\u5931\u8D25: ${error.message}`);
|
|
5267
5474
|
logger.info("\u6B63\u5728\u6062\u590D\u5907\u4EFD...");
|
|
5268
|
-
await
|
|
5269
|
-
await
|
|
5270
|
-
await
|
|
5475
|
+
await fs5.remove(targetPath);
|
|
5476
|
+
await fs5.copy(path18.join(backupDir, targetDir), targetPath);
|
|
5477
|
+
await fs5.remove(backupDir);
|
|
5271
5478
|
logger.info("\u5DF2\u6062\u590D\u5230\u66F4\u65B0\u524D\u7684\u72B6\u6001");
|
|
5272
5479
|
}
|
|
5273
5480
|
}
|
|
@@ -5871,6 +6078,9 @@ var init_diff = __esm({
|
|
|
5871
6078
|
var index_exports = {};
|
|
5872
6079
|
import { Command as Command16 } from "commander";
|
|
5873
6080
|
import chalk4 from "chalk";
|
|
6081
|
+
import fs6 from "fs-extra";
|
|
6082
|
+
import path19 from "path";
|
|
6083
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5874
6084
|
function showHelp() {
|
|
5875
6085
|
console.log("");
|
|
5876
6086
|
logger.header("team-cli - AI-Native \u56E2\u961F\u7814\u53D1\u811A\u624B\u67B6");
|
|
@@ -5925,7 +6135,7 @@ function showHelp() {
|
|
|
5925
6135
|
console.log(chalk4.gray("\u66F4\u591A\u4FE1\u606F: https://github.com/yungu/team-cli"));
|
|
5926
6136
|
console.log("");
|
|
5927
6137
|
}
|
|
5928
|
-
var program;
|
|
6138
|
+
var __dirname2, pkg, program;
|
|
5929
6139
|
var init_index = __esm({
|
|
5930
6140
|
"src/index.ts"() {
|
|
5931
6141
|
"use strict";
|
|
@@ -5947,8 +6157,10 @@ var init_index = __esm({
|
|
|
5947
6157
|
init_update();
|
|
5948
6158
|
init_config();
|
|
5949
6159
|
init_diff();
|
|
6160
|
+
__dirname2 = path19.dirname(fileURLToPath2(import.meta.url));
|
|
6161
|
+
pkg = fs6.readJsonSync(path19.join(__dirname2, "../package.json"));
|
|
5950
6162
|
program = new Command16();
|
|
5951
|
-
program.name("team-cli").description("AI-Native \u56E2\u961F\u7814\u53D1\u811A\u624B\u67B6").version(
|
|
6163
|
+
program.name("team-cli").description("AI-Native \u56E2\u961F\u7814\u53D1\u811A\u624B\u67B6").version(pkg.version);
|
|
5952
6164
|
program.option("-v, --verbose", "\u8BE6\u7EC6\u8F93\u51FA\u6A21\u5F0F").option("--debug", "\u8C03\u8BD5\u6A21\u5F0F");
|
|
5953
6165
|
program.addCommand(initCommand);
|
|
5954
6166
|
program.addCommand(splitPrdCommand);
|