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 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/cli/help.ts"],"names":[],"mappings":";;AAGA,8BA0CC;AAED,oCAQC;AAvDD,qCAAuC;AACvC,yCAAiC;AAEjC,SAAgB,SAAS;IACvB,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCd,CAAC,IAAI,EAAE,CAAC;IAEP,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC;AAED,SAAgB,YAAY;IAC1B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAA,gBAAI,EAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,+BAA+B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const arg_parser_js_1 = require("./arg-parser.js");
4
+ const config_loader_js_1 = require("./config-loader.js");
5
+ const help_js_1 = require("./help.js");
6
+ const orchestrator_js_1 = require("../core/orchestrator.js");
7
+ const interactive_viewer_js_1 = require("../tui/interactive-viewer.js");
8
+ const formatter_js_1 = require("../output/formatter.js");
9
+ const logger_js_1 = require("../utils/logger.js");
10
+ const node_fs_1 = require("node:fs");
11
+ const node_path_1 = require("node:path");
12
+ const DEFAULT_BATCH_SIZE = 10;
13
+ /**
14
+ * Apply a batch limit to grouped results — keeps only the first N detections total.
15
+ */
16
+ function applyBatchLimit(grouped, batchSize) {
17
+ const limited = new Map();
18
+ let remaining = batchSize;
19
+ for (const [filePath, results] of grouped) {
20
+ if (remaining <= 0)
21
+ break;
22
+ const limitedResults = [];
23
+ for (const result of results) {
24
+ if (remaining <= 0)
25
+ break;
26
+ if (result.detections.length <= remaining) {
27
+ limitedResults.push(result);
28
+ remaining -= result.detections.length;
29
+ }
30
+ else {
31
+ limitedResults.push({
32
+ ...result,
33
+ detections: result.detections.slice(0, remaining),
34
+ });
35
+ remaining = 0;
36
+ }
37
+ }
38
+ if (limitedResults.length > 0) {
39
+ limited.set(filePath, limitedResults);
40
+ }
41
+ }
42
+ return limited;
43
+ }
44
+ async function main() {
45
+ const { flags, positionals } = (0, arg_parser_js_1.parseArgs)(process.argv.slice(2));
46
+ if (flags.help) {
47
+ (0, help_js_1.printHelp)();
48
+ process.exit(0);
49
+ }
50
+ if (flags.version) {
51
+ (0, help_js_1.printVersion)();
52
+ process.exit(0);
53
+ }
54
+ const isInteractive = flags.interactive === true;
55
+ const hasBatchFlag = flags.batch !== undefined;
56
+ if (flags.verbose) {
57
+ (0, logger_js_1.setLogLevel)('debug');
58
+ }
59
+ else if (flags.quiet || isInteractive) {
60
+ (0, logger_js_1.setLogLevel)(isInteractive ? 'warn' : 'silent');
61
+ }
62
+ // Parse batch size
63
+ let batchSize = DEFAULT_BATCH_SIZE;
64
+ if (typeof flags.batch === 'string') {
65
+ const n = parseInt(flags.batch, 10);
66
+ if (isNaN(n) || n < 1) {
67
+ console.error(`Invalid batch size "${flags.batch}". Must be a positive integer.`);
68
+ process.exit(2);
69
+ }
70
+ batchSize = n;
71
+ }
72
+ try {
73
+ const config = (0, config_loader_js_1.loadConfig)(flags);
74
+ const targetDir = typeof flags.dir === 'string'
75
+ ? (0, node_path_1.resolve)(flags.dir)
76
+ : positionals[0]
77
+ ? (0, node_path_1.resolve)(positionals[0])
78
+ : process.cwd();
79
+ const result = await (0, orchestrator_js_1.orchestrate)(config, targetDir);
80
+ if (isInteractive) {
81
+ await (0, interactive_viewer_js_1.interactiveViewer)(result.grouped, result.issueCount, result.fileCount, targetDir, batchSize);
82
+ process.exit(result.issueCount > 0 ? 1 : 0);
83
+ }
84
+ // Apply batch limit if -b flag is used (even in non-interactive mode)
85
+ let outputStr;
86
+ if (hasBatchFlag) {
87
+ const limited = applyBatchLimit(result.grouped, batchSize);
88
+ outputStr = (0, formatter_js_1.formatOutput)(limited, config);
89
+ }
90
+ else {
91
+ outputStr = result.output;
92
+ }
93
+ if (config.outputPath) {
94
+ (0, node_fs_1.writeFileSync)(config.outputPath, outputStr, 'utf8');
95
+ }
96
+ else if (!flags.quiet) {
97
+ process.stdout.write(outputStr);
98
+ }
99
+ process.exit(result.issueCount > 0 ? 1 : 0);
100
+ }
101
+ catch (err) {
102
+ console.error(err instanceof Error ? err.message : String(err));
103
+ process.exit(2);
104
+ }
105
+ }
106
+ main();
107
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Discover files matching include patterns, excluding those matching exclude patterns.
3
+ * Uses an iterative directory walk to avoid stack overflow on large codebases.
4
+ * Skips excluded directories early during traversal for performance.
5
+ * Returns sorted array of absolute file paths.
6
+ */
7
+ export declare function discoverFiles(include: string[], exclude: string[], basePath: string): string[];
8
+ //# sourceMappingURL=file-discoverer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-discoverer.d.ts","sourceRoot":"","sources":["../../../src/core/file-discoverer.ts"],"names":[],"mappings":"AA6FA;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE,MAAM,EAAE,EACjB,QAAQ,EAAE,MAAM,GACf,MAAM,EAAE,CAqDV"}
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.discoverFiles = discoverFiles;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ /**
7
+ * Minimal glob pattern matcher.
8
+ * Supports: ** (any path), * (any name segment), {a,b} (alternatives)
9
+ */
10
+ function matchesGlob(filePath, pattern) {
11
+ // Expand {a,b} alternatives
12
+ const braceMatch = pattern.match(/\{([^}]+)\}/);
13
+ if (braceMatch) {
14
+ const alternatives = braceMatch[1].split(',');
15
+ return alternatives.some(alt => {
16
+ const expanded = pattern.replace(braceMatch[0], alt.trim());
17
+ return matchesGlob(filePath, expanded);
18
+ });
19
+ }
20
+ // Convert glob to regex
21
+ let regexStr = '^';
22
+ let i = 0;
23
+ while (i < pattern.length) {
24
+ const ch = pattern[i];
25
+ if (ch === '*' && pattern[i + 1] === '*') {
26
+ // ** matches any path
27
+ if (pattern[i + 2] === '/') {
28
+ regexStr += '(?:.+/)?';
29
+ i += 3;
30
+ }
31
+ else {
32
+ regexStr += '.*';
33
+ i += 2;
34
+ }
35
+ }
36
+ else if (ch === '*') {
37
+ // * matches any non-separator chars
38
+ regexStr += '[^/]*';
39
+ i++;
40
+ }
41
+ else if (ch === '?') {
42
+ regexStr += '[^/]';
43
+ i++;
44
+ }
45
+ else if (ch === '.') {
46
+ regexStr += '\\.';
47
+ i++;
48
+ }
49
+ else {
50
+ regexStr += ch;
51
+ i++;
52
+ }
53
+ }
54
+ regexStr += '$';
55
+ return new RegExp(regexStr).test(filePath);
56
+ }
57
+ /**
58
+ * Check if a file path matches any of the given glob patterns.
59
+ */
60
+ function matchesAny(filePath, patterns) {
61
+ return patterns.some(p => matchesGlob(filePath, p));
62
+ }
63
+ /**
64
+ * Build a set of simple directory names to skip during traversal.
65
+ * Extracts plain names (no globs, no slashes) from exclude patterns.
66
+ */
67
+ function buildExcludedDirs(exclude) {
68
+ const dirs = new Set();
69
+ for (const pattern of exclude) {
70
+ if (!pattern.includes('*') && !pattern.includes('/') && !pattern.includes('?')) {
71
+ dirs.add(pattern);
72
+ }
73
+ }
74
+ return dirs;
75
+ }
76
+ /**
77
+ * Check if a relative path matches any exclude pattern.
78
+ */
79
+ function isExcluded(normalized, exclude, excludedDirs) {
80
+ // Check simple directory name exclusion
81
+ const segments = normalized.split('/');
82
+ for (const segment of segments) {
83
+ if (excludedDirs.has(segment))
84
+ return true;
85
+ }
86
+ // Check glob-based exclusion
87
+ for (const pattern of exclude) {
88
+ if (pattern.includes('*') || pattern.includes('/') || pattern.includes('?')) {
89
+ if (matchesGlob(normalized, pattern))
90
+ return true;
91
+ }
92
+ }
93
+ return false;
94
+ }
95
+ /**
96
+ * Discover files matching include patterns, excluding those matching exclude patterns.
97
+ * Uses an iterative directory walk to avoid stack overflow on large codebases.
98
+ * Skips excluded directories early during traversal for performance.
99
+ * Returns sorted array of absolute file paths.
100
+ */
101
+ function discoverFiles(include, exclude, basePath) {
102
+ const results = [];
103
+ const excludedDirs = buildExcludedDirs(exclude);
104
+ // Iterative BFS directory walk
105
+ const queue = [basePath];
106
+ while (queue.length > 0) {
107
+ const dir = queue.shift();
108
+ let entries;
109
+ try {
110
+ entries = (0, node_fs_1.readdirSync)(dir);
111
+ }
112
+ catch {
113
+ continue;
114
+ }
115
+ for (const entry of entries) {
116
+ // Skip hidden directories/files (., .git, etc.)
117
+ if (entry.startsWith('.'))
118
+ continue;
119
+ // Early skip: if this directory name is in the simple exclude set, skip entirely
120
+ if (excludedDirs.has(entry))
121
+ continue;
122
+ const fullPath = (0, node_path_1.join)(dir, entry);
123
+ let stat;
124
+ try {
125
+ stat = (0, node_fs_1.statSync)(fullPath);
126
+ }
127
+ catch {
128
+ continue;
129
+ }
130
+ if (stat.isDirectory()) {
131
+ // Check if this directory path matches any glob exclude pattern
132
+ const relDir = (0, node_path_1.relative)(basePath, fullPath).replace(/\\/g, '/');
133
+ if (!isExcluded(relDir, exclude, excludedDirs)) {
134
+ queue.push(fullPath);
135
+ }
136
+ }
137
+ else if (stat.isFile()) {
138
+ const relPath = (0, node_path_1.relative)(basePath, fullPath).replace(/\\/g, '/');
139
+ // Check exclude patterns
140
+ if (isExcluded(relPath, exclude, excludedDirs))
141
+ continue;
142
+ // Check include patterns
143
+ if (matchesAny(relPath, include)) {
144
+ results.push(fullPath);
145
+ }
146
+ }
147
+ }
148
+ }
149
+ return results.sort();
150
+ }
151
+ //# sourceMappingURL=file-discoverer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-discoverer.js","sourceRoot":"","sources":["../../../src/core/file-discoverer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { SnifferConfig, SnifferResult } from '../sniffers/sniffer-interface.js';
2
+ export interface OrchestrateResult {
3
+ output: string;
4
+ issueCount: number;
5
+ fileCount: number;
6
+ grouped: Map<string, SnifferResult[]>;
7
+ }
8
+ /**
9
+ * Main orchestration pipeline.
10
+ * Discovers files, loads sniffers, dispatches to workers, collects results, formats output.
11
+ */
12
+ export declare function orchestrate(config: SnifferConfig, targetDir: string): Promise<OrchestrateResult>;
13
+ //# sourceMappingURL=orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../../src/core/orchestrator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAA4B,MAAM,kCAAkC,CAAC;AAQ/G,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;CACvC;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAuLtG"}
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.orchestrate = orchestrate;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const file_discoverer_js_1 = require("./file-discoverer.js");
7
+ const sniffer_registry_js_1 = require("./sniffer-registry.js");
8
+ const worker_pool_js_1 = require("./worker-pool.js");
9
+ const formatter_js_1 = require("../output/formatter.js");
10
+ const logger_js_1 = require("../utils/logger.js");
11
+ const sniffer_ignore_js_1 = require("./sniffer-ignore.js");
12
+ /**
13
+ * Main orchestration pipeline.
14
+ * Discovers files, loads sniffers, dispatches to workers, collects results, formats output.
15
+ */
16
+ async function orchestrate(config, targetDir) {
17
+ const startTime = Date.now();
18
+ // 1. Discover target files
19
+ (0, logger_js_1.step)(`Scanning ${(0, node_path_1.relative)(process.cwd(), targetDir) || '.'} for React files...`);
20
+ const files = (0, file_discoverer_js_1.discoverFiles)(config.include, config.exclude, targetDir);
21
+ if (files.length === 0) {
22
+ (0, logger_js_1.warn)('No matching files found.');
23
+ const emptyResults = new Map();
24
+ return { output: (0, formatter_js_1.formatOutput)(emptyResults, config), issueCount: 0, fileCount: 0, grouped: emptyResults };
25
+ }
26
+ (0, logger_js_1.success)(`Found ${files.length} file${files.length === 1 ? '' : 's'} to analyze`);
27
+ // 2. Build sniffer registry
28
+ (0, logger_js_1.step)('Loading sniffers...');
29
+ const registry = new sniffer_registry_js_1.SnifferRegistry();
30
+ registry.registerBuiltIn();
31
+ // Register plugins
32
+ for (const pluginEntry of config.plugins) {
33
+ (0, logger_js_1.info)(` Loading plugin: ${pluginEntry.path}`);
34
+ registry.registerPlugin(pluginEntry, targetDir);
35
+ }
36
+ // 3. Get enabled sniffers
37
+ const enabledSniffers = registry.getEnabledSniffers(config.sniffers);
38
+ if (enabledSniffers.length === 0) {
39
+ (0, logger_js_1.warn)('No sniffers enabled.');
40
+ const emptyResults = new Map();
41
+ return { output: (0, formatter_js_1.formatOutput)(emptyResults, config), issueCount: 0, fileCount: files.length, grouped: emptyResults };
42
+ }
43
+ (0, logger_js_1.success)(`${enabledSniffers.length} sniffer${enabledSniffers.length === 1 ? '' : 's'} active: ${enabledSniffers.map(s => s.name).join(', ')}`);
44
+ // 4. Run sniffers
45
+ const allResults = [];
46
+ const mode = config.parallel && files.length > 1 ? 'parallel' : 'sequential';
47
+ const totalTasks = files.length * enabledSniffers.length;
48
+ let completedTasks = 0;
49
+ (0, logger_js_1.step)(`Running analysis (${mode}, ${totalTasks} tasks across ${files.length} files)...`);
50
+ if (mode === 'parallel') {
51
+ // Parallel mode via worker pool
52
+ const workerScript = (0, node_path_1.join)(__dirname, 'worker-runner.js');
53
+ const pool = new worker_pool_js_1.WorkerPool(workerScript, config.maxWorkers);
54
+ (0, logger_js_1.debug)(`Worker pool started with ${config.maxWorkers} workers`);
55
+ try {
56
+ const tasks = [];
57
+ for (const filePath of files) {
58
+ const fileContent = (0, node_fs_1.readFileSync)(filePath, 'utf8');
59
+ for (const sniffer of enabledSniffers) {
60
+ const task = pool
61
+ .runTask(sniffer.snifferPath, fileContent, filePath, sniffer.config, config.timeoutMs)
62
+ .then(msg => {
63
+ allResults.push(msg.result);
64
+ completedTasks++;
65
+ (0, logger_js_1.fileProgress)(completedTasks, totalTasks, (0, node_path_1.relative)(targetDir, filePath));
66
+ })
67
+ .catch(err => {
68
+ allResults.push({
69
+ snifferName: sniffer.name,
70
+ filePath,
71
+ detections: [],
72
+ durationMs: 0,
73
+ error: err instanceof Error ? err.message : String(err),
74
+ });
75
+ completedTasks++;
76
+ });
77
+ tasks.push(task);
78
+ }
79
+ }
80
+ await Promise.allSettled(tasks);
81
+ }
82
+ finally {
83
+ await pool.destroy();
84
+ (0, logger_js_1.debug)('Worker pool destroyed');
85
+ }
86
+ }
87
+ else {
88
+ // Sequential mode — run in main thread
89
+ for (let fi = 0; fi < files.length; fi++) {
90
+ const filePath = files[fi];
91
+ const fileContent = (0, node_fs_1.readFileSync)(filePath, 'utf8');
92
+ for (const sniffer of enabledSniffers) {
93
+ const startTimeTask = Date.now();
94
+ try {
95
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
96
+ const raw = require(sniffer.snifferPath);
97
+ const snifferModule = raw.default ?? raw;
98
+ const detections = snifferModule.detect(fileContent, filePath, sniffer.config);
99
+ allResults.push({
100
+ snifferName: sniffer.name,
101
+ filePath,
102
+ detections: Array.isArray(detections) ? detections : [],
103
+ durationMs: Date.now() - startTimeTask,
104
+ error: null,
105
+ });
106
+ }
107
+ catch (err) {
108
+ allResults.push({
109
+ snifferName: sniffer.name,
110
+ filePath,
111
+ detections: [],
112
+ durationMs: Date.now() - startTimeTask,
113
+ error: err instanceof Error ? err.message : String(err),
114
+ });
115
+ }
116
+ completedTasks++;
117
+ (0, logger_js_1.fileProgress)(completedTasks, totalTasks, (0, node_path_1.relative)(targetDir, filePath));
118
+ }
119
+ }
120
+ }
121
+ // 5. Apply .snifferignore
122
+ const ignoreEntries = (0, sniffer_ignore_js_1.loadSnifferIgnore)(targetDir);
123
+ const filteredResults = ignoreEntries.length > 0
124
+ ? (0, sniffer_ignore_js_1.applySnifferIgnore)(allResults, ignoreEntries, targetDir)
125
+ : allResults;
126
+ if (ignoreEntries.length > 0) {
127
+ const beforeCount = allResults.reduce((s, r) => s + r.detections.length, 0);
128
+ const afterCount = filteredResults.reduce((s, r) => s + r.detections.length, 0);
129
+ const ignored = beforeCount - afterCount;
130
+ if (ignored > 0) {
131
+ (0, logger_js_1.debug)(`Filtered ${ignored} detection(s) via .snifferignore`);
132
+ }
133
+ }
134
+ // 6. Group results by file path
135
+ const grouped = new Map();
136
+ for (const result of filteredResults) {
137
+ const existing = grouped.get(result.filePath) || [];
138
+ existing.push(result);
139
+ grouped.set(result.filePath, existing);
140
+ }
141
+ // Log any errors
142
+ let errorCount = 0;
143
+ for (const result of filteredResults) {
144
+ if (result.error) {
145
+ errorCount++;
146
+ (0, logger_js_1.warn)(`Sniffer "${result.snifferName}" failed on "${(0, node_path_1.relative)(targetDir, result.filePath)}": ${result.error}`);
147
+ }
148
+ }
149
+ // 6. Count total issues
150
+ let issueCount = 0;
151
+ for (const result of filteredResults) {
152
+ issueCount += result.detections.length;
153
+ }
154
+ const elapsed = Date.now() - startTime;
155
+ const filesPerSec = Math.round(files.length / (elapsed / 1000));
156
+ if (issueCount > 0) {
157
+ (0, logger_js_1.step)(`Found ${issueCount} issue${issueCount === 1 ? '' : 's'} in ${elapsed}ms (${filesPerSec} files/sec)`);
158
+ }
159
+ else {
160
+ (0, logger_js_1.success)(`No issues found! Scanned ${files.length} files in ${elapsed}ms (${filesPerSec} files/sec)`);
161
+ }
162
+ if (errorCount > 0) {
163
+ (0, logger_js_1.warn)(`${errorCount} sniffer error${errorCount === 1 ? '' : 's'} occurred (see above)`);
164
+ }
165
+ // 7. Format and return output
166
+ (0, logger_js_1.step)('Generating report...');
167
+ const output = (0, formatter_js_1.formatOutput)(grouped, config);
168
+ (0, logger_js_1.success)('Done!');
169
+ return {
170
+ output,
171
+ issueCount,
172
+ fileCount: files.length,
173
+ grouped,
174
+ };
175
+ }
176
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../../src/core/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { SnifferResult } from '../sniffers/sniffer-interface.js';
2
+ interface IgnoreEntry {
3
+ filePath: string;
4
+ componentName: string | null;
5
+ snifferName: string | null;
6
+ }
7
+ /**
8
+ * Parse a .snifferignore file.
9
+ * Format per line:
10
+ * path/to/file.tsx:ComponentName # sniffer-name
11
+ * path/to/file.tsx # sniffer-name
12
+ * path/to/file.tsx
13
+ * Lines starting with # are comments. Empty lines are skipped.
14
+ */
15
+ export declare function parseSnifferIgnore(content: string): IgnoreEntry[];
16
+ /**
17
+ * Load .snifferignore from the target directory. Returns empty array if not found.
18
+ */
19
+ export declare function loadSnifferIgnore(targetDir: string): IgnoreEntry[];
20
+ /**
21
+ * Filter out ignored detections from results.
22
+ */
23
+ export declare function applySnifferIgnore(results: SnifferResult[], ignoreEntries: IgnoreEntry[], targetDir: string): SnifferResult[];
24
+ export {};
25
+ //# sourceMappingURL=sniffer-ignore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-ignore.d.ts","sourceRoot":"","sources":["../../../src/core/sniffer-ignore.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEtE,UAAU,WAAW;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,CAiCjE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,EAAE,CAUlE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,aAAa,EAAE,EACxB,aAAa,EAAE,WAAW,EAAE,EAC5B,SAAS,EAAE,MAAM,GAChB,aAAa,EAAE,CA8BjB"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseSnifferIgnore = parseSnifferIgnore;
4
+ exports.loadSnifferIgnore = loadSnifferIgnore;
5
+ exports.applySnifferIgnore = applySnifferIgnore;
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
8
+ /**
9
+ * Parse a .snifferignore file.
10
+ * Format per line:
11
+ * path/to/file.tsx:ComponentName # sniffer-name
12
+ * path/to/file.tsx # sniffer-name
13
+ * path/to/file.tsx
14
+ * Lines starting with # are comments. Empty lines are skipped.
15
+ */
16
+ function parseSnifferIgnore(content) {
17
+ const entries = [];
18
+ for (const rawLine of content.split('\n')) {
19
+ const line = rawLine.trim();
20
+ if (!line || line.startsWith('#'))
21
+ continue;
22
+ // Split off inline comment
23
+ let main = line;
24
+ let snifferName = null;
25
+ const commentIdx = line.indexOf(' #');
26
+ if (commentIdx !== -1) {
27
+ main = line.substring(0, commentIdx).trim();
28
+ snifferName = line.substring(commentIdx + 3).trim() || null;
29
+ }
30
+ // Split file:component
31
+ const colonIdx = main.indexOf(':');
32
+ let filePath;
33
+ let componentName = null;
34
+ if (colonIdx !== -1) {
35
+ filePath = main.substring(0, colonIdx);
36
+ componentName = main.substring(colonIdx + 1) || null;
37
+ }
38
+ else {
39
+ filePath = main;
40
+ }
41
+ entries.push({ filePath, componentName, snifferName });
42
+ }
43
+ return entries;
44
+ }
45
+ /**
46
+ * Load .snifferignore from the target directory. Returns empty array if not found.
47
+ */
48
+ function loadSnifferIgnore(targetDir) {
49
+ const ignorePath = (0, node_path_1.join)(targetDir, '.snifferignore');
50
+ if (!(0, node_fs_1.existsSync)(ignorePath))
51
+ return [];
52
+ try {
53
+ const content = (0, node_fs_1.readFileSync)(ignorePath, 'utf8');
54
+ return parseSnifferIgnore(content);
55
+ }
56
+ catch {
57
+ return [];
58
+ }
59
+ }
60
+ /**
61
+ * Filter out ignored detections from results.
62
+ */
63
+ function applySnifferIgnore(results, ignoreEntries, targetDir) {
64
+ if (ignoreEntries.length === 0)
65
+ return results;
66
+ return results.map(result => {
67
+ const filteredDetections = result.detections.filter(det => {
68
+ const relPath = (0, node_path_1.relative)(targetDir, det.filePath);
69
+ for (const entry of ignoreEntries) {
70
+ // Check file path match
71
+ if (relPath !== entry.filePath && det.filePath !== entry.filePath)
72
+ continue;
73
+ // Check sniffer name match (null = all sniffers)
74
+ if (entry.snifferName && entry.snifferName !== det.snifferName)
75
+ continue;
76
+ // Check component name match (null = entire file)
77
+ if (entry.componentName) {
78
+ const detComp = det.details?.componentName
79
+ || det.details?.hookName;
80
+ if (detComp !== entry.componentName)
81
+ continue;
82
+ }
83
+ // Matched an ignore entry — filter out
84
+ return false;
85
+ }
86
+ return true;
87
+ });
88
+ return { ...result, detections: filteredDetections };
89
+ });
90
+ }
91
+ //# sourceMappingURL=sniffer-ignore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-ignore.js","sourceRoot":"","sources":["../../../src/core/sniffer-ignore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { SnifferEntry, PluginEntry } from '../sniffers/sniffer-interface.js';
2
+ export declare class SnifferRegistry {
3
+ private sniffers;
4
+ registerBuiltIn(): void;
5
+ registerPlugin(pluginEntry: PluginEntry, basePath: string): void;
6
+ getEnabledSniffers(snifferConfig: Record<string, Record<string, unknown>>): SnifferEntry[];
7
+ }
8
+ //# sourceMappingURL=sniffer-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-registry.d.ts","sourceRoot":"","sources":["../../../src/core/sniffer-registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAiB,MAAM,kCAAkC,CAAC;AAUjG,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAoC;IAEpD,eAAe,IAAI,IAAI;IAiBvB,cAAc,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAmBhE,kBAAkB,CAChB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACrD,YAAY,EAAE;CA0BlB"}