@vibe-validate/extractors 0.17.6 → 0.18.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 (46) hide show
  1. package/dist/extractors/ava/index.test.js +17 -17
  2. package/dist/extractors/ava/index.test.js.map +1 -1
  3. package/dist/extractors/eslint/index.d.ts.map +1 -1
  4. package/dist/extractors/eslint/index.js +5 -2
  5. package/dist/extractors/eslint/index.js.map +1 -1
  6. package/dist/extractors/eslint/index.test.js +115 -47
  7. package/dist/extractors/eslint/index.test.js.map +1 -1
  8. package/dist/extractors/generic/index.test.js +34 -0
  9. package/dist/extractors/generic/index.test.js.map +1 -1
  10. package/dist/extractors/jasmine/index.test.js +37 -30
  11. package/dist/extractors/jasmine/index.test.js.map +1 -1
  12. package/dist/extractors/jest/index.d.ts.map +1 -1
  13. package/dist/extractors/jest/index.js +1 -4
  14. package/dist/extractors/jest/index.js.map +1 -1
  15. package/dist/extractors/jest/index.test.js +45 -44
  16. package/dist/extractors/jest/index.test.js.map +1 -1
  17. package/dist/extractors/junit/index.test.js +30 -33
  18. package/dist/extractors/junit/index.test.js.map +1 -1
  19. package/dist/extractors/maven-checkstyle/index.test.js +32 -29
  20. package/dist/extractors/maven-checkstyle/index.test.js.map +1 -1
  21. package/dist/extractors/maven-compiler/index.test.js +31 -26
  22. package/dist/extractors/maven-compiler/index.test.js.map +1 -1
  23. package/dist/extractors/maven-surefire/index.test.js +26 -24
  24. package/dist/extractors/maven-surefire/index.test.js.map +1 -1
  25. package/dist/extractors/mocha/index.test.js +27 -22
  26. package/dist/extractors/mocha/index.test.js.map +1 -1
  27. package/dist/extractors/playwright/index.test.js +26 -21
  28. package/dist/extractors/playwright/index.test.js.map +1 -1
  29. package/dist/extractors/tap/index.test.js +13 -10
  30. package/dist/extractors/tap/index.test.js.map +1 -1
  31. package/dist/extractors/typescript/index.test.js +52 -43
  32. package/dist/extractors/typescript/index.test.js.map +1 -1
  33. package/dist/extractors/vitest/index.d.ts.map +1 -1
  34. package/dist/extractors/vitest/index.js +71 -30
  35. package/dist/extractors/vitest/index.js.map +1 -1
  36. package/dist/extractors/vitest/index.test.js +103 -59
  37. package/dist/extractors/vitest/index.test.js.map +1 -1
  38. package/dist/test/helpers/extractor-test-helpers.d.ts +196 -0
  39. package/dist/test/helpers/extractor-test-helpers.d.ts.map +1 -0
  40. package/dist/test/helpers/extractor-test-helpers.js +238 -0
  41. package/dist/test/helpers/extractor-test-helpers.js.map +1 -0
  42. package/dist/test/helpers/max-errors-helper.d.ts +62 -0
  43. package/dist/test/helpers/max-errors-helper.d.ts.map +1 -0
  44. package/dist/test/helpers/max-errors-helper.js +75 -0
  45. package/dist/test/helpers/max-errors-helper.js.map +1 -0
  46. package/package.json +6 -2
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Shared test helpers for error extractor plugins
3
+ *
4
+ * Eliminates duplication across extractor tests by providing common assertion
5
+ * patterns for detection, extraction, metadata, and error object validation.
6
+ *
7
+ * @package @vibe-validate/extractors
8
+ */
9
+ import { expect } from 'vitest';
10
+ /**
11
+ * Verify plugin metadata matches expected values
12
+ *
13
+ * Reduces duplication in plugin metadata tests by consolidating common
14
+ * assertions for name, priority, hints, and tags.
15
+ *
16
+ * @param plugin - The extractor plugin to test
17
+ * @param expected - Expected metadata values
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * expectPluginMetadata(vitestPlugin, {
22
+ * name: 'vitest',
23
+ * priority: 85,
24
+ * requiredHints: [],
25
+ * anyOfHints: ['FAIL', 'test.ts', '❯'],
26
+ * });
27
+ * ```
28
+ */
29
+ export function expectPluginMetadata(plugin, expected) {
30
+ expect(plugin.metadata.name).toBe(expected.name);
31
+ expect(plugin.priority).toBe(expected.priority);
32
+ if (expected.requiredHints !== undefined) {
33
+ if (expected.requiredHints.length === 0) {
34
+ expect(plugin.hints?.required ?? []).toEqual([]);
35
+ }
36
+ else {
37
+ for (const hint of expected.requiredHints) {
38
+ expect(plugin.hints?.required).toContain(hint);
39
+ }
40
+ }
41
+ }
42
+ if (expected.anyOfHints !== undefined) {
43
+ for (const hint of expected.anyOfHints) {
44
+ expect(plugin.hints?.anyOf).toContain(hint);
45
+ }
46
+ }
47
+ if (expected.tags !== undefined) {
48
+ for (const tag of expected.tags) {
49
+ expect(plugin.metadata.tags).toContain(tag);
50
+ }
51
+ }
52
+ }
53
+ /**
54
+ * Verify detection result matches expected confidence and patterns
55
+ *
56
+ * Reduces duplication in detect() tests by consolidating confidence checks,
57
+ * pattern verification, and reason validation.
58
+ *
59
+ * @param plugin - The extractor plugin
60
+ * @param output - Test output string to detect
61
+ * @param expected - Expected detection results
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * // Exact confidence
66
+ * expectDetection(vitestPlugin, sampleOutput, {
67
+ * confidence: 90,
68
+ * patterns: ['Vitest', 'test failure marker'],
69
+ * reasonContains: 'Vitest'
70
+ * });
71
+ *
72
+ * // Confidence range
73
+ * expectDetection(vitestPlugin, sampleOutput, {
74
+ * confidence: { min: 70, max: 95 },
75
+ * reasonContains: 'Vitest'
76
+ * });
77
+ *
78
+ * // No detection
79
+ * expectDetection(vitestPlugin, 'random text', {
80
+ * confidence: 0
81
+ * });
82
+ * ```
83
+ */
84
+ export function expectDetection(plugin, output, expected) {
85
+ const result = plugin.detect(output);
86
+ // Check confidence (exact value or range)
87
+ if (typeof expected.confidence === 'number') {
88
+ expect(result.confidence).toBe(expected.confidence);
89
+ }
90
+ else {
91
+ if (expected.confidence.min !== undefined) {
92
+ expect(result.confidence).toBeGreaterThanOrEqual(expected.confidence.min);
93
+ }
94
+ if (expected.confidence.max !== undefined) {
95
+ expect(result.confidence).toBeLessThanOrEqual(expected.confidence.max);
96
+ }
97
+ }
98
+ // Check patterns
99
+ if (expected.patterns !== undefined) {
100
+ for (const pattern of expected.patterns) {
101
+ expect(result.patterns).toContain(pattern);
102
+ }
103
+ }
104
+ // Check reason
105
+ if (expected.reasonContains !== undefined) {
106
+ expect(result.reason).toContain(expected.reasonContains);
107
+ }
108
+ }
109
+ /**
110
+ * Verify extraction result structure matches expected values
111
+ *
112
+ * Reduces duplication in extract() tests by consolidating common assertions
113
+ * for error count, summary, guidance, and errorSummary.
114
+ *
115
+ * @param result - Extract result to verify
116
+ * @param expected - Expected result structure
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * const result = extract(output);
121
+ * expectExtractionResult(result, {
122
+ * errorCount: 3,
123
+ * summaryPattern: '3 test failure(s)',
124
+ * guidanceContains: ['Fix each failing test'],
125
+ * errorSummaryContains: ['Test 1/3']
126
+ * });
127
+ *
128
+ * // With regex
129
+ * expectExtractionResult(result, {
130
+ * errorCount: 5,
131
+ * summaryPattern: /5 (test|error)/,
132
+ * });
133
+ * ```
134
+ */
135
+ export function expectExtractionResult(result, expected) {
136
+ expect(result.errors).toHaveLength(expected.errorCount);
137
+ expect(result.totalErrors).toBe(expected.errorCount);
138
+ if (expected.summaryPattern !== undefined) {
139
+ if (typeof expected.summaryPattern === 'string') {
140
+ expect(result.summary).toBe(expected.summaryPattern);
141
+ }
142
+ else {
143
+ expect(result.summary).toMatch(expected.summaryPattern);
144
+ }
145
+ }
146
+ if (expected.guidanceContains !== undefined) {
147
+ for (const text of expected.guidanceContains) {
148
+ expect(result.guidance).toContain(text);
149
+ }
150
+ }
151
+ if (expected.errorSummaryContains !== undefined) {
152
+ for (const text of expected.errorSummaryContains) {
153
+ expect(result.errorSummary).toContain(text);
154
+ }
155
+ }
156
+ }
157
+ /**
158
+ * Verify empty or no-match output behavior
159
+ *
160
+ * Reduces duplication in edge case tests by consolidating assertions for
161
+ * empty string and non-matching output scenarios.
162
+ *
163
+ * @param extractFn - Extract function to test
164
+ * @param expectedSummary - Expected summary for empty/no-match cases (string or regex)
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * expectEmptyExtraction(vitestPlugin.extract, '0 test failure(s)');
169
+ * expectEmptyExtraction(eslintPlugin.extract, '0 ESLint error(s), 0 warning(s)');
170
+ * expectEmptyExtraction(junitPlugin.extract, /0 test.*failed/);
171
+ * ```
172
+ */
173
+ export function expectEmptyExtraction(extractFn, expectedSummary) {
174
+ const result = extractFn('');
175
+ expect(result.errors).toHaveLength(0);
176
+ expect(result.totalErrors).toBe(0);
177
+ if (typeof expectedSummary === 'string') {
178
+ expect(result.summary).toBe(expectedSummary);
179
+ }
180
+ else {
181
+ expect(result.summary).toMatch(expectedSummary);
182
+ }
183
+ }
184
+ /**
185
+ * Verify individual error object fields match expected values
186
+ *
187
+ * Reduces duplication in error validation tests by consolidating assertions
188
+ * for file, line, column, message, severity, and code fields.
189
+ *
190
+ * @param error - The error object to verify
191
+ * @param expected - Expected field values
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * // Basic fields
196
+ * expectErrorObject(result.errors[0], {
197
+ * file: 'test/example.test.ts',
198
+ * line: 57,
199
+ * column: 30,
200
+ * messageContains: 'expected 3000 to be 9999'
201
+ * });
202
+ *
203
+ * // Multiple message fragments
204
+ * expectErrorObject(result.errors[0], {
205
+ * file: 'src/index.ts',
206
+ * line: 42,
207
+ * messageContains: ['Type error', 'not assignable'],
208
+ * severity: 'error',
209
+ * code: 'TS2322'
210
+ * });
211
+ * ```
212
+ */
213
+ export function expectErrorObject(error, expected) {
214
+ if (expected.file !== undefined) {
215
+ expect(error.file).toBe(expected.file);
216
+ }
217
+ if (expected.line !== undefined) {
218
+ expect(error.line).toBe(expected.line);
219
+ }
220
+ if (expected.column !== undefined) {
221
+ expect(error.column).toBe(expected.column);
222
+ }
223
+ if (expected.messageContains !== undefined) {
224
+ const messages = Array.isArray(expected.messageContains)
225
+ ? expected.messageContains
226
+ : [expected.messageContains];
227
+ for (const msg of messages) {
228
+ expect(error.message).toContain(msg);
229
+ }
230
+ }
231
+ if (expected.severity !== undefined) {
232
+ expect(error.severity).toBe(expected.severity);
233
+ }
234
+ if (expected.code !== undefined) {
235
+ expect(error.code).toBe(expected.code);
236
+ }
237
+ }
238
+ //# sourceMappingURL=extractor-test-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor-test-helpers.js","sourceRoot":"","sources":["../../../src/test/helpers/extractor-test-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Shared test helper for MAX_ERRORS_IN_ARRAY truncation behavior
3
+ *
4
+ * Eliminates duplication across extractor tests that verify error array truncation.
5
+ *
6
+ * @package @vibe-validate/extractors
7
+ */
8
+ import type { ErrorExtractorResult } from '../../types.js';
9
+ /**
10
+ * Options for MAX_ERRORS_IN_ARRAY truncation assertion
11
+ */
12
+ interface MaxErrorsOptions {
13
+ /** Expected totalErrors count (e.g., 15) */
14
+ totalCount: number;
15
+ /** Expected value for first error (file or message content) */
16
+ firstError: string;
17
+ /** Expected value for last kept error at index 9 (file or message content) */
18
+ lastTruncatedError: string;
19
+ /** Regex or string to match in summary (e.g., "15 test failure(s)") */
20
+ summaryPattern: string | RegExp;
21
+ /** Field to check ('file' or 'message'). Defaults to 'file' */
22
+ checkField?: 'file' | 'message';
23
+ /** For 'message' field, use contains check instead of exact match */
24
+ messageContains?: boolean;
25
+ }
26
+ /**
27
+ * Assert MAX_ERRORS_IN_ARRAY truncation behavior
28
+ *
29
+ * Verifies that extractors correctly:
30
+ * 1. Preserve full error count in totalErrors
31
+ * 2. Truncate errors array to MAX_ERRORS_IN_ARRAY
32
+ * 3. Return first N errors in order
33
+ * 4. Include full count in summary
34
+ *
35
+ * @param result - Extraction result to verify
36
+ * @param options - Assertion options
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // Check file field (default)
41
+ * const result = extract(fifteenErrors);
42
+ * await expectMaxErrorsTruncation(result, {
43
+ * totalCount: 15,
44
+ * firstError: 'file1.ts',
45
+ * lastTruncatedError: 'file10.ts',
46
+ * summaryPattern: '15 test failure(s)'
47
+ * });
48
+ *
49
+ * // Check message field with contains
50
+ * await expectMaxErrorsTruncation(result, {
51
+ * totalCount: 15,
52
+ * firstError: 'test 1',
53
+ * lastTruncatedError: 'test 10',
54
+ * summaryPattern: /15 test/,
55
+ * checkField: 'message',
56
+ * messageContains: true
57
+ * });
58
+ * ```
59
+ */
60
+ export declare function expectMaxErrorsTruncation(result: ErrorExtractorResult, options: MaxErrorsOptions): Promise<void>;
61
+ export {};
62
+ //# sourceMappingURL=max-errors-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"max-errors-helper.d.ts","sourceRoot":"","sources":["../../../src/test/helpers/max-errors-helper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D;;GAEG;AACH,UAAU,gBAAgB;IACxB,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uEAAuE;IACvE,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAiCf"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Shared test helper for MAX_ERRORS_IN_ARRAY truncation behavior
3
+ *
4
+ * Eliminates duplication across extractor tests that verify error array truncation.
5
+ *
6
+ * @package @vibe-validate/extractors
7
+ */
8
+ import { expect } from 'vitest';
9
+ /**
10
+ * Assert MAX_ERRORS_IN_ARRAY truncation behavior
11
+ *
12
+ * Verifies that extractors correctly:
13
+ * 1. Preserve full error count in totalErrors
14
+ * 2. Truncate errors array to MAX_ERRORS_IN_ARRAY
15
+ * 3. Return first N errors in order
16
+ * 4. Include full count in summary
17
+ *
18
+ * @param result - Extraction result to verify
19
+ * @param options - Assertion options
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Check file field (default)
24
+ * const result = extract(fifteenErrors);
25
+ * await expectMaxErrorsTruncation(result, {
26
+ * totalCount: 15,
27
+ * firstError: 'file1.ts',
28
+ * lastTruncatedError: 'file10.ts',
29
+ * summaryPattern: '15 test failure(s)'
30
+ * });
31
+ *
32
+ * // Check message field with contains
33
+ * await expectMaxErrorsTruncation(result, {
34
+ * totalCount: 15,
35
+ * firstError: 'test 1',
36
+ * lastTruncatedError: 'test 10',
37
+ * summaryPattern: /15 test/,
38
+ * checkField: 'message',
39
+ * messageContains: true
40
+ * });
41
+ * ```
42
+ */
43
+ export async function expectMaxErrorsTruncation(result, options) {
44
+ const { totalCount, firstError, lastTruncatedError, summaryPattern, checkField = 'file', messageContains = false } = options;
45
+ // Import MAX_ERRORS_IN_ARRAY to verify we're testing the right value
46
+ const { MAX_ERRORS_IN_ARRAY } = await import('../../result-schema.js');
47
+ // totalErrors should preserve full count
48
+ expect(result.totalErrors).toBe(totalCount);
49
+ // errors array should be truncated to MAX_ERRORS_IN_ARRAY
50
+ expect(result.errors).toHaveLength(MAX_ERRORS_IN_ARRAY);
51
+ expect(result.errors).toHaveLength(10); // Explicit check for documentation
52
+ // Verify we got the first N errors (in order)
53
+ if (checkField === 'file') {
54
+ expect(result.errors[0].file).toBe(firstError);
55
+ expect(result.errors[9].file).toBe(lastTruncatedError);
56
+ }
57
+ else if (messageContains) {
58
+ // Check message field with contains
59
+ expect(result.errors[0].message).toContain(firstError);
60
+ expect(result.errors[9].message).toContain(lastTruncatedError);
61
+ }
62
+ else {
63
+ // Check message field with exact match
64
+ expect(result.errors[0].message).toBe(firstError);
65
+ expect(result.errors[9].message).toBe(lastTruncatedError);
66
+ }
67
+ // Summary should show full count
68
+ if (typeof summaryPattern === 'string') {
69
+ expect(result.summary).toBe(summaryPattern);
70
+ }
71
+ else {
72
+ expect(result.summary).toMatch(summaryPattern);
73
+ }
74
+ }
75
+ //# sourceMappingURL=max-errors-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"max-errors-helper.js","sourceRoot":"","sources":["../../../src/test/helpers/max-errors-helper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAsBhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,MAA4B,EAC5B,OAAyB;IAEzB,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,kBAAkB,EAAE,cAAc,EAAE,UAAU,GAAG,MAAM,EAAE,eAAe,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAE7H,qEAAqE;IACrE,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;IAEvE,yCAAyC;IACzC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAE5C,0DAA0D;IAC1D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;IACxD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,mCAAmC;IAE3E,8CAA8C;IAC9C,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACzD,CAAC;SAAM,IAAI,eAAe,EAAE,CAAC;QAC3B,oCAAoC;QACpC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,uCAAuC;QACvC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC5D,CAAC;IAED,iCAAiC;IACjC,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9C,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACjD,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-validate/extractors",
3
- "version": "0.17.6",
3
+ "version": "0.18.0",
4
4
  "description": "LLM-optimized error extractors for validation output",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -9,6 +9,10 @@
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.js"
12
+ },
13
+ "./testing": {
14
+ "types": "./dist/test/helpers/extractor-test-helpers.d.ts",
15
+ "import": "./dist/test/helpers/extractor-test-helpers.js"
12
16
  }
13
17
  },
14
18
  "files": [
@@ -43,7 +47,7 @@
43
47
  "dependencies": {
44
48
  "zod": "^3.25.76",
45
49
  "zod-to-json-schema": "^3.25.0",
46
- "@vibe-validate/config": "0.17.6"
50
+ "@vibe-validate/config": "0.18.0"
47
51
  },
48
52
  "engines": {
49
53
  "node": ">=20.0.0"