@devflow-tools/plugin-react 0.11.0 → 0.12.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.
Files changed (57) hide show
  1. package/package.json +2 -2
  2. package/dist/analyzers/__tests__/diagnose-bug.test.d.ts +0 -2
  3. package/dist/analyzers/__tests__/diagnose-bug.test.d.ts.map +0 -1
  4. package/dist/analyzers/__tests__/diagnose-bug.test.js +0 -45
  5. package/dist/analyzers/__tests__/diagnose-bug.test.js.map +0 -1
  6. package/dist/analyzers/__tests__/file-scanner.test.d.ts +0 -2
  7. package/dist/analyzers/__tests__/file-scanner.test.d.ts.map +0 -1
  8. package/dist/analyzers/__tests__/file-scanner.test.js +0 -32
  9. package/dist/analyzers/__tests__/file-scanner.test.js.map +0 -1
  10. package/dist/analyzers/__tests__/hooks-review.test.d.ts +0 -2
  11. package/dist/analyzers/__tests__/hooks-review.test.d.ts.map +0 -1
  12. package/dist/analyzers/__tests__/hooks-review.test.js +0 -95
  13. package/dist/analyzers/__tests__/hooks-review.test.js.map +0 -1
  14. package/dist/analyzers/__tests__/new-component.test.d.ts +0 -2
  15. package/dist/analyzers/__tests__/new-component.test.d.ts.map +0 -1
  16. package/dist/analyzers/__tests__/new-component.test.js +0 -40
  17. package/dist/analyzers/__tests__/new-component.test.js.map +0 -1
  18. package/dist/analyzers/__tests__/performance-audit.test.d.ts +0 -2
  19. package/dist/analyzers/__tests__/performance-audit.test.d.ts.map +0 -1
  20. package/dist/analyzers/__tests__/performance-audit.test.js +0 -42
  21. package/dist/analyzers/__tests__/performance-audit.test.js.map +0 -1
  22. package/dist/analyzers/__tests__/refactor-component.test.d.ts +0 -2
  23. package/dist/analyzers/__tests__/refactor-component.test.d.ts.map +0 -1
  24. package/dist/analyzers/__tests__/refactor-component.test.js +0 -65
  25. package/dist/analyzers/__tests__/refactor-component.test.js.map +0 -1
  26. package/dist/analyzers/diagnose-bug.d.ts +0 -9
  27. package/dist/analyzers/diagnose-bug.d.ts.map +0 -1
  28. package/dist/analyzers/diagnose-bug.js +0 -108
  29. package/dist/analyzers/diagnose-bug.js.map +0 -1
  30. package/dist/analyzers/file-scanner.d.ts +0 -9
  31. package/dist/analyzers/file-scanner.d.ts.map +0 -1
  32. package/dist/analyzers/file-scanner.js +0 -35
  33. package/dist/analyzers/file-scanner.js.map +0 -1
  34. package/dist/analyzers/hooks-review.d.ts +0 -3
  35. package/dist/analyzers/hooks-review.d.ts.map +0 -1
  36. package/dist/analyzers/hooks-review.js +0 -162
  37. package/dist/analyzers/hooks-review.js.map +0 -1
  38. package/dist/analyzers/new-component.d.ts +0 -12
  39. package/dist/analyzers/new-component.d.ts.map +0 -1
  40. package/dist/analyzers/new-component.js +0 -59
  41. package/dist/analyzers/new-component.js.map +0 -1
  42. package/dist/analyzers/performance-audit.d.ts +0 -3
  43. package/dist/analyzers/performance-audit.d.ts.map +0 -1
  44. package/dist/analyzers/performance-audit.js +0 -100
  45. package/dist/analyzers/performance-audit.js.map +0 -1
  46. package/dist/analyzers/refactor-component.d.ts +0 -3
  47. package/dist/analyzers/refactor-component.d.ts.map +0 -1
  48. package/dist/analyzers/refactor-component.js +0 -90
  49. package/dist/analyzers/refactor-component.js.map +0 -1
  50. package/dist/analyzers/types.d.ts +0 -23
  51. package/dist/analyzers/types.d.ts.map +0 -1
  52. package/dist/analyzers/types.js +0 -2
  53. package/dist/analyzers/types.js.map +0 -1
  54. package/dist/index.d.ts +0 -3
  55. package/dist/index.d.ts.map +0 -1
  56. package/dist/index.js +0 -1781
  57. package/dist/index.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devflow-tools/plugin-react",
3
- "version": "0.11.0",
3
+ "version": "0.12.6",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -26,5 +26,5 @@
26
26
  "files": [
27
27
  "dist"
28
28
  ],
29
- "gitHead": "ff6ac69b0f3cc95cb32ffe8bcbf21b24767aa914"
29
+ "gitHead": "d544427472016eb332c6c2107f0fc98d8ae59c14"
30
30
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=diagnose-bug.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"diagnose-bug.test.d.ts","sourceRoot":"","sources":["../../../src/analyzers/__tests__/diagnose-bug.test.ts"],"names":[],"mappings":""}
@@ -1,45 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'fs';
3
- import { join } from 'path';
4
- import { tmpdir } from 'os';
5
- import { diagnoseBug } from '../diagnose-bug.js';
6
- describe('diagnoseBug', () => {
7
- let tmpDir;
8
- beforeEach(() => {
9
- tmpDir = mkdtempSync(join(tmpdir(), 'diagnose-'));
10
- mkdirSync(join(tmpDir, 'src'));
11
- });
12
- afterEach(() => {
13
- rmSync(tmpDir, { recursive: true, force: true });
14
- });
15
- it('analyzes error and returns root causes', () => {
16
- writeFileSync(join(tmpDir, 'src', 'App.tsx'), `
17
- import { useState } from 'react';
18
- export function App() {
19
- const [data, setData] = useState(null);
20
- return <div>{data.name}</div>;
21
- }
22
- `);
23
- const result = diagnoseBug({
24
- projectRoot: tmpDir,
25
- errorMessage: "Cannot read properties of null (reading 'name')",
26
- stackTrace: 'at App (src/App.tsx:4)',
27
- });
28
- expect(result.success).toBe(true);
29
- expect(result.data).toBeDefined();
30
- expect(result.data.rootCauses).toBeDefined();
31
- });
32
- it('detects null access patterns', () => {
33
- writeFileSync(join(tmpDir, 'src', 'User.tsx'), `
34
- export function User({ user }: { user: any }) {
35
- return <div>{user.profile.name}</div>;
36
- }
37
- `);
38
- const result = diagnoseBug({
39
- projectRoot: tmpDir,
40
- errorMessage: "Cannot read properties of undefined (reading 'name')",
41
- });
42
- expect(result.data.rootCauses.length).toBeGreaterThan(0);
43
- });
44
- });
45
- //# sourceMappingURL=diagnose-bug.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"diagnose-bug.test.js","sourceRoot":"","sources":["../../../src/analyzers/__tests__/diagnose-bug.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;QAClD,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE;;;;;;CAMjD,CAAC,CAAC;QACC,MAAM,MAAM,GAAG,WAAW,CAAC;YACzB,WAAW,EAAE,MAAM;YACnB,YAAY,EAAE,iDAAiD;YAC/D,UAAU,EAAE,wBAAwB;SACrC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,CAAE,MAAM,CAAC,IAAY,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE;;;;CAIlD,CAAC,CAAC;QACC,MAAM,MAAM,GAAG,WAAW,CAAC;YACzB,WAAW,EAAE,MAAM;YACnB,YAAY,EAAE,sDAAsD;SACrE,CAAC,CAAC;QACH,MAAM,CAAE,MAAM,CAAC,IAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=file-scanner.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-scanner.test.d.ts","sourceRoot":"","sources":["../../../src/analyzers/__tests__/file-scanner.test.ts"],"names":[],"mappings":""}
@@ -1,32 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'fs';
3
- import { join } from 'path';
4
- import { tmpdir } from 'os';
5
- import { scanFiles } from '../file-scanner.js';
6
- describe('scanFiles', () => {
7
- let tmpDir;
8
- beforeEach(() => {
9
- tmpDir = mkdtempSync(join(tmpdir(), 'analyzer-test-'));
10
- mkdirSync(join(tmpDir, 'src'));
11
- writeFileSync(join(tmpDir, 'src', 'App.tsx'), 'export function App() {}');
12
- writeFileSync(join(tmpDir, 'src', 'utils.ts'), 'export const x = 1;');
13
- mkdirSync(join(tmpDir, 'node_modules'));
14
- writeFileSync(join(tmpDir, 'node_modules', 'lib.js'), '');
15
- });
16
- afterEach(() => {
17
- rmSync(tmpDir, { recursive: true, force: true });
18
- });
19
- it('scans tsx/ts files excluding node_modules', () => {
20
- const ctx = scanFiles(tmpDir);
21
- expect(ctx.files).toHaveLength(2);
22
- expect(ctx.files.some(f => f.endsWith('App.tsx'))).toBe(true);
23
- expect(ctx.files.some(f => f.endsWith('utils.ts'))).toBe(true);
24
- expect(ctx.files.some(f => f.includes('node_modules'))).toBe(false);
25
- });
26
- it('filters by extension', () => {
27
- const ctx = scanFiles(tmpDir, { extensions: ['.tsx'] });
28
- expect(ctx.files).toHaveLength(1);
29
- expect(ctx.files[0]).toContain('App.tsx');
30
- });
31
- });
32
- //# sourceMappingURL=file-scanner.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-scanner.test.js","sourceRoot":"","sources":["../../../src/analyzers/__tests__/file-scanner.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAmB,MAAM,oBAAoB,CAAC;AAEhE,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACvD,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAC/B,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,0BAA0B,CAAC,CAAC;QAC1E,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,qBAAqB,CAAC,CAAC;QACtE,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;QACxC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=hooks-review.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hooks-review.test.d.ts","sourceRoot":"","sources":["../../../src/analyzers/__tests__/hooks-review.test.ts"],"names":[],"mappings":""}
@@ -1,95 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'fs';
3
- import { join } from 'path';
4
- import { tmpdir } from 'os';
5
- import { reviewHooks } from '../hooks-review.js';
6
- describe('reviewHooks', () => {
7
- let tmpDir;
8
- beforeEach(() => {
9
- tmpDir = mkdtempSync(join(tmpdir(), 'hooks-review-'));
10
- mkdirSync(join(tmpDir, 'src'));
11
- });
12
- afterEach(() => {
13
- rmSync(tmpDir, { recursive: true, force: true });
14
- });
15
- it('detects conditional hook calls', () => {
16
- writeFileSync(join(tmpDir, 'src', 'Bad.tsx'), `
17
- import { useState } from 'react';
18
- export function Bad({ flag }: { flag: boolean }) {
19
- if (flag) {
20
- const [x, setX] = useState(0);
21
- }
22
- return null;
23
- }
24
- `);
25
- const result = reviewHooks({ projectRoot: tmpDir, files: [join(tmpDir, 'src', 'Bad.tsx')] });
26
- expect(result.success).toBe(true);
27
- expect(result.findings).toBeDefined();
28
- const critical = result.findings.filter(f => f.severity === 'critical');
29
- expect(critical.length).toBeGreaterThan(0);
30
- expect(critical[0].category).toBe('conditional-hook');
31
- });
32
- it('detects hooks inside loops', () => {
33
- writeFileSync(join(tmpDir, 'src', 'Loop.tsx'), `
34
- import { useState } from 'react';
35
- export function Loop({ items }: { items: string[] }) {
36
- for (const item of items) {
37
- const [x] = useState(item);
38
- }
39
- return null;
40
- }
41
- `);
42
- const result = reviewHooks({ projectRoot: tmpDir, files: [join(tmpDir, 'src', 'Loop.tsx')] });
43
- const critical = result.findings.filter(f => f.severity === 'critical');
44
- expect(critical.length).toBeGreaterThan(0);
45
- expect(critical[0].category).toBe('loop-hook');
46
- });
47
- it('detects missing useEffect cleanup', () => {
48
- writeFileSync(join(tmpDir, 'src', 'Timer.tsx'), `
49
- import { useEffect } from 'react';
50
- export function Timer() {
51
- useEffect(() => {
52
- const id = setInterval(() => {}, 1000);
53
- }, []);
54
- return null;
55
- }
56
- `);
57
- const result = reviewHooks({ projectRoot: tmpDir, files: [join(tmpDir, 'src', 'Timer.tsx')] });
58
- const warnings = result.findings.filter(f => f.severity === 'warning');
59
- expect(warnings.some(f => f.category === 'missing-cleanup')).toBe(true);
60
- });
61
- it('reports no critical issues for clean code', () => {
62
- writeFileSync(join(tmpDir, 'src', 'Good.tsx'), `
63
- import { useState, useEffect } from 'react';
64
- export function Good() {
65
- const [count, setCount] = useState(0);
66
- useEffect(() => {
67
- const timer = setTimeout(() => {}, 1000);
68
- return () => clearTimeout(timer);
69
- }, []);
70
- return <div>{count}</div>;
71
- }
72
- `);
73
- const result = reviewHooks({ projectRoot: tmpDir, files: [join(tmpDir, 'src', 'Good.tsx')] });
74
- const critical = result.findings.filter(f => f.severity === 'critical');
75
- expect(critical).toHaveLength(0);
76
- });
77
- it('returns metrics about hook usage', () => {
78
- writeFileSync(join(tmpDir, 'src', 'App.tsx'), `
79
- import { useState, useEffect, useMemo } from 'react';
80
- export function App() {
81
- const [a] = useState(1);
82
- const [b] = useState(2);
83
- useEffect(() => {}, []);
84
- const c = useMemo(() => a + b, [a, b]);
85
- return null;
86
- }
87
- `);
88
- const result = reviewHooks({ projectRoot: tmpDir, files: [join(tmpDir, 'src', 'App.tsx')] });
89
- expect(result.metrics).toBeDefined();
90
- expect(result.metrics.useState).toBe(2);
91
- expect(result.metrics.useEffect).toBe(1);
92
- expect(result.metrics.useMemo).toBe(1);
93
- });
94
- });
95
- //# sourceMappingURL=hooks-review.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hooks-review.test.js","sourceRoot":"","sources":["../../../src/analyzers/__tests__/hooks-review.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=new-component.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"new-component.test.d.ts","sourceRoot":"","sources":["../../../src/analyzers/__tests__/new-component.test.ts"],"names":[],"mappings":""}
@@ -1,40 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'fs';
3
- import { join } from 'path';
4
- import { tmpdir } from 'os';
5
- import { generateComponent } from '../new-component.js';
6
- describe('generateComponent', () => {
7
- let tmpDir;
8
- beforeEach(() => {
9
- tmpDir = mkdtempSync(join(tmpdir(), 'new-comp-'));
10
- mkdirSync(join(tmpDir, 'src', 'components'), { recursive: true });
11
- writeFileSync(join(tmpDir, 'src', 'components', 'Existing.tsx'), `
12
- import React from 'react';
13
- export const Existing = React.memo(function Existing({ name }: { name: string }) {
14
- return <div>{name}</div>;
15
- });
16
- `);
17
- });
18
- afterEach(() => {
19
- rmSync(tmpDir, { recursive: true, force: true });
20
- });
21
- it('generates component code following project patterns', () => {
22
- const result = generateComponent({
23
- projectRoot: tmpDir,
24
- componentName: 'UserCard',
25
- props: [{ name: 'name', type: 'string' }, { name: 'avatar', type: 'string' }],
26
- });
27
- expect(result.success).toBe(true);
28
- expect(result.data.generatedCode.component).toContain('UserCard');
29
- expect(result.data.generatedCode.component).toContain('React.memo');
30
- });
31
- it('detects existing patterns', () => {
32
- const result = generateComponent({
33
- projectRoot: tmpDir,
34
- componentName: 'Test',
35
- props: [],
36
- });
37
- expect(result.data.analysis.existingPatterns.usesReactMemo).toBe(true);
38
- });
39
- });
40
- //# sourceMappingURL=new-component.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"new-component.test.js","sourceRoot":"","sources":["../../../src/analyzers/__tests__/new-component.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;QAClD,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,cAAc,CAAC,EAAE;;;;;CAKpE,CAAC,CAAC;IACD,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,MAAM,GAAG,iBAAiB,CAAC;YAC/B,WAAW,EAAE,MAAM;YACnB,aAAa,EAAE,UAAU;YACzB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;SAC9E,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAE,MAAM,CAAC,IAAY,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC3E,MAAM,CAAE,MAAM,CAAC,IAAY,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,iBAAiB,CAAC;YAC/B,WAAW,EAAE,MAAM;YACnB,aAAa,EAAE,MAAM;YACrB,KAAK,EAAE,EAAE;SACV,CAAC,CAAC;QACH,MAAM,CAAE,MAAM,CAAC,IAAY,CAAC,QAAQ,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=performance-audit.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"performance-audit.test.d.ts","sourceRoot":"","sources":["../../../src/analyzers/__tests__/performance-audit.test.ts"],"names":[],"mappings":""}
@@ -1,42 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'fs';
3
- import { join } from 'path';
4
- import { tmpdir } from 'os';
5
- import { auditPerformance } from '../performance-audit.js';
6
- describe('auditPerformance', () => {
7
- let tmpDir;
8
- beforeEach(() => {
9
- tmpDir = mkdtempSync(join(tmpdir(), 'perf-audit-'));
10
- mkdirSync(join(tmpDir, 'src'));
11
- });
12
- afterEach(() => {
13
- rmSync(tmpDir, { recursive: true, force: true });
14
- });
15
- it('detects pure components without React.memo', () => {
16
- writeFileSync(join(tmpDir, 'src', 'Card.tsx'), `
17
- export function Card({ title, body }: { title: string; body: string }) {
18
- return <div><h1>{title}</h1><p>{body}</p></div>;
19
- }
20
- `);
21
- const result = auditPerformance({ projectRoot: tmpDir, files: [join(tmpDir, 'src', 'Card.tsx')] });
22
- expect(result.findings.some(f => f.category === 'missing-memo')).toBe(true);
23
- });
24
- it('detects inline object creation in JSX', () => {
25
- writeFileSync(join(tmpDir, 'src', 'List.tsx'), `
26
- import { useState } from 'react';
27
- export function List() {
28
- const [items] = useState([]);
29
- return items.map(item => <div key={item.id} style={{ color: 'red' }}>{item.name}</div>);
30
- }
31
- `);
32
- const result = auditPerformance({ projectRoot: tmpDir, files: [join(tmpDir, 'src', 'List.tsx')] });
33
- expect(result.findings.some(f => f.category === 'inline-object')).toBe(true);
34
- });
35
- it('returns metrics about components', () => {
36
- writeFileSync(join(tmpDir, 'src', 'A.tsx'), 'export function A() { return null; }');
37
- writeFileSync(join(tmpDir, 'src', 'B.tsx'), 'export function B() { return null; }');
38
- const result = auditPerformance({ projectRoot: tmpDir, files: [join(tmpDir, 'src', 'A.tsx'), join(tmpDir, 'src', 'B.tsx')] });
39
- expect(result.metrics.totalComponents).toBe(2);
40
- });
41
- });
42
- //# sourceMappingURL=performance-audit.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"performance-audit.test.js","sourceRoot":"","sources":["../../../src/analyzers/__tests__/performance-audit.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;QACpD,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE;;;;CAIlD,CAAC,CAAC;QACC,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;QACnG,MAAM,CAAC,MAAM,CAAC,QAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE;;;;;;CAMlD,CAAC,CAAC;QACC,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;QACnG,MAAM,CAAC,MAAM,CAAC,QAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,sCAAsC,CAAC,CAAC;QACpF,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,sCAAsC,CAAC,CAAC;QACpF,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9H,MAAM,CAAC,MAAM,CAAC,OAAQ,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=refactor-component.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"refactor-component.test.d.ts","sourceRoot":"","sources":["../../../src/analyzers/__tests__/refactor-component.test.ts"],"names":[],"mappings":""}
@@ -1,65 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'fs';
3
- import { join } from 'path';
4
- import { tmpdir } from 'os';
5
- import { refactorComponent } from '../refactor-component.js';
6
- describe('refactorComponent', () => {
7
- let tmpDir;
8
- beforeEach(() => {
9
- tmpDir = mkdtempSync(join(tmpdir(), 'refactor-'));
10
- mkdirSync(join(tmpDir, 'src'));
11
- });
12
- afterEach(() => {
13
- rmSync(tmpDir, { recursive: true, force: true });
14
- });
15
- it('calculates complexity score', () => {
16
- writeFileSync(join(tmpDir, 'src', 'Complex.tsx'), `
17
- import { useState, useEffect, useMemo, useCallback } from 'react';
18
- export function Complex({ a, b, c, d, e, f, g, h, i, j }: any) {
19
- const [x, setX] = useState(0);
20
- const [y, setY] = useState(0);
21
- useEffect(() => {}, [x]);
22
- const z = useMemo(() => x + y, [x, y]);
23
- const handler = useCallback(() => setX(x + 1), [x]);
24
- if (a) {
25
- if (b) {
26
- if (c) {
27
- return <div>deep</div>;
28
- }
29
- }
30
- }
31
- return null;
32
- }
33
- `);
34
- const result = refactorComponent(join(tmpDir, 'src', 'Complex.tsx'), tmpDir);
35
- expect(result.success).toBe(true);
36
- expect(result.data.complexity.score).toBeGreaterThan(50);
37
- expect(result.data.complexity.lines).toBeGreaterThan(10);
38
- });
39
- it('identifies too many props', () => {
40
- writeFileSync(join(tmpDir, 'src', 'ManyProps.tsx'), `
41
- export function ManyProps({ a, b, c, d, e, f, g, h, i }: any) {
42
- return <div />;
43
- }
44
- `);
45
- const result = refactorComponent(join(tmpDir, 'src', 'ManyProps.tsx'), tmpDir);
46
- expect(result.data.smells.some((s) => s.type === 'too-many-props')).toBe(true);
47
- });
48
- it('suggests extracting hooks for data fetching logic', () => {
49
- writeFileSync(join(tmpDir, 'src', 'WithData.tsx'), `
50
- import { useState, useEffect } from 'react';
51
- export function WithData() {
52
- const [data, setData] = useState(null);
53
- const [loading, setLoading] = useState(true);
54
- useEffect(() => {
55
- fetch('/api/data').then(r => r.json()).then(d => { setData(d); setLoading(false); });
56
- }, []);
57
- if (loading) return <div>Loading...</div>;
58
- return <div>{JSON.stringify(data)}</div>;
59
- }
60
- `);
61
- const result = refactorComponent(join(tmpDir, 'src', 'WithData.tsx'), tmpDir);
62
- expect(result.data.refactorPlan.some((p) => p.action === 'extract-hook')).toBe(true);
63
- });
64
- });
65
- //# sourceMappingURL=refactor-component.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"refactor-component.test.js","sourceRoot":"","sources":["../../../src/analyzers/__tests__/refactor-component.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;QAClD,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,EAAE;;;;;;;;;;;;;;;;;CAiBrD,CAAC,CAAC;QACC,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAE,MAAM,CAAC,IAAY,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAClE,MAAM,CAAE,MAAM,CAAC,IAAY,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,eAAe,CAAC,EAAE;;;;CAIvD,CAAC,CAAC;QACC,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;QAC/E,MAAM,CAAE,MAAM,CAAC,IAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,EAAE;;;;;;;;;;;CAWtD,CAAC,CAAC;QACC,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;QAC9E,MAAM,CAAE,MAAM,CAAC,IAAY,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrG,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,9 +0,0 @@
1
- import type { AnalysisResult } from './types.js';
2
- interface DiagnoseInput {
3
- projectRoot: string;
4
- errorMessage: string;
5
- stackTrace?: string;
6
- }
7
- export declare function diagnoseBug(input: DiagnoseInput): AnalysisResult;
8
- export {};
9
- //# sourceMappingURL=diagnose-bug.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"diagnose-bug.d.ts","sourceRoot":"","sources":["../../src/analyzers/diagnose-bug.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,YAAY,CAAC;AAKlE,UAAU,aAAa;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CA2FhE"}
@@ -1,108 +0,0 @@
1
- import { readFileContent, getRelativePath } from './file-scanner.js';
2
- import { readdirSync, statSync } from 'fs';
3
- import { join } from 'path';
4
- import { execSync } from 'child_process';
5
- export function diagnoseBug(input) {
6
- const { projectRoot, errorMessage, stackTrace } = input;
7
- const rootCauses = [];
8
- // Parse error type
9
- const isNullAccess = /Cannot read propert.*null|Cannot read propert.*undefined/.test(errorMessage);
10
- const isRenderError = /render|jsx|component/i.test(errorMessage);
11
- // Scan files for common patterns
12
- const files = scanProjectFiles(projectRoot);
13
- for (const file of files) {
14
- const content = readFileContent(file);
15
- const relPath = getRelativePath(projectRoot, file);
16
- const lines = content.split('\n');
17
- // Check for null/undefined access patterns
18
- if (isNullAccess) {
19
- for (let i = 0; i < lines.length; i++) {
20
- const line = lines[i];
21
- if (/\w+\.\w+\.\w+/.test(line) && !/\?\.|&&|\|\||\?/.test(line)) {
22
- if (!/import|from|type|interface/.test(line)) {
23
- rootCauses.push({
24
- probability: 'medium',
25
- description: '链式属性访问缺少空值检查',
26
- file: relPath,
27
- line: i + 1,
28
- evidence: line.trim(),
29
- fix: '使用可选链操作符 ?. 或添加空值检查',
30
- });
31
- }
32
- }
33
- }
34
- }
35
- // Check for missing keys in lists
36
- if (isRenderError) {
37
- for (let i = 0; i < lines.length; i++) {
38
- if (/\.map\s*\(.*=>\s*<\w+/.test(lines[i]) && !/key=/.test(lines[i])) {
39
- rootCauses.push({
40
- probability: 'medium',
41
- description: '列表渲染缺少 key 属性',
42
- file: relPath,
43
- line: i + 1,
44
- evidence: lines[i].trim(),
45
- fix: '为列表项添加唯一的 key 属性',
46
- });
47
- }
48
- }
49
- }
50
- }
51
- // Get recent git changes
52
- let recentChanges = [];
53
- try {
54
- const gitLog = execSync('git log --oneline -5', { cwd: projectRoot, encoding: 'utf-8' });
55
- recentChanges = gitLog.trim().split('\n');
56
- }
57
- catch { }
58
- // Extract file from stack trace
59
- let relevantFile;
60
- let relevantLine;
61
- if (stackTrace) {
62
- const fileMatch = stackTrace.match(/(?:at\s+\w+\s+\()?([^(]+:\d+):?\d*\)?/);
63
- if (fileMatch) {
64
- const [file, line] = fileMatch[1].split(':');
65
- relevantFile = file;
66
- relevantLine = parseInt(line);
67
- }
68
- }
69
- return {
70
- success: true,
71
- summary: `分析错误 "${errorMessage.substring(0, 50)}...",发现 ${rootCauses.length} 个可能原因`,
72
- data: { rootCauses, recentChanges, relevantFile, relevantLine },
73
- findings: rootCauses.map(rc => ({
74
- severity: rc.probability === 'high' ? 'critical' : 'warning',
75
- category: 'bug-root-cause',
76
- title: rc.description,
77
- description: rc.evidence ?? rc.description,
78
- file: rc.file,
79
- line: rc.line,
80
- suggestion: rc.fix,
81
- })),
82
- };
83
- }
84
- function scanProjectFiles(root) {
85
- const files = [];
86
- function walk(dir) {
87
- try {
88
- const entries = readdirSync(dir);
89
- for (const entry of entries) {
90
- if (['node_modules', 'dist', 'build', '.git'].includes(entry))
91
- continue;
92
- const fullPath = join(dir, entry);
93
- try {
94
- const stat = statSync(fullPath);
95
- if (stat.isDirectory())
96
- walk(fullPath);
97
- else if (/\.(tsx?|jsx?)$/.test(entry))
98
- files.push(fullPath);
99
- }
100
- catch { }
101
- }
102
- }
103
- catch { }
104
- }
105
- walk(root);
106
- return files;
107
- }
108
- //# sourceMappingURL=diagnose-bug.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"diagnose-bug.js","sourceRoot":"","sources":["../../src/analyzers/diagnose-bug.ts"],"names":[],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- import type { AnalyzerContext } from './types.js';
2
- export declare function scanFiles(root: string, options?: {
3
- extensions?: string[];
4
- ignore?: string[];
5
- pattern?: RegExp;
6
- }): AnalyzerContext;
7
- export declare function readFileContent(filePath: string): string;
8
- export declare function getRelativePath(root: string, filePath: string): string;
9
- //# sourceMappingURL=file-scanner.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-scanner.d.ts","sourceRoot":"","sources":["../../src/analyzers/file-scanner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACA,eAAe,CAuBjB;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEtE"}
@@ -1,35 +0,0 @@
1
- import { readdirSync, statSync, readFileSync } from 'fs';
2
- import { join, extname, relative } from 'path';
3
- const DEFAULT_IGNORE = ['node_modules', 'dist', 'build', '.git', '.next', 'coverage'];
4
- const REACT_EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js'];
5
- export function scanFiles(root, options) {
6
- const extensions = options?.extensions ?? REACT_EXTENSIONS;
7
- const ignore = options?.ignore ?? DEFAULT_IGNORE;
8
- const files = [];
9
- function walk(dir) {
10
- const entries = readdirSync(dir);
11
- for (const entry of entries) {
12
- if (ignore.includes(entry))
13
- continue;
14
- const fullPath = join(dir, entry);
15
- const stat = statSync(fullPath);
16
- if (stat.isDirectory()) {
17
- walk(fullPath);
18
- }
19
- else if (extensions.includes(extname(entry))) {
20
- if (!options?.pattern || options.pattern.test(fullPath)) {
21
- files.push(fullPath);
22
- }
23
- }
24
- }
25
- }
26
- walk(root);
27
- return { projectRoot: root, files };
28
- }
29
- export function readFileContent(filePath) {
30
- return readFileSync(filePath, 'utf-8');
31
- }
32
- export function getRelativePath(root, filePath) {
33
- return relative(root, filePath);
34
- }
35
- //# sourceMappingURL=file-scanner.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-scanner.js","sourceRoot":"","sources":["../../src/analyzers/file-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAG/C,MAAM,cAAc,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AACtF,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAExD,MAAM,UAAU,SAAS,CACvB,IAAY,EACZ,OAIC;IAED,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,gBAAgB,CAAC;IAC3D,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,cAAc,CAAC;IACjD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,SAAS,IAAI,CAAC,GAAW;QACvB,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAChC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvB,IAAI,CAAC,QAAQ,CAAC,CAAC;YACjB,CAAC;iBAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC/C,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACxD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,CAAC;IACX,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,QAAgB;IAC5D,OAAO,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { AnalysisResult, AnalyzerContext } from './types.js';
2
- export declare function reviewHooks(ctx: AnalyzerContext): AnalysisResult;
3
- //# sourceMappingURL=hooks-review.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hooks-review.d.ts","sourceRoot":"","sources":["../../src/analyzers/hooks-review.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAW,eAAe,EAAE,MAAM,YAAY,CAAC;AAW3E,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,cAAc,CAqIhE"}