@sudu-cli/fronted-preview-mcp 1.0.0-beta.3 → 1.0.0-beta.5
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/dist/cdp/connectionManager.d.ts +57 -0
- package/dist/cdp/connectionManager.js +153 -0
- package/dist/cdp/connectionManager.js.map +1 -0
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/constants.d.ts +19 -0
- package/dist/constants.js +26 -0
- package/dist/constants.js.map +1 -0
- package/dist/detectors/frameworkDetector.js +17 -13
- package/dist/detectors/frameworkDetector.js.map +1 -1
- package/dist/handlers/autoFixLoop.d.ts +24 -0
- package/dist/handlers/autoFixLoop.js +81 -4
- package/dist/handlers/autoFixLoop.js.map +1 -1
- package/dist/handlers/checkPageErrors.js +11 -50
- package/dist/handlers/checkPageErrors.js.map +1 -1
- package/dist/handlers/typescriptDiagnostics.d.ts +9 -0
- package/dist/handlers/typescriptDiagnostics.js +4 -25
- package/dist/handlers/typescriptDiagnostics.js.map +1 -1
- package/dist/index.js +15 -3
- package/dist/index.js.map +1 -1
- package/dist/serverManager.d.ts +22 -4
- package/dist/serverManager.js +215 -140
- package/dist/serverManager.js.map +1 -1
- package/dist/strategies/baseStrategy.d.ts +27 -0
- package/dist/strategies/baseStrategy.js +23 -0
- package/dist/strategies/baseStrategy.js.map +1 -0
- package/dist/strategies/index.d.ts +9 -0
- package/dist/strategies/index.js +22 -0
- package/dist/strategies/index.js.map +1 -0
- package/dist/strategies/missingImport.d.ts +16 -0
- package/dist/strategies/missingImport.js +156 -0
- package/dist/strategies/missingImport.js.map +1 -0
- package/dist/strategies/missingProperty.d.ts +13 -0
- package/dist/strategies/missingProperty.js +134 -0
- package/dist/strategies/missingProperty.js.map +1 -0
- package/dist/strategies/networkError.d.ts +10 -0
- package/dist/strategies/networkError.js +56 -0
- package/dist/strategies/networkError.js.map +1 -0
- package/dist/strategies/nullCheckInsertion.d.ts +14 -0
- package/dist/strategies/nullCheckInsertion.js +138 -0
- package/dist/strategies/nullCheckInsertion.js.map +1 -0
- package/dist/strategies/typeAssignment.d.ts +13 -0
- package/dist/strategies/typeAssignment.js +121 -0
- package/dist/strategies/typeAssignment.js.map +1 -0
- package/dist/strategies/unusedImportRemoval.d.ts +11 -0
- package/dist/strategies/unusedImportRemoval.js +138 -0
- package/dist/strategies/unusedImportRemoval.js.map +1 -0
- package/dist/types.d.ts +9 -0
- package/dist/types.js +21 -1
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts +7 -0
- package/dist/version.js +10 -0
- package/dist/version.js.map +1 -0
- package/package.json +1 -1
- package/templates/init/instructions.md +1 -11
- package/templates/init/opencode.json +1 -1
- package/dist/handlers/pickElement.d.ts +0 -10
- package/dist/handlers/pickElement.js +0 -413
- package/dist/handlers/pickElement.js.map +0 -1
- package/dist/handlers/takeScreenshot.d.ts +0 -17
- package/dist/handlers/takeScreenshot.js +0 -83
- package/dist/handlers/takeScreenshot.js.map +0 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Block, SyntaxKind } from 'ts-morph';
|
|
2
|
+
import { getSourceFile, getRelativePath, saveChanges } from './baseStrategy.js';
|
|
3
|
+
export class NullCheckInsertionStrategy {
|
|
4
|
+
errorType = 'console';
|
|
5
|
+
pattern = /Cannot read propert(?:y|ies) of (?:null|undefined)|Cannot read property '([^']+)' of (?:null|undefined)|is (?:null|undefined) and has no property/i;
|
|
6
|
+
canFix(error) {
|
|
7
|
+
return this.pattern.test(error.message);
|
|
8
|
+
}
|
|
9
|
+
async fix(context, error) {
|
|
10
|
+
const changes = [];
|
|
11
|
+
if (!error.url) {
|
|
12
|
+
return { success: false, message: 'No URL in console error', changes };
|
|
13
|
+
}
|
|
14
|
+
// Extract file path from URL (e.g., http://localhost:3000/src/main.ts -> src/main.ts)
|
|
15
|
+
const filePath = this.extractFilePathFromUrl(error.url);
|
|
16
|
+
if (!filePath) {
|
|
17
|
+
return { success: false, message: 'Could not extract file path from URL', changes };
|
|
18
|
+
}
|
|
19
|
+
const sourceFile = getSourceFile(context, filePath);
|
|
20
|
+
if (!sourceFile) {
|
|
21
|
+
return { success: false, message: `Source file not found: ${filePath}`, changes };
|
|
22
|
+
}
|
|
23
|
+
const originalText = sourceFile.getFullText();
|
|
24
|
+
const targetLine = error.lineNumber || 1;
|
|
25
|
+
try {
|
|
26
|
+
// Find the problematic property access at the error line
|
|
27
|
+
const propertyAccess = this.findPropertyAccessAtLine(sourceFile, targetLine);
|
|
28
|
+
if (!propertyAccess) {
|
|
29
|
+
return { success: false, message: `No property access found at line ${targetLine}`, changes };
|
|
30
|
+
}
|
|
31
|
+
// Strategy 1: Try to add optional chaining (?.) - modern and clean
|
|
32
|
+
const addedOptionalChaining = this.addOptionalChaining(propertyAccess);
|
|
33
|
+
if (!addedOptionalChaining) {
|
|
34
|
+
// Strategy 2: Wrap with null check if statement
|
|
35
|
+
const wrapped = this.wrapWithNullCheck(propertyAccess);
|
|
36
|
+
if (!wrapped) {
|
|
37
|
+
return { success: false, message: 'Could not add null check or optional chaining', changes };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
saveChanges(context);
|
|
41
|
+
const newText = sourceFile.getFullText();
|
|
42
|
+
const diff = this.generateDiff(originalText, newText, filePath);
|
|
43
|
+
changes.push({
|
|
44
|
+
file: getRelativePath(context, filePath),
|
|
45
|
+
description: `Added null/undefined check for property access at line ${targetLine}`,
|
|
46
|
+
diff,
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
success: true,
|
|
50
|
+
message: `Fixed null/undefined property access at line ${targetLine}`,
|
|
51
|
+
changes,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
56
|
+
return { success: false, message: `Fix failed: ${msg}`, changes };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
extractFilePathFromUrl(url) {
|
|
60
|
+
try {
|
|
61
|
+
const urlObj = new URL(url);
|
|
62
|
+
const pathname = urlObj.pathname;
|
|
63
|
+
// Remove leading slash and common prefixes
|
|
64
|
+
return pathname.replace(/^\//, '').replace(/^src\//, '').replace(/^app\//, '');
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
findPropertyAccessAtLine(sourceFile, line) {
|
|
71
|
+
const propertyAccesses = sourceFile.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression);
|
|
72
|
+
for (const propAccess of propertyAccesses) {
|
|
73
|
+
const startLine = propAccess.getStartLineNumber();
|
|
74
|
+
const endLine = propAccess.getEndLineNumber();
|
|
75
|
+
if (startLine <= line && endLine >= line) {
|
|
76
|
+
return propAccess;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
addOptionalChaining(propAccess) {
|
|
82
|
+
try {
|
|
83
|
+
// Check if it already has optional chaining
|
|
84
|
+
const expression = propAccess.getExpression();
|
|
85
|
+
if (expression.getKind() === SyntaxKind.NonNullExpression) {
|
|
86
|
+
return false; // Already has !
|
|
87
|
+
}
|
|
88
|
+
// Add optional chaining by replacing the dot with ?.
|
|
89
|
+
// We need to replace the entire property access expression
|
|
90
|
+
const exprText = propAccess.getExpression().getText();
|
|
91
|
+
const name = propAccess.getName();
|
|
92
|
+
const newText = `${exprText}?.${name}`;
|
|
93
|
+
propAccess.replaceWithText(newText);
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
wrapWithNullCheck(propAccess) {
|
|
101
|
+
try {
|
|
102
|
+
const statement = propAccess.getFirstAncestorByKind(SyntaxKind.ExpressionStatement);
|
|
103
|
+
if (!statement)
|
|
104
|
+
return false;
|
|
105
|
+
const parent = statement.getParent();
|
|
106
|
+
if (!parent || !Block.isBlock(parent))
|
|
107
|
+
return false;
|
|
108
|
+
const exprText = statement.getText().trim();
|
|
109
|
+
const checkExpr = propAccess.getExpression().getText();
|
|
110
|
+
// Create if statement: if (obj != null) { obj.prop = ...; }
|
|
111
|
+
const ifStatement = `if (${checkExpr} != null) {\n ${exprText}\n}`;
|
|
112
|
+
statement.replaceWithText(ifStatement);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
generateDiff(oldText, newText, fileName) {
|
|
120
|
+
const oldLines = oldText.split('\n');
|
|
121
|
+
const newLines = newText.split('\n');
|
|
122
|
+
let diff = `--- ${fileName}\n+++ ${fileName}\n`;
|
|
123
|
+
const maxLen = Math.max(oldLines.length, newLines.length);
|
|
124
|
+
for (let i = 0; i < maxLen; i++) {
|
|
125
|
+
const oldLine = oldLines[i];
|
|
126
|
+
const newLine = newLines[i];
|
|
127
|
+
if (oldLine !== newLine) {
|
|
128
|
+
if (oldLine !== undefined)
|
|
129
|
+
diff += `-${oldLine}\n`;
|
|
130
|
+
if (newLine !== undefined)
|
|
131
|
+
diff += `+${newLine}\n`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return diff;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
export const nullCheckInsertionStrategy = new NullCheckInsertionStrategy();
|
|
138
|
+
//# sourceMappingURL=nullCheckInsertion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nullCheckInsertion.js","sourceRoot":"","sources":["../../src/strategies/nullCheckInsertion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FixStrategy, FixContext, FixResult } from './baseStrategy.js';
|
|
2
|
+
import { DiagnosticInfo } from '../handlers/typescriptDiagnostics.js';
|
|
3
|
+
export declare class TypeAssignmentStrategy implements FixStrategy {
|
|
4
|
+
errorType: "typescript";
|
|
5
|
+
pattern: RegExp;
|
|
6
|
+
canFix(error: DiagnosticInfo): boolean;
|
|
7
|
+
fix(context: FixContext, error: DiagnosticInfo): Promise<FixResult>;
|
|
8
|
+
private findExpressionAtLine;
|
|
9
|
+
private isFixableExpression;
|
|
10
|
+
private addTypeAssertion;
|
|
11
|
+
private generateDiff;
|
|
12
|
+
}
|
|
13
|
+
export declare const typeAssignmentStrategy: TypeAssignmentStrategy;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { SyntaxKind } from 'ts-morph';
|
|
2
|
+
import { getSourceFile, getRelativePath, saveChanges } from './baseStrategy.js';
|
|
3
|
+
export class TypeAssignmentStrategy {
|
|
4
|
+
errorType = 'typescript';
|
|
5
|
+
pattern = /Type '([^']+)' is not assignable to type '([^']+)'/i;
|
|
6
|
+
canFix(error) {
|
|
7
|
+
return this.pattern.test(error.message) && error.severity === 'error';
|
|
8
|
+
}
|
|
9
|
+
async fix(context, error) {
|
|
10
|
+
const changes = [];
|
|
11
|
+
if (!error.file || error.line === undefined) {
|
|
12
|
+
return { success: false, message: 'No file path or line number in error', changes };
|
|
13
|
+
}
|
|
14
|
+
const match = error.message.match(this.pattern);
|
|
15
|
+
if (!match) {
|
|
16
|
+
return { success: false, message: 'Could not parse type assignment error', changes };
|
|
17
|
+
}
|
|
18
|
+
const sourceType = match[1];
|
|
19
|
+
const targetType = match[2];
|
|
20
|
+
const sourceFile = getSourceFile(context, error.file);
|
|
21
|
+
if (!sourceFile) {
|
|
22
|
+
return { success: false, message: `Source file not found: ${error.file}`, changes };
|
|
23
|
+
}
|
|
24
|
+
const originalText = sourceFile.getFullText();
|
|
25
|
+
try {
|
|
26
|
+
// Find the expression at the error location
|
|
27
|
+
const expression = this.findExpressionAtLine(sourceFile, error.line);
|
|
28
|
+
if (!expression) {
|
|
29
|
+
return { success: false, message: `No expression found at line ${error.line}`, changes };
|
|
30
|
+
}
|
|
31
|
+
// Strategy: Add type assertion (as targetType) to the expression
|
|
32
|
+
const fixed = this.addTypeAssertion(expression, targetType);
|
|
33
|
+
if (!fixed) {
|
|
34
|
+
return { success: false, message: 'Could not add type assertion to expression', changes };
|
|
35
|
+
}
|
|
36
|
+
saveChanges(context);
|
|
37
|
+
const newText = sourceFile.getFullText();
|
|
38
|
+
const diff = this.generateDiff(originalText, newText, error.file);
|
|
39
|
+
changes.push({
|
|
40
|
+
file: getRelativePath(context, error.file),
|
|
41
|
+
description: `Added type assertion 'as ${targetType}' to fix assignment`,
|
|
42
|
+
diff,
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
success: true,
|
|
46
|
+
message: `Fixed type assignment: added 'as ${targetType}' assertion`,
|
|
47
|
+
changes,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
52
|
+
return { success: false, message: `Fix failed: ${msg}`, changes };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
findExpressionAtLine(sourceFile, line) {
|
|
56
|
+
// Get all expressions in the file and find one at the target line
|
|
57
|
+
const expressions = sourceFile.getDescendantsOfKind(SyntaxKind.Identifier);
|
|
58
|
+
for (const expr of expressions) {
|
|
59
|
+
const startLine = expr.getStartLineNumber();
|
|
60
|
+
const endLine = expr.getEndLineNumber();
|
|
61
|
+
if (startLine <= line && endLine >= line) {
|
|
62
|
+
// Prefer variable declarations, call expressions, property access
|
|
63
|
+
if (this.isFixableExpression(expr)) {
|
|
64
|
+
return expr;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
isFixableExpression(expr) {
|
|
71
|
+
const kind = expr.getKind();
|
|
72
|
+
return (kind === SyntaxKind.VariableDeclaration ||
|
|
73
|
+
kind === SyntaxKind.CallExpression ||
|
|
74
|
+
kind === SyntaxKind.PropertyAccessExpression ||
|
|
75
|
+
kind === SyntaxKind.Identifier ||
|
|
76
|
+
kind === SyntaxKind.AsExpression);
|
|
77
|
+
}
|
|
78
|
+
addTypeAssertion(expr, targetType) {
|
|
79
|
+
// If it's already an AsExpression, update the type
|
|
80
|
+
if (expr.getKind() === SyntaxKind.AsExpression) {
|
|
81
|
+
const asExpr = expr;
|
|
82
|
+
asExpr.setType(targetType);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
// For other expressions, wrap with AsExpression
|
|
86
|
+
// We need to replace the expression with an AsExpression
|
|
87
|
+
const parent = expr.getParent();
|
|
88
|
+
if (!parent)
|
|
89
|
+
return false;
|
|
90
|
+
try {
|
|
91
|
+
// Create the new as expression text
|
|
92
|
+
const exprText = expr.getText();
|
|
93
|
+
const newText = `(${exprText} as ${targetType})`;
|
|
94
|
+
// Replace the expression in the parent
|
|
95
|
+
expr.replaceWithText(newText);
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
generateDiff(oldText, newText, fileName) {
|
|
103
|
+
const oldLines = oldText.split('\n');
|
|
104
|
+
const newLines = newText.split('\n');
|
|
105
|
+
let diff = `--- ${fileName}\n+++ ${fileName}\n`;
|
|
106
|
+
const maxLen = Math.max(oldLines.length, newLines.length);
|
|
107
|
+
for (let i = 0; i < maxLen; i++) {
|
|
108
|
+
const oldLine = oldLines[i];
|
|
109
|
+
const newLine = newLines[i];
|
|
110
|
+
if (oldLine !== newLine) {
|
|
111
|
+
if (oldLine !== undefined)
|
|
112
|
+
diff += `-${oldLine}\n`;
|
|
113
|
+
if (newLine !== undefined)
|
|
114
|
+
diff += `+${newLine}\n`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return diff;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export const typeAssignmentStrategy = new TypeAssignmentStrategy();
|
|
121
|
+
//# sourceMappingURL=typeAssignment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typeAssignment.js","sourceRoot":"","sources":["../../src/strategies/typeAssignment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FixStrategy, FixContext, FixResult } from './baseStrategy.js';
|
|
2
|
+
import { DiagnosticInfo } from '../handlers/typescriptDiagnostics.js';
|
|
3
|
+
export declare class UnusedImportRemovalStrategy implements FixStrategy {
|
|
4
|
+
errorType: "typescript";
|
|
5
|
+
pattern: RegExp;
|
|
6
|
+
canFix(error: DiagnosticInfo): boolean;
|
|
7
|
+
fix(context: FixContext, error: DiagnosticInfo): Promise<FixResult>;
|
|
8
|
+
private isSymbolUsedInFile;
|
|
9
|
+
private generateDiff;
|
|
10
|
+
}
|
|
11
|
+
export declare const unusedImportRemovalStrategy: UnusedImportRemovalStrategy;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { SyntaxKind } from 'ts-morph';
|
|
2
|
+
import { saveChanges, getSourceFile, getRelativePath } from './baseStrategy.js';
|
|
3
|
+
export class UnusedImportRemovalStrategy {
|
|
4
|
+
errorType = 'typescript';
|
|
5
|
+
pattern = /(?:Unused variable|unused import|is declared but its value is never read|'([^']+)' is defined but never used)/i;
|
|
6
|
+
canFix(error) {
|
|
7
|
+
return this.pattern.test(error.message) && error.severity === 'error';
|
|
8
|
+
}
|
|
9
|
+
async fix(context, error) {
|
|
10
|
+
const changes = [];
|
|
11
|
+
let fixedCount = 0;
|
|
12
|
+
if (!error.file) {
|
|
13
|
+
return { success: false, message: 'No file path in error', changes };
|
|
14
|
+
}
|
|
15
|
+
const sourceFile = getSourceFile(context, error.file);
|
|
16
|
+
if (!sourceFile) {
|
|
17
|
+
return { success: false, message: `Source file not found: ${error.file}`, changes };
|
|
18
|
+
}
|
|
19
|
+
const originalText = sourceFile.getFullText();
|
|
20
|
+
try {
|
|
21
|
+
// Handle unused imports
|
|
22
|
+
const importDecls = sourceFile.getImportDeclarations();
|
|
23
|
+
for (const importDecl of importDecls) {
|
|
24
|
+
const namedImports = importDecl.getNamedImports();
|
|
25
|
+
const unusedSpecifiers = [];
|
|
26
|
+
for (const specifier of namedImports) {
|
|
27
|
+
const symbol = specifier.getSymbol();
|
|
28
|
+
if (symbol && !this.isSymbolUsedInFile(symbol, sourceFile)) {
|
|
29
|
+
unusedSpecifiers.push(specifier);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (unusedSpecifiers.length > 0) {
|
|
33
|
+
if (unusedSpecifiers.length === namedImports.length) {
|
|
34
|
+
// All imports unused - remove entire declaration
|
|
35
|
+
const declText = importDecl.getText();
|
|
36
|
+
importDecl.remove();
|
|
37
|
+
changes.push({
|
|
38
|
+
file: getRelativePath(context, error.file),
|
|
39
|
+
description: `Removed unused import: ${declText.trim()}`,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// Remove only unused specifiers
|
|
44
|
+
for (const spec of unusedSpecifiers) {
|
|
45
|
+
const specText = spec.getText();
|
|
46
|
+
spec.remove();
|
|
47
|
+
changes.push({
|
|
48
|
+
file: getRelativePath(context, error.file),
|
|
49
|
+
description: `Removed unused import specifier: ${specText}`,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
// Fix formatting if needed
|
|
53
|
+
const syntaxList = importDecl.getFirstChildByKind(SyntaxKind.NamedImports)?.getFirstChildByKind(SyntaxKind.SyntaxList);
|
|
54
|
+
if (syntaxList) {
|
|
55
|
+
syntaxList.forEach?.(() => { });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
fixedCount += unusedSpecifiers.length;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Handle unused variables (const/let/var declarations)
|
|
62
|
+
const variableDecls = sourceFile.getVariableDeclarations();
|
|
63
|
+
for (const varDecl of variableDecls) {
|
|
64
|
+
const symbol = varDecl.getSymbol();
|
|
65
|
+
if (symbol && !this.isSymbolUsedInFile(symbol, sourceFile)) {
|
|
66
|
+
// Check if it's a simple unused variable (not part of destructuring used elsewhere)
|
|
67
|
+
const parent = varDecl.getParent();
|
|
68
|
+
if (parent && parent.getKind() === SyntaxKind.VariableDeclarationList) {
|
|
69
|
+
const declarations = parent.getDeclarations?.() || [];
|
|
70
|
+
if (declarations.length === 1) {
|
|
71
|
+
// Single declaration - remove entire statement
|
|
72
|
+
const statement = parent.getParent();
|
|
73
|
+
if (statement) {
|
|
74
|
+
const stmtText = statement.getText();
|
|
75
|
+
statement.remove();
|
|
76
|
+
changes.push({
|
|
77
|
+
file: getRelativePath(context, error.file),
|
|
78
|
+
description: `Removed unused variable declaration: ${stmtText.trim()}`,
|
|
79
|
+
});
|
|
80
|
+
fixedCount++;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (fixedCount > 0) {
|
|
87
|
+
saveChanges(context);
|
|
88
|
+
const newText = sourceFile.getFullText();
|
|
89
|
+
const diff = this.generateDiff(originalText, newText, error.file);
|
|
90
|
+
if (changes.length > 0) {
|
|
91
|
+
changes[changes.length - 1].diff = diff;
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
success: true,
|
|
95
|
+
message: `Removed ${fixedCount} unused import(s)/variable(s)`,
|
|
96
|
+
changes,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return { success: false, message: 'No unused imports/variables found to remove', changes };
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
103
|
+
return { success: false, message: `Fix failed: ${msg}`, changes };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
isSymbolUsedInFile(symbol, sourceFile) {
|
|
107
|
+
try {
|
|
108
|
+
const references = symbol.getReferences();
|
|
109
|
+
return references.some((ref) => {
|
|
110
|
+
const node = ref.getNode();
|
|
111
|
+
return node && node.getSourceFile() === sourceFile && node !== symbol.getDeclarations()[0];
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
generateDiff(oldText, newText, fileName) {
|
|
119
|
+
const oldLines = oldText.split('\n');
|
|
120
|
+
const newLines = newText.split('\n');
|
|
121
|
+
let diff = `--- ${fileName}\n+++ ${fileName}\n`;
|
|
122
|
+
// Simple line-by-line diff
|
|
123
|
+
const maxLen = Math.max(oldLines.length, newLines.length);
|
|
124
|
+
for (let i = 0; i < maxLen; i++) {
|
|
125
|
+
const oldLine = oldLines[i];
|
|
126
|
+
const newLine = newLines[i];
|
|
127
|
+
if (oldLine !== newLine) {
|
|
128
|
+
if (oldLine !== undefined)
|
|
129
|
+
diff += `-${oldLine}\n`;
|
|
130
|
+
if (newLine !== undefined)
|
|
131
|
+
diff += `+${newLine}\n`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return diff;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
export const unusedImportRemovalStrategy = new UnusedImportRemovalStrategy();
|
|
138
|
+
//# sourceMappingURL=unusedImportRemoval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unusedImportRemoval.js","sourceRoot":"","sources":["../../src/strategies/unusedImportRemoval.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -28,3 +28,12 @@ export interface ToolContext {
|
|
|
28
28
|
port?: number;
|
|
29
29
|
cdpPort?: number;
|
|
30
30
|
}
|
|
31
|
+
export type MCPErrorCode = 'FRAMEWORK_NOT_DETECTED' | 'DEV_SERVER_START_FAILED' | 'CDP_CONNECTION_FAILED' | 'PAGE_NAVIGATION_FAILED' | 'TYPE_CHECK_FAILED' | 'CONFIG_NOT_FOUND' | 'INVALID_PROJECT_DIR' | 'PORT_IN_USE' | 'TIMEOUT' | 'UNKNOWN_ERROR';
|
|
32
|
+
export interface MCPError {
|
|
33
|
+
code: MCPErrorCode;
|
|
34
|
+
message: string;
|
|
35
|
+
details?: unknown;
|
|
36
|
+
suggestion?: string;
|
|
37
|
+
}
|
|
38
|
+
export declare function createMCPError(code: MCPErrorCode, message: string, details?: unknown, suggestion?: string): MCPToolResponse;
|
|
39
|
+
export declare function createMCPSuccess(data: unknown): MCPToolResponse;
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1,22 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export function createMCPError(code, message, details, suggestion) {
|
|
2
|
+
return {
|
|
3
|
+
content: [
|
|
4
|
+
{
|
|
5
|
+
type: 'text',
|
|
6
|
+
text: JSON.stringify({ error: { code, message, details, suggestion } }, null, 2),
|
|
7
|
+
},
|
|
8
|
+
],
|
|
9
|
+
isError: true,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function createMCPSuccess(data) {
|
|
13
|
+
return {
|
|
14
|
+
content: [
|
|
15
|
+
{
|
|
16
|
+
type: 'text',
|
|
17
|
+
text: JSON.stringify(data, null, 2),
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
2
22
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAsDA,MAAM,UAAU,cAAc,CAC5B,IAAkB,EAClB,OAAe,EACf,OAAiB,EACjB,UAAmB;IAEnB,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;aACjF;SACF;QACD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;aACpC;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const VERSION = "1.0.0-beta.4";
|
|
2
|
+
export declare const VERSION_MAJOR = 1;
|
|
3
|
+
export declare const VERSION_MINOR = 0;
|
|
4
|
+
export declare const VERSION_PATCH = 0;
|
|
5
|
+
export declare const VERSION_PRERELEASE = "beta.4";
|
|
6
|
+
export declare const VERSION_STRING = "1.0.0-beta.4";
|
|
7
|
+
export declare const VERSION_SHORT = "1.0.0";
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Version management - single source of truth
|
|
2
|
+
export const VERSION = '1.0.0-beta.4';
|
|
3
|
+
export const VERSION_MAJOR = 1;
|
|
4
|
+
export const VERSION_MINOR = 0;
|
|
5
|
+
export const VERSION_PATCH = 0;
|
|
6
|
+
export const VERSION_PRERELEASE = 'beta.4';
|
|
7
|
+
// Formatted version strings
|
|
8
|
+
export const VERSION_STRING = VERSION;
|
|
9
|
+
export const VERSION_SHORT = `${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}`;
|
|
10
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,CAAC,MAAM,OAAO,GAAG,cAAc,CAAC;AACtC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAE3C,4BAA4B;AAC5B,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AACtC,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,aAAa,IAAI,aAAa,IAAI,aAAa,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudu-cli/fronted-preview-mcp",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.5",
|
|
4
4
|
"description": "MCP server for frontend project detection, dev server management, and preview workflow. Pairs with chrome-devtools-mcp for automated frontend checking.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,14 +22,6 @@
|
|
|
22
22
|
3. **`auto_fix_loop`** — 自动检测和修复错误(可选)
|
|
23
23
|
4. **汇总结果** — 告诉用户:错误类型、数量、修复建议
|
|
24
24
|
|
|
25
|
-
## 元素分析与截图工作流
|
|
26
|
-
|
|
27
|
-
当用户想"分析元素"、"截图"、"查看样式"时,按照以下步骤:
|
|
28
|
-
|
|
29
|
-
1. **`pick_element`** — 拾取页面元素获取详细信息
|
|
30
|
-
2. **`take_screenshot`** — 截图页面或特定元素
|
|
31
|
-
3. **汇总结果** — 告诉用户:元素信息、样式、截图结果
|
|
32
|
-
|
|
33
25
|
## 工具快速参考
|
|
34
26
|
|
|
35
27
|
| 工具 | 用途 | 优先使用场景 |
|
|
@@ -43,8 +35,6 @@
|
|
|
43
35
|
| `check_page_errors` | 检测页面 console 错误和网络失败 | 检查页面是否有 JavaScript 错误 |
|
|
44
36
|
| `get_typescript_diagnostics` | 检测 TypeScript 类型错误 | 检查代码类型错误和警告 |
|
|
45
37
|
| `auto_fix_loop` | 自动检测和修复错误 | 自动修复所有检测到的错误 |
|
|
46
|
-
| **元素分析工具** | | |
|
|
47
|
-
| `pick_element` | 拾取页面元素获取详细信息 | 分析特定元素的信息和样式 |
|
|
48
38
|
| **chrome-devtools** | | |
|
|
49
39
|
| `chrome-devtools `navigate_page` | 打开 URL | 拿到 URL 后立即使用 |
|
|
50
40
|
| `chrome-devtools `list_console_messages` | 检查 console 错误 | 页面加载完成后 |
|
|
@@ -57,4 +47,4 @@
|
|
|
57
47
|
- `quick_preview` 已包含 framework 检测,不要再重复调 `get_project_info`
|
|
58
48
|
- dev server 可以保持运行,不需要每次用完就关闭
|
|
59
49
|
- 使用 `auto_fix_loop` 时需要 Chrome 运行在调试模式(--remote-debugging-port=9222)
|
|
60
|
-
- `
|
|
50
|
+
- 元素拾取和截图功能已委托给 `chrome-devtools-mcp`
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { MCPToolResponse } from '../types.js';
|
|
2
|
-
interface PickElementArgs {
|
|
3
|
-
projectDir?: string;
|
|
4
|
-
customPort?: number;
|
|
5
|
-
cdpPort?: number;
|
|
6
|
-
selector?: string;
|
|
7
|
-
waitForLoadMs?: number;
|
|
8
|
-
}
|
|
9
|
-
declare function handlePickElement(args: PickElementArgs): Promise<MCPToolResponse>;
|
|
10
|
-
export { handlePickElement };
|