react-anti-pattern-sniffer 0.1.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 (97) hide show
  1. package/.snifferrc.json +29 -0
  2. package/LICENSE +21 -0
  3. package/README.md +289 -0
  4. package/bin/react-sniff.js +3 -0
  5. package/dist/src/cli/arg-parser.d.ts +10 -0
  6. package/dist/src/cli/arg-parser.d.ts.map +1 -0
  7. package/dist/src/cli/arg-parser.js +81 -0
  8. package/dist/src/cli/arg-parser.js.map +1 -0
  9. package/dist/src/cli/config-loader.d.ts +11 -0
  10. package/dist/src/cli/config-loader.d.ts.map +1 -0
  11. package/dist/src/cli/config-loader.js +140 -0
  12. package/dist/src/cli/config-loader.js.map +1 -0
  13. package/dist/src/cli/help.d.ts +3 -0
  14. package/dist/src/cli/help.d.ts.map +1 -0
  15. package/dist/src/cli/help.js +59 -0
  16. package/dist/src/cli/help.js.map +1 -0
  17. package/dist/src/cli/index.d.ts +2 -0
  18. package/dist/src/cli/index.d.ts.map +1 -0
  19. package/dist/src/cli/index.js +107 -0
  20. package/dist/src/cli/index.js.map +1 -0
  21. package/dist/src/core/file-discoverer.d.ts +8 -0
  22. package/dist/src/core/file-discoverer.d.ts.map +1 -0
  23. package/dist/src/core/file-discoverer.js +151 -0
  24. package/dist/src/core/file-discoverer.js.map +1 -0
  25. package/dist/src/core/orchestrator.d.ts +13 -0
  26. package/dist/src/core/orchestrator.d.ts.map +1 -0
  27. package/dist/src/core/orchestrator.js +176 -0
  28. package/dist/src/core/orchestrator.js.map +1 -0
  29. package/dist/src/core/sniffer-ignore.d.ts +25 -0
  30. package/dist/src/core/sniffer-ignore.d.ts.map +1 -0
  31. package/dist/src/core/sniffer-ignore.js +91 -0
  32. package/dist/src/core/sniffer-ignore.js.map +1 -0
  33. package/dist/src/core/sniffer-registry.d.ts +8 -0
  34. package/dist/src/core/sniffer-registry.d.ts.map +1 -0
  35. package/dist/src/core/sniffer-registry.js +64 -0
  36. package/dist/src/core/sniffer-registry.js.map +1 -0
  37. package/dist/src/core/worker-pool.d.ts +27 -0
  38. package/dist/src/core/worker-pool.d.ts.map +1 -0
  39. package/dist/src/core/worker-pool.js +176 -0
  40. package/dist/src/core/worker-pool.js.map +1 -0
  41. package/dist/src/core/worker-runner.d.ts +2 -0
  42. package/dist/src/core/worker-runner.d.ts.map +1 -0
  43. package/dist/src/core/worker-runner.js +52 -0
  44. package/dist/src/core/worker-runner.js.map +1 -0
  45. package/dist/src/output/formatter.d.ts +3 -0
  46. package/dist/src/output/formatter.d.ts.map +1 -0
  47. package/dist/src/output/formatter.js +13 -0
  48. package/dist/src/output/formatter.js.map +1 -0
  49. package/dist/src/output/json-renderer.d.ts +3 -0
  50. package/dist/src/output/json-renderer.d.ts.map +1 -0
  51. package/dist/src/output/json-renderer.js +49 -0
  52. package/dist/src/output/json-renderer.js.map +1 -0
  53. package/dist/src/output/markdown-renderer.d.ts +3 -0
  54. package/dist/src/output/markdown-renderer.d.ts.map +1 -0
  55. package/dist/src/output/markdown-renderer.js +70 -0
  56. package/dist/src/output/markdown-renderer.js.map +1 -0
  57. package/dist/src/plugins/plugin-loader.d.ts +7 -0
  58. package/dist/src/plugins/plugin-loader.d.ts.map +1 -0
  59. package/dist/src/plugins/plugin-loader.js +47 -0
  60. package/dist/src/plugins/plugin-loader.js.map +1 -0
  61. package/dist/src/plugins/plugin-sandbox.d.ts +3 -0
  62. package/dist/src/plugins/plugin-sandbox.d.ts.map +1 -0
  63. package/dist/src/plugins/plugin-sandbox.js +105 -0
  64. package/dist/src/plugins/plugin-sandbox.js.map +1 -0
  65. package/dist/src/plugins/plugin-validator.d.ts +14 -0
  66. package/dist/src/plugins/plugin-validator.d.ts.map +1 -0
  67. package/dist/src/plugins/plugin-validator.js +92 -0
  68. package/dist/src/plugins/plugin-validator.js.map +1 -0
  69. package/dist/src/sniffers/god-hook-sniffer.d.ts +12 -0
  70. package/dist/src/sniffers/god-hook-sniffer.d.ts.map +1 -0
  71. package/dist/src/sniffers/god-hook-sniffer.js +109 -0
  72. package/dist/src/sniffers/god-hook-sniffer.js.map +1 -0
  73. package/dist/src/sniffers/prop-drilling-sniffer.d.ts +5 -0
  74. package/dist/src/sniffers/prop-drilling-sniffer.d.ts.map +1 -0
  75. package/dist/src/sniffers/prop-drilling-sniffer.js +145 -0
  76. package/dist/src/sniffers/prop-drilling-sniffer.js.map +1 -0
  77. package/dist/src/sniffers/prop-explosion-sniffer.d.ts +4 -0
  78. package/dist/src/sniffers/prop-explosion-sniffer.d.ts.map +1 -0
  79. package/dist/src/sniffers/prop-explosion-sniffer.js +134 -0
  80. package/dist/src/sniffers/prop-explosion-sniffer.js.map +1 -0
  81. package/dist/src/sniffers/sniffer-interface.d.ts +88 -0
  82. package/dist/src/sniffers/sniffer-interface.d.ts.map +1 -0
  83. package/dist/src/sniffers/sniffer-interface.js +18 -0
  84. package/dist/src/sniffers/sniffer-interface.js.map +1 -0
  85. package/dist/src/tui/interactive-viewer.d.ts +7 -0
  86. package/dist/src/tui/interactive-viewer.d.ts.map +1 -0
  87. package/dist/src/tui/interactive-viewer.js +453 -0
  88. package/dist/src/tui/interactive-viewer.js.map +1 -0
  89. package/dist/src/utils/logger.d.ts +11 -0
  90. package/dist/src/utils/logger.d.ts.map +1 -0
  91. package/dist/src/utils/logger.js +90 -0
  92. package/dist/src/utils/logger.js.map +1 -0
  93. package/dist/src/utils/regex-helpers.d.ts +53 -0
  94. package/dist/src/utils/regex-helpers.d.ts.map +1 -0
  95. package/dist/src/utils/regex-helpers.js +275 -0
  96. package/dist/src/utils/regex-helpers.js.map +1 -0
  97. package/package.json +40 -0
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const regex_helpers_js_1 = require("../utils/regex-helpers.js");
4
+ function buildSuggestion(componentName) {
5
+ return (`**Consider refactoring \`${componentName}\`:**\n` +
6
+ '- Group related props into object props (e.g., `userConfig`, `handlers`)\n' +
7
+ '- Use React Context for widely-shared values\n' +
8
+ '- Split into smaller, focused components\n' +
9
+ '- Consider the Compound Components pattern');
10
+ }
11
+ /**
12
+ * Detect destructured props in component declarations that exceed the threshold.
13
+ *
14
+ * Searches for PascalCase function declarations with destructured parameters
15
+ * and counts the individual prop names.
16
+ */
17
+ function detectDestructuredProps(cleaned, originalSource, filePath, threshold, severity) {
18
+ const detections = [];
19
+ // Reset the regex since it has the global flag
20
+ const regex = new RegExp(regex_helpers_js_1.FUNCTIONAL_COMPONENT_DECL.source, regex_helpers_js_1.FUNCTIONAL_COMPONENT_DECL.flags);
21
+ let match;
22
+ while ((match = regex.exec(cleaned)) !== null) {
23
+ // Component name is in group 1 (function decl), group 2 (memo/forwardRef), or group 3 (const assignment)
24
+ const componentName = match[1] || match[2] || match[3];
25
+ if (!componentName)
26
+ continue;
27
+ // Find the destructured props after this match
28
+ // Look for the opening paren + destructuring pattern starting from the match
29
+ const afterMatch = cleaned.substring(match.index);
30
+ const destructuredMatch = regex_helpers_js_1.DESTRUCTURED_PROPS.exec(afterMatch);
31
+ if (!destructuredMatch)
32
+ continue;
33
+ const propsString = destructuredMatch[1];
34
+ const propNames = (0, regex_helpers_js_1.parseDestructuredProps)(propsString);
35
+ const propCount = propNames.length;
36
+ if (propCount > threshold) {
37
+ // Use the position in the original source for accurate line/column
38
+ const line = (0, regex_helpers_js_1.getLineNumber)(originalSource, match.index);
39
+ const column = (0, regex_helpers_js_1.getColumnNumber)(originalSource, match.index);
40
+ detections.push({
41
+ snifferName: 'prop-explosion',
42
+ filePath,
43
+ line,
44
+ column,
45
+ message: `Component "${componentName}" has ${propCount} props (threshold: ${threshold})`,
46
+ severity,
47
+ suggestion: buildSuggestion(componentName),
48
+ details: {
49
+ componentName,
50
+ propCount,
51
+ propNames,
52
+ threshold,
53
+ },
54
+ });
55
+ }
56
+ }
57
+ return detections;
58
+ }
59
+ /**
60
+ * Detect JSX usage sites where a PascalCase component receives too many attributes.
61
+ *
62
+ * Counts non-spread attributes on JSX opening tags. Spread attributes are excluded
63
+ * because they represent an unknown number of props.
64
+ */
65
+ function detectJsxAttributeExplosion(cleaned, originalSource, filePath, threshold, severity) {
66
+ const detections = [];
67
+ const jsxRegex = new RegExp(regex_helpers_js_1.JSX_OPENING_TAG.source, regex_helpers_js_1.JSX_OPENING_TAG.flags);
68
+ let match;
69
+ while ((match = jsxRegex.exec(cleaned)) !== null) {
70
+ const componentName = match[1];
71
+ const attributesText = match[2];
72
+ // Only look at PascalCase component names (skip HTML elements)
73
+ if (!componentName || !/^[A-Z]/.test(componentName))
74
+ continue;
75
+ // Skip self-referencing / no attributes
76
+ if (!attributesText || !attributesText.trim())
77
+ continue;
78
+ // Count non-spread attributes
79
+ const attrRegex = new RegExp(regex_helpers_js_1.JSX_ATTRIBUTE.source, regex_helpers_js_1.JSX_ATTRIBUTE.flags);
80
+ const propNames = [];
81
+ let attrMatch;
82
+ while ((attrMatch = attrRegex.exec(attributesText)) !== null) {
83
+ if (attrMatch[1]) {
84
+ propNames.push(attrMatch[1]);
85
+ }
86
+ }
87
+ const propCount = propNames.length;
88
+ if (propCount > threshold) {
89
+ const line = (0, regex_helpers_js_1.getLineNumber)(originalSource, match.index);
90
+ const column = (0, regex_helpers_js_1.getColumnNumber)(originalSource, match.index);
91
+ detections.push({
92
+ snifferName: 'prop-explosion',
93
+ filePath,
94
+ line,
95
+ column,
96
+ message: `Component "${componentName}" has ${propCount} props (threshold: ${threshold})`,
97
+ severity,
98
+ suggestion: buildSuggestion(componentName),
99
+ details: {
100
+ componentName,
101
+ propCount,
102
+ propNames,
103
+ threshold,
104
+ },
105
+ });
106
+ }
107
+ }
108
+ return detections;
109
+ }
110
+ const propExplosionSniffer = {
111
+ name: 'prop-explosion',
112
+ description: 'Detects React components that receive too many props, suggesting they should be refactored into smaller components or use composition patterns.',
113
+ meta: {
114
+ name: 'prop-explosion',
115
+ description: 'Detects React components that receive too many props, suggesting they should be refactored into smaller components or use composition patterns.',
116
+ category: 'props',
117
+ severity: 'warning',
118
+ defaultConfig: {
119
+ threshold: 7,
120
+ severity: 'warning',
121
+ },
122
+ },
123
+ detect(fileContent, filePath, config) {
124
+ const threshold = typeof config.threshold === 'number' ? config.threshold : 7;
125
+ const severity = config.severity || 'warning';
126
+ // Strip comments and strings so we don't get false positives
127
+ const cleaned = (0, regex_helpers_js_1.stripCommentsAndStrings)(fileContent);
128
+ const declarationDetections = detectDestructuredProps(cleaned, fileContent, filePath, threshold, severity);
129
+ const jsxDetections = detectJsxAttributeExplosion(cleaned, fileContent, filePath, threshold, severity);
130
+ return [...declarationDetections, ...jsxDetections];
131
+ },
132
+ };
133
+ exports.default = propExplosionSniffer;
134
+ //# sourceMappingURL=prop-explosion-sniffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prop-explosion-sniffer.js","sourceRoot":"","sources":["../../../src/sniffers/prop-explosion-sniffer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ export type Severity = 'info' | 'warning' | 'error';
2
+ export type SnifferCategory = 'props' | 'hooks' | 'architecture' | 'custom';
3
+ export interface Detection {
4
+ snifferName: string;
5
+ filePath: string;
6
+ line: number;
7
+ column: number;
8
+ message: string;
9
+ severity: Severity;
10
+ suggestion: string;
11
+ details?: Record<string, unknown>;
12
+ }
13
+ export interface SnifferMeta {
14
+ name: string;
15
+ description: string;
16
+ category: SnifferCategory;
17
+ severity: Severity;
18
+ defaultConfig: Record<string, unknown>;
19
+ }
20
+ export interface SnifferExport {
21
+ name: string;
22
+ description: string;
23
+ meta: SnifferMeta;
24
+ detect(fileContent: string, filePath: string, config: Record<string, unknown>): Detection[];
25
+ }
26
+ export interface SnifferResult {
27
+ snifferName: string;
28
+ filePath: string;
29
+ detections: Detection[];
30
+ durationMs: number;
31
+ error: string | null;
32
+ }
33
+ export interface SnifferConfig {
34
+ include: string[];
35
+ exclude: string[];
36
+ parallel: boolean;
37
+ maxWorkers: number;
38
+ timeoutMs: number;
39
+ outputFormat: 'markdown' | 'json';
40
+ outputPath: string | null;
41
+ sniffers: Record<string, Record<string, unknown>>;
42
+ plugins: PluginEntry[];
43
+ }
44
+ export interface PluginEntry {
45
+ path: string;
46
+ config?: Record<string, unknown>;
47
+ }
48
+ export interface SnifferEntry {
49
+ name: string;
50
+ snifferPath: string;
51
+ config: Record<string, unknown>;
52
+ }
53
+ export interface WorkerTask {
54
+ type: 'run-sniffer';
55
+ taskId: string;
56
+ snifferPath: string;
57
+ fileContent: string;
58
+ filePath: string;
59
+ config: Record<string, unknown>;
60
+ timeoutMs: number;
61
+ }
62
+ export interface WorkerResultMessage {
63
+ type: 'sniffer-result';
64
+ taskId: string;
65
+ result: SnifferResult;
66
+ }
67
+ export interface WorkerErrorMessage {
68
+ type: 'sniffer-error';
69
+ taskId: string;
70
+ error: string;
71
+ }
72
+ export type WorkerMessage = WorkerResultMessage | WorkerErrorMessage | {
73
+ type: 'shutdown';
74
+ };
75
+ export declare const REQUIRED_EXPORT_SCHEMA: {
76
+ readonly name: "string";
77
+ readonly description: "string";
78
+ readonly meta: "object";
79
+ readonly detect: "function";
80
+ };
81
+ export declare const REQUIRED_META_SCHEMA: {
82
+ readonly name: "string";
83
+ readonly description: "string";
84
+ readonly category: "string";
85
+ readonly severity: "string";
86
+ readonly defaultConfig: "object";
87
+ };
88
+ //# sourceMappingURL=sniffer-interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-interface.d.ts","sourceRoot":"","sources":["../../../src/sniffers/sniffer-interface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.REQUIRED_META_SCHEMA = exports.REQUIRED_EXPORT_SCHEMA = void 0;
4
+ // Validation schema for plugin exports
5
+ exports.REQUIRED_EXPORT_SCHEMA = {
6
+ name: 'string',
7
+ description: 'string',
8
+ meta: 'object',
9
+ detect: 'function',
10
+ };
11
+ exports.REQUIRED_META_SCHEMA = {
12
+ name: 'string',
13
+ description: 'string',
14
+ category: 'string',
15
+ severity: 'string',
16
+ defaultConfig: 'object',
17
+ };
18
+ //# sourceMappingURL=sniffer-interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-interface.js","sourceRoot":"","sources":["../../../src/sniffers/sniffer-interface.ts"],"names":[],"mappings":";;;AAqFA,uCAAuC;AAC1B,QAAA,sBAAsB,GAAG;IACpC,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,QAAQ;IACrB,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,UAAU;CACV,CAAC;AAEE,QAAA,oBAAoB,GAAG;IAClC,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,QAAQ;IACrB,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,QAAQ;IAClB,aAAa,EAAE,QAAQ;CACf,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { SnifferResult } from '../sniffers/sniffer-interface.js';
2
+ /**
3
+ * Launch the interactive TUI viewer.
4
+ * Returns a promise that resolves when the user quits.
5
+ */
6
+ export declare function interactiveViewer(results: Map<string, SnifferResult[]>, totalIssues: number, fileCount: number, targetDir: string, batchSize: number): Promise<void>;
7
+ //# sourceMappingURL=interactive-viewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive-viewer.d.ts","sourceRoot":"","sources":["../../../src/tui/interactive-viewer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAa,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAkSjF;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,EACrC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAqOf"}