lostconf 0.2.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 (201) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/LICENSE +21 -0
  3. package/LICENSE.md +21 -0
  4. package/README.md +445 -0
  5. package/dist/cli.d.ts +6 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +139 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/core/discovery.d.ts +23 -0
  10. package/dist/core/discovery.d.ts.map +1 -0
  11. package/dist/core/discovery.js +75 -0
  12. package/dist/core/discovery.js.map +1 -0
  13. package/dist/core/engine.d.ts +24 -0
  14. package/dist/core/engine.d.ts.map +1 -0
  15. package/dist/core/engine.js +86 -0
  16. package/dist/core/engine.js.map +1 -0
  17. package/dist/core/severity.d.ts +25 -0
  18. package/dist/core/severity.d.ts.map +1 -0
  19. package/dist/core/severity.js +225 -0
  20. package/dist/core/severity.js.map +1 -0
  21. package/dist/core/types.d.ts +77 -0
  22. package/dist/core/types.d.ts.map +1 -0
  23. package/dist/core/types.js +21 -0
  24. package/dist/core/types.js.map +1 -0
  25. package/dist/filetree/scanner.d.ts +26 -0
  26. package/dist/filetree/scanner.d.ts.map +1 -0
  27. package/dist/filetree/scanner.js +71 -0
  28. package/dist/filetree/scanner.js.map +1 -0
  29. package/dist/filetree/tree.d.ts +5 -0
  30. package/dist/filetree/tree.d.ts.map +1 -0
  31. package/dist/filetree/tree.js +5 -0
  32. package/dist/filetree/tree.js.map +1 -0
  33. package/dist/index.d.ts +15 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +18 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/output/formatter.d.ts +12 -0
  38. package/dist/output/formatter.d.ts.map +1 -0
  39. package/dist/output/formatter.js +5 -0
  40. package/dist/output/formatter.js.map +1 -0
  41. package/dist/output/json.d.ts +9 -0
  42. package/dist/output/json.d.ts.map +1 -0
  43. package/dist/output/json.js +14 -0
  44. package/dist/output/json.js.map +1 -0
  45. package/dist/output/sarif.d.ts +9 -0
  46. package/dist/output/sarif.d.ts.map +1 -0
  47. package/dist/output/sarif.js +84 -0
  48. package/dist/output/sarif.js.map +1 -0
  49. package/dist/output/text.d.ts +9 -0
  50. package/dist/output/text.d.ts.map +1 -0
  51. package/dist/output/text.js +87 -0
  52. package/dist/output/text.js.map +1 -0
  53. package/dist/parsers/bandit.d.ts +8 -0
  54. package/dist/parsers/bandit.d.ts.map +1 -0
  55. package/dist/parsers/bandit.js +66 -0
  56. package/dist/parsers/bandit.js.map +1 -0
  57. package/dist/parsers/biome.d.ts +8 -0
  58. package/dist/parsers/biome.d.ts.map +1 -0
  59. package/dist/parsers/biome.js +74 -0
  60. package/dist/parsers/biome.js.map +1 -0
  61. package/dist/parsers/clang.d.ts +9 -0
  62. package/dist/parsers/clang.d.ts.map +1 -0
  63. package/dist/parsers/clang.js +99 -0
  64. package/dist/parsers/clang.js.map +1 -0
  65. package/dist/parsers/deno.d.ts +8 -0
  66. package/dist/parsers/deno.d.ts.map +1 -0
  67. package/dist/parsers/deno.js +73 -0
  68. package/dist/parsers/deno.js.map +1 -0
  69. package/dist/parsers/dotnet.d.ts +9 -0
  70. package/dist/parsers/dotnet.d.ts.map +1 -0
  71. package/dist/parsers/dotnet.js +89 -0
  72. package/dist/parsers/dotnet.js.map +1 -0
  73. package/dist/parsers/elixir.d.ts +7 -0
  74. package/dist/parsers/elixir.d.ts.map +1 -0
  75. package/dist/parsers/elixir.js +59 -0
  76. package/dist/parsers/elixir.js.map +1 -0
  77. package/dist/parsers/eslint.d.ts +7 -0
  78. package/dist/parsers/eslint.d.ts.map +1 -0
  79. package/dist/parsers/eslint.js +43 -0
  80. package/dist/parsers/eslint.js.map +1 -0
  81. package/dist/parsers/flake8.d.ts +10 -0
  82. package/dist/parsers/flake8.d.ts.map +1 -0
  83. package/dist/parsers/flake8.js +89 -0
  84. package/dist/parsers/flake8.js.map +1 -0
  85. package/dist/parsers/gitignore.d.ts +11 -0
  86. package/dist/parsers/gitignore.d.ts.map +1 -0
  87. package/dist/parsers/gitignore.js +72 -0
  88. package/dist/parsers/gitignore.js.map +1 -0
  89. package/dist/parsers/gitleaks.d.ts +8 -0
  90. package/dist/parsers/gitleaks.d.ts.map +1 -0
  91. package/dist/parsers/gitleaks.js +127 -0
  92. package/dist/parsers/gitleaks.js.map +1 -0
  93. package/dist/parsers/golangci.d.ts +7 -0
  94. package/dist/parsers/golangci.d.ts.map +1 -0
  95. package/dist/parsers/golangci.js +73 -0
  96. package/dist/parsers/golangci.js.map +1 -0
  97. package/dist/parsers/hadolint.d.ts +8 -0
  98. package/dist/parsers/hadolint.d.ts.map +1 -0
  99. package/dist/parsers/hadolint.js +95 -0
  100. package/dist/parsers/hadolint.js.map +1 -0
  101. package/dist/parsers/index.d.ts +38 -0
  102. package/dist/parsers/index.d.ts.map +1 -0
  103. package/dist/parsers/index.js +154 -0
  104. package/dist/parsers/index.js.map +1 -0
  105. package/dist/parsers/java.d.ts +11 -0
  106. package/dist/parsers/java.d.ts.map +1 -0
  107. package/dist/parsers/java.js +75 -0
  108. package/dist/parsers/java.js.map +1 -0
  109. package/dist/parsers/jest.d.ts +7 -0
  110. package/dist/parsers/jest.d.ts.map +1 -0
  111. package/dist/parsers/jest.js +118 -0
  112. package/dist/parsers/jest.js.map +1 -0
  113. package/dist/parsers/kotlin.d.ts +7 -0
  114. package/dist/parsers/kotlin.d.ts.map +1 -0
  115. package/dist/parsers/kotlin.js +90 -0
  116. package/dist/parsers/kotlin.js.map +1 -0
  117. package/dist/parsers/markdown.d.ts +7 -0
  118. package/dist/parsers/markdown.d.ts.map +1 -0
  119. package/dist/parsers/markdown.js +40 -0
  120. package/dist/parsers/markdown.js.map +1 -0
  121. package/dist/parsers/php.d.ts +9 -0
  122. package/dist/parsers/php.d.ts.map +1 -0
  123. package/dist/parsers/php.js +92 -0
  124. package/dist/parsers/php.js.map +1 -0
  125. package/dist/parsers/prettier.d.ts +7 -0
  126. package/dist/parsers/prettier.d.ts.map +1 -0
  127. package/dist/parsers/prettier.js +43 -0
  128. package/dist/parsers/prettier.js.map +1 -0
  129. package/dist/parsers/pylint.d.ts +8 -0
  130. package/dist/parsers/pylint.d.ts.map +1 -0
  131. package/dist/parsers/pylint.js +92 -0
  132. package/dist/parsers/pylint.js.map +1 -0
  133. package/dist/parsers/pyproject.d.ts +7 -0
  134. package/dist/parsers/pyproject.d.ts.map +1 -0
  135. package/dist/parsers/pyproject.js +127 -0
  136. package/dist/parsers/pyproject.js.map +1 -0
  137. package/dist/parsers/pyright.d.ts +8 -0
  138. package/dist/parsers/pyright.d.ts.map +1 -0
  139. package/dist/parsers/pyright.js +63 -0
  140. package/dist/parsers/pyright.js.map +1 -0
  141. package/dist/parsers/rubocop.d.ts +7 -0
  142. package/dist/parsers/rubocop.d.ts.map +1 -0
  143. package/dist/parsers/rubocop.js +102 -0
  144. package/dist/parsers/rubocop.js.map +1 -0
  145. package/dist/parsers/rust.d.ts +9 -0
  146. package/dist/parsers/rust.d.ts.map +1 -0
  147. package/dist/parsers/rust.js +68 -0
  148. package/dist/parsers/rust.js.map +1 -0
  149. package/dist/parsers/scala.d.ts +9 -0
  150. package/dist/parsers/scala.d.ts.map +1 -0
  151. package/dist/parsers/scala.js +72 -0
  152. package/dist/parsers/scala.js.map +1 -0
  153. package/dist/parsers/semgrep.d.ts +10 -0
  154. package/dist/parsers/semgrep.d.ts.map +1 -0
  155. package/dist/parsers/semgrep.js +111 -0
  156. package/dist/parsers/semgrep.js.map +1 -0
  157. package/dist/parsers/shellcheck.d.ts +8 -0
  158. package/dist/parsers/shellcheck.d.ts.map +1 -0
  159. package/dist/parsers/shellcheck.js +49 -0
  160. package/dist/parsers/shellcheck.js.map +1 -0
  161. package/dist/parsers/stylelint.d.ts +9 -0
  162. package/dist/parsers/stylelint.d.ts.map +1 -0
  163. package/dist/parsers/stylelint.js +95 -0
  164. package/dist/parsers/stylelint.js.map +1 -0
  165. package/dist/parsers/swift.d.ts +7 -0
  166. package/dist/parsers/swift.d.ts.map +1 -0
  167. package/dist/parsers/swift.js +64 -0
  168. package/dist/parsers/swift.js.map +1 -0
  169. package/dist/parsers/tflint.d.ts +8 -0
  170. package/dist/parsers/tflint.d.ts.map +1 -0
  171. package/dist/parsers/tflint.js +59 -0
  172. package/dist/parsers/tflint.js.map +1 -0
  173. package/dist/parsers/typescript.d.ts +7 -0
  174. package/dist/parsers/typescript.d.ts.map +1 -0
  175. package/dist/parsers/typescript.js +138 -0
  176. package/dist/parsers/typescript.js.map +1 -0
  177. package/dist/parsers/yamllint.d.ts +8 -0
  178. package/dist/parsers/yamllint.d.ts.map +1 -0
  179. package/dist/parsers/yamllint.js +93 -0
  180. package/dist/parsers/yamllint.js.map +1 -0
  181. package/dist/plugin/registry.d.ts +20 -0
  182. package/dist/plugin/registry.d.ts.map +1 -0
  183. package/dist/plugin/registry.js +52 -0
  184. package/dist/plugin/registry.js.map +1 -0
  185. package/dist/plugin/types.d.ts +16 -0
  186. package/dist/plugin/types.d.ts.map +1 -0
  187. package/dist/plugin/types.js +5 -0
  188. package/dist/plugin/types.js.map +1 -0
  189. package/dist/validator/glob.d.ts +16 -0
  190. package/dist/validator/glob.d.ts.map +1 -0
  191. package/dist/validator/glob.js +44 -0
  192. package/dist/validator/glob.js.map +1 -0
  193. package/dist/validator/regex.d.ts +10 -0
  194. package/dist/validator/regex.d.ts.map +1 -0
  195. package/dist/validator/regex.js +45 -0
  196. package/dist/validator/regex.js.map +1 -0
  197. package/dist/validator/validator.d.ts +17 -0
  198. package/dist/validator/validator.d.ts.map +1 -0
  199. package/dist/validator/validator.js +85 -0
  200. package/dist/validator/validator.js.map +1 -0
  201. package/package.json +75 -0
package/dist/cli.js ADDED
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for lostconf
4
+ */
5
+ import { Command } from 'commander';
6
+ import fs from 'fs/promises';
7
+ import { createEngine } from './core/engine.js';
8
+ import { getBuiltinParsers } from './parsers/index.js';
9
+ import { createTextFormatter } from './output/text.js';
10
+ import { createJsonFormatter } from './output/json.js';
11
+ import { createSarifFormatter } from './output/sarif.js';
12
+ import { Severity } from './core/types.js';
13
+ const program = new Command();
14
+ program
15
+ .name('lostconf')
16
+ .description('A meta-linter that detects stale references in configuration files')
17
+ .version('0.1.0')
18
+ .argument('[paths...]', 'Paths to scan (default: current directory)')
19
+ .option('-f, --format <fmt>', 'Output format: text, json, sarif', 'text')
20
+ .option('-o, --output <file>', 'Write to file instead of stdout')
21
+ .option('--include <glob...>', 'Only check matching config files')
22
+ .option('--exclude <glob...>', 'Skip matching config files')
23
+ .option('--skip-ignore-files', 'Skip .gitignore, .prettierignore, etc. (reduces noise)')
24
+ .option('--exclude-parsers <names...>', 'Skip specific parsers (e.g., gitignore prettierignore)')
25
+ .option('--min-severity <level>', 'Minimum severity to show: low, medium, high (default: medium)', 'medium')
26
+ .option('--show-all', 'Show all findings including low severity (same as --min-severity=low)')
27
+ .option('--fail-on-stale', 'Exit code 1 if stale patterns found')
28
+ .option('-q, --quiet', 'Suppress non-error output')
29
+ .option('-v, --verbose', 'Show debug info')
30
+ .option('--no-progress', 'Disable progress indicator')
31
+ .action(async (paths, options) => {
32
+ try {
33
+ await run(paths, options);
34
+ }
35
+ catch (err) {
36
+ if (!options.quiet) {
37
+ console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
38
+ }
39
+ process.exit(2);
40
+ }
41
+ });
42
+ async function run(paths, options) {
43
+ const { format, output, include, exclude, skipIgnoreFiles = false, excludeParsers = [], minSeverity: minSeverityStr = 'medium', showAll = false, failOnStale = false, quiet = false, verbose = false, progress = true } = options;
44
+ // Determine minimum severity
45
+ let minSeverity;
46
+ if (showAll) {
47
+ minSeverity = Severity.LOW;
48
+ }
49
+ else {
50
+ switch (minSeverityStr.toLowerCase()) {
51
+ case 'low':
52
+ minSeverity = Severity.LOW;
53
+ break;
54
+ case 'medium':
55
+ minSeverity = Severity.MEDIUM;
56
+ break;
57
+ case 'high':
58
+ minSeverity = Severity.HIGH;
59
+ break;
60
+ default:
61
+ console.error(`Invalid severity level: ${minSeverityStr}. Using 'medium'.`);
62
+ minSeverity = Severity.MEDIUM;
63
+ }
64
+ }
65
+ // Default to current directory if no paths specified
66
+ const scanPaths = paths.length > 0 ? paths : ['.'];
67
+ // Get formatter
68
+ const formatter = getFormatter(format);
69
+ // Get all built-in parsers
70
+ let parsers = getBuiltinParsers();
71
+ // Filter parsers based on options
72
+ const ignoreParserNames = ['gitignore', 'dockerignore', 'prettierignore', 'eslintignore'];
73
+ const excludeParserSet = new Set([
74
+ ...(skipIgnoreFiles ? ignoreParserNames : []),
75
+ ...excludeParsers
76
+ ]);
77
+ if (excludeParserSet.size > 0) {
78
+ parsers = parsers.filter((p) => !excludeParserSet.has(p.name));
79
+ if (verbose) {
80
+ console.error(`[lostconf] Excluded parsers: ${Array.from(excludeParserSet).join(', ')}`);
81
+ }
82
+ }
83
+ // Create engine
84
+ const engine = createEngine(parsers, {
85
+ paths: scanPaths,
86
+ include,
87
+ exclude,
88
+ verbose,
89
+ progress: progress && !quiet && !verbose && format === 'text'
90
+ });
91
+ // Run validation
92
+ const rawResult = await engine.run();
93
+ // Filter findings based on severity
94
+ const severityOrder = { [Severity.LOW]: 0, [Severity.MEDIUM]: 1, [Severity.HIGH]: 2 };
95
+ const minSeverityLevel = severityOrder[minSeverity];
96
+ const filteredFindings = rawResult.findings.filter((finding) => severityOrder[finding.severity] >= minSeverityLevel);
97
+ const hiddenCount = rawResult.findings.length - filteredFindings.length;
98
+ const result = {
99
+ findings: filteredFindings,
100
+ summary: {
101
+ total: filteredFindings.length,
102
+ files: new Set(filteredFindings.map((f) => f.file)).size
103
+ }
104
+ };
105
+ // Format output
106
+ let formatted = formatter.format(result);
107
+ // Add note about hidden findings if any (only for text format)
108
+ if (hiddenCount > 0 && !quiet && format === 'text') {
109
+ const hiddenText = hiddenCount === 1 ? 'pattern' : 'patterns';
110
+ formatted += `\n${hiddenCount} low severity ${hiddenText} hidden. Use --show-all to see them.`;
111
+ }
112
+ // Write output
113
+ if (output) {
114
+ await fs.writeFile(output, formatted, 'utf-8');
115
+ if (!quiet) {
116
+ console.log(`Results written to ${output}`);
117
+ }
118
+ }
119
+ else if (!quiet) {
120
+ console.log(formatted);
121
+ }
122
+ // Exit code
123
+ if (failOnStale && result.findings.length > 0) {
124
+ process.exit(1);
125
+ }
126
+ }
127
+ function getFormatter(format) {
128
+ switch (format) {
129
+ case 'json':
130
+ return createJsonFormatter();
131
+ case 'sarif':
132
+ return createSarifFormatter();
133
+ case 'text':
134
+ default:
135
+ return createTextFormatter();
136
+ }
137
+ }
138
+ program.parse();
139
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Config file auto-discovery
3
+ */
4
+ import type { Parser } from '../plugin/types.js';
5
+ export interface DiscoveryOptions {
6
+ /** Directories to scan */
7
+ paths: string[];
8
+ /** Glob patterns to include */
9
+ include?: string[];
10
+ /** Glob patterns to exclude */
11
+ exclude?: string[];
12
+ }
13
+ export interface DiscoveredConfig {
14
+ /** Path to the config file (relative to base) */
15
+ path: string;
16
+ /** Absolute path */
17
+ absolutePath: string;
18
+ /** Parser that can handle this file */
19
+ parser: Parser;
20
+ }
21
+ /** Discover config files that can be parsed */
22
+ export declare function discoverConfigs(parsers: Parser[], options: DiscoveryOptions): Promise<DiscoveredConfig[]>;
23
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+CAA+C;AAC/C,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAgD7B"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Config file auto-discovery
3
+ */
4
+ import fg from 'fast-glob';
5
+ import path from 'path';
6
+ /** Discover config files that can be parsed */
7
+ export async function discoverConfigs(parsers, options) {
8
+ const { paths, include, exclude = [] } = options;
9
+ const basePath = paths.length === 1 ? path.resolve(paths[0]) : process.cwd();
10
+ // Build patterns from all parsers
11
+ const allPatterns = new Set();
12
+ for (const parser of parsers) {
13
+ for (const pattern of parser.filePatterns) {
14
+ allPatterns.add(pattern);
15
+ }
16
+ }
17
+ // Apply include filter if specified
18
+ let searchPatterns;
19
+ if (include && include.length > 0) {
20
+ searchPatterns = include;
21
+ }
22
+ else {
23
+ searchPatterns = Array.from(allPatterns);
24
+ }
25
+ // Default excludes
26
+ const defaultExclude = ['**/node_modules/**', '**/.git/**', '**/dist/**', '**/build/**'];
27
+ // Find all matching config files
28
+ const files = await fg(searchPatterns, {
29
+ cwd: basePath,
30
+ dot: true,
31
+ onlyFiles: true,
32
+ ignore: [...defaultExclude, ...exclude]
33
+ });
34
+ // Match files to parsers
35
+ const discovered = [];
36
+ for (const file of files) {
37
+ for (const parser of parsers) {
38
+ if (fileMatchesParser(file, parser)) {
39
+ discovered.push({
40
+ path: file,
41
+ absolutePath: path.join(basePath, file),
42
+ parser
43
+ });
44
+ break; // Only use first matching parser
45
+ }
46
+ }
47
+ }
48
+ return discovered;
49
+ }
50
+ /** Check if a file matches a parser's patterns */
51
+ function fileMatchesParser(file, parser) {
52
+ const basename = path.basename(file);
53
+ for (const pattern of parser.filePatterns) {
54
+ // Exact match
55
+ if (pattern === basename || pattern === file) {
56
+ return true;
57
+ }
58
+ // Handle **/pattern
59
+ if (pattern.startsWith('**/')) {
60
+ const suffix = pattern.slice(3);
61
+ if (basename === suffix || file.endsWith('/' + suffix)) {
62
+ return true;
63
+ }
64
+ }
65
+ // Handle *.extension patterns
66
+ if (pattern.startsWith('*.')) {
67
+ const ext = pattern.slice(1);
68
+ if (file.endsWith(ext)) {
69
+ return true;
70
+ }
71
+ }
72
+ }
73
+ return false;
74
+ }
75
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Main orchestration engine
3
+ */
4
+ import type { ValidationResult } from './types.js';
5
+ import type { Parser } from '../plugin/types.js';
6
+ export interface EngineOptions {
7
+ /** Directories to scan */
8
+ paths: string[];
9
+ /** Glob patterns to include config files */
10
+ include?: string[];
11
+ /** Glob patterns to exclude config files */
12
+ exclude?: string[];
13
+ /** Enable verbose logging */
14
+ verbose?: boolean;
15
+ /** Show progress indicator */
16
+ progress?: boolean;
17
+ }
18
+ export interface Engine {
19
+ /** Run validation and return results */
20
+ run(): Promise<ValidationResult>;
21
+ }
22
+ /** Create the validation engine */
23
+ export declare function createEngine(parsers: Parser[], options: EngineOptions): Engine;
24
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/core/engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAW,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAM5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,MAAM;IACrB,wCAAwC;IACxC,GAAG,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAClC;AAED,mCAAmC;AACnC,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAsF9E"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Main orchestration engine
3
+ */
4
+ import fs from 'fs/promises';
5
+ import path from 'path';
6
+ import { discoverConfigs } from './discovery.js';
7
+ import { scanFileTree } from '../filetree/tree.js';
8
+ import { validatePatterns } from '../validator/validator.js';
9
+ /** Create the validation engine */
10
+ export function createEngine(parsers, options) {
11
+ const { paths, include, exclude, verbose = false, progress = false } = options;
12
+ const log = verbose ? (msg) => console.error(`[lostconf] ${msg}`) : () => { };
13
+ return {
14
+ async run() {
15
+ // Step 1: Discover config files
16
+ log('Discovering config files...');
17
+ if (progress)
18
+ process.stderr.write('Discovering config files...');
19
+ const discoveryOptions = { paths, include, exclude };
20
+ const configs = await discoverConfigs(parsers, discoveryOptions);
21
+ log(`Found ${configs.length} config files`);
22
+ if (progress) {
23
+ process.stderr.write('\r\x1b[K'); // Clear line
24
+ process.stderr.write(`Found ${configs.length} config files\n`);
25
+ }
26
+ if (configs.length === 0) {
27
+ return {
28
+ findings: [],
29
+ summary: { total: 0, files: 0 }
30
+ };
31
+ }
32
+ // Step 2: Build file tree
33
+ log('Scanning file tree...');
34
+ if (progress)
35
+ process.stderr.write('Scanning file tree...');
36
+ const basePath = paths.length === 1 ? path.resolve(paths[0]) : process.cwd();
37
+ const tree = await scanFileTree({ paths: [basePath] });
38
+ log(`Found ${tree.files.size} files`);
39
+ if (progress) {
40
+ process.stderr.write('\r\x1b[K'); // Clear line
41
+ process.stderr.write(`Scanned ${tree.files.size} files\n`);
42
+ }
43
+ // Step 3: Parse and validate each config
44
+ const allFindings = [];
45
+ const filesWithFindings = new Set();
46
+ for (let i = 0; i < configs.length; i++) {
47
+ const config = configs[i];
48
+ log(`Processing ${config.path} with ${config.parser.name}...`);
49
+ // Show progress
50
+ if (progress) {
51
+ const percent = Math.round(((i + 1) / configs.length) * 100);
52
+ const shortPath = config.path.length > 60 ? '...' + config.path.slice(-57) : config.path;
53
+ process.stderr.write(`\r\x1b[K`); // Clear line
54
+ process.stderr.write(`Processing configs... [${i + 1}/${configs.length}] ${percent}% - ${shortPath}`);
55
+ }
56
+ try {
57
+ const content = await fs.readFile(config.absolutePath, 'utf-8');
58
+ const patterns = config.parser.parse(config.path, content);
59
+ log(` Found ${patterns.length} patterns`);
60
+ const findings = validatePatterns(config.path, patterns, config.parser.name, tree);
61
+ if (findings.length > 0) {
62
+ filesWithFindings.add(config.path);
63
+ allFindings.push(...findings);
64
+ log(` ${findings.length} stale patterns`);
65
+ }
66
+ }
67
+ catch (err) {
68
+ log(` Error: ${err instanceof Error ? err.message : String(err)}`);
69
+ }
70
+ }
71
+ // Clear progress line
72
+ if (progress) {
73
+ process.stderr.write('\r\x1b[K'); // Clear line
74
+ process.stderr.write(`Processed ${configs.length} config files\n\n`);
75
+ }
76
+ return {
77
+ findings: allFindings,
78
+ summary: {
79
+ total: allFindings.length,
80
+ files: filesWithFindings.size
81
+ }
82
+ };
83
+ }
84
+ };
85
+ }
86
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/core/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Severity classification for stale patterns
3
+ */
4
+ import { Severity } from './types.js';
5
+ /**
6
+ * Determine the severity of a stale pattern finding
7
+ */
8
+ export declare function classifySeverity(pattern: string, parserName: string, configFile: string): Severity;
9
+ /**
10
+ * Get a human-readable description of what each severity means
11
+ */
12
+ export declare function getSeverityDescription(severity: Severity): string;
13
+ /**
14
+ * Get an icon/emoji for a severity level
15
+ */
16
+ export declare function getSeverityIcon(severity: Severity): string;
17
+ /**
18
+ * Get ANSI color code for a severity level (for terminal output)
19
+ */
20
+ export declare function getSeverityColor(severity: Severity): string;
21
+ /**
22
+ * Reset ANSI color
23
+ */
24
+ export declare const RESET_COLOR = "\u001B[0m";
25
+ //# sourceMappingURL=severity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severity.d.ts","sourceRoot":"","sources":["../../src/core/severity.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA4ItC;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,QAAQ,CAyDV;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CASjE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAS1D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAS3D;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,cAAY,CAAC"}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Severity classification for stale patterns
3
+ */
4
+ import { Severity } from './types.js';
5
+ /**
6
+ * Common preventative patterns that are expected to be missing.
7
+ * These are typically in ignore files to protect against future files.
8
+ */
9
+ const COMMON_PREVENTATIVE_PATTERNS = new Set([
10
+ // Build artifacts
11
+ 'node_modules',
12
+ 'dist',
13
+ 'build',
14
+ 'out',
15
+ 'target',
16
+ 'coverage',
17
+ '.nyc_output',
18
+ 'htmlcov',
19
+ '__pycache__',
20
+ '*.pyc',
21
+ '*.pyo',
22
+ '*.so',
23
+ '*.dylib',
24
+ '*.dll',
25
+ '*.class',
26
+ '*.jar',
27
+ '*.war',
28
+ // Version control
29
+ '.git',
30
+ '.svn',
31
+ '.hg',
32
+ // Dependencies
33
+ 'vendor',
34
+ 'bower_components',
35
+ 'jspm_packages',
36
+ '.pnpm-store',
37
+ // Environment
38
+ '.env',
39
+ '.env.local',
40
+ '.env.*.local',
41
+ '.venv',
42
+ 'venv',
43
+ '.tox',
44
+ // IDE/Editor
45
+ '.idea',
46
+ '.vscode',
47
+ '*.swp',
48
+ '*.swo',
49
+ '*~',
50
+ '.DS_Store',
51
+ 'Thumbs.db',
52
+ // Logs
53
+ '*.log',
54
+ 'logs',
55
+ 'npm-debug.log*',
56
+ 'yarn-debug.log*',
57
+ 'yarn-error.log*',
58
+ '.pnpm-debug.log*',
59
+ // Temporary
60
+ 'tmp',
61
+ 'temp',
62
+ '.cache',
63
+ '.temp',
64
+ // Package manager
65
+ 'package-lock.json',
66
+ 'yarn.lock',
67
+ 'pnpm-lock.yaml',
68
+ 'Cargo.lock',
69
+ 'Gemfile.lock',
70
+ 'poetry.lock',
71
+ // Minified files
72
+ '*.min.js',
73
+ '*.min.css',
74
+ '**.min.js',
75
+ '**.min.css'
76
+ ]);
77
+ /**
78
+ * Patterns that are typically glob versions of common preventative patterns
79
+ */
80
+ const COMMON_GLOB_PATTERNS = new Set([
81
+ 'node_modules/**/*',
82
+ 'dist/**/*',
83
+ 'build/**/*',
84
+ 'coverage/**/*',
85
+ 'vendor/**/*',
86
+ 'tmp/**/*',
87
+ '.git/**/*',
88
+ '**/*.log',
89
+ '**/*.min.js',
90
+ '**/*.min.css',
91
+ '**/node_modules',
92
+ '**/dist/**',
93
+ '**/__pycache__'
94
+ ]);
95
+ /**
96
+ * Runtime-generated files that only exist during execution
97
+ */
98
+ const RUNTIME_GENERATED_PATTERNS = new Set([
99
+ 'next-env.d.ts',
100
+ '.next/types/**/*.ts',
101
+ '.next/dev/types/**/*.ts',
102
+ 'COMMIT_EDITMSG',
103
+ 'MERGE_MSG',
104
+ 'FETCH_HEAD'
105
+ ]);
106
+ /**
107
+ * Parsers that typically contain preventative patterns
108
+ */
109
+ const IGNORE_FILE_PARSERS = new Set([
110
+ 'gitignore',
111
+ 'dockerignore',
112
+ 'prettierignore',
113
+ 'eslintignore',
114
+ 'npmignore',
115
+ 'stylelintignore'
116
+ ]);
117
+ /**
118
+ * Context indicators in file paths that suggest test fixtures or templates
119
+ */
120
+ const LOW_PRIORITY_CONTEXTS = [
121
+ '/fixtures/',
122
+ '/__fixtures__/',
123
+ '/test/',
124
+ '/tests/',
125
+ '/__tests__/',
126
+ '/template',
127
+ '/scaffold',
128
+ '/example'
129
+ ];
130
+ /**
131
+ * Determine the severity of a stale pattern finding
132
+ */
133
+ export function classifySeverity(pattern, parserName, configFile) {
134
+ const normalizedPattern = pattern.toLowerCase().trim();
135
+ // Check if it's a test fixture or template context
136
+ const lowerConfigFile = configFile.toLowerCase();
137
+ for (const context of LOW_PRIORITY_CONTEXTS) {
138
+ if (lowerConfigFile.includes(context)) {
139
+ return Severity.MEDIUM;
140
+ }
141
+ }
142
+ // Check if it's a runtime-generated file
143
+ if (RUNTIME_GENERATED_PATTERNS.has(pattern)) {
144
+ return Severity.MEDIUM;
145
+ }
146
+ // Check if it's a common preventative pattern
147
+ if (COMMON_PREVENTATIVE_PATTERNS.has(normalizedPattern)) {
148
+ return Severity.LOW;
149
+ }
150
+ // Check if it's a common glob pattern
151
+ if (COMMON_GLOB_PATTERNS.has(normalizedPattern)) {
152
+ return Severity.LOW;
153
+ }
154
+ // Check if pattern contains common preventative components
155
+ if (normalizedPattern.includes('node_modules') ||
156
+ normalizedPattern.includes('dist/') ||
157
+ normalizedPattern.includes('/dist') ||
158
+ normalizedPattern.includes('build/') ||
159
+ normalizedPattern.includes('/build') ||
160
+ normalizedPattern.includes('coverage') ||
161
+ normalizedPattern.includes('vendor') ||
162
+ normalizedPattern.includes('.git/') ||
163
+ normalizedPattern.includes('/.git') ||
164
+ normalizedPattern.endsWith('.log') ||
165
+ normalizedPattern.endsWith('.min.js') ||
166
+ normalizedPattern.endsWith('.min.css')) {
167
+ return Severity.LOW;
168
+ }
169
+ // Patterns in ignore files are generally preventative
170
+ if (IGNORE_FILE_PARSERS.has(parserName)) {
171
+ // But not all - specific project paths in ignore files could be stale
172
+ // If it looks like a custom project path (not a common pattern), it might be HIGH
173
+ if (normalizedPattern.startsWith('./') || normalizedPattern.startsWith('../')) {
174
+ return Severity.HIGH;
175
+ }
176
+ return Severity.LOW;
177
+ }
178
+ // Default to HIGH severity for other patterns
179
+ // These are project-specific patterns in linter configs that should be reviewed
180
+ return Severity.HIGH;
181
+ }
182
+ /**
183
+ * Get a human-readable description of what each severity means
184
+ */
185
+ export function getSeverityDescription(severity) {
186
+ switch (severity) {
187
+ case Severity.LOW:
188
+ return 'Common preventative pattern (expected to be missing)';
189
+ case Severity.MEDIUM:
190
+ return 'Runtime-generated or context-specific pattern';
191
+ case Severity.HIGH:
192
+ return 'Project-specific pattern (review recommended)';
193
+ }
194
+ }
195
+ /**
196
+ * Get an icon/emoji for a severity level
197
+ */
198
+ export function getSeverityIcon(severity) {
199
+ switch (severity) {
200
+ case Severity.LOW:
201
+ return '🟢';
202
+ case Severity.MEDIUM:
203
+ return '🟡';
204
+ case Severity.HIGH:
205
+ return '🔴';
206
+ }
207
+ }
208
+ /**
209
+ * Get ANSI color code for a severity level (for terminal output)
210
+ */
211
+ export function getSeverityColor(severity) {
212
+ switch (severity) {
213
+ case Severity.LOW:
214
+ return '\x1b[90m'; // Gray
215
+ case Severity.MEDIUM:
216
+ return '\x1b[33m'; // Yellow
217
+ case Severity.HIGH:
218
+ return '\x1b[31m'; // Red
219
+ }
220
+ }
221
+ /**
222
+ * Reset ANSI color
223
+ */
224
+ export const RESET_COLOR = '\x1b[0m';
225
+ //# sourceMappingURL=severity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severity.js","sourceRoot":"","sources":["../../src/core/severity.ts"],"names":[],"mappings":"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"}