@gulibs/safe-coder 0.0.4 → 0.0.6
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 +112 -1
- package/dist/documentation/github-client.d.ts +3 -1
- package/dist/documentation/github-client.d.ts.map +1 -1
- package/dist/documentation/github-client.js +7 -5
- package/dist/documentation/github-client.js.map +1 -1
- package/dist/documentation/http-fetcher.d.ts +3 -0
- package/dist/documentation/http-fetcher.d.ts.map +1 -1
- package/dist/documentation/http-fetcher.js +6 -2
- package/dist/documentation/http-fetcher.js.map +1 -1
- package/dist/documentation/index.d.ts +5 -3
- package/dist/documentation/index.d.ts.map +1 -1
- package/dist/documentation/index.js +98 -14
- package/dist/documentation/index.js.map +1 -1
- package/dist/documentation/npm-client.d.ts +12 -0
- package/dist/documentation/npm-client.d.ts.map +1 -1
- package/dist/documentation/npm-client.js +150 -17
- package/dist/documentation/npm-client.js.map +1 -1
- package/dist/errors/api-validator.d.ts +9 -0
- package/dist/errors/api-validator.d.ts.map +1 -0
- package/dist/errors/api-validator.js +57 -0
- package/dist/errors/api-validator.js.map +1 -0
- package/dist/errors/contextual-analysis.d.ts +3 -0
- package/dist/errors/contextual-analysis.d.ts.map +1 -1
- package/dist/errors/contextual-analysis.js +102 -4
- package/dist/errors/contextual-analysis.js.map +1 -1
- package/dist/errors/cross-file-analyzer.d.ts +16 -0
- package/dist/errors/cross-file-analyzer.d.ts.map +1 -0
- package/dist/errors/cross-file-analyzer.js +172 -0
- package/dist/errors/cross-file-analyzer.js.map +1 -0
- package/dist/errors/eslint-integration.d.ts +1 -0
- package/dist/errors/eslint-integration.d.ts.map +1 -1
- package/dist/errors/eslint-integration.js +101 -22
- package/dist/errors/eslint-integration.js.map +1 -1
- package/dist/errors/framework-detector.d.ts +10 -0
- package/dist/errors/framework-detector.d.ts.map +1 -0
- package/dist/errors/framework-detector.js +126 -0
- package/dist/errors/framework-detector.js.map +1 -0
- package/dist/errors/index.d.ts +9 -2
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +78 -2
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/patterns.d.ts.map +1 -1
- package/dist/errors/patterns.js +314 -0
- package/dist/errors/patterns.js.map +1 -1
- package/dist/errors/performance-detector.d.ts +11 -0
- package/dist/errors/performance-detector.d.ts.map +1 -0
- package/dist/errors/performance-detector.js +119 -0
- package/dist/errors/performance-detector.js.map +1 -0
- package/dist/errors/runtime-detector.d.ts +7 -0
- package/dist/errors/runtime-detector.d.ts.map +1 -0
- package/dist/errors/runtime-detector.js +86 -0
- package/dist/errors/runtime-detector.js.map +1 -0
- package/dist/errors/security-detector.d.ts +6 -0
- package/dist/errors/security-detector.d.ts.map +1 -0
- package/dist/errors/security-detector.js +75 -0
- package/dist/errors/security-detector.js.map +1 -0
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +155 -61
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/utils/config.d.ts +12 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +24 -0
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/http-client.d.ts +17 -0
- package/dist/utils/http-client.d.ts.map +1 -0
- package/dist/utils/http-client.js +62 -0
- package/dist/utils/http-client.js.map +1 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +128 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +5 -4
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
export class CrossFileAnalyzer {
|
|
2
|
+
enabled;
|
|
3
|
+
constructor(enabled = false) {
|
|
4
|
+
this.enabled = enabled;
|
|
5
|
+
}
|
|
6
|
+
detectErrors(code, filename = 'code.ts', files) {
|
|
7
|
+
if (!this.enabled || !files || files.length === 0) {
|
|
8
|
+
return []; // Cross-file analysis disabled or no files provided
|
|
9
|
+
}
|
|
10
|
+
const errors = [];
|
|
11
|
+
const lines = code.split('\n');
|
|
12
|
+
// Extract imports from current file
|
|
13
|
+
const imports = this.extractImports(code);
|
|
14
|
+
// Check if imported symbols exist in other files
|
|
15
|
+
for (const importItem of imports) {
|
|
16
|
+
const sourceFile = files.find(f => f.path === importItem.source ||
|
|
17
|
+
f.path.endsWith(importItem.source.replace(/^\.\//, '')));
|
|
18
|
+
if (sourceFile) {
|
|
19
|
+
const exportedSymbols = this.extractExports(sourceFile.content);
|
|
20
|
+
for (const symbol of importItem.symbols) {
|
|
21
|
+
if (!exportedSymbols.has(symbol) && symbol !== '*') {
|
|
22
|
+
errors.push({
|
|
23
|
+
type: 'cross-file',
|
|
24
|
+
message: `Symbol '${symbol}' is imported from '${importItem.source}' but not exported`,
|
|
25
|
+
line: importItem.line,
|
|
26
|
+
column: importItem.column,
|
|
27
|
+
priority: 2,
|
|
28
|
+
fix: `Export '${symbol}' from '${importItem.source}' or remove the import`,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if (!importItem.source.startsWith('.')) {
|
|
34
|
+
// External import, skip
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// File not found
|
|
39
|
+
errors.push({
|
|
40
|
+
type: 'cross-file',
|
|
41
|
+
message: `Import source '${importItem.source}' not found in provided files`,
|
|
42
|
+
line: importItem.line,
|
|
43
|
+
column: importItem.column,
|
|
44
|
+
priority: 2,
|
|
45
|
+
fix: `Ensure '${importItem.source}' is included in file context`,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Detect circular dependencies (basic)
|
|
50
|
+
const circularDeps = this.detectCircularDependencies(files);
|
|
51
|
+
errors.push(...circularDeps);
|
|
52
|
+
return this.prioritize(errors);
|
|
53
|
+
}
|
|
54
|
+
extractImports(code) {
|
|
55
|
+
const imports = [];
|
|
56
|
+
const lines = code.split('\n');
|
|
57
|
+
for (let i = 0; i < lines.length; i++) {
|
|
58
|
+
const line = lines[i];
|
|
59
|
+
// Match: import { a, b } from 'source'
|
|
60
|
+
const namedMatch = line.match(/import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]/);
|
|
61
|
+
if (namedMatch) {
|
|
62
|
+
const symbols = namedMatch[1].split(',').map(s => s.trim().split(' as ')[0].trim());
|
|
63
|
+
imports.push({
|
|
64
|
+
source: namedMatch[2],
|
|
65
|
+
symbols,
|
|
66
|
+
line: i + 1,
|
|
67
|
+
column: line.indexOf('import') + 1,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
// Match: import * as name from 'source'
|
|
71
|
+
const namespaceMatch = line.match(/import\s+\*\s+as\s+(\w+)\s+from\s+['"]([^'"]+)['"]/);
|
|
72
|
+
if (namespaceMatch) {
|
|
73
|
+
imports.push({
|
|
74
|
+
source: namespaceMatch[2],
|
|
75
|
+
symbols: ['*'],
|
|
76
|
+
line: i + 1,
|
|
77
|
+
column: line.indexOf('import') + 1,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// Match: import default from 'source'
|
|
81
|
+
const defaultMatch = line.match(/import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/);
|
|
82
|
+
if (defaultMatch && !defaultMatch[0].includes('{')) {
|
|
83
|
+
imports.push({
|
|
84
|
+
source: defaultMatch[2],
|
|
85
|
+
symbols: ['default'],
|
|
86
|
+
line: i + 1,
|
|
87
|
+
column: line.indexOf('import') + 1,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return imports;
|
|
92
|
+
}
|
|
93
|
+
extractExports(code) {
|
|
94
|
+
const exports = new Set();
|
|
95
|
+
const lines = code.split('\n');
|
|
96
|
+
for (const line of lines) {
|
|
97
|
+
// Match: export const/let/var/function name
|
|
98
|
+
const exportMatch = line.match(/export\s+(?:const|let|var|function|class|interface|type)\s+(\w+)/);
|
|
99
|
+
if (exportMatch) {
|
|
100
|
+
exports.add(exportMatch[1]);
|
|
101
|
+
}
|
|
102
|
+
// Match: export { a, b }
|
|
103
|
+
const namedExportMatch = line.match(/export\s+\{([^}]+)\}/);
|
|
104
|
+
if (namedExportMatch) {
|
|
105
|
+
const symbols = namedExportMatch[1].split(',').map(s => s.trim().split(' as ')[0].trim());
|
|
106
|
+
symbols.forEach(s => exports.add(s));
|
|
107
|
+
}
|
|
108
|
+
// Match: export default
|
|
109
|
+
if (line.match(/export\s+default/)) {
|
|
110
|
+
exports.add('default');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return exports;
|
|
114
|
+
}
|
|
115
|
+
detectCircularDependencies(files) {
|
|
116
|
+
const errors = [];
|
|
117
|
+
const dependencyGraph = new Map();
|
|
118
|
+
// Build dependency graph
|
|
119
|
+
for (const file of files) {
|
|
120
|
+
const imports = this.extractImports(file.content);
|
|
121
|
+
const deps = new Set();
|
|
122
|
+
for (const imp of imports) {
|
|
123
|
+
if (imp.source.startsWith('.')) {
|
|
124
|
+
// Resolve relative path (simplified)
|
|
125
|
+
const depFile = files.find(f => f.path.includes(imp.source.replace(/^\.\//, '')));
|
|
126
|
+
if (depFile) {
|
|
127
|
+
deps.add(depFile.path);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
dependencyGraph.set(file.path, deps);
|
|
132
|
+
}
|
|
133
|
+
// Detect cycles (simplified DFS)
|
|
134
|
+
for (const [file, deps] of dependencyGraph.entries()) {
|
|
135
|
+
const visited = new Set();
|
|
136
|
+
const cycle = this.findCycle(file, file, dependencyGraph, visited, []);
|
|
137
|
+
if (cycle) {
|
|
138
|
+
errors.push({
|
|
139
|
+
type: 'cross-file',
|
|
140
|
+
message: `Circular dependency detected: ${cycle.join(' -> ')}`,
|
|
141
|
+
line: 1,
|
|
142
|
+
column: 1,
|
|
143
|
+
priority: 4,
|
|
144
|
+
fix: 'Refactor to break circular dependency',
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return errors;
|
|
149
|
+
}
|
|
150
|
+
findCycle(start, current, graph, visited, path) {
|
|
151
|
+
if (path.includes(current)) {
|
|
152
|
+
return [...path, current];
|
|
153
|
+
}
|
|
154
|
+
if (visited.has(current)) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
visited.add(current);
|
|
158
|
+
path.push(current);
|
|
159
|
+
const deps = graph.get(current) || new Set();
|
|
160
|
+
for (const dep of deps) {
|
|
161
|
+
const cycle = this.findCycle(start, dep, graph, visited, [...path]);
|
|
162
|
+
if (cycle) {
|
|
163
|
+
return cycle;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
prioritize(errors) {
|
|
169
|
+
return errors.sort((a, b) => a.priority - b.priority);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=cross-file-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-file-analyzer.js","sourceRoot":"","sources":["../../src/errors/cross-file-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-integration.d.ts","sourceRoot":"","sources":["../../src/errors/eslint-integration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAuB;;
|
|
1
|
+
{"version":3,"file":"eslint-integration.d.ts","sourceRoot":"","sources":["../../src/errors/eslint-integration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,WAAW,CAAuB;;IAuEpC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IA4DxF,OAAO,CAAC,UAAU;CAGnB"}
|
|
@@ -1,49 +1,128 @@
|
|
|
1
1
|
import { ESLint } from 'eslint';
|
|
2
2
|
export class ESLintIntegration {
|
|
3
3
|
eslint = null;
|
|
4
|
+
reactESLint = null;
|
|
4
5
|
constructor() {
|
|
5
6
|
try {
|
|
7
|
+
// Base ESLint with TypeScript support
|
|
6
8
|
this.eslint = new ESLint({
|
|
7
9
|
overrideConfig: {
|
|
8
10
|
rules: {
|
|
9
|
-
|
|
11
|
+
// Base rules
|
|
12
|
+
'no-unused-vars': 'off', // Use TypeScript version instead
|
|
10
13
|
'no-undef': 'error',
|
|
11
14
|
'no-console': 'off',
|
|
15
|
+
// TypeScript ESLint rules
|
|
16
|
+
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
|
|
17
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
18
|
+
'@typescript-eslint/explicit-function-return-type': 'off', // Too strict for general use
|
|
19
|
+
'@typescript-eslint/no-non-null-assertion': 'warn',
|
|
20
|
+
'@typescript-eslint/prefer-nullish-coalescing': 'warn',
|
|
21
|
+
'@typescript-eslint/prefer-optional-chain': 'warn',
|
|
22
|
+
'@typescript-eslint/no-floating-promises': 'error',
|
|
23
|
+
'@typescript-eslint/await-thenable': 'error',
|
|
24
|
+
// Security rules
|
|
25
|
+
'security/detect-object-injection': 'warn',
|
|
26
|
+
'security/detect-non-literal-regexp': 'warn',
|
|
27
|
+
'security/detect-unsafe-regex': 'error',
|
|
28
|
+
'security/detect-buffer-noassert': 'warn',
|
|
29
|
+
'security/detect-child-process': 'warn',
|
|
30
|
+
'security/detect-disable-mustache-escape': 'warn',
|
|
31
|
+
'security/detect-eval-with-expression': 'error',
|
|
32
|
+
'security/detect-no-csrf-before-method-override': 'warn',
|
|
33
|
+
'security/detect-non-literal-fs-filename': 'warn',
|
|
34
|
+
'security/detect-non-literal-require': 'warn',
|
|
35
|
+
'security/detect-possible-timing-attacks': 'warn',
|
|
36
|
+
'security/detect-pseudoRandomBytes': 'warn',
|
|
12
37
|
},
|
|
13
38
|
},
|
|
14
39
|
});
|
|
40
|
+
// React ESLint (optional, only if React code detected)
|
|
41
|
+
try {
|
|
42
|
+
this.reactESLint = new ESLint({
|
|
43
|
+
overrideConfig: {
|
|
44
|
+
rules: {
|
|
45
|
+
// React rules
|
|
46
|
+
'react/react-in-jsx-scope': 'off', // Not needed in React 17+
|
|
47
|
+
'react/prop-types': 'off', // Using TypeScript instead
|
|
48
|
+
'react-hooks/rules-of-hooks': 'error',
|
|
49
|
+
'react-hooks/exhaustive-deps': 'warn',
|
|
50
|
+
'react/jsx-uses-react': 'off',
|
|
51
|
+
'react/jsx-uses-vars': 'error',
|
|
52
|
+
},
|
|
53
|
+
settings: {
|
|
54
|
+
react: {
|
|
55
|
+
version: 'detect',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// React ESLint not available, continue without it
|
|
63
|
+
this.reactESLint = null;
|
|
64
|
+
}
|
|
15
65
|
}
|
|
16
66
|
catch (error) {
|
|
17
67
|
// ESLint initialization failed, continue without it
|
|
18
68
|
this.eslint = null;
|
|
69
|
+
this.reactESLint = null;
|
|
19
70
|
}
|
|
20
71
|
}
|
|
21
72
|
async detectErrors(code, filename = 'code.ts') {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
73
|
+
const errors = [];
|
|
74
|
+
// Detect if this is React code
|
|
75
|
+
const isReactCode = code.includes('import') && (code.includes('react') || code.includes('React')) ||
|
|
76
|
+
filename.endsWith('.tsx') || filename.endsWith('.jsx');
|
|
77
|
+
// Use base ESLint
|
|
78
|
+
if (this.eslint) {
|
|
79
|
+
try {
|
|
80
|
+
const results = await this.eslint.lintText(code, { filePath: filename });
|
|
81
|
+
for (const result of results) {
|
|
82
|
+
for (const message of result.messages) {
|
|
83
|
+
// Security errors get highest priority
|
|
84
|
+
const isSecurity = message.ruleId?.startsWith('security/');
|
|
85
|
+
const priority = isSecurity ? 1 : (message.severity === 2 ? 1 : 5);
|
|
86
|
+
errors.push({
|
|
87
|
+
type: isSecurity ? 'security' : 'eslint',
|
|
88
|
+
message: message.message,
|
|
89
|
+
line: message.line,
|
|
90
|
+
column: message.column,
|
|
91
|
+
priority,
|
|
92
|
+
fix: message.fix ? 'Auto-fix available' : undefined,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
39
95
|
}
|
|
40
96
|
}
|
|
41
|
-
|
|
97
|
+
catch (error) {
|
|
98
|
+
// ESLint might fail, continue
|
|
99
|
+
}
|
|
42
100
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
101
|
+
// Use React ESLint if available and code is React
|
|
102
|
+
if (isReactCode && this.reactESLint) {
|
|
103
|
+
try {
|
|
104
|
+
const results = await this.reactESLint.lintText(code, { filePath: filename });
|
|
105
|
+
for (const result of results) {
|
|
106
|
+
for (const message of result.messages) {
|
|
107
|
+
// React Hooks violations are critical
|
|
108
|
+
const isHooksError = message.ruleId?.startsWith('react-hooks/');
|
|
109
|
+
const priority = isHooksError ? 1 : (message.severity === 2 ? 1 : 5);
|
|
110
|
+
errors.push({
|
|
111
|
+
type: 'react',
|
|
112
|
+
message: message.message,
|
|
113
|
+
line: message.line,
|
|
114
|
+
column: message.column,
|
|
115
|
+
priority,
|
|
116
|
+
fix: message.fix ? 'Auto-fix available' : undefined,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
// React ESLint might fail, continue
|
|
123
|
+
}
|
|
46
124
|
}
|
|
125
|
+
return this.prioritize(errors);
|
|
47
126
|
}
|
|
48
127
|
prioritize(errors) {
|
|
49
128
|
return errors.sort((a, b) => a.priority - b.priority);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-integration.js","sourceRoot":"","sources":["../../src/errors/eslint-integration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,MAAM,OAAO,iBAAiB;IACpB,MAAM,GAAkB,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"eslint-integration.js","sourceRoot":"","sources":["../../src/errors/eslint-integration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DetectedError } from './pattern-matcher.js';
|
|
2
|
+
export declare class FrameworkDetector {
|
|
3
|
+
detectErrors(code: string, filename?: string): DetectedError[];
|
|
4
|
+
private detectReactErrors;
|
|
5
|
+
private detectNextJsErrors;
|
|
6
|
+
private detectVueErrors;
|
|
7
|
+
private isInRenderFunction;
|
|
8
|
+
private prioritize;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=framework-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework-detector.d.ts","sourceRoot":"","sources":["../../src/errors/framework-detector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,qBAAa,iBAAiB;IAC5B,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB,GAAG,aAAa,EAAE;IA2BzE,OAAO,CAAC,iBAAiB;IAsDzB,OAAO,CAAC,kBAAkB;IA0B1B,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,UAAU;CAGnB"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
export class FrameworkDetector {
|
|
2
|
+
detectErrors(code, filename = 'code.ts') {
|
|
3
|
+
const errors = [];
|
|
4
|
+
const lines = code.split('\n');
|
|
5
|
+
// Detect React code
|
|
6
|
+
const isReact = code.includes('react') || filename.endsWith('.tsx') || filename.endsWith('.jsx');
|
|
7
|
+
const isNextJs = code.includes('next/') || code.includes('getServerSideProps') || code.includes('getStaticProps');
|
|
8
|
+
const isVue = code.includes('vue') || filename.endsWith('.vue');
|
|
9
|
+
if (isReact) {
|
|
10
|
+
const reactErrors = this.detectReactErrors(code, lines);
|
|
11
|
+
errors.push(...reactErrors);
|
|
12
|
+
}
|
|
13
|
+
if (isNextJs) {
|
|
14
|
+
const nextErrors = this.detectNextJsErrors(code, lines);
|
|
15
|
+
errors.push(...nextErrors);
|
|
16
|
+
}
|
|
17
|
+
if (isVue) {
|
|
18
|
+
const vueErrors = this.detectVueErrors(code, lines);
|
|
19
|
+
errors.push(...vueErrors);
|
|
20
|
+
}
|
|
21
|
+
return this.prioritize(errors);
|
|
22
|
+
}
|
|
23
|
+
detectReactErrors(code, lines) {
|
|
24
|
+
const errors = [];
|
|
25
|
+
for (let i = 0; i < lines.length; i++) {
|
|
26
|
+
const line = lines[i];
|
|
27
|
+
const lineNumber = i + 1;
|
|
28
|
+
// Detect conditional hooks (already handled by ESLint, but add pattern matching)
|
|
29
|
+
const conditionalHookMatch = line.match(/(if|for|while|switch)\s*\([^)]*\)\s*\{[^}]*\b(use[A-Z]\w+)\s*\(/);
|
|
30
|
+
if (conditionalHookMatch) {
|
|
31
|
+
errors.push({
|
|
32
|
+
type: 'react',
|
|
33
|
+
message: `React Hook '${conditionalHookMatch[2]}' called conditionally violates Rules of Hooks`,
|
|
34
|
+
line: lineNumber,
|
|
35
|
+
column: line.indexOf(conditionalHookMatch[0]) + 1,
|
|
36
|
+
priority: 1,
|
|
37
|
+
fix: 'Move hook outside conditional or use early return',
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// Detect missing key in map
|
|
41
|
+
const mapMatch = line.match(/\.map\s*\([^)]*\)\s*=>/);
|
|
42
|
+
if (mapMatch) {
|
|
43
|
+
// Check if next few lines have JSX without key
|
|
44
|
+
const nextLines = lines.slice(i, Math.min(i + 5, lines.length)).join('\n');
|
|
45
|
+
if (nextLines.includes('<') && !nextLines.includes('key=')) {
|
|
46
|
+
errors.push({
|
|
47
|
+
type: 'react',
|
|
48
|
+
message: 'List item missing key prop',
|
|
49
|
+
line: lineNumber,
|
|
50
|
+
column: line.indexOf(mapMatch[0]) + 1,
|
|
51
|
+
priority: 3,
|
|
52
|
+
fix: 'Add unique key prop to list items',
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Detect setState in render
|
|
57
|
+
const setStateMatch = line.match(/setState\s*\(/);
|
|
58
|
+
if (setStateMatch && this.isInRenderFunction(code, i)) {
|
|
59
|
+
errors.push({
|
|
60
|
+
type: 'react',
|
|
61
|
+
message: 'setState called during render may cause infinite loop',
|
|
62
|
+
line: lineNumber,
|
|
63
|
+
column: line.indexOf(setStateMatch[0]) + 1,
|
|
64
|
+
priority: 2,
|
|
65
|
+
fix: 'Move setState to useEffect or event handler',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return errors;
|
|
70
|
+
}
|
|
71
|
+
detectNextJsErrors(code, lines) {
|
|
72
|
+
const errors = [];
|
|
73
|
+
for (let i = 0; i < lines.length; i++) {
|
|
74
|
+
const line = lines[i];
|
|
75
|
+
const lineNumber = i + 1;
|
|
76
|
+
// Detect server functions in client components
|
|
77
|
+
if (code.includes("'use client'")) {
|
|
78
|
+
const serverFuncMatch = line.match(/\b(getServerSideProps|getStaticProps|getStaticPaths)\s*\(/);
|
|
79
|
+
if (serverFuncMatch) {
|
|
80
|
+
errors.push({
|
|
81
|
+
type: 'nextjs',
|
|
82
|
+
message: `Server function '${serverFuncMatch[1]}' used in client component`,
|
|
83
|
+
line: lineNumber,
|
|
84
|
+
column: line.indexOf(serverFuncMatch[0]) + 1,
|
|
85
|
+
priority: 2,
|
|
86
|
+
fix: 'Remove server functions from client component',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return errors;
|
|
92
|
+
}
|
|
93
|
+
detectVueErrors(code, lines) {
|
|
94
|
+
const errors = [];
|
|
95
|
+
// Basic Vue error detection
|
|
96
|
+
for (let i = 0; i < lines.length; i++) {
|
|
97
|
+
const line = lines[i];
|
|
98
|
+
const lineNumber = i + 1;
|
|
99
|
+
// Detect Vue lifecycle hook issues (basic)
|
|
100
|
+
const lifecycleMatch = line.match(/\b(mounted|created|updated)\s*\([^)]*\)\s*\{/);
|
|
101
|
+
if (lifecycleMatch) {
|
|
102
|
+
// Check if async without proper handling
|
|
103
|
+
if (line.includes('async') && !line.includes('await')) {
|
|
104
|
+
errors.push({
|
|
105
|
+
type: 'vue',
|
|
106
|
+
message: `Vue lifecycle hook '${lifecycleMatch[1]}' is async but may not handle errors`,
|
|
107
|
+
line: lineNumber,
|
|
108
|
+
column: line.indexOf(lifecycleMatch[0]) + 1,
|
|
109
|
+
priority: 3,
|
|
110
|
+
fix: 'Add error handling for async lifecycle hooks',
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return errors;
|
|
116
|
+
}
|
|
117
|
+
isInRenderFunction(code, lineIndex) {
|
|
118
|
+
const beforeCode = code.split('\n').slice(0, lineIndex + 1).join('\n');
|
|
119
|
+
// Simple heuristic: check if we're in a function that returns JSX
|
|
120
|
+
return beforeCode.includes('return') && (beforeCode.includes('<') || beforeCode.includes('React.createElement'));
|
|
121
|
+
}
|
|
122
|
+
prioritize(errors) {
|
|
123
|
+
return errors.sort((a, b) => a.priority - b.priority);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=framework-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework-detector.js","sourceRoot":"","sources":["../../src/errors/framework-detector.ts"],"names":[],"mappings":"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"}
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { type DetectedError } from './pattern-matcher.js';
|
|
2
|
+
import { type FileContext } from './cross-file-analyzer.js';
|
|
2
3
|
export declare class ErrorDetectionService {
|
|
3
4
|
private patternMatcher;
|
|
4
5
|
private eslint;
|
|
5
6
|
private typescript;
|
|
6
7
|
private contextual;
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
private runtime;
|
|
9
|
+
private performance;
|
|
10
|
+
private security;
|
|
11
|
+
private framework;
|
|
12
|
+
private apiValidator;
|
|
13
|
+
private crossFile;
|
|
14
|
+
constructor(enableRuntime?: boolean, enablePerformance?: boolean, enableSecurity?: boolean, enableFramework?: boolean, enableApiValidation?: boolean, enableCrossFile?: boolean);
|
|
15
|
+
detectErrors(code: string, filename?: string, files?: FileContext[]): Promise<DetectedError[]>;
|
|
9
16
|
private deduplicateAndPrioritize;
|
|
10
17
|
}
|
|
11
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAS1E,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE/E,qBAAa,qBAAqB;IAChC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,SAAS,CAAoB;gBAGnC,aAAa,GAAE,OAAc,EAC7B,iBAAiB,GAAE,OAAc,EACjC,cAAc,GAAE,OAAc,EAC9B,eAAe,GAAE,OAAc,EAC/B,mBAAmB,GAAE,OAAc,EACnC,eAAe,GAAE,OAAe;IAc5B,YAAY,CAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAkB,EAC5B,KAAK,CAAC,EAAE,WAAW,EAAE,GACpB,OAAO,CAAC,aAAa,EAAE,CAAC;IAyF3B,OAAO,CAAC,wBAAwB;CAgBjC"}
|