@mgamil/mapx 0.2.4

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 (203) hide show
  1. package/LICENSE +194 -0
  2. package/README.md +488 -0
  3. package/VERSION +1 -0
  4. package/dist/agents/generator.d.ts +74 -0
  5. package/dist/agents/generator.js +375 -0
  6. package/dist/agents/templates.d.ts +29 -0
  7. package/dist/agents/templates.js +459 -0
  8. package/dist/cli.d.ts +16 -0
  9. package/dist/cli.js +1835 -0
  10. package/dist/core/cluster-engine.d.ts +32 -0
  11. package/dist/core/cluster-engine.js +314 -0
  12. package/dist/core/config.d.ts +29 -0
  13. package/dist/core/config.js +178 -0
  14. package/dist/core/context-builder.d.ts +61 -0
  15. package/dist/core/context-builder.js +252 -0
  16. package/dist/core/flow-tracer.d.ts +63 -0
  17. package/dist/core/flow-tracer.js +366 -0
  18. package/dist/core/git-tracker.d.ts +20 -0
  19. package/dist/core/git-tracker.js +159 -0
  20. package/dist/core/graph.d.ts +42 -0
  21. package/dist/core/graph.js +186 -0
  22. package/dist/core/metrics.d.ts +24 -0
  23. package/dist/core/metrics.js +87 -0
  24. package/dist/core/scanner.d.ts +53 -0
  25. package/dist/core/scanner.js +949 -0
  26. package/dist/core/store-bun.d.ts +13 -0
  27. package/dist/core/store-bun.js +34 -0
  28. package/dist/core/store-interface.d.ts +15 -0
  29. package/dist/core/store-interface.js +7 -0
  30. package/dist/core/store-node.d.ts +13 -0
  31. package/dist/core/store-node.js +35 -0
  32. package/dist/core/store.d.ts +132 -0
  33. package/dist/core/store.js +614 -0
  34. package/dist/core/workspace-manager.d.ts +9 -0
  35. package/dist/core/workspace-manager.js +64 -0
  36. package/dist/exporters/dot-exporter.d.ts +16 -0
  37. package/dist/exporters/dot-exporter.js +179 -0
  38. package/dist/exporters/graph-exporter.d.ts +14 -0
  39. package/dist/exporters/graph-exporter.js +85 -0
  40. package/dist/exporters/index.d.ts +9 -0
  41. package/dist/exporters/index.js +12 -0
  42. package/dist/exporters/llm-exporter.d.ts +18 -0
  43. package/dist/exporters/llm-exporter.js +224 -0
  44. package/dist/exporters/svg-exporter.d.ts +19 -0
  45. package/dist/exporters/svg-exporter.js +319 -0
  46. package/dist/exporters/toon-exporter.d.ts +16 -0
  47. package/dist/exporters/toon-exporter.js +246 -0
  48. package/dist/frameworks/detectors/aspnet.d.ts +11 -0
  49. package/dist/frameworks/detectors/aspnet.js +52 -0
  50. package/dist/frameworks/detectors/django.d.ts +14 -0
  51. package/dist/frameworks/detectors/django.js +135 -0
  52. package/dist/frameworks/detectors/drupal.d.ts +13 -0
  53. package/dist/frameworks/detectors/drupal.js +94 -0
  54. package/dist/frameworks/detectors/express.d.ts +12 -0
  55. package/dist/frameworks/detectors/express.js +234 -0
  56. package/dist/frameworks/detectors/fastapi.d.ts +12 -0
  57. package/dist/frameworks/detectors/fastapi.js +203 -0
  58. package/dist/frameworks/detectors/flask.d.ts +12 -0
  59. package/dist/frameworks/detectors/flask.js +244 -0
  60. package/dist/frameworks/detectors/go.d.ts +11 -0
  61. package/dist/frameworks/detectors/go.js +75 -0
  62. package/dist/frameworks/detectors/laravel.d.ts +11 -0
  63. package/dist/frameworks/detectors/laravel.js +462 -0
  64. package/dist/frameworks/detectors/nestjs.d.ts +12 -0
  65. package/dist/frameworks/detectors/nestjs.js +155 -0
  66. package/dist/frameworks/detectors/nextjs.d.ts +11 -0
  67. package/dist/frameworks/detectors/nextjs.js +118 -0
  68. package/dist/frameworks/detectors/rails.d.ts +12 -0
  69. package/dist/frameworks/detectors/rails.js +76 -0
  70. package/dist/frameworks/detectors/react-router.d.ts +11 -0
  71. package/dist/frameworks/detectors/react-router.js +115 -0
  72. package/dist/frameworks/detectors/rust.d.ts +11 -0
  73. package/dist/frameworks/detectors/rust.js +59 -0
  74. package/dist/frameworks/detectors/spring.d.ts +11 -0
  75. package/dist/frameworks/detectors/spring.js +56 -0
  76. package/dist/frameworks/detectors/sveltekit.d.ts +11 -0
  77. package/dist/frameworks/detectors/sveltekit.js +154 -0
  78. package/dist/frameworks/detectors/symfony.d.ts +13 -0
  79. package/dist/frameworks/detectors/symfony.js +175 -0
  80. package/dist/frameworks/detectors/tanstack-router.d.ts +12 -0
  81. package/dist/frameworks/detectors/tanstack-router.js +80 -0
  82. package/dist/frameworks/detectors/vapor.d.ts +11 -0
  83. package/dist/frameworks/detectors/vapor.js +52 -0
  84. package/dist/frameworks/detectors/vue-router.d.ts +12 -0
  85. package/dist/frameworks/detectors/vue-router.js +237 -0
  86. package/dist/frameworks/detectors/wordpress.d.ts +13 -0
  87. package/dist/frameworks/detectors/wordpress.js +141 -0
  88. package/dist/frameworks/detectors/yii.d.ts +11 -0
  89. package/dist/frameworks/detectors/yii.js +131 -0
  90. package/dist/frameworks/framework-registry.d.ts +13 -0
  91. package/dist/frameworks/framework-registry.js +77 -0
  92. package/dist/frameworks/route-registry.d.ts +26 -0
  93. package/dist/frameworks/route-registry.js +102 -0
  94. package/dist/index.d.ts +19 -0
  95. package/dist/index.js +30 -0
  96. package/dist/languages/index.d.ts +2 -0
  97. package/dist/languages/index.js +7 -0
  98. package/dist/languages/installer.d.ts +13 -0
  99. package/dist/languages/installer.js +103 -0
  100. package/dist/languages/registry.d.ts +19 -0
  101. package/dist/languages/registry.js +427 -0
  102. package/dist/main.d.ts +2 -0
  103. package/dist/main.js +20 -0
  104. package/dist/mcp.d.ts +11 -0
  105. package/dist/mcp.js +1699 -0
  106. package/dist/parsers/common-methods.d.ts +3 -0
  107. package/dist/parsers/common-methods.js +33 -0
  108. package/dist/parsers/fallback-parser.d.ts +10 -0
  109. package/dist/parsers/fallback-parser.js +18 -0
  110. package/dist/parsers/generic-wasm-parser.d.ts +23 -0
  111. package/dist/parsers/generic-wasm-parser.js +168 -0
  112. package/dist/parsers/ignored-symbols.d.ts +26 -0
  113. package/dist/parsers/ignored-symbols.js +77 -0
  114. package/dist/parsers/index.d.ts +9 -0
  115. package/dist/parsers/index.js +13 -0
  116. package/dist/parsers/languages/javascript.d.ts +11 -0
  117. package/dist/parsers/languages/javascript.js +28 -0
  118. package/dist/parsers/languages/php.d.ts +15 -0
  119. package/dist/parsers/languages/php.js +648 -0
  120. package/dist/parsers/languages/typescript.d.ts +10 -0
  121. package/dist/parsers/languages/typescript.js +9 -0
  122. package/dist/parsers/languages/vue.d.ts +13 -0
  123. package/dist/parsers/languages/vue.js +63 -0
  124. package/dist/parsers/parse-worker.d.ts +2 -0
  125. package/dist/parsers/parse-worker.js +185 -0
  126. package/dist/parsers/parser-interface.d.ts +9 -0
  127. package/dist/parsers/parser-interface.js +0 -0
  128. package/dist/parsers/parser-registry.d.ts +8 -0
  129. package/dist/parsers/parser-registry.js +52 -0
  130. package/dist/parsers/wasm-parser.d.ts +16 -0
  131. package/dist/parsers/wasm-parser.js +110 -0
  132. package/dist/types.d.ts +172 -0
  133. package/dist/types.js +0 -0
  134. package/dist/ui/index.html +270 -0
  135. package/dist/ui/main.js +581 -0
  136. package/dist/ui/main.js.map +7 -0
  137. package/dist/ui/styles.css +573 -0
  138. package/dist/ui-events.d.ts +36 -0
  139. package/dist/ui-events.js +61 -0
  140. package/dist/ui-server.d.ts +12 -0
  141. package/dist/ui-server.js +504 -0
  142. package/package.json +179 -0
  143. package/queries/bash/references.scm +22 -0
  144. package/queries/bash/symbols.scm +15 -0
  145. package/queries/c/references.scm +14 -0
  146. package/queries/c/symbols.scm +30 -0
  147. package/queries/c-sharp/references.scm +26 -0
  148. package/queries/c-sharp/symbols.scm +57 -0
  149. package/queries/cpp/references.scm +21 -0
  150. package/queries/cpp/symbols.scm +44 -0
  151. package/queries/dart/references.scm +33 -0
  152. package/queries/dart/symbols.scm +38 -0
  153. package/queries/elixir/references.scm +45 -0
  154. package/queries/elixir/symbols.scm +41 -0
  155. package/queries/go/references.scm +22 -0
  156. package/queries/go/symbols.scm +53 -0
  157. package/queries/java/references.scm +32 -0
  158. package/queries/java/symbols.scm +41 -0
  159. package/queries/javascript/references.scm +14 -0
  160. package/queries/javascript/symbols.scm +23 -0
  161. package/queries/kotlin/references.scm +31 -0
  162. package/queries/kotlin/symbols.scm +24 -0
  163. package/queries/lua/references.scm +19 -0
  164. package/queries/lua/symbols.scm +29 -0
  165. package/queries/pascal/references.scm +29 -0
  166. package/queries/pascal/symbols.scm +45 -0
  167. package/queries/php/references.scm +109 -0
  168. package/queries/php/symbols.scm +33 -0
  169. package/queries/python/references.scm +50 -0
  170. package/queries/python/symbols.scm +21 -0
  171. package/queries/ruby/references.scm +48 -0
  172. package/queries/ruby/symbols.scm +24 -0
  173. package/queries/rust/references.scm +31 -0
  174. package/queries/rust/symbols.scm +35 -0
  175. package/queries/scala/references.scm +30 -0
  176. package/queries/scala/symbols.scm +35 -0
  177. package/queries/svelte/references.scm +20 -0
  178. package/queries/svelte/symbols.scm +30 -0
  179. package/queries/swift/references.scm +22 -0
  180. package/queries/swift/symbols.scm +37 -0
  181. package/queries/typescript/references.scm +25 -0
  182. package/queries/typescript/symbols.scm +35 -0
  183. package/queries/vue/references.scm +20 -0
  184. package/queries/vue/symbols.scm +28 -0
  185. package/queries/zig/references.scm +20 -0
  186. package/queries/zig/symbols.scm +22 -0
  187. package/wasm/tree-sitter-c.wasm +0 -0
  188. package/wasm/tree-sitter-c_sharp.wasm +0 -0
  189. package/wasm/tree-sitter-cpp.wasm +0 -0
  190. package/wasm/tree-sitter-dart.wasm +0 -0
  191. package/wasm/tree-sitter-go.wasm +0 -0
  192. package/wasm/tree-sitter-java.wasm +0 -0
  193. package/wasm/tree-sitter-javascript.wasm +0 -0
  194. package/wasm/tree-sitter-kotlin.wasm +0 -0
  195. package/wasm/tree-sitter-php.wasm +0 -0
  196. package/wasm/tree-sitter-python.wasm +0 -0
  197. package/wasm/tree-sitter-ruby.wasm +0 -0
  198. package/wasm/tree-sitter-rust.wasm +0 -0
  199. package/wasm/tree-sitter-scala.wasm +0 -0
  200. package/wasm/tree-sitter-swift.wasm +0 -0
  201. package/wasm/tree-sitter-tsx.wasm +0 -0
  202. package/wasm/tree-sitter-typescript.wasm +0 -0
  203. package/wasm/tree-sitter-vue.wasm +0 -0
@@ -0,0 +1,179 @@
1
+ class DotExporter {
2
+ store;
3
+ graph;
4
+ constructor(store, graph) {
5
+ this.store = store;
6
+ this.graph = graph;
7
+ }
8
+ export(repo, filesFilter, opts) {
9
+ const clusterMode = opts?.cluster ?? "none";
10
+ const maxClusterDepth = opts?.depth ?? Infinity;
11
+ let files = this.store.getAllFiles(repo);
12
+ let edges = this.store.getAllEdges(repo);
13
+ let rankedFiles = this.graph.getRankedFiles();
14
+ if (filesFilter) {
15
+ const allowed = new Set(filesFilter);
16
+ files = files.filter((f) => allowed.has(f.path));
17
+ edges = edges.filter((e) => allowed.has(e.source_file) && allowed.has(e.target_file));
18
+ rankedFiles = rankedFiles.filter((f) => allowed.has(f.path));
19
+ }
20
+ const lines = [];
21
+ lines.push("digraph Mapx {");
22
+ lines.push(" newrank=true;");
23
+ lines.push(" rankdir=LR;");
24
+ lines.push(" node [shape=box, style=filled];");
25
+ lines.push("");
26
+ const langColors = {
27
+ php: "#8892BF",
28
+ javascript: "#F7DF1E",
29
+ typescript: "#3178C6",
30
+ python: "#3776AB",
31
+ go: "#00ADD8",
32
+ rust: "#DEA584",
33
+ java: "#ED8B00"
34
+ };
35
+ const rankMap = new Map(rankedFiles.map((f) => [f.path, f.pagerank]));
36
+ const clusters = this.store.getClusters(repo);
37
+ const memberships = this.store.getClusterMemberships(repo);
38
+ const primaryMemberships = /* @__PURE__ */ new Map();
39
+ for (const m of memberships) {
40
+ if (m.is_primary === 1) {
41
+ primaryMemberships.set(m.file_path, m.cluster_name);
42
+ }
43
+ }
44
+ const roots = [];
45
+ const childrenMap = /* @__PURE__ */ new Map();
46
+ const clusterFilesMap = /* @__PURE__ */ new Map();
47
+ for (const c of clusters) {
48
+ if (!c.parent_name) {
49
+ roots.push(c);
50
+ } else {
51
+ const parentName = c.parent_name;
52
+ if (!childrenMap.has(parentName)) {
53
+ childrenMap.set(parentName, []);
54
+ }
55
+ childrenMap.get(parentName).push(c);
56
+ }
57
+ }
58
+ for (const file of files) {
59
+ const path = file.path;
60
+ const clusterName = primaryMemberships.get(path);
61
+ if (clusterName) {
62
+ if (!clusterFilesMap.has(clusterName)) {
63
+ clusterFilesMap.set(clusterName, []);
64
+ }
65
+ clusterFilesMap.get(clusterName).push(path);
66
+ }
67
+ }
68
+ const outputCluster = (node, indent, currentDepth) => {
69
+ const pad = " ".repeat(indent);
70
+ const subLines = [];
71
+ const safeId = "cluster_" + node.name.replace(/[^a-zA-Z0-9]/g, "_");
72
+ subLines.push(`${pad}subgraph "${safeId}" {`);
73
+ subLines.push(`${pad} label="${node.label}";`);
74
+ subLines.push(`${pad} color=gray;`);
75
+ subLines.push(`${pad} style=dashed;`);
76
+ const fList = clusterFilesMap.get(node.name) || [];
77
+ for (const f of fList) {
78
+ const lang = files.find((file) => file.path === f)?.language;
79
+ const color = langColors[lang] || "#CCCCCC";
80
+ const label = f.split("/").pop() || f;
81
+ subLines.push(`${pad} "${f}" [label="${label}", fillcolor="${color}", fontcolor="white"];`);
82
+ }
83
+ const children = childrenMap.get(node.name) || [];
84
+ if (currentDepth < maxClusterDepth) {
85
+ for (const child of children) {
86
+ subLines.push(...outputCluster(child, indent + 1, currentDepth + 1));
87
+ }
88
+ } else {
89
+ const flattenFiles = (c) => {
90
+ const fList2 = clusterFilesMap.get(c.name) || [];
91
+ for (const f2 of fList2) {
92
+ const lang2 = files.find((file) => file.path === f2)?.language;
93
+ const color2 = langColors[lang2] || "#CCCCCC";
94
+ const label2 = f2.split("/").pop() || f2;
95
+ subLines.push(`${pad} "${f2}" [label="${label2}", fillcolor="${color2}", fontcolor="white"];`);
96
+ }
97
+ for (const gc of childrenMap.get(c.name) || []) {
98
+ flattenFiles(gc);
99
+ }
100
+ };
101
+ for (const child of children) {
102
+ flattenFiles(child);
103
+ }
104
+ }
105
+ subLines.push(`${pad}}`);
106
+ return subLines;
107
+ };
108
+ if (clusterMode === "none") {
109
+ for (const file of files) {
110
+ const path = file.path;
111
+ const lang = file.language;
112
+ const color = langColors[lang] || "#CCCCCC";
113
+ const label = path.split("/").pop() || path;
114
+ lines.push(` "${path}" [label="${label}", fillcolor="${color}", fontcolor="white"];`);
115
+ }
116
+ } else {
117
+ for (const file of files) {
118
+ const path = file.path;
119
+ if (!primaryMemberships.has(path)) {
120
+ const lang = file.language;
121
+ const color = langColors[lang] || "#CCCCCC";
122
+ const label = path.split("/").pop() || path;
123
+ lines.push(` "${path}" [label="${label}", fillcolor="${color}", fontcolor="white"];`);
124
+ }
125
+ }
126
+ for (const root of roots) {
127
+ lines.push(...outputCluster(root, 1, 1));
128
+ }
129
+ }
130
+ lines.push("");
131
+ const edgeStyles = {
132
+ import: "solid",
133
+ require: "solid",
134
+ extends: "bold",
135
+ implements: "dashed",
136
+ call: "dotted",
137
+ instantiation: "dotted",
138
+ relation: "bold",
139
+ route: "solid",
140
+ binding: "dashed",
141
+ middleware: "dotted",
142
+ dispatch: "dashed",
143
+ notify: "dotted"
144
+ };
145
+ const seen = /* @__PURE__ */ new Set();
146
+ for (const edge of edges) {
147
+ const src = edge.source_file;
148
+ const tgt = edge.target_file;
149
+ const type = edge.edge_type;
150
+ const key = `${src}->${tgt}:${type}`;
151
+ if (seen.has(key)) continue;
152
+ seen.add(key);
153
+ let style = edgeStyles[type] || "solid";
154
+ if (edge.verifiability === "inferred") {
155
+ style = "dashed";
156
+ }
157
+ let colorAttr = "";
158
+ if (type === "relation") {
159
+ colorAttr = ', color="blue"';
160
+ } else if (type === "route") {
161
+ colorAttr = ', color="green"';
162
+ } else if (type === "binding") {
163
+ colorAttr = ', color="purple"';
164
+ } else if (type === "middleware") {
165
+ colorAttr = ', color="orange"';
166
+ } else if (type === "dispatch") {
167
+ colorAttr = ', color="magenta"';
168
+ } else if (type === "notify") {
169
+ colorAttr = ', color="pink"';
170
+ }
171
+ lines.push(` "${src}" -> "${tgt}" [label="${type}", style=${style}${colorAttr}];`);
172
+ }
173
+ lines.push("}");
174
+ return lines.join("\n");
175
+ }
176
+ }
177
+ export {
178
+ DotExporter
179
+ };
@@ -0,0 +1,14 @@
1
+ import { Store } from '../core/store.js';
2
+ import { MapxGraph } from '../core/graph.js';
3
+ import '../core/store-interface.js';
4
+ import '../types.js';
5
+
6
+ declare class GraphExporter {
7
+ private store;
8
+ private graph;
9
+ constructor(store: Store, graph: MapxGraph);
10
+ exportAsJSON(repo?: string, filesFilter?: string[]): object;
11
+ exportAsJSONString(repo?: string, filesFilter?: string[]): string;
12
+ }
13
+
14
+ export { GraphExporter };
@@ -0,0 +1,85 @@
1
+ class GraphExporter {
2
+ store;
3
+ graph;
4
+ constructor(store, graph) {
5
+ this.store = store;
6
+ this.graph = graph;
7
+ }
8
+ exportAsJSON(repo, filesFilter) {
9
+ let files = this.store.getAllFiles(repo);
10
+ let symbols = this.store.getAllSymbols(repo);
11
+ let edges = this.store.getAllEdges(repo);
12
+ if (filesFilter) {
13
+ const allowed = new Set(filesFilter);
14
+ files = files.filter((f) => allowed.has(f.path));
15
+ symbols = symbols.filter((s) => allowed.has(s.file_path));
16
+ edges = edges.filter((e) => allowed.has(e.source_file) && allowed.has(e.target_file));
17
+ }
18
+ const graphData = this.graph.toJSON();
19
+ if (filesFilter) {
20
+ const allowed = new Set(filesFilter);
21
+ graphData.nodes = graphData.nodes.filter((n) => allowed.has(n.key));
22
+ graphData.edges = graphData.edges.filter((e) => allowed.has(e.source) && allowed.has(e.target));
23
+ }
24
+ const clusters = this.store.getClusters(repo);
25
+ const memberships = this.store.getClusterMemberships(repo);
26
+ return {
27
+ version: "1.0.0",
28
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
29
+ repo: repo || "all",
30
+ summary: {
31
+ totalFiles: files.length,
32
+ totalSymbols: symbols.length,
33
+ totalEdges: edges.length,
34
+ languages: this.store.getLanguageBreakdown(repo),
35
+ totalClusters: clusters.length
36
+ },
37
+ files: files.map((f) => ({
38
+ path: f.path,
39
+ language: f.language,
40
+ sizeBytes: f.size_bytes,
41
+ lines: f.lines,
42
+ lastScanned: f.last_scanned,
43
+ metadata: f.metadata ? JSON.parse(f.metadata) : void 0
44
+ })),
45
+ symbols: symbols.map((s) => ({
46
+ name: s.name,
47
+ kind: s.kind,
48
+ scope: s.scope || void 0,
49
+ signature: s.signature,
50
+ file: s.file_path,
51
+ line: s.start_line,
52
+ endLine: s.end_line
53
+ })),
54
+ edges: edges.map((e) => ({
55
+ source: e.source_file,
56
+ target: e.target_file,
57
+ type: e.edge_type,
58
+ sourceSymbol: e.source_symbol || void 0,
59
+ targetSymbol: e.target_symbol || void 0,
60
+ verifiability: e.verifiability || "verified",
61
+ metadata: e.metadata ? JSON.parse(e.metadata) : void 0
62
+ })),
63
+ clusters: clusters.map((c) => ({
64
+ name: c.name,
65
+ label: c.label,
66
+ source: c.source,
67
+ parentName: c.parent_name || void 0,
68
+ depth: c.depth,
69
+ fileCount: c.file_count
70
+ })),
71
+ memberships: memberships.map((m) => ({
72
+ filePath: m.file_path,
73
+ clusterName: m.cluster_name,
74
+ isPrimary: m.is_primary === 1
75
+ })),
76
+ graph: graphData
77
+ };
78
+ }
79
+ exportAsJSONString(repo, filesFilter) {
80
+ return JSON.stringify(this.exportAsJSON(repo, filesFilter), null, 2);
81
+ }
82
+ }
83
+ export {
84
+ GraphExporter
85
+ };
@@ -0,0 +1,9 @@
1
+ export { LLMExporter } from './llm-exporter.js';
2
+ export { GraphExporter } from './graph-exporter.js';
3
+ export { DotExporter } from './dot-exporter.js';
4
+ export { SvgExporter } from './svg-exporter.js';
5
+ export { ToonExporter } from './toon-exporter.js';
6
+ import '../core/store.js';
7
+ import '../core/store-interface.js';
8
+ import '../core/graph.js';
9
+ import '../types.js';
@@ -0,0 +1,12 @@
1
+ import { LLMExporter } from "./llm-exporter.js";
2
+ import { GraphExporter } from "./graph-exporter.js";
3
+ import { DotExporter } from "./dot-exporter.js";
4
+ import { SvgExporter } from "./svg-exporter.js";
5
+ import { ToonExporter } from "./toon-exporter.js";
6
+ export {
7
+ DotExporter,
8
+ GraphExporter,
9
+ LLMExporter,
10
+ SvgExporter,
11
+ ToonExporter
12
+ };
@@ -0,0 +1,18 @@
1
+ import { Store } from '../core/store.js';
2
+ import { MapxGraph } from '../core/graph.js';
3
+ import { ExportOptions } from '../types.js';
4
+ import '../core/store-interface.js';
5
+
6
+ declare class LLMExporter {
7
+ private store;
8
+ private graph;
9
+ constructor(store: Store, graph: MapxGraph);
10
+ export(options?: Partial<ExportOptions>): string;
11
+ private buildStructureSection;
12
+ private buildFileSection;
13
+ private buildSymbolSection;
14
+ private buildDependencySection;
15
+ private truncateToFit;
16
+ }
17
+
18
+ export { LLMExporter };
@@ -0,0 +1,224 @@
1
+ const TOKEN_CHARS_PER_LINE = 4;
2
+ class LLMExporter {
3
+ store;
4
+ graph;
5
+ constructor(store, graph) {
6
+ this.store = store;
7
+ this.graph = graph;
8
+ }
9
+ export(options) {
10
+ const opt = options || {};
11
+ const budget = opt.tokenBudget || 8192;
12
+ const parts = [];
13
+ let files = this.store.getAllFiles(opt.repo);
14
+ let symbols = this.store.getAllSymbols(opt.repo);
15
+ let edges = this.store.getAllEdges(opt.repo);
16
+ let rankedFiles = this.graph.getRankedFiles();
17
+ let rankedSymbols = this.graph.getRankedSymbols();
18
+ if (opt.files) {
19
+ const allowed = new Set(opt.files);
20
+ files = files.filter((f) => allowed.has(f.path));
21
+ symbols = symbols.filter((s) => allowed.has(s.file_path));
22
+ edges = edges.filter((e) => allowed.has(e.source_file) && allowed.has(e.target_file));
23
+ rankedFiles = rankedFiles.filter((f) => allowed.has(f.path));
24
+ rankedSymbols = rankedSymbols.filter((s) => allowed.has(s.filePath));
25
+ }
26
+ const repoName = opt.repo || "project";
27
+ parts.push(`# Mapx: ${repoName}`);
28
+ parts.push("");
29
+ const structureSection = this.buildStructureSection(opt.repo);
30
+ if (structureSection) {
31
+ parts.push(structureSection);
32
+ }
33
+ const fileSection = this.buildFileSection(files, rankedFiles, edges);
34
+ parts.push(fileSection);
35
+ const symbolSection = this.buildSymbolSection(rankedSymbols, budget);
36
+ parts.push(symbolSection);
37
+ if (edges.length > 0) {
38
+ const depSection = this.buildDependencySection(edges);
39
+ parts.push(depSection);
40
+ }
41
+ let result = parts.join("\n");
42
+ const estimatedTokens = Math.ceil(result.length / TOKEN_CHARS_PER_LINE);
43
+ if (estimatedTokens > budget) {
44
+ result = this.truncateToFit(result, budget);
45
+ }
46
+ return result;
47
+ }
48
+ buildStructureSection(repo) {
49
+ const clusters = this.store.getClusters(repo);
50
+ if (clusters.length === 0) return "";
51
+ const lines = [];
52
+ lines.push("## Structure");
53
+ const roots = [];
54
+ const childrenMap = /* @__PURE__ */ new Map();
55
+ for (const c of clusters) {
56
+ if (!c.parent_name) {
57
+ roots.push(c);
58
+ } else {
59
+ const parentName = c.parent_name;
60
+ if (!childrenMap.has(parentName)) {
61
+ childrenMap.set(parentName, []);
62
+ }
63
+ childrenMap.get(parentName).push(c);
64
+ }
65
+ }
66
+ for (const list of childrenMap.values()) {
67
+ list.sort((a, b) => a.name.localeCompare(b.name));
68
+ }
69
+ roots.sort((a, b) => a.name.localeCompare(b.name));
70
+ const printTree = (node, indent) => {
71
+ const padding = " ".repeat(indent);
72
+ const namePart = node.name;
73
+ const sourcePart = `(${node.source})`;
74
+ const filesPart = `[${node.file_count} files]`;
75
+ lines.push(`${padding}${namePart} ${sourcePart} ${filesPart}`);
76
+ const children = childrenMap.get(node.name) || [];
77
+ for (const child of children) {
78
+ printTree(child, indent + 1);
79
+ }
80
+ };
81
+ for (const root of roots) {
82
+ printTree(root, 0);
83
+ }
84
+ lines.push("");
85
+ return lines.join("\n");
86
+ }
87
+ buildFileSection(files, rankedFiles, edges) {
88
+ const lines = [];
89
+ lines.push(`## Files (${files.length})`);
90
+ const rankMap = new Map(rankedFiles.map((f) => [f.path, f.pagerank]));
91
+ const depMap = /* @__PURE__ */ new Map();
92
+ for (const edge of edges) {
93
+ const src = edge.source_file;
94
+ const tgt = edge.target_file;
95
+ const type = edge.edge_type;
96
+ if (!depMap.has(src)) depMap.set(src, []);
97
+ const infSuffix = edge.verifiability === "inferred" ? " [inferred]" : "";
98
+ depMap.get(src).push(`${tgt} (${type})${infSuffix}`);
99
+ }
100
+ const sorted = [...files].sort((a, b) => {
101
+ const ra = rankMap.get(a.path) || 0;
102
+ const rb = rankMap.get(b.path) || 0;
103
+ return rb - ra;
104
+ });
105
+ for (const file of sorted) {
106
+ const path = file.path;
107
+ const lang = file.language;
108
+ const deps = depMap.get(path);
109
+ const depStr = deps ? ` \u2192 ${deps.join(", ")}` : "";
110
+ lines.push(`- ${path} [${lang}]${depStr}`);
111
+ }
112
+ lines.push("");
113
+ return lines.join("\n");
114
+ }
115
+ buildSymbolSection(rankedSymbols, budget) {
116
+ const lines = [];
117
+ lines.push(`## Symbols (${rankedSymbols.length})`);
118
+ const byFile = /* @__PURE__ */ new Map();
119
+ for (const sym of rankedSymbols) {
120
+ if (!byFile.has(sym.filePath)) byFile.set(sym.filePath, []);
121
+ byFile.get(sym.filePath).push(sym);
122
+ }
123
+ const dbSymbols = this.store.getAllSymbols();
124
+ const sigMap = /* @__PURE__ */ new Map();
125
+ for (const s of dbSymbols) {
126
+ const key = `${s.file_path}::${s.name}`;
127
+ sigMap.set(key, s.signature);
128
+ }
129
+ const maxLines = Math.floor(budget * TOKEN_CHARS_PER_LINE / 40);
130
+ let lineCount = 0;
131
+ for (const [filePath, syms] of byFile) {
132
+ if (lineCount > maxLines) break;
133
+ const topLevel = syms.filter((s) => !s.scope);
134
+ for (const sym of topLevel) {
135
+ if (lineCount > maxLines) break;
136
+ const sig = sigMap.get(`${sym.filePath}::${sym.name}`) || sym.name;
137
+ lines.push(`- ${sym.kind} ${sig} @ ${sym.filePath}:${sym.startLine}`);
138
+ const children = syms.filter((s) => s.scope === sym.name);
139
+ for (const child of children) {
140
+ if (lineCount > maxLines) break;
141
+ const childSig = sigMap.get(`${child.filePath}::${child.name}`) || child.name;
142
+ lines.push(` - ${child.kind} ${childSig} @ :${child.startLine}`);
143
+ lineCount++;
144
+ }
145
+ lineCount++;
146
+ }
147
+ }
148
+ lines.push("");
149
+ return lines.join("\n");
150
+ }
151
+ buildDependencySection(edges) {
152
+ const lines = [];
153
+ lines.push("## Dependencies");
154
+ const routeGroups = /* @__PURE__ */ new Map();
155
+ const otherEdges = [];
156
+ for (const edge of edges) {
157
+ if (edge.edge_type === "route") {
158
+ const src = edge.source_file;
159
+ const controller = edge.target_symbol || edge.target_file.split("/").pop() || "Controller";
160
+ const key = `${src}->${controller}`;
161
+ let meta = {};
162
+ if (edge.metadata) {
163
+ try {
164
+ meta = typeof edge.metadata === "string" ? JSON.parse(edge.metadata) : edge.metadata;
165
+ } catch {
166
+ }
167
+ }
168
+ const verb = meta.httpVerb || "GET";
169
+ const uri = meta.uri || "/";
170
+ if (!routeGroups.has(key)) {
171
+ routeGroups.set(key, { source: src, controller, routes: [] });
172
+ }
173
+ routeGroups.get(key).routes.push({ verb, uri });
174
+ } else {
175
+ otherEdges.push(edge);
176
+ }
177
+ }
178
+ for (const group of routeGroups.values()) {
179
+ const uriToVerbs = /* @__PURE__ */ new Map();
180
+ for (const r of group.routes) {
181
+ if (!uriToVerbs.has(r.uri)) {
182
+ uriToVerbs.set(r.uri, /* @__PURE__ */ new Set());
183
+ }
184
+ uriToVerbs.get(r.uri).add(r.verb);
185
+ }
186
+ const descParts = [];
187
+ for (const [uri, verbs] of uriToVerbs.entries()) {
188
+ const verbsStr = Array.from(verbs).sort().join("/");
189
+ descParts.push(`${verbsStr} ${uri}`);
190
+ }
191
+ lines.push(`- ${group.source} \u2192 ${group.controller} (${group.routes.length} routes: ${descParts.join(", ")})`);
192
+ }
193
+ const unique = /* @__PURE__ */ new Map();
194
+ for (const edge of otherEdges) {
195
+ const key = `${edge.source_file}->${edge.target_file}:${edge.edge_type}`;
196
+ if (!unique.has(key)) {
197
+ unique.set(key, {
198
+ source: edge.source_file,
199
+ target: edge.target_file,
200
+ type: edge.edge_type,
201
+ verifiability: edge.verifiability || "verified",
202
+ targetRepo: edge.target_repo
203
+ });
204
+ }
205
+ }
206
+ for (const dep of unique.values()) {
207
+ const infSuffix = dep.verifiability === "inferred" ? " [inferred]" : "";
208
+ const targetRepoSuffix = dep.targetRepo ? ` [repo: ${dep.targetRepo}]` : "";
209
+ lines.push(`- ${dep.source} \u2192 ${dep.target}${targetRepoSuffix} (${dep.type})${infSuffix}`);
210
+ }
211
+ lines.push("");
212
+ return lines.join("\n");
213
+ }
214
+ truncateToFit(output, budget) {
215
+ const maxChars = budget * TOKEN_CHARS_PER_LINE;
216
+ if (output.length <= maxChars) return output;
217
+ const truncated = output.substring(0, maxChars);
218
+ const lastNewline = truncated.lastIndexOf("\n");
219
+ return truncated.substring(0, lastNewline) + "\n\n[... truncated to fit token budget]\n";
220
+ }
221
+ }
222
+ export {
223
+ LLMExporter
224
+ };
@@ -0,0 +1,19 @@
1
+ import { Store } from '../core/store.js';
2
+ import { MapxGraph } from '../core/graph.js';
3
+ import '../core/store-interface.js';
4
+ import '../types.js';
5
+
6
+ declare class SvgExporter {
7
+ private store;
8
+ private graph;
9
+ constructor(store: Store, graph: MapxGraph);
10
+ export(repo?: string, filesFilter?: string[], opts?: {
11
+ cluster?: 'none' | 'auto';
12
+ depth?: number;
13
+ forceFallback?: boolean;
14
+ }): string;
15
+ private renderFallback;
16
+ private escXml;
17
+ }
18
+
19
+ export { SvgExporter };