arcvision 0.2.1 → 0.2.3
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/arcvision.context.json +479 -47
- package/dist/index.js +1105 -21
- package/package.json +1 -1
- package/scan_output.txt +0 -0
- package/src/core/di-detector.js +202 -0
- package/src/core/method-tracker.js +174 -0
- package/src/core/parser-enhanced.js +73 -0
- package/src/core/parser.js +1 -1
- package/src/core/path-resolver.js +1 -1
- package/src/core/react-nextjs-detector.js +245 -0
- package/src/core/scanner.js +327 -42
- package/src/core/semantic-analyzer.js +204 -0
- package/src/core/type-analyzer.js +272 -0
- package/src/engine/context_builder.js +49 -18
- package/src/plugins/plugin-manager.js +2 -1
package/dist/index.js
CHANGED
|
@@ -56569,6 +56569,692 @@ var require_parser = __commonJS({
|
|
|
56569
56569
|
}
|
|
56570
56570
|
});
|
|
56571
56571
|
|
|
56572
|
+
// src/core/di-detector.js
|
|
56573
|
+
var require_di_detector = __commonJS({
|
|
56574
|
+
"src/core/di-detector.js"(exports2, module2) {
|
|
56575
|
+
var traverse = require_lib8().default;
|
|
56576
|
+
function detectConstructorInjection(ast) {
|
|
56577
|
+
const injections = [];
|
|
56578
|
+
traverse(ast, {
|
|
56579
|
+
ClassDeclaration(path2) {
|
|
56580
|
+
const className = path2.node.id ? path2.node.id.name : "Anonymous";
|
|
56581
|
+
const constructor = path2.node.body.body.find(
|
|
56582
|
+
(member) => member.kind === "constructor"
|
|
56583
|
+
);
|
|
56584
|
+
if (constructor && constructor.params) {
|
|
56585
|
+
constructor.params.forEach((param) => {
|
|
56586
|
+
let paramName = null;
|
|
56587
|
+
let paramType = null;
|
|
56588
|
+
if (param.type === "TSParameterProperty") {
|
|
56589
|
+
if (param.parameter.type === "Identifier") {
|
|
56590
|
+
paramName = param.parameter.name;
|
|
56591
|
+
if (param.parameter.typeAnnotation) {
|
|
56592
|
+
paramType = extractTypeName(param.parameter.typeAnnotation);
|
|
56593
|
+
}
|
|
56594
|
+
}
|
|
56595
|
+
} else if (param.type === "Identifier") {
|
|
56596
|
+
paramName = param.name;
|
|
56597
|
+
if (param.typeAnnotation) {
|
|
56598
|
+
paramType = extractTypeName(param.typeAnnotation);
|
|
56599
|
+
}
|
|
56600
|
+
}
|
|
56601
|
+
if (paramName) {
|
|
56602
|
+
injections.push({
|
|
56603
|
+
className,
|
|
56604
|
+
paramName,
|
|
56605
|
+
paramType,
|
|
56606
|
+
pattern: "constructor_injection",
|
|
56607
|
+
loc: constructor.loc
|
|
56608
|
+
});
|
|
56609
|
+
}
|
|
56610
|
+
});
|
|
56611
|
+
}
|
|
56612
|
+
}
|
|
56613
|
+
});
|
|
56614
|
+
return injections;
|
|
56615
|
+
}
|
|
56616
|
+
function detectReactContextUsage(ast) {
|
|
56617
|
+
const contextUsages = [];
|
|
56618
|
+
traverse(ast, {
|
|
56619
|
+
// Detect useContext hook calls
|
|
56620
|
+
CallExpression(path2) {
|
|
56621
|
+
if (path2.node.callee.name === "useContext" && path2.node.arguments.length > 0) {
|
|
56622
|
+
const contextArg = path2.node.arguments[0];
|
|
56623
|
+
let contextName = null;
|
|
56624
|
+
if (contextArg.type === "Identifier") {
|
|
56625
|
+
contextName = contextArg.name;
|
|
56626
|
+
} else if (contextArg.type === "MemberExpression") {
|
|
56627
|
+
contextName = extractMemberExpressionName(contextArg);
|
|
56628
|
+
}
|
|
56629
|
+
if (contextName) {
|
|
56630
|
+
contextUsages.push({
|
|
56631
|
+
type: "useContext",
|
|
56632
|
+
contextName,
|
|
56633
|
+
pattern: "context_consumer",
|
|
56634
|
+
loc: path2.node.loc
|
|
56635
|
+
});
|
|
56636
|
+
}
|
|
56637
|
+
}
|
|
56638
|
+
},
|
|
56639
|
+
// Detect Context.Provider usage in JSX
|
|
56640
|
+
JSXElement(path2) {
|
|
56641
|
+
const openingElement = path2.node.openingElement;
|
|
56642
|
+
if (openingElement.name.type === "JSXMemberExpression") {
|
|
56643
|
+
const objectName = openingElement.name.object.name;
|
|
56644
|
+
const propertyName = openingElement.name.property.name;
|
|
56645
|
+
if (propertyName === "Provider" || propertyName === "Consumer") {
|
|
56646
|
+
contextUsages.push({
|
|
56647
|
+
type: "JSXProvider",
|
|
56648
|
+
contextName: objectName,
|
|
56649
|
+
pattern: propertyName === "Provider" ? "context_provider" : "context_consumer",
|
|
56650
|
+
loc: path2.node.loc
|
|
56651
|
+
});
|
|
56652
|
+
}
|
|
56653
|
+
}
|
|
56654
|
+
}
|
|
56655
|
+
});
|
|
56656
|
+
return contextUsages;
|
|
56657
|
+
}
|
|
56658
|
+
function detectHookDependencies(ast) {
|
|
56659
|
+
const hookDeps = [];
|
|
56660
|
+
traverse(ast, {
|
|
56661
|
+
CallExpression(path2) {
|
|
56662
|
+
const calleeName = path2.node.callee.name;
|
|
56663
|
+
if (calleeName && calleeName.startsWith("use") && calleeName !== "useContext") {
|
|
56664
|
+
hookDeps.push({
|
|
56665
|
+
hookName: calleeName,
|
|
56666
|
+
pattern: "custom_hook",
|
|
56667
|
+
loc: path2.node.loc
|
|
56668
|
+
});
|
|
56669
|
+
}
|
|
56670
|
+
}
|
|
56671
|
+
});
|
|
56672
|
+
return hookDeps;
|
|
56673
|
+
}
|
|
56674
|
+
function detectDependencyInjection(ast) {
|
|
56675
|
+
if (!ast) {
|
|
56676
|
+
return {
|
|
56677
|
+
constructorInjections: [],
|
|
56678
|
+
contextUsages: [],
|
|
56679
|
+
hookDependencies: []
|
|
56680
|
+
};
|
|
56681
|
+
}
|
|
56682
|
+
return {
|
|
56683
|
+
constructorInjections: detectConstructorInjection(ast),
|
|
56684
|
+
contextUsages: detectReactContextUsage(ast),
|
|
56685
|
+
hookDependencies: detectHookDependencies(ast)
|
|
56686
|
+
};
|
|
56687
|
+
}
|
|
56688
|
+
function extractTypeName(typeAnnotation) {
|
|
56689
|
+
if (!typeAnnotation)
|
|
56690
|
+
return null;
|
|
56691
|
+
const annotation = typeAnnotation.typeAnnotation || typeAnnotation;
|
|
56692
|
+
if (annotation.type === "TSTypeReference" && annotation.typeName) {
|
|
56693
|
+
if (annotation.typeName.type === "Identifier") {
|
|
56694
|
+
return annotation.typeName.name;
|
|
56695
|
+
}
|
|
56696
|
+
}
|
|
56697
|
+
return null;
|
|
56698
|
+
}
|
|
56699
|
+
function extractMemberExpressionName(node) {
|
|
56700
|
+
if (node.type === "MemberExpression") {
|
|
56701
|
+
const object = node.object.name || "";
|
|
56702
|
+
const property = node.property.name || "";
|
|
56703
|
+
return object + "." + property;
|
|
56704
|
+
}
|
|
56705
|
+
return null;
|
|
56706
|
+
}
|
|
56707
|
+
module2.exports = {
|
|
56708
|
+
detectConstructorInjection,
|
|
56709
|
+
detectReactContextUsage,
|
|
56710
|
+
detectHookDependencies,
|
|
56711
|
+
detectDependencyInjection
|
|
56712
|
+
};
|
|
56713
|
+
}
|
|
56714
|
+
});
|
|
56715
|
+
|
|
56716
|
+
// src/core/method-tracker.js
|
|
56717
|
+
var require_method_tracker = __commonJS({
|
|
56718
|
+
"src/core/method-tracker.js"(exports2, module2) {
|
|
56719
|
+
var traverse = require_lib8().default;
|
|
56720
|
+
function trackMethodCalls(ast, imports = []) {
|
|
56721
|
+
const functionCalls = [];
|
|
56722
|
+
const methodCalls = [];
|
|
56723
|
+
const constructorCalls = [];
|
|
56724
|
+
if (!ast) {
|
|
56725
|
+
return { functionCalls, methodCalls, constructorCalls };
|
|
56726
|
+
}
|
|
56727
|
+
const importedSymbols = /* @__PURE__ */ new Set();
|
|
56728
|
+
imports.forEach((imp) => {
|
|
56729
|
+
if (imp.specifiers && Array.isArray(imp.specifiers)) {
|
|
56730
|
+
imp.specifiers.forEach((spec) => {
|
|
56731
|
+
const localName = spec.local || spec.imported || spec;
|
|
56732
|
+
if (typeof localName === "string") {
|
|
56733
|
+
importedSymbols.add(localName);
|
|
56734
|
+
}
|
|
56735
|
+
});
|
|
56736
|
+
}
|
|
56737
|
+
});
|
|
56738
|
+
traverse(ast, {
|
|
56739
|
+
CallExpression(path2) {
|
|
56740
|
+
const callee = path2.node.callee;
|
|
56741
|
+
if (callee.type === "Identifier") {
|
|
56742
|
+
const functionName = callee.name;
|
|
56743
|
+
if (importedSymbols.has(functionName) || /^[A-Z]/.test(functionName)) {
|
|
56744
|
+
functionCalls.push({
|
|
56745
|
+
name: functionName,
|
|
56746
|
+
type: "function_call",
|
|
56747
|
+
loc: path2.node.loc
|
|
56748
|
+
});
|
|
56749
|
+
}
|
|
56750
|
+
} else if (callee.type === "MemberExpression") {
|
|
56751
|
+
const objectName = extractObjectName(callee.object);
|
|
56752
|
+
const methodName = callee.property.name || callee.property.value;
|
|
56753
|
+
if (objectName && methodName) {
|
|
56754
|
+
methodCalls.push({
|
|
56755
|
+
object: objectName,
|
|
56756
|
+
method: methodName,
|
|
56757
|
+
type: "method_call",
|
|
56758
|
+
loc: path2.node.loc
|
|
56759
|
+
});
|
|
56760
|
+
}
|
|
56761
|
+
}
|
|
56762
|
+
},
|
|
56763
|
+
// Track constructor calls: new ClassName()
|
|
56764
|
+
NewExpression(path2) {
|
|
56765
|
+
const callee = path2.node.callee;
|
|
56766
|
+
if (callee.type === "Identifier") {
|
|
56767
|
+
const className = callee.name;
|
|
56768
|
+
if (importedSymbols.has(className)) {
|
|
56769
|
+
constructorCalls.push({
|
|
56770
|
+
className,
|
|
56771
|
+
type: "constructor_call",
|
|
56772
|
+
loc: path2.node.loc
|
|
56773
|
+
});
|
|
56774
|
+
}
|
|
56775
|
+
}
|
|
56776
|
+
}
|
|
56777
|
+
});
|
|
56778
|
+
return {
|
|
56779
|
+
functionCalls,
|
|
56780
|
+
methodCalls,
|
|
56781
|
+
constructorCalls
|
|
56782
|
+
};
|
|
56783
|
+
}
|
|
56784
|
+
function buildCallGraph(nodes) {
|
|
56785
|
+
const callEdges = [];
|
|
56786
|
+
nodes.forEach((node) => {
|
|
56787
|
+
const filePath = node.id;
|
|
56788
|
+
const metadata = node.metadata;
|
|
56789
|
+
if (!metadata)
|
|
56790
|
+
return;
|
|
56791
|
+
if (metadata.functionCalls && Array.isArray(metadata.functionCalls)) {
|
|
56792
|
+
metadata.functionCalls.forEach((call) => {
|
|
56793
|
+
callEdges.push({
|
|
56794
|
+
source: filePath,
|
|
56795
|
+
callType: "function",
|
|
56796
|
+
calledSymbol: call.name,
|
|
56797
|
+
loc: call.loc
|
|
56798
|
+
});
|
|
56799
|
+
});
|
|
56800
|
+
}
|
|
56801
|
+
if (metadata.constructorCalls && Array.isArray(metadata.constructorCalls)) {
|
|
56802
|
+
metadata.constructorCalls.forEach((call) => {
|
|
56803
|
+
callEdges.push({
|
|
56804
|
+
source: filePath,
|
|
56805
|
+
callType: "constructor",
|
|
56806
|
+
calledSymbol: call.className,
|
|
56807
|
+
loc: call.loc
|
|
56808
|
+
});
|
|
56809
|
+
});
|
|
56810
|
+
}
|
|
56811
|
+
if (metadata.methodCalls && Array.isArray(metadata.methodCalls)) {
|
|
56812
|
+
metadata.methodCalls.forEach((call) => {
|
|
56813
|
+
callEdges.push({
|
|
56814
|
+
source: filePath,
|
|
56815
|
+
callType: "method",
|
|
56816
|
+
calledSymbol: `${call.object}.${call.method}`,
|
|
56817
|
+
loc: call.loc
|
|
56818
|
+
});
|
|
56819
|
+
});
|
|
56820
|
+
}
|
|
56821
|
+
});
|
|
56822
|
+
return callEdges;
|
|
56823
|
+
}
|
|
56824
|
+
function extractObjectName(node) {
|
|
56825
|
+
if (node.type === "Identifier") {
|
|
56826
|
+
return node.name;
|
|
56827
|
+
} else if (node.type === "ThisExpression") {
|
|
56828
|
+
return "this";
|
|
56829
|
+
} else if (node.type === "MemberExpression") {
|
|
56830
|
+
const object = extractObjectName(node.object);
|
|
56831
|
+
const property = node.property.name || node.property.value;
|
|
56832
|
+
return object && property ? `${object}.${property}` : object;
|
|
56833
|
+
}
|
|
56834
|
+
return null;
|
|
56835
|
+
}
|
|
56836
|
+
module2.exports = {
|
|
56837
|
+
trackMethodCalls,
|
|
56838
|
+
buildCallGraph
|
|
56839
|
+
};
|
|
56840
|
+
}
|
|
56841
|
+
});
|
|
56842
|
+
|
|
56843
|
+
// src/core/type-analyzer.js
|
|
56844
|
+
var require_type_analyzer = __commonJS({
|
|
56845
|
+
"src/core/type-analyzer.js"(exports2, module2) {
|
|
56846
|
+
var traverse = require_lib8().default;
|
|
56847
|
+
function extractTypeImports(ast) {
|
|
56848
|
+
const typeImports = [];
|
|
56849
|
+
if (!ast)
|
|
56850
|
+
return typeImports;
|
|
56851
|
+
traverse(ast, {
|
|
56852
|
+
ImportDeclaration(path2) {
|
|
56853
|
+
const node = path2.node;
|
|
56854
|
+
if (node.importKind === "type") {
|
|
56855
|
+
const specifiers = [];
|
|
56856
|
+
node.specifiers.forEach((spec) => {
|
|
56857
|
+
if (spec.imported) {
|
|
56858
|
+
specifiers.push({
|
|
56859
|
+
imported: spec.imported.name || spec.imported.value,
|
|
56860
|
+
local: spec.local.name
|
|
56861
|
+
});
|
|
56862
|
+
}
|
|
56863
|
+
});
|
|
56864
|
+
typeImports.push({
|
|
56865
|
+
source: node.source.value,
|
|
56866
|
+
specifiers,
|
|
56867
|
+
importKind: "type",
|
|
56868
|
+
loc: node.loc
|
|
56869
|
+
});
|
|
56870
|
+
} else {
|
|
56871
|
+
const typeSpecifiers = [];
|
|
56872
|
+
node.specifiers.forEach((spec) => {
|
|
56873
|
+
if (spec.importKind === "type" && spec.imported) {
|
|
56874
|
+
typeSpecifiers.push({
|
|
56875
|
+
imported: spec.imported.name || spec.imported.value,
|
|
56876
|
+
local: spec.local.name
|
|
56877
|
+
});
|
|
56878
|
+
}
|
|
56879
|
+
});
|
|
56880
|
+
if (typeSpecifiers.length > 0) {
|
|
56881
|
+
typeImports.push({
|
|
56882
|
+
source: node.source.value,
|
|
56883
|
+
specifiers: typeSpecifiers,
|
|
56884
|
+
importKind: "mixed",
|
|
56885
|
+
loc: node.loc
|
|
56886
|
+
});
|
|
56887
|
+
}
|
|
56888
|
+
}
|
|
56889
|
+
}
|
|
56890
|
+
});
|
|
56891
|
+
return typeImports;
|
|
56892
|
+
}
|
|
56893
|
+
function extractInterfaceDependencies(ast) {
|
|
56894
|
+
const interfaceDeps = [];
|
|
56895
|
+
if (!ast)
|
|
56896
|
+
return interfaceDeps;
|
|
56897
|
+
traverse(ast, {
|
|
56898
|
+
// Interface extends
|
|
56899
|
+
TSInterfaceDeclaration(path2) {
|
|
56900
|
+
const node = path2.node;
|
|
56901
|
+
const interfaceName = node.id.name;
|
|
56902
|
+
if (node.extends && node.extends.length > 0) {
|
|
56903
|
+
node.extends.forEach((ext) => {
|
|
56904
|
+
const extendedInterface = extractTypeName(ext.expression);
|
|
56905
|
+
if (extendedInterface) {
|
|
56906
|
+
interfaceDeps.push({
|
|
56907
|
+
interface: interfaceName,
|
|
56908
|
+
extends: extendedInterface,
|
|
56909
|
+
type: "interface_extends",
|
|
56910
|
+
loc: node.loc
|
|
56911
|
+
});
|
|
56912
|
+
}
|
|
56913
|
+
});
|
|
56914
|
+
}
|
|
56915
|
+
},
|
|
56916
|
+
// Class implements
|
|
56917
|
+
ClassDeclaration(path2) {
|
|
56918
|
+
const node = path2.node;
|
|
56919
|
+
const className = node.id ? node.id.name : "Anonymous";
|
|
56920
|
+
if (node.implements && node.implements.length > 0) {
|
|
56921
|
+
node.implements.forEach((impl) => {
|
|
56922
|
+
const implementedInterface = extractTypeName(impl.expression);
|
|
56923
|
+
if (implementedInterface) {
|
|
56924
|
+
interfaceDeps.push({
|
|
56925
|
+
class: className,
|
|
56926
|
+
implements: implementedInterface,
|
|
56927
|
+
type: "class_implements",
|
|
56928
|
+
loc: node.loc
|
|
56929
|
+
});
|
|
56930
|
+
}
|
|
56931
|
+
});
|
|
56932
|
+
}
|
|
56933
|
+
}
|
|
56934
|
+
});
|
|
56935
|
+
return interfaceDeps;
|
|
56936
|
+
}
|
|
56937
|
+
function extractGenericDependencies(ast) {
|
|
56938
|
+
const genericDeps = [];
|
|
56939
|
+
if (!ast)
|
|
56940
|
+
return genericDeps;
|
|
56941
|
+
traverse(ast, {
|
|
56942
|
+
// Function return types
|
|
56943
|
+
FunctionDeclaration(path2) {
|
|
56944
|
+
const node = path2.node;
|
|
56945
|
+
const functionName = node.id ? node.id.name : "anonymous";
|
|
56946
|
+
if (node.returnType) {
|
|
56947
|
+
const returnTypeName = extractComplexTypeName(node.returnType.typeAnnotation);
|
|
56948
|
+
if (returnTypeName) {
|
|
56949
|
+
genericDeps.push({
|
|
56950
|
+
function: functionName,
|
|
56951
|
+
returnType: returnTypeName,
|
|
56952
|
+
type: "return_type",
|
|
56953
|
+
loc: node.loc
|
|
56954
|
+
});
|
|
56955
|
+
}
|
|
56956
|
+
}
|
|
56957
|
+
},
|
|
56958
|
+
// Arrow function return types
|
|
56959
|
+
ArrowFunctionExpression(path2) {
|
|
56960
|
+
const node = path2.node;
|
|
56961
|
+
if (node.returnType) {
|
|
56962
|
+
const returnTypeName = extractComplexTypeName(node.returnType.typeAnnotation);
|
|
56963
|
+
if (returnTypeName) {
|
|
56964
|
+
genericDeps.push({
|
|
56965
|
+
function: "arrow_function",
|
|
56966
|
+
returnType: returnTypeName,
|
|
56967
|
+
type: "return_type",
|
|
56968
|
+
loc: node.loc
|
|
56969
|
+
});
|
|
56970
|
+
}
|
|
56971
|
+
}
|
|
56972
|
+
},
|
|
56973
|
+
// Variable type annotations
|
|
56974
|
+
VariableDeclarator(path2) {
|
|
56975
|
+
const node = path2.node;
|
|
56976
|
+
const varName = node.id.name;
|
|
56977
|
+
if (node.id.typeAnnotation) {
|
|
56978
|
+
const typeName = extractComplexTypeName(node.id.typeAnnotation.typeAnnotation);
|
|
56979
|
+
if (typeName) {
|
|
56980
|
+
genericDeps.push({
|
|
56981
|
+
variable: varName,
|
|
56982
|
+
type: typeName,
|
|
56983
|
+
kind: "variable_type",
|
|
56984
|
+
loc: node.loc
|
|
56985
|
+
});
|
|
56986
|
+
}
|
|
56987
|
+
}
|
|
56988
|
+
}
|
|
56989
|
+
});
|
|
56990
|
+
return genericDeps;
|
|
56991
|
+
}
|
|
56992
|
+
function analyzeTypeDependencies(ast) {
|
|
56993
|
+
if (!ast) {
|
|
56994
|
+
return {
|
|
56995
|
+
typeImports: [],
|
|
56996
|
+
interfaceDependencies: [],
|
|
56997
|
+
genericDependencies: []
|
|
56998
|
+
};
|
|
56999
|
+
}
|
|
57000
|
+
return {
|
|
57001
|
+
typeImports: extractTypeImports(ast),
|
|
57002
|
+
interfaceDependencies: extractInterfaceDependencies(ast),
|
|
57003
|
+
genericDependencies: extractGenericDependencies(ast)
|
|
57004
|
+
};
|
|
57005
|
+
}
|
|
57006
|
+
function extractTypeName(node) {
|
|
57007
|
+
if (!node)
|
|
57008
|
+
return null;
|
|
57009
|
+
if (node.type === "Identifier") {
|
|
57010
|
+
return node.name;
|
|
57011
|
+
} else if (node.type === "TSTypeReference" && node.typeName) {
|
|
57012
|
+
if (node.typeName.type === "Identifier") {
|
|
57013
|
+
return node.typeName.name;
|
|
57014
|
+
}
|
|
57015
|
+
}
|
|
57016
|
+
return null;
|
|
57017
|
+
}
|
|
57018
|
+
function extractComplexTypeName(node) {
|
|
57019
|
+
if (!node)
|
|
57020
|
+
return null;
|
|
57021
|
+
if (node.type === "TSTypeReference" && node.typeName) {
|
|
57022
|
+
let baseName = extractTypeName(node);
|
|
57023
|
+
if (node.typeParameters && node.typeParameters.params) {
|
|
57024
|
+
const params = node.typeParameters.params.map((p) => extractComplexTypeName(p)).filter(Boolean).join(", ");
|
|
57025
|
+
if (params) {
|
|
57026
|
+
baseName += `<${params}>`;
|
|
57027
|
+
}
|
|
57028
|
+
}
|
|
57029
|
+
return baseName;
|
|
57030
|
+
} else if (node.type === "Identifier") {
|
|
57031
|
+
return node.name;
|
|
57032
|
+
} else if (node.type === "TSArrayType") {
|
|
57033
|
+
const elementType = extractComplexTypeName(node.elementType);
|
|
57034
|
+
return elementType ? `${elementType}[]` : null;
|
|
57035
|
+
}
|
|
57036
|
+
return null;
|
|
57037
|
+
}
|
|
57038
|
+
module2.exports = {
|
|
57039
|
+
extractTypeImports,
|
|
57040
|
+
extractInterfaceDependencies,
|
|
57041
|
+
extractGenericDependencies,
|
|
57042
|
+
analyzeTypeDependencies
|
|
57043
|
+
};
|
|
57044
|
+
}
|
|
57045
|
+
});
|
|
57046
|
+
|
|
57047
|
+
// src/core/react-nextjs-detector.js
|
|
57048
|
+
var require_react_nextjs_detector = __commonJS({
|
|
57049
|
+
"src/core/react-nextjs-detector.js"(exports2, module2) {
|
|
57050
|
+
var traverse = require_lib8().default;
|
|
57051
|
+
function detectComponentUsage(ast) {
|
|
57052
|
+
const componentUsages = [];
|
|
57053
|
+
if (!ast)
|
|
57054
|
+
return componentUsages;
|
|
57055
|
+
traverse(ast, {
|
|
57056
|
+
JSXElement(path2) {
|
|
57057
|
+
const openingElement = path2.node.openingElement;
|
|
57058
|
+
let componentName = null;
|
|
57059
|
+
if (openingElement.name.type === "JSXIdentifier") {
|
|
57060
|
+
componentName = openingElement.name.name;
|
|
57061
|
+
if (/^[A-Z]/.test(componentName)) {
|
|
57062
|
+
componentUsages.push({
|
|
57063
|
+
component: componentName,
|
|
57064
|
+
type: "jsx_component",
|
|
57065
|
+
loc: path2.node.loc
|
|
57066
|
+
});
|
|
57067
|
+
}
|
|
57068
|
+
} else if (openingElement.name.type === "JSXMemberExpression") {
|
|
57069
|
+
const object = openingElement.name.object.name;
|
|
57070
|
+
const property = openingElement.name.property.name;
|
|
57071
|
+
componentName = `${object}.${property}`;
|
|
57072
|
+
componentUsages.push({
|
|
57073
|
+
component: componentName,
|
|
57074
|
+
type: "jsx_member_component",
|
|
57075
|
+
loc: path2.node.loc
|
|
57076
|
+
});
|
|
57077
|
+
}
|
|
57078
|
+
}
|
|
57079
|
+
});
|
|
57080
|
+
return componentUsages;
|
|
57081
|
+
}
|
|
57082
|
+
function detectServerClientBoundaries(content) {
|
|
57083
|
+
const boundaries = {
|
|
57084
|
+
isClientComponent: false,
|
|
57085
|
+
isServerComponent: false,
|
|
57086
|
+
isServerAction: false
|
|
57087
|
+
};
|
|
57088
|
+
if (!content)
|
|
57089
|
+
return boundaries;
|
|
57090
|
+
if (/['"]use client['"]/.test(content)) {
|
|
57091
|
+
boundaries.isClientComponent = true;
|
|
57092
|
+
}
|
|
57093
|
+
if (/['"]use server['"]/.test(content)) {
|
|
57094
|
+
boundaries.isServerAction = true;
|
|
57095
|
+
}
|
|
57096
|
+
if (!boundaries.isClientComponent && !boundaries.isServerAction) {
|
|
57097
|
+
boundaries.isServerComponent = true;
|
|
57098
|
+
}
|
|
57099
|
+
return boundaries;
|
|
57100
|
+
}
|
|
57101
|
+
function detectAPIRouteDependencies(ast) {
|
|
57102
|
+
const apiDeps = [];
|
|
57103
|
+
if (!ast)
|
|
57104
|
+
return apiDeps;
|
|
57105
|
+
traverse(ast, {
|
|
57106
|
+
// Detect Next.js API route handlers: export async function GET/POST/etc
|
|
57107
|
+
ExportNamedDeclaration(path2) {
|
|
57108
|
+
const node = path2.node;
|
|
57109
|
+
if (node.declaration && node.declaration.type === "FunctionDeclaration") {
|
|
57110
|
+
const funcName = node.declaration.id ? node.declaration.id.name : null;
|
|
57111
|
+
if (["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"].includes(funcName)) {
|
|
57112
|
+
apiDeps.push({
|
|
57113
|
+
handler: funcName,
|
|
57114
|
+
type: "api_route_handler",
|
|
57115
|
+
loc: node.loc
|
|
57116
|
+
});
|
|
57117
|
+
}
|
|
57118
|
+
}
|
|
57119
|
+
},
|
|
57120
|
+
// Detect fetch calls and database queries within API routes
|
|
57121
|
+
CallExpression(path2) {
|
|
57122
|
+
const callee = path2.node.callee;
|
|
57123
|
+
if (callee.type === "MemberExpression") {
|
|
57124
|
+
const objectName = callee.object.name;
|
|
57125
|
+
const methodName = callee.property.name || callee.property.value;
|
|
57126
|
+
if (objectName === "supabase" || /supabase/i.test(objectName)) {
|
|
57127
|
+
apiDeps.push({
|
|
57128
|
+
service: "supabase",
|
|
57129
|
+
method: methodName,
|
|
57130
|
+
type: "database_query",
|
|
57131
|
+
loc: path2.node.loc
|
|
57132
|
+
});
|
|
57133
|
+
}
|
|
57134
|
+
if (objectName === "prisma" || /prisma/i.test(objectName)) {
|
|
57135
|
+
apiDeps.push({
|
|
57136
|
+
service: "prisma",
|
|
57137
|
+
method: methodName,
|
|
57138
|
+
type: "database_query",
|
|
57139
|
+
loc: path2.node.loc
|
|
57140
|
+
});
|
|
57141
|
+
}
|
|
57142
|
+
}
|
|
57143
|
+
}
|
|
57144
|
+
});
|
|
57145
|
+
return apiDeps;
|
|
57146
|
+
}
|
|
57147
|
+
function detectMiddlewareDependencies(ast, filePath = "") {
|
|
57148
|
+
const middlewareDeps = [];
|
|
57149
|
+
const isMiddleware = /middleware\.(ts|js)$/.test(filePath);
|
|
57150
|
+
if (!isMiddleware || !ast)
|
|
57151
|
+
return middlewareDeps;
|
|
57152
|
+
traverse(ast, {
|
|
57153
|
+
// Detect middleware function export
|
|
57154
|
+
ExportNamedDeclaration(path2) {
|
|
57155
|
+
const node = path2.node;
|
|
57156
|
+
if (node.declaration && node.declaration.type === "FunctionDeclaration") {
|
|
57157
|
+
const funcName = node.declaration.id ? node.declaration.id.name : null;
|
|
57158
|
+
if (funcName === "middleware") {
|
|
57159
|
+
middlewareDeps.push({
|
|
57160
|
+
function: funcName,
|
|
57161
|
+
type: "middleware_function",
|
|
57162
|
+
loc: node.loc
|
|
57163
|
+
});
|
|
57164
|
+
}
|
|
57165
|
+
}
|
|
57166
|
+
},
|
|
57167
|
+
// Detect auth checks and redirects
|
|
57168
|
+
CallExpression(path2) {
|
|
57169
|
+
const callee = path2.node.callee;
|
|
57170
|
+
if (callee.type === "MemberExpression") {
|
|
57171
|
+
const methodName = callee.property.name || callee.property.value;
|
|
57172
|
+
if (methodName === "getUser" || methodName === "getSession") {
|
|
57173
|
+
middlewareDeps.push({
|
|
57174
|
+
service: "auth",
|
|
57175
|
+
method: methodName,
|
|
57176
|
+
type: "auth_check",
|
|
57177
|
+
loc: path2.node.loc
|
|
57178
|
+
});
|
|
57179
|
+
}
|
|
57180
|
+
if (methodName === "redirect" || methodName === "rewrite") {
|
|
57181
|
+
middlewareDeps.push({
|
|
57182
|
+
service: "next",
|
|
57183
|
+
method: methodName,
|
|
57184
|
+
type: "middleware_action",
|
|
57185
|
+
loc: path2.node.loc
|
|
57186
|
+
});
|
|
57187
|
+
}
|
|
57188
|
+
}
|
|
57189
|
+
}
|
|
57190
|
+
});
|
|
57191
|
+
return middlewareDeps;
|
|
57192
|
+
}
|
|
57193
|
+
function detectReactNextJSPatterns(ast, content = "", filePath = "") {
|
|
57194
|
+
return {
|
|
57195
|
+
componentUsages: detectComponentUsage(ast),
|
|
57196
|
+
boundaries: detectServerClientBoundaries(content),
|
|
57197
|
+
apiDependencies: detectAPIRouteDependencies(ast),
|
|
57198
|
+
middlewareDependencies: detectMiddlewareDependencies(ast, filePath)
|
|
57199
|
+
};
|
|
57200
|
+
}
|
|
57201
|
+
module2.exports = {
|
|
57202
|
+
detectComponentUsage,
|
|
57203
|
+
detectServerClientBoundaries,
|
|
57204
|
+
detectAPIRouteDependencies,
|
|
57205
|
+
detectMiddlewareDependencies,
|
|
57206
|
+
detectReactNextJSPatterns
|
|
57207
|
+
};
|
|
57208
|
+
}
|
|
57209
|
+
});
|
|
57210
|
+
|
|
57211
|
+
// src/core/parser-enhanced.js
|
|
57212
|
+
var require_parser_enhanced = __commonJS({
|
|
57213
|
+
"src/core/parser-enhanced.js"(exports2, module2) {
|
|
57214
|
+
var { parseFile: originalParseFile } = require_parser();
|
|
57215
|
+
var { detectDependencyInjection } = require_di_detector();
|
|
57216
|
+
var { trackMethodCalls } = require_method_tracker();
|
|
57217
|
+
var { analyzeTypeDependencies } = require_type_analyzer();
|
|
57218
|
+
var { detectReactNextJSPatterns } = require_react_nextjs_detector();
|
|
57219
|
+
var fs2 = require("fs");
|
|
57220
|
+
function parseFileEnhanced(filePath) {
|
|
57221
|
+
const metadata = originalParseFile(filePath);
|
|
57222
|
+
if (!metadata.ast) {
|
|
57223
|
+
return metadata;
|
|
57224
|
+
}
|
|
57225
|
+
const ast = metadata.ast;
|
|
57226
|
+
const fileContent = fs2.readFileSync(filePath, "utf-8");
|
|
57227
|
+
try {
|
|
57228
|
+
const diPatterns = detectDependencyInjection(ast);
|
|
57229
|
+
metadata.constructorInjections = diPatterns.constructorInjections || [];
|
|
57230
|
+
metadata.contextUsages = diPatterns.contextUsages || [];
|
|
57231
|
+
metadata.hookDependencies = diPatterns.hookDependencies || [];
|
|
57232
|
+
const callTracking = trackMethodCalls(ast, metadata.imports);
|
|
57233
|
+
metadata.functionCalls = callTracking.functionCalls || [];
|
|
57234
|
+
metadata.constructorCalls = callTracking.constructorCalls || [];
|
|
57235
|
+
metadata.methodCalls = callTracking.methodCalls || [];
|
|
57236
|
+
const typeDeps = analyzeTypeDependencies(ast);
|
|
57237
|
+
metadata.typeImports = typeDeps.typeImports || [];
|
|
57238
|
+
metadata.interfaceDependencies = typeDeps.interfaceDependencies || [];
|
|
57239
|
+
metadata.genericDependencies = typeDeps.genericDependencies || [];
|
|
57240
|
+
const reactPatterns = detectReactNextJSPatterns(ast, fileContent, filePath);
|
|
57241
|
+
metadata.componentUsage = reactPatterns.componentUsages || [];
|
|
57242
|
+
metadata.serverClientBoundaries = reactPatterns.boundaries || {};
|
|
57243
|
+
metadata.apiDependencies = reactPatterns.apiDependencies || [];
|
|
57244
|
+
metadata.middlewareDependencies = reactPatterns.middlewareDependencies || [];
|
|
57245
|
+
} catch (error) {
|
|
57246
|
+
console.warn(`\u26A0\uFE0F Enhanced analysis failed for ${filePath}: ${error.message}`);
|
|
57247
|
+
}
|
|
57248
|
+
delete metadata.ast;
|
|
57249
|
+
return metadata;
|
|
57250
|
+
}
|
|
57251
|
+
module2.exports = {
|
|
57252
|
+
parseFile: parseFileEnhanced,
|
|
57253
|
+
parseFileBasic: originalParseFile
|
|
57254
|
+
};
|
|
57255
|
+
}
|
|
57256
|
+
});
|
|
57257
|
+
|
|
56572
57258
|
// src/plugins/plugin-manager.js
|
|
56573
57259
|
var require_plugin_manager = __commonJS({
|
|
56574
57260
|
"src/plugins/plugin-manager.js"(exports2, module2) {
|
|
@@ -56597,7 +57283,7 @@ var require_plugin_manager = __commonJS({
|
|
|
56597
57283
|
enhancedMetadata = { ...enhancedMetadata, ...result };
|
|
56598
57284
|
}
|
|
56599
57285
|
} catch (error) {
|
|
56600
|
-
console.warn(`Plugin ${plugin.name} failed: ${error.message}`);
|
|
57286
|
+
console.warn(`Plugin ${plugin.name} failed: ${error.message || error}`);
|
|
56601
57287
|
}
|
|
56602
57288
|
}
|
|
56603
57289
|
return enhancedMetadata;
|
|
@@ -56695,7 +57381,7 @@ var require_path_resolver = __commonJS({
|
|
|
56695
57381
|
const suffix = importPath.substring(patternBase.length);
|
|
56696
57382
|
for (const target of aliasTargets) {
|
|
56697
57383
|
const targetBase = target.replace(/\*.*$/, "");
|
|
56698
|
-
const targetPath = path2.resolve(projectRoot, targetBase
|
|
57384
|
+
const targetPath = path2.resolve(projectRoot, path2.join(targetBase, suffix));
|
|
56699
57385
|
const extensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".json"];
|
|
56700
57386
|
for (const ext of extensions) {
|
|
56701
57387
|
if (fs2.existsSync(targetPath + ext)) {
|
|
@@ -56982,29 +57668,43 @@ var require_context_builder = __commonJS({
|
|
|
56982
57668
|
for (const edge of edges) {
|
|
56983
57669
|
const sourceNode = nodes.find((n) => n.path === edge.source);
|
|
56984
57670
|
const targetNode = nodes.find((n) => n.path === edge.target);
|
|
56985
|
-
if (sourceNode
|
|
57671
|
+
if (sourceNode) {
|
|
56986
57672
|
let relationType = "imports";
|
|
56987
57673
|
if (edge.type === "imports" || edge.type === "require" || edge.type === "export-from" || edge.type === "export-all" || edge.type === "dynamic-import" || edge.type === "require-assignment") {
|
|
56988
57674
|
relationType = "imports";
|
|
57675
|
+
} else if (edge.type === "function_call" || edge.type === "method_call") {
|
|
57676
|
+
relationType = "calls";
|
|
57677
|
+
} else if (edge.type === "constructor_call") {
|
|
57678
|
+
relationType = "calls";
|
|
57679
|
+
} else if (edge.type === "component_usage" || edge.type === "jsx_component" || edge.type === "jsx_member_component") {
|
|
57680
|
+
relationType = "imports";
|
|
56989
57681
|
} else if (edge.type === "calls") {
|
|
56990
57682
|
relationType = "calls";
|
|
56991
57683
|
} else if (edge.type === "owns") {
|
|
56992
57684
|
relationType = "owns";
|
|
56993
57685
|
} else if (edge.type === "depends_on") {
|
|
56994
57686
|
relationType = "depends_on";
|
|
57687
|
+
} else {
|
|
57688
|
+
relationType = "imports";
|
|
57689
|
+
}
|
|
57690
|
+
if (targetNode) {
|
|
57691
|
+
schemaEdges.push({
|
|
57692
|
+
from: sourceNode.id,
|
|
57693
|
+
to: targetNode.id,
|
|
57694
|
+
relation: relationType
|
|
57695
|
+
});
|
|
57696
|
+
} else {
|
|
56995
57697
|
}
|
|
56996
|
-
schemaEdges.push({
|
|
56997
|
-
from: sourceNode.id,
|
|
56998
|
-
to: targetNode.id,
|
|
56999
|
-
relation: relationType
|
|
57000
|
-
});
|
|
57001
57698
|
}
|
|
57002
57699
|
}
|
|
57003
57700
|
const metrics = {
|
|
57004
57701
|
total_files: nodes.length,
|
|
57005
57702
|
total_nodes: nodes.length,
|
|
57006
57703
|
total_edges: schemaEdges.length,
|
|
57007
|
-
total_imports: schemaEdges.length,
|
|
57704
|
+
total_imports: schemaEdges.filter((edge) => edge.relation === "imports").length,
|
|
57705
|
+
total_calls: schemaEdges.filter((edge) => edge.relation === "calls").length,
|
|
57706
|
+
total_owns: schemaEdges.filter((edge) => edge.relation === "owns").length,
|
|
57707
|
+
total_depends_on: schemaEdges.filter((edge) => edge.relation === "depends_on").length,
|
|
57008
57708
|
files_with_functions: nodes.filter((n) => n.role === "Implementation").length
|
|
57009
57709
|
};
|
|
57010
57710
|
const context = {
|
|
@@ -63577,13 +64277,167 @@ var require_context_sorter = __commonJS({
|
|
|
63577
64277
|
}
|
|
63578
64278
|
});
|
|
63579
64279
|
|
|
64280
|
+
// src/core/semantic-analyzer.js
|
|
64281
|
+
var require_semantic_analyzer = __commonJS({
|
|
64282
|
+
"src/core/semantic-analyzer.js"(exports2, module2) {
|
|
64283
|
+
function buildSymbolTable(nodes) {
|
|
64284
|
+
const symbolTable = /* @__PURE__ */ new Map();
|
|
64285
|
+
nodes.forEach((node) => {
|
|
64286
|
+
const filePath = node.id;
|
|
64287
|
+
const metadata = node.metadata;
|
|
64288
|
+
if (!metadata)
|
|
64289
|
+
return;
|
|
64290
|
+
if (metadata.exports && Array.isArray(metadata.exports)) {
|
|
64291
|
+
metadata.exports.forEach((exp) => {
|
|
64292
|
+
const symbolName = exp.name;
|
|
64293
|
+
if (!symbolTable.has(symbolName)) {
|
|
64294
|
+
symbolTable.set(symbolName, []);
|
|
64295
|
+
}
|
|
64296
|
+
symbolTable.get(symbolName).push({
|
|
64297
|
+
file: filePath,
|
|
64298
|
+
type: exp.type,
|
|
64299
|
+
loc: exp.loc
|
|
64300
|
+
});
|
|
64301
|
+
});
|
|
64302
|
+
}
|
|
64303
|
+
if (metadata.functions && Array.isArray(metadata.functions)) {
|
|
64304
|
+
metadata.functions.forEach((func) => {
|
|
64305
|
+
const symbolName = func.name;
|
|
64306
|
+
if (!symbolTable.has(symbolName)) {
|
|
64307
|
+
symbolTable.set(symbolName, []);
|
|
64308
|
+
}
|
|
64309
|
+
symbolTable.get(symbolName).push({
|
|
64310
|
+
file: filePath,
|
|
64311
|
+
type: "function",
|
|
64312
|
+
loc: func.loc
|
|
64313
|
+
});
|
|
64314
|
+
});
|
|
64315
|
+
}
|
|
64316
|
+
if (metadata.classes && Array.isArray(metadata.classes)) {
|
|
64317
|
+
metadata.classes.forEach((cls) => {
|
|
64318
|
+
const symbolName = cls.name;
|
|
64319
|
+
if (!symbolTable.has(symbolName)) {
|
|
64320
|
+
symbolTable.set(symbolName, []);
|
|
64321
|
+
}
|
|
64322
|
+
symbolTable.get(symbolName).push({
|
|
64323
|
+
file: filePath,
|
|
64324
|
+
type: "class",
|
|
64325
|
+
loc: cls.loc
|
|
64326
|
+
});
|
|
64327
|
+
});
|
|
64328
|
+
}
|
|
64329
|
+
});
|
|
64330
|
+
return symbolTable;
|
|
64331
|
+
}
|
|
64332
|
+
function resolveSymbolUsage(node, symbolTable) {
|
|
64333
|
+
const resolvedUsages = [];
|
|
64334
|
+
const metadata = node.metadata;
|
|
64335
|
+
if (!metadata)
|
|
64336
|
+
return resolvedUsages;
|
|
64337
|
+
const importedSymbols = /* @__PURE__ */ new Map();
|
|
64338
|
+
if (metadata.imports && Array.isArray(metadata.imports)) {
|
|
64339
|
+
metadata.imports.forEach((imp) => {
|
|
64340
|
+
if (imp.specifiers && Array.isArray(imp.specifiers)) {
|
|
64341
|
+
imp.specifiers.forEach((spec) => {
|
|
64342
|
+
const localName = spec.local || spec.imported || spec;
|
|
64343
|
+
const importedName = spec.imported || spec.local || spec;
|
|
64344
|
+
importedSymbols.set(localName, {
|
|
64345
|
+
source: imp.source,
|
|
64346
|
+
originalName: importedName
|
|
64347
|
+
});
|
|
64348
|
+
});
|
|
64349
|
+
}
|
|
64350
|
+
});
|
|
64351
|
+
}
|
|
64352
|
+
if (metadata.functionCalls && Array.isArray(metadata.functionCalls)) {
|
|
64353
|
+
metadata.functionCalls.forEach((call) => {
|
|
64354
|
+
const callName = call.name;
|
|
64355
|
+
if (importedSymbols.has(callName)) {
|
|
64356
|
+
const importInfo = importedSymbols.get(callName);
|
|
64357
|
+
resolvedUsages.push({
|
|
64358
|
+
type: "function_call",
|
|
64359
|
+
symbol: callName,
|
|
64360
|
+
source: importInfo.source,
|
|
64361
|
+
loc: call.loc
|
|
64362
|
+
});
|
|
64363
|
+
}
|
|
64364
|
+
});
|
|
64365
|
+
}
|
|
64366
|
+
if (metadata.constructorCalls && Array.isArray(metadata.constructorCalls)) {
|
|
64367
|
+
metadata.constructorCalls.forEach((call) => {
|
|
64368
|
+
const className = call.className;
|
|
64369
|
+
if (importedSymbols.has(className)) {
|
|
64370
|
+
const importInfo = importedSymbols.get(className);
|
|
64371
|
+
resolvedUsages.push({
|
|
64372
|
+
type: "constructor_call",
|
|
64373
|
+
symbol: className,
|
|
64374
|
+
source: importInfo.source,
|
|
64375
|
+
loc: call.loc
|
|
64376
|
+
});
|
|
64377
|
+
}
|
|
64378
|
+
});
|
|
64379
|
+
}
|
|
64380
|
+
if (metadata.componentUsage && Array.isArray(metadata.componentUsage)) {
|
|
64381
|
+
metadata.componentUsage.forEach((comp) => {
|
|
64382
|
+
const componentName = comp.component;
|
|
64383
|
+
if (importedSymbols.has(componentName)) {
|
|
64384
|
+
const importInfo = importedSymbols.get(componentName);
|
|
64385
|
+
resolvedUsages.push({
|
|
64386
|
+
type: "component_usage",
|
|
64387
|
+
symbol: componentName,
|
|
64388
|
+
source: importInfo.source,
|
|
64389
|
+
loc: comp.loc
|
|
64390
|
+
});
|
|
64391
|
+
}
|
|
64392
|
+
});
|
|
64393
|
+
}
|
|
64394
|
+
return resolvedUsages;
|
|
64395
|
+
}
|
|
64396
|
+
function trackCrossFileReferences(nodes, symbolTable) {
|
|
64397
|
+
const usageEdges = [];
|
|
64398
|
+
nodes.forEach((node) => {
|
|
64399
|
+
const filePath = node.id;
|
|
64400
|
+
const resolvedUsages = resolveSymbolUsage(node, symbolTable);
|
|
64401
|
+
resolvedUsages.forEach((usage) => {
|
|
64402
|
+
usageEdges.push({
|
|
64403
|
+
source: filePath,
|
|
64404
|
+
target: usage.source,
|
|
64405
|
+
type: usage.type,
|
|
64406
|
+
symbol: usage.symbol,
|
|
64407
|
+
loc: usage.loc
|
|
64408
|
+
});
|
|
64409
|
+
});
|
|
64410
|
+
});
|
|
64411
|
+
return usageEdges;
|
|
64412
|
+
}
|
|
64413
|
+
function analyzeSemantics(nodes) {
|
|
64414
|
+
const symbolTable = buildSymbolTable(nodes);
|
|
64415
|
+
const usageEdges = trackCrossFileReferences(nodes, symbolTable);
|
|
64416
|
+
return {
|
|
64417
|
+
symbolTable,
|
|
64418
|
+
usageEdges,
|
|
64419
|
+
stats: {
|
|
64420
|
+
totalSymbols: symbolTable.size,
|
|
64421
|
+
totalUsages: usageEdges.length
|
|
64422
|
+
}
|
|
64423
|
+
};
|
|
64424
|
+
}
|
|
64425
|
+
module2.exports = {
|
|
64426
|
+
buildSymbolTable,
|
|
64427
|
+
resolveSymbolUsage,
|
|
64428
|
+
trackCrossFileReferences,
|
|
64429
|
+
analyzeSemantics
|
|
64430
|
+
};
|
|
64431
|
+
}
|
|
64432
|
+
});
|
|
64433
|
+
|
|
63580
64434
|
// src/core/scanner.js
|
|
63581
64435
|
var require_scanner = __commonJS({
|
|
63582
64436
|
"src/core/scanner.js"(exports2, module2) {
|
|
63583
64437
|
var { glob } = require_commonjs5();
|
|
63584
64438
|
var path2 = require("path");
|
|
63585
64439
|
var fs2 = require("fs");
|
|
63586
|
-
var parser =
|
|
64440
|
+
var parser = require_parser_enhanced();
|
|
63587
64441
|
var pluginManager = require_plugin_manager();
|
|
63588
64442
|
var { loadTSConfig } = require_tsconfig_utils();
|
|
63589
64443
|
var { resolveImport } = require_path_resolver();
|
|
@@ -63591,6 +64445,7 @@ var require_scanner = __commonJS({
|
|
|
63591
64445
|
var { buildContext } = require_context_builder();
|
|
63592
64446
|
var { validateContext } = require_context_validator();
|
|
63593
64447
|
var { sortContext } = require_context_sorter();
|
|
64448
|
+
var { analyzeSemantics } = require_semantic_analyzer();
|
|
63594
64449
|
async function scan(directory) {
|
|
63595
64450
|
const normalize = (p) => p.replace(/\\/g, "/");
|
|
63596
64451
|
const options = {
|
|
@@ -63607,6 +64462,7 @@ var require_scanner = __commonJS({
|
|
|
63607
64462
|
edges: []
|
|
63608
64463
|
};
|
|
63609
64464
|
const fileMap = /* @__PURE__ */ new Map();
|
|
64465
|
+
let totalImportsFound = 0;
|
|
63610
64466
|
for (const file of files) {
|
|
63611
64467
|
try {
|
|
63612
64468
|
const relativePath = path2.relative(directory, file);
|
|
@@ -63632,6 +64488,9 @@ var require_scanner = __commonJS({
|
|
|
63632
64488
|
metadata = parser.parseFile(file);
|
|
63633
64489
|
}
|
|
63634
64490
|
metadata = await pluginManager.processFile(file, metadata);
|
|
64491
|
+
if (metadata.imports && Array.isArray(metadata.imports)) {
|
|
64492
|
+
totalImportsFound += metadata.imports.length;
|
|
64493
|
+
}
|
|
63635
64494
|
const node = {
|
|
63636
64495
|
id: normalizedRelativePath,
|
|
63637
64496
|
type: "file",
|
|
@@ -63643,42 +64502,266 @@ var require_scanner = __commonJS({
|
|
|
63643
64502
|
console.warn(`\u26A0\uFE0F Failed to process ${file} \u2014 file skipped, you should check manually (${e.message})`);
|
|
63644
64503
|
}
|
|
63645
64504
|
}
|
|
64505
|
+
console.log("Performing semantic analysis...");
|
|
64506
|
+
const semanticResults = analyzeSemantics(architectureMap.nodes);
|
|
64507
|
+
console.log(`Semantic analysis complete: ${semanticResults.stats.totalSymbols} symbols, ${semanticResults.stats.totalUsages} usage edges`);
|
|
63646
64508
|
const tsconfig = loadTSConfig(directory);
|
|
64509
|
+
const allPossiblePaths = /* @__PURE__ */ new Set();
|
|
63647
64510
|
const pathToNodeIdMap = /* @__PURE__ */ new Map();
|
|
63648
64511
|
architectureMap.nodes.forEach((node) => {
|
|
63649
64512
|
const normalizedPath = normalize(node.id);
|
|
64513
|
+
allPossiblePaths.add(normalizedPath);
|
|
63650
64514
|
pathToNodeIdMap.set(normalizedPath, node.id);
|
|
63651
64515
|
});
|
|
64516
|
+
let unresolvedImports = 0;
|
|
64517
|
+
let resolvedImports = 0;
|
|
63652
64518
|
architectureMap.nodes.forEach((node) => {
|
|
63653
64519
|
if (node.metadata.imports && Array.isArray(node.metadata.imports)) {
|
|
63654
64520
|
node.metadata.imports.forEach((imp) => {
|
|
63655
64521
|
if (imp.source && typeof imp.source === "string") {
|
|
63656
|
-
|
|
63657
|
-
|
|
63658
|
-
|
|
63659
|
-
directory,
|
|
63660
|
-
tsconfig
|
|
63661
|
-
);
|
|
63662
|
-
if (resolvedPath) {
|
|
63663
|
-
const relativeResolvedPath = path2.relative(directory, resolvedPath);
|
|
63664
|
-
const normalizedResolvedPath = normalize(relativeResolvedPath);
|
|
63665
|
-
if (pathToNodeIdMap.has(normalizedResolvedPath)) {
|
|
64522
|
+
let targetFound = false;
|
|
64523
|
+
try {
|
|
64524
|
+
if (allPossiblePaths.has(imp.source)) {
|
|
63666
64525
|
architectureMap.edges.push({
|
|
63667
64526
|
source: normalize(node.id),
|
|
63668
|
-
target:
|
|
64527
|
+
target: imp.source,
|
|
63669
64528
|
type: imp.type || "import"
|
|
63670
64529
|
});
|
|
64530
|
+
resolvedImports++;
|
|
64531
|
+
targetFound = true;
|
|
63671
64532
|
}
|
|
64533
|
+
if (!targetFound) {
|
|
64534
|
+
const resolvedPath = resolveImport(
|
|
64535
|
+
imp.source,
|
|
64536
|
+
path2.join(directory, node.id),
|
|
64537
|
+
directory,
|
|
64538
|
+
tsconfig
|
|
64539
|
+
);
|
|
64540
|
+
if (resolvedPath) {
|
|
64541
|
+
const relativeResolvedPath = path2.relative(directory, resolvedPath);
|
|
64542
|
+
const normalizedResolvedPath = normalize(relativeResolvedPath);
|
|
64543
|
+
if (allPossiblePaths.has(normalizedResolvedPath)) {
|
|
64544
|
+
architectureMap.edges.push({
|
|
64545
|
+
source: normalize(node.id),
|
|
64546
|
+
target: normalizedResolvedPath,
|
|
64547
|
+
type: imp.type || "import"
|
|
64548
|
+
});
|
|
64549
|
+
resolvedImports++;
|
|
64550
|
+
targetFound = true;
|
|
64551
|
+
}
|
|
64552
|
+
}
|
|
64553
|
+
}
|
|
64554
|
+
if (!targetFound) {
|
|
64555
|
+
try {
|
|
64556
|
+
const baseDir = path2.dirname(path2.join(directory, node.id));
|
|
64557
|
+
const calculatedAbsolutePath = path2.resolve(baseDir, imp.source);
|
|
64558
|
+
const calculatedRelativePath = path2.relative(directory, calculatedAbsolutePath);
|
|
64559
|
+
const calculatedNormalizedPath = normalize(calculatedRelativePath);
|
|
64560
|
+
if (allPossiblePaths.has(calculatedNormalizedPath)) {
|
|
64561
|
+
architectureMap.edges.push({
|
|
64562
|
+
source: normalize(node.id),
|
|
64563
|
+
target: calculatedNormalizedPath,
|
|
64564
|
+
type: imp.type || "import"
|
|
64565
|
+
});
|
|
64566
|
+
resolvedImports++;
|
|
64567
|
+
targetFound = true;
|
|
64568
|
+
}
|
|
64569
|
+
} catch (e) {
|
|
64570
|
+
console.warn(`\u26A0\uFE0F Path calculation failed for import '${imp.source}' in file '${node.id}': ${e.message}`);
|
|
64571
|
+
}
|
|
64572
|
+
}
|
|
64573
|
+
if (!targetFound) {
|
|
64574
|
+
if (imp.source.startsWith("./") || imp.source.startsWith("../")) {
|
|
64575
|
+
const extensions = ["", ".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"];
|
|
64576
|
+
for (const ext of extensions) {
|
|
64577
|
+
let testPath = imp.source;
|
|
64578
|
+
if (!imp.source.endsWith(ext)) {
|
|
64579
|
+
testPath = imp.source + ext;
|
|
64580
|
+
}
|
|
64581
|
+
try {
|
|
64582
|
+
const baseDir = path2.dirname(path2.join(directory, node.id));
|
|
64583
|
+
const calculatedAbsolutePath = path2.resolve(baseDir, testPath);
|
|
64584
|
+
const calculatedRelativePath = path2.relative(directory, calculatedAbsolutePath);
|
|
64585
|
+
const calculatedNormalizedPath = normalize(calculatedRelativePath);
|
|
64586
|
+
if (allPossiblePaths.has(calculatedNormalizedPath)) {
|
|
64587
|
+
architectureMap.edges.push({
|
|
64588
|
+
source: normalize(node.id),
|
|
64589
|
+
target: calculatedNormalizedPath,
|
|
64590
|
+
type: imp.type || "import"
|
|
64591
|
+
});
|
|
64592
|
+
resolvedImports++;
|
|
64593
|
+
targetFound = true;
|
|
64594
|
+
break;
|
|
64595
|
+
}
|
|
64596
|
+
} catch (e) {
|
|
64597
|
+
console.warn(`\u26A0\uFE0F Extension path calculation failed for import '${imp.source}' with extension '${ext}' in file '${node.id}': ${e.message}`);
|
|
64598
|
+
}
|
|
64599
|
+
}
|
|
64600
|
+
}
|
|
64601
|
+
}
|
|
64602
|
+
if (!targetFound) {
|
|
64603
|
+
if (imp.source.startsWith("./") || imp.source.startsWith("../")) {
|
|
64604
|
+
try {
|
|
64605
|
+
const baseDir = path2.dirname(path2.join(directory, node.id));
|
|
64606
|
+
const calculatedAbsolutePath = path2.resolve(baseDir, imp.source);
|
|
64607
|
+
const directoryPath = calculatedAbsolutePath;
|
|
64608
|
+
const indexFiles = ["index.js", "index.ts", "index.jsx", "index.tsx", "index.mjs", "index.cjs"];
|
|
64609
|
+
for (const indexFile of indexFiles) {
|
|
64610
|
+
const indexPath = path2.join(directoryPath, indexFile);
|
|
64611
|
+
const indexRelativePath = path2.relative(directory, indexPath);
|
|
64612
|
+
const indexNormalizedPath = normalize(indexRelativePath);
|
|
64613
|
+
if (allPossiblePaths.has(indexNormalizedPath)) {
|
|
64614
|
+
architectureMap.edges.push({
|
|
64615
|
+
source: normalize(node.id),
|
|
64616
|
+
target: indexNormalizedPath,
|
|
64617
|
+
type: imp.type || "import"
|
|
64618
|
+
});
|
|
64619
|
+
resolvedImports++;
|
|
64620
|
+
targetFound = true;
|
|
64621
|
+
break;
|
|
64622
|
+
}
|
|
64623
|
+
}
|
|
64624
|
+
} catch (e) {
|
|
64625
|
+
console.warn(`\u26A0\uFE0F Index file check failed for import '${imp.source}' in file '${node.id}': ${e.message}`);
|
|
64626
|
+
}
|
|
64627
|
+
}
|
|
64628
|
+
}
|
|
64629
|
+
if (!targetFound) {
|
|
64630
|
+
if (imp.source.startsWith("@") || imp.source.startsWith("/") || !imp.source.startsWith(".")) {
|
|
64631
|
+
const commonSourceDirs = ["src", "app", "lib", "components", "utils", "services", "assets"];
|
|
64632
|
+
for (const srcDir of commonSourceDirs) {
|
|
64633
|
+
const potentialPath = path2.join(srcDir, imp.source);
|
|
64634
|
+
const potentialRelativePath = path2.relative(directory, path2.resolve(directory, potentialPath));
|
|
64635
|
+
const potentialNormalizedPath = normalize(potentialRelativePath);
|
|
64636
|
+
if (allPossiblePaths.has(potentialNormalizedPath)) {
|
|
64637
|
+
architectureMap.edges.push({
|
|
64638
|
+
source: normalize(node.id),
|
|
64639
|
+
target: potentialNormalizedPath,
|
|
64640
|
+
type: imp.type || "import"
|
|
64641
|
+
});
|
|
64642
|
+
resolvedImports++;
|
|
64643
|
+
targetFound = true;
|
|
64644
|
+
break;
|
|
64645
|
+
}
|
|
64646
|
+
const extensions = [
|
|
64647
|
+
".js",
|
|
64648
|
+
".ts",
|
|
64649
|
+
".jsx",
|
|
64650
|
+
".tsx",
|
|
64651
|
+
".mjs",
|
|
64652
|
+
".cjs",
|
|
64653
|
+
"index.js",
|
|
64654
|
+
"index.ts",
|
|
64655
|
+
"index.jsx",
|
|
64656
|
+
"index.tsx",
|
|
64657
|
+
"index.mjs",
|
|
64658
|
+
"index.cjs"
|
|
64659
|
+
];
|
|
64660
|
+
for (const ext of extensions) {
|
|
64661
|
+
let testPath;
|
|
64662
|
+
if (ext.startsWith("index")) {
|
|
64663
|
+
testPath = path2.join(srcDir, imp.source, ext);
|
|
64664
|
+
} else {
|
|
64665
|
+
testPath = path2.join(srcDir, imp.source + ext);
|
|
64666
|
+
}
|
|
64667
|
+
const testRelativePath = path2.relative(directory, path2.resolve(directory, testPath));
|
|
64668
|
+
const testNormalizedPath = normalize(testRelativePath);
|
|
64669
|
+
if (allPossiblePaths.has(testNormalizedPath)) {
|
|
64670
|
+
architectureMap.edges.push({
|
|
64671
|
+
source: normalize(node.id),
|
|
64672
|
+
target: testNormalizedPath,
|
|
64673
|
+
type: imp.type || "import"
|
|
64674
|
+
});
|
|
64675
|
+
resolvedImports++;
|
|
64676
|
+
targetFound = true;
|
|
64677
|
+
break;
|
|
64678
|
+
}
|
|
64679
|
+
}
|
|
64680
|
+
if (targetFound)
|
|
64681
|
+
break;
|
|
64682
|
+
}
|
|
64683
|
+
}
|
|
64684
|
+
}
|
|
64685
|
+
if (!targetFound) {
|
|
64686
|
+
if (imp.source.startsWith("@") || imp.source.startsWith("/")) {
|
|
64687
|
+
try {
|
|
64688
|
+
const parts = imp.source.split("/");
|
|
64689
|
+
if (parts.length > 1) {
|
|
64690
|
+
const dirParts = parts.slice(0, -1);
|
|
64691
|
+
const fileName = parts[parts.length - 1];
|
|
64692
|
+
const dirPath = dirParts.join("/") + "/index";
|
|
64693
|
+
const indexFiles = ["index.js", "index.ts", "index.jsx", "index.tsx", "index.mjs", "index.cjs"];
|
|
64694
|
+
for (const indexFile of indexFiles) {
|
|
64695
|
+
const indexPath = path2.join(dirParts.join("/"), indexFile);
|
|
64696
|
+
const indexRelativePath = path2.relative(directory, path2.resolve(directory, indexPath));
|
|
64697
|
+
const indexNormalizedPath = normalize(indexRelativePath);
|
|
64698
|
+
if (allPossiblePaths.has(indexNormalizedPath)) {
|
|
64699
|
+
architectureMap.edges.push({
|
|
64700
|
+
source: normalize(node.id),
|
|
64701
|
+
target: indexNormalizedPath,
|
|
64702
|
+
type: imp.type || "import"
|
|
64703
|
+
});
|
|
64704
|
+
resolvedImports++;
|
|
64705
|
+
targetFound = true;
|
|
64706
|
+
break;
|
|
64707
|
+
}
|
|
64708
|
+
}
|
|
64709
|
+
}
|
|
64710
|
+
} catch (e) {
|
|
64711
|
+
console.warn(`\u26A0\uFE0F Barrel file check failed for import '${imp.source}' in file '${node.id}': ${e.message}`);
|
|
64712
|
+
}
|
|
64713
|
+
}
|
|
64714
|
+
}
|
|
64715
|
+
if (!targetFound) {
|
|
64716
|
+
for (const possiblePath of allPossiblePaths) {
|
|
64717
|
+
if (possiblePath.toLowerCase() === imp.source.toLowerCase()) {
|
|
64718
|
+
architectureMap.edges.push({
|
|
64719
|
+
source: normalize(node.id),
|
|
64720
|
+
target: possiblePath,
|
|
64721
|
+
type: imp.type || "import"
|
|
64722
|
+
});
|
|
64723
|
+
resolvedImports++;
|
|
64724
|
+
targetFound = true;
|
|
64725
|
+
break;
|
|
64726
|
+
}
|
|
64727
|
+
}
|
|
64728
|
+
}
|
|
64729
|
+
} catch (e) {
|
|
64730
|
+
console.error(`\u274C Critical error processing import '${imp.source}' in file '${node.id}': ${e.message}`);
|
|
64731
|
+
console.error(e.stack);
|
|
64732
|
+
unresolvedImports++;
|
|
64733
|
+
}
|
|
64734
|
+
if (!targetFound) {
|
|
64735
|
+
unresolvedImports++;
|
|
63672
64736
|
}
|
|
63673
64737
|
}
|
|
63674
64738
|
});
|
|
63675
64739
|
}
|
|
63676
64740
|
});
|
|
64741
|
+
console.log("RESOLVED IMPORTS:", resolvedImports);
|
|
64742
|
+
console.log("UNRESOLVED IMPORTS:", unresolvedImports);
|
|
64743
|
+
console.log("IMPORT EDGES CREATED:", architectureMap.edges.length);
|
|
64744
|
+
if (semanticResults && semanticResults.usageEdges) {
|
|
64745
|
+
semanticResults.usageEdges.forEach((usageEdge) => {
|
|
64746
|
+
const sourceExists = architectureMap.nodes.some((n) => n.id === usageEdge.source);
|
|
64747
|
+
const targetExists = architectureMap.nodes.some((n) => n.id === usageEdge.target);
|
|
64748
|
+
if (sourceExists && targetExists) {
|
|
64749
|
+
architectureMap.edges.push({
|
|
64750
|
+
source: normalize(usageEdge.source),
|
|
64751
|
+
target: normalize(usageEdge.target),
|
|
64752
|
+
type: usageEdge.type
|
|
64753
|
+
// 'function_call', 'constructor_call', 'component_usage'
|
|
64754
|
+
});
|
|
64755
|
+
}
|
|
64756
|
+
});
|
|
64757
|
+
}
|
|
64758
|
+
console.log("TOTAL EDGES (with usage):", architectureMap.edges.length);
|
|
63677
64759
|
const reverseGraph = buildReverseDependencyGraph(architectureMap);
|
|
63678
64760
|
const blastRadiusMap = computeBlastRadius(reverseGraph);
|
|
63679
64761
|
architectureMap.nodes.forEach((node) => {
|
|
63680
64762
|
node.metadata.blast_radius = blastRadiusMap[node.id] || 0;
|
|
63681
64763
|
});
|
|
64764
|
+
console.log("BEFORE DEDUPLICATION EDGES:", architectureMap.edges.length);
|
|
63682
64765
|
const validEdges = [];
|
|
63683
64766
|
const edgeSet = /* @__PURE__ */ new Set();
|
|
63684
64767
|
architectureMap.edges.forEach((edge) => {
|
|
@@ -63696,6 +64779,7 @@ var require_scanner = __commonJS({
|
|
|
63696
64779
|
});
|
|
63697
64780
|
}
|
|
63698
64781
|
});
|
|
64782
|
+
console.log("AFTER DEDUPLICATION EDGES:", validEdges.length);
|
|
63699
64783
|
architectureMap.edges = validEdges;
|
|
63700
64784
|
const totalFiles = architectureMap.nodes.length;
|
|
63701
64785
|
const { computeBlastRadiusWithPercentage: computeBlastRadiusWithPercentage2, analyzeCriticality } = require_blastRadius();
|