kirograph 0.12.2 → 0.13.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.
- package/README.md +56 -2
- package/dist/architecture/layers/index.js +9 -1
- package/dist/architecture/layers/index.js.map +2 -2
- package/dist/architecture/layers/ocaml.js +105 -0
- package/dist/architecture/layers/ocaml.js.map +7 -0
- package/dist/architecture/layers/scala.js +120 -0
- package/dist/architecture/layers/scala.js.map +7 -0
- package/dist/architecture/layers/solidity.js +105 -0
- package/dist/architecture/layers/solidity.js.map +7 -0
- package/dist/architecture/layers/vue.js +111 -0
- package/dist/architecture/layers/vue.js.map +7 -0
- package/dist/architecture/manifest/elm.js +91 -0
- package/dist/architecture/manifest/elm.js.map +7 -0
- package/dist/architecture/manifest/index.js +13 -2
- package/dist/architecture/manifest/index.js.map +2 -2
- package/dist/architecture/manifest/ocaml.js +166 -0
- package/dist/architecture/manifest/ocaml.js.map +7 -0
- package/dist/architecture/manifest/scala.js +117 -0
- package/dist/architecture/manifest/scala.js.map +7 -0
- package/dist/bin/installer/hooks.js +21 -1
- package/dist/bin/installer/hooks.js.map +2 -2
- package/dist/bin/kirograph.js +1 -1
- package/dist/extraction/extractor.js +65 -2
- package/dist/extraction/extractor.js.map +2 -2
- package/dist/extraction/grammars.js +22 -0
- package/dist/extraction/grammars.js.map +2 -2
- package/dist/extraction/languages.js +39 -1
- package/dist/extraction/languages.js.map +2 -2
- package/dist/extraction/wasm/tree-sitter-hcl.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-scss.wasm +0 -0
- package/dist/frameworks/amplify.js +175 -0
- package/dist/frameworks/amplify.js.map +7 -0
- package/dist/frameworks/angular.js +132 -0
- package/dist/frameworks/angular.js.map +7 -0
- package/dist/frameworks/ansible.js +151 -0
- package/dist/frameworks/ansible.js.map +7 -0
- package/dist/frameworks/cloudformation.js +148 -0
- package/dist/frameworks/cloudformation.js.map +7 -0
- package/dist/frameworks/docker.js +149 -0
- package/dist/frameworks/docker.js.map +7 -0
- package/dist/frameworks/iac.js +401 -0
- package/dist/frameworks/iac.js.map +7 -0
- package/dist/frameworks/index.js +81 -3
- package/dist/frameworks/index.js.map +3 -3
- package/dist/frameworks/kubernetes.js +176 -0
- package/dist/frameworks/kubernetes.js.map +7 -0
- package/dist/frameworks/pulumi.js +93 -0
- package/dist/frameworks/pulumi.js.map +7 -0
- package/dist/frameworks/scala.js +124 -0
- package/dist/frameworks/scala.js.map +7 -0
- package/dist/frameworks/solidity.js +93 -0
- package/dist/frameworks/solidity.js.map +7 -0
- package/dist/frameworks/terraform.js +278 -0
- package/dist/frameworks/terraform.js.map +7 -0
- package/dist/frameworks/vue.js +163 -0
- package/dist/frameworks/vue.js.map +7 -0
- package/dist/graph/queries.js +1 -1
- package/dist/graph/queries.js.map +1 -1
- package/dist/types.js.map +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/frameworks/solidity.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Solidity Framework Resolver (OpenZeppelin, Hardhat, Foundry)\n */\n\nimport type { Node } from '../types';\nimport type { FrameworkResolver, UnresolvedRef, ResolvedRef, ResolutionContext } from './types';\n\nexport const solidityResolver: FrameworkResolver = {\n name: 'solidity',\n detect(context: ResolutionContext): boolean {\n if (context.fileExists('hardhat.config.ts') || context.fileExists('hardhat.config.js')) return true;\n if (context.fileExists('foundry.toml')) return true;\n if (context.fileExists('truffle-config.js')) return true;\n return context.getAllFiles().some(f => f.endsWith('.sol'));\n },\n resolve(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null {\n // Resolve interface references (IERC20, IUniswapV2Router, etc.)\n if (ref.referenceName.startsWith('I') && /^I[A-Z]/.test(ref.referenceName)) {\n const id = resolveInterface(ref.referenceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.85, resolvedBy: 'framework' };\n }\n // Resolve contract references (inheritance, instantiation)\n if (/^[A-Z][a-zA-Z0-9]+$/.test(ref.referenceName)) {\n const id = resolveContract(ref.referenceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.8, resolvedBy: 'framework' };\n }\n // Resolve library references\n if (ref.referenceKind === 'function') {\n const id = resolveLibraryFunction(ref.referenceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.75, resolvedBy: 'framework' };\n }\n return null;\n },\n extractNodes(filePath: string, content: string): Node[] {\n // Solidity doesn't have routes, but we can extract events and modifiers\n // as they form part of the contract's public API\n return [];\n },\n};\n\nfunction resolveInterface(name: string, context: ResolutionContext): string | null {\n const dirs = ['interfaces', 'contracts/interfaces', 'src/interfaces'];\n for (const file of context.getAllFiles()) {\n if (!file.endsWith('.sol')) continue;\n if (dirs.some(d => file.includes(`/${d}/`))) {\n const node = context.getNodesInFile(file).find(n => n.name === name && n.kind === 'interface');\n if (node) return node.id;\n }\n }\n // Fallback: search all .sol files\n for (const file of context.getAllFiles()) {\n if (!file.endsWith('.sol')) continue;\n const node = context.getNodesInFile(file).find(n => n.name === name && n.kind === 'interface');\n if (node) return node.id;\n }\n return null;\n}\n\nfunction resolveContract(name: string, context: ResolutionContext): string | null {\n const dirs = ['contracts', 'src', 'lib'];\n for (const file of context.getAllFiles()) {\n if (!file.endsWith('.sol')) continue;\n if (dirs.some(d => file.includes(`/${d}/`))) {\n const node = context.getNodesInFile(file).find(n => n.name === name && n.kind === 'class');\n if (node) return node.id;\n }\n }\n return null;\n}\n\nfunction resolveLibraryFunction(name: string, context: ResolutionContext): string | null {\n const dirs = ['libraries', 'contracts/libraries', 'lib'];\n for (const file of context.getAllFiles()) {\n if (!file.endsWith('.sol')) continue;\n if (dirs.some(d => file.includes(`/${d}/`))) {\n const node = context.getNodesInFile(file).find(n => n.name === name && n.kind === 'function');\n if (node) return node.id;\n }\n }\n return null;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var terraform_exports = {};
|
|
20
|
+
__export(terraform_exports, {
|
|
21
|
+
terraformResolver: () => terraformResolver
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(terraform_exports);
|
|
24
|
+
const terraformResolver = {
|
|
25
|
+
name: "terraform",
|
|
26
|
+
detect(context) {
|
|
27
|
+
if (context.fileExists(".terraform") || context.fileExists(".terraform.lock.hcl")) return true;
|
|
28
|
+
return context.getAllFiles().some((f) => f.endsWith(".tf"));
|
|
29
|
+
},
|
|
30
|
+
resolve(ref, context) {
|
|
31
|
+
if (ref.referenceName.includes(".")) {
|
|
32
|
+
const parts = ref.referenceName.split(".");
|
|
33
|
+
if (parts.length >= 2) {
|
|
34
|
+
const resourceName = parts.slice(0, 2).join(".");
|
|
35
|
+
const id = resolveResource(resourceName, context);
|
|
36
|
+
if (id) return { original: ref, targetNodeId: id, confidence: 0.85, resolvedBy: "framework" };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (ref.referenceName.startsWith("module.")) {
|
|
40
|
+
const moduleName = ref.referenceName.replace("module.", "");
|
|
41
|
+
const id = resolveModule(moduleName, context);
|
|
42
|
+
if (id) return { original: ref, targetNodeId: id, confidence: 0.9, resolvedBy: "framework" };
|
|
43
|
+
}
|
|
44
|
+
if (ref.referenceName.startsWith("var.")) {
|
|
45
|
+
const varName = ref.referenceName.replace("var.", "");
|
|
46
|
+
const id = resolveVariable(varName, context);
|
|
47
|
+
if (id) return { original: ref, targetNodeId: id, confidence: 0.9, resolvedBy: "framework" };
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
},
|
|
51
|
+
extractNodes(filePath, content) {
|
|
52
|
+
if (!filePath.endsWith(".tf") && !filePath.endsWith(".tfvars")) return [];
|
|
53
|
+
const nodes = [];
|
|
54
|
+
const now = Date.now();
|
|
55
|
+
const resourcePattern = /^resource\s+"([^"]+)"\s+"([^"]+)"\s*\{/gm;
|
|
56
|
+
let match;
|
|
57
|
+
while ((match = resourcePattern.exec(content)) !== null) {
|
|
58
|
+
const line = content.slice(0, match.index).split("\n").length;
|
|
59
|
+
const resourceType = match[1];
|
|
60
|
+
const resourceName = match[2];
|
|
61
|
+
const name = `${resourceType}.${resourceName}`;
|
|
62
|
+
const endLine = findBlockEnd(content, match.index + match[0].length);
|
|
63
|
+
nodes.push({
|
|
64
|
+
id: `resource:${filePath}:${name}:${line}`,
|
|
65
|
+
kind: "class",
|
|
66
|
+
name,
|
|
67
|
+
qualifiedName: `${filePath}::resource.${name}`,
|
|
68
|
+
filePath,
|
|
69
|
+
startLine: line,
|
|
70
|
+
endLine,
|
|
71
|
+
startColumn: 0,
|
|
72
|
+
endColumn: match[0].length,
|
|
73
|
+
language: "hcl",
|
|
74
|
+
updatedAt: now,
|
|
75
|
+
signature: `resource "${resourceType}" "${resourceName}"`
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const dataPattern = /^data\s+"([^"]+)"\s+"([^"]+)"\s*\{/gm;
|
|
79
|
+
while ((match = dataPattern.exec(content)) !== null) {
|
|
80
|
+
const line = content.slice(0, match.index).split("\n").length;
|
|
81
|
+
const dataType = match[1];
|
|
82
|
+
const dataName = match[2];
|
|
83
|
+
const name = `${dataType}.${dataName}`;
|
|
84
|
+
const endLine = findBlockEnd(content, match.index + match[0].length);
|
|
85
|
+
nodes.push({
|
|
86
|
+
id: `data:${filePath}:${name}:${line}`,
|
|
87
|
+
kind: "variable",
|
|
88
|
+
name: `data.${name}`,
|
|
89
|
+
qualifiedName: `${filePath}::data.${name}`,
|
|
90
|
+
filePath,
|
|
91
|
+
startLine: line,
|
|
92
|
+
endLine,
|
|
93
|
+
startColumn: 0,
|
|
94
|
+
endColumn: match[0].length,
|
|
95
|
+
language: "hcl",
|
|
96
|
+
updatedAt: now,
|
|
97
|
+
signature: `data "${dataType}" "${dataName}"`
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const modulePattern = /^module\s+"([^"]+)"\s*\{/gm;
|
|
101
|
+
while ((match = modulePattern.exec(content)) !== null) {
|
|
102
|
+
const line = content.slice(0, match.index).split("\n").length;
|
|
103
|
+
const moduleName = match[1];
|
|
104
|
+
const endLine = findBlockEnd(content, match.index + match[0].length);
|
|
105
|
+
nodes.push({
|
|
106
|
+
id: `module:${filePath}:${moduleName}:${line}`,
|
|
107
|
+
kind: "namespace",
|
|
108
|
+
name: `module.${moduleName}`,
|
|
109
|
+
qualifiedName: `${filePath}::module.${moduleName}`,
|
|
110
|
+
filePath,
|
|
111
|
+
startLine: line,
|
|
112
|
+
endLine,
|
|
113
|
+
startColumn: 0,
|
|
114
|
+
endColumn: match[0].length,
|
|
115
|
+
language: "hcl",
|
|
116
|
+
updatedAt: now,
|
|
117
|
+
signature: `module "${moduleName}"`
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
const variablePattern = /^variable\s+"([^"]+)"\s*\{/gm;
|
|
121
|
+
while ((match = variablePattern.exec(content)) !== null) {
|
|
122
|
+
const line = content.slice(0, match.index).split("\n").length;
|
|
123
|
+
const varName = match[1];
|
|
124
|
+
const endLine = findBlockEnd(content, match.index + match[0].length);
|
|
125
|
+
nodes.push({
|
|
126
|
+
id: `variable:${filePath}:${varName}:${line}`,
|
|
127
|
+
kind: "variable",
|
|
128
|
+
name: `var.${varName}`,
|
|
129
|
+
qualifiedName: `${filePath}::var.${varName}`,
|
|
130
|
+
filePath,
|
|
131
|
+
startLine: line,
|
|
132
|
+
endLine,
|
|
133
|
+
startColumn: 0,
|
|
134
|
+
endColumn: match[0].length,
|
|
135
|
+
language: "hcl",
|
|
136
|
+
updatedAt: now,
|
|
137
|
+
signature: `variable "${varName}"`
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
const outputPattern = /^output\s+"([^"]+)"\s*\{/gm;
|
|
141
|
+
while ((match = outputPattern.exec(content)) !== null) {
|
|
142
|
+
const line = content.slice(0, match.index).split("\n").length;
|
|
143
|
+
const outputName = match[1];
|
|
144
|
+
const endLine = findBlockEnd(content, match.index + match[0].length);
|
|
145
|
+
nodes.push({
|
|
146
|
+
id: `output:${filePath}:${outputName}:${line}`,
|
|
147
|
+
kind: "variable",
|
|
148
|
+
name: `output.${outputName}`,
|
|
149
|
+
qualifiedName: `${filePath}::output.${outputName}`,
|
|
150
|
+
filePath,
|
|
151
|
+
startLine: line,
|
|
152
|
+
endLine,
|
|
153
|
+
startColumn: 0,
|
|
154
|
+
endColumn: match[0].length,
|
|
155
|
+
language: "hcl",
|
|
156
|
+
updatedAt: now,
|
|
157
|
+
signature: `output "${outputName}"`,
|
|
158
|
+
isExported: true
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
const localsPattern = /^locals\s*\{/gm;
|
|
162
|
+
while ((match = localsPattern.exec(content)) !== null) {
|
|
163
|
+
const blockStart = match.index + match[0].length;
|
|
164
|
+
const blockContent = extractBlock(content, blockStart);
|
|
165
|
+
const localPattern = /^\s+(\w+)\s*=/gm;
|
|
166
|
+
let localMatch;
|
|
167
|
+
while ((localMatch = localPattern.exec(blockContent)) !== null) {
|
|
168
|
+
const localLine = content.slice(0, blockStart).split("\n").length + blockContent.slice(0, localMatch.index).split("\n").length - 1;
|
|
169
|
+
const localName = localMatch[1];
|
|
170
|
+
nodes.push({
|
|
171
|
+
id: `local:${filePath}:${localName}:${localLine}`,
|
|
172
|
+
kind: "constant",
|
|
173
|
+
name: `local.${localName}`,
|
|
174
|
+
qualifiedName: `${filePath}::local.${localName}`,
|
|
175
|
+
filePath,
|
|
176
|
+
startLine: localLine,
|
|
177
|
+
endLine: localLine,
|
|
178
|
+
startColumn: 0,
|
|
179
|
+
endColumn: localMatch[0].length,
|
|
180
|
+
language: "hcl",
|
|
181
|
+
updatedAt: now
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const apiResourcePattern = /resource\s+"aws_api_gateway_resource"\s+"([^"]+)"[\s\S]*?path_part\s*=\s*"([^"]+)"/g;
|
|
186
|
+
while ((match = apiResourcePattern.exec(content)) !== null) {
|
|
187
|
+
const line = content.slice(0, match.index).split("\n").length;
|
|
188
|
+
const routePath = `/${match[2]}`;
|
|
189
|
+
const name = `RESOURCE ${routePath}`;
|
|
190
|
+
nodes.push({
|
|
191
|
+
id: `route:${filePath}:RESOURCE:${routePath}:${line}`,
|
|
192
|
+
kind: "route",
|
|
193
|
+
name,
|
|
194
|
+
qualifiedName: `${filePath}::${name}`,
|
|
195
|
+
filePath,
|
|
196
|
+
startLine: line,
|
|
197
|
+
endLine: line,
|
|
198
|
+
startColumn: 0,
|
|
199
|
+
endColumn: match[0].length,
|
|
200
|
+
language: "hcl",
|
|
201
|
+
updatedAt: now
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
const apiMethodPattern = /resource\s+"aws_api_gateway_method"\s+"([^"]+)"[\s\S]*?http_method\s*=\s*"([^"]+)"/g;
|
|
205
|
+
while ((match = apiMethodPattern.exec(content)) !== null) {
|
|
206
|
+
const line = content.slice(0, match.index).split("\n").length;
|
|
207
|
+
const method = match[2];
|
|
208
|
+
const name = `${method} (api_gateway_method.${match[1]})`;
|
|
209
|
+
nodes.push({
|
|
210
|
+
id: `route:${filePath}:${method}:${match[1]}:${line}`,
|
|
211
|
+
kind: "route",
|
|
212
|
+
name,
|
|
213
|
+
qualifiedName: `${filePath}::${name}`,
|
|
214
|
+
filePath,
|
|
215
|
+
startLine: line,
|
|
216
|
+
endLine: line,
|
|
217
|
+
startColumn: 0,
|
|
218
|
+
endColumn: match[0].length,
|
|
219
|
+
language: "hcl",
|
|
220
|
+
updatedAt: now
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return nodes;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
function findBlockEnd(content, startOffset) {
|
|
227
|
+
let depth = 1;
|
|
228
|
+
for (let i = startOffset; i < content.length; i++) {
|
|
229
|
+
if (content[i] === "{") depth++;
|
|
230
|
+
else if (content[i] === "}") {
|
|
231
|
+
depth--;
|
|
232
|
+
if (depth === 0) return content.slice(0, i).split("\n").length;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return content.slice(0, startOffset).split("\n").length;
|
|
236
|
+
}
|
|
237
|
+
function extractBlock(content, startOffset) {
|
|
238
|
+
let depth = 1;
|
|
239
|
+
for (let i = startOffset; i < content.length; i++) {
|
|
240
|
+
if (content[i] === "{") depth++;
|
|
241
|
+
else if (content[i] === "}") {
|
|
242
|
+
depth--;
|
|
243
|
+
if (depth === 0) return content.slice(startOffset, i);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return content.slice(startOffset);
|
|
247
|
+
}
|
|
248
|
+
function resolveResource(name, context) {
|
|
249
|
+
for (const file of context.getAllFiles()) {
|
|
250
|
+
if (!file.endsWith(".tf")) continue;
|
|
251
|
+
const node = context.getNodesInFile(file).find((n) => n.name === name);
|
|
252
|
+
if (node) return node.id;
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
function resolveModule(name, context) {
|
|
257
|
+
const fullName = `module.${name}`;
|
|
258
|
+
for (const file of context.getAllFiles()) {
|
|
259
|
+
if (!file.endsWith(".tf")) continue;
|
|
260
|
+
const node = context.getNodesInFile(file).find((n) => n.name === fullName);
|
|
261
|
+
if (node) return node.id;
|
|
262
|
+
}
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
function resolveVariable(name, context) {
|
|
266
|
+
const fullName = `var.${name}`;
|
|
267
|
+
for (const file of context.getAllFiles()) {
|
|
268
|
+
if (!file.endsWith(".tf")) continue;
|
|
269
|
+
const node = context.getNodesInFile(file).find((n) => n.name === fullName);
|
|
270
|
+
if (node) return node.id;
|
|
271
|
+
}
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
275
|
+
0 && (module.exports = {
|
|
276
|
+
terraformResolver
|
|
277
|
+
});
|
|
278
|
+
//# sourceMappingURL=terraform.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/frameworks/terraform.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Terraform / OpenTofu Framework Resolver\n *\n * Since HCL doesn't have a bundled WASM grammar, this resolver uses regex-based\n * extraction to create nodes from .tf files. It extracts:\n * - Resources as class-like nodes\n * - Data sources as variable-like nodes\n * - Modules as namespace-like nodes\n * - Variables and outputs as variable/export nodes\n * - API Gateway routes as route nodes\n */\n\nimport type { Node } from '../types';\nimport type { FrameworkResolver, UnresolvedRef, ResolvedRef, ResolutionContext } from './types';\n\nexport const terraformResolver: FrameworkResolver = {\n name: 'terraform',\n detect(context: ResolutionContext): boolean {\n if (context.fileExists('.terraform') || context.fileExists('.terraform.lock.hcl')) return true;\n return context.getAllFiles().some(f => f.endsWith('.tf'));\n },\n resolve(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null {\n // Resolve resource references (e.g., aws_lambda_function.my_func)\n if (ref.referenceName.includes('.')) {\n const parts = ref.referenceName.split('.');\n if (parts.length >= 2) {\n const resourceName = parts.slice(0, 2).join('.');\n const id = resolveResource(resourceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.85, resolvedBy: 'framework' };\n }\n }\n // Resolve module references\n if (ref.referenceName.startsWith('module.')) {\n const moduleName = ref.referenceName.replace('module.', '');\n const id = resolveModule(moduleName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.9, resolvedBy: 'framework' };\n }\n // Resolve variable references\n if (ref.referenceName.startsWith('var.')) {\n const varName = ref.referenceName.replace('var.', '');\n const id = resolveVariable(varName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.9, resolvedBy: 'framework' };\n }\n return null;\n },\n extractNodes(filePath: string, content: string): Node[] {\n if (!filePath.endsWith('.tf') && !filePath.endsWith('.tfvars')) return [];\n\n const nodes: Node[] = [];\n const now = Date.now();\n\n // Extract resource blocks: resource \"aws_type\" \"name\" {\n const resourcePattern = /^resource\\s+\"([^\"]+)\"\\s+\"([^\"]+)\"\\s*\\{/gm;\n let match: RegExpExecArray | null;\n while ((match = resourcePattern.exec(content)) !== null) {\n const line = content.slice(0, match.index).split('\\n').length;\n const resourceType = match[1]!;\n const resourceName = match[2]!;\n const name = `${resourceType}.${resourceName}`;\n const endLine = findBlockEnd(content, match.index + match[0].length);\n nodes.push({\n id: `resource:${filePath}:${name}:${line}`,\n kind: 'class',\n name,\n qualifiedName: `${filePath}::resource.${name}`,\n filePath, startLine: line, endLine, startColumn: 0, endColumn: match[0].length,\n language: 'hcl', updatedAt: now,\n signature: `resource \"${resourceType}\" \"${resourceName}\"`,\n });\n }\n\n // Extract data blocks: data \"aws_type\" \"name\" {\n const dataPattern = /^data\\s+\"([^\"]+)\"\\s+\"([^\"]+)\"\\s*\\{/gm;\n while ((match = dataPattern.exec(content)) !== null) {\n const line = content.slice(0, match.index).split('\\n').length;\n const dataType = match[1]!;\n const dataName = match[2]!;\n const name = `${dataType}.${dataName}`;\n const endLine = findBlockEnd(content, match.index + match[0].length);\n nodes.push({\n id: `data:${filePath}:${name}:${line}`,\n kind: 'variable',\n name: `data.${name}`,\n qualifiedName: `${filePath}::data.${name}`,\n filePath, startLine: line, endLine, startColumn: 0, endColumn: match[0].length,\n language: 'hcl', updatedAt: now,\n signature: `data \"${dataType}\" \"${dataName}\"`,\n });\n }\n\n // Extract module blocks: module \"name\" {\n const modulePattern = /^module\\s+\"([^\"]+)\"\\s*\\{/gm;\n while ((match = modulePattern.exec(content)) !== null) {\n const line = content.slice(0, match.index).split('\\n').length;\n const moduleName = match[1]!;\n const endLine = findBlockEnd(content, match.index + match[0].length);\n nodes.push({\n id: `module:${filePath}:${moduleName}:${line}`,\n kind: 'namespace',\n name: `module.${moduleName}`,\n qualifiedName: `${filePath}::module.${moduleName}`,\n filePath, startLine: line, endLine, startColumn: 0, endColumn: match[0].length,\n language: 'hcl', updatedAt: now,\n signature: `module \"${moduleName}\"`,\n });\n }\n\n // Extract variable blocks: variable \"name\" {\n const variablePattern = /^variable\\s+\"([^\"]+)\"\\s*\\{/gm;\n while ((match = variablePattern.exec(content)) !== null) {\n const line = content.slice(0, match.index).split('\\n').length;\n const varName = match[1]!;\n const endLine = findBlockEnd(content, match.index + match[0].length);\n nodes.push({\n id: `variable:${filePath}:${varName}:${line}`,\n kind: 'variable',\n name: `var.${varName}`,\n qualifiedName: `${filePath}::var.${varName}`,\n filePath, startLine: line, endLine, startColumn: 0, endColumn: match[0].length,\n language: 'hcl', updatedAt: now,\n signature: `variable \"${varName}\"`,\n });\n }\n\n // Extract output blocks: output \"name\" {\n const outputPattern = /^output\\s+\"([^\"]+)\"\\s*\\{/gm;\n while ((match = outputPattern.exec(content)) !== null) {\n const line = content.slice(0, match.index).split('\\n').length;\n const outputName = match[1]!;\n const endLine = findBlockEnd(content, match.index + match[0].length);\n nodes.push({\n id: `output:${filePath}:${outputName}:${line}`,\n kind: 'variable',\n name: `output.${outputName}`,\n qualifiedName: `${filePath}::output.${outputName}`,\n filePath, startLine: line, endLine, startColumn: 0, endColumn: match[0].length,\n language: 'hcl', updatedAt: now,\n signature: `output \"${outputName}\"`,\n isExported: true,\n });\n }\n\n // Extract locals block entries: locals { name = ... }\n const localsPattern = /^locals\\s*\\{/gm;\n while ((match = localsPattern.exec(content)) !== null) {\n const blockStart = match.index + match[0].length;\n const blockContent = extractBlock(content, blockStart);\n const localPattern = /^\\s+(\\w+)\\s*=/gm;\n let localMatch: RegExpExecArray | null;\n while ((localMatch = localPattern.exec(blockContent)) !== null) {\n const localLine = content.slice(0, blockStart).split('\\n').length +\n blockContent.slice(0, localMatch.index).split('\\n').length - 1;\n const localName = localMatch[1]!;\n nodes.push({\n id: `local:${filePath}:${localName}:${localLine}`,\n kind: 'constant',\n name: `local.${localName}`,\n qualifiedName: `${filePath}::local.${localName}`,\n filePath, startLine: localLine, endLine: localLine, startColumn: 0, endColumn: localMatch[0].length,\n language: 'hcl', updatedAt: now,\n });\n }\n }\n\n // Extract API Gateway routes from aws_api_gateway_resource + aws_api_gateway_method\n const apiResourcePattern = /resource\\s+\"aws_api_gateway_resource\"\\s+\"([^\"]+)\"[\\s\\S]*?path_part\\s*=\\s*\"([^\"]+)\"/g;\n while ((match = apiResourcePattern.exec(content)) !== null) {\n const line = content.slice(0, match.index).split('\\n').length;\n const routePath = `/${match[2]}`;\n const name = `RESOURCE ${routePath}`;\n nodes.push({\n id: `route:${filePath}:RESOURCE:${routePath}:${line}`,\n kind: 'route', name,\n qualifiedName: `${filePath}::${name}`,\n filePath, startLine: line, endLine: line, startColumn: 0, endColumn: match[0].length,\n language: 'hcl', updatedAt: now,\n });\n }\n\n const apiMethodPattern = /resource\\s+\"aws_api_gateway_method\"\\s+\"([^\"]+)\"[\\s\\S]*?http_method\\s*=\\s*\"([^\"]+)\"/g;\n while ((match = apiMethodPattern.exec(content)) !== null) {\n const line = content.slice(0, match.index).split('\\n').length;\n const method = match[2]!;\n const name = `${method} (api_gateway_method.${match[1]})`;\n nodes.push({\n id: `route:${filePath}:${method}:${match[1]}:${line}`,\n kind: 'route', name,\n qualifiedName: `${filePath}::${name}`,\n filePath, startLine: line, endLine: line, startColumn: 0, endColumn: match[0].length,\n language: 'hcl', updatedAt: now,\n });\n }\n\n return nodes;\n },\n};\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction findBlockEnd(content: string, startOffset: number): number {\n let depth = 1;\n for (let i = startOffset; i < content.length; i++) {\n if (content[i] === '{') depth++;\n else if (content[i] === '}') {\n depth--;\n if (depth === 0) return content.slice(0, i).split('\\n').length;\n }\n }\n return content.slice(0, startOffset).split('\\n').length;\n}\n\nfunction extractBlock(content: string, startOffset: number): string {\n let depth = 1;\n for (let i = startOffset; i < content.length; i++) {\n if (content[i] === '{') depth++;\n else if (content[i] === '}') {\n depth--;\n if (depth === 0) return content.slice(startOffset, i);\n }\n }\n return content.slice(startOffset);\n}\n\nfunction resolveResource(name: string, context: ResolutionContext): string | null {\n for (const file of context.getAllFiles()) {\n if (!file.endsWith('.tf')) continue;\n const node = context.getNodesInFile(file).find(n => n.name === name);\n if (node) return node.id;\n }\n return null;\n}\n\nfunction resolveModule(name: string, context: ResolutionContext): string | null {\n const fullName = `module.${name}`;\n for (const file of context.getAllFiles()) {\n if (!file.endsWith('.tf')) continue;\n const node = context.getNodesInFile(file).find(n => n.name === fullName);\n if (node) return node.id;\n }\n return null;\n}\n\nfunction resolveVariable(name: string, context: ResolutionContext): string | null {\n const fullName = `var.${name}`;\n for (const file of context.getAllFiles()) {\n if (!file.endsWith('.tf')) continue;\n const node = context.getNodesInFile(file).find(n => n.name === fullName);\n if (node) return node.id;\n }\n return null;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var vue_exports = {};
|
|
20
|
+
__export(vue_exports, {
|
|
21
|
+
nuxtResolver: () => nuxtResolver,
|
|
22
|
+
vueResolver: () => vueResolver
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(vue_exports);
|
|
25
|
+
const nuxtResolver = {
|
|
26
|
+
name: "nuxt",
|
|
27
|
+
detect(context) {
|
|
28
|
+
if (context.fileExists("nuxt.config.ts") || context.fileExists("nuxt.config.js")) return true;
|
|
29
|
+
const pkg = context.readFile("package.json");
|
|
30
|
+
if (pkg) {
|
|
31
|
+
try {
|
|
32
|
+
const parsed = JSON.parse(pkg);
|
|
33
|
+
const deps = { ...parsed.dependencies, ...parsed.devDependencies };
|
|
34
|
+
if ("nuxt" in deps || "nuxt3" in deps) return true;
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
},
|
|
40
|
+
resolve(ref, context) {
|
|
41
|
+
if (ref.referenceName.startsWith("use")) {
|
|
42
|
+
const id = resolveComposable(ref.referenceName, context);
|
|
43
|
+
if (id) return { original: ref, targetNodeId: id, confidence: 0.9, resolvedBy: "framework" };
|
|
44
|
+
}
|
|
45
|
+
if (/^[A-Z][a-zA-Z]+$/.test(ref.referenceName)) {
|
|
46
|
+
const id = resolveComponent(ref.referenceName, context);
|
|
47
|
+
if (id) return { original: ref, targetNodeId: id, confidence: 0.85, resolvedBy: "framework" };
|
|
48
|
+
}
|
|
49
|
+
if (ref.referenceName.startsWith("use") && ref.referenceName.endsWith("Store")) {
|
|
50
|
+
const id = resolveStore(ref.referenceName, context);
|
|
51
|
+
if (id) return { original: ref, targetNodeId: id, confidence: 0.9, resolvedBy: "framework" };
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
},
|
|
55
|
+
extractNodes(filePath, content) {
|
|
56
|
+
const nodes = [];
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
if (filePath.includes("server/api/") || filePath.includes("server/routes/")) {
|
|
59
|
+
const routePath = filePath.replace(/.*server\/(api|routes)/, "/$1").replace(/\.(ts|js|mjs)$/, "").replace(/\/index$/, "").replace(/\[([^\]]+)\]/g, ":$1");
|
|
60
|
+
const methodMatch = routePath.match(/\.(get|post|put|patch|delete)$/i);
|
|
61
|
+
const method = methodMatch ? methodMatch[1].toUpperCase() : "ANY";
|
|
62
|
+
const cleanPath = methodMatch ? routePath.replace(/\.(get|post|put|patch|delete)$/i, "") : routePath;
|
|
63
|
+
const name = `${method} ${cleanPath}`;
|
|
64
|
+
nodes.push({
|
|
65
|
+
id: `route:${filePath}:${method}:${cleanPath}:1`,
|
|
66
|
+
kind: "route",
|
|
67
|
+
name,
|
|
68
|
+
qualifiedName: `${filePath}::${name}`,
|
|
69
|
+
filePath,
|
|
70
|
+
startLine: 1,
|
|
71
|
+
endLine: 1,
|
|
72
|
+
startColumn: 0,
|
|
73
|
+
endColumn: 0,
|
|
74
|
+
language: "typescript",
|
|
75
|
+
updatedAt: now
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (filePath.includes("pages/") && filePath.endsWith(".vue")) {
|
|
79
|
+
const routePath = filePath.replace(/.*pages/, "").replace(/\.vue$/, "").replace(/\/index$/, "").replace(/\[([^\]]+)\]/g, ":$1");
|
|
80
|
+
const name = `PAGE ${routePath || "/"}`;
|
|
81
|
+
nodes.push({
|
|
82
|
+
id: `route:${filePath}:PAGE:${routePath || "/"}:1`,
|
|
83
|
+
kind: "route",
|
|
84
|
+
name,
|
|
85
|
+
qualifiedName: `${filePath}::${name}`,
|
|
86
|
+
filePath,
|
|
87
|
+
startLine: 1,
|
|
88
|
+
endLine: 1,
|
|
89
|
+
startColumn: 0,
|
|
90
|
+
endColumn: 0,
|
|
91
|
+
language: "vue",
|
|
92
|
+
updatedAt: now
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return nodes;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const vueResolver = {
|
|
99
|
+
name: "vue",
|
|
100
|
+
detect(context) {
|
|
101
|
+
const pkg = context.readFile("package.json");
|
|
102
|
+
if (pkg) {
|
|
103
|
+
try {
|
|
104
|
+
const parsed = JSON.parse(pkg);
|
|
105
|
+
const deps = { ...parsed.dependencies, ...parsed.devDependencies };
|
|
106
|
+
if ("vue" in deps) return true;
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return context.getAllFiles().some((f) => f.endsWith(".vue"));
|
|
111
|
+
},
|
|
112
|
+
resolve(ref, context) {
|
|
113
|
+
if (/^[A-Z][a-zA-Z]+$/.test(ref.referenceName)) {
|
|
114
|
+
const id = resolveComponent(ref.referenceName, context);
|
|
115
|
+
if (id) return { original: ref, targetNodeId: id, confidence: 0.8, resolvedBy: "framework" };
|
|
116
|
+
}
|
|
117
|
+
if (ref.referenceName.startsWith("use")) {
|
|
118
|
+
const id = resolveComposable(ref.referenceName, context);
|
|
119
|
+
if (id) return { original: ref, targetNodeId: id, confidence: 0.85, resolvedBy: "framework" };
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
function resolveComposable(name, context) {
|
|
125
|
+
const dirs = ["composables", "src/composables", "hooks", "src/hooks"];
|
|
126
|
+
for (const file of context.getAllFiles()) {
|
|
127
|
+
if ((file.endsWith(".ts") || file.endsWith(".js")) && dirs.some((d) => file.includes(`/${d}/`))) {
|
|
128
|
+
const node = context.getNodesInFile(file).find((n) => n.name === name);
|
|
129
|
+
if (node) return node.id;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
function resolveComponent(name, context) {
|
|
135
|
+
const kebab = name.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
136
|
+
const dirs = ["components", "src/components"];
|
|
137
|
+
for (const file of context.getAllFiles()) {
|
|
138
|
+
if (!file.endsWith(".vue") && !file.endsWith(".tsx") && !file.endsWith(".ts")) continue;
|
|
139
|
+
if (!dirs.some((d) => file.includes(`/${d}/`))) continue;
|
|
140
|
+
const basename = file.split("/").pop()?.replace(/\.(vue|tsx|ts)$/, "") ?? "";
|
|
141
|
+
if (basename === name || basename === kebab || basename.toLowerCase() === name.toLowerCase()) {
|
|
142
|
+
const nodes = context.getNodesInFile(file);
|
|
143
|
+
if (nodes.length > 0) return nodes[0].id;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
function resolveStore(name, context) {
|
|
149
|
+
const dirs = ["stores", "store", "src/stores", "src/store"];
|
|
150
|
+
for (const file of context.getAllFiles()) {
|
|
151
|
+
if ((file.endsWith(".ts") || file.endsWith(".js")) && dirs.some((d) => file.includes(`/${d}/`))) {
|
|
152
|
+
const node = context.getNodesInFile(file).find((n) => n.name === name);
|
|
153
|
+
if (node) return node.id;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
159
|
+
0 && (module.exports = {
|
|
160
|
+
nuxtResolver,
|
|
161
|
+
vueResolver
|
|
162
|
+
});
|
|
163
|
+
//# sourceMappingURL=vue.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/frameworks/vue.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Vue / Nuxt Framework Resolver\n */\n\nimport type { Node } from '../types';\nimport type { FrameworkResolver, UnresolvedRef, ResolvedRef, ResolutionContext } from './types';\n\nexport const nuxtResolver: FrameworkResolver = {\n name: 'nuxt',\n detect(context: ResolutionContext): boolean {\n if (context.fileExists('nuxt.config.ts') || context.fileExists('nuxt.config.js')) return true;\n const pkg = context.readFile('package.json');\n if (pkg) {\n try {\n const parsed = JSON.parse(pkg);\n const deps = { ...parsed.dependencies, ...parsed.devDependencies };\n if ('nuxt' in deps || 'nuxt3' in deps) return true;\n } catch { /* ignore */ }\n }\n return false;\n },\n resolve(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null {\n // Resolve composable references (useXxx)\n if (ref.referenceName.startsWith('use')) {\n const id = resolveComposable(ref.referenceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.9, resolvedBy: 'framework' };\n }\n // Resolve component references (PascalCase)\n if (/^[A-Z][a-zA-Z]+$/.test(ref.referenceName)) {\n const id = resolveComponent(ref.referenceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.85, resolvedBy: 'framework' };\n }\n // Resolve store references\n if (ref.referenceName.startsWith('use') && ref.referenceName.endsWith('Store')) {\n const id = resolveStore(ref.referenceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.9, resolvedBy: 'framework' };\n }\n return null;\n },\n extractNodes(filePath: string, content: string): Node[] {\n const nodes: Node[] = [];\n const now = Date.now();\n\n // Nuxt server API routes: server/api/[...].ts \u2192 route based on file path\n if (filePath.includes('server/api/') || filePath.includes('server/routes/')) {\n const routePath = filePath\n .replace(/.*server\\/(api|routes)/, '/$1')\n .replace(/\\.(ts|js|mjs)$/, '')\n .replace(/\\/index$/, '')\n .replace(/\\[([^\\]]+)\\]/g, ':$1');\n\n // Detect HTTP method from filename (e.g., users.get.ts, users.post.ts)\n const methodMatch = routePath.match(/\\.(get|post|put|patch|delete)$/i);\n const method = methodMatch ? methodMatch[1]!.toUpperCase() : 'ANY';\n const cleanPath = methodMatch ? routePath.replace(/\\.(get|post|put|patch|delete)$/i, '') : routePath;\n\n const name = `${method} ${cleanPath}`;\n nodes.push({\n id: `route:${filePath}:${method}:${cleanPath}:1`,\n kind: 'route', name,\n qualifiedName: `${filePath}::${name}`,\n filePath, startLine: 1, endLine: 1, startColumn: 0, endColumn: 0,\n language: 'typescript', updatedAt: now,\n });\n }\n\n // Nuxt pages \u2192 routes (pages/users/[id].vue \u2192 /users/:id)\n if (filePath.includes('pages/') && filePath.endsWith('.vue')) {\n const routePath = filePath\n .replace(/.*pages/, '')\n .replace(/\\.vue$/, '')\n .replace(/\\/index$/, '')\n .replace(/\\[([^\\]]+)\\]/g, ':$1');\n\n const name = `PAGE ${routePath || '/'}`;\n nodes.push({\n id: `route:${filePath}:PAGE:${routePath || '/'}:1`,\n kind: 'route', name,\n qualifiedName: `${filePath}::${name}`,\n filePath, startLine: 1, endLine: 1, startColumn: 0, endColumn: 0,\n language: 'vue', updatedAt: now,\n });\n }\n\n return nodes;\n },\n};\n\nexport const vueResolver: FrameworkResolver = {\n name: 'vue',\n detect(context: ResolutionContext): boolean {\n const pkg = context.readFile('package.json');\n if (pkg) {\n try {\n const parsed = JSON.parse(pkg);\n const deps = { ...parsed.dependencies, ...parsed.devDependencies };\n if ('vue' in deps) return true;\n } catch { /* ignore */ }\n }\n return context.getAllFiles().some(f => f.endsWith('.vue'));\n },\n resolve(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null {\n // Resolve component references\n if (/^[A-Z][a-zA-Z]+$/.test(ref.referenceName)) {\n const id = resolveComponent(ref.referenceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.8, resolvedBy: 'framework' };\n }\n // Resolve composable references\n if (ref.referenceName.startsWith('use')) {\n const id = resolveComposable(ref.referenceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.85, resolvedBy: 'framework' };\n }\n return null;\n },\n};\n\nfunction resolveComposable(name: string, context: ResolutionContext): string | null {\n // Convert useFetchData \u2192 fetchData \u2192 fetch-data or fetchData\n const dirs = ['composables', 'src/composables', 'hooks', 'src/hooks'];\n for (const file of context.getAllFiles()) {\n if ((file.endsWith('.ts') || file.endsWith('.js')) && dirs.some(d => file.includes(`/${d}/`))) {\n const node = context.getNodesInFile(file).find(n => n.name === name);\n if (node) return node.id;\n }\n }\n return null;\n}\n\nfunction resolveComponent(name: string, context: ResolutionContext): string | null {\n // PascalCase \u2192 kebab-case for file matching\n const kebab = name.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');\n const dirs = ['components', 'src/components'];\n for (const file of context.getAllFiles()) {\n if (!file.endsWith('.vue') && !file.endsWith('.tsx') && !file.endsWith('.ts')) continue;\n if (!dirs.some(d => file.includes(`/${d}/`))) continue;\n // Match by filename (PascalCase or kebab-case)\n const basename = file.split('/').pop()?.replace(/\\.(vue|tsx|ts)$/, '') ?? '';\n if (basename === name || basename === kebab || basename.toLowerCase() === name.toLowerCase()) {\n const nodes = context.getNodesInFile(file);\n if (nodes.length > 0) return nodes[0].id;\n }\n }\n return null;\n}\n\nfunction resolveStore(name: string, context: ResolutionContext): string | null {\n const dirs = ['stores', 'store', 'src/stores', 'src/store'];\n for (const file of context.getAllFiles()) {\n if ((file.endsWith('.ts') || file.endsWith('.js')) && dirs.some(d => file.includes(`/${d}/`))) {\n const node = context.getNodesInFile(file).find(n => n.name === name);\n if (node) return node.id;\n }\n }\n return null;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOO,MAAM,eAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,OAAO,SAAqC;AAC1C,QAAI,QAAQ,WAAW,gBAAgB,KAAK,QAAQ,WAAW,gBAAgB,EAAG,QAAO;AACzF,UAAM,MAAM,QAAQ,SAAS,cAAc;AAC3C,QAAI,KAAK;AACP,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,cAAM,OAAO,EAAE,GAAG,OAAO,cAAc,GAAG,OAAO,gBAAgB;AACjE,YAAI,UAAU,QAAQ,WAAW,KAAM,QAAO;AAAA,MAChD,QAAQ;AAAA,MAAe;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAAA,EACA,QAAQ,KAAoB,SAAgD;AAE1E,QAAI,IAAI,cAAc,WAAW,KAAK,GAAG;AACvC,YAAM,KAAK,kBAAkB,IAAI,eAAe,OAAO;AACvD,UAAI,GAAI,QAAO,EAAE,UAAU,KAAK,cAAc,IAAI,YAAY,KAAK,YAAY,YAAY;AAAA,IAC7F;AAEA,QAAI,mBAAmB,KAAK,IAAI,aAAa,GAAG;AAC9C,YAAM,KAAK,iBAAiB,IAAI,eAAe,OAAO;AACtD,UAAI,GAAI,QAAO,EAAE,UAAU,KAAK,cAAc,IAAI,YAAY,MAAM,YAAY,YAAY;AAAA,IAC9F;AAEA,QAAI,IAAI,cAAc,WAAW,KAAK,KAAK,IAAI,cAAc,SAAS,OAAO,GAAG;AAC9E,YAAM,KAAK,aAAa,IAAI,eAAe,OAAO;AAClD,UAAI,GAAI,QAAO,EAAE,UAAU,KAAK,cAAc,IAAI,YAAY,KAAK,YAAY,YAAY;AAAA,IAC7F;AACA,WAAO;AAAA,EACT;AAAA,EACA,aAAa,UAAkB,SAAyB;AACtD,UAAM,QAAgB,CAAC;AACvB,UAAM,MAAM,KAAK,IAAI;AAGrB,QAAI,SAAS,SAAS,aAAa,KAAK,SAAS,SAAS,gBAAgB,GAAG;AAC3E,YAAM,YAAY,SACf,QAAQ,0BAA0B,KAAK,EACvC,QAAQ,kBAAkB,EAAE,EAC5B,QAAQ,YAAY,EAAE,EACtB,QAAQ,iBAAiB,KAAK;AAGjC,YAAM,cAAc,UAAU,MAAM,iCAAiC;AACrE,YAAM,SAAS,cAAc,YAAY,CAAC,EAAG,YAAY,IAAI;AAC7D,YAAM,YAAY,cAAc,UAAU,QAAQ,mCAAmC,EAAE,IAAI;AAE3F,YAAM,OAAO,GAAG,MAAM,IAAI,SAAS;AACnC,YAAM,KAAK;AAAA,QACT,IAAI,SAAS,QAAQ,IAAI,MAAM,IAAI,SAAS;AAAA,QAC5C,MAAM;AAAA,QAAS;AAAA,QACf,eAAe,GAAG,QAAQ,KAAK,IAAI;AAAA,QACnC;AAAA,QAAU,WAAW;AAAA,QAAG,SAAS;AAAA,QAAG,aAAa;AAAA,QAAG,WAAW;AAAA,QAC/D,UAAU;AAAA,QAAc,WAAW;AAAA,MACrC,CAAC;AAAA,IACH;AAGA,QAAI,SAAS,SAAS,QAAQ,KAAK,SAAS,SAAS,MAAM,GAAG;AAC5D,YAAM,YAAY,SACf,QAAQ,WAAW,EAAE,EACrB,QAAQ,UAAU,EAAE,EACpB,QAAQ,YAAY,EAAE,EACtB,QAAQ,iBAAiB,KAAK;AAEjC,YAAM,OAAO,QAAQ,aAAa,GAAG;AACrC,YAAM,KAAK;AAAA,QACT,IAAI,SAAS,QAAQ,SAAS,aAAa,GAAG;AAAA,QAC9C,MAAM;AAAA,QAAS;AAAA,QACf,eAAe,GAAG,QAAQ,KAAK,IAAI;AAAA,QACnC;AAAA,QAAU,WAAW;AAAA,QAAG,SAAS;AAAA,QAAG,aAAa;AAAA,QAAG,WAAW;AAAA,QAC/D,UAAU;AAAA,QAAO,WAAW;AAAA,MAC9B,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AACF;AAEO,MAAM,cAAiC;AAAA,EAC5C,MAAM;AAAA,EACN,OAAO,SAAqC;AAC1C,UAAM,MAAM,QAAQ,SAAS,cAAc;AAC3C,QAAI,KAAK;AACP,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,cAAM,OAAO,EAAE,GAAG,OAAO,cAAc,GAAG,OAAO,gBAAgB;AACjE,YAAI,SAAS,KAAM,QAAO;AAAA,MAC5B,QAAQ;AAAA,MAAe;AAAA,IACzB;AACA,WAAO,QAAQ,YAAY,EAAE,KAAK,OAAK,EAAE,SAAS,MAAM,CAAC;AAAA,EAC3D;AAAA,EACA,QAAQ,KAAoB,SAAgD;AAE1E,QAAI,mBAAmB,KAAK,IAAI,aAAa,GAAG;AAC9C,YAAM,KAAK,iBAAiB,IAAI,eAAe,OAAO;AACtD,UAAI,GAAI,QAAO,EAAE,UAAU,KAAK,cAAc,IAAI,YAAY,KAAK,YAAY,YAAY;AAAA,IAC7F;AAEA,QAAI,IAAI,cAAc,WAAW,KAAK,GAAG;AACvC,YAAM,KAAK,kBAAkB,IAAI,eAAe,OAAO;AACvD,UAAI,GAAI,QAAO,EAAE,UAAU,KAAK,cAAc,IAAI,YAAY,MAAM,YAAY,YAAY;AAAA,IAC9F;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,kBAAkB,MAAc,SAA2C;AAElF,QAAM,OAAO,CAAC,eAAe,mBAAmB,SAAS,WAAW;AACpE,aAAW,QAAQ,QAAQ,YAAY,GAAG;AACxC,SAAK,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,KAAK,MAAM,KAAK,KAAK,OAAK,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,GAAG;AAC7F,YAAM,OAAO,QAAQ,eAAe,IAAI,EAAE,KAAK,OAAK,EAAE,SAAS,IAAI;AACnE,UAAI,KAAM,QAAO,KAAK;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAAc,SAA2C;AAEjF,QAAM,QAAQ,KAAK,QAAQ,YAAY,KAAK,EAAE,YAAY,EAAE,QAAQ,MAAM,EAAE;AAC5E,QAAM,OAAO,CAAC,cAAc,gBAAgB;AAC5C,aAAW,QAAQ,QAAQ,YAAY,GAAG;AACxC,QAAI,CAAC,KAAK,SAAS,MAAM,KAAK,CAAC,KAAK,SAAS,MAAM,KAAK,CAAC,KAAK,SAAS,KAAK,EAAG;AAC/E,QAAI,CAAC,KAAK,KAAK,OAAK,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,EAAG;AAE9C,UAAM,WAAW,KAAK,MAAM,GAAG,EAAE,IAAI,GAAG,QAAQ,mBAAmB,EAAE,KAAK;AAC1E,QAAI,aAAa,QAAQ,aAAa,SAAS,SAAS,YAAY,MAAM,KAAK,YAAY,GAAG;AAC5F,YAAM,QAAQ,QAAQ,eAAe,IAAI;AACzC,UAAI,MAAM,SAAS,EAAG,QAAO,MAAM,CAAC,EAAE;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,aAAa,MAAc,SAA2C;AAC7E,QAAM,OAAO,CAAC,UAAU,SAAS,cAAc,WAAW;AAC1D,aAAW,QAAQ,QAAQ,YAAY,GAAG;AACxC,SAAK,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,KAAK,MAAM,KAAK,KAAK,OAAK,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,GAAG;AAC7F,YAAM,OAAO,QAAQ,eAAe,IAAI,EAAE,KAAK,OAAK,EAAE,SAAS,IAAI;AACnE,UAAI,KAAM,QAAO,KAAK;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/graph/queries.js
CHANGED
|
@@ -151,7 +151,7 @@ class GraphQueryManager {
|
|
|
151
151
|
const picomatch = require("picomatch");
|
|
152
152
|
const depth = opts?.depth ?? 5;
|
|
153
153
|
const isTest = picomatch(
|
|
154
|
-
opts?.testPattern ?? "{**/*.spec.*,**/*.test
|
|
154
|
+
opts?.testPattern ?? "{**/*.spec.*,**/*.test.*,**/*_test.*,**/*Test.*,**/*Spec.*,**/*.t.sol,**/*.bats,**/e2e/**,**/test/**,**/tests/**,**/spec/**,**/__tests__/**,**/src/test/**}"
|
|
155
155
|
);
|
|
156
156
|
const results = /* @__PURE__ */ new Set();
|
|
157
157
|
for (const file of changedFiles) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/graph/queries.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * KiroGraph Graph Query Manager\n * High-level graph queries built on top of GraphTraverser and GraphDatabase.\n */\n\nimport type { Node, NodeContext, NodeMetrics, Subgraph } from '../types';\nimport type { GraphDatabase } from '../db/database';\nimport { GraphTraverser, type TraversalOptions } from './traversal';\n\nexport class GraphQueryManager {\n private readonly traverser: GraphTraverser;\n\n constructor(private readonly db: GraphDatabase) {\n this.traverser = new GraphTraverser(db);\n }\n\n /** Get full context for a node (node + ancestors + children + callers + callees). */\n async getContext(nodeId: string): Promise<NodeContext> {\n const ctx = this.db.getNodeContext(nodeId);\n if (!ctx) {\n const node = this.db.getNode(nodeId);\n if (!node) throw new Error(`Node not found: ${nodeId}`);\n return { node, ancestors: [], children: [], callers: [], callees: [] };\n }\n return ctx;\n }\n\n /** Get all nodes that call the given node (depth=1, incoming 'calls' edges). */\n async getCallers(nodeId: string, limit?: number): Promise<Node[]> {\n return this.traverser.traverseBFS(nodeId, {\n direction: 'incoming',\n edgeKinds: ['calls'],\n maxDepth: 1,\n limit,\n });\n }\n\n /** Get all nodes called by the given node (depth=1, outgoing 'calls' edges). */\n async getCallees(nodeId: string, limit?: number): Promise<Node[]> {\n return this.traverser.traverseBFS(nodeId, {\n direction: 'outgoing',\n edgeKinds: ['calls'],\n maxDepth: 1,\n limit,\n });\n }\n\n /** Get the full call graph rooted at nodeId up to the given depth. */\n async getCallGraph(nodeId: string, depth = 3): Promise<Subgraph> {\n const nodes = await this.traverser.traverseBFS(nodeId, {\n direction: 'outgoing',\n edgeKinds: ['calls'],\n maxDepth: depth,\n includeStart: true,\n });\n const nodeIds = nodes.map(n => n.id);\n const edges = this.db.getEdgesForNodes(nodeIds).filter(\n e => nodeIds.includes(e.source) && nodeIds.includes(e.target) && e.kind === 'calls'\n );\n return { nodes, edges, entryPoints: [nodeId] };\n }\n\n /**\n * Get the type hierarchy for a node.\n * direction: 'up' = base types, 'down' = derived types, 'both' = all.\n */\n async getTypeHierarchy(nodeId: string, direction: 'up' | 'down' | 'both' = 'both'): Promise<Node[]> {\n const traversalDirection =\n direction === 'up' ? 'outgoing' :\n direction === 'down' ? 'incoming' :\n 'both';\n\n return this.traverser.traverseBFS(nodeId, {\n direction: traversalDirection,\n edgeKinds: ['extends', 'implements'],\n });\n }\n\n /** Get all nodes that would be impacted by changing nodeId (incoming edges). */\n async getImpactRadius(nodeId: string, depth = 2): Promise<Node[]> {\n return this.traverser.traverseBFS(nodeId, {\n direction: 'incoming',\n maxDepth: depth,\n });\n }\n\n /** Find the shortest path between two nodes via BFS. */\n async findPath(fromId: string, toId: string, maxDepth = 10): Promise<Node[]> {\n if (fromId === toId) {\n const node = this.db.getNode(fromId);\n return node ? [node] : [];\n }\n\n const prev = new Map<string, string>();\n const queue: Array<[string, number]> = [[fromId, 0]];\n const visited = new Set<string>([fromId]);\n let found = false;\n\n outer: while (queue.length > 0) {\n const [currentId, depth] = queue.shift()!;\n if (depth >= maxDepth) continue;\n\n const edges = this.db.getEdgesForNodes([currentId]);\n for (const edge of edges) {\n const neighborId = edge.source === currentId ? edge.target : edge.source;\n if (!visited.has(neighborId)) {\n visited.add(neighborId);\n prev.set(neighborId, currentId);\n if (neighborId === toId) {\n found = true;\n break outer;\n }\n queue.push([neighborId, depth + 1]);\n }\n }\n }\n\n if (!found) return [];\n\n // Reconstruct path\n const pathIds: string[] = [];\n let cur: string | undefined = toId;\n while (cur !== undefined) {\n pathIds.unshift(cur);\n cur = prev.get(cur);\n }\n\n const result: Node[] = [];\n for (const id of pathIds) {\n const node = this.db.getNode(id);\n if (node) result.push(node);\n }\n return result;\n }\n\n /** Get all ancestor containers of a node (incoming 'contains' edges). */\n async getAncestors(nodeId: string): Promise<Node[]> {\n return this.traverser.traverseBFS(nodeId, {\n direction: 'incoming',\n edgeKinds: ['contains'],\n });\n }\n\n /** Get direct children of a node (outgoing 'contains' edges, depth=1). */\n async getChildren(nodeId: string): Promise<Node[]> {\n return this.traverser.traverseBFS(nodeId, {\n direction: 'outgoing',\n edgeKinds: ['contains'],\n maxDepth: 1,\n });\n }\n\n /**\n * Find test files that are transitively affected by changes to the given source files.\n * BFS-traverses import/call dependents to discover which test files depend on changed code.\n */\n getAffectedTests(\n changedFiles: string[],\n opts?: { depth?: number; testPattern?: string },\n ): string[] {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const picomatch = require('picomatch');\n const depth = opts?.depth ?? 5;\n const isTest = picomatch(\n opts?.testPattern ?? '{**/*.spec.*,**/*.test
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph Graph Query Manager\n * High-level graph queries built on top of GraphTraverser and GraphDatabase.\n */\n\nimport type { Node, NodeContext, NodeMetrics, Subgraph } from '../types';\nimport type { GraphDatabase } from '../db/database';\nimport { GraphTraverser, type TraversalOptions } from './traversal';\n\nexport class GraphQueryManager {\n private readonly traverser: GraphTraverser;\n\n constructor(private readonly db: GraphDatabase) {\n this.traverser = new GraphTraverser(db);\n }\n\n /** Get full context for a node (node + ancestors + children + callers + callees). */\n async getContext(nodeId: string): Promise<NodeContext> {\n const ctx = this.db.getNodeContext(nodeId);\n if (!ctx) {\n const node = this.db.getNode(nodeId);\n if (!node) throw new Error(`Node not found: ${nodeId}`);\n return { node, ancestors: [], children: [], callers: [], callees: [] };\n }\n return ctx;\n }\n\n /** Get all nodes that call the given node (depth=1, incoming 'calls' edges). */\n async getCallers(nodeId: string, limit?: number): Promise<Node[]> {\n return this.traverser.traverseBFS(nodeId, {\n direction: 'incoming',\n edgeKinds: ['calls'],\n maxDepth: 1,\n limit,\n });\n }\n\n /** Get all nodes called by the given node (depth=1, outgoing 'calls' edges). */\n async getCallees(nodeId: string, limit?: number): Promise<Node[]> {\n return this.traverser.traverseBFS(nodeId, {\n direction: 'outgoing',\n edgeKinds: ['calls'],\n maxDepth: 1,\n limit,\n });\n }\n\n /** Get the full call graph rooted at nodeId up to the given depth. */\n async getCallGraph(nodeId: string, depth = 3): Promise<Subgraph> {\n const nodes = await this.traverser.traverseBFS(nodeId, {\n direction: 'outgoing',\n edgeKinds: ['calls'],\n maxDepth: depth,\n includeStart: true,\n });\n const nodeIds = nodes.map(n => n.id);\n const edges = this.db.getEdgesForNodes(nodeIds).filter(\n e => nodeIds.includes(e.source) && nodeIds.includes(e.target) && e.kind === 'calls'\n );\n return { nodes, edges, entryPoints: [nodeId] };\n }\n\n /**\n * Get the type hierarchy for a node.\n * direction: 'up' = base types, 'down' = derived types, 'both' = all.\n */\n async getTypeHierarchy(nodeId: string, direction: 'up' | 'down' | 'both' = 'both'): Promise<Node[]> {\n const traversalDirection =\n direction === 'up' ? 'outgoing' :\n direction === 'down' ? 'incoming' :\n 'both';\n\n return this.traverser.traverseBFS(nodeId, {\n direction: traversalDirection,\n edgeKinds: ['extends', 'implements'],\n });\n }\n\n /** Get all nodes that would be impacted by changing nodeId (incoming edges). */\n async getImpactRadius(nodeId: string, depth = 2): Promise<Node[]> {\n return this.traverser.traverseBFS(nodeId, {\n direction: 'incoming',\n maxDepth: depth,\n });\n }\n\n /** Find the shortest path between two nodes via BFS. */\n async findPath(fromId: string, toId: string, maxDepth = 10): Promise<Node[]> {\n if (fromId === toId) {\n const node = this.db.getNode(fromId);\n return node ? [node] : [];\n }\n\n const prev = new Map<string, string>();\n const queue: Array<[string, number]> = [[fromId, 0]];\n const visited = new Set<string>([fromId]);\n let found = false;\n\n outer: while (queue.length > 0) {\n const [currentId, depth] = queue.shift()!;\n if (depth >= maxDepth) continue;\n\n const edges = this.db.getEdgesForNodes([currentId]);\n for (const edge of edges) {\n const neighborId = edge.source === currentId ? edge.target : edge.source;\n if (!visited.has(neighborId)) {\n visited.add(neighborId);\n prev.set(neighborId, currentId);\n if (neighborId === toId) {\n found = true;\n break outer;\n }\n queue.push([neighborId, depth + 1]);\n }\n }\n }\n\n if (!found) return [];\n\n // Reconstruct path\n const pathIds: string[] = [];\n let cur: string | undefined = toId;\n while (cur !== undefined) {\n pathIds.unshift(cur);\n cur = prev.get(cur);\n }\n\n const result: Node[] = [];\n for (const id of pathIds) {\n const node = this.db.getNode(id);\n if (node) result.push(node);\n }\n return result;\n }\n\n /** Get all ancestor containers of a node (incoming 'contains' edges). */\n async getAncestors(nodeId: string): Promise<Node[]> {\n return this.traverser.traverseBFS(nodeId, {\n direction: 'incoming',\n edgeKinds: ['contains'],\n });\n }\n\n /** Get direct children of a node (outgoing 'contains' edges, depth=1). */\n async getChildren(nodeId: string): Promise<Node[]> {\n return this.traverser.traverseBFS(nodeId, {\n direction: 'outgoing',\n edgeKinds: ['contains'],\n maxDepth: 1,\n });\n }\n\n /**\n * Find test files that are transitively affected by changes to the given source files.\n * BFS-traverses import/call dependents to discover which test files depend on changed code.\n */\n getAffectedTests(\n changedFiles: string[],\n opts?: { depth?: number; testPattern?: string },\n ): string[] {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const picomatch = require('picomatch');\n const depth = opts?.depth ?? 5;\n const isTest = picomatch(\n opts?.testPattern ?? '{**/*.spec.*,**/*.test.*,**/*_test.*,**/*Test.*,**/*Spec.*,**/*.t.sol,**/*.bats,**/e2e/**,**/test/**,**/tests/**,**/spec/**,**/__tests__/**,**/src/test/**}'\n );\n\n const results = new Set<string>();\n\n for (const file of changedFiles) {\n const rel = file.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n\n if (isTest(rel)) { results.add(rel); continue; }\n\n const visited = new Set<string>([rel]);\n let frontier = [rel];\n\n for (let d = 0; d < depth; d++) {\n if (frontier.length === 0) break;\n const next: string[] = [];\n for (const f of frontier) {\n for (const dep of this.db.getDependentFiles(f)) {\n if (!visited.has(dep)) {\n visited.add(dep);\n next.push(dep);\n if (isTest(dep)) results.add(dep);\n }\n }\n }\n frontier = next;\n }\n }\n\n return [...results].sort();\n }\n\n /** Find all circular import dependencies. Returns arrays of file paths forming cycles. */\n async findCircularDependencies(): Promise<string[][]> {\n return this.db.findCircularDependencies();\n }\n\n /** Find nodes with no incoming edges (potential dead code). */\n async findDeadCode(limit = 50): Promise<Node[]> {\n return this.db.findDeadCode(limit);\n }\n\n /** Get metrics for a node (edge counts, callers, callees, children). */\n async getNodeMetrics(nodeId: string): Promise<NodeMetrics> {\n return this.db.getNodeMetrics(nodeId);\n }\n\n /**\n * Build a subgraph from a set of node IDs, optionally traversing further\n * with the given TraversalOptions.\n */\n async getFilteredSubgraph(nodeIds: string[], opts?: TraversalOptions): Promise<Subgraph> {\n const allNodeIds = new Set<string>(nodeIds);\n\n if (opts) {\n for (const startId of nodeIds) {\n const traversed = await this.traverser.traverseBFS(startId, opts);\n for (const node of traversed) {\n allNodeIds.add(node.id);\n }\n }\n }\n\n const ids = [...allNodeIds];\n const nodes: Node[] = [];\n for (const id of ids) {\n const node = this.db.getNode(id);\n if (node) nodes.push(node);\n }\n\n const edges = this.db.getEdgesForNodes(ids).filter(\n e => allNodeIds.has(e.source) && allNodeIds.has(e.target)\n );\n\n return { nodes, edges, entryPoints: nodeIds };\n }\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/types.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/types.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * KiroGraph Type Definitions\n */\n\nexport type NodeKind =\n | 'file' | 'module' | 'class' | 'struct' | 'interface' | 'trait' | 'protocol'\n | 'function' | 'method' | 'property' | 'field' | 'variable' | 'constant'\n | 'enum' | 'enum_member' | 'type_alias' | 'namespace' | 'parameter'\n | 'import' | 'export' | 'route' | 'component';\n\nexport type EdgeKind =\n | 'contains' | 'calls' | 'imports' | 'exports' | 'extends' | 'implements'\n | 'references' | 'type_of' | 'returns' | 'instantiates' | 'overrides' | 'decorates';\n\nexport type Language =\n | 'typescript' | 'javascript' | 'tsx' | 'jsx' | 'python' | 'go' | 'rust'\n | 'java' | 'c' | 'cpp' | 'csharp' | 'php' | 'ruby' | 'swift' | 'kotlin'\n | 'dart' | 'svelte' | 'pascal' | 'liquid' | 'elixir' | 'unknown';\n\nexport interface Node {\n id: string;\n kind: NodeKind;\n name: string;\n qualifiedName: string;\n filePath: string;\n language: Language;\n startLine: number;\n endLine: number;\n startColumn: number;\n endColumn: number;\n docstring?: string;\n signature?: string;\n visibility?: 'public' | 'private' | 'protected' | 'internal';\n isExported?: boolean;\n isAsync?: boolean;\n isStatic?: boolean;\n isAbstract?: boolean;\n decorators?: string[];\n typeParameters?: string[];\n updatedAt: number;\n}\n\nexport interface Edge {\n source: string;\n target: string;\n kind: EdgeKind;\n metadata?: Record<string, unknown>;\n line?: number;\n column?: number;\n}\n\nexport interface FileRecord {\n path: string;\n contentHash: string;\n language: Language;\n fileSize: number;\n symbolCount: number;\n indexedAt: number;\n}\n\nexport interface SearchResult {\n node: Node;\n score: number;\n matchType: 'exact' | 'prefix' | 'fuzzy' | 'semantic';\n}\n\nexport interface SearchOptions {\n kinds?: NodeKind[];\n languages?: Language[];\n limit?: number;\n minScore?: number;\n}\n\nexport interface Subgraph {\n nodes: Node[];\n edges: Edge[];\n entryPoints: string[];\n}\n\nexport interface NodeContext {\n node: Node;\n ancestors: Node[];\n children: Node[];\n callers: Node[];\n callees: Node[];\n}\n\nexport interface NodeMetrics {\n incomingEdgeCount: number;\n outgoingEdgeCount: number;\n callCount: number;\n callerCount: number;\n childCount: number;\n}\n\nexport interface GraphStats {\n files: number;\n nodes: number;\n edges: number;\n nodesByKind: Record<string, number>;\n filesByLanguage: Record<string, number>;\n dbSizeBytes: number;\n embeddingCount: number;\n embeddableNodeCount: number;\n embeddingsEnabled: boolean;\n embeddingModel: string;\n useVecIndex: boolean;\n semanticEngine: 'cosine' | 'sqlite-vec' | 'orama' | 'pglite' | 'lancedb' | 'qdrant' | 'typesense';\n vecIndexCount: number;\n engineFallback: string | null;\n frameworks: string[];\n architectureEnabled: boolean;\n architectureStats?: { packages: number; layers: number; packageDeps: number };\n}\n\nexport interface TaskContext {\n task: string;\n entryPoints: Node[];\n relatedNodes: Node[];\n edges: Edge[];\n codeSnippets: Map<string, string>;\n summary: string;\n}\n\nexport interface IndexProgress {\n phase: 'scanning' | 'parsing' | 'storing' | 'resolving' | 'detecting frameworks' | 'embeddings' | 'architecture' | 'retrying';\n current: number;\n total: number;\n currentFile?: string;\n meta?: Record<string, unknown>;\n}\n\nexport interface IndexResult {\n success: boolean;\n filesIndexed: number;\n nodesCreated: number;\n edgesCreated: number;\n errors: string[];\n duration: number;\n}\n\nexport interface SyncResult {\n added: string[];\n modified: string[];\n removed: string[];\n nodesCreated: number;\n nodesUpdated: number;\n nodesRemoved: number;\n edgesCreated: number;\n edgesRemoved: number;\n filesScanned: number;\n errors: string[];\n duration: number;\n}\n\n// \u2500\u2500 Error Classes (re-exported from src/errors.ts for backward compatibility) \u2500\u2500\n\nexport {\n KiroGraphError,\n FileError,\n ParseError,\n DatabaseError,\n ConfigError,\n} from './errors';\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph Type Definitions\n */\n\nexport type NodeKind =\n | 'file' | 'module' | 'class' | 'struct' | 'interface' | 'trait' | 'protocol'\n | 'function' | 'method' | 'property' | 'field' | 'variable' | 'constant'\n | 'enum' | 'enum_member' | 'type_alias' | 'namespace' | 'parameter'\n | 'import' | 'export' | 'route' | 'component';\n\nexport type EdgeKind =\n | 'contains' | 'calls' | 'imports' | 'exports' | 'extends' | 'implements'\n | 'references' | 'type_of' | 'returns' | 'instantiates' | 'overrides' | 'decorates';\n\nexport type Language =\n | 'typescript' | 'javascript' | 'tsx' | 'jsx' | 'python' | 'go' | 'rust'\n | 'java' | 'c' | 'cpp' | 'csharp' | 'php' | 'ruby' | 'swift' | 'kotlin'\n | 'dart' | 'svelte' | 'pascal' | 'liquid' | 'elixir'\n | 'scala' | 'lua' | 'zig' | 'bash' | 'ocaml' | 'elm' | 'solidity' | 'vue' | 'objc'\n | 'yaml' | 'hcl' | 'css' | 'scss' | 'html'\n | 'unknown';\n\nexport interface Node {\n id: string;\n kind: NodeKind;\n name: string;\n qualifiedName: string;\n filePath: string;\n language: Language;\n startLine: number;\n endLine: number;\n startColumn: number;\n endColumn: number;\n docstring?: string;\n signature?: string;\n visibility?: 'public' | 'private' | 'protected' | 'internal';\n isExported?: boolean;\n isAsync?: boolean;\n isStatic?: boolean;\n isAbstract?: boolean;\n decorators?: string[];\n typeParameters?: string[];\n updatedAt: number;\n}\n\nexport interface Edge {\n source: string;\n target: string;\n kind: EdgeKind;\n metadata?: Record<string, unknown>;\n line?: number;\n column?: number;\n}\n\nexport interface FileRecord {\n path: string;\n contentHash: string;\n language: Language;\n fileSize: number;\n symbolCount: number;\n indexedAt: number;\n}\n\nexport interface SearchResult {\n node: Node;\n score: number;\n matchType: 'exact' | 'prefix' | 'fuzzy' | 'semantic';\n}\n\nexport interface SearchOptions {\n kinds?: NodeKind[];\n languages?: Language[];\n limit?: number;\n minScore?: number;\n}\n\nexport interface Subgraph {\n nodes: Node[];\n edges: Edge[];\n entryPoints: string[];\n}\n\nexport interface NodeContext {\n node: Node;\n ancestors: Node[];\n children: Node[];\n callers: Node[];\n callees: Node[];\n}\n\nexport interface NodeMetrics {\n incomingEdgeCount: number;\n outgoingEdgeCount: number;\n callCount: number;\n callerCount: number;\n childCount: number;\n}\n\nexport interface GraphStats {\n files: number;\n nodes: number;\n edges: number;\n nodesByKind: Record<string, number>;\n filesByLanguage: Record<string, number>;\n dbSizeBytes: number;\n embeddingCount: number;\n embeddableNodeCount: number;\n embeddingsEnabled: boolean;\n embeddingModel: string;\n useVecIndex: boolean;\n semanticEngine: 'cosine' | 'sqlite-vec' | 'orama' | 'pglite' | 'lancedb' | 'qdrant' | 'typesense';\n vecIndexCount: number;\n engineFallback: string | null;\n frameworks: string[];\n architectureEnabled: boolean;\n architectureStats?: { packages: number; layers: number; packageDeps: number };\n}\n\nexport interface TaskContext {\n task: string;\n entryPoints: Node[];\n relatedNodes: Node[];\n edges: Edge[];\n codeSnippets: Map<string, string>;\n summary: string;\n}\n\nexport interface IndexProgress {\n phase: 'scanning' | 'parsing' | 'storing' | 'resolving' | 'detecting frameworks' | 'embeddings' | 'architecture' | 'retrying';\n current: number;\n total: number;\n currentFile?: string;\n meta?: Record<string, unknown>;\n}\n\nexport interface IndexResult {\n success: boolean;\n filesIndexed: number;\n nodesCreated: number;\n edgesCreated: number;\n errors: string[];\n duration: number;\n}\n\nexport interface SyncResult {\n added: string[];\n modified: string[];\n removed: string[];\n nodesCreated: number;\n nodesUpdated: number;\n nodesRemoved: number;\n edgesCreated: number;\n edgesRemoved: number;\n filesScanned: number;\n errors: string[];\n duration: number;\n}\n\n// \u2500\u2500 Error Classes (re-exported from src/errors.ts for backward compatibility) \u2500\u2500\n\nexport {\n KiroGraphError,\n FileError,\n ParseError,\n DatabaseError,\n ConfigError,\n} from './errors';\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgKA,oBAMO;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED