@anhnguyen02/catlas 0.1.2
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 +59 -0
- package/dist/assembler/context-assembler.d.ts +17 -0
- package/dist/assembler/context-assembler.d.ts.map +1 -0
- package/dist/assembler/context-assembler.js +18 -0
- package/dist/assembler/context-assembler.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +113 -0
- package/dist/cli.js.map +1 -0
- package/dist/detector/project-detector.d.ts +10 -0
- package/dist/detector/project-detector.d.ts.map +1 -0
- package/dist/detector/project-detector.js +171 -0
- package/dist/detector/project-detector.js.map +1 -0
- package/dist/exporter/markdown.d.ts +5 -0
- package/dist/exporter/markdown.d.ts.map +1 -0
- package/dist/exporter/markdown.js +106 -0
- package/dist/exporter/markdown.js.map +1 -0
- package/dist/extractor/ctags-runner.d.ts +8 -0
- package/dist/extractor/ctags-runner.d.ts.map +1 -0
- package/dist/extractor/ctags-runner.js +99 -0
- package/dist/extractor/ctags-runner.js.map +1 -0
- package/dist/extractor/import-graph.d.ts +6 -0
- package/dist/extractor/import-graph.d.ts.map +1 -0
- package/dist/extractor/import-graph.js +127 -0
- package/dist/extractor/import-graph.js.map +1 -0
- package/dist/extractor/module-graph.d.ts +16 -0
- package/dist/extractor/module-graph.d.ts.map +1 -0
- package/dist/extractor/module-graph.js +108 -0
- package/dist/extractor/module-graph.js.map +1 -0
- package/dist/ranker/priority-ranker.d.ts +15 -0
- package/dist/ranker/priority-ranker.d.ts.map +1 -0
- package/dist/ranker/priority-ranker.js +49 -0
- package/dist/ranker/priority-ranker.js.map +1 -0
- package/dist/scanner/file-classifier.d.ts +9 -0
- package/dist/scanner/file-classifier.d.ts.map +1 -0
- package/dist/scanner/file-classifier.js +21 -0
- package/dist/scanner/file-classifier.js.map +1 -0
- package/dist/scanner/role-detector.d.ts +9 -0
- package/dist/scanner/role-detector.d.ts.map +1 -0
- package/dist/scanner/role-detector.js +39 -0
- package/dist/scanner/role-detector.js.map +1 -0
- package/dist/scanner/tree-builder.d.ts +8 -0
- package/dist/scanner/tree-builder.d.ts.map +1 -0
- package/dist/scanner/tree-builder.js +13 -0
- package/dist/scanner/tree-builder.js.map +1 -0
- package/dist/scanner/tree-walker.d.ts +7 -0
- package/dist/scanner/tree-walker.d.ts.map +1 -0
- package/dist/scanner/tree-walker.js +43 -0
- package/dist/scanner/tree-walker.js.map +1 -0
- package/dist/types.d.ts +34 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cache.d.ts +18 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +50 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/diff.d.ts +10 -0
- package/dist/utils/diff.d.ts.map +1 -0
- package/dist/utils/diff.js +43 -0
- package/dist/utils/diff.js.map +1 -0
- package/dist/utils/gitignore.d.ts +9 -0
- package/dist/utils/gitignore.d.ts.map +1 -0
- package/dist/utils/gitignore.js +35 -0
- package/dist/utils/gitignore.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +33 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import { log } from '../utils/logger.js';
|
|
5
|
+
export class CtagsRunner {
|
|
6
|
+
ctagsPath;
|
|
7
|
+
constructor() {
|
|
8
|
+
this.ctagsPath = this.findCtags();
|
|
9
|
+
}
|
|
10
|
+
findCtags() {
|
|
11
|
+
// macOS Homebrew paths (ARM and Intel)
|
|
12
|
+
const brewPaths = ['/opt/homebrew/bin/ctags', '/usr/local/bin/ctags'];
|
|
13
|
+
if (os.platform() === 'darwin') {
|
|
14
|
+
for (const p of brewPaths) {
|
|
15
|
+
if (fs.existsSync(p))
|
|
16
|
+
return p;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return 'ctags';
|
|
20
|
+
}
|
|
21
|
+
extract(fileDataList, rootDir) {
|
|
22
|
+
const files = fileDataList.map(f => f.path);
|
|
23
|
+
if (files.length === 0)
|
|
24
|
+
return;
|
|
25
|
+
// Run ctags:
|
|
26
|
+
// --output-format=json: Easy to parse
|
|
27
|
+
// --fields=+nKZS: n=line, K=long kind, Z=scope, S=signature
|
|
28
|
+
// Language-specific kinds to extract
|
|
29
|
+
const baseArgs = [
|
|
30
|
+
'--output-format=json',
|
|
31
|
+
'--fields=+nKZS',
|
|
32
|
+
'--kinds-TypeScript=fcima', // function, class, interface, method, alias
|
|
33
|
+
'--kinds-JavaScript=fcm', // function, class, method
|
|
34
|
+
'--kinds-Python=fcm', // function, class, method
|
|
35
|
+
'--kinds-Go=fstim', // function, struct, type, interface, method
|
|
36
|
+
'--kinds-Rust=fstPim', // function, struct, type, implementation, method
|
|
37
|
+
'--kinds-Java=cim', // class, interface, method
|
|
38
|
+
'--kinds-Kotlin=cim' // class, interface, method
|
|
39
|
+
];
|
|
40
|
+
const CHUNK_SIZE = 200;
|
|
41
|
+
const lines = [];
|
|
42
|
+
for (let i = 0; i < files.length; i += CHUNK_SIZE) {
|
|
43
|
+
const chunk = files.slice(i, i + CHUNK_SIZE);
|
|
44
|
+
const args = [...baseArgs, ...chunk];
|
|
45
|
+
const result = spawnSync(this.ctagsPath, args, { cwd: rootDir, encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 });
|
|
46
|
+
if (result.error || result.status !== 0) {
|
|
47
|
+
const errMsg = result.error ? result.error.message : `Process exited with status ${result.status}`;
|
|
48
|
+
log('warn', `Failed to run ctags cleanly. Error: ${errMsg}`);
|
|
49
|
+
if (result.error)
|
|
50
|
+
return; // stop if totally missing
|
|
51
|
+
}
|
|
52
|
+
lines.push(...result.stdout.split('\n').filter(l => l.trim()));
|
|
53
|
+
}
|
|
54
|
+
// Group symbols by file path
|
|
55
|
+
const symbolsByFile = new Map();
|
|
56
|
+
for (const line of lines) {
|
|
57
|
+
if (!line.startsWith('{'))
|
|
58
|
+
continue;
|
|
59
|
+
try {
|
|
60
|
+
const tag = JSON.parse(line);
|
|
61
|
+
// Skip local scope variables/functions if possible (ctags 'scope' field helps)
|
|
62
|
+
// If it has a "scope" and scopeKind is "function", it's a local closure/variable. Skip.
|
|
63
|
+
if (tag.scopeKind === 'function' || tag.scopeKind === 'method') {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// Safely determine kind
|
|
67
|
+
const validKinds = ['function', 'class', 'interface', 'type', 'variable', 'method', 'component', 'alias', 'constant', 'unknown'];
|
|
68
|
+
const kind = validKinds.includes(tag.kind) ? tag.kind : 'unknown';
|
|
69
|
+
// Basic heuristic for isExported (ctags may provide access: 'public' or roles string)
|
|
70
|
+
const isExported = tag.access === 'public' || (tag.roles && tag.roles.includes('exported')) || false;
|
|
71
|
+
const sym = {
|
|
72
|
+
name: tag.name,
|
|
73
|
+
kind,
|
|
74
|
+
signature: tag.signature || '',
|
|
75
|
+
line: tag.line || 0,
|
|
76
|
+
isExported,
|
|
77
|
+
fileRole: 'unknown',
|
|
78
|
+
path: tag.path,
|
|
79
|
+
inDegree: 0
|
|
80
|
+
};
|
|
81
|
+
if (!symbolsByFile.has(tag.path)) {
|
|
82
|
+
symbolsByFile.set(tag.path, []);
|
|
83
|
+
}
|
|
84
|
+
symbolsByFile.get(tag.path).push(sym);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
// ignore malformed json lines
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Attach back to FileData
|
|
91
|
+
for (const fd of fileDataList) {
|
|
92
|
+
const syms = symbolsByFile.get(fd.path) || [];
|
|
93
|
+
// set file role to the symbol
|
|
94
|
+
syms.forEach(s => s.fileRole = fd.role);
|
|
95
|
+
fd.symbols = syms;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=ctags-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ctags-runner.js","sourceRoot":"","sources":["../../src/extractor/ctags-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-graph.d.ts","sourceRoot":"","sources":["../../src/extractor/import-graph.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,qBAAa,WAAW;IACf,KAAK,CAAC,YAAY,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IA+E/E,OAAO,CAAC,YAAY;CAiDrB"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export class ImportGraph {
|
|
4
|
+
build(fileDataList, language, rootDir) {
|
|
5
|
+
const importMap = new Map(); // path -> array of imported relative paths
|
|
6
|
+
const inDegreeMap = new Map();
|
|
7
|
+
// Initialize inDegree map for all known files
|
|
8
|
+
fileDataList.forEach(fd => inDegreeMap.set(fd.path, 0));
|
|
9
|
+
// Pre-calculate stripped paths to avoid regex inside the loop
|
|
10
|
+
const strippedPaths = fileDataList.map(f => ({
|
|
11
|
+
path: f.path,
|
|
12
|
+
stripped: f.path.replace(/\.[a-z]+$/, '')
|
|
13
|
+
}));
|
|
14
|
+
// Fast exact match lookup
|
|
15
|
+
const exactLookup = new Map();
|
|
16
|
+
for (const f of strippedPaths) {
|
|
17
|
+
exactLookup.set(f.stripped, f.path);
|
|
18
|
+
exactLookup.set(`${f.stripped}/index`, f.path);
|
|
19
|
+
}
|
|
20
|
+
// 1. Parse imports
|
|
21
|
+
for (const fd of fileDataList) {
|
|
22
|
+
const content = fs.readFileSync(path.join(rootDir, fd.path), 'utf-8');
|
|
23
|
+
const imports = this.parseImports(content, language);
|
|
24
|
+
fd.imports = imports;
|
|
25
|
+
const dir = path.dirname(fd.path);
|
|
26
|
+
const resolvedImports = [];
|
|
27
|
+
for (const imp of imports) {
|
|
28
|
+
let resolvedPath = '';
|
|
29
|
+
let isAbsolute = false;
|
|
30
|
+
if (imp.startsWith('.')) {
|
|
31
|
+
let normalizedImp = imp;
|
|
32
|
+
if (language === 'python' && imp.match(/^\.+[a-zA-Z0-9_]/)) {
|
|
33
|
+
normalizedImp = imp.replace(/^(\.+)(.*)$/, (m, dots, rest) => {
|
|
34
|
+
if (dots.length === 1)
|
|
35
|
+
return `./${rest}`;
|
|
36
|
+
return '../'.repeat(dots.length - 1) + rest;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
resolvedPath = path.posix.join(dir, normalizedImp).replace(/\\/g, '/');
|
|
40
|
+
}
|
|
41
|
+
else if (imp.startsWith('~/') || imp.startsWith('@/')) {
|
|
42
|
+
resolvedPath = imp.substring(2);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// absolute or node_module. Ex: python domain.models
|
|
46
|
+
resolvedPath = imp.replace(/\./g, '/');
|
|
47
|
+
isAbsolute = true;
|
|
48
|
+
}
|
|
49
|
+
// Drop extensions or try to match exactly
|
|
50
|
+
const rp = resolvedPath.replace(/\.[a-z]+$/, '');
|
|
51
|
+
let matchPath = exactLookup.get(rp);
|
|
52
|
+
if (!matchPath && isAbsolute) {
|
|
53
|
+
// Fallback to suffix matching for absolute imports (e.g. Python imports missing src/ prefix)
|
|
54
|
+
const target = strippedPaths.find(f => {
|
|
55
|
+
return f.stripped.endsWith(`/${rp}`) || f.stripped.endsWith(`/${rp}/index`);
|
|
56
|
+
});
|
|
57
|
+
if (target)
|
|
58
|
+
matchPath = target.path;
|
|
59
|
+
}
|
|
60
|
+
if (matchPath) {
|
|
61
|
+
resolvedImports.push(matchPath);
|
|
62
|
+
// Increment in-degree
|
|
63
|
+
inDegreeMap.set(matchPath, (inDegreeMap.get(matchPath) || 0) + 1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
importMap.set(fd.path, resolvedImports);
|
|
67
|
+
}
|
|
68
|
+
// 2. Attach inDegree
|
|
69
|
+
for (const fd of fileDataList) {
|
|
70
|
+
fd.inDegree = inDegreeMap.get(fd.path) || 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
parseImports(rawContent, language) {
|
|
74
|
+
// Strip comments to prevent false positive regex matches on strings/comments
|
|
75
|
+
const content = rawContent.replace(/\/\*[\s\S]*?\*\/|\/\/.*|#.*/g, '');
|
|
76
|
+
const imports = [];
|
|
77
|
+
if (language === 'typescript' || language === 'javascript') {
|
|
78
|
+
const es6Regex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/gs;
|
|
79
|
+
const exportRegex = /export\s+.*?\s+from\s+['"]([^'"]+)['"]/gs;
|
|
80
|
+
// side-effect imports: import 'y'
|
|
81
|
+
const sideEffectRegex = /import\s+['"]([^'"]+)['"]/g;
|
|
82
|
+
// dynamic imports: import('y')
|
|
83
|
+
const dynRegex = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
84
|
+
let match;
|
|
85
|
+
while ((match = es6Regex.exec(content)) !== null)
|
|
86
|
+
imports.push(match[1]);
|
|
87
|
+
while ((match = exportRegex.exec(content)) !== null)
|
|
88
|
+
imports.push(match[1]);
|
|
89
|
+
while ((match = sideEffectRegex.exec(content)) !== null)
|
|
90
|
+
imports.push(match[1]);
|
|
91
|
+
while ((match = dynRegex.exec(content)) !== null)
|
|
92
|
+
imports.push(match[1]);
|
|
93
|
+
}
|
|
94
|
+
else if (language === 'python') {
|
|
95
|
+
// from x import y
|
|
96
|
+
const pyRegex1 = /from\s+([^\s]+)\s+import/g;
|
|
97
|
+
// import x (only at start of line or after semicolon, to avoid matching 'from x import y')
|
|
98
|
+
const pyRegex2 = /(?:^|[\n;])\s*import\s+([^\r\n]+)/g;
|
|
99
|
+
let match;
|
|
100
|
+
while ((match = pyRegex1.exec(content)) !== null)
|
|
101
|
+
imports.push(match[1]);
|
|
102
|
+
while ((match = pyRegex2.exec(content)) !== null) {
|
|
103
|
+
const modules = match[1].split(',').map(m => m.trim().split(/\s+as\s+/)[0].trim());
|
|
104
|
+
imports.push(...modules);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else if (language === 'go') {
|
|
108
|
+
// Single import: import "fmt"
|
|
109
|
+
const goSingleRegex = /import\s+"([^"]+)"/g;
|
|
110
|
+
// Grouped import: import ( "fmt"\n "net/http" )
|
|
111
|
+
const goGroupRegex = /import\s*\(\s*([\s\S]*?)\)/g;
|
|
112
|
+
let match;
|
|
113
|
+
while ((match = goSingleRegex.exec(content)) !== null)
|
|
114
|
+
imports.push(match[1]);
|
|
115
|
+
while ((match = goGroupRegex.exec(content)) !== null) {
|
|
116
|
+
const block = match[1];
|
|
117
|
+
const lineRegex = /"([^"]+)"/g;
|
|
118
|
+
let lineMatch;
|
|
119
|
+
while ((lineMatch = lineRegex.exec(block)) !== null)
|
|
120
|
+
imports.push(lineMatch[1]);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Ensure uniqueness
|
|
124
|
+
return [...new Set(imports)];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=import-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-graph.js","sourceRoot":"","sources":["../../src/extractor/import-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FileData, ModuleNode } from '../types.js';
|
|
2
|
+
export declare class ModuleGraph {
|
|
3
|
+
/**
|
|
4
|
+
* Build a module-level (directory-level) dependency graph.
|
|
5
|
+
* Aggregates file-level import relationships into directory-level dependencies.
|
|
6
|
+
* This shows the high-level architecture: which modules depend on which.
|
|
7
|
+
*/
|
|
8
|
+
build(fileDataList: FileData[]): ModuleNode[];
|
|
9
|
+
/**
|
|
10
|
+
* Get the module directory for a file path.
|
|
11
|
+
* Uses first 2 segments as grouping key (e.g., "server/api" for "server/api/payment.ts").
|
|
12
|
+
* Root-level files get "." as their module.
|
|
13
|
+
*/
|
|
14
|
+
private getModuleDir;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=module-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-graph.d.ts","sourceRoot":"","sources":["../../src/extractor/module-graph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAEvD,qBAAa,WAAW;IACtB;;;;OAIG;IACI,KAAK,CAAC,YAAY,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE;IAqGpD;;;;OAIG;IACH,OAAO,CAAC,YAAY;CAMrB"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
export class ModuleGraph {
|
|
3
|
+
/**
|
|
4
|
+
* Build a module-level (directory-level) dependency graph.
|
|
5
|
+
* Aggregates file-level import relationships into directory-level dependencies.
|
|
6
|
+
* This shows the high-level architecture: which modules depend on which.
|
|
7
|
+
*/
|
|
8
|
+
build(fileDataList) {
|
|
9
|
+
// Map: module path → set of modules it depends on
|
|
10
|
+
const dependsOnMap = new Map();
|
|
11
|
+
// Map: module path → file count
|
|
12
|
+
const fileCountMap = new Map();
|
|
13
|
+
// 1. Count files per module and collect dependencies
|
|
14
|
+
for (const fd of fileDataList) {
|
|
15
|
+
const moduleDir = this.getModuleDir(fd.path);
|
|
16
|
+
fileCountMap.set(moduleDir, (fileCountMap.get(moduleDir) || 0) + 1);
|
|
17
|
+
if (!dependsOnMap.has(moduleDir)) {
|
|
18
|
+
dependsOnMap.set(moduleDir, new Set());
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// 1.5 Pre-calculate lookups for fast import resolution
|
|
22
|
+
const strippedPaths = fileDataList.map(f => ({
|
|
23
|
+
path: f.path,
|
|
24
|
+
stripped: f.path.replace(/\.[a-z]+$/, '')
|
|
25
|
+
}));
|
|
26
|
+
const exactLookup = new Map();
|
|
27
|
+
for (const f of strippedPaths) {
|
|
28
|
+
exactLookup.set(f.stripped, f.path);
|
|
29
|
+
exactLookup.set(`${f.stripped}/index`, f.path);
|
|
30
|
+
}
|
|
31
|
+
// 2. Resolve imports to module-level dependencies
|
|
32
|
+
for (const fd of fileDataList) {
|
|
33
|
+
const sourceModule = this.getModuleDir(fd.path);
|
|
34
|
+
const deps = dependsOnMap.get(sourceModule);
|
|
35
|
+
for (const imp of fd.imports) {
|
|
36
|
+
let resolvedPath = '';
|
|
37
|
+
let isAbsolute = false;
|
|
38
|
+
if (imp.startsWith('.')) {
|
|
39
|
+
resolvedPath = path.posix.join(path.dirname(fd.path), imp).replace(/\\/g, '/');
|
|
40
|
+
}
|
|
41
|
+
else if (imp.startsWith('~/') || imp.startsWith('@/')) {
|
|
42
|
+
resolvedPath = imp.substring(2);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
resolvedPath = imp.replace(/\./g, '/');
|
|
46
|
+
isAbsolute = true;
|
|
47
|
+
}
|
|
48
|
+
const rp = resolvedPath.replace(/\.[a-z]+$/, '');
|
|
49
|
+
let targetPath = exactLookup.get(rp);
|
|
50
|
+
if (!targetPath && isAbsolute) {
|
|
51
|
+
const target = strippedPaths.find(f => f.stripped.endsWith(`/${rp}`) || f.stripped.endsWith(`/${rp}/index`));
|
|
52
|
+
if (target)
|
|
53
|
+
targetPath = target.path;
|
|
54
|
+
}
|
|
55
|
+
if (targetPath) {
|
|
56
|
+
const targetModule = this.getModuleDir(targetPath);
|
|
57
|
+
// Skip self-references (same module)
|
|
58
|
+
if (targetModule !== sourceModule) {
|
|
59
|
+
deps.add(targetModule);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// 3. Build reverse map (dependedBy)
|
|
65
|
+
const dependedByMap = new Map();
|
|
66
|
+
for (const moduleDir of dependsOnMap.keys()) {
|
|
67
|
+
dependedByMap.set(moduleDir, new Set());
|
|
68
|
+
}
|
|
69
|
+
for (const [moduleDir, deps] of dependsOnMap) {
|
|
70
|
+
for (const dep of deps) {
|
|
71
|
+
if (!dependedByMap.has(dep)) {
|
|
72
|
+
dependedByMap.set(dep, new Set());
|
|
73
|
+
}
|
|
74
|
+
dependedByMap.get(dep).add(moduleDir);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// 4. Build ModuleNode list (only modules with dependencies)
|
|
78
|
+
const nodes = [];
|
|
79
|
+
for (const [moduleDir, deps] of dependsOnMap) {
|
|
80
|
+
const dependedBy = dependedByMap.get(moduleDir) || new Set();
|
|
81
|
+
// Only include modules that have relationships
|
|
82
|
+
if (deps.size > 0 || dependedBy.size > 0) {
|
|
83
|
+
nodes.push({
|
|
84
|
+
path: moduleDir,
|
|
85
|
+
fileCount: fileCountMap.get(moduleDir) || 0,
|
|
86
|
+
dependsOn: [...deps].sort(),
|
|
87
|
+
dependedBy: [...dependedBy].sort(),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Sort by most depended-on first
|
|
92
|
+
nodes.sort((a, b) => b.dependedBy.length - a.dependedBy.length);
|
|
93
|
+
return nodes;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get the module directory for a file path.
|
|
97
|
+
* Uses first 2 segments as grouping key (e.g., "server/api" for "server/api/payment.ts").
|
|
98
|
+
* Root-level files get "." as their module.
|
|
99
|
+
*/
|
|
100
|
+
getModuleDir(filePath) {
|
|
101
|
+
const dir = path.dirname(filePath);
|
|
102
|
+
if (dir === '.')
|
|
103
|
+
return '.';
|
|
104
|
+
const segments = dir.split('/');
|
|
105
|
+
return segments.length <= 2 ? dir : segments.slice(0, 2).join('/');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=module-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-graph.js","sourceRoot":"","sources":["../../src/extractor/module-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { FileData, ExtractedSymbol } from '../types.js';
|
|
2
|
+
export declare class PriorityRanker {
|
|
3
|
+
private readonly FILE_BUDGET;
|
|
4
|
+
private readonly SYMBOL_BUDGET;
|
|
5
|
+
/**
|
|
6
|
+
* Rank and return the top most-imported files.
|
|
7
|
+
*/
|
|
8
|
+
rankFiles(fileDataList: FileData[]): FileData[];
|
|
9
|
+
/**
|
|
10
|
+
* Rank and return the top most-impactful symbols.
|
|
11
|
+
* Focuses on exported functions, classes, interfaces from high-impact files.
|
|
12
|
+
*/
|
|
13
|
+
rankSymbols(fileDataList: FileData[]): ExtractedSymbol[];
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=priority-ranker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"priority-ranker.d.ts","sourceRoot":"","sources":["../../src/ranker/priority-ranker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE5D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAK;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAM;IAEpC;;OAEG;IACI,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE;IAOtD;;;OAGG;IACI,WAAW,CAAC,YAAY,EAAE,QAAQ,EAAE,GAAG,eAAe,EAAE;CAkChE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export class PriorityRanker {
|
|
2
|
+
FILE_BUDGET = 30;
|
|
3
|
+
SYMBOL_BUDGET = 100;
|
|
4
|
+
/**
|
|
5
|
+
* Rank and return the top most-imported files.
|
|
6
|
+
*/
|
|
7
|
+
rankFiles(fileDataList) {
|
|
8
|
+
return [...fileDataList]
|
|
9
|
+
.filter(fd => fd.inDegree >= 1)
|
|
10
|
+
.sort((a, b) => b.inDegree - a.inDegree)
|
|
11
|
+
.slice(0, this.FILE_BUDGET);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Rank and return the top most-impactful symbols.
|
|
15
|
+
* Focuses on exported functions, classes, interfaces from high-impact files.
|
|
16
|
+
*/
|
|
17
|
+
rankSymbols(fileDataList) {
|
|
18
|
+
const keptSymbols = [];
|
|
19
|
+
for (const fd of fileDataList) {
|
|
20
|
+
// Keep files with at least 1 importer, or api-route handlers (always kept)
|
|
21
|
+
const isExempt = fd.role === 'api-route' || fd.role === 'entry';
|
|
22
|
+
if (!isExempt && fd.inDegree < 1)
|
|
23
|
+
continue;
|
|
24
|
+
for (const sym of fd.symbols) {
|
|
25
|
+
// Only keep high-value symbol kinds
|
|
26
|
+
const validKinds = ['function', 'class', 'interface', 'type', 'method', 'alias', 'component'];
|
|
27
|
+
if (!validKinds.includes(sym.kind) && sym.kind !== 'constant' && sym.kind !== 'variable') {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
// Skip noise
|
|
31
|
+
if (sym.name.startsWith('_') || sym.name.toLowerCase().includes('helper')) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const clonedSym = { ...sym, inDegree: fd.inDegree };
|
|
35
|
+
keptSymbols.push({ sym: clonedSym, inDegree: fd.inDegree, isExempt });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Sort: exempt (api-routes) first, then by in-degree descending
|
|
39
|
+
keptSymbols.sort((a, b) => {
|
|
40
|
+
if (a.isExempt && !b.isExempt)
|
|
41
|
+
return -1;
|
|
42
|
+
if (!a.isExempt && b.isExempt)
|
|
43
|
+
return 1;
|
|
44
|
+
return b.inDegree - a.inDegree;
|
|
45
|
+
});
|
|
46
|
+
return keptSymbols.slice(0, this.SYMBOL_BUDGET).map(item => item.sym);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=priority-ranker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"priority-ranker.js","sourceRoot":"","sources":["../../src/ranker/priority-ranker.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,cAAc;IACR,WAAW,GAAG,EAAE,CAAA;IAChB,aAAa,GAAG,GAAG,CAAA;IAEpC;;OAEG;IACI,SAAS,CAAC,YAAwB;QACvC,OAAO,CAAC,GAAG,YAAY,CAAC;aACrB,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,IAAI,CAAC,CAAC;aAC9B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC;aACvC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;IAC/B,CAAC;IAED;;;OAGG;IACI,WAAW,CAAC,YAAwB;QACzC,MAAM,WAAW,GAAyE,EAAE,CAAA;QAE5F,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;YAC9B,2EAA2E;YAC3E,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,KAAK,WAAW,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO,CAAA;YAC/D,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,QAAQ,GAAG,CAAC;gBAAE,SAAQ;YAE1C,KAAK,MAAM,GAAG,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;gBAC7B,oCAAoC;gBACpC,MAAM,UAAU,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,CAAA;gBAC7F,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oBACzF,SAAQ;gBACV,CAAC;gBAED,aAAa;gBACb,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC1E,SAAQ;gBACV,CAAC;gBAED,MAAM,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAA;gBACnD,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAA;YACvE,CAAC;QACH,CAAC;QAED,gEAAgE;QAChE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACxB,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,QAAQ;gBAAE,OAAO,CAAC,CAAC,CAAA;YACxC,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ;gBAAE,OAAO,CAAC,CAAA;YACvC,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAA;QAChC,CAAC,CAAC,CAAA;QAEF,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACvE,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FileRole, ProjectProfile } from '../types.js';
|
|
2
|
+
export declare class FileClassifier {
|
|
3
|
+
private matchers;
|
|
4
|
+
constructor(profile: ProjectProfile);
|
|
5
|
+
classify(filePath: string): {
|
|
6
|
+
role: FileRole;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=file-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-classifier.d.ts","sourceRoot":"","sources":["../../src/scanner/file-classifier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE3D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAuE;gBAE3E,OAAO,EAAE,cAAc;IAS5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE;CAQtD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import picomatch from 'picomatch';
|
|
2
|
+
export class FileClassifier {
|
|
3
|
+
matchers = [];
|
|
4
|
+
constructor(profile) {
|
|
5
|
+
for (const [pattern, role] of Object.entries(profile.rolePatterns)) {
|
|
6
|
+
this.matchers.push({
|
|
7
|
+
matcher: picomatch(pattern),
|
|
8
|
+
role
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
classify(filePath) {
|
|
13
|
+
for (const { matcher, role } of this.matchers) {
|
|
14
|
+
if (matcher(filePath)) {
|
|
15
|
+
return { role };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return { role: 'unknown' };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=file-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-classifier.js","sourceRoot":"","sources":["../../src/scanner/file-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAA;AAGjC,MAAM,OAAO,cAAc;IACjB,QAAQ,GAAqE,EAAE,CAAA;IAEvF,YAAY,OAAuB;QACjC,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YACnE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACjB,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC;gBAC3B,IAAI;aACL,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAEM,QAAQ,CAAC,QAAgB;QAC9B,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9C,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtB,OAAO,EAAE,IAAI,EAAE,CAAA;YACjB,CAAC;QACH,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FileRole } from '../types.js';
|
|
2
|
+
export declare class RoleDetector {
|
|
3
|
+
/**
|
|
4
|
+
* Classify a file's role based on its path using generic heuristics.
|
|
5
|
+
* Works for any language/framework — no hardcoded convention files.
|
|
6
|
+
*/
|
|
7
|
+
classify(filePath: string): FileRole;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=role-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-detector.d.ts","sourceRoot":"","sources":["../../src/scanner/role-detector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AA2B3C,qBAAa,YAAY;IACvB;;;OAGG;IACI,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ;CAQ5C"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const ROLE_PATTERNS = [
|
|
2
|
+
// Entry points
|
|
3
|
+
{ test: /^(app|main|index)\.(ts|js|tsx|jsx|vue|py|go|rs|kt|java)$/, role: 'entry' },
|
|
4
|
+
// Config files
|
|
5
|
+
{ test: /\.config\.(ts|js|mjs|cjs)$/, role: 'config' },
|
|
6
|
+
{ test: /^(tsconfig|vite\.config|nuxt\.config|next\.config|webpack\.config|jest\.config|vitest\.config)/, role: 'config' },
|
|
7
|
+
{ test: /^config\//, role: 'config' },
|
|
8
|
+
// API routes / handlers
|
|
9
|
+
{ test: /\b(api|routes|endpoints|handlers|controllers)\b\/.*\.(ts|js|tsx|py|go|rs|kt|java)$/, role: 'api-route' },
|
|
10
|
+
// Pages / views
|
|
11
|
+
{ test: /\b(pages|views)\b\//, role: 'page' },
|
|
12
|
+
// Components
|
|
13
|
+
{ test: /\b(components)\b\//, role: 'component' },
|
|
14
|
+
// Services / business logic
|
|
15
|
+
{ test: /\b(services|common|domain|usecases|use-cases)\b\//, role: 'service' },
|
|
16
|
+
// Composables / hooks
|
|
17
|
+
{ test: /\b(composables|hooks)\b\//, role: 'composable' },
|
|
18
|
+
// Repository / data layer
|
|
19
|
+
{ test: /\b(repositories|repos|models|entities|dal|database|db)\b\//, role: 'repository' },
|
|
20
|
+
// Internal
|
|
21
|
+
{ test: /\b(internal|__internal__|private)\b\//, role: 'internal' },
|
|
22
|
+
// Utilities
|
|
23
|
+
{ test: /\b(utils|helpers|lib|shared|pkg|support)\b\//, role: 'util' },
|
|
24
|
+
];
|
|
25
|
+
export class RoleDetector {
|
|
26
|
+
/**
|
|
27
|
+
* Classify a file's role based on its path using generic heuristics.
|
|
28
|
+
* Works for any language/framework — no hardcoded convention files.
|
|
29
|
+
*/
|
|
30
|
+
classify(filePath) {
|
|
31
|
+
for (const { test, role } of ROLE_PATTERNS) {
|
|
32
|
+
if (test.test(filePath)) {
|
|
33
|
+
return role;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return 'unknown';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=role-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-detector.js","sourceRoot":"","sources":["../../src/scanner/role-detector.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa,GAA4C;IAC7D,eAAe;IACf,EAAE,IAAI,EAAE,0DAA0D,EAAE,IAAI,EAAE,OAAO,EAAE;IACnF,eAAe;IACf,EAAE,IAAI,EAAE,4BAA4B,EAAE,IAAI,EAAE,QAAQ,EAAE;IACtD,EAAE,IAAI,EAAE,gGAAgG,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC1H,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE;IACrC,wBAAwB;IACxB,EAAE,IAAI,EAAE,oFAAoF,EAAE,IAAI,EAAE,WAAW,EAAE;IACjH,gBAAgB;IAChB,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,MAAM,EAAE;IAC7C,aAAa;IACb,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,WAAW,EAAE;IACjD,4BAA4B;IAC5B,EAAE,IAAI,EAAE,mDAAmD,EAAE,IAAI,EAAE,SAAS,EAAE;IAC9E,sBAAsB;IACtB,EAAE,IAAI,EAAE,2BAA2B,EAAE,IAAI,EAAE,YAAY,EAAE;IACzD,0BAA0B;IAC1B,EAAE,IAAI,EAAE,4DAA4D,EAAE,IAAI,EAAE,YAAY,EAAE;IAC1F,WAAW;IACX,EAAE,IAAI,EAAE,uCAAuC,EAAE,IAAI,EAAE,UAAU,EAAE;IACnE,YAAY;IACZ,EAAE,IAAI,EAAE,8CAA8C,EAAE,IAAI,EAAE,MAAM,EAAE;CACvE,CAAA;AAED,MAAM,OAAO,YAAY;IACvB;;;OAGG;IACI,QAAQ,CAAC,QAAgB;QAC9B,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,aAAa,EAAE,CAAC;YAC3C,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACxB,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAA;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class TreeBuilder {
|
|
2
|
+
/**
|
|
3
|
+
* Build a complete, unrolled list of all file paths.
|
|
4
|
+
* This provides an exact "X-Ray" mapping so AI agents can target files precisely.
|
|
5
|
+
*/
|
|
6
|
+
build(filePaths: string[]): string;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=tree-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-builder.d.ts","sourceRoot":"","sources":["../../src/scanner/tree-builder.ts"],"names":[],"mappings":"AAEA,qBAAa,WAAW;IACtB;;;OAGG;IACI,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM;CAM1C"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class TreeBuilder {
|
|
2
|
+
/**
|
|
3
|
+
* Build a complete, unrolled list of all file paths.
|
|
4
|
+
* This provides an exact "X-Ray" mapping so AI agents can target files precisely.
|
|
5
|
+
*/
|
|
6
|
+
build(filePaths) {
|
|
7
|
+
return filePaths
|
|
8
|
+
.slice()
|
|
9
|
+
.sort((a, b) => a.localeCompare(b))
|
|
10
|
+
.join('\n');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=tree-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-builder.js","sourceRoot":"","sources":["../../src/scanner/tree-builder.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,WAAW;IACtB;;;OAGG;IACI,KAAK,CAAC,SAAmB;QAC9B,OAAO,SAAS;aACb,KAAK,EAAE;aACP,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;aAClC,IAAI,CAAC,IAAI,CAAC,CAAA;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-walker.d.ts","sourceRoot":"","sources":["../../src/scanner/tree-walker.ts"],"names":[],"mappings":"AAIA,qBAAa,UAAU;IACrB,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,OAAO,CAAQ;gBAEX,OAAO,EAAE,MAAM;IAYpB,IAAI,CAAC,GAAG,GAAE,MAAqB,GAAG,MAAM,EAAE;CA8BlD"}
|