@kridaydave/code-mapper 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 (53) hide show
  1. package/AGENTS.md +174 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +113 -0
  4. package/dist/graph/Graph.test.js +173 -0
  5. package/dist/graph/Graph.test.js.map +1 -0
  6. package/dist/graph/GraphAnalyzer.js +435 -0
  7. package/dist/graph/GraphAnalyzer.js.map +1 -0
  8. package/dist/graph/GraphBuilder.js +225 -0
  9. package/dist/graph/GraphBuilder.js.map +1 -0
  10. package/dist/graph/types.js +2 -0
  11. package/dist/graph/types.js.map +1 -0
  12. package/dist/index.js +29 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/mcp/cache.js +72 -0
  15. package/dist/mcp/cache.js.map +1 -0
  16. package/dist/mcp/resources.js +119 -0
  17. package/dist/mcp/resources.js.map +1 -0
  18. package/dist/mcp/tools.js +444 -0
  19. package/dist/mcp/tools.js.map +1 -0
  20. package/dist/mcp/tools.test.js +81 -0
  21. package/dist/mcp/tools.test.js.map +1 -0
  22. package/dist/parser/ComplexityAnalyzer.js +208 -0
  23. package/dist/parser/ComplexityAnalyzer.js.map +1 -0
  24. package/dist/parser/FileAnalyzer.js +191 -0
  25. package/dist/parser/FileAnalyzer.js.map +1 -0
  26. package/dist/parser/ProjectParser.js +134 -0
  27. package/dist/parser/ProjectParser.js.map +1 -0
  28. package/dist/parser/ProjectParser.test.js +77 -0
  29. package/dist/parser/ProjectParser.test.js.map +1 -0
  30. package/dist/parser/types.js +2 -0
  31. package/dist/parser/types.js.map +1 -0
  32. package/docs/PHASE2_PLAN.md +435 -0
  33. package/fixtures/test-project/calculator.ts +28 -0
  34. package/fixtures/test-project/index.ts +2 -0
  35. package/fixtures/test-project/math.ts +11 -0
  36. package/package.json +35 -0
  37. package/src/graph/Graph.test.ts +222 -0
  38. package/src/graph/GraphAnalyzer.ts +502 -0
  39. package/src/graph/GraphBuilder.ts +258 -0
  40. package/src/graph/types.ts +42 -0
  41. package/src/index.ts +38 -0
  42. package/src/mcp/cache.ts +89 -0
  43. package/src/mcp/resources.ts +137 -0
  44. package/src/mcp/tools.test.ts +104 -0
  45. package/src/mcp/tools.ts +529 -0
  46. package/src/parser/ComplexityAnalyzer.ts +275 -0
  47. package/src/parser/FileAnalyzer.ts +215 -0
  48. package/src/parser/ProjectParser.test.ts +96 -0
  49. package/src/parser/ProjectParser.ts +172 -0
  50. package/src/parser/types.ts +77 -0
  51. package/src/types/graphology-pagerank.d.ts +20 -0
  52. package/tsconfig.json +17 -0
  53. package/vitest.config.ts +15 -0
@@ -0,0 +1,225 @@
1
+ import { createRequire } from "node:module";
2
+ const require = createRequire(import.meta.url);
3
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
4
+ const Graph = require("graphology");
5
+ export class GraphBuilder {
6
+ build(parseResult) {
7
+ const graph = new Graph({ multi: true });
8
+ const nodes = [];
9
+ const edges = [];
10
+ const classLookup = new Map();
11
+ for (const fileInfo of parseResult.files) {
12
+ for (const cls of fileInfo.classes) {
13
+ classLookup.set(fileInfo.filePath + "::" + cls.name, { filePath: fileInfo.filePath, name: cls.name, lineNumber: cls.lineNumber });
14
+ }
15
+ }
16
+ const fileNodeIds = new Map();
17
+ // Phase 1: Create file nodes
18
+ for (const fileInfo of parseResult.files) {
19
+ const fileId = `file:${fileInfo.filePath}`;
20
+ fileNodeIds.set(fileInfo.relativePath, fileId);
21
+ fileNodeIds.set(fileInfo.filePath, fileId);
22
+ graph.addNode(fileId, {
23
+ kind: "file",
24
+ label: fileInfo.relativePath,
25
+ filePath: fileInfo.filePath,
26
+ });
27
+ nodes.push({
28
+ id: fileId,
29
+ kind: "file",
30
+ label: fileInfo.relativePath,
31
+ filePath: fileInfo.filePath,
32
+ });
33
+ }
34
+ // Phase 2: Create function and class nodes, add containment edges
35
+ for (const fileInfo of parseResult.files) {
36
+ const fileId = `file:${fileInfo.filePath}`;
37
+ for (const fn of fileInfo.functions) {
38
+ const fnId = `fn:${fileInfo.filePath}:${fn.name}:${fn.lineNumber}`;
39
+ graph.addNode(fnId, {
40
+ kind: "function",
41
+ label: fn.name,
42
+ filePath: fileInfo.filePath,
43
+ lineNumber: fn.lineNumber,
44
+ });
45
+ graph.addEdge(fileId, fnId, {
46
+ kind: "contains",
47
+ label: `contains ${fn.name}`,
48
+ });
49
+ edges.push({
50
+ source: fileId,
51
+ target: fnId,
52
+ kind: "contains",
53
+ label: `contains ${fn.name}`,
54
+ });
55
+ nodes.push({
56
+ id: fnId,
57
+ kind: "function",
58
+ label: fn.name,
59
+ filePath: fileInfo.filePath,
60
+ lineNumber: fn.lineNumber,
61
+ });
62
+ }
63
+ for (const cls of fileInfo.classes) {
64
+ const clsId = `class:${fileInfo.filePath}:${cls.name}:${cls.lineNumber}`;
65
+ graph.addNode(clsId, {
66
+ kind: "class",
67
+ label: cls.name,
68
+ filePath: fileInfo.filePath,
69
+ lineNumber: cls.lineNumber,
70
+ });
71
+ graph.addEdge(fileId, clsId, {
72
+ kind: "contains",
73
+ label: `contains ${cls.name}`,
74
+ });
75
+ edges.push({
76
+ source: fileId,
77
+ target: clsId,
78
+ kind: "contains",
79
+ label: `contains ${cls.name}`,
80
+ });
81
+ nodes.push({
82
+ id: clsId,
83
+ kind: "class",
84
+ label: cls.name,
85
+ filePath: fileInfo.filePath,
86
+ lineNumber: cls.lineNumber,
87
+ });
88
+ }
89
+ }
90
+ // Phase 3: Build import edges between files
91
+ for (const fileInfo of parseResult.files) {
92
+ const sourceFileId = `file:${fileInfo.filePath}`;
93
+ for (const imp of fileInfo.imports) {
94
+ const targetPath = this.resolveImportPath(fileInfo.filePath, imp.moduleSpecifier, parseResult);
95
+ if (targetPath) {
96
+ const targetFileId = `file:${targetPath}`;
97
+ if (graph.hasNode(targetFileId)) {
98
+ const edgeLabel = imp.namedImports.length > 0
99
+ ? `imports {${imp.namedImports.join(", ")}}`
100
+ : imp.defaultImport
101
+ ? `imports ${imp.defaultImport}`
102
+ : "imports module";
103
+ if (!graph.hasEdge(sourceFileId, targetFileId)) {
104
+ graph.addEdge(sourceFileId, targetFileId, {
105
+ kind: "imports",
106
+ label: edgeLabel,
107
+ });
108
+ edges.push({
109
+ source: sourceFileId,
110
+ target: targetFileId,
111
+ kind: "imports",
112
+ label: edgeLabel,
113
+ });
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }
119
+ // Phase 4: Build extends/implements edges for classes
120
+ for (const fileInfo of parseResult.files) {
121
+ for (const cls of fileInfo.classes) {
122
+ const clsId = `class:${fileInfo.filePath}:${cls.name}:${cls.lineNumber}`;
123
+ if (cls.extends) {
124
+ // Try to find the parent class in the codebase
125
+ const parentName = cls.extends.split("<")[0].trim(); // Handle generics
126
+ const parentClass = this.findClassByName(parentName, parseResult, classLookup);
127
+ if (parentClass) {
128
+ const parentId = `class:${parentClass.filePath}:${parentClass.name}:${parentClass.lineNumber}`;
129
+ if (graph.hasNode(parentId)) {
130
+ graph.addEdge(clsId, parentId, {
131
+ kind: "extends",
132
+ label: `extends ${parentClass.name}`,
133
+ });
134
+ edges.push({
135
+ source: clsId,
136
+ target: parentId,
137
+ kind: "extends",
138
+ label: `extends ${parentClass.name}`,
139
+ });
140
+ }
141
+ }
142
+ }
143
+ for (const impl of cls.implements) {
144
+ const implName = impl.split("<")[0].trim();
145
+ const implClass = this.findClassByName(implName, parseResult, classLookup);
146
+ if (implClass) {
147
+ const implId = `class:${implClass.filePath}:${implClass.name}:${implClass.lineNumber}`;
148
+ if (graph.hasNode(implId)) {
149
+ graph.addEdge(clsId, implId, {
150
+ kind: "implements",
151
+ label: `implements ${implClass.name}`,
152
+ });
153
+ edges.push({
154
+ source: clsId,
155
+ target: implId,
156
+ kind: "implements",
157
+ label: `implements ${implClass.name}`,
158
+ });
159
+ }
160
+ }
161
+ }
162
+ }
163
+ }
164
+ return { graph, nodes, edges };
165
+ }
166
+ resolveImportPath(fromFile, moduleSpecifier, parseResult) {
167
+ // Skip external packages (no leading . or /)
168
+ if (!moduleSpecifier.startsWith(".") && !moduleSpecifier.startsWith("/")) {
169
+ return null;
170
+ }
171
+ // Strip .js/.jsx/.ts/.tsx extension from the specifier
172
+ let specifier = moduleSpecifier;
173
+ for (const ext of [".js", ".jsx", ".ts", ".tsx"]) {
174
+ if (specifier.endsWith(ext)) {
175
+ specifier = specifier.slice(0, -ext.length);
176
+ break;
177
+ }
178
+ }
179
+ // Resolve relative path using forward-slash logic (ts-morph always uses /)
180
+ const fromDir = fromFile.replace(/\\/g, "/").replace(/\/[^/]+$/, "");
181
+ const parts = [...(fromDir === "" ? [] : fromDir.split("/")), ...specifier.split("/")];
182
+ const resolved = [];
183
+ for (const part of parts) {
184
+ if (part === "..") {
185
+ if (resolved.length > 0) {
186
+ resolved.pop();
187
+ }
188
+ // else: excessive ".." — ignore, prevents escaping root
189
+ }
190
+ else if (part !== "." && part !== "") {
191
+ resolved.push(part);
192
+ }
193
+ }
194
+ // Reconstruct with the drive prefix if present
195
+ let resolvedPath = resolved.join("/");
196
+ // If original fromFile had a Windows drive letter, preserve it
197
+ const fromFileNormalized = fromFile.replace(/\\/g, "/");
198
+ const driveMatch = fromFileNormalized.match(/^([A-Za-z]:\/)/);
199
+ if (driveMatch && !resolvedPath.startsWith(driveMatch[1])) {
200
+ resolvedPath = driveMatch[1] + resolvedPath;
201
+ }
202
+ // Try exact match first
203
+ if (parseResult.files.some(f => f.filePath === resolvedPath)) {
204
+ return resolvedPath;
205
+ }
206
+ // Try adding extensions
207
+ const extensions = [".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.tsx", "/index.js", "/index.jsx"];
208
+ for (const ext of extensions) {
209
+ const candidate = resolvedPath + ext;
210
+ if (parseResult.files.some(f => f.filePath === candidate)) {
211
+ return candidate;
212
+ }
213
+ }
214
+ return null;
215
+ }
216
+ findClassByName(name, _parseResult, classLookup) {
217
+ for (const [_key, value] of classLookup) {
218
+ if (value.name === name) {
219
+ return value;
220
+ }
221
+ }
222
+ return null;
223
+ }
224
+ }
225
+ //# sourceMappingURL=GraphBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphBuilder.js","sourceRoot":"","sources":["../../src/graph/GraphBuilder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/server";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/server";
4
+ import { registerTools } from "./mcp/tools.js";
5
+ import { registerResources } from "./mcp/resources.js";
6
+ async function main() {
7
+ const server = new McpServer({
8
+ name: "code-mapper",
9
+ version: "1.0.0",
10
+ }, {
11
+ instructions: "CodeMapper analyzes TypeScript/JavaScript codebases using AST parsing. " +
12
+ "Always start by calling scan_codebase with the target directory. " +
13
+ "Then use find_function to locate symbols, analyze_dependencies to see the graph, " +
14
+ "rank_impact to find central files, or trace_call_chain to follow dependency paths. " +
15
+ "The codebase://summary and codebase://graph/{format} resources provide cached views.",
16
+ });
17
+ // Register all tools and resources
18
+ registerTools(server);
19
+ registerResources(server);
20
+ // Connect via stdio
21
+ const transport = new StdioServerTransport();
22
+ await server.connect(transport);
23
+ console.error("CodeMapper MCP server running on stdio");
24
+ }
25
+ main().catch((error) => {
26
+ console.error("Fatal error:", error);
27
+ process.exit(1);
28
+ });
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,SAAS,CACzB;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EACV,yEAAyE;YACzE,mEAAmE;YACnE,mFAAmF;YACnF,qFAAqF;YACrF,sFAAsF;KACzF,CACH,CAAC;IAEF,mCAAmC;IACnC,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE1B,oBAAoB;IACpB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;AAC1D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { resolve } from "node:path";
2
+ const MAX_CACHE_SIZE = 10;
3
+ const CACHE_TTL_MS = 30 * 60 * 1000;
4
+ export const analyzerCache = new Map();
5
+ const pendingAnalyzers = new Map();
6
+ let _lastScannedDirectory = null;
7
+ export function setLastScannedDirectory(dir) {
8
+ _lastScannedDirectory = dir;
9
+ }
10
+ export function getLastScannedDirectory() {
11
+ return _lastScannedDirectory;
12
+ }
13
+ export function normalizeCacheKey(directory) {
14
+ return resolve(directory);
15
+ }
16
+ function evictIfNeeded() {
17
+ if (analyzerCache.size >= MAX_CACHE_SIZE) {
18
+ let oldestKey = null;
19
+ let oldestTime = Infinity;
20
+ for (const [key, entry] of analyzerCache) {
21
+ if (entry.timestamp < oldestTime) {
22
+ oldestTime = entry.timestamp;
23
+ oldestKey = key;
24
+ }
25
+ }
26
+ if (oldestKey) {
27
+ analyzerCache.delete(oldestKey);
28
+ }
29
+ }
30
+ }
31
+ function isEntryExpired(entry) {
32
+ return Date.now() - entry.timestamp > CACHE_TTL_MS;
33
+ }
34
+ export function getAnalyzerFromCache(directory) {
35
+ const normalizedDir = normalizeCacheKey(directory);
36
+ const entry = analyzerCache.get(normalizedDir);
37
+ if (entry && !isEntryExpired(entry)) {
38
+ return entry.analyzer;
39
+ }
40
+ if (entry) {
41
+ analyzerCache.delete(normalizedDir);
42
+ }
43
+ return undefined;
44
+ }
45
+ export function setAnalyzerInCache(directory, analyzer) {
46
+ evictIfNeeded();
47
+ const normalizedDir = normalizeCacheKey(directory);
48
+ analyzerCache.set(normalizedDir, {
49
+ analyzer,
50
+ timestamp: Date.now(),
51
+ });
52
+ }
53
+ export function getPendingAnalyzer(directory) {
54
+ const normalizedDir = normalizeCacheKey(directory);
55
+ return pendingAnalyzers.get(normalizedDir);
56
+ }
57
+ export function setPendingAnalyzer(directory, promise) {
58
+ const normalizedDir = normalizeCacheKey(directory);
59
+ pendingAnalyzers.set(normalizedDir, promise);
60
+ promise.finally(() => {
61
+ pendingAnalyzers.delete(normalizedDir);
62
+ });
63
+ }
64
+ export function clearAnalyzerCache(directory) {
65
+ if (directory) {
66
+ analyzerCache.delete(normalizeCacheKey(directory));
67
+ }
68
+ else {
69
+ analyzerCache.clear();
70
+ }
71
+ }
72
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/mcp/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import { ResourceTemplate } from "@modelcontextprotocol/server";
2
+ import { analyzerCache, getLastScannedDirectory } from "./cache.js";
3
+ const RANK_CACHE_LIMIT = 100;
4
+ const rankCache = new Map();
5
+ export function registerResources(server) {
6
+ // Resource 1: codebase://summary
7
+ server.registerResource("codebase-summary", "codebase://summary", {
8
+ title: "Codebase Summary",
9
+ description: "Returns a summary of the most recently scanned codebase. Scan a codebase first using the scan_codebase tool.",
10
+ mimeType: "application/json",
11
+ }, async () => {
12
+ if (analyzerCache.size === 0) {
13
+ return {
14
+ contents: [{
15
+ uri: "codebase://summary",
16
+ text: JSON.stringify({ message: "No codebase has been scanned yet. Use the scan_codebase tool first." }, null, 2),
17
+ }],
18
+ };
19
+ }
20
+ const summaries = [];
21
+ for (const [directory, entry] of analyzerCache) {
22
+ const analyzer = entry.analyzer;
23
+ const nodes = analyzer.getNodes();
24
+ const edges = analyzer.getEdges();
25
+ let ranked;
26
+ if (rankCache.has(directory)) {
27
+ ranked = rankCache.get(directory);
28
+ }
29
+ else {
30
+ ranked = analyzer.rankImpact("inDegree");
31
+ rankCache.set(directory, ranked);
32
+ }
33
+ const cycles = analyzer.detectCycles();
34
+ const fileNodes = nodes.filter((n) => n.kind === "file");
35
+ const functionNodes = nodes.filter((n) => n.kind === "function");
36
+ const classNodes = nodes.filter((n) => n.kind === "class");
37
+ summaries.push({
38
+ directory,
39
+ totalFiles: fileNodes.length,
40
+ totalFunctions: functionNodes.length,
41
+ totalClasses: classNodes.length,
42
+ totalEdges: edges.length,
43
+ mostCentralFile: ranked.length > 0 ? ranked[0] : null,
44
+ cycleCount: cycles.length,
45
+ topDependencies: ranked.slice(0, 5).map((r) => ({
46
+ path: r.relativePath,
47
+ inDegree: r.score,
48
+ })),
49
+ });
50
+ }
51
+ return {
52
+ contents: [{
53
+ uri: "codebase://summary",
54
+ text: JSON.stringify({ scannedCodebases: summaries }, null, 2),
55
+ }],
56
+ };
57
+ });
58
+ // Resource 2: codebase://graph/{format}
59
+ server.registerResource("codebase-graph", new ResourceTemplate("codebase://graph/{format}", {
60
+ list: async () => ({
61
+ resources: [
62
+ { uri: "codebase://graph/json", name: "Graph (JSON)" },
63
+ { uri: "codebase://graph/mermaid", name: "Graph (Mermaid)" },
64
+ ],
65
+ }),
66
+ }), {
67
+ title: "Codebase Dependency Graph",
68
+ description: "Returns the dependency graph of the scanned codebase in JSON or Mermaid format.",
69
+ mimeType: "application/json",
70
+ }, async (uri, { format }) => {
71
+ if (analyzerCache.size === 0) {
72
+ return {
73
+ contents: [{
74
+ uri: uri.href,
75
+ text: JSON.stringify({ message: "No codebase has been scanned yet. Use the scan_codebase tool first." }, null, 2),
76
+ }],
77
+ };
78
+ }
79
+ const targetKey = getLastScannedDirectory();
80
+ if (!targetKey) {
81
+ return {
82
+ contents: [{
83
+ uri: uri.href,
84
+ text: JSON.stringify({ message: "No codebase has been scanned yet. Use the scan_codebase tool first." }, null, 2),
85
+ }],
86
+ };
87
+ }
88
+ const entry = analyzerCache.get(targetKey);
89
+ if (!entry) {
90
+ return {
91
+ contents: [{
92
+ uri: uri.href,
93
+ text: JSON.stringify({ message: "Analyzer not found for the most recently scanned codebase." }, null, 2),
94
+ }],
95
+ };
96
+ }
97
+ const analyzer = entry.analyzer;
98
+ const nodes = analyzer.getNodes();
99
+ const edges = analyzer.getEdges();
100
+ let content;
101
+ if (format === "mermaid") {
102
+ content = analyzer.toMermaid();
103
+ }
104
+ else {
105
+ content = JSON.stringify({
106
+ directory: targetKey,
107
+ nodes: nodes.map((n) => ({ id: n.id, kind: n.kind, label: n.label, filePath: n.filePath })),
108
+ edges: edges.map((e) => ({ source: e.source, target: e.target, kind: e.kind, label: e.label })),
109
+ }, null, 2);
110
+ }
111
+ return {
112
+ contents: [{
113
+ uri: uri.href,
114
+ text: content,
115
+ }],
116
+ };
117
+ });
118
+ }
119
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/mcp/resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAE3E,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAwB,MAAM,YAAY,CAAC;AAE1F,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAwB,CAAC;AAElD,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,iCAAiC;IACjC,MAAM,CAAC,gBAAgB,CACrB,kBAAkB,EAClB,oBAAoB,EACpB;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,8GAA8G;QAC3H,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,IAAI,EAAE;QACT,IAAI,aAAa,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,QAAQ,EAAE,CAAC;wBACT,GAAG,EAAE,oBAAoB;wBACzB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,qEAAqE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;qBAClH,CAAC;aACH,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAA8B,EAAE,CAAC;QAChD,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,aAAa,EAAE,CAAC;YAC/C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;YAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAClC,IAAI,MAAoB,CAAC;YACzB,IAAI,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7B,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;gBACzC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACnC,CAAC;YACD,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,EAAE,CAAC;YAEvC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;YACpE,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;YAC5E,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;YAEtE,SAAS,CAAC,IAAI,CAAC;gBACb,SAAS;gBACT,UAAU,EAAE,SAAS,CAAC,MAAM;gBAC5B,cAAc,EAAE,aAAa,CAAC,MAAM;gBACpC,YAAY,EAAE,UAAU,CAAC,MAAM;gBAC/B,UAAU,EAAE,KAAK,CAAC,MAAM;gBACxB,eAAe,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;gBACrD,UAAU,EAAE,MAAM,CAAC,MAAM;gBACzB,eAAe,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC;oBAC1D,IAAI,EAAE,CAAC,CAAC,YAAY;oBACpB,QAAQ,EAAE,CAAC,CAAC,KAAK;iBAClB,CAAC,CAAC;aACJ,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,oBAAoB;oBACzB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,gBAAgB,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;iBAC/D,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,wCAAwC;IACxC,MAAM,CAAC,gBAAgB,CACrB,gBAAgB,EAChB,IAAI,gBAAgB,CAAC,2BAA2B,EAAE;QAChD,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACjB,SAAS,EAAE;gBACT,EAAE,GAAG,EAAE,uBAAuB,EAAE,IAAI,EAAE,cAAc,EAAE;gBACtD,EAAE,GAAG,EAAE,0BAA0B,EAAE,IAAI,EAAE,iBAAiB,EAAE;aAC7D;SACF,CAAC;KACH,CAAC,EACF;QACE,KAAK,EAAE,2BAA2B;QAClC,WAAW,EAAE,iFAAiF;QAC9F,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QACxB,IAAI,aAAa,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,QAAQ,EAAE,CAAC;wBACT,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,qEAAqE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;qBAClH,CAAC;aACH,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,uBAAuB,EAAE,CAAC;QAC5C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;gBACL,QAAQ,EAAE,CAAC;wBACT,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,qEAAqE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;qBAClH,CAAC;aACH,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;gBACL,QAAQ,EAAE,CAAC;wBACT,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,4DAA4D,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;qBACzG,CAAC;aACH,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAElC,IAAI,OAAe,CAAC;QACpB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;gBACvB,SAAS,EAAE,SAAS;gBACpB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACtG,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;aAC3G,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACd,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,IAAI,EAAE,OAAO;iBACd,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}