@vibe-validate/extractors 0.16.1 → 0.17.0-rc.11

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 (167) hide show
  1. package/dist/extractor-registry.d.ts +103 -0
  2. package/dist/extractor-registry.d.ts.map +1 -0
  3. package/dist/extractor-registry.js +278 -0
  4. package/dist/extractor-registry.js.map +1 -0
  5. package/dist/extractors/ava/index.d.ts +23 -0
  6. package/dist/extractors/ava/index.d.ts.map +1 -0
  7. package/dist/extractors/ava/index.js +507 -0
  8. package/dist/extractors/ava/index.js.map +1 -0
  9. package/dist/extractors/ava/index.test.d.ts +7 -0
  10. package/dist/extractors/ava/index.test.d.ts.map +1 -0
  11. package/dist/extractors/ava/index.test.js +408 -0
  12. package/dist/extractors/ava/index.test.js.map +1 -0
  13. package/dist/extractors/eslint/index.d.ts +18 -0
  14. package/dist/extractors/eslint/index.d.ts.map +1 -0
  15. package/dist/extractors/eslint/index.js +206 -0
  16. package/dist/extractors/eslint/index.js.map +1 -0
  17. package/dist/extractors/eslint/index.test.d.ts +9 -0
  18. package/dist/extractors/eslint/index.test.d.ts.map +1 -0
  19. package/dist/extractors/eslint/index.test.js +191 -0
  20. package/dist/extractors/eslint/index.test.js.map +1 -0
  21. package/dist/extractors/generic/index.d.ts +30 -0
  22. package/dist/extractors/generic/index.d.ts.map +1 -0
  23. package/dist/extractors/generic/index.js +140 -0
  24. package/dist/extractors/generic/index.js.map +1 -0
  25. package/dist/extractors/generic/index.test.d.ts +7 -0
  26. package/dist/extractors/generic/index.test.d.ts.map +1 -0
  27. package/dist/extractors/generic/index.test.js +61 -0
  28. package/dist/extractors/generic/index.test.js.map +1 -0
  29. package/dist/extractors/jasmine/index.d.ts +17 -0
  30. package/dist/extractors/jasmine/index.d.ts.map +1 -0
  31. package/dist/extractors/jasmine/index.js +254 -0
  32. package/dist/extractors/jasmine/index.js.map +1 -0
  33. package/dist/extractors/jasmine/index.test.d.ts +7 -0
  34. package/dist/extractors/jasmine/index.test.d.ts.map +1 -0
  35. package/dist/extractors/jasmine/index.test.js +345 -0
  36. package/dist/extractors/jasmine/index.test.js.map +1 -0
  37. package/dist/extractors/jest/index.d.ts +17 -0
  38. package/dist/extractors/jest/index.d.ts.map +1 -0
  39. package/dist/extractors/jest/index.js +278 -0
  40. package/dist/extractors/jest/index.js.map +1 -0
  41. package/dist/extractors/jest/index.test.d.ts +9 -0
  42. package/dist/extractors/jest/index.test.d.ts.map +1 -0
  43. package/dist/extractors/jest/index.test.js +353 -0
  44. package/dist/extractors/jest/index.test.js.map +1 -0
  45. package/dist/extractors/junit/index.d.ts +18 -0
  46. package/dist/extractors/junit/index.d.ts.map +1 -0
  47. package/dist/extractors/junit/index.js +259 -0
  48. package/dist/extractors/junit/index.js.map +1 -0
  49. package/dist/extractors/junit/index.test.d.ts +7 -0
  50. package/dist/extractors/junit/index.test.d.ts.map +1 -0
  51. package/dist/extractors/junit/index.test.js +341 -0
  52. package/dist/extractors/junit/index.test.js.map +1 -0
  53. package/dist/extractors/maven-checkstyle/index.d.ts +23 -0
  54. package/dist/extractors/maven-checkstyle/index.d.ts.map +1 -0
  55. package/dist/extractors/maven-checkstyle/index.js +263 -0
  56. package/dist/extractors/maven-checkstyle/index.js.map +1 -0
  57. package/dist/extractors/maven-checkstyle/index.test.d.ts +2 -0
  58. package/dist/extractors/maven-checkstyle/index.test.d.ts.map +1 -0
  59. package/dist/extractors/maven-checkstyle/index.test.js +197 -0
  60. package/dist/extractors/maven-checkstyle/index.test.js.map +1 -0
  61. package/dist/extractors/maven-compiler/index.d.ts +23 -0
  62. package/dist/extractors/maven-compiler/index.d.ts.map +1 -0
  63. package/dist/extractors/maven-compiler/index.js +271 -0
  64. package/dist/extractors/maven-compiler/index.js.map +1 -0
  65. package/dist/extractors/maven-compiler/index.test.d.ts +2 -0
  66. package/dist/extractors/maven-compiler/index.test.d.ts.map +1 -0
  67. package/dist/extractors/maven-compiler/index.test.js +189 -0
  68. package/dist/extractors/maven-compiler/index.test.js.map +1 -0
  69. package/dist/extractors/maven-surefire/index.d.ts +23 -0
  70. package/dist/extractors/maven-surefire/index.d.ts.map +1 -0
  71. package/dist/extractors/maven-surefire/index.js +292 -0
  72. package/dist/extractors/maven-surefire/index.js.map +1 -0
  73. package/dist/extractors/maven-surefire/index.test.d.ts +2 -0
  74. package/dist/extractors/maven-surefire/index.test.d.ts.map +1 -0
  75. package/dist/extractors/maven-surefire/index.test.js +169 -0
  76. package/dist/extractors/maven-surefire/index.test.js.map +1 -0
  77. package/dist/extractors/mocha/index.d.ts +17 -0
  78. package/dist/extractors/mocha/index.d.ts.map +1 -0
  79. package/dist/extractors/mocha/index.js +241 -0
  80. package/dist/extractors/mocha/index.js.map +1 -0
  81. package/dist/extractors/mocha/index.test.d.ts +7 -0
  82. package/dist/extractors/mocha/index.test.d.ts.map +1 -0
  83. package/dist/extractors/mocha/index.test.js +300 -0
  84. package/dist/extractors/mocha/index.test.js.map +1 -0
  85. package/dist/extractors/playwright/index.d.ts +17 -0
  86. package/dist/extractors/playwright/index.d.ts.map +1 -0
  87. package/dist/extractors/playwright/index.js +320 -0
  88. package/dist/extractors/playwright/index.js.map +1 -0
  89. package/dist/extractors/playwright/index.test.d.ts +7 -0
  90. package/dist/extractors/playwright/index.test.d.ts.map +1 -0
  91. package/dist/extractors/playwright/index.test.js +274 -0
  92. package/dist/extractors/playwright/index.test.js.map +1 -0
  93. package/dist/extractors/tap/index.d.ts +23 -0
  94. package/dist/extractors/tap/index.d.ts.map +1 -0
  95. package/dist/extractors/tap/index.js +352 -0
  96. package/dist/extractors/tap/index.js.map +1 -0
  97. package/dist/extractors/tap/index.test.d.ts +7 -0
  98. package/dist/extractors/tap/index.test.d.ts.map +1 -0
  99. package/dist/extractors/tap/index.test.js +100 -0
  100. package/dist/extractors/tap/index.test.js.map +1 -0
  101. package/dist/extractors/typescript/index.d.ts +17 -0
  102. package/dist/extractors/typescript/index.d.ts.map +1 -0
  103. package/dist/extractors/typescript/index.js +150 -0
  104. package/dist/extractors/typescript/index.js.map +1 -0
  105. package/dist/extractors/typescript/index.test.d.ts +9 -0
  106. package/dist/extractors/typescript/index.test.d.ts.map +1 -0
  107. package/dist/extractors/typescript/index.test.js +177 -0
  108. package/dist/extractors/typescript/index.test.js.map +1 -0
  109. package/dist/extractors/vitest/index.d.ts +17 -0
  110. package/dist/extractors/vitest/index.d.ts.map +1 -0
  111. package/dist/extractors/vitest/index.js +564 -0
  112. package/dist/extractors/vitest/index.js.map +1 -0
  113. package/dist/extractors/vitest/index.test.d.ts +9 -0
  114. package/dist/extractors/vitest/index.test.d.ts.map +1 -0
  115. package/dist/extractors/vitest/index.test.js +373 -0
  116. package/dist/extractors/vitest/index.test.js.map +1 -0
  117. package/dist/index.d.ts +27 -11
  118. package/dist/index.d.ts.map +1 -1
  119. package/dist/index.js +27 -11
  120. package/dist/index.js.map +1 -1
  121. package/dist/maven-checkstyle-extractor.d.ts +20 -0
  122. package/dist/maven-checkstyle-extractor.d.ts.map +1 -0
  123. package/dist/maven-checkstyle-extractor.js +208 -0
  124. package/dist/maven-checkstyle-extractor.js.map +1 -0
  125. package/dist/maven-compiler-extractor.d.ts +20 -0
  126. package/dist/maven-compiler-extractor.d.ts.map +1 -0
  127. package/dist/maven-compiler-extractor.js +218 -0
  128. package/dist/maven-compiler-extractor.js.map +1 -0
  129. package/dist/maven-surefire-extractor.d.ts +20 -0
  130. package/dist/maven-surefire-extractor.d.ts.map +1 -0
  131. package/dist/maven-surefire-extractor.js +228 -0
  132. package/dist/maven-surefire-extractor.js.map +1 -0
  133. package/dist/maven-utils.d.ts +24 -0
  134. package/dist/maven-utils.d.ts.map +1 -0
  135. package/dist/maven-utils.js +36 -0
  136. package/dist/maven-utils.js.map +1 -0
  137. package/dist/plugin-loader.d.ts +82 -0
  138. package/dist/plugin-loader.d.ts.map +1 -0
  139. package/dist/plugin-loader.js +201 -0
  140. package/dist/plugin-loader.js.map +1 -0
  141. package/dist/result-schema.d.ts +59 -9
  142. package/dist/result-schema.d.ts.map +1 -1
  143. package/dist/result-schema.js +3 -19
  144. package/dist/result-schema.js.map +1 -1
  145. package/dist/sandbox.d.ts +161 -0
  146. package/dist/sandbox.d.ts.map +1 -0
  147. package/dist/sandbox.js +254 -0
  148. package/dist/sandbox.js.map +1 -0
  149. package/dist/sandbox.test.d.ts +8 -0
  150. package/dist/sandbox.test.d.ts.map +1 -0
  151. package/dist/sandbox.test.js +395 -0
  152. package/dist/sandbox.test.js.map +1 -0
  153. package/dist/sandboxed-extractor.d.ts +46 -0
  154. package/dist/sandboxed-extractor.d.ts.map +1 -0
  155. package/dist/sandboxed-extractor.js +172 -0
  156. package/dist/sandboxed-extractor.js.map +1 -0
  157. package/dist/sandboxed-extractor.test.d.ts +5 -0
  158. package/dist/sandboxed-extractor.test.d.ts.map +1 -0
  159. package/dist/sandboxed-extractor.test.js +346 -0
  160. package/dist/sandboxed-extractor.test.js.map +1 -0
  161. package/dist/smart-extractor.d.ts +22 -10
  162. package/dist/smart-extractor.d.ts.map +1 -1
  163. package/dist/smart-extractor.js +116 -163
  164. package/dist/smart-extractor.js.map +1 -1
  165. package/dist/types.d.ts +94 -0
  166. package/dist/types.d.ts.map +1 -1
  167. package/package.json +3 -2
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Maven Surefire/Failsafe (JUnit) error extractor
3
+ *
4
+ * Extracts test failures from Maven Surefire and Failsafe plugin output.
5
+ * Supports JUnit 4, JUnit 5, and AssertJ assertion failures.
6
+ */
7
+ import { MAX_ERRORS_IN_ARRAY } from './result-schema.js';
8
+ /* eslint-disable sonarjs/slow-regex -- All regexes safe: Maven Surefire output is structured with limited line length */
9
+ const SUREFIRE_PATTERNS = {
10
+ // [ERROR] Tests run: 12, Failures: 8, Errors: 3, Skipped: 1
11
+ testSummary: /^\[ERROR\]\s+Tests run:\s+(\d+),\s+Failures:\s+(\d+),\s+Errors:\s+(\d+)/,
12
+ // [ERROR] com.example.FooTest.testBar:42 Expected 5 but was 3
13
+ errorShort: /^\[ERROR\]\s+([^:]+)\.([^:]+):(\d+)\s+(\w+(?:Error|Exception|Failure))?\s*(.+)$/,
14
+ // [ERROR] com.example.FooTest.testBar -- Time elapsed: 0.123 s <<< FAILURE!
15
+ errorHeader: /^\[ERROR\]\s+([^.]+)\.([^\s]+)\s+.*<<<\s+(FAILURE|ERROR)!/,
16
+ // Exception type line
17
+ exceptionType: /^([\w.]+(?:Error|Exception|AssertionError|AssertionFailedError)):\s*(.*)$/,
18
+ // "at package.Class.method(File.java:123)"
19
+ stackTraceLine: /^\s+at\s+([^(]+)\(([^:]+):(\d+)\)/,
20
+ };
21
+ /* eslint-enable sonarjs/slow-regex */
22
+ /**
23
+ * Detects if output is from Maven Surefire/Failsafe
24
+ */
25
+ export function detectMavenSurefire(output) {
26
+ const lines = output.split('\n');
27
+ let score = 0;
28
+ const foundPatterns = [];
29
+ for (const line of lines) {
30
+ if (line.includes('maven-surefire-plugin') ?? line.includes('maven-failsafe-plugin')) {
31
+ score += 40;
32
+ foundPatterns.push('Maven test plugin reference');
33
+ }
34
+ if (SUREFIRE_PATTERNS.testSummary.exec(line)) {
35
+ score += 40;
36
+ foundPatterns.push('Test summary (Tests run, Failures, Errors)');
37
+ }
38
+ if (line.includes('<<< FAILURE!') || line.includes('<<< ERROR!')) {
39
+ score += 20;
40
+ foundPatterns.push('Test failure markers');
41
+ }
42
+ if (line.includes('[ERROR] Failures:') || line.includes('[ERROR] Errors:')) {
43
+ score += 15;
44
+ foundPatterns.push('Test failure section headers');
45
+ }
46
+ if (/AssertionError|AssertionFailedError/.exec(line)) {
47
+ score += 10;
48
+ foundPatterns.push('JUnit assertion errors');
49
+ }
50
+ }
51
+ // Determine reason based on score
52
+ let reason;
53
+ if (score >= 70) {
54
+ reason = 'Maven Surefire/Failsafe test output detected';
55
+ }
56
+ else if (score >= 40) {
57
+ reason = 'Possible Maven test output';
58
+ }
59
+ else {
60
+ reason = 'Not Maven test output';
61
+ }
62
+ return {
63
+ confidence: Math.min(score, 100),
64
+ patterns: foundPatterns,
65
+ reason,
66
+ };
67
+ }
68
+ /**
69
+ * Extracts test failures from Maven Surefire/Failsafe output
70
+ */
71
+ // eslint-disable-next-line sonarjs/cognitive-complexity -- Complexity 43 acceptable for Maven Surefire parser (handles multiple test output formats with state machine)
72
+ export function extractMavenSurefire(output, command) {
73
+ const detection = detectMavenSurefire(output);
74
+ if (detection.confidence < 40) {
75
+ return {
76
+ summary: 'Not Maven test output',
77
+ totalErrors: 0,
78
+ errors: [],
79
+ metadata: {
80
+ detection: {
81
+ extractor: 'maven-surefire',
82
+ confidence: detection.confidence,
83
+ patterns: detection.patterns,
84
+ reason: detection.reason,
85
+ },
86
+ confidence: detection.confidence,
87
+ completeness: 100,
88
+ issues: [],
89
+ },
90
+ };
91
+ }
92
+ const failures = [];
93
+ const lines = output.split('\n');
94
+ // Extract test summary for metadata
95
+ let totalFailures = 0;
96
+ let totalErrors = 0;
97
+ for (const line of lines) {
98
+ const summaryMatch = SUREFIRE_PATTERNS.testSummary.exec(line);
99
+ if (summaryMatch) {
100
+ // totalTests would be summaryMatch[1] if needed
101
+ totalFailures = Number.parseInt(summaryMatch[2], 10);
102
+ totalErrors = Number.parseInt(summaryMatch[3], 10);
103
+ }
104
+ }
105
+ // Parse failure details
106
+ let currentFailure = null;
107
+ let inStackTrace = false;
108
+ for (const line of lines) {
109
+ // Check for error header: [ERROR] Class.method -- Time elapsed: ... <<< FAILURE!
110
+ const headerMatch = SUREFIRE_PATTERNS.errorHeader.exec(line);
111
+ if (headerMatch) {
112
+ // Save previous failure if exists
113
+ if (currentFailure?.testClass && currentFailure?.testMethod) {
114
+ failures.push(currentFailure);
115
+ }
116
+ const [, testClass, testMethod, errorType] = headerMatch;
117
+ currentFailure = {
118
+ testClass: testClass.trim(),
119
+ testMethod: testMethod.trim(),
120
+ errorType: errorType,
121
+ message: '',
122
+ stackTrace: [],
123
+ };
124
+ inStackTrace = false;
125
+ continue;
126
+ }
127
+ // Check for short error format: [ERROR] Class.method:line Message
128
+ const shortMatch = SUREFIRE_PATTERNS.errorShort.exec(line);
129
+ if (shortMatch && !currentFailure) {
130
+ const [, fullMethod, testMethod, lineStr, exceptionType, message] = shortMatch;
131
+ const testClass = fullMethod.substring(0, fullMethod.lastIndexOf('.'));
132
+ failures.push({
133
+ testClass,
134
+ testMethod,
135
+ line: Number.parseInt(lineStr, 10),
136
+ errorType: 'FAILURE',
137
+ exceptionType: exceptionType ?? undefined,
138
+ message: message.trim(),
139
+ });
140
+ continue;
141
+ }
142
+ // Parse exception type and message
143
+ if (currentFailure && !currentFailure.message) {
144
+ const exceptionMatch = SUREFIRE_PATTERNS.exceptionType.exec(line);
145
+ if (exceptionMatch) {
146
+ const [, exceptionType, message] = exceptionMatch;
147
+ currentFailure.exceptionType = exceptionType;
148
+ currentFailure.message = message.trim();
149
+ inStackTrace = true;
150
+ continue;
151
+ }
152
+ }
153
+ // Parse stack trace
154
+ if (currentFailure && inStackTrace) {
155
+ const stackMatch = SUREFIRE_PATTERNS.stackTraceLine.exec(line);
156
+ if (stackMatch) {
157
+ const [, method, file, lineStr] = stackMatch;
158
+ // Extract file and line from first stack frame
159
+ if (!currentFailure.file && file.endsWith('.java')) {
160
+ currentFailure.file = file;
161
+ currentFailure.line = Number.parseInt(lineStr, 10);
162
+ }
163
+ currentFailure.stackTrace = currentFailure.stackTrace ?? [];
164
+ currentFailure.stackTrace.push(` at ${method}(${file}:${lineStr})`);
165
+ // Limit stack trace depth
166
+ if (currentFailure.stackTrace.length >= 3) {
167
+ inStackTrace = false;
168
+ }
169
+ }
170
+ }
171
+ // End of error block
172
+ if (line.trim() === '' && currentFailure) {
173
+ inStackTrace = false;
174
+ }
175
+ }
176
+ // Save last failure
177
+ if (currentFailure?.testClass && currentFailure?.testMethod) {
178
+ failures.push(currentFailure);
179
+ }
180
+ // Convert to FormattedError format
181
+ const errors = failures.slice(0, MAX_ERRORS_IN_ARRAY).map((f) => {
182
+ const testId = `${f.testClass}.${f.testMethod}`;
183
+ let message = f.message ?? 'Test failed';
184
+ // Include exception type if available
185
+ if (f.exceptionType && !message.includes(f.exceptionType)) {
186
+ message = `${f.exceptionType}: ${message}`;
187
+ }
188
+ // Add stack trace preview (first line only)
189
+ if (f.stackTrace && f.stackTrace.length > 0) {
190
+ message += `\n${f.stackTrace[0]}`;
191
+ }
192
+ return {
193
+ file: f.file ?? `${f.testClass.replaceAll('.', '/')}.java`,
194
+ line: f.line,
195
+ message: `Test: ${testId}\n${message}`,
196
+ };
197
+ });
198
+ const failureCount = totalFailures ?? failures.filter((f) => f.errorType === 'FAILURE').length;
199
+ const errorCount = totalErrors ?? failures.filter((f) => f.errorType === 'ERROR').length;
200
+ const summary = `${failureCount + errorCount} test failure(s): ${failureCount} failures, ${errorCount} errors`;
201
+ // Generate guidance
202
+ const guidance = failures.length > 0
203
+ ? `Fix test failures. Run ${command ?? 'mvn test'} to see full details.`
204
+ : undefined;
205
+ // Create error summary
206
+ const errorSummary = errors.length > 0
207
+ ? errors.map((e, i) => `[Test ${i + 1}/${errors.length}] ${e.file}:${e.line ?? '?'}\n${e.message}`).join('\n\n')
208
+ : undefined;
209
+ return {
210
+ summary,
211
+ totalErrors: failures.length,
212
+ errors,
213
+ guidance,
214
+ errorSummary,
215
+ metadata: {
216
+ detection: {
217
+ extractor: 'maven-surefire',
218
+ confidence: detection.confidence,
219
+ patterns: detection.patterns,
220
+ reason: detection.reason,
221
+ },
222
+ confidence: 95,
223
+ completeness: 90,
224
+ issues: failures.length > 20 ? ['Many test failures - output may be truncated'] : [],
225
+ },
226
+ };
227
+ }
228
+ //# sourceMappingURL=maven-surefire-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maven-surefire-extractor.js","sourceRoot":"","sources":["../src/maven-surefire-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Maven Utilities
3
+ *
4
+ * Shared utility functions for Maven extractors (Checkstyle, Surefire, Compiler)
5
+ *
6
+ * @package @vibe-validate/extractors
7
+ */
8
+ /**
9
+ * Extract relative path from absolute path
10
+ *
11
+ * Attempts to extract the meaningful source path from absolute file paths
12
+ * by finding common Java/Kotlin source roots.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * extractRelativePath('/Users/name/project/src/main/java/com/example/Foo.java')
17
+ * // => 'src/main/java/com/example/Foo.java'
18
+ * ```
19
+ *
20
+ * @param absolutePath - Absolute file path
21
+ * @returns Relative path from source root, or fallback to last few segments
22
+ */
23
+ export declare function extractRelativePath(absolutePath: string): string;
24
+ //# sourceMappingURL=maven-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maven-utils.d.ts","sourceRoot":"","sources":["../src/maven-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAchE"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Maven Utilities
3
+ *
4
+ * Shared utility functions for Maven extractors (Checkstyle, Surefire, Compiler)
5
+ *
6
+ * @package @vibe-validate/extractors
7
+ */
8
+ /**
9
+ * Extract relative path from absolute path
10
+ *
11
+ * Attempts to extract the meaningful source path from absolute file paths
12
+ * by finding common Java/Kotlin source roots.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * extractRelativePath('/Users/name/project/src/main/java/com/example/Foo.java')
17
+ * // => 'src/main/java/com/example/Foo.java'
18
+ * ```
19
+ *
20
+ * @param absolutePath - Absolute file path
21
+ * @returns Relative path from source root, or fallback to last few segments
22
+ */
23
+ export function extractRelativePath(absolutePath) {
24
+ // Common Java/Kotlin source roots in Maven projects
25
+ const sourceRoots = ['src/main/java', 'src/test/java', 'src/main/kotlin', 'src/test/kotlin'];
26
+ for (const root of sourceRoots) {
27
+ const index = absolutePath.indexOf(root);
28
+ if (index !== -1) {
29
+ return absolutePath.slice(index);
30
+ }
31
+ }
32
+ // Fallback: return last few path segments (enough to identify the file)
33
+ const segments = absolutePath.split('/');
34
+ return segments.slice(-3).join('/');
35
+ }
36
+ //# sourceMappingURL=maven-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maven-utils.js","sourceRoot":"","sources":["../src/maven-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB;IACtD,oDAAoD;IACpD,MAAM,WAAW,GAAG,CAAC,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;IAE7F,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACjB,OAAO,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Plugin Loader
3
+ *
4
+ * Discovers and loads external extractor plugins from filesystem and npm packages.
5
+ * Provides security validation and interface compliance checking.
6
+ *
7
+ * @package @vibe-validate/extractors
8
+ */
9
+ import type { ExtractorPlugin } from './types.js';
10
+ /**
11
+ * Plugin source configuration
12
+ */
13
+ export type PluginSource = {
14
+ type: 'path';
15
+ path: string;
16
+ } | {
17
+ type: 'package';
18
+ package: string;
19
+ };
20
+ /**
21
+ * Plugin discovery configuration
22
+ */
23
+ export interface PluginDiscoveryConfig {
24
+ /** Explicit plugin sources from config */
25
+ extractors?: PluginSource[];
26
+ /** Base directory for auto-discovery (default: process.cwd()) */
27
+ baseDir?: string;
28
+ }
29
+ /**
30
+ * Plugin validation error
31
+ */
32
+ export declare class PluginValidationError extends Error {
33
+ readonly _pluginSource: string;
34
+ constructor(message: string, _pluginSource: string);
35
+ }
36
+ /**
37
+ * Load a single plugin from a source
38
+ *
39
+ * @param source - Plugin source (file path or npm package)
40
+ * @returns Validated extractor plugin
41
+ * @throws PluginValidationError if plugin is invalid
42
+ */
43
+ export declare function loadPlugin(source: PluginSource): Promise<ExtractorPlugin>;
44
+ /**
45
+ * Discover and load all plugins
46
+ *
47
+ * - Loads explicitly configured plugins from config
48
+ * - Auto-discovers plugins from vibe-validate-local-plugins/ directory
49
+ * - Skips invalid plugins with warnings (fail-safe)
50
+ *
51
+ * @param config - Plugin discovery configuration
52
+ * @returns Array of validated plugins
53
+ */
54
+ export declare function discoverPlugins(config?: PluginDiscoveryConfig): Promise<ExtractorPlugin[]>;
55
+ /**
56
+ * Validate that an object conforms to ExtractorPlugin interface
57
+ *
58
+ * @param plugin - Object to validate
59
+ * @param source - Plugin source (for error messages)
60
+ * @throws PluginValidationError if validation fails
61
+ */
62
+ export declare function validatePluginInterface(plugin: unknown, source: string): asserts plugin is ExtractorPlugin;
63
+ /**
64
+ * Register plugins dynamically with the extractor registry
65
+ *
66
+ * This function will be used to add external plugins to EXTRACTOR_REGISTRY
67
+ * at runtime after discovery.
68
+ *
69
+ * @param plugins - Array of validated plugins to register
70
+ * @returns Array of extractor descriptors added to registry
71
+ */
72
+ export declare function registerPlugins(plugins: ExtractorPlugin[]): Array<{
73
+ name: string;
74
+ priority: number;
75
+ detect: (_output: string) => {
76
+ confidence: number;
77
+ patterns: string[];
78
+ reason: string;
79
+ };
80
+ extract: (_output: string) => unknown;
81
+ }>;
82
+ //# sourceMappingURL=plugin-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../src/plugin-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;GAEG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;IAC5B,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;aAG5B,aAAa,EAAE,MAAM;gBADrC,OAAO,EAAE,MAAM,EACC,aAAa,EAAE,MAAM;CAKxC;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CA4B/E;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,MAAM,GAAE,qBAA0B,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAcpG;AA6ED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,eAAe,CA2C1G;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxF,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC,CAAC,CAOD"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Plugin Loader
3
+ *
4
+ * Discovers and loads external extractor plugins from filesystem and npm packages.
5
+ * Provides security validation and interface compliance checking.
6
+ *
7
+ * @package @vibe-validate/extractors
8
+ */
9
+ import { pathToFileURL } from 'node:url';
10
+ import { access, readdir } from 'node:fs/promises';
11
+ import { join, resolve } from 'node:path';
12
+ /**
13
+ * Plugin validation error
14
+ */
15
+ export class PluginValidationError extends Error {
16
+ _pluginSource;
17
+ constructor(message, _pluginSource) {
18
+ super(message);
19
+ this._pluginSource = _pluginSource;
20
+ this.name = 'PluginValidationError';
21
+ }
22
+ }
23
+ /**
24
+ * Load a single plugin from a source
25
+ *
26
+ * @param source - Plugin source (file path or npm package)
27
+ * @returns Validated extractor plugin
28
+ * @throws PluginValidationError if plugin is invalid
29
+ */
30
+ export async function loadPlugin(source) {
31
+ let plugin;
32
+ let pluginPath;
33
+ try {
34
+ if (source.type === 'path') {
35
+ // Load from file path
36
+ pluginPath = resolve(source.path);
37
+ const fileUrl = pathToFileURL(pluginPath).href;
38
+ const module = await import(fileUrl);
39
+ plugin = module.default ?? module;
40
+ }
41
+ else {
42
+ // Load from npm package
43
+ pluginPath = source.package;
44
+ const module = await import(source.package);
45
+ plugin = module.default ?? module;
46
+ }
47
+ }
48
+ catch (error) {
49
+ throw new PluginValidationError(`Failed to load plugin: ${error instanceof Error ? error.message : String(error)}`, source.type === 'path' ? source.path : source.package);
50
+ }
51
+ // Validate plugin interface
52
+ validatePluginInterface(plugin, pluginPath);
53
+ return plugin;
54
+ }
55
+ /**
56
+ * Discover and load all plugins
57
+ *
58
+ * - Loads explicitly configured plugins from config
59
+ * - Auto-discovers plugins from vibe-validate-local-plugins/ directory
60
+ * - Skips invalid plugins with warnings (fail-safe)
61
+ *
62
+ * @param config - Plugin discovery configuration
63
+ * @returns Array of validated plugins
64
+ */
65
+ export async function discoverPlugins(config = {}) {
66
+ const plugins = [];
67
+ const errors = [];
68
+ // 1. Load explicitly configured plugins
69
+ await loadConfiguredPlugins(config, plugins, errors);
70
+ // 2. Auto-discover from local plugins directory
71
+ await autoDiscoverLocalPlugins(config, plugins, errors);
72
+ // Log warnings for failed plugins (fail-safe behavior)
73
+ logPluginErrors(errors);
74
+ return plugins;
75
+ }
76
+ /**
77
+ * Load plugins explicitly configured in config
78
+ */
79
+ async function loadConfiguredPlugins(config, plugins, errors) {
80
+ if (!config.extractors || config.extractors.length === 0) {
81
+ return;
82
+ }
83
+ for (const source of config.extractors) {
84
+ try {
85
+ const plugin = await loadPlugin(source);
86
+ plugins.push(plugin);
87
+ }
88
+ catch (error) {
89
+ const sourceStr = source.type === 'path' ? source.path : source.package;
90
+ errors.push({
91
+ source: sourceStr,
92
+ error: error instanceof Error ? error.message : String(error),
93
+ });
94
+ }
95
+ }
96
+ }
97
+ /**
98
+ * Auto-discover plugins from local plugins directory
99
+ */
100
+ async function autoDiscoverLocalPlugins(config, plugins, errors) {
101
+ const baseDir = config.baseDir ?? process.cwd();
102
+ const localPluginsDir = join(baseDir, 'vibe-validate-local-plugins');
103
+ try {
104
+ await access(localPluginsDir);
105
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- Safe: localPluginsDir computed from validated config.baseDir (defaults to process.cwd()), no path traversal risk
106
+ const entries = await readdir(localPluginsDir, { withFileTypes: true });
107
+ for (const entry of entries) {
108
+ if (entry.isFile() && (entry.name.endsWith('.js') || entry.name.endsWith('.mjs'))) {
109
+ const pluginPath = join(localPluginsDir, entry.name);
110
+ try {
111
+ const plugin = await loadPlugin({ type: 'path', path: pluginPath });
112
+ plugins.push(plugin);
113
+ }
114
+ catch (error) {
115
+ errors.push({
116
+ source: pluginPath,
117
+ error: error instanceof Error ? error.message : String(error),
118
+ });
119
+ }
120
+ }
121
+ }
122
+ }
123
+ catch {
124
+ // Directory doesn't exist - that's fine, just skip auto-discovery
125
+ }
126
+ }
127
+ /**
128
+ * Log plugin loading errors
129
+ */
130
+ function logPluginErrors(errors) {
131
+ if (errors.length === 0) {
132
+ return;
133
+ }
134
+ console.warn('⚠️ Some plugins failed to load:');
135
+ for (const { source, error } of errors) {
136
+ console.warn(` - ${source}: ${error}`);
137
+ }
138
+ }
139
+ /**
140
+ * Validate that an object conforms to ExtractorPlugin interface
141
+ *
142
+ * @param plugin - Object to validate
143
+ * @param source - Plugin source (for error messages)
144
+ * @throws PluginValidationError if validation fails
145
+ */
146
+ export function validatePluginInterface(plugin, source) {
147
+ if (!plugin || typeof plugin !== 'object') {
148
+ throw new PluginValidationError('Plugin must be an object', source);
149
+ }
150
+ const p = plugin;
151
+ // Validate metadata
152
+ if (!p.metadata || typeof p.metadata !== 'object') {
153
+ throw new PluginValidationError('Plugin missing required metadata field', source);
154
+ }
155
+ const metadata = p.metadata;
156
+ if (!metadata.name || typeof metadata.name !== 'string') {
157
+ throw new PluginValidationError('Plugin metadata missing name', source);
158
+ }
159
+ if (!metadata.version || typeof metadata.version !== 'string') {
160
+ throw new PluginValidationError('Plugin metadata missing version', source);
161
+ }
162
+ if (!metadata.description || typeof metadata.description !== 'string') {
163
+ throw new PluginValidationError('Plugin metadata missing description', source);
164
+ }
165
+ // Validate required functions
166
+ if (typeof p.detect !== 'function') {
167
+ throw new PluginValidationError('Plugin missing required detect function', source);
168
+ }
169
+ if (typeof p.extract !== 'function') {
170
+ throw new PluginValidationError('Plugin missing required extract function', source);
171
+ }
172
+ // Validate priority
173
+ if (typeof p.priority !== 'number') {
174
+ throw new PluginValidationError('Plugin missing required priority field', source);
175
+ }
176
+ if (p.priority < 0 || p.priority > 100) {
177
+ throw new PluginValidationError('Priority must be between 0 and 100', source);
178
+ }
179
+ // Validate samples array
180
+ if (!Array.isArray(p.samples)) {
181
+ throw new PluginValidationError('Plugin missing required samples array', source);
182
+ }
183
+ }
184
+ /**
185
+ * Register plugins dynamically with the extractor registry
186
+ *
187
+ * This function will be used to add external plugins to EXTRACTOR_REGISTRY
188
+ * at runtime after discovery.
189
+ *
190
+ * @param plugins - Array of validated plugins to register
191
+ * @returns Array of extractor descriptors added to registry
192
+ */
193
+ export function registerPlugins(plugins) {
194
+ return plugins.map(plugin => ({
195
+ name: plugin.metadata.name,
196
+ priority: plugin.priority,
197
+ detect: plugin.detect,
198
+ extract: plugin.extract,
199
+ }));
200
+ }
201
+ //# sourceMappingURL=plugin-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../src/plugin-loader.ts"],"names":[],"mappings":"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"}