@savvy-web/vitest 1.4.0 → 1.5.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 (4) hide show
  1. package/index.d.ts +523 -556
  2. package/index.js +783 -517
  3. package/package.json +48 -59
  4. package/tsdoc-metadata.json +11 -11
package/index.d.ts CHANGED
@@ -1,556 +1,523 @@
1
- /**
2
- * Vitest utility functions for automatic project configuration discovery
3
- * in pnpm monorepo workspaces.
4
- *
5
- * @remarks
6
- * This package provides two main classes:
7
- *
8
- * - {@link VitestProject} - Represents a single Vitest project with sensible
9
- * defaults per test kind (unit, e2e, or custom).
10
- *
11
- * - {@link VitestConfig} - Orchestrates workspace discovery, coverage
12
- * configuration, reporter selection, and callback invocation.
13
- *
14
- * @example
15
- * ```typescript
16
- * import { VitestConfig } from "@savvy-web/vitest";
17
- *
18
- * export default VitestConfig.create();
19
- * ```
20
- *
21
- * @packageDocumentation
22
- */
23
-
24
- import type { AgentPluginOptions } from 'vitest-agent-reporter';
25
- import { TestProjectInlineConfiguration } from 'vitest/config';
26
- import type { ViteUserConfig } from 'vitest/config';
27
-
28
- /**
29
- * Pass-through configuration for `vitest-agent-reporter`'s `AgentPlugin`.
30
- *
31
- * @see {@link VitestConfigOptions.agentReporter}
32
- *
33
- * @public
34
- */
35
- export declare type AgentReporterConfig = AgentPluginOptions;
36
-
37
- /**
38
- * Named coverage level presets available on {@link VitestConfig.COVERAGE_LEVELS}.
39
- *
40
- * @public
41
- */
42
- export declare type CoverageLevelName = "none" | "basic" | "standard" | "strict" | "full";
43
-
44
- /**
45
- * Coverage thresholds with all four metrics required.
46
- *
47
- * @public
48
- */
49
- export declare interface CoverageThresholds {
50
- /** Minimum line coverage percentage. */
51
- lines: number;
52
- /** Minimum function coverage percentage. */
53
- functions: number;
54
- /** Minimum branch coverage percentage. */
55
- branches: number;
56
- /** Minimum statement coverage percentage. */
57
- statements: number;
58
- }
59
-
60
- /**
61
- * Override for a specific test kind (unit, e2e, int).
62
- *
63
- * @remarks
64
- * When an object is provided, it is merged into every project of that kind.
65
- * When a callback is provided, it receives a Map of project name to
66
- * {@link VitestProject} for fine-grained per-project mutation.
67
- *
68
- * @public
69
- */
70
- export declare type KindOverride = Partial<TestProjectInlineConfiguration["test"]> | ((projects: Map<string, VitestProject>) => void);
71
-
72
- /**
73
- * Post-process callback for escape-hatch customization of the assembled config.
74
- *
75
- * @param config - The assembled Vitest configuration
76
- * @returns A replacement config, or void to use the mutated original
77
- *
78
- * @public
79
- */
80
- export declare type PostProcessCallback = (config: ViteUserConfig) => ViteUserConfig | undefined;
81
-
82
- export { TestProjectInlineConfiguration }
83
-
84
- /**
85
- * Utility class for generating Vitest configuration in monorepo workspaces.
86
- *
87
- * @remarks
88
- * This class automatically discovers packages in a workspace that contain a
89
- * `src/` directory and generates appropriate {@link VitestProject} configurations.
90
- * Tests are discovered by filename convention:
91
- *
92
- * | Pattern | Kind |
93
- * | --- | --- |
94
- * | `*.test.ts` / `*.spec.ts` | unit |
95
- * | `*.e2e.test.ts` / `*.e2e.spec.ts` | e2e |
96
- *
97
- * It supports both running all tests and targeting specific projects via the
98
- * `--project` command line argument.
99
- *
100
- * Results are cached in static properties so that repeated config evaluations
101
- * during watch mode or HMR do not re-scan the filesystem.
102
- *
103
- * @example
104
- * ```typescript
105
- * import { VitestConfig } from "@savvy-web/vitest";
106
- *
107
- * export default VitestConfig.create();
108
- * ```
109
- *
110
- * @public
111
- */
112
- export declare class VitestConfig {
113
- /** Default glob patterns excluded from coverage reporting. */
114
- private static readonly DEFAULT_COVERAGE_EXCLUDE;
115
- /**
116
- * Named coverage level presets.
117
- *
118
- * @remarks
119
- * Use a level name with the `coverage` option in {@link VitestConfig.create}
120
- * to apply a preset. The object is frozen and cannot be mutated.
121
- *
122
- * | Level | lines | branches | functions | statements |
123
- * | -------- | ----- | -------- | --------- | ---------- |
124
- * | none | 0 | 0 | 0 | 0 |
125
- * | basic | 50 | 50 | 50 | 50 |
126
- * | standard | 70 | 65 | 70 | 70 |
127
- * | strict | 80 | 75 | 80 | 80 |
128
- * | full | 90 | 85 | 90 | 90 |
129
- */
130
- static readonly COVERAGE_LEVELS: Readonly<Record<CoverageLevelName, CoverageThresholds>>;
131
- private static cachedProjects;
132
- private static cachedVitestProjects;
133
- /**
134
- * Creates a complete Vitest configuration by discovering workspace projects
135
- * and generating appropriate settings.
136
- *
137
- * @param options - Optional declarative configuration
138
- * @param postProcess - Optional escape-hatch callback for full config control
139
- * @returns The assembled Vitest configuration
140
- *
141
- * @see {@link VitestConfigOptions} for available options
142
- * @see {@link PostProcessCallback} for the post-process callback signature
143
- */
144
- static create(options?: VitestConfigOptions, postProcess?: PostProcessCallback): Promise<ViteUserConfig>;
145
- /**
146
- * Applies kind-specific overrides to discovered projects.
147
- *
148
- * @privateRemarks
149
- * When the override is an object, it is merged into every project of the
150
- * matching kind. When it is a callback, it receives a Map of project name
151
- * to {@link VitestProject} for fine-grained per-project mutation.
152
- */
153
- private static applyKindOverrides;
154
- /**
155
- * Extracts all specific project names from command line arguments.
156
- *
157
- * @privateRemarks
158
- * Supports both `--project=value` and `--project value` formats to match
159
- * Vitest's own argument parsing behavior. All `--project` flags are
160
- * collected to support multi-project coverage scoping.
161
- */
162
- private static getSpecificProjects;
163
- /**
164
- * Reads the `name` field from a package's `package.json`.
165
- *
166
- * @privateRemarks
167
- * Uses try/catch because the package.json may not exist or may be malformed.
168
- * Returns `null` to signal the caller should skip this package.
169
- */
170
- private static getPackageNameFromPath;
171
- /**
172
- * Checks whether a path is an existing directory.
173
- *
174
- * @privateRemarks
175
- * Consolidates the repeated `statSync` + `isDirectory()` + try/catch
176
- * pattern used throughout workspace discovery.
177
- */
178
- private static isDirectory;
179
- /** Extensions probed (in order) when detecting a setup file. */
180
- private static readonly SETUP_FILE_EXTENSIONS;
181
- /**
182
- * Detects a `vitest.setup.{ts,tsx,js,jsx}` file at the package root.
183
- *
184
- * @privateRemarks
185
- * First match wins. Returns just the filename (e.g. `"vitest.setup.ts"`)
186
- * so the caller can prepend the relative prefix as needed.
187
- */
188
- private static detectSetupFile;
189
- /**
190
- * Recursively scans a directory for test files and classifies them by kind.
191
- *
192
- * @privateRemarks
193
- * Short-circuits as soon as all three kinds (unit, e2e, and int) are
194
- * found, avoiding unnecessary filesystem traversal.
195
- */
196
- private static scanForTestFiles;
197
- /**
198
- * Builds include glob patterns for a given relative path and optional
199
- * test directory.
200
- */
201
- private static buildIncludes;
202
- /**
203
- * Conventional subdirectories under `__test__/` that hold helpers, not
204
- * test files, and should be excluded from test discovery.
205
- */
206
- private static readonly TEST_DIR_EXCLUSIONS;
207
- /**
208
- * Returns exclusion patterns for fixture/utils directories under
209
- * `__test__/`, scoped to the given package prefix.
210
- *
211
- * @param prefix - Either `"<relativePath>/"` for non-root packages or
212
- * `""` for the workspace root.
213
- */
214
- private static buildTestDirExclusions;
215
- /**
216
- * Discovers all packages in the workspace that contain a `src/` directory
217
- * and generates {@link VitestProject} instances based on filename conventions.
218
- *
219
- * @privateRemarks
220
- * When a package has both unit and e2e test files, projects are suffixed
221
- * with `:unit` and `:e2e` to disambiguate. Packages with `src/` but no
222
- * test files still get a unit project entry as a forward-looking placeholder.
223
- */
224
- private static discoverWorkspaceProjects;
225
- /**
226
- * Resolves coverage thresholds from options.
227
- *
228
- * @privateRemarks
229
- * Priority: `options.coverage` (name or object) \> `COVERAGE_LEVELS.none`.
230
- */
231
- private static resolveThresholds;
232
- /**
233
- * Resolves coverage targets from options.
234
- *
235
- * @privateRemarks
236
- * Priority: `options.coverageTargets` (name or object) \> `COVERAGE_LEVELS.basic`.
237
- */
238
- private static resolveTargets;
239
- /**
240
- * Generates coverage configuration including thresholds.
241
- *
242
- * @privateRemarks
243
- * Strips `:unit`/`:e2e`/`:int` suffix when looking up project paths for
244
- * `--project` filtering, since coverage applies to the entire package
245
- * regardless of test kind. When multiple `--project` flags are provided,
246
- * coverage includes are unioned across all matched packages.
247
- */
248
- private static getCoverageConfig;
249
- }
250
-
251
- /**
252
- * Options for {@link VitestConfig.create}.
253
- *
254
- * @public
255
- */
256
- export declare interface VitestConfigOptions {
257
- /**
258
- * Coverage level name or explicit thresholds object.
259
- *
260
- * @remarks
261
- * When a {@link CoverageLevelName} string is provided, the corresponding
262
- * preset from {@link VitestConfig.COVERAGE_LEVELS} is used. When a
263
- * {@link CoverageThresholds} object is provided, it is used directly.
264
- *
265
- * @defaultValue `"none"` (lines: 0, branches: 0, functions: 0, statements: 0)
266
- */
267
- coverage?: CoverageLevelName | CoverageThresholds;
268
- /**
269
- * Coverage targets communicated to `vitest-agent-reporter`.
270
- *
271
- * @remarks
272
- * Targets inform the reporter where coverage gaps exist but do **not**
273
- * cause test failures. When the agent reporter is enabled, these
274
- * thresholds are forwarded to the plugin's `reporter.coverageTargets`.
275
- *
276
- * If {@link VitestConfigOptions.agentReporter | agentReporter} is an
277
- * object with its own `reporter.coverageTargets`, the explicit plugin
278
- * option takes precedence and a warning is logged.
279
- *
280
- * @defaultValue `"basic"` (lines: 50, branches: 50, functions: 50, statements: 50)
281
- */
282
- coverageTargets?: CoverageLevelName | CoverageThresholds;
283
- /** Additional glob patterns to exclude from coverage reporting. */
284
- coverageExclude?: string[];
285
- /**
286
- * Whether to inject the vitest-agent-reporter plugin.
287
- *
288
- * @remarks
289
- * When `true` or an {@link AgentReporterConfig} object, the plugin is
290
- * injected with the given options (with `strategy` defaulting to `"own"`
291
- * and `coverageThresholds` populated from the resolved coverage level).
292
- * When `false`, the plugin is not injected.
293
- *
294
- * @defaultValue `true`
295
- */
296
- agentReporter?: boolean | AgentReporterConfig;
297
- /**
298
- * Vitest pool mode.
299
- *
300
- * @defaultValue Uses Vitest's default (threads)
301
- */
302
- pool?: "threads" | "forks" | "vmThreads" | "vmForks";
303
- /** Override configuration for all unit test projects. */
304
- unit?: KindOverride;
305
- /** Override configuration for all e2e test projects. */
306
- e2e?: KindOverride;
307
- /** Override configuration for all integration test projects. */
308
- int?: KindOverride;
309
- }
310
-
311
- /**
312
- * Represents a single Vitest project with sensible defaults per test kind.
313
- *
314
- * @remarks
315
- * Instances are created through static factory methods. The private constructor
316
- * enforces that all projects are built with validated merge semantics.
317
- *
318
- * Override merge precedence (highest wins):
319
- * 1. `name` and `include` from options (always win)
320
- * 2. `overrides.test` fields
321
- * 3. Factory defaults for `test`
322
- * 4. Top-level: `overrides` rest spreads over factory defaults rest
323
- *
324
- * @example
325
- * ```typescript
326
- * import { VitestProject } from "@savvy-web/vitest";
327
- *
328
- * const unitProject = VitestProject.unit({
329
- * name: "@savvy-web/my-lib",
330
- * include: ["src/**\/*.test.ts"],
331
- * });
332
- *
333
- * const e2eProject = VitestProject.e2e({
334
- * name: "@savvy-web/my-lib:e2e",
335
- * include: ["test/e2e/**\/*.test.ts"],
336
- * });
337
- *
338
- * const config = unitProject.toConfig();
339
- * ```
340
- *
341
- * @public
342
- */
343
- export declare class VitestProject {
344
- #private;
345
- private constructor();
346
- /**
347
- * The project name.
348
- * @see {@link VitestProjectOptions.name}
349
- */
350
- get name(): string;
351
- /**
352
- * The test kind (e.g., `"unit"`, `"e2e"`, or a custom string).
353
- * @see {@link VitestProjectKind}
354
- */
355
- get kind(): VitestProjectKind;
356
- /**
357
- * Coverage exclusion patterns accumulated via {@link addCoverageExclude}.
358
- *
359
- * @remarks
360
- * These patterns are not embedded in the inline project config but are
361
- * made available for the workspace-level coverage configuration to consume.
362
- */
363
- get coverageExcludes(): readonly string[];
364
- /**
365
- * Returns the vitest-native inline configuration object.
366
- *
367
- * @returns A {@link https://vitest.dev/config/ | TestProjectInlineConfiguration}
368
- * with all defaults and overrides merged
369
- */
370
- toConfig(): TestProjectInlineConfiguration;
371
- /**
372
- * Creates a clone of this project with independent config state.
373
- *
374
- * @remarks
375
- * The clone has its own config object so mutations via
376
- * {@link override}, {@link addInclude}, {@link addExclude}, and
377
- * {@link addCoverageExclude} do not affect the original.
378
- *
379
- * @returns A new {@link VitestProject} with the same configuration
380
- */
381
- clone(): VitestProject;
382
- /**
383
- * Merges additional configuration over the current config.
384
- *
385
- * @remarks
386
- * The {@link VitestProjectOptions.name | name} and
387
- * {@link VitestProjectOptions.include | include} fields are preserved
388
- * and cannot be overridden.
389
- *
390
- * @param config - Partial configuration to merge
391
- * @returns `this` for chaining
392
- */
393
- override(config: Partial<TestProjectInlineConfiguration>): this;
394
- /**
395
- * Appends glob patterns to the test include list.
396
- *
397
- * @param patterns - Glob patterns to add
398
- * @returns `this` for chaining
399
- */
400
- addInclude(...patterns: string[]): this;
401
- /**
402
- * Appends glob patterns to the test exclude list.
403
- *
404
- * @param patterns - Glob patterns to add
405
- * @returns `this` for chaining
406
- */
407
- addExclude(...patterns: string[]): this;
408
- /**
409
- * Appends glob patterns to the coverage exclusion list.
410
- *
411
- * @remarks
412
- * These patterns are exposed via {@link coverageExcludes} for the
413
- * workspace-level coverage configuration to consume.
414
- *
415
- * @param patterns - Glob patterns to exclude from coverage
416
- * @returns `this` for chaining
417
- */
418
- addCoverageExclude(...patterns: string[]): this;
419
- /**
420
- * Creates a unit test project with sensible defaults.
421
- *
422
- * @remarks
423
- * Defaults applied: `extends: true`, `environment: "node"`.
424
- *
425
- * @param options - Project options (the `kind` field is forced to `"unit"`)
426
- * @returns A new {@link VitestProject} configured for unit tests
427
- *
428
- * @example
429
- * ```typescript
430
- * import { VitestProject } from "@savvy-web/vitest";
431
- *
432
- * const project = VitestProject.unit({
433
- * name: "@savvy-web/my-lib",
434
- * include: ["src/**\/*.test.ts"],
435
- * });
436
- * ```
437
- */
438
- static unit(options: VitestProjectOptions): VitestProject;
439
- /**
440
- * Creates an e2e test project with sensible defaults.
441
- *
442
- * @remarks
443
- * Defaults applied: `extends: true`, `environment: "node"`,
444
- * `testTimeout: 120_000`, `hookTimeout: 60_000`,
445
- * `maxConcurrency: clamp(floor(cpus / 2), 1, 8)`.
446
- *
447
- * @param options - Project options (the `kind` field is forced to `"e2e"`)
448
- * @returns A new {@link VitestProject} configured for e2e tests
449
- *
450
- * @example
451
- * ```typescript
452
- * import { VitestProject } from "@savvy-web/vitest";
453
- *
454
- * const project = VitestProject.e2e({
455
- * name: "@savvy-web/my-lib:e2e",
456
- * include: ["test/e2e/**\/*.test.ts"],
457
- * });
458
- * ```
459
- */
460
- static e2e(options: VitestProjectOptions): VitestProject;
461
- /**
462
- * Creates an integration test project with sensible defaults.
463
- *
464
- * @remarks
465
- * Defaults applied: `extends: true`, `environment: "node"`,
466
- * `testTimeout: 60_000`, `hookTimeout: 30_000`,
467
- * `maxConcurrency: clamp(floor(cpus / 2), 1, 8)`.
468
- *
469
- * @param options - Project options (the `kind` field is forced to `"int"`)
470
- * @returns A new {@link VitestProject} configured for integration tests
471
- *
472
- * @example
473
- * ```typescript
474
- * import { VitestProject } from "@savvy-web/vitest";
475
- *
476
- * const project = VitestProject.int({
477
- * name: "@savvy-web/my-lib:int",
478
- * include: ["__test__/integration/**\/*.int.test.ts"],
479
- * });
480
- * ```
481
- */
482
- static int(options: VitestProjectOptions): VitestProject;
483
- /**
484
- * Creates a custom test project with no preset defaults beyond `extends: true`.
485
- *
486
- * @remarks
487
- * Use this factory when the built-in `unit()` and `e2e()` presets do not
488
- * match your needs. The `kind` string is stored on the instance but does
489
- * not influence any default configuration.
490
- *
491
- * @param kind - A custom kind string (e.g., `"integration"`, `"smoke"`)
492
- * @param options - Project options
493
- * @returns A new {@link VitestProject} with no preset defaults
494
- *
495
- * @example
496
- * ```typescript
497
- * import { VitestProject } from "@savvy-web/vitest";
498
- *
499
- * const project = VitestProject.custom("integration", {
500
- * name: "@savvy-web/my-lib:integration",
501
- * include: ["test/integration/**\/*.test.ts"],
502
- * });
503
- * ```
504
- */
505
- static custom(kind: VitestProjectKind, options: VitestProjectOptions): VitestProject;
506
- }
507
-
508
- /**
509
- * The kind of test a {@link VitestProject} represents.
510
- *
511
- * @remarks
512
- * The built-in factories {@link VitestProject.unit | unit()} and
513
- * {@link VitestProject.e2e | e2e()} correspond to the `"unit"` and `"e2e"`
514
- * values respectively. The {@link VitestProject.custom | custom()} factory
515
- * accepts an arbitrary string that is stored as the kind.
516
- *
517
- * @public
518
- */
519
- export declare type VitestProjectKind = "unit" | "e2e" | "int" | (string & {});
520
-
521
- /**
522
- * Options for constructing a {@link VitestProject}.
523
- *
524
- * @see {@link VitestProject.unit} for creating unit test projects
525
- * @see {@link VitestProject.e2e} for creating e2e test projects
526
- * @see {@link VitestProject.custom} for creating custom test projects
527
- *
528
- * @public
529
- */
530
- export declare interface VitestProjectOptions {
531
- /**
532
- * The project name, typically a package name optionally suffixed
533
- * with `:unit` or `:e2e` when both kinds exist in the same package.
534
- */
535
- name: string;
536
- /** Glob patterns for test file inclusion. */
537
- include: string[];
538
- /**
539
- * The test kind. Defaults to `"unit"`.
540
- * @defaultValue `"unit"`
541
- */
542
- kind?: VitestProjectKind;
543
- /**
544
- * Vitest-native config fields to merge over the factory defaults.
545
- *
546
- * @remarks
547
- * The {@link VitestProjectOptions.name | name} and
548
- * {@link VitestProjectOptions.include | include} fields always take
549
- * precedence over any values provided in overrides.
550
- *
551
- * @see {@link https://vitest.dev/config/ | Vitest Configuration} for available fields
552
- */
553
- overrides?: Partial<TestProjectInlineConfiguration>;
554
- }
555
-
556
- export { }
1
+ import { TestProjectInlineConfiguration, TestProjectInlineConfiguration as TestProjectInlineConfiguration$1, ViteUserConfig } from "vitest/config";
2
+ import { AgentPluginOptions } from "vitest-agent-reporter";
3
+
4
+ //#region src/index.d.ts
5
+ /**
6
+ * The kind of test a {@link VitestProject} represents.
7
+ *
8
+ * @remarks
9
+ * The built-in factories {@link VitestProject.unit | unit()} and
10
+ * {@link VitestProject.e2e | e2e()} correspond to the `"unit"` and `"e2e"`
11
+ * values respectively. The {@link VitestProject.custom | custom()} factory
12
+ * accepts an arbitrary string that is stored as the kind.
13
+ *
14
+ * @public
15
+ */
16
+ type VitestProjectKind = "unit" | "e2e" | "int" | (string & {});
17
+ /**
18
+ * Options for constructing a {@link VitestProject}.
19
+ *
20
+ * @see {@link VitestProject.unit} for creating unit test projects
21
+ * @see {@link VitestProject.e2e} for creating e2e test projects
22
+ * @see {@link VitestProject.custom} for creating custom test projects
23
+ *
24
+ * @public
25
+ */
26
+ interface VitestProjectOptions {
27
+ /**
28
+ * The project name, typically a package name optionally suffixed
29
+ * with `:unit` or `:e2e` when both kinds exist in the same package.
30
+ */
31
+ name: string;
32
+ /** Glob patterns for test file inclusion. */
33
+ include: string[];
34
+ /**
35
+ * The test kind. Defaults to `"unit"`.
36
+ * @defaultValue `"unit"`
37
+ */
38
+ kind?: VitestProjectKind;
39
+ /**
40
+ * Vitest-native config fields to merge over the factory defaults.
41
+ *
42
+ * @remarks
43
+ * The {@link VitestProjectOptions.name | name} and
44
+ * {@link VitestProjectOptions.include | include} fields always take
45
+ * precedence over any values provided in overrides.
46
+ *
47
+ * @see {@link https://vitest.dev/config/ | Vitest Configuration} for available fields
48
+ */
49
+ overrides?: Partial<TestProjectInlineConfiguration$1>;
50
+ }
51
+ /**
52
+ * Pass-through configuration for `vitest-agent-reporter`'s `AgentPlugin`.
53
+ *
54
+ * @see {@link VitestConfigOptions.agentReporter}
55
+ *
56
+ * @public
57
+ */
58
+ type AgentReporterConfig = AgentPluginOptions;
59
+ /**
60
+ * Override for a specific test kind (unit, e2e, int).
61
+ *
62
+ * @remarks
63
+ * When an object is provided, it is merged into every project of that kind.
64
+ * When a callback is provided, it receives a Map of project name to
65
+ * {@link VitestProject} for fine-grained per-project mutation.
66
+ *
67
+ * @public
68
+ */
69
+ type KindOverride = Partial<TestProjectInlineConfiguration$1["test"]> | ((projects: Map<string, VitestProject>) => void);
70
+ /**
71
+ * Options for {@link VitestConfig.create}.
72
+ *
73
+ * @public
74
+ */
75
+ interface VitestConfigOptions {
76
+ /**
77
+ * Coverage level name or explicit thresholds object.
78
+ *
79
+ * @remarks
80
+ * When a {@link CoverageLevelName} string is provided, the corresponding
81
+ * preset from {@link VitestConfig.COVERAGE_LEVELS} is used. When a
82
+ * {@link CoverageThresholds} object is provided, it is used directly.
83
+ *
84
+ * @defaultValue `"none"` (lines: 0, branches: 0, functions: 0, statements: 0)
85
+ */
86
+ coverage?: CoverageLevelName | CoverageThresholds;
87
+ /**
88
+ * Coverage targets communicated to `vitest-agent-reporter`.
89
+ *
90
+ * @remarks
91
+ * Targets inform the reporter where coverage gaps exist but do **not**
92
+ * cause test failures. When the agent reporter is enabled, these
93
+ * thresholds are forwarded to the plugin's `reporter.coverageTargets`.
94
+ *
95
+ * If {@link VitestConfigOptions.agentReporter | agentReporter} is an
96
+ * object with its own `reporter.coverageTargets`, the explicit plugin
97
+ * option takes precedence and a warning is logged.
98
+ *
99
+ * @defaultValue `"basic"` (lines: 50, branches: 50, functions: 50, statements: 50)
100
+ */
101
+ coverageTargets?: CoverageLevelName | CoverageThresholds;
102
+ /** Additional glob patterns to exclude from coverage reporting. */
103
+ coverageExclude?: string[];
104
+ /**
105
+ * Whether to inject the vitest-agent-reporter plugin.
106
+ *
107
+ * @remarks
108
+ * When `true` or an {@link AgentReporterConfig} object, the plugin is
109
+ * injected with the given options (with `strategy` defaulting to `"own"`
110
+ * and `coverageThresholds` populated from the resolved coverage level).
111
+ * When `false`, the plugin is not injected.
112
+ *
113
+ * @defaultValue `true`
114
+ */
115
+ agentReporter?: boolean | AgentReporterConfig;
116
+ /**
117
+ * Vitest pool mode.
118
+ *
119
+ * @defaultValue Uses Vitest's default (threads)
120
+ */
121
+ pool?: "threads" | "forks" | "vmThreads" | "vmForks";
122
+ /** Override configuration for all unit test projects. */
123
+ unit?: KindOverride;
124
+ /** Override configuration for all e2e test projects. */
125
+ e2e?: KindOverride;
126
+ /** Override configuration for all integration test projects. */
127
+ int?: KindOverride;
128
+ }
129
+ /**
130
+ * Post-process callback for escape-hatch customization of the assembled config.
131
+ *
132
+ * @param config - The assembled Vitest configuration
133
+ * @returns A replacement config, or void to use the mutated original
134
+ *
135
+ * @public
136
+ */
137
+ type PostProcessCallback = (config: ViteUserConfig) => ViteUserConfig | undefined;
138
+ /**
139
+ * Coverage thresholds with all four metrics required.
140
+ *
141
+ * @public
142
+ */
143
+ interface CoverageThresholds {
144
+ /** Minimum line coverage percentage. */
145
+ lines: number;
146
+ /** Minimum function coverage percentage. */
147
+ functions: number;
148
+ /** Minimum branch coverage percentage. */
149
+ branches: number;
150
+ /** Minimum statement coverage percentage. */
151
+ statements: number;
152
+ }
153
+ /**
154
+ * Named coverage level presets available on {@link VitestConfig.COVERAGE_LEVELS}.
155
+ *
156
+ * @public
157
+ */
158
+ type CoverageLevelName = "none" | "basic" | "standard" | "strict" | "full";
159
+ /**
160
+ * Represents a single Vitest project with sensible defaults per test kind.
161
+ *
162
+ * @remarks
163
+ * Instances are created through static factory methods. The private constructor
164
+ * enforces that all projects are built with validated merge semantics.
165
+ *
166
+ * Override merge precedence (highest wins):
167
+ * 1. `name` and `include` from options (always win)
168
+ * 2. `overrides.test` fields
169
+ * 3. Factory defaults for `test`
170
+ * 4. Top-level: `overrides` rest spreads over factory defaults rest
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * import { VitestProject } from "@savvy-web/vitest";
175
+ *
176
+ * const unitProject = VitestProject.unit({
177
+ * name: "@savvy-web/my-lib",
178
+ * include: ["src/**\/*.test.ts"],
179
+ * });
180
+ *
181
+ * const e2eProject = VitestProject.e2e({
182
+ * name: "@savvy-web/my-lib:e2e",
183
+ * include: ["test/e2e/**\/*.test.ts"],
184
+ * });
185
+ *
186
+ * const config = unitProject.toConfig();
187
+ * ```
188
+ *
189
+ * @public
190
+ */
191
+ declare class VitestProject {
192
+ #private;
193
+ private constructor();
194
+ /**
195
+ * The project name.
196
+ * @see {@link VitestProjectOptions.name}
197
+ */
198
+ get name(): string;
199
+ /**
200
+ * The test kind (e.g., `"unit"`, `"e2e"`, or a custom string).
201
+ * @see {@link VitestProjectKind}
202
+ */
203
+ get kind(): VitestProjectKind;
204
+ /**
205
+ * Coverage exclusion patterns accumulated via {@link addCoverageExclude}.
206
+ *
207
+ * @remarks
208
+ * These patterns are not embedded in the inline project config but are
209
+ * made available for the workspace-level coverage configuration to consume.
210
+ */
211
+ get coverageExcludes(): readonly string[];
212
+ /**
213
+ * Returns the vitest-native inline configuration object.
214
+ *
215
+ * @returns A {@link https://vitest.dev/config/ | TestProjectInlineConfiguration}
216
+ * with all defaults and overrides merged
217
+ */
218
+ toConfig(): TestProjectInlineConfiguration$1;
219
+ /**
220
+ * Creates a clone of this project with independent config state.
221
+ *
222
+ * @remarks
223
+ * The clone has its own config object so mutations via
224
+ * {@link override}, {@link addInclude}, {@link addExclude}, and
225
+ * {@link addCoverageExclude} do not affect the original.
226
+ *
227
+ * @returns A new {@link VitestProject} with the same configuration
228
+ */
229
+ clone(): VitestProject;
230
+ /**
231
+ * Merges additional configuration over the current config.
232
+ *
233
+ * @remarks
234
+ * The {@link VitestProjectOptions.name | name} and
235
+ * {@link VitestProjectOptions.include | include} fields are preserved
236
+ * and cannot be overridden.
237
+ *
238
+ * @param config - Partial configuration to merge
239
+ * @returns `this` for chaining
240
+ */
241
+ override(config: Partial<TestProjectInlineConfiguration$1>): this;
242
+ /**
243
+ * Appends glob patterns to the test include list.
244
+ *
245
+ * @param patterns - Glob patterns to add
246
+ * @returns `this` for chaining
247
+ */
248
+ addInclude(...patterns: string[]): this;
249
+ /**
250
+ * Appends glob patterns to the test exclude list.
251
+ *
252
+ * @param patterns - Glob patterns to add
253
+ * @returns `this` for chaining
254
+ */
255
+ addExclude(...patterns: string[]): this;
256
+ /**
257
+ * Appends glob patterns to the coverage exclusion list.
258
+ *
259
+ * @remarks
260
+ * These patterns are exposed via {@link coverageExcludes} for the
261
+ * workspace-level coverage configuration to consume.
262
+ *
263
+ * @param patterns - Glob patterns to exclude from coverage
264
+ * @returns `this` for chaining
265
+ */
266
+ addCoverageExclude(...patterns: string[]): this;
267
+ /**
268
+ * Creates a unit test project with sensible defaults.
269
+ *
270
+ * @remarks
271
+ * Defaults applied: `extends: true`, `environment: "node"`.
272
+ *
273
+ * @param options - Project options (the `kind` field is forced to `"unit"`)
274
+ * @returns A new {@link VitestProject} configured for unit tests
275
+ *
276
+ * @example
277
+ * ```typescript
278
+ * import { VitestProject } from "@savvy-web/vitest";
279
+ *
280
+ * const project = VitestProject.unit({
281
+ * name: "@savvy-web/my-lib",
282
+ * include: ["src/**\/*.test.ts"],
283
+ * });
284
+ * ```
285
+ */
286
+ static unit(options: VitestProjectOptions): VitestProject;
287
+ /**
288
+ * Creates an e2e test project with sensible defaults.
289
+ *
290
+ * @remarks
291
+ * Defaults applied: `extends: true`, `environment: "node"`,
292
+ * `testTimeout: 120_000`, `hookTimeout: 60_000`,
293
+ * `maxConcurrency: clamp(floor(cpus / 2), 1, 8)`.
294
+ *
295
+ * @param options - Project options (the `kind` field is forced to `"e2e"`)
296
+ * @returns A new {@link VitestProject} configured for e2e tests
297
+ *
298
+ * @example
299
+ * ```typescript
300
+ * import { VitestProject } from "@savvy-web/vitest";
301
+ *
302
+ * const project = VitestProject.e2e({
303
+ * name: "@savvy-web/my-lib:e2e",
304
+ * include: ["test/e2e/**\/*.test.ts"],
305
+ * });
306
+ * ```
307
+ */
308
+ static e2e(options: VitestProjectOptions): VitestProject;
309
+ /**
310
+ * Creates an integration test project with sensible defaults.
311
+ *
312
+ * @remarks
313
+ * Defaults applied: `extends: true`, `environment: "node"`,
314
+ * `testTimeout: 60_000`, `hookTimeout: 30_000`,
315
+ * `maxConcurrency: clamp(floor(cpus / 2), 1, 8)`.
316
+ *
317
+ * @param options - Project options (the `kind` field is forced to `"int"`)
318
+ * @returns A new {@link VitestProject} configured for integration tests
319
+ *
320
+ * @example
321
+ * ```typescript
322
+ * import { VitestProject } from "@savvy-web/vitest";
323
+ *
324
+ * const project = VitestProject.int({
325
+ * name: "@savvy-web/my-lib:int",
326
+ * include: ["__test__/integration/**\/*.int.test.ts"],
327
+ * });
328
+ * ```
329
+ */
330
+ static int(options: VitestProjectOptions): VitestProject;
331
+ /**
332
+ * Creates a custom test project with no preset defaults beyond `extends: true`.
333
+ *
334
+ * @remarks
335
+ * Use this factory when the built-in `unit()` and `e2e()` presets do not
336
+ * match your needs. The `kind` string is stored on the instance but does
337
+ * not influence any default configuration.
338
+ *
339
+ * @param kind - A custom kind string (e.g., `"integration"`, `"smoke"`)
340
+ * @param options - Project options
341
+ * @returns A new {@link VitestProject} with no preset defaults
342
+ *
343
+ * @example
344
+ * ```typescript
345
+ * import { VitestProject } from "@savvy-web/vitest";
346
+ *
347
+ * const project = VitestProject.custom("integration", {
348
+ * name: "@savvy-web/my-lib:integration",
349
+ * include: ["test/integration/**\/*.test.ts"],
350
+ * });
351
+ * ```
352
+ */
353
+ static custom(kind: VitestProjectKind, options: VitestProjectOptions): VitestProject;
354
+ }
355
+ /**
356
+ * Utility class for generating Vitest configuration in monorepo workspaces.
357
+ *
358
+ * @remarks
359
+ * This class automatically discovers packages in a workspace that contain a
360
+ * `src/` directory and generates appropriate {@link VitestProject} configurations.
361
+ * Tests are discovered by filename convention:
362
+ *
363
+ * | Pattern | Kind |
364
+ * | --- | --- |
365
+ * | `*.test.ts` / `*.spec.ts` | unit |
366
+ * | `*.e2e.test.ts` / `*.e2e.spec.ts` | e2e |
367
+ *
368
+ * It supports both running all tests and targeting specific projects via the
369
+ * `--project` command line argument.
370
+ *
371
+ * Results are cached in static properties so that repeated config evaluations
372
+ * during watch mode or HMR do not re-scan the filesystem.
373
+ *
374
+ * @example
375
+ * ```typescript
376
+ * import { VitestConfig } from "@savvy-web/vitest";
377
+ *
378
+ * export default VitestConfig.create();
379
+ * ```
380
+ *
381
+ * @public
382
+ */
383
+ declare class VitestConfig {
384
+ /** Default glob patterns excluded from coverage reporting. */
385
+ private static readonly DEFAULT_COVERAGE_EXCLUDE;
386
+ /**
387
+ * Named coverage level presets.
388
+ *
389
+ * @remarks
390
+ * Use a level name with the `coverage` option in {@link VitestConfig.create}
391
+ * to apply a preset. The object is frozen and cannot be mutated.
392
+ *
393
+ * | Level | lines | branches | functions | statements |
394
+ * | -------- | ----- | -------- | --------- | ---------- |
395
+ * | none | 0 | 0 | 0 | 0 |
396
+ * | basic | 50 | 50 | 50 | 50 |
397
+ * | standard | 70 | 65 | 70 | 70 |
398
+ * | strict | 80 | 75 | 80 | 80 |
399
+ * | full | 90 | 85 | 90 | 90 |
400
+ */
401
+ static readonly COVERAGE_LEVELS: Readonly<Record<CoverageLevelName, CoverageThresholds>>;
402
+ private static cachedProjects;
403
+ private static cachedVitestProjects;
404
+ /**
405
+ * Creates a complete Vitest configuration by discovering workspace projects
406
+ * and generating appropriate settings.
407
+ *
408
+ * @param options - Optional declarative configuration
409
+ * @param postProcess - Optional escape-hatch callback for full config control
410
+ * @returns The assembled Vitest configuration
411
+ *
412
+ * @see {@link VitestConfigOptions} for available options
413
+ * @see {@link PostProcessCallback} for the post-process callback signature
414
+ */
415
+ static create(options?: VitestConfigOptions, postProcess?: PostProcessCallback): Promise<ViteUserConfig>;
416
+ /**
417
+ * Applies kind-specific overrides to discovered projects.
418
+ *
419
+ * @privateRemarks
420
+ * When the override is an object, it is merged into every project of the
421
+ * matching kind. When it is a callback, it receives a Map of project name
422
+ * to {@link VitestProject} for fine-grained per-project mutation.
423
+ */
424
+ private static applyKindOverrides;
425
+ /**
426
+ * Extracts all specific project names from command line arguments.
427
+ *
428
+ * @privateRemarks
429
+ * Supports both `--project=value` and `--project value` formats to match
430
+ * Vitest's own argument parsing behavior. All `--project` flags are
431
+ * collected to support multi-project coverage scoping.
432
+ */
433
+ private static getSpecificProjects;
434
+ /**
435
+ * Reads the `name` field from a package's `package.json`.
436
+ *
437
+ * @privateRemarks
438
+ * Uses try/catch because the package.json may not exist or may be malformed.
439
+ * Returns `null` to signal the caller should skip this package.
440
+ */
441
+ private static getPackageNameFromPath;
442
+ /**
443
+ * Checks whether a path is an existing directory.
444
+ *
445
+ * @privateRemarks
446
+ * Consolidates the repeated `statSync` + `isDirectory()` + try/catch
447
+ * pattern used throughout workspace discovery.
448
+ */
449
+ private static isDirectory;
450
+ /** Extensions probed (in order) when detecting a setup file. */
451
+ private static readonly SETUP_FILE_EXTENSIONS;
452
+ /**
453
+ * Detects a `vitest.setup.{ts,tsx,js,jsx}` file at the package root.
454
+ *
455
+ * @privateRemarks
456
+ * First match wins. Returns just the filename (e.g. `"vitest.setup.ts"`)
457
+ * so the caller can prepend the relative prefix as needed.
458
+ */
459
+ private static detectSetupFile;
460
+ /**
461
+ * Recursively scans a directory for test files and classifies them by kind.
462
+ *
463
+ * @privateRemarks
464
+ * Short-circuits as soon as all three kinds (unit, e2e, and int) are
465
+ * found, avoiding unnecessary filesystem traversal.
466
+ */
467
+ private static scanForTestFiles;
468
+ /**
469
+ * Builds include glob patterns for a given relative path and optional
470
+ * test directory.
471
+ */
472
+ private static buildIncludes;
473
+ /**
474
+ * Conventional subdirectories under `__test__/` that hold helpers, not
475
+ * test files, and should be excluded from test discovery.
476
+ */
477
+ private static readonly TEST_DIR_EXCLUSIONS;
478
+ /**
479
+ * Returns exclusion patterns for fixture/utils directories under
480
+ * `__test__/`, scoped to the given package prefix.
481
+ *
482
+ * @param prefix - Either `"<relativePath>/"` for non-root packages or
483
+ * `""` for the workspace root.
484
+ */
485
+ private static buildTestDirExclusions;
486
+ /**
487
+ * Discovers all packages in the workspace that contain a `src/` directory
488
+ * and generates {@link VitestProject} instances based on filename conventions.
489
+ *
490
+ * @privateRemarks
491
+ * When a package has both unit and e2e test files, projects are suffixed
492
+ * with `:unit` and `:e2e` to disambiguate. Packages with `src/` but no
493
+ * test files still get a unit project entry as a forward-looking placeholder.
494
+ */
495
+ private static discoverWorkspaceProjects;
496
+ /**
497
+ * Resolves coverage thresholds from options.
498
+ *
499
+ * @privateRemarks
500
+ * Priority: `options.coverage` (name or object) \> `COVERAGE_LEVELS.none`.
501
+ */
502
+ private static resolveThresholds;
503
+ /**
504
+ * Resolves coverage targets from options.
505
+ *
506
+ * @privateRemarks
507
+ * Priority: `options.coverageTargets` (name or object) \> `COVERAGE_LEVELS.basic`.
508
+ */
509
+ private static resolveTargets;
510
+ /**
511
+ * Generates coverage configuration including thresholds.
512
+ *
513
+ * @privateRemarks
514
+ * Strips `:unit`/`:e2e`/`:int` suffix when looking up project paths for
515
+ * `--project` filtering, since coverage applies to the entire package
516
+ * regardless of test kind. When multiple `--project` flags are provided,
517
+ * coverage includes are unioned across all matched packages.
518
+ */
519
+ private static getCoverageConfig;
520
+ }
521
+ //#endregion
522
+ export { AgentReporterConfig, CoverageLevelName, CoverageThresholds, KindOverride, PostProcessCallback, type TestProjectInlineConfiguration, VitestConfig, VitestConfigOptions, VitestProject, VitestProjectKind, VitestProjectOptions };
523
+ //# sourceMappingURL=index.d.ts.map