activo 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +87 -3
  2. package/dist/core/llm/ollama.d.ts +2 -0
  3. package/dist/core/llm/ollama.d.ts.map +1 -1
  4. package/dist/core/llm/ollama.js +26 -0
  5. package/dist/core/llm/ollama.js.map +1 -1
  6. package/dist/core/tools/ast.d.ts +81 -0
  7. package/dist/core/tools/ast.d.ts.map +1 -0
  8. package/dist/core/tools/ast.js +700 -0
  9. package/dist/core/tools/ast.js.map +1 -0
  10. package/dist/core/tools/cache.d.ts +19 -0
  11. package/dist/core/tools/cache.d.ts.map +1 -0
  12. package/dist/core/tools/cache.js +497 -0
  13. package/dist/core/tools/cache.js.map +1 -0
  14. package/dist/core/tools/cssAnalysis.d.ts +3 -0
  15. package/dist/core/tools/cssAnalysis.d.ts.map +1 -0
  16. package/dist/core/tools/cssAnalysis.js +270 -0
  17. package/dist/core/tools/cssAnalysis.js.map +1 -0
  18. package/dist/core/tools/dependencyAnalysis.d.ts +3 -0
  19. package/dist/core/tools/dependencyAnalysis.d.ts.map +1 -0
  20. package/dist/core/tools/dependencyAnalysis.js +295 -0
  21. package/dist/core/tools/dependencyAnalysis.js.map +1 -0
  22. package/dist/core/tools/embeddings.d.ts +8 -0
  23. package/dist/core/tools/embeddings.d.ts.map +1 -0
  24. package/dist/core/tools/embeddings.js +631 -0
  25. package/dist/core/tools/embeddings.js.map +1 -0
  26. package/dist/core/tools/frontendAst.d.ts +6 -0
  27. package/dist/core/tools/frontendAst.d.ts.map +1 -0
  28. package/dist/core/tools/frontendAst.js +680 -0
  29. package/dist/core/tools/frontendAst.js.map +1 -0
  30. package/dist/core/tools/htmlAnalysis.d.ts +3 -0
  31. package/dist/core/tools/htmlAnalysis.d.ts.map +1 -0
  32. package/dist/core/tools/htmlAnalysis.js +398 -0
  33. package/dist/core/tools/htmlAnalysis.js.map +1 -0
  34. package/dist/core/tools/index.d.ts +13 -0
  35. package/dist/core/tools/index.d.ts.map +1 -1
  36. package/dist/core/tools/index.js +27 -1
  37. package/dist/core/tools/index.js.map +1 -1
  38. package/dist/core/tools/javaAst.d.ts +6 -0
  39. package/dist/core/tools/javaAst.d.ts.map +1 -0
  40. package/dist/core/tools/javaAst.js +678 -0
  41. package/dist/core/tools/javaAst.js.map +1 -0
  42. package/dist/core/tools/memory.d.ts +11 -0
  43. package/dist/core/tools/memory.d.ts.map +1 -0
  44. package/dist/core/tools/memory.js +551 -0
  45. package/dist/core/tools/memory.js.map +1 -0
  46. package/dist/core/tools/mybatisAnalysis.d.ts +3 -0
  47. package/dist/core/tools/mybatisAnalysis.d.ts.map +1 -0
  48. package/dist/core/tools/mybatisAnalysis.js +251 -0
  49. package/dist/core/tools/mybatisAnalysis.js.map +1 -0
  50. package/dist/core/tools/openapiAnalysis.d.ts +3 -0
  51. package/dist/core/tools/openapiAnalysis.d.ts.map +1 -0
  52. package/dist/core/tools/openapiAnalysis.js +356 -0
  53. package/dist/core/tools/openapiAnalysis.js.map +1 -0
  54. package/dist/core/tools/pythonAnalysis.d.ts +3 -0
  55. package/dist/core/tools/pythonAnalysis.d.ts.map +1 -0
  56. package/dist/core/tools/pythonAnalysis.js +387 -0
  57. package/dist/core/tools/pythonAnalysis.js.map +1 -0
  58. package/dist/core/tools/sqlAnalysis.d.ts +3 -0
  59. package/dist/core/tools/sqlAnalysis.d.ts.map +1 -0
  60. package/dist/core/tools/sqlAnalysis.js +250 -0
  61. package/dist/core/tools/sqlAnalysis.js.map +1 -0
  62. package/package.json +2 -1
  63. package/src/core/llm/ollama.ts +30 -0
  64. package/src/core/tools/ast.ts +826 -0
  65. package/src/core/tools/cache.ts +570 -0
  66. package/src/core/tools/cssAnalysis.ts +324 -0
  67. package/src/core/tools/dependencyAnalysis.ts +363 -0
  68. package/src/core/tools/embeddings.ts +746 -0
  69. package/src/core/tools/frontendAst.ts +802 -0
  70. package/src/core/tools/htmlAnalysis.ts +466 -0
  71. package/src/core/tools/index.ts +27 -1
  72. package/src/core/tools/javaAst.ts +812 -0
  73. package/src/core/tools/memory.ts +655 -0
  74. package/src/core/tools/mybatisAnalysis.ts +322 -0
  75. package/src/core/tools/openapiAnalysis.ts +431 -0
  76. package/src/core/tools/pythonAnalysis.ts +477 -0
  77. package/src/core/tools/sqlAnalysis.ts +298 -0
  78. package/FINAL_SIMPLIFIED_SPEC.md +0 -456
  79. package/TODO.md +0 -193
@@ -0,0 +1,3 @@
1
+ import { Tool } from "./types.js";
2
+ export declare const mybatisTools: Tool[];
3
+ //# sourceMappingURL=mybatisAnalysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mybatisAnalysis.d.ts","sourceRoot":"","sources":["../../../src/core/tools/mybatisAnalysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,MAAM,YAAY,CAAC;AA8N9C,eAAO,MAAM,YAAY,EAAE,IAAI,EAmG9B,CAAC"}
@@ -0,0 +1,251 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ // MyBatis XML 파싱 및 분석
4
+ function analyzeMyBatisXml(filePath) {
5
+ const content = fs.readFileSync(filePath, "utf-8");
6
+ const lines = content.split("\n");
7
+ // MyBatis XML 여부 확인
8
+ const isMyBatis = content.includes("mybatis") ||
9
+ content.includes("ibatis") ||
10
+ content.includes('PUBLIC "-//mybatis.org') ||
11
+ content.includes('PUBLIC "-//ibatis.org') ||
12
+ /<mapper\s+namespace=/i.test(content);
13
+ if (!isMyBatis) {
14
+ return {
15
+ file: filePath,
16
+ isMyBatis: false,
17
+ summary: { statements: 0, withIssues: 0, injectionRisks: 0, dynamicSqlCount: 0 },
18
+ };
19
+ }
20
+ const statements = [];
21
+ const resultMaps = [];
22
+ const sqlFragments = [];
23
+ const mapperIssues = [];
24
+ // namespace 추출
25
+ const namespaceMatch = content.match(/<mapper\s+namespace=["']([^"']+)["']/);
26
+ const namespace = namespaceMatch ? namespaceMatch[1] : "unknown";
27
+ // resultMap 추출
28
+ const resultMapRegex = /<resultMap\s+[^>]*id=["']([^"']+)["'][^>]*>/g;
29
+ let match;
30
+ while ((match = resultMapRegex.exec(content)) !== null) {
31
+ resultMaps.push(match[1]);
32
+ }
33
+ // sql fragment 추출
34
+ const sqlFragmentRegex = /<sql\s+[^>]*id=["']([^"']+)["'][^>]*>/g;
35
+ while ((match = sqlFragmentRegex.exec(content)) !== null) {
36
+ sqlFragments.push(match[1]);
37
+ }
38
+ // statement 추출 함수
39
+ const extractStatements = (type) => {
40
+ const regex = new RegExp(`<${type}\\s+([^>]*)>([\\s\\S]*?)</${type}>`, "gi");
41
+ while ((match = regex.exec(content)) !== null) {
42
+ const attrs = match[1];
43
+ const sqlContent = match[2];
44
+ // 속성 파싱
45
+ const idMatch = attrs.match(/id=["']([^"']+)["']/);
46
+ const paramMatch = attrs.match(/parameterType=["']([^"']+)["']/);
47
+ const resultTypeMatch = attrs.match(/resultType=["']([^"']+)["']/);
48
+ const resultMapMatch = attrs.match(/resultMap=["']([^"']+)["']/);
49
+ const id = idMatch ? idMatch[1] : "unknown";
50
+ const issues = [];
51
+ const dynamicElements = [];
52
+ // ${} 사용 검사 (SQL Injection 위험)
53
+ const dollarBraceMatches = sqlContent.match(/\$\{[^}]+\}/g) || [];
54
+ if (dollarBraceMatches.length > 0) {
55
+ issues.push(`SQL Injection 위험: ${dollarBraceMatches.join(", ")} 사용`);
56
+ }
57
+ // 동적 SQL 요소 추출
58
+ const dynamicTags = ["if", "choose", "when", "otherwise", "where", "set", "foreach", "trim", "bind"];
59
+ dynamicTags.forEach((tag) => {
60
+ const tagRegex = new RegExp(`<${tag}[\\s>]`, "gi");
61
+ const count = (sqlContent.match(tagRegex) || []).length;
62
+ if (count > 0) {
63
+ dynamicElements.push(`${tag}(${count})`);
64
+ }
65
+ });
66
+ // SELECT * 검사
67
+ if (/SELECT\s+\*\s+FROM/i.test(sqlContent)) {
68
+ issues.push("SELECT * 사용");
69
+ }
70
+ // WHERE 없는 UPDATE/DELETE
71
+ if ((type === "update" || type === "delete") && !/<where>|WHERE/i.test(sqlContent)) {
72
+ issues.push("WHERE 절 없음 - 전체 테이블 영향 위험");
73
+ }
74
+ // 복잡한 동적 SQL
75
+ if (dynamicElements.length >= 5) {
76
+ issues.push(`복잡한 동적 SQL (${dynamicElements.length}개 요소)`);
77
+ }
78
+ // 중첩 foreach
79
+ const foreachCount = (sqlContent.match(/<foreach/gi) || []).length;
80
+ if (foreachCount >= 2) {
81
+ issues.push(`중첩 foreach ${foreachCount}개 - 성능 검토 필요`);
82
+ }
83
+ // LIKE '%${...}%' 패턴
84
+ if (/LIKE\s+['"]?%?\$\{/i.test(sqlContent)) {
85
+ issues.push("LIKE + ${} 패턴 - SQL Injection 및 인덱스 문제");
86
+ }
87
+ // ORDER BY ${} 패턴
88
+ if (/ORDER\s+BY\s+\$\{/i.test(sqlContent)) {
89
+ issues.push("ORDER BY ${} - SQL Injection 위험");
90
+ }
91
+ // 라인 번호 찾기
92
+ const statementIndex = content.indexOf(match[0]);
93
+ let lineNum = 1;
94
+ for (let i = 0; i < statementIndex; i++) {
95
+ if (content[i] === "\n")
96
+ lineNum++;
97
+ }
98
+ // SQL 정리
99
+ const cleanSql = sqlContent
100
+ .replace(/<[^>]+>/g, " ") // XML 태그 제거
101
+ .replace(/\s+/g, " ")
102
+ .trim();
103
+ statements.push({
104
+ id,
105
+ type,
106
+ parameterType: paramMatch ? paramMatch[1] : undefined,
107
+ resultType: resultTypeMatch ? resultTypeMatch[1] : undefined,
108
+ resultMap: resultMapMatch ? resultMapMatch[1] : undefined,
109
+ sql: cleanSql,
110
+ line: lineNum,
111
+ issues,
112
+ dynamicElements,
113
+ });
114
+ }
115
+ };
116
+ // 각 statement 타입 처리
117
+ extractStatements("select");
118
+ extractStatements("insert");
119
+ extractStatements("update");
120
+ extractStatements("delete");
121
+ // mapper 레벨 이슈 검사
122
+ if (!namespaceMatch) {
123
+ mapperIssues.push("namespace 미정의");
124
+ }
125
+ // 미사용 resultMap 검사 (간단한 체크)
126
+ resultMaps.forEach((rm) => {
127
+ const usageCount = (content.match(new RegExp(`resultMap=["']${rm}["']`, "g")) || []).length;
128
+ if (usageCount <= 1) {
129
+ // 정의만 있고 사용 없음
130
+ mapperIssues.push(`미사용 가능성: resultMap '${rm}'`);
131
+ }
132
+ });
133
+ // 통계
134
+ const injectionRisks = statements.filter((s) => s.issues.some((i) => i.includes("Injection"))).length;
135
+ const dynamicSqlCount = statements.filter((s) => s.dynamicElements.length > 0).length;
136
+ return {
137
+ file: filePath,
138
+ isMyBatis: true,
139
+ mapper: {
140
+ file: filePath,
141
+ namespace,
142
+ statements,
143
+ resultMaps,
144
+ sqlFragments,
145
+ issues: mapperIssues,
146
+ },
147
+ summary: {
148
+ statements: statements.length,
149
+ withIssues: statements.filter((s) => s.issues.length > 0).length,
150
+ injectionRisks,
151
+ dynamicSqlCount,
152
+ },
153
+ };
154
+ }
155
+ // 도구 정의
156
+ export const mybatisTools = [
157
+ {
158
+ name: "mybatis_check",
159
+ description: "MyBatis XML 매퍼 파일을 분석합니다. ${} SQL Injection 위험, 동적 SQL 복잡도, SELECT *, resultMap 사용 등을 검사합니다. DTD/namespace로 MyBatis 파일을 자동 감지합니다.",
160
+ parameters: {
161
+ type: "object",
162
+ properties: {
163
+ path: {
164
+ type: "string",
165
+ description: "분석할 XML 파일 또는 디렉토리 경로",
166
+ },
167
+ recursive: {
168
+ type: "boolean",
169
+ description: "디렉토리인 경우 하위 폴더 포함 여부 (기본: true)",
170
+ },
171
+ },
172
+ required: ["path"],
173
+ },
174
+ handler: async (args) => {
175
+ const targetPath = args.path;
176
+ const recursive = args.recursive !== false;
177
+ if (!fs.existsSync(targetPath)) {
178
+ return {
179
+ success: false,
180
+ content: "",
181
+ error: `경로를 찾을 수 없습니다: ${targetPath}`,
182
+ };
183
+ }
184
+ const results = [];
185
+ const stats = fs.statSync(targetPath);
186
+ if (stats.isFile()) {
187
+ if (targetPath.endsWith(".xml")) {
188
+ const result = analyzeMyBatisXml(targetPath);
189
+ if (result.isMyBatis) {
190
+ results.push(result);
191
+ }
192
+ }
193
+ }
194
+ else if (stats.isDirectory()) {
195
+ const walkDir = (dir) => {
196
+ const files = fs.readdirSync(dir);
197
+ for (const file of files) {
198
+ const filePath = path.join(dir, file);
199
+ const fileStat = fs.statSync(filePath);
200
+ if (fileStat.isDirectory() && recursive) {
201
+ if (!file.startsWith(".") && file !== "node_modules" && file !== "target" && file !== "build") {
202
+ walkDir(filePath);
203
+ }
204
+ }
205
+ else if (file.endsWith(".xml")) {
206
+ const result = analyzeMyBatisXml(filePath);
207
+ if (result.isMyBatis) {
208
+ results.push(result);
209
+ }
210
+ }
211
+ }
212
+ };
213
+ walkDir(targetPath);
214
+ }
215
+ // 전체 통계
216
+ const totalStatements = results.reduce((sum, r) => sum + r.summary.statements, 0);
217
+ const totalWithIssues = results.reduce((sum, r) => sum + r.summary.withIssues, 0);
218
+ const totalInjectionRisks = results.reduce((sum, r) => sum + r.summary.injectionRisks, 0);
219
+ const totalDynamicSql = results.reduce((sum, r) => sum + r.summary.dynamicSqlCount, 0);
220
+ const output = {
221
+ analyzedMappers: results.length,
222
+ totalStatements,
223
+ statementsWithIssues: totalWithIssues,
224
+ injectionRisks: totalInjectionRisks,
225
+ dynamicSqlStatements: totalDynamicSql,
226
+ mappers: results.map((r) => ({
227
+ file: r.file,
228
+ namespace: r.mapper?.namespace,
229
+ resultMaps: r.mapper?.resultMaps,
230
+ sqlFragments: r.mapper?.sqlFragments,
231
+ mapperIssues: r.mapper?.issues,
232
+ statements: r.mapper?.statements.map((s) => ({
233
+ id: s.id,
234
+ type: s.type,
235
+ line: s.line,
236
+ parameterType: s.parameterType,
237
+ resultType: s.resultType || s.resultMap,
238
+ dynamicElements: s.dynamicElements,
239
+ issues: s.issues,
240
+ sql: s.sql.length > 150 ? s.sql.substring(0, 150) + "..." : s.sql,
241
+ })),
242
+ })),
243
+ };
244
+ return {
245
+ success: true,
246
+ content: JSON.stringify(output, null, 2),
247
+ };
248
+ },
249
+ },
250
+ ];
251
+ //# sourceMappingURL=mybatisAnalysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mybatisAnalysis.js","sourceRoot":"","sources":["../../../src/core/tools/mybatisAnalysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Tool } from "./types.js";
2
+ export declare const openapiTools: Tool[];
3
+ //# sourceMappingURL=openapiAnalysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapiAnalysis.d.ts","sourceRoot":"","sources":["../../../src/core/tools/openapiAnalysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,MAAM,YAAY,CAAC;AAiU9C,eAAO,MAAM,YAAY,EAAE,IAAI,EA6G9B,CAAC"}
@@ -0,0 +1,356 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ // YAML 간단 파서 (기본적인 구조만)
4
+ function parseSimpleYaml(content) {
5
+ // JSON인 경우 바로 파싱
6
+ if (content.trim().startsWith("{")) {
7
+ return JSON.parse(content);
8
+ }
9
+ const result = {};
10
+ const lines = content.split("\n");
11
+ const stack = [{ indent: -1, obj: result, key: "" }];
12
+ for (const line of lines) {
13
+ if (!line.trim() || line.trim().startsWith("#"))
14
+ continue;
15
+ const indent = line.search(/\S/);
16
+ const trimmed = line.trim();
17
+ // 키-값 파싱
18
+ const colonIndex = trimmed.indexOf(":");
19
+ if (colonIndex === -1)
20
+ continue;
21
+ const key = trimmed.substring(0, colonIndex).trim();
22
+ let value = trimmed.substring(colonIndex + 1).trim();
23
+ // 따옴표 제거
24
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
25
+ value = value.slice(1, -1);
26
+ }
27
+ // 스택 조정
28
+ while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
29
+ stack.pop();
30
+ }
31
+ const parent = stack[stack.length - 1].obj;
32
+ if (value === "" || value === "|" || value === ">") {
33
+ // 중첩 객체
34
+ parent[key] = {};
35
+ stack.push({ indent, obj: parent[key], key });
36
+ }
37
+ else if (value.startsWith("[") && value.endsWith("]")) {
38
+ // 인라인 배열
39
+ parent[key] = value
40
+ .slice(1, -1)
41
+ .split(",")
42
+ .map((s) => s.trim().replace(/['"]/g, ""));
43
+ }
44
+ else if (trimmed.startsWith("- ")) {
45
+ // 배열 항목
46
+ if (!Array.isArray(parent)) {
47
+ const parentKey = stack[stack.length - 1].key;
48
+ const grandParent = stack.length > 1 ? stack[stack.length - 2].obj : result;
49
+ grandParent[parentKey] = [];
50
+ stack[stack.length - 1].obj = grandParent[parentKey];
51
+ }
52
+ stack[stack.length - 1].obj.push(trimmed.substring(2));
53
+ }
54
+ else {
55
+ parent[key] = value;
56
+ }
57
+ }
58
+ return result;
59
+ }
60
+ // OpenAPI 스펙 분석
61
+ function analyzeOpenApiSpec(filePath) {
62
+ const content = fs.readFileSync(filePath, "utf-8");
63
+ let spec;
64
+ try {
65
+ if (filePath.endsWith(".json")) {
66
+ spec = JSON.parse(content);
67
+ }
68
+ else {
69
+ spec = parseSimpleYaml(content);
70
+ }
71
+ }
72
+ catch (e) {
73
+ return {
74
+ file: filePath,
75
+ version: "unknown",
76
+ info: {},
77
+ endpoints: [],
78
+ schemas: [],
79
+ securitySchemes: [],
80
+ issues: [`파싱 실패: ${e}`],
81
+ summary: {
82
+ totalEndpoints: 0,
83
+ endpointsWithIssues: 0,
84
+ totalSchemas: 0,
85
+ coverage: { hasSummary: 0, hasDescription: 0, hasOperationId: 0, hasResponses: 0 },
86
+ },
87
+ };
88
+ }
89
+ const version = spec.openapi || spec.swagger || "unknown";
90
+ const info = spec.info || {};
91
+ const issues = [];
92
+ const endpoints = [];
93
+ // 전역 이슈 검사
94
+ if (!info.title)
95
+ issues.push("info.title 누락");
96
+ if (!info.version)
97
+ issues.push("info.version 누락");
98
+ if (!info.description)
99
+ issues.push("info.description 누락 (API 설명 권장)");
100
+ const servers = spec.servers?.map((s) => s.url || s) || [];
101
+ if (servers.length === 0 && !spec.host) {
102
+ issues.push("servers/host 미정의");
103
+ }
104
+ // paths 분석
105
+ const paths = spec.paths || {};
106
+ const httpMethods = ["get", "post", "put", "patch", "delete", "options", "head"];
107
+ for (const [pathUrl, pathItem] of Object.entries(paths)) {
108
+ if (!pathItem || typeof pathItem !== "object")
109
+ continue;
110
+ for (const method of httpMethods) {
111
+ const operation = pathItem[method];
112
+ if (!operation)
113
+ continue;
114
+ const endpointIssues = [];
115
+ // 엔드포인트 정보 추출
116
+ const parameters = [];
117
+ if (operation.parameters) {
118
+ for (const param of operation.parameters) {
119
+ parameters.push({
120
+ name: param.name || "unknown",
121
+ in: param.in || "query",
122
+ required: param.required || false,
123
+ type: param.schema?.type || param.type,
124
+ });
125
+ }
126
+ }
127
+ // 공통 파라미터
128
+ if (pathItem.parameters) {
129
+ for (const param of pathItem.parameters) {
130
+ parameters.push({
131
+ name: param.name || "unknown",
132
+ in: param.in || "query",
133
+ required: param.required || false,
134
+ type: param.schema?.type || param.type,
135
+ });
136
+ }
137
+ }
138
+ // 요청 본문
139
+ let requestBody;
140
+ if (operation.requestBody?.content) {
141
+ const contentTypes = Object.keys(operation.requestBody.content);
142
+ requestBody = {
143
+ contentType: contentTypes[0] || "unknown",
144
+ schema: operation.requestBody.content[contentTypes[0]]?.schema?.$ref,
145
+ };
146
+ }
147
+ // 응답
148
+ const responses = [];
149
+ if (operation.responses) {
150
+ for (const [status, response] of Object.entries(operation.responses)) {
151
+ responses.push({
152
+ status,
153
+ description: response?.description,
154
+ });
155
+ }
156
+ }
157
+ // 이슈 검사
158
+ if (!operation.summary && !operation.description) {
159
+ endpointIssues.push("summary/description 없음");
160
+ }
161
+ if (!operation.operationId) {
162
+ endpointIssues.push("operationId 없음 (코드 생성 시 필요)");
163
+ }
164
+ if (responses.length === 0) {
165
+ endpointIssues.push("responses 정의 없음");
166
+ }
167
+ else {
168
+ if (!responses.some((r) => r.status.startsWith("2"))) {
169
+ endpointIssues.push("성공 응답(2xx) 정의 없음");
170
+ }
171
+ if (!responses.some((r) => r.status.startsWith("4") || r.status.startsWith("5"))) {
172
+ endpointIssues.push("에러 응답(4xx/5xx) 정의 없음");
173
+ }
174
+ }
175
+ // POST/PUT/PATCH에 requestBody 없음
176
+ if (["post", "put", "patch"].includes(method) && !requestBody && !operation.requestBody) {
177
+ endpointIssues.push(`${method.toUpperCase()} 요청에 requestBody 없음`);
178
+ }
179
+ // 경로 파라미터 검사
180
+ const pathParams = (pathUrl.match(/\{([^}]+)\}/g) || []).map((p) => p.slice(1, -1));
181
+ for (const pathParam of pathParams) {
182
+ if (!parameters.some((p) => p.name === pathParam && p.in === "path")) {
183
+ endpointIssues.push(`경로 파라미터 '${pathParam}' 정의 없음`);
184
+ }
185
+ }
186
+ // 태그 없음
187
+ if (!operation.tags || operation.tags.length === 0) {
188
+ endpointIssues.push("tags 없음 (API 그룹화 권장)");
189
+ }
190
+ endpoints.push({
191
+ path: pathUrl,
192
+ method: method.toUpperCase(),
193
+ operationId: operation.operationId,
194
+ summary: operation.summary,
195
+ tags: operation.tags,
196
+ parameters,
197
+ requestBody,
198
+ responses,
199
+ issues: endpointIssues,
200
+ });
201
+ }
202
+ }
203
+ // 스키마 추출
204
+ const schemas = [];
205
+ const components = spec.components || spec.definitions || {};
206
+ if (components.schemas) {
207
+ schemas.push(...Object.keys(components.schemas));
208
+ }
209
+ else if (spec.definitions) {
210
+ schemas.push(...Object.keys(spec.definitions));
211
+ }
212
+ // 보안 스키마 추출
213
+ const securitySchemes = [];
214
+ if (components.securitySchemes) {
215
+ securitySchemes.push(...Object.keys(components.securitySchemes));
216
+ }
217
+ else if (spec.securityDefinitions) {
218
+ securitySchemes.push(...Object.keys(spec.securityDefinitions));
219
+ }
220
+ if (securitySchemes.length === 0) {
221
+ issues.push("securitySchemes 미정의 (인증 방식 정의 권장)");
222
+ }
223
+ // 커버리지 계산
224
+ const coverage = {
225
+ hasSummary: endpoints.filter((e) => e.summary).length,
226
+ hasDescription: endpoints.filter((e) => e.summary).length, // summary로 대체
227
+ hasOperationId: endpoints.filter((e) => e.operationId).length,
228
+ hasResponses: endpoints.filter((e) => e.responses.length > 0).length,
229
+ };
230
+ return {
231
+ file: filePath,
232
+ version,
233
+ info: {
234
+ title: info.title,
235
+ version: info.version,
236
+ description: info.description,
237
+ },
238
+ servers,
239
+ endpoints,
240
+ schemas,
241
+ securitySchemes,
242
+ issues,
243
+ summary: {
244
+ totalEndpoints: endpoints.length,
245
+ endpointsWithIssues: endpoints.filter((e) => e.issues.length > 0).length,
246
+ totalSchemas: schemas.length,
247
+ coverage,
248
+ },
249
+ };
250
+ }
251
+ // 도구 정의
252
+ export const openapiTools = [
253
+ {
254
+ name: "openapi_check",
255
+ description: "OpenAPI/Swagger 스펙 파일을 분석합니다. 엔드포인트, 파라미터, 응답을 추출하고 누락된 필드, 문서화 품질, 베스트 프랙티스를 검사합니다.",
256
+ parameters: {
257
+ type: "object",
258
+ properties: {
259
+ path: {
260
+ type: "string",
261
+ description: "분석할 OpenAPI/Swagger 파일 또는 디렉토리 경로 (.yaml, .yml, .json)",
262
+ },
263
+ recursive: {
264
+ type: "boolean",
265
+ description: "디렉토리인 경우 하위 폴더 포함 여부 (기본: true)",
266
+ },
267
+ },
268
+ required: ["path"],
269
+ },
270
+ handler: async (args) => {
271
+ const targetPath = args.path;
272
+ const recursive = args.recursive !== false;
273
+ if (!fs.existsSync(targetPath)) {
274
+ return {
275
+ success: false,
276
+ content: "",
277
+ error: `경로를 찾을 수 없습니다: ${targetPath}`,
278
+ };
279
+ }
280
+ const results = [];
281
+ const stats = fs.statSync(targetPath);
282
+ const apiExtensions = [".yaml", ".yml", ".json"];
283
+ const isOpenApiFile = (filePath) => {
284
+ const content = fs.readFileSync(filePath, "utf-8");
285
+ return content.includes("openapi") || content.includes("swagger") || content.includes("paths:");
286
+ };
287
+ const analyzeFile = (filePath) => {
288
+ try {
289
+ if (isOpenApiFile(filePath)) {
290
+ results.push(analyzeOpenApiSpec(filePath));
291
+ }
292
+ }
293
+ catch (e) {
294
+ // 파싱 실패 무시
295
+ }
296
+ };
297
+ if (stats.isFile()) {
298
+ analyzeFile(targetPath);
299
+ }
300
+ else if (stats.isDirectory()) {
301
+ const walkDir = (dir) => {
302
+ const files = fs.readdirSync(dir);
303
+ for (const file of files) {
304
+ const filePath = path.join(dir, file);
305
+ const fileStat = fs.statSync(filePath);
306
+ if (fileStat.isDirectory() && recursive) {
307
+ if (!file.startsWith(".") && file !== "node_modules" && file !== "target" && file !== "build") {
308
+ walkDir(filePath);
309
+ }
310
+ }
311
+ else {
312
+ const ext = path.extname(file).toLowerCase();
313
+ if (apiExtensions.includes(ext)) {
314
+ analyzeFile(filePath);
315
+ }
316
+ }
317
+ }
318
+ };
319
+ walkDir(targetPath);
320
+ }
321
+ // 전체 통계
322
+ const totalEndpoints = results.reduce((sum, r) => sum + r.summary.totalEndpoints, 0);
323
+ const totalWithIssues = results.reduce((sum, r) => sum + r.summary.endpointsWithIssues, 0);
324
+ const output = {
325
+ analyzedFiles: results.length,
326
+ totalEndpoints,
327
+ endpointsWithIssues: totalWithIssues,
328
+ specs: results.map((r) => ({
329
+ file: r.file,
330
+ version: r.version,
331
+ info: r.info,
332
+ servers: r.servers,
333
+ schemas: r.schemas,
334
+ securitySchemes: r.securitySchemes,
335
+ specIssues: r.issues,
336
+ summary: r.summary,
337
+ endpoints: r.endpoints.map((e) => ({
338
+ method: e.method,
339
+ path: e.path,
340
+ operationId: e.operationId,
341
+ summary: e.summary,
342
+ tags: e.tags,
343
+ parametersCount: e.parameters.length,
344
+ responsesCount: e.responses.length,
345
+ issues: e.issues,
346
+ })),
347
+ })),
348
+ };
349
+ return {
350
+ success: true,
351
+ content: JSON.stringify(output, null, 2),
352
+ };
353
+ },
354
+ },
355
+ ];
356
+ //# sourceMappingURL=openapiAnalysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapiAnalysis.js","sourceRoot":"","sources":["../../../src/core/tools/openapiAnalysis.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAmD7B,wBAAwB;AACxB,SAAS,eAAe,CAAC,OAAe;IACtC,iBAAiB;IACjB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,MAAM,GAAQ,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,KAAK,GAAgD,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IAElG,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAE1D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAE5B,SAAS;QACT,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,UAAU,KAAK,CAAC,CAAC;YAAE,SAAS;QAEhC,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;QACpD,IAAI,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAErD,SAAS;QACT,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACrG,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,QAAQ;QACR,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;YACpE,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAE3C,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YACnD,QAAQ;YACR,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxD,SAAS;YACT,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK;iBAChB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;iBACZ,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,QAAQ;YACR,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC9C,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC5E,WAAW,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;gBAC5B,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;YACvD,CAAC;YACD,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gBAAgB;AAChB,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,IAAS,CAAC;IAEd,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,SAAS;YAClB,IAAI,EAAE,EAAE;YACR,SAAS,EAAE,EAAE;YACb,OAAO,EAAE,EAAE;YACX,eAAe,EAAE,EAAE;YACnB,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE;gBACP,cAAc,EAAE,CAAC;gBACjB,mBAAmB,EAAE,CAAC;gBACtB,YAAY,EAAE,CAAC;gBACf,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE;aACnF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,SAAS,CAAC;IAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAkB,EAAE,CAAC;IAEpC,WAAW;IACX,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI,CAAC,OAAO;QAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAClD,IAAI,CAAC,IAAI,CAAC,WAAW;QAAE,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAEtE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAChE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAClC,CAAC;IAED,WAAW;IACX,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAEjF,KAAK,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,SAAS;QAExD,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;YACjC,MAAM,SAAS,GAAI,QAAgB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,SAAS;gBAAE,SAAS;YAEzB,MAAM,cAAc,GAAa,EAAE,CAAC;YAEpC,cAAc;YACd,MAAM,UAAU,GAA8B,EAAE,CAAC;YACjD,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;gBACzB,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;oBACzC,UAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,SAAS;wBAC7B,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,OAAO;wBACvB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK;wBACjC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,IAAI,KAAK,CAAC,IAAI;qBACvC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,UAAU;YACV,IAAK,QAAgB,CAAC,UAAU,EAAE,CAAC;gBACjC,KAAK,MAAM,KAAK,IAAK,QAAgB,CAAC,UAAU,EAAE,CAAC;oBACjD,UAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,SAAS;wBAC7B,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,OAAO;wBACvB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK;wBACjC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,IAAI,KAAK,CAAC,IAAI;qBACvC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,QAAQ;YACR,IAAI,WAAuC,CAAC;YAC5C,IAAI,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC;gBACnC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;gBAChE,WAAW,GAAG;oBACZ,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,SAAS;oBACzC,MAAM,EAAE,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI;iBACrE,CAAC;YACJ,CAAC;YAED,KAAK;YACL,MAAM,SAAS,GAA6B,EAAE,CAAC;YAC/C,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;gBACxB,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;oBACrE,SAAS,CAAC,IAAI,CAAC;wBACb,MAAM;wBACN,WAAW,EAAG,QAAgB,EAAE,WAAW;qBAC5C,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,QAAQ;YACR,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;gBACjD,cAAc,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YAChD,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;gBAC3B,cAAc,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YACrD,CAAC;YACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3B,cAAc,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBACrD,cAAc,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;gBAC1C,CAAC;gBACD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBACjF,cAAc,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;YAED,iCAAiC;YACjC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;gBACxF,cAAc,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;YACpE,CAAC;YAED,aAAa;YACb,MAAM,UAAU,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACpF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;gBACnC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC;oBACrE,cAAc,CAAC,IAAI,CAAC,YAAY,SAAS,SAAS,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;YAED,QAAQ;YACR,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnD,cAAc,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;YAC9C,CAAC;YAED,SAAS,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE;gBAC5B,WAAW,EAAE,SAAS,CAAC,WAAW;gBAClC,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,UAAU;gBACV,WAAW;gBACX,SAAS;gBACT,MAAM,EAAE,cAAc;aACvB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,SAAS;IACT,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;IAC7D,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,CAAC;SAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,YAAY;IACZ,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,IAAI,UAAU,CAAC,eAAe,EAAE,CAAC;QAC/B,eAAe,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC;IACnE,CAAC;SAAM,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACpC,eAAe,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IACnD,CAAC;IAED,UAAU;IACV,MAAM,QAAQ,GAAG;QACf,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM;QACrD,cAAc,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,cAAc;QACzE,cAAc,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM;QAC7D,YAAY,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM;KACrE,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,OAAO;QACP,IAAI,EAAE;YACJ,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B;QACD,OAAO;QACP,SAAS;QACT,OAAO;QACP,eAAe;QACf,MAAM;QACN,OAAO,EAAE;YACP,cAAc,EAAE,SAAS,CAAC,MAAM;YAChC,mBAAmB,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM;YACxE,YAAY,EAAE,OAAO,CAAC,MAAM;YAC5B,QAAQ;SACT;KACF,CAAC;AACJ,CAAC;AAED,QAAQ;AACR,MAAM,CAAC,MAAM,YAAY,GAAW;IAClC;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,sFAAsF;QACxF,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wDAAwD;iBACtE;gBACD,SAAS,EAAE;oBACT,IAAI,EAAE,SAAS;oBACf,WAAW,EAAE,iCAAiC;iBAC/C;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;SACnB;QACD,OAAO,EAAE,KAAK,EAAE,IAA6B,EAAuB,EAAE;YACpE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAc,CAAC;YACvC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;YAE3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/B,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,OAAO,EAAE,EAAE;oBACX,KAAK,EAAE,kBAAkB,UAAU,EAAE;iBACtC,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAA4B,EAAE,CAAC;YAC5C,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YACtC,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAEjD,MAAM,aAAa,GAAG,CAAC,QAAgB,EAAW,EAAE;gBAClD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACnD,OAAO,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAClG,CAAC,CAAC;YAEF,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,EAAE;gBACvC,IAAI,CAAC;oBACH,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;wBAC5B,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC;oBAC7C,CAAC;gBACH,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,WAAW;gBACb,CAAC;YACH,CAAC,CAAC;YAEF,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnB,WAAW,CAAC,UAAU,CAAC,CAAC;YAC1B,CAAC;iBAAM,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC/B,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,EAAE;oBAC9B,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;oBAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;wBACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;wBACtC,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;wBACvC,IAAI,QAAQ,CAAC,WAAW,EAAE,IAAI,SAAS,EAAE,CAAC;4BACxC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,cAAc,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gCAC9F,OAAO,CAAC,QAAQ,CAAC,CAAC;4BACpB,CAAC;wBACH,CAAC;6BAAM,CAAC;4BACN,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;4BAC7C,IAAI,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gCAChC,WAAW,CAAC,QAAQ,CAAC,CAAC;4BACxB,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC,CAAC;gBACF,OAAO,CAAC,UAAU,CAAC,CAAC;YACtB,CAAC;YAED,QAAQ;YACR,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;YACrF,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC;YAE3F,MAAM,MAAM,GAAG;gBACb,aAAa,EAAE,OAAO,CAAC,MAAM;gBAC7B,cAAc;gBACd,mBAAmB,EAAE,eAAe;gBACpC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACzB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,eAAe,EAAE,CAAC,CAAC,eAAe;oBAClC,UAAU,EAAE,CAAC,CAAC,MAAM;oBACpB,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBACjC,MAAM,EAAE,CAAC,CAAC,MAAM;wBAChB,IAAI,EAAE,CAAC,CAAC,IAAI;wBACZ,WAAW,EAAE,CAAC,CAAC,WAAW;wBAC1B,OAAO,EAAE,CAAC,CAAC,OAAO;wBAClB,IAAI,EAAE,CAAC,CAAC,IAAI;wBACZ,eAAe,EAAE,CAAC,CAAC,UAAU,CAAC,MAAM;wBACpC,cAAc,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM;wBAClC,MAAM,EAAE,CAAC,CAAC,MAAM;qBACjB,CAAC,CAAC;iBACJ,CAAC,CAAC;aACJ,CAAC;YAEF,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;aACzC,CAAC;QACJ,CAAC;KACF;CACF,CAAC"}