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
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Core type definitions for lostconf
3
+ */
4
+ /** Pattern types that can be extracted from config files */
5
+ export declare enum PatternType {
6
+ PATH = "path",
7
+ GLOB = "glob",
8
+ REGEX = "regex"
9
+ }
10
+ /** Reasons why a pattern is considered stale */
11
+ export type StaleReason = 'no_matches' | 'file_not_found' | 'invalid_pattern';
12
+ /** Severity levels for stale patterns */
13
+ export declare enum Severity {
14
+ /** Common preventative patterns (node_modules, dist, *.log) */
15
+ LOW = "low",
16
+ /** Runtime-generated or context-specific patterns (next-env.d.ts, test fixtures) */
17
+ MEDIUM = "medium",
18
+ /** Potentially stale project-specific patterns that should be reviewed */
19
+ HIGH = "high"
20
+ }
21
+ /** A pattern extracted from a config file */
22
+ export interface Pattern {
23
+ /** The raw pattern value */
24
+ value: string;
25
+ /** Type of pattern */
26
+ type: PatternType;
27
+ /** Line number in the config file (1-indexed) */
28
+ line: number;
29
+ /** Column number (optional, 1-indexed) */
30
+ column?: number;
31
+ /** Whether this is a negated pattern (e.g., !pattern) */
32
+ negated?: boolean;
33
+ /** Base path for relative patterns */
34
+ basePath?: string;
35
+ }
36
+ /** A finding representing a stale pattern */
37
+ export interface Finding {
38
+ /** Config file containing the stale pattern */
39
+ file: string;
40
+ /** Line number (1-indexed) */
41
+ line: number;
42
+ /** Column number (optional, 1-indexed) */
43
+ column?: number;
44
+ /** The stale pattern */
45
+ pattern: string;
46
+ /** Type of pattern */
47
+ type: PatternType;
48
+ /** Why the pattern is stale */
49
+ reason: StaleReason;
50
+ /** Name of the parser that found this */
51
+ parser: string;
52
+ /** Severity level of this finding */
53
+ severity: Severity;
54
+ }
55
+ /** Summary of validation results */
56
+ export interface Summary {
57
+ /** Total number of stale patterns found */
58
+ total: number;
59
+ /** Number of config files with stale patterns */
60
+ files: number;
61
+ }
62
+ /** Complete validation result */
63
+ export interface ValidationResult {
64
+ findings: Finding[];
65
+ summary: Summary;
66
+ }
67
+ /** CLI options */
68
+ export interface CliOptions {
69
+ format: 'text' | 'json' | 'sarif';
70
+ output?: string;
71
+ include?: string[];
72
+ exclude?: string[];
73
+ failOnStale: boolean;
74
+ quiet: boolean;
75
+ verbose: boolean;
76
+ }
77
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,4DAA4D;AAC5D,oBAAY,WAAW;IACrB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,KAAK,UAAU;CAChB;AAED,gDAAgD;AAChD,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAE9E,yCAAyC;AACzC,oBAAY,QAAQ;IAClB,+DAA+D;IAC/D,GAAG,QAAQ;IACX,oFAAoF;IACpF,MAAM,WAAW;IACjB,0EAA0E;IAC1E,IAAI,SAAS;CACd;AAED,6CAA6C;AAC7C,MAAM,WAAW,OAAO;IACtB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,6CAA6C;AAC7C,MAAM,WAAW,OAAO;IACtB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,+BAA+B;IAC/B,MAAM,EAAE,WAAW,CAAC;IACpB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,oCAAoC;AACpC,MAAM,WAAW,OAAO;IACtB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,iCAAiC;AACjC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,kBAAkB;AAClB,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Core type definitions for lostconf
3
+ */
4
+ /** Pattern types that can be extracted from config files */
5
+ export var PatternType;
6
+ (function (PatternType) {
7
+ PatternType["PATH"] = "path";
8
+ PatternType["GLOB"] = "glob";
9
+ PatternType["REGEX"] = "regex";
10
+ })(PatternType || (PatternType = {}));
11
+ /** Severity levels for stale patterns */
12
+ export var Severity;
13
+ (function (Severity) {
14
+ /** Common preventative patterns (node_modules, dist, *.log) */
15
+ Severity["LOW"] = "low";
16
+ /** Runtime-generated or context-specific patterns (next-env.d.ts, test fixtures) */
17
+ Severity["MEDIUM"] = "medium";
18
+ /** Potentially stale project-specific patterns that should be reviewed */
19
+ Severity["HIGH"] = "high";
20
+ })(Severity || (Severity = {}));
21
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,4DAA4D;AAC5D,MAAM,CAAN,IAAY,WAIX;AAJD,WAAY,WAAW;IACrB,4BAAa,CAAA;IACb,4BAAa,CAAA;IACb,8BAAe,CAAA;AACjB,CAAC,EAJW,WAAW,KAAX,WAAW,QAItB;AAKD,yCAAyC;AACzC,MAAM,CAAN,IAAY,QAOX;AAPD,WAAY,QAAQ;IAClB,+DAA+D;IAC/D,uBAAW,CAAA;IACX,oFAAoF;IACpF,6BAAiB,CAAA;IACjB,0EAA0E;IAC1E,yBAAa,CAAA;AACf,CAAC,EAPW,QAAQ,KAAR,QAAQ,QAOnB"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * File tree scanner using fast-glob
3
+ */
4
+ export interface ScanOptions {
5
+ /** Directories to scan */
6
+ paths: string[];
7
+ /** Glob patterns to exclude */
8
+ ignore?: string[];
9
+ /** Follow symlinks */
10
+ followSymlinks?: boolean;
11
+ }
12
+ export interface FileTree {
13
+ /** All files in the tree (relative paths) */
14
+ files: Set<string>;
15
+ /** All directories in the tree (relative paths) */
16
+ directories: Set<string>;
17
+ /** Base path for the tree */
18
+ basePath: string;
19
+ }
20
+ /** Scan a directory and build a file tree */
21
+ export declare function scanFileTree(options: ScanOptions): Promise<FileTree>;
22
+ /** Check if a path exists in the file tree */
23
+ export declare function pathExists(tree: FileTree, targetPath: string): boolean;
24
+ /** Get all files matching a glob pattern */
25
+ export declare function matchGlob(tree: FileTree, pattern: string): string[];
26
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/filetree/scanner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,WAAW,WAAW;IAC1B,0BAA0B;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,sBAAsB;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,6CAA6C;IAC7C,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,mDAAmD;IACnD,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAiBD,6CAA6C;AAC7C,wBAAsB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmC1E;AAED,8CAA8C;AAC9C,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAGtE;AAED,4CAA4C;AAC5C,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAanE"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * File tree scanner using fast-glob
3
+ */
4
+ import fg from 'fast-glob';
5
+ import path from 'path';
6
+ /** Default ignore patterns */
7
+ const DEFAULT_IGNORE = [
8
+ '**/node_modules/**',
9
+ '**/.git/**',
10
+ '**/dist/**',
11
+ '**/build/**',
12
+ '**/.next/**',
13
+ '**/coverage/**',
14
+ '**/__pycache__/**',
15
+ '**/.venv/**',
16
+ '**/venv/**',
17
+ '**/.tox/**',
18
+ '**/vendor/**'
19
+ ];
20
+ /** Scan a directory and build a file tree */
21
+ export async function scanFileTree(options) {
22
+ const { paths, ignore = [], followSymlinks = false } = options;
23
+ const basePath = paths.length === 1 ? path.resolve(paths[0]) : process.cwd();
24
+ const allIgnore = [...DEFAULT_IGNORE, ...ignore];
25
+ // Scan for all files
26
+ const files = await fg('**/*', {
27
+ cwd: basePath,
28
+ dot: true,
29
+ onlyFiles: true,
30
+ ignore: allIgnore,
31
+ followSymbolicLinks: followSymlinks
32
+ });
33
+ // Build directory set from file paths
34
+ const directories = new Set();
35
+ for (const file of files) {
36
+ const dir = path.dirname(file);
37
+ if (dir !== '.') {
38
+ // Add all parent directories
39
+ const parts = dir.split('/');
40
+ let current = '';
41
+ for (const part of parts) {
42
+ current = current ? `${current}/${part}` : part;
43
+ directories.add(current);
44
+ }
45
+ }
46
+ }
47
+ return {
48
+ files: new Set(files),
49
+ directories,
50
+ basePath
51
+ };
52
+ }
53
+ /** Check if a path exists in the file tree */
54
+ export function pathExists(tree, targetPath) {
55
+ const normalized = targetPath.replace(/\\/g, '/').replace(/^\.\//, '');
56
+ return tree.files.has(normalized) || tree.directories.has(normalized);
57
+ }
58
+ /** Get all files matching a glob pattern */
59
+ export function matchGlob(tree, pattern) {
60
+ // This is handled by the validator using micromatch
61
+ // This function is just for direct lookups
62
+ const normalized = pattern.replace(/\\/g, '/').replace(/^\.\//, '');
63
+ const matches = [];
64
+ for (const file of tree.files) {
65
+ if (file === normalized || file.startsWith(normalized + '/')) {
66
+ matches.push(file);
67
+ }
68
+ }
69
+ return matches;
70
+ }
71
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/filetree/scanner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,WAAW,CAAC;AAC3B,OAAO,IAAI,MAAM,MAAM,CAAC;AAoBxB,8BAA8B;AAC9B,MAAM,cAAc,GAAG;IACrB,oBAAoB;IACpB,YAAY;IACZ,YAAY;IACZ,aAAa;IACb,aAAa;IACb,gBAAgB;IAChB,mBAAmB;IACnB,aAAa;IACb,YAAY;IACZ,YAAY;IACZ,cAAc;CACf,CAAC;AAEF,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAoB;IACrD,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE,EAAE,cAAc,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAC/D,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAE7E,MAAM,SAAS,GAAG,CAAC,GAAG,cAAc,EAAE,GAAG,MAAM,CAAC,CAAC;IAEjD,qBAAqB;IACrB,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE;QAC7B,GAAG,EAAE,QAAQ;QACb,GAAG,EAAE,IAAI;QACT,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,SAAS;QACjB,mBAAmB,EAAE,cAAc;KACpC,CAAC,CAAC;IAEH,sCAAsC;IACtC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAChB,6BAA6B;YAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,OAAO,GAAG,EAAE,CAAC;YACjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBAChD,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC;QACrB,WAAW;QACX,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,UAAkB;IAC3D,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACvE,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACxE,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,SAAS,CAAC,IAAc,EAAE,OAAe;IACvD,oDAAoD;IACpD,2CAA2C;IAC3C,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACpE,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC,EAAE,CAAC;YAC7D,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * File tree data structure and utilities
3
+ */
4
+ export { FileTree, scanFileTree, pathExists, matchGlob } from './scanner.js';
5
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/filetree/tree.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * File tree data structure and utilities
3
+ */
4
+ export { scanFileTree, pathExists, matchGlob } from './scanner.js';
5
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/filetree/tree.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAY,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * lostconf - A meta-linter that detects stale references in configuration files
3
+ */
4
+ export { PatternType, Pattern, Finding, StaleReason, Summary, ValidationResult, CliOptions } from './core/types.js';
5
+ export { createEngine, Engine, EngineOptions } from './core/engine.js';
6
+ export { Parser, ParserFactory } from './plugin/types.js';
7
+ export { PluginRegistry, registry } from './plugin/registry.js';
8
+ export { getBuiltinParsers, gitignoreParser, dockerignoreParser, eslintIgnoreParser, prettierIgnoreParser, pyprojectParser, rubocopParser, createIgnoreParser } from './parsers/index.js';
9
+ export { Formatter, FormatterFactory } from './output/formatter.js';
10
+ export { createTextFormatter, textFormatter } from './output/text.js';
11
+ export { createJsonFormatter, jsonFormatter } from './output/json.js';
12
+ export { createSarifFormatter, sarifFormatter } from './output/sarif.js';
13
+ export { scanFileTree, pathExists, FileTree, ScanOptions } from './filetree/scanner.js';
14
+ export { validatePattern, validatePatterns, ValidatorOptions } from './validator/validator.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,WAAW,EACX,OAAO,EACP,OAAO,EACP,WAAW,EACX,OAAO,EACP,gBAAgB,EAChB,UAAU,EACX,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGvE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhE,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGzE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGxF,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * lostconf - A meta-linter that detects stale references in configuration files
3
+ */
4
+ // Core types
5
+ export { PatternType } from './core/types.js';
6
+ // Engine
7
+ export { createEngine } from './core/engine.js';
8
+ export { PluginRegistry, registry } from './plugin/registry.js';
9
+ // Parsers
10
+ export { getBuiltinParsers, gitignoreParser, dockerignoreParser, eslintIgnoreParser, prettierIgnoreParser, pyprojectParser, rubocopParser, createIgnoreParser } from './parsers/index.js';
11
+ export { createTextFormatter, textFormatter } from './output/text.js';
12
+ export { createJsonFormatter, jsonFormatter } from './output/json.js';
13
+ export { createSarifFormatter, sarifFormatter } from './output/sarif.js';
14
+ // File tree
15
+ export { scanFileTree, pathExists } from './filetree/scanner.js';
16
+ // Validator
17
+ export { validatePattern, validatePatterns } from './validator/validator.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,aAAa;AACb,OAAO,EACL,WAAW,EAOZ,MAAM,iBAAiB,CAAC;AAEzB,SAAS;AACT,OAAO,EAAE,YAAY,EAAyB,MAAM,kBAAkB,CAAC;AAIvE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhE,UAAU;AACV,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEzE,YAAY;AACZ,OAAO,EAAE,YAAY,EAAE,UAAU,EAAyB,MAAM,uBAAuB,CAAC;AAExF,YAAY;AACZ,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAoB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Formatter interface
3
+ */
4
+ import type { ValidationResult } from '../core/types.js';
5
+ /** Output formatter interface */
6
+ export interface Formatter {
7
+ /** Format the validation result */
8
+ format(result: ValidationResult): string;
9
+ }
10
+ /** Formatter factory type */
11
+ export type FormatterFactory = () => Formatter;
12
+ //# sourceMappingURL=formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/output/formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,iCAAiC;AACjC,MAAM,WAAW,SAAS;IACxB,mCAAmC;IACnC,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAAC;CAC1C;AAED,6BAA6B;AAC7B,MAAM,MAAM,gBAAgB,GAAG,MAAM,SAAS,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Formatter interface
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/output/formatter.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * JSON output formatter
3
+ */
4
+ import type { Formatter } from './formatter.js';
5
+ /** JSON formatter */
6
+ export declare const jsonFormatter: Formatter;
7
+ /** Create JSON formatter */
8
+ export declare function createJsonFormatter(): Formatter;
9
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/output/json.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,qBAAqB;AACrB,eAAO,MAAM,aAAa,EAAE,SAI3B,CAAC;AAEF,4BAA4B;AAC5B,wBAAgB,mBAAmB,IAAI,SAAS,CAE/C"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * JSON output formatter
3
+ */
4
+ /** JSON formatter */
5
+ export const jsonFormatter = {
6
+ format(result) {
7
+ return JSON.stringify(result, null, 2);
8
+ }
9
+ };
10
+ /** Create JSON formatter */
11
+ export function createJsonFormatter() {
12
+ return jsonFormatter;
13
+ }
14
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/output/json.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,qBAAqB;AACrB,MAAM,CAAC,MAAM,aAAa,GAAc;IACtC,MAAM,CAAC,MAAwB;QAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;CACF,CAAC;AAEF,4BAA4B;AAC5B,MAAM,UAAU,mBAAmB;IACjC,OAAO,aAAa,CAAC;AACvB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * SARIF output formatter for IDE integration
3
+ */
4
+ import type { Formatter } from './formatter.js';
5
+ /** SARIF formatter */
6
+ export declare const sarifFormatter: Formatter;
7
+ /** Create SARIF formatter */
8
+ export declare function createSarifFormatter(): Formatter;
9
+ //# sourceMappingURL=sarif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../src/output/sarif.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAkGhD,sBAAsB;AACtB,eAAO,MAAM,cAAc,EAAE,SAuB5B,CAAC;AAEF,6BAA6B;AAC7B,wBAAgB,oBAAoB,IAAI,SAAS,CAEhD"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * SARIF output formatter for IDE integration
3
+ */
4
+ /** SARIF rule IDs */
5
+ const RULE_IDS = {
6
+ no_matches: 'lostconf/no-matches',
7
+ file_not_found: 'lostconf/file-not-found',
8
+ invalid_pattern: 'lostconf/invalid-pattern'
9
+ };
10
+ /** SARIF rule descriptions */
11
+ const RULE_DESCRIPTIONS = {
12
+ no_matches: {
13
+ name: 'No matches',
14
+ description: 'Pattern does not match any files in the codebase'
15
+ },
16
+ file_not_found: {
17
+ name: 'File not found',
18
+ description: 'Referenced file or directory does not exist'
19
+ },
20
+ invalid_pattern: {
21
+ name: 'Invalid pattern',
22
+ description: 'Pattern syntax is invalid'
23
+ }
24
+ };
25
+ /** Convert a finding to a SARIF result */
26
+ function findingToResult(finding) {
27
+ return {
28
+ ruleId: RULE_IDS[finding.reason],
29
+ message: {
30
+ text: `Stale pattern "${finding.pattern}" - ${RULE_DESCRIPTIONS[finding.reason].description.toLowerCase()}`
31
+ },
32
+ locations: [
33
+ {
34
+ physicalLocation: {
35
+ artifactLocation: { uri: finding.file },
36
+ region: {
37
+ startLine: finding.line,
38
+ ...(finding.column && { startColumn: finding.column })
39
+ }
40
+ }
41
+ }
42
+ ],
43
+ level: 'warning'
44
+ };
45
+ }
46
+ /** Get unique rules from findings */
47
+ function getRules(findings) {
48
+ const reasons = new Set(findings.map((f) => f.reason));
49
+ return Array.from(reasons).map((reason) => ({
50
+ id: RULE_IDS[reason],
51
+ name: RULE_DESCRIPTIONS[reason].name,
52
+ shortDescription: { text: RULE_DESCRIPTIONS[reason].name },
53
+ fullDescription: { text: RULE_DESCRIPTIONS[reason].description },
54
+ defaultConfiguration: { level: 'warning' }
55
+ }));
56
+ }
57
+ /** SARIF formatter */
58
+ export const sarifFormatter = {
59
+ format(result) {
60
+ const output = {
61
+ $schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
62
+ version: '2.1.0',
63
+ runs: [
64
+ {
65
+ tool: {
66
+ driver: {
67
+ name: 'lostconf',
68
+ version: '0.1.0',
69
+ informationUri: 'https://github.com/lostconf/lostconf',
70
+ rules: getRules(result.findings)
71
+ }
72
+ },
73
+ results: result.findings.map(findingToResult)
74
+ }
75
+ ]
76
+ };
77
+ return JSON.stringify(output, null, 2);
78
+ }
79
+ };
80
+ /** Create SARIF formatter */
81
+ export function createSarifFormatter() {
82
+ return sarifFormatter;
83
+ }
84
+ //# sourceMappingURL=sarif.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.js","sourceRoot":"","sources":["../../src/output/sarif.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,qBAAqB;AACrB,MAAM,QAAQ,GAAgC;IAC5C,UAAU,EAAE,qBAAqB;IACjC,cAAc,EAAE,yBAAyB;IACzC,eAAe,EAAE,0BAA0B;CAC5C,CAAC;AAEF,8BAA8B;AAC9B,MAAM,iBAAiB,GAA+D;IACpF,UAAU,EAAE;QACV,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,kDAAkD;KAChE;IACD,cAAc,EAAE;QACd,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,6CAA6C;KAC3D;IACD,eAAe,EAAE;QACf,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,2BAA2B;KACzC;CACF,CAAC;AAyCF,0CAA0C;AAC1C,SAAS,eAAe,CAAC,OAAgB;IACvC,OAAO;QACL,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;QAChC,OAAO,EAAE;YACP,IAAI,EAAE,kBAAkB,OAAO,CAAC,OAAO,OAAO,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE;SAC5G;QACD,SAAS,EAAE;YACT;gBACE,gBAAgB,EAAE;oBAChB,gBAAgB,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE;oBACvC,MAAM,EAAE;wBACN,SAAS,EAAE,OAAO,CAAC,IAAI;wBACvB,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;qBACvD;iBACF;aACF;SACF;QACD,KAAK,EAAE,SAAS;KACjB,CAAC;AACJ,CAAC;AAED,qCAAqC;AACrC,SAAS,QAAQ,CAAC,QAAmB;IACnC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC1C,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC;QACpB,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI;QACpC,gBAAgB,EAAE,EAAE,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;QAC1D,eAAe,EAAE,EAAE,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE;QAChE,oBAAoB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;KAC3C,CAAC,CAAC,CAAC;AACN,CAAC;AAED,sBAAsB;AACtB,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,MAAM,CAAC,MAAwB;QAC7B,MAAM,MAAM,GAAgB;YAC1B,OAAO,EACL,gGAAgG;YAClG,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE;gBACJ;oBACE,IAAI,EAAE;wBACJ,MAAM,EAAE;4BACN,IAAI,EAAE,UAAU;4BAChB,OAAO,EAAE,OAAO;4BAChB,cAAc,EAAE,sCAAsC;4BACtD,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;yBACjC;qBACF;oBACD,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC;iBAC9C;aACF;SACF,CAAC;QAEF,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;CACF,CAAC;AAEF,6BAA6B;AAC7B,MAAM,UAAU,oBAAoB;IAClC,OAAO,cAAc,CAAC;AACxB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Text output formatter
3
+ */
4
+ import type { Formatter } from './formatter.js';
5
+ /** Text formatter */
6
+ export declare const textFormatter: Formatter;
7
+ /** Create text formatter */
8
+ export declare function createTextFormatter(): Formatter;
9
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/output/text.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAwChD,qBAAqB;AACrB,eAAO,MAAM,aAAa,EAAE,SAqD3B,CAAC;AAEF,4BAA4B;AAC5B,wBAAgB,mBAAmB,IAAI,SAAS,CAE/C"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Text output formatter
3
+ */
4
+ import chalk from 'chalk';
5
+ import { Severity } from '../core/types.js';
6
+ /** Format reason for display */
7
+ function formatReason(reason) {
8
+ switch (reason) {
9
+ case 'no_matches':
10
+ return 'no matches';
11
+ case 'file_not_found':
12
+ return 'file not found';
13
+ case 'invalid_pattern':
14
+ return 'invalid pattern';
15
+ }
16
+ }
17
+ /** Get severity icon */
18
+ function getSeverityIcon(severity) {
19
+ switch (severity) {
20
+ case Severity.LOW:
21
+ return chalk.gray('○');
22
+ case Severity.MEDIUM:
23
+ return chalk.yellow('●');
24
+ case Severity.HIGH:
25
+ return chalk.red('●');
26
+ }
27
+ }
28
+ /** Format a single finding */
29
+ function formatFinding(finding) {
30
+ const severityIcon = getSeverityIcon(finding.severity);
31
+ const location = chalk.cyan(`${finding.file}:${finding.line}`);
32
+ const pattern = chalk.yellow(finding.pattern);
33
+ const reason = chalk.dim(formatReason(finding.reason));
34
+ // Calculate padding for alignment
35
+ const locationStr = `${finding.file}:${finding.line}`;
36
+ const padding = Math.max(0, 25 - locationStr.length);
37
+ return `${severityIcon} ${location}${' '.repeat(padding)}${pattern.padEnd(30)}${reason}`;
38
+ }
39
+ /** Text formatter */
40
+ export const textFormatter = {
41
+ format(result) {
42
+ const lines = [];
43
+ if (result.findings.length === 0) {
44
+ lines.push(chalk.green('No stale patterns found'));
45
+ return lines.join('\n');
46
+ }
47
+ // Group findings by file
48
+ const byFile = new Map();
49
+ for (const finding of result.findings) {
50
+ const existing = byFile.get(finding.file) ?? [];
51
+ existing.push(finding);
52
+ byFile.set(finding.file, existing);
53
+ }
54
+ // Output findings
55
+ for (const [_file, findings] of byFile) {
56
+ for (const finding of findings) {
57
+ lines.push(formatFinding(finding));
58
+ }
59
+ }
60
+ // Summary with severity breakdown
61
+ lines.push('');
62
+ const severityCounts = {
63
+ [Severity.HIGH]: result.findings.filter((f) => f.severity === Severity.HIGH).length,
64
+ [Severity.MEDIUM]: result.findings.filter((f) => f.severity === Severity.MEDIUM).length,
65
+ [Severity.LOW]: result.findings.filter((f) => f.severity === Severity.LOW).length
66
+ };
67
+ const totalText = result.summary.total === 1 ? 'pattern' : 'patterns';
68
+ const filesText = result.summary.files === 1 ? 'file' : 'files';
69
+ const parts = [];
70
+ if (severityCounts[Severity.HIGH] > 0) {
71
+ parts.push(chalk.red(`${severityCounts[Severity.HIGH]} high`));
72
+ }
73
+ if (severityCounts[Severity.MEDIUM] > 0) {
74
+ parts.push(chalk.yellow(`${severityCounts[Severity.MEDIUM]} medium`));
75
+ }
76
+ if (severityCounts[Severity.LOW] > 0) {
77
+ parts.push(chalk.gray(`${severityCounts[Severity.LOW]} low`));
78
+ }
79
+ lines.push(`Found ${result.summary.total} stale ${totalText} in ${result.summary.files} ${filesText} (${parts.join(', ')})`);
80
+ return lines.join('\n');
81
+ }
82
+ };
83
+ /** Create text formatter */
84
+ export function createTextFormatter() {
85
+ return textFormatter;
86
+ }
87
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/output/text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Parser for Bandit configuration files
3
+ * Bandit is a security linter for Python
4
+ */
5
+ import type { Parser } from '../plugin/types.js';
6
+ /** Bandit .bandit file parser */
7
+ export declare const banditParser: Parser;
8
+ //# sourceMappingURL=bandit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bandit.d.ts","sourceRoot":"","sources":["../../src/parsers/bandit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AA0EjD,iCAAiC;AACjC,eAAO,MAAM,YAAY,EAAE,MAI1B,CAAC"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Parser for Bandit configuration files
3
+ * Bandit is a security linter for Python
4
+ */
5
+ import { parse as parseYaml } from 'yaml';
6
+ import { PatternType } from '../core/types.js';
7
+ import { isGlobPattern } from '../validator/glob.js';
8
+ /** Parse .bandit file */
9
+ function parseBandit(_filename, content) {
10
+ const patterns = [];
11
+ let config;
12
+ try {
13
+ config = parseYaml(content);
14
+ }
15
+ catch {
16
+ return patterns;
17
+ }
18
+ // Build line map for accurate line numbers
19
+ const lineMap = buildLineMap(content);
20
+ // Extract patterns from exclude_dirs and exclude
21
+ const sections = [config.exclude_dirs, config.exclude, config.tests];
22
+ for (const section of sections) {
23
+ if (!section || !Array.isArray(section))
24
+ continue;
25
+ for (const pattern of section) {
26
+ if (typeof pattern !== 'string')
27
+ continue;
28
+ const lineInfo = lineMap.get(pattern);
29
+ const line = lineInfo?.line ?? 1;
30
+ const column = lineInfo?.column;
31
+ const type = isGlobPattern(pattern) ? PatternType.GLOB : PatternType.PATH;
32
+ patterns.push({
33
+ value: pattern,
34
+ type,
35
+ line,
36
+ column
37
+ });
38
+ }
39
+ }
40
+ return patterns;
41
+ }
42
+ /** Build a map of string values to their line numbers */
43
+ function buildLineMap(content) {
44
+ const map = new Map();
45
+ const lines = content.split('\n');
46
+ for (let i = 0; i < lines.length; i++) {
47
+ const line = lines[i];
48
+ const lineNum = i + 1;
49
+ // Match quoted or unquoted values in YAML
50
+ const matches = line.matchAll(/[-:]\s*["']?([^"'\n]+)["']?/g);
51
+ for (const match of matches) {
52
+ const value = match[1]?.trim();
53
+ if (value && !map.has(value)) {
54
+ map.set(value, { line: lineNum, column: (match.index ?? 0) + 1 });
55
+ }
56
+ }
57
+ }
58
+ return map;
59
+ }
60
+ /** Bandit .bandit file parser */
61
+ export const banditParser = {
62
+ name: 'bandit',
63
+ filePatterns: ['.bandit', '**/.bandit'],
64
+ parse: parseBandit
65
+ };
66
+ //# sourceMappingURL=bandit.js.map