apifox-workspace-mcp 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 (125) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +22 -0
  3. package/README.md +380 -0
  4. package/config/apifox-mcp.json.example +5 -0
  5. package/dist/__tests__/logger.test.d.ts +2 -0
  6. package/dist/__tests__/logger.test.d.ts.map +1 -0
  7. package/dist/__tests__/logger.test.js +42 -0
  8. package/dist/__tests__/logger.test.js.map +1 -0
  9. package/dist/__tests__/types.test.d.ts +2 -0
  10. package/dist/__tests__/types.test.d.ts.map +1 -0
  11. package/dist/__tests__/types.test.js +30 -0
  12. package/dist/__tests__/types.test.js.map +1 -0
  13. package/dist/__tests__/url-parser.test.d.ts +2 -0
  14. package/dist/__tests__/url-parser.test.d.ts.map +1 -0
  15. package/dist/__tests__/url-parser.test.js +27 -0
  16. package/dist/__tests__/url-parser.test.js.map +1 -0
  17. package/dist/core/client/apifox.d.ts +62 -0
  18. package/dist/core/client/apifox.d.ts.map +1 -0
  19. package/dist/core/client/apifox.js +87 -0
  20. package/dist/core/client/apifox.js.map +1 -0
  21. package/dist/core/client/index.d.ts +6 -0
  22. package/dist/core/client/index.d.ts.map +1 -0
  23. package/dist/core/client/index.js +6 -0
  24. package/dist/core/client/index.js.map +1 -0
  25. package/dist/core/client/mcp-bridge.d.ts +55 -0
  26. package/dist/core/client/mcp-bridge.d.ts.map +1 -0
  27. package/dist/core/client/mcp-bridge.js +345 -0
  28. package/dist/core/client/mcp-bridge.js.map +1 -0
  29. package/dist/core/config/index.d.ts +5 -0
  30. package/dist/core/config/index.d.ts.map +1 -0
  31. package/dist/core/config/index.js +5 -0
  32. package/dist/core/config/index.js.map +1 -0
  33. package/dist/core/config/manager.d.ts +132 -0
  34. package/dist/core/config/manager.d.ts.map +1 -0
  35. package/dist/core/config/manager.js +298 -0
  36. package/dist/core/config/manager.js.map +1 -0
  37. package/dist/core/context-store.d.ts +46 -0
  38. package/dist/core/context-store.d.ts.map +1 -0
  39. package/dist/core/context-store.js +82 -0
  40. package/dist/core/context-store.js.map +1 -0
  41. package/dist/core/generator/artifact.d.ts +20 -0
  42. package/dist/core/generator/artifact.d.ts.map +1 -0
  43. package/dist/core/generator/artifact.js +127 -0
  44. package/dist/core/generator/artifact.js.map +1 -0
  45. package/dist/core/generator/index.d.ts +6 -0
  46. package/dist/core/generator/index.d.ts.map +1 -0
  47. package/dist/core/generator/index.js +5 -0
  48. package/dist/core/generator/index.js.map +1 -0
  49. package/dist/core/index.d.ts +11 -0
  50. package/dist/core/index.d.ts.map +1 -0
  51. package/dist/core/index.js +16 -0
  52. package/dist/core/index.js.map +1 -0
  53. package/dist/core/intent.d.ts +14 -0
  54. package/dist/core/intent.d.ts.map +1 -0
  55. package/dist/core/intent.js +80 -0
  56. package/dist/core/intent.js.map +1 -0
  57. package/dist/core/parser/index.d.ts +6 -0
  58. package/dist/core/parser/index.d.ts.map +1 -0
  59. package/dist/core/parser/index.js +5 -0
  60. package/dist/core/parser/index.js.map +1 -0
  61. package/dist/core/parser/url.d.ts +76 -0
  62. package/dist/core/parser/url.d.ts.map +1 -0
  63. package/dist/core/parser/url.js +232 -0
  64. package/dist/core/parser/url.js.map +1 -0
  65. package/dist/lib/env.d.ts +17 -0
  66. package/dist/lib/env.d.ts.map +1 -0
  67. package/dist/lib/env.js +98 -0
  68. package/dist/lib/env.js.map +1 -0
  69. package/dist/lib/errors.d.ts +39 -0
  70. package/dist/lib/errors.d.ts.map +1 -0
  71. package/dist/lib/errors.js +59 -0
  72. package/dist/lib/errors.js.map +1 -0
  73. package/dist/lib/index.d.ts +9 -0
  74. package/dist/lib/index.d.ts.map +1 -0
  75. package/dist/lib/index.js +12 -0
  76. package/dist/lib/index.js.map +1 -0
  77. package/dist/lib/logger.d.ts +27 -0
  78. package/dist/lib/logger.d.ts.map +1 -0
  79. package/dist/lib/logger.js +79 -0
  80. package/dist/lib/logger.js.map +1 -0
  81. package/dist/lib/project-root.d.ts +8 -0
  82. package/dist/lib/project-root.d.ts.map +1 -0
  83. package/dist/lib/project-root.js +46 -0
  84. package/dist/lib/project-root.js.map +1 -0
  85. package/dist/server/handlers/assistant.d.ts +20 -0
  86. package/dist/server/handlers/assistant.d.ts.map +1 -0
  87. package/dist/server/handlers/assistant.js +71 -0
  88. package/dist/server/handlers/assistant.js.map +1 -0
  89. package/dist/server/handlers/generate-artifacts.d.ts +31 -0
  90. package/dist/server/handlers/generate-artifacts.d.ts.map +1 -0
  91. package/dist/server/handlers/generate-artifacts.js +75 -0
  92. package/dist/server/handlers/generate-artifacts.js.map +1 -0
  93. package/dist/server/handlers/get-interface-detail.d.ts +28 -0
  94. package/dist/server/handlers/get-interface-detail.d.ts.map +1 -0
  95. package/dist/server/handlers/get-interface-detail.js +59 -0
  96. package/dist/server/handlers/get-interface-detail.js.map +1 -0
  97. package/dist/server/handlers/index.d.ts +11 -0
  98. package/dist/server/handlers/index.d.ts.map +1 -0
  99. package/dist/server/handlers/index.js +13 -0
  100. package/dist/server/handlers/index.js.map +1 -0
  101. package/dist/server/handlers/list-projects.d.ts +12 -0
  102. package/dist/server/handlers/list-projects.d.ts.map +1 -0
  103. package/dist/server/handlers/list-projects.js +37 -0
  104. package/dist/server/handlers/list-projects.js.map +1 -0
  105. package/dist/server/handlers/parse-and-add-project.d.ts +28 -0
  106. package/dist/server/handlers/parse-and-add-project.d.ts.map +1 -0
  107. package/dist/server/handlers/parse-and-add-project.js +224 -0
  108. package/dist/server/handlers/parse-and-add-project.js.map +1 -0
  109. package/dist/server/handlers/query-interfaces.d.ts +30 -0
  110. package/dist/server/handlers/query-interfaces.d.ts.map +1 -0
  111. package/dist/server/handlers/query-interfaces.js +67 -0
  112. package/dist/server/handlers/query-interfaces.js.map +1 -0
  113. package/dist/server/handlers/utils.d.ts +51 -0
  114. package/dist/server/handlers/utils.d.ts.map +1 -0
  115. package/dist/server/handlers/utils.js +79 -0
  116. package/dist/server/handlers/utils.js.map +1 -0
  117. package/dist/server/index.d.ts +3 -0
  118. package/dist/server/index.d.ts.map +1 -0
  119. package/dist/server/index.js +248 -0
  120. package/dist/server/index.js.map +1 -0
  121. package/dist/types/index.d.ts +119 -0
  122. package/dist/types/index.d.ts.map +1 -0
  123. package/dist/types/index.js +19 -0
  124. package/dist/types/index.js.map +1 -0
  125. package/package.json +78 -0
@@ -0,0 +1,127 @@
1
+ export function generateArtifact(type, payload) {
2
+ switch (type) {
3
+ case 'mock_data':
4
+ return generateMockData(payload);
5
+ case 'request_wrappers':
6
+ return generateRequestWrapper(payload);
7
+ case 'test_scripts':
8
+ return generateTestScript(payload);
9
+ default:
10
+ return generateTsTypes(payload);
11
+ }
12
+ }
13
+ function generateTsTypes(payload) {
14
+ const { interfaceDetail } = payload;
15
+ const name = interfaceDetail.name ?? 'Unknown';
16
+ const requestName = `${pascalCase(name)}Request`;
17
+ const responseName = `${pascalCase(name)}Response`;
18
+ const requestType = jsonToTypescript((interfaceDetail.request?.body?.json ?? {}));
19
+ const responseType = jsonToTypescript((interfaceDetail.response?.body?.json ?? {}));
20
+ const content = `// ${name}
21
+ export interface ${requestName} ${requestType || '{}'}
22
+
23
+ export interface ${responseName} ${responseType || '{}'}
24
+ `;
25
+ return {
26
+ title: `${name} 类型定义`,
27
+ content,
28
+ };
29
+ }
30
+ function generateMockData(payload) {
31
+ const { interfaceDetail } = payload;
32
+ const name = interfaceDetail.name ?? 'Unknown';
33
+ const mockJson = interfaceDetail.response?.body?.json ||
34
+ interfaceDetail.response?.example ||
35
+ defaultMockFromSummary(interfaceDetail);
36
+ const content = JSON.stringify(mockJson, null, 2);
37
+ return {
38
+ title: `${name} Mock 数据`,
39
+ content,
40
+ };
41
+ }
42
+ function generateRequestWrapper(payload) {
43
+ const { interfaceDetail, baseUrl } = payload;
44
+ const name = interfaceDetail.name ?? 'Unknown';
45
+ const method = interfaceDetail.method ?? 'GET';
46
+ const path = interfaceDetail.path ?? '/';
47
+ const fnName = camelCase(name);
48
+ const requestName = `${pascalCase(name)}Request`;
49
+ const responseName = `${pascalCase(name)}Response`;
50
+ const url = `${baseUrl ?? 'https://api.example.com'}${path}`;
51
+ const content = `import axios from 'axios';
52
+
53
+ export async function ${fnName}(payload: ${requestName}): Promise<${responseName}> {
54
+ const response = await axios.request<${responseName}>({
55
+ url: '${url}',
56
+ method: '${method}',
57
+ data: payload,
58
+ });
59
+ return response.data;
60
+ }
61
+ `;
62
+ return {
63
+ title: `${name} 请求封装`,
64
+ content,
65
+ };
66
+ }
67
+ function generateTestScript(payload) {
68
+ const { interfaceDetail } = payload;
69
+ const name = interfaceDetail.name ?? 'Unknown';
70
+ const method = interfaceDetail.method ?? 'get';
71
+ const path = interfaceDetail.path ?? '/';
72
+ const fnName = camelCase(name);
73
+ const responseName = `${pascalCase(name)}Response`;
74
+ const content = `import request from 'supertest';
75
+
76
+ describe('${name}', () => {
77
+ it('should work as expected', async () => {
78
+ const response = await request(process.env.API_BASE_URL || '')
79
+ .${method.toLowerCase()}('${path}')
80
+ .send(/* TODO: 填写请求参数 */);
81
+
82
+ expect(response.status).toBe(200);
83
+ const data: ${responseName} = response.body;
84
+ // TODO: 添加断言
85
+ });
86
+ });
87
+ `;
88
+ return {
89
+ title: `${name} 测试脚本`,
90
+ content,
91
+ };
92
+ }
93
+ function jsonToTypescript(json) {
94
+ if (Array.isArray(json)) {
95
+ if (json.length === 0) {
96
+ return 'any[]';
97
+ }
98
+ return `${jsonToTypescript(json[0])}[]`;
99
+ }
100
+ if (json && typeof json === 'object') {
101
+ const entries = Object.entries(json).map(([key, value]) => {
102
+ const optional = value === null ? '?' : '';
103
+ return `${key}${optional}: ${jsonToTypescript(value)};`;
104
+ });
105
+ return entries.length ? `{ ${entries.join(' ')} }` : '{}';
106
+ }
107
+ if (json === null) {
108
+ return 'any';
109
+ }
110
+ return typeof json;
111
+ }
112
+ function defaultMockFromSummary(detail) {
113
+ return {
114
+ message: 'Mock data generated from Apifox MCP',
115
+ interfaceId: detail.id,
116
+ };
117
+ }
118
+ function camelCase(input) {
119
+ return input
120
+ .replace(/[^a-zA-Z0-9]+(.)/g, (_, chr) => chr.toUpperCase())
121
+ .replace(/^[A-Z]/, (chr) => chr.toLowerCase());
122
+ }
123
+ function pascalCase(input) {
124
+ const camel = camelCase(input);
125
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
126
+ }
127
+ //# sourceMappingURL=artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact.js","sourceRoot":"","sources":["../../../src/core/generator/artifact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 生成器模块
3
+ */
4
+ export { generateArtifact, ArtifactType } from './artifact.js';
5
+ export type { ArtifactInput, GeneratedArtifact } from './artifact.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/generator/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 生成器模块
3
+ */
4
+ export { generateArtifact } from './artifact.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/generator/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAgB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 核心业务逻辑模块
3
+ */
4
+ export * from './config/index.js';
5
+ export * from './client/index.js';
6
+ export * from './parser/index.js';
7
+ export * from './generator/index.js';
8
+ export { ContextStore } from './context-store.js';
9
+ export type { InterfaceSummary } from './context-store.js';
10
+ export { parseIntent } from './intent.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,cAAc,mBAAmB,CAAC;AAGlC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,sBAAsB,CAAC;AAGrC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 核心业务逻辑模块
3
+ */
4
+ // 配置管理
5
+ export * from './config/index.js';
6
+ // 客户端
7
+ export * from './client/index.js';
8
+ // 解析器
9
+ export * from './parser/index.js';
10
+ // 生成器
11
+ export * from './generator/index.js';
12
+ // 上下文存储
13
+ export { ContextStore } from './context-store.js';
14
+ // 意图识别
15
+ export { parseIntent } from './intent.js';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO;AACP,cAAc,mBAAmB,CAAC;AAElC,MAAM;AACN,cAAc,mBAAmB,CAAC;AAElC,MAAM;AACN,cAAc,mBAAmB,CAAC;AAElC,MAAM;AACN,cAAc,sBAAsB,CAAC;AAErC,QAAQ;AACR,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO;AACP,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type IntentAction = 'listProjects' | 'searchInterfaces' | 'getInterfaceDetail' | 'generateArtifacts' | 'openBrowser' | 'help' | 'unknown';
2
+ export interface IntentResult {
3
+ action: IntentAction;
4
+ keyword?: string;
5
+ projectName?: string;
6
+ interfaceId?: string;
7
+ artifactType?: 'ts_types' | 'mock_data' | 'request_wrappers' | 'test_scripts';
8
+ targetName?: string;
9
+ }
10
+ export declare function parseIntent(promptRaw: string, context?: {
11
+ lastProjectName?: string;
12
+ lastInterfaceListNames?: string[];
13
+ }): IntentResult;
14
+ //# sourceMappingURL=intent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../src/core/intent.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACpB,cAAc,GACd,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,aAAa,GACb,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,kBAAkB,GAAG,cAAc,CAAC;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACxE,YAAY,CAqDd"}
@@ -0,0 +1,80 @@
1
+ const GENERATE_KEYWORDS = ['生成', '导出', '输出', 'mock', '类型', '封装', '代码'];
2
+ const DETAIL_KEYWORDS = ['详情', '具体', '字段', '参数', '文档'];
3
+ const SEARCH_KEYWORDS = ['查询', '搜索', '找', '接口列表', '有哪些', '列出'];
4
+ const BROWSER_KEYWORDS = ['勾选', '批量', '浏览器', '手动选择'];
5
+ export function parseIntent(promptRaw, context) {
6
+ const prompt = promptRaw.trim();
7
+ const lower = prompt.toLowerCase();
8
+ if (!prompt) {
9
+ return { action: 'help' };
10
+ }
11
+ // Detect ask to open browser for selection
12
+ if (BROWSER_KEYWORDS.some((kw) => prompt.includes(kw))) {
13
+ return { action: 'openBrowser' };
14
+ }
15
+ // Detect generate artifacts
16
+ if (GENERATE_KEYWORDS.some((kw) => prompt.includes(kw)) &&
17
+ (prompt.includes('类型') ||
18
+ prompt.toLowerCase().includes('type') ||
19
+ prompt.includes('mock') ||
20
+ prompt.includes('封装') ||
21
+ prompt.includes('测试'))) {
22
+ const type = detectArtifactType(prompt);
23
+ return {
24
+ action: 'generateArtifacts',
25
+ artifactType: type,
26
+ targetName: extractInterfaceName(prompt, context?.lastInterfaceListNames),
27
+ };
28
+ }
29
+ // Detect get detail by ID or name
30
+ if (DETAIL_KEYWORDS.some((kw) => prompt.includes(kw))) {
31
+ const id = extractInterfaceId(prompt);
32
+ return {
33
+ action: 'getInterfaceDetail',
34
+ interfaceId: id,
35
+ targetName: id ? undefined : extractInterfaceName(prompt, context?.lastInterfaceListNames),
36
+ };
37
+ }
38
+ // Default search/list
39
+ if (SEARCH_KEYWORDS.some((kw) => prompt.includes(kw)) || prompt.startsWith('接口')) {
40
+ return {
41
+ action: 'searchInterfaces',
42
+ keyword: extractKeyword(prompt),
43
+ };
44
+ }
45
+ if (prompt.includes('项目')) {
46
+ return { action: 'listProjects' };
47
+ }
48
+ return { action: 'unknown' };
49
+ }
50
+ function detectArtifactType(prompt) {
51
+ if (prompt.includes('mock')) {
52
+ return 'mock_data';
53
+ }
54
+ if (prompt.includes('封装') || prompt.toLowerCase().includes('request')) {
55
+ return 'request_wrappers';
56
+ }
57
+ if (prompt.includes('测试')) {
58
+ return 'test_scripts';
59
+ }
60
+ return 'ts_types';
61
+ }
62
+ function extractInterfaceId(prompt) {
63
+ const match = prompt.match(/(?:接口)?(\d{4,})/);
64
+ return match ? match[1] : undefined;
65
+ }
66
+ function extractKeyword(prompt) {
67
+ const trimmed = prompt
68
+ .replace(/\/?apifox/gi, '')
69
+ .replace(/接口列表|有哪些|搜索|查询|找|帮我|一下/g, '')
70
+ .trim();
71
+ return trimmed || undefined;
72
+ }
73
+ function extractInterfaceName(prompt, candidates) {
74
+ if (!candidates || candidates.length === 0) {
75
+ return undefined;
76
+ }
77
+ return (candidates.find((name) => prompt.includes(name)) ||
78
+ candidates.find((name) => prompt.toLowerCase().includes(name.toLowerCase())));
79
+ }
80
+ //# sourceMappingURL=intent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/core/intent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 解析器模块
3
+ */
4
+ export { isValidApifoxUrl, parseApifoxUrl, ShareLinkType } from './url.js';
5
+ export type { ParsedUrl } from './url.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/parser/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC3E,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 解析器模块
3
+ */
4
+ export { isValidApifoxUrl, parseApifoxUrl, ShareLinkType } from './url.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/parser/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * URL 解析工具
3
+ * 用于解析 Apifox 分享链接并提取关键信息
4
+ */
5
+ /**
6
+ * 分享链接类型
7
+ */
8
+ export declare enum ShareLinkType {
9
+ /** 项目分享链接: /apidoc/shared/{shareId} */
10
+ PROJECT = "project",
11
+ /** 接口分享链接: /apidoc/shared/{shareId}/api-{interfaceId} */
12
+ INTERFACE = "interface"
13
+ }
14
+ /**
15
+ * 解析后的 URL 信息
16
+ */
17
+ export interface ParsedUrl {
18
+ /** 项目 ID(从 x-run-in-apifox 提取的真实 projectId) */
19
+ projectId: string;
20
+ /** 分享 ID(URL 中的 shareId) */
21
+ shareId: string;
22
+ /** 接口 ID(如果是指向特定接口的链接) */
23
+ interfaceId?: string;
24
+ /** 基础 URL */
25
+ baseUrl: string;
26
+ /** 项目名称(从页面 title 提取) */
27
+ projectName?: string;
28
+ /** 链接类型 */
29
+ linkType: ShareLinkType;
30
+ /** llms.txt 的完整 URL */
31
+ llmsUrl: string;
32
+ /** 原始页面 URL */
33
+ pageUrl: string;
34
+ /** 页面标题 */
35
+ pageTitle?: string;
36
+ /** 第一个 API 文档 URL(用于后续 UI) */
37
+ firstApiDocUrl?: string;
38
+ }
39
+ /**
40
+ * 从 API 文档中提取真正的 projectId
41
+ * API 文档包含 x-run-in-apifox 字段,格式为:
42
+ * x-run-in-apifox: https://apifox.advai.net/web/project/{realProjectId}/apis/api-{interfaceId}-run
43
+ *
44
+ * @param apiDocUrl API 文档 URL (格式: .../api-{interfaceId} 或 .../api-{interfaceId}.md)
45
+ * @returns 真正的 projectId,如果提取失败则返回 null
46
+ */
47
+ export declare function extractRealProjectIdFromApiDoc(apiDocUrl: string): Promise<string | null>;
48
+ /**
49
+ * 从 LLM 文档中提取真正的 projectId 和第一个 API 文档 URL
50
+ * LLM 文档中的 API 文档包含 x-run-in-apifox 字段,格式为:
51
+ * https://apifox.advai.net/web/project/{realProjectId}/apis/api-{interfaceId}-run
52
+ *
53
+ * @param llmsUrl LLM 文档 URL (llms.txt)
54
+ * @returns 包含 projectId 和第一个 API 文档 URL 的对象,如果提取失败则返回 null
55
+ */
56
+ export declare function extractRealProjectIdFromLlms(llmsUrl: string): Promise<{
57
+ projectId: string;
58
+ firstApiDocUrl: string;
59
+ } | null>;
60
+ /**
61
+ * 解析 Apifox 分享链接
62
+ * 格式: https://apifox.advai.net/apidoc/shared/{shareId}/api-{interfaceId} (接口分享链接)
63
+ * 或: https://apifox.advai.net/apidoc/shared/{shareId} (项目分享链接)
64
+ * 或: https://apifox.advai.net/apidoc/shared/{shareId}/llms.txt (LLM 文档)
65
+ *
66
+ * @param url Apifox 分享链接
67
+ * @returns 解析结果,包含 projectId、项目名称、链接类型等完整信息
68
+ */
69
+ export declare function parseApifoxUrl(url: string): Promise<ParsedUrl | null>;
70
+ /**
71
+ * 验证 URL 是否为有效的 Apifox 分享链接
72
+ * @param url 待验证的 URL
73
+ * @returns 是否为有效的 Apifox 分享链接
74
+ */
75
+ export declare function isValidApifoxUrl(url: string): boolean;
76
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../../src/core/parser/url.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH;;GAEG;AACH,oBAAY,aAAa;IACvB,uCAAuC;IACvC,OAAO,YAAY;IACnB,yDAAyD;IACzD,SAAS,cAAc;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,QAAQ,EAAE,aAAa,CAAC;IACxB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6B9F;AAED;;;;;;;GAOG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAyC/D;AAoCD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAkG3E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CASrD"}
@@ -0,0 +1,232 @@
1
+ import axios from 'axios';
2
+ /**
3
+ * URL 解析工具
4
+ * 用于解析 Apifox 分享链接并提取关键信息
5
+ */
6
+ /**
7
+ * 分享链接类型
8
+ */
9
+ export var ShareLinkType;
10
+ (function (ShareLinkType) {
11
+ /** 项目分享链接: /apidoc/shared/{shareId} */
12
+ ShareLinkType["PROJECT"] = "project";
13
+ /** 接口分享链接: /apidoc/shared/{shareId}/api-{interfaceId} */
14
+ ShareLinkType["INTERFACE"] = "interface";
15
+ })(ShareLinkType || (ShareLinkType = {}));
16
+ /**
17
+ * 从 API 文档中提取真正的 projectId
18
+ * API 文档包含 x-run-in-apifox 字段,格式为:
19
+ * x-run-in-apifox: https://apifox.advai.net/web/project/{realProjectId}/apis/api-{interfaceId}-run
20
+ *
21
+ * @param apiDocUrl API 文档 URL (格式: .../api-{interfaceId} 或 .../api-{interfaceId}.md)
22
+ * @returns 真正的 projectId,如果提取失败则返回 null
23
+ */
24
+ export async function extractRealProjectIdFromApiDoc(apiDocUrl) {
25
+ try {
26
+ // 确保 URL 以 .md 结尾
27
+ const normalizedUrl = apiDocUrl.endsWith('.md') ? apiDocUrl : `${apiDocUrl}.md`;
28
+ // 获取 API 文档内容
29
+ const apiDocResponse = await axios.get(normalizedUrl, { timeout: 10000 });
30
+ const apiDocContent = apiDocResponse.data;
31
+ // 从 API 文档中提取 x-run-in-apifox 字段
32
+ // 格式: x-run-in-apifox: https://apifox.advai.net/web/project/{realProjectId}/apis/api-{interfaceId}-run
33
+ const runInApifoxMatch = apiDocContent.match(/x-run-in-apifox:\s*https:\/\/[^\/]+\/web\/project\/(\d+)\//);
34
+ if (!runInApifoxMatch) {
35
+ console.error('无法从 API 文档中找到 x-run-in-apifox 字段');
36
+ return null;
37
+ }
38
+ const realProjectId = runInApifoxMatch[1];
39
+ console.error(`✅ 从 API 文档中提取到真正的 projectId: ${realProjectId}`);
40
+ return realProjectId;
41
+ }
42
+ catch (error) {
43
+ console.error('从 API 文档提取 projectId 失败:', error instanceof Error ? error.message : String(error));
44
+ return null;
45
+ }
46
+ }
47
+ /**
48
+ * 从 LLM 文档中提取真正的 projectId 和第一个 API 文档 URL
49
+ * LLM 文档中的 API 文档包含 x-run-in-apifox 字段,格式为:
50
+ * https://apifox.advai.net/web/project/{realProjectId}/apis/api-{interfaceId}-run
51
+ *
52
+ * @param llmsUrl LLM 文档 URL (llms.txt)
53
+ * @returns 包含 projectId 和第一个 API 文档 URL 的对象,如果提取失败则返回 null
54
+ */
55
+ export async function extractRealProjectIdFromLlms(llmsUrl) {
56
+ try {
57
+ // 1. 获取 LLM 文档内容
58
+ const llmsResponse = await axios.get(llmsUrl, { timeout: 10000 });
59
+ const llmsContent = llmsResponse.data;
60
+ // 2. 从 LLM 文档中提取第一个 API 文档链接
61
+ // 格式: https://apifox.advai.net/apidoc/shared/{shareId}/api-{interfaceId}.md
62
+ const apiDocMatch = llmsContent.match(/https:\/\/[^\s]+\/api-(\d+)\.md/);
63
+ if (!apiDocMatch) {
64
+ console.error('无法从 LLM 文档中找到 API 文档链接');
65
+ return null;
66
+ }
67
+ // 3. 构建 API 文档 URL
68
+ const urlObj = new URL(llmsUrl);
69
+ const shareId = urlObj.pathname.match(/\/apidoc\/shared\/([^\/]+)/)?.[1];
70
+ if (!shareId) {
71
+ console.error('无法从 LLM URL 中提取分享 ID');
72
+ return null;
73
+ }
74
+ const apiDocUrl = `${urlObj.protocol}//${urlObj.host}/apidoc/shared/${shareId}/api-${apiDocMatch[1]}.md`;
75
+ // 4. 从 API 文档中提取 projectId
76
+ const projectId = await extractRealProjectIdFromApiDoc(apiDocUrl);
77
+ if (!projectId) {
78
+ return null;
79
+ }
80
+ return {
81
+ projectId,
82
+ firstApiDocUrl: apiDocUrl,
83
+ };
84
+ }
85
+ catch (error) {
86
+ console.error('从 LLM 文档提取 projectId 失败:', error instanceof Error ? error.message : String(error));
87
+ return null;
88
+ }
89
+ }
90
+ /**
91
+ * 从分享页面 HTML 中提取项目名称和页面标题
92
+ * @param pageUrl 页面 URL
93
+ * @returns 包含项目名称和页面标题的对象,如果提取失败则返回 null
94
+ */
95
+ async function extractProjectNameFromHtml(pageUrl) {
96
+ try {
97
+ const response = await axios.get(pageUrl, { timeout: 10000 });
98
+ const html = response.data;
99
+ const titleMatch = html.match(/<title>([\s\S]*?)<\/title>/i);
100
+ if (!titleMatch) {
101
+ return { projectName: null, pageTitle: null };
102
+ }
103
+ const title = titleMatch[1].trim();
104
+ const delimiterIndex = title.lastIndexOf(' - ');
105
+ let projectName = null;
106
+ if (delimiterIndex !== -1) {
107
+ projectName = title.substring(delimiterIndex + 3).trim();
108
+ }
109
+ else {
110
+ // 如果没有分隔符,尝试使用整个标题
111
+ projectName = title || null;
112
+ }
113
+ return { projectName, pageTitle: title };
114
+ }
115
+ catch (error) {
116
+ console.error('从分享页面解析项目名称失败:', error instanceof Error ? error.message : String(error));
117
+ return { projectName: null, pageTitle: null };
118
+ }
119
+ }
120
+ /**
121
+ * 解析 Apifox 分享链接
122
+ * 格式: https://apifox.advai.net/apidoc/shared/{shareId}/api-{interfaceId} (接口分享链接)
123
+ * 或: https://apifox.advai.net/apidoc/shared/{shareId} (项目分享链接)
124
+ * 或: https://apifox.advai.net/apidoc/shared/{shareId}/llms.txt (LLM 文档)
125
+ *
126
+ * @param url Apifox 分享链接
127
+ * @returns 解析结果,包含 projectId、项目名称、链接类型等完整信息
128
+ */
129
+ export async function parseApifoxUrl(url) {
130
+ try {
131
+ const urlObj = new URL(url);
132
+ const pathname = urlObj.pathname;
133
+ const baseUrl = `${urlObj.protocol}//${urlObj.host}`;
134
+ // 检查是否是 LLM 文档 (llms.txt)
135
+ if (pathname.endsWith('/llms.txt')) {
136
+ const shareMatch = pathname.match(/\/apidoc\/shared\/([^\/]+)/);
137
+ if (!shareMatch) {
138
+ return null;
139
+ }
140
+ const shareId = shareMatch[1];
141
+ // 从 LLM 文档中提取真正的 projectId
142
+ const result = await extractRealProjectIdFromLlms(url);
143
+ if (!result) {
144
+ console.error('⚠️ 无法从 LLM 文档中提取真正的 projectId,使用分享 ID 作为后备');
145
+ return {
146
+ projectId: shareId,
147
+ shareId,
148
+ baseUrl,
149
+ linkType: ShareLinkType.PROJECT,
150
+ llmsUrl: url,
151
+ pageUrl: url,
152
+ };
153
+ }
154
+ return {
155
+ projectId: result.projectId,
156
+ shareId,
157
+ baseUrl,
158
+ linkType: ShareLinkType.PROJECT,
159
+ llmsUrl: url,
160
+ pageUrl: url,
161
+ firstApiDocUrl: result.firstApiDocUrl,
162
+ };
163
+ }
164
+ // 匹配格式: /apidoc/shared/{shareId}/api-{interfaceId}
165
+ // 或: /apidoc/shared/{shareId}
166
+ const sharedMatch = pathname.match(/\/apidoc\/shared\/([^\/]+)(?:\/api-([^\/]+))?/);
167
+ if (!sharedMatch) {
168
+ return null;
169
+ }
170
+ const shareId = sharedMatch[1];
171
+ const interfaceId = sharedMatch[2];
172
+ const pageUrl = url;
173
+ const llmsUrl = `${baseUrl}/apidoc/shared/${shareId}/llms.txt`;
174
+ // 判断链接类型
175
+ const linkType = interfaceId ? ShareLinkType.INTERFACE : ShareLinkType.PROJECT;
176
+ // 获取项目名称和页面标题
177
+ const { projectName, pageTitle } = await extractProjectNameFromHtml(pageUrl);
178
+ // 优先通过 llms.txt 提取 projectId
179
+ let projectId = null;
180
+ let firstApiDocUrl = undefined;
181
+ const llmsResult = await extractRealProjectIdFromLlms(llmsUrl);
182
+ if (llmsResult) {
183
+ projectId = llmsResult.projectId;
184
+ firstApiDocUrl = llmsResult.firstApiDocUrl;
185
+ }
186
+ // 如果 llms.txt 解析失败且存在 interfaceId,尝试使用 API 文档提取
187
+ if (!projectId && interfaceId) {
188
+ const apiDocUrl = `${baseUrl}/apidoc/shared/${shareId}/api-${interfaceId}`;
189
+ projectId = await extractRealProjectIdFromApiDoc(apiDocUrl);
190
+ if (projectId && !firstApiDocUrl) {
191
+ firstApiDocUrl = `${apiDocUrl}.md`;
192
+ }
193
+ }
194
+ if (!projectId) {
195
+ console.error('⚠️ 无法从分享链接解析到真实 projectId,使用分享 ID 作为后备');
196
+ projectId = shareId;
197
+ }
198
+ return {
199
+ projectId,
200
+ shareId,
201
+ interfaceId,
202
+ baseUrl,
203
+ projectName: projectName || undefined,
204
+ linkType,
205
+ llmsUrl,
206
+ pageUrl,
207
+ pageTitle: pageTitle || undefined,
208
+ firstApiDocUrl,
209
+ };
210
+ }
211
+ catch (error) {
212
+ console.error('解析 URL 失败:', error);
213
+ return null;
214
+ }
215
+ }
216
+ /**
217
+ * 验证 URL 是否为有效的 Apifox 分享链接
218
+ * @param url 待验证的 URL
219
+ * @returns 是否为有效的 Apifox 分享链接
220
+ */
221
+ export function isValidApifoxUrl(url) {
222
+ try {
223
+ const urlObj = new URL(url);
224
+ const pathname = urlObj.pathname;
225
+ // 检查是否是 /apidoc/shared/ 格式
226
+ return /\/apidoc\/shared\//.test(pathname);
227
+ }
228
+ catch {
229
+ return false;
230
+ }
231
+ }
232
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../../../src/core/parser/url.ts"],"names":[],"mappings":"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"}