depwire-cli 0.9.29 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +258 -655
- package/dist/{chunk-FUIZQCYB.js → chunk-5BQLGAUL.js} +6 -6
- package/dist/{chunk-WUSXCZXA.js → chunk-IYKS66CG.js} +763 -156
- package/dist/index.js +4 -4
- package/dist/mcpb-entry.js +2 -2
- package/dist/parser/grammars/tree-sitter-c_sharp.wasm +0 -0
- package/dist/sdk.js +1 -1
- package/package.json +2 -1
|
@@ -32,7 +32,8 @@ function scanDirectory(rootDir, baseDir = rootDir) {
|
|
|
32
32
|
const isGo = entry.endsWith(".go") && !entry.endsWith("_test.go");
|
|
33
33
|
const isRust = entry.endsWith(".rs");
|
|
34
34
|
const isC = entry.endsWith(".c") || entry.endsWith(".h");
|
|
35
|
-
|
|
35
|
+
const isCSharp = entry.endsWith(".cs") || entry.endsWith(".csx") || entry.endsWith(".csproj");
|
|
36
|
+
if (isTypeScript || isJavaScript || isPython || isGo || isRust || isC || isCSharp) {
|
|
36
37
|
files.push(relative(rootDir, fullPath));
|
|
37
38
|
}
|
|
38
39
|
}
|
|
@@ -103,11 +104,11 @@ function findProjectRoot(startDir = process.cwd()) {
|
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
// src/parser/index.ts
|
|
106
|
-
import { readFileSync as
|
|
107
|
-
import { join as
|
|
107
|
+
import { readFileSync as readFileSync6, statSync as statSync3 } from "fs";
|
|
108
|
+
import { join as join9, resolve as resolve4 } from "path";
|
|
108
109
|
|
|
109
110
|
// src/parser/detect.ts
|
|
110
|
-
import { extname as
|
|
111
|
+
import { extname as extname4 } from "path";
|
|
111
112
|
|
|
112
113
|
// src/parser/wasm-init.ts
|
|
113
114
|
import { Parser, Language } from "web-tree-sitter";
|
|
@@ -134,7 +135,8 @@ async function initParser() {
|
|
|
134
135
|
"python": "tree-sitter-python.wasm",
|
|
135
136
|
"go": "tree-sitter-go.wasm",
|
|
136
137
|
"rust": "tree-sitter-rust.wasm",
|
|
137
|
-
"c": "tree-sitter-c.wasm"
|
|
138
|
+
"c": "tree-sitter-c.wasm",
|
|
139
|
+
"c_sharp": "tree-sitter-c_sharp.wasm"
|
|
138
140
|
};
|
|
139
141
|
for (const [name, file] of Object.entries(grammarFiles)) {
|
|
140
142
|
const wasmPath = path.join(grammarsDir, file);
|
|
@@ -2782,6 +2784,564 @@ var cParser = {
|
|
|
2782
2784
|
parseFile: parseCFile
|
|
2783
2785
|
};
|
|
2784
2786
|
|
|
2787
|
+
// src/parser/csharp.ts
|
|
2788
|
+
import { dirname as dirname7, join as join8, resolve as resolve3, basename } from "path";
|
|
2789
|
+
import { existsSync as existsSync8, readdirSync as readdirSync5, statSync as statSync2 } from "fs";
|
|
2790
|
+
function parseCSharpFile(filePath, sourceCode, projectRoot) {
|
|
2791
|
+
if (filePath.endsWith(".csproj")) {
|
|
2792
|
+
return parseCsprojFile(filePath, sourceCode, projectRoot);
|
|
2793
|
+
}
|
|
2794
|
+
const parser = getParser("c_sharp");
|
|
2795
|
+
const tree = parser.parse(sourceCode, null, { bufferSize: 1024 * 1024 });
|
|
2796
|
+
const context = {
|
|
2797
|
+
filePath,
|
|
2798
|
+
projectRoot,
|
|
2799
|
+
sourceCode,
|
|
2800
|
+
symbols: [],
|
|
2801
|
+
edges: [],
|
|
2802
|
+
currentScope: [],
|
|
2803
|
+
currentClass: null,
|
|
2804
|
+
currentNamespace: null,
|
|
2805
|
+
imports: /* @__PURE__ */ new Map(),
|
|
2806
|
+
isCsproj: false
|
|
2807
|
+
};
|
|
2808
|
+
walkNode7(tree.rootNode, context);
|
|
2809
|
+
return {
|
|
2810
|
+
filePath,
|
|
2811
|
+
symbols: context.symbols,
|
|
2812
|
+
edges: context.edges
|
|
2813
|
+
};
|
|
2814
|
+
}
|
|
2815
|
+
function walkNode7(node, context) {
|
|
2816
|
+
processNode7(node, context);
|
|
2817
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
2818
|
+
const child = node.child(i);
|
|
2819
|
+
if (child) {
|
|
2820
|
+
walkNode7(child, context);
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
function processNode7(node, context) {
|
|
2825
|
+
switch (node.type) {
|
|
2826
|
+
case "namespace_declaration":
|
|
2827
|
+
processNamespaceDeclaration(node, context);
|
|
2828
|
+
break;
|
|
2829
|
+
case "file_scoped_namespace_declaration":
|
|
2830
|
+
processFileScopedNamespace(node, context);
|
|
2831
|
+
break;
|
|
2832
|
+
case "class_declaration":
|
|
2833
|
+
processClassDeclaration3(node, context);
|
|
2834
|
+
break;
|
|
2835
|
+
case "interface_declaration":
|
|
2836
|
+
processInterfaceDeclaration2(node, context);
|
|
2837
|
+
break;
|
|
2838
|
+
case "struct_declaration":
|
|
2839
|
+
processStructDeclaration(node, context);
|
|
2840
|
+
break;
|
|
2841
|
+
case "enum_declaration":
|
|
2842
|
+
processEnumDeclaration2(node, context);
|
|
2843
|
+
break;
|
|
2844
|
+
case "record_declaration":
|
|
2845
|
+
processRecordDeclaration(node, context);
|
|
2846
|
+
break;
|
|
2847
|
+
case "delegate_declaration":
|
|
2848
|
+
processDelegateDeclaration(node, context);
|
|
2849
|
+
break;
|
|
2850
|
+
case "method_declaration":
|
|
2851
|
+
processMethodDeclaration2(node, context);
|
|
2852
|
+
break;
|
|
2853
|
+
case "constructor_declaration":
|
|
2854
|
+
processConstructorDeclaration(node, context);
|
|
2855
|
+
break;
|
|
2856
|
+
case "property_declaration":
|
|
2857
|
+
processPropertyDeclaration(node, context);
|
|
2858
|
+
break;
|
|
2859
|
+
case "event_field_declaration":
|
|
2860
|
+
processEventFieldDeclaration(node, context);
|
|
2861
|
+
break;
|
|
2862
|
+
case "indexer_declaration":
|
|
2863
|
+
processIndexerDeclaration(node, context);
|
|
2864
|
+
break;
|
|
2865
|
+
case "using_directive":
|
|
2866
|
+
processUsingDirective(node, context);
|
|
2867
|
+
break;
|
|
2868
|
+
case "global_statement":
|
|
2869
|
+
processGlobalStatement(node, context);
|
|
2870
|
+
break;
|
|
2871
|
+
case "invocation_expression":
|
|
2872
|
+
processCallExpression7(node, context);
|
|
2873
|
+
break;
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
function processNamespaceDeclaration(node, context) {
|
|
2877
|
+
const nameNode = node.childForFieldName("name");
|
|
2878
|
+
if (!nameNode) return;
|
|
2879
|
+
const name = nodeText6(nameNode, context);
|
|
2880
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
2881
|
+
context.symbols.push({
|
|
2882
|
+
id: symbolId,
|
|
2883
|
+
name,
|
|
2884
|
+
kind: "module",
|
|
2885
|
+
filePath: context.filePath,
|
|
2886
|
+
startLine: node.startPosition.row + 1,
|
|
2887
|
+
endLine: node.endPosition.row + 1,
|
|
2888
|
+
exported: true
|
|
2889
|
+
});
|
|
2890
|
+
const oldNamespace = context.currentNamespace;
|
|
2891
|
+
context.currentNamespace = name;
|
|
2892
|
+
context.currentScope.push(name);
|
|
2893
|
+
const body = findChildByType7(node, "declaration_list");
|
|
2894
|
+
if (body) {
|
|
2895
|
+
walkNode7(body, context);
|
|
2896
|
+
}
|
|
2897
|
+
context.currentScope.pop();
|
|
2898
|
+
context.currentNamespace = oldNamespace;
|
|
2899
|
+
}
|
|
2900
|
+
function processFileScopedNamespace(node, context) {
|
|
2901
|
+
const nameNode = node.childForFieldName("name");
|
|
2902
|
+
if (!nameNode) return;
|
|
2903
|
+
const name = nodeText6(nameNode, context);
|
|
2904
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
2905
|
+
context.symbols.push({
|
|
2906
|
+
id: symbolId,
|
|
2907
|
+
name,
|
|
2908
|
+
kind: "module",
|
|
2909
|
+
filePath: context.filePath,
|
|
2910
|
+
startLine: node.startPosition.row + 1,
|
|
2911
|
+
endLine: node.endPosition.row + 1,
|
|
2912
|
+
exported: true
|
|
2913
|
+
});
|
|
2914
|
+
context.currentNamespace = name;
|
|
2915
|
+
}
|
|
2916
|
+
function processClassDeclaration3(node, context) {
|
|
2917
|
+
processTypeDeclaration2(node, context, "class");
|
|
2918
|
+
}
|
|
2919
|
+
function processInterfaceDeclaration2(node, context) {
|
|
2920
|
+
processTypeDeclaration2(node, context, "interface");
|
|
2921
|
+
}
|
|
2922
|
+
function processStructDeclaration(node, context) {
|
|
2923
|
+
processTypeDeclaration2(node, context, "class");
|
|
2924
|
+
}
|
|
2925
|
+
function processRecordDeclaration(node, context) {
|
|
2926
|
+
processTypeDeclaration2(node, context, "class");
|
|
2927
|
+
}
|
|
2928
|
+
function processTypeDeclaration2(node, context, kind) {
|
|
2929
|
+
const nameNode = node.childForFieldName("name");
|
|
2930
|
+
if (!nameNode) return;
|
|
2931
|
+
let name = nodeText6(nameNode, context);
|
|
2932
|
+
const angleBracketIdx = name.indexOf("<");
|
|
2933
|
+
if (angleBracketIdx > 0) {
|
|
2934
|
+
name = name.substring(0, angleBracketIdx);
|
|
2935
|
+
}
|
|
2936
|
+
const exported = hasModifier(node, context, "public") || hasModifier(node, context, "internal");
|
|
2937
|
+
const scope = context.currentClass || void 0;
|
|
2938
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
2939
|
+
context.symbols.push({
|
|
2940
|
+
id: symbolId,
|
|
2941
|
+
name,
|
|
2942
|
+
kind,
|
|
2943
|
+
filePath: context.filePath,
|
|
2944
|
+
startLine: node.startPosition.row + 1,
|
|
2945
|
+
endLine: node.endPosition.row + 1,
|
|
2946
|
+
exported,
|
|
2947
|
+
scope
|
|
2948
|
+
});
|
|
2949
|
+
const baseList = findChildByType7(node, "base_list");
|
|
2950
|
+
if (baseList) {
|
|
2951
|
+
for (let i = 0; i < baseList.childCount; i++) {
|
|
2952
|
+
const child = baseList.child(i);
|
|
2953
|
+
if (!child) continue;
|
|
2954
|
+
if (child.type === "simple_base_type" || child.type === "identifier" || child.type === "generic_name" || child.type === "qualified_name") {
|
|
2955
|
+
let baseName = extractBaseTypeName(child, context);
|
|
2956
|
+
if (baseName) {
|
|
2957
|
+
const baseId = resolveSymbol6(baseName, context);
|
|
2958
|
+
if (baseId) {
|
|
2959
|
+
const edgeKind = baseName.startsWith("I") && baseName.length > 1 && baseName[1] === baseName[1].toUpperCase() ? "implements" : "inherits";
|
|
2960
|
+
context.edges.push({
|
|
2961
|
+
source: symbolId,
|
|
2962
|
+
target: baseId,
|
|
2963
|
+
kind: edgeKind,
|
|
2964
|
+
filePath: context.filePath,
|
|
2965
|
+
line: child.startPosition.row + 1
|
|
2966
|
+
});
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
const oldClass = context.currentClass;
|
|
2973
|
+
context.currentClass = name;
|
|
2974
|
+
context.currentScope.push(name);
|
|
2975
|
+
const body = findChildByType7(node, "declaration_list");
|
|
2976
|
+
if (body) {
|
|
2977
|
+
walkNode7(body, context);
|
|
2978
|
+
}
|
|
2979
|
+
context.currentScope.pop();
|
|
2980
|
+
context.currentClass = oldClass;
|
|
2981
|
+
}
|
|
2982
|
+
function processEnumDeclaration2(node, context) {
|
|
2983
|
+
const nameNode = node.childForFieldName("name");
|
|
2984
|
+
if (!nameNode) return;
|
|
2985
|
+
const name = nodeText6(nameNode, context);
|
|
2986
|
+
const exported = hasModifier(node, context, "public") || hasModifier(node, context, "internal");
|
|
2987
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
2988
|
+
context.symbols.push({
|
|
2989
|
+
id: symbolId,
|
|
2990
|
+
name,
|
|
2991
|
+
kind: "enum",
|
|
2992
|
+
filePath: context.filePath,
|
|
2993
|
+
startLine: node.startPosition.row + 1,
|
|
2994
|
+
endLine: node.endPosition.row + 1,
|
|
2995
|
+
exported
|
|
2996
|
+
});
|
|
2997
|
+
const body = findChildByType7(node, "enum_member_declaration_list");
|
|
2998
|
+
if (body) {
|
|
2999
|
+
const members = findChildrenByType2(body, "enum_member_declaration");
|
|
3000
|
+
for (const member of members) {
|
|
3001
|
+
const memberNameNode = member.childForFieldName("name");
|
|
3002
|
+
if (!memberNameNode) continue;
|
|
3003
|
+
const memberName = nodeText6(memberNameNode, context);
|
|
3004
|
+
const memberId = `${context.filePath}::${name}.${memberName}`;
|
|
3005
|
+
context.symbols.push({
|
|
3006
|
+
id: memberId,
|
|
3007
|
+
name: memberName,
|
|
3008
|
+
kind: "constant",
|
|
3009
|
+
filePath: context.filePath,
|
|
3010
|
+
startLine: member.startPosition.row + 1,
|
|
3011
|
+
endLine: member.endPosition.row + 1,
|
|
3012
|
+
exported,
|
|
3013
|
+
scope: name
|
|
3014
|
+
});
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
function processDelegateDeclaration(node, context) {
|
|
3019
|
+
const nameNode = node.childForFieldName("name");
|
|
3020
|
+
if (!nameNode) return;
|
|
3021
|
+
let name = nodeText6(nameNode, context);
|
|
3022
|
+
const angleBracketIdx = name.indexOf("<");
|
|
3023
|
+
if (angleBracketIdx > 0) name = name.substring(0, angleBracketIdx);
|
|
3024
|
+
const exported = hasModifier(node, context, "public") || hasModifier(node, context, "internal");
|
|
3025
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
3026
|
+
context.symbols.push({
|
|
3027
|
+
id: symbolId,
|
|
3028
|
+
name,
|
|
3029
|
+
kind: "type_alias",
|
|
3030
|
+
filePath: context.filePath,
|
|
3031
|
+
startLine: node.startPosition.row + 1,
|
|
3032
|
+
endLine: node.endPosition.row + 1,
|
|
3033
|
+
exported
|
|
3034
|
+
});
|
|
3035
|
+
}
|
|
3036
|
+
function processMethodDeclaration2(node, context) {
|
|
3037
|
+
const nameNode = node.childForFieldName("name");
|
|
3038
|
+
if (!nameNode) return;
|
|
3039
|
+
const name = nodeText6(nameNode, context);
|
|
3040
|
+
const exported = hasModifier(node, context, "public");
|
|
3041
|
+
const scope = context.currentClass || void 0;
|
|
3042
|
+
const symbolId = scope ? `${context.filePath}::${scope}.${name}` : `${context.filePath}::${name}`;
|
|
3043
|
+
context.symbols.push({
|
|
3044
|
+
id: symbolId,
|
|
3045
|
+
name,
|
|
3046
|
+
kind: context.currentClass ? "method" : "function",
|
|
3047
|
+
filePath: context.filePath,
|
|
3048
|
+
startLine: node.startPosition.row + 1,
|
|
3049
|
+
endLine: node.endPosition.row + 1,
|
|
3050
|
+
exported,
|
|
3051
|
+
scope
|
|
3052
|
+
});
|
|
3053
|
+
const scopeName = scope ? `${scope}.${name}` : name;
|
|
3054
|
+
context.currentScope.push(scopeName);
|
|
3055
|
+
const body = node.childForFieldName("body");
|
|
3056
|
+
if (body) {
|
|
3057
|
+
walkNode7(body, context);
|
|
3058
|
+
}
|
|
3059
|
+
context.currentScope.pop();
|
|
3060
|
+
}
|
|
3061
|
+
function processConstructorDeclaration(node, context) {
|
|
3062
|
+
const nameNode = node.childForFieldName("name");
|
|
3063
|
+
if (!nameNode) return;
|
|
3064
|
+
const name = nodeText6(nameNode, context);
|
|
3065
|
+
const exported = hasModifier(node, context, "public");
|
|
3066
|
+
const scope = context.currentClass || void 0;
|
|
3067
|
+
const symbolId = scope ? `${context.filePath}::${scope}.${name}` : `${context.filePath}::${name}`;
|
|
3068
|
+
context.symbols.push({
|
|
3069
|
+
id: symbolId,
|
|
3070
|
+
name,
|
|
3071
|
+
kind: "method",
|
|
3072
|
+
filePath: context.filePath,
|
|
3073
|
+
startLine: node.startPosition.row + 1,
|
|
3074
|
+
endLine: node.endPosition.row + 1,
|
|
3075
|
+
exported,
|
|
3076
|
+
scope
|
|
3077
|
+
});
|
|
3078
|
+
const scopeName = scope ? `${scope}.${name}` : name;
|
|
3079
|
+
context.currentScope.push(scopeName);
|
|
3080
|
+
const body = node.childForFieldName("body");
|
|
3081
|
+
if (body) {
|
|
3082
|
+
walkNode7(body, context);
|
|
3083
|
+
}
|
|
3084
|
+
context.currentScope.pop();
|
|
3085
|
+
}
|
|
3086
|
+
function processPropertyDeclaration(node, context) {
|
|
3087
|
+
const nameNode = node.childForFieldName("name");
|
|
3088
|
+
if (!nameNode) return;
|
|
3089
|
+
const name = nodeText6(nameNode, context);
|
|
3090
|
+
const exported = hasModifier(node, context, "public");
|
|
3091
|
+
const scope = context.currentClass || void 0;
|
|
3092
|
+
const symbolId = scope ? `${context.filePath}::${scope}.${name}` : `${context.filePath}::${name}`;
|
|
3093
|
+
context.symbols.push({
|
|
3094
|
+
id: symbolId,
|
|
3095
|
+
name,
|
|
3096
|
+
kind: "property",
|
|
3097
|
+
filePath: context.filePath,
|
|
3098
|
+
startLine: node.startPosition.row + 1,
|
|
3099
|
+
endLine: node.endPosition.row + 1,
|
|
3100
|
+
exported,
|
|
3101
|
+
scope
|
|
3102
|
+
});
|
|
3103
|
+
}
|
|
3104
|
+
function processEventFieldDeclaration(node, context) {
|
|
3105
|
+
const varDecl = findChildByType7(node, "variable_declaration");
|
|
3106
|
+
if (!varDecl) return;
|
|
3107
|
+
const declarator = findChildByType7(varDecl, "variable_declarator");
|
|
3108
|
+
if (!declarator) return;
|
|
3109
|
+
const nameNode = declarator.childForFieldName("name") || findChildByType7(declarator, "identifier");
|
|
3110
|
+
if (!nameNode) return;
|
|
3111
|
+
const name = nodeText6(nameNode, context);
|
|
3112
|
+
const exported = hasModifier(node, context, "public");
|
|
3113
|
+
const scope = context.currentClass || void 0;
|
|
3114
|
+
const symbolId = scope ? `${context.filePath}::${scope}.${name}` : `${context.filePath}::${name}`;
|
|
3115
|
+
context.symbols.push({
|
|
3116
|
+
id: symbolId,
|
|
3117
|
+
name,
|
|
3118
|
+
kind: "property",
|
|
3119
|
+
filePath: context.filePath,
|
|
3120
|
+
startLine: node.startPosition.row + 1,
|
|
3121
|
+
endLine: node.endPosition.row + 1,
|
|
3122
|
+
exported,
|
|
3123
|
+
scope
|
|
3124
|
+
});
|
|
3125
|
+
}
|
|
3126
|
+
function processIndexerDeclaration(node, context) {
|
|
3127
|
+
const exported = hasModifier(node, context, "public");
|
|
3128
|
+
const scope = context.currentClass || void 0;
|
|
3129
|
+
const name = "this[]";
|
|
3130
|
+
const symbolId = scope ? `${context.filePath}::${scope}.${name}` : `${context.filePath}::${name}`;
|
|
3131
|
+
context.symbols.push({
|
|
3132
|
+
id: symbolId,
|
|
3133
|
+
name,
|
|
3134
|
+
kind: "property",
|
|
3135
|
+
filePath: context.filePath,
|
|
3136
|
+
startLine: node.startPosition.row + 1,
|
|
3137
|
+
endLine: node.endPosition.row + 1,
|
|
3138
|
+
exported,
|
|
3139
|
+
scope
|
|
3140
|
+
});
|
|
3141
|
+
}
|
|
3142
|
+
function processUsingDirective(node, context) {
|
|
3143
|
+
const nameNode = node.childForFieldName("name");
|
|
3144
|
+
if (!nameNode) return;
|
|
3145
|
+
const name = nodeText6(nameNode, context);
|
|
3146
|
+
const resolvedPath = resolveCSharpNamespace(name, context.filePath, context.projectRoot);
|
|
3147
|
+
if (resolvedPath) {
|
|
3148
|
+
const sourceId = `${context.filePath}::__file__`;
|
|
3149
|
+
const targetId = `${resolvedPath}::__file__`;
|
|
3150
|
+
context.edges.push({
|
|
3151
|
+
source: sourceId,
|
|
3152
|
+
target: targetId,
|
|
3153
|
+
kind: "imports",
|
|
3154
|
+
filePath: context.filePath,
|
|
3155
|
+
line: node.startPosition.row + 1
|
|
3156
|
+
});
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
function processGlobalStatement(node, context) {
|
|
3160
|
+
const symbolId = `${context.filePath}::__toplevel__`;
|
|
3161
|
+
if (context.symbols.find((s) => s.id === symbolId)) return;
|
|
3162
|
+
context.symbols.push({
|
|
3163
|
+
id: symbolId,
|
|
3164
|
+
name: "__toplevel__",
|
|
3165
|
+
kind: "function",
|
|
3166
|
+
filePath: context.filePath,
|
|
3167
|
+
startLine: node.startPosition.row + 1,
|
|
3168
|
+
endLine: node.endPosition.row + 1,
|
|
3169
|
+
exported: true
|
|
3170
|
+
});
|
|
3171
|
+
}
|
|
3172
|
+
function processCallExpression7(node, context) {
|
|
3173
|
+
const functionNode = node.childForFieldName("function");
|
|
3174
|
+
if (!functionNode) return;
|
|
3175
|
+
let calleeName = null;
|
|
3176
|
+
if (functionNode.type === "identifier") {
|
|
3177
|
+
calleeName = nodeText6(functionNode, context);
|
|
3178
|
+
} else if (functionNode.type === "member_access_expression") {
|
|
3179
|
+
const nameNode = functionNode.childForFieldName("name");
|
|
3180
|
+
if (nameNode) {
|
|
3181
|
+
calleeName = nodeText6(nameNode, context);
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
if (!calleeName) return;
|
|
3185
|
+
const builtins = ["ToString", "Equals", "GetHashCode", "GetType", "Console", "Write", "WriteLine", "Format", "Parse", "TryParse"];
|
|
3186
|
+
if (builtins.includes(calleeName)) return;
|
|
3187
|
+
const callerId = getCurrentSymbolId7(context);
|
|
3188
|
+
if (!callerId) return;
|
|
3189
|
+
const calleeId = resolveSymbol6(calleeName, context);
|
|
3190
|
+
if (calleeId) {
|
|
3191
|
+
context.edges.push({
|
|
3192
|
+
source: callerId,
|
|
3193
|
+
target: calleeId,
|
|
3194
|
+
kind: "calls",
|
|
3195
|
+
filePath: context.filePath,
|
|
3196
|
+
line: node.startPosition.row + 1
|
|
3197
|
+
});
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
function parseCsprojFile(filePath, sourceCode, projectRoot) {
|
|
3201
|
+
const symbols = [];
|
|
3202
|
+
const edges = [];
|
|
3203
|
+
const lines = sourceCode.split("\n");
|
|
3204
|
+
const projectName = basename(filePath, ".csproj");
|
|
3205
|
+
symbols.push({
|
|
3206
|
+
id: `${filePath}::${projectName}`,
|
|
3207
|
+
name: projectName,
|
|
3208
|
+
kind: "module",
|
|
3209
|
+
filePath,
|
|
3210
|
+
startLine: 1,
|
|
3211
|
+
endLine: lines.length,
|
|
3212
|
+
exported: true
|
|
3213
|
+
});
|
|
3214
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3215
|
+
const line = lines[i];
|
|
3216
|
+
const lineNum = i + 1;
|
|
3217
|
+
const projectRefMatch = line.match(/<ProjectReference\s+Include\s*=\s*"([^"]+)"/);
|
|
3218
|
+
if (projectRefMatch) {
|
|
3219
|
+
const refPath = projectRefMatch[1];
|
|
3220
|
+
const csprojDir = dirname7(join8(projectRoot, filePath));
|
|
3221
|
+
const resolvedRef = resolve3(csprojDir, refPath);
|
|
3222
|
+
const relativeRef = resolvedRef.startsWith(projectRoot + "/") ? resolvedRef.substring(projectRoot.length + 1) : null;
|
|
3223
|
+
if (relativeRef && existsSync8(resolvedRef)) {
|
|
3224
|
+
edges.push({
|
|
3225
|
+
source: `${filePath}::__file__`,
|
|
3226
|
+
target: `${relativeRef}::__file__`,
|
|
3227
|
+
kind: "imports",
|
|
3228
|
+
filePath,
|
|
3229
|
+
line: lineNum
|
|
3230
|
+
});
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
const packageRefMatch = line.match(/<PackageReference\s+Include\s*=\s*"([^"]+)"/);
|
|
3234
|
+
if (packageRefMatch) {
|
|
3235
|
+
const packageName = packageRefMatch[1];
|
|
3236
|
+
const versionMatch = line.match(/Version\s*=\s*"([^"]+)"/);
|
|
3237
|
+
const version = versionMatch ? versionMatch[1] : "unknown";
|
|
3238
|
+
symbols.push({
|
|
3239
|
+
id: `${filePath}::pkg:${packageName}`,
|
|
3240
|
+
name: `${packageName}@${version}`,
|
|
3241
|
+
kind: "import",
|
|
3242
|
+
filePath,
|
|
3243
|
+
startLine: lineNum,
|
|
3244
|
+
endLine: lineNum,
|
|
3245
|
+
exported: false
|
|
3246
|
+
});
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
return { filePath, symbols, edges };
|
|
3250
|
+
}
|
|
3251
|
+
function resolveCSharpNamespace(namespace, currentFile, projectRoot) {
|
|
3252
|
+
const namespacePath = namespace.replace(/\./g, "/");
|
|
3253
|
+
const candidates = [
|
|
3254
|
+
join8(projectRoot, namespacePath),
|
|
3255
|
+
join8(projectRoot, "src", namespacePath)
|
|
3256
|
+
];
|
|
3257
|
+
for (const candidate of candidates) {
|
|
3258
|
+
if (existsSync8(candidate)) {
|
|
3259
|
+
try {
|
|
3260
|
+
const stats = statSync2(candidate);
|
|
3261
|
+
if (stats.isDirectory()) {
|
|
3262
|
+
const csFiles = readdirSync5(candidate).filter((f) => f.endsWith(".cs"));
|
|
3263
|
+
if (csFiles.length > 0) {
|
|
3264
|
+
const fullPath = join8(candidate, csFiles[0]);
|
|
3265
|
+
return fullPath.substring(projectRoot.length + 1);
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
} catch {
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
}
|
|
3272
|
+
return null;
|
|
3273
|
+
}
|
|
3274
|
+
function resolveSymbol6(name, context) {
|
|
3275
|
+
if (context.imports.has(name)) {
|
|
3276
|
+
return context.imports.get(name) || null;
|
|
3277
|
+
}
|
|
3278
|
+
const currentFileId = `${context.filePath}::${name}`;
|
|
3279
|
+
if (context.symbols.find((s) => s.id === currentFileId)) {
|
|
3280
|
+
return currentFileId;
|
|
3281
|
+
}
|
|
3282
|
+
if (context.currentClass) {
|
|
3283
|
+
const classMethodId = `${context.filePath}::${context.currentClass}.${name}`;
|
|
3284
|
+
if (context.symbols.find((s) => s.id === classMethodId)) {
|
|
3285
|
+
return classMethodId;
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3288
|
+
return null;
|
|
3289
|
+
}
|
|
3290
|
+
function hasModifier(node, context, modifier) {
|
|
3291
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
3292
|
+
const child = node.child(i);
|
|
3293
|
+
if (child && child.type === "modifier" && nodeText6(child, context) === modifier) {
|
|
3294
|
+
return true;
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
if (modifier === "internal") {
|
|
3298
|
+
const hasExplicitAccess = ["public", "private", "protected", "internal"].some((m) => {
|
|
3299
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
3300
|
+
const child = node.child(i);
|
|
3301
|
+
if (child && child.type === "modifier" && nodeText6(child, context) === m) return true;
|
|
3302
|
+
}
|
|
3303
|
+
return false;
|
|
3304
|
+
});
|
|
3305
|
+
return !hasExplicitAccess;
|
|
3306
|
+
}
|
|
3307
|
+
return false;
|
|
3308
|
+
}
|
|
3309
|
+
function extractBaseTypeName(node, context) {
|
|
3310
|
+
const text = nodeText6(node, context).trim();
|
|
3311
|
+
if (!text || text === ":" || text === ",") return null;
|
|
3312
|
+
const angleBracketIdx = text.indexOf("<");
|
|
3313
|
+
const name = angleBracketIdx > 0 ? text.substring(0, angleBracketIdx) : text;
|
|
3314
|
+
const dotIdx = name.lastIndexOf(".");
|
|
3315
|
+
return dotIdx >= 0 ? name.substring(dotIdx + 1) : name;
|
|
3316
|
+
}
|
|
3317
|
+
function findChildByType7(node, type) {
|
|
3318
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
3319
|
+
const child = node.child(i);
|
|
3320
|
+
if (child && child.type === type) return child;
|
|
3321
|
+
}
|
|
3322
|
+
return null;
|
|
3323
|
+
}
|
|
3324
|
+
function findChildrenByType2(node, type) {
|
|
3325
|
+
const results = [];
|
|
3326
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
3327
|
+
const child = node.child(i);
|
|
3328
|
+
if (child && child.type === type) results.push(child);
|
|
3329
|
+
}
|
|
3330
|
+
return results;
|
|
3331
|
+
}
|
|
3332
|
+
function nodeText6(node, context) {
|
|
3333
|
+
return context.sourceCode.substring(node.startIndex, node.endIndex);
|
|
3334
|
+
}
|
|
3335
|
+
function getCurrentSymbolId7(context) {
|
|
3336
|
+
if (context.currentScope.length === 0) return null;
|
|
3337
|
+
return `${context.filePath}::${context.currentScope[context.currentScope.length - 1]}`;
|
|
3338
|
+
}
|
|
3339
|
+
var csharpParser = {
|
|
3340
|
+
name: "csharp",
|
|
3341
|
+
extensions: [".cs", ".csx", ".csproj"],
|
|
3342
|
+
parseFile: parseCSharpFile
|
|
3343
|
+
};
|
|
3344
|
+
|
|
2785
3345
|
// src/parser/detect.ts
|
|
2786
3346
|
var parsers = [
|
|
2787
3347
|
typescriptParser,
|
|
@@ -2789,10 +3349,11 @@ var parsers = [
|
|
|
2789
3349
|
javascriptParser,
|
|
2790
3350
|
goParser,
|
|
2791
3351
|
rustParser,
|
|
2792
|
-
cParser
|
|
3352
|
+
cParser,
|
|
3353
|
+
csharpParser
|
|
2793
3354
|
];
|
|
2794
3355
|
function getParserForFile(filePath) {
|
|
2795
|
-
const ext =
|
|
3356
|
+
const ext = extname4(filePath).toLowerCase();
|
|
2796
3357
|
return parsers.find((p) => p.extensions.includes(ext)) || null;
|
|
2797
3358
|
}
|
|
2798
3359
|
|
|
@@ -2801,7 +3362,7 @@ import { minimatch } from "minimatch";
|
|
|
2801
3362
|
var MAX_FILE_SIZE = 1e6;
|
|
2802
3363
|
function shouldParseFile(fullPath) {
|
|
2803
3364
|
try {
|
|
2804
|
-
const stats =
|
|
3365
|
+
const stats = statSync3(fullPath);
|
|
2805
3366
|
if (stats.size > MAX_FILE_SIZE) {
|
|
2806
3367
|
console.error(`[Parser] Skipping ${fullPath} \u2014 file too large (${(stats.size / 1024).toFixed(0)}KB)`);
|
|
2807
3368
|
return false;
|
|
@@ -2819,8 +3380,8 @@ async function parseProject(projectRoot, options) {
|
|
|
2819
3380
|
let errorFiles = 0;
|
|
2820
3381
|
for (const file of files) {
|
|
2821
3382
|
try {
|
|
2822
|
-
const fullPath =
|
|
2823
|
-
if (!
|
|
3383
|
+
const fullPath = join9(projectRoot, file);
|
|
3384
|
+
if (!resolve4(fullPath).startsWith(resolve4(projectRoot))) {
|
|
2824
3385
|
skippedFiles++;
|
|
2825
3386
|
continue;
|
|
2826
3387
|
}
|
|
@@ -2849,7 +3410,7 @@ async function parseProject(projectRoot, options) {
|
|
|
2849
3410
|
skippedFiles++;
|
|
2850
3411
|
continue;
|
|
2851
3412
|
}
|
|
2852
|
-
const sourceCode =
|
|
3413
|
+
const sourceCode = readFileSync6(fullPath, "utf-8");
|
|
2853
3414
|
const parsed = parser.parseFile(file, sourceCode, projectRoot);
|
|
2854
3415
|
parsedFiles.push(parsed);
|
|
2855
3416
|
} catch (err) {
|
|
@@ -2872,13 +3433,14 @@ async function parseProject(projectRoot, options) {
|
|
|
2872
3433
|
}
|
|
2873
3434
|
|
|
2874
3435
|
// src/cross-language/detectors/rest-api.ts
|
|
2875
|
-
import { readFileSync as
|
|
2876
|
-
import { join as
|
|
3436
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
3437
|
+
import { join as join10, resolve as resolve5 } from "path";
|
|
2877
3438
|
function getLanguage(filePath) {
|
|
2878
3439
|
if (filePath.endsWith(".ts") || filePath.endsWith(".tsx")) return "typescript";
|
|
2879
3440
|
if (filePath.endsWith(".js") || filePath.endsWith(".jsx") || filePath.endsWith(".mjs") || filePath.endsWith(".cjs")) return "javascript";
|
|
2880
3441
|
if (filePath.endsWith(".py")) return "python";
|
|
2881
3442
|
if (filePath.endsWith(".go")) return "go";
|
|
3443
|
+
if (filePath.endsWith(".cs") || filePath.endsWith(".csx")) return "csharp";
|
|
2882
3444
|
return "unknown";
|
|
2883
3445
|
}
|
|
2884
3446
|
function normalizePath(routePath) {
|
|
@@ -3015,6 +3577,49 @@ function extractRouteDefinitions(source, filePath) {
|
|
|
3015
3577
|
}
|
|
3016
3578
|
}
|
|
3017
3579
|
}
|
|
3580
|
+
if (lang === "csharp") {
|
|
3581
|
+
const attrMatch = line.match(/\[\s*Http(Get|Post|Put|Delete|Patch)\s*\(\s*"([^"]+)"\s*\)\s*\]/);
|
|
3582
|
+
if (attrMatch) {
|
|
3583
|
+
routes.push({
|
|
3584
|
+
method: attrMatch[1].toUpperCase(),
|
|
3585
|
+
path: attrMatch[2],
|
|
3586
|
+
normalizedPath: normalizePath(attrMatch[2]),
|
|
3587
|
+
file: filePath,
|
|
3588
|
+
line: i + 1
|
|
3589
|
+
});
|
|
3590
|
+
}
|
|
3591
|
+
const routeAttrMatch = line.match(/\[\s*Route\s*\(\s*"([^"]+)"\s*\)\s*\]/);
|
|
3592
|
+
if (routeAttrMatch) {
|
|
3593
|
+
let routePath = routeAttrMatch[1];
|
|
3594
|
+
if (routePath.includes("[controller]")) {
|
|
3595
|
+
const classMatch = source.match(/class\s+(\w+?)Controller\s/);
|
|
3596
|
+
if (classMatch) {
|
|
3597
|
+
routePath = routePath.replace("[controller]", classMatch[1].toLowerCase());
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3600
|
+
if (!routePath.startsWith("/")) routePath = "/" + routePath;
|
|
3601
|
+
routes.push({
|
|
3602
|
+
method: "ANY",
|
|
3603
|
+
path: routePath,
|
|
3604
|
+
normalizedPath: normalizePath(routePath),
|
|
3605
|
+
file: filePath,
|
|
3606
|
+
line: i + 1
|
|
3607
|
+
});
|
|
3608
|
+
}
|
|
3609
|
+
const minimalMatch = line.match(/app\s*\.\s*Map(Get|Post|Put|Delete|Patch)\s*\(\s*"([^"]+)"/);
|
|
3610
|
+
if (minimalMatch) {
|
|
3611
|
+
const path6 = minimalMatch[2];
|
|
3612
|
+
if (path6.startsWith("/")) {
|
|
3613
|
+
routes.push({
|
|
3614
|
+
method: minimalMatch[1].toUpperCase(),
|
|
3615
|
+
path: path6,
|
|
3616
|
+
normalizedPath: normalizePath(path6),
|
|
3617
|
+
file: filePath,
|
|
3618
|
+
line: i + 1
|
|
3619
|
+
});
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
}
|
|
3018
3623
|
}
|
|
3019
3624
|
return routes;
|
|
3020
3625
|
}
|
|
@@ -3042,7 +3647,7 @@ function getConfidence(callPath, callMethod, routePath, routeMethod) {
|
|
|
3042
3647
|
const normalizedCall = normalizePath(stripTrailingSlash(callPath));
|
|
3043
3648
|
const normalizedRoute = normalizePath(stripTrailingSlash(routePath));
|
|
3044
3649
|
const exactPath = normalizedCall === normalizedRoute;
|
|
3045
|
-
const methodMatch = callMethod === routeMethod;
|
|
3650
|
+
const methodMatch = callMethod === routeMethod || routeMethod === "ANY";
|
|
3046
3651
|
if (exactPath && methodMatch) return "high";
|
|
3047
3652
|
if (exactPath) return "medium";
|
|
3048
3653
|
if (methodMatch) return "medium";
|
|
@@ -3053,11 +3658,11 @@ function detectRestApiEdges(files, projectRoot) {
|
|
|
3053
3658
|
const allCalls = [];
|
|
3054
3659
|
const allRoutes = [];
|
|
3055
3660
|
for (const file of files) {
|
|
3056
|
-
const fullPath =
|
|
3057
|
-
if (!
|
|
3661
|
+
const fullPath = join10(projectRoot, file.filePath);
|
|
3662
|
+
if (!resolve5(fullPath).startsWith(resolve5(projectRoot))) continue;
|
|
3058
3663
|
let source;
|
|
3059
3664
|
try {
|
|
3060
|
-
source =
|
|
3665
|
+
source = readFileSync7(fullPath, "utf-8");
|
|
3061
3666
|
} catch {
|
|
3062
3667
|
continue;
|
|
3063
3668
|
}
|
|
@@ -3093,8 +3698,8 @@ function detectRestApiEdges(files, projectRoot) {
|
|
|
3093
3698
|
}
|
|
3094
3699
|
|
|
3095
3700
|
// src/cross-language/detectors/subprocess.ts
|
|
3096
|
-
import { readFileSync as
|
|
3097
|
-
import { join as
|
|
3701
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
3702
|
+
import { join as join11, resolve as resolve6, basename as basename2 } from "path";
|
|
3098
3703
|
var SCRIPT_EXTENSIONS = [".py", ".js", ".ts", ".go", ".rs"];
|
|
3099
3704
|
function getLanguage2(filePath) {
|
|
3100
3705
|
if (filePath.endsWith(".ts") || filePath.endsWith(".tsx")) return "typescript";
|
|
@@ -3193,16 +3798,16 @@ function detectSubprocessEdges(files, projectRoot) {
|
|
|
3193
3798
|
const knownFiles = new Set(files.map((f) => f.filePath));
|
|
3194
3799
|
const basenameMap = /* @__PURE__ */ new Map();
|
|
3195
3800
|
for (const f of files) {
|
|
3196
|
-
const base =
|
|
3801
|
+
const base = basename2(f.filePath);
|
|
3197
3802
|
if (!basenameMap.has(base)) basenameMap.set(base, []);
|
|
3198
3803
|
basenameMap.get(base).push(f.filePath);
|
|
3199
3804
|
}
|
|
3200
3805
|
for (const file of files) {
|
|
3201
|
-
const fullPath =
|
|
3202
|
-
if (!
|
|
3806
|
+
const fullPath = join11(projectRoot, file.filePath);
|
|
3807
|
+
if (!resolve6(fullPath).startsWith(resolve6(projectRoot))) continue;
|
|
3203
3808
|
let source;
|
|
3204
3809
|
try {
|
|
3205
|
-
source =
|
|
3810
|
+
source = readFileSync8(fullPath, "utf-8");
|
|
3206
3811
|
} catch {
|
|
3207
3812
|
continue;
|
|
3208
3813
|
}
|
|
@@ -3214,7 +3819,7 @@ function detectSubprocessEdges(files, projectRoot) {
|
|
|
3214
3819
|
targetFile = call.calledFile;
|
|
3215
3820
|
confidence = "high";
|
|
3216
3821
|
} else {
|
|
3217
|
-
const base =
|
|
3822
|
+
const base = basename2(call.calledFile);
|
|
3218
3823
|
const candidates = basenameMap.get(base);
|
|
3219
3824
|
if (candidates && candidates.length > 0) {
|
|
3220
3825
|
const exactCandidate = candidates.find((c) => c.endsWith(call.calledFile));
|
|
@@ -3593,7 +4198,7 @@ function getArchitectureSummary(graph) {
|
|
|
3593
4198
|
}
|
|
3594
4199
|
|
|
3595
4200
|
// src/health/metrics.ts
|
|
3596
|
-
import { dirname as
|
|
4201
|
+
import { dirname as dirname8 } from "path";
|
|
3597
4202
|
function scoreToGrade(score) {
|
|
3598
4203
|
if (score >= 90) return "A";
|
|
3599
4204
|
if (score >= 80) return "B";
|
|
@@ -3626,8 +4231,8 @@ function calculateCouplingScore(graph) {
|
|
|
3626
4231
|
totalEdges++;
|
|
3627
4232
|
fileConnections.set(sourceAttrs.filePath, (fileConnections.get(sourceAttrs.filePath) || 0) + 1);
|
|
3628
4233
|
fileConnections.set(targetAttrs.filePath, (fileConnections.get(targetAttrs.filePath) || 0) + 1);
|
|
3629
|
-
const sourceDir =
|
|
3630
|
-
const targetDir =
|
|
4234
|
+
const sourceDir = dirname8(sourceAttrs.filePath).split("/")[0];
|
|
4235
|
+
const targetDir = dirname8(targetAttrs.filePath).split("/")[0];
|
|
3631
4236
|
if (sourceDir !== targetDir) {
|
|
3632
4237
|
crossDirEdges++;
|
|
3633
4238
|
}
|
|
@@ -3674,8 +4279,8 @@ function calculateCohesionScore(graph) {
|
|
|
3674
4279
|
const sourceAttrs = graph.getNodeAttributes(source);
|
|
3675
4280
|
const targetAttrs = graph.getNodeAttributes(target);
|
|
3676
4281
|
if (sourceAttrs.filePath !== targetAttrs.filePath) {
|
|
3677
|
-
const sourceDir =
|
|
3678
|
-
const targetDir =
|
|
4282
|
+
const sourceDir = dirname8(sourceAttrs.filePath);
|
|
4283
|
+
const targetDir = dirname8(targetAttrs.filePath);
|
|
3679
4284
|
if (!dirEdges.has(sourceDir)) {
|
|
3680
4285
|
dirEdges.set(sourceDir, { internal: 0, total: 0 });
|
|
3681
4286
|
}
|
|
@@ -3957,8 +4562,8 @@ function calculateDepthScore(graph) {
|
|
|
3957
4562
|
}
|
|
3958
4563
|
|
|
3959
4564
|
// src/health/index.ts
|
|
3960
|
-
import { readFileSync as
|
|
3961
|
-
import { dirname as
|
|
4565
|
+
import { readFileSync as readFileSync9, writeFileSync, existsSync as existsSync9, mkdirSync } from "fs";
|
|
4566
|
+
import { dirname as dirname9, resolve as resolve7 } from "path";
|
|
3962
4567
|
function calculateHealthScore(graph, projectRoot) {
|
|
3963
4568
|
const coupling = calculateCouplingScore(graph);
|
|
3964
4569
|
const cohesion = calculateCohesionScore(graph);
|
|
@@ -4057,8 +4662,8 @@ function getHealthTrend(projectRoot, currentScore) {
|
|
|
4057
4662
|
}
|
|
4058
4663
|
}
|
|
4059
4664
|
function saveHealthHistory(projectRoot, report) {
|
|
4060
|
-
const resolvedRoot =
|
|
4061
|
-
const historyFile =
|
|
4665
|
+
const resolvedRoot = resolve7(projectRoot);
|
|
4666
|
+
const historyFile = resolve7(resolvedRoot, ".depwire", "health-history.json");
|
|
4062
4667
|
if (!historyFile.startsWith(resolvedRoot)) {
|
|
4063
4668
|
return;
|
|
4064
4669
|
}
|
|
@@ -4073,10 +4678,10 @@ function saveHealthHistory(projectRoot, report) {
|
|
|
4073
4678
|
}))
|
|
4074
4679
|
};
|
|
4075
4680
|
let history = [];
|
|
4076
|
-
if (
|
|
4681
|
+
if (existsSync9(historyFile)) {
|
|
4077
4682
|
try {
|
|
4078
4683
|
if (!historyFile.startsWith(resolvedRoot)) return;
|
|
4079
|
-
const content =
|
|
4684
|
+
const content = readFileSync9(historyFile, "utf-8");
|
|
4080
4685
|
history = JSON.parse(content);
|
|
4081
4686
|
} catch {
|
|
4082
4687
|
}
|
|
@@ -4085,19 +4690,19 @@ function saveHealthHistory(projectRoot, report) {
|
|
|
4085
4690
|
if (history.length > 50) {
|
|
4086
4691
|
history = history.slice(-50);
|
|
4087
4692
|
}
|
|
4088
|
-
mkdirSync(
|
|
4693
|
+
mkdirSync(dirname9(historyFile), { recursive: true });
|
|
4089
4694
|
if (!historyFile.startsWith(resolvedRoot)) return;
|
|
4090
4695
|
writeFileSync(historyFile, JSON.stringify(history, null, 2), "utf-8");
|
|
4091
4696
|
}
|
|
4092
4697
|
function loadHealthHistory(projectRoot) {
|
|
4093
|
-
const resolvedRoot =
|
|
4094
|
-
const historyFile =
|
|
4095
|
-
if (!historyFile.startsWith(resolvedRoot) || !
|
|
4698
|
+
const resolvedRoot = resolve7(projectRoot);
|
|
4699
|
+
const historyFile = resolve7(resolvedRoot, ".depwire", "health-history.json");
|
|
4700
|
+
if (!historyFile.startsWith(resolvedRoot) || !existsSync9(historyFile)) {
|
|
4096
4701
|
return [];
|
|
4097
4702
|
}
|
|
4098
4703
|
try {
|
|
4099
4704
|
if (!historyFile.startsWith(resolvedRoot)) return [];
|
|
4100
|
-
const content =
|
|
4705
|
+
const content = readFileSync9(historyFile, "utf-8");
|
|
4101
4706
|
return JSON.parse(content);
|
|
4102
4707
|
} catch {
|
|
4103
4708
|
return [];
|
|
@@ -4106,7 +4711,7 @@ function loadHealthHistory(projectRoot) {
|
|
|
4106
4711
|
|
|
4107
4712
|
// src/dead-code/detector.ts
|
|
4108
4713
|
import path2 from "path";
|
|
4109
|
-
import { readFileSync as
|
|
4714
|
+
import { readFileSync as readFileSync10, existsSync as existsSync10 } from "fs";
|
|
4110
4715
|
function findDeadSymbols(graph, projectRoot, includeTests = false, debug = false) {
|
|
4111
4716
|
const deadSymbols = [];
|
|
4112
4717
|
const context = { graph, projectRoot };
|
|
@@ -4218,8 +4823,10 @@ function isRelevantForDeadCodeDetection(attrs) {
|
|
|
4218
4823
|
"class",
|
|
4219
4824
|
"interface",
|
|
4220
4825
|
"type",
|
|
4826
|
+
"type_alias",
|
|
4221
4827
|
"enum",
|
|
4222
4828
|
"const",
|
|
4829
|
+
"constant",
|
|
4223
4830
|
"let",
|
|
4224
4831
|
"var",
|
|
4225
4832
|
"method",
|
|
@@ -4237,11 +4844,11 @@ function getPackageEntryPoints(projectRoot) {
|
|
|
4237
4844
|
const entryPoints = /* @__PURE__ */ new Set();
|
|
4238
4845
|
const resolvedRoot = path2.resolve(projectRoot);
|
|
4239
4846
|
const packageJsonPath = path2.resolve(resolvedRoot, "package.json");
|
|
4240
|
-
if (!packageJsonPath.startsWith(resolvedRoot) || !
|
|
4847
|
+
if (!packageJsonPath.startsWith(resolvedRoot) || !existsSync10(packageJsonPath)) {
|
|
4241
4848
|
return entryPoints;
|
|
4242
4849
|
}
|
|
4243
4850
|
try {
|
|
4244
|
-
const packageJson = JSON.parse(
|
|
4851
|
+
const packageJson = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
4245
4852
|
if (packageJson.main) {
|
|
4246
4853
|
entryPoints.add(path2.resolve(projectRoot, packageJson.main));
|
|
4247
4854
|
}
|
|
@@ -4314,7 +4921,7 @@ function isTypeDeclarationFile(filePath) {
|
|
|
4314
4921
|
return filePath.endsWith(".d.ts");
|
|
4315
4922
|
}
|
|
4316
4923
|
function isFrameworkAutoLoadedFile(filePath) {
|
|
4317
|
-
return filePath.includes("/pages/") || filePath.includes("/routes/") || filePath.includes("/middleware/") || filePath.includes("/commands/") || filePath.includes("/api/") || filePath.includes("/app/");
|
|
4924
|
+
return filePath.includes("/pages/") || filePath.includes("/routes/") || filePath.includes("/middleware/") || filePath.includes("/commands/") || filePath.includes("/api/") || filePath.includes("/app/") || filePath.includes("/Controllers/") || filePath.includes("/Hubs/") || filePath.includes("/Migrations/");
|
|
4318
4925
|
}
|
|
4319
4926
|
|
|
4320
4927
|
// src/dead-code/classifier.ts
|
|
@@ -4382,8 +4989,8 @@ function generateReason(symbol, confidence) {
|
|
|
4382
4989
|
return "Potentially unused";
|
|
4383
4990
|
}
|
|
4384
4991
|
function isBarrelFile(filePath) {
|
|
4385
|
-
const
|
|
4386
|
-
return
|
|
4992
|
+
const basename6 = path3.basename(filePath);
|
|
4993
|
+
return basename6 === "index.ts" || basename6 === "index.js";
|
|
4387
4994
|
}
|
|
4388
4995
|
function isTestFile2(filePath) {
|
|
4389
4996
|
return filePath.includes("__tests__/") || filePath.includes(".test.") || filePath.includes(".spec.") || filePath.includes("/test/") || filePath.includes("/tests/");
|
|
@@ -4562,11 +5169,11 @@ function filterByConfidence(symbols, minConfidence) {
|
|
|
4562
5169
|
}
|
|
4563
5170
|
|
|
4564
5171
|
// src/docs/generator.ts
|
|
4565
|
-
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as
|
|
4566
|
-
import { join as
|
|
5172
|
+
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync13 } from "fs";
|
|
5173
|
+
import { join as join15 } from "path";
|
|
4567
5174
|
|
|
4568
5175
|
// src/docs/architecture.ts
|
|
4569
|
-
import { dirname as
|
|
5176
|
+
import { dirname as dirname10 } from "path";
|
|
4570
5177
|
|
|
4571
5178
|
// src/docs/templates.ts
|
|
4572
5179
|
function header(text, level = 1) {
|
|
@@ -4717,7 +5324,7 @@ function generateModuleStructure(graph) {
|
|
|
4717
5324
|
function getDirectoryStats(graph) {
|
|
4718
5325
|
const dirMap = /* @__PURE__ */ new Map();
|
|
4719
5326
|
graph.forEachNode((node, attrs) => {
|
|
4720
|
-
const dir =
|
|
5327
|
+
const dir = dirname10(attrs.filePath);
|
|
4721
5328
|
if (dir === ".") return;
|
|
4722
5329
|
if (!dirMap.has(dir)) {
|
|
4723
5330
|
dirMap.set(dir, {
|
|
@@ -4742,7 +5349,7 @@ function getDirectoryStats(graph) {
|
|
|
4742
5349
|
});
|
|
4743
5350
|
const filesPerDir = /* @__PURE__ */ new Map();
|
|
4744
5351
|
graph.forEachNode((node, attrs) => {
|
|
4745
|
-
const dir =
|
|
5352
|
+
const dir = dirname10(attrs.filePath);
|
|
4746
5353
|
if (!filesPerDir.has(dir)) {
|
|
4747
5354
|
filesPerDir.set(dir, /* @__PURE__ */ new Set());
|
|
4748
5355
|
}
|
|
@@ -4757,8 +5364,8 @@ function getDirectoryStats(graph) {
|
|
|
4757
5364
|
graph.forEachEdge((edge, attrs, source, target) => {
|
|
4758
5365
|
const sourceAttrs = graph.getNodeAttributes(source);
|
|
4759
5366
|
const targetAttrs = graph.getNodeAttributes(target);
|
|
4760
|
-
const sourceDir =
|
|
4761
|
-
const targetDir =
|
|
5367
|
+
const sourceDir = dirname10(sourceAttrs.filePath);
|
|
5368
|
+
const targetDir = dirname10(targetAttrs.filePath);
|
|
4762
5369
|
if (sourceDir !== targetDir) {
|
|
4763
5370
|
if (!dirEdges.has(sourceDir)) {
|
|
4764
5371
|
dirEdges.set(sourceDir, { in: 0, out: 0 });
|
|
@@ -4965,7 +5572,7 @@ function detectCycles(graph) {
|
|
|
4965
5572
|
}
|
|
4966
5573
|
|
|
4967
5574
|
// src/docs/conventions.ts
|
|
4968
|
-
import { basename as
|
|
5575
|
+
import { basename as basename3, extname as extname5 } from "path";
|
|
4969
5576
|
function generateConventions(graph, projectRoot, version) {
|
|
4970
5577
|
let output = "";
|
|
4971
5578
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -5003,7 +5610,7 @@ function generateFileOrganization(graph) {
|
|
|
5003
5610
|
graph.forEachNode((node, attrs) => {
|
|
5004
5611
|
if (!files.has(attrs.filePath)) {
|
|
5005
5612
|
files.add(attrs.filePath);
|
|
5006
|
-
const fileName =
|
|
5613
|
+
const fileName = basename3(attrs.filePath);
|
|
5007
5614
|
if (fileName === "index.ts" || fileName === "index.js" || fileName === "index.tsx" || fileName === "index.jsx") {
|
|
5008
5615
|
barrelFileCount++;
|
|
5009
5616
|
}
|
|
@@ -5062,7 +5669,7 @@ function generateNamingPatterns(graph) {
|
|
|
5062
5669
|
graph.forEachNode((node, attrs) => {
|
|
5063
5670
|
if (!files.has(attrs.filePath)) {
|
|
5064
5671
|
files.add(attrs.filePath);
|
|
5065
|
-
const fileName =
|
|
5672
|
+
const fileName = basename3(attrs.filePath, extname5(attrs.filePath));
|
|
5066
5673
|
if (isCamelCase(fileName)) patterns.files.camelCase++;
|
|
5067
5674
|
else if (isPascalCase(fileName)) patterns.files.PascalCase++;
|
|
5068
5675
|
else if (isKebabCase(fileName)) patterns.files.kebabCase++;
|
|
@@ -5739,7 +6346,7 @@ function detectCyclesDetailed(graph) {
|
|
|
5739
6346
|
}
|
|
5740
6347
|
|
|
5741
6348
|
// src/docs/onboarding.ts
|
|
5742
|
-
import { dirname as
|
|
6349
|
+
import { dirname as dirname11 } from "path";
|
|
5743
6350
|
function generateOnboarding(graph, projectRoot, version) {
|
|
5744
6351
|
let output = "";
|
|
5745
6352
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -5798,7 +6405,7 @@ function generateQuickOrientation(graph) {
|
|
|
5798
6405
|
const primaryLang = Object.entries(languages2).sort((a, b) => b[1] - a[1])[0];
|
|
5799
6406
|
const dirs = /* @__PURE__ */ new Set();
|
|
5800
6407
|
graph.forEachNode((node, attrs) => {
|
|
5801
|
-
const dir =
|
|
6408
|
+
const dir = dirname11(attrs.filePath);
|
|
5802
6409
|
if (dir !== ".") {
|
|
5803
6410
|
const topLevel = dir.split("/")[0];
|
|
5804
6411
|
dirs.add(topLevel);
|
|
@@ -5902,7 +6509,7 @@ function generateModuleMap(graph) {
|
|
|
5902
6509
|
function getDirectoryStats2(graph) {
|
|
5903
6510
|
const dirMap = /* @__PURE__ */ new Map();
|
|
5904
6511
|
graph.forEachNode((node, attrs) => {
|
|
5905
|
-
const dir =
|
|
6512
|
+
const dir = dirname11(attrs.filePath);
|
|
5906
6513
|
if (dir === ".") return;
|
|
5907
6514
|
if (!dirMap.has(dir)) {
|
|
5908
6515
|
dirMap.set(dir, {
|
|
@@ -5917,7 +6524,7 @@ function getDirectoryStats2(graph) {
|
|
|
5917
6524
|
});
|
|
5918
6525
|
const filesPerDir = /* @__PURE__ */ new Map();
|
|
5919
6526
|
graph.forEachNode((node, attrs) => {
|
|
5920
|
-
const dir =
|
|
6527
|
+
const dir = dirname11(attrs.filePath);
|
|
5921
6528
|
if (!filesPerDir.has(dir)) {
|
|
5922
6529
|
filesPerDir.set(dir, /* @__PURE__ */ new Set());
|
|
5923
6530
|
}
|
|
@@ -5932,8 +6539,8 @@ function getDirectoryStats2(graph) {
|
|
|
5932
6539
|
graph.forEachEdge((edge, attrs, source, target) => {
|
|
5933
6540
|
const sourceAttrs = graph.getNodeAttributes(source);
|
|
5934
6541
|
const targetAttrs = graph.getNodeAttributes(target);
|
|
5935
|
-
const sourceDir =
|
|
5936
|
-
const targetDir =
|
|
6542
|
+
const sourceDir = dirname11(sourceAttrs.filePath);
|
|
6543
|
+
const targetDir = dirname11(targetAttrs.filePath);
|
|
5937
6544
|
if (sourceDir !== targetDir) {
|
|
5938
6545
|
if (!dirEdges.has(sourceDir)) {
|
|
5939
6546
|
dirEdges.set(sourceDir, { in: 0, out: 0 });
|
|
@@ -6014,7 +6621,7 @@ function detectClusters(graph) {
|
|
|
6014
6621
|
const dirFiles = /* @__PURE__ */ new Map();
|
|
6015
6622
|
const fileEdges = /* @__PURE__ */ new Map();
|
|
6016
6623
|
graph.forEachNode((node, attrs) => {
|
|
6017
|
-
const dir =
|
|
6624
|
+
const dir = dirname11(attrs.filePath);
|
|
6018
6625
|
if (!dirFiles.has(dir)) {
|
|
6019
6626
|
dirFiles.set(dir, /* @__PURE__ */ new Set());
|
|
6020
6627
|
}
|
|
@@ -6068,8 +6675,8 @@ function inferClusterName(files) {
|
|
|
6068
6675
|
if (sortedWords.length > 0 && sortedWords[0][1] > 1) {
|
|
6069
6676
|
return capitalizeFirst2(sortedWords[0][0]);
|
|
6070
6677
|
}
|
|
6071
|
-
const commonDir =
|
|
6072
|
-
if (files.every((f) =>
|
|
6678
|
+
const commonDir = dirname11(files[0]);
|
|
6679
|
+
if (files.every((f) => dirname11(f) === commonDir)) {
|
|
6073
6680
|
return capitalizeFirst2(commonDir.split("/").pop() || "Core");
|
|
6074
6681
|
}
|
|
6075
6682
|
return "Core";
|
|
@@ -6127,7 +6734,7 @@ function generateDepwireUsage(projectRoot) {
|
|
|
6127
6734
|
}
|
|
6128
6735
|
|
|
6129
6736
|
// src/docs/files.ts
|
|
6130
|
-
import { dirname as
|
|
6737
|
+
import { dirname as dirname12, basename as basename4 } from "path";
|
|
6131
6738
|
function generateFiles(graph, projectRoot, version) {
|
|
6132
6739
|
let output = "";
|
|
6133
6740
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -6231,7 +6838,7 @@ function generateDirectoryBreakdown(graph) {
|
|
|
6231
6838
|
const fileStats = getFileStats2(graph);
|
|
6232
6839
|
const dirMap = /* @__PURE__ */ new Map();
|
|
6233
6840
|
for (const file of fileStats) {
|
|
6234
|
-
const dir =
|
|
6841
|
+
const dir = dirname12(file.filePath);
|
|
6235
6842
|
const topDir = dir === "." ? "." : dir.split("/")[0];
|
|
6236
6843
|
if (!dirMap.has(topDir)) {
|
|
6237
6844
|
dirMap.set(topDir, {
|
|
@@ -6246,7 +6853,7 @@ function generateDirectoryBreakdown(graph) {
|
|
|
6246
6853
|
dirStats.symbolCount += file.symbolCount;
|
|
6247
6854
|
if (file.totalConnections > dirStats.maxConnections) {
|
|
6248
6855
|
dirStats.maxConnections = file.totalConnections;
|
|
6249
|
-
dirStats.mostConnectedFile =
|
|
6856
|
+
dirStats.mostConnectedFile = basename4(file.filePath);
|
|
6250
6857
|
}
|
|
6251
6858
|
}
|
|
6252
6859
|
if (dirMap.size === 0) {
|
|
@@ -6874,7 +7481,7 @@ function generateRecommendations(graph) {
|
|
|
6874
7481
|
}
|
|
6875
7482
|
|
|
6876
7483
|
// src/docs/tests.ts
|
|
6877
|
-
import { basename as
|
|
7484
|
+
import { basename as basename5, dirname as dirname13 } from "path";
|
|
6878
7485
|
function generateTests(graph, projectRoot, version) {
|
|
6879
7486
|
let output = "";
|
|
6880
7487
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -6902,8 +7509,8 @@ function getFileCount8(graph) {
|
|
|
6902
7509
|
return files.size;
|
|
6903
7510
|
}
|
|
6904
7511
|
function isTestFile3(filePath) {
|
|
6905
|
-
const fileName =
|
|
6906
|
-
const dirPath =
|
|
7512
|
+
const fileName = basename5(filePath).toLowerCase();
|
|
7513
|
+
const dirPath = dirname13(filePath).toLowerCase();
|
|
6907
7514
|
if (dirPath.includes("test") || dirPath.includes("spec") || dirPath.includes("__tests__")) {
|
|
6908
7515
|
return true;
|
|
6909
7516
|
}
|
|
@@ -6961,13 +7568,13 @@ function generateTestFileInventory(graph) {
|
|
|
6961
7568
|
return output;
|
|
6962
7569
|
}
|
|
6963
7570
|
function matchTestToSource(testFile) {
|
|
6964
|
-
const testFileName =
|
|
6965
|
-
const testDir =
|
|
7571
|
+
const testFileName = basename5(testFile);
|
|
7572
|
+
const testDir = dirname13(testFile);
|
|
6966
7573
|
let sourceFileName = testFileName.replace(/\.test\./g, ".").replace(/\.spec\./g, ".").replace(/_test\./g, ".").replace(/_spec\./g, ".");
|
|
6967
7574
|
const possiblePaths = [];
|
|
6968
7575
|
possiblePaths.push(testDir + "/" + sourceFileName);
|
|
6969
7576
|
if (testDir.endsWith("/test") || testDir.endsWith("/tests") || testDir.endsWith("/__tests__")) {
|
|
6970
|
-
const parentDir =
|
|
7577
|
+
const parentDir = dirname13(testDir);
|
|
6971
7578
|
possiblePaths.push(parentDir + "/" + sourceFileName);
|
|
6972
7579
|
}
|
|
6973
7580
|
if (testDir.includes("test")) {
|
|
@@ -7123,7 +7730,7 @@ function generateTestCoverageMap(graph) {
|
|
|
7123
7730
|
const rows = mappings.slice(0, 30).map((m) => [
|
|
7124
7731
|
`\`${m.sourceFile}\``,
|
|
7125
7732
|
m.hasTest ? "\u2705" : "\u274C",
|
|
7126
|
-
m.testFile ? `\`${
|
|
7733
|
+
m.testFile ? `\`${basename5(m.testFile)}\`` : "-",
|
|
7127
7734
|
formatNumber(m.symbolCount)
|
|
7128
7735
|
]);
|
|
7129
7736
|
let output = table(headers, rows);
|
|
@@ -7164,7 +7771,7 @@ function generateTestStatistics(graph) {
|
|
|
7164
7771
|
`;
|
|
7165
7772
|
const dirTestCoverage = /* @__PURE__ */ new Map();
|
|
7166
7773
|
for (const sourceFile of sourceFiles) {
|
|
7167
|
-
const dir =
|
|
7774
|
+
const dir = dirname13(sourceFile).split("/")[0];
|
|
7168
7775
|
if (!dirTestCoverage.has(dir)) {
|
|
7169
7776
|
dirTestCoverage.set(dir, { total: 0, tested: 0 });
|
|
7170
7777
|
}
|
|
@@ -7187,7 +7794,7 @@ function generateTestStatistics(graph) {
|
|
|
7187
7794
|
}
|
|
7188
7795
|
|
|
7189
7796
|
// src/docs/history.ts
|
|
7190
|
-
import { dirname as
|
|
7797
|
+
import { dirname as dirname14 } from "path";
|
|
7191
7798
|
import { execSync } from "child_process";
|
|
7192
7799
|
function generateHistory(graph, projectRoot, version) {
|
|
7193
7800
|
let output = "";
|
|
@@ -7468,7 +8075,7 @@ function generateFeatureClusters(graph) {
|
|
|
7468
8075
|
const dirFiles = /* @__PURE__ */ new Map();
|
|
7469
8076
|
const fileEdges = /* @__PURE__ */ new Map();
|
|
7470
8077
|
graph.forEachNode((node, attrs) => {
|
|
7471
|
-
const dir =
|
|
8078
|
+
const dir = dirname14(attrs.filePath);
|
|
7472
8079
|
if (!dirFiles.has(dir)) {
|
|
7473
8080
|
dirFiles.set(dir, /* @__PURE__ */ new Set());
|
|
7474
8081
|
}
|
|
@@ -7550,7 +8157,7 @@ function capitalizeFirst3(str) {
|
|
|
7550
8157
|
}
|
|
7551
8158
|
|
|
7552
8159
|
// src/docs/current.ts
|
|
7553
|
-
import { dirname as
|
|
8160
|
+
import { dirname as dirname15 } from "path";
|
|
7554
8161
|
function generateCurrent(graph, projectRoot, version) {
|
|
7555
8162
|
let output = "";
|
|
7556
8163
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -7688,7 +8295,7 @@ function generateCompleteFileIndex(graph) {
|
|
|
7688
8295
|
fileInfos.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
7689
8296
|
const dirGroups = /* @__PURE__ */ new Map();
|
|
7690
8297
|
for (const info of fileInfos) {
|
|
7691
|
-
const dir =
|
|
8298
|
+
const dir = dirname15(info.filePath);
|
|
7692
8299
|
const topDir = dir === "." ? "root" : dir.split("/")[0];
|
|
7693
8300
|
if (!dirGroups.has(topDir)) {
|
|
7694
8301
|
dirGroups.set(topDir, []);
|
|
@@ -7899,8 +8506,8 @@ function getTopLevelDir2(filePath) {
|
|
|
7899
8506
|
}
|
|
7900
8507
|
|
|
7901
8508
|
// src/docs/status.ts
|
|
7902
|
-
import { readFileSync as
|
|
7903
|
-
import { resolve as
|
|
8509
|
+
import { readFileSync as readFileSync11, existsSync as existsSync11 } from "fs";
|
|
8510
|
+
import { resolve as resolve8 } from "path";
|
|
7904
8511
|
function generateStatus(graph, projectRoot, version) {
|
|
7905
8512
|
let output = "";
|
|
7906
8513
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -7933,16 +8540,16 @@ function getFileCount11(graph) {
|
|
|
7933
8540
|
}
|
|
7934
8541
|
function extractComments(projectRoot, filePath) {
|
|
7935
8542
|
const comments = [];
|
|
7936
|
-
const resolvedRoot =
|
|
7937
|
-
const fullPath =
|
|
8543
|
+
const resolvedRoot = resolve8(projectRoot);
|
|
8544
|
+
const fullPath = resolve8(resolvedRoot, filePath);
|
|
7938
8545
|
if (!fullPath.startsWith(resolvedRoot)) {
|
|
7939
8546
|
return comments;
|
|
7940
8547
|
}
|
|
7941
|
-
if (!
|
|
8548
|
+
if (!existsSync11(fullPath)) {
|
|
7942
8549
|
return comments;
|
|
7943
8550
|
}
|
|
7944
8551
|
try {
|
|
7945
|
-
const content =
|
|
8552
|
+
const content = readFileSync11(fullPath, "utf-8");
|
|
7946
8553
|
const lines = content.split("\n");
|
|
7947
8554
|
const patterns = [
|
|
7948
8555
|
{ type: "TODO", regex: /(?:\/\/|#|\/\*)\s*TODO:?\s*(.+)/i },
|
|
@@ -8521,16 +9128,16 @@ function generateConfidenceSection(title, description, symbols, projectRoot) {
|
|
|
8521
9128
|
}
|
|
8522
9129
|
|
|
8523
9130
|
// src/docs/metadata.ts
|
|
8524
|
-
import { existsSync as
|
|
8525
|
-
import { resolve as
|
|
9131
|
+
import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync2 } from "fs";
|
|
9132
|
+
import { resolve as resolve9 } from "path";
|
|
8526
9133
|
function loadMetadata(outputDir) {
|
|
8527
|
-
const resolvedDir =
|
|
8528
|
-
const metadataPath =
|
|
8529
|
-
if (!metadataPath.startsWith(resolvedDir) || !
|
|
9134
|
+
const resolvedDir = resolve9(outputDir);
|
|
9135
|
+
const metadataPath = resolve9(resolvedDir, "metadata.json");
|
|
9136
|
+
if (!metadataPath.startsWith(resolvedDir) || !existsSync12(metadataPath)) {
|
|
8530
9137
|
return null;
|
|
8531
9138
|
}
|
|
8532
9139
|
try {
|
|
8533
|
-
const content =
|
|
9140
|
+
const content = readFileSync12(metadataPath, "utf-8");
|
|
8534
9141
|
return JSON.parse(content);
|
|
8535
9142
|
} catch (err) {
|
|
8536
9143
|
console.error("Failed to load metadata:", err);
|
|
@@ -8538,8 +9145,8 @@ function loadMetadata(outputDir) {
|
|
|
8538
9145
|
}
|
|
8539
9146
|
}
|
|
8540
9147
|
function saveMetadata(outputDir, metadata) {
|
|
8541
|
-
const resolvedDir =
|
|
8542
|
-
const metadataPath =
|
|
9148
|
+
const resolvedDir = resolve9(outputDir);
|
|
9149
|
+
const metadataPath = resolve9(resolvedDir, "metadata.json");
|
|
8543
9150
|
if (!metadataPath.startsWith(resolvedDir)) {
|
|
8544
9151
|
throw new Error(`Path traversal attempt blocked: ${metadataPath}`);
|
|
8545
9152
|
}
|
|
@@ -8585,7 +9192,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8585
9192
|
const generated = [];
|
|
8586
9193
|
const errors = [];
|
|
8587
9194
|
try {
|
|
8588
|
-
if (!
|
|
9195
|
+
if (!existsSync13(options.outputDir)) {
|
|
8589
9196
|
mkdirSync2(options.outputDir, { recursive: true });
|
|
8590
9197
|
if (options.verbose) {
|
|
8591
9198
|
console.log(`Created output directory: ${options.outputDir}`);
|
|
@@ -8624,7 +9231,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8624
9231
|
try {
|
|
8625
9232
|
if (options.verbose) console.log("Generating ARCHITECTURE.md...");
|
|
8626
9233
|
const content = generateArchitecture(graph, projectRoot, version, parseTime);
|
|
8627
|
-
const filePath =
|
|
9234
|
+
const filePath = join15(options.outputDir, "ARCHITECTURE.md");
|
|
8628
9235
|
writeFileSync3(filePath, content, "utf-8");
|
|
8629
9236
|
generated.push("ARCHITECTURE.md");
|
|
8630
9237
|
} catch (err) {
|
|
@@ -8635,7 +9242,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8635
9242
|
try {
|
|
8636
9243
|
if (options.verbose) console.log("Generating CONVENTIONS.md...");
|
|
8637
9244
|
const content = generateConventions(graph, projectRoot, version);
|
|
8638
|
-
const filePath =
|
|
9245
|
+
const filePath = join15(options.outputDir, "CONVENTIONS.md");
|
|
8639
9246
|
writeFileSync3(filePath, content, "utf-8");
|
|
8640
9247
|
generated.push("CONVENTIONS.md");
|
|
8641
9248
|
} catch (err) {
|
|
@@ -8646,7 +9253,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8646
9253
|
try {
|
|
8647
9254
|
if (options.verbose) console.log("Generating DEPENDENCIES.md...");
|
|
8648
9255
|
const content = generateDependencies(graph, projectRoot, version);
|
|
8649
|
-
const filePath =
|
|
9256
|
+
const filePath = join15(options.outputDir, "DEPENDENCIES.md");
|
|
8650
9257
|
writeFileSync3(filePath, content, "utf-8");
|
|
8651
9258
|
generated.push("DEPENDENCIES.md");
|
|
8652
9259
|
} catch (err) {
|
|
@@ -8657,7 +9264,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8657
9264
|
try {
|
|
8658
9265
|
if (options.verbose) console.log("Generating ONBOARDING.md...");
|
|
8659
9266
|
const content = generateOnboarding(graph, projectRoot, version);
|
|
8660
|
-
const filePath =
|
|
9267
|
+
const filePath = join15(options.outputDir, "ONBOARDING.md");
|
|
8661
9268
|
writeFileSync3(filePath, content, "utf-8");
|
|
8662
9269
|
generated.push("ONBOARDING.md");
|
|
8663
9270
|
} catch (err) {
|
|
@@ -8668,7 +9275,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8668
9275
|
try {
|
|
8669
9276
|
if (options.verbose) console.log("Generating FILES.md...");
|
|
8670
9277
|
const content = generateFiles(graph, projectRoot, version);
|
|
8671
|
-
const filePath =
|
|
9278
|
+
const filePath = join15(options.outputDir, "FILES.md");
|
|
8672
9279
|
writeFileSync3(filePath, content, "utf-8");
|
|
8673
9280
|
generated.push("FILES.md");
|
|
8674
9281
|
} catch (err) {
|
|
@@ -8679,7 +9286,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8679
9286
|
try {
|
|
8680
9287
|
if (options.verbose) console.log("Generating API_SURFACE.md...");
|
|
8681
9288
|
const content = generateApiSurface(graph, projectRoot, version);
|
|
8682
|
-
const filePath =
|
|
9289
|
+
const filePath = join15(options.outputDir, "API_SURFACE.md");
|
|
8683
9290
|
writeFileSync3(filePath, content, "utf-8");
|
|
8684
9291
|
generated.push("API_SURFACE.md");
|
|
8685
9292
|
} catch (err) {
|
|
@@ -8690,7 +9297,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8690
9297
|
try {
|
|
8691
9298
|
if (options.verbose) console.log("Generating ERRORS.md...");
|
|
8692
9299
|
const content = generateErrors(graph, projectRoot, version);
|
|
8693
|
-
const filePath =
|
|
9300
|
+
const filePath = join15(options.outputDir, "ERRORS.md");
|
|
8694
9301
|
writeFileSync3(filePath, content, "utf-8");
|
|
8695
9302
|
generated.push("ERRORS.md");
|
|
8696
9303
|
} catch (err) {
|
|
@@ -8701,7 +9308,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8701
9308
|
try {
|
|
8702
9309
|
if (options.verbose) console.log("Generating TESTS.md...");
|
|
8703
9310
|
const content = generateTests(graph, projectRoot, version);
|
|
8704
|
-
const filePath =
|
|
9311
|
+
const filePath = join15(options.outputDir, "TESTS.md");
|
|
8705
9312
|
writeFileSync3(filePath, content, "utf-8");
|
|
8706
9313
|
generated.push("TESTS.md");
|
|
8707
9314
|
} catch (err) {
|
|
@@ -8712,7 +9319,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8712
9319
|
try {
|
|
8713
9320
|
if (options.verbose) console.log("Generating HISTORY.md...");
|
|
8714
9321
|
const content = generateHistory(graph, projectRoot, version);
|
|
8715
|
-
const filePath =
|
|
9322
|
+
const filePath = join15(options.outputDir, "HISTORY.md");
|
|
8716
9323
|
writeFileSync3(filePath, content, "utf-8");
|
|
8717
9324
|
generated.push("HISTORY.md");
|
|
8718
9325
|
} catch (err) {
|
|
@@ -8723,7 +9330,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8723
9330
|
try {
|
|
8724
9331
|
if (options.verbose) console.log("Generating CURRENT.md...");
|
|
8725
9332
|
const content = generateCurrent(graph, projectRoot, version);
|
|
8726
|
-
const filePath =
|
|
9333
|
+
const filePath = join15(options.outputDir, "CURRENT.md");
|
|
8727
9334
|
writeFileSync3(filePath, content, "utf-8");
|
|
8728
9335
|
generated.push("CURRENT.md");
|
|
8729
9336
|
} catch (err) {
|
|
@@ -8734,7 +9341,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8734
9341
|
try {
|
|
8735
9342
|
if (options.verbose) console.log("Generating STATUS.md...");
|
|
8736
9343
|
const content = generateStatus(graph, projectRoot, version);
|
|
8737
|
-
const filePath =
|
|
9344
|
+
const filePath = join15(options.outputDir, "STATUS.md");
|
|
8738
9345
|
writeFileSync3(filePath, content, "utf-8");
|
|
8739
9346
|
generated.push("STATUS.md");
|
|
8740
9347
|
} catch (err) {
|
|
@@ -8745,7 +9352,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8745
9352
|
try {
|
|
8746
9353
|
if (options.verbose) console.log("Generating HEALTH.md...");
|
|
8747
9354
|
const content = generateHealth(graph, projectRoot, version);
|
|
8748
|
-
const filePath =
|
|
9355
|
+
const filePath = join15(options.outputDir, "HEALTH.md");
|
|
8749
9356
|
writeFileSync3(filePath, content, "utf-8");
|
|
8750
9357
|
generated.push("HEALTH.md");
|
|
8751
9358
|
} catch (err) {
|
|
@@ -8756,7 +9363,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8756
9363
|
try {
|
|
8757
9364
|
if (options.verbose) console.log("Generating DEAD_CODE.md...");
|
|
8758
9365
|
const content = generateDeadCode(graph, projectRoot, version);
|
|
8759
|
-
const filePath =
|
|
9366
|
+
const filePath = join15(options.outputDir, "DEAD_CODE.md");
|
|
8760
9367
|
writeFileSync3(filePath, content, "utf-8");
|
|
8761
9368
|
generated.push("DEAD_CODE.md");
|
|
8762
9369
|
} catch (err) {
|
|
@@ -8800,7 +9407,7 @@ function getFileCount13(graph) {
|
|
|
8800
9407
|
}
|
|
8801
9408
|
|
|
8802
9409
|
// src/simulation/engine.ts
|
|
8803
|
-
import { dirname as
|
|
9410
|
+
import { dirname as dirname16, join as join16 } from "path";
|
|
8804
9411
|
function normalizePath2(p) {
|
|
8805
9412
|
return p.replace(/^\.\//, "").replace(/\/+$/, "");
|
|
8806
9413
|
}
|
|
@@ -8931,7 +9538,7 @@ var SimulationEngine = class {
|
|
|
8931
9538
|
}
|
|
8932
9539
|
}
|
|
8933
9540
|
applyRename(clone, target, newName, brokenImports) {
|
|
8934
|
-
const destination =
|
|
9541
|
+
const destination = join16(dirname16(target), newName);
|
|
8935
9542
|
this.applyMove(clone, target, destination, brokenImports);
|
|
8936
9543
|
}
|
|
8937
9544
|
applySplit(clone, target, newFile, symbols, brokenImports) {
|
|
@@ -9131,13 +9738,13 @@ var SimulationEngine = class {
|
|
|
9131
9738
|
};
|
|
9132
9739
|
|
|
9133
9740
|
// src/security/scanner.ts
|
|
9134
|
-
import { existsSync as
|
|
9135
|
-
import { join as
|
|
9741
|
+
import { existsSync as existsSync15 } from "fs";
|
|
9742
|
+
import { join as join26 } from "path";
|
|
9136
9743
|
|
|
9137
9744
|
// src/security/checks/dependencies.ts
|
|
9138
9745
|
import { execSync as execSync2 } from "child_process";
|
|
9139
|
-
import { existsSync as
|
|
9140
|
-
import { join as
|
|
9746
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13, readdirSync as readdirSync6 } from "fs";
|
|
9747
|
+
import { join as join17 } from "path";
|
|
9141
9748
|
function cvssToSeverity(score) {
|
|
9142
9749
|
if (score >= 9) return "critical";
|
|
9143
9750
|
if (score >= 7) return "high";
|
|
@@ -9147,18 +9754,18 @@ function cvssToSeverity(score) {
|
|
|
9147
9754
|
async function checkDependencies(_files, projectRoot) {
|
|
9148
9755
|
const findings = [];
|
|
9149
9756
|
try {
|
|
9150
|
-
if (
|
|
9757
|
+
if (existsSync14(join17(projectRoot, "package.json"))) {
|
|
9151
9758
|
findings.push(...checkNpmAudit(projectRoot));
|
|
9152
9759
|
findings.push(...checkPackageJsonPatterns(projectRoot));
|
|
9153
9760
|
findings.push(...checkPostinstallScripts(projectRoot));
|
|
9154
9761
|
}
|
|
9155
|
-
if (
|
|
9762
|
+
if (existsSync14(join17(projectRoot, "requirements.txt")) || existsSync14(join17(projectRoot, "pyproject.toml"))) {
|
|
9156
9763
|
findings.push(...checkPipAudit(projectRoot));
|
|
9157
9764
|
}
|
|
9158
|
-
if (
|
|
9765
|
+
if (existsSync14(join17(projectRoot, "Cargo.toml"))) {
|
|
9159
9766
|
findings.push(...checkCargoAudit(projectRoot));
|
|
9160
9767
|
}
|
|
9161
|
-
if (
|
|
9768
|
+
if (existsSync14(join17(projectRoot, "go.mod"))) {
|
|
9162
9769
|
findings.push(...checkGoVerify(projectRoot));
|
|
9163
9770
|
}
|
|
9164
9771
|
} catch (err) {
|
|
@@ -9247,8 +9854,8 @@ function checkNpmAudit(projectRoot) {
|
|
|
9247
9854
|
function checkPackageJsonPatterns(projectRoot) {
|
|
9248
9855
|
const findings = [];
|
|
9249
9856
|
try {
|
|
9250
|
-
const pkgPath =
|
|
9251
|
-
const pkg = JSON.parse(
|
|
9857
|
+
const pkgPath = join17(projectRoot, "package.json");
|
|
9858
|
+
const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
|
|
9252
9859
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
9253
9860
|
for (const [name, version] of Object.entries(allDeps)) {
|
|
9254
9861
|
if (version.startsWith("^") || version.startsWith("~")) {
|
|
@@ -9270,15 +9877,15 @@ function checkPackageJsonPatterns(projectRoot) {
|
|
|
9270
9877
|
}
|
|
9271
9878
|
function checkPostinstallScripts(projectRoot) {
|
|
9272
9879
|
const findings = [];
|
|
9273
|
-
const nodeModules =
|
|
9274
|
-
if (!
|
|
9880
|
+
const nodeModules = join17(projectRoot, "node_modules");
|
|
9881
|
+
if (!existsSync14(nodeModules)) return findings;
|
|
9275
9882
|
try {
|
|
9276
|
-
const topLevelDeps =
|
|
9883
|
+
const topLevelDeps = readdirSync6(nodeModules).filter((d) => !d.startsWith("."));
|
|
9277
9884
|
for (const dep of topLevelDeps) {
|
|
9278
|
-
const depPkgPath =
|
|
9279
|
-
if (!
|
|
9885
|
+
const depPkgPath = join17(nodeModules, dep, "package.json");
|
|
9886
|
+
if (!existsSync14(depPkgPath)) continue;
|
|
9280
9887
|
try {
|
|
9281
|
-
const depPkg = JSON.parse(
|
|
9888
|
+
const depPkg = JSON.parse(readFileSync13(depPkgPath, "utf-8"));
|
|
9282
9889
|
const scripts = depPkg.scripts || {};
|
|
9283
9890
|
if (scripts.postinstall || scripts.preinstall || scripts.install) {
|
|
9284
9891
|
const scriptName = scripts.postinstall ? "postinstall" : scripts.preinstall ? "preinstall" : "install";
|
|
@@ -9316,7 +9923,7 @@ function checkPipAudit(projectRoot) {
|
|
|
9316
9923
|
id: "",
|
|
9317
9924
|
severity: cvssToSeverity(vuln.cvss?.score || 5),
|
|
9318
9925
|
vulnerabilityClass: "dependency-cve",
|
|
9319
|
-
file:
|
|
9926
|
+
file: existsSync14(join17(projectRoot, "requirements.txt")) ? "requirements.txt" : "pyproject.toml",
|
|
9320
9927
|
title: `Vulnerable Python dependency: ${vuln.name}`,
|
|
9321
9928
|
description: `${vuln.name}@${vuln.version} \u2014 ${vuln.id}: ${vuln.description || "Known vulnerability"}`,
|
|
9322
9929
|
attackScenario: `An attacker could exploit the vulnerability in ${vuln.name}.`,
|
|
@@ -9413,8 +10020,8 @@ function checkGoVerify(projectRoot) {
|
|
|
9413
10020
|
}
|
|
9414
10021
|
|
|
9415
10022
|
// src/security/checks/injection.ts
|
|
9416
|
-
import { readFileSync as
|
|
9417
|
-
import { join as
|
|
10023
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
10024
|
+
import { join as join18 } from "path";
|
|
9418
10025
|
var SKIP_DIRS = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
|
|
9419
10026
|
var TEST_PATTERNS = ["test", "spec", "fixture", "mock", "__tests__", "__mocks__"];
|
|
9420
10027
|
var USER_INPUT_NAMES = /(?:input|user|name|path|query|branch|hash|cmd|command|req\.|params|body|args|url|dir|file|subdirectory)/i;
|
|
@@ -9515,7 +10122,7 @@ async function checkInjection(files, projectRoot) {
|
|
|
9515
10122
|
if (shouldSkip(file.filePath) || isTestFile4(file.filePath)) continue;
|
|
9516
10123
|
let content;
|
|
9517
10124
|
try {
|
|
9518
|
-
content =
|
|
10125
|
+
content = readFileSync14(join18(projectRoot, file.filePath), "utf-8");
|
|
9519
10126
|
} catch {
|
|
9520
10127
|
continue;
|
|
9521
10128
|
}
|
|
@@ -9553,8 +10160,8 @@ async function checkInjection(files, projectRoot) {
|
|
|
9553
10160
|
}
|
|
9554
10161
|
|
|
9555
10162
|
// src/security/checks/secrets.ts
|
|
9556
|
-
import { readFileSync as
|
|
9557
|
-
import { join as
|
|
10163
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
10164
|
+
import { join as join19 } from "path";
|
|
9558
10165
|
var SKIP_DIRS2 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
|
|
9559
10166
|
var TEST_PATTERNS2 = ["test", "spec", "fixture", "mock", "__tests__", "__mocks__", ".example", ".sample"];
|
|
9560
10167
|
var SECRET_PATTERNS = [
|
|
@@ -9587,7 +10194,7 @@ async function checkSecrets(files, projectRoot) {
|
|
|
9587
10194
|
if (shouldSkip2(file.filePath) || isTestFile5(file.filePath)) continue;
|
|
9588
10195
|
let content;
|
|
9589
10196
|
try {
|
|
9590
|
-
content =
|
|
10197
|
+
content = readFileSync15(join19(projectRoot, file.filePath), "utf-8");
|
|
9591
10198
|
} catch {
|
|
9592
10199
|
continue;
|
|
9593
10200
|
}
|
|
@@ -9620,8 +10227,8 @@ async function checkSecrets(files, projectRoot) {
|
|
|
9620
10227
|
}
|
|
9621
10228
|
|
|
9622
10229
|
// src/security/checks/path-traversal.ts
|
|
9623
|
-
import { readFileSync as
|
|
9624
|
-
import { join as
|
|
10230
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
10231
|
+
import { join as join20 } from "path";
|
|
9625
10232
|
var SKIP_DIRS3 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
|
|
9626
10233
|
var USER_INPUT_VARS = /(?:req\.|params|query|body|input|path|dir|subdirectory|file|userInput|fileName|filePath)/i;
|
|
9627
10234
|
var PATTERNS2 = [
|
|
@@ -9668,7 +10275,7 @@ async function checkPathTraversal(files, projectRoot) {
|
|
|
9668
10275
|
if (shouldSkip3(file.filePath)) continue;
|
|
9669
10276
|
let content;
|
|
9670
10277
|
try {
|
|
9671
|
-
content =
|
|
10278
|
+
content = readFileSync16(join20(projectRoot, file.filePath), "utf-8");
|
|
9672
10279
|
} catch {
|
|
9673
10280
|
continue;
|
|
9674
10281
|
}
|
|
@@ -9710,8 +10317,8 @@ async function checkPathTraversal(files, projectRoot) {
|
|
|
9710
10317
|
}
|
|
9711
10318
|
|
|
9712
10319
|
// src/security/checks/auth.ts
|
|
9713
|
-
import { readFileSync as
|
|
9714
|
-
import { join as
|
|
10320
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
10321
|
+
import { join as join21 } from "path";
|
|
9715
10322
|
var SKIP_DIRS4 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
|
|
9716
10323
|
function shouldSkip4(filePath) {
|
|
9717
10324
|
return SKIP_DIRS4.some((d) => filePath.includes(d));
|
|
@@ -9727,7 +10334,7 @@ async function checkAuth(files, projectRoot) {
|
|
|
9727
10334
|
if (shouldSkip4(file.filePath)) continue;
|
|
9728
10335
|
let content;
|
|
9729
10336
|
try {
|
|
9730
|
-
content =
|
|
10337
|
+
content = readFileSync17(join21(projectRoot, file.filePath), "utf-8");
|
|
9731
10338
|
} catch {
|
|
9732
10339
|
continue;
|
|
9733
10340
|
}
|
|
@@ -9818,8 +10425,8 @@ async function checkAuth(files, projectRoot) {
|
|
|
9818
10425
|
}
|
|
9819
10426
|
|
|
9820
10427
|
// src/security/checks/input-validation.ts
|
|
9821
|
-
import { readFileSync as
|
|
9822
|
-
import { join as
|
|
10428
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
10429
|
+
import { join as join22 } from "path";
|
|
9823
10430
|
var SKIP_DIRS5 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
|
|
9824
10431
|
function shouldSkip5(filePath) {
|
|
9825
10432
|
return SKIP_DIRS5.some((d) => filePath.includes(d));
|
|
@@ -9831,7 +10438,7 @@ async function checkInputValidation(files, projectRoot) {
|
|
|
9831
10438
|
if (shouldSkip5(file.filePath)) continue;
|
|
9832
10439
|
let content;
|
|
9833
10440
|
try {
|
|
9834
|
-
content =
|
|
10441
|
+
content = readFileSync18(join22(projectRoot, file.filePath), "utf-8");
|
|
9835
10442
|
} catch {
|
|
9836
10443
|
continue;
|
|
9837
10444
|
}
|
|
@@ -9908,8 +10515,8 @@ async function checkInputValidation(files, projectRoot) {
|
|
|
9908
10515
|
}
|
|
9909
10516
|
|
|
9910
10517
|
// src/security/checks/information-disclosure.ts
|
|
9911
|
-
import { readFileSync as
|
|
9912
|
-
import { join as
|
|
10518
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
10519
|
+
import { join as join23 } from "path";
|
|
9913
10520
|
var SKIP_DIRS6 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
|
|
9914
10521
|
function shouldSkip6(filePath) {
|
|
9915
10522
|
return SKIP_DIRS6.some((d) => filePath.includes(d));
|
|
@@ -9921,7 +10528,7 @@ async function checkInformationDisclosure(files, projectRoot) {
|
|
|
9921
10528
|
if (shouldSkip6(file.filePath)) continue;
|
|
9922
10529
|
let content;
|
|
9923
10530
|
try {
|
|
9924
|
-
content =
|
|
10531
|
+
content = readFileSync19(join23(projectRoot, file.filePath), "utf-8");
|
|
9925
10532
|
} catch {
|
|
9926
10533
|
continue;
|
|
9927
10534
|
}
|
|
@@ -9991,8 +10598,8 @@ async function checkInformationDisclosure(files, projectRoot) {
|
|
|
9991
10598
|
}
|
|
9992
10599
|
|
|
9993
10600
|
// src/security/checks/cryptography.ts
|
|
9994
|
-
import { readFileSync as
|
|
9995
|
-
import { join as
|
|
10601
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
10602
|
+
import { join as join24 } from "path";
|
|
9996
10603
|
var SKIP_DIRS7 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
|
|
9997
10604
|
function shouldSkip7(filePath) {
|
|
9998
10605
|
return SKIP_DIRS7.some((d) => filePath.includes(d));
|
|
@@ -10008,7 +10615,7 @@ async function checkCryptography(files, projectRoot) {
|
|
|
10008
10615
|
if (shouldSkip7(file.filePath)) continue;
|
|
10009
10616
|
let content;
|
|
10010
10617
|
try {
|
|
10011
|
-
content =
|
|
10618
|
+
content = readFileSync20(join24(projectRoot, file.filePath), "utf-8");
|
|
10012
10619
|
} catch {
|
|
10013
10620
|
continue;
|
|
10014
10621
|
}
|
|
@@ -10090,8 +10697,8 @@ async function checkCryptography(files, projectRoot) {
|
|
|
10090
10697
|
}
|
|
10091
10698
|
|
|
10092
10699
|
// src/security/checks/frontend.ts
|
|
10093
|
-
import { readFileSync as
|
|
10094
|
-
import { join as
|
|
10700
|
+
import { readFileSync as readFileSync21 } from "fs";
|
|
10701
|
+
import { join as join25 } from "path";
|
|
10095
10702
|
var SKIP_DIRS8 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
|
|
10096
10703
|
function shouldSkip8(filePath) {
|
|
10097
10704
|
return SKIP_DIRS8.some((d) => filePath.includes(d));
|
|
@@ -10107,7 +10714,7 @@ async function checkFrontend(files, projectRoot) {
|
|
|
10107
10714
|
if (!isFrontendFile(file.filePath)) continue;
|
|
10108
10715
|
let content;
|
|
10109
10716
|
try {
|
|
10110
|
-
content =
|
|
10717
|
+
content = readFileSync21(join25(projectRoot, file.filePath), "utf-8");
|
|
10111
10718
|
} catch {
|
|
10112
10719
|
continue;
|
|
10113
10720
|
}
|
|
@@ -10567,11 +11174,11 @@ async function scanSecurity(projectRoot, graph, options = {}) {
|
|
|
10567
11174
|
};
|
|
10568
11175
|
}
|
|
10569
11176
|
function detectPackageManager(projectRoot) {
|
|
10570
|
-
if (
|
|
10571
|
-
if (
|
|
10572
|
-
if (
|
|
10573
|
-
if (
|
|
10574
|
-
if (
|
|
11177
|
+
if (existsSync15(join26(projectRoot, "package.json"))) return "npm";
|
|
11178
|
+
if (existsSync15(join26(projectRoot, "requirements.txt"))) return "pip";
|
|
11179
|
+
if (existsSync15(join26(projectRoot, "pyproject.toml"))) return "pip";
|
|
11180
|
+
if (existsSync15(join26(projectRoot, "Cargo.toml"))) return "cargo";
|
|
11181
|
+
if (existsSync15(join26(projectRoot, "go.mod"))) return "go";
|
|
10575
11182
|
return "unknown";
|
|
10576
11183
|
}
|
|
10577
11184
|
|