@devflow-tools/plugin-react 0.12.6 → 0.13.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.
Files changed (57) hide show
  1. package/dist/analyzers/__tests__/diagnose-bug.test.d.ts +2 -0
  2. package/dist/analyzers/__tests__/diagnose-bug.test.d.ts.map +1 -0
  3. package/dist/analyzers/__tests__/diagnose-bug.test.js +45 -0
  4. package/dist/analyzers/__tests__/diagnose-bug.test.js.map +1 -0
  5. package/dist/analyzers/__tests__/file-scanner.test.d.ts +2 -0
  6. package/dist/analyzers/__tests__/file-scanner.test.d.ts.map +1 -0
  7. package/dist/analyzers/__tests__/file-scanner.test.js +32 -0
  8. package/dist/analyzers/__tests__/file-scanner.test.js.map +1 -0
  9. package/dist/analyzers/__tests__/hooks-review.test.d.ts +2 -0
  10. package/dist/analyzers/__tests__/hooks-review.test.d.ts.map +1 -0
  11. package/dist/analyzers/__tests__/hooks-review.test.js +185 -0
  12. package/dist/analyzers/__tests__/hooks-review.test.js.map +1 -0
  13. package/dist/analyzers/__tests__/new-component.test.d.ts +2 -0
  14. package/dist/analyzers/__tests__/new-component.test.d.ts.map +1 -0
  15. package/dist/analyzers/__tests__/new-component.test.js +40 -0
  16. package/dist/analyzers/__tests__/new-component.test.js.map +1 -0
  17. package/dist/analyzers/__tests__/performance-audit.test.d.ts +2 -0
  18. package/dist/analyzers/__tests__/performance-audit.test.d.ts.map +1 -0
  19. package/dist/analyzers/__tests__/performance-audit.test.js +109 -0
  20. package/dist/analyzers/__tests__/performance-audit.test.js.map +1 -0
  21. package/dist/analyzers/__tests__/refactor-component.test.d.ts +2 -0
  22. package/dist/analyzers/__tests__/refactor-component.test.d.ts.map +1 -0
  23. package/dist/analyzers/__tests__/refactor-component.test.js +65 -0
  24. package/dist/analyzers/__tests__/refactor-component.test.js.map +1 -0
  25. package/dist/analyzers/diagnose-bug.d.ts +9 -0
  26. package/dist/analyzers/diagnose-bug.d.ts.map +1 -0
  27. package/dist/analyzers/diagnose-bug.js +108 -0
  28. package/dist/analyzers/diagnose-bug.js.map +1 -0
  29. package/dist/analyzers/file-scanner.d.ts +16 -0
  30. package/dist/analyzers/file-scanner.d.ts.map +1 -0
  31. package/dist/analyzers/file-scanner.js +143 -0
  32. package/dist/analyzers/file-scanner.js.map +1 -0
  33. package/dist/analyzers/hooks-review.d.ts +10 -0
  34. package/dist/analyzers/hooks-review.d.ts.map +1 -0
  35. package/dist/analyzers/hooks-review.js +307 -0
  36. package/dist/analyzers/hooks-review.js.map +1 -0
  37. package/dist/analyzers/new-component.d.ts +12 -0
  38. package/dist/analyzers/new-component.d.ts.map +1 -0
  39. package/dist/analyzers/new-component.js +59 -0
  40. package/dist/analyzers/new-component.js.map +1 -0
  41. package/dist/analyzers/performance-audit.d.ts +10 -0
  42. package/dist/analyzers/performance-audit.d.ts.map +1 -0
  43. package/dist/analyzers/performance-audit.js +239 -0
  44. package/dist/analyzers/performance-audit.js.map +1 -0
  45. package/dist/analyzers/refactor-component.d.ts +3 -0
  46. package/dist/analyzers/refactor-component.d.ts.map +1 -0
  47. package/dist/analyzers/refactor-component.js +90 -0
  48. package/dist/analyzers/refactor-component.js.map +1 -0
  49. package/dist/analyzers/types.d.ts +27 -0
  50. package/dist/analyzers/types.d.ts.map +1 -0
  51. package/dist/analyzers/types.js +2 -0
  52. package/dist/analyzers/types.js.map +1 -0
  53. package/dist/index.d.ts +3 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +1861 -0
  56. package/dist/index.js.map +1 -0
  57. package/package.json +3 -3
@@ -0,0 +1,59 @@
1
+ import { readFileContent, scanFiles } from './file-scanner.js';
2
+ export function generateComponent(input) {
3
+ const { projectRoot, componentName, props } = input;
4
+ // Analyze existing patterns
5
+ const ctx = scanFiles(projectRoot, { extensions: ['.tsx'] });
6
+ let usesReactMemo = false;
7
+ let usesInterface = false;
8
+ for (const file of ctx.files.slice(0, 10)) {
9
+ const content = readFileContent(file);
10
+ if (/React\.memo|memo\(/.test(content))
11
+ usesReactMemo = true;
12
+ if (/interface\s+\w+Props/.test(content))
13
+ usesInterface = true;
14
+ }
15
+ // Generate code
16
+ const propsInterface = usesInterface
17
+ ? `interface ${componentName}Props {\n${props.map(p => ` ${p.name}: ${p.type};`).join('\n')}\n}`
18
+ : `{ ${props.map(p => `${p.name}: ${p.type}`).join(', ')} }`;
19
+ const propsParam = usesInterface
20
+ ? `props: ${componentName}Props`
21
+ : `{ ${props.map(p => p.name).join(', ')} }: ${usesInterface ? `${componentName}Props` : `{ ${props.map(p => `${p.name}: ${p.type}`).join(', ')}`} }`;
22
+ const componentCode = `import React from 'react';
23
+
24
+ ${usesInterface ? propsInterface + '\n\n' : ''}
25
+ ${usesReactMemo ? `export const ${componentName} = React.memo(function ${componentName}(${propsParam}) {` : `export function ${componentName}(${propsParam}) {`}
26
+ return (
27
+ <div>
28
+ {/* TODO: Implement ${componentName} */}
29
+ </div>
30
+ );
31
+ }${usesReactMemo ? ');' : ''}
32
+ `;
33
+ const propsString = props.map(p => `${p.name}="${p.type === 'string' ? 'test' : '{}'}"`).join(' ');
34
+ const testCode = `import { describe, it, expect } from 'vitest';
35
+ import { render, screen } from '@testing-library/react';
36
+ import { ${componentName} } from './${componentName}';
37
+
38
+ describe('${componentName}', () => {
39
+ it('renders without crashing', () => {
40
+ render(<${componentName} ${propsString} />);
41
+ });
42
+ });
43
+ `;
44
+ return {
45
+ success: true,
46
+ summary: `生成 ${componentName} 组件,遵循项目现有模式`,
47
+ data: {
48
+ analysis: {
49
+ existingPatterns: { usesReactMemo, usesInterface },
50
+ },
51
+ generatedCode: { component: componentCode, test: testCode },
52
+ filesToCreate: [
53
+ { path: `src/components/${componentName}.tsx`, type: 'component' },
54
+ { path: `src/components/${componentName}.test.tsx`, type: 'test' },
55
+ ],
56
+ },
57
+ };
58
+ }
59
+ //# sourceMappingURL=new-component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"new-component.js","sourceRoot":"","sources":["../../src/analyzers/new-component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { AnalysisResult, AnalyzerContext } from './types.js';
2
+ export interface PerformanceAuditOptions {
3
+ filePath?: string;
4
+ componentName?: string;
5
+ scope?: 'target' | 'related' | 'project';
6
+ maxFindings?: number;
7
+ outputMode?: 'summary' | 'focused' | 'full';
8
+ }
9
+ export declare function auditPerformance(ctx: AnalyzerContext, options?: PerformanceAuditOptions): AnalysisResult;
10
+ //# sourceMappingURL=performance-audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance-audit.d.ts","sourceRoot":"","sources":["../../src/analyzers/performance-audit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAW,eAAe,EAAE,MAAM,YAAY,CAAC;AAE3E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;CAC7C;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,eAAe,EACpB,OAAO,GAAE,uBAA4B,GACpC,cAAc,CAoIhB"}
@@ -0,0 +1,239 @@
1
+ import { readFileContent, getRelativePath, selectAnalyzerFiles } from './file-scanner.js';
2
+ export function auditPerformance(ctx, options = {}) {
3
+ const scope = options.scope ?? (options.filePath || options.componentName ? 'target' : 'project');
4
+ const outputMode = options.outputMode ?? (scope === 'project' ? 'focused' : 'summary');
5
+ const maxFindings = normalizeMaxFindings(options.maxFindings, outputMode);
6
+ const selectedFiles = selectFiles(ctx, options, scope);
7
+ const findings = [];
8
+ let totalComponents = 0;
9
+ let memoizedComponents = 0;
10
+ let inlineObjectCount = 0;
11
+ for (const file of selectedFiles) {
12
+ const relPath = getRelativePath(ctx.projectRoot, file);
13
+ // Skip test fixtures and node_modules
14
+ if (relPath.includes('__tests__') || relPath.includes('node_modules'))
15
+ continue;
16
+ // Skip plugin source files that contain code examples as strings
17
+ if (relPath.includes('plugins/') && relPath.endsWith('src/index.ts'))
18
+ continue;
19
+ const content = readFileContent(file);
20
+ const lines = content.split('\n');
21
+ // 同时支持 `export function X()` 与 `export const X = () => {}` 组件声明。
22
+ for (const componentMatch of findComponentDeclarations(content)) {
23
+ totalComponents++;
24
+ const componentName = componentMatch.name;
25
+ // Check if wrapped in React.memo
26
+ const beforeComponent = content.substring(0, componentMatch.index);
27
+ if (!/React\.memo\s*\(|memo\s*\(/.test(beforeComponent.slice(-200))) {
28
+ // Check if it's a "pure" component (no hooks that manage state)
29
+ const componentBlock = extractFunctionBlock(content, componentMatch.index);
30
+ if (!/useState|useReducer|useRef/.test(componentBlock)) {
31
+ findings.push({
32
+ severity: 'suggestion',
33
+ category: 'missing-memo',
34
+ title: '纯展示组件缺少 React.memo',
35
+ description: `组件 ${componentName} 无内部状态,适合 memo 优化`,
36
+ file: relPath,
37
+ line: content.substring(0, componentMatch.index).split('\n').length,
38
+ suggestion: `用 React.memo(${componentName}) 包裹组件`,
39
+ });
40
+ }
41
+ }
42
+ else {
43
+ memoizedComponents++;
44
+ }
45
+ }
46
+ // Detect inline objects in JSX
47
+ for (let i = 0; i < lines.length; i++) {
48
+ const line = lines[i];
49
+ // Strip string literals before detection (avoid false positives in grep commands, string templates)
50
+ const codeOnly = line
51
+ .replace(/"[^"]*"/g, '""')
52
+ .replace(/'[^']*'/g, "''")
53
+ .replace(/`[^`]*`/g, '``');
54
+ // Skip comment lines
55
+ const trimmed = codeOnly.trim();
56
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*'))
57
+ continue;
58
+ // style={{ ... }} or other inline objects
59
+ if (/\w+\s*=\s*\{\s*\{/.test(codeOnly)) {
60
+ inlineObjectCount++;
61
+ findings.push({
62
+ severity: 'warning',
63
+ category: 'inline-object',
64
+ title: '渲染中创建内联对象',
65
+ description: '每次渲染创建新对象引用,触发子组件重渲染',
66
+ file: relPath,
67
+ line: i + 1,
68
+ codeSnippet: line.trim(),
69
+ suggestion: '使用 useMemo 缓存对象',
70
+ });
71
+ }
72
+ }
73
+ }
74
+ const sortedFindings = sortFindings(findings, options);
75
+ const limitedFindings = outputMode === 'full'
76
+ ? sortedFindings
77
+ : sortedFindings.slice(0, maxFindings);
78
+ const truncated = limitedFindings.length < sortedFindings.length;
79
+ const targetLabel = describeTarget(options, scope);
80
+ const reportId = truncated ? buildReportId(targetLabel, selectedFiles) : undefined;
81
+ return {
82
+ success: true,
83
+ summary: buildSummary({
84
+ targetLabel,
85
+ scannedFiles: selectedFiles.length,
86
+ totalComponents,
87
+ totalFindings: sortedFindings.length,
88
+ shownFindings: limitedFindings.length,
89
+ truncated,
90
+ }),
91
+ findings: limitedFindings,
92
+ metrics: {
93
+ scannedFiles: selectedFiles.length,
94
+ totalComponents,
95
+ memoizedComponents,
96
+ memoizationRate: totalComponents > 0 ? memoizedComponents / totalComponents : 0,
97
+ inlineObjects: inlineObjectCount,
98
+ },
99
+ totalFindings: sortedFindings.length,
100
+ truncated,
101
+ reportId,
102
+ data: {
103
+ target: targetLabel,
104
+ scope,
105
+ outputMode,
106
+ scannedFiles: selectedFiles.map((file) => getRelativePath(ctx.projectRoot, file)),
107
+ totalFindings: sortedFindings.length,
108
+ shownFindings: limitedFindings.length,
109
+ truncated,
110
+ reportId,
111
+ },
112
+ _report: reportId ? {
113
+ target: targetLabel,
114
+ scope,
115
+ outputMode,
116
+ scannedFiles: selectedFiles.map((file) => getRelativePath(ctx.projectRoot, file)),
117
+ metrics: {
118
+ scannedFiles: selectedFiles.length,
119
+ totalComponents,
120
+ memoizedComponents,
121
+ memoizationRate: totalComponents > 0 ? memoizedComponents / totalComponents : 0,
122
+ inlineObjects: inlineObjectCount,
123
+ },
124
+ findings: sortedFindings,
125
+ } : undefined,
126
+ };
127
+ }
128
+ function findComponentDeclarations(content) {
129
+ const patterns = [
130
+ /export\s+(?:default\s+)?function\s+([A-Z][a-zA-Z0-9_]*)\s*\(/g,
131
+ /export\s+(?:const|let|var)\s+([A-Z][a-zA-Z0-9_]*)\s*=\s*(?:async\s*)?(?:\([^=]*\)|[a-zA-Z_$][\w$]*)\s*=>/g,
132
+ /export\s+(?:const|let|var)\s+([A-Z][a-zA-Z0-9_]*)\s*=\s*function\s*\(/g,
133
+ ];
134
+ const seen = new Set();
135
+ const matches = [];
136
+ for (const pattern of patterns) {
137
+ let match;
138
+ while ((match = pattern.exec(content)) !== null) {
139
+ const name = match[1];
140
+ const key = `${name}:${match.index}`;
141
+ if (seen.has(key))
142
+ continue;
143
+ seen.add(key);
144
+ matches.push({ name, index: match.index });
145
+ }
146
+ }
147
+ return matches.sort((a, b) => a.index - b.index);
148
+ }
149
+ function extractFunctionBlock(content, startIdx) {
150
+ let depth = 0;
151
+ let started = false;
152
+ for (let i = startIdx; i < content.length; i++) {
153
+ if (content[i] === '{') {
154
+ depth++;
155
+ started = true;
156
+ }
157
+ if (content[i] === '}') {
158
+ depth--;
159
+ if (started && depth === 0)
160
+ return content.substring(startIdx, i + 1);
161
+ }
162
+ }
163
+ return content.substring(startIdx, Math.min(startIdx + 500, content.length));
164
+ }
165
+ function normalizeMaxFindings(maxFindings, outputMode) {
166
+ if (outputMode === 'full')
167
+ return Number.MAX_SAFE_INTEGER;
168
+ if (!maxFindings || Number.isNaN(maxFindings)) {
169
+ return outputMode === 'summary' ? 5 : 10;
170
+ }
171
+ return Math.max(1, Math.min(maxFindings, 50));
172
+ }
173
+ function selectFiles(ctx, options, scope) {
174
+ return selectAnalyzerFiles(ctx, {
175
+ filePath: options.filePath,
176
+ componentName: options.componentName,
177
+ scope,
178
+ matchComponent: (file, componentName) => {
179
+ const componentPattern = new RegExp(`(?:^|[^a-zA-Z0-9_])${escapeRegExp(componentName)}(?:[^a-zA-Z0-9_]|$)`);
180
+ return componentPattern.test(readFileContent(file));
181
+ },
182
+ });
183
+ }
184
+ function sortFindings(findings, options) {
185
+ const severityRank = {
186
+ critical: 0,
187
+ warning: 1,
188
+ suggestion: 2,
189
+ info: 3,
190
+ };
191
+ const targetPath = options.filePath?.replace(/\\/g, '/');
192
+ const targetName = options.componentName?.toLowerCase();
193
+ return [...findings].sort((a, b) => {
194
+ const aTarget = getTargetScore(a, targetPath, targetName);
195
+ const bTarget = getTargetScore(b, targetPath, targetName);
196
+ if (aTarget !== bTarget)
197
+ return bTarget - aTarget;
198
+ const severityDiff = severityRank[a.severity] - severityRank[b.severity];
199
+ if (severityDiff !== 0)
200
+ return severityDiff;
201
+ return (a.file ?? '').localeCompare(b.file ?? '');
202
+ });
203
+ }
204
+ function getTargetScore(finding, targetPath, targetName) {
205
+ const file = finding.file?.replace(/\\/g, '/').toLowerCase() ?? '';
206
+ const title = `${finding.title} ${finding.description}`.toLowerCase();
207
+ let score = 0;
208
+ if (targetPath && file.includes(targetPath.toLowerCase()))
209
+ score += 2;
210
+ if (targetName && title.includes(targetName))
211
+ score += 1;
212
+ return score;
213
+ }
214
+ function describeTarget(options, scope) {
215
+ if (options.filePath)
216
+ return `文件 ${options.filePath}`;
217
+ if (options.componentName)
218
+ return `组件 ${options.componentName}`;
219
+ return scope === 'project' ? '当前项目' : '目标范围';
220
+ }
221
+ function buildSummary(params) {
222
+ const { targetLabel, scannedFiles, totalComponents, totalFindings, shownFindings, truncated } = params;
223
+ const base = `已分析${targetLabel},扫描 ${scannedFiles} 个文件、${totalComponents} 个组件,发现 ${totalFindings} 个性能问题`;
224
+ if (!truncated)
225
+ return base;
226
+ return `${base};当前仅返回前 ${shownFindings} 条高优先级发现`;
227
+ }
228
+ function buildReportId(targetLabel, files) {
229
+ const source = `${targetLabel}:${files.join('|')}`;
230
+ let hash = 0;
231
+ for (let i = 0; i < source.length; i++) {
232
+ hash = (hash * 31 + source.charCodeAt(i)) >>> 0;
233
+ }
234
+ return `react-perf-${hash.toString(16)}`;
235
+ }
236
+ function escapeRegExp(value) {
237
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
238
+ }
239
+ //# sourceMappingURL=performance-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance-audit.js","sourceRoot":"","sources":["../../src/analyzers/performance-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AnalysisResult } from './types.js';
2
+ export declare function refactorComponent(filePath: string, projectRoot: string): AnalysisResult;
3
+ //# sourceMappingURL=refactor-component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refactor-component.d.ts","sourceRoot":"","sources":["../../src/analyzers/refactor-component.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,CAgFvF"}
@@ -0,0 +1,90 @@
1
+ import { readFileContent, getRelativePath } from './file-scanner.js';
2
+ export function refactorComponent(filePath, projectRoot) {
3
+ const content = readFileContent(filePath);
4
+ const relPath = getRelativePath(projectRoot, filePath);
5
+ const lines = content.split('\n');
6
+ // Calculate metrics
7
+ const lineCount = lines.length;
8
+ const propsMatch = content.match(/\(\s*\{([^}]+)\}\s*(?::\s*\w+)?\s*\)/);
9
+ const propsCount = propsMatch ? propsMatch[1].split(',').filter(p => p.trim()).length : 0;
10
+ const hooksMatch = content.match(/\buse[A-Z][a-zA-Z]*\s*\(/g);
11
+ const hooksCount = hooksMatch ? hooksMatch.length : 0;
12
+ const nestingDepth = calculateMaxNesting(content);
13
+ const conditionals = (content.match(/\b(if|else if|switch|\?)\b/g) || []).length;
14
+ // Calculate score (0-100, higher = more complex)
15
+ const score = Math.min(100, Math.max(0, lineCount * 0.2 + propsCount * 5 + hooksCount * 3 + nestingDepth * 8 + conditionals * 2));
16
+ const level = score >= 70 ? 'high' : score >= 40 ? 'medium' : 'low';
17
+ // Identify smells
18
+ const smells = [];
19
+ if (propsCount > 8) {
20
+ smells.push({
21
+ type: 'too-many-props',
22
+ description: `${propsCount} 个 props 超过建议阈值(8 个)`,
23
+ suggestion: '将相关 props 合并为对象或使用 context',
24
+ });
25
+ }
26
+ if (lineCount > 200) {
27
+ smells.push({
28
+ type: 'too-long',
29
+ description: `组件 ${lineCount} 行超过建议阈值(200 行)`,
30
+ suggestion: '拆分为多个子组件',
31
+ });
32
+ }
33
+ if (/fetch|axios|api\./.test(content) && /useState.*useEffect/.test(content)) {
34
+ smells.push({
35
+ type: 'mixed-responsibilities',
36
+ description: '组件同时处理数据获取和 UI 渲染',
37
+ suggestion: '拆分为 Container(数据)+ Presentational(UI)',
38
+ });
39
+ }
40
+ // Generate refactor plan
41
+ const plan = [];
42
+ if (/fetch|api\./.test(content) && hooksCount >= 2) {
43
+ plan.push({
44
+ action: 'extract-hook',
45
+ name: `use${extractComponentName(content)}Data`,
46
+ description: '提取数据获取逻辑到自定义 Hook',
47
+ estimatedReduction: '减少 30-50 行',
48
+ });
49
+ }
50
+ if (nestingDepth > 4) {
51
+ plan.push({
52
+ action: 'extract-component',
53
+ name: `${extractComponentName(content)}Header`,
54
+ description: '提取深层嵌套 UI 为独立组件',
55
+ estimatedReduction: '减少 20-40 行',
56
+ });
57
+ }
58
+ return {
59
+ success: true,
60
+ summary: `组件复杂度评分 ${Math.round(score)}/100(${level})`,
61
+ metrics: { score: Math.round(score), level, lines: lineCount, propsCount, hooksCount, nestingDepth, conditionals },
62
+ data: { complexity: { score: Math.round(score), level, lines: lineCount, propsCount, hooksCount, nestingDepth }, smells, refactorPlan: plan },
63
+ findings: smells.map(s => ({
64
+ severity: 'warning',
65
+ category: s.type,
66
+ title: s.type,
67
+ description: s.description,
68
+ file: relPath,
69
+ suggestion: s.suggestion,
70
+ })),
71
+ };
72
+ }
73
+ function calculateMaxNesting(content) {
74
+ let maxDepth = 0;
75
+ let depth = 0;
76
+ for (const ch of content) {
77
+ if (ch === '{') {
78
+ depth++;
79
+ maxDepth = Math.max(maxDepth, depth);
80
+ }
81
+ if (ch === '}')
82
+ depth--;
83
+ }
84
+ return maxDepth;
85
+ }
86
+ function extractComponentName(content) {
87
+ const match = content.match(/function\s+([A-Z][a-zA-Z]*)/);
88
+ return match ? match[1] : 'Component';
89
+ }
90
+ //# sourceMappingURL=refactor-component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refactor-component.js","sourceRoot":"","sources":["../../src/analyzers/refactor-component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export interface AnalysisResult {
2
+ success: boolean;
3
+ summary: string;
4
+ findings?: Finding[];
5
+ metrics?: Record<string, number | string>;
6
+ data?: unknown;
7
+ totalFindings?: number;
8
+ truncated?: boolean;
9
+ reportId?: string;
10
+ _report?: Record<string, unknown>;
11
+ error?: string;
12
+ }
13
+ export interface Finding {
14
+ severity: 'critical' | 'warning' | 'info' | 'suggestion';
15
+ category: string;
16
+ title: string;
17
+ description: string;
18
+ file?: string;
19
+ line?: number;
20
+ suggestion?: string;
21
+ codeSnippet?: string;
22
+ }
23
+ export interface AnalyzerContext {
24
+ projectRoot: string;
25
+ files: string[];
26
+ }
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/analyzers/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,YAAY,CAAC;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/analyzers/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { DevFlowPlugin } from "@devflow-tools/sdk";
2
+ export declare const reactPlugin: DevFlowPlugin;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD,eAAO,MAAM,WAAW,EAAE,aAk1DzB,CAAC"}