@reasonabletech/config-vitest 0.1.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.
- package/README.md +96 -0
- package/dist/src/global-setup.d.ts +15 -0
- package/dist/src/global-setup.d.ts.map +1 -0
- package/dist/src/index.d.ts +63 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +352 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/node.d.ts +29 -0
- package/dist/src/node.d.ts.map +1 -0
- package/dist/src/node.js +209 -0
- package/dist/src/node.js.map +1 -0
- package/dist/src/react.d.ts +46 -0
- package/dist/src/react.d.ts.map +1 -0
- package/dist/src/react.js +225 -0
- package/dist/src/react.js.map +1 -0
- package/dist/src/workspace.d.ts +29 -0
- package/dist/src/workspace.d.ts.map +1 -0
- package/dist/src/workspace.js +33 -0
- package/dist/src/workspace.js.map +1 -0
- package/docs/README.md +28 -0
- package/docs/api/api-reference.md +469 -0
- package/docs/api/base-config.md +542 -0
- package/docs/guides/migration.md +47 -0
- package/docs/guides/usage-guide.md +81 -0
- package/package.json +100 -0
- package/src/global-setup.ts +58 -0
- package/src/index.ts +280 -0
- package/src/node.ts +74 -0
- package/src/react.ts +241 -0
- package/src/workspace.ts +62 -0
package/package.json
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reasonabletech/config-vitest",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared Vitest configuration",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"reasonabletech",
|
|
7
|
+
"config",
|
|
8
|
+
"typescript",
|
|
9
|
+
"vitest",
|
|
10
|
+
"testing",
|
|
11
|
+
"test-config",
|
|
12
|
+
"coverage",
|
|
13
|
+
"vite"
|
|
14
|
+
],
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "dist/src/index.js",
|
|
17
|
+
"types": "./dist/src/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/src/index.d.ts",
|
|
21
|
+
"import": "./dist/src/index.js",
|
|
22
|
+
"default": "./dist/src/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./node": {
|
|
25
|
+
"types": "./dist/src/node.d.ts",
|
|
26
|
+
"import": "./dist/src/node.js",
|
|
27
|
+
"default": "./dist/src/node.js"
|
|
28
|
+
},
|
|
29
|
+
"./react": {
|
|
30
|
+
"types": "./dist/src/react.d.ts",
|
|
31
|
+
"import": "./dist/src/react.js",
|
|
32
|
+
"default": "./dist/src/react.js"
|
|
33
|
+
},
|
|
34
|
+
"./workspace": {
|
|
35
|
+
"types": "./dist/src/workspace.d.ts",
|
|
36
|
+
"import": "./dist/src/workspace.js",
|
|
37
|
+
"default": "./dist/src/workspace.js"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"docs/**/*",
|
|
43
|
+
"src"
|
|
44
|
+
],
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@vitejs/plugin-react": "5.1.4",
|
|
47
|
+
"vite": "7.3.1",
|
|
48
|
+
"vitest": "4.0.18"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "25.3.1",
|
|
52
|
+
"@vitest/coverage-v8": "4.0.18",
|
|
53
|
+
"eslint": "10.0.2",
|
|
54
|
+
"tsup": "8.5.1",
|
|
55
|
+
"typescript": "5.9.3",
|
|
56
|
+
"vitest": "4.0.18",
|
|
57
|
+
"@reasonabletech/config-eslint": "0.1.0",
|
|
58
|
+
"@reasonabletech/config-typescript": "0.1.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"vite": ">=7.3.1 <8",
|
|
62
|
+
"vitest": ">=4.0.18 <5"
|
|
63
|
+
},
|
|
64
|
+
"license": "MIT",
|
|
65
|
+
"author": "Reasonable Tech Company",
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public",
|
|
68
|
+
"registry": "https://registry.npmjs.org/"
|
|
69
|
+
},
|
|
70
|
+
"repository": {
|
|
71
|
+
"type": "git",
|
|
72
|
+
"url": "https://github.com/ReasonableTech/core-utils.git",
|
|
73
|
+
"directory": "packages/config-vitest"
|
|
74
|
+
},
|
|
75
|
+
"bugs": {
|
|
76
|
+
"url": "https://github.com/ReasonableTech/core-utils/issues"
|
|
77
|
+
},
|
|
78
|
+
"homepage": "https://github.com/ReasonableTech/core-utils/tree/main/packages/config-vitest",
|
|
79
|
+
"sideEffects": false,
|
|
80
|
+
"engines": {
|
|
81
|
+
"node": ">=22"
|
|
82
|
+
},
|
|
83
|
+
"scripts": {
|
|
84
|
+
"build": "tsup && tsc --emitDeclarationOnly -p tsconfig.build.json",
|
|
85
|
+
"clean": "rm -rf dist .turbo node_modules tsconfig.tsbuildinfo",
|
|
86
|
+
"dev": "tsc --watch",
|
|
87
|
+
"docs:coverage": "tsx ../../../scripts/analysis/check-doc-coverage.ts --html",
|
|
88
|
+
"lint": "eslint . --fix",
|
|
89
|
+
"lint:check": "eslint .",
|
|
90
|
+
"test": "vitest run",
|
|
91
|
+
"test:coverage": "vitest run --coverage",
|
|
92
|
+
"test:e2e": "vitest run tests/e2e",
|
|
93
|
+
"test:integration": "vitest run tests/integration",
|
|
94
|
+
"test:ui": "vitest --ui",
|
|
95
|
+
"test:unit": "vitest run tests/unit",
|
|
96
|
+
"test:watch": "vitest --watch",
|
|
97
|
+
"typecheck": "tsc --noEmit",
|
|
98
|
+
"verify:release": "pnpm typecheck && pnpm lint:check && pnpm test && pnpm build"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { findRepoRoot, readPackageName } from "./workspace.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Builds the pnpm + turbo CLI arguments needed to build all upstream
|
|
6
|
+
* workspace dependencies of the given package.
|
|
7
|
+
* @param packageName - The package name (e.g. `@reasonabletech/utils`)
|
|
8
|
+
* @returns An array of CLI arguments for `spawnSync("pnpm", ...)`
|
|
9
|
+
*/
|
|
10
|
+
export function getTurboBuildArgs(packageName: string): readonly string[] {
|
|
11
|
+
return [
|
|
12
|
+
"-w",
|
|
13
|
+
"turbo",
|
|
14
|
+
"run",
|
|
15
|
+
"build",
|
|
16
|
+
`--filter=${packageName}^...`,
|
|
17
|
+
] as const;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Vitest global setup that builds workspace dependencies before tests run.
|
|
22
|
+
*
|
|
23
|
+
* Skipped when `RT_VITEST_SKIP_DEP_BUILD=true` is set or when
|
|
24
|
+
* a parent build is already in progress (re-entrancy guard).
|
|
25
|
+
*/
|
|
26
|
+
export default function globalSetup(): void {
|
|
27
|
+
if (process.env.RT_VITEST_SKIP_DEP_BUILD === "true") {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (process.env.RT_VITEST_DEP_BUILD_RUNNING === "true") {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const packageDir = process.cwd();
|
|
36
|
+
const packageName = readPackageName(packageDir);
|
|
37
|
+
if (packageName === null) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const repoRoot = findRepoRoot(packageDir);
|
|
42
|
+
const args = getTurboBuildArgs(packageName);
|
|
43
|
+
|
|
44
|
+
const result = spawnSync("pnpm", args, {
|
|
45
|
+
cwd: repoRoot,
|
|
46
|
+
stdio: "inherit",
|
|
47
|
+
env: {
|
|
48
|
+
...process.env,
|
|
49
|
+
RT_VITEST_DEP_BUILD_RUNNING: "true",
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (result.status !== 0) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`Failed to build workspace dependencies (exit code: ${result.status ?? "unknown"})`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Vitest configuration for all packages
|
|
3
|
+
* @module @reasonabletech/config-vitest
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { defaultClientConditions, defaultServerConditions } from "vite";
|
|
9
|
+
import { defineConfig } from "vitest/config";
|
|
10
|
+
import type { InlineConfig } from "vitest/node";
|
|
11
|
+
import { readPackageName } from "./workspace.js";
|
|
12
|
+
|
|
13
|
+
/** Recursively makes all properties of T readonly */
|
|
14
|
+
export type DeepReadonly<T> = {
|
|
15
|
+
readonly [P in keyof T]: T[P] extends ReadonlyArray<infer U>
|
|
16
|
+
? ReadonlyArray<DeepReadonly<U>>
|
|
17
|
+
: T[P] extends Array<infer U>
|
|
18
|
+
? ReadonlyArray<DeepReadonly<U>>
|
|
19
|
+
: T[P] extends object
|
|
20
|
+
? DeepReadonly<T[P]>
|
|
21
|
+
: T[P];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Immutable configuration object accepted by {@link createVitestConfig} and
|
|
26
|
+
* related helpers.
|
|
27
|
+
*/
|
|
28
|
+
export type VitestConfig = DeepReadonly<{
|
|
29
|
+
test?: InlineConfig;
|
|
30
|
+
resolve?: {
|
|
31
|
+
conditions?: string[];
|
|
32
|
+
alias?: Record<string, string>;
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
};
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}>;
|
|
37
|
+
|
|
38
|
+
// Empty readonly config for default parameters
|
|
39
|
+
const EMPTY_CONFIG = {} as const satisfies VitestConfig;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Base configuration options that apply to all test environments
|
|
43
|
+
*/
|
|
44
|
+
export const baseConfig = {
|
|
45
|
+
test: {
|
|
46
|
+
testTimeout: 10000, // 10 seconds default timeout
|
|
47
|
+
hookTimeout: 10000, // 10 seconds for setup/teardown hooks
|
|
48
|
+
coverage: {
|
|
49
|
+
provider: "v8" as const,
|
|
50
|
+
reporter: ["text", "html", "lcov", "json"],
|
|
51
|
+
reportsDirectory: "./generated/test-coverage",
|
|
52
|
+
exclude: [
|
|
53
|
+
"**/node_modules/**",
|
|
54
|
+
"**/dist/**",
|
|
55
|
+
"**/tests/**",
|
|
56
|
+
"**/*.d.ts",
|
|
57
|
+
"**/*.config.{js,ts,mjs,mts}",
|
|
58
|
+
"**/coverage/**",
|
|
59
|
+
"**/examples/**",
|
|
60
|
+
"**/src/index.ts",
|
|
61
|
+
"**/src/*/index.ts",
|
|
62
|
+
"**/src/types/**",
|
|
63
|
+
"tsup.config.ts",
|
|
64
|
+
"vitest.config.mts",
|
|
65
|
+
"tailwind.config.mjs",
|
|
66
|
+
"**/vitest.setup.ts",
|
|
67
|
+
],
|
|
68
|
+
thresholds:
|
|
69
|
+
process.env.VITEST_COVERAGE_THRESHOLDS_DISABLED === "true"
|
|
70
|
+
? {
|
|
71
|
+
lines: 0,
|
|
72
|
+
functions: 0,
|
|
73
|
+
branches: 0,
|
|
74
|
+
statements: 0,
|
|
75
|
+
}
|
|
76
|
+
: {
|
|
77
|
+
lines: 100,
|
|
78
|
+
functions: 100,
|
|
79
|
+
branches: 100,
|
|
80
|
+
statements: 100,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Generates resolve aliases that map a package's own name back to its source
|
|
88
|
+
* directory. This allows test files to `import { foo } from "@reasonabletech/my-pkg"`
|
|
89
|
+
* and have Vite resolve it to the local `src/` tree instead of requiring a prior
|
|
90
|
+
* build step.
|
|
91
|
+
*
|
|
92
|
+
* Placed before user-supplied aliases so consumers can override if needed.
|
|
93
|
+
* @param projectDir - Absolute path to the project directory
|
|
94
|
+
* @returns A record mapping the package name to its `src/` directory
|
|
95
|
+
*/
|
|
96
|
+
function generateSelfPackageAliases(
|
|
97
|
+
projectDir: string,
|
|
98
|
+
): Record<string, string> {
|
|
99
|
+
const packageName = readPackageName(projectDir);
|
|
100
|
+
if (packageName === null) {
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
[packageName]: `${projectDir}/src`,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Auto-detects setup files in a project directory
|
|
110
|
+
* @param projectDir - The project directory path
|
|
111
|
+
* @returns Array of detected setup file paths
|
|
112
|
+
*/
|
|
113
|
+
function autoDetectSetupFiles(projectDir?: string): string[] {
|
|
114
|
+
if (projectDir === undefined || projectDir === "") {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const vitestSetupPath = join(projectDir, "vitest.setup.ts");
|
|
119
|
+
if (existsSync(vitestSetupPath)) {
|
|
120
|
+
return ["./vitest.setup.ts"];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const testsSetupPath = join(projectDir, "tests/setup.ts");
|
|
124
|
+
if (existsSync(testsSetupPath)) {
|
|
125
|
+
return ["./tests/setup.ts"];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Auto-detects test include patterns based on project structure
|
|
133
|
+
* @returns Array of include patterns
|
|
134
|
+
*/
|
|
135
|
+
function autoDetectIncludePatterns(): string[] {
|
|
136
|
+
return ["tests/**/*.test.{ts,tsx,js,jsx}"];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** @overload */
|
|
140
|
+
/**
|
|
141
|
+
* Creates a merged configuration from the base and any custom options.
|
|
142
|
+
* @param projectDirOrConfig - Either the absolute project directory (use `import.meta.dirname`) or a prebuilt config.
|
|
143
|
+
* @param customConfig - Additional configuration to merge when a project directory is provided.
|
|
144
|
+
* @returns A merged Vitest configuration tailored for the caller.
|
|
145
|
+
*/
|
|
146
|
+
export function createVitestConfig(
|
|
147
|
+
projectDirOrConfig?: string | VitestConfig,
|
|
148
|
+
customConfig?: VitestConfig,
|
|
149
|
+
): ReturnType<typeof defineConfig> {
|
|
150
|
+
// Handle overloaded parameters
|
|
151
|
+
let projectDir: string | undefined;
|
|
152
|
+
let config: VitestConfig;
|
|
153
|
+
|
|
154
|
+
if (typeof projectDirOrConfig === "string") {
|
|
155
|
+
projectDir = projectDirOrConfig;
|
|
156
|
+
config = customConfig ?? EMPTY_CONFIG;
|
|
157
|
+
} else {
|
|
158
|
+
projectDir = undefined;
|
|
159
|
+
config = projectDirOrConfig ?? EMPTY_CONFIG;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Auto-detect configuration if not explicitly provided
|
|
163
|
+
const autoSetupFiles =
|
|
164
|
+
config.test?.setupFiles !== undefined && config.test.setupFiles.length > 0
|
|
165
|
+
? []
|
|
166
|
+
: autoDetectSetupFiles(projectDir);
|
|
167
|
+
const autoIncludePatterns =
|
|
168
|
+
config.test?.include !== undefined && config.test.include.length > 0
|
|
169
|
+
? []
|
|
170
|
+
: autoDetectIncludePatterns();
|
|
171
|
+
|
|
172
|
+
return defineConfig({
|
|
173
|
+
...baseConfig,
|
|
174
|
+
...config,
|
|
175
|
+
test: {
|
|
176
|
+
...baseConfig.test,
|
|
177
|
+
// Auto-detect setupFiles if not explicitly provided
|
|
178
|
+
...(autoSetupFiles.length > 0 && { setupFiles: autoSetupFiles }),
|
|
179
|
+
// Auto-detect include patterns if not explicitly provided
|
|
180
|
+
...(autoIncludePatterns.length > 0 && { include: autoIncludePatterns }),
|
|
181
|
+
...config.test,
|
|
182
|
+
coverage: {
|
|
183
|
+
...baseConfig.test.coverage,
|
|
184
|
+
...config.test?.coverage,
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
resolve: {
|
|
188
|
+
// Prefer "source" condition in package.json exports, allowing
|
|
189
|
+
// Vitest to resolve workspace dependencies directly to TypeScript source
|
|
190
|
+
// files without requiring a prior build step.
|
|
191
|
+
//
|
|
192
|
+
// Since Vite 6, resolve.conditions REPLACES the defaults instead of
|
|
193
|
+
// extending them. We must include defaultClientConditions to preserve
|
|
194
|
+
// standard conditions like "module", "browser", "development|production".
|
|
195
|
+
conditions: ["source", ...defaultClientConditions],
|
|
196
|
+
alias: {
|
|
197
|
+
// Work around packages whose "module" entry is bundler-oriented but not
|
|
198
|
+
// directly Node.js ESM-resolvable in Vitest (e.g. extensionless internal
|
|
199
|
+
// specifiers). Prefer the Node/CJS build for tests.
|
|
200
|
+
"@opentelemetry/api": "@opentelemetry/api/build/src/index.js",
|
|
201
|
+
// Auto-generate self-package alias (e.g. "@reasonabletech/utils" → "./src")
|
|
202
|
+
...(projectDir !== undefined &&
|
|
203
|
+
projectDir !== "" &&
|
|
204
|
+
generateSelfPackageAliases(projectDir)),
|
|
205
|
+
// Standard "@" → src alias
|
|
206
|
+
...(projectDir !== undefined &&
|
|
207
|
+
projectDir !== "" && { "@": `${projectDir}/src` }),
|
|
208
|
+
// Consumer-provided aliases override everything above
|
|
209
|
+
...config.resolve?.alias,
|
|
210
|
+
},
|
|
211
|
+
...config.resolve,
|
|
212
|
+
},
|
|
213
|
+
// Vitest runs in Vite's SSR mode. Since Vite 6, ssr.resolve.conditions is
|
|
214
|
+
// independent from resolve.conditions and defaults to defaultServerConditions.
|
|
215
|
+
// We must explicitly include "source" in ssr.resolve.conditions so
|
|
216
|
+
// workspace dependencies resolve to TypeScript source during test execution.
|
|
217
|
+
// Additionally, ssr.resolve.externalConditions passes "source" to
|
|
218
|
+
// Node.js when it natively resolves externalized packages.
|
|
219
|
+
//
|
|
220
|
+
// Note: We intentionally omit the "module" export condition for SSR tests.
|
|
221
|
+
// Some third-party packages expose a "module" build that is bundler-friendly
|
|
222
|
+
// but not directly Node.js ESM-resolvable (for example: extensionless internal
|
|
223
|
+
// specifiers). For tests, preferring Node-compatible ("node"/"default") entry
|
|
224
|
+
// points avoids runtime import failures.
|
|
225
|
+
ssr: {
|
|
226
|
+
resolve: {
|
|
227
|
+
conditions: [
|
|
228
|
+
"source",
|
|
229
|
+
...defaultServerConditions.filter(
|
|
230
|
+
(condition) => condition !== "module",
|
|
231
|
+
),
|
|
232
|
+
],
|
|
233
|
+
externalConditions: ["source"],
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** @overload */
|
|
240
|
+
/**
|
|
241
|
+
* Creates a configuration with extended timeouts for long-running tests.
|
|
242
|
+
* @param projectDirOrConfig - Either the absolute project directory or an existing configuration to extend.
|
|
243
|
+
* @param customConfig - Additional configuration to merge when a project directory is supplied.
|
|
244
|
+
* @returns A Vitest configuration suited for long-running suites.
|
|
245
|
+
*/
|
|
246
|
+
export function createLongRunningTestConfig(
|
|
247
|
+
projectDirOrConfig?: string | VitestConfig,
|
|
248
|
+
customConfig?: VitestConfig,
|
|
249
|
+
): ReturnType<typeof defineConfig> {
|
|
250
|
+
// Handle overloaded parameters
|
|
251
|
+
let projectDir: string | undefined;
|
|
252
|
+
let config: VitestConfig;
|
|
253
|
+
|
|
254
|
+
if (typeof projectDirOrConfig === "string") {
|
|
255
|
+
projectDir = projectDirOrConfig;
|
|
256
|
+
config = customConfig ?? EMPTY_CONFIG;
|
|
257
|
+
} else {
|
|
258
|
+
projectDir = undefined;
|
|
259
|
+
config = projectDirOrConfig ?? EMPTY_CONFIG;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const longRunningConfig: VitestConfig = {
|
|
263
|
+
...config,
|
|
264
|
+
test: {
|
|
265
|
+
testTimeout: 30000, // 30 seconds for long-running tests
|
|
266
|
+
hookTimeout: 30000, // 30 seconds for setup/teardown hooks
|
|
267
|
+
...config.test,
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
if (projectDir !== undefined) {
|
|
272
|
+
return createVitestConfig(projectDir, longRunningConfig);
|
|
273
|
+
}
|
|
274
|
+
return createVitestConfig(longRunningConfig);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Re-export for convenience
|
|
278
|
+
export { createReactConfig, createReactConfigWithPlugins } from "./react.js";
|
|
279
|
+
|
|
280
|
+
export default createVitestConfig;
|
package/src/node.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js-specific Vitest configuration
|
|
3
|
+
* @module @reasonabletech/config-vitest/node
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { InlineConfig } from "vitest/node";
|
|
7
|
+
import type { UserConfig } from "vite";
|
|
8
|
+
import { createVitestConfig, type DeepReadonly } from "./index.js";
|
|
9
|
+
|
|
10
|
+
/** Immutable Vitest configuration type combining Vite UserConfig with Vitest InlineConfig */
|
|
11
|
+
export type VitestConfig = DeepReadonly<UserConfig> & {
|
|
12
|
+
readonly test?: DeepReadonly<InlineConfig>;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// Empty readonly config for default parameters
|
|
16
|
+
const EMPTY_CONFIG = {} as const satisfies VitestConfig;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Node.js-specific configuration options
|
|
20
|
+
*/
|
|
21
|
+
export const nodeConfig = {
|
|
22
|
+
test: {
|
|
23
|
+
environment: "node" as const,
|
|
24
|
+
include: ["tests/**/*.test.ts"],
|
|
25
|
+
},
|
|
26
|
+
} as const satisfies VitestConfig;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Creates a Vitest configuration for Node.js-based packages.
|
|
30
|
+
* @param projectDirOrConfig - Either the absolute project directory (use `import.meta.dirname`) or a prebuilt config.
|
|
31
|
+
* @param customConfig - Additional configuration to merge when a project directory is provided.
|
|
32
|
+
* @returns A Vitest configuration optimized for Node.js environments
|
|
33
|
+
*/
|
|
34
|
+
export function createNodeConfig(
|
|
35
|
+
projectDirOrConfig?: string | VitestConfig,
|
|
36
|
+
customConfig?: VitestConfig,
|
|
37
|
+
): ReturnType<typeof createVitestConfig> {
|
|
38
|
+
// Handle overloaded parameters
|
|
39
|
+
let projectDir: string | undefined;
|
|
40
|
+
let config: VitestConfig;
|
|
41
|
+
|
|
42
|
+
if (typeof projectDirOrConfig === "string") {
|
|
43
|
+
projectDir = projectDirOrConfig;
|
|
44
|
+
config = customConfig ?? EMPTY_CONFIG;
|
|
45
|
+
} else {
|
|
46
|
+
projectDir = undefined;
|
|
47
|
+
config = projectDirOrConfig ?? EMPTY_CONFIG;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Merge node-specific settings with consumer config
|
|
51
|
+
const mergedConfig = {
|
|
52
|
+
...nodeConfig,
|
|
53
|
+
...config,
|
|
54
|
+
test: {
|
|
55
|
+
...nodeConfig.test,
|
|
56
|
+
...config.test,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Delegate to createVitestConfig which handles aliasing and base config.
|
|
61
|
+
// When projectDir is present, pass both args so createVitestConfig generates aliases.
|
|
62
|
+
// When absent, pass the merged config as the sole argument.
|
|
63
|
+
if (projectDir !== undefined) {
|
|
64
|
+
return createVitestConfig(
|
|
65
|
+
projectDir,
|
|
66
|
+
mergedConfig as Parameters<typeof createVitestConfig>[1],
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return createVitestConfig(
|
|
70
|
+
mergedConfig as Parameters<typeof createVitestConfig>[0],
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export default createNodeConfig;
|