@anren-utils/mcp-audit 1.0.0

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.
Files changed (115) hide show
  1. package/.editorconfig +13 -0
  2. package/dist/audit/auditUtils.d.ts +12 -0
  3. package/dist/audit/auditUtils.d.ts.map +1 -0
  4. package/dist/audit/auditUtils.js +22 -0
  5. package/dist/audit/auditUtils.js.map +1 -0
  6. package/dist/audit/currentAudit.d.ts +53 -0
  7. package/dist/audit/currentAudit.d.ts.map +1 -0
  8. package/dist/audit/currentAudit.js +54 -0
  9. package/dist/audit/currentAudit.js.map +1 -0
  10. package/dist/audit/getDepChain.d.ts +16 -0
  11. package/dist/audit/getDepChain.d.ts.map +1 -0
  12. package/dist/audit/getDepChain.js +60 -0
  13. package/dist/audit/getDepChain.js.map +1 -0
  14. package/dist/audit/index.d.ts +11 -0
  15. package/dist/audit/index.d.ts.map +1 -0
  16. package/dist/audit/index.js +64 -0
  17. package/dist/audit/index.js.map +1 -0
  18. package/dist/audit/normalizeAuditResult.d.ts +13 -0
  19. package/dist/audit/normalizeAuditResult.d.ts.map +1 -0
  20. package/dist/audit/normalizeAuditResult.js +81 -0
  21. package/dist/audit/normalizeAuditResult.js.map +1 -0
  22. package/dist/audit/remoteAudit.d.ts +3 -0
  23. package/dist/audit/remoteAudit.d.ts.map +1 -0
  24. package/dist/audit/remoteAudit.js +24 -0
  25. package/dist/audit/remoteAudit.js.map +1 -0
  26. package/dist/generateLock/index.d.ts +17 -0
  27. package/dist/generateLock/index.d.ts.map +1 -0
  28. package/dist/generateLock/index.js +141 -0
  29. package/dist/generateLock/index.js.map +1 -0
  30. package/dist/index.d.ts +7 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +48 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/mcpServer.d.ts +2 -0
  35. package/dist/mcpServer.d.ts.map +1 -0
  36. package/dist/mcpServer.js +34 -0
  37. package/dist/mcpServer.js.map +1 -0
  38. package/dist/parseProject/detectPackageManager.d.ts +8 -0
  39. package/dist/parseProject/detectPackageManager.d.ts.map +1 -0
  40. package/dist/parseProject/detectPackageManager.js +22 -0
  41. package/dist/parseProject/detectPackageManager.js.map +1 -0
  42. package/dist/parseProject/index.d.ts +11 -0
  43. package/dist/parseProject/index.d.ts.map +1 -0
  44. package/dist/parseProject/index.js +20 -0
  45. package/dist/parseProject/index.js.map +1 -0
  46. package/dist/parseProject/parseLocalProject.d.ts +17 -0
  47. package/dist/parseProject/parseLocalProject.d.ts.map +1 -0
  48. package/dist/parseProject/parseLocalProject.js +28 -0
  49. package/dist/parseProject/parseLocalProject.js.map +1 -0
  50. package/dist/parseProject/parseLocalWorkspace.d.ts +2 -0
  51. package/dist/parseProject/parseLocalWorkspace.d.ts.map +1 -0
  52. package/dist/parseProject/parseLocalWorkspace.js +2 -0
  53. package/dist/parseProject/parseLocalWorkspace.js.map +1 -0
  54. package/dist/parseProject/parseRemoteProject.d.ts +41 -0
  55. package/dist/parseProject/parseRemoteProject.d.ts.map +1 -0
  56. package/dist/parseProject/parseRemoteProject.js +180 -0
  57. package/dist/parseProject/parseRemoteProject.js.map +1 -0
  58. package/dist/parseProject/parseRemoteWorkspace.d.ts +2 -0
  59. package/dist/parseProject/parseRemoteWorkspace.d.ts.map +1 -0
  60. package/dist/parseProject/parseRemoteWorkspace.js +2 -0
  61. package/dist/parseProject/parseRemoteWorkspace.js.map +1 -0
  62. package/dist/parseProject/parseWorkspace.d.ts +19 -0
  63. package/dist/parseProject/parseWorkspace.d.ts.map +1 -0
  64. package/dist/parseProject/parseWorkspace.js +140 -0
  65. package/dist/parseProject/parseWorkspace.js.map +1 -0
  66. package/dist/render/index.d.ts +9 -0
  67. package/dist/render/index.d.ts.map +1 -0
  68. package/dist/render/index.js +24 -0
  69. package/dist/render/index.js.map +1 -0
  70. package/dist/render/markdown.d.ts +12 -0
  71. package/dist/render/markdown.d.ts.map +1 -0
  72. package/dist/render/markdown.js +16 -0
  73. package/dist/render/markdown.js.map +1 -0
  74. package/dist/render/template/audit.ejs +30 -0
  75. package/dist/render/template/detail-item.ejs +32 -0
  76. package/dist/render/template/detail.ejs +7 -0
  77. package/dist/render/template/index.ejs +8 -0
  78. package/dist/types.d.ts +371 -0
  79. package/dist/types.d.ts.map +1 -0
  80. package/dist/types.js +2 -0
  81. package/dist/types.js.map +1 -0
  82. package/dist/utils/dirUtils.d.ts +11 -0
  83. package/dist/utils/dirUtils.d.ts.map +1 -0
  84. package/dist/utils/dirUtils.js +28 -0
  85. package/dist/utils/dirUtils.js.map +1 -0
  86. package/dist/utils/index.d.ts +34 -0
  87. package/dist/utils/index.d.ts.map +1 -0
  88. package/dist/utils/index.js +74 -0
  89. package/dist/utils/index.js.map +1 -0
  90. package/eslint.config.js +38 -0
  91. package/package.json +38 -0
  92. package/src/audit/auditUtils.ts +24 -0
  93. package/src/audit/currentAudit.ts +116 -0
  94. package/src/audit/getDepChain.ts +71 -0
  95. package/src/audit/index.ts +90 -0
  96. package/src/audit/normalizeAuditResult.ts +99 -0
  97. package/src/audit/remoteAudit.ts +26 -0
  98. package/src/generateLock/index.ts +203 -0
  99. package/src/index.ts +48 -0
  100. package/src/mcpServer.ts +43 -0
  101. package/src/parseProject/detectPackageManager.ts +24 -0
  102. package/src/parseProject/index.ts +20 -0
  103. package/src/parseProject/parseLocalProject.ts +39 -0
  104. package/src/parseProject/parseRemoteProject.ts +225 -0
  105. package/src/parseProject/parseWorkspace.ts +202 -0
  106. package/src/render/index.ts +30 -0
  107. package/src/render/markdown.ts +29 -0
  108. package/src/render/template/audit.ejs +30 -0
  109. package/src/render/template/detail-item.ejs +32 -0
  110. package/src/render/template/detail.ejs +7 -0
  111. package/src/render/template/index.ejs +8 -0
  112. package/src/types.ts +429 -0
  113. package/src/utils/dirUtils.ts +31 -0
  114. package/src/utils/index.ts +88 -0
  115. package/tsconfig.json +42 -0
@@ -0,0 +1,141 @@
1
+ import fs from "fs";
2
+ import { join, dirname } from "path";
3
+ import { getReadFileUrl, runCommand } from "../utils/index.js";
4
+ /**
5
+ * @Desc: 处理 package.json 中的 workspace 依赖
6
+ * @param {Object} packageJson package.json文件内容
7
+ * @returns {Object} 处理后的 package.json 文件内容
8
+ */
9
+ function processPackageJson(packageJson) {
10
+ // 深拷贝 packageJson 以避免修改原始对象
11
+ const processedPackageJson = JSON.parse(JSON.stringify(packageJson));
12
+ // 处理 dependencies
13
+ if (processedPackageJson.dependencies) {
14
+ for (const [key, value] of Object.entries(processedPackageJson.dependencies)) {
15
+ if (typeof value === "string" && value.startsWith("workspace:")) {
16
+ delete processedPackageJson.dependencies[key];
17
+ }
18
+ }
19
+ }
20
+ // 处理 devDependencies
21
+ if (processedPackageJson.devDependencies) {
22
+ for (const [key, value] of Object.entries(processedPackageJson.devDependencies)) {
23
+ if (typeof value === "string" && value.startsWith("workspace:")) {
24
+ delete processedPackageJson.devDependencies[key];
25
+ }
26
+ }
27
+ }
28
+ // 处理 peerDependencies
29
+ if (processedPackageJson.peerDependencies) {
30
+ for (const [key, value] of Object.entries(processedPackageJson.peerDependencies)) {
31
+ if (typeof value === "string" && value.startsWith("workspace:")) {
32
+ delete processedPackageJson.peerDependencies[key];
33
+ }
34
+ }
35
+ }
36
+ // 处理 optionalDependencies
37
+ if (processedPackageJson.optionalDependencies) {
38
+ for (const [key, value] of Object.entries(processedPackageJson.optionalDependencies)) {
39
+ if (typeof value === "string" && value.startsWith("workspace:")) {
40
+ delete processedPackageJson.optionalDependencies[key];
41
+ }
42
+ }
43
+ }
44
+ return processedPackageJson;
45
+ }
46
+ /**
47
+ * @Desc: 根据子包的信息,生成子包的package.json文件
48
+ * @param {string} workDir 工作目录
49
+ * @param {string} projectRoot 项目根目录
50
+ * @param {RemoteWorkspaceInfo} subPackageInfos 子包信息
51
+ */
52
+ async function writeSubPackageJson(workDir, projectRoot, subPackageInfos) {
53
+ const { gitInfo, branchName, subPackageNames } = subPackageInfos;
54
+ // 根据subPackageNames,在workDir下创建子包目录并写入package.json文件
55
+ const dirPaths = subPackageNames.map((subPackageName) => join(workDir, subPackageName));
56
+ // 创建子包目录
57
+ dirPaths.forEach((dirPath) => {
58
+ fs.mkdirSync(dirPath, { recursive: true });
59
+ });
60
+ if (gitInfo && branchName) {
61
+ for (const subPackageName of subPackageNames) {
62
+ const filePath = subPackageName + "/package.json";
63
+ const packageJsonUrl = getReadFileUrl(gitInfo, branchName, filePath);
64
+ const subPackageJson = (await fetch(packageJsonUrl).then((resp) => resp.json()));
65
+ // 处理 package.json 中的 workspace 依赖
66
+ const processedPackageJson = processPackageJson(subPackageJson);
67
+ const packageJsonPath = join(workDir, subPackageName, "package.json");
68
+ // 将处理后的 packageJson 写入文件
69
+ await fs.promises.writeFile(packageJsonPath, JSON.stringify(processedPackageJson), "utf8");
70
+ }
71
+ }
72
+ else {
73
+ // 解析本地工程根目录下的package.json文件
74
+ for (const subPackageName of subPackageNames) {
75
+ const subPackageJsonPath = join(projectRoot, subPackageName, "package.json");
76
+ const subPackageJson = await fs.promises.readFile(subPackageJsonPath, "utf8");
77
+ const processedPackageJson = processPackageJson(JSON.parse(subPackageJson));
78
+ await fs.promises.writeFile(join(workDir, subPackageName, "package.json"), JSON.stringify(processedPackageJson), "utf8");
79
+ }
80
+ }
81
+ }
82
+ /**
83
+ * @Desc: 向工作目录添加package.json文件
84
+ * @param {string} workDir 工作目录
85
+ * @param {Object} packageJson package.json文件内容
86
+ */
87
+ async function writePackageJson(options) {
88
+ const { workDir, packageJson, subPackageInfos, projectRoot } = options;
89
+ const packageJsonPath = join(workDir, "package.json");
90
+ fs.mkdirSync(dirname(packageJsonPath), { recursive: true });
91
+ if (subPackageInfos?.subPackageNames) {
92
+ // 处理 package.json 中的 workspace 依赖
93
+ const processedPackageJson = processPackageJson(packageJson);
94
+ // 处理子包
95
+ await writeSubPackageJson(workDir, projectRoot, subPackageInfos);
96
+ // 将处理后的 packageJson 写入文件
97
+ await fs.promises.writeFile(packageJsonPath, JSON.stringify(processedPackageJson), "utf8");
98
+ }
99
+ else {
100
+ await fs.promises.writeFile(packageJsonPath, JSON.stringify(packageJson), "utf8");
101
+ }
102
+ }
103
+ /**
104
+ * @Desc: 在指定工作目录中生成lock文件
105
+ * @param {string} workDir 工作目录
106
+ */
107
+ async function createLockFile(workDir, subPackageInfos, currentPackageManager) {
108
+ // 只支持pnpm和npm
109
+ if (!subPackageInfos) {
110
+ const cmd = "npm install --package-lock-only --force";
111
+ // 在工作目录中执行命令
112
+ await runCommand(cmd, workDir);
113
+ }
114
+ else {
115
+ const { subPackageNames } = subPackageInfos;
116
+ const cmd = currentPackageManager === "pnpm"
117
+ ? `pnpm install --lockfile-only`
118
+ : `npm install --package-lock-only --force`;
119
+ // 在不同的工作目录中执行命令
120
+ for (const subPackageName of subPackageNames) {
121
+ const subPackageDir = join(workDir, subPackageName);
122
+ await runCommand(cmd, subPackageDir);
123
+ }
124
+ // 最后在工作目录中执行命令
125
+ await runCommand(cmd, workDir);
126
+ }
127
+ }
128
+ /**
129
+ * @Desc: 向工作目录添加package.json文件,然后生成lock文件
130
+ * @param {string} workDir 工作目录
131
+ * @param {Object} packageJson package.json文件内容
132
+ */
133
+ export async function generateLock(options) {
134
+ const { workDir, subPackageInfos, currentPackageManager } = options;
135
+ // 1. 将 package.json 写入工作目录
136
+ // NOTE:不管是npm还是pnpm,package.json文件基本都是相同的
137
+ await writePackageJson(options);
138
+ // 2. 生成 lock 文件
139
+ await createLockFile(workDir, subPackageInfos, currentPackageManager);
140
+ }
141
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generateLock/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 根据项目根目录,审计项目中所有的包(含项目本身)
3
+ * @param {string} projectRoot 项目根目录,可以是本地目录的绝对路径,也可以是远程仓库的URL
4
+ * @param {string} savePath 保存审计结果的文件名,审计结果是一个标准格式的markdown字符串
5
+ */
6
+ export declare function auditProject(projectRoot: string, savePath: string): Promise<void>;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,iBAiCvE"}
package/dist/index.js ADDED
@@ -0,0 +1,48 @@
1
+ import { audit } from "./audit/index.js";
2
+ import { generateLock } from "./generateLock/index.js";
3
+ import { detectPackageManager } from "./parseProject/detectPackageManager.js";
4
+ import { parseProject } from "./parseProject/index.js";
5
+ import { parseWorkspace } from "./parseProject/parseWorkspace.js";
6
+ import { render } from "./render/index.js";
7
+ import { createWorkDir, deleteWorkDir } from "./utils/dirUtils.js";
8
+ import fs from "fs";
9
+ /**
10
+ * 根据项目根目录,审计项目中所有的包(含项目本身)
11
+ * @param {string} projectRoot 项目根目录,可以是本地目录的绝对路径,也可以是远程仓库的URL
12
+ * @param {string} savePath 保存审计结果的文件名,审计结果是一个标准格式的markdown字符串
13
+ */
14
+ export async function auditProject(projectRoot, savePath) {
15
+ // 1. 创建工作目录
16
+ const workDir = await createWorkDir();
17
+ // 2. 判断项目的包管理器类型
18
+ const currentPackageManager = detectPackageManager(projectRoot);
19
+ // 3. 解析项目的package.json文件
20
+ const packageJson = await parseProject(projectRoot);
21
+ // 4· 判断项目是否是monorepo工程
22
+ const subPackageInfos = await parseWorkspace({
23
+ projectRoot,
24
+ packageJsonRoot: packageJson,
25
+ });
26
+ // 5. 向工作目录添加package.json文件,然后生成lock文件
27
+ await generateLock({
28
+ workDir,
29
+ packageJson,
30
+ subPackageInfos,
31
+ projectRoot,
32
+ currentPackageManager,
33
+ });
34
+ // 6. 对工作目录进行审计
35
+ const auditResult = await audit({
36
+ workDir,
37
+ packageJson,
38
+ subPackageInfos,
39
+ currentPackageManager,
40
+ });
41
+ // 7. 渲染审计结果
42
+ const renderedResult = await render(auditResult, packageJson);
43
+ // 8. 删除工作目录
44
+ await deleteWorkDir(workDir);
45
+ // 9. 将结果保存到指定路径
46
+ await fs.promises.writeFile(savePath, renderedResult);
47
+ }
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,QAAgB;IACtE,YAAY;IACZ,MAAM,OAAO,GAAG,MAAM,aAAa,EAAE,CAAC;IACtC,iBAAiB;IACjB,MAAM,qBAAqB,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAChE,yBAAyB;IACzB,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;IACpD,uBAAuB;IACvB,MAAM,eAAe,GAAG,MAAM,cAAc,CAAC;QAC3C,WAAW;QACX,eAAe,EAAE,WAAW;KAC7B,CAAC,CAAC;IACH,sCAAsC;IACtC,MAAM,YAAY,CAAC;QACjB,OAAO;QACP,WAAW;QACX,eAAe;QACf,WAAW;QACX,qBAAqB;KACtB,CAAC,CAAC;IACH,eAAe;IACf,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC;QAC9B,OAAO;QACP,WAAW;QACX,eAAe;QACf,qBAAqB;KACtB,CAAC,CAAC;IACH,YAAY;IACZ,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC9D,YAAY;IACZ,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;IAC7B,gBAAgB;IAChB,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mcpServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpServer.d.ts","sourceRoot":"","sources":["../src/mcpServer.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import { auditProject } from "./index.js";
5
+ const server = new McpServer({
6
+ name: "audit-server",
7
+ title: "前端工程安全审计服务",
8
+ version: "0.1.0",
9
+ });
10
+ server.registerTool("auditProject", {
11
+ title: "审计前端工程",
12
+ description: "审计前端工程的所有直接和间接依赖,得到安全审计结果。支持本地工程的审计,也支持远程仓库的审计。审计结果为标准格式的markdown字符串,不用修改,直接用于展示即可。",
13
+ inputSchema: {
14
+ projectRoot: z
15
+ .string()
16
+ .describe("本地工程的根路径,或者远程仓库的URL地址"),
17
+ savePath: z
18
+ .string()
19
+ .describe("保存审计结果的路径,传递当前工程的根路径下的工程明audit.md,如果没有当前工程,则传递桌面路径下的audit.md(注意,桌面路径必须传入绝对路径)"),
20
+ },
21
+ }, async ({ projectRoot, savePath }) => {
22
+ await auditProject(projectRoot, savePath);
23
+ return {
24
+ content: [
25
+ {
26
+ type: "text",
27
+ text: `审计完成,结果已保存到: ${savePath}`,
28
+ },
29
+ ],
30
+ };
31
+ });
32
+ const transport = new StdioServerTransport();
33
+ server.connect(transport);
34
+ //# sourceMappingURL=mcpServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpServer.js","sourceRoot":"","sources":["../src/mcpServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,YAAY;IACnB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;IACE,KAAK,EAAE,QAAQ;IACf,WAAW,EACT,qFAAqF;IACvF,WAAW,EAAE;QACX,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,QAAQ,CAAC,uBAAuB,CAAC;QACpC,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,CACP,+EAA+E,CAChF;KACJ;CACF,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE;IAClC,MAAM,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC1C,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,gBAAgB,QAAQ,EAAE;aACjC;SACF;KACF,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { PackageManager } from "../types.js";
2
+ /**
3
+ * 检测当前项目使用的包管理器
4
+ * @param projectRoot - 项目根目录
5
+ * @returns 'npm' | 'pnpm' | 'yarn',默认返回 'npm'
6
+ */
7
+ export declare function detectPackageManager(projectRoot: string): PackageManager;
8
+ //# sourceMappingURL=detectPackageManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detectPackageManager.d.ts","sourceRoot":"","sources":["../../src/parseProject/detectPackageManager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAcxE"}
@@ -0,0 +1,22 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ /**
4
+ * 检测当前项目使用的包管理器
5
+ * @param projectRoot - 项目根目录
6
+ * @returns 'npm' | 'pnpm' | 'yarn',默认返回 'npm'
7
+ */
8
+ export function detectPackageManager(projectRoot) {
9
+ // 检查锁文件
10
+ if (fs.existsSync(path.join(projectRoot, "pnpm-lock.yaml"))) {
11
+ return "pnpm";
12
+ }
13
+ if (fs.existsSync(path.join(projectRoot, "package-lock.json"))) {
14
+ return "npm";
15
+ }
16
+ if (fs.existsSync(path.join(projectRoot, "yarn.lock"))) {
17
+ return "yarn";
18
+ }
19
+ // 默认返回 npm 作为兜底
20
+ return "npm";
21
+ }
22
+ //# sourceMappingURL=detectPackageManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detectPackageManager.js","sourceRoot":"","sources":["../../src/parseProject/detectPackageManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,QAAQ;IACR,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC;QAC/D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;QACvD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,gBAAgB;IAChB,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 解析工程根目录下的package.json文件,得到文件内容
3
+ * @param {string} projectRoot 工程本地的根目录或远程仓库的URL
4
+ * @example
5
+ * parseProject('/path/to/local/project');
6
+ * parseProject('https://github.com/webpack/webpack');
7
+ * @returns {Promise<Object>} 返回解析后的package.json内容
8
+ * @throws {Error} 如果解析失败或文件不存在
9
+ */
10
+ export declare function parseProject(projectRoot: string): Promise<import("../types.js").PackageJsonInfo>;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parseProject/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,kDAO/C"}
@@ -0,0 +1,20 @@
1
+ import { parseLocalProject } from "./parseLocalProject.js";
2
+ import { parseRemoteProject } from "./parseRemoteProject.js";
3
+ /**
4
+ * 解析工程根目录下的package.json文件,得到文件内容
5
+ * @param {string} projectRoot 工程本地的根目录或远程仓库的URL
6
+ * @example
7
+ * parseProject('/path/to/local/project');
8
+ * parseProject('https://github.com/webpack/webpack');
9
+ * @returns {Promise<Object>} 返回解析后的package.json内容
10
+ * @throws {Error} 如果解析失败或文件不存在
11
+ */
12
+ export function parseProject(projectRoot) {
13
+ // 分辨是本地工程还是远程仓库
14
+ if (projectRoot.startsWith("http://") || projectRoot.startsWith("https://")) {
15
+ // 远程项目
16
+ return parseRemoteProject(projectRoot);
17
+ }
18
+ return parseLocalProject(projectRoot);
19
+ }
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parseProject/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,gBAAgB;IAChB,IAAI,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5E,OAAO;QACP,OAAO,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,iBAAiB,CAAC,WAAW,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { PackageJsonInfo } from "../types.js";
2
+ /**
3
+ * @Desc: 解析本地工程根目录下的package.json文件
4
+ * @param {string} projectRoot 本地工程的根目录
5
+ * @return {Promise<Object>} 返回解析后的package.json内容
6
+ */
7
+ export declare function parseLocalProject(projectRoot: string): Promise<PackageJsonInfo>;
8
+ /**
9
+ * @Desc: 解析本地monorepo工程根目录下的package.json文件
10
+ * @param {string} projectRoot 本地工程的根目录
11
+ * @param {string[]} workspaceNames 工作空间名称列表,每个元素为一个子包的名称
12
+ * @return {Promise<Object[]>} 返回解析后的package.json内容列表
13
+ */
14
+ export declare function parseMonorepoProject(projectRoot: string, workspaceNames: string[]): Promise<{
15
+ [x: string]: Object;
16
+ }[]>;
17
+ //# sourceMappingURL=parseLocalProject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseLocalProject.d.ts","sourceRoot":"","sources":["../../src/parseProject/parseLocalProject.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,4BAI1D;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EAAE;;KAezB"}
@@ -0,0 +1,28 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ /**
4
+ * @Desc: 解析本地工程根目录下的package.json文件
5
+ * @param {string} projectRoot 本地工程的根目录
6
+ * @return {Promise<Object>} 返回解析后的package.json内容
7
+ */
8
+ export async function parseLocalProject(projectRoot) {
9
+ const packageJsonPath = path.join(projectRoot, "package.json");
10
+ const json = await fs.promises.readFile(packageJsonPath, "utf8");
11
+ return JSON.parse(json);
12
+ }
13
+ /**
14
+ * @Desc: 解析本地monorepo工程根目录下的package.json文件
15
+ * @param {string} projectRoot 本地工程的根目录
16
+ * @param {string[]} workspaceNames 工作空间名称列表,每个元素为一个子包的名称
17
+ * @return {Promise<Object[]>} 返回解析后的package.json内容列表
18
+ */
19
+ export async function parseMonorepoProject(projectRoot, workspaceNames) {
20
+ // 获取workspaceNames对应的package.json文件内容
21
+ const packageJsonList = await Promise.all(workspaceNames.map(async (workspaceName) => {
22
+ const packageJsonPath = path.join(projectRoot, workspaceName, "package.json");
23
+ const json = await fs.promises.readFile(packageJsonPath, "utf8");
24
+ return { [workspaceName]: JSON.parse(json) };
25
+ }));
26
+ return packageJsonList;
27
+ }
28
+ //# sourceMappingURL=parseLocalProject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseLocalProject.js","sourceRoot":"","sources":["../../src/parseProject/parseLocalProject.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,WAAmB;IACzD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACjE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAoB,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,WAAmB,EACnB,cAAwB;IAExB,sCAAsC;IACtC,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,CACvC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;QACzC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAC/B,WAAW,EACX,aAAa,EACb,cAAc,CACf,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QACjE,OAAO,EAAE,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAW,EAAE,CAAC;IACzD,CAAC,CAAC,CACH,CAAC;IACF,OAAO,eAAe,CAAC;AACzB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parseLocalWorkspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseLocalWorkspace.d.ts","sourceRoot":"","sources":["../../src/parseProject/parseLocalWorkspace.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parseLocalWorkspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseLocalWorkspace.js","sourceRoot":"","sources":["../../src/parseProject/parseLocalWorkspace.ts"],"names":[],"mappings":""}
@@ -0,0 +1,41 @@
1
+ import type { PackageJsonInfo } from "../types.js";
2
+ export interface RemoteProjectUrlInfo {
3
+ owner: string;
4
+ repo: string;
5
+ path: string;
6
+ platform: string;
7
+ originalUrl: string;
8
+ }
9
+ export interface PackageJsonUrlInfo {
10
+ branchName: string;
11
+ packageJsonUrl: string;
12
+ }
13
+ /**
14
+ * 解析 Git 仓库 URL,提取 owner、repo、platform 和后续路径
15
+ * 支持格式:
16
+ * - https://github.com/owner/repo
17
+ * - https://github.com/owner/repo/tree/branch
18
+ * - https://github.com/owner/repo/blame
19
+ * - https://gitee.com/he_kai1/creat-exam-ts
20
+ * - https://gitee.com/he_kai1/creat-exam-ts/tree/dev/
21
+ * - https://gitlab.com/owner/repo
22
+ * - https://gitlab.com/owner/repo/-/tree/branch
23
+ * - ...
24
+ * @param {string} url - Git 仓库 URL
25
+ * @returns {Object} { owner, repo, path, platform, originalUrl }
26
+ * @throws {Error} 如果 URL 格式不合法或无法解析
27
+ */
28
+ export declare function parseGitUrl(url: string): RemoteProjectUrlInfo;
29
+ /**
30
+ * @Desc: 获取 Git 仓库的 package.json URL
31
+ * @return {string} package.json 的 URL
32
+ * @param {Object} gitUrlInfo - 解析后的 Git 仓库信息 { owner, repo, path, platform }
33
+ */
34
+ export declare function getPackageJsonUrl(gitUrlInfo: RemoteProjectUrlInfo): Promise<PackageJsonUrlInfo>;
35
+ /**
36
+ * @Desc: 获取远程仓库的 package.json文件内容
37
+ * @return {*}
38
+ * @param {string} gitUrl
39
+ */
40
+ export declare function parseRemoteProject(gitUrl: string): Promise<PackageJsonInfo>;
41
+ //# sourceMappingURL=parseRemoteProject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseRemoteProject.d.ts","sourceRoot":"","sources":["../../src/parseProject/parseRemoteProject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,wBAgDtC;AAkFD;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,oBAAoB,+BAYvE;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,4BAOtD"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * 解析 Git 仓库 URL,提取 owner、repo、platform 和后续路径
3
+ * 支持格式:
4
+ * - https://github.com/owner/repo
5
+ * - https://github.com/owner/repo/tree/branch
6
+ * - https://github.com/owner/repo/blame
7
+ * - https://gitee.com/he_kai1/creat-exam-ts
8
+ * - https://gitee.com/he_kai1/creat-exam-ts/tree/dev/
9
+ * - https://gitlab.com/owner/repo
10
+ * - https://gitlab.com/owner/repo/-/tree/branch
11
+ * - ...
12
+ * @param {string} url - Git 仓库 URL
13
+ * @returns {Object} { owner, repo, path, platform, originalUrl }
14
+ * @throws {Error} 如果 URL 格式不合法或无法解析
15
+ */
16
+ export function parseGitUrl(url) {
17
+ try {
18
+ const parsedUrl = new URL(url);
19
+ const hostname = parsedUrl.hostname;
20
+ // 确定平台
21
+ let platform;
22
+ if (hostname === "github.com" || hostname.endsWith(".github.com")) {
23
+ platform = "github";
24
+ }
25
+ else if (hostname === "gitee.com" || hostname.endsWith(".gitee.com")) {
26
+ platform = "gitee";
27
+ }
28
+ else if (hostname === "gitlab.com" || hostname.endsWith(".gitlab.com")) {
29
+ platform = "gitlab";
30
+ }
31
+ else {
32
+ platform = "unknown";
33
+ }
34
+ // 获取路径并去除空字符串(如开头的 /)
35
+ const parts = parsedUrl.pathname.split("/").filter(Boolean);
36
+ // 至少需要 owner(项目所属者) 和 repo(项目名称) 两段
37
+ // https://github.com/anren-hk/slt-erp
38
+ if (parts.length < 2) {
39
+ throw new Error("Invalid repository URL: insufficient path segments");
40
+ }
41
+ const owner = parts[0];
42
+ const repo = parts[1];
43
+ // https://github.com/anren-hk/webpack-vue-create/tree/gh-pages
44
+ const restPath = parts.slice(2); // 剩余路径,如 ['tree', 'v5.2.2'],即分支名称或者版本号
45
+ // 构造 path:如果有后续路径,则以 '/' 开头拼接;否则为空字符串
46
+ const path = restPath.length > 0 ? "/" + restPath.join("/") : "";
47
+ const projectUrlInfo = {
48
+ owner,
49
+ repo,
50
+ path,
51
+ platform,
52
+ originalUrl: url,
53
+ };
54
+ return projectUrlInfo;
55
+ }
56
+ catch (error) {
57
+ if (error instanceof TypeError) {
58
+ throw new Error("Invalid URL: malformed or missing");
59
+ }
60
+ throw error;
61
+ }
62
+ }
63
+ /**
64
+ * @Desc: 获取 GitHub 仓库的 package.json URL
65
+ */
66
+ async function getGithubPackageJsonUrl(projectUrlInfo) {
67
+ const { owner, repo, path } = projectUrlInfo;
68
+ let branchName;
69
+ // 如果path以 /tree/ 开头,则表示是分支路径,如 /tree/v5.2.2或者/tree/dev,则取分支名称 v5.2.2
70
+ if (path.startsWith("/tree/")) {
71
+ const pathParts = path.split("/").filter(Boolean);
72
+ branchName = pathParts[1];
73
+ }
74
+ else {
75
+ // 通过 API 获取仓库信息,获取默认分支名称
76
+ const url = `https://api.github.com/repos/${owner}/${repo}`;
77
+ const info = (await fetch(url).then((resp) => resp.json()));
78
+ branchName = info.default_branch;
79
+ }
80
+ return {
81
+ branchName,
82
+ packageJsonUrl: `https://raw.githubusercontent.com/${owner}/${repo}/${branchName}/package.json`,
83
+ };
84
+ }
85
+ /**
86
+ * @Desc: 获取 Gitee 仓库的 package.json URL
87
+ */
88
+ async function getGiteePackageJsonUrl(projectUrlInfo) {
89
+ const { owner, repo, path } = projectUrlInfo;
90
+ let branchName;
91
+ if (path.startsWith("/tree/")) {
92
+ const pathParts = path.split("/").filter(Boolean);
93
+ branchName = pathParts[1];
94
+ }
95
+ else {
96
+ // 通过 API 获取仓库信息,获取默认分支名称
97
+ const url = `https://gitee.com/api/v5/repos/${owner}/${repo}`;
98
+ const info = (await fetch(url).then((resp) => resp.json()));
99
+ branchName = info.default_branch;
100
+ }
101
+ return {
102
+ branchName,
103
+ packageJsonUrl: `https://gitee.com/${owner}/${repo}/raw/${branchName}/package.json`,
104
+ };
105
+ }
106
+ /**
107
+ * @Desc: 获取 GitLab 仓库的 package.json URL
108
+ */
109
+ async function getGitlabPackageJsonUrl(projectUrlInfo) {
110
+ const { owner, repo, path } = projectUrlInfo;
111
+ let branchName;
112
+ if (path.startsWith("/tree/")) {
113
+ const pathParts = path.split("/").filter(Boolean);
114
+ branchName = `${pathParts[1]}`;
115
+ }
116
+ else {
117
+ // 通过 API 获取仓库信息,获取默认分支名称
118
+ // TODO:地址可能有问题
119
+ const url = `https://gitlab.com/api/v4/projects/${owner}/${repo}`;
120
+ const info = (await fetch(url).then((resp) => resp.json()));
121
+ branchName = info.default_branch;
122
+ }
123
+ return {
124
+ branchName,
125
+ packageJsonUrl: `https://gitlab.com/${owner}/${repo}/-/raw/${branchName}/package.json`,
126
+ };
127
+ }
128
+ /**
129
+ * @Desc: 获取 Git 仓库的 package.json URL
130
+ * @return {string} package.json 的 URL
131
+ * @param {Object} gitUrlInfo - 解析后的 Git 仓库信息 { owner, repo, path, platform }
132
+ */
133
+ export async function getPackageJsonUrl(gitUrlInfo) {
134
+ // 具体是何种远程仓库,根据平台选择不同的 URL 构造函数
135
+ switch (gitUrlInfo.platform) {
136
+ case "github":
137
+ return await getGithubPackageJsonUrl(gitUrlInfo);
138
+ case "gitee":
139
+ return await getGiteePackageJsonUrl(gitUrlInfo);
140
+ case "gitlab":
141
+ return await getGitlabPackageJsonUrl(gitUrlInfo);
142
+ default:
143
+ throw new Error(`Unsupported platform: ${gitUrlInfo.platform}`);
144
+ }
145
+ }
146
+ /**
147
+ * @Desc: 获取远程仓库的 package.json文件内容
148
+ * @return {*}
149
+ * @param {string} gitUrl
150
+ */
151
+ export async function parseRemoteProject(gitUrl) {
152
+ const gitInfo = parseGitUrl(gitUrl);
153
+ const { packageJsonUrl } = await getPackageJsonUrl(gitInfo);
154
+ // 返回json
155
+ return (await fetch(packageJsonUrl).then((resp) => resp.json()));
156
+ }
157
+ /**
158
+ * @Desc: 获取 GitHub 仓库的 package.json URL
159
+ * @param {Object} projectUrlInfo - 解析后的 Git 仓库信息 { owner, repo, path, platform }
160
+ * @param {string[]} workspaceNames - 工作空间名称列表,每个元素为一个子包的名称
161
+ * @return {Promise<string>} package.json 的 URL
162
+ */
163
+ async function getGithubSubPackagePackageJsonUrl(projectUrlInfo, workspaceNames) {
164
+ const { owner, repo, path } = projectUrlInfo;
165
+ let branchName;
166
+ // 如果path以 /tree/ 开头,则表示是分支路径,如 /tree/v5.2.2或者/tree/dev,则取分支名称 v5.2.2
167
+ if (path.startsWith("/tree/")) {
168
+ const pathParts = path.split("/").filter(Boolean);
169
+ branchName = pathParts[1];
170
+ }
171
+ else {
172
+ // 通过 API 获取仓库信息,获取默认分支名称
173
+ const url = `https://api.github.com/repos/${owner}/${repo}`;
174
+ const info = (await fetch(url).then((resp) => resp.json()));
175
+ branchName = info.default_branch;
176
+ }
177
+ // return `https://raw.githubusercontent.com/${owner}/${repo}/${branchName}/package.json`;
178
+ return `https://raw.githubusercontent.com/anren-hk/slt-erp/main/packages/net/package.json`;
179
+ }
180
+ //# sourceMappingURL=parseRemoteProject.js.map